Twitter From Scratch Using Laravel: Create Tweet with Laravel Dusk

In our previous lesson we've learned about how to give a user the ability to create tweet. In this lesson we're going to learn how to automate browser test for our create tweet feature using Laravel Dusk.
First, let's install Laravel Dusk:
composer require laravel/dusk
Next, let's register it in our
app/Providers/AppServiceProvider.php
within the register
method:
use Laravel\Dusk\DuskServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
if ($this->app->environment('local', 'testing')) {
$this->app->register(DuskServiceProvider::class);
}
}
}
Next, let's run
dusk:install
artisan command:
php artisan dusk:install
This will create a Browser
directory under our tests
directory.Next, let's create
.env.dusk.local
file in our root directory to force Dusk to use its own environment file when running tests.Next, make sure to set your
APP_URL
environment variable in your .env.dusk.local
file. The value should match the URL you use to access your application in a browser. In my case I use:
APP_URL=http://twitter.dev
To run our browser tests we need to use
dusk
artisan command:
php artisan dusk
Next, let's create a user test:
php artisan dusk:make UserTest
class UserTest extends DuskTestCase
{
use DatabaseMigrations;
/** @test */
public function a_logged_in_user_can_create_a_tweet()
{
$this->browse(function (Browser $browser) {
$user = factory('App\User')->create();
$tweet = 'My first tweet';
$browser->loginAs($user)
->visit('/')
->type('body', $tweet)
->press('Tweet');
$this->assertDatabaseHas('tweets', ['body' => $tweet]);
});
}
}
What we're doing here is we create a user using the factory and log it in using the loginAs
method then visit the home page then simulate the typing of the textarea with a name of body
and pressing the tweet button, then assert that the tweet is saved in the tweets
table.php artisan dusk
There was 1 error:
1) Tests\Browser\UserTest::a_logged_in_user_can_create_a_tweet
Swift_TransportException: Expected response code 250 but got code "530", with message "530 5.7.1 Authentication required"
This is because in our email verification lesson we opt-in to the created
event of the User
model. Therefore, every time we create a new user an email will be send.Since in my end I don't have yet a mail setup, I'll just use log for the meantime and it's more practical in testing. So, in my
.env.dusk.local
file:
MAIL_DRIVER=log
php artisan dusk
There was 1 error:
1) Tests\Browser\UserTest::a_logged_in_user_can_create_a_tweet
Facebook\WebDriver\Exception\NoSuchElementException: no such element: Unable to locate element
Next, let's update our
routes/web.php
and remove /home
:
Route::get('/', 'HomeController@index');
So, basically our root url will have two different displays depending if the user is authenticated or not.Next, let's remove the constructor and update the
index
method in our HomeController.php
:
class HomeController extends Controller
{
/**
* Show the application dashboard.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function index(Request $request)
{
if (is_null($request->user())) {
return view('welcome');
}
return view('home');
}
}
If the user is authenticated let's display the home
view otherwise let's display the welcome
view.Next, let's update the
$redirectTo
property in both LoginController.php
and RegisterController.php
:
protected $redirectTo = '/';
Next, let's add a create tweet form in our
home.blade.php
:
<form action="{{ route('tweet.store', ['username' => $loggedUser->username]) }}" method="POST">
{{ csrf_field() }}
<div class="form-group">
<textarea name="body" class="form-control" rows="3"></textarea>
</div>
<div class="text-right">
<button type="submit" class="btn btn-primary">Tweet</button>
</div>
</form>
Next, let's make that
$loggedUser
variable available in all our views by updating our Controller.php
:
use App\User;
use Illuminate\Support\Facades\View;
class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
/**
* Create a new controller instance.
*/
public function __construct()
{
$this->middleware(function ($request, $next) {
$user = auth()->user();
View::share('loggedIn', $user ? true : false);
View::share('loggedUser', $user ?? new User);
return $next($request);
});
}
}
We also add a global $loggedIn
variable that can be useful when checking if the user is logged in. This time when we run our test again we should get green.
That's all for this lesson. If you have any question please write it down in the comment below and I will try to answer them in the best of my ability. See you in the next lesson. Thanks!
View the source code for this lesson on GitHub.
Previous: Create Tweet
Post a Comment