From b15c758788b2237e280866e0021368bfcfa85506 Mon Sep 17 00:00:00 2001 From: 4gray Date: Mon, 28 Sep 2026 22:00:59 +0200 Subject: [PATCH] fix(dashboard): treat description and category corrections as changed answers The hero renders a live programme's description and category (#1738), so sameLiveEpgAnswers must compare them too; otherwise a guide correction to either was dropped by distinctUntilChanged until the programme changed. Co-Authored-By: Claude Opus 5.5 --- .../rails/dashboard-live-epg.utils.spec.ts | 32 +++++++++++++++++++ .../src/lib/rails/dashboard-live-epg.utils.ts | 8 ++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/libs/workspace/dashboard/feature/src/lib/rails/dashboard-live-epg.utils.spec.ts b/libs/workspace/dashboard/feature/src/lib/rails/dashboard-live-epg.utils.spec.ts index 04e9d039b..d7c7ade5d 100644 --- a/libs/workspace/dashboard/feature/src/lib/rails/dashboard-live-epg.utils.spec.ts +++ b/libs/workspace/dashboard/feature/src/lib/rails/dashboard-live-epg.utils.spec.ts @@ -3,6 +3,7 @@ import { buildDashboardLiveEpgDetails, calcEpgProgress, formatEpgTimeRange, + sameLiveEpgAnswers, } from './dashboard-live-epg.utils'; // Local-time wall clock so the formatted range is stable in every timezone @@ -143,4 +144,35 @@ describe('dashboard-live-epg.utils', () => { expect(buildDashboardLiveEpgDetails(row, MIDPOINT_MS)).toBeNull(); }); }); + + describe('sameLiveEpgAnswers', () => { + const answers = (row: EpgProgram | null) => + new Map([['key', row]]); + + it('treats fresh objects with the same rendered fields as unchanged', () => { + expect( + sameLiveEpgAnswers(answers(program()), answers(program())) + ).toBe(true); + }); + + it.each([ + ['title', { title: 'Late News' }], + ['description', { desc: 'Corrected summary' }], + ['category', { category: 'Sport' }], + ['stop', { stop: new Date(2026, 0, 15, 21, 30).toISOString() }], + ])('sees a guide correction to the %s', (_, change) => { + expect( + sameLiveEpgAnswers( + answers(program()), + answers(program(change as Partial)) + ) + ).toBe(false); + }); + + it('sees a programme appear or disappear', () => { + expect(sameLiveEpgAnswers(answers(null), answers(program()))).toBe( + false + ); + }); + }); }); diff --git a/libs/workspace/dashboard/feature/src/lib/rails/dashboard-live-epg.utils.ts b/libs/workspace/dashboard/feature/src/lib/rails/dashboard-live-epg.utils.ts index dd7257044..bff7d1390 100644 --- a/libs/workspace/dashboard/feature/src/lib/rails/dashboard-live-epg.utils.ts +++ b/libs/workspace/dashboard/feature/src/lib/rails/dashboard-live-epg.utils.ts @@ -282,7 +282,11 @@ export function liveEpgAnswersNeedRefresh( return false; } -/** Same keys answered with the same programmes (by time and title). */ +/** + * Same keys answered with the same programmes: everything the dashboard + * renders from one (title, times, description, category) must match, or a + * guide correction to any of them would be dropped as "unchanged". + */ export function sameLiveEpgAnswers( a: ReadonlyMap, b: ReadonlyMap @@ -297,6 +301,8 @@ export function sameLiveEpgAnswers( !program || !other || program.title !== other.title || + program.desc !== other.desc || + program.category !== other.category || epgTimestampMs(program, 'start') !== epgTimestampMs(other, 'start') || epgTimestampMs(program, 'stop') !== epgTimestampMs(other, 'stop')