refactor: initialise data

This commit is contained in:
Carlos Valente
2024-07-05 21:19:14 +02:00
committed by Carlos Valente
parent dae32e89a3
commit 84792bc00d
31 changed files with 1031 additions and 545 deletions
@@ -1,5 +1,12 @@
import { describe, it, expect } from 'vitest';
import { appendToName, ensureJsonExtension } from '../fileManagement.js';
import { describe, it, expect, Mock } from 'vitest';
import * as fs from 'fs';
import { appendToName, ensureJsonExtension, generateUniqueFileName } from '../fileManagement.js';
// Mock fs.existsSync to control the test environment
vi.mock('fs', () => ({
existsSync: vi.fn(),
}));
describe('ensureJsonExtension', () => {
it('should add .json to a filename without an extension', () => {
@@ -49,3 +56,37 @@ describe('appendToName', () => {
expect(result).toBe('strange.file.name (recovered).json');
});
});
describe('generateUniqueFileName', () => {
const directory = '/test/directory';
const filename = 'testFile.txt';
const baseName = 'testFile';
const extension = '.txt';
beforeEach(() => {
// Clear all mocks before each test
vi.clearAllMocks();
});
it('should return original file name if there is no conflict', () => {
(fs.existsSync as Mock).mockReturnValue(false);
const uniqueFilename = generateUniqueFileName(directory, filename);
expect(uniqueFilename).toBe(filename);
});
it('should append a counter to the filename if a conflict exists', () => {
// Mock the first call to return true (file exists), then false
(fs.existsSync as Mock).mockReturnValueOnce(true).mockReturnValueOnce(false);
const expectedFilename = `${baseName} (1)${extension}`;
const uniqueFilename = generateUniqueFileName(directory, filename);
expect(uniqueFilename).toBe(expectedFilename);
});
it('should increment the counter for each conflict until a unique filename is found', () => {
// Mock the first two calls to return true (file exists), then false
(fs.existsSync as Mock).mockReturnValueOnce(true).mockReturnValueOnce(true).mockReturnValueOnce(false);
const expectedFilename = `${baseName} (2)${extension}`;
const uniqueFilename = generateUniqueFileName(directory, filename);
expect(uniqueFilename).toBe(expectedFilename);
});
});
+27 -13
View File
@@ -16,7 +16,7 @@ import {
import { dbModel } from '../../models/dataModel.js';
import { createEvent, getCustomFieldData, parseExcel, parseJson } from '../parser.js';
import { createEvent, getCustomFieldData, parseExcel, parseDatabaseModel } from '../parser.js';
import { makeString } from '../parserUtils.js';
import { parseRundown, parseUrlPresets, parseViewSettings } from '../parserFunctions.js';
import { ImportMap, MILLIS_PER_MINUTE } from 'ontime-utils';
@@ -27,6 +27,20 @@ const requiredSettings = {
version: 'any',
};
// mock data provider
beforeAll(() => {
vi.mock('../../classes/data-provider/DataProvider.js', () => {
return {
getDataProvider: vi.fn().mockImplementation(() => {
return {
setRundown: vi.fn().mockImplementation((newData) => newData),
setCustomFields: vi.fn().mockImplementation((newData) => newData),
};
}),
};
});
});
describe('test json parser with valid def', () => {
const testData: Partial<DatabaseModel> = {
rundown: [
@@ -187,7 +201,7 @@ describe('test json parser with valid def', () => {
viewSettings: {} as ViewSettings,
};
const { data } = parseJson(testData);
const { data } = parseDatabaseModel(testData);
it('has 7 events', () => {
const length = data.rundown.length;
@@ -257,7 +271,7 @@ describe('test parser edge cases', () => {
};
// @ts-expect-error -- we know this is wrong, testing imports outside domain
const { data } = parseJson(testData);
const { data } = parseDatabaseModel(testData);
expect(typeof (data.rundown[0] as OntimeEvent).cue).toBe('string');
expect(typeof (data.rundown[1] as OntimeEvent).cue).toBe('string');
});
@@ -274,7 +288,7 @@ describe('test parser edge cases', () => {
};
// @ts-expect-error -- we know this is wrong, testing imports outside domain
const { data } = parseJson(testData);
const { data } = parseDatabaseModel(testData);
expect(data.rundown[0].id).toBeDefined();
});
@@ -297,7 +311,7 @@ describe('test parser edge cases', () => {
};
//@ts-expect-error -- we know this is wrong, testing imports outside domain
const { data, errors } = parseJson(testData);
const { data, errors } = parseDatabaseModel(testData);
expect(data.rundown.length).toBe(1);
expect(errors.length).toBe(7);
});
@@ -319,7 +333,7 @@ describe('test parser edge cases', () => {
};
// @ts-expect-error -- we know this is wrong, testing imports outside domain
const { data } = parseJson(testData);
const { data } = parseDatabaseModel(testData);
expect(data.rundown.length).toBe(0);
});
@@ -332,7 +346,7 @@ describe('test parser edge cases', () => {
};
// @ts-expect-error -- we know this is wrong, testing imports outside domain
expect(() => parseJson(testData)).toThrow();
expect(() => parseDatabaseModel(testData)).toThrow();
});
});
@@ -375,7 +389,7 @@ describe('test corrupt data', () => {
};
// @ts-expect-error -- we know this is wrong, testing imports outside domain
const { data } = parseJson(emptyEvents);
const { data } = parseDatabaseModel(emptyEvents);
expect(data.rundown.length).toBe(2);
});
@@ -400,7 +414,7 @@ describe('test corrupt data', () => {
};
// @ts-expect-error -- we know this is wrong, testing imports outside domain
const { data } = parseJson(emptyEvents);
const { data } = parseDatabaseModel(emptyEvents);
expect(data.rundown.length).toBe(0);
});
@@ -418,7 +432,7 @@ describe('test corrupt data', () => {
};
// @ts-expect-error -- we know this is wrong, testing imports outside domain
const { data: parsedDef } = parseJson(emptyProjectData);
const { data: parsedDef } = parseDatabaseModel(emptyProjectData);
expect(parsedDef.project).toStrictEqual(dbModel.project);
});
@@ -433,13 +447,13 @@ describe('test corrupt data', () => {
};
// @ts-expect-error -- we know this is wrong, testing imports outside domain
const { data } = parseJson(missingSettings);
const { data } = parseDatabaseModel(missingSettings);
expect(data.settings).toStrictEqual(dbModel.settings);
});
it('fails with invalid JSON', () => {
// @ts-expect-error -- we know this is wrong, testing imports outside domain
expect(() => parseJson('some random dataset')).toThrow();
expect(() => parseDatabaseModel('some random dataset')).toThrow();
});
});
@@ -667,7 +681,7 @@ describe('test import of v2 datamodel', () => {
},
};
// @ts-expect-error -- we know this is wrong, testing imports outside domain
const { data: parsed, _errors } = parseJson(v2ProjectFile);
const { data: parsed, _errors } = parseDatabaseModel(v2ProjectFile);
expect(parsed.rundown.length).toBe(3);
expect(parsed.rundown[0]).toMatchObject({ type: SupportedEvent.Block });
expect(parsed.rundown[0]).toEqual(
+39 -1
View File
@@ -1,6 +1,6 @@
import { existsSync, mkdirSync } from 'fs';
import { readdir } from 'fs/promises';
import { parse } from 'path';
import { basename, extname, join, parse } from 'path';
/**
* @description Creates a directory if it doesn't exist
@@ -47,3 +47,41 @@ export function appendToName(filePath: string, append: string): string {
const extension = filePath.split('.').pop();
return filePath.replace(`.${extension}`, ` ${append}.${extension}`);
}
/**
* Generates a unique file name within the specified directory.
* If a file with the same name already exists, appends a counter to the filename.
*/
export function generateUniqueFileName(directory: string, filename: string): string {
const extension = extname(filename);
const baseName = basename(filename, extension);
let counter = 0;
let uniqueFilename = filename;
while (fileExists(uniqueFilename)) {
counter++;
// Append counter to filename if the file exists.
uniqueFilename = `${baseName} (${counter})${extension}`;
}
return uniqueFilename;
function fileExists(name: string) {
return existsSync(join(directory, name));
}
}
/**
* retrieves the filename from a given path
*/
export function getFileNameFromPath(filePath: string): string {
return basename(filePath);
}
/**
* Utility naivly checks for paths on whether it includes directories
*/
export function isPath(filePath: string): boolean {
return filePath !== basename(filePath);
}
@@ -1,26 +0,0 @@
import { existsSync } from 'fs';
import path from 'path';
/**
* Generates a unique file name within the specified directory.
* If a file with the same name already exists, appends a counter to the filename.
*/
export const generateUniqueFileName = (directory: string, filename: string): string => {
const baseName = path.basename(filename, path.extname(filename));
const extension = path.extname(filename);
let counter = 0;
let uniqueFilename = filename;
while (fileExists(uniqueFilename)) {
counter++;
// Append counter to filename if the file exists.
uniqueFilename = `${baseName} (${counter})${extension}`;
}
return uniqueFilename;
function fileExists(name: string) {
return existsSync(path.join(directory, name));
}
};
+2 -2
View File
@@ -288,11 +288,11 @@ export type ParsingError = {
};
/**
* @description JSON parser function for ontime project file
* @description handles parsing of ontime project file
* @param {object} jsonData - project file to be parsed
* @returns {object} - parsed object
*/
export function parseJson(jsonData: Partial<DatabaseModel>): { data: DatabaseModel; errors: ParsingError[] } {
export function parseDatabaseModel(jsonData: Partial<DatabaseModel>): { data: DatabaseModel; errors: ParsingError[] } {
// we need to parse settings first to make sure the data is ours
// this may throw
const settings = parseSettings(jsonData);