test(focus-rings): add failing Playwright tests for --c-focus-ring token and element ring colors
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
88
frontend/e2e/focus-rings.spec.ts
Normal file
88
frontend/e2e/focus-rings.spec.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
// Expected focus ring resolved colors
|
||||
// Light: --c-focus-ring: #012851 (brand-navy)
|
||||
const FOCUS_RING_LIGHT = 'rgb(1, 40, 81)';
|
||||
// Dark: --c-focus-ring: #a1dcd8 (brand-mint)
|
||||
const FOCUS_RING_DARK = 'rgb(161, 220, 216)';
|
||||
|
||||
test.describe('Focus ring token — CSS custom property', () => {
|
||||
test('--c-focus-ring is defined in light mode', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await page.waitForSelector('[data-hydrated]');
|
||||
|
||||
const value = await page.evaluate(() =>
|
||||
getComputedStyle(document.documentElement).getPropertyValue('--c-focus-ring').trim()
|
||||
);
|
||||
expect(value).toBe('#012851');
|
||||
});
|
||||
|
||||
test('--c-focus-ring is defined in dark mode', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await page.waitForSelector('[data-hydrated]');
|
||||
await page.evaluate(() => document.documentElement.setAttribute('data-theme', 'dark'));
|
||||
|
||||
const value = await page.evaluate(() =>
|
||||
getComputedStyle(document.documentElement).getPropertyValue('--c-focus-ring').trim()
|
||||
);
|
||||
expect(value).toBe('#a1dcd8');
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Focus ring — header interactive elements', () => {
|
||||
test('ThemeToggle has brand-navy ring in light mode', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await page.waitForSelector('[data-hydrated]');
|
||||
|
||||
await page.getByRole('button', { name: /dark mode|dunkelmodus/i }).focus();
|
||||
const boxShadow = await page.evaluate(
|
||||
() => getComputedStyle(document.activeElement as HTMLElement).boxShadow
|
||||
);
|
||||
expect(boxShadow).toContain(FOCUS_RING_LIGHT);
|
||||
});
|
||||
|
||||
test('AppNav link has brand-mint ring in dark mode', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await page.waitForSelector('[data-hydrated]');
|
||||
await page.evaluate(() => document.documentElement.setAttribute('data-theme', 'dark'));
|
||||
|
||||
// Focus first desktop nav link
|
||||
await page.locator('header nav').getByRole('link').first().focus();
|
||||
const boxShadow = await page.evaluate(
|
||||
() => getComputedStyle(document.activeElement as HTMLElement).boxShadow
|
||||
);
|
||||
expect(boxShadow).toContain(FOCUS_RING_DARK);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Focus ring — form inputs', () => {
|
||||
test.use({ storageState: { cookies: [], origins: [] } });
|
||||
|
||||
test('login username input has brand-mint ring in dark mode', async ({ page }) => {
|
||||
await page.goto('/login');
|
||||
await page.evaluate(() => document.documentElement.setAttribute('data-theme', 'dark'));
|
||||
|
||||
await page.locator('#username').focus();
|
||||
const boxShadow = await page.evaluate(
|
||||
() => getComputedStyle(document.activeElement as HTMLElement).boxShadow
|
||||
);
|
||||
expect(boxShadow).toContain(FOCUS_RING_DARK);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Focus ring — PersonTypeahead', () => {
|
||||
test('PersonTypeahead input has brand-navy ring in light mode', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await page.waitForSelector('[data-hydrated]');
|
||||
|
||||
// Open advanced filter panel to expose the sender PersonTypeahead
|
||||
await page.getByRole('button', { name: /filter/i }).click();
|
||||
await page.waitForSelector('#senderId-search');
|
||||
|
||||
await page.locator('#senderId-search').focus();
|
||||
const boxShadow = await page.evaluate(
|
||||
() => getComputedStyle(document.activeElement as HTMLElement).boxShadow
|
||||
);
|
||||
expect(boxShadow).toContain(FOCUS_RING_LIGHT);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user