mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-19 22:24:11 +00:00
test: cover runtime update gating and colour parsing
Adds unit tests for two pure modules which had no coverage: - `runtime.utils.ts` gates every websocket broadcast and the `onUpdate` / `onClock` automation triggers. The tests pin the second-boundary rounding, the documented cases where a field is deliberately *not* broadcast (`elapsed`, `expectedFinish`), and the wrap-around behaviour of the load-next / load-previous / go-to-cue lookups. - `colour.utils.ts` parses user supplied colour strings for both the Google Sheets export and the cuesheet rows. The tests cover the hex/CSS-name parsing, the null returns for invalid input, and the hexToColour <-> colourToHex round trip. Both files are pure, so neither test uses a mock. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SAH21unBqSzEH9HMwqfa5Q
This commit is contained in:
@@ -0,0 +1,89 @@
|
||||
import { colourToHex, cssOrHexToColour, hexToColour, isLightColour, mixColours } from './colour.utils';
|
||||
|
||||
describe('hexToColour()', () => {
|
||||
it('parses a full length hex', () => {
|
||||
expect(hexToColour('#ff8800')).toStrictEqual({ red: 255, green: 136, blue: 0, alpha: 1 });
|
||||
});
|
||||
|
||||
it('parses a compressed hex by duplicating each digit', () => {
|
||||
expect(hexToColour('#f80')).toStrictEqual(hexToColour('#ff8800'));
|
||||
});
|
||||
|
||||
it('parses the alpha channel of a full length hex', () => {
|
||||
expect(hexToColour('#ff880000')).toStrictEqual({ red: 255, green: 136, blue: 0, alpha: 0 });
|
||||
expect(hexToColour('#ff8800ff')).toStrictEqual({ red: 255, green: 136, blue: 0, alpha: 1 });
|
||||
});
|
||||
|
||||
it('parses the alpha channel of a compressed hex', () => {
|
||||
expect(hexToColour('#f800')).toStrictEqual(hexToColour('#ff880000'));
|
||||
});
|
||||
|
||||
it('is case insensitive', () => {
|
||||
expect(hexToColour('#FF8800')).toStrictEqual(hexToColour('#ff8800'));
|
||||
});
|
||||
|
||||
it('returns null for values which are not a hex colour', () => {
|
||||
// these are the values which reach us from user input
|
||||
for (const invalid of ['', 'red', '#', '#ff', '#fffff', '#ffg', 'ff8800']) {
|
||||
expect(hexToColour(invalid)).toBeNull();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('colourToHex()', () => {
|
||||
it('pads single digit channels', () => {
|
||||
expect(colourToHex({ red: 0, green: 1, blue: 2, alpha: 1 })).toBe('#000102ff');
|
||||
});
|
||||
|
||||
it('round trips with hexToColour', () => {
|
||||
for (const hex of ['#000000ff', '#ff8800ff', '#ffffffff', '#12345600']) {
|
||||
expect(colourToHex(hexToColour(hex)!)).toBe(hex);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('cssOrHexToColour()', () => {
|
||||
it('resolves named css colours', () => {
|
||||
expect(cssOrHexToColour('red')).toStrictEqual({ red: 255, green: 0, blue: 0, alpha: 1 });
|
||||
});
|
||||
|
||||
it('resolves named css colours regardless of casing', () => {
|
||||
expect(cssOrHexToColour('CornflowerBlue')).toStrictEqual(cssOrHexToColour('cornflowerblue'));
|
||||
});
|
||||
|
||||
it('delegates hex values to the hex parser', () => {
|
||||
expect(cssOrHexToColour('#f80')).toStrictEqual(hexToColour('#f80'));
|
||||
});
|
||||
|
||||
it('returns null for an unknown colour name', () => {
|
||||
expect(cssOrHexToColour('not-a-colour')).toBeNull();
|
||||
expect(cssOrHexToColour('')).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('mixColours()', () => {
|
||||
const black = { red: 0, green: 0, blue: 0, alpha: 1 };
|
||||
const white = { red: 255, green: 255, blue: 255, alpha: 1 };
|
||||
|
||||
it('defaults to an even mix', () => {
|
||||
expect(mixColours(black, white)).toStrictEqual({ red: 128, green: 128, blue: 128, alpha: 1 });
|
||||
});
|
||||
|
||||
it('weights the first colour by the given proportion', () => {
|
||||
expect(mixColours(black, white, 1)).toStrictEqual({ ...black, alpha: 1 });
|
||||
expect(mixColours(black, white, 0)).toStrictEqual({ ...white, alpha: 1 });
|
||||
});
|
||||
});
|
||||
|
||||
describe('isLightColour()', () => {
|
||||
it('detects light and dark colours', () => {
|
||||
expect(isLightColour({ red: 255, green: 255, blue: 255, alpha: 1 })).toBe(true);
|
||||
expect(isLightColour({ red: 0, green: 0, blue: 0, alpha: 1 })).toBe(false);
|
||||
});
|
||||
|
||||
it('weights green most heavily, as per the YIQ calculation', () => {
|
||||
// pure green is considered light, pure blue is not
|
||||
expect(isLightColour({ red: 0, green: 255, blue: 0, alpha: 1 })).toBe(true);
|
||||
expect(isLightColour({ red: 0, green: 0, blue: 255, alpha: 1 })).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user