user = User::factory()->create([ 'email' => 'test@example.com', 'password' => bcrypt('password'), ]); } /** @test */ public function it_renders_the_login_component() { $component = Livewire::test(Login::class); $component->assertStatus(200); $component->assertSee('Email'); $component->assertSee('Password'); } /** @test */ public function it_validates_required_email_field() { $component = Livewire::test(Login::class); $component->set('email', '') ->call('login') ->assertHasErrors(['email' => 'required']); } /** @test */ public function it_validates_email_format() { $component = Livewire::test(Login::class); $component->set('email', 'invalid-email') ->call('login') ->assertHasErrors(['email' => 'email']); } /** @test */ public function it_validates_required_password_field() { $component = Livewire::test(Login::class); $component->set('password', '') ->call('login') ->assertHasErrors(['password' => 'required']); } /** @test */ public function it_authenticates_user_with_valid_credentials() { $component = Livewire::test(Login::class); $component->set('email', 'test@example.com') ->set('password', 'password') ->call('login'); $this->assertAuthenticatedAs($this->user); $component->assertRedirect('/dashboard'); } /** @test */ public function it_fails_authentication_with_invalid_credentials() { $component = Livewire::test(Login::class); $component->set('email', 'test@example.com') ->set('password', 'wrong-password') ->call('login') ->assertHasErrors('email'); } /** @test */ public function it_handles_rate_limiting() { // Clear any existing rate limit attempts RateLimiter::clear('login:' . request()->ip()); // Exceed the rate limit (5 attempts by default) for ($i = 0; $i < 6; $i++) { $component = Livewire::test(Login::class); $component->set('email', 'test@example.com') ->set('password', 'wrong-password') ->call('login'); } // Should be rate limited now $component = Livewire::test(Login::class); $component->set('email', 'test@example.com') ->set('password', 'password') ->call('login') ->assertHasErrors('email'); } /** @test */ public function it_redirects_authenticated_users_away() { $this->actingAs($this->user); $component = Livewire::test(Login::class); // Component should still render but show logged in state $component->assertStatus(200); } /** @test */ public function it_handles_lockout_event() { // Clear any existing rate limit attempts RateLimiter::clear('login:' . request()->ip()); // Exceed the rate limit to trigger lockout for ($i = 0; $i < 6; $i++) { $component = Livewire::test(Login::class); $component->set('email', 'test@example.com') ->set('password', 'wrong-password') ->call('login'); } // Should be rate limited now $component = Livewire::test(Login::class); $component->set('email', 'test@example.com') ->set('password', 'password') ->call('login') ->assertHasErrors('email'); } /** @test */ public function it_clears_session_after_successful_login() { Session::put('old_url', '/some-page'); $component = Livewire::test(Login::class); $component->set('email', 'test@example.com') ->set('password', 'password') ->call('login'); $this->assertAuthenticatedAs($this->user); // User should be authenticated after successful login $this->assertTrue(Auth::check()); } /** @test */ public function it_remember_me_functionality_works() { $component = Livewire::test(Login::class); $component->set('email', 'test@example.com') ->set('password', 'password') ->set('remember', true) ->call('login'); $this->assertAuthenticatedAs($this->user); } }