| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 9ae80e1 commit b62f2f8
7 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3034,6 +3034,31 @@ This event is only emitted if `--test` flag is passed. | |||
| 3034 | 3034 | This event is not guaranteed to be emitted in the same order as the tests are | |
| 3035 | 3035 | defined. | |
| 3036 | 3036 | ||
| 3037 | + ### Event: `'test:summary'` | ||
| 3038 | + | ||
| 3039 | + * `data` {Object} | ||
| 3040 | + * `counts` {Object} An object containing the counts of various test results. | ||
| 3041 | + * `cancelled` {number} The total number of cancelled tests. | ||
| 3042 | + * `failed` {number} The total number of failed tests. | ||
| 3043 | + * `passed` {number} The total number of passed tests. | ||
| 3044 | + * `skipped` {number} The total number of skipped tests. | ||
| 3045 | + * `suites` {number} The total number of suites run. | ||
| 3046 | + * `tests` {number} The total number of tests run, excluding suites. | ||
| 3047 | + * `todo` {number} The total number of TODO tests. | ||
| 3048 | + * `topLevel` {number} The total number of top level tests and suites. | ||
| 3049 | + * `duration_ms` {number} The duration of the test run in milliseconds. | ||
| 3050 | + * `file` {string|undefined} The path of the test file that generated the | ||
| 3051 | + summary. If the summary corresponds to multiple files, this value is | ||
| 3052 | + `undefined`. | ||
| 3053 | + * `success` {boolean} Indicates whether or not the test run is considered | ||
| 3054 | + successful or not. If any error condition occurs, such as a failing test or | ||
| 3055 | + unmet coverage threshold, this value will be set to `false`. | ||
| 3056 | + | ||
| 3057 | + Emitted when a test run completes. This event contains metrics pertaining to | ||
| 3058 | + the completed test run, and is useful for determining if a test run passed or | ||
| 3059 | + failed. If process-level test isolation is used, a `'test:summary'` event is | ||
| 3060 | + generated for each test file in addition to a final cumulative summary. | ||
| 3061 | + | ||
| 3037 | 3062 | ### Event: `'test:watch:drained'` | |
| 3038 | 3063 | ||
| 3039 | 3064 | Emitted when no more tests are queued for execution in watch mode. | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -31,8 +31,8 @@ if (isUsingInspector() && options.isolation === 'process') { | |||
| 31 | 31 | options.globPatterns = ArrayPrototypeSlice(process.argv, 1); | |
| 32 | 32 | ||
| 33 | 33 | debug('test runner configuration:', options); | |
| 34 | - run(options).on('test:fail', (data) => { | ||
| 35 | - if (data.todo === undefined || data.todo === false) { | ||
| 34 | + run(options).on('test:summary', (data) => { | ||
| 35 | + if (!data.success) { | ||
| 36 | 36 | process.exitCode = kGenericUserError; | |
| 37 | 37 | } | |
| 38 | 38 | }); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -52,7 +52,7 @@ function createTestTree(rootTestOptions, globalOptions) { | |||
| 52 | 52 | resetCounters() { | |
| 53 | 53 | harness.counters = { | |
| 54 | 54 | __proto__: null, | |
| 55 | - all: 0, | ||
| 55 | + tests: 0, | ||
| 56 | 56 | failed: 0, | |
| 57 | 57 | passed: 0, | |
| 58 | 58 | cancelled: 0, | |
@@ -62,6 +62,7 @@ function createTestTree(rootTestOptions, globalOptions) { | |||
| 62 | 62 | suites: 0, | |
| 63 | 63 | }; | |
| 64 | 64 | }, | |
| 65 | + success: true, | ||
| 65 | 66 | counters: null, | |
| 66 | 67 | shouldColorizeTestFiles: shouldColorizeTestFiles(globalOptions.destinations), | |
| 67 | 68 | teardown: null, | |
@@ -130,6 +131,7 @@ function createProcessEventHandler(eventName, rootTest) { | |||
| 130 | 131 | } | |
| 131 | 132 | ||
| 132 | 133 | rootTest.diagnostic(msg); | |
| 134 | + rootTest.harness.success = false; | ||
| 133 | 135 | process.exitCode = kGenericUserError; | |
| 134 | 136 | return; | |
| 135 | 137 | } | |
@@ -152,6 +154,7 @@ function configureCoverage(rootTest, globalOptions) { | |||
| 152 | 154 | const msg = `Warning: Code coverage could not be enabled. ${err}`; | |
| 153 | 155 | ||
| 154 | 156 | rootTest.diagnostic(msg); | |
| 157 | + rootTest.harness.success = false; | ||
| 155 | 158 | process.exitCode = kGenericUserError; | |
| 156 | 159 | } | |
| 157 | 160 | } | |
@@ -167,13 +170,15 @@ function collectCoverage(rootTest, coverage) { | |||
| 167 | 170 | summary = coverage.summary(); | |
| 168 | 171 | } catch (err) { | |
| 169 | 172 | rootTest.diagnostic(`Warning: Could not report code coverage. ${err}`); | |
| 173 | + rootTest.harness.success = false; | ||
| 170 | 174 | process.exitCode = kGenericUserError; | |
| 171 | 175 | } | |
| 172 | 176 | ||
| 173 | 177 | try { | |
| 174 | 178 | coverage.cleanup(); | |
| 175 | 179 | } catch (err) { | |
| 176 | 180 | rootTest.diagnostic(`Warning: Could not clean up code coverage. ${err}`); | |
| 181 | + rootTest.harness.success = false; | ||
| 177 | 182 | process.exitCode = kGenericUserError; | |
| 178 | 183 | } | |
| 179 | 184 | ||
@@ -248,14 +253,16 @@ function lazyBootstrapRoot() { | |||
| 248 | 253 | if (!globalRoot) { | |
| 249 | 254 | // This is where the test runner is bootstrapped when node:test is used | |
| 250 | 255 | // without the --test flag or the run() API. | |
| 256 | + const entryFile = process.argv?.[1]; | ||
| 251 | 257 | const rootTestOptions = { | |
| 252 | 258 | __proto__: null, | |
| 253 | - entryFile: process.argv?.[1], | ||
| 259 | + entryFile, | ||
| 260 | + loc: entryFile ? [1, 1, entryFile] : undefined, | ||
| 254 | 261 | }; | |
| 255 | 262 | const globalOptions = parseCommandLine(); | |
| 256 | 263 | createTestTree(rootTestOptions, globalOptions); | |
| 257 | - globalRoot.reporter.on('test:fail', (data) => { | ||
| 258 | - if (data.todo === undefined || data.todo === false) { | ||
| 264 | + globalRoot.reporter.on('test:summary', (data) => { | ||
| 265 | + if (!data.success) { | ||
| 259 | 266 | process.exitCode = kGenericUserError; | |
| 260 | 267 | } | |
| 261 | 268 | }); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1043,14 +1043,15 @@ class Test extends AsyncResource { | |||
| 1043 | 1043 | reporter.diagnostic(nesting, loc, diagnostics[i]); | |
| 1044 | 1044 | } | |
| 1045 | 1045 | ||
| 1046 | - reporter.diagnostic(nesting, loc, `tests ${harness.counters.all}`); | ||
| 1046 | + const duration = this.duration(); | ||
| 1047 | + reporter.diagnostic(nesting, loc, `tests ${harness.counters.tests}`); | ||
| 1047 | 1048 | reporter.diagnostic(nesting, loc, `suites ${harness.counters.suites}`); | |
| 1048 | 1049 | reporter.diagnostic(nesting, loc, `pass ${harness.counters.passed}`); | |
| 1049 | 1050 | reporter.diagnostic(nesting, loc, `fail ${harness.counters.failed}`); | |
| 1050 | 1051 | reporter.diagnostic(nesting, loc, `cancelled ${harness.counters.cancelled}`); | |
| 1051 | 1052 | reporter.diagnostic(nesting, loc, `skipped ${harness.counters.skipped}`); | |
| 1052 | 1053 | reporter.diagnostic(nesting, loc, `todo ${harness.counters.todo}`); | |
| 1053 | - reporter.diagnostic(nesting, loc, `duration_ms ${this.duration()}`); | ||
| 1054 | + reporter.diagnostic(nesting, loc, `duration_ms ${duration}`); | ||
| 1054 | 1055 | ||
| 1055 | 1056 | if (coverage) { | |
| 1056 | 1057 | const coverages = [ | |
@@ -1067,6 +1068,7 @@ class Test extends AsyncResource { | |||
| 1067 | 1068 | for (let i = 0; i < coverages.length; i++) { | |
| 1068 | 1069 | const { threshold, actual, name } = coverages[i]; | |
| 1069 | 1070 | if (actual < threshold) { | |
| 1071 | + harness.success = false; | ||
| 1070 | 1072 | process.exitCode = kGenericUserError; | |
| 1071 | 1073 | reporter.diagnostic(nesting, loc, `Error: ${NumberPrototypeToFixed(actual, 2)}% ${name} coverage does not meet threshold of ${threshold}%.`); | |
| 1072 | 1074 | } | |
@@ -1075,6 +1077,10 @@ class Test extends AsyncResource { | |||
| 1075 | 1077 | reporter.coverage(nesting, loc, coverage); | |
| 1076 | 1078 | } | |
| 1077 | 1079 | ||
| 1080 | + reporter.summary( | ||
| 1081 | + nesting, loc?.file, harness.success, harness.counters, duration, | ||
| 1082 | + ); | ||
| 1083 | + | ||
| 1078 | 1084 | if (harness.watching) { | |
| 1079 | 1085 | this.reported = false; | |
| 1080 | 1086 | harness.resetCounters(); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -132,6 +132,16 @@ class TestsStream extends Readable { | |||
| 132 | 132 | }); | |
| 133 | 133 | } | |
| 134 | 134 | ||
| 135 | + summary(nesting, file, success, counts, duration_ms) { | ||
| 136 | + this[kEmitMessage]('test:summary', { | ||
| 137 | + __proto__: null, | ||
| 138 | + success, | ||
| 139 | + counts, | ||
| 140 | + duration_ms, | ||
| 141 | + file, | ||
| 142 | + }); | ||
| 143 | + } | ||
| 144 | + | ||
| 135 | 145 | end() { | |
| 136 | 146 | this.#tryPush(null); | |
| 137 | 147 | } | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -357,12 +357,14 @@ function countCompletedTest(test, harness = test.root.harness) { | |||
| 357 | 357 | harness.counters.todo++; | |
| 358 | 358 | } else if (test.cancelled) { | |
| 359 | 359 | harness.counters.cancelled++; | |
| 360 | + harness.success = false; | ||
| 360 | 361 | } else if (!test.passed) { | |
| 361 | 362 | harness.counters.failed++; | |
| 363 | + harness.success = false; | ||
| 362 | 364 | } else { | |
| 363 | 365 | harness.counters.passed++; | |
| 364 | 366 | } | |
| 365 | - harness.counters.all++; | ||
| 367 | + harness.counters.tests++; | ||
| 366 | 368 | } | |
| 367 | 369 | ||
| 368 | 370 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -113,7 +113,7 @@ describe('node:test reporters', { concurrency: true }, () => { | |||
| 113 | 113 | testFile]); | |
| 114 | 114 | assert.strictEqual(child.stderr.toString(), ''); | |
| 115 | 115 | const stdout = child.stdout.toString(); | |
| 116 | - assert.match(stdout, /{"test:enqueue":5,"test:dequeue":5,"test:complete":5,"test:start":4,"test:pass":2,"test:fail":2,"test:plan":2,"test:diagnostic":\d+}$/); | ||
| 116 | + assert.match(stdout, /{"test:enqueue":5,"test:dequeue":5,"test:complete":5,"test:start":4,"test:pass":2,"test:fail":2,"test:plan":2,"test:summary":2,"test:diagnostic":\d+}$/); | ||
| 117 | 117 | assert.strictEqual(stdout.slice(0, filename.length + 2), `${filename} {`); | |
| 118 | 118 | }); | |
| 119 | 119 | }); | |
@@ -125,7 +125,7 @@ describe('node:test reporters', { concurrency: true }, () => { | |||
| 125 | 125 | assert.strictEqual(child.stderr.toString(), ''); | |
| 126 | 126 | assert.match( | |
| 127 | 127 | child.stdout.toString(), | |
| 128 | - /^package: reporter-cjs{"test:enqueue":5,"test:dequeue":5,"test:complete":5,"test:start":4,"test:pass":2,"test:fail":2,"test:plan":2,"test:diagnostic":\d+}$/, | ||
| 128 | + /^package: reporter-cjs{"test:enqueue":5,"test:dequeue":5,"test:complete":5,"test:start":4,"test:pass":2,"test:fail":2,"test:plan":2,"test:summary":2,"test:diagnostic":\d+}$/, | ||
| 129 | 129 | ); | |
| 130 | 130 | }); | |
| 131 | 131 | ||
@@ -136,7 +136,7 @@ describe('node:test reporters', { concurrency: true }, () => { | |||
| 136 | 136 | assert.strictEqual(child.stderr.toString(), ''); | |
| 137 | 137 | assert.match( | |
| 138 | 138 | child.stdout.toString(), | |
| 139 | - /^package: reporter-esm{"test:enqueue":5,"test:dequeue":5,"test:complete":5,"test:start":4,"test:pass":2,"test:fail":2,"test:plan":2,"test:diagnostic":\d+}$/, | ||
| 139 | + /^package: reporter-esm{"test:enqueue":5,"test:dequeue":5,"test:complete":5,"test:start":4,"test:pass":2,"test:fail":2,"test:plan":2,"test:summary":2,"test:diagnostic":\d+}$/, | ||
| 140 | 140 | ); | |
| 141 | 141 | }); | |
| 142 | 142 | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments