mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-09 09:23:51 +00:00
fix: roll resets day
This commit is contained in:
committed by
Carlos Valente
parent
a29a493678
commit
efd19353e9
@@ -1,4 +1,5 @@
|
||||
import { PlayableEvent, Playback, TimerPhase } from 'ontime-types';
|
||||
import { MILLIS_PER_HOUR, MILLIS_PER_MINUTE } from 'ontime-utils';
|
||||
|
||||
import { makeOntimeGroup, makeOntimeEvent, makeRundown } from '../../api-data/rundown/__mocks__/rundown.mocks.js';
|
||||
import { initRundown } from '../../api-data/rundown/rundown.service.js';
|
||||
@@ -394,6 +395,191 @@ describe('roll mode', () => {
|
||||
|
||||
expect(getState().rundown.currentDay).toBe(1);
|
||||
});
|
||||
|
||||
test('pending roll crossing midnight keeps currentDay null', async () => {
|
||||
// Event starts at 01:00 (future event, will be pending)
|
||||
const mockRundown = makeRundown({
|
||||
entries: {
|
||||
1: {
|
||||
...mockEvent,
|
||||
id: '1',
|
||||
timeStart: 1 * MILLIS_PER_HOUR, // 01:00
|
||||
timeEnd: 2 * MILLIS_PER_HOUR, // 02:00
|
||||
duration: 1 * MILLIS_PER_HOUR, // 1 hour
|
||||
dayOffset: 0,
|
||||
},
|
||||
},
|
||||
order: ['1'],
|
||||
});
|
||||
|
||||
await initRundown(mockRundown, {});
|
||||
vi.runAllTimers();
|
||||
|
||||
// Clock is at 23:50 (before midnight, event is pending for tomorrow 01:00)
|
||||
vi.setSystemTime('jan 1 23:50');
|
||||
const { rundown, metadata } = rundownCache.get();
|
||||
const result = roll(rundown, metadata);
|
||||
|
||||
expect(result.eventId).toBe('1');
|
||||
expect(result.didStart).toBe(false);
|
||||
|
||||
const stateBeforeMidnight = getState();
|
||||
expect(stateBeforeMidnight.timer.secondaryTimer).not.toBeNull();
|
||||
// currentDay is null when pending (rundown hasn't started)
|
||||
expect(stateBeforeMidnight.rundown.currentDay).toBeNull();
|
||||
|
||||
// Cross midnight while still pending
|
||||
vi.setSystemTime('jan 2 00:10');
|
||||
update();
|
||||
|
||||
const stateAfterMidnight = getState();
|
||||
// currentDay stays null while pending (rundown hasn't started yet)
|
||||
expect(stateAfterMidnight.rundown.currentDay).toBeNull();
|
||||
// should still be pending (event starts at 01:00)
|
||||
expect(stateAfterMidnight.timer.secondaryTimer).not.toBeNull();
|
||||
});
|
||||
|
||||
test('pending roll sets currentDay to 0 when event starts (rundown starts fresh)', async () => {
|
||||
// Event starts at 01:00
|
||||
const mockRundown = makeRundown({
|
||||
entries: {
|
||||
1: {
|
||||
...mockEvent,
|
||||
id: '1',
|
||||
timeStart: 1 * MILLIS_PER_HOUR, // 01:00
|
||||
timeEnd: 2 * MILLIS_PER_HOUR, // 02:00
|
||||
duration: 1 * MILLIS_PER_HOUR, // 1 hour
|
||||
dayOffset: 0,
|
||||
},
|
||||
},
|
||||
order: ['1'],
|
||||
});
|
||||
|
||||
await initRundown(mockRundown, {});
|
||||
vi.runAllTimers();
|
||||
|
||||
// Start pending at 23:50
|
||||
vi.setSystemTime('jan 1 23:50');
|
||||
const { rundown, metadata } = rundownCache.get();
|
||||
roll(rundown, metadata);
|
||||
|
||||
// Cross midnight
|
||||
vi.setSystemTime('jan 2 00:10');
|
||||
update();
|
||||
|
||||
// Now the event starts at 01:05 - call roll again to simulate runtime service
|
||||
vi.setSystemTime('jan 2 01:05');
|
||||
const result = roll(rundown, metadata);
|
||||
|
||||
expect(result.didStart).toBe(true);
|
||||
|
||||
const state = getState();
|
||||
// currentDay is 0 because the rundown just started (this is day 0)
|
||||
// the pending time before midnight doesn't count as rundown time
|
||||
expect(state.rundown.currentDay).toBe(0);
|
||||
});
|
||||
|
||||
test('pending roll crossing midnight updates secondaryTimer correctly', async () => {
|
||||
// Event starts at 01:00
|
||||
const mockRundown = makeRundown({
|
||||
entries: {
|
||||
1: {
|
||||
...mockEvent,
|
||||
id: '1',
|
||||
timeStart: 1 * MILLIS_PER_HOUR, // 01:00
|
||||
timeEnd: 2 * MILLIS_PER_HOUR, // 02:00
|
||||
duration: 1 * MILLIS_PER_HOUR, // 1 hour
|
||||
dayOffset: 0,
|
||||
},
|
||||
},
|
||||
order: ['1'],
|
||||
});
|
||||
|
||||
await initRundown(mockRundown, {});
|
||||
vi.runAllTimers();
|
||||
|
||||
// Clock is at 23:50
|
||||
vi.setSystemTime('jan 1 23:50');
|
||||
const { rundown, metadata } = rundownCache.get();
|
||||
roll(rundown, metadata);
|
||||
|
||||
const stateBeforeMidnight = getState();
|
||||
// secondaryTimer should be time until 01:00 (1h 10min = 70 min)
|
||||
expect(stateBeforeMidnight.timer.secondaryTimer).toBe(70 * MILLIS_PER_MINUTE);
|
||||
|
||||
// Cross midnight to 00:10
|
||||
vi.setSystemTime('jan 2 00:10');
|
||||
update();
|
||||
|
||||
const stateAfterMidnight = getState();
|
||||
// secondaryTimer should now be 50 minutes until 01:00
|
||||
expect(stateAfterMidnight.timer.secondaryTimer).toBe(50 * MILLIS_PER_MINUTE);
|
||||
});
|
||||
|
||||
test('rundown loops back after finishing and resets currentDay when first event starts again', async () => {
|
||||
// Rundown: 09:00-23:00, then overnight event 23:00-01:00
|
||||
const mockRundown = makeRundown({
|
||||
entries: {
|
||||
1: {
|
||||
...mockEvent,
|
||||
id: '1',
|
||||
timeStart: 9 * MILLIS_PER_HOUR, // 09:00
|
||||
timeEnd: 23 * MILLIS_PER_HOUR, // 23:00
|
||||
duration: 14 * MILLIS_PER_HOUR, // 14 hours
|
||||
dayOffset: 0,
|
||||
},
|
||||
2: {
|
||||
...mockEvent,
|
||||
id: '2',
|
||||
timeStart: 23 * MILLIS_PER_HOUR, // 23:00
|
||||
timeEnd: 1 * MILLIS_PER_HOUR, // 01:00 (next day)
|
||||
duration: 2 * MILLIS_PER_HOUR, // 2 hours
|
||||
dayOffset: 0,
|
||||
},
|
||||
},
|
||||
order: ['1', '2'],
|
||||
});
|
||||
|
||||
await initRundown(mockRundown, {});
|
||||
vi.runAllTimers();
|
||||
|
||||
const { rundown, metadata } = rundownCache.get();
|
||||
|
||||
// Day 1: Start at 09:05 - first event is playing
|
||||
vi.setSystemTime('jan 1 09:05');
|
||||
let result = roll(rundown, metadata);
|
||||
expect(result.eventId).toBe('1');
|
||||
expect(result.didStart).toBe(true);
|
||||
expect(getState().rundown.currentDay).toBe(0);
|
||||
|
||||
// Day 1: Move to 23:05 - second event (overnight) is playing
|
||||
vi.setSystemTime('jan 1 23:05');
|
||||
result = roll(rundown, metadata);
|
||||
expect(result.eventId).toBe('2');
|
||||
expect(result.didStart).toBe(true);
|
||||
|
||||
// Cross midnight
|
||||
vi.setSystemTime('jan 2 00:30');
|
||||
update();
|
||||
expect(getState().rundown.currentDay).toBe(1);
|
||||
|
||||
// Day 2: 01:05 - rundown finishes, loops back to first event (pending for 09:00)
|
||||
vi.setSystemTime('jan 2 01:05');
|
||||
result = roll(rundown, metadata);
|
||||
// First event is pending (09:00 is in the future)
|
||||
expect(result.eventId).toBe('1');
|
||||
expect(result.didStart).toBe(false);
|
||||
// currentDay is null while pending (rundown hasn't "restarted" yet)
|
||||
expect(getState().rundown.currentDay).toBeNull();
|
||||
|
||||
// Day 2: 09:05 - first event starts again (fresh rundown cycle)
|
||||
vi.setSystemTime('jan 2 09:05');
|
||||
result = roll(rundown, metadata);
|
||||
expect(result.eventId).toBe('1');
|
||||
expect(result.didStart).toBe(true);
|
||||
// currentDay resets to 0 for the new cycle
|
||||
expect(getState().rundown.currentDay).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('normal roll', async () => {
|
||||
|
||||
@@ -751,6 +751,13 @@ export function roll(
|
||||
// preload timer properties
|
||||
runtimeState.timer.duration = calculateDuration(runtimeState.eventNow.timeStart, runtimeState.eventNow.timeEnd);
|
||||
runtimeState.timer.current = runtimeState.timer.duration;
|
||||
|
||||
// reset rundown state - the rundown will start fresh when the event begins
|
||||
runtimeState.rundown.actualStart = null;
|
||||
runtimeState.rundown.currentDay = null;
|
||||
runtimeState._startDayOffset = null;
|
||||
runtimeState._startEpoch = null;
|
||||
|
||||
return { eventId: runtimeState.eventNow.id, didStart: false };
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user