diff --git a/tests/a11y/domains.a11y.spec.ts b/tests/a11y/domains.a11y.spec.ts new file mode 100644 index 00000000..eb981547 --- /dev/null +++ b/tests/a11y/domains.a11y.spec.ts @@ -0,0 +1,35 @@ +import { test } from '../fixtures/a11y'; +import { waitForLoadingComplete } from '../utils/wait-helpers'; +import { expectNoA11yViolations } from '../utils/a11y-helpers'; +import { getBaselinedRuleIds } from './a11y-baseline'; + +const domainRoutes = [ + { route: '/domains', name: 'domains' }, + { route: '/remote-servers', name: 'remote servers' }, +] as const; + +test.describe('Accessibility: Domains & Remote Servers', () => { + test.describe.configure({ mode: 'parallel' }); + + for (const { route, name } of domainRoutes) { + test(`${name} page has no critical a11y violations`, async ({ page, makeAxeBuilder }) => { + await test.step(`Navigate to ${name}`, async () => { + await page.goto(route); + await waitForLoadingComplete(page); + }); + + await test.step('Run axe accessibility scan', async () => { + const results = await makeAxeBuilder().analyze(); + + test.info().attach('a11y-results', { + body: JSON.stringify(results.violations, null, 2), + contentType: 'application/json', + }); + + expectNoA11yViolations(results, { + knownViolations: getBaselinedRuleIds(route), + }); + }); + }); + } +}); diff --git a/tests/a11y/notifications.a11y.spec.ts b/tests/a11y/notifications.a11y.spec.ts new file mode 100644 index 00000000..1befde48 --- /dev/null +++ b/tests/a11y/notifications.a11y.spec.ts @@ -0,0 +1,35 @@ +import { test } from '../fixtures/a11y'; +import { waitForLoadingComplete } from '../utils/wait-helpers'; +import { expectNoA11yViolations } from '../utils/a11y-helpers'; +import { getBaselinedRuleIds } from './a11y-baseline'; + +const notificationRoutes = [ + { route: '/settings/notifications', name: 'notifications' }, + { route: '/settings/smtp', name: 'SMTP settings' }, +] as const; + +test.describe('Accessibility: Notifications', () => { + test.describe.configure({ mode: 'parallel' }); + + for (const { route, name } of notificationRoutes) { + test(`${name} page has no critical a11y violations`, async ({ page, makeAxeBuilder }) => { + await test.step(`Navigate to ${name}`, async () => { + await page.goto(route); + await waitForLoadingComplete(page); + }); + + await test.step('Run axe accessibility scan', async () => { + const results = await makeAxeBuilder().analyze(); + + test.info().attach('a11y-results', { + body: JSON.stringify(results.violations, null, 2), + contentType: 'application/json', + }); + + expectNoA11yViolations(results, { + knownViolations: getBaselinedRuleIds(route), + }); + }); + }); + } +}); diff --git a/tests/a11y/setup.a11y.spec.ts b/tests/a11y/setup.a11y.spec.ts new file mode 100644 index 00000000..535f97d2 --- /dev/null +++ b/tests/a11y/setup.a11y.spec.ts @@ -0,0 +1,34 @@ +import { test } from '../fixtures/a11y'; +import { waitForLoadingComplete } from '../utils/wait-helpers'; +import { expectNoA11yViolations } from '../utils/a11y-helpers'; +import { getBaselinedRuleIds } from './a11y-baseline'; + +test.use({ storageState: { cookies: [], origins: [] } }); + +test.describe('Accessibility: Setup', () => { + test.describe.configure({ mode: 'parallel' }); + + test('setup page has no critical a11y violations', async ({ page, makeAxeBuilder }) => { + await test.step('Navigate to setup page', async () => { + await page.goto('/setup'); + + const url = page.url(); + test.skip(!url.includes('/setup'), 'Setup already complete — page redirected'); + + await waitForLoadingComplete(page); + }); + + await test.step('Run axe accessibility scan', async () => { + const results = await makeAxeBuilder().analyze(); + + test.info().attach('a11y-results', { + body: JSON.stringify(results.violations, null, 2), + contentType: 'application/json', + }); + + expectNoA11yViolations(results, { + knownViolations: getBaselinedRuleIds('/setup'), + }); + }); + }); +}); diff --git a/tests/a11y/tasks.a11y.spec.ts b/tests/a11y/tasks.a11y.spec.ts new file mode 100644 index 00000000..be15bc43 --- /dev/null +++ b/tests/a11y/tasks.a11y.spec.ts @@ -0,0 +1,39 @@ +import { test } from '../fixtures/a11y'; +import { waitForLoadingComplete } from '../utils/wait-helpers'; +import { expectNoA11yViolations } from '../utils/a11y-helpers'; +import { getBaselinedRuleIds } from './a11y-baseline'; + +const taskRoutes = [ + { route: '/tasks/backups', name: 'backups' }, + { route: '/tasks/logs', name: 'logs' }, + { route: '/tasks/import/caddyfile', name: 'Caddyfile import' }, + { route: '/tasks/import/crowdsec', name: 'CrowdSec import' }, + { route: '/tasks/import/npm', name: 'NPM import' }, + { route: '/tasks/import/json', name: 'JSON import' }, +] as const; + +test.describe('Accessibility: Tasks', () => { + test.describe.configure({ mode: 'parallel' }); + + for (const { route, name } of taskRoutes) { + test(`${name} page has no critical a11y violations`, async ({ page, makeAxeBuilder }) => { + await test.step(`Navigate to ${name}`, async () => { + await page.goto(route); + await waitForLoadingComplete(page); + }); + + await test.step('Run axe accessibility scan', async () => { + const results = await makeAxeBuilder().analyze(); + + test.info().attach('a11y-results', { + body: JSON.stringify(results.violations, null, 2), + contentType: 'application/json', + }); + + expectNoA11yViolations(results, { + knownViolations: getBaselinedRuleIds(route), + }); + }); + }); + } +});