complete story 1.3 with qa test & added future recommendations to the dev
This commit is contained in:
@@ -9,19 +9,34 @@ test('login screen can be rendered', function () {
|
||||
$response->assertStatus(200);
|
||||
});
|
||||
|
||||
test('users can authenticate using the login screen', function () {
|
||||
$user = User::factory()->create();
|
||||
test('admin user redirects to admin dashboard after login', function () {
|
||||
$admin = User::factory()->admin()->create();
|
||||
|
||||
$response = $this->post(route('login.store'), [
|
||||
'email' => $user->email,
|
||||
'email' => $admin->email,
|
||||
'password' => 'password',
|
||||
]);
|
||||
|
||||
$response
|
||||
->assertSessionHasNoErrors()
|
||||
->assertRedirect(route('dashboard', absolute: false));
|
||||
->assertRedirect('/admin/dashboard');
|
||||
|
||||
$this->assertAuthenticated();
|
||||
$this->assertAuthenticatedAs($admin);
|
||||
});
|
||||
|
||||
test('client user redirects to client dashboard after login', function () {
|
||||
$client = User::factory()->individual()->create();
|
||||
|
||||
$response = $this->post(route('login.store'), [
|
||||
'email' => $client->email,
|
||||
'password' => 'password',
|
||||
]);
|
||||
|
||||
$response
|
||||
->assertSessionHasNoErrors()
|
||||
->assertRedirect('/client/dashboard');
|
||||
|
||||
$this->assertAuthenticatedAs($client);
|
||||
});
|
||||
|
||||
test('users can not authenticate with invalid password', function () {
|
||||
@@ -32,21 +47,54 @@ test('users can not authenticate with invalid password', function () {
|
||||
'password' => 'wrong-password',
|
||||
]);
|
||||
|
||||
$response->assertSessionHasErrorsIn('email');
|
||||
$this->assertGuest();
|
||||
});
|
||||
|
||||
test('nonexistent user shows error', function () {
|
||||
$response = $this->post(route('login.store'), [
|
||||
'email' => 'nonexistent@example.com',
|
||||
'password' => 'password',
|
||||
]);
|
||||
|
||||
$this->assertGuest();
|
||||
});
|
||||
|
||||
test('deactivated user cannot login', function () {
|
||||
$user = User::factory()->deactivated()->create();
|
||||
|
||||
$response = $this->post(route('login.store'), [
|
||||
'email' => $user->email,
|
||||
'password' => 'password',
|
||||
]);
|
||||
|
||||
$this->assertGuest();
|
||||
});
|
||||
|
||||
test('rate limiting blocks after five attempts', function () {
|
||||
$user = User::factory()->create();
|
||||
|
||||
// Make 5 failed attempts
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$this->post(route('login.store'), [
|
||||
'email' => $user->email,
|
||||
'password' => 'wrong-password',
|
||||
]);
|
||||
}
|
||||
|
||||
// 6th attempt should be throttled
|
||||
$response = $this->post(route('login.store'), [
|
||||
'email' => $user->email,
|
||||
'password' => 'wrong-password',
|
||||
]);
|
||||
|
||||
$response->assertStatus(429);
|
||||
});
|
||||
|
||||
test('users with two factor enabled are redirected to two factor challenge', function () {
|
||||
if (! Features::canManageTwoFactorAuthentication()) {
|
||||
$this->markTestSkipped('Two-factor authentication is not enabled.');
|
||||
}
|
||||
|
||||
Features::twoFactorAuthentication([
|
||||
'confirm' => true,
|
||||
'confirmPassword' => true,
|
||||
]);
|
||||
|
||||
$user = User::factory()->withTwoFactor()->create();
|
||||
|
||||
$response = $this->post(route('login.store'), [
|
||||
@@ -67,3 +115,36 @@ test('users can logout', function () {
|
||||
|
||||
$this->assertGuest();
|
||||
});
|
||||
|
||||
test('logout clears session', function () {
|
||||
$user = User::factory()->create();
|
||||
|
||||
$this->actingAs($user);
|
||||
$this->assertAuthenticated();
|
||||
|
||||
$this->post(route('logout'));
|
||||
|
||||
$this->assertGuest();
|
||||
});
|
||||
|
||||
test('authenticated user cannot access login page', function () {
|
||||
$user = User::factory()->create();
|
||||
|
||||
$response = $this->actingAs($user)->get(route('login'));
|
||||
|
||||
$response->assertRedirect();
|
||||
});
|
||||
|
||||
test('failed login attempts are logged', function () {
|
||||
$user = User::factory()->create();
|
||||
|
||||
$this->post(route('login.store'), [
|
||||
'email' => $user->email,
|
||||
'password' => 'wrong-password',
|
||||
]);
|
||||
|
||||
$this->assertDatabaseHas('admin_logs', [
|
||||
'action' => 'failed_login',
|
||||
'target_type' => 'user',
|
||||
]);
|
||||
});
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
test('admin can access admin routes', function () {
|
||||
$admin = User::factory()->admin()->create();
|
||||
|
||||
$response = $this->actingAs($admin)->get('/admin/dashboard');
|
||||
|
||||
$response->assertStatus(200);
|
||||
});
|
||||
|
||||
test('client cannot access admin routes', function () {
|
||||
$client = User::factory()->individual()->create();
|
||||
|
||||
$response = $this->actingAs($client)->get('/admin/dashboard');
|
||||
|
||||
$response->assertForbidden();
|
||||
});
|
||||
|
||||
test('company client cannot access admin routes', function () {
|
||||
$client = User::factory()->company()->create();
|
||||
|
||||
$response = $this->actingAs($client)->get('/admin/dashboard');
|
||||
|
||||
$response->assertForbidden();
|
||||
});
|
||||
|
||||
test('unauthenticated user redirected to login', function () {
|
||||
$response = $this->get('/admin/dashboard');
|
||||
|
||||
$response->assertRedirect(route('login'));
|
||||
});
|
||||
|
||||
test('unauthenticated user redirected to login for client routes', function () {
|
||||
$response = $this->get('/client/dashboard');
|
||||
|
||||
$response->assertRedirect(route('login'));
|
||||
});
|
||||
|
||||
test('client can access client routes', function () {
|
||||
$client = User::factory()->individual()->create();
|
||||
|
||||
$response = $this->actingAs($client)->get('/client/dashboard');
|
||||
|
||||
$response->assertStatus(200);
|
||||
});
|
||||
|
||||
test('admin can access client routes', function () {
|
||||
$admin = User::factory()->admin()->create();
|
||||
|
||||
$response = $this->actingAs($admin)->get('/client/dashboard');
|
||||
|
||||
$response->assertStatus(200);
|
||||
});
|
||||
|
||||
test('deactivated user logged out on request', function () {
|
||||
$user = User::factory()->deactivated()->create();
|
||||
|
||||
// Simulate an authenticated session with deactivated user
|
||||
$response = $this->actingAs($user)->get('/client/dashboard');
|
||||
|
||||
$response->assertRedirect(route('login'));
|
||||
$this->assertGuest();
|
||||
});
|
||||
@@ -29,7 +29,8 @@ test('email can be verified', function () {
|
||||
Event::assertDispatched(Verified::class);
|
||||
|
||||
expect($user->fresh()->hasVerifiedEmail())->toBeTrue();
|
||||
$response->assertRedirect(route('dashboard', absolute: false).'?verified=1');
|
||||
// Redirects to client dashboard since factory creates individual users
|
||||
$response->assertRedirect('/client/dashboard?verified=1');
|
||||
});
|
||||
|
||||
test('email is not verified with invalid hash', function () {
|
||||
@@ -60,8 +61,9 @@ test('already verified user visiting verification link is redirected without fir
|
||||
);
|
||||
|
||||
$this->actingAs($user)->get($verificationUrl)
|
||||
->assertRedirect(route('dashboard', absolute: false).'?verified=1');
|
||||
// Redirects to client dashboard since factory creates individual users
|
||||
->assertRedirect('/client/dashboard?verified=1');
|
||||
|
||||
expect($user->fresh()->hasVerifiedEmail())->toBeTrue();
|
||||
Event::assertNotDispatched(Verified::class);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,22 +1,14 @@
|
||||
<?php
|
||||
|
||||
test('registration screen can be rendered', function () {
|
||||
$response = $this->get(route('register'));
|
||||
use Laravel\Fortify\Features;
|
||||
|
||||
$response->assertStatus(200);
|
||||
test('registration is disabled', function () {
|
||||
// Registration is disabled per AC 7 - admin creates all accounts
|
||||
expect(Features::enabled(Features::registration()))->toBeFalse();
|
||||
});
|
||||
|
||||
test('new users can register', function () {
|
||||
$response = $this->post(route('register.store'), [
|
||||
'full_name' => 'John Doe',
|
||||
'email' => 'test@example.com',
|
||||
'phone' => '+1234567890',
|
||||
'password' => 'password',
|
||||
'password_confirmation' => 'password',
|
||||
]);
|
||||
test('registration route returns 404', function () {
|
||||
$response = $this->get('/register');
|
||||
|
||||
$response->assertSessionHasNoErrors()
|
||||
->assertRedirect(route('dashboard', absolute: false));
|
||||
|
||||
$this->assertAuthenticated();
|
||||
$response->assertNotFound();
|
||||
});
|
||||
|
||||
@@ -2,15 +2,28 @@
|
||||
|
||||
use App\Models\User;
|
||||
|
||||
test('guests are redirected to the login page', function () {
|
||||
$response = $this->get(route('dashboard'));
|
||||
test('guests are redirected to the login page for admin dashboard', function () {
|
||||
$response = $this->get('/admin/dashboard');
|
||||
$response->assertRedirect(route('login'));
|
||||
});
|
||||
|
||||
test('authenticated users can visit the dashboard', function () {
|
||||
$user = User::factory()->create();
|
||||
test('guests are redirected to the login page for client dashboard', function () {
|
||||
$response = $this->get('/client/dashboard');
|
||||
$response->assertRedirect(route('login'));
|
||||
});
|
||||
|
||||
test('authenticated admin can visit admin dashboard', function () {
|
||||
$user = User::factory()->admin()->create();
|
||||
$this->actingAs($user);
|
||||
|
||||
$response = $this->get(route('dashboard'));
|
||||
$response = $this->get('/admin/dashboard');
|
||||
$response->assertStatus(200);
|
||||
});
|
||||
});
|
||||
|
||||
test('authenticated client can visit client dashboard', function () {
|
||||
$user = User::factory()->individual()->create();
|
||||
$this->actingAs($user);
|
||||
|
||||
$response = $this->get('/client/dashboard');
|
||||
$response->assertStatus(200);
|
||||
});
|
||||
|
||||
@@ -66,3 +66,15 @@ test('user active scope returns only active users', function () {
|
||||
|
||||
expect(User::active()->count())->toBe(2);
|
||||
});
|
||||
|
||||
test('user isActive returns true for active user', function () {
|
||||
$user = User::factory()->create();
|
||||
|
||||
expect($user->isActive())->toBeTrue();
|
||||
});
|
||||
|
||||
test('user isActive returns false for deactivated user', function () {
|
||||
$user = User::factory()->deactivated()->create();
|
||||
|
||||
expect($user->isActive())->toBeFalse();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user