Skip to content

Commit 899be47

Browse files
committed
Run tests on GJS
1 parent 7ddbca1 commit 899be47

7 files changed

Lines changed: 198 additions & 3 deletions

File tree

.github/workflows/ci.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,13 @@ jobs:
4848
- run: npm run ci
4949
env:
5050
JASMINE_BROWSER: safari
51+
52+
test-gjs:
53+
runs-on: ubuntu-24.04
54+
timeout-minutes: 10
55+
steps:
56+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
57+
- run: sudo apt-get update
58+
- run: sudo apt-get install -y gjs
59+
- run: npm ci
60+
- run: npm run test:gjs

eslint.config.mjs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,11 @@ export default defineConfig([{
5454
"no-console": "error",
5555
},
5656
}], [{
57-
files: ["scripts/lib/structuredClone.rollup.js"],
57+
files: [
58+
"scripts/lib/structuredClone.rollup.js",
59+
"spec/helpers/gjsDefineJasmineUnderTest.js",
60+
"scripts/runSpecsInGJS.js",
61+
],
5862
languageOptions: {
5963
sourceType: "module",
6064
}

lib/jasmine-core/jasmine.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const getJasmineRequireObj = (function() {
3737
jasmineRequire = exports;
3838
} else {
3939
// Browser
40-
jasmineRequire = {};
40+
jasmineRequire = globalThis.getJasmineRequireObj?.() ?? {};
4141
}
4242

4343
function getJasmineRequire() {

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
"lint": "eslint \"src/**/*.js\" \"spec/**/*.js\" && prettier --check \"src/**/*.js\" \"spec/**/*.js\"",
1818
"test": "node scripts/runSpecsInNode.js && npm run lint",
1919
"test:parallel": "node scripts/runSpecsInParallel.js",
20+
"test:gjs": "gjs -m scripts/runSpecsInGJS.js",
2021
"cleanup": "prettier --write \"src/**/*.js\" \"spec/**/*.js\"",
2122
"build": "node scripts/buildDistribution.js",
2223
"buildStandaloneDist": "node scripts/buildStandaloneDist.js",

scripts/runSpecsInGJS.js

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
#!/usr/bin/env -S gjs -m
2+
3+
import GLib from 'gi://GLib';
4+
import Gio from 'gi://Gio';
5+
import System from 'system';
6+
7+
import '../lib/jasmine-core/jasmine.js';
8+
9+
class Reporter {
10+
jasmineStarted(suiteInfo) {
11+
console.log('Started', JSON.stringify(suiteInfo, null, 2));
12+
}
13+
14+
jasmineDone(suiteInfo) {
15+
if (suiteInfo.overallStatus === 'passed' && !suiteInfo.failedExpectations?.length)
16+
console.log(suiteInfo.overallStatus, JSON.stringify(suiteInfo, null, 2));
17+
else
18+
console.warn(suiteInfo.overallStatus, JSON.stringify(suiteInfo, null, 2));
19+
}
20+
21+
suiteStarted(result) {
22+
console.info('Suite started', JSON.stringify(result, null, 2));
23+
}
24+
25+
suiteDone(result) {
26+
if (result.status === 'passed')
27+
console.info('Suite', result.status, JSON.stringify(result, null, 2));
28+
else
29+
console.warn('Suite', result.status, JSON.stringify(result, null, 2));
30+
}
31+
32+
specStarted(result) {
33+
console.info('Spec started', JSON.stringify(result, null, 2));
34+
}
35+
36+
specDone(result) {
37+
if (result.status === 'passed')
38+
console.info('Spec', result.status, JSON.stringify(result, null, 2));
39+
else
40+
console.warn('Spec', result.status, JSON.stringify(result, null, 2));
41+
}
42+
}
43+
44+
const app = new Gio.Application();
45+
46+
const helpers = [
47+
'../spec/helpers/init.js',
48+
'../spec/helpers/integrationMatchers.js',
49+
'../spec/helpers/callerFilenameShim.js',
50+
'../spec/helpers/monkeyPatchingSpecs.js',
51+
'../spec/helpers/gjsDefineJasmineUnderTest.js',
52+
'../spec/helpers/resetEnv.js',
53+
];
54+
55+
function* collectFiles(directory) {
56+
const enumerator = directory.enumerate_children(
57+
'standard::*',
58+
Gio.FileQueryInfoFlags.NONE,
59+
null
60+
);
61+
62+
let info;
63+
while ((info = enumerator.next_file(null))) {
64+
const file = enumerator.get_child(info);
65+
66+
if (info.get_file_type() === Gio.FileType.DIRECTORY) {
67+
yield* collectFiles(file);
68+
} else {
69+
if (/[Ss]pec\.js$/.test(file.get_path())) {
70+
yield file;
71+
}
72+
}
73+
}
74+
}
75+
76+
const specUri = GLib.Uri.resolve_relative(
77+
import.meta.url,
78+
'../spec/core',
79+
GLib.UriFlags.NONE
80+
);
81+
82+
const specFiles = Array.from(collectFiles(Gio.File.new_for_uri(specUri)));
83+
84+
const exclude = [
85+
];
86+
87+
app.connect('activate', async () => {
88+
let result;
89+
90+
app.hold();
91+
92+
try {
93+
const env = jasmine.getEnv();
94+
95+
env.addReporter(new Reporter());
96+
97+
env.configure({
98+
specFilter: spec => !exclude.some(pattern => pattern.test(spec.getFullName())),
99+
});
100+
101+
for (const helper of helpers) {
102+
await import(helper);
103+
}
104+
105+
for (const specFile of specFiles) {
106+
await import(specFile.get_uri());
107+
}
108+
109+
await new Promise(resolve => GLib.idle_add(GLib.PRIORITY_LOW, () => resolve()));
110+
111+
result = await env.execute();
112+
} catch (error) {
113+
logError(error);
114+
} finally {
115+
app.release();
116+
app.quit();
117+
}
118+
119+
if (result?.overallStatus !== 'passed') {
120+
System.exit(1);
121+
}
122+
});
123+
124+
app.runAsync([System.programInvocationName, ...System.programArgs]).catch(logError);
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import GLib from 'gi://GLib';
2+
import Gio from 'gi://Gio';
3+
4+
let jasmineUnderTestRequire = {};
5+
6+
// Individual source files call getJasmineRequireObj. It's normally defined
7+
// by requireCore.js which is concatenated into jasmine.js before other source
8+
// files. Since we're bypassing that mechanism, we need to provide our own.
9+
globalThis.getJasmineRequireObj = function() {
10+
return jasmineUnderTestRequire;
11+
};
12+
13+
function* collectFiles(directory) {
14+
const enumerator = directory.enumerate_children(
15+
'standard::*',
16+
Gio.FileQueryInfoFlags.NONE,
17+
null
18+
);
19+
20+
let info;
21+
while ((info = enumerator.next_file(null))) {
22+
const file = enumerator.get_child(info);
23+
24+
if (info.get_file_type() === Gio.FileType.DIRECTORY) {
25+
yield* collectFiles(file);
26+
} else {
27+
const basename = file.get_basename();
28+
29+
if (basename.endsWith('.js') && basename !== 'requireSuffix.js') {
30+
yield file;
31+
}
32+
}
33+
}
34+
}
35+
36+
const coreUri = GLib.Uri.resolve_relative(
37+
import.meta.url,
38+
'../../src/core',
39+
GLib.UriFlags.NONE
40+
);
41+
42+
const srcFiles = Array.from(collectFiles(Gio.File.new_for_uri(coreUri)));
43+
44+
await import('../../src/core/requireCore.js');
45+
46+
for (const file of srcFiles) {
47+
await import(file.get_uri());
48+
}
49+
50+
await import('../../src/version.js');
51+
52+
delete globalThis.getJasmineRequireObj;
53+
54+
const built = jasmineUnderTestRequire.core(jasmineUnderTestRequire);
55+
globalThis.jasmineUnderTest = built.jasmine;
56+
globalThis.privateUnderTest = built.private;

src/core/requireCore.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const getJasmineRequireObj = (function() {
1212
jasmineRequire = exports;
1313
} else {
1414
// Browser
15-
jasmineRequire = {};
15+
jasmineRequire = globalThis.getJasmineRequireObj?.() ?? {};
1616
}
1717

1818
function getJasmineRequire() {

0 commit comments

Comments
 (0)