diff --git a/apps/client/src/common/utils/__tests__/eventsManager.test.js b/apps/client/src/common/utils/__tests__/eventsManager.test.js index c4ac98239..5b24034e8 100644 --- a/apps/client/src/common/utils/__tests__/eventsManager.test.js +++ b/apps/client/src/common/utils/__tests__/eventsManager.test.js @@ -1,127 +1,232 @@ import { formatEventList, getEventsWithDelay, trimEventlist } from '../eventsManager'; -test('getEventsWithDelay function', () => { - const testData = [ - { - title: 'Welcome to Ontime', - timeStart: 28800000, - timeEnd: 30600000, - colour: '', - type: 'event', - id: '5946', - }, - { - duration: 60000, - type: 'delay', - id: '24240', - }, - { - title: 'Unless recalled by the OSC address', - timeStart: 34920000, - timeEnd: 35520000, - colour: '', - type: 'event', - id: '8ee5', - }, - { - title: 'Use simpler times to create a timer', - timeStart: 120000, - timeEnd: 720000, - colour: '', - type: 'event', - id: '8222', - }, - { - duration: 900000, - type: 'delay', - revision: 0, - id: 'a386', - }, - { - title: 'Add delay blocks to affect all events', - timeStart: 37320000, - timeEnd: 38520000, - colour: '', - type: 'event', - id: '6dce', - }, - { - title: 'Add and remove events with [+] and [-]', - timeStart: 38520000, - timeEnd: 45120000, - colour: '', - type: 'event', - id: '2651', - }, - { - type: 'block', - id: 'e6a1', - }, - { - title: 'And control whether they are public', - timeStart: 46800000, - timeEnd: 57600000, - colour: '', - type: 'event', - id: '1358', - }, - ]; +describe('getEventsWithDelay function', () => { + test('with positive delays', () => { + const testData = [ + { + title: 'Welcome to Ontime', + timeStart: 28800000, + timeEnd: 30600000, + colour: '', + type: 'event', + id: '5946', + }, + { + duration: 60000, + type: 'delay', + id: '24240', + }, + { + title: 'Unless recalled by the OSC address', + timeStart: 34920000, + timeEnd: 35520000, + colour: '', + type: 'event', + id: '8ee5', + }, + { + title: 'Use simpler times to create a timer', + timeStart: 120000, + timeEnd: 720000, + colour: '', + type: 'event', + id: '8222', + }, + { + duration: 900000, + type: 'delay', + revision: 0, + id: 'a386', + }, + { + title: 'Add delay blocks to affect all events', + timeStart: 37320000, + timeEnd: 38520000, + colour: '', + type: 'event', + id: '6dce', + }, + { + title: 'Add and remove events with [+] and [-]', + timeStart: 38520000, + timeEnd: 45120000, + colour: '', + type: 'event', + id: '2651', + }, + { + type: 'block', + id: 'e6a1', + }, + { + title: 'And control whether they are public', + timeStart: 46800000, + timeEnd: 57600000, + colour: '', + type: 'event', + id: '1358', + }, + ]; - const expected = [ - { - title: 'Welcome to Ontime', - timeStart: 28800000, - timeEnd: 30600000, - colour: '', - type: 'event', - id: '5946', - }, - { - title: 'Unless recalled by the OSC address', - timeStart: 34920000 + 60000, - timeEnd: 35520000 + 60000, - colour: '', - type: 'event', - id: '8ee5', - }, - { - title: 'Use simpler times to create a timer', - timeStart: 120000 + 60000, - timeEnd: 720000 + 60000, - colour: '', - type: 'event', - id: '8222', - }, - { - title: 'Add delay blocks to affect all events', - timeStart: 37320000 + 60000 + 900000, - timeEnd: 38520000 + 60000 + 900000, - colour: '', - type: 'event', - id: '6dce', - }, - { - title: 'Add and remove events with [+] and [-]', - timeStart: 38520000 + 60000 + 900000, - timeEnd: 45120000 + 60000 + 900000, - colour: '', - type: 'event', - id: '2651', - }, - { - title: 'And control whether they are public', - timeStart: 46800000, - timeEnd: 57600000, - colour: '', - type: 'event', - id: '1358', - }, - ]; + const expected = [ + { + title: 'Welcome to Ontime', + timeStart: 28800000, + timeEnd: 30600000, + colour: '', + type: 'event', + id: '5946', + }, + { + title: 'Unless recalled by the OSC address', + timeStart: 34920000 + 60000, + timeEnd: 35520000 + 60000, + colour: '', + type: 'event', + id: '8ee5', + }, + { + title: 'Use simpler times to create a timer', + timeStart: 120000 + 60000, + timeEnd: 720000 + 60000, + colour: '', + type: 'event', + id: '8222', + }, + { + title: 'Add delay blocks to affect all events', + timeStart: 37320000 + 60000 + 900000, + timeEnd: 38520000 + 60000 + 900000, + colour: '', + type: 'event', + id: '6dce', + }, + { + title: 'Add and remove events with [+] and [-]', + timeStart: 38520000 + 60000 + 900000, + timeEnd: 45120000 + 60000 + 900000, + colour: '', + type: 'event', + id: '2651', + }, + { + title: 'And control whether they are public', + timeStart: 46800000, + timeEnd: 57600000, + colour: '', + type: 'event', + id: '1358', + }, + ]; - expect(getEventsWithDelay(testData)).toStrictEqual(expected); + expect(getEventsWithDelay(testData)).toStrictEqual(expected); + }); + test('with negative delays', () => { + const testData = [ + { + duration: -20, + type: 'delay', + id: '24240', + }, + { + title: 'Welcome to Ontime', + timeStart: 100, + timeEnd: 200, + colour: '', + type: 'event', + id: '5946', + }, + ]; + + const expected = [ + { + title: 'Welcome to Ontime', + timeStart: 80, + timeEnd: 180, + colour: '', + type: 'event', + id: '5946', + }, + ]; + + expect(getEventsWithDelay(testData)).toStrictEqual(expected); + }); }); describe('getEventsWithDelay edge cases', () => { + it('ensures time start cannot be below 0', () => { + const testData = [ + { + duration: -200, + type: 'delay', + id: '24240', + }, + { + title: 'Welcome to Ontime', + timeStart: 10, + timeEnd: 20, + colour: '', + type: 'event', + id: '5946', + }, + ]; + + const expected = [ + { + title: 'Welcome to Ontime', + timeStart: 0, + timeEnd: 0, + colour: '', + type: 'event', + id: '5946', + }, + ]; + + expect(getEventsWithDelay(testData)).toStrictEqual(expected); + }); + it('does not modify original array', () => { + const testData = [ + { + duration: 10, + type: 'delay', + id: '24240', + }, + { + title: 'Welcome to Ontime', + timeStart: 10, + timeEnd: 20, + colour: '', + type: 'event', + id: '5946', + }, + ]; + + const expected = [ + { + title: 'Welcome to Ontime', + timeStart: 20, + timeEnd: 30, + colour: '', + type: 'event', + id: '5946', + }, + ]; + + const expectedSafe = [ + { + title: 'Welcome to Ontime', + timeStart: 20, + timeEnd: 30, + colour: '', + type: 'event', + id: '5946', + }, + ]; + + expect(getEventsWithDelay(testData)).toStrictEqual(expected); + expect(getEventsWithDelay(expectedSafe)).toStrictEqual(expected); + }); + it('given an empty array', () => { const emptyArray = { test: [], diff --git a/apps/client/src/common/utils/eventsManager.ts b/apps/client/src/common/utils/eventsManager.ts index 867060726..9f07ba48d 100644 --- a/apps/client/src/common/utils/eventsManager.ts +++ b/apps/client/src/common/utils/eventsManager.ts @@ -11,21 +11,27 @@ import { formatTime } from './time'; export const getEventsWithDelay = (events: OntimeRundownEntry[]): OntimeEvent[] => { if (events == null) return []; - const unfilteredEvents = [...events]; + const delayedEvents: OntimeEvent[] = []; // Add running delay let delay = 0; - for (const event of unfilteredEvents) { + for (const event of events) { if (event.type === SupportedEvent.Block) delay = 0; - else if (event.type === SupportedEvent.Delay) delay = delay + event.duration; - else if (event.type === SupportedEvent.Event && delay > 0) { - event.timeStart += delay; - event.timeEnd += delay; + else if (event.type === SupportedEvent.Delay) { + if (typeof event.duration === 'number') { + delay += event.duration; + } + } else if (event.type === SupportedEvent.Event) { + const delayedEvent = { ...event }; + if (delay !== 0) { + delayedEvent.timeStart = Math.max(delayedEvent.timeStart + delay, 0); + delayedEvent.timeEnd = Math.max(delayedEvent.timeEnd + delay, 0); + } + delayedEvents.push(delayedEvent); } } - // filter just events - return unfilteredEvents.filter((event) => event.type === SupportedEvent.Event) as OntimeEvent[]; + return delayedEvents; }; /** @@ -57,7 +63,7 @@ export const trimEventlist = (events: OntimeRundownEntry[], selectedId: string, type FormatEventListOptionsProp = { showEnd?: boolean; -} +}; /** * @description Returns list of events formatted to be displayed * @param {Object[]} events - given events @@ -67,7 +73,12 @@ type FormatEventListOptionsProp = { * @param {boolean} [options.showEnd] - whether to show the end time * @returns {Object[]} Formatted list of events [{time: -, title: -, isNow, isNext}] */ -export const formatEventList = (events: OntimeEvent[], selectedId: string, nextId: string, options: FormatEventListOptionsProp) => { +export const formatEventList = ( + events: OntimeEvent[], + selectedId: string, + nextId: string, + options: FormatEventListOptionsProp, +) => { if (events == null) return []; const { showEnd = false } = options; diff --git a/apps/client/src/common/utils/time.ts b/apps/client/src/common/utils/time.ts index e24b8f8f6..269c07a12 100644 --- a/apps/client/src/common/utils/time.ts +++ b/apps/client/src/common/utils/time.ts @@ -46,7 +46,7 @@ type FormatOptions = { * @param {function} resolver * @return {string} */ -export const formatTime = (milliseconds: number | null, options: FormatOptions, resolver = resolveTimeFormat) => { +export const formatTime = (milliseconds: number | null, options?: FormatOptions, resolver = resolveTimeFormat) => { if (milliseconds === null) { return '...'; }