jasmine-browser-runner 3.0.0-beta.2 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/MIT.LICENSE +1 -1
- package/README.md +28 -22
- package/lib/examples/default_esm_config.mjs +2 -0
- package/lib/runner.js +0 -5
- package/lib/server.js +37 -6
- package/lib/support/batchReporter.js +15 -0
- package/lib/support/loaders.js +0 -19
- package/lib/types.js +10 -0
- package/package.json +1 -1
- package/run.html.ejs +3 -1
package/MIT.LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -56,7 +56,7 @@ To use a browser other than Firefox, add a `browser` field to
|
|
|
56
56
|
```javascript
|
|
57
57
|
export default {
|
|
58
58
|
// ...
|
|
59
|
-
|
|
59
|
+
browser: "chrome"
|
|
60
60
|
}
|
|
61
61
|
```
|
|
62
62
|
|
|
@@ -71,8 +71,8 @@ in PEM format in `jasmine-browser.mjs`:
|
|
|
71
71
|
```javascript
|
|
72
72
|
export default {
|
|
73
73
|
// ...
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
tlsKey: "/path/to/tlsKey.pem",
|
|
75
|
+
tlsCert: "/path/to/tlsCert.pem",
|
|
76
76
|
// ...
|
|
77
77
|
}
|
|
78
78
|
```
|
|
@@ -85,38 +85,41 @@ or command line options may be necessary to use an invalid TLS certificate.
|
|
|
85
85
|
|
|
86
86
|
## Controlling which network interfaces are listened to
|
|
87
87
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
88
|
+
**Note: This behavior differs between 2.x and 3.x. If you are using 2.x, please
|
|
89
|
+
consult the README for the version you're using.**
|
|
90
|
+
|
|
91
|
+
By default, jasmine-browser-runner listens to the network interface that
|
|
92
|
+
corresponds to localhost. To listen on a different interface, set `listenAddress`
|
|
93
|
+
to the corresponding hostname or IP address. To listen on all available network
|
|
94
|
+
interfaces, set `listenAddress` to `"*"`. You might need to do that if you're
|
|
95
|
+
using a remote grid such as Saucelabs.
|
|
91
96
|
|
|
92
97
|
```javascript
|
|
93
98
|
export default {
|
|
94
99
|
// ...
|
|
95
|
-
|
|
100
|
+
listenAddress: "*",
|
|
96
101
|
// ...
|
|
97
102
|
}
|
|
98
103
|
```
|
|
99
104
|
|
|
100
105
|
## Hostname support
|
|
101
106
|
|
|
107
|
+
**Note: This behavior differs between 2.x and 3.x. If you are using 2.x, please
|
|
108
|
+
consult the README for the version you're using.**
|
|
109
|
+
|
|
102
110
|
If you need to access your tests via a specific hostname, you can do that by
|
|
103
111
|
setting the `hostname` configuration property:
|
|
104
112
|
|
|
105
113
|
```javascript
|
|
106
114
|
export default {
|
|
107
115
|
// ...
|
|
108
|
-
|
|
116
|
+
hostname: "mymachine.mynetwork",
|
|
109
117
|
// ...
|
|
110
118
|
}
|
|
111
119
|
```
|
|
112
120
|
|
|
113
121
|
This can also be specified on the command line with `--hostname`.
|
|
114
122
|
|
|
115
|
-
Setting `hostname` but not `listenAddress` has the same effect as setting
|
|
116
|
-
`listenAddress` to the same value as `hostname`. If you need to set a hostname
|
|
117
|
-
but retain the default behavior of listening to all network interfaces, you can
|
|
118
|
-
do that by setting `listenAddress` to `"*"`.
|
|
119
|
-
|
|
120
123
|
There are a few important caveats when doing this:
|
|
121
124
|
|
|
122
125
|
1. This name must either be an IP or a name that can really be resolved on your
|
|
@@ -145,7 +148,7 @@ If a source, spec, or helper file's name ends in `.mjs`, it will be loaded as
|
|
|
145
148
|
an ES module rather than a regular script. Note that ES modules can only be
|
|
146
149
|
loaded from other ES modules. So if your source files are ES modules, your
|
|
147
150
|
spec files need to be ES modules too. Want to use a different extension than
|
|
148
|
-
`.
|
|
151
|
+
`.mjs`? Just set the `esmFilenameExtension` config property, e.g.
|
|
149
152
|
`"esmFilenameExtension": ".js"`.
|
|
150
153
|
|
|
151
154
|
To allow spec files to import source files via relative paths, set the `specDir`
|
|
@@ -153,8 +156,11 @@ config field to something that's high enough up to include both spec and source
|
|
|
153
156
|
files, and set `srcFiles` to `[]`. You can autogenerate such a configuration by
|
|
154
157
|
running `npx jasmine-browser-runner init --esm`.
|
|
155
158
|
|
|
159
|
+
If you want to load ES module source directly on load instead of loading it from
|
|
160
|
+
the corresponding spec, set the `modulesWithSideEffectsInSrcFiles` config property to `true`.
|
|
161
|
+
|
|
156
162
|
If you have specs or helper files that use top-level await, set the
|
|
157
|
-
`enableTopLevelAwait` config property
|
|
163
|
+
`enableTopLevelAwait` config property to `true`.
|
|
158
164
|
|
|
159
165
|
[Import maps](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/script/type/importmap)
|
|
160
166
|
are also supported:
|
|
@@ -326,7 +332,7 @@ import jasmineBrowser from 'jasmine-browser-runner';
|
|
|
326
332
|
import config from './spec/support/jasmine-browser.mjs';
|
|
327
333
|
|
|
328
334
|
config.projectBaseDir = path.resolve('some/path');
|
|
329
|
-
jasmineBrowser.startServer(config
|
|
335
|
+
jasmineBrowser.startServer(config);
|
|
330
336
|
|
|
331
337
|
|
|
332
338
|
// CommonJS
|
|
@@ -336,7 +342,7 @@ const jasmineBrowser = require('jasmine-browser-runner');
|
|
|
336
342
|
import('./spec/support/jasmine-browser.mjs')
|
|
337
343
|
.then(function({default: config}) {
|
|
338
344
|
config.projectBaseDir = path.resolve('some/path');
|
|
339
|
-
jasmineBrowser.startServer(config
|
|
345
|
+
jasmineBrowser.startServer(config);
|
|
340
346
|
});
|
|
341
347
|
```
|
|
342
348
|
|
|
@@ -348,7 +354,7 @@ Firefox, and Microsoft Edge) as well as Node.
|
|
|
348
354
|
| Environment | Supported versions |
|
|
349
355
|
|-------------------|----------------------------|
|
|
350
356
|
| Node | 18, 20, 22 |
|
|
351
|
-
| Safari | 15*, 16
|
|
357
|
+
| Safari | 15*, 16*, 17* |
|
|
352
358
|
| Chrome | Evergreen |
|
|
353
359
|
| Firefox | Evergreen, 102*, 115*, 128 |
|
|
354
360
|
| Edge | Evergreen |
|
|
@@ -359,13 +365,13 @@ browsers, as well as older & newer versions of some supported browsers, are
|
|
|
359
365
|
likely to work. However, jasmine-browser-runner isn't tested against them and
|
|
360
366
|
they aren't actively supported.
|
|
361
367
|
|
|
362
|
-
\*
|
|
363
|
-
|
|
364
|
-
|
|
368
|
+
\* Supported on a best-effort basis. Support for these versions may be dropped
|
|
369
|
+
if it becomes impractical, and bugs affecting only these versions may not be
|
|
370
|
+
treated as release blockers.
|
|
365
371
|
|
|
366
372
|
|
|
367
373
|
To find out what environments work with a particular Jasmine release, see the [release notes](https://github.com/jasmine/jasmine/tree/main/release_notes).
|
|
368
374
|
|
|
369
375
|
Copyright (c) 2019 Pivotal Labs<br>
|
|
370
|
-
Copyright (c) 2020-
|
|
376
|
+
Copyright (c) 2020-2025 The Jasmine developers<br>
|
|
371
377
|
This software is licensed under the MIT License.
|
|
@@ -11,6 +11,8 @@ export default {
|
|
|
11
11
|
"spec/helpers/**/*.?(m)js"
|
|
12
12
|
],
|
|
13
13
|
esmFilenameExtension: ".mjs",
|
|
14
|
+
// Set to true if you need to load module src files instead of loading via the spec files.
|
|
15
|
+
modulesWithSideEffectsInSrcFiles: false,
|
|
14
16
|
// Allows the use of top-level await in src/spec/helper files. This is off by
|
|
15
17
|
// default because it makes files load more slowly.
|
|
16
18
|
enableTopLevelAwait: false,
|
package/lib/runner.js
CHANGED
|
@@ -8,11 +8,6 @@ function getBatch(driver) {
|
|
|
8
8
|
'if (results[i][1].passedExpectations) {\n' +
|
|
9
9
|
'expectations = expectations.concat(results[i][1].passedExpectations);\n' +
|
|
10
10
|
'}\n' +
|
|
11
|
-
'for (var j = 0; j < expectations.length; j++) {\n' +
|
|
12
|
-
'var expectation = expectations[j];\n' +
|
|
13
|
-
"try { JSON.stringify(expectation.expected); } catch (e) { expectation.expected = '<circular expected>'; }\n" +
|
|
14
|
-
"try { JSON.stringify(expectation.actual); } catch (e) { expectation.actual = '<circular actual>'; }\n" +
|
|
15
|
-
'}\n' +
|
|
16
11
|
'}\n' +
|
|
17
12
|
'return results;'
|
|
18
13
|
);
|
package/lib/server.js
CHANGED
|
@@ -82,8 +82,11 @@ class Server {
|
|
|
82
82
|
this.options.srcFiles,
|
|
83
83
|
'/__src__'
|
|
84
84
|
).filter(url => {
|
|
85
|
-
// Exclude ES modules. These will be loaded by other ES modules.
|
|
86
|
-
return
|
|
85
|
+
// Exclude ES modules by default. These will be loaded by other ES modules.
|
|
86
|
+
return (
|
|
87
|
+
this.options.modulesWithSideEffectsInSrcFiles ||
|
|
88
|
+
!url.endsWith(this.options.esmFilenameExtension)
|
|
89
|
+
);
|
|
87
90
|
});
|
|
88
91
|
const helperUrls = this.getUrls(
|
|
89
92
|
this.options.specDir,
|
|
@@ -111,14 +114,22 @@ class Server {
|
|
|
111
114
|
const resultMap = {};
|
|
112
115
|
|
|
113
116
|
if (importMap.imports) {
|
|
114
|
-
resultMap.imports = reifyRawSpecifierMap(
|
|
117
|
+
resultMap.imports = reifyRawSpecifierMap(
|
|
118
|
+
importMap.imports,
|
|
119
|
+
this.options,
|
|
120
|
+
this.projectBaseDir
|
|
121
|
+
);
|
|
115
122
|
}
|
|
116
123
|
|
|
117
124
|
if (importMap.scopes) {
|
|
118
125
|
resultMap.scopes = {};
|
|
119
126
|
|
|
120
127
|
for (const [scope, map] of Object.entries(importMap.scopes)) {
|
|
121
|
-
resultMap.scopes[scope] = reifyRawSpecifierMap(
|
|
128
|
+
resultMap.scopes[scope] = reifyRawSpecifierMap(
|
|
129
|
+
map,
|
|
130
|
+
this.options,
|
|
131
|
+
this.projectBaseDir
|
|
132
|
+
);
|
|
122
133
|
}
|
|
123
134
|
}
|
|
124
135
|
|
|
@@ -191,6 +202,8 @@ class Server {
|
|
|
191
202
|
esmFilenameExtension: self.options.esmFilenameExtension,
|
|
192
203
|
importMap: self.importMap(),
|
|
193
204
|
enableTopLevelAwait: self.options.enableTopLevelAwait || false,
|
|
205
|
+
modulesWithSideEffectsInSrcFiles:
|
|
206
|
+
self.options.modulesWithSideEffectsInSrcFiles || false,
|
|
194
207
|
})
|
|
195
208
|
);
|
|
196
209
|
} catch (error) {
|
|
@@ -372,14 +385,32 @@ function unWindows(filePath) {
|
|
|
372
385
|
// paths that the run.html.ejs file will contain. The `rawSpecifierMap` is not
|
|
373
386
|
// the entire importMap. It is a key/value map that may be the "imports" value
|
|
374
387
|
// or an individual map inside of "scopes"[someScope].
|
|
375
|
-
function reifyRawSpecifierMap(rawSpecifierMap) {
|
|
388
|
+
function reifyRawSpecifierMap(rawSpecifierMap, options, projectBaseDir) {
|
|
376
389
|
const concreteMap = {};
|
|
390
|
+
const absoluteModuleRootDir = options.importMap.moduleRootDir
|
|
391
|
+
? path.resolve(projectBaseDir, options.importMap.moduleRootDir)
|
|
392
|
+
: projectBaseDir;
|
|
377
393
|
|
|
378
394
|
for (const [key, value] of Object.entries(rawSpecifierMap)) {
|
|
379
395
|
if (value.match(/^https?:\/\//)) {
|
|
380
396
|
concreteMap[key] = value; // pass through unchanged
|
|
381
|
-
|
|
397
|
+
continue;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
const absolutePath = path.join(absoluteModuleRootDir, value);
|
|
401
|
+
const endsWithSeparator = value.endsWith('/') || value.endsWith('\\');
|
|
402
|
+
|
|
403
|
+
const resolvedSrcDir = path.join(absoluteModuleRootDir, options.srcDir);
|
|
404
|
+
const relativeFromSrcDir = path.relative(resolvedSrcDir, absolutePath);
|
|
405
|
+
|
|
406
|
+
if (relativeFromSrcDir.startsWith('..')) {
|
|
382
407
|
concreteMap[key] = './' + unWindows(path.join('__moduleRoot__', value));
|
|
408
|
+
} else {
|
|
409
|
+
// We are under srcDir: Reuse existing __src__ path
|
|
410
|
+
concreteMap[key] =
|
|
411
|
+
'./' +
|
|
412
|
+
unWindows(path.join('__src__', relativeFromSrcDir)) +
|
|
413
|
+
(endsWithSeparator ? '/' : '');
|
|
383
414
|
}
|
|
384
415
|
}
|
|
385
416
|
|
|
@@ -21,16 +21,31 @@ function BatchReporter() {
|
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
this.jasmineDone = function(info) {
|
|
24
|
+
deleteExpectedAndActual(info);
|
|
24
25
|
events.push(['jasmineDone', info]);
|
|
25
26
|
};
|
|
26
27
|
|
|
27
28
|
this.suiteDone = function(info) {
|
|
29
|
+
deleteExpectedAndActual(info);
|
|
28
30
|
events.push(['suiteDone', info]);
|
|
29
31
|
};
|
|
30
32
|
|
|
31
33
|
this.specDone = function(info) {
|
|
34
|
+
deleteExpectedAndActual(info);
|
|
32
35
|
events.push(['specDone', info]);
|
|
33
36
|
};
|
|
37
|
+
|
|
38
|
+
function deleteExpectedAndActual(info) {
|
|
39
|
+
for (const e of info.failedExpectations) {
|
|
40
|
+
// Delete expected and actual. Not all JS objects are serializable, we
|
|
41
|
+
// don't have a reliable way to determine what Selenium can and can't
|
|
42
|
+
// serialize, not everything that's serializable survives the process
|
|
43
|
+
// intact, and there are no known reporters that use the expected or
|
|
44
|
+
// actual properties of expectation results.
|
|
45
|
+
delete e.expected;
|
|
46
|
+
delete e.actual;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
34
49
|
}
|
|
35
50
|
|
|
36
51
|
window.batchReporter = new BatchReporter();
|
package/lib/support/loaders.js
CHANGED
|
@@ -1,24 +1,5 @@
|
|
|
1
1
|
/* eslint-env browser, jasmine */
|
|
2
2
|
|
|
3
|
-
window._jasmine_loadEsModule = function(src) {
|
|
4
|
-
const script = document.createElement('script');
|
|
5
|
-
script.type = 'module';
|
|
6
|
-
|
|
7
|
-
// Safari reports syntax errors in ES modules as a script element error
|
|
8
|
-
// event rather than a global error event. Rethrow so that Jasmine can
|
|
9
|
-
// pick it up and fail the suite.
|
|
10
|
-
script.addEventListener('error', function(event) {
|
|
11
|
-
const msg =
|
|
12
|
-
'An error occurred while loading ' +
|
|
13
|
-
src +
|
|
14
|
-
'. Check the browser console for details.';
|
|
15
|
-
throw new Error(msg);
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
script.src = src;
|
|
19
|
-
document.head.appendChild(script);
|
|
20
|
-
};
|
|
21
|
-
|
|
22
3
|
window._jasmine_loadWithTopLevelAwaitSupport = async function(
|
|
23
4
|
scriptUrls,
|
|
24
5
|
esmFilenameExtension
|
package/lib/types.js
CHANGED
|
@@ -153,6 +153,16 @@
|
|
|
153
153
|
* @type boolean | undefined
|
|
154
154
|
* @default false
|
|
155
155
|
*/
|
|
156
|
+
/**
|
|
157
|
+
* If set to true jasmine loads also ES Modules which are included in SrcFiles.
|
|
158
|
+
* This option is off by default because in most scenarios it is better to load the
|
|
159
|
+
* module under test from the test itself.
|
|
160
|
+
* But if the module has wanted side effects (like for example polyfills) you can
|
|
161
|
+
* interleave ES module and classic scripts in your SrcFiles.
|
|
162
|
+
* @name Configuration#modulesWithSideEffectsInSrcFiles
|
|
163
|
+
* @type boolean | undefined
|
|
164
|
+
* @default false
|
|
165
|
+
*/
|
|
156
166
|
/**
|
|
157
167
|
* <p>An optional map from paths to Express application middleware to mount on
|
|
158
168
|
* those paths. This can be used to serve static files, proxy requests to
|
package/package.json
CHANGED
package/run.html.ejs
CHANGED
|
@@ -29,7 +29,9 @@
|
|
|
29
29
|
<% } else { %>
|
|
30
30
|
<% userJsFiles.forEach(function(jsFile) { %>
|
|
31
31
|
<% if (jsFile.endsWith(esmFilenameExtension)) { %>
|
|
32
|
-
<script
|
|
32
|
+
<script src="<%= jsFile %>" type="module"></script>
|
|
33
|
+
<% } else if (modulesWithSideEffectsInSrcFiles) { %>
|
|
34
|
+
<script src="<%= jsFile %>" type="text/javascript" defer></script>
|
|
33
35
|
<% } else { %>
|
|
34
36
|
<script src="<%= jsFile %>" type="text/javascript"></script>
|
|
35
37
|
<% } %>
|