jasmine-browser-runner 2.4.0 → 2.5.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/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  jasmine-browser-runner runs your Jasmine specs in a browser. It's suitable for
2
2
  interactive use with normal browsers as well as running specs in CI builds
3
- using either headless Chrome or Saucelabs.
3
+ using either headless browsers or with a remote Selenuium grid provider
4
+ such as Saucelabs.
4
5
 
5
6
  # Getting started
6
7
 
@@ -19,13 +20,21 @@ npx jasmine-browser-runner init
19
20
  If you intend to use ES modules, add `--esm` to the `jasmine-browser-runner init`
20
21
  command.
21
22
 
22
- Then, customize `spec/support/jasmine-browser.json` to suit your needs. You can
23
+ Then, customize `spec/support/jasmine-browser.mjs` to suit your needs. You can
23
24
  change the spec files, helpers, and source files that are loaded, specify the
24
25
  [Jasmine env's configuration](https://jasmine.github.io/api/edge/Configuration.html),
25
26
  and more.
26
27
 
27
- You can also use the `--config` option to specify a different file.
28
- This file can be a JSON file or a javascript file that exports a object that looks like the JSON above.
28
+ In addition to `spec/support/jasmine-browser.mjs`, jasmine-browser-runner also
29
+ supports other config file paths:
30
+
31
+ * `spec/support/jasmine-browser.js`
32
+ * `spec/support/jasmine-browser.json` (generated by previous versions of the
33
+ `init` subcommand)
34
+ * Any other JavaScript or JSON file, if you use the `--config` option. This
35
+ file can be a JSON file or a javascript file whose default export is a config
36
+ object.
37
+
29
38
  More information about the configuration can be found at the runner [documentation website](https://jasmine.github.io/api/browser-runner/edge/Configuration.html).
30
39
 
31
40
  To start the server so that you can run the specs interactively (particularly
@@ -42,10 +51,10 @@ npx jasmine-browser-runner runSpecs
42
51
  ```
43
52
 
44
53
  To use a browser other than Firefox, add a `browser` field to
45
- `jasmine-browser.json`:
54
+ `jasmine-browser.mjs`:
46
55
 
47
56
  ```javascript
48
- {
57
+ export default {
49
58
  // ...
50
59
  "browser": "chrome"
51
60
  }
@@ -57,10 +66,10 @@ Its value can be `"firefox"`, `"headlessFirefox"`, `"safari"`,
57
66
  ## TLS support
58
67
 
59
68
  To serve tests over HTTPS instead of HTTP, supply a path to a TLS cert and key
60
- in PEM format in `jasmine-browser.json`:
69
+ in PEM format in `jasmine-browser.mjs`:
61
70
 
62
71
  ```javascript
63
- {
72
+ export default {
64
73
  // ...
65
74
  "tlsKey": "/path/to/tlsKey.pem",
66
75
  "tlsCert": "/path/to/tlsCert.pem",
@@ -74,13 +83,27 @@ Note that if you are using a self-signed or otherwise invalid certificate, the
74
83
  browser will not allow the connection by default. Additional browser configs
75
84
  or command line options may be necessary to use an invalid TLS certificate.
76
85
 
86
+ ## Controlling which network interfaces are listened to
87
+
88
+ By default, jasmine-browser-runner listens to all available network interfaces.
89
+ You might need that if you're using a remote grid such as Saucelabs. If you
90
+ don't need that, you can improve security by listening only to localhost.
91
+
92
+ ```javascript
93
+ export default {
94
+ // ...
95
+ "listenAddress": "localhost",
96
+ // ...
97
+ }
98
+ ```
99
+
77
100
  ## Hostname support
78
101
 
79
- To serve tests on a specific interface or IP, you can specify a hostname in
80
- `jasmine-browser.json`:
102
+ If you need to access your tests via a specific hostname, you can do that by
103
+ setting the `hostname` configuration property:
81
104
 
82
105
  ```javascript
83
- {
106
+ export default {
84
107
  // ...
85
108
  "hostname": "mymachine.mynetwork",
86
109
  // ...
@@ -89,6 +112,11 @@ To serve tests on a specific interface or IP, you can specify a hostname in
89
112
 
90
113
  This can also be specified on the command line with `--hostname`.
91
114
 
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
+
92
120
  There are a few important caveats when doing this:
93
121
 
94
122
  1. This name must either be an IP or a name that can really be resolved on your
@@ -132,7 +160,7 @@ If you have specs or helper files that use top-level await, set the
132
160
  are also supported:
133
161
 
134
162
  ```javascript
135
- {
163
+ export default {
136
164
  // ...
137
165
  "importMap": {
138
166
  "moduleRootDir": "node_modules",
@@ -154,9 +182,9 @@ whether you use the Asset Pipeline or Webpacker.
154
182
 
155
183
  1. Run `yarn add --dev jasmine-browser-runner jasmine-core`.
156
184
  2. Run `npx jasmine-browser-runner init`.
157
- 3. Edit `spec/support/jasmine-browser.json` as follows:
185
+ 3. Edit `spec/support/jasmine-browser.mjs` as follows:
158
186
  ```
159
- {
187
+ export default {
160
188
  "srcDir": ".",
161
189
  "srcFiles": [],
162
190
  "specDir": "public/packs/js",
@@ -196,9 +224,9 @@ To run the specs:
196
224
  the Rails application.
197
225
  2. Run `yarn add --dev jasmine-browser-runner`.
198
226
  3. Run `npx jasmine-browser-runner init`.
199
- 5. Edit `spec/support/jasmine-browser.json` as follows:
227
+ 5. Edit `spec/support/jasmine-browser.mjs` as follows:
200
228
  ```
201
- {
229
+ export default {
202
230
  "srcDir": "public/assets",
203
231
  "srcFiles": [
204
232
  "application-*.js"
@@ -230,9 +258,9 @@ provider like [Saucelabs](https://saucelabs.com/),
230
258
  To use a remote grid hub, set the `browser` object
231
259
  in your config file as follows:
232
260
 
233
- ```json
234
- // jasmine-browser.json
235
- {
261
+ ```javascript
262
+ // jasmine-browser.mjs
263
+ export default {
236
264
  // ...
237
265
  // BrowserStack
238
266
  "browser": {
@@ -254,9 +282,9 @@ in your config file as follows:
254
282
  }
255
283
  }
256
284
  ```
257
- ```json
258
- // jasmine-browser.json
259
- {
285
+ ```javascript
286
+ // jasmine-browser.mjs
287
+ export default {
260
288
  // ...
261
289
  // Saucelabs
262
290
  "browser": {
@@ -292,13 +320,24 @@ second parameter to`startServer`.
292
320
  ## Want more control?
293
321
 
294
322
  ```javascript
295
- const path = require('path');
296
- const jasmineBrowser = require('jasmine-browser-runner');
323
+ // ESM
324
+ import path from 'path';
325
+ import jasmineBrowser from 'jasmine-browser-runner';
326
+ import config from './spec/support/jasmine-browser.mjs';
297
327
 
298
- const config = require(path.resolve('spec/support/jasmine-browser.json'));
299
328
  config.projectBaseDir = path.resolve('some/path');
300
-
301
329
  jasmineBrowser.startServer(config, { port: 4321 });
330
+
331
+
332
+ // CommonJS
333
+ const path = require('path');
334
+ const jasmineBrowser = require('jasmine-browser-runner');
335
+
336
+ import('./spec/support/jasmine-browser.mjs')
337
+ .then(function({default: config}) {
338
+ config.projectBaseDir = path.resolve('some/path');
339
+ jasmineBrowser.startServer(config, { port: 4321 });
340
+ });
302
341
  ```
303
342
 
304
343
  ## Supported environments
package/index.js CHANGED
@@ -80,13 +80,17 @@ module.exports = {
80
80
  const server = new ServerClass(options);
81
81
 
82
82
  const reporters = await createReporters(options, deps);
83
- const useSauce = options.browser && options.browser.useSauce;
83
+ const useLegacySauce = options.browser && options.browser.useSauce;
84
84
  const useRemote = options.browser && options.browser.useRemoteSeleniumGrid;
85
+ const useSauceCompletionReporting =
86
+ useLegacySauce ||
87
+ (useRemote &&
88
+ options.browser.remoteSeleniumGrid?.url?.includes('saucelabs.com'));
85
89
  let portRequest;
86
90
 
87
91
  if (options.port) {
88
92
  portRequest = options.port;
89
- } else if (useSauce || useRemote) {
93
+ } else if (useLegacySauce || useRemote) {
90
94
  portRequest = 5555;
91
95
  } else {
92
96
  portRequest = 0;
@@ -122,7 +126,7 @@ module.exports = {
122
126
 
123
127
  return details;
124
128
  } finally {
125
- if (useSauce) {
129
+ if (useSauceCompletionReporting) {
126
130
  await webdriver.executeScript(
127
131
  `sauce:job-result=${process.exitCode === 0}`
128
132
  );
package/lib/command.js CHANGED
@@ -165,7 +165,7 @@ class Command {
165
165
  }
166
166
 
167
167
  init(options) {
168
- const dest = 'spec/support/jasmine-browser.json';
168
+ const dest = 'spec/support/jasmine-browser.mjs';
169
169
 
170
170
  if (fs.existsSync(dest)) {
171
171
  this._logger.log(`${dest} already exists.`);
package/lib/config.js CHANGED
@@ -20,10 +20,12 @@ async function loadConfig(baseDir, cliOptions) {
20
20
 
21
21
  const candidates = (specifiedConfigFile
22
22
  ? [specifiedConfigFile]
23
- : ['spec/support/jasmine-browser.js', 'spec/support/jasmine-browser.json']
24
- )
25
- .filter(name => !!name)
26
- .map(name => path.resolve(baseDir, name));
23
+ : [
24
+ 'spec/support/jasmine-browser.mjs',
25
+ 'spec/support/jasmine-browser.js',
26
+ 'spec/support/jasmine-browser.json',
27
+ ]
28
+ ).map(name => path.resolve(baseDir, name));
27
29
 
28
30
  const fullPath = candidates.find(p => fs.existsSync(p));
29
31
 
@@ -57,18 +59,15 @@ function validateConfig(config) {
57
59
  }
58
60
 
59
61
  function defaultConfig() {
60
- return fs.readFileSync(require.resolve('./examples/default_config.json'), {
62
+ return fs.readFileSync(require.resolve('./examples/default_config.mjs'), {
61
63
  encoding: 'utf8',
62
64
  });
63
65
  }
64
66
 
65
67
  function defaultEsmConfig() {
66
- return fs.readFileSync(
67
- require.resolve('./examples/default_esm_config.json'),
68
- {
69
- encoding: 'utf8',
70
- }
71
- );
68
+ return fs.readFileSync(require.resolve('./examples/default_esm_config.mjs'), {
69
+ encoding: 'utf8',
70
+ });
72
71
  }
73
72
 
74
73
  function validateImportMap(importMap) {
@@ -0,0 +1,30 @@
1
+ export default {
2
+ srcDir: "src",
3
+ srcFiles: [
4
+ "**/*.js"
5
+ ],
6
+ specDir: "spec",
7
+ specFiles: [
8
+ "**/*[sS]pec.js"
9
+ ],
10
+ helpers: [
11
+ "helpers/**/*.js"
12
+ ],
13
+ env: {
14
+ stopSpecOnExpectationFailure: false,
15
+ stopOnSpecFailure: false,
16
+ random: true
17
+ },
18
+
19
+ // For security, listen only to localhost. You can also specify a different
20
+ // hostname or IP address, or remove the property or set it to "*" to listen
21
+ // to all network interfaces.
22
+ listenAddress: "localhost",
23
+
24
+ // The hostname that the browser will use to connect to the server.
25
+ hostname: "localhost",
26
+
27
+ browser: {
28
+ name: "firefox"
29
+ }
30
+ };
@@ -0,0 +1,34 @@
1
+ export default {
2
+ srcDir: "src",
3
+ // srcFiles should usually be left empty when using ES modules, because you'll
4
+ // explicitly import sources from your specs.
5
+ srcFiles: [],
6
+ specDir: ".",
7
+ specFiles: [
8
+ "spec/**/*[sS]pec.?(m)js"
9
+ ],
10
+ helpers: [
11
+ "spec/helpers/**/*.?(m)js"
12
+ ],
13
+ esmFilenameExtension: ".mjs",
14
+ // Allows the use of top-level await in src/spec/helper files. This is off by
15
+ // default because it makes files load more slowly.
16
+ enableTopLevelAwait: false,
17
+ env: {
18
+ stopSpecOnExpectationFailure: false,
19
+ stopOnSpecFailure: false,
20
+ random: true
21
+ },
22
+
23
+ // For security, listen only to localhost. You can also specify a different
24
+ // hostname or IP address, or remove the property or set it to "*" to listen
25
+ // to all network interfaces.
26
+ listenAddress: "localhost",
27
+
28
+ // The hostname that the browser will use to connect to the server.
29
+ hostname: "localhost",
30
+
31
+ browser: {
32
+ name: "firefox"
33
+ }
34
+ };
package/lib/server.js CHANGED
@@ -15,8 +15,9 @@ class Server {
15
15
  * @constructor
16
16
  * @param {ServerCtorOptions} options
17
17
  */
18
- constructor(options) {
18
+ constructor(options, deps) {
19
19
  this.options = { ...options };
20
+ this._deps = deps || { http, https };
20
21
  this.express = this.options.express || defaultExpress;
21
22
  this.useHtmlReporter =
22
23
  options.useHtmlReporter === undefined ? true : options.useHtmlReporter;
@@ -223,14 +224,20 @@ class Server {
223
224
  const tlsCert = serverOptions.tlsCert || this.options.tlsCert;
224
225
  const tlsKey = serverOptions.tlsKey || this.options.tlsKey;
225
226
  const hostname = serverOptions.hostname || this.options.hostname;
227
+ // The last two fallbacks here are necessary for backwards compatibility.
228
+ let listenAddress =
229
+ serverOptions.listenAddress ||
230
+ this.options.listenAddress ||
231
+ hostname ||
232
+ '';
233
+
234
+ if (listenAddress === '*') {
235
+ listenAddress = '';
236
+ }
226
237
 
227
- // NOTE: Before hostname support, jasmine-browser-runner would listen on
228
- // all IPs (no hostname) and point browsers to "localhost". We preserve
229
- // backward compatibility here by using different defaults for these two
230
- // things.
231
238
  const listenOptions = {
232
239
  port,
233
- host: hostname || '',
240
+ host: listenAddress,
234
241
  };
235
242
  this._httpHostname = hostname || 'localhost';
236
243
 
@@ -260,12 +267,12 @@ class Server {
260
267
  key: fs.readFileSync(tlsKey),
261
268
  cert: fs.readFileSync(tlsCert),
262
269
  };
263
- this._httpServer = https
270
+ this._httpServer = this._deps.https
264
271
  .createServer(httpsOptions, app)
265
272
  .listen(listenOptions, callback);
266
273
  this._httpServerScheme = 'https';
267
274
  } else {
268
- this._httpServer = http
275
+ this._httpServer = this._deps.http
269
276
  .createServer(app)
270
277
  .listen(listenOptions, callback);
271
278
  this._httpServerScheme = 'http';
package/lib/types.js CHANGED
@@ -52,12 +52,23 @@
52
52
  * @type string
53
53
  */
54
54
  /**
55
- * The hostname to use. This influences both the URL given to browsers and the
56
- * addresses on which the socket listens. If blank, for backward
57
- * compatibility, the browsers will be pointed to localhost, but the listening
58
- * socket will listen on all IPs.
55
+ * The hostname or IP address of the network interface to listen on. For
56
+ * security, this should be set to localhost or an equivalent unless you need
57
+ * the server to be accessible over other network interfaces. Set to "*" to
58
+ * listen on all interfaces, which may be required by some remote Selenium
59
+ * grids.
60
+ * @name ServerCtorOptions#listenAddress
61
+ * @default The value of {@link ServerCtorOptions#hostname} or {@link ServerStartOptions#hostname} if configured, otherwise "*"
62
+ * @type string | undefined
63
+ */
64
+ /**
65
+ * The hostname to use in the URL given to browsers. For backward compatibility,
66
+ * setting this property without also setting {@link ServerCtorOptions#listenAddress}
67
+ * or {@link ServerStartOptions#listenAddress} has the same effect as setting
68
+ * the listen address to the hostname.
59
69
  * @name ServerCtorOptions#hostname
60
- * @type string
70
+ * @default "localhost"
71
+ * @type string | undefined
61
72
  */
62
73
  /**
63
74
  * The root directory of the project.
@@ -304,12 +315,12 @@
304
315
  * @type string
305
316
  */
306
317
  /**
307
- * The hostname to use. This influences both the URL given to browsers and the
308
- * addresses on which the socket listens. If blank, for backward
309
- * compatibility, the browsers will be pointed to localhost, but the listening
310
- * socket will listen on all IPs.
318
+ * @see ServerCtorOptions#hostname
311
319
  * @name ServerStartOptions#hostname
312
- * @type string
320
+ */
321
+ /**
322
+ * @see ServerCtorOptions#listenAddress
323
+ * @name ServerStartOptions#listenAddress
313
324
  */
314
325
 
315
326
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jasmine-browser-runner",
3
- "version": "2.4.0",
3
+ "version": "2.5.0",
4
4
  "description": "Serve and run your Jasmine specs in a browser",
5
5
  "bin": "bin/jasmine-browser-runner",
6
6
  "exports": "./index.js",
@@ -13,8 +13,8 @@
13
13
  "run.html.ejs",
14
14
  "bin/*.js",
15
15
  "lib/**/*.js",
16
- "lib/examples/default_config.json",
17
- "lib/examples/default_esm_config.json"
16
+ "lib/examples/default_config.mjs",
17
+ "lib/examples/default_esm_config.mjs"
18
18
  ],
19
19
  "scripts": {
20
20
  "posttest": "eslint bin/* lib spec index.js --ignore-path=.styleIgnore && prettier --check --ignore-path=.styleIgnore \"lib/**/*.js\" \"spec/**/*.js\" index.js",
@@ -38,7 +38,7 @@
38
38
  "homepage": "https://github.com/jasmine/jasmine-browser-runner#readme",
39
39
  "dependencies": {
40
40
  "ejs": "^3.1.6",
41
- "express": "^4.16.4",
41
+ "express": "^4.19.2",
42
42
  "glob": "^10.0.0",
43
43
  "selenium-webdriver": "^4.12.0"
44
44
  },
@@ -1,21 +0,0 @@
1
- {
2
- "srcDir": "src",
3
- "srcFiles": [
4
- "**/*.js"
5
- ],
6
- "specDir": "spec",
7
- "specFiles": [
8
- "**/*[sS]pec.js"
9
- ],
10
- "helpers": [
11
- "helpers/**/*.js"
12
- ],
13
- "env": {
14
- "stopSpecOnExpectationFailure": false,
15
- "stopOnSpecFailure": false,
16
- "random": true
17
- },
18
- "browser": {
19
- "name": "firefox"
20
- }
21
- }
@@ -1,21 +0,0 @@
1
- {
2
- "srcDir": "src",
3
- "srcFiles": [],
4
- "specDir": ".",
5
- "specFiles": [
6
- "spec/**/*[sS]pec.?(m)js"
7
- ],
8
- "helpers": [
9
- "spec/helpers/**/*.?(m)js"
10
- ],
11
- "esmFilenameExtension": ".mjs",
12
- "enableTopLevelAwait": false,
13
- "env": {
14
- "stopSpecOnExpectationFailure": false,
15
- "stopOnSpecFailure": false,
16
- "random": true
17
- },
18
- "browser": {
19
- "name": "firefox"
20
- }
21
- }