tstyche 5.0.0-beta.1 → 5.0.0-beta.3

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.
@@ -218,11 +218,11 @@ declare const describe: Describe;
218
218
  /**
219
219
  * Defines a single test.
220
220
  */
221
- declare const test: Test;
221
+ declare const it: Test;
222
222
  /**
223
223
  * Defines a single test.
224
224
  */
225
- declare const it: Test;
225
+ declare const test: Test;
226
226
  interface Actions {
227
227
  /**
228
228
  * Calls the given function with the provided arguments.
@@ -218,11 +218,11 @@ declare const describe: Describe;
218
218
  /**
219
219
  * Defines a single test.
220
220
  */
221
- declare const test: Test;
221
+ declare const it: Test;
222
222
  /**
223
223
  * Defines a single test.
224
224
  */
225
- declare const it: Test;
225
+ declare const test: Test;
226
226
  interface Actions {
227
227
  /**
228
228
  * Calls the given function with the provided arguments.
package/build/index.d.cts CHANGED
@@ -222,11 +222,11 @@ declare const describe: Describe;
222
222
  /**
223
223
  * Defines a single test.
224
224
  */
225
- declare const test: Test;
225
+ declare const it: Test;
226
226
  /**
227
227
  * Defines a single test.
228
228
  */
229
- declare const it: Test;
229
+ declare const test: Test;
230
230
  interface Actions {
231
231
  /**
232
232
  * Calls the given function with the provided arguments.
package/build/index.d.ts CHANGED
@@ -222,11 +222,11 @@ declare const describe: Describe;
222
222
  /**
223
223
  * Defines a single test.
224
224
  */
225
- declare const test: Test;
225
+ declare const it: Test;
226
226
  /**
227
227
  * Defines a single test.
228
228
  */
229
- declare const it: Test;
229
+ declare const test: Test;
230
230
  interface Actions {
231
231
  /**
232
232
  * Calls the given function with the provided arguments.
@@ -9,9 +9,9 @@ declare enum CancellationReason {
9
9
 
10
10
  declare class CancellationToken {
11
11
  #private;
12
- get isCancellationRequested(): boolean;
13
- get reason(): CancellationReason | undefined;
14
12
  cancel(reason: CancellationReason): void;
13
+ isCancellationRequested(): boolean;
14
+ getReason(): CancellationReason | undefined;
15
15
  reset(): void;
16
16
  }
17
17
 
@@ -35,6 +35,7 @@ interface SuppressedError {
35
35
  declare enum TestTreeNodeBrand {
36
36
  Describe = "describe",
37
37
  Test = "test",
38
+ It = "it",
38
39
  Expect = "expect",
39
40
  When = "when"
40
41
  }
@@ -614,6 +615,8 @@ declare class OutputService {
614
615
  static writeWarning(element: ScribblerJsx.Element | Array<ScribblerJsx.Element>): void;
615
616
  }
616
617
 
618
+ declare function prologueText(runnerVersion: string, rootPath: string): ScribblerJsx.Element;
619
+
617
620
  interface SummaryTextOptions {
618
621
  targetCounts: ResultCounts;
619
622
  fileCounts: ResultCounts;
@@ -730,5 +733,5 @@ declare class Version {
730
733
  static isSatisfiedWith(source: string, target: string): boolean;
731
734
  }
732
735
 
733
- export { BaseReporter, CancellationReason, CancellationToken, Cli, Color, Config, ConfigDiagnosticText, DescribeResult, Diagnostic, DiagnosticCategory, DiagnosticOrigin, Directive, EventEmitter, ExpectResult, FileLocation, FileResult, Line, ListReporter, OptionBrand, OptionGroup, Options, OutputService, Path, PluginService, ProjectResult, Result, ResultStatus, Runner, Scribbler, ScribblerJsx, Select, SelectDiagnosticText, SetupReporter, Store, SummaryReporter, SuppressedResult, TargetResult, TestResult, Text, Version, WatchReporter, addsPackageText, defaultOptions, describeNameText, diagnosticBelongsToNode, diagnosticText, environmentOptions, fileStatusText, fileViewText, formattedText, getDiagnosticMessageText, getTextSpanEnd, helpText, isDiagnosticWithLocation, summaryText, testNameText, usesCompilerText, waitingForFileChangesText, watchUsageText };
736
+ export { BaseReporter, CancellationReason, CancellationToken, Cli, Color, Config, ConfigDiagnosticText, DescribeResult, Diagnostic, DiagnosticCategory, DiagnosticOrigin, Directive, EventEmitter, ExpectResult, FileLocation, FileResult, Line, ListReporter, OptionBrand, OptionGroup, Options, OutputService, Path, PluginService, ProjectResult, Result, ResultStatus, Runner, Scribbler, ScribblerJsx, Select, SelectDiagnosticText, SetupReporter, Store, SummaryReporter, SuppressedResult, TargetResult, TestResult, Text, Version, WatchReporter, addsPackageText, defaultOptions, describeNameText, diagnosticBelongsToNode, diagnosticText, environmentOptions, fileStatusText, fileViewText, formattedText, getDiagnosticMessageText, getTextSpanEnd, helpText, isDiagnosticWithLocation, prologueText, summaryText, testNameText, usesCompilerText, waitingForFileChangesText, watchUsageText };
734
737
  export type { AssertionCounts, AssertionResultStatus, CodeFrameOptions, CommandLineOptions, ConfigFileOptions, DiagnosticsHandler, DirectiveRange, EnvironmentOptions, Event, EventHandler, FileCounts, FileResultStatus, InlineConfig, ItemDefinition, OptionDefinition, Plugin, Reporter, ReporterEvent, ResolvedConfig, ResultCounts, ResultTiming, ScribblerOptions, SelectHookContext, SuppressedCounts, SuppressedResultStatus, TargetCounts, TargetResultStatus, TestCounts, TestResultStatus, TextRange };
package/build/tstyche.js CHANGED
@@ -968,7 +968,7 @@ class Store {
968
968
  modulePath = Path.resolve(modulePath, "../tsserverlibrary.js");
969
969
  }
970
970
  const sourceText = await fs.readFile(modulePath, { encoding: "utf8" });
971
- const toExpose = ["isApplicableIndexType", "isTypeIdenticalTo"];
971
+ const toExpose = ["isTypeIdenticalTo"];
972
972
  const modifiedSourceText = sourceText.replace("return checker;", `return { ...checker, ${toExpose.join(", ")} };`);
973
973
  const compiledWrapper = vm.compileFunction(modifiedSourceText, ["exports", "require", "module", "__filename", "__dirname"], { filename: modulePath });
974
974
  compiledWrapper(exports, createRequire(modulePath), module, modulePath, Path.dirname(modulePath));
@@ -2491,6 +2491,10 @@ class OutputService {
2491
2491
  }
2492
2492
  }
2493
2493
 
2494
+ function prologueText(runnerVersion, rootPath) {
2495
+ return (jsx(Text, { children: [jsx(Line, { children: [jsx(Text, { color: "90", children: "····" }), " TSTyche ", runnerVersion, jsx(Text, { color: "90", children: [" at ", rootPath] })] }), jsx(Line, {})] }));
2496
+ }
2497
+
2494
2498
  function RowText({ label, text }) {
2495
2499
  return (jsx(Line, { children: [`${label}:`.padEnd(12), text] }));
2496
2500
  }
@@ -2595,9 +2599,6 @@ class FileView {
2595
2599
  #indent = 0;
2596
2600
  #lines = [];
2597
2601
  #messages = [];
2598
- get hasErrors() {
2599
- return this.#messages.length > 0;
2600
- }
2601
2602
  addMessage(message) {
2602
2603
  this.#messages.push(message);
2603
2604
  }
@@ -2620,7 +2621,10 @@ class FileView {
2620
2621
  return this.#messages;
2621
2622
  }
2622
2623
  getViewText(options) {
2623
- return fileViewText(this.#lines, options?.appendEmptyLine || this.hasErrors);
2624
+ return fileViewText(this.#lines, options?.appendEmptyLine || this.hasErrors());
2625
+ }
2626
+ hasErrors() {
2627
+ return this.#messages.length > 0;
2624
2628
  }
2625
2629
  }
2626
2630
 
@@ -2631,7 +2635,7 @@ class ListReporter extends BaseReporter {
2631
2635
  #hasReportedError = false;
2632
2636
  #hasReportedUses = false;
2633
2637
  #isFileViewExpanded = false;
2634
- get #isLastFile() {
2638
+ #isLastFile() {
2635
2639
  return this.#fileCount === 0;
2636
2640
  }
2637
2641
  on([event, payload]) {
@@ -2684,8 +2688,8 @@ class ListReporter extends BaseReporter {
2684
2688
  OutputService.eraseLastLine();
2685
2689
  }
2686
2690
  OutputService.writeMessage(fileStatusText(payload.result.status, payload.result.file));
2687
- OutputService.writeMessage(this.#fileView.getViewText({ appendEmptyLine: this.#isLastFile }));
2688
- if (this.#fileView.hasErrors) {
2691
+ OutputService.writeMessage(this.#fileView.getViewText({ appendEmptyLine: this.#isLastFile() }));
2692
+ if (this.#fileView.hasErrors()) {
2689
2693
  OutputService.writeError(this.#fileView.getMessages());
2690
2694
  this.#hasReportedError = true;
2691
2695
  }
@@ -2829,18 +2833,18 @@ var CancellationReason;
2829
2833
  class CancellationToken {
2830
2834
  #isCancelled = false;
2831
2835
  #reason;
2832
- get isCancellationRequested() {
2833
- return this.#isCancelled;
2834
- }
2835
- get reason() {
2836
- return this.#reason;
2837
- }
2838
2836
  cancel(reason) {
2839
2837
  if (!this.#isCancelled) {
2840
2838
  this.#isCancelled = true;
2841
2839
  this.#reason = reason;
2842
2840
  }
2843
2841
  }
2842
+ isCancellationRequested() {
2843
+ return this.#isCancelled;
2844
+ }
2845
+ getReason() {
2846
+ return this.#reason;
2847
+ }
2844
2848
  reset() {
2845
2849
  if (this.#isCancelled) {
2846
2850
  this.#isCancelled = false;
@@ -3225,7 +3229,7 @@ class WatchService {
3225
3229
  for (const watcher of this.#watchers) {
3226
3230
  watcher.watch();
3227
3231
  }
3228
- while (!cancellationToken.isCancellationRequested) {
3232
+ while (!cancellationToken.isCancellationRequested()) {
3229
3233
  const testFiles = await debounce.schedule();
3230
3234
  if (testFiles.length > 0) {
3231
3235
  yield testFiles;
@@ -3257,6 +3261,9 @@ function deepCompareKeys(a, b, keys) {
3257
3261
  }
3258
3262
  return true;
3259
3263
  }
3264
+ function nodeBelongsToArgumentList(compiler, node) {
3265
+ return compiler.isCallExpression(node.parent) && node.parent.arguments.some((argument) => argument === node);
3266
+ }
3260
3267
  function nodeIsChildOfExpressionStatement(compiler, node) {
3261
3268
  return compiler.isExpressionStatement(node.parent);
3262
3269
  }
@@ -3302,6 +3309,7 @@ class AbilityLayer {
3302
3309
  const expectExpressionEnd = expect.node.expression.getEnd();
3303
3310
  const expectEnd = expect.node.getEnd();
3304
3311
  const matcherNameEnd = expect.matcherNameNode.getEnd();
3312
+ const matcherNodeEnd = expect.matcherNode.getEnd();
3305
3313
  switch (expect.matcherNameNode.name.text) {
3306
3314
  case "toBeApplicable":
3307
3315
  this.#nodes.push(expect);
@@ -3310,30 +3318,102 @@ class AbilityLayer {
3310
3318
  [expectEnd, matcherNameEnd],
3311
3319
  ]);
3312
3320
  break;
3313
- case "toBeCallableWith":
3321
+ case "toBeCallableWith": {
3314
3322
  this.#nodes.push(expect);
3315
- this.#editor.eraseTrailingComma(expect.source);
3316
- this.#editor.replaceRanges([
3317
- [
3318
- expectStart,
3319
- expectExpressionEnd,
3320
- nodeIsChildOfExpressionStatement(this.#compiler, expect.matcherNode) ? ";" : "",
3321
- ],
3322
- [expectEnd, matcherNameEnd],
3323
- ]);
3323
+ const sourceNode = expect.source[0];
3324
+ if (!sourceNode) {
3325
+ return;
3326
+ }
3327
+ if (nodeBelongsToArgumentList(this.#compiler, sourceNode)) {
3328
+ this.#editor.eraseTrailingComma(expect.source);
3329
+ this.#editor.replaceRanges([
3330
+ [
3331
+ expectStart,
3332
+ expectExpressionEnd,
3333
+ nodeIsChildOfExpressionStatement(this.#compiler, expect.matcherNode) ? ";" : "",
3334
+ ],
3335
+ [expectEnd, matcherNameEnd],
3336
+ ]);
3337
+ }
3338
+ else {
3339
+ const sourceText = sourceNode.getFullText();
3340
+ this.#editor.replaceRanges([
3341
+ [
3342
+ expectStart,
3343
+ matcherNameEnd,
3344
+ nodeIsChildOfExpressionStatement(this.#compiler, expect.matcherNode)
3345
+ ? `;(undefined as any as ${sourceText})`
3346
+ : `(undefined as any as ${sourceText})`,
3347
+ ],
3348
+ ]);
3349
+ }
3324
3350
  break;
3325
- case "toBeConstructableWith":
3351
+ }
3352
+ case "toBeConstructableWith": {
3326
3353
  this.#nodes.push(expect);
3327
- this.#editor.eraseTrailingComma(expect.source);
3328
- this.#editor.replaceRanges([
3329
- [
3330
- expectStart,
3331
- expectExpressionEnd,
3332
- nodeIsChildOfExpressionStatement(this.#compiler, expect.matcherNode) ? "; new" : "new",
3333
- ],
3334
- [expectEnd, matcherNameEnd],
3335
- ]);
3354
+ const sourceNode = expect.source[0];
3355
+ if (!sourceNode) {
3356
+ return;
3357
+ }
3358
+ if (nodeBelongsToArgumentList(this.#compiler, sourceNode)) {
3359
+ this.#editor.eraseTrailingComma(expect.source);
3360
+ this.#editor.replaceRanges([
3361
+ [
3362
+ expectStart,
3363
+ expectExpressionEnd,
3364
+ nodeIsChildOfExpressionStatement(this.#compiler, expect.matcherNode) ? "; new" : "new",
3365
+ ],
3366
+ [expectEnd, matcherNameEnd],
3367
+ ]);
3368
+ }
3369
+ else {
3370
+ const sourceText = sourceNode.getFullText();
3371
+ this.#editor.replaceRanges([
3372
+ [
3373
+ expectStart,
3374
+ matcherNameEnd,
3375
+ nodeIsChildOfExpressionStatement(this.#compiler, expect.matcherNode)
3376
+ ? `;new (undefined as any as ${sourceText})`
3377
+ : `new (undefined as any as ${sourceText})`,
3378
+ ],
3379
+ ]);
3380
+ }
3381
+ break;
3382
+ }
3383
+ case "toHaveProperty": {
3384
+ this.#nodes.push(expect);
3385
+ const sourceNode = expect.source[0];
3386
+ const targetNode = expect.target?.[0];
3387
+ if (!sourceNode || !targetNode) {
3388
+ return;
3389
+ }
3390
+ const sourceText = sourceNode.getFullText();
3391
+ const targetText = targetNode.getFullText();
3392
+ if (nodeBelongsToArgumentList(this.#compiler, sourceNode)) {
3393
+ this.#editor.eraseTrailingComma(expect.source);
3394
+ this.#editor.replaceRanges([
3395
+ [
3396
+ expectStart,
3397
+ matcherNodeEnd,
3398
+ nodeIsChildOfExpressionStatement(this.#compiler, expect.matcherNode)
3399
+ ? `;(${sourceText})[${targetText}]`
3400
+ : `(${sourceText})[${targetText}]`,
3401
+ ],
3402
+ ]);
3403
+ }
3404
+ else {
3405
+ this.#editor.replaceRanges([
3406
+ [
3407
+ expectStart,
3408
+ matcherNodeEnd,
3409
+ nodeIsChildOfExpressionStatement(this.#compiler, expect.matcherNode)
3410
+ ? `;(undefined as any as ${sourceText})[${targetText}]`
3411
+ : `(undefined as any as ${sourceText})[${targetText}]`,
3412
+ ],
3413
+ ]);
3414
+ }
3336
3415
  break;
3416
+ }
3337
3417
  }
3338
3418
  }
3339
3419
  visitWhen(when) {
@@ -3675,14 +3755,15 @@ class IdentifierLookup {
3675
3755
  }
3676
3756
  switch (identifier) {
3677
3757
  case "describe":
3678
- return { brand: "describe", flags, identifier };
3758
+ return { brand: "describe", flags };
3679
3759
  case "it":
3760
+ return { brand: "it", flags };
3680
3761
  case "test":
3681
- return { brand: "test", flags, identifier };
3762
+ return { brand: "test", flags };
3682
3763
  case "expect":
3683
- return { brand: "expect", flags, identifier };
3764
+ return { brand: "expect", flags };
3684
3765
  case "when":
3685
- return { brand: "when", flags, identifier };
3766
+ return { brand: "when", flags };
3686
3767
  }
3687
3768
  return;
3688
3769
  }
@@ -3735,7 +3816,9 @@ class CollectService {
3735
3816
  if (!this.#checkNode(node, meta, parent)) {
3736
3817
  return;
3737
3818
  }
3738
- if (meta.brand === "describe" || meta.brand === "test") {
3819
+ if (meta.brand === "describe" ||
3820
+ meta.brand === "it" ||
3821
+ meta.brand === "test") {
3739
3822
  const testTreeNode = new TestTreeNode(this.#compiler, meta.brand, node, parent, meta.flags);
3740
3823
  this.#compiler.forEachChild(node, (node) => {
3741
3824
  this.#collectTestTreeNodes(node, testTreeNode, testTree);
@@ -3746,15 +3829,24 @@ class CollectService {
3746
3829
  if (meta.brand === "expect") {
3747
3830
  const modifierNode = this.#getChainedNode(node, "type");
3748
3831
  if (!modifierNode) {
3832
+ const text = "'expect()' must be followed by the '.type' modifier.";
3833
+ const origin = DiagnosticOrigin.fromNode(node);
3834
+ this.#onDiagnostics(Diagnostic.error(text, origin));
3749
3835
  return;
3750
3836
  }
3751
3837
  const notNode = this.#getChainedNode(modifierNode, "not");
3752
3838
  const matcherNameNode = this.#getChainedNode(notNode ?? modifierNode);
3753
3839
  if (!matcherNameNode) {
3840
+ const text = "The final element in the chain must be a matcher.";
3841
+ const origin = DiagnosticOrigin.fromNode(notNode ?? modifierNode);
3842
+ this.#onDiagnostics(Diagnostic.error(text, origin));
3754
3843
  return;
3755
3844
  }
3756
3845
  const matcherNode = this.#getMatcherNode(matcherNameNode);
3757
3846
  if (!matcherNode) {
3847
+ const text = "The matcher must be called with an argument.";
3848
+ const origin = DiagnosticOrigin.fromNode(matcherNameNode);
3849
+ this.#onDiagnostics(Diagnostic.error(text, origin));
3758
3850
  return;
3759
3851
  }
3760
3852
  const expectNode = new ExpectNode(this.#compiler, meta.brand, node, parent, meta.flags, matcherNode, matcherNameNode, modifierNode, notNode);
@@ -3768,17 +3860,25 @@ class CollectService {
3768
3860
  if (meta.brand === "when") {
3769
3861
  const actionNameNode = this.#getChainedNode(node);
3770
3862
  if (!actionNameNode) {
3863
+ const text = "The final element in the chain must be an action.";
3864
+ const origin = DiagnosticOrigin.fromNode(node);
3865
+ this.#onDiagnostics(Diagnostic.error(text, origin));
3771
3866
  return;
3772
3867
  }
3773
3868
  const actionNode = this.#getActionNode(actionNameNode);
3774
3869
  if (!actionNode) {
3870
+ const text = "The action must be called with an argument.";
3871
+ const origin = DiagnosticOrigin.fromNode(actionNameNode);
3872
+ this.#onDiagnostics(Diagnostic.error(text, origin));
3775
3873
  return;
3776
3874
  }
3777
3875
  this.#compiler.forEachChild(actionNode, (node) => {
3778
3876
  if (this.#compiler.isCallExpression(node)) {
3779
3877
  const meta = this.#identifierLookup.resolveTestTreeNodeMeta(node);
3780
- if (meta?.brand === "describe" || meta?.brand === "test") {
3781
- const text = CollectDiagnosticText.cannotBeNestedWithin(meta.identifier, "when");
3878
+ if (meta?.brand === "describe" ||
3879
+ meta?.brand === "it" ||
3880
+ meta?.brand === "test") {
3881
+ const text = CollectDiagnosticText.cannotBeNestedWithin(meta.brand, "when");
3782
3882
  const origin = DiagnosticOrigin.fromNode(node);
3783
3883
  this.#onDiagnostics(Diagnostic.error(text, origin));
3784
3884
  }
@@ -3811,7 +3911,7 @@ class CollectService {
3811
3911
  }
3812
3912
  #checkNode(node, meta, parent) {
3813
3913
  if ("brand" in parent && !this.#isNodeAllowed(meta, parent)) {
3814
- const text = CollectDiagnosticText.cannotBeNestedWithin(meta.identifier, parent.node.expression.getText());
3914
+ const text = CollectDiagnosticText.cannotBeNestedWithin(meta.brand, parent.brand);
3815
3915
  const origin = DiagnosticOrigin.fromNode(node);
3816
3916
  this.#onDiagnostics(Diagnostic.error(text, origin));
3817
3917
  return false;
@@ -3821,8 +3921,11 @@ class CollectService {
3821
3921
  #isNodeAllowed(meta, parent) {
3822
3922
  switch (meta.brand) {
3823
3923
  case "describe":
3924
+ case "it":
3824
3925
  case "test":
3825
- if (parent.brand === "test" || parent.brand === "expect") {
3926
+ if (parent.brand === "it" ||
3927
+ parent.brand === "test" ||
3928
+ parent.brand === "expect") {
3826
3929
  return false;
3827
3930
  }
3828
3931
  break;
@@ -3874,14 +3977,11 @@ class CollectService {
3874
3977
  }
3875
3978
  }
3876
3979
 
3877
- function nodeBelongsToArgumentList(compiler, node) {
3878
- return compiler.isCallExpression(node.parent) && node.parent.arguments.some((argument) => argument === node);
3879
- }
3880
-
3881
3980
  var TestTreeNodeBrand;
3882
3981
  (function (TestTreeNodeBrand) {
3883
3982
  TestTreeNodeBrand["Describe"] = "describe";
3884
3983
  TestTreeNodeBrand["Test"] = "test";
3984
+ TestTreeNodeBrand["It"] = "it";
3885
3985
  TestTreeNodeBrand["Expect"] = "expect";
3886
3986
  TestTreeNodeBrand["When"] = "when";
3887
3987
  })(TestTreeNodeBrand || (TestTreeNodeBrand = {}));
@@ -4261,19 +4361,6 @@ class MatchWorker {
4261
4361
  this.typeChecker = typeChecker;
4262
4362
  this.assertionNode = assertionNode;
4263
4363
  }
4264
- checkHasApplicableIndexType(sourceNode, targetNode) {
4265
- const sourceType = this.getType(sourceNode);
4266
- const targetType = this.getType(targetNode);
4267
- return this.typeChecker
4268
- .getIndexInfosOfType(sourceType)
4269
- .some(({ keyType }) => this.typeChecker.isApplicableIndexType(targetType, keyType));
4270
- }
4271
- checkHasProperty(sourceNode, propertyNameText) {
4272
- const sourceType = this.getType(sourceNode);
4273
- return sourceType
4274
- .getProperties()
4275
- .some((property) => this.#compiler.unescapeLeadingUnderscores(property.escapedName) === propertyNameText);
4276
- }
4277
4364
  checkIsAssignableTo(sourceNode, targetNode) {
4278
4365
  return this.#checkIsRelatedTo(sourceNode, targetNode, "assignable");
4279
4366
  }
@@ -4702,19 +4789,8 @@ class ToBeCallableWith extends AbilityMatcherBase {
4702
4789
  explainText = ExpectDiagnosticText.isCallable;
4703
4790
  explainNotText = ExpectDiagnosticText.isNotCallable;
4704
4791
  match(matchWorker, sourceNode, targetNodes, onDiagnostics) {
4705
- let type;
4706
- if (this.compiler.isCallExpression(sourceNode)) {
4707
- type = matchWorker.typeChecker.getResolvedSignature(sourceNode)?.getReturnType();
4708
- }
4709
- if (this.compiler.isArrowFunction(sourceNode) ||
4710
- this.compiler.isFunctionDeclaration(sourceNode) ||
4711
- this.compiler.isFunctionExpression(sourceNode) ||
4712
- this.compiler.isExpressionWithTypeArguments(sourceNode) ||
4713
- this.compiler.isIdentifier(sourceNode) ||
4714
- this.compiler.isPropertyAccessExpression(sourceNode)) {
4715
- type = matchWorker.getType(sourceNode);
4716
- }
4717
- if (!type || type.getCallSignatures().length === 0) {
4792
+ const sourceType = matchWorker.getType(sourceNode);
4793
+ if (sourceType.getCallSignatures().length === 0) {
4718
4794
  const text = [];
4719
4795
  if (nodeBelongsToArgumentList(this.compiler, sourceNode)) {
4720
4796
  text.push(ExpectDiagnosticText.argumentMustBe("source", "a callable expression"));
@@ -4722,7 +4798,7 @@ class ToBeCallableWith extends AbilityMatcherBase {
4722
4798
  else {
4723
4799
  text.push(ExpectDiagnosticText.typeArgumentMustBe("Source", "a callable type"));
4724
4800
  }
4725
- if (type != null && type.getConstructSignatures().length > 0) {
4801
+ if (sourceType.getConstructSignatures().length > 0) {
4726
4802
  text.push(ExpectDiagnosticText.didYouMeanToUse("the '.toBeConstructableWith()' matcher"));
4727
4803
  }
4728
4804
  const origin = DiagnosticOrigin.fromNode(sourceNode);
@@ -4740,16 +4816,8 @@ class ToBeConstructableWith extends AbilityMatcherBase {
4740
4816
  explainText = ExpectDiagnosticText.isConstructable;
4741
4817
  explainNotText = ExpectDiagnosticText.isNotConstructable;
4742
4818
  match(matchWorker, sourceNode, targetNodes, onDiagnostics) {
4743
- let type;
4744
- if (this.compiler.isCallExpression(sourceNode)) {
4745
- type = matchWorker.typeChecker.getResolvedSignature(sourceNode)?.getReturnType();
4746
- }
4747
- if (this.compiler.isExpressionWithTypeArguments(sourceNode) ||
4748
- this.compiler.isIdentifier(sourceNode) ||
4749
- this.compiler.isPropertyAccessExpression(sourceNode)) {
4750
- type = matchWorker.getType(sourceNode);
4751
- }
4752
- if (!type || type.getConstructSignatures().length === 0) {
4819
+ const sourceType = matchWorker.getType(sourceNode);
4820
+ if (sourceType.getConstructSignatures().length === 0) {
4753
4821
  const text = [];
4754
4822
  if (nodeBelongsToArgumentList(this.compiler, sourceNode)) {
4755
4823
  text.push(ExpectDiagnosticText.argumentMustBe("source", "a constructable expression"));
@@ -4757,7 +4825,7 @@ class ToBeConstructableWith extends AbilityMatcherBase {
4757
4825
  else {
4758
4826
  text.push(ExpectDiagnosticText.typeArgumentMustBe("Source", "a constructable type"));
4759
4827
  }
4760
- if (type != null && type.getCallSignatures().length > 0) {
4828
+ if (sourceType.getCallSignatures().length > 0) {
4761
4829
  text.push(ExpectDiagnosticText.didYouMeanToUse("the '.toBeCallableWith()' matcher"));
4762
4830
  }
4763
4831
  const origin = DiagnosticOrigin.fromNode(sourceNode);
@@ -4804,14 +4872,7 @@ class ToHaveProperty {
4804
4872
  diagnostics.push(Diagnostic.error(text, origin));
4805
4873
  }
4806
4874
  const targetType = matchWorker.getType(targetNode);
4807
- let propertyNameText = "";
4808
- if (isStringOrNumberLiteralType(this.#compiler, targetType)) {
4809
- propertyNameText = targetType.value.toString();
4810
- }
4811
- else if (isUniqueSymbolType(this.#compiler, targetType)) {
4812
- propertyNameText = this.#compiler.unescapeLeadingUnderscores(targetType.escapedName);
4813
- }
4814
- else {
4875
+ if (!(isStringOrNumberLiteralType(this.#compiler, targetType) || isUniqueSymbolType(this.#compiler, targetType))) {
4815
4876
  const expectedText = "of type 'string | number | symbol'";
4816
4877
  const text = ExpectDiagnosticText.argumentMustBe("key", expectedText);
4817
4878
  const origin = DiagnosticOrigin.fromNode(targetNode);
@@ -4821,11 +4882,9 @@ class ToHaveProperty {
4821
4882
  onDiagnostics(diagnostics);
4822
4883
  return;
4823
4884
  }
4824
- const isMatch = matchWorker.checkHasProperty(sourceNode, propertyNameText) ||
4825
- matchWorker.checkHasApplicableIndexType(sourceNode, targetNode);
4826
4885
  return {
4827
4886
  explain: () => this.#explain(matchWorker, sourceNode, targetNode),
4828
- isMatch,
4887
+ isMatch: matchWorker.assertionNode.abilityDiagnostics.size === 0,
4829
4888
  };
4830
4889
  }
4831
4890
  }
@@ -5153,8 +5212,7 @@ class FixmeService {
5153
5212
  FixmeService.#range = FixmeService.#range?.previous;
5154
5213
  }
5155
5214
  if (isFail === false) {
5156
- const targetText = owner.node.expression.getText();
5157
- const text = [FixmeDiagnosticText.wasSupposedToFail(targetText), FixmeDiagnosticText.considerRemoving()];
5215
+ const text = [FixmeDiagnosticText.wasSupposedToFail(owner.brand), FixmeDiagnosticText.considerRemoving()];
5158
5216
  const origin = new DiagnosticOrigin(directive.namespace.start, directive.directive.end, directive.sourceFile);
5159
5217
  onFileDiagnostics([Diagnostic.error(text, origin)]);
5160
5218
  }
@@ -5206,17 +5264,18 @@ class TestTreeWalker {
5206
5264
  }
5207
5265
  async visit(nodes, runModeFlags, parentResult) {
5208
5266
  for (const node of nodes) {
5209
- if (this.#cancellationToken?.isCancellationRequested) {
5267
+ if (this.#cancellationToken?.isCancellationRequested()) {
5210
5268
  break;
5211
5269
  }
5212
5270
  const fixmeDirective = Directive.getDirectiveRange(this.#compiler, node, "fixme");
5213
5271
  if (fixmeDirective) {
5214
- FixmeService.start(fixmeDirective, node);
5272
+ await FixmeService.start(fixmeDirective, node);
5215
5273
  }
5216
5274
  switch (node.brand) {
5217
5275
  case "describe":
5218
5276
  await this.#visitDescribe(node, runModeFlags, parentResult);
5219
5277
  break;
5278
+ case "it":
5220
5279
  case "test":
5221
5280
  await this.#visitTest(node, runModeFlags, parentResult);
5222
5281
  break;
@@ -5348,7 +5407,7 @@ class FileRunner {
5348
5407
  EventEmitter.dispatch(["file:error", { diagnostics, result }]);
5349
5408
  }
5350
5409
  async run(file, cancellationToken) {
5351
- if (cancellationToken.isCancellationRequested) {
5410
+ if (cancellationToken.isCancellationRequested()) {
5352
5411
  return;
5353
5412
  }
5354
5413
  this.#projectService.openFile(file.path);
@@ -5423,7 +5482,7 @@ class FileRunner {
5423
5482
  class Runner {
5424
5483
  #eventEmitter = new EventEmitter();
5425
5484
  #resolvedConfig;
5426
- static version = "5.0.0-beta.1";
5485
+ static version = "5.0.0-beta.3";
5427
5486
  constructor(resolvedConfig) {
5428
5487
  this.#resolvedConfig = resolvedConfig;
5429
5488
  }
@@ -5461,6 +5520,9 @@ class Runner {
5461
5520
  }
5462
5521
  }
5463
5522
  async run(files, cancellationToken = new CancellationToken()) {
5523
+ if (!this.#resolvedConfig.watch) {
5524
+ OutputService.writeMessage(prologueText(Runner.version, this.#resolvedConfig.rootPath));
5525
+ }
5464
5526
  const fileLocations = files.map((file) => (file instanceof FileLocation ? file : new FileLocation(file)));
5465
5527
  this.#addHandlers(cancellationToken);
5466
5528
  await this.#addReporters();
@@ -5487,7 +5549,7 @@ class Runner {
5487
5549
  EventEmitter.dispatch(["target:end", { result: targetResult }]);
5488
5550
  }
5489
5551
  EventEmitter.dispatch(["run:end", { result }]);
5490
- if (cancellationToken.reason === "failFast") {
5552
+ if (cancellationToken.getReason() === "failFast") {
5491
5553
  cancellationToken.reset();
5492
5554
  }
5493
5555
  }
@@ -5533,11 +5595,11 @@ class Cli {
5533
5595
  return;
5534
5596
  }
5535
5597
  const { commandLineOptions, pathMatch } = await Config.parseCommandLine(commandLine);
5536
- if (cancellationToken.isCancellationRequested) {
5598
+ if (cancellationToken.isCancellationRequested()) {
5537
5599
  return;
5538
5600
  }
5539
5601
  do {
5540
- if (cancellationToken.reason === "configChange") {
5602
+ if (cancellationToken.getReason() === "configChange") {
5541
5603
  cancellationToken.reset();
5542
5604
  exitCodeHandler.resetCode();
5543
5605
  OutputService.clearTerminal();
@@ -5551,7 +5613,7 @@ class Cli {
5551
5613
  commandLineOptions,
5552
5614
  pathMatch,
5553
5615
  });
5554
- if (cancellationToken.isCancellationRequested) {
5616
+ if (cancellationToken.isCancellationRequested()) {
5555
5617
  if (commandLine.includes("--watch")) {
5556
5618
  await this.#waitForChangedFiles(resolvedConfig, cancellationToken);
5557
5619
  }
@@ -5592,7 +5654,7 @@ class Cli {
5592
5654
  const runner = new Runner(resolvedConfig);
5593
5655
  await runner.run(testFiles, cancellationToken);
5594
5656
  PluginService.removeHandlers();
5595
- } while (cancellationToken.reason === "configChange");
5657
+ } while (cancellationToken.getReason() === "configChange");
5596
5658
  this.#eventEmitter.removeHandlers();
5597
5659
  }
5598
5660
  #waitForChangedFiles(resolvedConfig, cancellationToken) {
@@ -5623,4 +5685,4 @@ class Cli {
5623
5685
  }
5624
5686
  }
5625
5687
 
5626
- export { BaseReporter, CancellationReason, CancellationToken, Cli, Color, Config, ConfigDiagnosticText, DescribeResult, Diagnostic, DiagnosticCategory, DiagnosticOrigin, Directive, EventEmitter, ExpectResult, FileLocation, FileResult, Line, ListReporter, OptionBrand, OptionGroup, Options, OutputService, Path, PluginService, ProjectResult, Result, ResultStatus, Runner, Scribbler, Select, SelectDiagnosticText, SetupReporter, Store, SummaryReporter, SuppressedResult, TargetResult, TestResult, Text, Version, WatchReporter, addsPackageText, defaultOptions, describeNameText, diagnosticBelongsToNode, diagnosticText, environmentOptions, fileStatusText, fileViewText, formattedText, getDiagnosticMessageText, getTextSpanEnd, helpText, isDiagnosticWithLocation, summaryText, testNameText, usesCompilerText, waitingForFileChangesText, watchUsageText };
5688
+ export { BaseReporter, CancellationReason, CancellationToken, Cli, Color, Config, ConfigDiagnosticText, DescribeResult, Diagnostic, DiagnosticCategory, DiagnosticOrigin, Directive, EventEmitter, ExpectResult, FileLocation, FileResult, Line, ListReporter, OptionBrand, OptionGroup, Options, OutputService, Path, PluginService, ProjectResult, Result, ResultStatus, Runner, Scribbler, Select, SelectDiagnosticText, SetupReporter, Store, SummaryReporter, SuppressedResult, TargetResult, TestResult, Text, Version, WatchReporter, addsPackageText, defaultOptions, describeNameText, diagnosticBelongsToNode, diagnosticText, environmentOptions, fileStatusText, fileViewText, formattedText, getDiagnosticMessageText, getTextSpanEnd, helpText, isDiagnosticWithLocation, prologueText, summaryText, testNameText, usesCompilerText, waitingForFileChangesText, watchUsageText };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tstyche",
3
- "version": "5.0.0-beta.1",
3
+ "version": "5.0.0-beta.3",
4
4
  "description": "Everything You Need for Type Testing.",
5
5
  "keywords": [
6
6
  "typescript",