fix(epg): avoid duplicate track keys for archive rows

This commit is contained in:
4gray committed 2026-06-28 11:55:56 +02:00
1 parent 148affdfca
commit aee5f61c1b
3 files changed
+69 -1

No files matched your search

@@ -35,7 +35,7 @@
<!-- program list -->
<div id="program-list" class="app-scrollbar" #programList>
@if (items.length > 0) {
@for (program of items; track program.start) {
@for (program of items; track trackProgram($index, program)) {
@if (!canActivateProgram(program)) {
<div
class="program-item"
@@ -266,6 +266,61 @@ describe('EpgListComponent', () => {
expect(emitted).toEqual([{ program: programs[0], type: 'timeshift' }]);
});
it('renders duplicate-start programs without duplicate track-key errors and keeps clicks bound to each row', () => {
const programs = [
buildProgram(
'duplicate-a',
'Duplicate Start A',
'2026-04-05T09:00:00.000Z',
'2026-04-05T09:30:00.000Z'
),
buildProgram(
'duplicate-b',
'Duplicate Start B',
'2026-04-05T09:00:00.000Z',
'2026-04-05T10:00:00.000Z'
),
buildProgram(
'current',
'Current Show',
'2026-04-05T11:30:00.000Z',
'2026-04-05T12:30:00.000Z'
),
];
const emitted: unknown[] = [];
const consoleErrorSpy = jest
.spyOn(console, 'error')
.mockImplementation(() => undefined);
component.programActivated.subscribe((event) => emitted.push(event));
fixture.componentRef.setInput('controlledPrograms', programs);
fixture.componentRef.setInput('archivePlaybackAvailable', true);
try {
expect(component.trackProgram(0, programs[0])).not.toBe(
component.trackProgram(1, programs[1])
);
fixture.detectChanges();
const duplicateTrackKeyError = consoleErrorSpy.mock.calls.some(
(args) => args.some((arg) => String(arg).includes('NG0955'))
);
const rows =
fixture.nativeElement.querySelectorAll<HTMLElement>(
'.program-item.clickable'
);
rows[1].click();
expect(duplicateTrackKeyError).toBe(false);
expect(rows).toHaveLength(3);
expect(emitted).toEqual([
{ program: programs[1], type: 'timeshift' },
]);
} finally {
consoleErrorSpy.mockRestore();
}
});
it('updates the selected-day header when the app language changes', () => {
fixture.componentRef.setInput('controlledPrograms', buildPrograms());
fixture.detectChanges();
@@ -241,6 +241,19 @@ export class EpgListComponent {
this.activateProgram(program);
}
trackProgram(index: number, program: EpgProgram): string {
const start = getProgramTimeMs(program.start, program.startTimestamp);
const stop = getProgramTimeMs(program.stop, program.stopTimestamp);
return [
program.channel ?? '',
Number.isFinite(start) ? start : program.start,
Number.isFinite(stop) ? stop : program.stop,
program.title ?? '',
index,
].join('|');
}
canActivateProgram(program: EpgProgram): boolean {
return (
this.isProgramPlaying(program) ||