Files
MagicMirror/tests/unit/classes/utils_spec.js
T
Veeck 4b4a59534f Release 2.37.0 (#4194)
## Release Notes
Thanks to: @angeldeejay, @egeekial, @khassel, @KristjanESPERANTO,
@MikeBishop, @rejas
> ⚠️ This release needs nodejs version >=22.21.1 <23 || >=24 (no change
to previous release)

[Compare to previous Release
v2.36.0](https://github.com/MagicMirrorOrg/MagicMirror/compare/v2.36.0...develop)


### [core]
- Prepare Release 2.37.0 (#4193)
- fix(electron): map IPv6 :: wildcard to localhost (#4188)
- refactor(main): modernize DOM update flow with async/await (#4186)
- refactor(main): simplify _updateDom with async/await (#4185)
- fix(security): prevent unauthorized secret expansion in socket
payloads (#4184)
- refactor(main): simplify updateDomWithContent async flow (#4182)
- fix: modules losing data after HTTP 304 responses (#4180)
- chore: add missing core defaults (#4181)
- fix(server): enforce ipWhitelist for Socket.IO too (#4169)
- feat(systeminfo): include Git hash and branch in system information
log (#4167)
- feat(electron): support object-based electronSwitches (#4161)
- systeminformation thread not ending: move error handling from utils to
app (#4160)
- fix systeminformation thread not ending (#4155)
- refactor: use ES module imports in browser core (#4158)
- refactor(core): remove old Object.assign polyfill (#4157)
- refactor: rewrite Module as an ES6 class (#4151)
- refactor: rewrite NodeHelper as an ES6 class (#4147)
- update eletron to v42 (#4144)
- refactor(utils): drop ajv dependency (#4142)
- fix(systeminformation): output right 'used node' version (from parent
process) (#4141)
- fix: skip postinstall git clean when not in a git repository (#4139)
- Remove unnecessary conditionals and fix falsy property check in
imperial conversion (#4135)
- update version in package.json

### [dependencies]
- update dependencies (#4191)
- Bump actions/checkout from 6 to 7 (#4190)
- chore: update dependencies and adjust import path for SunCalc (#4189)
- update dependencies incl. electron and revert
yauzl-electron-install-fix (#4183)
- update dependencies, add electron fix in package.json (#4175)
- chore: update dependencies (#4162)
- Bump actions/dependency-review-action from 4 to 5 (#4152)
- Unify linting: replace Stylelint and markdownlint with ESLint (#4148)
- update dependencies and workflows to node v26 (#4140)

### [modules/alert]
- CodeQL cleanup for alerts #18, #19, #20 (#4153)
- fix: resolve CodeQL alerts #24 and #26 (#4145)
- fix(electron): resolve CodeQL alerts #22 and #25 in electron.js
(#4136)

### [modules/calendar]
- perf(calendar): pre-filter ICS data before parsing (#4168)
- perf(calendar): use async ICS parsing to avoid blocking event loop
(#4143)

### [modules/newsfeed]
- [newsfeed] add allowBasicHtmlTags option for basic emphasis (#4176)

### [modules/updatenotification]
- fix(updatenotification): don't spawn a child process when running
under PM2 (#4166)
- fix(updatenotification): use process.argv[0] as restart binary (#4163)
- fix(updatenotification): preserve start mode on restart (#4156)
- fix(updatenotification): fix ref diff parsing for fetch --dry-run
(#4138)
- refactor(updatenotification): replace pm2 usage with node logic
(#4134)

### [modules/weather]
- feat(weather): add Buienradar provider (#4164)

### [testing]
- remove warning in unit tests (for nodejs >= v25) (#4149)
- polish HTTP 304 docs/test/handling (#4129)

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com>
Co-authored-by: BugHaver <43462320+bughaver@users.noreply.github.com>
Co-authored-by: BugHaver <43462320+lsaadeh@users.noreply.github.com>
Co-authored-by: Karsten Hassel <hassel@gmx.de>
Co-authored-by: Magnus <34011212+MagMar94@users.noreply.github.com>
Co-authored-by: Koen Konst <koenspero@gmail.com>
Co-authored-by: Koen Konst <c.h.konst@avisi.nl>
Co-authored-by: Bugsounet - Cédric <github@bugsounet.fr>
Co-authored-by: dathbe <github@beffa.us>
Co-authored-by: veeck <gitkraken@veeck.de>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Marcel <m-idler@users.noreply.github.com>
Co-authored-by: sam detweiler <sdetweil@gmail.com>
Co-authored-by: Kevin G. <crazylegstoo@gmail.com>
Co-authored-by: Jboucly <33218155+jboucly@users.noreply.github.com>
Co-authored-by: Jboucly <contact@jboucly.fr>
Co-authored-by: Jarno <54169345+jarnoml@users.noreply.github.com>
Co-authored-by: Jordan Welch <JordanHWelch@gmail.com>
Co-authored-by: Blackspirits <blackspirits@gmail.com>
Co-authored-by: Samed Ozdemir <samed@xsor.io>
Co-authored-by: in-voker <58696565+in-voker@users.noreply.github.com>
Co-authored-by: Andrés Vanegas Jiménez <142350+angeldeejay@users.noreply.github.com>
Co-authored-by: cgillinger <christian.gillinger@gmail.com>
Co-authored-by: Sonny B <43247590+sonnyb9@users.noreply.github.com>
Co-authored-by: sonnyb9 <sonnyb9@users.noreply.github.com>
Co-authored-by: Morgan McBee <egeekial@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Mike Bishop <mbishop@evequefou.be>
2026-07-01 22:01:42 +02:00

84 lines
2.3 KiB
JavaScript

const fs = require("node:fs");
const Log = require("../../../js/logger");
const { checkConfigFile, ConfigError } = require("../../../js/utils");
const createConfigObject = (modules) => ({
configFilename: "config.js",
configContentFull: "module.exports = { modules: [] };",
fullConf: { modules }
});
const runCheck = (modules) => {
checkConfigFile(createConfigObject(modules));
};
const expectExitForModules = (modules) => {
vi.spyOn(process, "exit").mockImplementation(() => {
throw new ConfigError("");
});
expect(() => {
runCheck(modules);
}).toThrow(ConfigError);
};
describe("utils", () => {
let originalReadFileSync;
beforeEach(() => {
originalReadFileSync = fs.readFileSync;
vi.spyOn(fs, "readFileSync").mockImplementation((fileName, ...args) => {
if (fileName === "index.html") {
return "<div class=\"region top_bar\"></div>\n<div class=\"region lower_third\"></div>";
}
return originalReadFileSync.call(fs, fileName, ...args);
});
vi.spyOn(fs, "writeFileSync").mockImplementation(() => {});
vi.spyOn(Log, "info").mockImplementation(() => {});
vi.spyOn(Log, "warn").mockImplementation(() => {});
vi.spyOn(Log, "error").mockImplementation(() => {});
});
afterEach(() => {
vi.restoreAllMocks();
});
it("accepts valid module entries", () => {
expect(() => {
runCheck([
{ module: "clock", position: "top_bar" },
{ module: "newsfeed" }
]);
}).not.toThrow();
expect(Log.error).not.toHaveBeenCalled();
});
it("exits when modules is not an array", () => {
expectExitForModules("not-an-array");
expect(Log.error).toHaveBeenCalledWith("This module configuration contains errors:\nmodules must be an array");
});
it("exits when module field is missing or not a string", () => {
expectExitForModules([{ module: 123, position: "top_bar" }]);
expect(Log.error).toHaveBeenCalled();
expect(Log.error.mock.calls[0][0]).toContain("module: must be a string");
});
it("warns for unknown positions without exiting", () => {
const exitSpy = vi.spyOn(process, "exit").mockImplementation(() => {
throw new ConfigError("");
});
expect(() => {
runCheck([{ module: "clock", position: "made_up_region" }]);
}).not.toThrow();
expect(exitSpy).not.toHaveBeenCalled();
expect(Log.warn).toHaveBeenCalled();
expect(Log.warn.mock.calls[0][0]).toContain("uses unknown position");
});
});