- smartauth-login.spec.ts: Google Sign-In button presence, MFA challenge not shown initially - smartauth-mfa-settings.spec.ts: MFA status, setup/disable flows with API mocking - smartauth-security-dashboard.spec.ts: stats cards, login events table, suspicious filter - smartauth-devices.spec.ts: device list, trust badges, revoke all button - smartauth-passkeys.spec.ts: passkey list, add button, empty state, device type labels
85 lines
3.0 KiB
TypeScript
85 lines
3.0 KiB
TypeScript
import { test, expect } from '@playwright/test';
|
|
|
|
test.describe('SmartAuth: MFA Settings Page', () => {
|
|
test.beforeEach(async ({ page }) => {
|
|
// Simulate authenticated state with mock token
|
|
await page.goto('/login');
|
|
await page.evaluate(() => {
|
|
localStorage.setItem('admin_access_token', 'mock-token');
|
|
localStorage.setItem('admin_refresh_token', 'mock-refresh');
|
|
localStorage.setItem(
|
|
'admin_auth_user',
|
|
JSON.stringify({
|
|
email: 'admin@example.com',
|
|
name: 'Admin User',
|
|
role: 'super_admin',
|
|
})
|
|
);
|
|
});
|
|
});
|
|
|
|
test('security settings page loads', async ({ page }) => {
|
|
await page.goto('/settings/security');
|
|
await expect(page.getByText('Security Settings')).toBeVisible({ timeout: 10000 });
|
|
});
|
|
|
|
test('shows Two-Factor Authentication section', async ({ page }) => {
|
|
await page.goto('/settings/security');
|
|
await expect(page.getByText('Two-Factor Authentication')).toBeVisible({ timeout: 10000 });
|
|
});
|
|
|
|
test('shows setup button when MFA is not enabled', async ({ page }) => {
|
|
// Mock the MFA status API to return disabled
|
|
await page.route('**/api/auth/mfa/status', async route => {
|
|
await route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({ mfaEnabled: false, methods: [], recoveryCodesRemaining: 0 }),
|
|
});
|
|
});
|
|
await page.goto('/settings/security');
|
|
await expect(page.getByRole('button', { name: /set up authenticator/i })).toBeVisible({
|
|
timeout: 10000,
|
|
});
|
|
});
|
|
|
|
test('shows disable button when MFA is enabled', async ({ page }) => {
|
|
await page.route('**/api/auth/mfa/status', async route => {
|
|
await route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({ mfaEnabled: true, methods: ['totp'], recoveryCodesRemaining: 8 }),
|
|
});
|
|
});
|
|
await page.goto('/settings/security');
|
|
await expect(page.getByRole('button', { name: /disable two-factor/i })).toBeVisible({
|
|
timeout: 10000,
|
|
});
|
|
});
|
|
|
|
test('TOTP setup flow shows QR code', async ({ page }) => {
|
|
await page.route('**/api/auth/mfa/status', async route => {
|
|
await route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({ mfaEnabled: false, methods: [], recoveryCodesRemaining: 0 }),
|
|
});
|
|
});
|
|
await page.route('**/api/auth/mfa/totp/setup', async route => {
|
|
await route.fulfill({
|
|
status: 200,
|
|
contentType: 'application/json',
|
|
body: JSON.stringify({
|
|
otpauthUri: 'otpauth://totp/Test?secret=JBSWY3DPEHPK3PXP',
|
|
qrDataUrl: '',
|
|
recoveryCodes: ['ABC123', 'DEF456', 'GHI789', 'JKL012'],
|
|
}),
|
|
});
|
|
});
|
|
await page.goto('/settings/security');
|
|
await page.getByRole('button', { name: /set up authenticator/i }).click();
|
|
await expect(page.getByText('Set up authenticator')).toBeVisible();
|
|
await expect(page.getByText('Recovery Codes')).toBeVisible();
|
|
});
|
|
});
|