mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-09 01:13:55 +00:00
dce87c3a81
* inti relative mode * send imediat update on mode change * add relative to test * don't persist offset mode * add test relative and update calc function * pass data from ssocket * add dev guard * spelling and comments * show relative in offset overview * remove comments * refactor: move totalDelay to _rundown * update clear naming and comments * remove old testing values
298 lines
9.1 KiB
TypeScript
298 lines
9.1 KiB
TypeScript
import { OffsetMode } from 'ontime-types';
|
|
import { dayInMs } from 'ontime-utils';
|
|
|
|
import { calculateTimeUntilStart, formatTime, nowInMillis } from '../time';
|
|
|
|
describe('nowInMillis()', () => {
|
|
it('should return the current time in milliseconds', () => {
|
|
const mockDate = new Date(2022, 1, 1, 13, 0, 0); // This date corresponds to 13:00:00
|
|
const expectedMillis = 13 * 60 * 60 * 1000;
|
|
const dateSpy = vi.spyOn(global, 'Date').mockImplementation(() => mockDate as any);
|
|
|
|
const result = nowInMillis();
|
|
|
|
expect(result).toBe(expectedMillis);
|
|
dateSpy.mockRestore();
|
|
});
|
|
});
|
|
|
|
describe('formatTime()', () => {
|
|
it('parses 24h strings', () => {
|
|
const ms = 13 * 60 * 60 * 1000;
|
|
const time = formatTime(ms, { format12: 'hh:mm:ss', format24: 'HH:mm:ss' }, (_format12, format24) => format24);
|
|
expect(time).toStrictEqual('13:00:00');
|
|
});
|
|
|
|
it('parses same string in 12h strings', () => {
|
|
const ms = 13 * 60 * 60 * 1000;
|
|
const time = formatTime(ms, { format12: 'hh:mm:ss a', format24: 'HH:mm:ss' }, (format12, _format24) => format12);
|
|
expect(time).toStrictEqual('01:00:00 PM');
|
|
});
|
|
|
|
it('handles null times', () => {
|
|
const ms = null;
|
|
const time = formatTime(ms);
|
|
expect(time).toStrictEqual('...');
|
|
});
|
|
|
|
it('handles negative times', () => {
|
|
const ms = 1 * 60 * 60 * 1000;
|
|
const time = formatTime(-ms, { format12: 'hh:mm a', format24: 'HH:mm' }, (_format12, format24) => format24);
|
|
expect(time).toStrictEqual('-01:00');
|
|
});
|
|
});
|
|
|
|
describe('calculateTimeUntilStart()', () => {
|
|
describe('Absolute offset mode', () => {
|
|
test('ontime', () => {
|
|
const test = {
|
|
timeStart: 100,
|
|
dayOffset: 0,
|
|
delay: 0,
|
|
currentDay: 0,
|
|
totalGap: 0,
|
|
clock: 90,
|
|
offset: 0,
|
|
offsetMode: OffsetMode.Absolute,
|
|
actualStart: null,
|
|
plannedStart: null,
|
|
};
|
|
|
|
expect(calculateTimeUntilStart({ ...test, isLinkedToLoaded: false })).toBe(10);
|
|
expect(calculateTimeUntilStart({ ...test, isLinkedToLoaded: true })).toBe(10);
|
|
});
|
|
|
|
test('running behind', () => {
|
|
const test = {
|
|
timeStart: 100,
|
|
dayOffset: 0,
|
|
delay: 0,
|
|
currentDay: 0,
|
|
totalGap: 0,
|
|
clock: 90,
|
|
offset: -20,
|
|
offsetMode: OffsetMode.Absolute,
|
|
actualStart: null,
|
|
plannedStart: null,
|
|
};
|
|
|
|
expect(calculateTimeUntilStart({ ...test, isLinkedToLoaded: false })).toBe(30);
|
|
expect(calculateTimeUntilStart({ ...test, isLinkedToLoaded: true })).toBe(30);
|
|
});
|
|
|
|
test('running ahead', () => {
|
|
const test = {
|
|
timeStart: 100,
|
|
dayOffset: 0,
|
|
delay: 0,
|
|
currentDay: 0,
|
|
totalGap: 0,
|
|
clock: 80,
|
|
offset: 10,
|
|
offsetMode: OffsetMode.Absolute,
|
|
actualStart: null,
|
|
plannedStart: null,
|
|
};
|
|
|
|
expect(calculateTimeUntilStart({ ...test, isLinkedToLoaded: false })).toBe(20); // <-- when running ahead the unlinked timer stays put
|
|
expect(calculateTimeUntilStart({ ...test, isLinkedToLoaded: true })).toBe(10);
|
|
});
|
|
|
|
test('running behind with enough gaps', () => {
|
|
const test = {
|
|
timeStart: 100,
|
|
dayOffset: 0,
|
|
delay: 0,
|
|
currentDay: 0,
|
|
totalGap: 20,
|
|
clock: 50,
|
|
offset: -20,
|
|
offsetMode: OffsetMode.Absolute,
|
|
actualStart: null,
|
|
plannedStart: null,
|
|
};
|
|
|
|
expect(calculateTimeUntilStart({ ...test, isLinkedToLoaded: false })).toBe(50); // <-- when gap is enough to compensate for the running behind
|
|
expect(calculateTimeUntilStart({ ...test, isLinkedToLoaded: true })).toBe(70); // This should not be possible
|
|
});
|
|
|
|
test('running behind with too little gaps', () => {
|
|
const test = {
|
|
timeStart: 100,
|
|
dayOffset: 0,
|
|
delay: 0,
|
|
currentDay: 0,
|
|
totalGap: 10,
|
|
clock: 50,
|
|
offset: -20,
|
|
offsetMode: OffsetMode.Absolute,
|
|
actualStart: 0,
|
|
plannedStart: 0,
|
|
};
|
|
|
|
expect(calculateTimeUntilStart({ ...test, isLinkedToLoaded: false })).toBe(60); // <-- when gap is not enough to compensate for the running behind it absorbs at much as possible
|
|
expect(calculateTimeUntilStart({ ...test, isLinkedToLoaded: true })).toBe(70); // This should not be possible
|
|
});
|
|
});
|
|
|
|
describe('Relative offset mode', () => {
|
|
test('basic function', () => {
|
|
const test = {
|
|
timeStart: 0,
|
|
dayOffset: 0,
|
|
delay: 0,
|
|
currentDay: 0,
|
|
totalGap: 0,
|
|
clock: 100,
|
|
actualStart: 100,
|
|
plannedStart: 0,
|
|
offset: 0,
|
|
offsetMode: OffsetMode.Relative,
|
|
};
|
|
|
|
const timeStartEvent2 = 10;
|
|
const timeStartEvent3 = 20;
|
|
|
|
//event 1 is the currently running event
|
|
|
|
//event 2
|
|
expect(calculateTimeUntilStart({ ...test, timeStart: timeStartEvent2, isLinkedToLoaded: true })).toBe(10);
|
|
expect(calculateTimeUntilStart({ ...test, timeStart: timeStartEvent2, isLinkedToLoaded: false })).toBe(10);
|
|
|
|
//event 3
|
|
expect(calculateTimeUntilStart({ ...test, timeStart: timeStartEvent3, isLinkedToLoaded: true })).toBe(20);
|
|
expect(calculateTimeUntilStart({ ...test, timeStart: timeStartEvent3, isLinkedToLoaded: false })).toBe(20);
|
|
|
|
// When clock advances by 5ms, time until start should decrease by 5ms
|
|
test.clock = 105;
|
|
|
|
//event 2
|
|
expect(calculateTimeUntilStart({ ...test, timeStart: timeStartEvent2, isLinkedToLoaded: true })).toBe(5);
|
|
expect(calculateTimeUntilStart({ ...test, timeStart: timeStartEvent2, isLinkedToLoaded: false })).toBe(5);
|
|
|
|
//event 3
|
|
expect(calculateTimeUntilStart({ ...test, timeStart: timeStartEvent3, isLinkedToLoaded: true })).toBe(15);
|
|
expect(calculateTimeUntilStart({ ...test, timeStart: timeStartEvent3, isLinkedToLoaded: false })).toBe(15);
|
|
});
|
|
|
|
test('gaps', () => {
|
|
const test = {
|
|
timeStart: 20,
|
|
dayOffset: 0,
|
|
delay: 0,
|
|
currentDay: 0,
|
|
totalGap: 10,
|
|
clock: 100,
|
|
actualStart: 100,
|
|
plannedStart: 0,
|
|
offset: 0,
|
|
offsetMode: OffsetMode.Relative,
|
|
};
|
|
|
|
expect(calculateTimeUntilStart({ ...test, isLinkedToLoaded: true })).toBe(20);
|
|
expect(calculateTimeUntilStart({ ...test, isLinkedToLoaded: false })).toBe(20);
|
|
|
|
// When clock advances by 5ms, time until start should decrease by 5ms
|
|
test.clock = 105;
|
|
expect(calculateTimeUntilStart({ ...test, isLinkedToLoaded: true })).toBe(15);
|
|
expect(calculateTimeUntilStart({ ...test, isLinkedToLoaded: false })).toBe(15);
|
|
});
|
|
|
|
test('added/remove time', () => {
|
|
const test = {
|
|
timeStart: 20,
|
|
dayOffset: 0,
|
|
delay: 0,
|
|
currentDay: 0,
|
|
totalGap: 0,
|
|
clock: 100,
|
|
actualStart: 100,
|
|
plannedStart: 0,
|
|
offset: 0,
|
|
offsetMode: OffsetMode.Relative,
|
|
};
|
|
|
|
expect(calculateTimeUntilStart({ ...test, isLinkedToLoaded: true })).toBe(20);
|
|
expect(calculateTimeUntilStart({ ...test, isLinkedToLoaded: false })).toBe(20);
|
|
|
|
test.offset = 5; // remove 5 with addtime - we are ahead of time
|
|
|
|
expect(calculateTimeUntilStart({ ...test, isLinkedToLoaded: true })).toBe(15);
|
|
expect(calculateTimeUntilStart({ ...test, isLinkedToLoaded: false })).toBe(20); // unlocked evets will stay on schedule
|
|
|
|
test.offset = -5; // add 5 with addtime - we are behind
|
|
|
|
expect(calculateTimeUntilStart({ ...test, isLinkedToLoaded: true })).toBe(25);
|
|
expect(calculateTimeUntilStart({ ...test, isLinkedToLoaded: false })).toBe(25);
|
|
});
|
|
|
|
test('next day', () => {
|
|
const test = {
|
|
delay: 0,
|
|
currentDay: 0,
|
|
clock: 100,
|
|
actualStart: 100,
|
|
plannedStart: 0,
|
|
offset: 0,
|
|
offsetMode: OffsetMode.Relative,
|
|
};
|
|
|
|
// this event will start the current day
|
|
expect(
|
|
calculateTimeUntilStart({
|
|
...test,
|
|
timeStart: 10,
|
|
dayOffset: 0,
|
|
totalGap: 0,
|
|
isLinkedToLoaded: false,
|
|
}),
|
|
).toBe(10);
|
|
|
|
// this event will start the next day
|
|
// in absolute mode this would start in dayInMs - 100 since the gap would compensate
|
|
// but in relative mode with and actual start that is 100 offset it starts in dayInMs
|
|
expect(
|
|
calculateTimeUntilStart({
|
|
...test,
|
|
timeStart: 0,
|
|
dayOffset: 1,
|
|
totalGap: dayInMs - 20,
|
|
isLinkedToLoaded: false,
|
|
}),
|
|
).toBe(dayInMs);
|
|
|
|
// advancing 100ms
|
|
test.clock = 200;
|
|
|
|
expect(
|
|
calculateTimeUntilStart({
|
|
...test,
|
|
timeStart: 0,
|
|
dayOffset: 1,
|
|
totalGap: dayInMs - 20,
|
|
isLinkedToLoaded: false,
|
|
}),
|
|
).toBe(dayInMs - 100);
|
|
});
|
|
});
|
|
|
|
test('overlap with negative total gap', () => {
|
|
const test = {
|
|
dayOffset: 0,
|
|
delay: 0,
|
|
currentDay: 0,
|
|
clock: 100,
|
|
actualStart: 100,
|
|
plannedStart: 0,
|
|
offset: 0,
|
|
offsetMode: OffsetMode.Relative,
|
|
isLinkedToLoaded: false,
|
|
};
|
|
|
|
// the overlap will be pushed out to the expected available time
|
|
expect(calculateTimeUntilStart({ ...test, timeStart: 5, totalGap: -5 })).toBe(10);
|
|
|
|
test.clock = 105;
|
|
});
|
|
});
|