Files
Claude-Code-Workflow/ccw/frontend/tests/e2e/settings-page.spec.ts
catlog22 81725c94b1 Add E2E tests for internationalization across multiple pages
- Implemented navigation.spec.ts to test language switching and translation of navigation elements.
- Created sessions-page.spec.ts to verify translations on the sessions page, including headers, status badges, and date formatting.
- Developed settings-page.spec.ts to ensure settings page content is translated and persists across sessions.
- Added skills-page.spec.ts to validate translations for skill categories, action buttons, and empty states.
2026-01-30 22:54:21 +08:00

236 lines
8.4 KiB
TypeScript

// ========================================
// E2E Tests: Settings Page i18n
// ========================================
// Tests for settings page internationalization
import { test, expect } from '@playwright/test';
import {
switchLanguageAndVerify,
verifyI18nState,
verifyPersistenceAfterReload,
} from './helpers/i18n-helpers';
test.describe('[Settings Page] - i18n E2E Tests', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/', { waitUntil: 'networkidle' });
// Navigate to settings page
const settingsLink = page.getByRole('link', { name: /settings/i });
const isVisible = await settingsLink.isVisible().catch(() => false);
if (isVisible) {
await settingsLink.click();
await page.waitForLoadState('networkidle');
}
});
/**
* SET-01: Verify settings page render in English
* Priority: P0
*/
test('SET-01: should render settings page in English', async ({ page }) => {
// Verify initial locale is English
const lang = await page.evaluate(() => document.documentElement.lang);
expect(lang).toBe('en');
// Verify settings page has English content
const pageContent = await page.content();
expect(pageContent).toBeTruthy();
// Look for settings-related headings or labels
const heading = page.getByRole('heading', { name: /settings/i });
const isVisible = await heading.isVisible().catch(() => false);
if (isVisible) {
await expect(heading).toBeVisible();
}
});
/**
* SET-02: Verify settings page render in Chinese
* Priority: P0
*/
test('SET-02: should render settings page in Chinese', async ({ page }) => {
const languageSwitcher = page.getByRole('combobox', { name: /select language/i }).first();
// Switch to Chinese
await switchLanguageAndVerify(page, 'zh', languageSwitcher);
// Verify i18n state
await verifyI18nState(page, 'zh');
// Verify settings page has Chinese content
const pageContent = await page.content();
expect(pageContent).toMatch(/[\u4e00-\u9fa5]/);
});
/**
* SET-03: Verify localStorage persists locale selection
* Priority: P0
*/
test('SET-03: should persist locale selection to localStorage', async ({ page }) => {
const languageSwitcher = page.getByRole('combobox', { name: /select language/i }).first();
// Switch to Chinese
await switchLanguageAndVerify(page, 'zh', languageSwitcher);
// Verify localStorage contains locale
const storage = await page.evaluate(() => {
const item = localStorage.getItem('ccw-app-store');
return item ? JSON.parse(item) : null;
});
expect(storage).not.toBeNull();
expect(storage?.state?.locale).toBe('zh');
// Verify persistence after reload
await verifyPersistenceAfterReload(page, 'zh');
});
/**
* SET-04: Verify aria-label updates on settings form
* Priority: P0
*/
test('SET-04: should update aria-labels on settings form controls', async ({ page }) => {
// Find form controls with aria-label
const formInputs = page.locator('input[aria-label], select[aria-label], button[aria-label]').first();
const isVisible = await formInputs.isVisible().catch(() => false);
if (isVisible) {
// Get initial aria-label
const initialAriaLabel = await formInputs.getAttribute('aria-label');
expect(initialAriaLabel).toBeTruthy();
// Switch to Chinese
const languageSwitcher = page.getByRole('combobox', { name: /select language/i }).first();
await switchLanguageAndVerify(page, 'zh', languageSwitcher);
// Get updated aria-label
const updatedAriaLabel = await formInputs.getAttribute('aria-label');
expect(updatedAriaLabel).toBeTruthy();
// Aria-label should be different (translated)
// Note: Some aria-labels might not change if they're UI-independent
if (initialAriaLabel === updatedAriaLabel) {
// If same, verify at least lang attribute changed
const lang = await page.evaluate(() => document.documentElement.lang);
expect(lang).toBe('zh');
}
}
});
/**
* SET-05: Verify form input placeholders are translated
* Priority: P0
*/
test('SET-05: should translate form input placeholders', async ({ page }) => {
// Find inputs with placeholders
const inputsWithPlaceholder = page.locator('input[placeholder]').first();
const isVisible = await inputsWithPlaceholder.isVisible().catch(() => false);
if (isVisible) {
// Get initial placeholder
const initialPlaceholder = await inputsWithPlaceholder.getAttribute('placeholder');
expect(initialPlaceholder).toBeTruthy();
// Switch to Chinese
const languageSwitcher = page.getByRole('combobox', { name: /select language/i }).first();
await switchLanguageAndVerify(page, 'zh', languageSwitcher);
// Get updated placeholder
const updatedPlaceholder = await inputsWithPlaceholder.getAttribute('placeholder');
// Placeholder should be different (translated) or contain Chinese characters
if (updatedPlaceholder) {
const hasChineseOrDifferent = updatedPlaceholder !== initialPlaceholder ||
/[\u4e00-\u9fa5]/.test(updatedPlaceholder);
expect(hasChineseOrDifferent).toBeTruthy();
}
}
});
/**
* Additional: Verify save/cancel buttons are translated
*/
test('should translate save and cancel buttons', async ({ page }) => {
// Find action buttons
const saveButton = page.getByRole('button', { name: /save|apply/i }).first();
const isSaveVisible = await saveButton.isVisible().catch(() => false);
if (isSaveVisible) {
// Get initial button text
const initialText = await saveButton.textContent();
expect(initialText).toBeTruthy();
// Switch to Chinese
const languageSwitcher = page.getByRole('combobox', { name: /select language/i }).first();
await switchLanguageAndVerify(page, 'zh', languageSwitcher);
// Get updated button text
const updatedText = await saveButton.textContent();
expect(updatedText).toBeTruthy();
// Text should be different (translated) or contain Chinese characters
const hasChineseOrDifferent = updatedText !== initialText ||
/[\u4e00-\u9fa5]/.test(updatedText || '');
expect(hasChineseOrDifferent).toBeTruthy();
}
});
/**
* Additional: Verify settings state persists across sessions
*/
test('should maintain language preference across browser sessions', async ({ page, context }) => {
const languageSwitcher = page.getByRole('combobox', { name: /select language/i }).first();
// Switch to Chinese
await switchLanguageAndVerify(page, 'zh', languageSwitcher);
// Close and reopen page
await page.close();
const newPage = await context.newPage();
await newPage.goto('/', { waitUntil: 'networkidle' });
// Navigate to settings again
const settingsLink = newPage.getByRole('link', { name: /settings/i });
const isVisible = await settingsLink.isVisible().catch(() => false);
if (isVisible) {
await settingsLink.click();
await newPage.waitForLoadState('networkidle');
}
// Verify language is still Chinese (check text content)
const newLanguageSwitcher = newPage.getByRole('combobox', { name: /select language/i }).first();
await expect(newLanguageSwitcher).toContainText('中文');
const lang = await newPage.evaluate(() => document.documentElement.lang);
expect(lang).toBe('zh');
});
/**
* Additional: Verify form validation messages are translated
*/
test('should translate form validation messages', async ({ page }) => {
// Try to find a required input
const requiredInput = page.locator('input[required], select[required]').first();
const isVisible = await requiredInput.isVisible().catch(() => false);
if (isVisible) {
// Get validation message in English
const englishMessage = await requiredInput.evaluate(el =>
(el as HTMLInputElement).validationMessage
);
// Switch to Chinese
const languageSwitcher = page.getByRole('combobox', { name: /select language/i }).first();
await switchLanguageAndVerify(page, 'zh', languageSwitcher);
// Note: Browser validation messages might not translate
// This test verifies the mechanism exists even if browser provides English
const lang = await page.evaluate(() => document.documentElement.lang);
expect(lang).toBe('zh');
}
});
});