Skip to content

Commit 2030f21

Browse files
committed
Add Electron test runner
- add Node/Electron test runner scripts with runtime version logging - update npm scripts and .npmignore to use new runners - run Electron tests on Ubuntu CI (AppArmor tweak + xvfb) - clarify README testing section for Node vs Electron suites
1 parent 193f5b8 commit 2030f21

9 files changed

Lines changed: 101 additions & 2 deletions

File tree

.github/workflows/test.yml

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,17 @@ jobs:
3030

3131
- name: Install
3232
run: npm install
33-
33+
3434
- name: Test
3535
run: npm test
36+
37+
# https://github.com/electron/electron/issues/42510#issuecomment-2171583086
38+
- name: Disable AppArmor restriction
39+
if: matrix.os == 'ubuntu-latest'
40+
run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0
41+
42+
- name: Test Electron
43+
if: matrix.os == 'ubuntu-latest' && matrix.node == '18'
44+
uses: GabrielBB/xvfb-action@v1
45+
with:
46+
run: npm run test-electron

.npmignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
.github/
22
.vscode/
33
test/
4+
scripts/
45
build/
56
.clang-format
67
.gitignore

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,11 @@ s7server.on('readWrite', (sender, operation, tag, buffer, done) => {
127127
s7server.StartTo('127.0.0.1');
128128
```
129129

130+
## Testing
131+
- Run Node.js tests (Node runtime): `npm test`
132+
- Run the same suite inside Electron's Node runtime: `npm run test-electron`
133+
On headless CI, wrap with `xvfb-run npm run test-electron`.
134+
130135
## License & copyright
131136
Copyright (c) 2025, Mathias Küsel
132137

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
"node-gyp-build": "~4.8.4"
3939
},
4040
"devDependencies": {
41+
"electron": "^30.0.0",
4142
"node-addon-api": "~8.5.0",
4243
"node-gyp": "^12.1.0",
4344
"prebuildify": "^6.0.1",
@@ -48,7 +49,8 @@
4849
"install": "node-gyp-build",
4950
"rebuild": "npm run install --build-from-source",
5051
"prebuild": "prebuildify -t 18.20.8 --napi --strip",
51-
"test": "node --test --test-concurrency=1",
52+
"test": "node ./scripts/run-node-tests.js",
53+
"test-electron": "node ./scripts/run-electron-tests.js",
5254
"download-prebuilds": "prebuildify-ci download",
5355
"prebuild-linux-arm": "prebuildify-cross -i linux-armv6 -i linux-armv7 -i linux-arm64-lts -t 18.20.8 --napi --strip",
5456
"prebuild-android-arm": "prebuildify-cross -i android-armv7 -i android-arm64 -t 18.20.8 --napi --strip",

scripts/run-electron-tests.js

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
const { spawn, spawnSync } = require('child_process');
2+
const electronBinary = require('electron');
3+
const os = require('os');
4+
5+
function getElectronProcessVersions() {
6+
try {
7+
const result = spawnSync(
8+
electronBinary,
9+
['-e', 'console.log(JSON.stringify(process.versions))'],
10+
{
11+
env: { ...process.env, ELECTRON_RUN_AS_NODE: '1' },
12+
encoding: 'utf8'
13+
}
14+
);
15+
if (result.status === 0 && result.stdout) {
16+
return JSON.parse(result.stdout.trim());
17+
}
18+
} catch {
19+
// ignore and fall back to empty object
20+
}
21+
return {};
22+
}
23+
24+
const electronVersions = getElectronProcessVersions();
25+
const electronNode = electronVersions.node || 'unknown';
26+
const electronChrome = electronVersions.chrome || 'unknown';
27+
const electronV8 = electronVersions.v8 || 'unknown';
28+
const electronNapi = electronVersions.napi || 'unknown';
29+
const electronVersion = electronVersions.electron || 'unknown';
30+
31+
console.log(
32+
`[electron-tests] electron ${electronVersion} (node ${electronNode}, chrome ${electronChrome}, v8 ${electronV8}, napi ${electronNapi}); runner node ${process.version} (v8 ${process.versions.v8}, napi ${process.versions.napi})${os.EOL}`
33+
);
34+
35+
// Use Electron's embedded Node to run the Node.js test runner on the collected files.
36+
// Keep concurrency at 1 to avoid port collisions in integration tests.
37+
const child = spawn(
38+
electronBinary,
39+
['--test', '--test-concurrency=1'],
40+
{
41+
stdio: 'inherit',
42+
env: {
43+
...process.env,
44+
ELECTRON_RUN_AS_NODE: '1'
45+
}
46+
}
47+
);
48+
49+
child.on('exit', code => {
50+
process.exit(code);
51+
});
52+
53+
child.on('error', err => {
54+
console.error('Failed to start Electron for tests:', err);
55+
process.exit(1);
56+
});

scripts/run-node-tests.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
const { spawn } = require('child_process');
2+
const os = require('os');
3+
4+
console.log(
5+
`[node-tests] node ${process.version} (v8 ${process.versions.v8}, napi ${process.versions.napi})${os.EOL}`
6+
);
7+
8+
const child = spawn(
9+
process.execPath,
10+
['--test', '--test-concurrency=1'],
11+
{
12+
stdio: 'inherit',
13+
env: process.env
14+
}
15+
);
16+
17+
child.on('exit', code => {
18+
process.exit(code);
19+
});
20+
21+
child.on('error', err => {
22+
console.error('Failed to start Node tests:', err);
23+
process.exit(1);
24+
});
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)