mirror of
https://github.com/cpvalente/ontime.git
synced 2026-09-08 15:59:16 +00:00
refactor: restructure model to contain an object of rundowns
This commit is contained in:
@@ -1,61 +1,84 @@
|
||||
import { OntimeBlock, OntimeEvent, OntimeRundown, SupportedEvent } from 'ontime-types';
|
||||
import { OntimeEvent, SupportedEvent } from 'ontime-types';
|
||||
import { MILLIS_PER_HOUR } from 'ontime-utils';
|
||||
|
||||
import { apply } from '../delayUtils.js';
|
||||
import { makeOntimeDelay, makeOntimeEvent } from '../__mocks__/rundown.mocks.js';
|
||||
import { makeOntimeBlock, makeOntimeDelay, makeOntimeEvent, makeRundown } from '../__mocks__/rundown.mocks.js';
|
||||
|
||||
describe('apply()', () => {
|
||||
it('applies a positive delay to the rundown', () => {
|
||||
const testRundown = [
|
||||
makeOntimeDelay(10),
|
||||
makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 10, duration: 10 }),
|
||||
makeOntimeEvent({ id: '2', timeStart: 10, timeEnd: 20, duration: 10, linkStart: '1' }),
|
||||
{ id: '3', type: SupportedEvent.Block } as OntimeBlock,
|
||||
makeOntimeEvent({ id: '4', timeStart: 20, timeEnd: 30, duration: 10, linkStart: null }),
|
||||
makeOntimeEvent({ id: '5', timeStart: 30, timeEnd: 40, duration: 10, linkStart: '4' }),
|
||||
];
|
||||
const testRundown = makeRundown({
|
||||
revision: 0,
|
||||
order: ['delay', '1', '2', '3', '4', '5'],
|
||||
entries: {
|
||||
delay: makeOntimeDelay({ id: 'delay', duration: 10 }),
|
||||
'1': makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 10, duration: 10 }),
|
||||
'2': makeOntimeEvent({ id: '2', timeStart: 10, timeEnd: 20, duration: 10, linkStart: '1' }),
|
||||
'3': makeOntimeBlock({ id: '3' }),
|
||||
'4': makeOntimeEvent({ id: '4', timeStart: 20, timeEnd: 30, duration: 10, linkStart: null }),
|
||||
'5': makeOntimeEvent({ id: '5', timeStart: 30, timeEnd: 40, duration: 10, linkStart: '4' }),
|
||||
},
|
||||
});
|
||||
|
||||
const updatedRundown = apply('delay', testRundown);
|
||||
expect(updatedRundown).not.toBe(testRundown);
|
||||
expect(updatedRundown).toMatchObject([
|
||||
{ id: '1', timeStart: 10, timeEnd: 20, duration: 10, revision: 2 },
|
||||
{ id: '2', timeStart: 20, timeEnd: 30, duration: 10, revision: 2, linkStart: '1' },
|
||||
{ id: '3' },
|
||||
{ id: '4', timeStart: 30, timeEnd: 40, duration: 10, revision: 2, linkStart: null },
|
||||
{ id: '5', timeStart: 40, timeEnd: 50, duration: 10, revision: 2, linkStart: '4' },
|
||||
]);
|
||||
apply('delay', testRundown);
|
||||
expect(testRundown.revision).toBe(1);
|
||||
expect(testRundown.order).toMatchObject(['1', '2', '3', '4', '5']);
|
||||
expect(testRundown.entries).toMatchObject({
|
||||
'1': { id: '1', timeStart: 10, timeEnd: 20, duration: 10, revision: 2 },
|
||||
'2': { id: '2', timeStart: 20, timeEnd: 30, duration: 10, revision: 2, linkStart: '1' },
|
||||
'3': { id: '3' },
|
||||
'4': { id: '4', timeStart: 30, timeEnd: 40, duration: 10, revision: 2, linkStart: null },
|
||||
'5': { id: '5', timeStart: 40, timeEnd: 50, duration: 10, revision: 2, linkStart: '4' },
|
||||
});
|
||||
});
|
||||
|
||||
it('applies negative delays', () => {
|
||||
const testRundown = [
|
||||
makeOntimeDelay(-10),
|
||||
makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 10, duration: 10 }),
|
||||
makeOntimeEvent({ id: '2', timeStart: 10, timeEnd: 20, duration: 10, linkStart: '1' }),
|
||||
{ id: '3', type: SupportedEvent.Block } as OntimeBlock,
|
||||
makeOntimeEvent({ id: '4', timeStart: 20, timeEnd: 30, duration: 10, linkStart: null }),
|
||||
makeOntimeEvent({ id: '5', timeStart: 30, timeEnd: 40, duration: 10, linkStart: '4' }),
|
||||
];
|
||||
const testRundown = makeRundown({
|
||||
revision: 0,
|
||||
order: ['delay', '1', '2', '3', '4', '5'],
|
||||
entries: {
|
||||
delay: makeOntimeDelay({ id: 'delay', duration: -10 }),
|
||||
'1': makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 10, duration: 10 }),
|
||||
'2': makeOntimeEvent({ id: '2', timeStart: 10, timeEnd: 20, duration: 10, linkStart: '1' }),
|
||||
'3': makeOntimeBlock({ id: '3' }),
|
||||
'4': makeOntimeEvent({ id: '4', timeStart: 20, timeEnd: 30, duration: 10, linkStart: null }),
|
||||
'5': makeOntimeEvent({ id: '5', timeStart: 30, timeEnd: 40, duration: 10, linkStart: '4' }),
|
||||
},
|
||||
});
|
||||
|
||||
const updatedRundown = apply('delay', testRundown);
|
||||
expect(updatedRundown).toMatchObject([
|
||||
{ id: '1', timeStart: 0, timeEnd: 10, duration: 10, revision: 2 },
|
||||
{ id: '2', timeStart: 0, timeEnd: 10, duration: 10, revision: 2, linkStart: null },
|
||||
{ id: '3' },
|
||||
{ id: '4', timeStart: 10, timeEnd: 20, duration: 10, revision: 2, linkStart: null },
|
||||
{ id: '5', timeStart: 20, timeEnd: 30, duration: 10, revision: 2, linkStart: '4' },
|
||||
]);
|
||||
apply('delay', testRundown);
|
||||
expect(testRundown.revision).toBe(1);
|
||||
expect(testRundown.order).toMatchObject(['1', '2', '3', '4', '5']);
|
||||
expect(testRundown.entries).toMatchObject({
|
||||
'1': { id: '1', timeStart: 0, timeEnd: 10, duration: 10, revision: 2 },
|
||||
'2': { id: '2', timeStart: 0, timeEnd: 10, duration: 10, revision: 2, linkStart: null },
|
||||
'3': { id: '3' },
|
||||
'4': { id: '4', timeStart: 10, timeEnd: 20, duration: 10, revision: 2, linkStart: null },
|
||||
'5': { id: '5', timeStart: 20, timeEnd: 30, duration: 10, revision: 2, linkStart: '4' },
|
||||
});
|
||||
});
|
||||
|
||||
it('should account for minimum duration and start when applying negative delays', () => {
|
||||
const testRundown: OntimeRundown = [
|
||||
makeOntimeDelay(-50),
|
||||
makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 100, duration: 100 }),
|
||||
makeOntimeEvent({ id: '2', timeStart: 100, timeEnd: 150, duration: 50, linkStart: '1' }),
|
||||
];
|
||||
const testRundown = makeRundown({
|
||||
order: ['delay', '1', '2'],
|
||||
entries: {
|
||||
delay: makeOntimeDelay({ id: 'delay', duration: -50 }),
|
||||
'1': makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 100, duration: 100 }),
|
||||
'2': makeOntimeEvent({ id: '2', timeStart: 100, timeEnd: 150, duration: 50, linkStart: '1' }),
|
||||
},
|
||||
});
|
||||
|
||||
const expected = [
|
||||
{ id: '1', type: SupportedEvent.Event, timeStart: 0, timeEnd: 100, duration: 100, revision: 2 } as OntimeEvent,
|
||||
{
|
||||
apply('delay', testRundown);
|
||||
expect(testRundown.order).toMatchObject(['1', '2']);
|
||||
expect(testRundown.entries).toMatchObject({
|
||||
'1': {
|
||||
id: '1',
|
||||
type: SupportedEvent.Event,
|
||||
timeStart: 0,
|
||||
timeEnd: 100,
|
||||
duration: 100,
|
||||
revision: 2,
|
||||
} as OntimeEvent,
|
||||
'2': {
|
||||
id: '2',
|
||||
type: SupportedEvent.Event,
|
||||
timeStart: 50,
|
||||
@@ -63,173 +86,222 @@ describe('apply()', () => {
|
||||
duration: 50,
|
||||
linkStart: null,
|
||||
revision: 2,
|
||||
} as OntimeEvent,
|
||||
];
|
||||
|
||||
const updatedRundown = apply('delay', testRundown);
|
||||
expect(updatedRundown).toMatchObject(expected);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('unlinks events to maintain gaps when applying positive delays', () => {
|
||||
const testRundown = [
|
||||
makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 100, duration: 100, revision: 1 }),
|
||||
makeOntimeDelay(50),
|
||||
makeOntimeEvent({ id: '2', timeStart: 100, timeEnd: 150, duration: 50, revision: 1, linkStart: '1' }),
|
||||
];
|
||||
const testRundown = makeRundown({
|
||||
order: ['1', 'delay', '2'],
|
||||
entries: {
|
||||
'1': makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 100, duration: 100, revision: 1 }),
|
||||
delay: makeOntimeDelay({ id: 'delay', duration: 50 }),
|
||||
'2': makeOntimeEvent({ id: '2', timeStart: 100, timeEnd: 150, duration: 50, revision: 1, linkStart: '1' }),
|
||||
},
|
||||
});
|
||||
|
||||
expect(apply('delay', testRundown)).toMatchObject([
|
||||
{ id: '1', type: SupportedEvent.Event, timeStart: 0, timeEnd: 100, duration: 100, revision: 1 } as OntimeEvent,
|
||||
{
|
||||
apply('delay', testRundown);
|
||||
expect(testRundown.order).toMatchObject(['1', '2']);
|
||||
expect(testRundown.entries).toMatchObject({
|
||||
'1': {
|
||||
id: '1',
|
||||
timeStart: 0,
|
||||
timeEnd: 100,
|
||||
duration: 100,
|
||||
revision: 1,
|
||||
},
|
||||
'2': {
|
||||
id: '2',
|
||||
type: SupportedEvent.Event,
|
||||
timeStart: 150,
|
||||
timeEnd: 200,
|
||||
duration: 50,
|
||||
linkStart: null,
|
||||
revision: 2,
|
||||
} as OntimeEvent,
|
||||
]);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('maintains links if there is no gap', () => {
|
||||
const testRundown = [
|
||||
makeOntimeDelay(50),
|
||||
makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 100, duration: 100, revision: 1 }),
|
||||
makeOntimeEvent({ id: '2', timeStart: 100, timeEnd: 150, duration: 50, revision: 1, linkStart: '1' }),
|
||||
];
|
||||
const testRundown = makeRundown({
|
||||
order: ['delay', '1', '2'],
|
||||
entries: {
|
||||
delay: makeOntimeDelay({ id: 'delay', duration: 50 }),
|
||||
'1': makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 100, duration: 100, revision: 1 }),
|
||||
'2': makeOntimeEvent({ id: '2', timeStart: 100, timeEnd: 150, duration: 50, revision: 1, linkStart: '1' }),
|
||||
},
|
||||
});
|
||||
|
||||
expect(apply('delay', testRundown)).toMatchObject([
|
||||
{ id: '1', type: SupportedEvent.Event, timeStart: 50, timeEnd: 150, duration: 100, revision: 2 } as OntimeEvent,
|
||||
{
|
||||
apply('delay', testRundown);
|
||||
expect(testRundown.order).toMatchObject(['1', '2']);
|
||||
expect(testRundown.entries).toMatchObject({
|
||||
'1': {
|
||||
id: '1',
|
||||
timeStart: 50,
|
||||
timeEnd: 150,
|
||||
duration: 100,
|
||||
revision: 2,
|
||||
},
|
||||
'2': {
|
||||
id: '2',
|
||||
type: SupportedEvent.Event,
|
||||
timeStart: 150,
|
||||
timeEnd: 200,
|
||||
duration: 50,
|
||||
linkStart: '1',
|
||||
revision: 2,
|
||||
} as OntimeEvent,
|
||||
]);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('unlinks events to maintain gaps when applying negative delays', () => {
|
||||
const testRundown = [
|
||||
makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 100, duration: 100, revision: 1 }),
|
||||
makeOntimeDelay(-50),
|
||||
makeOntimeEvent({ id: '2', timeStart: 100, timeEnd: 150, duration: 50, revision: 1, linkStart: '1' }),
|
||||
];
|
||||
const testRundown = makeRundown({
|
||||
order: ['1', 'delay', '2'],
|
||||
entries: {
|
||||
'1': makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 100, duration: 100, revision: 1 }),
|
||||
delay: makeOntimeDelay({ id: 'delay', duration: -50 }),
|
||||
'2': makeOntimeEvent({ id: '2', timeStart: 100, timeEnd: 150, duration: 50, revision: 1, linkStart: '1' }),
|
||||
},
|
||||
});
|
||||
|
||||
expect(apply('delay', testRundown)).toMatchObject([
|
||||
{ id: '1', type: SupportedEvent.Event, timeStart: 0, timeEnd: 100, duration: 100, revision: 1 } as OntimeEvent,
|
||||
{
|
||||
apply('delay', testRundown);
|
||||
expect(testRundown.order).toMatchObject(['1', '2']);
|
||||
expect(testRundown.entries).toMatchObject({
|
||||
'1': { id: '1', timeStart: 0, timeEnd: 100, duration: 100, revision: 1 },
|
||||
'2': {
|
||||
id: '2',
|
||||
type: SupportedEvent.Event,
|
||||
timeStart: 50,
|
||||
timeEnd: 100,
|
||||
duration: 50,
|
||||
linkStart: null,
|
||||
revision: 2,
|
||||
} as OntimeEvent,
|
||||
]);
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('gaps reduce positive delay', () => {
|
||||
const testRundown: OntimeRundown = [
|
||||
makeOntimeDelay(100),
|
||||
makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 100, duration: 100 }),
|
||||
// gap 50
|
||||
makeOntimeEvent({ id: '2', timeStart: 150, timeEnd: 200, duration: 50, gap: 50 }),
|
||||
// gap 0
|
||||
makeOntimeEvent({ id: '3', timeStart: 200, timeEnd: 250, duration: 50, gap: 0 }),
|
||||
// gap 50
|
||||
makeOntimeEvent({ id: '4', timeStart: 300, timeEnd: 350, duration: 50, gap: 50 }),
|
||||
// linked
|
||||
makeOntimeEvent({ id: '5', timeStart: 350, timeEnd: 400, duration: 50, linkStart: '4' }),
|
||||
];
|
||||
const testRundown = makeRundown({
|
||||
order: ['delay', '1', '2', '3', '4', '5'],
|
||||
entries: {
|
||||
delay: makeOntimeDelay({ id: 'delay', duration: 100 }),
|
||||
'1': makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 100, duration: 100 }),
|
||||
// gap 50
|
||||
'2': makeOntimeEvent({ id: '2', timeStart: 150, timeEnd: 200, duration: 50, gap: 50 }),
|
||||
// gap 0
|
||||
'3': makeOntimeEvent({ id: '3', timeStart: 200, timeEnd: 250, duration: 50, gap: 0 }),
|
||||
// gap 50
|
||||
'4': makeOntimeEvent({ id: '4', timeStart: 300, timeEnd: 350, duration: 50, gap: 50 }),
|
||||
// linked
|
||||
'5': makeOntimeEvent({ id: '5', timeStart: 350, timeEnd: 400, duration: 50, linkStart: '4' }),
|
||||
},
|
||||
});
|
||||
|
||||
const updatedRundown = apply('delay', testRundown);
|
||||
expect(updatedRundown).toMatchObject([
|
||||
{ id: '1', timeStart: 0 + 100, timeEnd: 100 + 100, duration: 100, revision: 2 },
|
||||
apply('delay', testRundown);
|
||||
expect(testRundown.order).toMatchObject(['1', '2', '3', '4', '5']);
|
||||
expect(testRundown.entries).toMatchObject({
|
||||
'1': { id: '1', timeStart: 0 + 100, timeEnd: 100 + 100, duration: 100, revision: 2 },
|
||||
// gap 50 (100 - 50)
|
||||
{ id: '2', timeStart: 150 + 50, timeEnd: 200 + 50, duration: 50, revision: 2 },
|
||||
'2': { id: '2', timeStart: 150 + 50, timeEnd: 200 + 50, duration: 50, revision: 2 },
|
||||
// gap 50 (50 - 50)
|
||||
{ id: '3', timeStart: 200 + 50, timeEnd: 250 + 50, duration: 50, revision: 2, gap: 0 },
|
||||
'3': { id: '3', timeStart: 200 + 50, timeEnd: 250 + 50, duration: 50, revision: 2, gap: 0 },
|
||||
// gap (delay is 0)
|
||||
{ id: '4', timeStart: 300, timeEnd: 350, duration: 50, revision: 1 },
|
||||
'4': { id: '4', timeStart: 300, timeEnd: 350, duration: 50, revision: 1 },
|
||||
// linked
|
||||
{ id: '5', timeStart: 350, timeEnd: 400, duration: 50, revision: 1, linkStart: '4' },
|
||||
]);
|
||||
'5': { id: '5', timeStart: 350, timeEnd: 400, duration: 50, revision: 1, linkStart: '4' },
|
||||
});
|
||||
});
|
||||
|
||||
it('gaps reduce positive delay (2)', () => {
|
||||
const testRundown: OntimeRundown = [
|
||||
makeOntimeDelay(2 * MILLIS_PER_HOUR),
|
||||
makeOntimeEvent({
|
||||
id: '1',
|
||||
gap: 0,
|
||||
dayOffset: 0,
|
||||
timeStart: 46800000, // 13:00:00
|
||||
timeEnd: 50400000, // 14:00:00
|
||||
duration: MILLIS_PER_HOUR,
|
||||
}),
|
||||
// gap 1h
|
||||
makeOntimeEvent({
|
||||
id: '2',
|
||||
gap: 1 * MILLIS_PER_HOUR,
|
||||
dayOffset: 0,
|
||||
timeStart: 54000000, // 15:00:00
|
||||
timeEnd: 57600000, // 16:00:00
|
||||
duration: MILLIS_PER_HOUR,
|
||||
}),
|
||||
];
|
||||
const testRundown = makeRundown({
|
||||
order: ['delay', '1', '2'],
|
||||
entries: {
|
||||
delay: makeOntimeDelay({ id: 'delay', duration: 2 * MILLIS_PER_HOUR }),
|
||||
'1': makeOntimeEvent({
|
||||
id: '1',
|
||||
gap: 0,
|
||||
dayOffset: 0,
|
||||
timeStart: 46800000, // 13:00:00
|
||||
timeEnd: 50400000, // 14:00:00
|
||||
duration: MILLIS_PER_HOUR,
|
||||
}),
|
||||
// gap 1h
|
||||
'2': makeOntimeEvent({
|
||||
id: '2',
|
||||
gap: 1 * MILLIS_PER_HOUR,
|
||||
dayOffset: 0,
|
||||
timeStart: 54000000, // 15:00:00
|
||||
timeEnd: 57600000, // 16:00:00
|
||||
duration: MILLIS_PER_HOUR,
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
const updatedRundown = apply('delay', testRundown);
|
||||
expect(updatedRundown).toMatchObject([
|
||||
{ id: '1', timeStart: 54000000 /* 16 */, revision: 2 },
|
||||
apply('delay', testRundown);
|
||||
expect(testRundown.order).toMatchObject(['1', '2']);
|
||||
expect(testRundown.entries).toMatchObject({
|
||||
'1': { id: '1', timeStart: 54000000 /* 16 */, revision: 2 },
|
||||
// gap 1h (2h - 1h)
|
||||
{ id: '2', timeStart: 57600000 /* 16 */, revision: 2 },
|
||||
]);
|
||||
'2': { id: '2', timeStart: 57600000 /* 16 */, revision: 2 },
|
||||
});
|
||||
});
|
||||
|
||||
it('removes empty delays without applying changes', () => {
|
||||
const testRundown: OntimeRundown = [
|
||||
makeOntimeDelay(0),
|
||||
makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 100, duration: 100 }),
|
||||
];
|
||||
const testRundown = makeRundown({
|
||||
order: ['delay', '1'],
|
||||
entries: {
|
||||
delay: makeOntimeDelay({ id: 'delay', duration: 0 }),
|
||||
'1': makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 100, duration: 100 }),
|
||||
},
|
||||
});
|
||||
|
||||
const updatedRundown = apply('delay', testRundown);
|
||||
expect(updatedRundown).toMatchObject([{ id: '1', timeStart: 0, timeEnd: 100, duration: 100 }]);
|
||||
apply('delay', testRundown);
|
||||
expect(testRundown.order).toMatchObject(['1']);
|
||||
expect(testRundown.entries).toMatchObject({ '1': { id: '1', timeStart: 0, timeEnd: 100, duration: 100 } });
|
||||
});
|
||||
|
||||
it('removes delays in last position without applying changes', () => {
|
||||
const testRundown: OntimeRundown = [
|
||||
makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 100, duration: 100 }),
|
||||
makeOntimeDelay(100),
|
||||
];
|
||||
const testRundown = makeRundown({
|
||||
order: ['1', 'delay'],
|
||||
entries: {
|
||||
'1': makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 100, duration: 100 }),
|
||||
delay: makeOntimeDelay({ id: 'delay', duration: 100 }),
|
||||
},
|
||||
});
|
||||
|
||||
const updatedRundown = apply('delay', testRundown);
|
||||
expect(updatedRundown).toMatchObject([{ id: '1', timeStart: 0, timeEnd: 100, duration: 100 }]);
|
||||
apply('delay', testRundown);
|
||||
expect(testRundown.order).toMatchObject(['1']);
|
||||
expect(testRundown.entries).toMatchObject({ '1': { id: '1', timeStart: 0, timeEnd: 100, duration: 100 } });
|
||||
});
|
||||
|
||||
it('unlinks events to across blocks is it is the first event after the delay', () => {
|
||||
const testRundown = [
|
||||
makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 100, duration: 100, revision: 1 }),
|
||||
makeOntimeDelay(50),
|
||||
{ id: 'block', type: SupportedEvent.Block } as OntimeBlock,
|
||||
makeOntimeEvent({ id: '2', timeStart: 100, timeEnd: 150, duration: 50, revision: 1, linkStart: '1' }),
|
||||
];
|
||||
expect(apply('delay', testRundown)).toMatchObject([
|
||||
{ id: '1', type: SupportedEvent.Event, timeStart: 0, timeEnd: 100, duration: 100, revision: 1 } as OntimeEvent,
|
||||
{ id: 'block', type: SupportedEvent.Block },
|
||||
{
|
||||
const testRundown = makeRundown({
|
||||
order: ['1', 'delay', 'block', '2'],
|
||||
entries: {
|
||||
'1': makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 100, duration: 100, revision: 1 }),
|
||||
delay: makeOntimeDelay({ id: 'delay', duration: 50 }),
|
||||
block: makeOntimeBlock({ id: 'block' }),
|
||||
'2': makeOntimeEvent({ id: '2', timeStart: 100, timeEnd: 150, duration: 50, revision: 1, linkStart: '1' }),
|
||||
},
|
||||
});
|
||||
|
||||
apply('delay', testRundown);
|
||||
expect(testRundown.order).toMatchObject(['1', 'block', '2']);
|
||||
|
||||
expect(testRundown.entries).toMatchObject({
|
||||
'1': {
|
||||
id: '1',
|
||||
timeStart: 0,
|
||||
timeEnd: 100,
|
||||
duration: 100,
|
||||
revision: 1,
|
||||
},
|
||||
block: { id: 'block' },
|
||||
'2': {
|
||||
id: '2',
|
||||
type: SupportedEvent.Event,
|
||||
timeStart: 150,
|
||||
timeEnd: 200,
|
||||
duration: 50,
|
||||
linkStart: null,
|
||||
revision: 2,
|
||||
} as OntimeEvent,
|
||||
]);
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,13 +1,4 @@
|
||||
import {
|
||||
CustomFields,
|
||||
EventCustomFields,
|
||||
OntimeBlock,
|
||||
OntimeDelay,
|
||||
OntimeEvent,
|
||||
OntimeRundown,
|
||||
SupportedEvent,
|
||||
TimeStrategy,
|
||||
} from 'ontime-types';
|
||||
import { CustomFields, OntimeEvent, SupportedEvent, TimeStrategy } from 'ontime-types';
|
||||
import { MILLIS_PER_HOUR, MILLIS_PER_MINUTE, dayInMs } from 'ontime-utils';
|
||||
|
||||
import {
|
||||
@@ -23,6 +14,7 @@ import {
|
||||
removeCustomField,
|
||||
customFieldChangelog,
|
||||
} from '../rundownCache.js';
|
||||
import { makeOntimeBlock, makeOntimeDelay, makeOntimeEvent, makeRundown } from '../__mocks__/rundown.mocks.js';
|
||||
|
||||
beforeAll(() => {
|
||||
vi.mock('../../../classes/data-provider/DataProvider.js', () => {
|
||||
@@ -39,13 +31,16 @@ beforeAll(() => {
|
||||
|
||||
describe('generate()', () => {
|
||||
it('creates normalised versions of a given rundown', () => {
|
||||
const testRundown: OntimeRundown = [
|
||||
{ type: SupportedEvent.Event, id: '1' } as OntimeEvent,
|
||||
{ type: SupportedEvent.Block, id: '2' } as OntimeBlock,
|
||||
{ type: SupportedEvent.Delay, id: '3' } as OntimeDelay,
|
||||
];
|
||||
const rundown = makeRundown({
|
||||
order: ['1', '2', '3'],
|
||||
entries: {
|
||||
'1': makeOntimeEvent({ id: '1' }),
|
||||
'2': makeOntimeBlock({ id: '2' }),
|
||||
'3': makeOntimeDelay({ id: '3' }),
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(testRundown);
|
||||
const initResult = generate(rundown);
|
||||
expect(initResult.order.length).toBe(3);
|
||||
expect(initResult.order).toStrictEqual(['1', '2', '3']);
|
||||
expect(initResult.rundown['1'].type).toBe(SupportedEvent.Event);
|
||||
@@ -54,29 +49,35 @@ describe('generate()', () => {
|
||||
});
|
||||
|
||||
it('calculates delays versions of a given rundown', () => {
|
||||
const testRundown: OntimeRundown = [
|
||||
{ type: SupportedEvent.Delay, id: '1', duration: 100 } as OntimeDelay,
|
||||
{ type: SupportedEvent.Event, id: '2', timeStart: 1, timeEnd: 100 } as OntimeEvent,
|
||||
];
|
||||
const rundown = makeRundown({
|
||||
order: ['1', '2'],
|
||||
entries: {
|
||||
'1': makeOntimeDelay({ id: '1', duration: 100 }),
|
||||
'2': makeOntimeEvent({ id: '2', timeStart: 1, timeEnd: 100 }),
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(testRundown);
|
||||
const initResult = generate(rundown);
|
||||
expect(initResult.order.length).toBe(2);
|
||||
expect((initResult.rundown['2'] as OntimeEvent).delay).toBe(100);
|
||||
expect(initResult.totalDelay).toBe(100);
|
||||
});
|
||||
|
||||
it('accounts for gaps in rundown when calculating delays', () => {
|
||||
const testRundown: OntimeRundown = [
|
||||
{ type: SupportedEvent.Event, id: '1', timeStart: 100, timeEnd: 200, duration: 100 } as OntimeEvent,
|
||||
{ type: SupportedEvent.Delay, id: 'delay', duration: 200 } as OntimeDelay,
|
||||
{ type: SupportedEvent.Event, id: '2', timeStart: 200, timeEnd: 300, duration: 100 } as OntimeEvent,
|
||||
{ type: SupportedEvent.Block, id: 'block', title: 'break' } as OntimeBlock,
|
||||
{ type: SupportedEvent.Event, id: '3', timeStart: 400, timeEnd: 500, duration: 100 } as OntimeEvent,
|
||||
{ type: SupportedEvent.Block, id: 'another-block', title: 'another-break' } as OntimeBlock,
|
||||
{ type: SupportedEvent.Event, id: '4', timeStart: 600, timeEnd: 700, duration: 100 } as OntimeEvent,
|
||||
];
|
||||
const rundown = makeRundown({
|
||||
order: ['1', 'delay', '2', 'block', '3', 'another-block', '4'],
|
||||
entries: {
|
||||
'1': makeOntimeEvent({ id: '1', timeStart: 100, timeEnd: 200, duration: 100 }),
|
||||
delay: makeOntimeDelay({ id: 'delay', duration: 200 }),
|
||||
'2': makeOntimeEvent({ id: '2', timeStart: 200, timeEnd: 300, duration: 100 }),
|
||||
block: makeOntimeBlock({ id: 'block', title: 'break' }),
|
||||
'3': makeOntimeEvent({ id: '3', timeStart: 400, timeEnd: 500, duration: 100 }),
|
||||
'another-block': makeOntimeBlock({ id: 'another-block', title: 'another-break' }),
|
||||
'4': makeOntimeEvent({ id: '4', timeStart: 600, timeEnd: 700, duration: 100 }),
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(testRundown);
|
||||
const initResult = generate(rundown);
|
||||
expect(initResult.order.length).toBe(7);
|
||||
expect((initResult.rundown['1'] as OntimeEvent).delay).toBe(0);
|
||||
expect((initResult.rundown['2'] as OntimeEvent).delay).toBe(200);
|
||||
@@ -87,76 +88,84 @@ describe('generate()', () => {
|
||||
});
|
||||
|
||||
it('accounts for overlaps in rundown', () => {
|
||||
const testRundown: OntimeRundown = [
|
||||
{ type: SupportedEvent.Event, id: '1', timeStart: 9000, timeEnd: 10000, duration: 1000 } as OntimeEvent,
|
||||
{ type: SupportedEvent.Event, id: '2', timeStart: 9250, timeEnd: 9500, duration: 250 } as OntimeEvent,
|
||||
{ type: SupportedEvent.Event, id: '3', timeStart: 9500, timeEnd: 10500, duration: 1000 } as OntimeEvent,
|
||||
];
|
||||
const rundown = makeRundown({
|
||||
order: ['1', '2', '3'],
|
||||
entries: {
|
||||
'1': makeOntimeEvent({ id: '1', timeStart: 9000, timeEnd: 10000, duration: 1000 }),
|
||||
'2': makeOntimeEvent({ id: '2', timeStart: 9250, timeEnd: 9500, duration: 250 }),
|
||||
'3': makeOntimeEvent({ id: '3', timeStart: 9500, timeEnd: 10500, duration: 1000 }),
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(testRundown);
|
||||
const initResult = generate(rundown);
|
||||
expect(initResult.totalDuration).toBe(10500 - 9000); // last end - first start
|
||||
});
|
||||
|
||||
it('accounts for overlaps in rundown (with added gap)', () => {
|
||||
const testRundown: OntimeRundown = [
|
||||
{ type: SupportedEvent.Event, id: '1', timeStart: 9000, timeEnd: 10000, duration: 1000 } as OntimeEvent,
|
||||
{ type: SupportedEvent.Event, id: '2', timeStart: 9250, timeEnd: 9500, duration: 250 } as OntimeEvent,
|
||||
{ type: SupportedEvent.Event, id: '3', timeStart: 9500, timeEnd: 10500, duration: 1000 } as OntimeEvent,
|
||||
{ type: SupportedEvent.Event, id: '4', timeStart: 15000, timeEnd: 20000, duration: 5000 } as OntimeEvent,
|
||||
];
|
||||
const rundown = makeRundown({
|
||||
order: ['1', '2', '3', '4'],
|
||||
entries: {
|
||||
'1': makeOntimeEvent({ id: '1', timeStart: 9000, timeEnd: 10000, duration: 1000 }),
|
||||
'2': makeOntimeEvent({ id: '2', timeStart: 9250, timeEnd: 9500, duration: 250 }),
|
||||
'3': makeOntimeEvent({ id: '3', timeStart: 9500, timeEnd: 10500, duration: 1000 }),
|
||||
'4': makeOntimeEvent({ id: '4', timeStart: 15000, timeEnd: 20000, duration: 5000 }),
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(testRundown);
|
||||
const initResult = generate(rundown);
|
||||
expect(initResult.totalDuration).toBe(20000 - 9000); // last end - first start
|
||||
});
|
||||
|
||||
it('accounts for overlaps in rundown (with multiple days)', () => {
|
||||
const testRundown: OntimeRundown = [
|
||||
{
|
||||
type: SupportedEvent.Event,
|
||||
id: '1',
|
||||
timeStart: 9 * MILLIS_PER_HOUR,
|
||||
timeEnd: 10 * MILLIS_PER_HOUR,
|
||||
duration: MILLIS_PER_HOUR,
|
||||
} as OntimeEvent,
|
||||
{
|
||||
type: SupportedEvent.Event,
|
||||
id: '2',
|
||||
timeStart: 9 * MILLIS_PER_HOUR + 15 * MILLIS_PER_MINUTE,
|
||||
timeEnd: 9 * MILLIS_PER_HOUR + 45 * MILLIS_PER_MINUTE,
|
||||
duration: 30 * MILLIS_PER_MINUTE,
|
||||
} as OntimeEvent,
|
||||
{
|
||||
type: SupportedEvent.Event,
|
||||
id: '3',
|
||||
timeStart: 9 * MILLIS_PER_HOUR + 30 * MILLIS_PER_MINUTE,
|
||||
timeEnd: 10 * MILLIS_PER_HOUR + 30 * MILLIS_PER_MINUTE,
|
||||
duration: MILLIS_PER_HOUR,
|
||||
} as OntimeEvent,
|
||||
{
|
||||
type: SupportedEvent.Event,
|
||||
id: '4',
|
||||
timeStart: 9 * MILLIS_PER_HOUR,
|
||||
timeEnd: 10 * MILLIS_PER_HOUR,
|
||||
duration: MILLIS_PER_HOUR,
|
||||
} as OntimeEvent,
|
||||
];
|
||||
const rundown = makeRundown({
|
||||
order: ['1', '2', '3', '4'],
|
||||
entries: {
|
||||
'1': makeOntimeEvent({
|
||||
id: '1',
|
||||
timeStart: 9 * MILLIS_PER_HOUR,
|
||||
timeEnd: 10 * MILLIS_PER_HOUR,
|
||||
duration: MILLIS_PER_HOUR,
|
||||
}),
|
||||
'2': makeOntimeEvent({
|
||||
id: '2',
|
||||
timeStart: 9 * MILLIS_PER_HOUR + 15 * MILLIS_PER_MINUTE,
|
||||
timeEnd: 9 * MILLIS_PER_HOUR + 45 * MILLIS_PER_MINUTE,
|
||||
duration: 30 * MILLIS_PER_MINUTE,
|
||||
}),
|
||||
'3': makeOntimeEvent({
|
||||
id: '3',
|
||||
timeStart: 9 * MILLIS_PER_HOUR + 30 * MILLIS_PER_MINUTE,
|
||||
timeEnd: 10 * MILLIS_PER_HOUR + 30 * MILLIS_PER_MINUTE,
|
||||
duration: MILLIS_PER_HOUR,
|
||||
}),
|
||||
'4': makeOntimeEvent({
|
||||
id: '4',
|
||||
timeStart: 9 * MILLIS_PER_HOUR,
|
||||
timeEnd: 10 * MILLIS_PER_HOUR,
|
||||
duration: MILLIS_PER_HOUR,
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(testRundown);
|
||||
const initResult = generate(rundown);
|
||||
expect(initResult.totalDuration).toBe(dayInMs + MILLIS_PER_HOUR); // day + last end - first start
|
||||
});
|
||||
|
||||
it('handles negative delays', () => {
|
||||
const testRundown: OntimeRundown = [
|
||||
{ type: SupportedEvent.Event, id: '1', timeStart: 100, timeEnd: 200, duration: 100 } as OntimeEvent,
|
||||
{ type: SupportedEvent.Delay, id: 'delay', duration: -200 } as OntimeDelay,
|
||||
{ type: SupportedEvent.Event, id: '2', timeStart: 200, timeEnd: 300, duration: 100 } as OntimeEvent,
|
||||
{ type: SupportedEvent.Block, id: 'block', title: 'break' } as OntimeBlock,
|
||||
{ type: SupportedEvent.Event, id: '3', timeStart: 400, timeEnd: 500, duration: 100 } as OntimeEvent,
|
||||
{ type: SupportedEvent.Block, id: 'another-block', title: 'another-break' } as OntimeBlock,
|
||||
{ type: SupportedEvent.Event, id: '4', timeStart: 600, timeEnd: 700, duration: 100 } as OntimeEvent,
|
||||
];
|
||||
const rundown = makeRundown({
|
||||
order: ['1', 'delay', '2', 'block', '3', 'another-block', '4'],
|
||||
entries: {
|
||||
'1': makeOntimeEvent({ id: '1', timeStart: 100, timeEnd: 200, duration: 100 }),
|
||||
delay: makeOntimeDelay({ id: 'delay', duration: -200 }),
|
||||
'2': makeOntimeEvent({ id: '2', timeStart: 200, timeEnd: 300, duration: 100 }),
|
||||
block: makeOntimeBlock({ id: 'block', title: 'break' }),
|
||||
'3': makeOntimeEvent({ id: '3', timeStart: 400, timeEnd: 500, duration: 100 }),
|
||||
'another-block': makeOntimeBlock({ id: 'another-block', title: 'another-break' }),
|
||||
'4': makeOntimeEvent({ id: '4', timeStart: 600, timeEnd: 700, duration: 100 }),
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(testRundown);
|
||||
const initResult = generate(rundown);
|
||||
expect(initResult.order.length).toBe(7);
|
||||
expect((initResult.rundown['1'] as OntimeEvent).delay).toBe(0);
|
||||
expect((initResult.rundown['2'] as OntimeEvent).delay).toBe(-200);
|
||||
@@ -167,38 +176,38 @@ describe('generate()', () => {
|
||||
});
|
||||
|
||||
it('links times across events', () => {
|
||||
const testRundown: OntimeRundown = [
|
||||
{
|
||||
type: SupportedEvent.Event,
|
||||
id: '1',
|
||||
timeStart: 1,
|
||||
duration: 1,
|
||||
timeEnd: 2,
|
||||
timeStrategy: TimeStrategy.LockEnd,
|
||||
} as OntimeEvent,
|
||||
{
|
||||
type: SupportedEvent.Event,
|
||||
id: '2',
|
||||
timeStart: 11,
|
||||
duration: 1,
|
||||
timeEnd: 12,
|
||||
linkStart: '1',
|
||||
timeStrategy: TimeStrategy.LockEnd,
|
||||
} as OntimeEvent,
|
||||
{ type: SupportedEvent.Block, id: 'block' } as OntimeBlock,
|
||||
{ type: SupportedEvent.Delay, id: 'delay' } as OntimeDelay,
|
||||
{
|
||||
type: SupportedEvent.Event,
|
||||
id: '3',
|
||||
timeStart: 21,
|
||||
duration: 1,
|
||||
timeEnd: 22,
|
||||
linkStart: '2',
|
||||
timeStrategy: TimeStrategy.LockEnd,
|
||||
} as OntimeEvent,
|
||||
];
|
||||
const rundown = makeRundown({
|
||||
order: ['1', '2', 'block', 'delay', '3'],
|
||||
entries: {
|
||||
'1': makeOntimeEvent({
|
||||
id: '1',
|
||||
timeStart: 1,
|
||||
duration: 1,
|
||||
timeEnd: 2,
|
||||
timeStrategy: TimeStrategy.LockEnd,
|
||||
}),
|
||||
'2': makeOntimeEvent({
|
||||
id: '2',
|
||||
timeStart: 11,
|
||||
duration: 1,
|
||||
timeEnd: 12,
|
||||
linkStart: '1',
|
||||
timeStrategy: TimeStrategy.LockEnd,
|
||||
}),
|
||||
block: makeOntimeBlock({ id: 'block' }),
|
||||
delay: makeOntimeDelay({ id: 'delay' }),
|
||||
'3': makeOntimeEvent({
|
||||
id: '3',
|
||||
timeStart: 21,
|
||||
duration: 1,
|
||||
timeEnd: 22,
|
||||
linkStart: '2',
|
||||
timeStrategy: TimeStrategy.LockEnd,
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(testRundown);
|
||||
const initResult = generate(rundown);
|
||||
expect(initResult.order.length).toBe(5);
|
||||
expect((initResult.rundown['2'] as OntimeEvent).timeStart).toBe(2);
|
||||
expect((initResult.rundown['2'] as OntimeEvent).timeEnd).toBe(12);
|
||||
@@ -213,13 +222,16 @@ describe('generate()', () => {
|
||||
});
|
||||
|
||||
it('links times across events, reordered', () => {
|
||||
const testRundown: OntimeRundown = [
|
||||
{ type: SupportedEvent.Event, id: '1', timeStart: 1, timeEnd: 2 } as OntimeEvent,
|
||||
{ type: SupportedEvent.Event, id: '3', timeStart: 21, timeEnd: 22, linkStart: '2' } as OntimeEvent,
|
||||
{ type: SupportedEvent.Event, id: '2', timeStart: 11, timeEnd: 12, linkStart: '1' } as OntimeEvent,
|
||||
];
|
||||
const rundown = makeRundown({
|
||||
order: ['1', '3', '2'],
|
||||
entries: {
|
||||
'1': makeOntimeEvent({ id: '1', timeStart: 1, timeEnd: 2 }),
|
||||
'3': makeOntimeEvent({ id: '3', timeStart: 21, timeEnd: 22, linkStart: '2' }),
|
||||
'2': makeOntimeEvent({ id: '2', timeStart: 11, timeEnd: 12, linkStart: '1' }),
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(testRundown);
|
||||
const initResult = generate(rundown);
|
||||
expect(initResult.order.length).toBe(3);
|
||||
expect((initResult.rundown['3'] as OntimeEvent).timeStart).toBe(2);
|
||||
expect(initResult.links['1']).toBe('3');
|
||||
@@ -227,159 +239,156 @@ describe('generate()', () => {
|
||||
});
|
||||
|
||||
it('calculates total duration', () => {
|
||||
const testRundown: OntimeRundown = [
|
||||
{ type: SupportedEvent.Event, id: '1', timeStart: 100, timeEnd: 200, duration: 100 } as OntimeEvent,
|
||||
{ type: SupportedEvent.Event, id: '2', timeStart: 200, timeEnd: 300, duration: 100 } as OntimeEvent,
|
||||
{
|
||||
type: SupportedEvent.Event,
|
||||
id: 'skipped',
|
||||
skip: true,
|
||||
timeStart: 300,
|
||||
timeEnd: 400,
|
||||
duration: 100,
|
||||
} as OntimeEvent,
|
||||
{ type: SupportedEvent.Event, id: '3', timeStart: 400, timeEnd: 500, duration: 100 } as OntimeEvent,
|
||||
];
|
||||
const rundown = makeRundown({
|
||||
order: ['1', '2', 'skipped', '3'],
|
||||
entries: {
|
||||
'1': makeOntimeEvent({ id: '1', timeStart: 100, timeEnd: 200, duration: 100 }),
|
||||
'2': makeOntimeEvent({ id: '2', timeStart: 200, timeEnd: 300, duration: 100 }),
|
||||
skipped: makeOntimeEvent({ id: 'skipped', skip: true, timeStart: 300, timeEnd: 400, duration: 100 }),
|
||||
'3': makeOntimeEvent({ id: '2', timeStart: 400, timeEnd: 500, duration: 100 }),
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(testRundown);
|
||||
const initResult = generate(rundown);
|
||||
expect(initResult.order.length).toBe(4);
|
||||
expect(initResult.totalDuration).toBe(500 - 100);
|
||||
});
|
||||
|
||||
it('calculates total duration with 0 duration events without causing a next day', () => {
|
||||
const testRundown: OntimeRundown = [
|
||||
{ type: SupportedEvent.Event, id: '1', timeStart: 100, timeEnd: 100, duration: 0 } as OntimeEvent,
|
||||
{ type: SupportedEvent.Event, id: '2', timeStart: 100, timeEnd: 300, duration: 200 } as OntimeEvent,
|
||||
{
|
||||
type: SupportedEvent.Event,
|
||||
id: 'skipped',
|
||||
skip: true,
|
||||
timeStart: 300,
|
||||
timeEnd: 400,
|
||||
duration: 0,
|
||||
} as OntimeEvent,
|
||||
{ type: SupportedEvent.Event, id: '3', timeStart: 400, timeEnd: 500, duration: 100 } as OntimeEvent,
|
||||
];
|
||||
const rundown = makeRundown({
|
||||
order: ['1', '2', 'skipped', '3'],
|
||||
entries: {
|
||||
'1': makeOntimeEvent({ id: '1', timeStart: 100, timeEnd: 100, duration: 0 }),
|
||||
'2': makeOntimeEvent({ id: '2', timeStart: 100, timeEnd: 300, duration: 200 }),
|
||||
skipped: makeOntimeEvent({ id: 'skipped', skip: true, timeStart: 300, timeEnd: 400, duration: 0 }),
|
||||
'3': makeOntimeEvent({ id: '2', timeStart: 400, timeEnd: 500, duration: 100 }),
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(testRundown);
|
||||
const initResult = generate(rundown);
|
||||
expect(initResult.order.length).toBe(4);
|
||||
expect(initResult.totalDuration).toBe(500 - 100);
|
||||
});
|
||||
|
||||
it('calculates total duration across days with gap', () => {
|
||||
const testRundown: OntimeRundown = [
|
||||
{
|
||||
type: SupportedEvent.Event,
|
||||
id: '1',
|
||||
timeStart: 9 * MILLIS_PER_HOUR,
|
||||
timeEnd: 23 * MILLIS_PER_HOUR,
|
||||
duration: (23 - 9) * MILLIS_PER_HOUR,
|
||||
} as OntimeEvent,
|
||||
{
|
||||
type: SupportedEvent.Event,
|
||||
id: '2',
|
||||
timeStart: 9 * MILLIS_PER_HOUR,
|
||||
timeEnd: 23 * MILLIS_PER_HOUR,
|
||||
duration: (23 - 9) * MILLIS_PER_HOUR,
|
||||
} as OntimeEvent,
|
||||
{
|
||||
type: SupportedEvent.Event,
|
||||
id: '3',
|
||||
timeStart: 9 * MILLIS_PER_HOUR,
|
||||
timeEnd: 23 * MILLIS_PER_HOUR,
|
||||
duration: (23 - 9) * MILLIS_PER_HOUR,
|
||||
} as OntimeEvent,
|
||||
];
|
||||
const rundown = makeRundown({
|
||||
order: ['1', '2', '3'],
|
||||
entries: {
|
||||
'1': makeOntimeEvent({
|
||||
id: '1',
|
||||
timeStart: 9 * MILLIS_PER_HOUR,
|
||||
timeEnd: 23 * MILLIS_PER_HOUR,
|
||||
duration: (23 - 9) * MILLIS_PER_HOUR,
|
||||
}),
|
||||
'2': makeOntimeEvent({
|
||||
id: '2',
|
||||
timeStart: 9 * MILLIS_PER_HOUR,
|
||||
timeEnd: 23 * MILLIS_PER_HOUR,
|
||||
duration: (23 - 9) * MILLIS_PER_HOUR,
|
||||
}),
|
||||
'3': makeOntimeEvent({
|
||||
id: '2',
|
||||
timeStart: 9 * MILLIS_PER_HOUR,
|
||||
timeEnd: 23 * MILLIS_PER_HOUR,
|
||||
duration: (23 - 9) * MILLIS_PER_HOUR,
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(testRundown);
|
||||
const initResult = generate(rundown);
|
||||
expect(initResult.totalDuration).toBe((23 - 9 + 48) * MILLIS_PER_HOUR);
|
||||
});
|
||||
|
||||
it('calculates total duration across days', () => {
|
||||
const testRundown: OntimeRundown = [
|
||||
{
|
||||
type: SupportedEvent.Event,
|
||||
id: '1',
|
||||
timeStart: 12 * MILLIS_PER_HOUR,
|
||||
timeEnd: 22 * MILLIS_PER_HOUR,
|
||||
duration: 10 * MILLIS_PER_HOUR,
|
||||
} as OntimeEvent,
|
||||
{
|
||||
type: SupportedEvent.Event,
|
||||
id: '2',
|
||||
timeStart: 22 * MILLIS_PER_HOUR,
|
||||
timeEnd: 8 * MILLIS_PER_HOUR,
|
||||
duration: (24 - 22 + 8) * MILLIS_PER_HOUR,
|
||||
} as OntimeEvent,
|
||||
];
|
||||
const rundown = makeRundown({
|
||||
order: ['1', '2'],
|
||||
entries: {
|
||||
'1': makeOntimeEvent({
|
||||
id: '1',
|
||||
timeStart: 12 * MILLIS_PER_HOUR,
|
||||
timeEnd: 22 * MILLIS_PER_HOUR,
|
||||
duration: 10 * MILLIS_PER_HOUR,
|
||||
}),
|
||||
'2': makeOntimeEvent({
|
||||
id: '2',
|
||||
timeStart: 22 * MILLIS_PER_HOUR,
|
||||
timeEnd: 8 * MILLIS_PER_HOUR,
|
||||
duration: (24 - 22 + 8) * MILLIS_PER_HOUR,
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(testRundown);
|
||||
const initResult = generate(rundown);
|
||||
const expectedDuration = 8 * MILLIS_PER_HOUR + (dayInMs - 12 * MILLIS_PER_HOUR);
|
||||
expect(initResult.totalDuration).toBe(expectedDuration);
|
||||
});
|
||||
|
||||
it('handles updating event sequence', () => {
|
||||
const testRundown: OntimeRundown = [
|
||||
{
|
||||
type: SupportedEvent.Event,
|
||||
id: '97cc3e',
|
||||
timeStart: 0,
|
||||
timeEnd: 600000,
|
||||
duration: 600000,
|
||||
timeStrategy: TimeStrategy.LockDuration,
|
||||
linkStart: null,
|
||||
} as OntimeEvent,
|
||||
{
|
||||
type: SupportedEvent.Event,
|
||||
id: 'e01948',
|
||||
timeStart: 600000,
|
||||
timeEnd: 601000,
|
||||
duration: 85801000, // <------------- value out of sync
|
||||
timeStrategy: TimeStrategy.LockEnd,
|
||||
linkStart: '97cc3e',
|
||||
} as OntimeEvent,
|
||||
{
|
||||
type: SupportedEvent.Event,
|
||||
id: '25c1af',
|
||||
timeStart: 100, // <------------- value out of sync
|
||||
timeEnd: 602000,
|
||||
duration: 0,
|
||||
timeStrategy: TimeStrategy.LockEnd,
|
||||
linkStart: 'e01948',
|
||||
} as OntimeEvent,
|
||||
];
|
||||
const rundown = makeRundown({
|
||||
order: ['1', '2', '3'],
|
||||
entries: {
|
||||
'1': makeOntimeEvent({
|
||||
id: '1',
|
||||
timeStart: 0,
|
||||
timeEnd: 600000,
|
||||
duration: 600000,
|
||||
timeStrategy: TimeStrategy.LockDuration,
|
||||
linkStart: null,
|
||||
}),
|
||||
'2': makeOntimeEvent({
|
||||
id: '2',
|
||||
timeStart: 600000,
|
||||
timeEnd: 601000,
|
||||
duration: 85801000, // <------------- value out of sync
|
||||
timeStrategy: TimeStrategy.LockEnd,
|
||||
linkStart: '1',
|
||||
}),
|
||||
'3': makeOntimeEvent({
|
||||
id: '3',
|
||||
timeStart: 100, // <------------- value out of sync
|
||||
timeEnd: 602000,
|
||||
duration: 0,
|
||||
timeStrategy: TimeStrategy.LockEnd,
|
||||
linkStart: '2',
|
||||
}),
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(testRundown);
|
||||
const initResult = generate(rundown);
|
||||
expect(initResult.rundown).toMatchObject({
|
||||
'97cc3e': {
|
||||
'1': {
|
||||
timeStart: 0,
|
||||
timeEnd: 600000,
|
||||
duration: 600000,
|
||||
timeStrategy: 'lock-duration',
|
||||
linkStart: null,
|
||||
},
|
||||
e01948: {
|
||||
'2': {
|
||||
timeStart: 600000,
|
||||
timeEnd: 601000,
|
||||
duration: 1000,
|
||||
timeStrategy: 'lock-end',
|
||||
linkStart: '97cc3e',
|
||||
linkStart: '1',
|
||||
},
|
||||
'25c1af': {
|
||||
'3': {
|
||||
timeStart: 601000,
|
||||
timeEnd: 602000,
|
||||
duration: 1000,
|
||||
timeStrategy: 'lock-end',
|
||||
linkStart: 'e01948',
|
||||
linkStart: '2',
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('deletes links if invalid', () => {
|
||||
const testRundown: OntimeRundown = [
|
||||
{ type: SupportedEvent.Event, id: '1', timeStart: 1, linkStart: '10' } as OntimeEvent,
|
||||
];
|
||||
const initResult = generate(testRundown);
|
||||
const rundown = makeRundown({
|
||||
order: ['1'],
|
||||
entries: {
|
||||
'1': makeOntimeEvent({ id: '1', timeStart: 1, linkStart: '10' }),
|
||||
},
|
||||
});
|
||||
|
||||
const initResult = generate(rundown);
|
||||
expect(initResult.order.length).toBe(1);
|
||||
expect((initResult.rundown['1'] as OntimeEvent).timeStart).toBe(1);
|
||||
expect(Object.keys(initResult.links).length).toBe(0);
|
||||
@@ -399,24 +408,26 @@ describe('generate()', () => {
|
||||
colour: 'red',
|
||||
},
|
||||
};
|
||||
const testRundown: OntimeRundown = [
|
||||
{
|
||||
type: SupportedEvent.Event,
|
||||
id: '1',
|
||||
custom: {
|
||||
lighting: 'event 1 lx',
|
||||
} as EventCustomFields,
|
||||
} as OntimeEvent,
|
||||
{
|
||||
type: SupportedEvent.Event,
|
||||
id: '2',
|
||||
custom: {
|
||||
lighting: 'event 2 lx',
|
||||
sound: 'event 2 sound',
|
||||
} as EventCustomFields,
|
||||
} as OntimeEvent,
|
||||
];
|
||||
const initResult = generate(testRundown, customProperties);
|
||||
|
||||
const rundown = makeRundown({
|
||||
order: ['1', '2'],
|
||||
entries: {
|
||||
'1': makeOntimeEvent({
|
||||
id: '1',
|
||||
custom: {
|
||||
lighting: 'event 1 lx',
|
||||
},
|
||||
}),
|
||||
'2': makeOntimeEvent({
|
||||
id: '2',
|
||||
custom: {
|
||||
lighting: 'event 2 lx',
|
||||
sound: 'event 2 sound',
|
||||
},
|
||||
}),
|
||||
},
|
||||
});
|
||||
const initResult = generate(rundown, customProperties);
|
||||
expect(initResult.order.length).toBe(2);
|
||||
expect(initResult.assignedCustomFields).toMatchObject({
|
||||
lighting: ['1', '2'],
|
||||
@@ -433,47 +444,64 @@ describe('generate()', () => {
|
||||
|
||||
describe('add() mutation', () => {
|
||||
test('adds an event to the rundown', () => {
|
||||
const mockEvent = { id: 'mock', cue: 'mock', type: SupportedEvent.Event } as OntimeEvent;
|
||||
const testRundown: OntimeRundown = [];
|
||||
const { newRundown } = add({ atIndex: 0, event: mockEvent, rundown: testRundown });
|
||||
expect(newRundown.length).toBe(1);
|
||||
expect(newRundown[0]).toMatchObject(mockEvent);
|
||||
const mockEvent = makeOntimeEvent({ id: 'mock', cue: 'mock' });
|
||||
const rundown = makeRundown({});
|
||||
const { newRundown } = add({ atIndex: 0, event: mockEvent, rundown });
|
||||
expect(newRundown.order.length).toBe(1);
|
||||
expect(newRundown.entries['mock']).toMatchObject(mockEvent);
|
||||
});
|
||||
});
|
||||
|
||||
describe('remove() mutation', () => {
|
||||
test('deletes an event from the rundown', () => {
|
||||
const mockEvent = { id: 'mock', cue: 'mock', type: SupportedEvent.Event } as OntimeEvent;
|
||||
const testRundown: OntimeRundown = [mockEvent];
|
||||
const { newRundown } = remove({ eventIds: [mockEvent.id], rundown: testRundown });
|
||||
expect(newRundown.length).toBe(0);
|
||||
const mockEvent = makeOntimeEvent({ id: 'mock', cue: 'mock' });
|
||||
const rundown = makeRundown({
|
||||
order: ['mock'],
|
||||
entries: {
|
||||
mock: mockEvent,
|
||||
},
|
||||
});
|
||||
|
||||
const { newRundown } = remove({ eventIds: [mockEvent.id], rundown });
|
||||
expect(newRundown.order.length).toBe(0);
|
||||
});
|
||||
|
||||
test('deletes multiple events from the rundown', () => {
|
||||
const testRundown: OntimeRundown = [
|
||||
{ type: SupportedEvent.Event, id: '1' } as OntimeEvent,
|
||||
{ type: SupportedEvent.Block, id: '2' } as OntimeBlock,
|
||||
{ type: SupportedEvent.Delay, id: '3' } as OntimeDelay,
|
||||
{ type: SupportedEvent.Event, id: '4' } as OntimeEvent,
|
||||
{ type: SupportedEvent.Event, id: '5' } as OntimeEvent,
|
||||
{ type: SupportedEvent.Event, id: '6' } as OntimeEvent,
|
||||
];
|
||||
const { newRundown } = remove({ eventIds: ['1', '2', '3'], rundown: testRundown });
|
||||
expect(newRundown.length).toBe(3);
|
||||
expect(newRundown.at(0)?.id).toBe('4');
|
||||
const rundown = makeRundown({
|
||||
order: ['1', '2', '3', '4', '5', '6'],
|
||||
entries: {
|
||||
'1': makeOntimeEvent({ id: '1' }),
|
||||
'2': makeOntimeBlock({ id: '2' }),
|
||||
'3': makeOntimeDelay({ id: '3' }),
|
||||
'4': makeOntimeEvent({ id: '4' }),
|
||||
'5': makeOntimeEvent({ id: '5' }),
|
||||
'6': makeOntimeEvent({ id: '6' }),
|
||||
},
|
||||
});
|
||||
|
||||
const { newRundown } = remove({ eventIds: ['1', '2', '3'], rundown });
|
||||
expect(newRundown.order.length).toBe(3);
|
||||
expect(newRundown.entries[newRundown.order[0]].id).toBe('4');
|
||||
});
|
||||
});
|
||||
|
||||
describe('edit() mutation', () => {
|
||||
test('edits an event in the rundown', () => {
|
||||
const mockEvent = { id: 'mock', cue: 'mock', type: SupportedEvent.Event } as OntimeEvent;
|
||||
const mockEventPatch = { cue: 'patched' } as OntimeEvent;
|
||||
const testRundown: OntimeRundown = [mockEvent];
|
||||
const mockEvent = makeOntimeEvent({ id: 'mock', cue: 'mock' });
|
||||
const mockEventPatch = makeOntimeEvent({ cue: 'patched' });
|
||||
const rundown = makeRundown({
|
||||
order: ['mock'],
|
||||
entries: {
|
||||
mock: mockEvent,
|
||||
},
|
||||
});
|
||||
|
||||
const { newRundown, newEvent } = edit({
|
||||
eventId: mockEvent.id,
|
||||
patch: mockEventPatch,
|
||||
rundown: testRundown,
|
||||
rundown,
|
||||
});
|
||||
expect(newRundown.length).toBe(1);
|
||||
expect(newRundown.order.length).toBe(1);
|
||||
expect(newEvent).toMatchObject({
|
||||
id: 'mock',
|
||||
cue: 'patched',
|
||||
@@ -484,73 +512,96 @@ describe('edit() mutation', () => {
|
||||
|
||||
describe('batchEdit() mutation', () => {
|
||||
it('should correctly apply the patch to the events with the given IDs', () => {
|
||||
const testRundown: OntimeRundown = [
|
||||
{ id: '1', type: SupportedEvent.Event, cue: 'data1' } as OntimeEvent,
|
||||
{ id: '2', type: SupportedEvent.Event, cue: 'data2' } as OntimeEvent,
|
||||
{ id: '3', type: SupportedEvent.Event, cue: 'data3' } as OntimeEvent,
|
||||
];
|
||||
const rundown = makeRundown({
|
||||
order: ['1', '2', '3'],
|
||||
entries: {
|
||||
'1': makeOntimeEvent({ id: '1', cue: 'data1' }),
|
||||
'2': makeOntimeEvent({ id: '2', cue: 'data2' }),
|
||||
'3': makeOntimeEvent({ id: '3', cue: 'data3' }),
|
||||
},
|
||||
});
|
||||
|
||||
const eventIds = ['1', '3'];
|
||||
const patch = { cue: 'newData' };
|
||||
|
||||
const { newRundown } = batchEdit({ rundown: testRundown, eventIds, patch });
|
||||
const { newRundown } = batchEdit({ rundown, eventIds, patch });
|
||||
|
||||
expect(newRundown).toMatchObject([
|
||||
{ id: '1', type: SupportedEvent.Event, cue: 'newData' },
|
||||
{ id: '2', type: SupportedEvent.Event, cue: 'data2' },
|
||||
{ id: '3', type: SupportedEvent.Event, cue: 'newData' },
|
||||
]);
|
||||
expect(newRundown.entries).toMatchObject({
|
||||
'1': { id: '1', type: SupportedEvent.Event, cue: 'newData' },
|
||||
'2': { id: '2', type: SupportedEvent.Event, cue: 'data2' },
|
||||
'3': { id: '3', type: SupportedEvent.Event, cue: 'newData' },
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('reorder() mutation', () => {
|
||||
it('should correctly reorder two events', () => {
|
||||
const testRundown: OntimeRundown = [
|
||||
{ id: '1', type: SupportedEvent.Event, cue: 'data1', revision: 0 } as OntimeEvent,
|
||||
{ id: '2', type: SupportedEvent.Event, cue: 'data2', revision: 0 } as OntimeEvent,
|
||||
{ id: '3', type: SupportedEvent.Event, cue: 'data3', revision: 0 } as OntimeEvent,
|
||||
];
|
||||
const { newRundown } = reorder({
|
||||
rundown: testRundown,
|
||||
eventId: testRundown[0].id,
|
||||
from: 0,
|
||||
to: testRundown.length - 1,
|
||||
const rundown = makeRundown({
|
||||
order: ['1', '2', '3'],
|
||||
entries: {
|
||||
'1': makeOntimeEvent({ id: '1', cue: 'data1', revision: 0 }),
|
||||
'2': makeOntimeEvent({ id: '2', cue: 'data2', revision: 0 }),
|
||||
'3': makeOntimeEvent({ id: '3', cue: 'data3', revision: 0 }),
|
||||
},
|
||||
});
|
||||
|
||||
expect(newRundown).toMatchObject([
|
||||
{ id: '2', type: SupportedEvent.Event, cue: 'data2', revision: 1 },
|
||||
{ id: '3', type: SupportedEvent.Event, cue: 'data3', revision: 1 },
|
||||
{ id: '1', type: SupportedEvent.Event, cue: 'data1', revision: 1 },
|
||||
]);
|
||||
// move first event to the end
|
||||
const { newRundown } = reorder({
|
||||
rundown: rundown,
|
||||
eventId: rundown.order[0],
|
||||
from: 0,
|
||||
to: rundown.order.length - 1,
|
||||
});
|
||||
|
||||
expect(newRundown.order).toStrictEqual(['2', '3', '1']);
|
||||
expect(newRundown.entries).toMatchObject({
|
||||
'2': { id: '2', cue: 'data2', revision: 1 },
|
||||
'3': { id: '3', cue: 'data3', revision: 1 },
|
||||
'1': { id: '1', cue: 'data1', revision: 1 },
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('swap() mutation', () => {
|
||||
it('should correctly swap data between events', () => {
|
||||
const testRundown: OntimeRundown = [
|
||||
{ id: '1', type: SupportedEvent.Event, cue: 'data1', timeStart: 1, revision: 0 } as OntimeEvent,
|
||||
{ id: '2', type: SupportedEvent.Event, cue: 'data2', timeStart: 2, revision: 0 } as OntimeEvent,
|
||||
{ id: '3', type: SupportedEvent.Event, cue: 'data3', timeStart: 3, revision: 0 } as OntimeEvent,
|
||||
];
|
||||
const { newRundown } = swap({
|
||||
rundown: testRundown,
|
||||
fromId: testRundown[0].id,
|
||||
toId: testRundown[1].id,
|
||||
const rundown = makeRundown({
|
||||
order: ['1', '2', '3'],
|
||||
entries: {
|
||||
'1': makeOntimeEvent({ id: '1', cue: 'data1', timeStart: 1, revision: 4 }),
|
||||
'2': makeOntimeEvent({ id: '2', cue: 'data2', timeStart: 2, revision: 8 }),
|
||||
'3': makeOntimeEvent({ id: '3', cue: 'data3', timeStart: 3, revision: 12 }),
|
||||
},
|
||||
});
|
||||
|
||||
expect((newRundown[0] as OntimeEvent).id).toBe('1');
|
||||
expect((newRundown[0] as OntimeEvent).cue).toBe('data2');
|
||||
expect((newRundown[0] as OntimeEvent).timeStart).toBe(1);
|
||||
expect((newRundown[0] as OntimeEvent).revision).toBe(1);
|
||||
// swap first and second event
|
||||
const { newRundown } = swap({
|
||||
rundown: rundown,
|
||||
fromId: rundown.order[0],
|
||||
toId: rundown.order[1],
|
||||
});
|
||||
|
||||
expect((newRundown[1] as OntimeEvent).id).toBe('2');
|
||||
expect((newRundown[1] as OntimeEvent).cue).toBe('data1');
|
||||
expect((newRundown[1] as OntimeEvent).timeStart).toBe(2);
|
||||
expect((newRundown[1] as OntimeEvent).revision).toBe(1);
|
||||
expect(newRundown.order).toStrictEqual(['1', '2', '3']);
|
||||
|
||||
expect((newRundown[2] as OntimeEvent).id).toBe('3');
|
||||
expect((newRundown[2] as OntimeEvent).cue).toBe('data3');
|
||||
expect((newRundown[2] as OntimeEvent).timeStart).toBe(3);
|
||||
expect((newRundown[2] as OntimeEvent).revision).toBe(0);
|
||||
expect(newRundown.entries['1']).toMatchObject({
|
||||
id: '1',
|
||||
cue: 'data2',
|
||||
timeStart: 1,
|
||||
revision: 5,
|
||||
});
|
||||
|
||||
expect(newRundown.entries['2']).toMatchObject({
|
||||
id: '2',
|
||||
cue: 'data1',
|
||||
timeStart: 2,
|
||||
revision: 9,
|
||||
});
|
||||
|
||||
expect(newRundown.entries['3']).toMatchObject({
|
||||
id: '3',
|
||||
cue: 'data3',
|
||||
timeStart: 3,
|
||||
revision: 12,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import {
|
||||
CustomFields,
|
||||
EndAction,
|
||||
OntimeEvent,
|
||||
OntimeRundown,
|
||||
RundownEntries,
|
||||
SupportedEvent,
|
||||
TimeStrategy,
|
||||
TimerType,
|
||||
@@ -10,46 +10,25 @@ import {
|
||||
import {
|
||||
addToCustomAssignment,
|
||||
calculateDayOffset,
|
||||
getLink,
|
||||
handleCustomField,
|
||||
handleLink,
|
||||
hasChanges,
|
||||
isDataStale,
|
||||
} from '../rundownCacheUtils.js';
|
||||
import { MILLIS_PER_HOUR } from 'ontime-utils';
|
||||
|
||||
describe('getLink()', () => {
|
||||
it('should return null if there is no link', () => {
|
||||
const rundown = [
|
||||
{ type: SupportedEvent.Block, id: 'block' },
|
||||
{ type: SupportedEvent.Event, id: '1' },
|
||||
] as OntimeRundown;
|
||||
|
||||
const result = getLink(1, rundown);
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it('returns previous event', () => {
|
||||
const rundown = [
|
||||
{ type: SupportedEvent.Event, id: '1', timeEnd: 100 },
|
||||
{ type: SupportedEvent.Event, id: '2', timeStart: 0, linkStart: '1' },
|
||||
] as OntimeRundown;
|
||||
|
||||
const result = getLink(1, rundown);
|
||||
expect(result.id).toBe('1');
|
||||
});
|
||||
});
|
||||
import { makeOntimeBlock, makeOntimeEvent } from '../__mocks__/rundown.mocks.js';
|
||||
|
||||
describe('handleLink()', () => {
|
||||
it('populates data in object and updates link map', () => {
|
||||
const rundown = [
|
||||
{ type: SupportedEvent.Event, id: '1', timeEnd: 100 },
|
||||
{ type: SupportedEvent.Event, id: '2', timeStart: 0, linkStart: '1' },
|
||||
] as OntimeRundown;
|
||||
const mutableEvent = { ...rundown[1] } as OntimeEvent;
|
||||
const entries: RundownEntries = {
|
||||
'1': makeOntimeEvent({ id: '1', timeEnd: 100 }),
|
||||
'2': makeOntimeEvent({ id: '2', timeStart: 0, linkStart: '1' }),
|
||||
};
|
||||
|
||||
const mutableEvent = { ...entries[2] } as OntimeEvent;
|
||||
const links = {};
|
||||
|
||||
const result = handleLink(1, rundown, mutableEvent, links);
|
||||
const result = handleLink(mutableEvent, entries[1] as OntimeEvent, links);
|
||||
expect(result).toBeUndefined();
|
||||
expect(mutableEvent.timeStart).toBe(100);
|
||||
expect(mutableEvent.linkStart).toBe('1');
|
||||
@@ -57,17 +36,17 @@ describe('handleLink()', () => {
|
||||
});
|
||||
|
||||
it('removes link if linked event is not found', () => {
|
||||
const rundown = [
|
||||
{ type: SupportedEvent.Block, id: '1' },
|
||||
{ type: SupportedEvent.Event, id: '2', timeStart: 0, linkStart: '1' },
|
||||
] as OntimeRundown;
|
||||
const mutableEvent = { ...rundown[1] } as OntimeEvent;
|
||||
const entries: RundownEntries = {
|
||||
'1': makeOntimeBlock({ id: '1' }),
|
||||
'2': makeOntimeEvent({ id: '2', timeStart: 0, linkStart: '1' }),
|
||||
};
|
||||
const mutableEvent = { ...entries[2] } as OntimeEvent;
|
||||
const links = {};
|
||||
|
||||
const result = handleLink(1, rundown, mutableEvent, links);
|
||||
const result = handleLink(mutableEvent, null, links);
|
||||
expect(result).toBeUndefined();
|
||||
expect(mutableEvent.timeStart).toBe(0);
|
||||
expect(mutableEvent.linkStart).toBe(null);
|
||||
expect(mutableEvent.linkStart).toBe('true');
|
||||
expect(links).toStrictEqual({});
|
||||
});
|
||||
});
|
||||
@@ -252,7 +231,7 @@ describe('hasChanges()', () => {
|
||||
|
||||
describe('calculateDayOffset', () => {
|
||||
it('returns 0 if there is no previous event', () => {
|
||||
expect(calculateDayOffset({ timeStart: 0 })).toBe(0);
|
||||
expect(calculateDayOffset({ timeStart: 0 }, null)).toBe(0);
|
||||
});
|
||||
|
||||
it('returns 0 if the previous event duration is 0', () => {
|
||||
|
||||
Reference in New Issue
Block a user