From 974baa6cc294dcc04a4e4dd0ef98979fb286ec13 Mon Sep 17 00:00:00 2001 From: Ad5001 Date: Sat, 12 Oct 2024 05:31:42 +0200 Subject: [PATCH] Adding base module tests --- common/src/module/common.mjs | 14 +++-- common/test/basics/events.mjs | 14 ++--- common/test/basics/interface.mjs | 11 +++- common/test/basics/module.mjs | 89 ++++++++++++++++++++++++++++++++ common/test/basics/utils.mjs | 40 +++++++------- 5 files changed, 136 insertions(+), 32 deletions(-) create mode 100644 common/test/basics/module.mjs diff --git a/common/src/module/common.mjs b/common/src/module/common.mjs index 243fed2..4cd7993 100644 --- a/common/src/module/common.mjs +++ b/common/src/module/common.mjs @@ -30,6 +30,8 @@ export class Module extends BaseEventEmitter { #name /** @type {Object.} */ #initializationParameters + /** @type {boolean} */ + #initialized = false /** * @@ -41,8 +43,14 @@ export class Module extends BaseEventEmitter { console.log(`Loading module ${name}...`) this.#name = name this.#initializationParameters = initializationParameters - this.initialized = false + } + get name() { + return this.#name; + } + + get initialized() { + return this.#initialized } /** @@ -50,7 +58,7 @@ export class Module extends BaseEventEmitter { * @param {Object.} options */ initialize(options) { - if(this.initialized) + if(this.#initialized) throw new Error(`Cannot reinitialize module ${this.#name}.`) console.log(`Initializing ${this.#name}...`) for(const [name, value] of Object.entries(this.#initializationParameters)) { @@ -61,6 +69,6 @@ export class Module extends BaseEventEmitter { else if(typeof value !== typeof options[name]) throw new Error(`Option '${name}' of initialize of module ${this.#name} is not a '${value}' (${typeof options[name]}).`) } - this.initialized = true + this.#initialized = true } } diff --git a/common/test/basics/events.mjs b/common/test/basics/events.mjs index 15d44aa..8261ff1 100644 --- a/common/test/basics/events.mjs +++ b/common/test/basics/events.mjs @@ -45,13 +45,13 @@ class MockEvent2 extends BaseEvent { const sandbox = spy.sandbox() -describe("EventsEmitters", function() { +describe("Lib/EventsEmitters", function() { afterEach(() => { sandbox.restore() }) - it("should forward events to all of its listeners", function() { + it("forwards events to all of its listeners", function() { const emitter = new MockEmitter() const listener1 = spy() const listener2 = spy() @@ -62,7 +62,7 @@ describe("EventsEmitters", function() { expect(listener2).to.have.been.called.once }) - it("should forward multiple events to a singular listener", function() { + it("forwards multiple events to a singular listener", function() { const emitter = new MockEmitter() const listener = spy() const mockEvent1 = new MockEvent1() @@ -75,7 +75,7 @@ describe("EventsEmitters", function() { expect(listener).to.also.have.been.called.with.exactly(mockEvent2) }) - it("should be able to have listeners remvoed", function() { + it("is able to have listeners removed", function() { const emitter = new MockEmitter() const listener = spy() emitter.on("example1", listener) @@ -93,7 +93,7 @@ describe("EventsEmitters", function() { expect(removedFromOneOfTheEvents).to.be.true }) - it("should be able to remove one listener listening to one event when said listener listens to multiple", function() { + it("is able to have one listener's listening to a single event removed when said listener listens to multiple", function() { const emitter = new MockEmitter() const listener = spy() const mockEvent1 = new MockEvent1() @@ -107,7 +107,7 @@ describe("EventsEmitters", function() { expect(listener).to.also.have.been.called.with.exactly(mockEvent2) }) - it("shouldn't be able to add listen/unlisten to, or emit inexistant events", function() { + it("is not able to emit or add/remove listeners for inexistant events", function() { const emitter = new MockEmitter() const listener = spy() expect(() => emitter.on("inexistant", listener)).to.throw(Error) @@ -115,7 +115,7 @@ describe("EventsEmitters", function() { expect(() => emitter.emit(new BaseEvent("inexistant"))).to.throw(Error) }) - it("shouldn't be able to emit non-events", function() { + it("isn't able to emit non-events", function() { const emitter = new MockEmitter() expect(() => emitter.emit("not-an-event")).to.throw(Error) }) diff --git a/common/test/basics/interface.mjs b/common/test/basics/interface.mjs index a8d8d32..aaf512e 100644 --- a/common/test/basics/interface.mjs +++ b/common/test/basics/interface.mjs @@ -33,9 +33,16 @@ import { MockDialog } from "../mock/dialog.mjs" import { MockRootElement } from "../mock/root.mjs" import { MockCanvas } from "../mock/canvas.mjs" -describe("Interface", function() { +describe("Interfaces", function() { + describe("#interface methods", function() { + it("throws an error when called directly", function() { + const obj = new CanvasInterface() + expect(() => obj.markDirty()).to.throw(Error) + }) + }) + describe("#checkImplementation", function() { - it("should validate the implementation of mocks", function() { + it("validates the implementation of mocks", function() { const checkMockLatex = () => Interface.checkImplementation(LatexInterface, new MockLatex()) const checkMockHelper = () => Interface.checkImplementation(HelperInterface, new MockHelper()) const checkMockDialog = () => Interface.checkImplementation(DialogInterface, new MockDialog()) diff --git a/common/test/basics/module.mjs b/common/test/basics/module.mjs new file mode 100644 index 0000000..5093096 --- /dev/null +++ b/common/test/basics/module.mjs @@ -0,0 +1,89 @@ +/** + * LogarithmPlotter - 2D plotter software to make BODE plots, sequences and distribution functions. + * Copyright (C) 2021-2024 Ad5001 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// Load prior events +import "./events.mjs" +import "./interface.mjs" + +import { describe, it } from "mocha" +import { expect } from "chai" +import { BOOLEAN, DialogInterface, FUNCTION, NUMBER, STRING } from "../../src/module/interface.mjs" +import { Module } from "../../src/module/common.mjs" +import { MockDialog } from "../mock/dialog.mjs" + +class MockModule extends Module { + constructor() { + super("mock", { + number: NUMBER, + bool: BOOLEAN, + str: STRING, + func: FUNCTION, + dialog: DialogInterface + }) + } +} + +describe("Modules/Base", function() { + it("defined a Modules global", function() { + expect(globalThis.Modules).to.not.be.undefined + }) + + it("is not be initialized upon construction", function() { + const module = new MockModule() + expect(module.name).to.equal("mock") + expect(module.initialized).to.be.false + }) + + it("is only be initialized with the right arguments", function() { + const module = new MockModule() + const initializeWithNoArg = () => module.initialize({}) + const initializeWithSomeArg = () => module.initialize({ number: 0, str: "" }) + const initializeWithWrongType = () => module.initialize({ + number: () => {}, + str: 0, + bool: "", + func: false, + dialog: null + }) + const initializeProperly = () => module.initialize({ + number: 0, + str: "", + bool: true, + func: FUNCTION, + dialog: new MockDialog() + }) + expect(initializeWithNoArg).to.throw(Error) + expect(initializeWithSomeArg).to.throw(Error) + expect(initializeWithWrongType).to.throw(Error) + expect(initializeProperly).to.not.throw(Error) + expect(module.initialized).to.be.true + }) + + it("cannot be initialized twice", function() { + const module = new MockModule() + const initialize = () => module.initialize({ + number: 0, + str: "", + bool: true, + func: FUNCTION, + dialog: new MockDialog() + }) + expect(initialize).to.not.throw(Error) + expect(initialize).to.throw(Error) + }) +}) \ No newline at end of file diff --git a/common/test/basics/utils.mjs b/common/test/basics/utils.mjs index 8078645..aab2cf5 100644 --- a/common/test/basics/utils.mjs +++ b/common/test/basics/utils.mjs @@ -22,23 +22,23 @@ import { textsup, textsub, parseName, getRandomColor, escapeHTML, exponentsToExp import { describe, it } from "mocha" import { expect } from "chai" -describe("Extensions", function() { +describe("Lib/PrototypeExtensions", function() { describe("#String.toLatinUppercase", function() { - it("should be able to transform latin characters from strings to their uppercase version", function() { + it("transforms latin characters from strings to their uppercase version", function() { expect("abc".toLatinUppercase()).to.equal("ABC") expect("abCd".toLatinUppercase()).to.equal("ABCD") expect("ab123cd456".toLatinUppercase()).to.equal("AB123CD456") expect("ABC".toLatinUppercase()).to.equal("ABC") }) - it("shouldn't transform non latin characters to their uppercase version", function() { + it("does not transform non latin characters to their uppercase version", function() { expect("abαπ".toLatinUppercase()).to.equal("ABαπ") expect("abαπ".toLatinUppercase()).to.not.equal("abαπ".toUpperCase()) }) }) describe("#String.removeEnclosure", function() { - it("should be able to remove the first and last characters", function() { + it("is able to remove the first and last characters", function() { expect("[1+t]".removeEnclosure()).to.equal("1+t") expect('"a+b+c*d"'.removeEnclosure()).to.equal("a+b+c*d") expect("(pi/2)".removeEnclosure()).to.equal("pi/2") @@ -46,7 +46,7 @@ describe("Extensions", function() { }) describe("#Number.toDecimalPrecision", function() { - it("should be able to round a number to a fixed decimal precision", function() { + it("rounds a number to a fixed decimal precision", function() { expect(123.456789.toDecimalPrecision()).to.equal(123) expect(123.456789.toDecimalPrecision(1)).to.equal(123.5) expect(123.456789.toDecimalPrecision(2)).to.equal(123.46) @@ -59,42 +59,42 @@ describe("Extensions", function() { }) }) -describe("Utils", function() { +describe("Lib/Utils", function() { describe("#textsup", function() { - it("should transform characters which have a sup unicode equivalent", function() { + it("transforms characters which have a sup unicode equivalent", function() { expect(textsup("-+=()")).to.equal("⁻⁺⁼⁽⁾") expect(textsup("0123456789")).to.equal("⁰¹²³⁴⁵⁶⁷⁸⁹") expect(textsup("abcdefghijklmnoprstuvwxyz")).to.equal("ᵃᵇᶜᵈᵉᶠᵍʰⁱʲᵏˡᵐⁿᵒᵖʳˢᵗᵘᵛʷˣʸᶻ") }) - it("shouldn't transform characters without a sup equivalent", function() { + it("does not transform characters without a sup equivalent", function() { expect(textsup("ABCDEFGHIJKLMNOPQRSTUVWXYZq")).to.equal("ABCDEFGHIJKLMNOPQRSTUVWXYZq") }) - it("should partially transform strings which only have a few characters with a sup equivalent", function() { + it("partially transforms strings which only have a few characters with a sup equivalent", function() { expect(textsup("ABCabcABC")).to.equal("ABCᵃᵇᶜABC") }) }) describe("#textsub", function() { - it("should transform characters which have a sub unicode equivalent", function() { + it("transforms characters which have a sub unicode equivalent", function() { expect(textsub("-+=()")).to.equal("₋₊₌₍₎") expect(textsub("0123456789")).to.equal("₀₁₂₃₄₅₆₇₈₉") expect(textsub("aehijklmnoprstuvx")).to.equal("ₐₑₕᵢⱼₖₗₘₙₒₚᵣₛₜᵤᵥₓ") }) - it("shouldn't transform characters without a sub equivalent", function() { + it("does not transform characters without a sub equivalent", function() { expect(textsub("ABCDEFGHIJKLMNOPQRSTUVWXYZ")).to.equal("ABCDEFGHIJKLMNOPQRSTUVWXYZ") expect(textsub("bcdfgqyz")).to.equal("bcdfgqyz") }) - it("should partially transform strings which only have a few characters with a sub equivalent", function() { + it("partially transforms strings which only have a few characters with a sub equivalent", function() { expect(textsub("ABC123ABC")).to.equal("ABC₁₂₃ABC") }) }) describe("#parseName", function() { - it("should parse greek letter names", function() { + it("parses greek letter names", function() { const shorthands = { "α": ["al", "alpha"], "β": ["be", "beta"], @@ -135,27 +135,27 @@ describe("Utils", function() { } }) - it("should parse array elements into sub", function() { + it("parses array elements into sub", function() { expect(parseName("u[n+1]")).to.equal("uₙ₊₁") expect(parseName("u[(n+x)]")).to.equal("u₍ₙ₊ₓ₎") expect(parseName("u[A]")).to.equal("uA") }) - it("should remove disallowed characters when indicated", function() { + it("removes disallowed characters when indicated", function() { const disallowed = "xnπℝℕ\\∪∩[] ()^/^/÷*×+=1234567890¹²³⁴⁵⁶⁷⁸⁹⁰-" expect(parseName(disallowed)).to.equal("") expect(parseName("AA" + disallowed)).to.equal("AA") expect(parseName(disallowed, false)).to.equal(disallowed) }) - it("should be able to do all three at once", function() { + it("is able to do all three at once", function() { expect(parseName("al[n+1]+n")).to.equal("αₙ₊₁") expect(parseName("al[n+1]+n", false)).to.equal("αₙ₊₁+n") }) }) describe("#getRandomColor", function() { - it("should provide a valid color", function() { + it("provides a valid color", function() { const colorReg = /^#[A-F\d]{6}$/ for(let i = 0; i < 50; i++) expect(getRandomColor()).to.match(colorReg) @@ -163,19 +163,19 @@ describe("Utils", function() { }) describe("#escapeHTML", function() { - it("should should escape ampersands", function() { + it("escapes ampersands", function() { expect(escapeHTML("&")).to.equal("&") expect(escapeHTML("High & Mighty")).to.equal("High & Mighty") }) - it("should escape injected HTML tags", function() { + it("escapes injected HTML tags", function() { expect(escapeHTML("")).to.equal("<script>alert('Injected!')</script>") expect(escapeHTML('Link')).to.equal('<a href="javascript:alert()">Link</a>') }) }) describe("#exponentsToExpression", function() { - it("should transform exponents to power expression", function() { + it("transforms exponents to power expression", function() { expect(exponentsToExpression("x¹²³⁴⁵⁶⁷⁸⁹⁰")).to.equal("x^1234567890") expect(exponentsToExpression("x¹²+y³⁴")).to.equal("x^12+y^34") })