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:
<?php
declare(strict_types=1);
namespace App\Actions\Fortify;
use App\Models\User;
use App\Models\UserPreferences;
use Composer\InstalledVersions;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Validator;
use Illuminate\Validation\ValidationException;
use Laravel\Fortify\Contracts\CreatesNewUsers;
use Laravel\Jetstream\Jetstream;
class CreateNewUser implements CreatesNewUsers
{
use PasswordValidationRules;
private array $errors = []; // Collect all errors
/**
* Validate and create a newly registered user.
*
* @param array<string, string> $input
*/
public function create(array $input): User
{
Validator::make($input, [
'name' => ['required', 'string', 'max:255'],
'last_name' => ['required', 'string', 'max:255'],
'email' => ['required', 'string', 'email', 'max:255', 'unique:users'],
'password' => $this->passwordRules(),
'terms' => Jetstream::hasTermsAndPrivacyPolicyFeature() ? ['accepted', 'required'] : '',
])->validate();
// Check name and email against a blacklisted words
$this->checkBlacklist($input['name'], $input['last_name'], $input['email']);
if (! $this->errors) {
$usrtmp = User::create([
'name' => $input['name'],
'last_name' => $input['last_name'],
'email' => $input['email'],
'password' => Hash::make($input['password']),
]);
return $usrtmp;
} else {
throw ValidationException::withMessages($this->errors);
}
}
/**
* Check if the name or last name contains blacklisted terms.
*
* @throws ValidationException
*/
protected function checkBlacklist(string $name, string $lastName, string $email)
{
$blacklist = config('blacklist.blacklist');
foreach ($blacklist as $blacklistedName) {
if (stripos($name, $blacklistedName) !== false) {
$this->errors['name'] = 'The name contains a blacklisted word: ' . $blacklistedName;
Log::warning(
'An attempt to register with name containing a blacklisted word: {' .
$blacklistedName .
'} detected',
);
}
if (stripos($lastName, $blacklistedName) !== false) {
$this->errors['last_name'] = 'The last name contains a blacklisted word: ' . $blacklistedName;
Log::warning(
'An attempt to register with last name containing a blacklisted word: {' .
$blacklistedName .
'} detected',
);
}
if (stripos($email, $blacklistedName) !== false) {
$this->errors['email'] = 'The email contains a blacklisted word: ' . $blacklistedName;
Log::warning(
'An attempt to register with email containing a blacklisted word: {' .
$blacklistedName .
'} detected',
);
}
}
if (! empty($this->errors)) {
return $this->errors;
} else {
return 0;
}
}
}
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()?