93 lines
3.4 KiB
PHP
93 lines
3.4 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Feature\Auth;
|
|
|
|
use App\Filament\Pages\Auth\RequestPasswordReset;
|
|
use App\Models\User;
|
|
use Filament\Auth\Notifications\ResetPassword;
|
|
use Filament\Notifications\Notification as FilamentNotification;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\Notification as MailNotification;
|
|
use Illuminate\Support\Facades\Password;
|
|
use Livewire\Livewire;
|
|
use Tests\TestCase;
|
|
|
|
/**
|
|
* SPEC 12.1 / ADM-01 "reset seguro": the request-reset page must not let a
|
|
* caller distinguish a registered email from an unregistered one. Filament's
|
|
* stock page fails this two ways — a distinguishable danger notification for
|
|
* both Password::INVALID_USER (no such user) and Password::RESET_THROTTLED
|
|
* (only ever returned for a user that exists, per
|
|
* Illuminate\Auth\Passwords\PasswordBroker::sendResetLink). App\Filament\
|
|
* Pages\Auth\RequestPasswordReset normalizes both to the same "sent"
|
|
* response. Assertions for the two emails live in separate test methods
|
|
* because the page's own rate limiter allows only 2 requests per IP before
|
|
* an unrelated "throttled" notification kicks in.
|
|
*/
|
|
class PasswordResetRequestTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
public function test_reset_request_for_registered_email_sends_notification_and_reports_success(): void
|
|
{
|
|
MailNotification::fake();
|
|
|
|
$user = User::factory()->admin()->create([
|
|
'email' => 'registered@example.com',
|
|
]);
|
|
|
|
Livewire::test(RequestPasswordReset::class)
|
|
->set('data.email', $user->email)
|
|
->call('request')
|
|
->assertNotified($this->expectedSentNotification());
|
|
|
|
MailNotification::assertSentTo($user, ResetPassword::class);
|
|
}
|
|
|
|
public function test_reset_request_for_unknown_email_reports_the_same_success_response(): void
|
|
{
|
|
MailNotification::fake();
|
|
|
|
Livewire::test(RequestPasswordReset::class)
|
|
->set('data.email', 'nobody@example.com')
|
|
->call('request')
|
|
->assertNotified($this->expectedSentNotification());
|
|
|
|
MailNotification::assertNothingSent();
|
|
}
|
|
|
|
public function test_repeated_reset_requests_for_a_registered_email_keep_reporting_success(): void
|
|
{
|
|
MailNotification::fake();
|
|
|
|
$user = User::factory()->admin()->create([
|
|
'email' => 'registered-repeat@example.com',
|
|
]);
|
|
|
|
$page = Livewire::test(RequestPasswordReset::class);
|
|
|
|
// First request creates a reset token; the second, within Laravel's
|
|
// default 60s broker throttle, would surface Password::RESET_THROTTLED
|
|
// instead of Password::RESET_LINK_SENT without the override above.
|
|
// The email field is re-set before each call because a successful
|
|
// `request()` resets the form (see the base page's `$this->form->fill()`).
|
|
$page->set('data.email', $user->email)
|
|
->call('request')
|
|
->assertNotified($this->expectedSentNotification());
|
|
|
|
$page->set('data.email', $user->email)
|
|
->call('request')
|
|
->assertNotified($this->expectedSentNotification());
|
|
}
|
|
|
|
private function expectedSentNotification(): FilamentNotification
|
|
{
|
|
return FilamentNotification::make()
|
|
->title(__(Password::RESET_LINK_SENT))
|
|
->body(__('filament-panels::auth/pages/password-reset/request-password-reset.notifications.sent.body'))
|
|
->success();
|
|
}
|
|
}
|