withSession(['_token' => 'test-token']) ->post('/login', array_merge(['_token' => 'test-token'], $data)); } it('renders the login page', function () { $this->get('/login') ->assertOk() ->assertSee('CluPilot') ->assertSee('name="email"', false); }); it('logs in with valid credentials and redirects to the dashboard', function () { $user = User::factory()->create(['password' => Hash::make('secret-password')]); loginPost(['email' => $user->email, 'password' => 'secret-password']) ->assertRedirect('/dashboard'); $this->assertAuthenticatedAs($user); }); it('still sends an already signed-in customer to the portal dashboard, not the console', function () { // The mirror of OperatorLoginTest's "sends an already signed-in operator // back to the console" — the redirectUsersTo() override that fixes that // is keyed on AdminArea::isConsole($request), so a plain portal request // must stay on the path it always took. $user = User::factory()->create(); $this->actingAs($user) ->get('/login') ->assertRedirect('/dashboard'); }); it('rejects invalid credentials', function () { $user = User::factory()->create(['password' => Hash::make('secret-password')]); loginPost(['email' => $user->email, 'password' => 'wrong-password']) ->assertSessionHasErrors('email'); $this->assertGuest(); }); it('throttles repeated failed attempts', function () { $user = User::factory()->create(['password' => Hash::make('secret-password')]); // Exceed the 5/min login limiter. foreach (range(1, 6) as $ignored) { loginPost(['email' => $user->email, 'password' => 'wrong-password']); } // Once throttled, even correct credentials are refused. loginPost(['email' => $user->email, 'password' => 'secret-password']); $this->assertGuest(); });