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 +128 -43
- package/lib/api.js +1 -1
- package/lib/reporters/dot_reporter.js +7 -7
- package/lib/runner_pages/custom.js +18 -0
- package/lib/runner_pages/directory.js +12 -0
- package/lib/runner_pages/html.js +45 -0
- package/lib/runner_pages/index.js +19 -0
- package/{views/jasminerunner.mustache → lib/runner_pages/jasmine.js} +11 -5
- package/lib/runner_pages/jasmine2.js +38 -0
- package/lib/runner_pages/mocha.js +25 -0
- package/lib/runner_pages/mocha_chai.js +83 -0
- package/lib/runner_pages/qunit.js +22 -0
- package/{views/taprunner.mustache → lib/runner_pages/tap.js} +9 -5
- package/lib/server/index.js +74 -38
- package/lib/utils/jasmine1_deprecation.js +27 -0
- package/lib/utils/mustache_test_page_deprecation.js +27 -0
- package/lib/utils/promises.js +6 -1
- package/lib/utils/report-file.js +7 -13
- package/lib/utils/runner_framework_assets.js +154 -0
- package/package.json +15 -23
- package/public/testem/jasmine_adapter.js +7 -1
- package/views/customrunner.mustache +0 -12
- package/views/directorylisting.mustache +0 -4
- package/views/jasmine2runner.mustache +0 -20
- package/views/mochachairunner.mustache +0 -19
- package/views/mocharunner.mustache +0 -19
- package/views/qunitrunner.mustache +0 -16
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Got Scripts? Test’em!
|
|
2
2
|
=================
|
|
3
3
|
|
|
4
|
-
[](https://github.com/testem/testem/actions/workflows/ci.yml?query=branch%3Amain) [](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 **>=
|
|
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
|
-

|
|
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
|
-

|
|
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
|
-

|
|
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
|
-

|
|
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/
|
|
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/
|
|
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/
|
|
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": "
|
|
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
|
-
|
|
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/
|
|
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/
|
|
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/
|
|
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
|
|
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/
|
|
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/
|
|
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/
|
|
629
|
-
|
|
630
|
-
* [Vite (middleware + plugin)](https://github.com/testem/testem/tree/
|
|
631
|
-
* [
|
|
632
|
-
* [
|
|
633
|
-
* [
|
|
634
|
-
* [
|
|
635
|
-
* [
|
|
636
|
-
* [Simple
|
|
637
|
-
* [Jasmine
|
|
638
|
-
* [
|
|
639
|
-
* [
|
|
640
|
-
* [Mocha
|
|
641
|
-
* [
|
|
642
|
-
* [
|
|
643
|
-
* [
|
|
644
|
-
* [
|
|
645
|
-
* [
|
|
646
|
-
* [
|
|
647
|
-
* [
|
|
648
|
-
* [
|
|
649
|
-
* [
|
|
650
|
-
* [
|
|
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/
|
|
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
|
-
|
|
81
|
+
this.out.write(`${String(idx + 1).padStart(3)}) [${data.launcher}] ${result.name}\n`);
|
|
82
82
|
|
|
83
83
|
if (error.message) {
|
|
84
|
-
|
|
84
|
+
this.out.write(` ${error.message}\n`);
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
if ('expected' in error && 'actual' in error) {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
-
|
|
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, '&')
|
|
4
|
+
.replace(/</g, '<')
|
|
5
|
+
.replace(/>/g, '>')
|
|
6
|
+
.replace(/"/g, '"');
|
|
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
|
-
|
|
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
|
-
{
|
|
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
|
-
{
|
|
28
|
+
${styleTags(styles)}
|
|
24
29
|
</head>
|
|
25
30
|
<body>
|
|
26
31
|
<div id="jasmine_content"></div>
|
|
27
32
|
</body>
|
|
28
|
-
{
|
|
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
|
+
};
|