tstyche 7.0.0-beta.3 → 7.0.0-beta.5

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/dist/api.d.ts CHANGED
@@ -15,13 +15,9 @@ declare class CancellationToken {
15
15
  reset(): void;
16
16
  }
17
17
 
18
- interface CliOptions {
19
- noErrorExitCode?: boolean;
20
- }
21
18
  declare class Cli {
22
19
  #private;
23
- constructor(options?: CliOptions);
24
- run(commandLine: ReadonlyArray<string>, cancellationToken?: CancellationToken): Promise<void>;
20
+ run(commandLine: ReadonlyArray<string>, cancellationToken?: CancellationToken): Promise<number>;
25
21
  }
26
22
 
27
23
  declare enum DiagnosticCategory {
@@ -755,4 +751,4 @@ declare class Version {
755
751
  }
756
752
 
757
753
  export { BaseReporter, CancellationReason, CancellationToken, Cli, Color, Config, ConfigDiagnosticText, DescribeResult, Diagnostic, DiagnosticCategory, DiagnosticOrigin, Directive, DotReporter, EventEmitter, ExpectResult, FileLocation, FileResult, Line, ListReporter, OptionBrand, OptionGroup, Options, OutputService, Path, ProjectConfigKind, ProjectResult, Result, ResultStatus, Runner, Scribbler, ScribblerJsx, Select, SelectDiagnosticText, SetupReporter, Store, StreamController, SummaryReporter, SuppressedResult, TargetResult, TestResult, Text, Version, WatchReporter, addsText, defaultOptions, describeNameText, diagnosticBelongsToNode, diagnosticText, dotText, environmentOptions, fileStatusText, formattedText, getDiagnosticMessageText, getTextSpanEnd, helpText, isDiagnosticWithLocation, prologueText, summaryText, testNameText, usesText, waitingForFileChangesText, watchUsageText };
758
- export type { AssertionCounts, AssertionResultStatus, CliOptions, CodeFrameOptions, CommandLineOptions, ConfigFileOptions, DiagnosticsHandler, DirectiveRange, EnvironmentOptions, Event, EventHandler, FileCounts, FileResultStatus, InlineConfig, ItemDefinition, OptionDefinition, ProjectConfig, Reporter, ReporterEvent, ResolvedConfig, ResultCounts, ResultTiming, ScribblerOptions, SuppressedCounts, SuppressedResultStatus, TargetCounts, TargetResultStatus, TestCounts, TestResultStatus, TextRange, WriteStream };
754
+ export type { AssertionCounts, AssertionResultStatus, CodeFrameOptions, CommandLineOptions, ConfigFileOptions, DiagnosticsHandler, DirectiveRange, EnvironmentOptions, Event, EventHandler, FileCounts, FileResultStatus, InlineConfig, ItemDefinition, OptionDefinition, ProjectConfig, Reporter, ReporterEvent, ResolvedConfig, ResultCounts, ResultTiming, ScribblerOptions, SuppressedCounts, SuppressedResultStatus, TargetCounts, TargetResultStatus, TestCounts, TestResultStatus, TextRange, WriteStream };
package/dist/api.js CHANGED
@@ -56,25 +56,24 @@ class JsonNode {
56
56
  this.text = text;
57
57
  }
58
58
  getValue(options) {
59
- if (this.text == null) {
60
- return undefined;
61
- }
62
- if (/^['"]/.test(this.text)) {
63
- return this.text.slice(1, -1).replaceAll("\\", "");
64
- }
65
- if (options?.expectsIdentifier) {
66
- return this.text;
67
- }
68
- if (this.text === "true") {
69
- return true;
70
- }
71
- if (this.text === "false") {
72
- return false;
73
- }
74
- if (/^\d/.test(this.text)) {
75
- return Number.parseFloat(this.text);
59
+ if (this.text != null) {
60
+ if (/^['"]/.test(this.text)) {
61
+ return this.text.slice(1, -1).replaceAll("\\", "");
62
+ }
63
+ if (options?.expectsIdentifier) {
64
+ return this.text;
65
+ }
66
+ if (this.text === "true") {
67
+ return true;
68
+ }
69
+ if (this.text === "false") {
70
+ return false;
71
+ }
72
+ if (/^\d/.test(this.text)) {
73
+ return Number.parseFloat(this.text);
74
+ }
76
75
  }
77
- return undefined;
76
+ return;
78
77
  }
79
78
  }
80
79
 
@@ -730,7 +729,9 @@ class ManifestService {
730
729
  const versions = [];
731
730
  const packageMetadata = (await response.json());
732
731
  for (const [tag, meta] of Object.entries(packageMetadata.versions)) {
733
- if (!tag.includes("-") && Version.isSatisfiedWith(tag, "5.4.2")) {
732
+ if (!tag.includes("-") &&
733
+ Version.isSatisfiedWith(tag, "5.4") &&
734
+ !Version.isSatisfiedWith(tag, "7.0")) {
734
735
  versions.push(tag);
735
736
  packages[tag] = { integrity: meta.dist.integrity, tarball: meta.dist.tarball };
736
737
  }
@@ -752,6 +753,7 @@ class ManifestService {
752
753
  }
753
754
  }
754
755
  }
756
+ resolutions["latest"] = versions.findLast((version) => version.startsWith("6"));
755
757
  return new Manifest({ minorVersions, npmRegistry: this.#npmRegistry, packages, resolutions, versions });
756
758
  }
757
759
  async open(options) {
@@ -1795,22 +1797,23 @@ class CancellationHandler {
1795
1797
  }
1796
1798
 
1797
1799
  class ExitCodeHandler {
1800
+ #exitCode = 0;
1801
+ getExitCode() {
1802
+ return this.#exitCode;
1803
+ }
1798
1804
  on([event, payload]) {
1799
1805
  if (event === "run:start") {
1800
- this.resetCode();
1806
+ this.#exitCode = 0;
1801
1807
  return;
1802
1808
  }
1803
1809
  if ("diagnostics" in payload) {
1804
1810
  if (payload.diagnostics.some((diagnostic) => diagnostic.category === "error")) {
1805
- this.#setCode(1);
1811
+ this.#exitCode = 1;
1806
1812
  }
1807
1813
  }
1808
1814
  }
1809
- resetCode() {
1810
- this.#setCode(0);
1811
- }
1812
- #setCode(exitCode) {
1813
- process.exitCode = exitCode;
1815
+ reset() {
1816
+ this.#exitCode = 0;
1814
1817
  }
1815
1818
  }
1816
1819
 
@@ -4517,12 +4520,12 @@ class MatchWorker {
4517
4520
  this.typeChecker = program.getTypeChecker();
4518
4521
  this.assertionNode = assertionNode;
4519
4522
  }
4523
+ checkIsAssignableFrom(sourceNode, targetNode) {
4524
+ return this.#checkIsRelatedTo(targetNode, sourceNode);
4525
+ }
4520
4526
  checkIsAssignableTo(sourceNode, targetNode) {
4521
4527
  return this.#checkIsRelatedTo(sourceNode, targetNode);
4522
4528
  }
4523
- checkIsAssignableWith(sourceNode, targetNode) {
4524
- return this.#checkIsRelatedTo(targetNode, sourceNode);
4525
- }
4526
4529
  #checkIsRelatedTo(sourceNode, targetNode) {
4527
4530
  const sourceType = this.getType(sourceNode);
4528
4531
  const targetType = this.getType(targetNode);
@@ -4623,9 +4626,6 @@ class ToAcceptProps {
4623
4626
  if (!sourceProperty) {
4624
4627
  return false;
4625
4628
  }
4626
- if (this.#isOptionalProperty(targetProperty) && !this.#isOptionalProperty(sourceProperty)) {
4627
- return false;
4628
- }
4629
4629
  const targetPropertyType = this.#typeChecker.getTypeOfSymbol(targetProperty);
4630
4630
  const sourcePropertyType = this.#typeChecker.getTypeOfSymbol(sourceProperty);
4631
4631
  if (!this.#typeChecker.isTypeAssignableTo(targetPropertyType, sourcePropertyType)) {
@@ -4668,15 +4668,6 @@ class ToAcceptProps {
4668
4668
  diagnostics.push(diagnostic.extendWith(text, origin));
4669
4669
  continue;
4670
4670
  }
4671
- if (this.#isOptionalProperty(targetProperty) && !this.#isOptionalProperty(sourceProperty)) {
4672
- const text = [
4673
- ExpectDiagnosticText.isNotAssignableFrom(sourceTypeText, targetTypeText),
4674
- ExpectDiagnosticText.requiresProperty(sourceTypeText, targetPropertyName),
4675
- ];
4676
- const origin = matchWorker.resolveDiagnosticOrigin(targetProperty, targetNode);
4677
- diagnostics.push(diagnostic.extendWith(text, origin));
4678
- continue;
4679
- }
4680
4671
  const targetPropertyType = this.#typeChecker.getTypeOfSymbol(targetProperty);
4681
4672
  const sourcePropertyType = this.#typeChecker.getTypeOfSymbol(sourceProperty);
4682
4673
  if (!this.#typeChecker.isTypeAssignableTo(targetPropertyType, sourcePropertyType)) {
@@ -4744,9 +4735,7 @@ class ToAcceptProps {
4744
4735
  const targetType = matchWorker.getType(targetNode);
4745
4736
  if (!(targetType.flags & this.#compiler.TypeFlags.Object)) {
4746
4737
  const expectedText = "of an object type";
4747
- const text = nodeBelongsToArgumentList(this.#compiler, targetNode)
4748
- ? ExpectDiagnosticText.argumentMustBe("target", expectedText)
4749
- : ExpectDiagnosticText.typeArgumentMustBe("Target", expectedText);
4738
+ const text = ExpectDiagnosticText.argumentMustBe("props", expectedText);
4750
4739
  const origin = DiagnosticOrigin.fromNode(targetNode);
4751
4740
  diagnostics.push(Diagnostic.error(text, origin));
4752
4741
  }
@@ -5378,7 +5367,7 @@ class ToBeAssignableFrom extends RelationMatcherBase {
5378
5367
  match(matchWorker, sourceNode, targetNode) {
5379
5368
  return {
5380
5369
  explain: () => this.explain(matchWorker, sourceNode, targetNode),
5381
- isMatch: matchWorker.checkIsAssignableWith(sourceNode, targetNode),
5370
+ isMatch: matchWorker.checkIsAssignableFrom(sourceNode, targetNode),
5382
5371
  };
5383
5372
  }
5384
5373
  }
@@ -6176,7 +6165,7 @@ class FileRunner {
6176
6165
  class Runner {
6177
6166
  #eventEmitter = new EventEmitter();
6178
6167
  #resolvedConfig;
6179
- static version = "7.0.0-beta.3";
6168
+ static version = "7.0.0-beta.5";
6180
6169
  constructor(resolvedConfig) {
6181
6170
  this.#resolvedConfig = resolvedConfig;
6182
6171
  }
@@ -6275,15 +6264,20 @@ class CliDiagnosticText {
6275
6264
  class Cli {
6276
6265
  #deferredDiagnostics;
6277
6266
  #eventEmitter = new EventEmitter();
6278
- #noErrorExitCode;
6279
- constructor(options) {
6280
- this.#noErrorExitCode = options?.noErrorExitCode ?? false;
6281
- }
6282
6267
  async run(commandLine, cancellationToken = new CancellationToken()) {
6268
+ const exitCodeHandler = new ExitCodeHandler();
6269
+ this.#eventEmitter.addHandler(exitCodeHandler);
6270
+ await this.#run(commandLine, exitCodeHandler, cancellationToken);
6271
+ if (this.#deferredDiagnostics != null) {
6272
+ OutputService.writeBlankLine();
6273
+ OutputService.writeWarning(diagnosticText(this.#deferredDiagnostics));
6274
+ }
6275
+ this.#eventEmitter.removeHandlers();
6276
+ return exitCodeHandler.getExitCode();
6277
+ }
6278
+ async #run(commandLine, exitCodeHandler, cancellationToken) {
6283
6279
  const cancellationHandler = new CancellationHandler(cancellationToken, "configError");
6284
6280
  this.#eventEmitter.addHandler(cancellationHandler);
6285
- const exitCodeHandler = new ExitCodeHandler();
6286
- !this.#noErrorExitCode && this.#eventEmitter.addHandler(exitCodeHandler);
6287
6281
  const setupReporter = new SetupReporter();
6288
6282
  this.#eventEmitter.addReporter(setupReporter);
6289
6283
  if (commandLine.includes("--help")) {
@@ -6325,7 +6319,7 @@ class Cli {
6325
6319
  do {
6326
6320
  if (cancellationToken.getReason() === "configChange") {
6327
6321
  cancellationToken.reset();
6328
- exitCodeHandler.resetCode();
6322
+ exitCodeHandler.reset();
6329
6323
  OutputService.clearTerminal();
6330
6324
  this.#eventEmitter.addHandler(cancellationHandler);
6331
6325
  this.#eventEmitter.addReporter(setupReporter);
@@ -6367,11 +6361,6 @@ class Cli {
6367
6361
  const runner = new Runner(resolvedConfig);
6368
6362
  await runner.run(testFiles, cancellationToken);
6369
6363
  } while (cancellationToken.getReason() === "configChange");
6370
- if (this.#deferredDiagnostics != null) {
6371
- OutputService.writeBlankLine();
6372
- OutputService.writeWarning(diagnosticText(this.#deferredDiagnostics));
6373
- }
6374
- this.#eventEmitter.removeHandlers();
6375
6364
  }
6376
6365
  #waitForChangedFiles(resolvedConfig, cancellationToken) {
6377
6366
  return new Promise((resolve) => {
package/dist/bin.js CHANGED
@@ -3,4 +3,5 @@ import process from 'node:process';
3
3
  import { Cli } from './api.js';
4
4
 
5
5
  const cli = new Cli();
6
- await cli.run(process.argv.slice(2));
6
+ const commandLine = process.argv.slice(2);
7
+ process.exitCode = await cli.run(commandLine);
package/dist/index.d.cts CHANGED
@@ -74,16 +74,7 @@ interface Matchers {
74
74
  /**
75
75
  * Checks if the JSX component accepts the given props.
76
76
  */
77
- toAcceptProps: {
78
- /**
79
- * Checks if the JSX component accepts props of the given type.
80
- */
81
- <Target>(): void;
82
- /**
83
- * Checks if the JSX component accepts the given props.
84
- */
85
- (target: unknown): void;
86
- };
77
+ toAcceptProps: (props: Record<string, unknown>) => void;
87
78
  /**
88
79
  * Checks if the decorator is applicable to the given class or class member.
89
80
  */
@@ -104,8 +95,12 @@ interface Matchers {
104
95
  * Checks if the type has the given property.
105
96
  */
106
97
  toHaveProperty: (key: string | number | symbol) => void;
98
+ }
99
+ interface Matchers {
107
100
  /**
108
101
  * Checks if the type raises an error.
102
+ *
103
+ * @deprecated This matcher is planned to be removed. For a replacement, see https://tstyche.org/guides/expect-errors.
109
104
  */
110
105
  toRaiseError: (...target: Array<string | number | RegExp>) => void;
111
106
  }
package/dist/index.d.ts CHANGED
@@ -74,16 +74,7 @@ interface Matchers {
74
74
  /**
75
75
  * Checks if the JSX component accepts the given props.
76
76
  */
77
- toAcceptProps: {
78
- /**
79
- * Checks if the JSX component accepts props of the given type.
80
- */
81
- <Target>(): void;
82
- /**
83
- * Checks if the JSX component accepts the given props.
84
- */
85
- (target: unknown): void;
86
- };
77
+ toAcceptProps: (props: Record<string, unknown>) => void;
87
78
  /**
88
79
  * Checks if the decorator is applicable to the given class or class member.
89
80
  */
@@ -104,8 +95,12 @@ interface Matchers {
104
95
  * Checks if the type has the given property.
105
96
  */
106
97
  toHaveProperty: (key: string | number | symbol) => void;
98
+ }
99
+ interface Matchers {
107
100
  /**
108
101
  * Checks if the type raises an error.
102
+ *
103
+ * @deprecated This matcher is planned to be removed. For a replacement, see https://tstyche.org/guides/expect-errors.
109
104
  */
110
105
  toRaiseError: (...target: Array<string | number | RegExp>) => void;
111
106
  }
package/dist/tag.js CHANGED
@@ -1,31 +1,10 @@
1
- import { Cli, EventEmitter, CancellationToken } from './api.js';
1
+ import { Cli } from './api.js';
2
2
 
3
- class StatusHandler {
4
- #hasError = false;
5
- hasError() {
6
- return this.#hasError;
7
- }
8
- on([event, payload]) {
9
- if (event === "run:start") {
10
- this.#hasError = false;
11
- return;
12
- }
13
- if ("diagnostics" in payload) {
14
- if (payload.diagnostics.some((diagnostic) => diagnostic.category === "error")) {
15
- this.#hasError = true;
16
- }
17
- }
18
- }
19
- }
20
3
  async function tstyche(template, ...substitutions) {
21
- const cli = new Cli({ noErrorExitCode: true });
4
+ const cli = new Cli();
22
5
  const commandLine = String.raw(template, ...substitutions).split(/\s+/);
23
- const eventEmitter = new EventEmitter();
24
- const statusHandler = new StatusHandler();
25
- eventEmitter.addHandler(statusHandler);
26
- await cli.run(commandLine, new CancellationToken());
27
- eventEmitter.removeHandler(statusHandler);
28
- if (statusHandler.hasError()) {
6
+ const exitCode = await cli.run(commandLine);
7
+ if (exitCode > 0) {
29
8
  throw new Error("TSTyche test run failed. Check the output above for details.");
30
9
  }
31
10
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tstyche",
3
- "version": "7.0.0-beta.3",
3
+ "version": "7.0.0-beta.5",
4
4
  "description": "Everything You Need for Type Testing.",
5
5
  "keywords": [
6
6
  "typescript",
@@ -0,0 +1,88 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "type": "object",
4
+ "properties": {
5
+ "checkDeclarationFiles": {
6
+ "description": "Check declaration files for type errors.",
7
+ "default": true,
8
+ "type": "boolean"
9
+ },
10
+ "checkSuppressedErrors": {
11
+ "description": "Check errors silenced by '@ts-expect-error' directives.",
12
+ "default": true,
13
+ "type": "boolean"
14
+ },
15
+ "failFast": {
16
+ "description": "Stop running tests after the first failed assertion.",
17
+ "default": false,
18
+ "type": "boolean"
19
+ },
20
+ "fixtureFileMatch": {
21
+ "description": "The list of glob patterns matching the fixture files.",
22
+ "default": [
23
+ "**/__fixtures__/*.{ts,tsx}",
24
+ "**/fixtures/*.{ts,tsx}"
25
+ ],
26
+ "type": "array",
27
+ "uniqueItems": true,
28
+ "items": {
29
+ "type": "string"
30
+ }
31
+ },
32
+ "quiet": {
33
+ "description": "Silence all test runner output except errors and warnings.",
34
+ "default": false,
35
+ "type": "boolean"
36
+ },
37
+ "rejectAnyType": {
38
+ "description": "Reject the 'any' type passed as an argument to the 'expect()' function or a matcher.",
39
+ "default": true,
40
+ "type": "boolean"
41
+ },
42
+ "rejectNeverType": {
43
+ "description": "Reject the 'never' type passed as an argument to the 'expect()' function or a matcher.",
44
+ "default": true,
45
+ "type": "boolean"
46
+ },
47
+ "reporters": {
48
+ "description": "The list of reporters to use.",
49
+ "default": [
50
+ "list",
51
+ "summary"
52
+ ],
53
+ "type": "array",
54
+ "uniqueItems": true,
55
+ "items": {
56
+ "type": "string"
57
+ }
58
+ },
59
+ "target": {
60
+ "description": "The range of TypeScript versions to test against.",
61
+ "default": "*",
62
+ "type": "string"
63
+ },
64
+ "testFileMatch": {
65
+ "description": "The list of glob patterns matching the test files.",
66
+ "default": [
67
+ "**/*.tst.*",
68
+ "**/__typetests__/*.test.*",
69
+ "**/typetests/*.test.*"
70
+ ],
71
+ "type": "array",
72
+ "uniqueItems": true,
73
+ "items": {
74
+ "type": "string"
75
+ }
76
+ },
77
+ "tsconfig": {
78
+ "description": "The TSConfig to load.",
79
+ "default": "findup",
80
+ "type": "string"
81
+ },
82
+ "verbose": {
83
+ "description": "Enable detailed logging.",
84
+ "default": false,
85
+ "type": "boolean"
86
+ }
87
+ }
88
+ }