Skip to content

Commit 9a3502e

Browse files
tests: add setupDOMEnvironment helper function to eliminate repetitive JSDOM setup code
1 parent 1b31cf1 commit 9a3502e

File tree

3 files changed

+70
-102
lines changed

3 files changed

+70
-102
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Thanks to: @dathbe.
2020
- [refactor] Add new file `js/module_functions.js` to move code used in several modules to one place (#3837)
2121
- [tests] refactor: simplify jest config file (#3844)
2222
- [tests] refactor: extract constants for weather electron tests (#3845)
23+
- [tests] refactor: add `setupDOMEnvironment` helper function to eliminate repetitive JSDOM setup code
2324
- [tests] replace `console` with `Log` in calendar `debug.js` to avoid exception in eslint config (#3846)
2425
- [tests] speed up e2e tests, cleanup and stabilize weather e2e tests (#3847, #3848)
2526

tests/e2e/translations_spec.js

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,21 @@ const express = require("express");
66
const sinon = require("sinon");
77
const translations = require("../../translations/translations");
88

9+
/**
10+
* Helper function to setup DOM environment.
11+
* @returns {object} The JSDOM window object
12+
*/
13+
function setupDOMEnvironment () {
14+
const dom = new JSDOM("", { runScripts: "dangerously", resources: "usable" });
15+
16+
dom.window.Log = { log: jest.fn(), error: jest.fn() };
17+
const translatorJs = fs.readFileSync(path.join(__dirname, "..", "..", "js", "translator.js"), "utf-8");
18+
dom.window.translations = translations;
19+
dom.window.eval(translatorJs);
20+
21+
return dom.window;
22+
}
23+
924
describe("translations", () => {
1025
let server;
1126

@@ -38,10 +53,10 @@ describe("translations", () => {
3853

3954
beforeEach(() => {
4055
// Create a new JSDOM instance for each test
41-
dom = new JSDOM("", { runScripts: "dangerously", resources: "usable" });
56+
const window = setupDOMEnvironment();
57+
dom = { window };
4258

43-
// Mock the necessary global objects
44-
dom.window.Log = { log: jest.fn(), error: jest.fn() };
59+
// Additional setup for loadTranslations tests
4560
dom.window.Translator = {};
4661
dom.window.config = { language: "de" };
4762

@@ -132,21 +147,16 @@ describe("translations", () => {
132147
}
133148
};
134149

135-
const translatorJs = fs.readFileSync(path.join(__dirname, "..", "..", "js", "translator.js"), "utf-8");
136-
137150
describe("parsing language files through the Translator class", () => {
138151
for (const language in translations) {
139152
it(`should parse ${language}`, async () => {
140-
const dom = new JSDOM("", { runScripts: "dangerously", resources: "usable" });
141-
dom.window.Log = { log: jest.fn() };
142-
dom.window.translations = translations;
143-
dom.window.eval(translatorJs);
153+
const window = setupDOMEnvironment();
144154

145155
await new Promise((resolve) => {
146-
dom.window.onload = resolve;
156+
window.onload = resolve;
147157
});
148158

149-
const { Translator } = dom.window;
159+
const { Translator } = window;
150160
await Translator.load(mmm, translations[language], false);
151161

152162
expect(typeof Translator.translations[mmm.name]).toBe("object");
@@ -178,14 +188,11 @@ describe("translations", () => {
178188

179189
// Function to initialize JSDOM and load translations
180190
const initializeTranslationDOM = (language) => {
181-
const dom = new JSDOM("", { runScripts: "dangerously", resources: "usable" });
182-
dom.window.Log = { log: jest.fn() };
183-
dom.window.translations = translations;
184-
dom.window.eval(translatorJs);
191+
const window = setupDOMEnvironment();
185192

186193
return new Promise((resolve) => {
187-
dom.window.onload = async () => {
188-
const { Translator } = dom.window;
194+
window.onload = async () => {
195+
const { Translator } = window;
189196
await Translator.load(mmm, translations[language], false);
190197
resolve(Translator.translations[mmm.name]);
191198
};

tests/unit/classes/translator_spec.js

Lines changed: 45 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,21 @@ const helmet = require("helmet");
44
const { JSDOM } = require("jsdom");
55
const express = require("express");
66

7+
/**
8+
* Helper function to setup DOM environment.
9+
* @param {string} scriptContent - The script content to evaluate
10+
* @returns {Promise<object>} The JSDOM window object
11+
*/
12+
async function setupDOMEnvironment (scriptContent) {
13+
const dom = new JSDOM("", { runScripts: "outside-only" });
14+
15+
dom.window.eval(scriptContent);
16+
dom.window.Log = { log: jest.fn(), error: jest.fn() };
17+
18+
await new Promise((resolve) => dom.window.onload = resolve);
19+
return dom.window;
20+
}
21+
722
describe("Translator", () => {
823
let server;
924
const sockets = new Set();
@@ -81,12 +96,8 @@ describe("Translator", () => {
8196
};
8297

8398
it("should return custom module translation", async () => {
84-
const dom = new JSDOM("", { runScripts: "outside-only" });
85-
dom.window.eval(translatorJsScriptContent);
86-
87-
await new Promise((resolve) => dom.window.onload = resolve);
88-
89-
const { Translator } = dom.window;
99+
const window = await setupDOMEnvironment(translatorJsScriptContent);
100+
const { Translator } = window;
90101
setTranslations(Translator);
91102

92103
let translation = Translator.translate({ name: "MMM-Module" }, "Hello");
@@ -97,12 +108,8 @@ describe("Translator", () => {
97108
});
98109

99110
it("should return core translation", async () => {
100-
const dom = new JSDOM("", { runScripts: "outside-only" });
101-
dom.window.eval(translatorJsScriptContent);
102-
103-
await new Promise((resolve) => dom.window.onload = resolve);
104-
105-
const { Translator } = dom.window;
111+
const window = await setupDOMEnvironment(translatorJsScriptContent);
112+
const { Translator } = window;
106113
setTranslations(Translator);
107114
let translation = Translator.translate({ name: "MMM-Module" }, "FOO");
108115
expect(translation).toBe("Foo");
@@ -111,48 +118,32 @@ describe("Translator", () => {
111118
});
112119

113120
it("should return custom module translation fallback", async () => {
114-
const dom = new JSDOM("", { runScripts: "outside-only" });
115-
dom.window.eval(translatorJsScriptContent);
116-
117-
await new Promise((resolve) => dom.window.onload = resolve);
118-
119-
const { Translator } = dom.window;
121+
const window = await setupDOMEnvironment(translatorJsScriptContent);
122+
const { Translator } = window;
120123
setTranslations(Translator);
121124
const translation = Translator.translate({ name: "MMM-Module" }, "A key");
122125
expect(translation).toBe("A translation");
123126
});
124127

125128
it("should return core translation fallback", async () => {
126-
const dom = new JSDOM("", { runScripts: "outside-only" });
127-
dom.window.eval(translatorJsScriptContent);
128-
129-
await new Promise((resolve) => dom.window.onload = resolve);
130-
131-
const { Translator } = dom.window;
129+
const window = await setupDOMEnvironment(translatorJsScriptContent);
130+
const { Translator } = window;
132131
setTranslations(Translator);
133132
const translation = Translator.translate({ name: "MMM-Module" }, "Fallback");
134133
expect(translation).toBe("core fallback");
135134
});
136135

137136
it("should return translation with placeholder for missing variables", async () => {
138-
const dom = new JSDOM("", { runScripts: "outside-only" });
139-
dom.window.eval(translatorJsScriptContent);
140-
141-
await new Promise((resolve) => dom.window.onload = resolve);
142-
143-
const { Translator } = dom.window;
137+
const window = await setupDOMEnvironment(translatorJsScriptContent);
138+
const { Translator } = window;
144139
setTranslations(Translator);
145140
const translation = Translator.translate({ name: "MMM-Module" }, "Hello {username}");
146141
expect(translation).toBe("Hallo {username}");
147142
});
148143

149144
it("should return key if no translation was found", async () => {
150-
const dom = new JSDOM("", { runScripts: "outside-only" });
151-
dom.window.eval(translatorJsScriptContent);
152-
153-
await new Promise((resolve) => dom.window.onload = resolve);
154-
155-
const { Translator } = dom.window;
145+
const window = await setupDOMEnvironment(translatorJsScriptContent);
146+
const { Translator } = window;
156147
setTranslations(Translator);
157148
const translation = Translator.translate({ name: "MMM-Module" }, "MISSING");
158149
expect(translation).toBe("MISSING");
@@ -168,12 +159,8 @@ describe("Translator", () => {
168159
};
169160

170161
it("should load translations", async () => {
171-
const dom = new JSDOM("", { runScripts: "outside-only" });
172-
dom.window.eval(translatorJsScriptContent);
173-
dom.window.Log = { log: jest.fn() };
174-
await new Promise((resolve) => dom.window.onload = resolve);
175-
176-
const { Translator } = dom.window;
162+
const window = await setupDOMEnvironment(translatorJsScriptContent);
163+
const { Translator } = window;
177164
const file = "translation_test.json";
178165

179166
await Translator.load(mmm, file, false);
@@ -182,30 +169,20 @@ describe("Translator", () => {
182169
});
183170

184171
it("should load translation fallbacks", async () => {
185-
const dom = new JSDOM("", { runScripts: "outside-only" });
186-
dom.window.eval(translatorJsScriptContent);
187-
188-
await new Promise((resolve) => dom.window.onload = resolve);
189-
190-
const { Translator } = dom.window;
172+
const window = await setupDOMEnvironment(translatorJsScriptContent);
173+
const { Translator } = window;
191174
const file = "translation_test.json";
192175

193-
dom.window.Log = { log: jest.fn() };
194176
await Translator.load(mmm, file, true);
195177
const json = JSON.parse(fs.readFileSync(path.join(__dirname, "..", "..", "..", "tests", "mocks", file), "utf8"));
196178
expect(Translator.translationsFallback[mmm.name]).toEqual(json);
197179
});
198180

199181
it("should not load translations, if module fallback exists", async () => {
200-
const dom = new JSDOM("", { runScripts: "outside-only" });
201-
dom.window.eval(translatorJsScriptContent);
202-
await new Promise((resolve) => dom.window.onload = resolve);
203-
204-
const { Translator } = dom.window;
182+
const window = await setupDOMEnvironment(translatorJsScriptContent);
183+
const { Translator } = window;
205184
const file = "translation_test.json";
206185

207-
208-
dom.window.Log = { log: jest.fn() };
209186
Translator.translationsFallback[mmm.name] = {
210187
Hello: "Hallo"
211188
};
@@ -220,13 +197,9 @@ describe("Translator", () => {
220197

221198
describe("loadCoreTranslations", () => {
222199
it("should load core translations and fallback", async () => {
223-
const dom = new JSDOM("", { runScripts: "outside-only" });
224-
dom.window.eval(translatorJsScriptContent);
225-
dom.window.translations = { en: "http://localhost:3000/translations/translation_test.json" };
226-
dom.window.Log = { log: jest.fn() };
227-
await new Promise((resolve) => dom.window.onload = resolve);
228-
229-
const { Translator } = dom.window;
200+
const window = await setupDOMEnvironment(translatorJsScriptContent);
201+
window.translations = { en: "http://localhost:3000/translations/translation_test.json" };
202+
const { Translator } = window;
230203
await Translator.loadCoreTranslations("en");
231204

232205
const en = translationTestData;
@@ -238,13 +211,9 @@ describe("Translator", () => {
238211
});
239212

240213
it("should load core fallback if language cannot be found", async () => {
241-
const dom = new JSDOM("", { runScripts: "outside-only" });
242-
dom.window.eval(translatorJsScriptContent);
243-
dom.window.translations = { en: "http://localhost:3000/translations/translation_test.json" };
244-
dom.window.Log = { log: jest.fn() };
245-
await new Promise((resolve) => dom.window.onload = resolve);
246-
247-
const { Translator } = dom.window;
214+
const window = await setupDOMEnvironment(translatorJsScriptContent);
215+
window.translations = { en: "http://localhost:3000/translations/translation_test.json" };
216+
const { Translator } = window;
248217
await Translator.loadCoreTranslations("MISSINGLANG");
249218

250219
const en = translationTestData;
@@ -258,13 +227,9 @@ describe("Translator", () => {
258227

259228
describe("loadCoreTranslationsFallback", () => {
260229
it("should load core translations fallback", async () => {
261-
const dom = new JSDOM("", { runScripts: "outside-only" });
262-
dom.window.eval(translatorJsScriptContent);
263-
dom.window.translations = { en: "http://localhost:3000/translations/translation_test.json" };
264-
dom.window.Log = { log: jest.fn() };
265-
await new Promise((resolve) => dom.window.onload = resolve);
266-
267-
const { Translator } = dom.window;
230+
const window = await setupDOMEnvironment(translatorJsScriptContent);
231+
window.translations = { en: "http://localhost:3000/translations/translation_test.json" };
232+
const { Translator } = window;
268233
await Translator.loadCoreTranslationsFallback();
269234

270235
const en = translationTestData;
@@ -275,14 +240,9 @@ describe("Translator", () => {
275240
});
276241

277242
it("should load core fallback if language cannot be found", async () => {
278-
const dom = new JSDOM("", { runScripts: "outside-only" });
279-
dom.window.eval(translatorJsScriptContent);
280-
dom.window.translations = {};
281-
dom.window.Log = { log: jest.fn() };
282-
283-
await new Promise((resolve) => dom.window.onload = resolve);
284-
285-
const { Translator } = dom.window;
243+
const window = await setupDOMEnvironment(translatorJsScriptContent);
244+
window.translations = {};
245+
const { Translator } = window;
286246
await Translator.loadCoreTranslations();
287247

288248
await new Promise((resolve) => setTimeout(resolve, 500));

0 commit comments

Comments
 (0)