mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-13 03:13:47 +00:00
fix: midnight roll (#484)
* refactor: extract utilities and types * refactor: extract and simplify progress bar logic * refactor: duration validation handles midnight * fix: prevent stale event loader * refactor: consider next event in timer invalidation * refactor: reload changes on changed roll target * refactor: timer load accounts for midnight * fix: issues with midnight on roll * refactor: prevent stale secondary event
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
import { vi } from 'vitest';
|
||||
import { dbModel } from '../../models/dataModel.ts';
|
||||
import { parseExcel, parseJson, validateEvent } from '../parser.ts';
|
||||
import { makeString, validateDuration } from '../parserUtils.js';
|
||||
import { makeString } from '../parserUtils.ts';
|
||||
import { parseAliases, parseUserFields, parseViewSettings } from '../parserFunctions.ts';
|
||||
import { EndAction, TimerType } from 'ontime-types';
|
||||
import { dayInMs } from 'ontime-utils';
|
||||
|
||||
describe('test json parser with valid def', () => {
|
||||
const testData = {
|
||||
@@ -898,34 +899,3 @@ describe('test views import', () => {
|
||||
expect(parsed).toStrictEqual(expectedParsedViewSettings);
|
||||
});
|
||||
});
|
||||
|
||||
describe('test validateDuration()', () => {
|
||||
describe('handles valid inputs', () => {
|
||||
const valid = [
|
||||
{ test: 'zero values', timeStart: 0, timeEnd: 0 },
|
||||
{ test: 'end after start', timeStart: 0, timeEnd: 1 },
|
||||
];
|
||||
|
||||
valid.forEach((t) => {
|
||||
it(t.test, () => {
|
||||
const d = validateDuration(t.timeStart, t.timeEnd);
|
||||
expect(d).toBe(t.timeEnd - t.timeStart);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('handles edge cases', () => {
|
||||
// edge cases
|
||||
const testData = [
|
||||
{ test: 'negative 0', timeStart: -0, timeEnd: -0, expected: 0 },
|
||||
{ test: 'end before start', timeStart: 2, timeEnd: 1, expected: 0 },
|
||||
];
|
||||
|
||||
testData.forEach((t) => {
|
||||
it(t.test, () => {
|
||||
const d = validateDuration(t.timeStart, t.timeEnd);
|
||||
expect(d).toBe(t.expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
-3
@@ -5,9 +5,6 @@ describe('isEmptyObject()', () => {
|
||||
const isEmpty = isEmptyObject({});
|
||||
expect(isEmpty).toBe(true);
|
||||
});
|
||||
test('throws on other types', () => {
|
||||
expect(() => isEmptyObject(12)).toThrow();
|
||||
});
|
||||
test('resolves an object with methods', () => {
|
||||
const isEmpty = isEmptyObject({ test: 'yes' });
|
||||
expect(isEmpty).toBe(false);
|
||||
@@ -3,11 +3,11 @@
|
||||
|
||||
import fs from 'fs';
|
||||
import xlsx from 'node-xlsx';
|
||||
import { generateId } from 'ontime-utils';
|
||||
import { generateId, calculateDuration } from 'ontime-utils';
|
||||
import { DatabaseModel, EventData, OntimeEvent, OntimeRundown, UserFields } from 'ontime-types';
|
||||
import { event as eventDef } from '../models/eventsDefinition.js';
|
||||
import { dbModel } from '../models/dataModel.js';
|
||||
import { deleteFile, makeString, validateDuration } from './parserUtils.js';
|
||||
import { deleteFile, makeString } from './parserUtils.js';
|
||||
import {
|
||||
parseAliases,
|
||||
parseEventData,
|
||||
@@ -322,7 +322,7 @@ export const validateEvent = (eventArgs) => {
|
||||
timeEnd: end,
|
||||
endAction: makeString(e.endAction, d.endAction),
|
||||
timerType: makeString(e.timerType, d.timerType),
|
||||
duration: validateDuration(start, end),
|
||||
duration: calculateDuration(start, end),
|
||||
isPublic: typeof e.isPublic === 'boolean' ? e.isPublic : d.isPublic,
|
||||
skip: typeof e.skip === 'boolean' ? e.skip : d.skip,
|
||||
note: makeString(e.note, d.note),
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import fs from 'fs';
|
||||
import { dayInMs } from 'ontime-utils';
|
||||
|
||||
/**
|
||||
* @description Ensures variable is string, it skips object types
|
||||
@@ -6,23 +7,12 @@ import fs from 'fs';
|
||||
* @param {string} [fallback=''] - fallback value
|
||||
* @returns {string} - value as string or fallback if not possible
|
||||
*/
|
||||
export const makeString = (val, fallback = '') => {
|
||||
export const makeString = (val: any, fallback = ''): string => {
|
||||
if (typeof val === 'string') return val;
|
||||
else if (val == null || val.constructor === Object) return fallback;
|
||||
return val.toString();
|
||||
};
|
||||
|
||||
/**
|
||||
* @description validates a duration value against options
|
||||
* @param {number} timeStart
|
||||
* @param {number} timeEnd
|
||||
* @returns {number}
|
||||
*/
|
||||
export const validateDuration = (timeStart, timeEnd) => {
|
||||
// Durations must be positive
|
||||
return Math.max(timeEnd - timeStart, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* @description Delete file from system
|
||||
* @param {string} file - reference to file
|
||||
@@ -54,7 +44,7 @@ export const validateFile = (file) => {
|
||||
* @description Verifies if object is empty
|
||||
* @param {object} obj
|
||||
*/
|
||||
export const isEmptyObject = (obj) => {
|
||||
export const isEmptyObject = (obj: object) => {
|
||||
if (typeof obj === 'object' && obj !== null && !Array.isArray(obj)) {
|
||||
return Object.keys(obj).length === 0;
|
||||
}
|
||||
@@ -78,7 +68,7 @@ export const mergeObject = (a, b) => {
|
||||
* @description Removes undefined
|
||||
* @param {object} obj
|
||||
*/
|
||||
export const removeUndefined = (obj) => {
|
||||
export const removeUndefined = (obj: object) => {
|
||||
const patched = {};
|
||||
Object.keys({ ...obj })
|
||||
.filter((key) => typeof obj[key] !== 'undefined')
|
||||
@@ -6,7 +6,6 @@ const mth = 1000 * 60 * 60; // millis to hours
|
||||
|
||||
export const timeFormat = 'HH:mm';
|
||||
export const timeFormatSeconds = 'HH:mm:ss';
|
||||
export const DAY_TO_MS = 86400000;
|
||||
|
||||
/**
|
||||
* @description Converts an excel date to milliseconds
|
||||
|
||||
Reference in New Issue
Block a user