Started Settings unit tests.

This commit is contained in:
marley 2023-05-17 14:43:14 -07:00
parent a30c0dd179
commit 72648f7430
3 changed files with 250 additions and 140 deletions

59
__mocks__/fs.js Normal file
View file

@ -0,0 +1,59 @@
const fs = jest.createMockFromModule('fs');
let fileContents = '';
function __setFileContents(contents) {
fileContents = contents;
}
let writePromise = null;
function __setWritePromise(resolve) {
writePromise = Promise.resolve(resolve);
}
// example info from Node docs
function statSync(file) {
return {
dev: 2114,
ino: 48064969,
mode: 33188,
nlink: 1,
uid: 85,
gid: 100,
rdev: 0,
size: 527,
blksize: 4096,
blocks: 8,
atimeMs: 1318289051000.1,
mtimeMs: 1318289051000.1,
ctimeMs: 1318289051000.1,
birthtimeMs: 1318289051000.1,
atime: 'Mon, 10 Oct 2011 23:24:11 GMT',
mtime: 'Mon, 10 Oct 2011 23:24:11 GMT',
ctime: 'Mon, 10 Oct 2011 23:24:11 GMT',
birthtime: 'Mon, 10 Oct 2011 23:24:11 GMT',
};
}
function writeFileSync(file, contents) {
}
function readFileSync(file, options) {
return fileContents;
}
let promises = {
writeFile: jest.fn(() => writePromise),
readFile: jest.fn(() => fileContents),
};
fs.__setFileContents = __setFileContents;
fs.__setWritePromise = __setWritePromise;
fs.statSync = statSync;
fs.writeFileSync = writeFileSync;
fs.readFileSync = readFileSync;
fs.promises = promises;
module.exports = fs;

View file

@ -1,14 +1,17 @@
import { EliteMatrix } from "elite-matrix";
import {EliteMatrix} from 'elite-matrix';
import {PathLike} from 'fs';
const EventEmitter = require('node:events');
const fs = require('node:fs/promises');
const { statSync, writeFileSync, readFileSync } = require('node:fs');
// Jest can't parse 'node:fs' so this has to be 'fs' for testing.
const fs = require('fs/promises');
const {statSync, writeFileSync, readFileSync} = require('fs');
const ini = require('ini');
const os = require('node:os');
const path = require('node:path');
const { setTimeout } = require('node:timers/promises');
const {setTimeout} = require('node:timers/promises');
const xmlJS = require('xml-js');
import { Log } from "./Log";
import {Log} from './Log';
interface settingsFile {
minValue: number,
@ -19,13 +22,13 @@ interface settingsFile {
export class Settings extends EventEmitter {
static #instance: Settings;
#file: string;
readonly #file: string;
#writing: boolean;
minValue: number;
maxDistance: number;
#matrixFile: null|string;
#matrixFile: null | string;
matrix?: EliteMatrix;
private constructor(isPackaged: boolean) {
@ -38,7 +41,7 @@ export class Settings extends EventEmitter {
}
// Check if settings file exists, and create it if not. Using sync since it's such a small
// file, and this information is neccesary to build the UI.
// file, and this information is necessary to build the UI.
try {
statSync(this.#file);
} catch (err) {
@ -54,7 +57,7 @@ export class Settings extends EventEmitter {
}
// Initial reading of settings file done in sync for same reasons as above.
const contents: settingsFile = JSON.parse(readFileSync(this.#file, { encoding: 'utf8' }));
const contents: settingsFile = JSON.parse(readFileSync(this.#file, {encoding: 'utf8'}));
this.minValue = contents.minValue;
this.maxDistance = contents.maxDistance;
this.#matrixFile = contents.matrixFile;
@ -76,14 +79,10 @@ export class Settings extends EventEmitter {
/* -------------------------------------------------------------------------------- save ---- */
async save(settings: settingsFile): Promise<boolean> {
if (!this.#writing) {
try {
Log.write('Attempting to save changed settings...');
// So we don't try to write again before this one finishes.
this.#writing = true;
await fs.writeFile(this.#file, JSON.stringify(settings));
this.#writing = false;
Log.write('Settings saved!');
@ -91,20 +90,18 @@ export class Settings extends EventEmitter {
await this.#read();
return true;
} catch (err) {
Log.write(err);
return false;
}
} else {
return false;
}
}
/* ------------------------------------------------------------------------------- #read ---- */
async #read(): Promise<boolean> {
try {
const file: string = await fs.readFile(this.#file, { encoding: 'utf8' });
const file: string = await fs.readFile(this.#file, {encoding: 'utf8'});
const contents: settingsFile = JSON.parse(file);
this.minValue = contents.minValue;
@ -126,19 +123,21 @@ export class Settings extends EventEmitter {
/* -------------------------------------------------------------------------- #setMatrix ---- */
async #setMatrix(): Promise<void> {
const file: string = await fs.readFile(this.#matrixFile, { encoding: 'utf8' });
const file: string = await fs.readFile((
this.#matrixFile as PathLike
), {encoding: 'utf8'});
let matrixRed: [number, number, number];
let matrixGreen: [number, number, number];
let matrixBlue: [number, number, number];
if (path.basename(this.#matrixFile) === 'GraphicsConfiguration.xml') {
if (this.#matrixFile && path.basename(this.#matrixFile) === 'GraphicsConfiguration.xml') {
const options = {
trim: true,
ignoreDeclaration: true,
ignoreAttributes: true,
compact: true,
textKey: '$'
textKey: '$',
};
const contents = xmlJS.xml2js(file, options);
@ -150,14 +149,16 @@ export class Settings extends EventEmitter {
matrix = matrix.map(v => v.replace(/\s/g, '').split(','));
matrixRed = matrix[0].length === 3 ? matrix[0] : [1,0,0];
matrixGreen = matrix[1].length === 3 ? matrix[1] : [0,1,0];
matrixBlue = matrix[2].length === 3 ? matrix[2] : [0,0,1];
matrixRed = matrix[0].length === 3 ? matrix[0] : [1, 0, 0];
matrixGreen = matrix[1].length === 3 ? matrix[1] : [0, 1, 0];
matrixBlue = matrix[2].length === 3 ? matrix[2] : [0, 0, 1];
this.matrix = new EliteMatrix(matrixRed, matrixGreen, matrixBlue);
} else if (path.basename(this.#matrixFile) === 'XML-Profile.ini') {
const contents = (ini.parse(file)).constants;
} else if (this.#matrixFile && path.basename(this.#matrixFile) === 'XML-Profile.ini') {
const contents = (
ini.parse(file)
).constants;
matrixRed = [contents.x150, contents.y150, contents.z150];
matrixGreen = [contents.x151, contents.y151, contents.z151];

50
test/Settings.test.ts Normal file
View file

@ -0,0 +1,50 @@
import {expect} from '@jest/globals';
import {Settings} from '../src/models/Settings';
jest.mock('fs');
describe('Settings', () => {
const settingsFile = {
minValue: 500000,
maxDistance: 10000,
matrixFile: '',
};
beforeEach(() => {
require('fs').__setFileContents(JSON.stringify(settingsFile));
});
describe('get()', () => {
it('should get instance', () => {
expect(Settings.get()).toBeInstanceOf(Settings);
});
it('should set initial values', () => {
const minValue = Settings.get().minValue;
expect(minValue).toBeDefined();
expect(typeof minValue).toBe('number');
const maxDistance = Settings.get().maxDistance;
expect(maxDistance).toBeDefined();
expect(typeof maxDistance).toBe('number');
const matrix = Settings.get().matrix;
expect(matrix).toBeUndefined();
});
});
describe('save()', () => {
it('should return boolean', async () => {
const result = await Settings.get().save(settingsFile);
expect(typeof result).toBe('boolean');
require('fs').__setWritePromise(true);
const resultResolve = await Settings.get().save(settingsFile);
expect(resultResolve).toBe(true);
require('fs').__setWritePromise(false);
const resultReject = await Settings.get().save(settingsFile);
expect(resultReject).toBe(false);
});
});
});