Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

Merklin's avatar

How to test login and regostration form?

Hi all, I spent a lot of time googling and searching, but I didn't find an answer to my question.

As you know, in Laravel there are some mock test for authentication and registration but they are not exactly what I want. Actually, I fell they test the code itself, not the form and bypass some of the workflows.

Example of pre-existing test for registration

public function new_users_can_register(): void
    {
        if (! Features::enabled(Features::registration())) {
            $this->markTestSkipped('Registration support is not enabled.');
        }

        $password = generateRandomPassword();

        $response = $this->post('/register', [
            'name' => 'John',
            'last_name' => 'Doe',
            'email' => '[email protected]',
            'password' => $password,
            'password_confirmation' => $password,
            'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature(),
        ]);

        $this->assertAuthenticated();
        $response->assertRedirect(route('dashboard', absolute: false));
    }

However, in fact, I have added a config file with blacklisted words that cannot be used in the user name or last_name. Then, I have modified CreateNewUser like this:

When testing the form itself, it works as expected. However, if I run this test:

public function user_cannot_register_with_name_containing_blacklisted_word()
    {
        $this->withExceptionHandling();

        $blacklist = config('blacklist.blacklist');

        $key = array_rand($blacklist);
        $blacklistedWord = $blacklist[$key];
        $password = generateRandomPassword();

        $response = $this->post('/register', [
            'name' => $blacklistedWord,
            'last_name' => 'Doe',
            'email' => '[email protected]',
            'password' => $password,
            'password_confirmation' => $password,
            'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature(),
        ]);

        $response->assertSee('The name or last name contains a blacklisted word');
    }

the response in the test is actually a redirect:

FAILED  Tests\Feature\User\RegistrationTest > user cannot register with name containing blacklisted word
  Expected: <!DOCTYPE html>\n
<html>\n
    <head>\n
        <meta charset="UTF-8" />\n
        <meta http-equiv="refresh" content="0;url='/dashboard'" />\n
\n
        <title>Redirecting to /dashboard</title>\n
    </head>\n
    <body>\n
        Redirecting to <a href="/dashboard">dashboard</a>.\n
    </body>\n
</html>

  To contain: The name or last name contains a blacklisted word

  at tests\Feature\User\RegistrationTest.php:90
     86▕             'password_confirmation' => $password,
     87▕             'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature(),
     88▕         ]);
     89▕
  ➜  90▕         $response->assertSee('The name or last name contains a blacklisted word');
     91▕     }
     92▕ }
     93▕


  Tests:    1 failed, 1 skipped, 2 passed (5 assertions)
  Duration: 4.93s

Am I doing something wrong?

And how can I test the form itself? Something like Livewire::test()->fillForm()?

0 likes
5 replies
Merklin's avatar

So, I've found a solution that I also find viable, to test the session:

#[Test]
    public function user_cannot_register_with_name_containing_blacklisted_word()
    {
        $blacklist = config('blacklist.blacklist');

        $key = array_rand($blacklist);
        $blacklistedWord = $blacklist[$key];
        $password = generateRandomPassword();

        $response = $this->post('/register', [
            'name' => $blacklistedWord,
            'last_name' => 'Doe',
            'email' => '[email protected]',
            'password' => $password,
            'password_confirmation' => $password,
            'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature(),
        ]);

        $response->assertSessionHasErrors(['name' => 'The name contains a blacklisted word: ' . $blacklistedWord]);
    }

Anyway, if someone knows how to test the web-form please advice. :)

martinbean's avatar

@merklin What exactly is the problem? If you want to write tests to test a particular case, then you’re free to do so.

I’d also use a data provider so your test case can be ran once for each blacklisted word, instead of just picking a random one each time you run your test suite:

public static function blacklistedWordsProvider(): array
{
    return config('blacklist.blacklist'); // Assuming just an array of terms
}

#[DataProvider('blacklistedWordsProvider')]
#[Test]
public function user_cannot_register_with_name_containing_blacklisted_word(string $word): void
{
    $response = $this->post('/register', [
        'name' => $word,
    ]);

    $response->assertInvalid('name');
}
Merklin's avatar

@martinbean The problem with the first test was that the $response didn't contain the error but instead redirects to the dashboard page as if the user is authenticated.

In the live test, the registration halts and an error is displayed above the form.

I expect the test to behave the same way as I am using the form in the browser: re-render the form with the error message displayed on top. Not the code in the 4th block of my question.

martinbean's avatar

@Merklin But if that’s the response you would get: a redirect response (either to the home page if registration was successful, or back to the registration form if there are validation errors).

You’re expecting validation errors, so that’s why you would use the appropriate expectations (such as assertInvalid) on the response, to ensure that the response has the validation failures you’re expecting flashed to the session.

Niush's avatar

You can write test in multiple ways:

$response = $this->post('/register', [
  // ...
]);

// 1) Assert for validation exception
$response->assertInvalid([
    'name' => 'The name contains a blacklisted word: ' . $blacklistedWord,
]);

// 2) Assert that session has validation error message
$response->assertSessionHasErrors([
    'name' => 'The name contains a blacklisted word: ' . $blacklistedWord,
]);

// 3) Follow the redirection, and check if view has correct error message displayed.
$this->followRedirects($response)->assertSee(
  'The name contains a blacklisted word: ' . $blacklistedWord,
);

The 3rd option is what you are looking for. I could not find it in the official documentation.

Please or to participate in this conversation.