74 lines
3.2 KiB
TypeScript
74 lines
3.2 KiB
TypeScript
import { readFileSync } from 'node:fs';
|
|
import { resolve } from 'node:path';
|
|
import {
|
|
EventState,
|
|
LED_COLOR_BY_STATE,
|
|
ledBackgroundColor,
|
|
} from '../../frontend/src/app/core/services/event-status.pure';
|
|
|
|
describe('LED state -> background-color mapping', () => {
|
|
it.each([
|
|
['running', 'var(--color-success)'],
|
|
['countdown', 'var(--color-warning)'],
|
|
['stopped', 'var(--color-danger)'],
|
|
['unconfigured', 'var(--color-secondary)'],
|
|
] as const)('maps %s to %s', (state, expected) => {
|
|
expect(ledBackgroundColor(state)).toBe(expected);
|
|
expect(LED_COLOR_BY_STATE[state]).toBe(expected);
|
|
});
|
|
|
|
it('covers every EventState variant with a non-transparent token', () => {
|
|
for (const state of Object.keys(LED_COLOR_BY_STATE) as EventState[]) {
|
|
const color = ledBackgroundColor(state);
|
|
expect(color).toMatch(/^var\(--color-/);
|
|
expect(color).not.toBe('transparent');
|
|
expect(color).not.toBe('');
|
|
}
|
|
});
|
|
});
|
|
|
|
describe('ShellHeaderComponent LED wiring', () => {
|
|
const sourcePath = resolve(
|
|
__dirname,
|
|
'../../frontend/src/app/features/shell/header/shell-header.component.ts',
|
|
);
|
|
const source = readFileSync(sourcePath, 'utf8');
|
|
|
|
it('does not declare a transparent background on the LED base', () => {
|
|
const baseBlock = source.match(/\.led\s*\{[^}]*\}/);
|
|
expect(baseBlock).not.toBeNull();
|
|
expect(baseBlock?.[0]).not.toMatch(/background-color\s*:\s*transparent/);
|
|
});
|
|
|
|
it('keeps the component shape (size, radius, no border, inline-block, vertical-align)', () => {
|
|
const baseBlock = source.match(/\.led\s*\{[^}]*\}/);
|
|
expect(baseBlock?.[0]).toMatch(/display:\s*inline-block/);
|
|
expect(baseBlock?.[0]).toMatch(/width:\s*10px/);
|
|
expect(baseBlock?.[0]).toMatch(/height:\s*10px/);
|
|
expect(baseBlock?.[0]).toMatch(/border-radius:\s*50%/);
|
|
expect(baseBlock?.[0]).toMatch(/border:\s*0/);
|
|
expect(baseBlock?.[0]).toMatch(/vertical-align:\s*middle/);
|
|
});
|
|
|
|
it('binds the LED background color directly from the state signal', () => {
|
|
expect(source).toMatch(/\[style\.background-color\]="ledColor\(\)"/);
|
|
expect(source).toMatch(/ledColor\s*=\s*computed\(/);
|
|
expect(source).toMatch(/ledBackgroundColor\(this\.eventState\(\)\)/);
|
|
});
|
|
|
|
it('keeps the four state class bindings, testid, and accessible state label', () => {
|
|
expect(source).toContain('[class.led-running]="eventState() === \'running\'"');
|
|
expect(source).toContain('[class.led-countdown]="eventState() === \'countdown\'"');
|
|
expect(source).toContain('[class.led-stopped]="eventState() === \'stopped\'"');
|
|
expect(source).toContain('[class.led-unconfigured]="eventState() === \'unconfigured\'"');
|
|
expect(source).toContain('data-testid="shell-led"');
|
|
expect(source).toContain("[attr.aria-label]=\"'Event status: ' + eventState()\"");
|
|
});
|
|
|
|
it('does not redeclare LED state colors in the component styles', () => {
|
|
expect(source).not.toMatch(/\.led-running\s*\{[^}]*background-color/);
|
|
expect(source).not.toMatch(/\.led-countdown\s*\{[^}]*background-color/);
|
|
expect(source).not.toMatch(/\.led-stopped\s*\{[^}]*background-color/);
|
|
expect(source).not.toMatch(/\.led-unconfigured\s*\{[^}]*background-color/);
|
|
});
|
|
}); |