Skip to content

Commit ecd87c4

Browse files
[tests] Review and refactor translation tests
1 parent 6501aab commit ecd87c4

File tree

3 files changed

+260
-275
lines changed

3 files changed

+260
-275
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ planned for 2025-07-01
3838
- Removed as many of the date conversions as possible
3939
- Use `moment-timezone` when calculating recurring events, this will fix problems from the past with offsets and DST not being handled properly
4040
- Added some tests to test the behavior of the refactored methods to make sure the correct event dates are returned
41-
- [linter] Enable ESLint rule `no-console` and replace `console` with `Log` in some files
41+
- [linter] Enable ESLint rule `no-console` and replace `console` with `Log` in some files (#3810)
42+
- [tests] Review and refactor translation tests (#3792)
4243

4344
### Fixed
4445

tests/e2e/translations_spec.js

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

9-
describe("Translations", () => {
9+
describe("translations", () => {
1010
let server;
1111

1212
beforeAll(() => {
@@ -26,8 +26,9 @@ describe("Translations", () => {
2626
});
2727

2828
it("should have a translation file in the specified path", () => {
29-
for (let language in translations) {
29+
for (const language in translations) {
3030
const file = fs.statSync(translations[language]);
31+
3132
expect(file.isFile()).toBe(true);
3233
}
3334
});
@@ -36,90 +37,91 @@ describe("Translations", () => {
3637
let dom;
3738

3839
beforeEach(() => {
39-
dom = new JSDOM(
40-
`<script>var Translator = {}; var Log = {log: () => {}}; var config = {language: 'de'};</script>\
41-
<script src="file://${path.join(__dirname, "..", "..", "js", "class.js")}"></script>\
42-
<script src="file://${path.join(__dirname, "..", "..", "js", "module.js")}"></script>`,
43-
{ runScripts: "dangerously", resources: "usable" }
44-
);
40+
// Create a new JSDOM instance for each test
41+
dom = new JSDOM("", { runScripts: "dangerously", resources: "usable" });
42+
43+
// Mock the necessary global objects
44+
dom.window.Log = { log: jest.fn(), error: jest.fn() };
45+
dom.window.Translator = {};
46+
dom.window.config = { language: "de" };
47+
48+
// Load class.js and module.js content directly
49+
const classJs = fs.readFileSync(path.join(__dirname, "..", "..", "js", "class.js"), "utf-8");
50+
const moduleJs = fs.readFileSync(path.join(__dirname, "..", "..", "js", "module.js"), "utf-8");
51+
52+
// Execute the scripts in the JSDOM context
53+
dom.window.eval(classJs);
54+
dom.window.eval(moduleJs);
4555
});
4656

47-
it("should load translation file", () => {
48-
return new Promise((done) => {
49-
dom.window.onload = async () => {
50-
const { Translator, Module, config } = dom.window;
51-
config.language = "en";
52-
Translator.load = sinon.stub().callsFake((_m, _f, _fb) => null);
57+
it("should load translation file", async () => {
58+
await new Promise((resolve) => {
59+
dom.window.onload = resolve;
60+
});
5361

54-
Module.register("name", { getTranslations: () => translations });
55-
const MMM = Module.create("name");
62+
const { Translator, Module, config } = dom.window;
63+
config.language = "en";
64+
Translator.load = sinon.stub().callsFake((_m, _f, _fb) => null);
5665

57-
await MMM.loadTranslations();
66+
Module.register("name", { getTranslations: () => translations });
67+
const MMM = Module.create("name");
5868

59-
expect(Translator.load.args).toHaveLength(1);
60-
expect(Translator.load.calledWith(MMM, "translations/en.json", false)).toBe(true);
69+
await MMM.loadTranslations();
6170

62-
done();
63-
};
64-
});
71+
expect(Translator.load.args).toHaveLength(1);
72+
expect(Translator.load.calledWith(MMM, "translations/en.json", false)).toBe(true);
6573
});
6674

67-
it("should load translation + fallback file", () => {
68-
return new Promise((done) => {
69-
dom.window.onload = async () => {
70-
const { Translator, Module } = dom.window;
71-
Translator.load = sinon.stub().callsFake((_m, _f, _fb) => null);
75+
it("should load translation + fallback file", async () => {
76+
await new Promise((resolve) => {
77+
dom.window.onload = resolve;
78+
});
7279

73-
Module.register("name", { getTranslations: () => translations });
74-
const MMM = Module.create("name");
80+
const { Translator, Module } = dom.window;
81+
Translator.load = sinon.stub().callsFake((_m, _f, _fb) => null);
7582

76-
await MMM.loadTranslations();
83+
Module.register("name", { getTranslations: () => translations });
84+
const MMM = Module.create("name");
7785

78-
expect(Translator.load.args).toHaveLength(2);
79-
expect(Translator.load.calledWith(MMM, "translations/de.json", false)).toBe(true);
80-
expect(Translator.load.calledWith(MMM, "translations/en.json", true)).toBe(true);
86+
await MMM.loadTranslations();
8187

82-
done();
83-
};
84-
});
88+
expect(Translator.load.args).toHaveLength(2);
89+
expect(Translator.load.calledWith(MMM, "translations/de.json", false)).toBe(true);
90+
expect(Translator.load.calledWith(MMM, "translations/en.json", true)).toBe(true);
8591
});
8692

87-
it("should load translation fallback file", () => {
88-
return new Promise((done) => {
89-
dom.window.onload = async () => {
90-
const { Translator, Module, config } = dom.window;
91-
config.language = "--";
92-
Translator.load = sinon.stub().callsFake((_m, _f, _fb) => null);
93+
it("should load translation fallback file", async () => {
94+
await new Promise((resolve) => {
95+
dom.window.onload = resolve;
96+
});
9397

94-
Module.register("name", { getTranslations: () => translations });
95-
const MMM = Module.create("name");
98+
const { Translator, Module, config } = dom.window;
99+
config.language = "--";
100+
Translator.load = sinon.stub().callsFake((_m, _f, _fb) => null);
96101

97-
await MMM.loadTranslations();
102+
Module.register("name", { getTranslations: () => translations });
103+
const MMM = Module.create("name");
98104

99-
expect(Translator.load.args).toHaveLength(1);
100-
expect(Translator.load.calledWith(MMM, "translations/en.json", true)).toBe(true);
105+
await MMM.loadTranslations();
101106

102-
done();
103-
};
104-
});
107+
expect(Translator.load.args).toHaveLength(1);
108+
expect(Translator.load.calledWith(MMM, "translations/en.json", true)).toBe(true);
105109
});
106110

107-
it("should load no file", () => {
108-
return new Promise((done) => {
109-
dom.window.onload = async () => {
110-
const { Translator, Module } = dom.window;
111-
Translator.load = sinon.stub();
111+
it("should load no file", async () => {
112+
await new Promise((resolve) => {
113+
dom.window.onload = resolve;
114+
});
112115

113-
Module.register("name", {});
114-
const MMM = Module.create("name");
116+
const { Translator, Module } = dom.window;
117+
Translator.load = sinon.stub();
115118

116-
await MMM.loadTranslations();
119+
Module.register("name", {});
120+
const MMM = Module.create("name");
117121

118-
expect(Translator.load.callCount).toBe(0);
122+
await MMM.loadTranslations();
119123

120-
done();
121-
};
122-
});
124+
expect(Translator.load.callCount).toBe(0);
123125
});
124126
});
125127

@@ -130,29 +132,30 @@ describe("Translations", () => {
130132
}
131133
};
132134

133-
describe("Parsing language files through the Translator class", () => {
134-
for (let language in translations) {
135-
it(`should parse ${language}`, () => {
136-
return new Promise((done) => {
137-
const dom = new JSDOM(
138-
`<script>var translations = ${JSON.stringify(translations)}; var Log = {log: () => {}};</script>\
139-
<script src="file://${path.join(__dirname, "..", "..", "js", "translator.js")}">`,
140-
{ runScripts: "dangerously", resources: "usable" }
141-
);
142-
dom.window.onload = async () => {
143-
const { Translator } = dom.window;
144-
145-
await Translator.load(mmm, translations[language], false);
146-
expect(typeof Translator.translations[mmm.name]).toBe("object");
147-
expect(Object.keys(Translator.translations[mmm.name]).length).toBeGreaterThanOrEqual(1);
148-
done();
149-
};
135+
const translatorJs = fs.readFileSync(path.join(__dirname, "..", "..", "js", "translator.js"), "utf-8");
136+
137+
describe("parsing language files through the Translator class", () => {
138+
for (const language in translations) {
139+
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);
144+
145+
await new Promise((resolve) => {
146+
dom.window.onload = resolve;
150147
});
148+
149+
const { Translator } = dom.window;
150+
await Translator.load(mmm, translations[language], false);
151+
152+
expect(typeof Translator.translations[mmm.name]).toBe("object");
153+
expect(Object.keys(Translator.translations[mmm.name]).length).toBeGreaterThanOrEqual(1);
151154
});
152155
}
153156
});
154157

155-
describe("Same keys", () => {
158+
describe("same keys", () => {
156159
let base;
157160

158161
// Some expressions are not easy to translate automatically. For the sake of a working test, we filter them out.
@@ -178,7 +181,6 @@ describe("Translations", () => {
178181
const dom = new JSDOM("", { runScripts: "dangerously", resources: "usable" });
179182
dom.window.Log = { log: jest.fn() };
180183
dom.window.translations = translations;
181-
const translatorJs = fs.readFileSync(path.join(__dirname, "..", "..", "js", "translator.js"), "utf-8");
182184
dom.window.eval(translatorJs);
183185

184186
return new Promise((resolve) => {

0 commit comments

Comments
 (0)