mocha 10.4.0 → 10.5.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 +7 -7
- package/browser-entry.js +2 -2
- package/lib/cli/collect-files.js +49 -7
- package/lib/cli/options.js +13 -4
- package/lib/cli/run-helpers.js +47 -6
- package/lib/cli/watch-run.js +2 -2
- package/lib/nodejs/reporters/parallel-buffered.js +1 -1
- package/lib/nodejs/serializer.js +1 -1
- package/lib/reporters/html.js +27 -22
- package/mocha.css +54 -17
- package/mocha.js +30 -163
- package/mocha.js.map +1 -1
- package/package.json +2 -8
- package/lib/browser/progress.js +0 -138
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<p align="center">☕️ Simple, flexible, fun JavaScript test framework for Node.js & The Browser ☕️</p>
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
|
-
<a href="https://github.com/mochajs/mocha/actions?query=workflow%3ATests+branch%
|
|
8
|
+
<a href="https://github.com/mochajs/mocha/actions?query=workflow%3ATests+branch%3Amain"><img src="https://github.com/mochajs/mocha/workflows/Tests/badge.svg?branch=main" alt="GitHub Actions Build Status"></a>
|
|
9
9
|
<a href="https://coveralls.io/github/mochajs/mocha"><img src="https://coveralls.io/repos/github/mochajs/mocha/badge.svg" alt="Coverage Status"></a>
|
|
10
10
|
<a href="https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmochajs%2Fmocha?ref=badge_shield"><img src="https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmochajs%2Fmocha.svg?type=shield" alt="FOSSA Status"></a>
|
|
11
11
|
<a href="https://discord.gg/KeDn2uXhER"><img alt="Chat - Discord" src="https://img.shields.io/badge/chat-Discord-5765F2.svg" /></a>
|
|
@@ -23,10 +23,10 @@
|
|
|
23
23
|
## Links
|
|
24
24
|
|
|
25
25
|
- **[Documentation](https://mochajs.org)**
|
|
26
|
-
- **[Release Notes / History / Changes](https://github.com/mochajs/mocha/blob/
|
|
27
|
-
- [Code of Conduct](https://github.com/mochajs/mocha/blob/
|
|
28
|
-
- [Contributing](https://github.com/mochajs/mocha/blob/
|
|
29
|
-
- [Development](https://github.com/mochajs/mocha/blob/
|
|
26
|
+
- **[Release Notes / History / Changes](https://github.com/mochajs/mocha/blob/main/CHANGELOG.md)**
|
|
27
|
+
- [Code of Conduct](https://github.com/mochajs/mocha/blob/main/.github/CODE_OF_CONDUCT.md)
|
|
28
|
+
- [Contributing](https://github.com/mochajs/mocha/blob/main/.github/CONTRIBUTING.md)
|
|
29
|
+
- [Development](https://github.com/mochajs/mocha/blob/main/.github/DEVELOPMENT.md)
|
|
30
30
|
- [Discord](https://discord.gg/KeDn2uXhER) (ask questions here!)
|
|
31
31
|
- [Issue Tracker](https://github.com/mochajs/mocha/issues)
|
|
32
32
|
|
|
@@ -59,7 +59,7 @@ You might want to help:
|
|
|
59
59
|
|
|
60
60
|
- New to contributing to Mocha? Check out this list of [good first issues](https://github.com/mochajs/mocha/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22)
|
|
61
61
|
- Mocha could use a hand with [these issues](https://github.com/mochajs/mocha/issues?q=is%3Aopen+is%3Aissue+label%3A%22status%3A+accepting+prs%22)
|
|
62
|
-
- The [maintainer's handbook](https://github.com/mochajs/mocha/blob/
|
|
62
|
+
- The [maintainer's handbook](https://github.com/mochajs/mocha/blob/main/MAINTAINERS.md) explains how things get done
|
|
63
63
|
|
|
64
64
|
Finally, come [chat with the maintainers on Discord](https://discord.gg/KeDn2uXhER) if you want to help with:
|
|
65
65
|
|
|
@@ -69,6 +69,6 @@ Finally, come [chat with the maintainers on Discord](https://discord.gg/KeDn2uXh
|
|
|
69
69
|
|
|
70
70
|
## License
|
|
71
71
|
|
|
72
|
-
Copyright 2011-2022 OpenJS Foundation and contributors. Licensed [MIT](https://github.com/mochajs/mocha/blob/
|
|
72
|
+
Copyright 2011-2022 OpenJS Foundation and contributors. Licensed [MIT](https://github.com/mochajs/mocha/blob/main/LICENSE).
|
|
73
73
|
|
|
74
74
|
[](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmochajs%2Fmocha?ref=badge_large)
|
package/browser-entry.js
CHANGED
|
@@ -71,8 +71,8 @@ process.listenerCount = function (name) {
|
|
|
71
71
|
|
|
72
72
|
process.on = function (e, fn) {
|
|
73
73
|
if (e === 'uncaughtException') {
|
|
74
|
-
global.onerror = function (
|
|
75
|
-
fn(new Error(
|
|
74
|
+
global.onerror = function (msg, url, line, col, err) {
|
|
75
|
+
fn(err || new Error(msg + ' (' + url + ':' + line + ':' + col + ')'));
|
|
76
76
|
return !mocha.options.allowUncaught;
|
|
77
77
|
};
|
|
78
78
|
uncaughtExceptionHandlers.push(fn);
|
package/lib/cli/collect-files.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const fs = require('fs');
|
|
3
4
|
const path = require('path');
|
|
4
5
|
const ansi = require('ansi-colors');
|
|
5
6
|
const debug = require('debug')('mocha:cli:run:helpers');
|
|
@@ -19,7 +20,7 @@ const {castArray} = require('../utils');
|
|
|
19
20
|
/**
|
|
20
21
|
* Smash together an array of test files in the correct order
|
|
21
22
|
* @param {FileCollectionOptions} [opts] - Options
|
|
22
|
-
* @returns {
|
|
23
|
+
* @returns {FileCollectionResponse} An object containing a list of files to test and unmatched files.
|
|
23
24
|
* @private
|
|
24
25
|
*/
|
|
25
26
|
module.exports = ({
|
|
@@ -30,7 +31,7 @@ module.exports = ({
|
|
|
30
31
|
sort,
|
|
31
32
|
spec
|
|
32
33
|
} = {}) => {
|
|
33
|
-
const
|
|
34
|
+
const unmatchedSpecFiles = [];
|
|
34
35
|
const specFiles = spec.reduce((specFiles, arg) => {
|
|
35
36
|
try {
|
|
36
37
|
const moreSpecFiles = castArray(lookupFiles(arg, extension, recursive))
|
|
@@ -44,7 +45,7 @@ module.exports = ({
|
|
|
44
45
|
return [...specFiles, ...moreSpecFiles];
|
|
45
46
|
} catch (err) {
|
|
46
47
|
if (err.code === NO_FILES_MATCH_PATTERN) {
|
|
47
|
-
|
|
48
|
+
unmatchedSpecFiles.push({message: err.message, pattern: err.pattern});
|
|
48
49
|
return specFiles;
|
|
49
50
|
}
|
|
50
51
|
|
|
@@ -52,6 +53,27 @@ module.exports = ({
|
|
|
52
53
|
}
|
|
53
54
|
}, []);
|
|
54
55
|
|
|
56
|
+
// check that each file passed in to --file exists
|
|
57
|
+
|
|
58
|
+
const unmatchedFiles = [];
|
|
59
|
+
fileArgs.forEach(file => {
|
|
60
|
+
const fileAbsolutePath = path.resolve(file);
|
|
61
|
+
try {
|
|
62
|
+
// Used instead of fs.existsSync to ensure that file-ending less files are still resolved correctly
|
|
63
|
+
require.resolve(fileAbsolutePath);
|
|
64
|
+
} catch (err) {
|
|
65
|
+
if (err.code === 'MODULE_NOT_FOUND') {
|
|
66
|
+
unmatchedFiles.push({
|
|
67
|
+
pattern: file,
|
|
68
|
+
absolutePath: fileAbsolutePath
|
|
69
|
+
});
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
throw err;
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
55
77
|
// ensure we don't sort the stuff from fileArgs; order is important!
|
|
56
78
|
if (sort) {
|
|
57
79
|
specFiles.sort();
|
|
@@ -67,19 +89,24 @@ module.exports = ({
|
|
|
67
89
|
if (!files.length) {
|
|
68
90
|
// give full message details when only 1 file is missing
|
|
69
91
|
const noneFoundMsg =
|
|
70
|
-
|
|
71
|
-
? `Error: No test files found: ${JSON.stringify(
|
|
92
|
+
unmatchedSpecFiles.length === 1
|
|
93
|
+
? `Error: No test files found: ${JSON.stringify(
|
|
94
|
+
unmatchedSpecFiles[0].pattern
|
|
95
|
+
)}` // stringify to print escaped characters raw
|
|
72
96
|
: 'Error: No test files found';
|
|
73
97
|
console.error(ansi.red(noneFoundMsg));
|
|
74
98
|
process.exit(1);
|
|
75
99
|
} else {
|
|
76
100
|
// print messages as a warning
|
|
77
|
-
|
|
101
|
+
unmatchedSpecFiles.forEach(warning => {
|
|
78
102
|
console.warn(ansi.yellow(`Warning: ${warning.message}`));
|
|
79
103
|
});
|
|
80
104
|
}
|
|
81
105
|
|
|
82
|
-
return
|
|
106
|
+
return {
|
|
107
|
+
files,
|
|
108
|
+
unmatchedFiles
|
|
109
|
+
};
|
|
83
110
|
};
|
|
84
111
|
|
|
85
112
|
/**
|
|
@@ -93,3 +120,18 @@ module.exports = ({
|
|
|
93
120
|
* @property {boolean} recursive - Find files recursively
|
|
94
121
|
* @property {boolean} sort - Sort test files
|
|
95
122
|
*/
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Diagnostic object containing unmatched files
|
|
126
|
+
* @typedef {Object} UnmatchedFile -
|
|
127
|
+
* @property {string} absolutePath - A list of unmatched files derived from the file arguments passed in.
|
|
128
|
+
* @property {string} pattern - A list of unmatched files derived from the file arguments passed in.
|
|
129
|
+
*
|
|
130
|
+
*/
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Response object containing a list of files to test and unmatched files.
|
|
134
|
+
* @typedef {Object} FileCollectionResponse
|
|
135
|
+
* @property {string[]} files - A list of files to test
|
|
136
|
+
* @property {UnmatchedFile[]} unmatchedFiles - A list of unmatched files derived from the file arguments passed in.
|
|
137
|
+
*/
|
package/lib/cli/options.js
CHANGED
|
@@ -208,9 +208,10 @@ module.exports.loadPkgRc = loadPkgRc;
|
|
|
208
208
|
* Priority list:
|
|
209
209
|
*
|
|
210
210
|
* 1. Command-line args
|
|
211
|
-
* 2.
|
|
212
|
-
* 3.
|
|
213
|
-
* 4.
|
|
211
|
+
* 2. `MOCHA_OPTIONS` environment variable.
|
|
212
|
+
* 3. RC file (`.mocharc.c?js`, `.mocharc.ya?ml`, `mocharc.json`)
|
|
213
|
+
* 4. `mocha` prop of `package.json`
|
|
214
|
+
* 5. default configuration (`lib/mocharc.json`)
|
|
214
215
|
*
|
|
215
216
|
* If a {@link module:lib/cli/one-and-dones.ONE_AND_DONE_ARGS "one-and-done" option} is present in the `argv` array, no external config files will be read.
|
|
216
217
|
* @summary Parses options read from `.mocharc.*` and `package.json`.
|
|
@@ -231,6 +232,7 @@ const loadOptions = (argv = []) => {
|
|
|
231
232
|
return args;
|
|
232
233
|
}
|
|
233
234
|
|
|
235
|
+
const envConfig = parse(process.env.MOCHA_OPTIONS || '');
|
|
234
236
|
const rcConfig = loadRc(args);
|
|
235
237
|
const pkgConfig = loadPkgRc(args);
|
|
236
238
|
|
|
@@ -243,7 +245,14 @@ const loadOptions = (argv = []) => {
|
|
|
243
245
|
args._ = args._.concat(pkgConfig._ || []);
|
|
244
246
|
}
|
|
245
247
|
|
|
246
|
-
args = parse(
|
|
248
|
+
args = parse(
|
|
249
|
+
args._,
|
|
250
|
+
mocharc,
|
|
251
|
+
args,
|
|
252
|
+
envConfig,
|
|
253
|
+
rcConfig || {},
|
|
254
|
+
pkgConfig || {}
|
|
255
|
+
);
|
|
247
256
|
|
|
248
257
|
// recombine positional arguments and "spec"
|
|
249
258
|
if (args.spec) {
|
package/lib/cli/run-helpers.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
const fs = require('fs');
|
|
11
11
|
const path = require('path');
|
|
12
|
+
const ansi = require('ansi-colors');
|
|
12
13
|
const debug = require('debug')('mocha:cli:run:helpers');
|
|
13
14
|
const {watchRun, watchParallelRun} = require('./watch-run');
|
|
14
15
|
const collectFiles = require('./collect-files');
|
|
@@ -16,6 +17,7 @@ const {format} = require('util');
|
|
|
16
17
|
const {createInvalidLegacyPluginError} = require('../errors');
|
|
17
18
|
const {requireOrImport} = require('../nodejs/esm-utils');
|
|
18
19
|
const PluginLoader = require('../plugin-loader');
|
|
20
|
+
const {UnmatchedFile} = require('./collect-files');
|
|
19
21
|
|
|
20
22
|
/**
|
|
21
23
|
* Exits Mocha when tests + code under test has finished execution (default)
|
|
@@ -106,6 +108,32 @@ exports.handleRequires = async (requires = [], {ignoredPlugins = []} = {}) => {
|
|
|
106
108
|
return plugins;
|
|
107
109
|
};
|
|
108
110
|
|
|
111
|
+
/**
|
|
112
|
+
* Logs errors and exits the app if unmatched files exist
|
|
113
|
+
* @param {Mocha} mocha - Mocha instance
|
|
114
|
+
* @param {UnmatchedFile} unmatchedFiles - object containing unmatched file paths
|
|
115
|
+
* @returns {Promise<Runner>}
|
|
116
|
+
* @private
|
|
117
|
+
*/
|
|
118
|
+
const handleUnmatchedFiles = (mocha, unmatchedFiles) => {
|
|
119
|
+
if (unmatchedFiles.length === 0) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
unmatchedFiles.forEach(({pattern, absolutePath}) => {
|
|
124
|
+
console.error(
|
|
125
|
+
ansi.yellow(
|
|
126
|
+
`Warning: Cannot find any files matching pattern "${pattern}" at the absolute path "${absolutePath}"`
|
|
127
|
+
)
|
|
128
|
+
);
|
|
129
|
+
});
|
|
130
|
+
console.log(
|
|
131
|
+
'No test file(s) found with the given pattern, exiting with code 1'
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
return mocha.run(exitMocha(1));
|
|
135
|
+
};
|
|
136
|
+
|
|
109
137
|
/**
|
|
110
138
|
* Collect and load test files, then run mocha instance.
|
|
111
139
|
* @param {Mocha} mocha - Mocha instance
|
|
@@ -117,9 +145,14 @@ exports.handleRequires = async (requires = [], {ignoredPlugins = []} = {}) => {
|
|
|
117
145
|
* @private
|
|
118
146
|
*/
|
|
119
147
|
const singleRun = async (mocha, {exit}, fileCollectParams) => {
|
|
120
|
-
const
|
|
121
|
-
|
|
122
|
-
|
|
148
|
+
const fileCollectionObj = collectFiles(fileCollectParams);
|
|
149
|
+
|
|
150
|
+
if (fileCollectionObj.unmatchedFiles.length > 0) {
|
|
151
|
+
return handleUnmatchedFiles(mocha, fileCollectionObj.unmatchedFiles);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
debug('single run with %d file(s)', fileCollectionObj.files.length);
|
|
155
|
+
mocha.files = fileCollectionObj.files;
|
|
123
156
|
|
|
124
157
|
// handles ESM modules
|
|
125
158
|
await mocha.loadFilesAsync();
|
|
@@ -140,9 +173,17 @@ const singleRun = async (mocha, {exit}, fileCollectParams) => {
|
|
|
140
173
|
* @private
|
|
141
174
|
*/
|
|
142
175
|
const parallelRun = async (mocha, options, fileCollectParams) => {
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
176
|
+
const fileCollectionObj = collectFiles(fileCollectParams);
|
|
177
|
+
|
|
178
|
+
if (fileCollectionObj.unmatchedFiles.length > 0) {
|
|
179
|
+
return handleUnmatchedFiles(mocha, fileCollectionObj.unmatchedFiles);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
debug(
|
|
183
|
+
'executing %d test file(s) in parallel mode',
|
|
184
|
+
fileCollectionObj.files.length
|
|
185
|
+
);
|
|
186
|
+
mocha.files = fileCollectionObj.files;
|
|
146
187
|
|
|
147
188
|
// note that we DO NOT load any files here; this is handled by the worker
|
|
148
189
|
return mocha.run(options.exit ? exitMocha : exitMochaLater);
|
package/lib/cli/watch-run.js
CHANGED
|
@@ -58,7 +58,7 @@ exports.watchParallelRun = (
|
|
|
58
58
|
newMocha.suite.ctx = new Context();
|
|
59
59
|
|
|
60
60
|
// reset the list of files
|
|
61
|
-
newMocha.files = collectFiles(fileCollectParams);
|
|
61
|
+
newMocha.files = collectFiles(fileCollectParams).files;
|
|
62
62
|
|
|
63
63
|
// because we've swapped out the root suite (see the `run` inner function
|
|
64
64
|
// in `createRerunner`), we need to call `mocha.ui()` again to set up the context/globals.
|
|
@@ -120,7 +120,7 @@ exports.watchRun = (mocha, {watchFiles, watchIgnore}, fileCollectParams) => {
|
|
|
120
120
|
newMocha.suite.ctx = new Context();
|
|
121
121
|
|
|
122
122
|
// reset the list of files
|
|
123
|
-
newMocha.files = collectFiles(fileCollectParams);
|
|
123
|
+
newMocha.files = collectFiles(fileCollectParams).files;
|
|
124
124
|
|
|
125
125
|
// because we've swapped out the root suite (see the `run` inner function
|
|
126
126
|
// in `createRerunner`), we need to call `mocha.ui()` again to set up the context/globals.
|
|
@@ -54,7 +54,7 @@ const ONCE_EVENT_NAMES = [EVENT_DELAY_BEGIN, EVENT_DELAY_END];
|
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
56
|
* The `ParallelBuffered` reporter is used by each worker process in "parallel"
|
|
57
|
-
* mode, by default. Instead of reporting to
|
|
57
|
+
* mode, by default. Instead of reporting to `STDOUT`, etc., it retains a
|
|
58
58
|
* list of events it receives and hands these off to the callback passed into
|
|
59
59
|
* {@link Mocha#run}. That callback will then return the data to the main
|
|
60
60
|
* process.
|
package/lib/nodejs/serializer.js
CHANGED
|
@@ -117,7 +117,7 @@ class SerializableEvent {
|
|
|
117
117
|
/**
|
|
118
118
|
* Constructs a `SerializableEvent`, throwing if we receive unexpected data.
|
|
119
119
|
*
|
|
120
|
-
* Practically, events emitted from `Runner` have a
|
|
120
|
+
* Practically, events emitted from `Runner` have a minimum of zero (0)
|
|
121
121
|
* arguments-- (for example, {@link Runnable.constants.EVENT_RUN_BEGIN}) and a
|
|
122
122
|
* maximum of two (2) (for example,
|
|
123
123
|
* {@link Runnable.constants.EVENT_TEST_FAIL}, where the second argument is an
|
package/lib/reporters/html.js
CHANGED
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
|
|
11
11
|
var Base = require('./base');
|
|
12
12
|
var utils = require('../utils');
|
|
13
|
-
var Progress = require('../browser/progress');
|
|
14
13
|
var escapeRe = require('escape-string-regexp');
|
|
15
14
|
var constants = require('../runner').constants;
|
|
16
15
|
var EVENT_TEST_PASS = constants.EVENT_TEST_PASS;
|
|
@@ -38,7 +37,7 @@ exports = module.exports = HTML;
|
|
|
38
37
|
|
|
39
38
|
var statsTemplate =
|
|
40
39
|
'<ul id="mocha-stats">' +
|
|
41
|
-
'<li class="progress"><
|
|
40
|
+
'<li class="progress-contain"><progress class="progress-element" max="100" value="0"></progress><svg class="progress-ring"><circle class="ring-flatlight" stroke-dasharray="100%,0%"/><circle class="ring-highlight" stroke-dasharray="0%,100%"/></svg><div class="progress-text">0%</div></li>' +
|
|
42
41
|
'<li class="passes"><a href="javascript:void(0);">passes:</a> <em>0</em></li>' +
|
|
43
42
|
'<li class="failures"><a href="javascript:void(0);">failures:</a> <em>0</em></li>' +
|
|
44
43
|
'<li class="duration">duration: <em>0</em>s</li>' +
|
|
@@ -68,24 +67,16 @@ function HTML(runner, options) {
|
|
|
68
67
|
var failures = items[2].getElementsByTagName('em')[0];
|
|
69
68
|
var failuresLink = items[2].getElementsByTagName('a')[0];
|
|
70
69
|
var duration = items[3].getElementsByTagName('em')[0];
|
|
71
|
-
var canvas = stat.getElementsByTagName('canvas')[0];
|
|
72
70
|
var report = fragment('<ul id="mocha-report"></ul>');
|
|
73
71
|
var stack = [report];
|
|
74
|
-
var
|
|
75
|
-
var
|
|
72
|
+
var progressText = items[0].getElementsByTagName('div')[0];
|
|
73
|
+
var progressBar = items[0].getElementsByTagName('progress')[0];
|
|
74
|
+
var progressRing = [
|
|
75
|
+
items[0].getElementsByClassName('ring-flatlight')[0],
|
|
76
|
+
items[0].getElementsByClassName('ring-highlight')[0]];
|
|
77
|
+
var progressRingRadius = null; // computed CSS unavailable now, so set later
|
|
76
78
|
var root = document.getElementById('mocha');
|
|
77
79
|
|
|
78
|
-
if (canvas.getContext) {
|
|
79
|
-
var ratio = window.devicePixelRatio || 1;
|
|
80
|
-
canvas.style.width = canvas.width;
|
|
81
|
-
canvas.style.height = canvas.height;
|
|
82
|
-
canvas.width *= ratio;
|
|
83
|
-
canvas.height *= ratio;
|
|
84
|
-
ctx = canvas.getContext('2d');
|
|
85
|
-
ctx.scale(ratio, ratio);
|
|
86
|
-
progress = new Progress();
|
|
87
|
-
}
|
|
88
|
-
|
|
89
80
|
if (!root) {
|
|
90
81
|
return error('#mocha div missing, add it to your document');
|
|
91
82
|
}
|
|
@@ -115,10 +106,6 @@ function HTML(runner, options) {
|
|
|
115
106
|
root.appendChild(stat);
|
|
116
107
|
root.appendChild(report);
|
|
117
108
|
|
|
118
|
-
if (progress) {
|
|
119
|
-
progress.size(40);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
109
|
runner.on(EVENT_SUITE_BEGIN, function (suite) {
|
|
123
110
|
if (suite.root) {
|
|
124
111
|
return;
|
|
@@ -234,8 +221,26 @@ function HTML(runner, options) {
|
|
|
234
221
|
function updateStats() {
|
|
235
222
|
// TODO: add to stats
|
|
236
223
|
var percent = ((stats.tests / runner.total) * 100) | 0;
|
|
237
|
-
|
|
238
|
-
|
|
224
|
+
progressBar.value = percent;
|
|
225
|
+
if (progressText) {
|
|
226
|
+
// setting a toFixed that is too low, makes small changes to progress not shown
|
|
227
|
+
// setting it too high, makes the progress text longer then it needs to
|
|
228
|
+
// to address this, calculate the toFixed based on the magnitude of total
|
|
229
|
+
var decimalPlaces = Math.ceil(Math.log10(runner.total / 100));
|
|
230
|
+
text(
|
|
231
|
+
progressText,
|
|
232
|
+
percent.toFixed(Math.min(Math.max(decimalPlaces, 0), 100)) + '%'
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
if (progressRing) {
|
|
236
|
+
var radius = parseFloat(getComputedStyle(progressRing[0]).getPropertyValue('r'));
|
|
237
|
+
var wholeArc = Math.PI * 2 * radius;
|
|
238
|
+
var highlightArc = percent * (wholeArc / 100);
|
|
239
|
+
// The progress ring is in 2 parts, the flatlight color and highlight color.
|
|
240
|
+
// Rendering both on top of the other, seems to make a 3rd color on the edges.
|
|
241
|
+
// To create 1 whole ring with 2 colors, both parts are inverse of the other.
|
|
242
|
+
progressRing[0].style['stroke-dasharray'] = `0,${highlightArc}px,${wholeArc}px`;
|
|
243
|
+
progressRing[1].style['stroke-dasharray'] = `${highlightArc}px,${wholeArc}px`;
|
|
239
244
|
}
|
|
240
245
|
|
|
241
246
|
// update stats
|
package/mocha.css
CHANGED
|
@@ -22,6 +22,9 @@
|
|
|
22
22
|
--mocha-stats-color: #888;
|
|
23
23
|
--mocha-stats-em-color: #000;
|
|
24
24
|
--mocha-stats-hover-color: #eee;
|
|
25
|
+
--mocha-progress-ring-color: #eee;
|
|
26
|
+
--mocha-progress-ring-highlight-color: #9f9f9f;
|
|
27
|
+
--mocha-progress-text-color: #000;
|
|
25
28
|
--mocha-error-color: #c00;
|
|
26
29
|
|
|
27
30
|
--mocha-code-comment: #ddd;
|
|
@@ -54,6 +57,9 @@
|
|
|
54
57
|
--mocha-stats-color: #aaa;
|
|
55
58
|
--mocha-stats-em-color: #fff;
|
|
56
59
|
--mocha-stats-hover-color: #444;
|
|
60
|
+
--mocha-progress-ring-color: #444;
|
|
61
|
+
--mocha-progress-ring-highlight-color: #888;
|
|
62
|
+
--mocha-progress-text-color: #fff;
|
|
57
63
|
--mocha-error-color: #f44;
|
|
58
64
|
|
|
59
65
|
--mocha-code-comment: #ddd;
|
|
@@ -325,6 +331,10 @@ body {
|
|
|
325
331
|
}
|
|
326
332
|
|
|
327
333
|
#mocha-stats {
|
|
334
|
+
--ring-container-size: 40px;
|
|
335
|
+
--ring-size: 39px;
|
|
336
|
+
--ring-radius: calc(var(--ring-size) / 2);
|
|
337
|
+
|
|
328
338
|
position: fixed;
|
|
329
339
|
top: 15px;
|
|
330
340
|
right: 10px;
|
|
@@ -334,20 +344,52 @@ body {
|
|
|
334
344
|
z-index: 1;
|
|
335
345
|
}
|
|
336
346
|
|
|
337
|
-
#mocha-stats .progress {
|
|
347
|
+
#mocha-stats .progress-contain {
|
|
338
348
|
float: right;
|
|
339
|
-
padding
|
|
349
|
+
padding: 0;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
#mocha-stats :is(.progress-element, .progress-text) {
|
|
353
|
+
width: var(--ring-container-size);
|
|
354
|
+
display: block;
|
|
355
|
+
top: 12px;
|
|
356
|
+
position: absolute;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
#mocha-stats .progress-element {
|
|
360
|
+
visibility: hidden;
|
|
361
|
+
height: calc(var(--ring-container-size) / 2);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
#mocha-stats .progress-text {
|
|
365
|
+
text-align: center;
|
|
366
|
+
text-overflow: clip;
|
|
367
|
+
overflow: hidden;
|
|
368
|
+
color: var(--mocha-stats-em-color);
|
|
369
|
+
font-size: 11px;
|
|
370
|
+
}
|
|
340
371
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
-
|
|
348
|
-
-
|
|
349
|
-
|
|
350
|
-
|
|
372
|
+
#mocha-stats .progress-ring {
|
|
373
|
+
width: var(--ring-container-size);
|
|
374
|
+
height: var(--ring-container-size);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
#mocha-stats :is(.ring-flatlight, .ring-highlight) {
|
|
378
|
+
--stroke-thickness: 1.65px;
|
|
379
|
+
--center: calc(var(--ring-container-size) / 2);
|
|
380
|
+
cx: var(--center);
|
|
381
|
+
cy: var(--center);
|
|
382
|
+
r: calc(var(--ring-radius) - calc(var(--stroke-thickness) / 2));
|
|
383
|
+
fill: hsla(0, 0%, 0%, 0);
|
|
384
|
+
stroke-width: var(--stroke-thickness);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
#mocha-stats .ring-flatlight {
|
|
388
|
+
stroke: var(--mocha-progress-ring-color);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
#mocha-stats .ring-highlight {
|
|
392
|
+
stroke: var(--mocha-progress-ring-highlight-color);
|
|
351
393
|
}
|
|
352
394
|
|
|
353
395
|
#mocha-stats em {
|
|
@@ -370,11 +412,6 @@ body {
|
|
|
370
412
|
padding-top: 11px;
|
|
371
413
|
}
|
|
372
414
|
|
|
373
|
-
#mocha-stats canvas {
|
|
374
|
-
width: 40px;
|
|
375
|
-
height: 40px;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
415
|
#mocha code .comment { color: var(--mocha-code-comment); }
|
|
379
416
|
#mocha code .init { color: var(--mocha-code-init); }
|
|
380
417
|
#mocha code .string { color: var(--mocha-code-string); }
|