Add Prettier and ESLint tooling (Refs #77)

This commit is contained in:
2026-10-09 15:56:13 -04:00
parent 8ed059b8d3
commit 16469e2d43
711 changed files with 99737 additions and 28286 deletions
+36 -19
View File
@@ -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=/);