update electron to v40, update node versions in workflows (#4018)

- remove param `--enable-features=UseOzonePlatform` in start electron
tests (as we did already in `package.json`)
- update node versions in github workflows, remove `22.21.1`, add `25.x`
- fix formatting in tests
- update dependencies including electron to v40

This is still a draft PR because most calendar electron tests are not
running which is caused by the electron update from `v39.3.0` to
`v40.0.0`. Maybe @KristjanESPERANTO has an idea ...

---------

Co-authored-by: Kristjan ESPERANTO <35647502+KristjanESPERANTO@users.noreply.github.com>
This commit is contained in:
Karsten Hassel
2026-01-24 13:15:15 +01:00
committed by GitHub
parent 34913bfb9f
commit 5e0cd28980
23 changed files with 1188 additions and 1266 deletions

View File

@@ -42,7 +42,7 @@ jobs:
timeout-minutes: 30
strategy:
matrix:
node-version: [22.21.1, 22.x, 24.x]
node-version: [22.x, 24.x, 25.x]
steps:
- name: Install electron dependencies and labwc
run: |

View File

@@ -8,7 +8,7 @@ jobs:
runs-on: ubuntu-slim
strategy:
matrix:
node-version: [22.21.1, 22.x, 24.x]
node-version: [22.x, 24.x, 25.x]
steps:
- name: Checkout code
uses: actions/checkout@v6

View File

@@ -1,6 +1,6 @@
import {defineConfig, globalIgnores} from "eslint/config";
import { defineConfig, globalIgnores } from "eslint/config";
import globals from "globals";
import {flatConfigs as importX} from "eslint-plugin-import-x";
import { flatConfigs as importX } from "eslint-plugin-import-x";
import js from "@eslint/js";
import jsdocPlugin from "eslint-plugin-jsdoc";
import packageJson from "eslint-plugin-package-json";
@@ -24,26 +24,25 @@ export default defineConfig([
moment: "readonly"
}
},
plugins: {js, stylistic},
extends: [importX.recommended, "js/recommended", jsdocPlugin.configs["flat/recommended"], "stylistic/all"],
plugins: { js, stylistic },
extends: [importX.recommended, "js/recommended", jsdocPlugin.configs["flat/recommended"], stylistic.configs.customize({ indent: "tab", quotes: "double", semi: true, commaDangle: "never" })],
rules: {
"@stylistic/array-element-newline": ["error", "consistent"],
"@stylistic/arrow-parens": ["error", "always"],
"@stylistic/brace-style": "off",
"@stylistic/comma-dangle": ["error", "never"],
"@stylistic/dot-location": ["error", "property"],
"@stylistic/function-call-argument-newline": ["error", "consistent"],
"@stylistic/function-paren-newline": ["error", "consistent"],
"@stylistic/implicit-arrow-linebreak": ["error", "beside"],
"@stylistic/indent": ["error", "tab"],
"@stylistic/max-statements-per-line": ["error", {max: 2}],
"@stylistic/max-statements-per-line": ["error", { max: 2 }],
"@stylistic/multiline-comment-style": "off",
"@stylistic/multiline-ternary": ["error", "always-multiline"],
"@stylistic/newline-per-chained-call": ["error", {ignoreChainWithDepth: 4}],
"@stylistic/newline-per-chained-call": ["error", { ignoreChainWithDepth: 4 }],
"@stylistic/no-extra-parens": "off",
"@stylistic/no-tabs": "off",
"@stylistic/object-curly-spacing": ["error", "always"],
"@stylistic/object-property-newline": ["error", {allowAllPropertiesOnSameLine: true}],
"@stylistic/object-property-newline": ["error", { allowAllPropertiesOnSameLine: true }],
"@stylistic/operator-linebreak": ["error", "before"],
"@stylistic/padded-blocks": "off",
"@stylistic/quote-props": ["error", "as-needed"],
@@ -86,11 +85,11 @@ export default defineConfig([
"js/logger.js",
"tests/**/*.js"
],
rules: {"no-console": "error"}
rules: { "no-console": "error" }
},
{
files: ["**/package.json"],
plugins: {packageJson},
plugins: { packageJson },
extends: ["packageJson/recommended"]
},
{
@@ -102,15 +101,15 @@ export default defineConfig([
},
sourceType: "module"
},
plugins: {js, stylistic},
extends: [importX.recommended, "js/all", "stylistic/all"],
plugins: { js, stylistic },
extends: [importX.recommended, "js/all", stylistic.configs.customize({ indent: "tab", quotes: "double", semi: true, commaDangle: "never" })],
rules: {
"@stylistic/array-element-newline": "off",
"@stylistic/indent": ["error", "tab"],
"@stylistic/object-property-newline": ["error", {allowAllPropertiesOnSameLine: true}],
"@stylistic/object-property-newline": ["error", { allowAllPropertiesOnSameLine: true }],
"@stylistic/padded-blocks": ["error", "never"],
"@stylistic/quote-props": ["error", "as-needed"],
"import-x/no-unresolved": ["error", {ignore: ["eslint/config"]}],
"import-x/no-unresolved": ["error", { ignore: ["eslint/config"] }],
"max-lines-per-function": ["error", 100],
"no-magic-numbers": "off",
"one-var": ["error", "never"],
@@ -124,7 +123,7 @@ export default defineConfig([
...vitest.environments.env.globals
}
},
plugins: {vitest},
plugins: { vitest },
extends: [vitest.configs.recommended],
rules: {
"vitest/consistent-test-it": "error",
@@ -142,7 +141,7 @@ export default defineConfig([
]
}
],
"vitest/max-nested-describe": ["error", {max: 3}],
"vitest/max-nested-describe": ["error", { max: 3 }],
"vitest/prefer-to-be": "error",
"vitest/prefer-to-have-length": "error"
}

View File

@@ -190,7 +190,7 @@ Module.register("clock", {
}
sunWrapperInnerHTML += `<span><i class="fas fa-arrow-up" aria-hidden="true"></i> ${formatTime(this.config, sunTimes.sunrise)}</span>`
+ `<span><i class="fas fa-arrow-down" aria-hidden="true"></i> ${formatTime(this.config, sunTimes.sunset)}</span>`;
+ `<span><i class="fas fa-arrow-down" aria-hidden="true"></i> ${formatTime(this.config, sunTimes.sunset)}</span>`;
sunWrapper.innerHTML = sunWrapperInnerHTML;
digitalWrapper.appendChild(sunWrapper);
@@ -218,8 +218,8 @@ Module.register("clock", {
moonWrapper.innerHTML
= `<span class="${isVisible ? "bright" : ""}">${image} ${showFraction ? illuminatedFractionString : ""}</span>`
+ `<span><i class="fas fa-arrow-up" aria-hidden="true"></i> ${moonRise ? formatTime(this.config, moonRise) : "..."}</span>`
+ `<span><i class="fas fa-arrow-down" aria-hidden="true"></i> ${moonSet ? formatTime(this.config, moonSet) : "..."}</span>`;
+ `<span><i class="fas fa-arrow-up" aria-hidden="true"></i> ${moonRise ? formatTime(this.config, moonRise) : "..."}</span>`
+ `<span><i class="fas fa-arrow-down" aria-hidden="true"></i> ${moonSet ? formatTime(this.config, moonSet) : "..."}</span>`;
digitalWrapper.appendChild(moonWrapper);
}

2359
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -91,7 +91,7 @@
"feedme": "^2.0.2",
"helmet": "^8.1.0",
"html-to-text": "^9.0.5",
"iconv-lite": "^0.7.1",
"iconv-lite": "^0.7.2",
"ipaddr.js": "^2.3.0",
"moment": "^2.30.1",
"moment-timezone": "^0.6.0",
@@ -100,36 +100,36 @@
"pm2": "^6.0.14",
"socket.io": "^4.8.3",
"suncalc": "^1.9.0",
"systeminformation": "^5.30.1",
"undici": "^7.18.2",
"systeminformation": "^5.30.5",
"undici": "^7.19.0",
"weathericons": "^2.1.0"
},
"devDependencies": {
"@stylistic/eslint-plugin": "^5.6.1",
"@vitest/coverage-v8": "^4.0.16",
"@stylistic/eslint-plugin": "^5.7.1",
"@vitest/coverage-v8": "^4.0.18",
"@vitest/eslint-plugin": "^1.6.6",
"@vitest/ui": "^4.0.16",
"cspell": "^9.4.0",
"@vitest/ui": "^4.0.18",
"cspell": "^9.6.0",
"eslint-plugin-import-x": "^4.16.1",
"eslint-plugin-jsdoc": "^61.5.0",
"eslint-plugin-package-json": "^0.88.1",
"eslint-plugin-playwright": "^2.4.0",
"eslint-plugin-jsdoc": "^62.4.0",
"eslint-plugin-package-json": "^0.88.2",
"eslint-plugin-playwright": "^2.5.0",
"express-basic-auth": "^1.2.1",
"husky": "^9.1.7",
"jsdom": "^27.4.0",
"lint-staged": "^16.2.7",
"markdownlint-cli2": "^0.20.0",
"msw": "^2.12.7",
"playwright": "^1.57.0",
"prettier": "^3.7.4",
"playwright": "^1.58.0",
"prettier": "^3.8.1",
"prettier-plugin-jinja-template": "^2.1.0",
"stylelint": "^16.26.1",
"stylelint-config-standard": "^39.0.1",
"stylelint": "^17.0.0",
"stylelint-config-standard": "^40.0.0",
"stylelint-prettier": "^5.0.3",
"vitest": "^4.0.16"
"vitest": "^4.0.18"
},
"optionalDependencies": {
"electron": "^39.2.7"
"electron": "^40.0.0"
},
"engines": {
"node": ">=22.21.1 <23 || >=24"

View File

@@ -1,4 +1,3 @@
let config = {
address: "0.0.0.0",
ipWhitelist: [],

View File

@@ -10,6 +10,7 @@ describe("Custom Position of modules", () => {
await helpers.getDocument();
page = helpers.getPage();
});
afterAll(async () => {
await helpers.stopApplication();
await helpers.restoreIndex();

View File

@@ -9,6 +9,7 @@ describe("App environment", () => {
await helpers.getDocument();
page = helpers.getPage();
});
afterAll(async () => {
await helpers.stopApplication();
});

View File

@@ -16,6 +16,7 @@ describe("All font files from roboto.css should be downloadable", () => {
beforeAll(async () => {
await helpers.startApplication("tests/configs/without_modules.js");
});
afterAll(async () => {
await helpers.stopApplication();
});

View File

@@ -88,7 +88,6 @@ exports.getPage = () => {
return page;
};
exports.startApplication = async (configFilename, exec) => {
vi.resetModules();

View File

@@ -5,6 +5,7 @@ describe("ipWhitelist directive configuration", () => {
beforeAll(async () => {
await helpers.startApplication("tests/configs/noIpWhiteList.js");
});
afterAll(async () => {
await helpers.stopApplication();
});
@@ -20,6 +21,7 @@ describe("ipWhitelist directive configuration", () => {
beforeAll(async () => {
await helpers.startApplication("tests/configs/empty_ipWhiteList.js");
});
afterAll(async () => {
await helpers.stopApplication();
});

View File

@@ -104,6 +104,7 @@ describe("Compliments module", () => {
await helpers.getDocument();
page = helpers.getPage();
});
it("shows 'Remote compliment file works!' as only anytime list set", async () => {
//await helpers.startApplication("tests/configs/modules/compliments/compliments_file.js", "01 Jan 2022 10:00:00 GMT");
await doTest(["Remote compliment file works!"]);
@@ -119,6 +120,7 @@ describe("Compliments module", () => {
await helpers.getDocument();
page = helpers.getPage();
});
it("shows 'test in morning' as test time set to 10am", async () => {
//await helpers.startApplication("tests/configs/modules/compliments/compliments_file_change.js", "01 Jan 2022 10:00:00 GMT");
await doTest(["Remote compliment file works!"]);

View File

@@ -9,6 +9,7 @@ describe("Display of modules", () => {
await helpers.getDocument();
page = helpers.getPage();
});
afterAll(async () => {
await helpers.stopApplication();
});

View File

@@ -9,6 +9,7 @@ describe("Check configuration without modules", () => {
await helpers.getDocument();
page = helpers.getPage();
});
afterAll(async () => {
await helpers.stopApplication();
});

View File

@@ -7,6 +7,7 @@ describe("Position of modules", () => {
await helpers.startApplication("tests/configs/modules/positions.js");
await helpers.getDocument();
});
afterAll(async () => {
await helpers.stopApplication();
});

View File

@@ -5,6 +5,7 @@ describe("port directive configuration", () => {
beforeAll(async () => {
await helpers.startApplication("tests/configs/port_8090.js");
});
afterAll(async () => {
await helpers.stopApplication();
});
@@ -20,6 +21,7 @@ describe("port directive configuration", () => {
beforeAll(async () => {
await helpers.startApplication("tests/configs/port_8090.js", (process.env.MM_PORT = 8100));
});
afterAll(async () => {
await helpers.stopApplication();
});

View File

@@ -20,6 +20,7 @@ describe("App environment", () => {
// we have to wait until the server is started
await delay(2000);
});
afterAll(async () => {
await process.kill(-serverProcess.pid);
});

View File

@@ -5,6 +5,7 @@ describe("templated config with port variable", () => {
beforeAll(async () => {
await helpers.startApplication("tests/configs/port_variable.js");
});
afterAll(async () => {
await helpers.stopApplication();
try {

View File

@@ -4,6 +4,7 @@ describe("Vendors", () => {
beforeAll(async () => {
await helpers.startApplication("tests/configs/default.js");
});
afterAll(async () => {
await helpers.stopApplication();
});

View File

@@ -15,7 +15,7 @@ exports.startApplication = async (configFilename, systemDate = null, electronPar
// check environment for DISPLAY or WAYLAND_DISPLAY
if (process.env.WAYLAND_DISPLAY) {
electronParams.unshift("js/electron.js", "--enable-features=UseOzonePlatform", "--ozone-platform=wayland");
electronParams.unshift("js/electron.js", "--ozone-platform=wayland");
} else {
electronParams.unshift("js/electron.js");
}

View File

@@ -440,4 +440,3 @@ describe("fetch() method", () => {
expect(errorInfo.errorType).toBe("NETWORK_ERROR");
});
});

View File

@@ -1,4 +1,4 @@
import {defineConfig} from "vitest/config";
import { defineConfig } from "vitest/config";
/*
* Sequential execution keeps our shared test server stable: