I am getting started using Laravel Dusk for browser testing, and have created a couple of tests to test my login form. I have the following code:
class LoginTest extends DuskTestCase
{
public function testLogin()
{
$this->browse(function (Browser $browser) {
$browser->visit('/admin')
->type('email', 'inigo@mydomain.co.uk')
->type('password', 'MyPass')
->press('Login')
->assertSee('Loading...');
});
}
public function testLoginFailure(){
$this->browse(function (Browser $browser){
$browser->visit('/admin/logout'); // I have to add this to logout first, otherwise it's already logged in for this test!
$browser->visit('/admin')
->type('email', 'someemail@afakedomain.com')
->type('password', 'somefakepasswordthatdoesntwork')
->press('Login')
->assertSee('These credentials do not match our records.');
});
}
See the comment. The first function runs fine, but when it comes to the second function, I have to logout first, since the user is already logged in as a result of running the first function. This came as a surprise to me as I thought unit tests were completely independent, with session data being destroyed automatically.
Is there a better way of doing this- some Dusk method that I'm missing perhaps- than having to call $browser->visit('/admin/logout');
?
Thanks
EDIT Thanks for the 2 answers so far, which both seem valid solutions. I've updated the second function to the following:
public function testLoginFailure(){
$this->createBrowsersFor(function(Browser $browser){
$browser->visit('/admin')
->type('email', 'someshit@afakedomain.com')
->type('password', 'somefakepasswordthatdoesntwork')
->press('Login')
->assertSee('These credentials do not match our records.');
});
}
Which does the job. So
You can call
$this->logout();
InteractsWithAuthentication - Github
Edit:
This is the behaviour of the Dusk Test case, the primary browser instance remains for the other tests.
A second solution, create a second browser instance, which will be destroyed after the single test
You could flush the session in a tearDown()
method:
class LoginTest extends DuskTestCase
{
// Your tests
public function tearDown()
{
session()->flush();
parent::tearDown();
}
}
If in case it helps some one else. You can use tearDown
method to clear all cookies. Following is the example of doing so, you can add this method in DuskTestCase.php file
public function tearDown()
{
parent::tearDown();
$this->browse(function (Browser $browser) {
$browser->driver->manage()->deleteAllCookies();
});
}
I hope this will help.
If you just want to logout your signed in user, after login test, simply use:
$browser->visit('/login')
->loginAs(\App\User::find(1))
...
some assertions
...
->logout();
In my case, tearDown()
was not enough, for some reason, a logged users was still persisted between tests, so I placed deleteAllCookies()
at setUp()
.
So, in my DuskTestCase.php I added:
/**
* Temporal solution for cleaning up session
*/
protected function setUp()
{
parent::setUp();
foreach (static::$browsers as $browser) {
$browser->driver->manage()->deleteAllCookies();
}
}
It was the only way I could flush up session around all tests. I hope it helps.
Note: I'm using Homestead and Windows 10.
I'm not sure if its the answer you are looking for, but you can create multiple browsers to perform a test that requires clean history/cookies/cache.
For example, if you have lots of tests where the user should be logged in and you don't want to log out for only one test that checks reset password form, then you can create an additional browser for this exact case and switch to the previous browser when moving to the next tests.
It might look the next way:
public function testfirstTest()
{
$this->browse(function ($browser) {
//some actions where you login etc
});
}
public function testSecondTestWhereYouNeedToBeLoggedOut()
{
$this->browse(function ($currentBrowser, $newBrowser) {
//here the new browser will be created, at the same time your previous browser window won't be closed, but history/cookies/cache will be empty for the newly created browser window
$newBrowser->visit('/admin')
//do some actions
$newBrowser->quit();//here you close this window
});
}
public function testWhereYouShouldContinueWorkingWithUserLoggedIn()
{
$this->browse(function ($browser) {
$browser->doSomething()//here all actions will be performed in the initially opened browser with user logged in
});
}