This is a companion package to Behat's Laravel Extension that provides utilities to work around some issues and limitations when testing Javascript applications using browser emulators, like Selenium, PhantomJS or Zombie.
The workarounds used in this package are heavily inspired by Laravel Dusk code. Read this post if you wish to have more context about the history of the issues.
If you're here, you probably already know about the extension limitations, but in case you don't; read on.
Install, and use these three traits in your FeatureContext
and you're done. Remember to not to use
DatabaseTransactions
and/or Migrator
traits.
<?php
use Laracasts\Behat\Context\MigrateRefresh;
use Sepehr\BehatLaravelJs\Concerns\AuthenticateUsers;
use Sepehr\BehatLaravelJs\Concerns\PreserveBehatEnvironment;
class FeatureContext extends MinkContext implements Context
{
use PreserveBehatEnvironment, AuthenticateUsers, MigrateRefresh;
// ...
}
To alleviate this issue, you need to use the
\Sepehr\BehatLaravelJs\Concerns\PreserveBehatEnvironment
trait in yourFeatureContext
class.
Consider this example: Your testing environment is set to use SQLite as the database while your local/production
environment use MySQL. When you run a @javascript
Behat scenario, a browser emulator dispatches a request
to your Laravel app endpoint. And to your surprise, it meets with another Laravel instance that is using the .env
file. An instance operating in a different environment: different databases, cache drivers, queues, etc.
To alleviate this one, you need to use
Laracasts\Behat\Context\MigrateRefresh
trait in yourFeatureContext
class instead of usingDatabaseTransactions
andMigrator
traits.
The very popular DatabaseTransactions
trait and its
BLE counterpart,
begin a transaction before a scenario. The transaction will be commited only if there are no exceptions. Then after the
scenario, they will rollback it in order to keep the database state intact.
In middle of the process, when a browser emulator dispatches the request to another instance of Laravel, the transaction won't be commited and thus you will encounter unexpected results.
Consider a scenario, when you first insert a few test users into the database in the testing instance and in the next
step, you request a page (to the other instance) to see if their data exist on a page. To your surprise, the data you're
looking for won't be available.
Instead, in order to maintain a clean database state, use the MigrateRefresh
trait to refresh the database before each
scenario.
To alleviate this one, you should be using the
\Sepehr\BehatLaravelJs\Concerns\AuthenticateUsers
trait in yourFeatureContext
class. It will provide you with helper authentication methods to login, logout and get the current user data.
Authentication is another problem. In the testing environment you log a user into the system, then you tell Behat to fire a Selenium session and check a protected page. As you might already know, the user won't be logged-in. The testing browser has no authentication cookie to send to the other Laravel instance.
Available methods are:
Description | Signature |
---|---|
Login as a user | loginAs($user|$userId, $guard|null) |
Logout | logout($guard|null) |
Get current user's data | currentUserInfo($guard|null) |
Assert that the user is authenticated | assertAuthenticated($guard|null) |
Assert that the user is authenticated AS | assertAuthenticatedAs($user, $guard|null) |
Assert that the user is NOT authenticated | assertGuest($guard|null) |
Just as Dusk.
Install the package using composer:
composer install sepehr/behat-laravel-js
Then, in your AppServiceProvider::boot()
, register the package service provider for testing environments. Please note
that it'd be a SECURITY RISK if you enable this in your production environment. See the package service provider to find
out why.
<?php
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
if ($this->app->environment('local', 'testing', 'acceptance')) {
$this->app->register(\Sepehr\BehatLaravelJs\ServiceProvider::class);
}
}
// ...
}