refactor: migrate custom fields to transactions

refactor: extract functions to api domain

refactor: strict custom field parsing

refactor: remove rundown cache utilities

refactor: directory restructure
This commit is contained in:
Carlos Valente
2025-06-06 21:08:30 +02:00
committed by arc-alex
parent f3b4ea0155
commit 2498e59156
75 changed files with 2060 additions and 2480 deletions
@@ -1,18 +1,35 @@
import { CustomFields, OntimeBlock, OntimeDelay, OntimeEvent, SupportedEntry, TimeStrategy } from 'ontime-types';
import { dayInMs, MILLIS_PER_HOUR, MILLIS_PER_MINUTE } from 'ontime-utils';
import { makeOntimeEvent, makeRundown, makeOntimeBlock, makeOntimeDelay } from '../__mocks__/rundown.mocks.js';
import {
makeOntimeEvent,
makeRundown,
makeOntimeBlock,
makeOntimeDelay,
makeCustomField,
} from '../__mocks__/rundown.mocks.js';
import { createTransaction, processRundown, rundownCache, rundownMutation } from '../rundown.dao.js';
import {
createTransaction,
customFieldMutation,
processRundown,
rundownCache,
rundownMutation,
} from '../rundown.dao.js';
import { demoDb } from '../../../models/demoProject.js';
import { ProcessedRundownMetadata } from '../../../services/rundown-service/rundownCache.utils.js';
import type { AssignedMap } from '../rundown.types.js';
import { type ProcessedRundownMetadata } from '../rundown.parser.js';
const setRundownMock = vi.fn();
const setCustomFieldsMock = vi.fn();
beforeAll(() => {
vi.mock('../../../classes/data-provider/DataProvider.js', () => {
return {
getDataProvider: vi.fn().mockImplementation(() => {
return {
setRundown: vi.fn().mockImplementation(() => undefined),
setRundown: setRundownMock,
setCustomFields: setCustomFieldsMock,
};
}),
};
@@ -24,17 +41,39 @@ afterAll(() => {
});
describe('createTransaction', () => {
it('should return a snapshot of the cached rundown and an commit function', () => {
const { rundown, commit } = createTransaction();
beforeEach(() => {
vi.useFakeTimers({ shouldAdvanceTime: true });
});
afterEach(() => {
vi.runOnlyPendingTimers();
vi.useRealTimers();
});
it('should return a snapshot of the cached data and an commit function', () => {
const { rundown, customFields, commit } = createTransaction({ mutableRundown: true, mutableCustomFields: true });
expect(rundown).toBeDefined();
expect(customFields).toBeDefined();
expect(typeof commit).toBe('function');
});
it('should return the updated rundown after commit is called and update the db', () => {
const { rundown, commit } = createTransaction();
it('should return the updated data after commit is called and writes are scheduled', () => {
const { rundown, customFields, commit } = createTransaction({ mutableRundown: true, mutableCustomFields: true });
rundown.title = 'Another Title';
customFields['newField'] = {
label: 'New Field',
type: 'string',
colour: 'blue',
};
const updated = commit();
vi.runAllTimers();
expect(updated.rundown.title).toBe('Another Title');
expect(updated.customFields).toHaveProperty('newField');
expect(setRundownMock).toHaveBeenCalledOnce();
expect(setCustomFieldsMock).toHaveBeenCalledOnce();
});
});
@@ -1568,3 +1607,119 @@ describe('rundownMutation.ungroup()', () => {
});
});
});
describe('customFieldMutation.add()', () => {
it('adds a custom field given object', () => {
const customFields = {
one: makeCustomField({ label: 'one' }),
};
customFieldMutation.add(customFields, 'two', makeCustomField({ label: 'two' }));
expect(customFields).toMatchObject({
one: { label: 'one' },
two: { label: 'two' },
});
});
});
describe('customFieldMutation.edit()', () => {
it('changes properties of an existing custom field', () => {
const customFields = {
one: makeCustomField({ label: 'one', colour: 'blue' }),
};
customFieldMutation.edit(customFields, 'one', customFields.one, { colour: 'red' });
expect(customFields).toMatchObject({
one: { label: 'one', colour: 'red' },
});
});
it('changing the label makes a new key', () => {
const customFields = {
one: makeCustomField({ label: 'one', colour: 'blue' }),
};
const { oldKey, newKey } = customFieldMutation.edit(customFields, 'one', customFields.one, {
label: 'two',
colour: 'red',
});
expect(oldKey).toBe('one');
expect(newKey).not.toEqual(oldKey);
expect(customFields).toMatchObject({
[oldKey]: { label: 'one', colour: 'blue' },
[newKey]: { label: 'two', colour: 'red' },
});
});
});
describe('customFieldMutation.remove()', () => {
it('deletes a custom field from the object', () => {
const customFields = {
one: makeCustomField({ label: 'one', colour: 'blue' }),
};
customFieldMutation.remove(customFields, 'one');
expect(customFields).not.toHaveProperty('one');
});
});
describe('customFieldMutation.renameUsages()', () => {
it('renames all custom field entries in a given rundown', () => {
const rundown = makeRundown({
order: ['1', '2', '3'],
entries: {
'1': makeOntimeEvent({ id: '1', custom: { one: 'value1' } }),
'2': makeOntimeEvent({ id: '2', custom: { one: 'value2' } }),
'3': makeOntimeEvent({ id: '3', custom: { two: 'value3' } }),
},
});
const assigned: AssignedMap = {
one: ['1', '2'],
two: ['3'],
};
customFieldMutation.renameUsages(rundown, assigned, 'one', 'new-one');
expect(rundown.entries).toMatchObject({
'1': { id: '1', custom: { 'new-one': 'value1' } },
'2': { id: '2', custom: { 'new-one': 'value2' } },
'3': { id: '3', custom: { two: 'value3' } },
});
expect(assigned).toStrictEqual({
'new-one': ['1', '2'],
two: ['3'],
});
});
});
describe('customFieldMutation.removeUsages()', () => {
it('deletes all custom field entries in a given rundown', () => {
const rundown = makeRundown({
order: ['1', '2', '3'],
entries: {
'1': makeOntimeEvent({ id: '1', custom: { one: 'value1' } }),
'2': makeOntimeEvent({ id: '2', custom: { one: 'value2' } }),
'3': makeOntimeEvent({ id: '3', custom: { two: 'value3' } }),
},
});
const assigned: AssignedMap = {
one: ['1', '2'],
two: ['3'],
};
customFieldMutation.removeUsages(rundown, assigned, 'one');
expect((rundown.entries['1'] as OntimeEvent).custom).not.toHaveProperty('one');
expect((rundown.entries['2'] as OntimeEvent).custom).not.toHaveProperty('one');
expect(assigned).toStrictEqual({
two: ['3'],
});
});
});