testem 3.20.2 → 3.21.1

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,7 +1,7 @@
1
1
  Got Scripts? Test’em!
2
2
  =================
3
3
 
4
- [![Build Status](https://github.com/testem/testem/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/testem/testem/actions/workflows/ci.yml?query=branch%3Amaster) [![npm version](https://badge.fury.io/js/testem.svg)](https://badge.fury.io/js/testem)
4
+ [![Build Status](https://github.com/testem/testem/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/testem/testem/actions/workflows/ci.yml?query=branch%3Amain) [![npm version](https://badge.fury.io/js/testem.svg)](https://badge.fury.io/js/testem)
5
5
 
6
6
  Testem is a **JavaScript test runner** that runs your tests in **real desktop browsers**—Chrome, Firefox, Safari, Edge, and others you launch—so your specs execute in the same browser engines and DOM your users get, not a pretend environment. It also runs tests in **[Node](https://nodejs.org/)**, **Chrome** (including **headless** runs via `browser_args`, e.g. `--headless`), or any launcher you configure. It is **framework-agnostic** and aimed at **any kind of tests** you want to run: unit, integration, end-to-end style suites, or custom setups—you pick the style; Testem wires it to the browser or process.
7
7
 
@@ -33,7 +33,7 @@ Features
33
33
 
34
34
  Installation
35
35
  ------------
36
- Testem needs a supported **[Node.js](https://nodejs.org/)** runtime. The required range is defined in [`package.json`](package.json) under `engines` (currently **^20.19.0**, **^22.12.0**, or **>=24.0.0**).
36
+ Testem needs a supported **[Node.js](https://nodejs.org/)** runtime. The required range is defined in [`package.json`](package.json) under `engines` (currently **^20.19.0**, **^22.12.0**, **^24.0.0**, or **>= 26.0.0**).
37
37
 
38
38
  **Recommended:** install Testem **both** as a **dev dependency** (so your project pins a version) **and** **globally** (so the `testem` command is always available on your `PATH`):
39
39
 
@@ -60,11 +60,11 @@ The simplest way to use Testem, in the TDD spirit, is to start in an empty direc
60
60
 
61
61
  You will see a terminal-based interface which looks like this
62
62
 
63
- ![Initial interface](https://github.com/testem/testem/raw/master/images/initial.png)
63
+ ![Initial interface](https://github.com/testem/testem/raw/main/images/initial.png)
64
64
 
65
65
  Now open a **real browser** (the URL Testem prints is a normal page in Chrome, Firefox, Safari, etc.) and go to the specified URL. You should now see
66
66
 
67
- ![Zero of zero](https://github.com/testem/testem/raw/master/images/zeros.png)
67
+ ![Zero of zero](https://github.com/testem/testem/raw/main/images/zeros.png)
68
68
 
69
69
  We see 0/0 for tests because at this point we haven't written any code. As we write them, Testem will pick up any `.js` files
70
70
  that were added, include them, and if there are tests, run them automatically. So let's first write `hello_spec.js` in the spirit of "test first" (written in Jasmine)
@@ -78,7 +78,7 @@ describe('hello', function(){
78
78
  ```
79
79
  Save that file and now you should see
80
80
 
81
- ![Red](https://github.com/testem/testem/raw/master/images/red.png)
81
+ ![Red](https://github.com/testem/testem/raw/main/images/red.png)
82
82
 
83
83
  Testem should automatically pick up the new files you've added and also any changes that you make to them and rerun the tests. The test fails as we'd expect. Now we implement the spec like so in `hello.js`
84
84
 
@@ -90,7 +90,7 @@ function hello(){
90
90
 
91
91
  So you should now see
92
92
 
93
- ![Green](https://github.com/testem/testem/raw/master/images/green.png)
93
+ ![Green](https://github.com/testem/testem/raw/main/images/green.png)
94
94
 
95
95
  ### Using the Text User Interface
96
96
 
@@ -143,7 +143,7 @@ To use Testem for continuous integration
143
143
 
144
144
  testem ci
145
145
 
146
- **GitHub Actions** is a common way to run Testem in CI: add a workflow job that runs `testem ci` (often with the **Headless Chrome** or **Chromium** launcher). This project’s own workflow is in [`.github/workflows/ci.yml`](https://github.com/testem/testem/blob/master/.github/workflows/ci.yml).
146
+ **GitHub Actions** is a common way to run Testem in CI: add a workflow job that runs `testem ci` (often with the **Headless Chrome** or **Chromium** launcher). This project’s own workflow is in [`.github/workflows/ci.yml`](https://github.com/testem/testem/blob/main/.github/workflows/ci.yml).
147
147
 
148
148
  In CI mode, Testem runs your tests on all the browsers that are available on the system one after another.
149
149
 
@@ -178,9 +178,9 @@ When you run `testem ci` to run tests, it outputs the results in the [TAP](https
178
178
 
179
179
  # ok
180
180
 
181
- TAP is a human-readable and language-agnostic test result format. On **GitHub Actions**, a typical pattern is a step that runs `testem ci` and relies on the exit code to fail the job (see [`.github/workflows/ci.yml`](https://github.com/testem/testem/blob/master/.github/workflows/ci.yml) in this repository). For **Jenkins** and **TeamCity**, use TAP plugins:
181
+ TAP is a human-readable and language-agnostic test result format. On **GitHub Actions**, a typical pattern is a step that runs `testem ci` and relies on the exit code to fail the job (see [`.github/workflows/ci.yml`](https://github.com/testem/testem/blob/main/.github/workflows/ci.yml) in this repository). For **Jenkins** and **TeamCity**, use TAP plugins:
182
182
 
183
- * [Jenkins TAP plugin](https://plugins.jenkins.io/tap/) - I've added [detailed instructions](https://github.com/testem/testem/blob/master/docs/use_with_jenkins.md) for setup with Jenkins.
183
+ * [Jenkins TAP plugin](https://plugins.jenkins.io/tap/) - I've added [detailed instructions](https://github.com/testem/testem/blob/main/docs/use_with_jenkins.md) for setup with Jenkins.
184
184
  * [TeamCity TAP plugin](https://github.com/pavelsher/teamcity-tap-parser)
185
185
 
186
186
  ## TAP Options
@@ -278,7 +278,7 @@ This calls for the `testem.json` configuration file (you can also alternatively
278
278
 
279
279
  ```json
280
280
  {
281
- "framework": "jasmine",
281
+ "framework": "jasmine2",
282
282
  "src_files": [
283
283
  "hello.js",
284
284
  "hello_spec.js"
@@ -286,6 +286,8 @@ This calls for the `testem.json` configuration file (you can also alternatively
286
286
  }
287
287
  ```
288
288
 
289
+ The default `framework` is still `"jasmine"` (Jasmine 1.x). That default is **deprecated** and will be removed in the next version of Testem. New projects should use `"jasmine2"` with `jasmine-core` (see [Browser framework dependencies](#browser-framework-dependencies)).
290
+
289
291
  The `src_files` can also be unix glob patterns.
290
292
 
291
293
  ```json
@@ -312,6 +314,48 @@ You can also ignore certain files using `src_files_ignore`.
312
314
 
313
315
  Read [more details](docs/config_file.md) about the config options.
314
316
 
317
+ Browser framework dependencies
318
+ ------------------------------
319
+
320
+ Built-in `mocha`, `mocha+chai`, `qunit`, and `jasmine2` runners **prefer** files from `/node_modules/` in the project `cwd`. If those packages are not installed, Testem still loads the previous CDN URLs (Mocha 2.3.4, Chai 3.4.1, QUnit 1.20.0, Jasmine 2.4.1). Installing the packages is optional on this version and required in the next major version.
321
+
322
+ | `framework` | Install for modern versions |
323
+ |---|---|
324
+ | `jasmine2` | `jasmine-core` |
325
+ | `qunit` | `qunit` |
326
+ | `mocha` | `mocha` |
327
+ | `mocha+chai` | `mocha` and `chai` |
328
+
329
+ Run `npm install` in the project directory. In a monorepo, or when `cwd` is not the install root, map the path with `routes`:
330
+
331
+ ```json
332
+ {
333
+ "routes": {
334
+ "/node_modules": "../node_modules"
335
+ }
336
+ }
337
+ ```
338
+
339
+ The `mocha+chai` runner loads local Chai when Mocha is also local. Chai 4 uses the UMD build `chai/chai.js` as a classic script. Chai 5+ (`"type": "module"`) is imported as an ES module, then your spec files load as classic scripts (`var expect = chai.expect` still works).
340
+
341
+ `jasmine2` uses `jasmine-core` 5 `boot0.js`/`boot1.js` when those files are present, and `boot.js` for jasmine-core 3/4. Incomplete installs fall back to the CDN pin.
342
+
343
+ ### Jasmine 1.x deprecation
344
+
345
+ `framework: "jasmine"` (the default) still runs Jasmine 1.3.1 from CDN. Testem logs a deprecation warning on the server, and the Jasmine 1 adapter logs a warning in the browser (including custom `test_page`s that still load Jasmine 1).
346
+
347
+ **The next version of Testem will not support Jasmine 1.** Migrate with:
348
+
349
+ ```json
350
+ {
351
+ "framework": "jasmine2"
352
+ }
353
+ ```
354
+
355
+ ```bash
356
+ npm install --save-dev jasmine-core
357
+ ```
358
+
315
359
  Custom Test Pages
316
360
  -----------------
317
361
 
@@ -330,7 +374,7 @@ Next, the test page you use needs to have the adapter code installed on them, as
330
374
 
331
375
  ### Include Snippet
332
376
 
333
- Include this snippet directly after your `jasmine.js`, `qunit.js` or `mocha.js` scripts to enable *Testem* with your test page.
377
+ Include this snippet directly after your `jasmine.js`, `qunit.js` or `mocha.js` scripts to enable *Testem* with your test page. Prefer loading those frameworks from `/node_modules/...` (see [examples/qunit_lazy](examples/qunit_lazy) and [examples/vite](examples/vite)); CDN URLs still work.
334
378
 
335
379
  ```html
336
380
  <script src="/testem.js"></script>
@@ -340,9 +384,11 @@ Or if you are using require.js or another loader, just make sure you load `/test
340
384
 
341
385
  '/testem.js' here is dynamically generated to be used client-side and it should not be confused with server-side 'testem.js'.
342
386
 
343
- ### Dynamic Substitution
387
+ ### Dynamic Substitution (deprecated)
344
388
 
345
- To enable dynamic substitutions within the JavaScript files in your custom test page, you must
389
+ Naming `test_page` with a `.mustache` extension to interpolate `serve_files` / `css_files` is **deprecated** and will be removed in Testem 4. Prefer a static HTML page and include `<script src="/testem.js"></script>` as shown above.
390
+
391
+ On Testem 3.x the old form still works:
346
392
 
347
393
  1. name your test page using `.mustache` as the extension
348
394
  2. use `{{#serve_files}}` to loop over the set of JavaScript files to be served, and then reference its `src` property to access their path (or `{{#css_files}}` for stylesheets)
@@ -357,6 +403,28 @@ Example:
357
403
  <link rel="stylesheet" href="{{src}}">
358
404
  {{/css_files}}
359
405
 
406
+ To migrate, rename the page to `.html`, list the same scripts and styles as tags, and point `test_page` at that file. `serve_files` can stay in config for watching or compilation; it no longer needs to be injected.
407
+
408
+ Before:
409
+
410
+ ```html
411
+ {{#serve_files}}
412
+ <script src="{{src}}"></script>
413
+ {{/serve_files}}
414
+ {{#css_files}}
415
+ <link rel="stylesheet" href="{{src}}">
416
+ {{/css_files}}
417
+ ```
418
+
419
+ After, if config has `"serve_files": ["test-bundle.js"]` and `"css_files": ["app.css"]`:
420
+
421
+ ```html
422
+ <script src="test-bundle.js"></script>
423
+ <link rel="stylesheet" href="app.css">
424
+ ```
425
+
426
+ Keep `/testem.js` and your test framework scripts in the same order as a normal custom page. If you interpolated other config keys (`{{port}}`, custom options), bake those values into the HTML or generate the page in `before_tests`.
427
+
360
428
  ### Multiple Test Pages
361
429
 
362
430
  You can also specify multiple test pages to run by passing an array to the `test_page` option.
@@ -443,6 +511,8 @@ When you run `testem`, it will auto-launch the mocha process based on the specif
443
511
  Processes with TAP Output
444
512
  -------------------------
445
513
 
514
+ Node's built-in test runner emits TAP with `node --test --test-reporter=tap` plus `"protocol": "tap"`. See the [node:test example](examples/node_test).
515
+
446
516
  If your process outputs test results in [TAP](https://en.wikipedia.org/wiki/Test_Anything_Protocol) format, you can tell that to testem via the `protocol` property. For example
447
517
 
448
518
  ```javascript
@@ -454,8 +524,12 @@ If your process outputs test results in [TAP](https://en.wikipedia.org/wiki/Test
454
524
  }
455
525
  ```
456
526
 
527
+ Vitest emits TAP with `--reporter=tap-flat` (use `vitest run`, not watch mode) plus `"protocol": "tap"`. See the [Vitest example](examples/vitest).
528
+
457
529
  When this is done, Testem will read in the process's stdout and parse it as TAP, and then display the test results in Testem's normal format. It will also hide the process's stdout output from the console log panel, although it will still display the stderr.
458
530
 
531
+ Jest has no built-in TAP reporter, so the equivalent is a package such as [`jest-tap-reporter`](https://www.npmjs.com/package/jest-tap-reporter) plus `"protocol": "tap"`. See the [Jest example](examples/jest).
532
+
459
533
  Headless Chrome
460
534
  ---------------
461
535
 
@@ -538,7 +612,7 @@ Let's say you want to serve `tests.html` at the top level url `/tests.html`, all
538
612
  DIY: Use Any Test Framework
539
613
  ---------------------------
540
614
 
541
- If you want to use Testem with a test framework that's not supported out of the box, you can write your own custom test framework adapter. See [customAdapter.js](https://github.com/testem/testem/blob/master/examples/custom_adapter/customAdapter.js) for an example of how to write a custom adapter.
615
+ If you want to use Testem with a test framework that's not supported out of the box, you can write your own custom test framework adapter. See [customAdapter.js](https://github.com/testem/testem/blob/main/examples/custom_adapter/customAdapter.js) for an example of how to write a custom adapter.
542
616
 
543
617
  Then, to use it, in your config file simply set
544
618
 
@@ -546,7 +620,7 @@ Then, to use it, in your config file simply set
546
620
  "framework": "custom"
547
621
  ```
548
622
 
549
- And then make sure you include the adapter code in your test suite and you are ready to go. See here for the [full example](https://github.com/testem/testem/tree/master/examples/custom_adapter).
623
+ And then make sure you include the adapter code in your test suite and you are ready to go. See here for the [full example](https://github.com/testem/testem/tree/main/examples/custom_adapter).
550
624
 
551
625
  Native notifications
552
626
  --------------------------------
@@ -576,7 +650,7 @@ Simply add a `proxies` section to the `testem.json` configuration file.
576
650
  ```
577
651
 
578
652
  This functionality is implemented as a *transparent proxy*, hence a request to
579
- `http://localhost:7357/api/posts.json` will be proxied to `http://localhost:4200/api/posts.json` without removing the `/api` prefix. Setting the `secure` option to `false` as in the above `/xmlapi` configuration block will ignore TLS certificate validation and allow tests to successfully reach that URL even if testem was launched over HTTP. Other available options can be found here: https://github.com/http-party/node-http-proxy#options
653
+ `http://localhost:7357/api/posts.json` will be proxied to `http://localhost:4200/api/posts.json` without removing the `/api` prefix. Setting the `secure` option to `false` as in the above `/xmlapi` configuration block will ignore TLS certificate validation and allow tests to successfully reach that URL even if testem was launched over HTTP. Other available options can be found here: https://github.com/unjs/httpxy#options
580
654
 
581
655
  To limit the functionality to only certain content types, use "onlyContentTypes".
582
656
 
@@ -585,16 +659,22 @@ Preprocessors (Babel, TypeScript, LESS, Sass, Browserify, CoffeeScript, etc)
585
659
 
586
660
  If you need to run a preprocessor (or indeed any shell command before the start of the tests) use the `before_tests` option, such as
587
661
 
588
- "before_tests": "coffee -c *.coffee"
662
+ "before_tests": "coffee -c hello.coffee tests.coffee"
663
+
664
+ On Windows, list files explicitly in string hooks like this—cmd.exe does not expand `*` for external programs (see [Available hooks](docs/config_file.md#available-hooks) and the [coffeescript example](examples/coffeescript)). Testem's own `src_files` / `watch_files` globs are expanded by Testem, not by the hook shell.
589
665
 
590
- or, with Babel (see the [Babel example](https://github.com/testem/testem/tree/master/examples/babel)):
666
+ or, with Babel (see the [Babel example](https://github.com/testem/testem/tree/main/examples/babel)):
591
667
 
592
668
  "before_tests": "babel src --out-dir ."
593
669
 
594
- or, with a `tsconfig.json` that emits JavaScript next to your project (see the [TypeScript example](https://github.com/testem/testem/tree/master/examples/typescript)):
670
+ or, with a `tsconfig.json` that emits JavaScript next to your project (see the [TypeScript example](https://github.com/testem/testem/tree/main/examples/typescript)):
595
671
 
596
672
  "before_tests": "tsc"
597
673
 
674
+ or, with Webpack + React (see the [Webpack + React example](https://github.com/testem/testem/tree/main/examples/webpack_react)):
675
+
676
+ "before_tests": "npx webpack"
677
+
598
678
  And Testem will run it before each test run. Point **`src_files`** at the sources you want
599
679
  watched (see **File watching** under Development Mode above).
600
680
 
@@ -625,29 +705,34 @@ If you would prefer simply to clean up when Testem exits, you can use the `on_ex
625
705
  Example Projects
626
706
  ----------------
627
707
 
628
- I've created [examples](https://github.com/testem/testem/tree/master/examples/) for various setups
629
-
630
- * [Vite (middleware + plugin)](https://github.com/testem/testem/tree/master/examples/vite)
631
- * [Electron](https://github.com/testem/testem/tree/master/examples/electron)
632
- * [TypeScript Project](https://github.com/testem/testem/tree/master/examples/typescript)
633
- * [ESLint Example](https://github.com/testem/testem/tree/master/examples/eslint)
634
- * [Babel Project](https://github.com/testem/testem/tree/master/examples/babel)
635
- * [Simple QUnit project](https://github.com/testem/testem/tree/master/examples/qunit_simple)
636
- * [Simple Jasmine project](https://github.com/testem/testem/tree/master/examples/jasmine_simple)
637
- * [Jasmine 2](https://github.com/testem/testem/tree/master/examples/jasmine2)
638
- * [Custom Jasmine project](https://github.com/testem/testem/tree/master/examples/jasmine_custom)
639
- * [Simple Mocha Project](https://github.com/testem/testem/tree/master/examples/mocha_simple)
640
- * [Mocha + Chai](https://github.com/testem/testem/tree/master/examples/mocha_chai_simple)
641
- * [Hybrid Project](https://github.com/testem/testem/tree/master/examples/hybrid_simple) - Mocha tests running in both the browser and Node.
642
- * [Custom Test Framework](https://github.com/testem/testem/tree/master/examples/custom_adapter)
643
- * [Tape Example](https://github.com/testem/testem/tree/master/examples/tape_example)
644
- * [Browserify Project](https://github.com/testem/testem/tree/master/examples/browserify)
645
- * [JSHint Example](https://github.com/testem/testem/tree/master/examples/jshint)
646
- * [Coffeescript Project](https://github.com/testem/testem/tree/master/examples/coffeescript)
647
- * [Custom Jasmine project using Require.js](https://github.com/testem/testem/tree/master/examples/jasmine_requirejs)
648
- * [BrowserStack Integration](https://github.com/testem/testem/tree/master/examples/browserstack)
649
- * [SauceLabs Integration](https://github.com/testem/testem/tree/master/examples/saucelabs)
650
- * [Code Coverage with Istanbul](https://github.com/testem/testem/tree/master/examples/coverage_istanbul)
708
+ I've created [examples](https://github.com/testem/testem/tree/main/examples/) for various setups
709
+
710
+ * [Vite (middleware + plugin)](https://github.com/testem/testem/tree/main/examples/vite)
711
+ * [Vitest](https://github.com/testem/testem/tree/main/examples/vitest) - Vitest via a TAP process launcher (`tap-flat`).
712
+ * [Electron](https://github.com/testem/testem/tree/main/examples/electron)
713
+ * [TypeScript Project](https://github.com/testem/testem/tree/main/examples/typescript)
714
+ * [ESLint Example](https://github.com/testem/testem/tree/main/examples/eslint)
715
+ * [Babel Project](https://github.com/testem/testem/tree/main/examples/babel)
716
+ * [Simple QUnit project](https://github.com/testem/testem/tree/main/examples/qunit_simple)
717
+ * [Simple Jasmine project](https://github.com/testem/testem/tree/main/examples/jasmine_simple)
718
+ * [Jasmine 2](https://github.com/testem/testem/tree/main/examples/jasmine2)
719
+ * [Custom Jasmine project](https://github.com/testem/testem/tree/main/examples/jasmine_custom)
720
+ * [Simple Mocha Project](https://github.com/testem/testem/tree/main/examples/mocha_simple)
721
+ * [Simple React](https://github.com/testem/testem/tree/main/examples/react_simple) - React 19 in a real browser via import maps, no bundler.
722
+ * [Mocha + Chai](https://github.com/testem/testem/tree/main/examples/mocha_chai_simple)
723
+ * [Hybrid Project](https://github.com/testem/testem/tree/main/examples/hybrid_simple) - Mocha tests running in both the browser and Node.
724
+ * [Jest](https://github.com/testem/testem/tree/main/examples/jest) - Node Jest via a TAP process launcher (`jest-tap-reporter`).
725
+ * [Custom Test Framework](https://github.com/testem/testem/tree/main/examples/custom_adapter)
726
+ * [Tape Example](https://github.com/testem/testem/tree/main/examples/tape_example)
727
+ * [Node.js test runner](https://github.com/testem/testem/tree/main/examples/node_test) - `node:test` via a TAP process launcher.
728
+ * [Browserify Project](https://github.com/testem/testem/tree/main/examples/browserify)
729
+ * [Webpack + React](https://github.com/testem/testem/tree/main/examples/webpack_react) - React Testing Library in a real browser via Webpack and Mocha.
730
+ * [JSHint Example](https://github.com/testem/testem/tree/main/examples/jshint)
731
+ * [Coffeescript Project](https://github.com/testem/testem/tree/main/examples/coffeescript)
732
+ * [Custom Jasmine project using Require.js](https://github.com/testem/testem/tree/main/examples/jasmine_requirejs)
733
+ * [BrowserStack Integration](https://github.com/testem/testem/tree/main/examples/browserstack)
734
+ * [SauceLabs Integration](https://github.com/testem/testem/tree/main/examples/saucelabs)
735
+ * [Code Coverage with Istanbul](https://github.com/testem/testem/tree/main/examples/coverage_istanbul)
651
736
 
652
737
  Historical Screencasts
653
738
  ----------------------
@@ -661,7 +746,7 @@ These YouTube screencasts are from around **2012** and may not match the current
661
746
  Contributing
662
747
  ------------
663
748
 
664
- If you want to [contribute to the project](https://github.com/testem/testem/blob/master/CONTRIBUTING.md), I am going to do my best to stay out of your way.
749
+ If you want to [contribute to the project](https://github.com/testem/testem/blob/main/CONTRIBUTING.md), I am going to do my best to stay out of your way.
665
750
 
666
751
  Core Maintainer(s)
667
752
  ------------------
package/lib/api.js CHANGED
@@ -25,7 +25,7 @@ const Server = require('./server');
25
25
  launch_in_dev: [Array] list of launchers to use for dev runs
26
26
  launch_in_ci: [Array] list of launchers to use for CI runs
27
27
  timeout: [Number] timeout for a browser
28
- framework: [String] test framework to use
28
+ framework: [String] test framework to use (jasmine [deprecated Jasmine 1.x], jasmine2, qunit, mocha, mocha+chai, custom, tap)
29
29
  url: [String] url server runs at (http://{host}:{port}/)
30
30
  src_files: [Array] list of files or file patterns to use
31
31
  src_files_ignore: [Array] list of files or file patterns to exclude from usage
@@ -1,7 +1,7 @@
1
1
 
2
2
 
3
+ const { inspect } = require('util');
3
4
  const indent = require('../utils/strutils').indent;
4
- const printf = require('printf');
5
5
  const displayutils = require('../utils/displayutils');
6
6
 
7
7
  module.exports = class DotReporter {
@@ -78,20 +78,20 @@ module.exports = class DotReporter {
78
78
  return;
79
79
  }
80
80
 
81
- printf(this.out, '%*d) [%s] %s\n', idx + 1, 3, data.launcher, result.name);
81
+ this.out.write(`${String(idx + 1).padStart(3)}) [${data.launcher}] ${result.name}\n`);
82
82
 
83
83
  if (error.message) {
84
- printf(this.out, ' %s\n', error.message);
84
+ this.out.write(` ${error.message}\n`);
85
85
  }
86
86
 
87
87
  if ('expected' in error && 'actual' in error) {
88
- printf(this.out, '\n' +
89
- ' expected: %s%O\n' +
90
- ' actual: %O\n', (error.negative ? 'NOT ' : ''), error.expected, error.actual);
88
+ this.out.write('\n' +
89
+ ` expected: ${error.negative ? 'NOT ' : ''}${inspect(error.expected)}\n` +
90
+ ` actual: ${inspect(error.actual)}\n`);
91
91
  }
92
92
 
93
93
  if (error.stack) {
94
- printf(this.out, '\n%s', indent(error.stack, 5));
94
+ this.out.write(`\n${indent(error.stack, 5)}`);
95
95
  }
96
96
 
97
97
  this.out.write('\n\n');
@@ -0,0 +1,18 @@
1
+ const { scriptTags, styleTags } = require('./html');
2
+
3
+ module.exports = function renderCustomRunner({
4
+ scripts, styles, footer_scripts
5
+ }) {
6
+ return `<!doctype html>
7
+ <html>
8
+ <head>
9
+ <title>Test'em</title>
10
+ <script src="/testem.js"></script>
11
+ ${scriptTags(scripts)}
12
+ ${styleTags(styles)}
13
+ </head>
14
+ <body>
15
+ </body>
16
+ ${scriptTags(footer_scripts)}
17
+ </html>`;
18
+ };
@@ -0,0 +1,12 @@
1
+ const { escapeHtml } = require('./html');
2
+
3
+ module.exports = function renderDirectoryListing({ files }) {
4
+ const items = (files || []).map(name => {
5
+ const safe = escapeHtml(name);
6
+ return `<li><a href="${safe}">${safe}</a></li>`;
7
+ }).join('');
8
+ return `<h1>Files In This Directory</h1>
9
+ <ul>
10
+ ${items}
11
+ </ul>`;
12
+ };
@@ -0,0 +1,45 @@
1
+ function escapeHtml(value) {
2
+ return String(value)
3
+ .replace(/&/g, '&amp;')
4
+ .replace(/</g, '&lt;')
5
+ .replace(/>/g, '&gt;')
6
+ .replace(/"/g, '&quot;');
7
+ }
8
+
9
+ function attrSuffix(attrs) {
10
+ return (attrs || []).map(attr => ` ${attr}`).join('');
11
+ }
12
+
13
+ function scriptTags(files) {
14
+ return (files || [])
15
+ .map(file => `<script src="${file.src}"${attrSuffix(file.attrs)}></script>`)
16
+ .join('');
17
+ }
18
+
19
+ function asHrefList(hrefs) {
20
+ if (hrefs === undefined || hrefs === null || hrefs === '') {
21
+ return [];
22
+ }
23
+ return Array.isArray(hrefs) ? hrefs : [hrefs];
24
+ }
25
+
26
+ function styleTags(hrefs) {
27
+ return asHrefList(hrefs)
28
+ .map(href => `<link rel="stylesheet" href="${escapeHtml(href)}">`)
29
+ .join('');
30
+ }
31
+
32
+ function loadScriptCalls(files) {
33
+ return (files || []).map(file => {
34
+ const extra = (file.attrs || []).map(attr => `, '${attr}'`).join('');
35
+ return `await loadScript('${file.src}'${extra});`;
36
+ }).join('\n');
37
+ }
38
+
39
+ module.exports = {
40
+ escapeHtml,
41
+ attrSuffix,
42
+ scriptTags,
43
+ styleTags,
44
+ loadScriptCalls
45
+ };
@@ -0,0 +1,19 @@
1
+ const pages = {
2
+ jasmine: require('./jasmine'),
3
+ jasmine2: require('./jasmine2'),
4
+ qunit: require('./qunit'),
5
+ mocha: require('./mocha'),
6
+ 'mocha+chai': require('./mocha_chai'),
7
+ custom: require('./custom'),
8
+ tap: require('./tap')
9
+ };
10
+
11
+ function renderRunner(framework, data) {
12
+ const render = pages[framework];
13
+ return render ? render(data) : null;
14
+ }
15
+
16
+ module.exports = {
17
+ renderRunner,
18
+ renderDirectoryListing: require('./directory')
19
+ };
@@ -1,4 +1,9 @@
1
- <!doctype html>
1
+ const { scriptTags, styleTags } = require('./html');
2
+
3
+ module.exports = function renderJasmineRunner({
4
+ scripts, styles, footer_scripts
5
+ }) {
6
+ return `<!doctype html>
2
7
  <html>
3
8
  <head>
4
9
  <title>Test'em</title>
@@ -16,14 +21,15 @@
16
21
  })();
17
22
  </script>
18
23
 
19
- {{#scripts}}<script src="{{{src}}}"{{#attrs}} {{&.}}{{/attrs}}></script>{{/scripts}}
24
+ ${scriptTags(scripts)}
20
25
 
21
26
  <link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/jasmine/1.3.1/jasmine.css">
22
27
 
23
- {{#styles}}<link rel="stylesheet" href="{{.}}">{{/styles}}
28
+ ${styleTags(styles)}
24
29
  </head>
25
30
  <body>
26
31
  <div id="jasmine_content"></div>
27
32
  </body>
28
- {{#footer_scripts}}<script src="{{{src}}}"{{#attrs}} {{&.}}{{/attrs}}></script>{{/footer_scripts}}
29
- </html>
33
+ ${scriptTags(footer_scripts)}
34
+ </html>`;
35
+ };
@@ -0,0 +1,38 @@
1
+ const { scriptTags, styleTags } = require('./html');
2
+
3
+ module.exports = function renderJasmine2Runner({
4
+ jasmineJs,
5
+ jasmineHtml,
6
+ jasmineCss,
7
+ jasmineBoot,
8
+ jasmineCoreV5,
9
+ scripts,
10
+ styles,
11
+ footer_scripts
12
+ }) {
13
+ const boot = jasmineCoreV5
14
+ ? `<script src="/node_modules/jasmine-core/lib/jasmine-core/boot0.js"></script>
15
+ <script src="/node_modules/jasmine-core/lib/jasmine-core/boot1.js"></script>`
16
+ : `<script src="${jasmineBoot || ''}"></script>`;
17
+
18
+ return `<!doctype html>
19
+ <html>
20
+ <head>
21
+ <title>Test'em</title>
22
+ <script src="${jasmineJs}"></script>
23
+ <script src="${jasmineHtml}"></script>
24
+ ${boot}
25
+ <script src="/testem.js"></script>
26
+
27
+ ${scriptTags(scripts)}
28
+
29
+ <link rel="stylesheet" href="${jasmineCss}">
30
+
31
+ ${styleTags(styles)}
32
+ </head>
33
+ <body>
34
+ <div id="jasmine_content"></div>
35
+ </body>
36
+ ${scriptTags(footer_scripts)}
37
+ </html>`;
38
+ };
@@ -0,0 +1,25 @@
1
+ const { scriptTags, styleTags } = require('./html');
2
+
3
+ module.exports = function renderMochaRunner({
4
+ mochaCss, mochaJs, scripts, styles, footer_scripts
5
+ }) {
6
+ return `<!doctype html>
7
+ <html>
8
+ <head>
9
+ <title>Test'em</title>
10
+ <link rel="stylesheet" href="${mochaCss}">
11
+ <script src="${mochaJs}"></script>
12
+ <script src="/testem.js"></script>
13
+ <script>mocha.setup('bdd')</script>
14
+ ${scriptTags(scripts)}
15
+ ${styleTags(styles)}
16
+ </head>
17
+ <body>
18
+ <div id="mocha"></div>
19
+ ${scriptTags(footer_scripts)}
20
+ <script>
21
+ mocha.run()
22
+ </script>
23
+ </body>
24
+ </html>`;
25
+ };