import { test, expect } from '@playwright/test'; import { AxeBuilder } from '@axe-core/playwright'; test.describe('Accessible Spinner Component', () => { // Before each test, navigate to the specific EJS view serving the spinner test.beforeEach(async ({ page }) => { // Assuming your test harness routes this to /test/spinner await page.goto('/test/spinner'); }); test('should pass AAA accessibility audits', async ({ page }) => { // Wait for the component to be fully hydrated await page.waitForLoadState('networkidle'); // Run the Axe-core engine against the page const accessibilityScanResults = await new AxeBuilder({ page }) .withTags(['wcag2a', 'wcag2aa', 'wcag2aaa', 'best-practice']) .analyze(); // If there are violations, the test fails and prints them in the console expect(accessibilityScanResults.violations).toEqual([]); }); test('should render correct ARIA attributes and variant classes based on props', async ({ page }) => { // Test Default Spinner const defaultSpinner = page.locator('#example-spinner'); await expect(defaultSpinner).toBeVisible(); await expect(defaultSpinner).toHaveAttribute('aria-busy', 'true'); // Ensure no extra variant classes leaked into the default spinner await expect(defaultSpinner).not.toHaveClass(/inline/); await expect(defaultSpinner).not.toHaveClass(/fast|slow/); // Test Inline Spinner const inlineSpinner = page.locator('#inline-spinner'); await expect(inlineSpinner).toHaveClass(/inline/); await expect(inlineSpinner).toHaveAttribute('aria-busy', 'true'); // Test Speed Variants const slowSpinner = page.locator('#slow-spinner'); await expect(slowSpinner).toHaveClass(/slow/); const fastSpinner = page.locator('#fast-spinner'); await expect(fastSpinner).toHaveClass(/fast/); // Test Combo (Slow + Inline) const comboSpinner = page.locator('#slow-inline-spinner'); await expect(comboSpinner).toHaveClass(/inline/); await expect(comboSpinner).toHaveClass(/slow/); }); test('visual regression: component variants render correctly without layout shifts', async ({ page }) => { // We capture the entire
block to ensure all variants render correctly relative to standard text. const mainContent = page.locator('main'); // CRITICAL: Because spinners use CSS @keyframes, the rotation angle will be slightly different // every time Playwright takes a screenshot, causing the test to flake and fail. // `animations: 'disabled'` tells Playwright to pause all CSS animations and transitions instantly. await expect(mainContent).toHaveScreenshot('spinner-all-variants.png', { animations: 'disabled' }); }); });