Twitter From Scratch Using Laravel: Create Tweet

In our previous lesson we've learned about how to verify users email and how to test email. In this lesson we will be talking about how we can give the user the ability to create tweet.
As always let's create a test first in our
tests/Feature/UserTest.php
. In our lesson called "Our First Test" we already have a route for creating a tweet right? because we're using a resource controller. So, let's use that now. Remember your can always use php artisan route:list
to see what are the routes available in your application:
/** @test */
public function a_user_can_create_a_tweet()
{
$user = factory('App\User')->create();
$tweet = 'My first tweet';
$this->post(route('tweet.store', ['username' => $user->username]), [
'body' => $tweet
]);
$this->assertDatabaseHas('tweets', ['body' => $tweet]);
}
phpunit --filter a_user_can_create_a_tweet
There was 1 error:
1) Tests\Feature\UserTest::a_user_can_create_a_tweet
Failed asserting that a row in the table [tweets] matches the attributes {
"body": "My first tweet"
}.
The table is empty.
Next, let's update our
User\TweetController.php
. First, let's make sure the user is logged in when they hit the create, store, edit, update, and destroy methods in this controller by adding the auth
middleware into the constructor:
class TweetController extends Controller
{
/**
* Create a new controller instance
*/
public function __construct()
{
$this->middleware('auth', [
'only' => ['create', 'store', 'edit', 'update', 'destroy']
]);
}
}
phpunit --filter a_user_can_create_a_tweet
There was 1 error:
1) Tests\Feature\UserTest::a_user_can_create_a_tweet
Illuminate\Auth\AuthenticationException: Unauthenticated.
Next, let's use the
actingAs()
method in our test to simulate an authenticated user:
$this->actingAs($user)
->post(route('tweet.store', ['username' => $user->username]), [
'body' => $tweet
]);
Next, let's add some logic into the
store
method in our User\TweetController.php
:
public function store(Request $request)
{
$this->validate($request, [
'body' => 'required'
]);
return $request->user()->tweets()->create($request->only(['body']));
}
phpunit --filter a_user_can_create_a_tweet
There was 1 error:
1) Tests\Feature\UserTest::a_user_can_create_a_tweet
BadMethodCallException: Call to undefined method Illuminate\Database\Query\Builder::tweets()
What we're doing here is we make sure that the body of the tweet is not empty using the validate
method which will throw an exception and a proper error response automatically when the validation fails. Then, we get the authenticated user from the $request
variable and call a tweets
and create
method. In this way we don't have to figure out what's the id of the user is, Laravel will automatically attach the user_id
in the tweet for us.Next, let's create that
tweets
relationship in our User
model:
/**
* Get all the user tweets
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function tweets()
{
return $this->hasMany(Tweet::class);
}
phpunit --filter a_user_can_create_a_tweet
There was 1 error:
1) Tests\Feature\UserTest::a_user_can_create_a_tweet
Illuminate\Database\Eloquent\MassAssignmentException: body
Next, let's make that
body
column fillable in our Tweet
model:
class Tweet extends Model
{
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['body'];
}
phpunit --filter a_user_can_create_a_tweet
OK (1 test, 1 assertion)
That's all for this lesson. In our next lesson we will try to make a browser test for this using Laravel Dusk. As always if you have any questions please write it down in the comment below. See you in the next lesson. Thanks!
View the source code for this lesson on GitHub.
Previous: Email Verification with TestNext: Create Tweet with Laravel Dusk
Post a Comment