mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-14 05:06:16 -08:00
* docs(skills): design implementation synchronization * docs(skills): plan implementation synchronization * fix(release): filter internal notes from public body * docs(release): synchronize release workflow guidance * fix(stalker): normalize catalog series flags * fix(stalker): preserve progress with scoped episode IDs * fix(playback): expose strict position persistence * docs(stalker): record series position compatibility * test(skills): validate repository skill contracts * fix(database): keep SQL trace values private * docs(skills): refresh Nx and SQLite ownership * docs(skills): align provider and UI guidance * docs(skills): tighten validated guidance * docs(release): require exact release pushes * style(electron): remove trailing blank line * fix(ci): classify repository skills coverage
78 lines
2.2 KiB
TypeScript
78 lines
2.2 KiB
TypeScript
import {
|
|
extractStalkerItemType,
|
|
isStalkerRadioItem,
|
|
normalizeStalkerDate,
|
|
} from './stalker-item.normalizer';
|
|
|
|
describe('extractStalkerItemType', () => {
|
|
it('treats Stalker radio stations as live collection items', () => {
|
|
expect(
|
|
extractStalkerItemType({
|
|
id: '40001',
|
|
title: 'Jazz Radio',
|
|
category_id: 'radio',
|
|
radio: true,
|
|
})
|
|
).toBe('live');
|
|
expect(
|
|
extractStalkerItemType({
|
|
id: '40002',
|
|
title: 'Rock Radio',
|
|
category_id: 'radio-genre-1',
|
|
radio: 'true',
|
|
})
|
|
).toBe('live');
|
|
});
|
|
|
|
it.each([true, 1, '1'] as const)(
|
|
'treats is_series=%p as a series item',
|
|
(isSeries) => {
|
|
expect(
|
|
extractStalkerItemType({
|
|
id: '50001',
|
|
title: 'Portal Series',
|
|
is_series: isSeries,
|
|
})
|
|
).toBe('series');
|
|
}
|
|
);
|
|
});
|
|
|
|
describe('isStalkerRadioItem', () => {
|
|
it('does not infer radio from a generic HTTP path segment', () => {
|
|
expect(
|
|
isStalkerRadioItem({
|
|
id: '77',
|
|
title: 'News Channel',
|
|
cmd: 'https://media.example.com/live/radio/news/index.m3u8',
|
|
})
|
|
).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe('normalizeStalkerDate', () => {
|
|
it('normalizes SQLite UTC timestamps without relying on engine-specific parsing', () => {
|
|
const originalParse = Date.parse;
|
|
const parseSpy = jest
|
|
.spyOn(Date, 'parse')
|
|
.mockImplementation((value: string) => {
|
|
if (value === '2026-04-21 22:49:02') {
|
|
return Number.NaN;
|
|
}
|
|
|
|
return originalParse(value);
|
|
});
|
|
|
|
expect(normalizeStalkerDate('2026-04-21 22:49:02')).toBe(
|
|
'2026-04-21T22:49:02.000Z'
|
|
);
|
|
expect(parseSpy).not.toHaveBeenCalledWith('2026-04-21 22:49:02');
|
|
});
|
|
|
|
it('preserves fractional seconds in SQLite UTC timestamps', () => {
|
|
expect(normalizeStalkerDate('2026-04-21 22:49:02.7')).toBe(
|
|
'2026-04-21T22:49:02.700Z'
|
|
);
|
|
});
|
|
});
|