refactor: improve async handling

This commit is contained in:
Carlos Valente
2025-02-15 14:05:53 +01:00
committed by Carlos Valente
parent c65761448d
commit 891bda6661
8 changed files with 88 additions and 87 deletions
@@ -40,43 +40,43 @@ afterAll(() => {
});
describe('addTrigger()', () => {
beforeEach(() => {
deleteAllTriggers();
beforeEach(async () => {
await deleteAllTriggers();
});
it('should accept a valid automation', () => {
it('should accept a valid trigger', async () => {
const testData: TriggerDTO = {
title: 'test',
trigger: TimerLifeCycle.onLoad,
automationId: 'test-automation-id',
};
const trigger = addTrigger(testData);
const trigger = await addTrigger(testData);
expect(trigger).toMatchObject(testData);
});
});
describe('editTrigger()', () => {
beforeEach(() => {
deleteAllTriggers();
addTrigger({
beforeEach(async () => {
await deleteAllTriggers();
await addTrigger({
title: 'test-osc',
trigger: TimerLifeCycle.onLoad,
automationId: 'test-osc-automation',
});
addTrigger({
await addTrigger({
title: 'test-http',
trigger: TimerLifeCycle.onFinish,
automationId: 'test-http-automation',
});
});
it('should edit the contents of an automation', () => {
it('should edit the contents of a trigger', async () => {
const triggers = getAutomationTriggers();
const fistTrigger = triggers[0];
expect(fistTrigger).toMatchObject({ id: expect.any(String), title: 'test-osc' });
const editedOSC = editTrigger(fistTrigger.id, {
const editedOSC = await editTrigger(fistTrigger.id, {
title: 'edited-title',
trigger: TimerLifeCycle.onDanger,
automationId: 'test-osc-automation',
@@ -92,9 +92,9 @@ describe('editTrigger()', () => {
});
describe('deleteTrigger()', () => {
beforeEach(() => {
deleteAllTriggers();
addTrigger({
beforeEach(async () => {
await deleteAllTriggers();
await addTrigger({
title: 'test-osc',
trigger: TimerLifeCycle.onLoad,
automationId: 'test-osc-automation',
@@ -106,13 +106,13 @@ describe('deleteTrigger()', () => {
});
});
it('should remove an automation from the list', () => {
it('should remove an automation from the list', async () => {
const triggers = getAutomationTriggers();
expect(triggers.length).toEqual(2);
const fistTrigger = triggers[0];
expect(fistTrigger).toMatchObject({ id: expect.any(String), title: 'test-osc' });
deleteTrigger(fistTrigger.id);
await deleteTrigger(fistTrigger.id);
const removed = getAutomationTriggers();
expect(removed.length).toEqual(1);
expect(removed[0].title).not.toEqual('test-osc');
@@ -120,11 +120,11 @@ describe('deleteTrigger()', () => {
});
describe('addAutomation()', () => {
beforeEach(() => {
deleteAll();
beforeEach(async () => {
await deleteAll();
});
it('should accept a valid automation', () => {
it('should accept a valid automation', async () => {
const testData: AutomationDTO = {
title: 'test',
filterRule: 'all',
@@ -132,24 +132,24 @@ describe('addAutomation()', () => {
outputs: [makeOSCAction(), makeHTTPAction()],
};
const automation = addAutomation(testData);
const automation = await addAutomation(testData);
const automations = getAutomations();
expect(automations[automation.id]).toMatchObject(testData);
});
});
describe('editAutomation()', () => {
describe('editAutomation()', async () => {
// saving the ID of the added automation
let firstAutomation: Automation;
beforeEach(() => {
deleteAll();
firstAutomation = addAutomation({
beforeEach(async () => {
await deleteAll();
firstAutomation = await addAutomation({
title: 'test-osc',
filterRule: 'all',
filters: [],
outputs: [],
});
addAutomation({
await addAutomation({
title: 'test-http',
filterRule: 'all',
filters: [],
@@ -157,7 +157,7 @@ describe('editAutomation()', () => {
});
});
it('should edit the contents of an automation', () => {
it('should edit the contents of an automation', async () => {
const automations = getAutomations();
expect(Object.keys(automations).length).toEqual(2);
expect(automations[firstAutomation.id]).toMatchObject({
@@ -168,7 +168,7 @@ describe('editAutomation()', () => {
outputs: expect.any(Array),
});
const editedOSC = editAutomation(firstAutomation.id, {
const editedOSC = await editAutomation(firstAutomation.id, {
title: 'edited-title',
filterRule: 'any',
filters: [],
@@ -188,9 +188,9 @@ describe('editAutomation()', () => {
describe('deleteAutomation()', () => {
// saving the ID of the added automation
let firstAutomation: Automation;
beforeEach(() => {
deleteAll();
firstAutomation = addAutomation({
beforeEach(async () => {
await deleteAll();
firstAutomation = await addAutomation({
title: 'test-osc',
filterRule: 'all',
filters: [],
@@ -198,18 +198,18 @@ describe('deleteAutomation()', () => {
});
});
it('should remove m automation from the list', () => {
it('should remove m automation from the list', async () => {
const automations = getAutomations();
expect(Object.keys(automations).length).toEqual(1);
deleteAutomation(Object.keys(automations)[0]);
await deleteAutomation(Object.keys(automations)[0]);
const removed = getAutomations();
expect(Object.keys(removed).length).toEqual(0);
});
it('should not remove an automation which is in use', () => {
it('should not remove an automation which is in use', async () => {
const automations = getAutomations();
addTrigger({
await addTrigger({
title: 'test-automation',
trigger: TimerLifeCycle.onLoad,
automationId: firstAutomation.id,
@@ -227,6 +227,6 @@ describe('deleteAutomation()', () => {
outputs: expect.any(Array),
});
expect(() => deleteAutomation(automationId)).toThrowError();
await expect(deleteAutomation(automationId)).rejects.toThrowError();
});
});
@@ -39,29 +39,29 @@ describe('triggerAction()', () => {
let oscSpy = vi.spyOn(oscClient, 'emitOSC');
let httpSpy = vi.spyOn(httpClient, 'emitHTTP');
beforeEach(() => {
beforeEach(async () => {
oscSpy = vi.spyOn(oscClient, 'emitOSC').mockImplementation(() => {});
httpSpy = vi.spyOn(httpClient, 'emitHTTP').mockImplementation(() => {});
deleteAllTriggers();
const oscAutomation = addAutomation({
await deleteAllTriggers();
const oscAutomation = await addAutomation({
title: 'test-osc',
filterRule: 'all',
filters: [],
outputs: [makeOSCAction()],
});
const httpAutomation = addAutomation({
const httpAutomation = await addAutomation({
title: 'test-http',
filterRule: 'any',
filters: [],
outputs: [makeHTTPAction()],
});
addTrigger({
await addTrigger({
title: 'test-osc',
trigger: TimerLifeCycle.onLoad,
automationId: oscAutomation.id,
});
addTrigger({
await addTrigger({
title: 'test-http',
trigger: TimerLifeCycle.onFinish,
automationId: httpAutomation.id,
@@ -11,10 +11,10 @@ export function getAutomationSettings(_req: Request, res: Response<AutomationSet
res.json(automationDao.getAutomationSettings());
}
export function postAutomationSettings(req: Request, res: Response<AutomationSettings | ErrorResponse>) {
export async function postAutomationSettings(req: Request, res: Response<AutomationSettings | ErrorResponse>) {
try {
// body payload is a patch object that must contain root properties
const automationSettings = automationDao.editAutomationSettings({
const automationSettings = await automationDao.editAutomationSettings({
enabledAutomations: req.body.enabledAutomations,
enabledOscIn: req.body.enabledOscIn,
oscPortIn: req.body.oscPortIn,
@@ -33,9 +33,9 @@ export function postAutomationSettings(req: Request, res: Response<AutomationSet
}
}
export function postTrigger(req: Request, res: Response<Trigger | ErrorResponse>) {
export async function postTrigger(req: Request, res: Response<Trigger | ErrorResponse>) {
try {
const automation = automationDao.addTrigger({
const automation = await automationDao.addTrigger({
title: req.body.title,
trigger: req.body.trigger,
automationId: req.body.automationId,
@@ -47,10 +47,10 @@ export function postTrigger(req: Request, res: Response<Trigger | ErrorResponse>
}
}
export function putTrigger(req: Request, res: Response<Trigger | ErrorResponse>) {
export async function putTrigger(req: Request, res: Response<Trigger | ErrorResponse>) {
try {
// body payload is a patch object
const automation = automationDao.editTrigger(req.params.id, {
const automation = await automationDao.editTrigger(req.params.id, {
title: req.body.title ?? undefined,
trigger: req.body.trigger ?? undefined,
automationId: req.body.automationId ?? undefined,
@@ -62,9 +62,9 @@ export function putTrigger(req: Request, res: Response<Trigger | ErrorResponse>)
}
}
export function deleteTrigger(req: Request, res: Response<void | ErrorResponse>) {
export async function deleteTrigger(req: Request, res: Response<void | ErrorResponse>) {
try {
automationDao.deleteTrigger(req.params.id);
await automationDao.deleteTrigger(req.params.id);
res.status(204).send();
} catch (error) {
const message = getErrorMessage(error);
@@ -72,9 +72,9 @@ export function deleteTrigger(req: Request, res: Response<void | ErrorResponse>)
}
}
export function postAutomation(req: Request, res: Response<Automation | ErrorResponse>) {
export async function postAutomation(req: Request, res: Response<Automation | ErrorResponse>) {
try {
const newAutomation = automationDao.addAutomation({
const newAutomation = await automationDao.addAutomation({
title: req.body.title,
filterRule: req.body.filterRule,
filters: req.body.filters,
@@ -87,9 +87,9 @@ export function postAutomation(req: Request, res: Response<Automation | ErrorRes
}
}
export function editAutomation(req: Request, res: Response<Automation | ErrorResponse>) {
export async function editAutomation(req: Request, res: Response<Automation | ErrorResponse>) {
try {
const newAutomation = automationDao.editAutomation(req.params.id, {
const newAutomation = await automationDao.editAutomation(req.params.id, {
title: req.body.title,
filterRule: req.body.filterRule,
filters: req.body.filters,
@@ -102,9 +102,9 @@ export function editAutomation(req: Request, res: Response<Automation | ErrorRes
}
}
export function deleteAutomation(req: Request, res: Response<void | ErrorResponse>) {
export async function deleteAutomation(req: Request, res: Response<void | ErrorResponse>) {
try {
automationDao.deleteAutomation(req.params.id);
await automationDao.deleteAutomation(req.params.id);
res.status(204).send();
} catch (error) {
const message = getErrorMessage(error);
@@ -1,4 +1,11 @@
import type { Automation, AutomationDTO, AutomationSettings, NormalisedAutomation, Trigger, TriggerDTO } from 'ontime-types';
import type {
Automation,
AutomationDTO,
AutomationSettings,
NormalisedAutomation,
Trigger,
TriggerDTO,
} from 'ontime-types';
import { deleteAtIndex, generateId } from 'ontime-utils';
import { getDataProvider } from '../../classes/data-provider/DataProvider.js';
@@ -34,27 +41,27 @@ export function getAutomations(): NormalisedAutomation {
/**
* Patches the automation settings object
*/
export function editAutomationSettings(settings: Partial<AutomationSettings>): AutomationSettings {
saveChanges(settings);
export async function editAutomationSettings(settings: Partial<AutomationSettings>): Promise<AutomationSettings> {
await saveChanges(settings);
return getAutomationSettings();
}
/**
* Adds a validated automation to the store
*/
export function addTrigger(newTrigger: TriggerDTO): Trigger {
export async function addTrigger(newTrigger: TriggerDTO): Promise<Trigger> {
const triggers = getAutomationTriggers();
const id = getUniqueTriggerId(triggers);
const trigger = { ...newTrigger, id };
triggers.push(trigger);
saveChanges({ triggers });
await saveChanges({ triggers });
return trigger;
}
/**
* Patches an existing automation trigger
*/
export function editTrigger(id: string, newTrigger: TriggerDTO): Trigger {
export async function editTrigger(id: string, newTrigger: TriggerDTO): Promise<Trigger> {
const triggers = getAutomationTriggers();
const index = triggers.findIndex((trigger) => trigger.id === id);
@@ -63,14 +70,14 @@ export function editTrigger(id: string, newTrigger: TriggerDTO): Trigger {
}
triggers[index] = { ...triggers[index], ...newTrigger };
saveChanges({ triggers });
await saveChanges({ triggers });
return triggers[index];
}
/**
* Deletes an automation trigger given its ID
*/
export function deleteTrigger(id: string): void {
export async function deleteTrigger(id: string): Promise<void> {
let triggers = getAutomationTriggers();
const index = triggers.findIndex((trigger) => trigger.id === id);
@@ -79,53 +86,53 @@ export function deleteTrigger(id: string): void {
}
triggers = deleteAtIndex(index, triggers);
saveChanges({ triggers });
await saveChanges({ triggers });
}
/**
* Deletes all project automation triggers
*/
export function deleteAllTriggers(): void {
saveChanges({ triggers: [] });
export async function deleteAllTriggers(): Promise<void> {
await saveChanges({ triggers: [] });
}
/**
* Deletes all project automation triggers and automations
* We do this together to avoid issues with missing references
*/
export function deleteAll(): void {
saveChanges({ triggers: [], automations: {} });
export async function deleteAll() {
await saveChanges({ triggers: [], automations: {} });
}
/**
* Adds a validated automation to the store
*/
export function addAutomation(newAutomation: AutomationDTO): Automation {
export async function addAutomation(newAutomation: AutomationDTO): Promise<Automation> {
const automations = getAutomations();
const id = getUniqueAutomationId(automations);
automations[id] = { ...newAutomation, id };
saveChanges({ automations });
await saveChanges({ automations });
return automations[id];
}
/**
* Updates an existing automation with a new entry
*/
export function editAutomation(id: string, newAutomation: AutomationDTO): Automation {
export async function editAutomation(id: string, newAutomation: AutomationDTO): Promise<Automation> {
const automations = getAutomations();
if (!Object.hasOwn(automations, id)) {
throw new Error(`Automation with id ${id} not found`);
}
automations[id] = { ...newAutomation, id };
saveChanges({ automations });
await saveChanges({ automations });
return automations[id];
}
/**
* Deletes a automation given its ID
*/
export function deleteAutomation(id: string): void {
export async function deleteAutomation(id: string): Promise<void> {
const automations = getAutomations();
// ignore request if automation does not exist
if (!Object.hasOwn(automations, id)) {
@@ -140,7 +147,7 @@ export function deleteAutomation(id: string): void {
}
}
delete automations[id];
saveChanges({ automations });
await saveChanges({ automations });
}
/**