@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.
Files changed (132) hide show
  1. package/LICENSE +21 -0
  2. package/api/index.d.ts +2015 -0
  3. package/api/index.js +42 -0
  4. package/api/index.js.map +1 -0
  5. package/decorators/category.js +23 -0
  6. package/decorators/category.js.map +1 -0
  7. package/decorators/skip.js +17 -0
  8. package/decorators/skip.js.map +1 -0
  9. package/decorators/test-class.js +12 -0
  10. package/decorators/test-class.js.map +1 -0
  11. package/decorators/test-data.js +23 -0
  12. package/decorators/test-data.js.map +1 -0
  13. package/decorators/test-method.js +12 -0
  14. package/decorators/test-method.js.map +1 -0
  15. package/enums/test-outcome.js +14 -0
  16. package/enums/test-outcome.js.map +1 -0
  17. package/enums/test-worker-message-kind.js +17 -0
  18. package/enums/test-worker-message-kind.js.map +1 -0
  19. package/enums/test-worker-value-kind.js +16 -0
  20. package/enums/test-worker-value-kind.js.map +1 -0
  21. package/exceptions/assert-failed.exception.js +19 -0
  22. package/exceptions/assert-failed.exception.js.map +1 -0
  23. package/exceptions/test-timeout.exception.js +20 -0
  24. package/exceptions/test-timeout.exception.js.map +1 -0
  25. package/exceptions/testing.exception.js +14 -0
  26. package/exceptions/testing.exception.js.map +1 -0
  27. package/interfaces/i-clock.js +9 -0
  28. package/interfaces/i-clock.js.map +1 -0
  29. package/interfaces/i-coverage-range.js +9 -0
  30. package/interfaces/i-coverage-range.js.map +1 -0
  31. package/interfaces/i-coverage-report.js +9 -0
  32. package/interfaces/i-coverage-report.js.map +1 -0
  33. package/interfaces/i-function-coverage.js +9 -0
  34. package/interfaces/i-function-coverage.js.map +1 -0
  35. package/interfaces/i-script-coverage.js +9 -0
  36. package/interfaces/i-script-coverage.js.map +1 -0
  37. package/interfaces/i-source-map-data.js +9 -0
  38. package/interfaces/i-source-map-data.js.map +1 -0
  39. package/interfaces/i-test-progress-listener.js +9 -0
  40. package/interfaces/i-test-progress-listener.js.map +1 -0
  41. package/models/coverage/block-coverage.js +21 -0
  42. package/models/coverage/block-coverage.js.map +1 -0
  43. package/models/coverage/coverage-project.js +23 -0
  44. package/models/coverage/coverage-project.js.map +1 -0
  45. package/models/coverage/coverage-range.js +18 -0
  46. package/models/coverage/coverage-range.js.map +1 -0
  47. package/models/coverage/coverage-result.js +28 -0
  48. package/models/coverage/coverage-result.js.map +1 -0
  49. package/models/coverage/file-coverage.js +45 -0
  50. package/models/coverage/file-coverage.js.map +1 -0
  51. package/models/coverage/function-coverage.js +14 -0
  52. package/models/coverage/function-coverage.js.map +1 -0
  53. package/models/coverage/line-range.js +25 -0
  54. package/models/coverage/line-range.js.map +1 -0
  55. package/models/coverage/mapped-source-line.js +22 -0
  56. package/models/coverage/mapped-source-line.js.map +1 -0
  57. package/models/coverage/source-map-segment.js +18 -0
  58. package/models/coverage/source-map-segment.js.map +1 -0
  59. package/models/decorators/test-data-entry.js +17 -0
  60. package/models/decorators/test-data-entry.js.map +1 -0
  61. package/models/decorators/test-marks.js +16 -0
  62. package/models/decorators/test-marks.js.map +1 -0
  63. package/models/discovery/discovered-test-class.js +36 -0
  64. package/models/discovery/discovered-test-class.js.map +1 -0
  65. package/models/discovery/discovered-test-method.js +42 -0
  66. package/models/discovery/discovered-test-method.js.map +1 -0
  67. package/models/discovery/test-project.js +20 -0
  68. package/models/discovery/test-project.js.map +1 -0
  69. package/models/execution/test-worker-message.js +76 -0
  70. package/models/execution/test-worker-message.js.map +1 -0
  71. package/models/execution/test-worker-record.js +75 -0
  72. package/models/execution/test-worker-record.js.map +1 -0
  73. package/models/execution/test-worker-result.js +45 -0
  74. package/models/execution/test-worker-result.js.map +1 -0
  75. package/models/execution/test-worker-run.js +31 -0
  76. package/models/execution/test-worker-run.js.map +1 -0
  77. package/models/execution/test-worker-start.js +33 -0
  78. package/models/execution/test-worker-start.js.map +1 -0
  79. package/models/execution/test-worker-text.js +17 -0
  80. package/models/execution/test-worker-text.js.map +1 -0
  81. package/models/execution/test-worker-value.js +104 -0
  82. package/models/execution/test-worker-value.js.map +1 -0
  83. package/models/reporting/coverage-report-row.js +22 -0
  84. package/models/reporting/coverage-report-row.js.map +1 -0
  85. package/models/results/test-class-result.js +29 -0
  86. package/models/results/test-class-result.js.map +1 -0
  87. package/models/results/test-method-result.js +59 -0
  88. package/models/results/test-method-result.js.map +1 -0
  89. package/models/results/test-run-result.js +34 -0
  90. package/models/results/test-run-result.js.map +1 -0
  91. package/models/results/test-run-totals.js +36 -0
  92. package/models/results/test-run-totals.js.map +1 -0
  93. package/models/results/test-selection.js +33 -0
  94. package/models/results/test-selection.js.map +1 -0
  95. package/package.json +25 -4
  96. package/resources.js +309 -0
  97. package/resources.js.map +1 -0
  98. package/services/assert.js +92 -0
  99. package/services/assert.js.map +1 -0
  100. package/services/coverage/coverage-analyzer.js +52 -0
  101. package/services/coverage/coverage-analyzer.js.map +1 -0
  102. package/services/coverage/coverage-report.reader.js +126 -0
  103. package/services/coverage/coverage-report.reader.js.map +1 -0
  104. package/services/coverage/file-coverage-analyzer.js +206 -0
  105. package/services/coverage/file-coverage-analyzer.js.map +1 -0
  106. package/services/coverage/source-map.js +135 -0
  107. package/services/coverage/source-map.js.map +1 -0
  108. package/services/discovery/test-discovery.js +198 -0
  109. package/services/discovery/test-discovery.js.map +1 -0
  110. package/services/execution/parallel-test-runner.js +24 -0
  111. package/services/execution/parallel-test-runner.js.map +1 -0
  112. package/services/execution/test-executor.js +116 -0
  113. package/services/execution/test-executor.js.map +1 -0
  114. package/services/execution/test-run-entry-point.js +89 -0
  115. package/services/execution/test-run-entry-point.js.map +1 -0
  116. package/services/execution/test-run-supervisor.js +251 -0
  117. package/services/execution/test-run-supervisor.js.map +1 -0
  118. package/services/execution/test-run-worker-entry-point.js +18 -0
  119. package/services/execution/test-run-worker-entry-point.js.map +1 -0
  120. package/services/execution/test-run-worker.js +116 -0
  121. package/services/execution/test-run-worker.js.map +1 -0
  122. package/services/execution/test-runner.js +58 -0
  123. package/services/execution/test-runner.js.map +1 -0
  124. package/services/reporting/coverage-report-writer.js +81 -0
  125. package/services/reporting/coverage-report-writer.js.map +1 -0
  126. package/services/reporting/test-console-reporter.js +72 -0
  127. package/services/reporting/test-console-reporter.js.map +1 -0
  128. package/services/reporting/test-report-writer.js +111 -0
  129. package/services/reporting/test-report-writer.js.map +1 -0
  130. package/services/timing/system-clock.js +26 -0
  131. package/services/timing/system-clock.js.map +1 -0
  132. 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
+ }