feat(ui): implement 'Twilight Velvet' dark theme and fix visibility issues
- Add 'Twilight Velvet' color palette to globals.css with OKLCH values - Update SettingsPage headers, cards, and dialogs to use semantic theme variables - Update HistoryCard, HistoryFeed, and DraftContent to support dark mode - Update ProviderSelector and ProviderList to use custom card background (#2A2A3D) - Add ThemeToggle component with improved visibility - Ensure consistent use of 'bg-card', 'text-foreground', and 'text-muted-foreground'
This commit is contained in:
70
tests/e2e/gatekeeper.spec.ts
Normal file
70
tests/e2e/gatekeeper.spec.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.describe('Gatekeeper Security', () => {
|
||||
// Use a distinct context to ensure no previous state
|
||||
test.use({ storageState: { cookies: [], origins: [] } });
|
||||
|
||||
test('should redirect unauthenticated users to login', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await expect(page).toHaveURL('/login');
|
||||
await expect(page.getByRole('heading', { name: 'Gatekeeper' })).toBeVisible();
|
||||
});
|
||||
|
||||
test('should allow login with correct password', async ({ page }) => {
|
||||
await page.goto('/login');
|
||||
|
||||
// Assuming APP_PASSWORD is "password" per .env.example
|
||||
await page.fill('input[type="password"]', 'password');
|
||||
await page.click('button[type="submit"]');
|
||||
|
||||
await expect(page).toHaveURL('/');
|
||||
await expect(page.getByRole('heading', { name: 'My Journal' })).toBeVisible();
|
||||
});
|
||||
|
||||
test('should show error with incorrect password', async ({ page }) => {
|
||||
await page.goto('/login');
|
||||
|
||||
await page.fill('input[type="password"]', 'wrongpassword');
|
||||
await page.click('button[type="submit"]');
|
||||
|
||||
await expect(page.getByText('Invalid password')).toBeVisible();
|
||||
await expect(page).toHaveURL('/login');
|
||||
});
|
||||
|
||||
test('should persist session after reload', async ({ page }) => {
|
||||
// Login first
|
||||
await page.goto('/login');
|
||||
await page.fill('input[type="password"]', 'password');
|
||||
await page.click('button[type="submit"]');
|
||||
await expect(page).toHaveURL('/');
|
||||
|
||||
// Reload
|
||||
await page.reload();
|
||||
await expect(page).toHaveURL('/');
|
||||
await expect(page.getByRole('heading', { name: 'My Journal' })).toBeVisible();
|
||||
});
|
||||
|
||||
test('should logout successfully', async ({ page }) => {
|
||||
// Login first
|
||||
await page.goto('/login');
|
||||
await page.fill('input[type="password"]', 'password');
|
||||
await page.click('button[type="submit"]');
|
||||
await expect(page).toHaveURL('/');
|
||||
|
||||
// Go to settings
|
||||
await page.goto('/settings');
|
||||
|
||||
// Handle confirm dialog
|
||||
page.on('dialog', dialog => dialog.accept());
|
||||
|
||||
// Click logout
|
||||
await page.getByRole('button', { name: 'Logout' }).click();
|
||||
|
||||
// Verify redirect
|
||||
await expect(page).toHaveURL('/login');
|
||||
|
||||
// Verify access denied
|
||||
await page.goto('/');
|
||||
await expect(page).toHaveURL('/login');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user