DEV Community

kris
kris

Posted on • Originally published at Medium on

Building Advance Blog on Laravel 5.5 with TDD mode #4 User can submit comment

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

  1. create route for connect to endpoint
  2. create and save comment object to DB
  3. 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


Top comments (0)