mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-09 17:33:55 +00:00
refactor: initialise data
This commit is contained in:
committed by
Carlos Valente
parent
dae32e89a3
commit
84792bc00d
@@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
};
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user