tstyche 7.0.0-rc.1 → 7.1.0
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 +22 -18
- package/dist/api.d.ts +7 -17
- package/dist/api.js +45 -217
- package/dist/index.cjs +0 -1
- package/dist/index.d.cts +2 -23
- package/dist/index.d.ts +2 -23
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/schemas/config.json +2 -2
package/README.md
CHANGED
|
@@ -30,14 +30,14 @@ test("isSameLength", () => {
|
|
|
30
30
|
});
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
TSTyche lets you organize tests using:
|
|
34
34
|
|
|
35
|
-
- `test()`, `it()` and `describe()`
|
|
36
|
-
-
|
|
35
|
+
- helpers: `test()`, `it()` and `describe()`
|
|
36
|
+
- run mode flags: `.only`, `.skip` and `.todo`
|
|
37
37
|
|
|
38
38
|
## Assertions
|
|
39
39
|
|
|
40
|
-
The `expect` style assertions can check either the inferred type of an expression
|
|
40
|
+
The `expect` style assertions can check either the inferred type of an expression or a type directly:
|
|
41
41
|
|
|
42
42
|
```ts
|
|
43
43
|
import { type _, expect } from "tstyche";
|
|
@@ -58,32 +58,32 @@ expect<WithLoading<_>>().type.not.toBeInstantiableWith<[string]>();
|
|
|
58
58
|
|
|
59
59
|
Relation matchers:
|
|
60
60
|
|
|
61
|
-
- `.toBe()` checks if a type is the same as the given type
|
|
62
|
-
- `.toBeAssignableFrom()` checks if a type is assignable from the given type
|
|
63
|
-
- `.toBeAssignableTo()` checks if a type is assignable to the given type
|
|
61
|
+
- `.toBe()` checks if a type is the same as the given type
|
|
62
|
+
- `.toBeAssignableFrom()` checks if a type is assignable from the given type
|
|
63
|
+
- `.toBeAssignableTo()` checks if a type is assignable to the given type
|
|
64
64
|
|
|
65
65
|
Ability matchers:
|
|
66
66
|
|
|
67
|
-
- `.toAcceptProps()` checks if a JSX component accepts the given props
|
|
68
|
-
- `.toBeApplicable` checks if a decorator is applicable to the given class or class member
|
|
69
|
-
- `.toBeCallableWith()` checks if a function is callable with the given arguments
|
|
70
|
-
- `.toBeConstructableWith()` checks if a class is constructable with the given arguments
|
|
71
|
-
- `.toBeInstantiableWith()` checks if a generic is instantiable with the given type arguments
|
|
72
|
-
- `.toHaveProperty()` checks if a type has the given property
|
|
67
|
+
- `.toAcceptProps()` checks if a JSX component accepts the given props
|
|
68
|
+
- `.toBeApplicable` checks if a decorator is applicable to the given class or class member
|
|
69
|
+
- `.toBeCallableWith()` checks if a function is callable with the given arguments
|
|
70
|
+
- `.toBeConstructableWith()` checks if a class is constructable with the given arguments
|
|
71
|
+
- `.toBeInstantiableWith()` checks if a generic is instantiable with the given type arguments
|
|
72
|
+
- `.toHaveProperty()` checks if a type has the given property
|
|
73
73
|
|
|
74
74
|
## Runner
|
|
75
75
|
|
|
76
|
-
The `tstyche` command is the heart of TSTyche. It
|
|
76
|
+
The `tstyche` command is the heart of TSTyche. It lets you select test files by path, filter tests by name and run them against specific versions of TypeScript:
|
|
77
77
|
|
|
78
78
|
```shell
|
|
79
79
|
tstyche query-params --only multiple --target '>=5.6'
|
|
80
80
|
```
|
|
81
81
|
|
|
82
|
-
|
|
82
|
+
That is just the beginning. It even lets you:
|
|
83
83
|
|
|
84
|
-
-
|
|
85
|
-
-
|
|
86
|
-
-
|
|
84
|
+
- check messages of errors suppressed by `@ts-expect-error` directives
|
|
85
|
+
- generate type tests from a template file
|
|
86
|
+
- run tests in watch mode
|
|
87
87
|
|
|
88
88
|
## Try It Out
|
|
89
89
|
|
|
@@ -95,6 +95,10 @@ Try TSTyche online on StackBlitz:
|
|
|
95
95
|
|
|
96
96
|
Visit [tstyche.org](https://tstyche.org) to view the full documentation.
|
|
97
97
|
|
|
98
|
+
## Roadmap
|
|
99
|
+
|
|
100
|
+
See [ROADMAP.md](https://github.com/tstyche/tstyche/blob/main/ROADMAP.md) for planned features.
|
|
101
|
+
|
|
98
102
|
## License
|
|
99
103
|
|
|
100
104
|
[MIT][license-url] © TSTyche
|
package/dist/api.d.ts
CHANGED
|
@@ -36,8 +36,7 @@ declare enum TestTreeNodeBrand {
|
|
|
36
36
|
Describe = "describe",
|
|
37
37
|
Test = "test",
|
|
38
38
|
It = "it",
|
|
39
|
-
Expect = "expect"
|
|
40
|
-
When = "when"
|
|
39
|
+
Expect = "expect"
|
|
41
40
|
}
|
|
42
41
|
|
|
43
42
|
declare enum TestTreeNodeFlags {
|
|
@@ -47,17 +46,9 @@ declare enum TestTreeNodeFlags {
|
|
|
47
46
|
Todo = 4
|
|
48
47
|
}
|
|
49
48
|
|
|
50
|
-
declare class WhenNode extends TestTreeNode {
|
|
51
|
-
actionNode: ts.CallExpression;
|
|
52
|
-
actionNameNode: ts.PropertyAccessExpression;
|
|
53
|
-
abilityDiagnostics: Set<ts.Diagnostic>;
|
|
54
|
-
target: ts.NodeArray<ts.Expression> | ts.NodeArray<ts.TypeNode>;
|
|
55
|
-
constructor(compiler: typeof ts, brand: TestTreeNodeBrand, node: ts.CallExpression, parent: TestTree | TestTreeNode, flags: TestTreeNodeFlags, actionNode: ts.CallExpression, actionNameNode: ts.PropertyAccessExpression);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
49
|
declare class TestTreeNode {
|
|
59
50
|
brand: TestTreeNodeBrand;
|
|
60
|
-
children: Array<TestTreeNode | ExpectNode
|
|
51
|
+
children: Array<TestTreeNode | ExpectNode>;
|
|
61
52
|
diagnostics: Set<ts.Diagnostic>;
|
|
62
53
|
flags: TestTreeNodeFlags;
|
|
63
54
|
name: string;
|
|
@@ -79,7 +70,7 @@ declare class ExpectNode extends TestTreeNode {
|
|
|
79
70
|
}
|
|
80
71
|
|
|
81
72
|
declare class TestTree {
|
|
82
|
-
children: Array<TestTreeNode | ExpectNode
|
|
73
|
+
children: Array<TestTreeNode | ExpectNode>;
|
|
83
74
|
diagnostics: Set<ts.Diagnostic>;
|
|
84
75
|
hasOnly: boolean;
|
|
85
76
|
sourceFile: ts.SourceFile;
|
|
@@ -95,7 +86,6 @@ declare class DiagnosticOrigin {
|
|
|
95
86
|
constructor(start: number, end: number, sourceFile: ts.SourceFile | JsonSourceFile, assertionNode?: ExpectNode);
|
|
96
87
|
static fromAssertion(assertionNode: ExpectNode): DiagnosticOrigin;
|
|
97
88
|
static fromNode(node: ts.Node, assertionNode?: ExpectNode): DiagnosticOrigin;
|
|
98
|
-
static fromNodes(nodes: ts.NodeArray<ts.Node>, assertionNode?: ExpectNode): DiagnosticOrigin;
|
|
99
89
|
}
|
|
100
90
|
|
|
101
91
|
declare class Diagnostic {
|
|
@@ -451,9 +441,6 @@ declare class SuppressedResult {
|
|
|
451
441
|
constructor(suppressed: SuppressedError);
|
|
452
442
|
}
|
|
453
443
|
|
|
454
|
-
interface EventHandler {
|
|
455
|
-
on: (event: Event) => void;
|
|
456
|
-
}
|
|
457
444
|
type Event = ["config:error", {
|
|
458
445
|
diagnostics: Array<Diagnostic>;
|
|
459
446
|
}] | ["select:error", {
|
|
@@ -490,7 +477,7 @@ type Event = ["config:error", {
|
|
|
490
477
|
}] | ["collect:error", {
|
|
491
478
|
diagnostics: Array<Diagnostic>;
|
|
492
479
|
}] | ["collect:node", {
|
|
493
|
-
node: TestTreeNode | ExpectNode
|
|
480
|
+
node: TestTreeNode | ExpectNode;
|
|
494
481
|
}] | ["collect:end", {
|
|
495
482
|
tree: TestTree;
|
|
496
483
|
}] | ["describe:start", {
|
|
@@ -536,6 +523,9 @@ type Event = ["config:error", {
|
|
|
536
523
|
}] | ["watch:error", {
|
|
537
524
|
diagnostics: Array<Diagnostic>;
|
|
538
525
|
}];
|
|
526
|
+
interface EventHandler {
|
|
527
|
+
on: (event: Event) => void;
|
|
528
|
+
}
|
|
539
529
|
|
|
540
530
|
declare class EventEmitter {
|
|
541
531
|
#private;
|
package/dist/api.js
CHANGED
|
@@ -112,9 +112,6 @@ class DiagnosticOrigin {
|
|
|
112
112
|
static fromNode(node, assertionNode) {
|
|
113
113
|
return new DiagnosticOrigin(node.getStart(), node.getEnd(), node.getSourceFile(), assertionNode);
|
|
114
114
|
}
|
|
115
|
-
static fromNodes(nodes, assertionNode) {
|
|
116
|
-
return new DiagnosticOrigin(nodes.pos, nodes.end, nodes[0].getSourceFile(), assertionNode);
|
|
117
|
-
}
|
|
118
115
|
}
|
|
119
116
|
|
|
120
117
|
function diagnosticBelongsToNode(diagnostic, node) {
|
|
@@ -776,9 +773,7 @@ class ManifestService {
|
|
|
776
773
|
return manifest;
|
|
777
774
|
}
|
|
778
775
|
async #persist(manifest) {
|
|
779
|
-
|
|
780
|
-
await fs.mkdir(this.#storePath, { recursive: true });
|
|
781
|
-
}
|
|
776
|
+
await fs.mkdir(this.#storePath, { recursive: true });
|
|
782
777
|
await fs.writeFile(this.#manifestFilePath, manifest.stringify());
|
|
783
778
|
}
|
|
784
779
|
async prune() {
|
|
@@ -851,28 +846,8 @@ class PackageService {
|
|
|
851
846
|
this.#fetcher = fetcher;
|
|
852
847
|
this.#lockService = lockService;
|
|
853
848
|
}
|
|
854
|
-
async #add(packagePath, resource, diagnostic) {
|
|
855
|
-
const request = new Request(resource.tarball, { integrity: resource.integrity });
|
|
856
|
-
const response = await this.#fetcher.get(request, diagnostic);
|
|
857
|
-
if (response?.body != null) {
|
|
858
|
-
const targetPath = `${packagePath}-${Math.random().toString(32).slice(2)}`;
|
|
859
|
-
const stream = response.body.pipeThrough(new DecompressionStream("gzip"));
|
|
860
|
-
const tarReader = new TarReader(stream);
|
|
861
|
-
for await (const file of tarReader.extract()) {
|
|
862
|
-
const filePath = Path.join(targetPath, file.name.replace(/^package\//, ""));
|
|
863
|
-
const directoryPath = Path.dirname(filePath);
|
|
864
|
-
if (!existsSync(directoryPath)) {
|
|
865
|
-
await fs.mkdir(directoryPath, { recursive: true });
|
|
866
|
-
}
|
|
867
|
-
await fs.writeFile(filePath, file.content);
|
|
868
|
-
}
|
|
869
|
-
await fs.rename(targetPath, packagePath);
|
|
870
|
-
return packagePath;
|
|
871
|
-
}
|
|
872
|
-
return;
|
|
873
|
-
}
|
|
874
849
|
async ensure(packageVersion, manifest) {
|
|
875
|
-
|
|
850
|
+
const packagePath = Path.join(this.#storePath, `typescript@${packageVersion}`);
|
|
876
851
|
const diagnostic = Diagnostic.error(StoreDiagnosticText.failedToFetchPackage(packageVersion));
|
|
877
852
|
if (await this.#lockService.isLocked(packagePath, diagnostic)) {
|
|
878
853
|
return;
|
|
@@ -881,18 +856,29 @@ class PackageService {
|
|
|
881
856
|
return packagePath;
|
|
882
857
|
}
|
|
883
858
|
EventEmitter.dispatch(["store:adds", { packagePath, packageVersion }]);
|
|
884
|
-
const resource = manifest
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
859
|
+
const resource = manifest.packages[packageVersion];
|
|
860
|
+
const lock = this.#lockService.getLock(packagePath);
|
|
861
|
+
try {
|
|
862
|
+
const request = new Request(resource.tarball, { integrity: resource.integrity });
|
|
863
|
+
const response = await this.#fetcher.get(request, diagnostic);
|
|
864
|
+
if (!response?.body) {
|
|
865
|
+
return;
|
|
889
866
|
}
|
|
890
|
-
|
|
891
|
-
|
|
867
|
+
const targetPath = await fs.mkdtemp(`${packagePath}-`);
|
|
868
|
+
const stream = response.body.pipeThrough(new DecompressionStream("gzip"));
|
|
869
|
+
const tarReader = new TarReader(stream);
|
|
870
|
+
for await (const file of tarReader.extract()) {
|
|
871
|
+
const filePath = Path.join(targetPath, file.name.replace(/^package\//, ""));
|
|
872
|
+
const directoryPath = Path.dirname(filePath);
|
|
873
|
+
await fs.mkdir(directoryPath, { recursive: true });
|
|
874
|
+
await fs.writeFile(filePath, file.content);
|
|
892
875
|
}
|
|
876
|
+
await fs.rename(targetPath, packagePath);
|
|
893
877
|
return packagePath;
|
|
894
878
|
}
|
|
895
|
-
|
|
879
|
+
finally {
|
|
880
|
+
lock.release();
|
|
881
|
+
}
|
|
896
882
|
}
|
|
897
883
|
}
|
|
898
884
|
|
|
@@ -912,17 +898,20 @@ class Store {
|
|
|
912
898
|
Store.#packageService = new PackageService(Store.#storePath, Store.#fetcher, Store.#lockService);
|
|
913
899
|
Store.#manifestService = new ManifestService(Store.#storePath, Store.#npmRegistry, Store.#fetcher);
|
|
914
900
|
}
|
|
915
|
-
static async
|
|
916
|
-
if (tag === "*" && environmentOptions.typescriptModule != null) {
|
|
917
|
-
return;
|
|
918
|
-
}
|
|
901
|
+
static async #ensure(tag) {
|
|
919
902
|
await Store.open();
|
|
920
903
|
const version = Store.manifest?.resolve(tag);
|
|
921
904
|
if (!version) {
|
|
922
905
|
Store.#onDiagnostics(Diagnostic.error(StoreDiagnosticText.cannotAddTypeScriptPackage(tag)));
|
|
923
906
|
return;
|
|
924
907
|
}
|
|
925
|
-
await Store.#packageService.ensure(version, Store.manifest);
|
|
908
|
+
return await Store.#packageService.ensure(version, Store.manifest);
|
|
909
|
+
}
|
|
910
|
+
static async fetch(tag) {
|
|
911
|
+
if (tag === "*" && environmentOptions.typescriptModule != null) {
|
|
912
|
+
return;
|
|
913
|
+
}
|
|
914
|
+
await Store.#ensure(tag);
|
|
926
915
|
}
|
|
927
916
|
static async load(tag) {
|
|
928
917
|
let resolvedModule;
|
|
@@ -930,13 +919,7 @@ class Store {
|
|
|
930
919
|
resolvedModule = environmentOptions.typescriptModule;
|
|
931
920
|
}
|
|
932
921
|
else {
|
|
933
|
-
await Store
|
|
934
|
-
const version = Store.manifest?.resolve(tag);
|
|
935
|
-
if (!version) {
|
|
936
|
-
Store.#onDiagnostics(Diagnostic.error(StoreDiagnosticText.cannotAddTypeScriptPackage(tag)));
|
|
937
|
-
return;
|
|
938
|
-
}
|
|
939
|
-
const packagePath = await Store.#packageService.ensure(version, Store.manifest);
|
|
922
|
+
const packagePath = await Store.#ensure(tag);
|
|
940
923
|
if (packagePath != null) {
|
|
941
924
|
resolvedModule = pathToFileURL(`${packagePath}/lib/typescript.js`).toString();
|
|
942
925
|
}
|
|
@@ -950,7 +933,9 @@ class Store {
|
|
|
950
933
|
EventEmitter.dispatch(["store:error", { diagnostics: [diagnostic] }]);
|
|
951
934
|
}
|
|
952
935
|
static async open() {
|
|
953
|
-
Store.
|
|
936
|
+
if (Store.manifest != null) {
|
|
937
|
+
return;
|
|
938
|
+
}
|
|
954
939
|
Store.manifest = await Store.#manifestService.open();
|
|
955
940
|
if (Store.manifest != null) {
|
|
956
941
|
Store.#supportedTags = [...Object.keys(Store.manifest.resolutions), ...Store.manifest.versions];
|
|
@@ -1040,7 +1025,7 @@ class Options {
|
|
|
1040
1025
|
},
|
|
1041
1026
|
{
|
|
1042
1027
|
brand: "boolean",
|
|
1043
|
-
description: "Check errors
|
|
1028
|
+
description: "Check errors suppressed by '@ts-expect-error' directives.",
|
|
1044
1029
|
group: 4,
|
|
1045
1030
|
name: "checkSuppressedErrors",
|
|
1046
1031
|
},
|
|
@@ -1092,13 +1077,13 @@ class Options {
|
|
|
1092
1077
|
},
|
|
1093
1078
|
{
|
|
1094
1079
|
brand: "string",
|
|
1095
|
-
description: "Only run tests with matching name.",
|
|
1080
|
+
description: "Only run tests with a matching name.",
|
|
1096
1081
|
group: 2,
|
|
1097
1082
|
name: "only",
|
|
1098
1083
|
},
|
|
1099
1084
|
{
|
|
1100
1085
|
brand: "true",
|
|
1101
|
-
description: "Remove all
|
|
1086
|
+
description: "Remove all fetched versions of the 'typescript' package and exit.",
|
|
1102
1087
|
group: 2,
|
|
1103
1088
|
name: "prune",
|
|
1104
1089
|
},
|
|
@@ -1132,7 +1117,7 @@ class Options {
|
|
|
1132
1117
|
},
|
|
1133
1118
|
{
|
|
1134
1119
|
brand: "string",
|
|
1135
|
-
description: "The path to
|
|
1120
|
+
description: "The path to the root directory of a test project.",
|
|
1136
1121
|
group: 2,
|
|
1137
1122
|
name: "root",
|
|
1138
1123
|
},
|
|
@@ -1144,13 +1129,13 @@ class Options {
|
|
|
1144
1129
|
},
|
|
1145
1130
|
{
|
|
1146
1131
|
brand: "string",
|
|
1147
|
-
description: "Skip tests with matching name.",
|
|
1132
|
+
description: "Skip tests with a matching name.",
|
|
1148
1133
|
group: 2,
|
|
1149
1134
|
name: "skip",
|
|
1150
1135
|
},
|
|
1151
1136
|
{
|
|
1152
1137
|
brand: "range",
|
|
1153
|
-
description: "The range of
|
|
1138
|
+
description: "The TypeScript version or range of versions to test against.",
|
|
1154
1139
|
group: 2 | 4 | 8,
|
|
1155
1140
|
name: "target",
|
|
1156
1141
|
},
|
|
@@ -3350,15 +3335,8 @@ class AbilityLayer {
|
|
|
3350
3335
|
this.#editor = editor;
|
|
3351
3336
|
}
|
|
3352
3337
|
#belongsToNode(node, diagnostic) {
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
return (diagnosticBelongsToNode(diagnostic, node.matcherNode) ||
|
|
3356
|
-
diagnosticBelongsToNode(diagnostic, node.source));
|
|
3357
|
-
case "when":
|
|
3358
|
-
return (diagnosticBelongsToNode(diagnostic, node.actionNode) &&
|
|
3359
|
-
!diagnosticBelongsToNode(diagnostic, node.target));
|
|
3360
|
-
}
|
|
3361
|
-
return false;
|
|
3338
|
+
return (diagnosticBelongsToNode(diagnostic, node.matcherNode) ||
|
|
3339
|
+
diagnosticBelongsToNode(diagnostic, node.source));
|
|
3362
3340
|
}
|
|
3363
3341
|
close(diagnostics) {
|
|
3364
3342
|
if (diagnostics != null && this.#nodes.length > 0) {
|
|
@@ -3534,22 +3512,6 @@ class AbilityLayer {
|
|
|
3534
3512
|
}
|
|
3535
3513
|
}
|
|
3536
3514
|
}
|
|
3537
|
-
visitWhen(when) {
|
|
3538
|
-
const whenStart = when.node.getStart();
|
|
3539
|
-
const whenExpressionEnd = when.node.expression.getEnd();
|
|
3540
|
-
const whenEnd = when.node.getEnd();
|
|
3541
|
-
const actionNameEnd = when.actionNameNode.getEnd();
|
|
3542
|
-
switch (when.actionNameNode.name.text) {
|
|
3543
|
-
case "isCalledWith":
|
|
3544
|
-
this.#nodes.push(when);
|
|
3545
|
-
this.#editor.eraseTrailingComma(when.target);
|
|
3546
|
-
this.#editor.replaceRanges([
|
|
3547
|
-
[whenStart, whenExpressionEnd, nodeIsChildOfExpressionStatement(this.#compiler, when.actionNode) ? ";" : ""],
|
|
3548
|
-
[whenEnd, actionNameEnd],
|
|
3549
|
-
]);
|
|
3550
|
-
break;
|
|
3551
|
-
}
|
|
3552
|
-
}
|
|
3553
3515
|
}
|
|
3554
3516
|
|
|
3555
3517
|
class SourceTextEditor {
|
|
@@ -3721,14 +3683,7 @@ class Layers {
|
|
|
3721
3683
|
this.#suppressedLayer.close(this.#suppressedDiagnostics);
|
|
3722
3684
|
}
|
|
3723
3685
|
visit(node) {
|
|
3724
|
-
|
|
3725
|
-
case "expect":
|
|
3726
|
-
this.#abilityLayer.visitExpect(node);
|
|
3727
|
-
break;
|
|
3728
|
-
case "when":
|
|
3729
|
-
this.#abilityLayer.visitWhen(node);
|
|
3730
|
-
break;
|
|
3731
|
-
}
|
|
3686
|
+
this.#abilityLayer.visitExpect(node);
|
|
3732
3687
|
}
|
|
3733
3688
|
}
|
|
3734
3689
|
|
|
@@ -3880,8 +3835,6 @@ class IdentifierLookup {
|
|
|
3880
3835
|
return { brand: "test", flags };
|
|
3881
3836
|
case "expect":
|
|
3882
3837
|
return { brand: "expect", flags };
|
|
3883
|
-
case "when":
|
|
3884
|
-
return { brand: "when", flags };
|
|
3885
3838
|
}
|
|
3886
3839
|
return;
|
|
3887
3840
|
}
|
|
@@ -3899,25 +3852,6 @@ class TestTree {
|
|
|
3899
3852
|
}
|
|
3900
3853
|
}
|
|
3901
3854
|
|
|
3902
|
-
class WhenNode extends TestTreeNode {
|
|
3903
|
-
actionNode;
|
|
3904
|
-
actionNameNode;
|
|
3905
|
-
abilityDiagnostics = new Set();
|
|
3906
|
-
target;
|
|
3907
|
-
constructor(compiler, brand, node, parent, flags, actionNode, actionNameNode) {
|
|
3908
|
-
super(compiler, brand, node, parent, flags);
|
|
3909
|
-
this.actionNode = actionNode;
|
|
3910
|
-
this.actionNameNode = actionNameNode;
|
|
3911
|
-
this.target = this.node.typeArguments ?? this.node.arguments;
|
|
3912
|
-
for (const diagnostic of parent.diagnostics) {
|
|
3913
|
-
if (diagnosticBelongsToNode(diagnostic, node)) {
|
|
3914
|
-
this.diagnostics.add(diagnostic);
|
|
3915
|
-
parent.diagnostics.delete(diagnostic);
|
|
3916
|
-
}
|
|
3917
|
-
}
|
|
3918
|
-
}
|
|
3919
|
-
}
|
|
3920
|
-
|
|
3921
3855
|
class CollectService {
|
|
3922
3856
|
#layers;
|
|
3923
3857
|
#compiler;
|
|
@@ -3977,38 +3911,6 @@ class CollectService {
|
|
|
3977
3911
|
this.#onNode(expectNode, parent, testTree);
|
|
3978
3912
|
return;
|
|
3979
3913
|
}
|
|
3980
|
-
if (meta.brand === "when") {
|
|
3981
|
-
const actionNameNode = this.#getChainedNode(node);
|
|
3982
|
-
if (!actionNameNode) {
|
|
3983
|
-
const text = "The final element in the chain must be an action.";
|
|
3984
|
-
const origin = DiagnosticOrigin.fromNode(node);
|
|
3985
|
-
this.#onDiagnostics(Diagnostic.error(text, origin));
|
|
3986
|
-
return;
|
|
3987
|
-
}
|
|
3988
|
-
const actionNode = this.#getActionNode(actionNameNode);
|
|
3989
|
-
if (!actionNode) {
|
|
3990
|
-
const text = "The action must be called with an argument.";
|
|
3991
|
-
const origin = DiagnosticOrigin.fromNode(actionNameNode);
|
|
3992
|
-
this.#onDiagnostics(Diagnostic.error(text, origin));
|
|
3993
|
-
return;
|
|
3994
|
-
}
|
|
3995
|
-
this.#compiler.forEachChild(actionNode, (node) => {
|
|
3996
|
-
if (this.#compiler.isCallExpression(node)) {
|
|
3997
|
-
const meta = this.#identifierLookup.resolveTestTreeNodeMeta(node);
|
|
3998
|
-
if (meta?.brand === "describe" ||
|
|
3999
|
-
meta?.brand === "it" ||
|
|
4000
|
-
meta?.brand === "test") {
|
|
4001
|
-
const text = CollectDiagnosticText.cannotBeNestedWithin(meta.brand, "when");
|
|
4002
|
-
const origin = DiagnosticOrigin.fromNode(node);
|
|
4003
|
-
this.#onDiagnostics(Diagnostic.error(text, origin));
|
|
4004
|
-
}
|
|
4005
|
-
}
|
|
4006
|
-
});
|
|
4007
|
-
const whenNode = new WhenNode(this.#compiler, meta.brand, node, parent, meta.flags, actionNode, actionNameNode);
|
|
4008
|
-
this.#layers.visit(whenNode);
|
|
4009
|
-
this.#onNode(whenNode, parent, testTree);
|
|
4010
|
-
return;
|
|
4011
|
-
}
|
|
4012
3914
|
}
|
|
4013
3915
|
}
|
|
4014
3916
|
if (this.#compiler.isImportDeclaration(node)) {
|
|
@@ -4050,7 +3952,6 @@ class CollectService {
|
|
|
4050
3952
|
}
|
|
4051
3953
|
break;
|
|
4052
3954
|
case "expect":
|
|
4053
|
-
case "when":
|
|
4054
3955
|
if (parent.brand === "describe") {
|
|
4055
3956
|
return false;
|
|
4056
3957
|
}
|
|
@@ -4079,12 +3980,6 @@ class CollectService {
|
|
|
4079
3980
|
}
|
|
4080
3981
|
return;
|
|
4081
3982
|
}
|
|
4082
|
-
#getActionNode(node) {
|
|
4083
|
-
if (this.#compiler.isCallExpression(node.parent)) {
|
|
4084
|
-
return node.parent;
|
|
4085
|
-
}
|
|
4086
|
-
return;
|
|
4087
|
-
}
|
|
4088
3983
|
#onDiagnostics(diagnostic) {
|
|
4089
3984
|
EventEmitter.dispatch(["collect:error", { diagnostics: [diagnostic] }]);
|
|
4090
3985
|
}
|
|
@@ -4103,7 +3998,6 @@ var TestTreeNodeBrand;
|
|
|
4103
3998
|
TestTreeNodeBrand["Test"] = "test";
|
|
4104
3999
|
TestTreeNodeBrand["It"] = "it";
|
|
4105
4000
|
TestTreeNodeBrand["Expect"] = "expect";
|
|
4106
|
-
TestTreeNodeBrand["When"] = "when";
|
|
4107
4001
|
})(TestTreeNodeBrand || (TestTreeNodeBrand = {}));
|
|
4108
4002
|
|
|
4109
4003
|
var TestTreeNodeFlags;
|
|
@@ -4117,7 +4011,7 @@ var TestTreeNodeFlags;
|
|
|
4117
4011
|
class ProjectService {
|
|
4118
4012
|
#compiler;
|
|
4119
4013
|
#host;
|
|
4120
|
-
#lastSeenProject = "";
|
|
4014
|
+
#lastSeenProject = "none";
|
|
4121
4015
|
#projectConfig;
|
|
4122
4016
|
#resolvedConfig;
|
|
4123
4017
|
#seenProjects = new Set();
|
|
@@ -4182,7 +4076,6 @@ class ProjectService {
|
|
|
4182
4076
|
noUncheckedIndexedAccess: true,
|
|
4183
4077
|
resolveJsonModule: true,
|
|
4184
4078
|
strict: true,
|
|
4185
|
-
verbatimModuleSyntax: true,
|
|
4186
4079
|
target: this.#compiler.ScriptTarget.ESNext,
|
|
4187
4080
|
};
|
|
4188
4081
|
if (Version.isSatisfiedWith(this.#compiler.version, "5.6")) {
|
|
@@ -4226,7 +4119,7 @@ class ProjectService {
|
|
|
4226
4119
|
if (Options.isJsonString(specifier)) {
|
|
4227
4120
|
return {
|
|
4228
4121
|
kind: 3,
|
|
4229
|
-
specifier: Path.resolve(this.#resolvedConfig.rootPath, `${
|
|
4122
|
+
specifier: Path.resolve(this.#resolvedConfig.rootPath, `${Date.now().toString(36)}.tsconfig.json`),
|
|
4230
4123
|
};
|
|
4231
4124
|
}
|
|
4232
4125
|
return { kind: 2, specifier };
|
|
@@ -5797,63 +5690,6 @@ class Reject {
|
|
|
5797
5690
|
}
|
|
5798
5691
|
}
|
|
5799
5692
|
|
|
5800
|
-
class WhenDiagnosticText {
|
|
5801
|
-
static actionIsNotSupported(actionNameText) {
|
|
5802
|
-
return `The '.${actionNameText}()' action is not supported.`;
|
|
5803
|
-
}
|
|
5804
|
-
}
|
|
5805
|
-
|
|
5806
|
-
class WhenService {
|
|
5807
|
-
#compiler;
|
|
5808
|
-
#onDiagnostics;
|
|
5809
|
-
#reject;
|
|
5810
|
-
constructor(compiler, reject, onDiagnostics) {
|
|
5811
|
-
this.#compiler = compiler;
|
|
5812
|
-
this.#reject = reject;
|
|
5813
|
-
this.#onDiagnostics = onDiagnostics;
|
|
5814
|
-
}
|
|
5815
|
-
action(when) {
|
|
5816
|
-
if (!argumentIsProvided(this.#compiler, "target", when.target[0], when.node.expression, this.#onDiagnostics) ||
|
|
5817
|
-
this.#reject.argumentType([["target", when.target[0]]], this.#onDiagnostics)) {
|
|
5818
|
-
return;
|
|
5819
|
-
}
|
|
5820
|
-
const actionNameText = when.actionNameNode.name.getText();
|
|
5821
|
-
switch (actionNameText) {
|
|
5822
|
-
case "isCalledWith":
|
|
5823
|
-
break;
|
|
5824
|
-
default:
|
|
5825
|
-
this.#onActionIsNotSupported(actionNameText, when, this.#onDiagnostics);
|
|
5826
|
-
return;
|
|
5827
|
-
}
|
|
5828
|
-
if (when.abilityDiagnostics.size > 0) {
|
|
5829
|
-
const diagnostics = [];
|
|
5830
|
-
for (const diagnostic of when.abilityDiagnostics) {
|
|
5831
|
-
if (isDiagnosticWithLocation(diagnostic)) {
|
|
5832
|
-
const text = getDiagnosticMessageText(diagnostic);
|
|
5833
|
-
let origin;
|
|
5834
|
-
if (isDiagnosticWithLocation(diagnostic) && diagnosticBelongsToNode(diagnostic, when.node)) {
|
|
5835
|
-
origin = DiagnosticOrigin.fromNodes(when.target);
|
|
5836
|
-
}
|
|
5837
|
-
else {
|
|
5838
|
-
origin = new DiagnosticOrigin(diagnostic.start, getTextSpanEnd(diagnostic), when.node.getSourceFile());
|
|
5839
|
-
}
|
|
5840
|
-
let related;
|
|
5841
|
-
if (diagnostic.relatedInformation != null) {
|
|
5842
|
-
related = Diagnostic.fromDiagnostics(diagnostic.relatedInformation);
|
|
5843
|
-
}
|
|
5844
|
-
diagnostics.push(Diagnostic.error(text, origin).add({ related }));
|
|
5845
|
-
}
|
|
5846
|
-
}
|
|
5847
|
-
this.#onDiagnostics(diagnostics);
|
|
5848
|
-
}
|
|
5849
|
-
}
|
|
5850
|
-
#onActionIsNotSupported(actionNameText, when, onDiagnostics) {
|
|
5851
|
-
const text = WhenDiagnosticText.actionIsNotSupported(actionNameText);
|
|
5852
|
-
const origin = DiagnosticOrigin.fromNode(when.actionNameNode.name);
|
|
5853
|
-
onDiagnostics([Diagnostic.error(text, origin)]);
|
|
5854
|
-
}
|
|
5855
|
-
}
|
|
5856
|
-
|
|
5857
5693
|
class FixmeDiagnosticText {
|
|
5858
5694
|
static considerRemoving() {
|
|
5859
5695
|
return "Consider removing the '// @tstyche fixme' directive.";
|
|
@@ -5920,7 +5756,6 @@ class TestTreeWalker {
|
|
|
5920
5756
|
#onFileDiagnostics;
|
|
5921
5757
|
#position;
|
|
5922
5758
|
#resolvedConfig;
|
|
5923
|
-
#whenService;
|
|
5924
5759
|
constructor(compiler, program, resolvedConfig, onFileDiagnostics, options) {
|
|
5925
5760
|
this.#compiler = compiler;
|
|
5926
5761
|
this.#resolvedConfig = resolvedConfig;
|
|
@@ -5930,7 +5765,6 @@ class TestTreeWalker {
|
|
|
5930
5765
|
this.#position = options.position;
|
|
5931
5766
|
const reject = new Reject(compiler, program, resolvedConfig);
|
|
5932
5767
|
this.#expectService = new ExpectService(compiler, program, reject);
|
|
5933
|
-
this.#whenService = new WhenService(compiler, reject, onFileDiagnostics);
|
|
5934
5768
|
}
|
|
5935
5769
|
async #resolveRunMode(flags, node) {
|
|
5936
5770
|
const ifDirective = Directive.getDirectiveRange(this.#compiler, node, "if");
|
|
@@ -5975,9 +5809,6 @@ class TestTreeWalker {
|
|
|
5975
5809
|
case "expect":
|
|
5976
5810
|
await this.#visitExpect(node, runModeFlags, parentResult);
|
|
5977
5811
|
break;
|
|
5978
|
-
case "when":
|
|
5979
|
-
this.#visitWhen(node);
|
|
5980
|
-
break;
|
|
5981
5812
|
}
|
|
5982
5813
|
if (fixmeDirective) {
|
|
5983
5814
|
FixmeService.end(fixmeDirective, node, this.#onFileDiagnostics);
|
|
@@ -6079,9 +5910,6 @@ class TestTreeWalker {
|
|
|
6079
5910
|
EventEmitter.dispatch(["test:fail", { result: testResult }]);
|
|
6080
5911
|
}
|
|
6081
5912
|
}
|
|
6082
|
-
#visitWhen(when) {
|
|
6083
|
-
this.#whenService.action(when);
|
|
6084
|
-
}
|
|
6085
5913
|
}
|
|
6086
5914
|
|
|
6087
5915
|
class FileRunner {
|
|
@@ -6170,7 +5998,7 @@ class FileRunner {
|
|
|
6170
5998
|
class Runner {
|
|
6171
5999
|
#eventEmitter = new EventEmitter();
|
|
6172
6000
|
#resolvedConfig;
|
|
6173
|
-
static version = "7.
|
|
6001
|
+
static version = "7.1.0";
|
|
6174
6002
|
constructor(resolvedConfig) {
|
|
6175
6003
|
this.#resolvedConfig = resolvedConfig;
|
|
6176
6004
|
}
|
package/dist/index.cjs
CHANGED
package/dist/index.d.cts
CHANGED
|
@@ -100,7 +100,7 @@ interface Matchers {
|
|
|
100
100
|
/**
|
|
101
101
|
* Checks if the type raises an error.
|
|
102
102
|
*
|
|
103
|
-
* @deprecated This
|
|
103
|
+
* @deprecated This API is planned to be removed. For a replacement, see https://tstyche.org/guides/expect-errors.
|
|
104
104
|
*/
|
|
105
105
|
toRaiseError: (...target: Array<string | number | RegExp>) => void;
|
|
106
106
|
}
|
|
@@ -183,23 +183,6 @@ interface Test {
|
|
|
183
183
|
todo: (name: string, callback?: () => void | Promise<void>) => void;
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
-
interface Actions {
|
|
187
|
-
/**
|
|
188
|
-
* Calls the given function with the provided arguments.
|
|
189
|
-
*/
|
|
190
|
-
isCalledWith: (...args: Array<unknown>) => void;
|
|
191
|
-
}
|
|
192
|
-
interface When {
|
|
193
|
-
/**
|
|
194
|
-
* Creates a test plan.
|
|
195
|
-
*/
|
|
196
|
-
<T>(): Actions;
|
|
197
|
-
/**
|
|
198
|
-
* Creates a test plan.
|
|
199
|
-
*/
|
|
200
|
-
(target: unknown): Actions;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
186
|
/**
|
|
204
187
|
* The fill-in type. Useful to fill in the required type arguments of generic types.
|
|
205
188
|
*/
|
|
@@ -228,10 +211,6 @@ declare const it: Test;
|
|
|
228
211
|
* Defines a single test.
|
|
229
212
|
*/
|
|
230
213
|
declare const test: Test;
|
|
231
|
-
/**
|
|
232
|
-
* Creates a test plan.
|
|
233
|
-
*/
|
|
234
|
-
declare const when: When;
|
|
235
214
|
|
|
236
|
-
export { describe, expect, it, omit, pick, test
|
|
215
|
+
export { describe, expect, it, omit, pick, test };
|
|
237
216
|
export type { _ };
|
package/dist/index.d.ts
CHANGED
|
@@ -100,7 +100,7 @@ interface Matchers {
|
|
|
100
100
|
/**
|
|
101
101
|
* Checks if the type raises an error.
|
|
102
102
|
*
|
|
103
|
-
* @deprecated This
|
|
103
|
+
* @deprecated This API is planned to be removed. For a replacement, see https://tstyche.org/guides/expect-errors.
|
|
104
104
|
*/
|
|
105
105
|
toRaiseError: (...target: Array<string | number | RegExp>) => void;
|
|
106
106
|
}
|
|
@@ -183,23 +183,6 @@ interface Test {
|
|
|
183
183
|
todo: (name: string, callback?: () => void | Promise<void>) => void;
|
|
184
184
|
}
|
|
185
185
|
|
|
186
|
-
interface Actions {
|
|
187
|
-
/**
|
|
188
|
-
* Calls the given function with the provided arguments.
|
|
189
|
-
*/
|
|
190
|
-
isCalledWith: (...args: Array<unknown>) => void;
|
|
191
|
-
}
|
|
192
|
-
interface When {
|
|
193
|
-
/**
|
|
194
|
-
* Creates a test plan.
|
|
195
|
-
*/
|
|
196
|
-
<T>(): Actions;
|
|
197
|
-
/**
|
|
198
|
-
* Creates a test plan.
|
|
199
|
-
*/
|
|
200
|
-
(target: unknown): Actions;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
186
|
/**
|
|
204
187
|
* The fill-in type. Useful to fill in the required type arguments of generic types.
|
|
205
188
|
*/
|
|
@@ -228,10 +211,6 @@ declare const it: Test;
|
|
|
228
211
|
* Defines a single test.
|
|
229
212
|
*/
|
|
230
213
|
declare const test: Test;
|
|
231
|
-
/**
|
|
232
|
-
* Creates a test plan.
|
|
233
|
-
*/
|
|
234
|
-
declare const when: When;
|
|
235
214
|
|
|
236
|
-
export { describe, expect, it, omit, pick, test
|
|
215
|
+
export { describe, expect, it, omit, pick, test };
|
|
237
216
|
export type { _ };
|
package/dist/index.js
CHANGED
|
@@ -9,4 +9,4 @@ const noopChain = new Proxy(noop, {
|
|
|
9
9
|
},
|
|
10
10
|
});
|
|
11
11
|
|
|
12
|
-
export { noopChain as describe, noopChain as expect, noopChain as it, noop as omit, noop as pick, noopChain as test
|
|
12
|
+
export { noopChain as describe, noopChain as expect, noopChain as it, noop as omit, noop as pick, noopChain as test };
|
package/package.json
CHANGED
package/schemas/config.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"type": "boolean"
|
|
9
9
|
},
|
|
10
10
|
"checkSuppressedErrors": {
|
|
11
|
-
"description": "Check errors
|
|
11
|
+
"description": "Check errors suppressed by '@ts-expect-error' directives.",
|
|
12
12
|
"default": true,
|
|
13
13
|
"type": "boolean"
|
|
14
14
|
},
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
}
|
|
58
58
|
},
|
|
59
59
|
"target": {
|
|
60
|
-
"description": "The range of
|
|
60
|
+
"description": "The TypeScript version or range of versions to test against.",
|
|
61
61
|
"default": "*",
|
|
62
62
|
"type": "string"
|
|
63
63
|
},
|