1
votes

I am looking for the Laravel Dusk equivalent of

this->expectException(InvalidArgumentException::class); 

I'm new to using Laravel Dusk (running Laravel 5.7) and cannot find a way to test for an expected error. When I run the following test.

I get the following:

There was 1 error:

1) Tests\Browser\RegistrationTest::test_user_cannot_register_with_duplicate_email Illuminate\Database\QueryException: SQLSTATE[23000]: Integrity constraint violation: 19 UNIQUE constraint failed: users.email (SQL: insert into "users" ("name", "email", "password", "updated_at", "created_a t") values (Eoj, [email protected], 654321, 2018-10-16 20:35:09, 2018-10-16 20:35:09))

Caused by PDOException: SQLSTATE[23000]: Integrity constraint violation: 19 UNIQUE constraint failed: users.email

ERRORS! Tests: 4, Assertions: 5, Errors: 1.

public function test_user_cannot_register_with_duplicate_email()
{
    User::create([
        'name' => 'Eoj',
        'email' => '[email protected]',
        'password' => '654321'

    ]);

    $this->browse(function ($browser) {
        $browser->visit('/') //Go to the homepage
        ->clickLink('Register') //Click the Register link
        ->assertSee('Register') //Make sure the phrase in the argument is on the page
        //Fill the form with these values
        ->value('#name', 'Joe')
            ->value('#email', '[email protected]')
            ->value('#password', '123456')
            ->value('#password-confirm', '123456')
            ->click('button[type="submit"]') //Click the submit button on the page
            ->assertPathIs('/register') //Make sure you are still on the register page
            //Make sure you see the phrase in the argument
            ->assertSee("The email has already been taken");
    });

}

Obviously I was expecting an error - but can't work out how to tell dusk this.

When I change my code to the following I get a different error:

1) >Tests\Browser\RegistrationTest::test_user_cannot_register_with_duplicate_email Did not see expected text [The email has already been taken] within element [body]. Failed asserting that false is true.

I am not running any other tests at the moment.

    <?php

namespace Tests\Browser;

use App\User;
use Tests\DuskTestCase;
use Laravel\Dusk\Browser;
use Illuminate\Foundation\Testing\RefreshDatabase;


class RegistrationTest extends DuskTestCase

{
    use RefreshDatabase;

protected function setUp()
{
    parent::setUp();
    foreach (static::$browsers as $browser) {
        $browser->driver->manage()->deleteAllCookies();
    }
}

public function test_user_cannot_register_with_duplicate_email()
{
    User::create([
        'name' => 'Eoj',
        'email' => '[email protected]',
        'password' => '654321'

    ]);

    $this->browse(function ($browser) {
        $browser->visit('/') //Go to the homepage
        ->clickLink('Register') //Click the Register link
        ->assertSee('Register') //Make sure the phrase in the argument is on the page
        //Fill the form with these values
        ->value('#name', 'Joe')
            ->value('#email', '[email protected]')
            ->value('#password', '123456')
            ->value('#password-confirm', '123456')
            ->click('button[type="submit"]') //Click the submit button on the page
            ->assertPathIs('/register') //Make sure you are still on the register page
            //Make sure you see the phrase in the argument
            ->assertSee("The email has already been taken");
    });

}

}

2
It seems that you have a problem with your code that register user, not the test. You may want to share the controller/model code that saves the user.Felippe Duarte
It's the out of the box Laravel Auth/RegisterController.php that you get after running make:auth. When I have tested it in the browser it works as expected (i.e. doesn't allow you to register a user when the email already exists in database). I should also add the test for registering a new unique user works as expected.user8334049
Do you already have an email [email protected] in your database? You may need to use RefreshDatabase trait.Felippe Duarte
It seems that User::create([..]) in your test is the one throwing this error. Change the e-mail to a totally different one and try again.Felippe Duarte
I don't think you understand what I'm trying to say. Your test is trying to insert an already duplicated email. That's why you have this error. Change this e-mail to a different one, both in User::create and in ->value('#email', '...')Felippe Duarte

2 Answers

1
votes

As you can see in the error:

Tests\Browser\RegistrationTest::test_user_cannot_register_with_duplicate_email Illuminate\Database\QueryException: SQLSTATE[23000]: Integrity constraint violation: 19 UNIQUE constraint failed: users.email (SQL: insert into "users" ("name", "email", "password", "updated_at", "created_a t") values (Eoj, [email protected], 654321, 2018-10-16 20:35:09, 2018-10-16 20:35:09))

The values are exactly the ones that you are trying to insert here:

User::create([
    'name' => 'Eoj',
    'email' => '[email protected]',
    'password' => '654321'
]);

So, you can change this e-mail to a different one:

User::create([
    'name' => 'Eoj',
    'email' => '[email protected]',
    'password' => '654321'
]);

And again here to the test makes sense:

->value('#email', '[email protected]')

This way, the email will not be duplicated, because at some point you already have a "[email protected]".

A good practice is to reset the database before the tests.

In tests/TestCase.php you may have something like this:

use Illuminate\Foundation\Testing\RefreshDatabase; //<--HERE

abstract class TestCase extends BaseTestCase
{
    use RefreshDatabase; //<--HERE

And your test must extend this class:

use Tests\TestCase; //<--HERE
class MyTest extends TestCase { //<--HERE

That way the data you be reseted, avoiding the duplicate e-mail issue in the subsequent tests.

0
votes

I think the problem is that you not waiting answer from server (you are submitting form via js, right?), and assertion fires too early. Just use waitFor or waitForText in these type of scenarios.