- theme-switch.spec.ts · 3 主题切换 + localStorage 持久化 + inline script 防闪烁 - chat-send-receive.spec.ts · 用户消息 → SSE 流式 → markdown 渲染 (content 字段) - form-submit-validation.spec.ts · SubmitButton 守卫 (Enter 触发 + mobile force) - plan-create-view.spec.ts · PlanSchema 真实结构 + section 形式详情页 - data-query-search.spec.ts · 院校/专业/分数线 真实接口 - review-flow-approve.spec.ts · 审核状态机 + 3 操作按钮 - poster-generate-download.spec.ts · 3 模板 + Zod url() 校验 G3 闸门 e2e 项: 84/84 passed (4 浏览器 × 21 测试)
44 lines
1.7 KiB
TypeScript
44 lines
1.7 KiB
TypeScript
/**
|
||
* V10 · Sprint 4 · T-B-23.1 · e2e: theme switch (3-mode persistence)
|
||
*
|
||
* V10 不变量 D2: light / dark / system
|
||
* ThemeToggle 实现:3 个 radio 按钮 + 同步 localStorage['theme-pref']
|
||
*/
|
||
import { test, expect } from '@playwright/test';
|
||
|
||
test.describe('Theme Switch (V10 Sprint 4 · T-B-23.1 · V10 不变量 D2)', () => {
|
||
test('3-theme switch + persistence', async ({ page }) => {
|
||
await page.goto('/');
|
||
|
||
const html = page.locator('html');
|
||
|
||
// 切换到亮色
|
||
await page.getByRole('radio', { name: '亮色' }).click();
|
||
await expect(html).toHaveClass(/light/);
|
||
await expect(page.getByRole('radio', { name: '亮色' })).toHaveAttribute('aria-checked', 'true');
|
||
|
||
// 切换到暗色
|
||
await page.getByRole('radio', { name: '暗色' }).click();
|
||
await expect(html).toHaveClass(/dark/);
|
||
await expect(page.getByRole('radio', { name: '暗色' })).toHaveAttribute('aria-checked', 'true');
|
||
|
||
// 切换到跟随系统
|
||
await page.getByRole('radio', { name: '系统' }).click();
|
||
await expect(html).toHaveClass(/light|dark/);
|
||
await expect(page.getByRole('radio', { name: '系统' })).toHaveAttribute('aria-checked', 'true');
|
||
|
||
// localStorage 持久化
|
||
const stored = await page.evaluate(() => localStorage.getItem('theme-pref'));
|
||
expect(stored).toBe('system');
|
||
|
||
// 刷新后保持
|
||
await page.reload();
|
||
await expect(page.getByRole('radio', { name: '系统' })).toHaveAttribute('aria-checked', 'true');
|
||
});
|
||
|
||
test('inline script prevents theme flash on first paint', async ({ page }) => {
|
||
await page.goto('/');
|
||
const htmlClass = await page.locator('html').getAttribute('class');
|
||
expect(htmlClass).toMatch(/light|dark/);
|
||
});
|
||
}); |