tstyche 4.0.0-rc.1 → 4.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +15 -7
- package/build/tstyche.d.ts +38 -162
- package/build/tstyche.js +171 -150
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[![install-size][install-size-badge]][install-size-url]
|
|
6
6
|
[![coverage][coverage-badge]][coverage-url]
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Everything You Need for Type Testing.
|
|
9
9
|
|
|
10
10
|
---
|
|
11
11
|
|
|
@@ -37,21 +37,29 @@ To organize, debug and plan tests TSTyche has:
|
|
|
37
37
|
|
|
38
38
|
## Assertions
|
|
39
39
|
|
|
40
|
-
The assertions can be used to write type tests (like in the above example) or mixed in your
|
|
40
|
+
The assertions can be used to write type tests (like in the above example) or mixed in your unit tests:
|
|
41
41
|
|
|
42
42
|
```ts
|
|
43
43
|
import assert from "node:assert";
|
|
44
44
|
import test from "node:test";
|
|
45
45
|
import * as tstyche from "tstyche";
|
|
46
46
|
|
|
47
|
-
function
|
|
48
|
-
|
|
47
|
+
function toMilliseconds(value: number) {
|
|
48
|
+
if (typeof value === "number" && !Number.isNaN(value)) {
|
|
49
|
+
return value * 1000;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
throw new Error("Not a number");
|
|
49
53
|
}
|
|
50
54
|
|
|
51
|
-
test("
|
|
52
|
-
|
|
55
|
+
test("toMilliseconds", () => {
|
|
56
|
+
const sample = toMilliseconds(10);
|
|
57
|
+
|
|
58
|
+
assert.equal(sample, 10_000);
|
|
59
|
+
tstyche.expect(sample).type.toBe<number>();
|
|
53
60
|
|
|
54
|
-
|
|
61
|
+
// Will pass as a type test and not throw at runtime
|
|
62
|
+
tstyche.expect(toMilliseconds).type.not.toBeCallableWith("20");
|
|
55
63
|
});
|
|
56
64
|
```
|
|
57
65
|
|
package/build/tstyche.d.ts
CHANGED
|
@@ -20,152 +20,37 @@ declare class Cli {
|
|
|
20
20
|
run(commandLine: Array<string>, cancellationToken?: CancellationToken): Promise<void>;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
declare enum OptionBrand {
|
|
24
|
-
String = "string",
|
|
25
|
-
Number = "number",
|
|
26
|
-
Boolean = "boolean",
|
|
27
|
-
BareTrue = "bareTrue",// a boolean option that does not take a value and when specified is interpreted as 'true'
|
|
28
|
-
List = "list"
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
declare class ConfigDiagnosticText {
|
|
32
|
-
static expected(element: string): string;
|
|
33
|
-
static expectsListItemType(optionName: string, optionBrand: OptionBrand): string;
|
|
34
|
-
static expectsValue(optionName: string): string;
|
|
35
|
-
static fileDoesNotExist(filePath: string): string;
|
|
36
|
-
static inspectSupportedVersions(): string;
|
|
37
|
-
static moduleWasNotFound(specifier: string): string;
|
|
38
|
-
static rangeIsNotValid(value: string): string;
|
|
39
|
-
static rangeUsage(): Array<string>;
|
|
40
|
-
static requiresValueType(optionName: string, optionBrand: OptionBrand): string;
|
|
41
|
-
static seen(element: string): string;
|
|
42
|
-
static testFileMatchCannotStartWith(segment: string): Array<string>;
|
|
43
|
-
static unknownOption(optionName: string): string;
|
|
44
|
-
static usage(optionName: string, optionBrand: OptionBrand): Array<string>;
|
|
45
|
-
static versionIsNotSupported(value: string): string;
|
|
46
|
-
static watchCannotBeEnabled(): string;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Options passed through the command line.
|
|
51
|
-
*/
|
|
52
23
|
interface CommandLineOptions {
|
|
53
|
-
/**
|
|
54
|
-
* The path to a TSTyche configuration file.
|
|
55
|
-
*/
|
|
56
24
|
config?: string;
|
|
57
|
-
/**
|
|
58
|
-
* Stop running tests after the first failed assertion.
|
|
59
|
-
*/
|
|
60
25
|
failFast?: boolean;
|
|
61
|
-
/**
|
|
62
|
-
* Fetch the specified versions of the 'typescript' package and exit.
|
|
63
|
-
*/
|
|
64
26
|
fetch?: boolean;
|
|
65
|
-
/**
|
|
66
|
-
* Print the list of command line options with brief descriptions and exit.
|
|
67
|
-
*/
|
|
68
27
|
help?: boolean;
|
|
69
|
-
/**
|
|
70
|
-
* Print the list of supported versions of the 'typescript' package and exit.
|
|
71
|
-
*/
|
|
72
28
|
list?: boolean;
|
|
73
|
-
/**
|
|
74
|
-
* Print the list of the selected test files and exit.
|
|
75
|
-
*/
|
|
76
29
|
listFiles?: boolean;
|
|
77
|
-
/**
|
|
78
|
-
* Only run tests with matching name.
|
|
79
|
-
*/
|
|
80
30
|
only?: string;
|
|
81
|
-
/**
|
|
82
|
-
* The list of plugins to use.
|
|
83
|
-
*/
|
|
84
31
|
plugins?: Array<string>;
|
|
85
|
-
/**
|
|
86
|
-
* Remove all installed versions of the 'typescript' package and exit.
|
|
87
|
-
*/
|
|
88
32
|
prune?: boolean;
|
|
89
|
-
/**
|
|
90
|
-
* The list of reporters to use.
|
|
91
|
-
*/
|
|
92
33
|
reporters?: Array<string>;
|
|
93
|
-
/**
|
|
94
|
-
* Print the resolved configuration and exit.
|
|
95
|
-
*/
|
|
96
34
|
showConfig?: boolean;
|
|
97
|
-
/**
|
|
98
|
-
* Skip tests with matching name.
|
|
99
|
-
*/
|
|
100
35
|
skip?: string;
|
|
101
|
-
/**
|
|
102
|
-
* The list of TypeScript versions to be tested on.
|
|
103
|
-
*/
|
|
104
36
|
target?: Array<string>;
|
|
105
|
-
/**
|
|
106
|
-
* The look up strategy to be used to find the TSConfig file.
|
|
107
|
-
*/
|
|
108
37
|
tsconfig?: string;
|
|
109
|
-
/**
|
|
110
|
-
* Fetch the 'typescript' package metadata from the registry and exit.
|
|
111
|
-
*/
|
|
112
38
|
update?: boolean;
|
|
113
|
-
/**
|
|
114
|
-
* Print the version number and exit.
|
|
115
|
-
*/
|
|
116
39
|
version?: boolean;
|
|
117
|
-
/**
|
|
118
|
-
* Watch for changes and rerun related test files.
|
|
119
|
-
*/
|
|
120
40
|
watch?: boolean;
|
|
121
41
|
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Options loaded from the configuration file.
|
|
125
|
-
*/
|
|
126
42
|
interface ConfigFileOptions {
|
|
127
|
-
/**
|
|
128
|
-
* Enable type error reporting for source files.
|
|
129
|
-
*/
|
|
130
43
|
checkSourceFiles?: boolean;
|
|
131
|
-
/**
|
|
132
|
-
* Stop running tests after the first failed assertion.
|
|
133
|
-
*/
|
|
134
44
|
failFast?: boolean;
|
|
135
|
-
/**
|
|
136
|
-
* The list of plugins to use.
|
|
137
|
-
*/
|
|
138
45
|
plugins?: Array<string>;
|
|
139
|
-
/**
|
|
140
|
-
* Reject the 'any' type passed as an argument to the 'expect()' function or a matcher.
|
|
141
|
-
*/
|
|
142
46
|
rejectAnyType?: boolean;
|
|
143
|
-
/**
|
|
144
|
-
* Reject the 'never' type passed as an argument to the 'expect()' function or a matcher.
|
|
145
|
-
*/
|
|
146
47
|
rejectNeverType?: boolean;
|
|
147
|
-
/**
|
|
148
|
-
* The list of reporters to use.
|
|
149
|
-
*/
|
|
150
48
|
reporters?: Array<string>;
|
|
151
|
-
/**
|
|
152
|
-
* The path to a directory containing files of a test project.
|
|
153
|
-
*/
|
|
154
49
|
rootPath?: string;
|
|
155
|
-
/**
|
|
156
|
-
* The list of TypeScript versions to be tested on.
|
|
157
|
-
*/
|
|
158
50
|
target?: Array<string>;
|
|
159
|
-
/**
|
|
160
|
-
* The list of glob patterns matching the test files.
|
|
161
|
-
*/
|
|
162
51
|
testFileMatch?: Array<string>;
|
|
163
|
-
/**
|
|
164
|
-
* The look up strategy to be used to find the TSConfig file.
|
|
165
|
-
*/
|
|
166
52
|
tsconfig?: string;
|
|
167
53
|
}
|
|
168
|
-
|
|
169
54
|
interface InlineConfig {
|
|
170
55
|
if?: {
|
|
171
56
|
target?: Array<string>;
|
|
@@ -173,13 +58,7 @@ interface InlineConfig {
|
|
|
173
58
|
template?: boolean;
|
|
174
59
|
}
|
|
175
60
|
interface ResolvedConfig extends Omit<CommandLineOptions, "config" | keyof ConfigFileOptions>, Required<ConfigFileOptions> {
|
|
176
|
-
/**
|
|
177
|
-
* The path to a TSTyche configuration file.
|
|
178
|
-
*/
|
|
179
61
|
configFilePath: string;
|
|
180
|
-
/**
|
|
181
|
-
* Only run test files with matching path.
|
|
182
|
-
*/
|
|
183
62
|
pathMatch: Array<string>;
|
|
184
63
|
}
|
|
185
64
|
|
|
@@ -202,6 +81,33 @@ declare class Config {
|
|
|
202
81
|
static resolveConfigFilePath(filePath?: string): string;
|
|
203
82
|
}
|
|
204
83
|
|
|
84
|
+
declare enum OptionBrand {
|
|
85
|
+
String = "string",
|
|
86
|
+
Number = "number",
|
|
87
|
+
Boolean = "boolean",
|
|
88
|
+
BareTrue = "bareTrue",
|
|
89
|
+
List = "list"
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
declare class ConfigDiagnosticText {
|
|
93
|
+
static expected(element: string): string;
|
|
94
|
+
static expectsListItemType(optionName: string, optionBrand: OptionBrand): string;
|
|
95
|
+
static expectsValue(optionName: string): string;
|
|
96
|
+
static fileDoesNotExist(filePath: string): string;
|
|
97
|
+
static inspectSupportedVersions(): string;
|
|
98
|
+
static moduleWasNotFound(specifier: string): string;
|
|
99
|
+
static rangeIsNotValid(value: string): string;
|
|
100
|
+
static rangeUsage(): Array<string>;
|
|
101
|
+
static requiresValueType(optionName: string, optionBrand: OptionBrand): string;
|
|
102
|
+
static seen(element: string): string;
|
|
103
|
+
static testFileMatchCannotStartWith(segment: string): Array<string>;
|
|
104
|
+
static unexpected(element: string): string;
|
|
105
|
+
static unknownOption(optionName: string): string;
|
|
106
|
+
static usage(optionName: string, optionBrand: OptionBrand): Array<string>;
|
|
107
|
+
static versionIsNotSupported(value: string): string;
|
|
108
|
+
static watchCannotBeEnabled(): string;
|
|
109
|
+
}
|
|
110
|
+
|
|
205
111
|
interface TextRange {
|
|
206
112
|
start: number;
|
|
207
113
|
end: number;
|
|
@@ -221,6 +127,15 @@ declare class Directive {
|
|
|
221
127
|
static getInlineConfig(ranges: DirectiveRanges | undefined): Promise<InlineConfig | undefined>;
|
|
222
128
|
}
|
|
223
129
|
|
|
130
|
+
declare const defaultOptions: Required<ConfigFileOptions>;
|
|
131
|
+
|
|
132
|
+
declare enum OptionGroup {
|
|
133
|
+
CommandLine = 2,
|
|
134
|
+
ConfigFile = 4,
|
|
135
|
+
InlineConditions = 8,
|
|
136
|
+
ResolvedConfig = 6
|
|
137
|
+
}
|
|
138
|
+
|
|
224
139
|
declare enum DiagnosticCategory {
|
|
225
140
|
Error = "error",
|
|
226
141
|
Warning = "warning"
|
|
@@ -273,13 +188,6 @@ declare function isDiagnosticWithLocation(diagnostic: ts.Diagnostic): diagnostic
|
|
|
273
188
|
|
|
274
189
|
type DiagnosticsHandler<T extends Diagnostic | Array<Diagnostic> = Diagnostic> = (this: void, diagnostics: T) => void;
|
|
275
190
|
|
|
276
|
-
declare enum OptionGroup {
|
|
277
|
-
CommandLine = 2,
|
|
278
|
-
ConfigFile = 4,
|
|
279
|
-
InlineConditions = 8,
|
|
280
|
-
ResolvedConfig = 6
|
|
281
|
-
}
|
|
282
|
-
|
|
283
191
|
interface BaseOptionDefinition {
|
|
284
192
|
brand: OptionBrand;
|
|
285
193
|
description: string;
|
|
@@ -305,8 +213,6 @@ declare class Options {
|
|
|
305
213
|
static validate(optionName: string, optionValue: string, optionBrand: OptionBrand, onDiagnostics: DiagnosticsHandler, origin?: DiagnosticOrigin): Promise<void>;
|
|
306
214
|
}
|
|
307
215
|
|
|
308
|
-
declare const defaultOptions: Required<ConfigFileOptions>;
|
|
309
|
-
|
|
310
216
|
declare enum TestTreeNodeBrand {
|
|
311
217
|
Describe = "describe",
|
|
312
218
|
Test = "test",
|
|
@@ -385,33 +291,12 @@ declare function argumentIsProvided<T>(argumentNameText: string, node: T, enclos
|
|
|
385
291
|
declare function argumentOrTypeArgumentIsProvided<T>(argumentNameText: string, typeArgumentNameText: string, node: T, enclosingNode: ts.Node, onDiagnostics: DiagnosticsHandler<Array<Diagnostic>>): node is NonNullable<T>;
|
|
386
292
|
|
|
387
293
|
interface EnvironmentOptions {
|
|
388
|
-
/**
|
|
389
|
-
* Is `true` if the process is running in continuous integration environment.
|
|
390
|
-
*/
|
|
391
294
|
isCi: boolean;
|
|
392
|
-
/**
|
|
393
|
-
* Specifies whether color should be disabled in the output.
|
|
394
|
-
*/
|
|
395
295
|
noColor: boolean;
|
|
396
|
-
/**
|
|
397
|
-
* Specifies whether interactive elements should be disabled in the output.
|
|
398
|
-
*/
|
|
399
296
|
noInteractive: boolean;
|
|
400
|
-
/**
|
|
401
|
-
* The base URL of the 'npm' registry to use.
|
|
402
|
-
*/
|
|
403
297
|
npmRegistry: string;
|
|
404
|
-
/**
|
|
405
|
-
* The directory where to store the 'typescript' packages.
|
|
406
|
-
*/
|
|
407
298
|
storePath: string;
|
|
408
|
-
/**
|
|
409
|
-
* The number of seconds to wait before giving up stale operations.
|
|
410
|
-
*/
|
|
411
299
|
timeout: number;
|
|
412
|
-
/**
|
|
413
|
-
* The specifier of the TypeScript module.
|
|
414
|
-
*/
|
|
415
300
|
typescriptModule: string | undefined;
|
|
416
301
|
}
|
|
417
302
|
|
|
@@ -751,8 +636,6 @@ interface CodeFrameOptions {
|
|
|
751
636
|
|
|
752
637
|
declare function diagnosticText(diagnostic: Diagnostic, codeFrameOptions?: CodeFrameOptions): ScribblerJsx.Element;
|
|
753
638
|
|
|
754
|
-
declare function taskStatusText(status: TaskResultStatus, task: Task): ScribblerJsx.Element;
|
|
755
|
-
|
|
756
639
|
declare function fileViewText(lines: Array<ScribblerJsx.Element>, addEmptyFinalLine: boolean): ScribblerJsx.Element;
|
|
757
640
|
|
|
758
641
|
declare function formattedText(input: string | Array<string> | Record<string, unknown>): ScribblerJsx.Element;
|
|
@@ -776,6 +659,8 @@ declare function summaryText({ duration, expectCount, fileCount, targetCount, te
|
|
|
776
659
|
testCount: ResultCount;
|
|
777
660
|
}): ScribblerJsx.Element;
|
|
778
661
|
|
|
662
|
+
declare function taskStatusText(status: TaskResultStatus, task: Task): ScribblerJsx.Element;
|
|
663
|
+
|
|
779
664
|
declare function testNameText(status: "fail" | "pass" | "skip" | "todo", name: string, indent?: number): ScribblerJsx.Element;
|
|
780
665
|
|
|
781
666
|
declare function usesCompilerText(compilerVersion: string, projectConfigFilePath: string | undefined, options?: {
|
|
@@ -798,17 +683,8 @@ interface SelectHookContext {
|
|
|
798
683
|
resolvedConfig: ResolvedConfig;
|
|
799
684
|
}
|
|
800
685
|
interface Plugin {
|
|
801
|
-
/**
|
|
802
|
-
* The name of this plugin.
|
|
803
|
-
*/
|
|
804
686
|
name: string;
|
|
805
|
-
/**
|
|
806
|
-
* Is called after configuration is resolved and allows to modify it.
|
|
807
|
-
*/
|
|
808
687
|
config?: (resolvedConfig: ResolvedConfig) => ResolvedConfig | Promise<ResolvedConfig>;
|
|
809
|
-
/**
|
|
810
|
-
* Is called after test files are selected and allows to modify the list.
|
|
811
|
-
*/
|
|
812
688
|
select?: (this: SelectHookContext, testFiles: Array<string>) => Array<string | URL> | Promise<Array<string | URL>>;
|
|
813
689
|
}
|
|
814
690
|
|
package/build/tstyche.js
CHANGED
|
@@ -8,73 +8,6 @@ import { createRequire } from 'node:module';
|
|
|
8
8
|
import vm from 'node:vm';
|
|
9
9
|
import streamConsumers from 'node:stream/consumers';
|
|
10
10
|
|
|
11
|
-
class ConfigDiagnosticText {
|
|
12
|
-
static expected(element) {
|
|
13
|
-
return `Expected ${element}.`;
|
|
14
|
-
}
|
|
15
|
-
static expectsListItemType(optionName, optionBrand) {
|
|
16
|
-
return `Item of the '${optionName}' list must be of type ${optionBrand}.`;
|
|
17
|
-
}
|
|
18
|
-
static expectsValue(optionName) {
|
|
19
|
-
return `Option '${optionName}' expects a value.`;
|
|
20
|
-
}
|
|
21
|
-
static fileDoesNotExist(filePath) {
|
|
22
|
-
return `The specified path '${filePath}' does not exist.`;
|
|
23
|
-
}
|
|
24
|
-
static inspectSupportedVersions() {
|
|
25
|
-
return "Use the '--list' command line option to inspect the list of supported versions.";
|
|
26
|
-
}
|
|
27
|
-
static moduleWasNotFound(specifier) {
|
|
28
|
-
return `The specified module '${specifier}' was not found.`;
|
|
29
|
-
}
|
|
30
|
-
static rangeIsNotValid(value) {
|
|
31
|
-
return `The specified range '${value}' is not valid.`;
|
|
32
|
-
}
|
|
33
|
-
static rangeUsage() {
|
|
34
|
-
return [
|
|
35
|
-
"A range must be specified using an operator and a minor version.",
|
|
36
|
-
"To set an upper bound, the intersection of two ranges can be used.",
|
|
37
|
-
"Examples: '>=5.5', '>=5.0 <5.3'.",
|
|
38
|
-
];
|
|
39
|
-
}
|
|
40
|
-
static requiresValueType(optionName, optionBrand) {
|
|
41
|
-
return `Option '${optionName}' requires a value of type ${optionBrand}.`;
|
|
42
|
-
}
|
|
43
|
-
static seen(element) {
|
|
44
|
-
return `The ${element} was seen here.`;
|
|
45
|
-
}
|
|
46
|
-
static testFileMatchCannotStartWith(segment) {
|
|
47
|
-
return [
|
|
48
|
-
`A test file match pattern cannot start with '${segment}'.`,
|
|
49
|
-
"The test files are only collected within the 'rootPath' directory.",
|
|
50
|
-
];
|
|
51
|
-
}
|
|
52
|
-
static unknownOption(optionName) {
|
|
53
|
-
return `Unknown option '${optionName}'.`;
|
|
54
|
-
}
|
|
55
|
-
static usage(optionName, optionBrand) {
|
|
56
|
-
switch (optionName.startsWith("--") ? optionName.slice(2) : optionName) {
|
|
57
|
-
case "target": {
|
|
58
|
-
const text = [];
|
|
59
|
-
if (optionName.startsWith("--")) {
|
|
60
|
-
text.push("Value for the '--target' option must be a string or a comma separated list.", "Examples: '--target 5.2', '--target next', '--target '>=5.0 <5.3, 5.4.2, >=5.5''.");
|
|
61
|
-
}
|
|
62
|
-
return text;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
return [ConfigDiagnosticText.requiresValueType(optionName, optionBrand)];
|
|
66
|
-
}
|
|
67
|
-
static versionIsNotSupported(value) {
|
|
68
|
-
if (value === "current") {
|
|
69
|
-
return "Cannot use 'current' as a target. Failed to resolve the installed TypeScript module.";
|
|
70
|
-
}
|
|
71
|
-
return `TypeScript version '${value}' is not supported.`;
|
|
72
|
-
}
|
|
73
|
-
static watchCannotBeEnabled() {
|
|
74
|
-
return "Watch mode cannot be enabled in continuous integration environment.";
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
|
|
78
11
|
var DiagnosticCategory;
|
|
79
12
|
(function (DiagnosticCategory) {
|
|
80
13
|
DiagnosticCategory["Error"] = "error";
|
|
@@ -279,6 +212,76 @@ class Path {
|
|
|
279
212
|
}
|
|
280
213
|
}
|
|
281
214
|
|
|
215
|
+
class ConfigDiagnosticText {
|
|
216
|
+
static expected(element) {
|
|
217
|
+
return `Expected ${element}.`;
|
|
218
|
+
}
|
|
219
|
+
static expectsListItemType(optionName, optionBrand) {
|
|
220
|
+
return `Item of the '${optionName}' list must be of type ${optionBrand}.`;
|
|
221
|
+
}
|
|
222
|
+
static expectsValue(optionName) {
|
|
223
|
+
return `Option '${optionName}' expects a value.`;
|
|
224
|
+
}
|
|
225
|
+
static fileDoesNotExist(filePath) {
|
|
226
|
+
return `The specified path '${filePath}' does not exist.`;
|
|
227
|
+
}
|
|
228
|
+
static inspectSupportedVersions() {
|
|
229
|
+
return "Use the '--list' command line option to inspect the list of supported versions.";
|
|
230
|
+
}
|
|
231
|
+
static moduleWasNotFound(specifier) {
|
|
232
|
+
return `The specified module '${specifier}' was not found.`;
|
|
233
|
+
}
|
|
234
|
+
static rangeIsNotValid(value) {
|
|
235
|
+
return `The specified range '${value}' is not valid.`;
|
|
236
|
+
}
|
|
237
|
+
static rangeUsage() {
|
|
238
|
+
return [
|
|
239
|
+
"A range must be specified using an operator and a minor version.",
|
|
240
|
+
"To set an upper bound, the intersection of two ranges can be used.",
|
|
241
|
+
"Examples: '>=5.5', '>=5.0 <5.3'.",
|
|
242
|
+
];
|
|
243
|
+
}
|
|
244
|
+
static requiresValueType(optionName, optionBrand) {
|
|
245
|
+
return `Option '${optionName}' requires a value of type ${optionBrand}.`;
|
|
246
|
+
}
|
|
247
|
+
static seen(element) {
|
|
248
|
+
return `The ${element} was seen here.`;
|
|
249
|
+
}
|
|
250
|
+
static testFileMatchCannotStartWith(segment) {
|
|
251
|
+
return [
|
|
252
|
+
`A test file match pattern cannot start with '${segment}'.`,
|
|
253
|
+
"The test files are only collected within the 'rootPath' directory.",
|
|
254
|
+
];
|
|
255
|
+
}
|
|
256
|
+
static unexpected(element) {
|
|
257
|
+
return `Unexpected ${element}.`;
|
|
258
|
+
}
|
|
259
|
+
static unknownOption(optionName) {
|
|
260
|
+
return `Unknown option '${optionName}'.`;
|
|
261
|
+
}
|
|
262
|
+
static usage(optionName, optionBrand) {
|
|
263
|
+
switch (optionName.startsWith("--") ? optionName.slice(2) : optionName) {
|
|
264
|
+
case "target": {
|
|
265
|
+
const text = [];
|
|
266
|
+
if (optionName.startsWith("--")) {
|
|
267
|
+
text.push("Value for the '--target' option must be a string or a comma separated list.", "Examples: '--target 5.2', '--target next', '--target '>=5.0 <5.3, 5.4.2, >=5.5''.");
|
|
268
|
+
}
|
|
269
|
+
return text;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return [ConfigDiagnosticText.requiresValueType(optionName, optionBrand)];
|
|
273
|
+
}
|
|
274
|
+
static versionIsNotSupported(value) {
|
|
275
|
+
if (value === "current") {
|
|
276
|
+
return "Cannot use 'current' as a target. Failed to resolve the installed TypeScript module.";
|
|
277
|
+
}
|
|
278
|
+
return `TypeScript version '${value}' is not supported.`;
|
|
279
|
+
}
|
|
280
|
+
static watchCannotBeEnabled() {
|
|
281
|
+
return "Watch mode cannot be enabled in continuous integration environment.";
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
282
285
|
var OptionBrand;
|
|
283
286
|
(function (OptionBrand) {
|
|
284
287
|
OptionBrand["String"] = "string";
|
|
@@ -510,7 +513,7 @@ class LockService {
|
|
|
510
513
|
}
|
|
511
514
|
return isLocked;
|
|
512
515
|
}
|
|
513
|
-
|
|
516
|
+
#sleep(delay) {
|
|
514
517
|
return new Promise((resolve) => setTimeout(resolve, delay));
|
|
515
518
|
}
|
|
516
519
|
}
|
|
@@ -1375,6 +1378,13 @@ class ConfigParser {
|
|
|
1375
1378
|
related: [Diagnostic.error(relatedText, leftBraceToken.origin)],
|
|
1376
1379
|
});
|
|
1377
1380
|
this.#onDiagnostics(diagnostic);
|
|
1381
|
+
return;
|
|
1382
|
+
}
|
|
1383
|
+
const unexpectedToken = this.#jsonScanner.readToken(/\S/);
|
|
1384
|
+
if (unexpectedToken.text != null) {
|
|
1385
|
+
const text = ConfigDiagnosticText.unexpected("token");
|
|
1386
|
+
const diagnostic = Diagnostic.error(text, unexpectedToken.origin);
|
|
1387
|
+
this.#onDiagnostics(diagnostic);
|
|
1378
1388
|
}
|
|
1379
1389
|
}
|
|
1380
1390
|
async parse() {
|
|
@@ -1382,6 +1392,19 @@ class ConfigParser {
|
|
|
1382
1392
|
}
|
|
1383
1393
|
}
|
|
1384
1394
|
|
|
1395
|
+
const defaultOptions = {
|
|
1396
|
+
checkSourceFiles: true,
|
|
1397
|
+
failFast: false,
|
|
1398
|
+
plugins: [],
|
|
1399
|
+
rejectAnyType: true,
|
|
1400
|
+
rejectNeverType: true,
|
|
1401
|
+
reporters: ["list", "summary"],
|
|
1402
|
+
rootPath: Path.resolve("./"),
|
|
1403
|
+
target: environmentOptions.typescriptModule != null ? ["current"] : ["latest"],
|
|
1404
|
+
testFileMatch: ["**/*.tst.*", "**/__typetests__/*.test.*", "**/typetests/*.test.*"],
|
|
1405
|
+
tsconfig: "findup",
|
|
1406
|
+
};
|
|
1407
|
+
|
|
1385
1408
|
class JsonNode {
|
|
1386
1409
|
origin;
|
|
1387
1410
|
text;
|
|
@@ -1474,9 +1497,10 @@ class JsonScanner {
|
|
|
1474
1497
|
readToken(token) {
|
|
1475
1498
|
this.#skipTrivia();
|
|
1476
1499
|
this.#previousPosition = this.#position;
|
|
1477
|
-
|
|
1500
|
+
const character = this.#peekCharacter();
|
|
1501
|
+
if (typeof token === "string" ? token === character : token.test(character)) {
|
|
1478
1502
|
this.#position++;
|
|
1479
|
-
return new JsonNode(
|
|
1503
|
+
return new JsonNode(character, this.#getOrigin());
|
|
1480
1504
|
}
|
|
1481
1505
|
return new JsonNode(undefined, this.#getOrigin());
|
|
1482
1506
|
}
|
|
@@ -1514,19 +1538,6 @@ class JsonScanner {
|
|
|
1514
1538
|
}
|
|
1515
1539
|
}
|
|
1516
1540
|
|
|
1517
|
-
const defaultOptions = {
|
|
1518
|
-
checkSourceFiles: true,
|
|
1519
|
-
failFast: false,
|
|
1520
|
-
plugins: [],
|
|
1521
|
-
rejectAnyType: true,
|
|
1522
|
-
rejectNeverType: true,
|
|
1523
|
-
reporters: ["list", "summary"],
|
|
1524
|
-
rootPath: Path.resolve("./"),
|
|
1525
|
-
target: environmentOptions.typescriptModule != null ? ["current"] : ["latest"],
|
|
1526
|
-
testFileMatch: ["**/*.tst.*", "**/__typetests__/*.test.*", "**/typetests/*.test.*"],
|
|
1527
|
-
tsconfig: "findup",
|
|
1528
|
-
};
|
|
1529
|
-
|
|
1530
1541
|
class Config {
|
|
1531
1542
|
static #onDiagnostics(diagnostic) {
|
|
1532
1543
|
EventEmitter.dispatch(["config:error", { diagnostics: [diagnostic] }]);
|
|
@@ -1578,20 +1589,19 @@ class Config {
|
|
|
1578
1589
|
}
|
|
1579
1590
|
|
|
1580
1591
|
class DirectiveDiagnosticText {
|
|
1581
|
-
static doesNotTakeArgument(
|
|
1582
|
-
return
|
|
1592
|
+
static doesNotTakeArgument() {
|
|
1593
|
+
return "Directive does not take an argument.";
|
|
1583
1594
|
}
|
|
1584
1595
|
static isNotSupported(directive) {
|
|
1585
1596
|
return `The '${directive}' directive is not supported.`;
|
|
1586
1597
|
}
|
|
1587
|
-
static requiresArgument(
|
|
1588
|
-
return
|
|
1598
|
+
static requiresArgument() {
|
|
1599
|
+
return "Directive requires an argument.";
|
|
1589
1600
|
}
|
|
1590
1601
|
}
|
|
1591
1602
|
|
|
1592
1603
|
class Directive {
|
|
1593
|
-
static #
|
|
1594
|
-
static #directiveRegex = /^(\/\/\s*@tstyche)(\s*|-)?(\S*)?(\s*)?(.*)?/i;
|
|
1604
|
+
static #directiveRegex = /^(\/\/ *@tstyche)( *|-)?(\S*)?( *)?(.*)?/i;
|
|
1595
1605
|
static getDirectiveRanges(compiler, sourceFile, position = 0) {
|
|
1596
1606
|
const comments = compiler.getLeadingCommentRanges(sourceFile.text, position);
|
|
1597
1607
|
if (!comments || comments.length === 0) {
|
|
@@ -1620,28 +1630,28 @@ class Directive {
|
|
|
1620
1630
|
return inlineConfig;
|
|
1621
1631
|
}
|
|
1622
1632
|
static #getRange(sourceFile, comment) {
|
|
1623
|
-
const [text] = sourceFile.text.substring(comment.pos, comment.end).split(
|
|
1624
|
-
const
|
|
1625
|
-
const namespaceText =
|
|
1633
|
+
const [text] = sourceFile.text.substring(comment.pos, comment.end).split(/--+/);
|
|
1634
|
+
const match = text?.match(Directive.#directiveRegex);
|
|
1635
|
+
const namespaceText = match?.[1];
|
|
1626
1636
|
if (!namespaceText) {
|
|
1627
1637
|
return;
|
|
1628
1638
|
}
|
|
1629
|
-
const
|
|
1639
|
+
const range = {
|
|
1630
1640
|
namespace: { start: comment.pos, end: comment.pos + namespaceText.length, text: namespaceText },
|
|
1631
1641
|
};
|
|
1632
|
-
const directiveSeparatorText =
|
|
1633
|
-
const directiveText =
|
|
1634
|
-
if (directiveText
|
|
1635
|
-
const start =
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1642
|
+
const directiveSeparatorText = match?.[2];
|
|
1643
|
+
const directiveText = match?.[3];
|
|
1644
|
+
if (typeof directiveText === "string" && typeof directiveSeparatorText === "string") {
|
|
1645
|
+
const start = range.namespace.end + directiveSeparatorText.length;
|
|
1646
|
+
range.directive = { start, end: start + directiveText.length, text: directiveText };
|
|
1647
|
+
const argumentSeparatorText = match?.[4];
|
|
1648
|
+
const argumentText = match?.[5]?.trimEnd();
|
|
1649
|
+
if (typeof argumentSeparatorText === "string" && typeof argumentText === "string") {
|
|
1650
|
+
const start = range.directive.end + argumentSeparatorText.length;
|
|
1651
|
+
range.argument = { start, end: start + argumentText.length, text: argumentText };
|
|
1652
|
+
}
|
|
1643
1653
|
}
|
|
1644
|
-
return
|
|
1654
|
+
return range;
|
|
1645
1655
|
}
|
|
1646
1656
|
static #onDiagnostics(diagnostic) {
|
|
1647
1657
|
EventEmitter.dispatch(["directive:error", { diagnostics: [diagnostic] }]);
|
|
@@ -1651,8 +1661,8 @@ class Directive {
|
|
|
1651
1661
|
case "if":
|
|
1652
1662
|
{
|
|
1653
1663
|
if (!ranges.argument?.text) {
|
|
1654
|
-
const text = DirectiveDiagnosticText.requiresArgument(
|
|
1655
|
-
const origin = new DiagnosticOrigin(ranges.
|
|
1664
|
+
const text = DirectiveDiagnosticText.requiresArgument();
|
|
1665
|
+
const origin = new DiagnosticOrigin(ranges.namespace.start, ranges.directive.end, sourceFile);
|
|
1656
1666
|
Directive.#onDiagnostics(Diagnostic.error(text, origin));
|
|
1657
1667
|
return;
|
|
1658
1668
|
}
|
|
@@ -1662,8 +1672,8 @@ class Directive {
|
|
|
1662
1672
|
return;
|
|
1663
1673
|
case "template":
|
|
1664
1674
|
if (ranges.argument?.text != null) {
|
|
1665
|
-
const text = DirectiveDiagnosticText.doesNotTakeArgument(
|
|
1666
|
-
const origin = new DiagnosticOrigin(ranges.
|
|
1675
|
+
const text = DirectiveDiagnosticText.doesNotTakeArgument();
|
|
1676
|
+
const origin = new DiagnosticOrigin(ranges.argument.start, ranges.argument.end, sourceFile);
|
|
1667
1677
|
Directive.#onDiagnostics(Diagnostic.error(text, origin));
|
|
1668
1678
|
}
|
|
1669
1679
|
inlineConfig.template = true;
|
|
@@ -2204,33 +2214,6 @@ function diagnosticText(diagnostic, codeFrameOptions = {}) {
|
|
|
2204
2214
|
return (jsx(Text, { children: [prefix, jsx(DiagnosticText, { codeFrameOptions: codeFrameOptions, diagnostic: diagnostic })] }));
|
|
2205
2215
|
}
|
|
2206
2216
|
|
|
2207
|
-
function FileNameText({ filePath }) {
|
|
2208
|
-
const relativePath = Path.relative("", filePath);
|
|
2209
|
-
const lastPathSeparator = relativePath.lastIndexOf("/");
|
|
2210
|
-
const directoryNameText = relativePath.slice(0, lastPathSeparator + 1);
|
|
2211
|
-
const fileNameText = relativePath.slice(lastPathSeparator + 1);
|
|
2212
|
-
return (jsx(Text, { children: [jsx(Text, { color: Color.Gray, children: directoryNameText }), fileNameText] }));
|
|
2213
|
-
}
|
|
2214
|
-
function taskStatusText(status, task) {
|
|
2215
|
-
let statusColor;
|
|
2216
|
-
let statusText;
|
|
2217
|
-
switch (status) {
|
|
2218
|
-
case ResultStatus.Runs:
|
|
2219
|
-
statusColor = Color.Yellow;
|
|
2220
|
-
statusText = "runs";
|
|
2221
|
-
break;
|
|
2222
|
-
case ResultStatus.Passed:
|
|
2223
|
-
statusColor = Color.Green;
|
|
2224
|
-
statusText = "pass";
|
|
2225
|
-
break;
|
|
2226
|
-
case ResultStatus.Failed:
|
|
2227
|
-
statusColor = Color.Red;
|
|
2228
|
-
statusText = "fail";
|
|
2229
|
-
break;
|
|
2230
|
-
}
|
|
2231
|
-
return (jsx(Line, { children: [jsx(Text, { color: statusColor, children: statusText }), " ", jsx(FileNameText, { filePath: task.filePath })] }));
|
|
2232
|
-
}
|
|
2233
|
-
|
|
2234
2217
|
function fileViewText(lines, addEmptyFinalLine) {
|
|
2235
2218
|
return (jsx(Text, { children: [[...lines], addEmptyFinalLine ? jsx(Line, {}) : undefined] }));
|
|
2236
2219
|
}
|
|
@@ -2350,6 +2333,33 @@ function summaryText({ duration, expectCount, fileCount, targetCount, testCount,
|
|
|
2350
2333
|
return (jsx(Text, { children: [targetCountText, fileCountText, testCount.total > 0 ? testCountText : undefined, expectCount.total > 0 ? assertionCountText : undefined, jsx(RowText, { label: "Duration", text: jsx(DurationText, { seconds: duration / 1000 }) })] }));
|
|
2351
2334
|
}
|
|
2352
2335
|
|
|
2336
|
+
function FileNameText({ filePath }) {
|
|
2337
|
+
const relativePath = Path.relative("", filePath);
|
|
2338
|
+
const lastPathSeparator = relativePath.lastIndexOf("/");
|
|
2339
|
+
const directoryNameText = relativePath.slice(0, lastPathSeparator + 1);
|
|
2340
|
+
const fileNameText = relativePath.slice(lastPathSeparator + 1);
|
|
2341
|
+
return (jsx(Text, { children: [jsx(Text, { color: Color.Gray, children: directoryNameText }), fileNameText] }));
|
|
2342
|
+
}
|
|
2343
|
+
function taskStatusText(status, task) {
|
|
2344
|
+
let statusColor;
|
|
2345
|
+
let statusText;
|
|
2346
|
+
switch (status) {
|
|
2347
|
+
case ResultStatus.Runs:
|
|
2348
|
+
statusColor = Color.Yellow;
|
|
2349
|
+
statusText = "runs";
|
|
2350
|
+
break;
|
|
2351
|
+
case ResultStatus.Passed:
|
|
2352
|
+
statusColor = Color.Green;
|
|
2353
|
+
statusText = "pass";
|
|
2354
|
+
break;
|
|
2355
|
+
case ResultStatus.Failed:
|
|
2356
|
+
statusColor = Color.Red;
|
|
2357
|
+
statusText = "fail";
|
|
2358
|
+
break;
|
|
2359
|
+
}
|
|
2360
|
+
return (jsx(Line, { children: [jsx(Text, { color: statusColor, children: statusText }), " ", jsx(FileNameText, { filePath: task.filePath })] }));
|
|
2361
|
+
}
|
|
2362
|
+
|
|
2353
2363
|
function StatusText({ status }) {
|
|
2354
2364
|
switch (status) {
|
|
2355
2365
|
case "fail":
|
|
@@ -2635,6 +2645,14 @@ class Task {
|
|
|
2635
2645
|
}
|
|
2636
2646
|
}
|
|
2637
2647
|
|
|
2648
|
+
var CancellationReason;
|
|
2649
|
+
(function (CancellationReason) {
|
|
2650
|
+
CancellationReason["ConfigChange"] = "configChange";
|
|
2651
|
+
CancellationReason["ConfigError"] = "configError";
|
|
2652
|
+
CancellationReason["FailFast"] = "failFast";
|
|
2653
|
+
CancellationReason["WatchClose"] = "watchClose";
|
|
2654
|
+
})(CancellationReason || (CancellationReason = {}));
|
|
2655
|
+
|
|
2638
2656
|
class CancellationToken {
|
|
2639
2657
|
#isCancelled = false;
|
|
2640
2658
|
#reason;
|
|
@@ -2658,14 +2676,6 @@ class CancellationToken {
|
|
|
2658
2676
|
}
|
|
2659
2677
|
}
|
|
2660
2678
|
|
|
2661
|
-
var CancellationReason;
|
|
2662
|
-
(function (CancellationReason) {
|
|
2663
|
-
CancellationReason["ConfigChange"] = "configChange";
|
|
2664
|
-
CancellationReason["ConfigError"] = "configError";
|
|
2665
|
-
CancellationReason["FailFast"] = "failFast";
|
|
2666
|
-
CancellationReason["WatchClose"] = "watchClose";
|
|
2667
|
-
})(CancellationReason || (CancellationReason = {}));
|
|
2668
|
-
|
|
2669
2679
|
class Watcher {
|
|
2670
2680
|
#onChanged;
|
|
2671
2681
|
#onRemoved;
|
|
@@ -3037,7 +3047,8 @@ class AssertionNode extends TestTreeNode {
|
|
|
3037
3047
|
this.target = this.matcherNode.typeArguments ?? this.matcherNode.arguments;
|
|
3038
3048
|
}
|
|
3039
3049
|
for (const diagnostic of parent.diagnostics) {
|
|
3040
|
-
if (diagnosticBelongsToNode(diagnostic, this.source)
|
|
3050
|
+
if (diagnosticBelongsToNode(diagnostic, this.source) ||
|
|
3051
|
+
(this.target != null && diagnosticBelongsToNode(diagnostic, this.target))) {
|
|
3041
3052
|
this.diagnostics.add(diagnostic);
|
|
3042
3053
|
parent.diagnostics.delete(diagnostic);
|
|
3043
3054
|
}
|
|
@@ -3629,6 +3640,7 @@ var RunMode;
|
|
|
3629
3640
|
RunMode[RunMode["Only"] = 2] = "Only";
|
|
3630
3641
|
RunMode[RunMode["Skip"] = 4] = "Skip";
|
|
3631
3642
|
RunMode[RunMode["Todo"] = 8] = "Todo";
|
|
3643
|
+
RunMode[RunMode["Void"] = 16] = "Void";
|
|
3632
3644
|
})(RunMode || (RunMode = {}));
|
|
3633
3645
|
|
|
3634
3646
|
class EnsureDiagnosticText {
|
|
@@ -4674,7 +4686,7 @@ class TestTreeWalker {
|
|
|
4674
4686
|
const directiveRanges = node.getDirectiveRanges(this.#compiler);
|
|
4675
4687
|
const inlineConfig = await Directive.getInlineConfig(directiveRanges);
|
|
4676
4688
|
if (inlineConfig?.if?.target != null && !Version.isIncluded(this.#compiler.version, inlineConfig.if.target)) {
|
|
4677
|
-
mode |= RunMode.
|
|
4689
|
+
mode |= RunMode.Void;
|
|
4678
4690
|
}
|
|
4679
4691
|
if (node.flags & TestTreeNodeFlags.Fail) {
|
|
4680
4692
|
mode |= RunMode.Fail;
|
|
@@ -4719,9 +4731,12 @@ class TestTreeWalker {
|
|
|
4719
4731
|
}
|
|
4720
4732
|
async #visitAssertion(assertion, runMode, parentResult) {
|
|
4721
4733
|
await this.visit(assertion.children, runMode, parentResult);
|
|
4734
|
+
runMode = await this.#resolveRunMode(runMode, assertion);
|
|
4735
|
+
if (runMode & RunMode.Void) {
|
|
4736
|
+
return;
|
|
4737
|
+
}
|
|
4722
4738
|
const expectResult = new ExpectResult(assertion, parentResult);
|
|
4723
4739
|
EventEmitter.dispatch(["expect:start", { result: expectResult }]);
|
|
4724
|
-
runMode = await this.#resolveRunMode(runMode, assertion);
|
|
4725
4740
|
if (runMode & RunMode.Skip || (this.#hasOnly && !(runMode & RunMode.Only))) {
|
|
4726
4741
|
EventEmitter.dispatch(["expect:skip", { result: expectResult }]);
|
|
4727
4742
|
return;
|
|
@@ -4758,9 +4773,12 @@ class TestTreeWalker {
|
|
|
4758
4773
|
}
|
|
4759
4774
|
}
|
|
4760
4775
|
async #visitDescribe(describe, runMode, parentResult) {
|
|
4776
|
+
runMode = await this.#resolveRunMode(runMode, describe);
|
|
4777
|
+
if (runMode & RunMode.Void) {
|
|
4778
|
+
return;
|
|
4779
|
+
}
|
|
4761
4780
|
const describeResult = new DescribeResult(describe, parentResult);
|
|
4762
4781
|
EventEmitter.dispatch(["describe:start", { result: describeResult }]);
|
|
4763
|
-
runMode = await this.#resolveRunMode(runMode, describe);
|
|
4764
4782
|
if (!(runMode & RunMode.Skip || (this.#hasOnly && !(runMode & RunMode.Only)) || runMode & RunMode.Todo) &&
|
|
4765
4783
|
describe.diagnostics.size > 0) {
|
|
4766
4784
|
this.#onTaskDiagnostics(Diagnostic.fromDiagnostics([...describe.diagnostics]));
|
|
@@ -4771,9 +4789,12 @@ class TestTreeWalker {
|
|
|
4771
4789
|
EventEmitter.dispatch(["describe:end", { result: describeResult }]);
|
|
4772
4790
|
}
|
|
4773
4791
|
async #visitTest(test, runMode, parentResult) {
|
|
4792
|
+
runMode = await this.#resolveRunMode(runMode, test);
|
|
4793
|
+
if (runMode & RunMode.Void) {
|
|
4794
|
+
return;
|
|
4795
|
+
}
|
|
4774
4796
|
const testResult = new TestResult(test, parentResult);
|
|
4775
4797
|
EventEmitter.dispatch(["test:start", { result: testResult }]);
|
|
4776
|
-
runMode = await this.#resolveRunMode(runMode, test);
|
|
4777
4798
|
if (runMode & RunMode.Todo) {
|
|
4778
4799
|
EventEmitter.dispatch(["test:todo", { result: testResult }]);
|
|
4779
4800
|
return;
|
|
@@ -4894,7 +4915,7 @@ class TaskRunner {
|
|
|
4894
4915
|
class Runner {
|
|
4895
4916
|
#eventEmitter = new EventEmitter();
|
|
4896
4917
|
#resolvedConfig;
|
|
4897
|
-
static version = "4.0.
|
|
4918
|
+
static version = "4.0.1";
|
|
4898
4919
|
constructor(resolvedConfig) {
|
|
4899
4920
|
this.#resolvedConfig = resolvedConfig;
|
|
4900
4921
|
}
|