Skip to content

Commit b137a93

Browse files
Merge branch 'develop' into update-subclass-language-use-override
2 parents b7d9ada + 462abf7 commit b137a93

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+6489
-7592
lines changed

.github/CONTRIBUTING.md

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,19 @@ To run markdownlint, use `node --run lint:markdown`.
3030

3131
## Testing
3232

33-
We use [Jest](https://jestjs.io) for JavaScript testing.
33+
We use [Vitest](https://vitest.dev) for JavaScript testing.
3434

3535
To run all tests, use `node --run test`.
3636

37-
The specific test commands are defined in `package.json`.
38-
So you can also run the specific tests with other commands, e.g. `node --run test:unit` or `npx jest tests/e2e/env_spec.js`.
37+
The `package.json` scripts expose finer-grained test commands:
38+
39+
- `test:unit` – run unit tests only
40+
- `test:e2e` – execute browser-driven end-to-end tests
41+
- `test:electron` – launch the Electron-based regression suite
42+
- `test:coverage` – collect coverage while running every suite
43+
- `test:watch` – keep Vitest in watch mode for fast local feedback
44+
- `test:ui` – open the Vitest UI dashboard (needs OS file-watch support enabled)
45+
- `test:calendar` – run the legacy calendar debug helper
46+
- `test:css`, `test:markdown`, `test:prettier`, `test:spelling`, `test:js` – lint-only scripts that enforce formatting, spelling, markdown style, and ESLint.
47+
48+
You can invoke any script with `node --run <script>` (or `npm run <script>`). Individual files can still be targeted directly, e.g. `npx vitest run tests/e2e/env_spec.js`.

.github/workflows/automated-tests.yaml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
- name: "Checkout code"
2121
uses: actions/checkout@v5
2222
- name: "Use Node.js"
23-
uses: actions/setup-node@v5
23+
uses: actions/setup-node@v6
2424
with:
2525
node-version: lts/*
2626
cache: "npm"
@@ -38,7 +38,7 @@ jobs:
3838
timeout-minutes: 30
3939
strategy:
4040
matrix:
41-
node-version: [22.18.0, 22.x, 24.x]
41+
node-version: [22.20.0, 22.x, 24.x]
4242
steps:
4343
- name: Install electron dependencies and labwc
4444
run: |
@@ -47,7 +47,7 @@ jobs:
4747
- name: "Checkout code"
4848
uses: actions/checkout@v5
4949
- name: "Use Node.js ${{ matrix.node-version }}"
50-
uses: actions/setup-node@v5
50+
uses: actions/setup-node@v6
5151
with:
5252
node-version: ${{ matrix.node-version }}
5353
check-latest: true

.github/workflows/electron-rebuild.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ jobs:
88
runs-on: ubuntu-latest
99
strategy:
1010
matrix:
11-
node-version: [22.18.0, 22.x, 24.x]
11+
node-version: [22.20.0, 22.x, 24.x]
1212
steps:
1313
- name: Checkout code
1414
uses: actions/checkout@v5
1515
- name: "Use Node.js ${{ matrix.node-version }}"
16-
uses: actions/setup-node@v5
16+
uses: actions/setup-node@v6
1717
with:
1818
node-version: ${{ matrix.node-version }}
1919
check-latest: true

.github/workflows/spellcheck.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
with:
2020
ref: develop
2121
- name: Set up Node.js
22-
uses: actions/setup-node@v5
22+
uses: actions/setup-node@v6
2323
with:
2424
node-version: lts/*
2525
check-latest: true

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,3 +88,6 @@ js/positions.js
8888
# Ignore lock files other than package-lock.json
8989
pnpm-lock.yaml
9090
yarn.lock
91+
92+
# Vitest temporary test files
93+
tests/**/.tmp/

CHANGELOG.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,29 @@ planned for 2026-01-01
1313

1414
### Added
1515

16+
- [weather] feat: add configurable forecast date format option (#3918)
17+
- [core] Add new `server:watch` script to run MagicMirror² server-only with automatic restarts when files (defined in `config.watchTargets`) change (#3920)
18+
1619
### Changed
1720

1821
- [core] refactor: replace `module-alias` dependency with internal alias resolver (#3893)
22+
- [check_config] refactor: improve error handling (#3927)
23+
- [calendar] test: remove "Recurring event per timezone" test (#3929)
24+
- [calendar] chore: remove `requiresVersion: "2.1.0"` (#3932)
25+
- [tests] migrate from `jest` to `vitest` (#3940)
1926

2027
### Fixed
2128

2229
- feat: add ESlint rule `no-sparse-arrays` for config check to fix #3910 (#3911)
2330
- fixed eslint warnings shown in #3911 and updated npm publish docs (#3913)
31+
- [core] refactor: replace `express-ipfilter` with lightweight custom middleware (#3917) - This fixes security issue [CVE-2023-42282](https://github.com/advisories/GHSA-78xj-cgh5-2h22), which is not very likely to be exploitable in MagicMirror² setups, but still should be fixed.
32+
- fixed the Environment Canada weather URL (#3912) and now converts a windspeed of 'calm' to 0
33+
- fixed problems with daylight-saving-time in weather provider `openmeto` (#3930, #3931)
2434

2535
### Updated
2636

27-
- [core] Update dependencies (#3909)
37+
- [core] Update dependencies (#3909, #3916, #3921, #3925, #3934)
38+
- [logger] Add prefixes to most Log messages (#3923, #3926)
2839

2940
## [2.33.0] - 2025-10-01
3041

@@ -355,7 +366,7 @@ For more info, please read the following post: [A New Chapter for MagicMirror: T
355366
### Fixed
356367

357368
- [weather] Correct apiBase of weathergov weatherProvider to match documentation (#2926)
358-
- Worked around several issues in the RRULE library that were causing deleted calender events to still show, some
369+
- Worked around several issues in the RRULE library that were causing deleted calendar events to still show, some
359370
initial and recurring events to not show, and some event times to be off an hour. (#3291)
360371
- Skip changelog requirement when running tests for dependency updates (#3320)
361372
- Display precipitation probability when it is 0% instead of blank/empty (#3345)

Collaboration.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Are done by
3636
- [ ] test `prep-release` branch
3737
- [ ] update `CHANGELOG.md`
3838
- [ ] add all contributor names: `...`
39-
- [ ] add min. node version: > ⚠️ This release needs nodejs version `v22.18.0` or higher
39+
- [ ] add min. node version: > ⚠️ This release needs nodejs version `v22.20.0` or higher
4040
- [ ] check release link at the bottom of the file
4141
- [ ] commit and push all changes
4242
- [ ] create pull request from `prep-release` to `develop` branch with title `Prepare Release 2.xx.0`

eslint.config.mjs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import {defineConfig, globalIgnores} from "eslint/config";
22
import globals from "globals";
33
import {flatConfigs as importX} from "eslint-plugin-import-x";
4-
import jest from "eslint-plugin-jest";
54
import js from "@eslint/js";
65
import jsdocPlugin from "eslint-plugin-jsdoc";
76
import packageJson from "eslint-plugin-package-json";
87
import stylistic from "@stylistic/eslint-plugin";
8+
import vitest from "eslint-plugin-vitest";
99

1010
export default defineConfig([
1111
globalIgnores(["config/**", "modules/**/*", "!modules/default/**", "js/positions.js"]),
@@ -16,15 +16,16 @@ export default defineConfig([
1616
globals: {
1717
...globals.browser,
1818
...globals.node,
19+
...vitest.environments.env.globals,
1920
Log: "readonly",
2021
MM: "readonly",
2122
Module: "readonly",
2223
config: "readonly",
2324
moment: "readonly"
2425
}
2526
},
26-
plugins: {js, stylistic},
27-
extends: [importX.recommended, jest.configs["flat/recommended"], "js/recommended", jsdocPlugin.configs["flat/recommended"], "stylistic/all"],
27+
plugins: {js, stylistic, vitest},
28+
extends: [importX.recommended, vitest.configs.recommended, "js/recommended", jsdocPlugin.configs["flat/recommended"], "stylistic/all"],
2829
rules: {
2930
"@stylistic/array-element-newline": ["error", "consistent"],
3031
"@stylistic/arrow-parens": ["error", "always"],
@@ -57,12 +58,9 @@ export default defineConfig([
5758
"import-x/newline-after-import": "error",
5859
"import-x/order": "error",
5960
"init-declarations": "off",
60-
"jest/consistent-test-it": "warn",
61-
"jest/no-done-callback": "warn",
62-
"jest/prefer-expect-resolves": "warn",
63-
"jest/prefer-mock-promise-shorthand": "warn",
64-
"jest/prefer-to-be": "warn",
65-
"jest/prefer-to-have-length": "warn",
61+
"vitest/consistent-test-it": "warn",
62+
"vitest/prefer-to-be": "warn",
63+
"vitest/prefer-to-have-length": "warn",
6664
"max-lines-per-function": ["warn", 400],
6765
"max-statements": "off",
6866
"no-global-assign": "off",

js/animateCSS.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ function addAnimateCSS (element, animation, animationTime) {
132132
const node = document.getElementById(element);
133133
if (!node) {
134134
// don't execute animate: we don't find div
135-
Log.warn("addAnimateCSS: node not found for", element);
135+
Log.warn("node not found for adding", element);
136136
return;
137137
}
138138
node.style.setProperty("--animate-duration", `${animationTime}s`);
@@ -149,7 +149,7 @@ function removeAnimateCSS (element, animation) {
149149
const node = document.getElementById(element);
150150
if (!node) {
151151
// don't execute animate: we don't find div
152-
Log.warn("removeAnimateCSS: node not found for", element);
152+
Log.warn("node not found for removing", element);
153153
return;
154154
}
155155
node.classList.remove("animate__animated", animationName);

js/app.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const Utils = require(`${__dirname}/utils`);
1515
const defaultModules = require(`${global.root_path}/modules/default/defaultmodules`);
1616
// used to control fetch timeout for node_helpers
1717
const { setGlobalDispatcher, Agent } = require("undici");
18-
const { getEnvVarsAsObj } = require("#server_functions");
18+
const { getEnvVarsAsObj, getConfigFilePath } = require("#server_functions");
1919
// common timeout value, provide environment override in case
2020
const fetch_timeout = process.env.mmFetchTimeout !== undefined ? process.env.mmFetchTimeout : 30000;
2121

@@ -65,14 +65,14 @@ function App () {
6565
async function loadConfig () {
6666
Log.log("Loading config ...");
6767
const defaults = require(`${__dirname}/defaults`);
68-
if (process.env.JEST_WORKER_ID !== undefined) {
69-
// if we are running with jest
68+
if (global.mmTestMode) {
69+
// if we are running in test mode
7070
defaults.address = "0.0.0.0";
7171
}
7272

7373
// For this check proposed to TestSuite
7474
// https://forum.magicmirror.builders/topic/1456/test-suite-for-magicmirror/8
75-
const configFilename = path.resolve(global.configuration_file || `${global.root_path}/config/config.js`);
75+
const configFilename = getConfigFilePath();
7676
let templateFile = `${configFilename}.template`;
7777

7878
// check if templateFile exists
@@ -185,10 +185,10 @@ function App () {
185185

186186
if (defaultModules.includes(moduleName)) {
187187
const defaultModuleFolder = path.resolve(`${global.root_path}/modules/default/`, module);
188-
if (process.env.JEST_WORKER_ID === undefined) {
188+
if (!global.mmTestMode) {
189189
moduleFolder = defaultModuleFolder;
190190
} else {
191-
// running in Jest, allow defaultModules placed under moduleDir for testing
191+
// running in test mode, allow defaultModules placed under moduleDir for testing
192192
if (env.modulesDir === "modules" || env.modulesDir === "tests/mocks") {
193193
moduleFolder = defaultModuleFolder;
194194
}

0 commit comments

Comments
 (0)