Building Advance Blog on Laravel 5.5 with TDD mode #4 User can submit comment
0xAirdropfarmer
Posted on November 26, 2017
in the previous episode, we display comment by creating test first
again in this episode starting with a feature
User can submit comment
if you follow this first post I don’t use User in test case because require authentication state
but now we don’t allow guest or anonymous submit a comment
A Post can add comment
first, we test in small scale with deep down to unit level generate unit test file name PostTest with artisan
php artisan make:test PostTest --unit
open this file and fill user story first
public function test_a_post_can_add_a_comments()
{
//Giving a Post
// Add a commemnt
// Then post should have a comment
}
next fill in blank
public function test_a_post_can_add_a_comments()
{
//Giving a Post
$post = factory('App\Post')->create();
// Add a comemnt
$post->storeComment([
'body'=>'Testing',
'user_id'=>1
]);
// Then post should have comment
$this->assertCount(1,$post->comment);
}
try test
p filter tests/Unit/PostTest.php
result
ok this make sense
open Comment Model
fill $guarded
and run single test again
we got green
Submit Comment Test Feature Test
next we up level to create comment but in big scale with
- create route for connect to endpoint
- create and save comment object to DB
- check comment are exist in show page
The only user can submit a comment is a feature test because it’s work with other feature.
Doesn’t isolate them self from display name.
Open terminal php artisan make:test SubmitComment
Let’s generate user story
public function test_user_can_submit_comment(){
// Given a Guest
// make guest to Authenticate user
// And Post is exist
// And Giving comment object
// When the user submit comment to the post
// Then their should see comment
}
next fill in the blank
public function test_user_can_submit_comment(){
// Given a Guest
$guest = factory('App\User')->create();
// create Authenticate user
$user = $this->be($guest);
// And Post is exist
$post = factory('App\Post')->create();
// And Giving comment object
$comment = factory('App\Comment')->make();
// When the user submit comment to the post
$this->post('/blog/'.$post->id.'/comment',$comment->toArray());
// Then their should see comment
$this->get('/blog/'.$post->id)->assertSee($comment->body);
}
Note:: You’ve see when create comment why I use make instead of create because make only create object doesn’t create DB record and we use object create real record in next line for more reference
now we got a map let’s follow
first this should red
Create route first
Route::post('/blog/{post}/comment','CommentController@store');
next create endpoint , in CommentController create store method for call storeCommment
use Illuminate\Http\Request;
use App\Post;
class CommentController extends Controller
{
public function store(Post $post,Request $request){
$post->storeComment([
'body'=>$request->get('body'),
'user_id'=> auth()->id()
]);
}
}
save and test again
Gotcha ,we got green
but some detail I’ve fixit
An authenticate user only can submit comment
we need to block a guest that try to submit comment with add auth middleware
in CommentController
public function _construct(){
$this->middleware('auth');
}
and for making sure we add a test for check this
comment $this->be and change $user to unauthenticated user
try p
ok that’s work let’s me explain
when user doesn’t authenticate and post request to end point it’s doens’t work
for next step in our test it’s call get for orignal post that add comment
we expect to see comment that we create before but that doesn’t create
and try uncomment
save and test again
ok let’s separate function to check if a guest can’t submit a comment
grab code from before test but remove $user = $this->be($guest);
function test_guest_can_not_submit_comment(){
// Given a Guest
$guest = factory('App\User')->create();
// And Post is exist
$post = factory('App\Post')->create();
// And Giving comment object
$comment = factory('App\Comment')->make();
// When the user submit comment to the post
$this->post('/blog/'.$post->id.'/comment',$comment->toArray());
// Then their should see comment
$this->get('/blog/'.$post->id)->assertSee($comment->body);
}
test again
should fail next make it green
function test_guest_can_not_submit_comment(){
// Given a Guest
$guest = factory('App\User')->create();
// And Post is exist
$post = factory('App\Post')->create();
// And Giving comment object
$comment = factory('App\Comment')->make();
// When the user submit comment to the post
$this->post('/blog/'.$post->id.'/comment',$comment->toArray());
// Then their should don't see comment
$this->get('/blog/'.$post->id)->assertDontSee($comment->body);
}
rerun test
it’s green
we completely work under the hood.
Finish in frontend
now that’s time to add form for end of this episode
first I’ve give name to route
Route::post('/blog/{post}/comment','CommentController@store')->name('addcomment');
then openpost/show.blade.php
scroll to bottom page
copy code this below
@if (auth()->check())
<div class="row">
<div class="col-md-8 col-md-offset-2">
<form method="POST" action="{{ route('addcomment',$post->id) }}">
{{ csrf_field() }}
<div class="form-group">
<textarea name="body" id="body" class="form-control" placeholder="Have something to say?" rows="5"></textarea>
</div>
<button type="submit" class="btn btn-default">Post</button>
</form>
</div>
</div>
@else
<p class="text-center">Please <a href="{{ route('login') }}">sign in</a> to comment in post.</p>
@endif
and paste to this position
save and next go to check
click on link for signin
after sign in go to some post and add this
and submit You’ve redirect back to this page
ok it’s almost completely work fine
bonus section
display post creator
we know comment creator
but we don’t know who post creator
let’s display it with TDD way with write test first
open tests/Unit/PostTest.php
add function test_post_has_a_creator
function test_post_has_a_creator()
{
// Giving post
// expect found User who create post
}
fill in blank
again
function test_post_has_a_creator()
{
// Giving post
$post = factory('App\Post')->create();
// expect found User who create post
$this->assertInstanceOf('App\User', $post->creator);
}
let’s test again
should fail
next we add relationship for Post model
run test again
display in post add to single post
save and refresh
complete
before we end in this episode I’ve need tweak something
with add home menu
first I’ve add name to blog route
save and refresh
got blog menu
hope your enjoy this
if you like this please give me 50 claps and hit follow that encouragement to move forward
this project Github commit and you can star it
Posted on November 26, 2017
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 26, 2017