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:
Max
2026-01-27 11:03:55 +07:00
parent e9e6fadb1d
commit 9b79856827
49 changed files with 2411 additions and 878 deletions

View 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');
});
});