Add Prettier and ESLint tooling (Refs #77)
This commit is contained in:
@@ -9,7 +9,9 @@ import { statusPresentation } from '../../src/lib/ui/status.js';
|
||||
import { uiNow } from '../../src/lib/ui/stores/servers.js';
|
||||
import { gameEvent } from '../helpers/telemetry.js';
|
||||
|
||||
vi.mock('$app/stores', () => ({ page: writable({ url: new URL('http://localhost/?filter=occupied') }) }));
|
||||
vi.mock('$app/stores', () => ({
|
||||
page: writable({ url: new URL('http://localhost/?filter=occupied') })
|
||||
}));
|
||||
|
||||
describe('status accessibility', () => {
|
||||
it.each([
|
||||
@@ -19,14 +21,17 @@ describe('status accessibility', () => {
|
||||
['stale', 'Not responding', 'warning', 'triangle'],
|
||||
['offline', 'Offline', 'danger', 'square'],
|
||||
['queued', 'Queued', 'neutral', 'hollow']
|
||||
])('pairs %s with a consistent word and non-color cue without creating a live region', (state, label, tone, shape) => {
|
||||
expect(statusPresentation(state)).toEqual({ label, tone, shape });
|
||||
const body = render(StatusBadge, { props: { state } }).body;
|
||||
expect(body).toContain(label);
|
||||
expect(body).toContain(`shape-${shape}`);
|
||||
expect(body).toContain(`v-${tone}`);
|
||||
expect(body).not.toMatch(/role="status"|aria-live=/);
|
||||
});
|
||||
])(
|
||||
'pairs %s with a consistent word and non-color cue without creating a live region',
|
||||
(state, label, tone, shape) => {
|
||||
expect(statusPresentation(state)).toEqual({ label, tone, shape });
|
||||
const body = render(StatusBadge, { props: { state } }).body;
|
||||
expect(body).toContain(label);
|
||||
expect(body).toContain(`shape-${shape}`);
|
||||
expect(body).toContain(`v-${tone}`);
|
||||
expect(body).not.toMatch(/role="status"|aria-live=/);
|
||||
}
|
||||
);
|
||||
|
||||
it('provides a static accessible name only when an isolated pip needs one', () => {
|
||||
const decorative = render(StatusPip, { props: { health: 'online' } }).body;
|
||||
@@ -40,35 +45,47 @@ describe('status accessibility', () => {
|
||||
|
||||
it('names the card link from its title and keeps its clock and roster out of live regions', () => {
|
||||
const receivedAt = new Date(get(uiNow) - 10_000).toISOString();
|
||||
const body = render(ServerCard, { props: {
|
||||
name: 't5_zombie_theater_1', health: 'online', players: 4,
|
||||
telemetry: { ...gameEvent('heartbeat', 30, 4), receivedAt },
|
||||
activeSince: receivedAt, gameStartedAt: receivedAt,
|
||||
roster: [{ num: 0, name: 'Player One', score: 30000, ping: 40, guid: '1' }]
|
||||
} }).body;
|
||||
const body = render(ServerCard, {
|
||||
props: {
|
||||
name: 't5_zombie_theater_1',
|
||||
health: 'online',
|
||||
players: 4,
|
||||
telemetry: { ...gameEvent('heartbeat', 30, 4), receivedAt },
|
||||
activeSince: receivedAt,
|
||||
gameStartedAt: receivedAt,
|
||||
roster: [{ num: 0, name: 'Player One', score: 30000, ping: 40, guid: '1' }]
|
||||
}
|
||||
}).body;
|
||||
const card = body.match(/<a\b[^>]*>/)?.[0] ?? '';
|
||||
const titleId = card.match(/aria-labelledby="([^"]+)"/)?.[1]?.split(' ')[0];
|
||||
expect(titleId).toBeTruthy();
|
||||
expect(body).toContain(`id="${titleId}"`);
|
||||
expect(card).not.toContain('aria-label=');
|
||||
expect(body).toContain('Online');
|
||||
expect(body).toMatch(/<dt[^>]*>Round<\/dt><dd[^>]*>30<\/dd>/);
|
||||
expect(body).toMatch(/<dt[^>]*>Round<\/dt>\s*<dd[^>]*>30<\/dd>/);
|
||||
expect(body).toContain('Player One');
|
||||
expect(body).not.toMatch(/aria-live=|role="status"/);
|
||||
});
|
||||
|
||||
it('decodes persisted errors and keeps unknown technical errors in diagnostics', () => {
|
||||
const props = { name: 't5_zombie_theater_1', health: 'offline' as const };
|
||||
const known = render(ServerCard, { props: { ...props, lastError: 'timeout:Agent received no reply.' } }).body;
|
||||
const known = render(ServerCard, {
|
||||
props: { ...props, lastError: 'timeout:Agent received no reply.' }
|
||||
}).body;
|
||||
expect(known).toContain('Agent received no reply.');
|
||||
expect(known).not.toContain('timeout:');
|
||||
const unknown = render(ServerCard, { props: { ...props, lastError: 'unknown-error:raw diagnostic data' } }).body;
|
||||
const unknown = render(ServerCard, {
|
||||
props: { ...props, lastError: 'unknown-error:raw diagnostic data' }
|
||||
}).body;
|
||||
expect(unknown).toContain('Open diagnostics for details.');
|
||||
expect(unknown).not.toContain('raw diagnostic data');
|
||||
});
|
||||
|
||||
it('uses a page-level heading by default and allows nested empty states without live announcements', () => {
|
||||
const props = { title: 'No campaigns', description: 'Campaigns apply file changes to your servers.' };
|
||||
const props = {
|
||||
title: 'No campaigns',
|
||||
description: 'Campaigns apply file changes to your servers.'
|
||||
};
|
||||
const body = render(EmptyState, { props }).body;
|
||||
expect(body.replaceAll(/<!--.*?-->/g, '')).toMatch(/<h2\b[^>]*>No campaigns<\/h2>/);
|
||||
expect(body).not.toMatch(/role="status"|aria-live=/);
|
||||
|
||||
Reference in New Issue
Block a user