@noldova/context.testing 0.0.0-stage → 0.0.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/LICENSE +21 -0
- package/api/index.d.ts +2015 -0
- package/api/index.js +42 -0
- package/api/index.js.map +1 -0
- package/decorators/category.js +23 -0
- package/decorators/category.js.map +1 -0
- package/decorators/skip.js +17 -0
- package/decorators/skip.js.map +1 -0
- package/decorators/test-class.js +12 -0
- package/decorators/test-class.js.map +1 -0
- package/decorators/test-data.js +23 -0
- package/decorators/test-data.js.map +1 -0
- package/decorators/test-method.js +12 -0
- package/decorators/test-method.js.map +1 -0
- package/enums/test-outcome.js +14 -0
- package/enums/test-outcome.js.map +1 -0
- package/enums/test-worker-message-kind.js +17 -0
- package/enums/test-worker-message-kind.js.map +1 -0
- package/enums/test-worker-value-kind.js +16 -0
- package/enums/test-worker-value-kind.js.map +1 -0
- package/exceptions/assert-failed.exception.js +19 -0
- package/exceptions/assert-failed.exception.js.map +1 -0
- package/exceptions/test-timeout.exception.js +20 -0
- package/exceptions/test-timeout.exception.js.map +1 -0
- package/exceptions/testing.exception.js +14 -0
- package/exceptions/testing.exception.js.map +1 -0
- package/interfaces/i-clock.js +9 -0
- package/interfaces/i-clock.js.map +1 -0
- package/interfaces/i-coverage-range.js +9 -0
- package/interfaces/i-coverage-range.js.map +1 -0
- package/interfaces/i-coverage-report.js +9 -0
- package/interfaces/i-coverage-report.js.map +1 -0
- package/interfaces/i-function-coverage.js +9 -0
- package/interfaces/i-function-coverage.js.map +1 -0
- package/interfaces/i-script-coverage.js +9 -0
- package/interfaces/i-script-coverage.js.map +1 -0
- package/interfaces/i-source-map-data.js +9 -0
- package/interfaces/i-source-map-data.js.map +1 -0
- package/interfaces/i-test-progress-listener.js +9 -0
- package/interfaces/i-test-progress-listener.js.map +1 -0
- package/models/coverage/block-coverage.js +21 -0
- package/models/coverage/block-coverage.js.map +1 -0
- package/models/coverage/coverage-project.js +23 -0
- package/models/coverage/coverage-project.js.map +1 -0
- package/models/coverage/coverage-range.js +18 -0
- package/models/coverage/coverage-range.js.map +1 -0
- package/models/coverage/coverage-result.js +28 -0
- package/models/coverage/coverage-result.js.map +1 -0
- package/models/coverage/file-coverage.js +45 -0
- package/models/coverage/file-coverage.js.map +1 -0
- package/models/coverage/function-coverage.js +14 -0
- package/models/coverage/function-coverage.js.map +1 -0
- package/models/coverage/line-range.js +25 -0
- package/models/coverage/line-range.js.map +1 -0
- package/models/coverage/mapped-source-line.js +22 -0
- package/models/coverage/mapped-source-line.js.map +1 -0
- package/models/coverage/source-map-segment.js +18 -0
- package/models/coverage/source-map-segment.js.map +1 -0
- package/models/decorators/test-data-entry.js +17 -0
- package/models/decorators/test-data-entry.js.map +1 -0
- package/models/decorators/test-marks.js +16 -0
- package/models/decorators/test-marks.js.map +1 -0
- package/models/discovery/discovered-test-class.js +36 -0
- package/models/discovery/discovered-test-class.js.map +1 -0
- package/models/discovery/discovered-test-method.js +42 -0
- package/models/discovery/discovered-test-method.js.map +1 -0
- package/models/discovery/test-project.js +20 -0
- package/models/discovery/test-project.js.map +1 -0
- package/models/execution/test-worker-message.js +76 -0
- package/models/execution/test-worker-message.js.map +1 -0
- package/models/execution/test-worker-record.js +75 -0
- package/models/execution/test-worker-record.js.map +1 -0
- package/models/execution/test-worker-result.js +45 -0
- package/models/execution/test-worker-result.js.map +1 -0
- package/models/execution/test-worker-run.js +31 -0
- package/models/execution/test-worker-run.js.map +1 -0
- package/models/execution/test-worker-start.js +33 -0
- package/models/execution/test-worker-start.js.map +1 -0
- package/models/execution/test-worker-text.js +17 -0
- package/models/execution/test-worker-text.js.map +1 -0
- package/models/execution/test-worker-value.js +104 -0
- package/models/execution/test-worker-value.js.map +1 -0
- package/models/reporting/coverage-report-row.js +22 -0
- package/models/reporting/coverage-report-row.js.map +1 -0
- package/models/results/test-class-result.js +29 -0
- package/models/results/test-class-result.js.map +1 -0
- package/models/results/test-method-result.js +59 -0
- package/models/results/test-method-result.js.map +1 -0
- package/models/results/test-run-result.js +34 -0
- package/models/results/test-run-result.js.map +1 -0
- package/models/results/test-run-totals.js +36 -0
- package/models/results/test-run-totals.js.map +1 -0
- package/models/results/test-selection.js +33 -0
- package/models/results/test-selection.js.map +1 -0
- package/package.json +25 -4
- package/resources.js +309 -0
- package/resources.js.map +1 -0
- package/services/assert.js +92 -0
- package/services/assert.js.map +1 -0
- package/services/coverage/coverage-analyzer.js +52 -0
- package/services/coverage/coverage-analyzer.js.map +1 -0
- package/services/coverage/coverage-report.reader.js +126 -0
- package/services/coverage/coverage-report.reader.js.map +1 -0
- package/services/coverage/file-coverage-analyzer.js +206 -0
- package/services/coverage/file-coverage-analyzer.js.map +1 -0
- package/services/coverage/source-map.js +135 -0
- package/services/coverage/source-map.js.map +1 -0
- package/services/discovery/test-discovery.js +198 -0
- package/services/discovery/test-discovery.js.map +1 -0
- package/services/execution/parallel-test-runner.js +24 -0
- package/services/execution/parallel-test-runner.js.map +1 -0
- package/services/execution/test-executor.js +116 -0
- package/services/execution/test-executor.js.map +1 -0
- package/services/execution/test-run-entry-point.js +89 -0
- package/services/execution/test-run-entry-point.js.map +1 -0
- package/services/execution/test-run-supervisor.js +251 -0
- package/services/execution/test-run-supervisor.js.map +1 -0
- package/services/execution/test-run-worker-entry-point.js +18 -0
- package/services/execution/test-run-worker-entry-point.js.map +1 -0
- package/services/execution/test-run-worker.js +116 -0
- package/services/execution/test-run-worker.js.map +1 -0
- package/services/execution/test-runner.js +58 -0
- package/services/execution/test-runner.js.map +1 -0
- package/services/reporting/coverage-report-writer.js +81 -0
- package/services/reporting/coverage-report-writer.js.map +1 -0
- package/services/reporting/test-console-reporter.js +72 -0
- package/services/reporting/test-console-reporter.js.map +1 -0
- package/services/reporting/test-report-writer.js +111 -0
- package/services/reporting/test-report-writer.js.map +1 -0
- package/services/timing/system-clock.js +26 -0
- package/services/timing/system-clock.js.map +1 -0
- package/README.md +0 -3
package/api/index.d.ts
ADDED
|
@@ -0,0 +1,2015 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) Noldova.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import "@noldova/context.core";
|
|
10
|
+
import type { Exception, ExceptionOptions } from "@noldova/context.exceptions";
|
|
11
|
+
import "@noldova/context.text";
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Adds a repeatable category name to a test class or method. Method categories
|
|
15
|
+
* combine with categories inherited from their declaring test class. Category
|
|
16
|
+
* metadata supports explicit selection and does not control execution order or
|
|
17
|
+
* concurrency.
|
|
18
|
+
*
|
|
19
|
+
* @param name The non-whitespace, case-sensitive category identity. Repeated decorators preserve their written order.
|
|
20
|
+
* @returns The decorator that attaches the category to a test class or public instance test method.
|
|
21
|
+
* @throws ArgumentException if name is empty or whitespace.
|
|
22
|
+
* @throws TestingException if applying the decorator encounters corrupt existing category metadata.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* import { Assert, Category, TestClass, TestData, TestMethod } from "@noldova/context.testing";
|
|
27
|
+
*
|
|
28
|
+
* @Category("Unit")
|
|
29
|
+
* @TestClass
|
|
30
|
+
* export class AdditionTests {
|
|
31
|
+
* @Category("Arithmetic")
|
|
32
|
+
* @TestData(2, 3, 5)
|
|
33
|
+
* @TestData(-1, 1, 0)
|
|
34
|
+
* @TestMethod
|
|
35
|
+
* public adds(left: number, right: number, expected: number): void {
|
|
36
|
+
* Assert.areEqual(expected, left + right);
|
|
37
|
+
* }
|
|
38
|
+
* }
|
|
39
|
+
* // Select with category:Unit or category:Arithmetic; each row remains a separate test.
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export declare function Category(name: string): (value: Function) => void;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Marks a class as a test class. Discovery accepts only exported classes
|
|
46
|
+
* whose name ends in `Tests` and which carry this mark.
|
|
47
|
+
*
|
|
48
|
+
* @param value The exported class constructor to mark. Its export name must end in Tests and its instances must be constructible without arguments.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* import { Assert, TestClass, TestMethod } from "@noldova/context.testing";
|
|
53
|
+
*
|
|
54
|
+
* @TestClass
|
|
55
|
+
* export class CounterTests {
|
|
56
|
+
* private count: number = 0;
|
|
57
|
+
*
|
|
58
|
+
* @TestMethod
|
|
59
|
+
* public startsWithFreshState(): void {
|
|
60
|
+
* Assert.areEqual(0, this.count);
|
|
61
|
+
* this.count++;
|
|
62
|
+
* }
|
|
63
|
+
* }
|
|
64
|
+
* // Save as counter.test.ts and export the marked class.
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
export declare function TestClass(value: Function): void;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Adds one inline argument row to a test method. Each repeated `TestData`
|
|
71
|
+
* decorator is discovered, executed, timed, and reported as an independent
|
|
72
|
+
* test in written order.
|
|
73
|
+
*
|
|
74
|
+
* @param values The non-empty inline argument row for TArguments. Its array is copied, but referenced values are shared; discovery requires the fixed
|
|
75
|
+
* runtime arity to match.
|
|
76
|
+
* @returns The decorator for an instance method accepting the TArguments tuple and also marked with TestMethod.
|
|
77
|
+
* @throws ArgumentException if the row is empty.
|
|
78
|
+
* @throws TestingException if applying the decorator encounters corrupt existing data metadata.
|
|
79
|
+
*
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* import { Assert, TestClass, TestData, TestMethod } from "@noldova/context.testing";
|
|
83
|
+
*
|
|
84
|
+
* @TestClass
|
|
85
|
+
* export class LengthTests {
|
|
86
|
+
* @TestData("", 0)
|
|
87
|
+
* @TestData("abc", 3)
|
|
88
|
+
* @TestMethod
|
|
89
|
+
* public measures(value: string, expected: number): void {
|
|
90
|
+
* Assert.areEqual(expected, value.length);
|
|
91
|
+
* }
|
|
92
|
+
* }
|
|
93
|
+
* // Reports measures[0] and measures[1] independently, in this written order.
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
export declare function TestData<TArguments extends unknown[]>(...values: TArguments): (value: (...testArguments: TArguments) => unknown) => void;
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Marks a public instance method of a test class as a test method.
|
|
100
|
+
*
|
|
101
|
+
* @param value The synchronous or promise-returning public instance method to mark. Static, symbol-named, and generator tests are rejected by discovery.
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* ```ts
|
|
105
|
+
* import { Assert, TestClass, TestMethod } from "@noldova/context.testing";
|
|
106
|
+
*
|
|
107
|
+
* @TestClass
|
|
108
|
+
* export class AsyncTests {
|
|
109
|
+
* @TestMethod
|
|
110
|
+
* public async awaitsWorkAsync(): Promise<void> {
|
|
111
|
+
* Assert.areEqual(42, await Promise.resolve(42));
|
|
112
|
+
* }
|
|
113
|
+
* }
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
export declare function TestMethod(value: Function): void;
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Marks a test class or test method as skipped for the given reason. The
|
|
120
|
+
* reason is required and is reported with the skipped result.
|
|
121
|
+
* Discovery rejects a skip mark without the corresponding TestClass or
|
|
122
|
+
* TestMethod mark; Skip does not turn an otherwise unmarked target into a test.
|
|
123
|
+
*
|
|
124
|
+
* @param reason The non-whitespace reason reported for every affected invocation. A method reason takes precedence over a class reason.
|
|
125
|
+
* @returns The decorator that skips a marked test class or method.
|
|
126
|
+
* @throws ArgumentException if reason is empty or whitespace.
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* ```ts
|
|
130
|
+
* import { Skip, TestClass, TestMethod } from "@noldova/context.testing";
|
|
131
|
+
*
|
|
132
|
+
* @TestClass
|
|
133
|
+
* export class StorageTests {
|
|
134
|
+
* @Skip("Requires the integration test server.")
|
|
135
|
+
* @TestMethod
|
|
136
|
+
* public connects(): void { }
|
|
137
|
+
* }
|
|
138
|
+
* // The skipped invocation and its reason remain visible in reduced-detail reports.
|
|
139
|
+
* ```
|
|
140
|
+
*/
|
|
141
|
+
export declare function Skip(reason: string): (value: Function) => void;
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* The exception that is thrown when a test assertion fails. Carries the
|
|
145
|
+
* expected and actual values beside the message.
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* ```ts
|
|
149
|
+
* import { Assert, AssertFailedException } from "@noldova/context.testing";
|
|
150
|
+
*
|
|
151
|
+
* const failure = Assert.throws(() => Assert.areEqual(1, 2), AssertFailedException);
|
|
152
|
+
* Assert.areEqual(1, failure.expected);
|
|
153
|
+
* Assert.areEqual(2, failure.actual);
|
|
154
|
+
* const explicitFailure = new AssertFailedException();
|
|
155
|
+
* Assert.areEqual("Assertion failed.", explicitFailure.message);
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
export declare class AssertFailedException extends TestingException {
|
|
159
|
+
/**
|
|
160
|
+
* The value the assertion expected, when applicable.
|
|
161
|
+
*/
|
|
162
|
+
public readonly expected: unknown;
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* The value the assertion observed, when applicable.
|
|
166
|
+
*/
|
|
167
|
+
public readonly actual: unknown;
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Initializes the exception. A missing message defaults to the canonical
|
|
171
|
+
* assertion-failure text.
|
|
172
|
+
*
|
|
173
|
+
* @param message Optional failure text. Omission selects the operation's canonical message; an empty string is preserved.
|
|
174
|
+
* @param expected The expected value, retained by reference rather than deep-copied.
|
|
175
|
+
* @param actual The observed value, retained by reference rather than deep-copied.
|
|
176
|
+
* @param options Optional exception context. Its cause is retained without cloning.
|
|
177
|
+
*
|
|
178
|
+
* See {@link AssertFailedException} for usage examples.
|
|
179
|
+
*/
|
|
180
|
+
public constructor(message?: string, expected?: unknown, actual?: unknown, options?: ExceptionOptions);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* The base exception for failures owned by the Testing package. It is thrown
|
|
185
|
+
* directly when discovery or execution violates the testing contract.
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* ```ts
|
|
189
|
+
* import { ExceptionOptions } from "@noldova/context.exceptions";
|
|
190
|
+
* import { Assert, TestingException } from "@noldova/context.testing";
|
|
191
|
+
*
|
|
192
|
+
* const cause = new Error("module loading failed");
|
|
193
|
+
* const failure = new TestingException("Cannot discover the test project.", new ExceptionOptions(cause));
|
|
194
|
+
* Assert.areEqual(cause, failure.cause);
|
|
195
|
+
* ```
|
|
196
|
+
*/
|
|
197
|
+
export declare class TestingException extends Exception {
|
|
198
|
+
/**
|
|
199
|
+
* Initializes the exception with the violation description.
|
|
200
|
+
*
|
|
201
|
+
* @param message The description of the testing failure, preserved as supplied.
|
|
202
|
+
* @param options Optional exception context. Its cause is retained without cloning.
|
|
203
|
+
*
|
|
204
|
+
* See {@link TestingException} for usage examples.
|
|
205
|
+
*/
|
|
206
|
+
public constructor(message: string, options?: ExceptionOptions);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* The exception that fails a test which did not settle within the executor's
|
|
211
|
+
* timeout.
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* ```ts
|
|
215
|
+
* import { Assert, TestTimeoutException } from "@noldova/context.testing";
|
|
216
|
+
*
|
|
217
|
+
* const failure = new TestTimeoutException(500);
|
|
218
|
+
* Assert.areEqual(500, failure.timeoutMilliseconds);
|
|
219
|
+
* // This describes a failure; constructing it does not start a timer.
|
|
220
|
+
* ```
|
|
221
|
+
*/
|
|
222
|
+
export declare class TestTimeoutException extends TestingException {
|
|
223
|
+
/**
|
|
224
|
+
* The timeout that elapsed, in milliseconds.
|
|
225
|
+
*/
|
|
226
|
+
public readonly timeoutMilliseconds: number;
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Initializes the exception with a positive integer timeout. Invalid values
|
|
230
|
+
* throw `ArgumentOutOfRangeException`.
|
|
231
|
+
*
|
|
232
|
+
* @param timeoutMilliseconds A positive integer duration in milliseconds.
|
|
233
|
+
* @param options Optional exception context. Its cause is retained without cloning.
|
|
234
|
+
* @throws ArgumentOutOfRangeException if the timeout is not a positive integer.
|
|
235
|
+
*
|
|
236
|
+
* See {@link TestTimeoutException} for usage examples.
|
|
237
|
+
*/
|
|
238
|
+
public constructor(timeoutMilliseconds: number, options?: ExceptionOptions);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* The assertion vocabulary. Every failure throws `AssertFailedException`.
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* ```ts
|
|
246
|
+
* import { Assert } from "@noldova/context.testing";
|
|
247
|
+
*
|
|
248
|
+
* Assert.isTrue(3 > 2);
|
|
249
|
+
* Assert.isFalse(3 < 2);
|
|
250
|
+
* Assert.areEqual(Number.NaN, Number.NaN);
|
|
251
|
+
* Assert.areNotEqual(0, -0);
|
|
252
|
+
* Assert.isNull(null);
|
|
253
|
+
* Assert.isUndefined(undefined);
|
|
254
|
+
* Assert.isNotNull(undefined); // Excludes null only.
|
|
255
|
+
* Assert.isDefined(null); // Excludes undefined only.
|
|
256
|
+
* const value: unknown = new Error("sample");
|
|
257
|
+
* Assert.isInstanceOf(value, Error);
|
|
258
|
+
* Assert.areEqual("sample", value.message);
|
|
259
|
+
*
|
|
260
|
+
* const caught = Assert.throws(() => { throw new Error("expected"); }, Error);
|
|
261
|
+
* Assert.areEqual("expected", caught.message);
|
|
262
|
+
* await Assert.throwsAsync(async () => { throw new Error("rejected"); }, Error);
|
|
263
|
+
* Assert.doesNotThrow(() => Assert.areEqual(2, 1 + 1));
|
|
264
|
+
* Assert.throws(() => Assert.fail("deliberate failure"), Error);
|
|
265
|
+
* ```
|
|
266
|
+
*/
|
|
267
|
+
export declare class Assert {
|
|
268
|
+
/**
|
|
269
|
+
* Fails unless the condition is true; a passing call narrows the condition.
|
|
270
|
+
*
|
|
271
|
+
* @param condition The boolean condition that must be true. Success narrows it to true.
|
|
272
|
+
* @param message Optional failure text. Omission selects the operation's canonical message; an empty string is preserved.
|
|
273
|
+
* @throws AssertFailedException if the asserted condition is not satisfied.
|
|
274
|
+
*
|
|
275
|
+
* See {@link Assert} for usage examples.
|
|
276
|
+
*/
|
|
277
|
+
public static isTrue(condition: boolean, message?: string): asserts condition;
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Fails unless the condition is false; a passing call narrows to `false`.
|
|
281
|
+
*
|
|
282
|
+
* @param condition The boolean condition that must be false. Success narrows it to false.
|
|
283
|
+
* @param message Optional failure text. Omission selects the operation's canonical message; an empty string is preserved.
|
|
284
|
+
* @throws AssertFailedException if the asserted condition is not satisfied.
|
|
285
|
+
*
|
|
286
|
+
* See {@link Assert} for usage examples.
|
|
287
|
+
*/
|
|
288
|
+
public static isFalse(condition: boolean, message?: string): asserts condition is false;
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Fails unless the values are equal by SameValue semantics.
|
|
292
|
+
*
|
|
293
|
+
* @param expected The expected T value; equality uses Object.is, not structural comparison.
|
|
294
|
+
* @param actual The observed T value. NaN equals NaN; positive and negative zero differ; objects compare by identity.
|
|
295
|
+
* @param message Optional failure text. Omission selects the operation's canonical message; an empty string is preserved.
|
|
296
|
+
* @throws AssertFailedException if the asserted condition is not satisfied.
|
|
297
|
+
*
|
|
298
|
+
* See {@link Assert} for usage examples.
|
|
299
|
+
*/
|
|
300
|
+
public static areEqual<T>(expected: T, actual: T, message?: string): void;
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Fails when the values are equal by SameValue semantics.
|
|
304
|
+
*
|
|
305
|
+
* @param notExpected The T value that the actual value must differ from under Object.is.
|
|
306
|
+
* @param actual The observed T value, compared by SameValue rather than deep equality.
|
|
307
|
+
* @param message Optional failure text. Omission selects the operation's canonical message; an empty string is preserved.
|
|
308
|
+
* @throws AssertFailedException if the asserted condition is not satisfied.
|
|
309
|
+
*
|
|
310
|
+
* See {@link Assert} for usage examples.
|
|
311
|
+
*/
|
|
312
|
+
public static areNotEqual<T>(notExpected: T, actual: T, message?: string): void;
|
|
313
|
+
|
|
314
|
+
/**
|
|
315
|
+
* Fails unless the value is exactly null; a passing call narrows to `null`.
|
|
316
|
+
*
|
|
317
|
+
* @param value The value that must be exactly null, not undefined. Success narrows it to null.
|
|
318
|
+
* @param message Optional failure text. Omission selects the operation's canonical message; an empty string is preserved.
|
|
319
|
+
* @throws AssertFailedException if the asserted condition is not satisfied.
|
|
320
|
+
*
|
|
321
|
+
* See {@link Assert} for usage examples.
|
|
322
|
+
*/
|
|
323
|
+
public static isNull(value: unknown, message?: string): asserts value is null;
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Fails when the value is exactly null; a passing call excludes `null`.
|
|
327
|
+
*
|
|
328
|
+
* @param value The T value that must not be null. Undefined remains valid; success narrows to Exclude<T, null>.
|
|
329
|
+
* @param message Optional failure text. Omission selects the operation's canonical message; an empty string is preserved.
|
|
330
|
+
* @throws AssertFailedException if the asserted condition is not satisfied.
|
|
331
|
+
*
|
|
332
|
+
* See {@link Assert} for usage examples.
|
|
333
|
+
*/
|
|
334
|
+
public static isNotNull<T>(value: T, message?: string): asserts value is Exclude<T, null>;
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Fails unless the value is exactly undefined; a passing call narrows to
|
|
338
|
+
* `undefined`.
|
|
339
|
+
*
|
|
340
|
+
* @param value The value that must be exactly undefined, not null. Success narrows it to undefined.
|
|
341
|
+
* @param message Optional failure text. Omission selects the operation's canonical message; an empty string is preserved.
|
|
342
|
+
* @throws AssertFailedException if the asserted condition is not satisfied.
|
|
343
|
+
*
|
|
344
|
+
* See {@link Assert} for usage examples.
|
|
345
|
+
*/
|
|
346
|
+
public static isUndefined(value: unknown, message?: string): asserts value is undefined;
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Fails when the value is undefined; a passing call excludes `undefined`
|
|
350
|
+
* from the type.
|
|
351
|
+
*
|
|
352
|
+
* @param value The T value that must not be undefined. Null remains valid; success narrows to Exclude<T, undefined>.
|
|
353
|
+
* @param message Optional failure text. Omission selects the operation's canonical message; an empty string is preserved.
|
|
354
|
+
* @throws AssertFailedException if the asserted condition is not satisfied.
|
|
355
|
+
*
|
|
356
|
+
* See {@link Assert} for usage examples.
|
|
357
|
+
*/
|
|
358
|
+
public static isDefined<T>(value: T, message?: string): asserts value is Exclude<T, undefined>;
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Fails unless the value is an instance of the type; a passing call narrows
|
|
362
|
+
* to that type.
|
|
363
|
+
*
|
|
364
|
+
* @param value The value to test and narrow to T on success.
|
|
365
|
+
* @param type The runtime constructor whose prototype defines T. Derived instances also satisfy the assertion.
|
|
366
|
+
* @param message Optional failure text. Omission selects the operation's canonical message; an empty string is preserved.
|
|
367
|
+
* @throws AssertFailedException if the asserted condition is not satisfied.
|
|
368
|
+
*
|
|
369
|
+
* See {@link Assert} for usage examples.
|
|
370
|
+
*/
|
|
371
|
+
public static isInstanceOf<T>(value: unknown, type: Function & { readonly prototype: T }, message?: string): asserts value is T;
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Fails unless the action throws an instance of the exception type; returns
|
|
375
|
+
* the caught exception for further assertions.
|
|
376
|
+
*
|
|
377
|
+
* @param action The synchronous action to invoke once. Use throwsAsync for promise-returning work.
|
|
378
|
+
* @param exceptionType The expected TException constructor; derived exceptions also match.
|
|
379
|
+
* @param message Optional failure text. Omission selects the operation's canonical message; an empty string is preserved.
|
|
380
|
+
* @returns The original matching exception, retaining identity and custom fields.
|
|
381
|
+
* @throws AssertFailedException if the action does not throw or throws a different exception type.
|
|
382
|
+
*
|
|
383
|
+
* See {@link Assert} for usage examples.
|
|
384
|
+
*/
|
|
385
|
+
public static throws<TException extends Error>(
|
|
386
|
+
action: () => void,
|
|
387
|
+
exceptionType: Function & (abstract new (...arguments_: never[]) => TException),
|
|
388
|
+
message?: string): TException;
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* Fails unless the awaited action rejects with an instance of the exception
|
|
392
|
+
* type; returns the caught exception for further assertions.
|
|
393
|
+
*
|
|
394
|
+
* @param action The action invoked once and awaited. Either a synchronous throw or a promise rejection is examined.
|
|
395
|
+
* @param exceptionType The expected TException constructor; derived exceptions also match.
|
|
396
|
+
* @param message Optional failure text. Omission selects the operation's canonical message; an empty string is preserved.
|
|
397
|
+
* @returns A promise resolving to the original matching exception.
|
|
398
|
+
* @throws AssertFailedException via promise rejection if the action succeeds or fails with a different exception type.
|
|
399
|
+
*
|
|
400
|
+
* See {@link Assert} for usage examples.
|
|
401
|
+
*/
|
|
402
|
+
public static throwsAsync<TException extends Error>(
|
|
403
|
+
action: () => Promise<unknown>,
|
|
404
|
+
exceptionType: Function & (abstract new (...arguments_: never[]) => TException),
|
|
405
|
+
message?: string): Promise<TException>;
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* Fails when the action throws.
|
|
409
|
+
*
|
|
410
|
+
* @param action The synchronous action to invoke once. This assertion does not await asynchronous work.
|
|
411
|
+
* @param message Optional failure text. Omission selects the operation's canonical message; an empty string is preserved.
|
|
412
|
+
* @throws AssertFailedException if the action throws.
|
|
413
|
+
*
|
|
414
|
+
* See {@link Assert} for usage examples.
|
|
415
|
+
*/
|
|
416
|
+
public static doesNotThrow(action: () => void, message?: string): void;
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Fails unconditionally.
|
|
420
|
+
*
|
|
421
|
+
* @param message Optional failure text. Omission selects the operation's canonical message; an empty string is preserved.
|
|
422
|
+
* @returns Never returns; it always throws AssertFailedException.
|
|
423
|
+
* @throws AssertFailedException always.
|
|
424
|
+
*
|
|
425
|
+
* See {@link Assert} for usage examples.
|
|
426
|
+
*/
|
|
427
|
+
public static fail(message?: string): never;
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* The outcome of one executed or skipped test invocation.
|
|
432
|
+
*/
|
|
433
|
+
export declare enum TestOutcome {
|
|
434
|
+
/**
|
|
435
|
+
* The test executed without a failure.
|
|
436
|
+
*/
|
|
437
|
+
Passed = "Passed",
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* The test executed and produced a failure.
|
|
441
|
+
*/
|
|
442
|
+
Failed = "Failed",
|
|
443
|
+
|
|
444
|
+
/**
|
|
445
|
+
* The test did not execute because it carries an explicit skip reason.
|
|
446
|
+
*/
|
|
447
|
+
Skipped = "Skipped",
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* The result snapshot of one test-method invocation. The constructor rejects
|
|
452
|
+
* contradictory outcome, failure, skip, and test-data states.
|
|
453
|
+
*
|
|
454
|
+
* @example
|
|
455
|
+
* ```ts
|
|
456
|
+
* import { Assert, TestMethodResult, TestOutcome } from "@noldova/context.testing";
|
|
457
|
+
*
|
|
458
|
+
* const row = new TestMethodResult("Sample", "LengthTests", "measures", 0, ["abc", 3],
|
|
459
|
+
* TestOutcome.Passed, 1.5, undefined, undefined);
|
|
460
|
+
* Assert.areEqual("LengthTests.measures[0]", row.displayName);
|
|
461
|
+
* const skipped = new TestMethodResult("Sample", "StorageTests", "connects", undefined, [],
|
|
462
|
+
* TestOutcome.Skipped, 0, undefined, "Server unavailable.");
|
|
463
|
+
* Assert.areEqual("Server unavailable.", skipped.skipReason);
|
|
464
|
+
* ```
|
|
465
|
+
*/
|
|
466
|
+
export declare class TestMethodResult {
|
|
467
|
+
/**
|
|
468
|
+
* The canonical package identity of the test.
|
|
469
|
+
*/
|
|
470
|
+
public readonly packageName: string;
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* The discovered test-class name.
|
|
474
|
+
*/
|
|
475
|
+
public readonly className: string;
|
|
476
|
+
|
|
477
|
+
/**
|
|
478
|
+
* The discovered test-method name.
|
|
479
|
+
*/
|
|
480
|
+
public readonly methodName: string;
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* The zero-based inline-data index, or undefined for a method without test
|
|
484
|
+
* data.
|
|
485
|
+
*/
|
|
486
|
+
public readonly testDataIndex: number | undefined;
|
|
487
|
+
|
|
488
|
+
/**
|
|
489
|
+
* The inline arguments supplied to this invocation. Empty for a method
|
|
490
|
+
* without test data.
|
|
491
|
+
*/
|
|
492
|
+
public readonly testData: readonly unknown[];
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* The final classified outcome.
|
|
496
|
+
*/
|
|
497
|
+
public readonly outcome: TestOutcome;
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* The measured execution duration in milliseconds.
|
|
501
|
+
*/
|
|
502
|
+
public readonly durationMilliseconds: number;
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* The original failure when the outcome is Failed. It may itself be undefined
|
|
506
|
+
* when the test threw undefined; the outcome, not this value, identifies failure.
|
|
507
|
+
*/
|
|
508
|
+
public readonly failure: unknown;
|
|
509
|
+
|
|
510
|
+
/**
|
|
511
|
+
* The declared skip reason when the outcome is Skipped; undefined
|
|
512
|
+
* otherwise.
|
|
513
|
+
*/
|
|
514
|
+
public readonly skipReason: string | undefined;
|
|
515
|
+
|
|
516
|
+
/**
|
|
517
|
+
* The `ClassName.methodName` identity, followed by `[index]` for a
|
|
518
|
+
* parameterized invocation.
|
|
519
|
+
*/
|
|
520
|
+
public readonly displayName: string;
|
|
521
|
+
|
|
522
|
+
/**
|
|
523
|
+
* Initializes the complete result snapshot; fails on contradictory data,
|
|
524
|
+
* outcome, failure, or skip state.
|
|
525
|
+
*
|
|
526
|
+
* @param packageName The explicit, non-whitespace package identity; it is never inferred from a path.
|
|
527
|
+
* @param className The non-whitespace discovered class identity.
|
|
528
|
+
* @param methodName The non-whitespace public instance-method name, without a data-row suffix.
|
|
529
|
+
* @param testDataIndex The non-negative integer, zero-based row index; undefined for a non-parameterized invocation.
|
|
530
|
+
* @param testData The row's arguments. Non-empty exactly when testDataIndex is present. The array is copied; its values remain shared.
|
|
531
|
+
* @param outcome The final Passed, Failed, or Skipped outcome; failure and skipReason must agree with it.
|
|
532
|
+
* @param durationMilliseconds The non-negative finite elapsed duration for this invocation, in milliseconds.
|
|
533
|
+
* @param failure The original thrown or rejected value for a failed outcome, including undefined when that was thrown. Must be undefined otherwise.
|
|
534
|
+
* @param skipReason A non-whitespace reason when skipped, or undefined otherwise.
|
|
535
|
+
* @throws ArgumentException if an identity or required skip reason is blank, data identity is inconsistent, or failure/skip state contradicts the outcome.
|
|
536
|
+
* @throws ArgumentOutOfRangeException if the row index is negative or fractional, or duration is negative or non-finite.
|
|
537
|
+
*
|
|
538
|
+
* See {@link TestMethodResult} for usage examples.
|
|
539
|
+
*/
|
|
540
|
+
public constructor(
|
|
541
|
+
packageName: string,
|
|
542
|
+
className: string,
|
|
543
|
+
methodName: string,
|
|
544
|
+
testDataIndex: number | undefined,
|
|
545
|
+
testData: readonly unknown[],
|
|
546
|
+
outcome: TestOutcome,
|
|
547
|
+
durationMilliseconds: number,
|
|
548
|
+
failure: unknown,
|
|
549
|
+
skipReason: string | undefined);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
/**
|
|
553
|
+
* The result snapshots of one test class.
|
|
554
|
+
*
|
|
555
|
+
* @example
|
|
556
|
+
* ```ts
|
|
557
|
+
* import { Assert, TestClassResult, TestMethodResult, TestOutcome } from "@noldova/context.testing";
|
|
558
|
+
*
|
|
559
|
+
* const method = new TestMethodResult("Sample", "SampleTests", "passes", undefined, [],
|
|
560
|
+
* TestOutcome.Passed, 2, undefined, undefined);
|
|
561
|
+
* const result = new TestClassResult("Sample", "SampleTests", "sample.test.js", [method]);
|
|
562
|
+
* Assert.areEqual(method, result.methodResults[0]);
|
|
563
|
+
* ```
|
|
564
|
+
*/
|
|
565
|
+
export declare class TestClassResult {
|
|
566
|
+
/**
|
|
567
|
+
* The canonical package identity shared by every contained method result.
|
|
568
|
+
*/
|
|
569
|
+
public readonly packageName: string;
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* The discovered test-class name.
|
|
573
|
+
*/
|
|
574
|
+
public readonly className: string;
|
|
575
|
+
|
|
576
|
+
/**
|
|
577
|
+
* The package-relative path of the compiled test file, using `/` separators.
|
|
578
|
+
*/
|
|
579
|
+
public readonly filePath: string;
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* The method results in deterministic execution order.
|
|
583
|
+
*/
|
|
584
|
+
public readonly methodResults: readonly TestMethodResult[];
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* Initializes the complete result snapshot. At least one method result is
|
|
588
|
+
* required, and every method must carry this package and class identity.
|
|
589
|
+
*
|
|
590
|
+
* @param packageName The explicit, non-whitespace package identity; it is never inferred from a path.
|
|
591
|
+
* @param className The non-whitespace discovered class identity.
|
|
592
|
+
* @param filePath The non-whitespace compiled test-file identity, normally package-relative with forward slashes.
|
|
593
|
+
* @param methodResults A non-empty collection whose results all match this package and class. The array is copied; results are shared.
|
|
594
|
+
* @throws ArgumentException if an identity is blank, the collection is empty, or a method belongs to another package or class.
|
|
595
|
+
*
|
|
596
|
+
* See {@link TestClassResult} for usage examples.
|
|
597
|
+
*/
|
|
598
|
+
public constructor(packageName: string, className: string, filePath: string, methodResults: readonly TestMethodResult[]);
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* The filters of a run and how many tests they discovered, selected and left out.
|
|
603
|
+
*
|
|
604
|
+
* @example
|
|
605
|
+
* ```ts
|
|
606
|
+
* import { Assert, TestSelection } from "@noldova/context.testing";
|
|
607
|
+
*
|
|
608
|
+
* const selection = new TestSelection(["category:fast"], 120, 8);
|
|
609
|
+
* Assert.areEqual(112, selection.unselected);
|
|
610
|
+
* Assert.isTrue(selection.isFiltered);
|
|
611
|
+
* ```
|
|
612
|
+
*/
|
|
613
|
+
export declare class TestSelection {
|
|
614
|
+
/**
|
|
615
|
+
* The filters, in the order given; none when the run was not filtered.
|
|
616
|
+
*/
|
|
617
|
+
public readonly filters: readonly string[];
|
|
618
|
+
|
|
619
|
+
/**
|
|
620
|
+
* How many tests discovery found.
|
|
621
|
+
*/
|
|
622
|
+
public readonly discovered: number;
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* How many of them the filters selected.
|
|
626
|
+
*/
|
|
627
|
+
public readonly selected: number;
|
|
628
|
+
|
|
629
|
+
/**
|
|
630
|
+
* How many the filters left out: discovered minus selected.
|
|
631
|
+
*/
|
|
632
|
+
public readonly unselected: number;
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* True when the run had at least one filter.
|
|
636
|
+
*/
|
|
637
|
+
public readonly isFiltered: boolean;
|
|
638
|
+
|
|
639
|
+
/**
|
|
640
|
+
* Creates the selection and computes the number left out.
|
|
641
|
+
*
|
|
642
|
+
* @param filters The filters, in the order given. The selection keeps its own copy.
|
|
643
|
+
* @param discovered How many tests discovery found.
|
|
644
|
+
* @param selected How many of them the filters selected.
|
|
645
|
+
* @throws ArgumentOutOfRangeException if a count is negative or fractional, or selected exceeds discovered.
|
|
646
|
+
*
|
|
647
|
+
* See {@link TestSelection} for usage examples.
|
|
648
|
+
*/
|
|
649
|
+
public constructor(filters: readonly string[], discovered: number, selected: number);
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
/**
|
|
653
|
+
* The reconciled counts of a run: what passed, failed, and was skipped, and how long the tests took.
|
|
654
|
+
*
|
|
655
|
+
* @example
|
|
656
|
+
* ```ts
|
|
657
|
+
* import { Assert, TestRunTotals } from "@noldova/context.testing";
|
|
658
|
+
*
|
|
659
|
+
* const totals = new TestRunTotals(3, 1, 2, 12.5);
|
|
660
|
+
* Assert.areEqual(4, totals.executed);
|
|
661
|
+
* Assert.areEqual(6, totals.total);
|
|
662
|
+
* ```
|
|
663
|
+
*/
|
|
664
|
+
export declare class TestRunTotals {
|
|
665
|
+
/**
|
|
666
|
+
* The measured duration in milliseconds: the sum of the tests' durations for a {@link TestRunResult}, or the elapsed time of a run
|
|
667
|
+
* whose tests ran in parallel.
|
|
668
|
+
*/
|
|
669
|
+
public readonly durationMilliseconds: number;
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* The number of passed tests.
|
|
673
|
+
*/
|
|
674
|
+
public readonly passed: number;
|
|
675
|
+
|
|
676
|
+
/**
|
|
677
|
+
* The number of failed tests.
|
|
678
|
+
*/
|
|
679
|
+
public readonly failed: number;
|
|
680
|
+
|
|
681
|
+
/**
|
|
682
|
+
* The number of explicitly skipped tests.
|
|
683
|
+
*/
|
|
684
|
+
public readonly skipped: number;
|
|
685
|
+
|
|
686
|
+
/**
|
|
687
|
+
* The number of tests that actually ran: passed plus failed.
|
|
688
|
+
*/
|
|
689
|
+
public readonly executed: number;
|
|
690
|
+
|
|
691
|
+
/**
|
|
692
|
+
* Executed plus skipped; must reconcile exactly with discovery.
|
|
693
|
+
*/
|
|
694
|
+
public readonly total: number;
|
|
695
|
+
|
|
696
|
+
/**
|
|
697
|
+
* Initializes the counts and derives the executed and total counts from them.
|
|
698
|
+
*
|
|
699
|
+
* @param passed The number of passed tests, a non-negative integer.
|
|
700
|
+
* @param failed The number of failed tests, a non-negative integer.
|
|
701
|
+
* @param skipped The number of skipped tests, a non-negative integer.
|
|
702
|
+
* @param durationMilliseconds The measured duration in milliseconds, a non-negative finite number.
|
|
703
|
+
* @throws ArgumentOutOfRangeException if a count is negative or fractional, or the duration is negative or not finite.
|
|
704
|
+
*
|
|
705
|
+
* See {@link TestRunTotals} for usage examples.
|
|
706
|
+
*/
|
|
707
|
+
public constructor(passed: number, failed: number, skipped: number, durationMilliseconds: number);
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
/**
|
|
711
|
+
* The reconciled result snapshot of one complete run: its class results and the totals they add up to.
|
|
712
|
+
*
|
|
713
|
+
* @example
|
|
714
|
+
* ```ts
|
|
715
|
+
* import { Assert, TestClassResult, TestMethodResult, TestOutcome, TestRunResult } from "@noldova/context.testing";
|
|
716
|
+
*
|
|
717
|
+
* const method = new TestMethodResult("Sample", "SampleTests", "passes", undefined, [],
|
|
718
|
+
* TestOutcome.Passed, 2, undefined, undefined);
|
|
719
|
+
* const result = new TestRunResult([new TestClassResult("Sample", "SampleTests", "sample.test.js", [method])]);
|
|
720
|
+
* Assert.areEqual(1, result.passed);
|
|
721
|
+
* Assert.areEqual(2, result.durationMilliseconds);
|
|
722
|
+
* Assert.areEqual(0, new TestRunResult([]).total);
|
|
723
|
+
* ```
|
|
724
|
+
*/
|
|
725
|
+
export declare class TestRunResult extends TestRunTotals {
|
|
726
|
+
/**
|
|
727
|
+
* The class results in deterministic execution order.
|
|
728
|
+
*/
|
|
729
|
+
public readonly classResults: readonly TestClassResult[];
|
|
730
|
+
|
|
731
|
+
/**
|
|
732
|
+
* What the run selected out of what it discovered.
|
|
733
|
+
*/
|
|
734
|
+
public readonly selection: TestSelection;
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
* Initializes the result and computes the totals from the class results.
|
|
738
|
+
*
|
|
739
|
+
* @param classResults Class results in execution order. May be empty. The array is copied; result objects are shared.
|
|
740
|
+
* @param selection What the run discovered and selected; every test counts as selected, with no filters, when absent.
|
|
741
|
+
*
|
|
742
|
+
* See {@link TestRunResult} for usage examples.
|
|
743
|
+
*/
|
|
744
|
+
public constructor(classResults: readonly TestClassResult[], selection?: TestSelection);
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
/**
|
|
748
|
+
* One independently executable invocation of a discovered test method.
|
|
749
|
+
*
|
|
750
|
+
* @example
|
|
751
|
+
* ```ts
|
|
752
|
+
* import { Assert, DiscoveredTestMethod } from "@noldova/context.testing";
|
|
753
|
+
*
|
|
754
|
+
* const ordinary = new DiscoveredTestMethod("passes", undefined, [], undefined);
|
|
755
|
+
* const row = new DiscoveredTestMethod("measures", 0, ["abc", 3], undefined, ["Unit"]);
|
|
756
|
+
* Assert.areEqual("passes", ordinary.displayName);
|
|
757
|
+
* Assert.areEqual("measures[0]", row.displayName);
|
|
758
|
+
* ```
|
|
759
|
+
*/
|
|
760
|
+
export declare class DiscoveredTestMethod {
|
|
761
|
+
/**
|
|
762
|
+
* The marked public instance-method name.
|
|
763
|
+
*/
|
|
764
|
+
public readonly methodName: string;
|
|
765
|
+
|
|
766
|
+
/**
|
|
767
|
+
* The zero-based inline-data index, or undefined for a method without test
|
|
768
|
+
* data.
|
|
769
|
+
*/
|
|
770
|
+
public readonly testDataIndex: number | undefined;
|
|
771
|
+
|
|
772
|
+
/**
|
|
773
|
+
* The inline arguments supplied to this invocation. Empty for a method
|
|
774
|
+
* without test data.
|
|
775
|
+
*/
|
|
776
|
+
public readonly testData: readonly unknown[];
|
|
777
|
+
|
|
778
|
+
/**
|
|
779
|
+
* The explicit skip reason, when the method is skipped.
|
|
780
|
+
*/
|
|
781
|
+
public readonly skipReason: string | undefined;
|
|
782
|
+
|
|
783
|
+
/**
|
|
784
|
+
* The distinct category names declared by the method and inherited from its
|
|
785
|
+
* test class, in written order.
|
|
786
|
+
*/
|
|
787
|
+
public readonly categories: readonly string[];
|
|
788
|
+
|
|
789
|
+
/**
|
|
790
|
+
* The method name followed by its data index when this is a parameterized
|
|
791
|
+
* invocation.
|
|
792
|
+
*/
|
|
793
|
+
public readonly displayName: string;
|
|
794
|
+
|
|
795
|
+
/**
|
|
796
|
+
* Initializes one discovered invocation and validates its data identity and
|
|
797
|
+
* optional skip reason and categories.
|
|
798
|
+
*
|
|
799
|
+
* @param methodName The non-whitespace public instance-method name, without a data-row suffix.
|
|
800
|
+
* @param testDataIndex The non-negative integer, zero-based row index; undefined for a non-parameterized invocation.
|
|
801
|
+
* @param testData The row's arguments. Non-empty exactly when testDataIndex is present. The array is copied; its values remain shared.
|
|
802
|
+
* @param skipReason A non-whitespace reason when skipped, or undefined otherwise.
|
|
803
|
+
* @param categories Optional non-whitespace category names. Defaults to empty; duplicates are removed in first-occurrence order and the array is copied.
|
|
804
|
+
* @throws ArgumentException if the name, reason, or categories are blank, or the row data and index disagree.
|
|
805
|
+
* @throws ArgumentOutOfRangeException if the data index is negative or fractional.
|
|
806
|
+
*
|
|
807
|
+
* See {@link DiscoveredTestMethod} for usage examples.
|
|
808
|
+
*/
|
|
809
|
+
public constructor(
|
|
810
|
+
methodName: string,
|
|
811
|
+
testDataIndex: number | undefined,
|
|
812
|
+
testData: readonly unknown[],
|
|
813
|
+
skipReason: string | undefined,
|
|
814
|
+
categories?: readonly string[]);
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
/**
|
|
818
|
+
* One discovered test class, its constructor, and its test methods.
|
|
819
|
+
*
|
|
820
|
+
* @example
|
|
821
|
+
* ```ts
|
|
822
|
+
* import { Assert, DiscoveredTestClass, DiscoveredTestMethod } from "@noldova/context.testing";
|
|
823
|
+
*
|
|
824
|
+
* class SampleTests {
|
|
825
|
+
* public passes(): void { }
|
|
826
|
+
* }
|
|
827
|
+
* const method = new DiscoveredTestMethod("passes", undefined, [], undefined);
|
|
828
|
+
* const discovered = new DiscoveredTestClass("Sample", "SampleTests", "sample.test.js",
|
|
829
|
+
* SampleTests, undefined, [method], ["Unit"]);
|
|
830
|
+
* Assert.areEqual(SampleTests, discovered.testClassConstructor);
|
|
831
|
+
* // Normally obtain this model from TestDiscovery rather than assemble it.
|
|
832
|
+
* ```
|
|
833
|
+
*/
|
|
834
|
+
export declare class DiscoveredTestClass {
|
|
835
|
+
/**
|
|
836
|
+
* The canonical package identity supplied by the test project.
|
|
837
|
+
*/
|
|
838
|
+
public readonly packageName: string;
|
|
839
|
+
|
|
840
|
+
/**
|
|
841
|
+
* The exported marked class name.
|
|
842
|
+
*/
|
|
843
|
+
public readonly className: string;
|
|
844
|
+
|
|
845
|
+
/**
|
|
846
|
+
* The package-relative path of the compiled test file, using `/` separators.
|
|
847
|
+
*/
|
|
848
|
+
public readonly filePath: string;
|
|
849
|
+
|
|
850
|
+
/**
|
|
851
|
+
* The constructor used to create a fresh instance for each test invocation.
|
|
852
|
+
*/
|
|
853
|
+
public readonly testClassConstructor: new () => object;
|
|
854
|
+
|
|
855
|
+
/**
|
|
856
|
+
* The explicit class-level skip reason, when the complete class is skipped.
|
|
857
|
+
*/
|
|
858
|
+
public readonly skipReason: string | undefined;
|
|
859
|
+
|
|
860
|
+
/**
|
|
861
|
+
* The discovered method invocations in deterministic method and data order.
|
|
862
|
+
*/
|
|
863
|
+
public readonly methods: readonly DiscoveredTestMethod[];
|
|
864
|
+
|
|
865
|
+
/**
|
|
866
|
+
* The distinct category names declared by the test class, in written order.
|
|
867
|
+
*/
|
|
868
|
+
public readonly categories: readonly string[];
|
|
869
|
+
|
|
870
|
+
/**
|
|
871
|
+
* Initializes the discovered class with at least one method and an immutable
|
|
872
|
+
* copy of the method and category collections.
|
|
873
|
+
*
|
|
874
|
+
* @param packageName The explicit, non-whitespace package identity; it is never inferred from a path.
|
|
875
|
+
* @param className The non-whitespace discovered class identity.
|
|
876
|
+
* @param filePath The non-whitespace compiled test-file identity, normally package-relative with forward slashes.
|
|
877
|
+
* @param testClassConstructor The parameterless constructor used for a fresh instance per invocation. It must create the discovered public instance
|
|
878
|
+
* methods.
|
|
879
|
+
* @param skipReason A non-whitespace reason when skipped, or undefined otherwise.
|
|
880
|
+
* @param methods The non-empty, ordered discovered invocations. The array is copied; method objects are shared.
|
|
881
|
+
* @param categories Optional non-whitespace category names. Defaults to empty; duplicates are removed in first-occurrence order and the array is copied.
|
|
882
|
+
* @throws ArgumentException if an identity, reason, or category is blank, or no methods are supplied.
|
|
883
|
+
*
|
|
884
|
+
* See {@link DiscoveredTestClass} for usage examples.
|
|
885
|
+
*/
|
|
886
|
+
public constructor(
|
|
887
|
+
packageName: string,
|
|
888
|
+
className: string,
|
|
889
|
+
filePath: string,
|
|
890
|
+
testClassConstructor: new () => object,
|
|
891
|
+
skipReason: string | undefined,
|
|
892
|
+
methods: readonly DiscoveredTestMethod[],
|
|
893
|
+
categories?: readonly string[]);
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
/**
|
|
897
|
+
* One test project's explicit package identity and compiled test root.
|
|
898
|
+
*
|
|
899
|
+
* @example
|
|
900
|
+
* ```ts
|
|
901
|
+
* import { Assert, TestProject } from "@noldova/context.testing";
|
|
902
|
+
*
|
|
903
|
+
* const project = new TestProject("Sample", "./compiled/tests");
|
|
904
|
+
* Assert.areEqual("Sample", project.packageName);
|
|
905
|
+
* // The build supplies the compiled root explicitly; identity is not inferred from its path.
|
|
906
|
+
* ```
|
|
907
|
+
*/
|
|
908
|
+
export declare class TestProject {
|
|
909
|
+
/**
|
|
910
|
+
* The canonical package identity assigned to discovered tests.
|
|
911
|
+
*/
|
|
912
|
+
public readonly packageName: string;
|
|
913
|
+
|
|
914
|
+
/**
|
|
915
|
+
* The root directory containing the compiled test project.
|
|
916
|
+
*/
|
|
917
|
+
public readonly rootDirectory: string;
|
|
918
|
+
|
|
919
|
+
/**
|
|
920
|
+
* Initializes the project identity used by discovery and reporting.
|
|
921
|
+
*
|
|
922
|
+
* @param packageName The explicit, non-whitespace package identity; it is never inferred from a path.
|
|
923
|
+
* @param rootDirectory The non-whitespace compiled test root. Discovery resolves filesystem access using the host working directory for relative paths.
|
|
924
|
+
* @throws ArgumentException if the package identity or root is blank.
|
|
925
|
+
*
|
|
926
|
+
* See {@link TestProject} for usage examples.
|
|
927
|
+
*/
|
|
928
|
+
public constructor(packageName: string, rootDirectory: string);
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
/**
|
|
932
|
+
* Deterministic discovery of test classes from compiled test output.
|
|
933
|
+
* Violations of the testing contract fail with `TestingException`.
|
|
934
|
+
*
|
|
935
|
+
* @example
|
|
936
|
+
* ```ts
|
|
937
|
+
* import { Assert, TestClass, TestDiscovery, TestMethod } from "@noldova/context.testing";
|
|
938
|
+
*
|
|
939
|
+
* @TestClass
|
|
940
|
+
* class SampleTests {
|
|
941
|
+
* @TestMethod
|
|
942
|
+
* public passes(): void { }
|
|
943
|
+
* }
|
|
944
|
+
* const classes = new TestDiscovery().discoverModuleExports({ SampleTests }, "sample.test.js", "Sample");
|
|
945
|
+
* Assert.areEqual("passes", classes[0]?.methods[0]?.methodName);
|
|
946
|
+
* ```
|
|
947
|
+
*/
|
|
948
|
+
export declare class TestDiscovery {
|
|
949
|
+
/**
|
|
950
|
+
* Discovers every test class beneath the explicitly identified projects:
|
|
951
|
+
* `*.test.js` files in sorted order, exports in sorted order, methods in
|
|
952
|
+
* sorted order.
|
|
953
|
+
*
|
|
954
|
+
* @param testProjects Explicit project identities and compiled roots. An empty collection discovers no tests.
|
|
955
|
+
* @param onFileImported Optional callback given each test file's path, relative to its project root with `/` separators, once the file is
|
|
956
|
+
* imported and before its classes are discovered. Defaults to none.
|
|
957
|
+
* @returns A promise resolving to discovered classes in code-unit order by package, root, file, export, then method; rows preserve written order.
|
|
958
|
+
* @throws ArgumentException via promise rejection if a supplied root is blank.
|
|
959
|
+
* @throws TestingException via promise rejection for invalid test declarations or metadata, including a test file with no marked class.
|
|
960
|
+
* @throws Error via promise rejection when host filesystem access or module loading fails.
|
|
961
|
+
*
|
|
962
|
+
* See {@link TestDiscovery} for usage examples.
|
|
963
|
+
*/
|
|
964
|
+
public discoverAsync(testProjects: readonly TestProject[], onFileImported?: (filePath: string) => void): Promise<DiscoveredTestClass[]>;
|
|
965
|
+
|
|
966
|
+
/**
|
|
967
|
+
* Discovers the test classes of one loaded module under the given package
|
|
968
|
+
* name. Exposed for programmatic and framework self-verification use.
|
|
969
|
+
*
|
|
970
|
+
* @param moduleExports The loaded module's exports. Discovery reads own data properties without invoking export getters.
|
|
971
|
+
* @param filePath The non-whitespace compiled test-file identity, normally package-relative with forward slashes.
|
|
972
|
+
* @param packageName The explicit, non-whitespace package identity; it is never inferred from a path.
|
|
973
|
+
* @returns The discovered classes in export-name code-unit order, with methods in name order and data rows in written order.
|
|
974
|
+
* @throws ArgumentException if filePath or packageName is blank.
|
|
975
|
+
* @throws TestingException if a declaration or mark is invalid, or the module yields no marked test class.
|
|
976
|
+
*
|
|
977
|
+
* See {@link TestDiscovery} for usage examples.
|
|
978
|
+
*/
|
|
979
|
+
public discoverModuleExports(moduleExports: object, filePath: string, packageName: string): DiscoveredTestClass[];
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
/**
|
|
983
|
+
* Receives a run's progress while it executes. {@link TestConsoleReporter} implements it to write each class's
|
|
984
|
+
* results as soon as they are known.
|
|
985
|
+
*
|
|
986
|
+
* @example
|
|
987
|
+
* ```ts
|
|
988
|
+
* import { Assert, type ITestProgressListener, TestClass, TestClassResult, TestDiscovery, TestExecutor, TestMethod } from "@noldova/context.testing";
|
|
989
|
+
*
|
|
990
|
+
* class CompletedClassNames implements ITestProgressListener {
|
|
991
|
+
* public readonly names: string[] = [];
|
|
992
|
+
*
|
|
993
|
+
* public onClassCompleted(classResult: TestClassResult): void {
|
|
994
|
+
* this.names.push(classResult.className);
|
|
995
|
+
* }
|
|
996
|
+
* }
|
|
997
|
+
*
|
|
998
|
+
* @TestClass
|
|
999
|
+
* class SampleTests {
|
|
1000
|
+
* @TestMethod
|
|
1001
|
+
* public passes(): void {
|
|
1002
|
+
* Assert.isTrue(true);
|
|
1003
|
+
* }
|
|
1004
|
+
* }
|
|
1005
|
+
* const listener = new CompletedClassNames();
|
|
1006
|
+
* await new TestExecutor(1000).executeAsync(new TestDiscovery().discoverModuleExports({ SampleTests }, "sample.test.js", "Sample"), listener);
|
|
1007
|
+
* Assert.areEqual("SampleTests", listener.names.join(","));
|
|
1008
|
+
* ```
|
|
1009
|
+
*/
|
|
1010
|
+
export declare interface ITestProgressListener {
|
|
1011
|
+
/**
|
|
1012
|
+
* Receives each method invocation just before it runs, in execution order, including invocations that are skipped or recorded as stopped.
|
|
1013
|
+
*
|
|
1014
|
+
* @param testClass The class the invocation belongs to.
|
|
1015
|
+
* @param method The invocation about to run.
|
|
1016
|
+
* @throws Error of any kind; the throw ends the run by rejecting the executing promise.
|
|
1017
|
+
*
|
|
1018
|
+
* See {@link ITestProgressListener} for usage examples.
|
|
1019
|
+
*/
|
|
1020
|
+
onMethodStarted?(testClass: DiscoveredTestClass, method: DiscoveredTestMethod): void;
|
|
1021
|
+
|
|
1022
|
+
/**
|
|
1023
|
+
* Receives each invocation's result as soon as it is known, before the next invocation starts.
|
|
1024
|
+
*
|
|
1025
|
+
* @param methodResult The invocation's result, the same object its class result later holds.
|
|
1026
|
+
* @throws Error of any kind; the throw ends the run by rejecting the executing promise.
|
|
1027
|
+
*
|
|
1028
|
+
* See {@link ITestProgressListener} for usage examples.
|
|
1029
|
+
*/
|
|
1030
|
+
onMethodCompleted?(methodResult: TestMethodResult): void;
|
|
1031
|
+
|
|
1032
|
+
/**
|
|
1033
|
+
* Receives a class's result as soon as every invocation of that class has finished, before the next class starts.
|
|
1034
|
+
*
|
|
1035
|
+
* @param classResult The finished class's result, the same object the run later returns.
|
|
1036
|
+
* @throws Error of any kind; the throw ends the run by rejecting the executing promise.
|
|
1037
|
+
*
|
|
1038
|
+
* See {@link ITestProgressListener} for usage examples.
|
|
1039
|
+
*/
|
|
1040
|
+
onClassCompleted(classResult: TestClassResult): void;
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
/**
|
|
1044
|
+
* The clock a test executor reads its durations from and arms its per-test
|
|
1045
|
+
* timeout on, a parallel runner times its workers on, and a console reporter
|
|
1046
|
+
* animates its progress line on. Each uses the system clock by default; a test
|
|
1047
|
+
* of a runner may pass its own to force a time without waiting for it.
|
|
1048
|
+
*
|
|
1049
|
+
* @example
|
|
1050
|
+
* ```ts
|
|
1051
|
+
* import { Assert, type IClock, TestClass, TestDiscovery, TestExecutor, TestMethod, TestOutcome } from "@noldova/context.testing";
|
|
1052
|
+
*
|
|
1053
|
+
* class FixedClock implements IClock {
|
|
1054
|
+
* public now(): number {
|
|
1055
|
+
* return 0;
|
|
1056
|
+
* }
|
|
1057
|
+
*
|
|
1058
|
+
* public setTimeout(callback: () => void, delayMilliseconds: number): number {
|
|
1059
|
+
* return Number(setTimeout(callback, delayMilliseconds));
|
|
1060
|
+
* }
|
|
1061
|
+
*
|
|
1062
|
+
* public clearTimeout(timer: number | undefined): void {
|
|
1063
|
+
* clearTimeout(timer);
|
|
1064
|
+
* }
|
|
1065
|
+
* }
|
|
1066
|
+
*
|
|
1067
|
+
* @TestClass
|
|
1068
|
+
* class SampleTests {
|
|
1069
|
+
* @TestMethod
|
|
1070
|
+
* public passes(): void {
|
|
1071
|
+
* Assert.isTrue(true);
|
|
1072
|
+
* }
|
|
1073
|
+
* }
|
|
1074
|
+
* const classes = new TestDiscovery().discoverModuleExports({ SampleTests }, "sample.test.js", "Sample");
|
|
1075
|
+
* const results = await new TestExecutor(1000, new FixedClock()).executeAsync(classes);
|
|
1076
|
+
* Assert.areEqual(TestOutcome.Passed, results[0]?.methodResults[0]?.outcome);
|
|
1077
|
+
* Assert.areEqual(0, results[0]?.methodResults[0]?.durationMilliseconds);
|
|
1078
|
+
* ```
|
|
1079
|
+
*/
|
|
1080
|
+
export declare interface IClock {
|
|
1081
|
+
/**
|
|
1082
|
+
* Reads the current time in milliseconds, from an arbitrary origin that never moves backwards.
|
|
1083
|
+
*
|
|
1084
|
+
* @returns The current time in milliseconds.
|
|
1085
|
+
*
|
|
1086
|
+
* See {@link IClock} for usage examples.
|
|
1087
|
+
*/
|
|
1088
|
+
now(): number;
|
|
1089
|
+
|
|
1090
|
+
/**
|
|
1091
|
+
* Arms a timer that calls the callback once, after the delay.
|
|
1092
|
+
*
|
|
1093
|
+
* @param callback The function to call when the timer fires.
|
|
1094
|
+
* @param delayMilliseconds The delay in milliseconds before the callback runs.
|
|
1095
|
+
* @returns The timer's id, which `clearTimeout` takes.
|
|
1096
|
+
*
|
|
1097
|
+
* See {@link IClock} for usage examples.
|
|
1098
|
+
*/
|
|
1099
|
+
setTimeout(callback: () => void, delayMilliseconds: number): number;
|
|
1100
|
+
|
|
1101
|
+
/**
|
|
1102
|
+
* Disarms a timer so its callback never runs; an id that is `undefined`, already fired or already cleared is ignored.
|
|
1103
|
+
*
|
|
1104
|
+
* @param timer The id `setTimeout` returned, or `undefined`.
|
|
1105
|
+
*
|
|
1106
|
+
* See {@link IClock} for usage examples.
|
|
1107
|
+
*/
|
|
1108
|
+
clearTimeout(timer: number | undefined): void;
|
|
1109
|
+
}
|
|
1110
|
+
|
|
1111
|
+
/**
|
|
1112
|
+
* Executes discovered tests: a fresh instance per method invocation, awaited
|
|
1113
|
+
* asynchronous work, a loud timeout, and unhandled-rejection attribution.
|
|
1114
|
+
* During bootstrap, calls must not overlap. A timeout cannot interrupt running
|
|
1115
|
+
* work or synchronous runaway code; the caller must not treat it as isolation.
|
|
1116
|
+
* The command-line run and {@link ParallelTestRunner} supply that isolation:
|
|
1117
|
+
* they run the executor in parallel worker threads they time per invocation
|
|
1118
|
+
* and stop a worker when an invocation overruns. A fresh worker keeps every result already reported and
|
|
1119
|
+
* resumes after an invocation whose timeout the worker reported, or records an
|
|
1120
|
+
* invocation the main thread had to stop as timed out without running it again.
|
|
1121
|
+
* The first invocation failure is preserved when a pending stray rejection also occurs.
|
|
1122
|
+
*
|
|
1123
|
+
* @example
|
|
1124
|
+
* ```ts
|
|
1125
|
+
* import { Assert, TestClass, TestDiscovery, TestExecutor, TestMethod, TestOutcome } from "@noldova/context.testing";
|
|
1126
|
+
*
|
|
1127
|
+
* @TestClass
|
|
1128
|
+
* class SampleTests {
|
|
1129
|
+
* @TestMethod
|
|
1130
|
+
* public async passesAsync(): Promise<void> {
|
|
1131
|
+
* Assert.areEqual(1, await Promise.resolve(1));
|
|
1132
|
+
* }
|
|
1133
|
+
* }
|
|
1134
|
+
* const classes = new TestDiscovery().discoverModuleExports({ SampleTests }, "sample.test.js", "Sample");
|
|
1135
|
+
* const results = await new TestExecutor(1000).executeAsync(classes);
|
|
1136
|
+
* Assert.areEqual(TestOutcome.Passed, results[0]?.methodResults[0]?.outcome);
|
|
1137
|
+
* ```
|
|
1138
|
+
*/
|
|
1139
|
+
export declare class TestExecutor {
|
|
1140
|
+
/**
|
|
1141
|
+
* Initializes the executor with a positive integer per-test timeout in
|
|
1142
|
+
* milliseconds. Invalid values throw `ArgumentOutOfRangeException`.
|
|
1143
|
+
*
|
|
1144
|
+
* @param timeoutMilliseconds The per-test positive integer timeout in milliseconds, at most 2147483647 in the Node bootstrap.
|
|
1145
|
+
* @param clock The clock that times each invocation and arms its timeout. Defaults to the system clock.
|
|
1146
|
+
* @throws ArgumentOutOfRangeException if the timeout is non-positive, fractional, or exceeds the Node timer limit.
|
|
1147
|
+
*
|
|
1148
|
+
* See {@link TestExecutor} for usage examples.
|
|
1149
|
+
*/
|
|
1150
|
+
public constructor(timeoutMilliseconds: number, clock?: IClock);
|
|
1151
|
+
|
|
1152
|
+
/**
|
|
1153
|
+
* Executes every method invocation of every class in order and returns its
|
|
1154
|
+
* independent result.
|
|
1155
|
+
*
|
|
1156
|
+
* @param testClasses The already discovered, validated classes in execution order. May be empty.
|
|
1157
|
+
* @param progressListener Optional listener told of each invocation as it starts and finishes and of each class's result as soon as that class
|
|
1158
|
+
* finishes, in execution order and before the next class starts.
|
|
1159
|
+
* @param stoppedMethods Invocations a supervisor stopped because they overran the timeout; each is recorded as a Failed result carrying a
|
|
1160
|
+
* {@link TestTimeoutException} and a duration of the timeout, without running it again. Defaults to none.
|
|
1161
|
+
* @param isStopping Optional check that stops the run: the executor calls it before each invocation, and once it returns `true` the
|
|
1162
|
+
* executor starts no further invocation, completes a class only when its last invocation has finished, and returns the results of the
|
|
1163
|
+
* classes that completed. The listener's `onMethodCompleted` may make it return `true` to stop after that invocation.
|
|
1164
|
+
* @returns A promise resolving to one result per supplied class and invocation. Test failures become Failed results, not rejection of this promise.
|
|
1165
|
+
* Empty input returns an empty array; a stopped run returns only the classes that completed before it stopped.
|
|
1166
|
+
* @throws Error via promise rejection with the listener's own exception when the listener throws; the executor's unhandled-rejection listener is
|
|
1167
|
+
* removed either way.
|
|
1168
|
+
* @example
|
|
1169
|
+
* ```ts
|
|
1170
|
+
* import { Assert, TestClass, TestDiscovery, TestExecutor, TestMethod } from "@noldova/context.testing";
|
|
1171
|
+
*
|
|
1172
|
+
* @TestClass
|
|
1173
|
+
* class FirstTests {
|
|
1174
|
+
* @TestMethod
|
|
1175
|
+
* public passes(): void { }
|
|
1176
|
+
* }
|
|
1177
|
+
*
|
|
1178
|
+
* @TestClass
|
|
1179
|
+
* class SecondTests {
|
|
1180
|
+
* @TestMethod
|
|
1181
|
+
* public passes(): void { }
|
|
1182
|
+
* }
|
|
1183
|
+
* const classes = new TestDiscovery().discoverModuleExports({ FirstTests, SecondTests }, "sample.test.js", "Sample");
|
|
1184
|
+
* let completedClasses = 0;
|
|
1185
|
+
* const listener = { onClassCompleted: (): void => { completedClasses++; } };
|
|
1186
|
+
* const results = await new TestExecutor(1000).executeAsync(classes, listener, undefined, () => completedClasses > 0);
|
|
1187
|
+
* Assert.areEqual(1, results.length); // Stopped after the first class.
|
|
1188
|
+
* ```
|
|
1189
|
+
*/
|
|
1190
|
+
public executeAsync(testClasses: readonly DiscoveredTestClass[], progressListener?: ITestProgressListener,
|
|
1191
|
+
stoppedMethods?: ReadonlySet<DiscoveredTestMethod>, isStopping?: () => boolean): Promise<TestClassResult[]>;
|
|
1192
|
+
}
|
|
1193
|
+
|
|
1194
|
+
/**
|
|
1195
|
+
* Orchestrates discovery, selection, execution, and reconciliation.
|
|
1196
|
+
*
|
|
1197
|
+
* @example
|
|
1198
|
+
* ```ts
|
|
1199
|
+
* import { TestDiscovery, TestExecutor, TestProject, TestRunner, TestRunResult } from "@noldova/context.testing";
|
|
1200
|
+
*
|
|
1201
|
+
* export async function runUnitTestsAsync(compiledTestDirectory: string): Promise<TestRunResult> {
|
|
1202
|
+
* const runner = new TestRunner(new TestDiscovery(), new TestExecutor(5000));
|
|
1203
|
+
* return runner.runAsync([new TestProject("Sample", compiledTestDirectory)], ["category:Unit"]);
|
|
1204
|
+
* }
|
|
1205
|
+
* // Pass an existing compiled test root. Omitting filters selects every discovered test.
|
|
1206
|
+
* ```
|
|
1207
|
+
*/
|
|
1208
|
+
export declare class TestRunner {
|
|
1209
|
+
/**
|
|
1210
|
+
* Initializes the runner with its discovery and executor.
|
|
1211
|
+
*
|
|
1212
|
+
* @param discovery The discovery service used for the supplied compiled projects.
|
|
1213
|
+
* @param executor The execution service used for selected invocations.
|
|
1214
|
+
*
|
|
1215
|
+
* See {@link TestRunner} for usage examples.
|
|
1216
|
+
*/
|
|
1217
|
+
public constructor(discovery: TestDiscovery, executor: TestExecutor);
|
|
1218
|
+
|
|
1219
|
+
/**
|
|
1220
|
+
* Runs the explicitly identified test projects. Optional filters select by
|
|
1221
|
+
* package name, file path, class name, `ClassName.methodName`, indexed
|
|
1222
|
+
* data-case substring, or exact `category:name` identity and are combined
|
|
1223
|
+
* with OR semantics. Fails when result totals do not reconcile with discovery.
|
|
1224
|
+
*
|
|
1225
|
+
* @param testProjects Explicit project identities and compiled roots. An empty collection discovers no tests.
|
|
1226
|
+
* @param filters Optional case-sensitive identity substrings or exact category:name selectors, combined with OR. Defaults to no filtering.
|
|
1227
|
+
* @param progressListener Optional listener told of each selected class's result as soon as that class finishes, before the totals are
|
|
1228
|
+
* reconciled; see {@link TestExecutor.executeAsync}.
|
|
1229
|
+
* @returns A promise resolving to the reconciled result. No matches produce a zero-test result; the command-line entry treats it as failure.
|
|
1230
|
+
* @throws TestingException via promise rejection if execution totals do not match the selected invocations.
|
|
1231
|
+
* @throws Error via promise rejection when discovery fails; the original discovery failure is preserved.
|
|
1232
|
+
*
|
|
1233
|
+
* See {@link TestRunner} for usage examples.
|
|
1234
|
+
*/
|
|
1235
|
+
public runAsync(testProjects: readonly TestProject[], filters?: readonly string[], progressListener?: ITestProgressListener): Promise<TestRunResult>;
|
|
1236
|
+
|
|
1237
|
+
/**
|
|
1238
|
+
* Discovers the explicitly identified test projects and returns the classes the filters select, in execution order, without running them.
|
|
1239
|
+
* Filters select as {@link TestRunner.runAsync} describes; a class selected only through some of its methods holds just those methods.
|
|
1240
|
+
*
|
|
1241
|
+
* @param testProjects Explicit project identities and compiled roots. An empty collection discovers no tests.
|
|
1242
|
+
* @param filters Optional case-sensitive identity substrings or exact category:name selectors, combined with OR. Defaults to no filtering.
|
|
1243
|
+
* @returns A promise resolving to the selected classes in execution order.
|
|
1244
|
+
* @throws Error via promise rejection when discovery fails; the original discovery failure is preserved.
|
|
1245
|
+
*
|
|
1246
|
+
* See {@link TestRunner} for usage examples.
|
|
1247
|
+
*/
|
|
1248
|
+
public selectAsync(testProjects: readonly TestProject[], filters?: readonly string[]): Promise<DiscoveredTestClass[]>;
|
|
1249
|
+
|
|
1250
|
+
/**
|
|
1251
|
+
* Returns the already discovered classes the filters select, in execution order, without running them.
|
|
1252
|
+
* Filters select as {@link TestRunner.runAsync} describes; a class selected only through some of its methods holds just those methods.
|
|
1253
|
+
*
|
|
1254
|
+
* @param testClasses Discovered classes in execution order; the collection and its classes are not mutated.
|
|
1255
|
+
* @param filters Optional case-sensitive identity substrings or exact category:name selectors, combined with OR. Defaults to no filtering.
|
|
1256
|
+
* @returns The selected classes in execution order; a copy of the input when there are no filters.
|
|
1257
|
+
* @example
|
|
1258
|
+
* ```ts
|
|
1259
|
+
* import { Assert, TestClass, TestDiscovery, TestExecutor, TestMethod, TestRunner } from "@noldova/context.testing";
|
|
1260
|
+
*
|
|
1261
|
+
* @TestClass
|
|
1262
|
+
* class SampleTests {
|
|
1263
|
+
* @TestMethod
|
|
1264
|
+
* public adds(): void { }
|
|
1265
|
+
*
|
|
1266
|
+
* @TestMethod
|
|
1267
|
+
* public subtracts(): void { }
|
|
1268
|
+
* }
|
|
1269
|
+
* const discovery = new TestDiscovery();
|
|
1270
|
+
* const classes = discovery.discoverModuleExports({ SampleTests }, "sample.test.js", "Sample");
|
|
1271
|
+
* const selected = new TestRunner(discovery, new TestExecutor(1000)).select(classes, ["SampleTests.adds"]);
|
|
1272
|
+
* Assert.areEqual(1, selected[0]?.methods.length);
|
|
1273
|
+
* ```
|
|
1274
|
+
*/
|
|
1275
|
+
public select(testClasses: readonly DiscoveredTestClass[], filters?: readonly string[]): DiscoveredTestClass[];
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
/**
|
|
1279
|
+
* Runs tests in parallel worker threads, as the command-line run does, and
|
|
1280
|
+
* returns the same result objects as {@link TestRunner}. Each worker discovers
|
|
1281
|
+
* the projects itself and takes whole classes from one shared queue; the main
|
|
1282
|
+
* thread loads no test module. A test that overruns the timeout, whether it
|
|
1283
|
+
* never settles or runs synchronous code that never ends, is recorded as
|
|
1284
|
+
* timed out with a {@link TestTimeoutException}, its worker is ended, and a
|
|
1285
|
+
* fresh worker resumes after it, so no test runs twice and the run goes on.
|
|
1286
|
+
* Every worker has ended before the returned promise settles. The runner
|
|
1287
|
+
* leaves the process's environment unchanged; an app that wants the tests'
|
|
1288
|
+
* temporary files in a folder of its own sets `TMPDIR`, `TEMP` and `TMP` first.
|
|
1289
|
+
*
|
|
1290
|
+
* Results cross from the workers as data. Test data, assertion values and
|
|
1291
|
+
* thrown values that are a string, number, boolean, bigint, `null` or
|
|
1292
|
+
* `undefined` arrive unchanged; any other value arrives as a value that prints
|
|
1293
|
+
* as the original did. An {@link AssertFailedException} or a
|
|
1294
|
+
* {@link TestTimeoutException} arrives as that exception; any other error
|
|
1295
|
+
* arrives as an `Error` with the original's name, message and stack.
|
|
1296
|
+
* {@link TestReportWriter.formatMethodLines} therefore gives the same lines for
|
|
1297
|
+
* a result from either runner.
|
|
1298
|
+
*
|
|
1299
|
+
* @example
|
|
1300
|
+
* ```ts
|
|
1301
|
+
* import { ParallelTestRunner, TestProject, type TestRunResult } from "@noldova/context.testing";
|
|
1302
|
+
*
|
|
1303
|
+
* export async function runUnitTestsAsync(compiledTestDirectory: string): Promise<TestRunResult> {
|
|
1304
|
+
* return new ParallelTestRunner(5000).runAsync([new TestProject("Sample", compiledTestDirectory)], ["category:Unit"]);
|
|
1305
|
+
* }
|
|
1306
|
+
* // Pass an existing compiled test root. Omitting filters selects every discovered test.
|
|
1307
|
+
* ```
|
|
1308
|
+
*/
|
|
1309
|
+
export declare class ParallelTestRunner {
|
|
1310
|
+
/**
|
|
1311
|
+
* Initializes the runner with a positive integer per-test timeout in milliseconds and its number of workers.
|
|
1312
|
+
*
|
|
1313
|
+
* @param timeoutMilliseconds The per-test positive integer timeout in milliseconds; with the main thread's 250 ms grace, at most 2147483647
|
|
1314
|
+
* in the Node bootstrap.
|
|
1315
|
+
* @param workerCount The positive integer number of workers. Defaults to one per available processor and at least two.
|
|
1316
|
+
* @param clock The clock the main thread times its workers on: the start limit, of 5000 ms or the timeout plus 250 ms, whichever is longer, and
|
|
1317
|
+
* the timeout plus 250 ms for each test. Defaults to the system clock. The workers time each test on the system clock.
|
|
1318
|
+
* @throws ArgumentOutOfRangeException if the timeout or the worker count is non-positive or fractional, or the timeout exceeds the Node timer
|
|
1319
|
+
* limit.
|
|
1320
|
+
*
|
|
1321
|
+
* See {@link ParallelTestRunner} for usage examples.
|
|
1322
|
+
*/
|
|
1323
|
+
public constructor(timeoutMilliseconds: number, workerCount?: number, clock?: IClock);
|
|
1324
|
+
|
|
1325
|
+
/**
|
|
1326
|
+
* Runs the explicitly identified test projects in parallel workers. Filters select as {@link TestRunner.runAsync} describes.
|
|
1327
|
+
*
|
|
1328
|
+
* @param testProjects Explicit project identities and compiled roots. An empty collection discovers no tests.
|
|
1329
|
+
* @param filters Optional case-sensitive identity substrings or exact category:name selectors, combined with OR. Defaults to no filtering.
|
|
1330
|
+
* @param progressListener Optional listener told of each test's result as it finishes, in whichever worker, and of each class's result in
|
|
1331
|
+
* discovery order. Its `onMethodStarted` is never called: only the workers load the test modules, so the main thread holds no discovered
|
|
1332
|
+
* class or method to pass, and loading the modules there too would run their top-level code a second time.
|
|
1333
|
+
* @returns A promise resolving to the reconciled result, with classes in discovery order and each class's methods in execution order. Its time
|
|
1334
|
+
* is the sum of its tests' durations, as from {@link TestRunner}. No matches produce a zero-test result; the command-line entry treats it as
|
|
1335
|
+
* failure. Test failures and timeouts become Failed results, not rejection of this promise.
|
|
1336
|
+
* @throws TestingException via promise rejection when a worker crashes or exits, starts no test within its start limit, discovers different
|
|
1337
|
+
* tests from another worker, or exchanges invalid data, when a class leaves a timer, handle or request open in its worker, or when the totals
|
|
1338
|
+
* do not reconcile with the selected tests; every worker has ended first.
|
|
1339
|
+
* @throws Error via promise rejection with the worker's own error when a worker fails to start or discovery fails, or with the listener's own
|
|
1340
|
+
* exception when the listener throws; every worker has ended first.
|
|
1341
|
+
*
|
|
1342
|
+
* See {@link ParallelTestRunner} for usage examples.
|
|
1343
|
+
*/
|
|
1344
|
+
public runAsync(testProjects: readonly TestProject[], filters?: readonly string[], progressListener?: ITestProgressListener): Promise<TestRunResult>;
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
/**
|
|
1348
|
+
* Console formatting of a run result: one block per class, then the totals.
|
|
1349
|
+
* Each class heading includes its package, package-relative file path, and
|
|
1350
|
+
* class identity. The structured result remains the authority; no consumer
|
|
1351
|
+
* parses this output. {@link TestConsoleReporter} writes the same blocks while
|
|
1352
|
+
* a run progresses.
|
|
1353
|
+
*
|
|
1354
|
+
* @example
|
|
1355
|
+
* ```ts
|
|
1356
|
+
* import { Assert, TestClassResult, TestMethodResult, TestOutcome, TestReportWriter, TestRunResult } from "@noldova/context.testing";
|
|
1357
|
+
*
|
|
1358
|
+
* const writer = new TestReportWriter();
|
|
1359
|
+
* const classResult = new TestClassResult("Sample", "SampleTests", "sample.test.js", [
|
|
1360
|
+
* new TestMethodResult("Sample", "SampleTests", "passes", undefined, [], TestOutcome.Passed, 1, undefined, undefined)]);
|
|
1361
|
+
* Assert.isTrue(writer.formatLines(new TestRunResult([]), true).includes("Total: 0"));
|
|
1362
|
+
* Assert.areEqual("Sample/sample.test.js — SampleTests", writer.formatClassLines(classResult, false)[0]);
|
|
1363
|
+
* Assert.areEqual(0, writer.formatClassLines(classResult, true).length);
|
|
1364
|
+
* ```
|
|
1365
|
+
*/
|
|
1366
|
+
export declare class TestReportWriter {
|
|
1367
|
+
/**
|
|
1368
|
+
* Returns the lines of the whole report: every class block, then the totals.
|
|
1369
|
+
*
|
|
1370
|
+
* @param result The structured result to present; formatting does not mutate it.
|
|
1371
|
+
* @param skipPassingDetails True to hide passing tests and fully passing class headings. Failures, skips, totals, and duration remain visible.
|
|
1372
|
+
* @returns Fresh human-readable lines, including totals and cumulative test execution time. No console output is performed.
|
|
1373
|
+
*
|
|
1374
|
+
* See {@link TestReportWriter} for usage examples.
|
|
1375
|
+
*/
|
|
1376
|
+
public formatLines(result: TestRunResult, skipPassingDetails: boolean): string[];
|
|
1377
|
+
|
|
1378
|
+
/**
|
|
1379
|
+
* Returns one class's block: its heading, one entry per presented invocation, and a closing blank line.
|
|
1380
|
+
*
|
|
1381
|
+
* @param classResult The class result to present; formatting does not mutate it.
|
|
1382
|
+
* @param skipPassingDetails True to hide passing invocations. Failures and skips remain visible.
|
|
1383
|
+
* @returns Fresh lines for the class, or an empty array when passing details are hidden and every invocation passed.
|
|
1384
|
+
*
|
|
1385
|
+
* See {@link TestReportWriter} for usage examples.
|
|
1386
|
+
*/
|
|
1387
|
+
public formatClassLines(classResult: TestClassResult, skipPassingDetails: boolean): string[];
|
|
1388
|
+
|
|
1389
|
+
/**
|
|
1390
|
+
* Returns the heading that opens a class's block: its package, package-relative file path, and class name.
|
|
1391
|
+
*
|
|
1392
|
+
* @param classResult The class result whose identity is presented; formatting does not mutate it.
|
|
1393
|
+
* @returns The heading line.
|
|
1394
|
+
* @example
|
|
1395
|
+
* ```ts
|
|
1396
|
+
* import { Assert, TestClassResult, TestReportWriter } from "@noldova/context.testing";
|
|
1397
|
+
*
|
|
1398
|
+
* const classResult = new TestClassResult("Sample", "SampleTests", "sample.test.js", []);
|
|
1399
|
+
* Assert.areEqual("Sample/sample.test.js — SampleTests", new TestReportWriter().formatClassHeading(classResult));
|
|
1400
|
+
* ```
|
|
1401
|
+
*/
|
|
1402
|
+
public formatClassHeading(classResult: TestClassResult): string;
|
|
1403
|
+
|
|
1404
|
+
/**
|
|
1405
|
+
* Returns one invocation's entry in a class's block: its outcome mark, name, data, and duration, followed by the failure's lines when it failed.
|
|
1406
|
+
*
|
|
1407
|
+
* @param methodResult The invocation to present; formatting does not mutate it.
|
|
1408
|
+
* @param skipPassingDetails True to hide a passing invocation. Failures and skips remain visible.
|
|
1409
|
+
* @returns Fresh lines for the invocation, or an empty array when it passed and passing details are hidden.
|
|
1410
|
+
* @example
|
|
1411
|
+
* ```ts
|
|
1412
|
+
* import { Assert, TestMethodResult, TestOutcome, TestReportWriter } from "@noldova/context.testing";
|
|
1413
|
+
*
|
|
1414
|
+
* const writer = new TestReportWriter();
|
|
1415
|
+
* const methodResult = new TestMethodResult("Sample", "SampleTests", "passes", undefined, [], TestOutcome.Passed, 1, undefined, undefined);
|
|
1416
|
+
* Assert.isTrue(writer.formatMethodLines(methodResult, false)[0]?.includes("passes (1 ms)") ?? false);
|
|
1417
|
+
* Assert.areEqual(0, writer.formatMethodLines(methodResult, true).length);
|
|
1418
|
+
* ```
|
|
1419
|
+
*/
|
|
1420
|
+
public formatMethodLines(methodResult: TestMethodResult, skipPassingDetails: boolean): string[];
|
|
1421
|
+
|
|
1422
|
+
/**
|
|
1423
|
+
* Returns a class's block from its heading and its invocations' entries, as {@link TestReportWriter.formatClassLines} does for a whole class
|
|
1424
|
+
* result.
|
|
1425
|
+
*
|
|
1426
|
+
* @param heading The class's heading, as {@link TestReportWriter.formatClassHeading} returns it.
|
|
1427
|
+
* @param methodLines The entries of the class's invocations in order, as {@link TestReportWriter.formatMethodLines} returns them.
|
|
1428
|
+
* @param skipPassingDetails True to hide the whole block when no entry is presented.
|
|
1429
|
+
* @returns Fresh lines: the heading, the entries, and a closing blank line; or an empty array when passing details are hidden and there are no
|
|
1430
|
+
* entries.
|
|
1431
|
+
* @example
|
|
1432
|
+
* ```ts
|
|
1433
|
+
* import { Assert, TestReportWriter } from "@noldova/context.testing";
|
|
1434
|
+
*
|
|
1435
|
+
* const writer = new TestReportWriter();
|
|
1436
|
+
* Assert.areEqual(3, writer.formatClassBlock("Sample/sample.test.js — SampleTests", [" entry"], true).length);
|
|
1437
|
+
* Assert.areEqual(0, writer.formatClassBlock("Sample/sample.test.js — SampleTests", [], true).length);
|
|
1438
|
+
* ```
|
|
1439
|
+
*/
|
|
1440
|
+
public formatClassBlock(heading: string, methodLines: readonly string[], skipPassingDetails: boolean): string[];
|
|
1441
|
+
|
|
1442
|
+
/**
|
|
1443
|
+
* Returns the totals that close a report: a separator, then for a filtered run its filters and its discovered, selected and unselected
|
|
1444
|
+
* counts, then the invocation count, the totals' duration, and the passed count, followed by the failed and skipped counts when either is
|
|
1445
|
+
* non-zero.
|
|
1446
|
+
*
|
|
1447
|
+
* @param totals The totals presented, a whole {@link TestRunResult} or the {@link TestRunTotals} a run counted; formatting does not mutate them.
|
|
1448
|
+
* @param selection What the run selected out of what it discovered; its rows appear only when it is filtered. Defaults to none.
|
|
1449
|
+
* @returns Fresh human-readable lines. No console output is performed.
|
|
1450
|
+
* @example
|
|
1451
|
+
* ```ts
|
|
1452
|
+
* import { Assert, TestReportWriter, TestRunTotals, TestSelection } from "@noldova/context.testing";
|
|
1453
|
+
*
|
|
1454
|
+
* const lines = new TestReportWriter().formatSummaryLines(new TestRunTotals(2, 0, 0, 5), new TestSelection(["Alpha"], 6, 2));
|
|
1455
|
+
* Assert.isTrue(lines.includes("Unselected: 4"));
|
|
1456
|
+
* ```
|
|
1457
|
+
*/
|
|
1458
|
+
public formatSummaryLines(totals: TestRunTotals, selection?: TestSelection): string[];
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
/**
|
|
1462
|
+
* Writes a run to a console while it progresses: each class block as soon as its class finishes, then the totals. In an interactive terminal it
|
|
1463
|
+
* also keeps an animated "Running tests" line below the written blocks until the totals are written. The blocks are those of
|
|
1464
|
+
* {@link TestReportWriter}, so output that is no terminal holds exactly the report's lines.
|
|
1465
|
+
*
|
|
1466
|
+
* @example
|
|
1467
|
+
* ```ts
|
|
1468
|
+
* import { Assert, TestClassResult, TestConsoleReporter, TestMethodResult, TestOutcome, TestRunResult } from "@noldova/context.testing";
|
|
1469
|
+
*
|
|
1470
|
+
* const output: string[] = [];
|
|
1471
|
+
* const reporter = new TestConsoleReporter(t => output.push(t), false, false);
|
|
1472
|
+
* const classResult = new TestClassResult("Sample", "SampleTests", "sample.test.js", [
|
|
1473
|
+
* new TestMethodResult("Sample", "SampleTests", "passes", undefined, [], TestOutcome.Passed, 1, undefined, undefined)]);
|
|
1474
|
+
* reporter.start();
|
|
1475
|
+
* reporter.onClassCompleted(classResult);
|
|
1476
|
+
* reporter.writeSummary(new TestRunResult([classResult]));
|
|
1477
|
+
* Assert.isTrue(output[0]?.startsWith("Sample/sample.test.js — SampleTests") ?? false);
|
|
1478
|
+
* Assert.isTrue(output.join("").includes("Total: 1"));
|
|
1479
|
+
* // With isInteractive true, start() shows the progress line and writeSummary(result) removes it.
|
|
1480
|
+
* ```
|
|
1481
|
+
*/
|
|
1482
|
+
export declare class TestConsoleReporter implements ITestProgressListener {
|
|
1483
|
+
/**
|
|
1484
|
+
* Initializes a reporter for one run.
|
|
1485
|
+
*
|
|
1486
|
+
* @param write Receives each piece of console text exactly as written, including control sequences and line feeds; it must not add its own.
|
|
1487
|
+
* @param isInteractive True when the text reaches an interactive terminal, which shows the progress line; false writes the report's lines only.
|
|
1488
|
+
* @param skipPassingDetails True to hide passing invocations and fully passing classes. Failures, skips, and totals remain visible.
|
|
1489
|
+
* @param clock The clock that times the progress line's animation. Defaults to the system clock, whose timer never keeps the process alive.
|
|
1490
|
+
*
|
|
1491
|
+
* See {@link TestConsoleReporter} for usage examples.
|
|
1492
|
+
*/
|
|
1493
|
+
public constructor(write: (text: string) => void, isInteractive: boolean, skipPassingDetails: boolean, clock?: IClock);
|
|
1494
|
+
|
|
1495
|
+
/**
|
|
1496
|
+
* Shows the progress line and keeps it animated until {@link TestConsoleReporter.stop} or
|
|
1497
|
+
* {@link TestConsoleReporter.writeSummary}. Does nothing when the output is not interactive. Call it once per run. The animation's timer never
|
|
1498
|
+
* keeps the process alive, and it advances only while the thread writing it is free; the command-line run keeps that thread free by running
|
|
1499
|
+
* the tests in a worker.
|
|
1500
|
+
*
|
|
1501
|
+
* See {@link TestConsoleReporter} for usage examples.
|
|
1502
|
+
*/
|
|
1503
|
+
public start(): void;
|
|
1504
|
+
|
|
1505
|
+
/**
|
|
1506
|
+
* Writes one finished class's block above the progress line, as {@link TestReportWriter.formatClassLines} formats it. A class whose block is
|
|
1507
|
+
* empty writes nothing. Passing the reporter to {@link TestRunner.runAsync} calls this for every class as it finishes.
|
|
1508
|
+
*
|
|
1509
|
+
* @param classResult The finished class's result; writing does not mutate it.
|
|
1510
|
+
*
|
|
1511
|
+
* See {@link TestConsoleReporter} for usage examples.
|
|
1512
|
+
*/
|
|
1513
|
+
public onClassCompleted(classResult: TestClassResult): void;
|
|
1514
|
+
|
|
1515
|
+
/**
|
|
1516
|
+
* Writes one finished class's block above the progress line as already formatted lines, such as a test worker formats them with
|
|
1517
|
+
* {@link TestReportWriter.formatClassLines}. An empty block writes nothing.
|
|
1518
|
+
*
|
|
1519
|
+
* @param lines The block's lines, without line feeds; writing does not mutate them.
|
|
1520
|
+
*
|
|
1521
|
+
* See {@link TestConsoleReporter} for usage examples.
|
|
1522
|
+
*/
|
|
1523
|
+
public writeClassLines(lines: readonly string[]): void;
|
|
1524
|
+
|
|
1525
|
+
/**
|
|
1526
|
+
* Removes the progress line and stops its animation, for a run that ends without totals. Does nothing when no progress line is shown, so it
|
|
1527
|
+
* may be called more than once.
|
|
1528
|
+
*
|
|
1529
|
+
* See {@link TestConsoleReporter} for usage examples.
|
|
1530
|
+
*/
|
|
1531
|
+
public stop(): void;
|
|
1532
|
+
|
|
1533
|
+
/**
|
|
1534
|
+
* Removes the progress line, when one is shown, and writes the run's totals as
|
|
1535
|
+
* {@link TestReportWriter.formatSummaryLines} formats them.
|
|
1536
|
+
*
|
|
1537
|
+
* @param totals The finished run's totals, a whole {@link TestRunResult} or the {@link TestRunTotals} a run counted; writing does not mutate
|
|
1538
|
+
* them.
|
|
1539
|
+
* @param selection What the run selected out of what it discovered; its rows appear only when it is filtered. Defaults to none.
|
|
1540
|
+
*
|
|
1541
|
+
* See {@link TestConsoleReporter} for usage examples.
|
|
1542
|
+
*/
|
|
1543
|
+
public writeSummary(totals: TestRunTotals, selection?: TestSelection): void;
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
/**
|
|
1547
|
+
* One contiguous span of source lines, 1-based and inclusive.
|
|
1548
|
+
*
|
|
1549
|
+
* @example
|
|
1550
|
+
* ```ts
|
|
1551
|
+
* import { Assert, LineRange } from "@noldova/context.testing";
|
|
1552
|
+
*
|
|
1553
|
+
* Assert.areEqual("3", new LineRange(3, 3).displayText);
|
|
1554
|
+
* Assert.areEqual("3-5", new LineRange(3, 5).displayText);
|
|
1555
|
+
* ```
|
|
1556
|
+
*/
|
|
1557
|
+
export declare class LineRange {
|
|
1558
|
+
/**
|
|
1559
|
+
* The inclusive 1-based first line.
|
|
1560
|
+
*/
|
|
1561
|
+
public readonly startLine: number;
|
|
1562
|
+
|
|
1563
|
+
/**
|
|
1564
|
+
* The inclusive 1-based final line.
|
|
1565
|
+
*/
|
|
1566
|
+
public readonly endLine: number;
|
|
1567
|
+
|
|
1568
|
+
/**
|
|
1569
|
+
* The range as `start` or `start-end` for reports.
|
|
1570
|
+
*/
|
|
1571
|
+
public readonly displayText: string;
|
|
1572
|
+
|
|
1573
|
+
/**
|
|
1574
|
+
* Initializes the range.
|
|
1575
|
+
*
|
|
1576
|
+
* @param startLine The positive integer, 1-based first line, inclusive.
|
|
1577
|
+
* @param endLine The integer, 1-based last line, inclusive; must be at least startLine.
|
|
1578
|
+
* @throws ArgumentOutOfRangeException if startLine is not a positive integer or endLine is not an integer at least startLine.
|
|
1579
|
+
*
|
|
1580
|
+
* See {@link LineRange} for usage examples.
|
|
1581
|
+
*/
|
|
1582
|
+
public constructor(startLine: number, endLine: number);
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
/**
|
|
1586
|
+
* One coverage block: a distinct instrumented V8 block range, excluding
|
|
1587
|
+
* function roots, and whether any test run entered it.
|
|
1588
|
+
*
|
|
1589
|
+
* @example
|
|
1590
|
+
* ```ts
|
|
1591
|
+
* import { Assert, BlockCoverage } from "@noldova/context.testing";
|
|
1592
|
+
*
|
|
1593
|
+
* const block = new BlockCoverage(7, true);
|
|
1594
|
+
* Assert.areEqual(7, block.line);
|
|
1595
|
+
* Assert.isTrue(block.isTaken);
|
|
1596
|
+
* ```
|
|
1597
|
+
*/
|
|
1598
|
+
export declare class BlockCoverage {
|
|
1599
|
+
/**
|
|
1600
|
+
* The 1-based source line containing the instrumented block.
|
|
1601
|
+
*/
|
|
1602
|
+
public readonly line: number;
|
|
1603
|
+
|
|
1604
|
+
/**
|
|
1605
|
+
* True when at least one test execution entered the block.
|
|
1606
|
+
*/
|
|
1607
|
+
public readonly isTaken: boolean;
|
|
1608
|
+
|
|
1609
|
+
/**
|
|
1610
|
+
* Initializes the block coverage.
|
|
1611
|
+
*
|
|
1612
|
+
* @param line The positive integer, 1-based line number.
|
|
1613
|
+
* @param isTaken Whether any measured run entered this instrumented block.
|
|
1614
|
+
* @throws ArgumentOutOfRangeException if line is not a positive integer.
|
|
1615
|
+
*
|
|
1616
|
+
* See {@link BlockCoverage} for usage examples.
|
|
1617
|
+
*/
|
|
1618
|
+
public constructor(line: number, isTaken: boolean);
|
|
1619
|
+
}
|
|
1620
|
+
|
|
1621
|
+
/**
|
|
1622
|
+
* The flat Source Map v3 payload emitted by the pinned TypeScript bootstrap and
|
|
1623
|
+
* consumed by `SourceMap`.
|
|
1624
|
+
*
|
|
1625
|
+
* @example
|
|
1626
|
+
* ```ts
|
|
1627
|
+
* import { Assert, type ISourceMapData, SourceMap } from "@noldova/context.testing";
|
|
1628
|
+
*
|
|
1629
|
+
* const data: ISourceMapData = { version: 3, sources: ["sample.ts"], mappings: "AAAA" };
|
|
1630
|
+
* Assert.areEqual(1, new SourceMap(data, ".").mapToSource(1, 0)?.line);
|
|
1631
|
+
* ```
|
|
1632
|
+
*/
|
|
1633
|
+
export declare interface ISourceMapData {
|
|
1634
|
+
/**
|
|
1635
|
+
* The Source Map schema version; only version 3 is accepted.
|
|
1636
|
+
*/
|
|
1637
|
+
readonly version: number;
|
|
1638
|
+
|
|
1639
|
+
/**
|
|
1640
|
+
* The ordered original-source paths referenced by mapping segments.
|
|
1641
|
+
*/
|
|
1642
|
+
readonly sources: readonly string[];
|
|
1643
|
+
|
|
1644
|
+
/**
|
|
1645
|
+
* The base64 VLQ-encoded generated-to-original mappings.
|
|
1646
|
+
*/
|
|
1647
|
+
readonly mappings: string;
|
|
1648
|
+
|
|
1649
|
+
/**
|
|
1650
|
+
* The optional source-root prefix applied during source-path resolution.
|
|
1651
|
+
*/
|
|
1652
|
+
readonly sourceRoot?: string;
|
|
1653
|
+
|
|
1654
|
+
/**
|
|
1655
|
+
* The optional symbol-name table referenced by five-field segments.
|
|
1656
|
+
*/
|
|
1657
|
+
readonly names?: readonly string[];
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1660
|
+
/**
|
|
1661
|
+
* An original source file and its mapped 1-based line. This model does not
|
|
1662
|
+
* contain a character coordinate.
|
|
1663
|
+
*
|
|
1664
|
+
* @example
|
|
1665
|
+
* ```ts
|
|
1666
|
+
* import { Assert, MappedSourceLine } from "@noldova/context.testing";
|
|
1667
|
+
*
|
|
1668
|
+
* const position = new MappedSourceLine("/project/sample.ts", 12);
|
|
1669
|
+
* Assert.areEqual(12, position.line);
|
|
1670
|
+
* // MappedSourceLine stores the supplied path; SourceMap performs path resolution.
|
|
1671
|
+
* ```
|
|
1672
|
+
*/
|
|
1673
|
+
export declare class MappedSourceLine {
|
|
1674
|
+
/**
|
|
1675
|
+
* The original-source path supplied to this model; no normalization is performed.
|
|
1676
|
+
*/
|
|
1677
|
+
public readonly sourcePath: string;
|
|
1678
|
+
|
|
1679
|
+
/**
|
|
1680
|
+
* The resolved 1-based original source line.
|
|
1681
|
+
*/
|
|
1682
|
+
public readonly line: number;
|
|
1683
|
+
|
|
1684
|
+
/**
|
|
1685
|
+
* Records the original source file and its mapped line.
|
|
1686
|
+
*
|
|
1687
|
+
* @param sourcePath The non-whitespace original source path to store. This model does not resolve or normalize it.
|
|
1688
|
+
* @param line The positive integer, 1-based line number.
|
|
1689
|
+
* @throws ArgumentException if sourcePath is blank.
|
|
1690
|
+
* @throws ArgumentOutOfRangeException if line is not a positive integer.
|
|
1691
|
+
*
|
|
1692
|
+
* See {@link MappedSourceLine} for usage examples.
|
|
1693
|
+
*/
|
|
1694
|
+
public constructor(sourcePath: string, line: number);
|
|
1695
|
+
}
|
|
1696
|
+
|
|
1697
|
+
/**
|
|
1698
|
+
* A decoded flat Source Map v3 document from the pinned TypeScript bootstrap.
|
|
1699
|
+
* Maps generated positions back to the original sources; source paths resolve
|
|
1700
|
+
* against the map's directory.
|
|
1701
|
+
*
|
|
1702
|
+
* @example
|
|
1703
|
+
* ```ts
|
|
1704
|
+
* import { Assert, SourceMap } from "@noldova/context.testing";
|
|
1705
|
+
*
|
|
1706
|
+
* const map = new SourceMap({ version: 3, sources: ["sample.ts"], mappings: "AAKA;;AACA" }, ".");
|
|
1707
|
+
* Assert.areEqual(6, map.mapToSource(1, 0)?.line);
|
|
1708
|
+
* Assert.isUndefined(map.mapToSource(2, 0)); // No mapping on this generated line.
|
|
1709
|
+
* Assert.areEqual(7, map.mapToSource(3, 0)?.line);
|
|
1710
|
+
* ```
|
|
1711
|
+
*/
|
|
1712
|
+
export declare class SourceMap {
|
|
1713
|
+
/**
|
|
1714
|
+
* Initializes the map from its parsed payload and the directory containing
|
|
1715
|
+
* the map file. Fails unless the payload is a valid flat Source Map v3
|
|
1716
|
+
* document within the accepted TypeScript bootstrap subset.
|
|
1717
|
+
*
|
|
1718
|
+
* @param data The typed flat Source Map v3 payload from the pinned emitter. The caller validates external JSON shape before supplying this model.
|
|
1719
|
+
* @param mapDirectory The non-whitespace directory containing the map, used to resolve sourceRoot and source paths.
|
|
1720
|
+
* @throws ArgumentException if mapDirectory is blank.
|
|
1721
|
+
* @throws TestingException if the version or encoded mapping is outside the supported flat v3 subset.
|
|
1722
|
+
*
|
|
1723
|
+
* See {@link SourceMap} for usage examples.
|
|
1724
|
+
*/
|
|
1725
|
+
public constructor(data: ISourceMapData, mapDirectory: string);
|
|
1726
|
+
|
|
1727
|
+
/**
|
|
1728
|
+
* Maps a generated 1-based line and 0-based column to its original source file and line,
|
|
1729
|
+
* using the nearest preceding segment on the same generated line; undefined
|
|
1730
|
+
* when no segment maps that position. Invalid coordinates throw
|
|
1731
|
+
* `ArgumentOutOfRangeException`.
|
|
1732
|
+
*
|
|
1733
|
+
* @param generatedLine The positive integer, 1-based line in generated JavaScript.
|
|
1734
|
+
* @param generatedColumn The non-negative integer, 0-based column in generated JavaScript.
|
|
1735
|
+
* @returns The mapped original path and 1-based line, or undefined before the first mapped segment, on an unmapped segment, or outside mapped lines. It
|
|
1736
|
+
* never borrows a mapping from another line.
|
|
1737
|
+
* @throws ArgumentOutOfRangeException if the generated coordinates are negative, fractional, or the line is zero.
|
|
1738
|
+
*
|
|
1739
|
+
* See {@link SourceMap} for usage examples.
|
|
1740
|
+
*/
|
|
1741
|
+
public mapToSource(generatedLine: number, generatedColumn: number): MappedSourceLine | undefined;
|
|
1742
|
+
}
|
|
1743
|
+
|
|
1744
|
+
/**
|
|
1745
|
+
* One explicitly identified production project included in a coverage run.
|
|
1746
|
+
*
|
|
1747
|
+
* @example
|
|
1748
|
+
* ```ts
|
|
1749
|
+
* import { Assert, CoverageProject } from "@noldova/context.testing";
|
|
1750
|
+
*
|
|
1751
|
+
* const project = new CoverageProject("Sample", "./installed/sample", "./src/sample");
|
|
1752
|
+
* Assert.areEqual("Sample", project.name);
|
|
1753
|
+
* // The first root contains emitted .js files; the second resolves displayed source paths.
|
|
1754
|
+
* ```
|
|
1755
|
+
*/
|
|
1756
|
+
export declare class CoverageProject {
|
|
1757
|
+
/**
|
|
1758
|
+
* The canonical project identity shown in coverage reports.
|
|
1759
|
+
*/
|
|
1760
|
+
public readonly name: string;
|
|
1761
|
+
|
|
1762
|
+
/**
|
|
1763
|
+
* The directory containing the installed production JavaScript files.
|
|
1764
|
+
*/
|
|
1765
|
+
public readonly productionDirectory: string;
|
|
1766
|
+
|
|
1767
|
+
/**
|
|
1768
|
+
* The directory against which mapped source paths are reported.
|
|
1769
|
+
*/
|
|
1770
|
+
public readonly sourceDirectory: string;
|
|
1771
|
+
|
|
1772
|
+
/**
|
|
1773
|
+
* Initializes the explicit project identity and its production and source
|
|
1774
|
+
* roots.
|
|
1775
|
+
*
|
|
1776
|
+
* @param name The non-whitespace project identity to display.
|
|
1777
|
+
* @param productionDirectory The non-whitespace root of installed production JavaScript to inventory, including files no test loads.
|
|
1778
|
+
* @param sourceDirectory The non-whitespace source root used for mapped display paths; mapped files must stay within it.
|
|
1779
|
+
* @throws ArgumentException if the name or either directory is blank.
|
|
1780
|
+
*
|
|
1781
|
+
* See {@link CoverageProject} for usage examples.
|
|
1782
|
+
*/
|
|
1783
|
+
public constructor(name: string, productionDirectory: string, sourceDirectory: string);
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1786
|
+
/**
|
|
1787
|
+
* The coverage state of one production file. During bootstrap, lengths measure
|
|
1788
|
+
* generated JavaScript UTF-16 code units, including text inside claimed ranges,
|
|
1789
|
+
* not a count of original TypeScript statements or branches.
|
|
1790
|
+
*
|
|
1791
|
+
* @example
|
|
1792
|
+
* ```ts
|
|
1793
|
+
* import { Assert, BlockCoverage, FileCoverage, LineRange } from "@noldova/context.testing";
|
|
1794
|
+
*
|
|
1795
|
+
* const partial = new FileCoverage("Sample", "sample.ts", [new LineRange(3, 3)], 100, 20, [new BlockCoverage(3, false)]);
|
|
1796
|
+
* Assert.isFalse(partial.isFullyCovered);
|
|
1797
|
+
* const inert = new FileCoverage("Sample", "types.ts", [], 0, 0, []);
|
|
1798
|
+
* Assert.isFalse(inert.isExecutable);
|
|
1799
|
+
* Assert.isFalse(inert.isFullyCovered);
|
|
1800
|
+
* ```
|
|
1801
|
+
*/
|
|
1802
|
+
export declare class FileCoverage {
|
|
1803
|
+
/**
|
|
1804
|
+
* The canonical identity of the file's project.
|
|
1805
|
+
*/
|
|
1806
|
+
public readonly projectName: string;
|
|
1807
|
+
|
|
1808
|
+
/**
|
|
1809
|
+
* The file path relative to its declared project root.
|
|
1810
|
+
*/
|
|
1811
|
+
public readonly relativePath: string;
|
|
1812
|
+
|
|
1813
|
+
/**
|
|
1814
|
+
* The uncovered 1-based source-line ranges.
|
|
1815
|
+
*/
|
|
1816
|
+
public readonly uncoveredLineRanges: readonly LineRange[];
|
|
1817
|
+
|
|
1818
|
+
/**
|
|
1819
|
+
* The measured generated JavaScript length in UTF-16 code units; zero for
|
|
1820
|
+
* inert files. This is not a count of executable statements.
|
|
1821
|
+
*/
|
|
1822
|
+
public readonly totalLength: number;
|
|
1823
|
+
|
|
1824
|
+
/**
|
|
1825
|
+
* The uncovered executable source length measured in code units.
|
|
1826
|
+
*/
|
|
1827
|
+
public readonly uncoveredLength: number;
|
|
1828
|
+
|
|
1829
|
+
/**
|
|
1830
|
+
* The distinct instrumented blocks of the file, excluding function roots.
|
|
1831
|
+
* Their taken count is reported separately from code-unit completion.
|
|
1832
|
+
*/
|
|
1833
|
+
public readonly blockCoverages: readonly BlockCoverage[];
|
|
1834
|
+
|
|
1835
|
+
/**
|
|
1836
|
+
* True when the file is executable and has no uncovered range.
|
|
1837
|
+
*/
|
|
1838
|
+
public readonly isFullyCovered: boolean;
|
|
1839
|
+
|
|
1840
|
+
/**
|
|
1841
|
+
* True when the file contains executable source ranges. Type-only and other
|
|
1842
|
+
* inert files remain in the inventory but do not enter coverage totals.
|
|
1843
|
+
*/
|
|
1844
|
+
public readonly isExecutable: boolean;
|
|
1845
|
+
|
|
1846
|
+
/**
|
|
1847
|
+
* The number of distinct instrumented blocks.
|
|
1848
|
+
*/
|
|
1849
|
+
public readonly blockCount: number;
|
|
1850
|
+
|
|
1851
|
+
/**
|
|
1852
|
+
* The number of blocks entered by at least one test run.
|
|
1853
|
+
*/
|
|
1854
|
+
public readonly takenBlockCount: number;
|
|
1855
|
+
|
|
1856
|
+
/**
|
|
1857
|
+
* Initializes the file coverage; fails when the uncovered line ranges and
|
|
1858
|
+
* the uncovered length disagree about whether anything is uncovered, or
|
|
1859
|
+
* when a length is negative, fractional, or exceeds the total.
|
|
1860
|
+
*
|
|
1861
|
+
* @param projectName The non-whitespace canonical project identity.
|
|
1862
|
+
* @param relativePath The non-whitespace project-relative displayed path, using the source root when mapped and the production root otherwise.
|
|
1863
|
+
* @param uncoveredLineRanges The uncovered, inclusive line ranges. Empty exactly when uncoveredLength is zero. The array is copied; ranges are shared.
|
|
1864
|
+
* @param totalLength The non-negative integer length measured in generated JavaScript UTF-16 code units; zero marks an inert file.
|
|
1865
|
+
* @param uncoveredLength The non-negative integer count of uncovered code units; cannot exceed totalLength.
|
|
1866
|
+
* @param blockCoverages Distinct instrumented blocks, excluding function roots. Must be empty for an inert file. The array is copied; blocks are shared.
|
|
1867
|
+
* @throws ArgumentException if identity/path is blank, uncovered ranges disagree with uncoveredLength, or an inert file has blocks.
|
|
1868
|
+
* @throws ArgumentOutOfRangeException if lengths are negative, fractional, or uncoveredLength exceeds totalLength.
|
|
1869
|
+
*
|
|
1870
|
+
* See {@link FileCoverage} for usage examples.
|
|
1871
|
+
*/
|
|
1872
|
+
public constructor(
|
|
1873
|
+
projectName: string,
|
|
1874
|
+
relativePath: string,
|
|
1875
|
+
uncoveredLineRanges: readonly LineRange[],
|
|
1876
|
+
totalLength: number,
|
|
1877
|
+
uncoveredLength: number,
|
|
1878
|
+
blockCoverages: readonly BlockCoverage[]);
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1881
|
+
/**
|
|
1882
|
+
* The aggregated coverage of one complete test run.
|
|
1883
|
+
*
|
|
1884
|
+
* @example
|
|
1885
|
+
* ```ts
|
|
1886
|
+
* import { Assert, CoverageResult, FileCoverage } from "@noldova/context.testing";
|
|
1887
|
+
*
|
|
1888
|
+
* const result = new CoverageResult([
|
|
1889
|
+
* new FileCoverage("Sample", "sample.ts", [], 100, 0, []),
|
|
1890
|
+
* new FileCoverage("Sample", "types.ts", [], 0, 0, [])
|
|
1891
|
+
* ]);
|
|
1892
|
+
* Assert.isTrue(result.isComplete);
|
|
1893
|
+
* Assert.areEqual(1, result.executableFileCoverages.length);
|
|
1894
|
+
* Assert.areEqual(100, result.totalLength);
|
|
1895
|
+
* ```
|
|
1896
|
+
*/
|
|
1897
|
+
export declare class CoverageResult {
|
|
1898
|
+
/**
|
|
1899
|
+
* The coverage state of every inventoried production file.
|
|
1900
|
+
*/
|
|
1901
|
+
public readonly fileCoverages: readonly FileCoverage[];
|
|
1902
|
+
|
|
1903
|
+
/**
|
|
1904
|
+
* True when every executable file is fully covered.
|
|
1905
|
+
*/
|
|
1906
|
+
public readonly isComplete: boolean;
|
|
1907
|
+
|
|
1908
|
+
/**
|
|
1909
|
+
* The inventoried files that contain executable source ranges.
|
|
1910
|
+
*/
|
|
1911
|
+
public readonly executableFileCoverages: readonly FileCoverage[];
|
|
1912
|
+
|
|
1913
|
+
/**
|
|
1914
|
+
* The files that still have uncovered ranges.
|
|
1915
|
+
*/
|
|
1916
|
+
public readonly incompleteFileCoverages: readonly FileCoverage[];
|
|
1917
|
+
|
|
1918
|
+
/**
|
|
1919
|
+
* The summed executable length of every inventoried file.
|
|
1920
|
+
*/
|
|
1921
|
+
public readonly totalLength: number;
|
|
1922
|
+
|
|
1923
|
+
/**
|
|
1924
|
+
* The summed uncovered length across every measured file.
|
|
1925
|
+
*/
|
|
1926
|
+
public readonly uncoveredLength: number;
|
|
1927
|
+
|
|
1928
|
+
/**
|
|
1929
|
+
* The summed block count across every measured file.
|
|
1930
|
+
*/
|
|
1931
|
+
public readonly blockCount: number;
|
|
1932
|
+
|
|
1933
|
+
/**
|
|
1934
|
+
* The summed taken-block count across every measured file.
|
|
1935
|
+
*/
|
|
1936
|
+
public readonly takenBlockCount: number;
|
|
1937
|
+
|
|
1938
|
+
/**
|
|
1939
|
+
* Initializes the result.
|
|
1940
|
+
*
|
|
1941
|
+
* @param fileCoverages The inventoried file results, including inert files. The array is copied; file objects are shared.
|
|
1942
|
+
*
|
|
1943
|
+
* See {@link CoverageResult} for usage examples.
|
|
1944
|
+
*/
|
|
1945
|
+
public constructor(fileCoverages: readonly FileCoverage[]);
|
|
1946
|
+
}
|
|
1947
|
+
|
|
1948
|
+
/**
|
|
1949
|
+
* Terminal presentation of a coverage result: one percentage per executable
|
|
1950
|
+
* production file, not-applicable markers for inert files, uncovered line
|
|
1951
|
+
* ranges, and the overall total. The structured result remains the authority;
|
|
1952
|
+
* no consumer parses this output.
|
|
1953
|
+
*
|
|
1954
|
+
* @example
|
|
1955
|
+
* ```ts
|
|
1956
|
+
* import { Assert, CoverageReportWriter, CoverageResult, FileCoverage } from "@noldova/context.testing";
|
|
1957
|
+
*
|
|
1958
|
+
* const result = new CoverageResult([new FileCoverage("Sample", "types.ts", [], 0, 0, [])]);
|
|
1959
|
+
* const lines = new CoverageReportWriter().formatLines(result, false);
|
|
1960
|
+
* Assert.isTrue(lines.some(t => t.includes("types.ts")));
|
|
1961
|
+
* Assert.isTrue(lines.every(t => !t.includes("100.0%"))); // Inert files display "-".
|
|
1962
|
+
* ```
|
|
1963
|
+
*/
|
|
1964
|
+
export declare class CoverageReportWriter {
|
|
1965
|
+
/**
|
|
1966
|
+
* Returns the report lines without writing them.
|
|
1967
|
+
*
|
|
1968
|
+
* @param result The structured result to present; formatting does not mutate it.
|
|
1969
|
+
* @param skipCoveredDetails True to omit fully covered and inert file rows. Incomplete files, uncovered lines, and the overall row remain visible.
|
|
1970
|
+
* @returns Fresh ANSI-colored table lines. Inert files display a not-applicable marker and do not contribute to executable-file totals.
|
|
1971
|
+
*
|
|
1972
|
+
* See {@link CoverageReportWriter} for usage examples.
|
|
1973
|
+
*/
|
|
1974
|
+
public formatLines(result: CoverageResult, skipCoveredDetails: boolean): string[];
|
|
1975
|
+
}
|
|
1976
|
+
|
|
1977
|
+
/**
|
|
1978
|
+
* Reads the V8 coverage reports written by a test-run child process and
|
|
1979
|
+
* computes the uncovered line ranges of the production files.
|
|
1980
|
+
*
|
|
1981
|
+
* @example
|
|
1982
|
+
* ```ts
|
|
1983
|
+
* import { CoverageAnalyzer, CoverageProject, CoverageResult } from "@noldova/context.testing";
|
|
1984
|
+
*
|
|
1985
|
+
* export async function measureAsync(coverageDirectory: string, installedDirectory: string, sourceDirectory: string): Promise<CoverageResult> {
|
|
1986
|
+
* return new CoverageAnalyzer().analyzeAsync(coverageDirectory, [
|
|
1987
|
+
* new CoverageProject("Sample", installedDirectory, sourceDirectory)
|
|
1988
|
+
* ]);
|
|
1989
|
+
* }
|
|
1990
|
+
* // Supply fresh V8 reports and the production inventory from the same build.
|
|
1991
|
+
* ```
|
|
1992
|
+
*/
|
|
1993
|
+
export declare class CoverageAnalyzer {
|
|
1994
|
+
/**
|
|
1995
|
+
* Analyzes every report in the coverage directory against the complete
|
|
1996
|
+
* inventory of `.js` files beneath the projects' production directories,
|
|
1997
|
+
* merging coverage across processes. A file the reports never mention
|
|
1998
|
+
* counts as fully uncovered unless it holds no executable content; a
|
|
1999
|
+
* position no report claims counts as uncovered; a missing source map falls
|
|
2000
|
+
* back to generated coordinates, while a malformed report, source map, or
|
|
2001
|
+
* source path outside its declared project root fails the analysis. An empty
|
|
2002
|
+
* inventory fails.
|
|
2003
|
+
*
|
|
2004
|
+
* @param coverageDirectory The non-whitespace directory of V8 coverage JSON reports from the matching build.
|
|
2005
|
+
* @param projects The non-empty explicit production-project inventory, with installed and original-source roots.
|
|
2006
|
+
* @returns A promise resolving to inventory-wide coverage merged across reports. Missing files in reports count as uncovered unless inert.
|
|
2007
|
+
* @throws ArgumentException via promise rejection if coverageDirectory is blank or projects is empty.
|
|
2008
|
+
* @throws TestingException via promise rejection for an empty production inventory, malformed reports/maps, out-of-file ranges, or mapped paths outside
|
|
2009
|
+
* their declared roots.
|
|
2010
|
+
* @throws Error via promise rejection for host I/O failures. An absent source map alone falls back to generated coordinates.
|
|
2011
|
+
*
|
|
2012
|
+
* See {@link CoverageAnalyzer} for usage examples.
|
|
2013
|
+
*/
|
|
2014
|
+
public analyzeAsync(coverageDirectory: string, projects: readonly CoverageProject[]): Promise<CoverageResult>;
|
|
2015
|
+
}
|