diff --git a/package-lock.json b/package-lock.json
index 9f19b17f..095c35e8 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -376,6 +376,41 @@
"integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==",
"optional": true
},
+ "@sinonjs/commons": {
+ "version": "1.8.2",
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.2.tgz",
+ "integrity": "sha512-sruwd86RJHdsVf/AtBoijDmUqJp3B6hF/DGC23C+JaegnDHaZyewCjoVGTdg3J0uz3Zs7NnIT05OBOmML72lQw==",
+ "dev": true,
+ "requires": {
+ "type-detect": "4.0.8"
+ }
+ },
+ "@sinonjs/fake-timers": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-6.0.1.tgz",
+ "integrity": "sha512-MZPUxrmFubI36XS1DI3qmI0YdN1gks62JtFZvxR67ljjSNCeK6U08Zx4msEWOXuofgqUt6zPHSi1H9fbjR/NRA==",
+ "dev": true,
+ "requires": {
+ "@sinonjs/commons": "^1.7.0"
+ }
+ },
+ "@sinonjs/samsam": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-5.3.1.tgz",
+ "integrity": "sha512-1Hc0b1TtyfBu8ixF/tpfSHTVWKwCBLY4QJbkgnE7HcwyvT2xArDxb4K7dMgqRm3szI+LJbzmW/s4xxEhv6hwDg==",
+ "dev": true,
+ "requires": {
+ "@sinonjs/commons": "^1.6.0",
+ "lodash.get": "^4.4.2",
+ "type-detect": "^4.0.8"
+ }
+ },
+ "@sinonjs/text-encoding": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz",
+ "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==",
+ "dev": true
+ },
"@stylelint/postcss-css-in-js": {
"version": "0.37.2",
"resolved": "https://registry.npmjs.org/@stylelint/postcss-css-in-js/-/postcss-css-in-js-0.37.2.tgz",
@@ -3943,6 +3978,12 @@
"verror": "1.10.0"
}
},
+ "just-extend": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.1.tgz",
+ "integrity": "sha512-aWgeGFW67BP3e5181Ep1Fv2v8z//iBJfrvyTnq8wG86vEESwmonn1zPBJ0VfmT9CJq2FIT0VsETtrNFm2a+SHA==",
+ "dev": true
+ },
"keyv": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz",
@@ -4021,6 +4062,12 @@
"integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=",
"dev": true
},
+ "lodash.get": {
+ "version": "4.4.2",
+ "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
+ "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=",
+ "dev": true
+ },
"lodash.sortby": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
@@ -4527,6 +4574,36 @@
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
},
+ "nise": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/nise/-/nise-4.0.4.tgz",
+ "integrity": "sha512-bTTRUNlemx6deJa+ZyoCUTRvH3liK5+N6VQZ4NIw90AgDXY6iPnsqplNFf6STcj+ePk0H/xqxnP75Lr0J0Fq3A==",
+ "dev": true,
+ "requires": {
+ "@sinonjs/commons": "^1.7.0",
+ "@sinonjs/fake-timers": "^6.0.0",
+ "@sinonjs/text-encoding": "^0.7.1",
+ "just-extend": "^4.0.2",
+ "path-to-regexp": "^1.7.0"
+ },
+ "dependencies": {
+ "isarray": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
+ "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=",
+ "dev": true
+ },
+ "path-to-regexp": {
+ "version": "1.8.0",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz",
+ "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==",
+ "dev": true,
+ "requires": {
+ "isarray": "0.0.1"
+ }
+ }
+ }
+ },
"node-ical": {
"version": "0.12.7",
"resolved": "https://registry.npmjs.org/node-ical/-/node-ical-0.12.7.tgz",
@@ -6149,6 +6226,37 @@
}
}
},
+ "sinon": {
+ "version": "9.2.4",
+ "resolved": "https://registry.npmjs.org/sinon/-/sinon-9.2.4.tgz",
+ "integrity": "sha512-zljcULZQsJxVra28qIAL6ow1Z9tpattkCTEJR4RBP3TGc00FcttsP5pK284Nas5WjMZU5Yzy3kAIp3B3KRf5Yg==",
+ "dev": true,
+ "requires": {
+ "@sinonjs/commons": "^1.8.1",
+ "@sinonjs/fake-timers": "^6.0.1",
+ "@sinonjs/samsam": "^5.3.1",
+ "diff": "^4.0.2",
+ "nise": "^4.0.4",
+ "supports-color": "^7.1.0"
+ },
+ "dependencies": {
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
"slash": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
diff --git a/package.json b/package.json
index 56910da6..5473d04d 100644
--- a/package.json
+++ b/package.json
@@ -58,6 +58,7 @@
"nyc": "^15.1.0",
"prettier": "^2.2.1",
"pretty-quick": "^3.1.0",
+ "sinon": "^9.2.4",
"spectron": "^10.0.1",
"stylelint": "^13.8.0",
"stylelint-config-prettier": "^8.0.2",
diff --git a/tests/e2e/translations_spec.js b/tests/e2e/translations_spec.js
index a66d0ea4..639f8f12 100644
--- a/tests/e2e/translations_spec.js
+++ b/tests/e2e/translations_spec.js
@@ -7,6 +7,7 @@ const translations = require("../../translations/translations.js");
const helmet = require("helmet");
const { JSDOM } = require("jsdom");
const express = require("express");
+const sinon = require("sinon");
describe("Translations", function () {
let server;
@@ -34,6 +35,79 @@ describe("Translations", function () {
}
});
+ describe("loadTranslations", () => {
+ let dom;
+
+ beforeEach(() => {
+ dom = new JSDOM(
+ `\
+ \
+ `,
+ { runScripts: "dangerously", resources: "usable" }
+ );
+ });
+
+ it("should load translation file", (done) => {
+ dom.window.onload = async function () {
+ const { Translator, Module, config } = dom.window;
+ config.language = "en";
+ Translator.load = sinon.stub().callsFake((_m, _f, _fb, callback) => callback());
+
+ Module.register("name", { getTranslations: () => translations });
+ const MMM = Module.create("name");
+
+ const loaded = sinon.stub();
+ MMM.loadTranslations(loaded);
+
+ expect(loaded.callCount).to.equal(1);
+ expect(Translator.load.args.length).to.equal(1);
+ expect(Translator.load.calledWith(MMM, "translations/en.json", false, sinon.match.func)).to.be.true;
+
+ done();
+ };
+ });
+
+ it("should load translation + fallback file", (done) => {
+ dom.window.onload = async function () {
+ const { Translator, Module } = dom.window;
+ Translator.load = sinon.stub().callsFake((_m, _f, _fb, callback) => callback());
+
+ Module.register("name", { getTranslations: () => translations });
+ const MMM = Module.create("name");
+
+ const loaded = sinon.stub();
+ MMM.loadTranslations(loaded);
+
+ expect(loaded.callCount).to.equal(1);
+ expect(Translator.load.args.length).to.equal(2);
+ expect(Translator.load.calledWith(MMM, "translations/de.json", false, sinon.match.func)).to.be.true;
+ expect(Translator.load.calledWith(MMM, "translations/en.json", true, sinon.match.func)).to.be.true;
+
+ done();
+ };
+ });
+
+ it("should load translation fallback file", (done) => {
+ dom.window.onload = async function () {
+ const { Translator, Module, config } = dom.window;
+ config.language = "--";
+ Translator.load = sinon.stub().callsFake((_m, _f, _fb, callback) => callback());
+
+ Module.register("name", { getTranslations: () => translations });
+ const MMM = Module.create("name");
+
+ const loaded = sinon.stub();
+ MMM.loadTranslations(loaded);
+
+ expect(loaded.callCount).to.equal(1);
+ expect(Translator.load.args.length).to.equal(1);
+ expect(Translator.load.calledWith(MMM, "translations/en.json", true, sinon.match.func)).to.be.true;
+
+ done();
+ };
+ });
+ });
+
const mmm = {
name: "TranslationTest",
file(file) {