diff --git a/eslint.config.mjs b/eslint.config.mjs index d31a648c0327..b299e7140604 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -36,6 +36,7 @@ const vitestFiles = [ 'packages/parser/tests/lib/**/*.test.{ts,tsx,cts,mts}', 'packages/parser/tests/test-utils/**/*.{ts,tsx,cts,mts}', 'packages/utils/tests/**/*.test?(-d).{ts,tsx,cts,mts}', + 'packages/type-utils/tests/**/*.test.{ts,tsx,cts,mts}', ]; export default tseslint.config( diff --git a/nx.json b/nx.json index 6f69941fe0d4..ac7a356e5991 100644 --- a/nx.json +++ b/nx.json @@ -103,12 +103,11 @@ "{workspaceRoot}/vitest.config.base.mts", "{projectRoot}/vitest.config.mts" ], - "outputs": ["{options.reportsDirectory}"], + "outputs": ["{projectRoot}/coverage"], "cache": true, "options": { "config": "{projectRoot}/vitest.config.mts", - "watch": false, - "reportsDirectory": "{projectRoot}/coverage" + "watch": false } }, "lint": { @@ -132,7 +131,7 @@ }, "typecheck": { "dependsOn": ["types:copy-ast-spec"], - "outputs": ["{workspaceRoot}/dist/out-tsc/{projectRoot}"], + "outputs": ["{workspaceRoot}/dist"], "cache": true } }, diff --git a/packages/ast-spec/project.json b/packages/ast-spec/project.json index bb045ad1f6be..a46843d6def3 100644 --- a/packages/ast-spec/project.json +++ b/packages/ast-spec/project.json @@ -1,21 +1,21 @@ { "name": "ast-spec", "$schema": "../../node_modules/nx/schemas/project-schema.json", - "type": "library", + "projectType": "library", "implicitDependencies": ["!typescript-estree"], + "root": "packages/ast-spec", + "sourceRoot": "packages/ast-spec/src", "targets": { "build": { - "executor": "nx:run-commands", - "options": { - "cwd": "packages/ast-spec", - "commands": ["yarn build"] - }, "outputs": ["{projectRoot}/dist/**/*.ts"] }, "lint": { "executor": "@nx/eslint:lint", "outputs": ["{options.outputFile}"] }, + "test": { + "dependsOn": ["typecheck"] + }, "typecheck": { "dependsOn": ["typescript-estree:build"] } diff --git a/packages/type-utils/jest.config.js b/packages/type-utils/jest.config.js deleted file mode 100644 index 910991b20cff..000000000000 --- a/packages/type-utils/jest.config.js +++ /dev/null @@ -1,7 +0,0 @@ -'use strict'; - -// @ts-check -/** @type {import('@jest/types').Config.InitialOptions} */ -module.exports = { - ...require('../../jest.config.base.js'), -}; diff --git a/packages/type-utils/package.json b/packages/type-utils/package.json index 0b27cc760a3f..5e3b42a78d34 100644 --- a/packages/type-utils/package.json +++ b/packages/type-utils/package.json @@ -40,10 +40,10 @@ "build": "tsc -b tsconfig.build.json", "postbuild": "downlevel-dts dist _ts4.3/dist --to=4.3", "clean": "tsc -b tsconfig.build.json --clean", - "postclean": "rimraf dist && rimraf _ts3.4 && rimraf _ts4.3 && rimraf coverage", + "postclean": "rimraf dist/ _ts4.3/ coverage/", "format": "prettier --write \"./**/*.{ts,mts,cts,tsx,js,mjs,cjs,jsx,json,md,css}\" --ignore-path ../../.prettierignore", "lint": "npx nx lint", - "test": "jest", + "test": "vitest --run --config=$INIT_CWD/vitest.config.mts", "check-types": "npx nx typecheck" }, "dependencies": { @@ -57,14 +57,14 @@ "typescript": ">=4.8.4 <5.9.0" }, "devDependencies": { - "@jest/types": "29.6.3", "@typescript-eslint/parser": "8.29.1", + "@vitest/coverage-v8": "^3.1.1", "ajv": "^6.12.6", "downlevel-dts": "*", - "jest": "29.7.0", "prettier": "^3.2.5", "rimraf": "*", - "typescript": "*" + "typescript": "*", + "vitest": "^3.1.1" }, "funding": { "type": "opencollective", diff --git a/packages/type-utils/project.json b/packages/type-utils/project.json index 4ac211280e6b..8c91c0ace943 100644 --- a/packages/type-utils/project.json +++ b/packages/type-utils/project.json @@ -1,12 +1,16 @@ { "name": "type-utils", "$schema": "../../node_modules/nx/schemas/project-schema.json", - "type": "library", - "implicitDependencies": [], + "projectType": "library", + "root": "packages/type-utils", + "sourceRoot": "packages/type-utils/src", "targets": { "lint": { "executor": "@nx/eslint:lint", "outputs": ["{options.outputFile}"] + }, + "test": { + "executor": "@nx/vite:test" } } } diff --git a/packages/type-utils/tests/TypeOrValueSpecifier.test.ts b/packages/type-utils/tests/TypeOrValueSpecifier.test.ts index b58ae80df8d2..70ae2bda9313 100644 --- a/packages/type-utils/tests/TypeOrValueSpecifier.test.ts +++ b/packages/type-utils/tests/TypeOrValueSpecifier.test.ts @@ -1,4 +1,5 @@ import type { TSESTree } from '@typescript-eslint/utils'; +import type { TestContext } from 'vitest'; import { parseForESLint } from '@typescript-eslint/parser'; import Ajv from 'ajv'; @@ -8,41 +9,51 @@ import type { TypeOrValueSpecifier } from '../src/TypeOrValueSpecifier'; import { typeMatchesSpecifier, typeOrValueSpecifiersSchema } from '../src'; +const ROOT_DIR = path.posix.join( + ...path.relative(process.cwd(), path.join(__dirname, '..')).split(path.sep), +); + describe('TypeOrValueSpecifier', () => { describe('Schema', () => { const ajv = new Ajv(); const validate = ajv.compile(typeOrValueSpecifiersSchema); - function runTestPositive(typeOrValueSpecifier: unknown): void { + function runTestPositive( + [typeOrValueSpecifier]: readonly [typeOrValueSpecifier: unknown], + { expect }: TestContext, + ): void { expect(validate([typeOrValueSpecifier])).toBe(true); } - function runTestNegative(typeOrValueSpecifier: unknown): void { + function runTestNegative( + [typeOrValueSpecifier]: readonly [typeOrValueSpecifier: unknown], + { expect }: TestContext, + ): void { expect(validate([typeOrValueSpecifier])).toBe(false); } - it.each([['MyType'], ['myValue'], ['any'], ['void'], ['never']])( + it.for([['MyType'], ['myValue'], ['any'], ['void'], ['never']] as const)( 'matches a simple string specifier %s', runTestPositive, ); - it.each([ + it.for([ [42], [false], [null], [undefined], [['MyType']], [(): void => {}], - ])("doesn't match any non-string basic type: %s", runTestNegative); + ] as const)("doesn't match any non-string basic type: %s", runTestNegative); - it.each([ + it.for([ [{ from: 'file', name: 'MyType' }], [{ from: 'file', name: ['MyType', 'myValue'] }], [{ from: 'file', name: 'MyType', path: './filename.js' }], [{ from: 'file', name: ['MyType', 'myValue'], path: './filename.js' }], - ])('matches a file specifier: %s', runTestPositive); + ] as const)('matches a file specifier: %s', runTestPositive); - it.each([ + it.for([ [{ from: 'file', name: 42 }], [{ from: 'file', name: ['MyType', 42] }], [{ from: 'file', name: ['MyType', 'MyType'] }], @@ -59,23 +70,26 @@ describe('TypeOrValueSpecifier', () => { }, ], [{ from: 'file', name: 'MyType', unrelatedProperty: '' }], - ])("doesn't match a malformed file specifier: %s", runTestNegative); + ] as const)( + "doesn't match a malformed file specifier: %s", + runTestNegative, + ); - it.each([ + it.for([ [{ from: 'lib', name: 'MyType' }], [{ from: 'lib', name: ['MyType', 'myValue'] }], - ])('matches a lib specifier: %s', runTestPositive); + ] as const)('matches a lib specifier: %s', runTestPositive); - it.each([ + it.for([ [{ from: 'lib', name: 42 }], [{ from: 'lib', name: ['MyType', 42] }], [{ from: 'lib', name: ['MyType', 'MyType'] }], [{ from: 'lib', name: [] }], [{ from: 'lib' }], [{ from: 'lib', name: 'MyType', unrelatedProperty: '' }], - ])("doesn't match a malformed lib specifier: %s", runTestNegative); + ] as const)("doesn't match a malformed lib specifier: %s", runTestNegative); - it.each([ + it.for([ [{ from: 'package', name: 'MyType', package: 'jquery' }], [ { @@ -84,9 +98,9 @@ describe('TypeOrValueSpecifier', () => { package: 'jquery', }, ], - ])('matches a package specifier: %s', runTestPositive); + ] as const)('matches a package specifier: %s', runTestPositive); - it.each([ + it.for([ [{ from: 'package', name: 42, package: 'jquery' }], [{ from: 'package', name: ['MyType', 42], package: 'jquery' }], [ @@ -119,14 +133,18 @@ describe('TypeOrValueSpecifier', () => { unrelatedProperty: '', }, ], - ])("doesn't match a malformed package specifier: %s", runTestNegative); + ] as const)( + "doesn't match a malformed package specifier: %s", + runTestNegative, + ); }); - describe('typeMatchesSpecifier', () => { + describe(typeMatchesSpecifier, () => { function runTests( code: string, specifier: TypeOrValueSpecifier, expected: boolean, + expect: TestContext['expect'], ): void { const rootDir = path.join(__dirname, 'fixtures'); const { ast, services } = parseForESLint(code, { @@ -149,35 +167,48 @@ describe('TypeOrValueSpecifier', () => { } function runTestPositive( - code: string, - specifier: TypeOrValueSpecifier, + [code, specifier]: readonly [ + code: string, + specifier: TypeOrValueSpecifier, + ], + testContext: Partial & Pick = { + expect, + }, ): void { - runTests(code, specifier, true); + runTests(code, specifier, true, testContext.expect); } function runTestNegative( - code: string, - specifier: TypeOrValueSpecifier, + [code, specifier]: readonly [ + code: string, + specifier: TypeOrValueSpecifier, + ], + testContext: Partial & Pick = { + expect, + }, ): void { - runTests(code, specifier, false); + runTests(code, specifier, false, testContext.expect); } - it.each<[string, TypeOrValueSpecifier]>([ + it.for([ ['interface Foo {prop: string}; type Test = Foo;', 'Foo'], ['type Test = RegExp;', 'RegExp'], - ])('matches a matching universal string specifier', runTestPositive); + ] as const satisfies [string, TypeOrValueSpecifier][])( + 'matches a matching universal string specifier', + runTestPositive, + ); - it.each<[string, TypeOrValueSpecifier]>([ + it.for([ ['interface Foo {prop: string}; type Test = Foo;', 'Bar'], ['interface Foo {prop: string}; type Test = Foo;', 'RegExp'], ['type Test = RegExp;', 'Foo'], ['type Test = RegExp;', 'BigInt'], - ])( + ] as const satisfies [string, TypeOrValueSpecifier][])( "doesn't match a mismatched universal string specifier", runTestNegative, ); - it.each<[string, TypeOrValueSpecifier]>([ + it.for([ [ 'interface Foo {prop: string}; type Test = Foo;', { from: 'file', name: 'Foo' }, @@ -196,11 +227,19 @@ describe('TypeOrValueSpecifier', () => { ], [ 'interface Foo {prop: string}; type Test = Foo;', - { from: 'file', name: 'Foo', path: 'tests/fixtures/file.ts' }, + { + from: 'file', + name: 'Foo', + path: `${ROOT_DIR}/tests/fixtures/file.ts`, + }, ], [ 'type Foo = {prop: string}; type Test = Foo;', - { from: 'file', name: 'Foo', path: 'tests/fixtures/file.ts' }, + { + from: 'file', + name: 'Foo', + path: `${ROOT_DIR}/tests/fixtures/file.ts`, + }, ], [ 'type Foo = Promise & {hey?: string}; let foo: Foo = Promise.resolve(5); type Test = typeof foo;', @@ -211,7 +250,7 @@ describe('TypeOrValueSpecifier', () => { { from: 'file', name: 'Foo', - path: 'tests/../tests/fixtures/////file.ts', + path: `${ROOT_DIR}/tests/../tests/fixtures/////file.ts`, }, ], [ @@ -219,7 +258,7 @@ describe('TypeOrValueSpecifier', () => { { from: 'file', name: 'Foo', - path: 'tests/../tests/fixtures/////file.ts', + path: `${ROOT_DIR}/tests/../tests/fixtures/////file.ts`, }, ], [ @@ -227,7 +266,7 @@ describe('TypeOrValueSpecifier', () => { { from: 'file', name: ['Foo', 'Bar'], - path: 'tests/fixtures/file.ts', + path: `${ROOT_DIR}/tests/fixtures/file.ts`, }, ], [ @@ -235,12 +274,15 @@ describe('TypeOrValueSpecifier', () => { { from: 'file', name: ['Foo', 'Bar'], - path: 'tests/fixtures/file.ts', + path: `${ROOT_DIR}/tests/fixtures/file.ts`, }, ], - ])('matches a matching file specifier: %s', runTestPositive); + ] as const satisfies [string, TypeOrValueSpecifier][])( + 'matches a matching file specifier: %s', + runTestPositive, + ); - it.each<[string, TypeOrValueSpecifier]>([ + it.for([ [ 'interface Foo {prop: string}; type Test = Foo;', { from: 'file', name: 'Bar' }, @@ -261,32 +303,44 @@ describe('TypeOrValueSpecifier', () => { path: 'tests/fixtures/wrong-file.ts', }, ], - ])("doesn't match a mismatched file specifier: %s", runTestNegative); + ] as const satisfies [string, TypeOrValueSpecifier][])( + "doesn't match a mismatched file specifier: %s", + runTestNegative, + ); - it.each<[string, TypeOrValueSpecifier]>([ + it.for([ ['type Test = RegExp;', { from: 'lib', name: 'RegExp' }], ['type Test = RegExp;', { from: 'lib', name: ['RegExp', 'BigInt'] }], - ])('matches a matching lib specifier: %s', runTestPositive); + ] as const satisfies [string, TypeOrValueSpecifier][])( + 'matches a matching lib specifier: %s', + runTestPositive, + ); - it.each<[string, TypeOrValueSpecifier]>([ + it.for([ ['type Test = RegExp;', { from: 'lib', name: 'BigInt' }], ['type Test = RegExp;', { from: 'lib', name: ['BigInt', 'Date'] }], - ])("doesn't match a mismatched lib specifier: %s", runTestNegative); + ] as const satisfies [string, TypeOrValueSpecifier][])( + "doesn't match a mismatched lib specifier: %s", + runTestNegative, + ); - it.each<[string, TypeOrValueSpecifier]>([ + it.for([ ['type Test = string;', { from: 'lib', name: 'string' }], ['type Test = string;', { from: 'lib', name: ['string', 'number'] }], - ])('matches a matching intrinsic type specifier: %s', runTestPositive); + ] as const satisfies [string, TypeOrValueSpecifier][])( + 'matches a matching intrinsic type specifier: %s', + runTestPositive, + ); - it.each<[string, TypeOrValueSpecifier]>([ + it.for([ ['type Test = string;', { from: 'lib', name: 'number' }], ['type Test = string;', { from: 'lib', name: ['number', 'boolean'] }], - ])( + ] as const satisfies [string, TypeOrValueSpecifier][])( "doesn't match a mismatched intrinsic type specifier: %s", runTestNegative, ); - it.each<[string, TypeOrValueSpecifier]>([ + it.for([ [ 'import type {Node} from "typescript"; type Test = Node;', { from: 'package', name: 'Node', package: 'typescript' }, @@ -366,9 +420,12 @@ describe('TypeOrValueSpecifier', () => { package: 'node:test', }, ], - ])('matches a matching package specifier: %s', runTestPositive); + ] as const satisfies [string, TypeOrValueSpecifier][])( + 'matches a matching package specifier: %s', + runTestPositive, + ); - it.each<[string, TypeOrValueSpecifier]>([ + it.for([ [ ` type Other = { __otherBrand: true }; @@ -386,12 +443,12 @@ describe('TypeOrValueSpecifier', () => { `, { from: 'file', name: ['SafePromise'] }, ], - ])( + ] as const satisfies [string, TypeOrValueSpecifier][])( "doesn't match a mismatched type specifier for an intersection type: %s", runTestNegative, ); - it.each<[string, TypeOrValueSpecifier]>([ + it.for([ [ ` type SafePromise = Promise & { __safeBrand: string }; @@ -400,12 +457,12 @@ describe('TypeOrValueSpecifier', () => { `, { from: 'file', name: ['ResultType'] }, ], - ])( + ] as const satisfies [string, TypeOrValueSpecifier][])( 'matches a matching type specifier for an intersection type: %s', runTestPositive, ); - it.each<[string, TypeOrValueSpecifier]>([ + it.for([ [ ` declare module "node:test" { @@ -425,12 +482,12 @@ describe('TypeOrValueSpecifier', () => { package: 'node:test', }, ], - ])( + ] as const satisfies [string, TypeOrValueSpecifier][])( 'matches a matching package specifier for an intersection type: %s', runTestPositive, ); - it.each<[string, TypeOrValueSpecifier]>([ + it.for([ [ ` declare module "node:test" { @@ -450,13 +507,13 @@ describe('TypeOrValueSpecifier', () => { package: 'node:test', }, ], - ])( + ] as const satisfies [string, TypeOrValueSpecifier][])( "doesn't match a mismatched package specifier for an intersection type: %s", runTestNegative, ); it("does not match a `declare global` with the 'global' package name", () => { - runTestNegative( + runTestNegative([ ` declare global { export type URL = {}; @@ -469,10 +526,10 @@ describe('TypeOrValueSpecifier', () => { name: 'URL', package: 'global', }, - ); + ]); }); - it.each<[string, TypeOrValueSpecifier]>([ + it.for([ [ 'import type {Node} from "typescript"; type Test = Node;', { from: 'package', name: 'Symbol', package: 'typescript' }, @@ -497,9 +554,12 @@ describe('TypeOrValueSpecifier', () => { 'import type {Node as TsNode} from "typescript"; type Test = TsNode;', { from: 'package', name: 'TsNode', package: 'typescript' }, ], - ])("doesn't match a mismatched package specifier: %s", runTestNegative); + ] as const satisfies [string, TypeOrValueSpecifier][])( + "doesn't match a mismatched package specifier: %s", + runTestNegative, + ); - it.each<[string, TypeOrValueSpecifier]>([ + it.for([ [ 'interface Foo {prop: string}; type Test = Foo;', { from: 'lib', name: 'Foo' }, @@ -528,18 +588,25 @@ describe('TypeOrValueSpecifier', () => { package: 'foo-package', }, ], - ['type Test = RegExp;', { from: 'file', name: 'RegExp' }], - ['type Test = RegExp;', { from: 'file', name: ['RegExp', 'BigInt'] }], + ['type Test = RegExp;', { from: 'file', name: 'RegExp', path: ROOT_DIR }], + [ + 'type Test = RegExp;', + { from: 'file', name: ['RegExp', 'BigInt'], path: ROOT_DIR }, + ], [ 'type Test = RegExp;', - { from: 'file', name: 'RegExp', path: 'tests/fixtures/file.ts' }, + { + from: 'file', + name: 'RegExp', + path: `${ROOT_DIR}/tests/fixtures/file.ts`, + }, ], [ 'type Test = RegExp;', { from: 'file', name: ['RegExp', 'BigInt'], - path: 'tests/fixtures/file.ts', + path: `${ROOT_DIR}/tests/fixtures/file.ts`, }, ], [ @@ -550,11 +617,17 @@ describe('TypeOrValueSpecifier', () => { 'type Test = RegExp;', { from: 'package', name: ['RegExp', 'BigInt'], package: 'foo-package' }, ], - ])("doesn't match a mismatched specifier type: %s", runTestNegative); + ] as const satisfies [string, TypeOrValueSpecifier][])( + "doesn't match a mismatched specifier type: %s", + runTestNegative, + ); - it.each<[string, TypeOrValueSpecifier]>([ + it.for([ ['type Test = Foo;', { from: 'lib', name: 'Foo' }], ['type Test = Foo;', { from: 'lib', name: ['Foo', 'number'] }], - ])("doesn't match an error type: %s", runTestNegative); + ] as const satisfies [string, TypeOrValueSpecifier][])( + "doesn't match an error type: %s", + runTestNegative, + ); }); }); diff --git a/packages/type-utils/tests/containsAllTypesByName.test.ts b/packages/type-utils/tests/containsAllTypesByName.test.ts index 46933b01f092..351e5fb84c91 100644 --- a/packages/type-utils/tests/containsAllTypesByName.test.ts +++ b/packages/type-utils/tests/containsAllTypesByName.test.ts @@ -1,5 +1,6 @@ import type { TSESTree } from '@typescript-eslint/typescript-estree'; import type * as ts from 'typescript'; +import type { TestContext } from 'vitest'; import { parseForESLint } from '@typescript-eslint/parser'; import path from 'node:path'; @@ -7,7 +8,7 @@ import path from 'node:path'; import { containsAllTypesByName } from '../src'; import { expectToHaveParserServices } from './test-utils/expectToHaveParserServices'; -describe('containsAllTypesByName', () => { +describe(containsAllTypesByName, () => { const rootDir = path.join(__dirname, 'fixtures'); function getType(code: string): ts.Type { @@ -27,6 +28,7 @@ describe('containsAllTypesByName', () => { code: string, allowAny: boolean, expected: boolean, + { expect }: TestContext, ): void { const type = getType(code); const result = containsAllTypesByName(type, allowAny, new Set()); @@ -34,27 +36,33 @@ describe('containsAllTypesByName', () => { } describe('is true', () => { - function runTest(code: string, expected: boolean): void { - runTestForAliasDeclaration(code, true, expected); + function runTest( + [code, expected]: readonly [code: string, expected: boolean], + testContext: TestContext, + ): void { + runTestForAliasDeclaration(code, true, expected, testContext); } - it.each([ + it.for([ ['type Test = unknown;', false], ['type Test = any;', false], ['type Test = string;', false], - ])('when code is "%s" expected is %s', runTest); + ] as const)('when code is "%s" expected is %s', runTest); }); describe('is false', () => { - function runTest(code: string, expected: boolean): void { - runTestForAliasDeclaration(code, false, expected); + function runTest( + [code, expected]: readonly [code: string, expected: boolean], + testContext: TestContext, + ): void { + runTestForAliasDeclaration(code, false, expected, testContext); } - it.each([ + it.for([ ['type Test = unknown;', true], ['type Test = any;', true], ['type Test = string;', false], - ])('when code is "%s" expected is %s', runTest); + ] as const)('when code is "%s" expected is %s', runTest); }); }); @@ -63,6 +71,7 @@ describe('containsAllTypesByName', () => { code: string, matchAnyInstead: boolean, expected: boolean, + { expect }: TestContext, ): void { const type = getType(code); const result = containsAllTypesByName( @@ -75,27 +84,33 @@ describe('containsAllTypesByName', () => { } describe('is true', () => { - function runTest(code: string, expected: boolean): void { - runTestForAliasDeclaration(code, true, expected); + function runTest( + [code, expected]: readonly [code: string, expected: boolean], + testContext: TestContext, + ): void { + runTestForAliasDeclaration(code, true, expected, testContext); } - it.each([ + it.for([ [`type Test = Promise & string`, true], ['type Test = Promise | string', true], ['type Test = Promise | Object', true], - ])('when code is "%s" expected is %s', runTest); + ] as const)('when code is "%s" expected is %s', runTest); }); describe('is false', () => { - function runTest(code: string, expected: boolean): void { - runTestForAliasDeclaration(code, false, expected); + function runTest( + [code, expected]: readonly [code: string, expected: boolean], + testContext: TestContext, + ): void { + runTestForAliasDeclaration(code, false, expected, testContext); } - it.each([ + it.for([ ['type Test = Promise & string', false], ['type Test = Promise | string', false], ['type Test = Promise | Object', true], - ])('when code is "%s" expected is %s', runTest); + ] as const)('when code is "%s" expected is %s', runTest); }); }); }); diff --git a/packages/type-utils/tests/discriminateAnyType.test.ts b/packages/type-utils/tests/discriminateAnyType.test.ts index 67a84298b057..6b933322086e 100644 --- a/packages/type-utils/tests/discriminateAnyType.test.ts +++ b/packages/type-utils/tests/discriminateAnyType.test.ts @@ -1,4 +1,5 @@ import type { TSESTree } from '@typescript-eslint/typescript-estree'; +import type { TestContext } from 'vitest'; import { parseForESLint } from '@typescript-eslint/parser'; import path from 'node:path'; @@ -8,7 +9,7 @@ import { expectToHaveParserServices } from './test-utils/expectToHaveParserServi type GetNode = (ast: TSESTree.Program) => TSESTree.Node; -describe('discriminateAnyType', () => { +describe(discriminateAnyType, () => { const rootDir = path.join(__dirname, 'fixtures'); function getDeclarationId(ast: TSESTree.Program): TSESTree.Node { @@ -36,9 +37,12 @@ describe('discriminateAnyType', () => { } function runTest( - code: string, - expected: AnyType, - getNode: GetNode = getDeclarationId, + [code, expected, getNode = getDeclarationId]: readonly [ + code: string, + expected: AnyType, + getNode?: GetNode, + ], + { expect }: TestContext, ): void { const { checker, program, tsNode, type } = getTypes(code, getNode); const result = discriminateAnyType(type, checker, program, tsNode); @@ -46,13 +50,13 @@ describe('discriminateAnyType', () => { } describe('returns Safe', () => { - it.each([ + it.for([ ['const foo = "foo";', AnyType.Safe], ['const foo = 1;', AnyType.Safe], ['const foo = [1, 2];', AnyType.Safe], - ])('when code is %s, returns %s', runTest); + ] as const)('when code is %s, returns %s', runTest); - it('should returns Safe for a recursive thenable.', () => { + it('should returns Safe for a recursive thenable.', testContext => { const code = ` class Foo { foo() { @@ -63,39 +67,46 @@ class Foo { } }; `; - runTest(code, AnyType.Safe, ast => { - const classDeclration = ast.body[0] as TSESTree.ClassDeclaration; - const method = classDeclration.body - .body[0] as TSESTree.MethodDefinition; - const returnStatement = method.value.body?.body.at( - -1, - ) as TSESTree.ReturnStatement; - return returnStatement.argument!; - }); + runTest( + [ + code, + AnyType.Safe, + ast => { + const classDeclration = ast.body[0] as TSESTree.ClassDeclaration; + const method = classDeclration.body + .body[0] as TSESTree.MethodDefinition; + const returnStatement = method.value.body?.body.at( + -1, + ) as TSESTree.ReturnStatement; + return returnStatement.argument!; + }, + ], + testContext, + ); }); }); describe('returns Any', () => { - it.each([ + it.for([ ['const foo = 1 as any;', AnyType.Any], ['let foo;', AnyType.Any], - ])('when code is %s, returns %s', runTest); + ] as const)('when code is %s, returns %s', runTest); }); describe('returns PromiseAny', () => { - it.each([ + it.for([ ['const foo = Promise.resolve({} as any);', AnyType.PromiseAny], [ 'const foo = Promise.resolve(Promise.resolve({} as any));', AnyType.PromiseAny, ], - ])('when code is %s, returns %s', runTest); + ] as const)('when code is %s, returns %s', runTest); }); describe('returns AnyArray', () => { - it.each([ + it.for([ ['const foo = [{} as any];', AnyType.AnyArray], ['const foo = [{} as any, 2];', AnyType.AnyArray], - ])('when code is %s, returns %s', runTest); + ] as const)('when code is %s, returns %s', runTest); }); }); diff --git a/packages/type-utils/tests/getConstrainedTypeAtLocation.test.ts b/packages/type-utils/tests/getConstrainedTypeAtLocation.test.ts index 598e78500afe..c033dba526d7 100644 --- a/packages/type-utils/tests/getConstrainedTypeAtLocation.test.ts +++ b/packages/type-utils/tests/getConstrainedTypeAtLocation.test.ts @@ -21,9 +21,9 @@ function parseCodeForEslint(code: string): ReturnType & { }); } -describe('getConstrainedTypeAtLocation', () => { +describe(getConstrainedTypeAtLocation, () => { // See https://github.com/typescript-eslint/typescript-eslint/issues/10438 - // eslint-disable-next-line jest/no-disabled-tests -- known issue. + // eslint-disable-next-line vitest/no-disabled-tests -- known issue. it.skip('returns unknown for unconstrained generic', () => { const sourceCode = ` function foo(x: T); diff --git a/packages/type-utils/tests/getDeclaration.test.ts b/packages/type-utils/tests/getDeclaration.test.ts index a7af315b6b28..172e4b8bbd4b 100644 --- a/packages/type-utils/tests/getDeclaration.test.ts +++ b/packages/type-utils/tests/getDeclaration.test.ts @@ -24,7 +24,7 @@ const mockDeclaration = (): ts.Declaration => { return {} as ts.Declaration; }; -describe('getDeclaration', () => { +describe(getDeclaration, () => { describe('when symbol does not exist', () => { it('returns null', () => { const services = mockServices(); diff --git a/packages/type-utils/tests/getTypeName.test.ts b/packages/type-utils/tests/getTypeName.test.ts index 7ab59ae0aae7..92aa0140204b 100644 --- a/packages/type-utils/tests/getTypeName.test.ts +++ b/packages/type-utils/tests/getTypeName.test.ts @@ -1,5 +1,6 @@ import type { TSESTree } from '@typescript-eslint/typescript-estree'; import type * as ts from 'typescript'; +import type { TestContext } from 'vitest'; import { parseForESLint } from '@typescript-eslint/parser'; import path from 'node:path'; @@ -7,7 +8,7 @@ import path from 'node:path'; import { getTypeName } from '../src'; import { expectToHaveParserServices } from './test-utils/expectToHaveParserServices'; -describe('getTypeName', () => { +describe(getTypeName, () => { function getTypes(code: string): { checker: ts.TypeChecker; type: ts.Type } { const rootDir = path.join(__dirname, 'fixtures'); @@ -24,14 +25,17 @@ describe('getTypeName', () => { return { checker, type: services.getTypeAtLocation(declaration.id) }; } - function runTest(code: string, expected: string): void { + function runTest( + [code, expected]: readonly [code: string, expected: string], + { expect }: TestContext, + ): void { const { checker, type } = getTypes(code); const result = getTypeName(checker, type); expect(result).toBe(expected); } describe('returns primitive type', () => { - it.each([ + it.for([ ['type Test = string;', 'string'], ['type Test = "text";', 'string'], ['type Test = string | "text";', 'string'], @@ -45,11 +49,11 @@ describe('getTypeName', () => { ['type Test = undefined;', 'undefined'], ['type Test = null;', 'null'], ['type Test = symbol;', 'symbol'], - ])('when code is %s, returns %s', runTest); + ] as const)('when code is %s, returns %s', runTest); }); describe('returns non-primitive type', () => { - it.each([ + it.for([ ['type Test = 123;', '123'], ['type Test = true;', 'true'], ['type Test = false;', 'false'], @@ -57,6 +61,6 @@ describe('getTypeName', () => { ['type Test = T & boolean;', 'Test'], ['type Test = string | number;', 'Test'], ['type Test = string | string[];', 'Test'], - ])('when code is %s, returns %s', runTest); + ] as const)('when code is %s, returns %s', runTest); }); }); diff --git a/packages/type-utils/tests/isSymbolFromDefaultLibrary.test.ts b/packages/type-utils/tests/isSymbolFromDefaultLibrary.test.ts index 4f7050fb38d9..eb4ecbf55b83 100644 --- a/packages/type-utils/tests/isSymbolFromDefaultLibrary.test.ts +++ b/packages/type-utils/tests/isSymbolFromDefaultLibrary.test.ts @@ -1,5 +1,6 @@ import type { TSESTree } from '@typescript-eslint/typescript-estree'; import type * as ts from 'typescript'; +import type { TestContext } from 'vitest'; import { parseForESLint } from '@typescript-eslint/parser'; import path from 'node:path'; @@ -7,7 +8,7 @@ import path from 'node:path'; import { isSymbolFromDefaultLibrary } from '../src'; import { expectToHaveParserServices } from './test-utils/expectToHaveParserServices'; -describe('isSymbolFromDefaultLibrary', () => { +describe(isSymbolFromDefaultLibrary, () => { const rootDir = path.join(__dirname, 'fixtures'); function getTypes(code: string): { @@ -26,35 +27,45 @@ describe('isSymbolFromDefaultLibrary', () => { return { program: services.program, symbol: type.getSymbol() }; } - function runTestForAliasDeclaration(code: string, expected: boolean): void { + function runTestForAliasDeclaration( + code: string, + expected: boolean, + expect: TestContext['expect'], + ): void { const { program, symbol } = getTypes(code); const result = isSymbolFromDefaultLibrary(program, symbol); expect(result).toBe(expected); } describe('is symbol from default library', () => { - function runTest(code: string): void { - runTestForAliasDeclaration(code, true); + function runTest( + [code]: readonly [code: string], + { expect }: TestContext, + ): void { + runTestForAliasDeclaration(code, true, expect); } - it.each([ + it.for([ ['type Test = Array;'], ['type Test = Map;'], ['type Test = Promise'], ['type Test = Error'], ['type Test = Object'], - ])('when code is %s, returns true', runTest); + ] as const)('when code is %s, returns true', runTest); }); describe('is not symbol from default library', () => { - function runTest(code: string): void { - runTestForAliasDeclaration(code, false); + function runTest( + [code]: readonly [code: string], + { expect }: TestContext, + ): void { + runTestForAliasDeclaration(code, false, expect); } - it.each([ + it.for([ ['const test: Array = [1,2,3];'], ['type Test = number;'], ['interface Test { bar: string; };'], - ])('when code is %s, returns false', runTest); + ] as const)('when code is %s, returns false', runTest); }); }); diff --git a/packages/type-utils/tests/isTypeReadonly.test.ts b/packages/type-utils/tests/isTypeReadonly.test.ts index f7405e2e5add..8f2d04765cb8 100644 --- a/packages/type-utils/tests/isTypeReadonly.test.ts +++ b/packages/type-utils/tests/isTypeReadonly.test.ts @@ -2,6 +2,7 @@ import type { TSESTree } from '@typescript-eslint/utils'; import type * as ts from 'typescript'; import { parseForESLint } from '@typescript-eslint/parser'; +import { AST_NODE_TYPES } from '@typescript-eslint/utils'; import path from 'node:path'; import type { ReadonlynessOptions } from '../src/isTypeReadonly'; @@ -9,10 +10,10 @@ import type { ReadonlynessOptions } from '../src/isTypeReadonly'; import { isTypeReadonly } from '../src/isTypeReadonly'; import { expectToHaveParserServices } from './test-utils/expectToHaveParserServices'; -describe('isTypeReadonly', () => { +describe(isTypeReadonly, () => { const rootDir = path.join(__dirname, 'fixtures'); - describe('TSTypeAliasDeclaration ', () => { + describe(AST_NODE_TYPES.TSTypeAliasDeclaration, () => { function getType(code: string): { program: ts.Program; type: ts.Type; @@ -24,8 +25,7 @@ describe('isTypeReadonly', () => { tsconfigRootDir: rootDir, }); expectToHaveParserServices(services); - const program = services.program; - const esTreeNodeToTSNodeMap = services.esTreeNodeToTSNodeMap; + const { esTreeNodeToTSNodeMap, program } = services; const declaration = ast.body[0] as TSESTree.TSTypeAliasDeclaration; return { @@ -59,33 +59,33 @@ describe('isTypeReadonly', () => { } describe('basics', () => { - describe('is readonly', () => { + describe('is readonly', { timeout: 10_000 }, () => { const runTests = runTestIsReadonly; // Record. it.each([ ['type Test = { readonly bar: string; };'], ['type Test = Readonly<{ bar: string; }>;'], - ])('handles fully readonly records', runTests); + ] as const)('handles fully readonly records', runTests); // Array. it.each([ ['type Test = Readonly;'], ['type Test = Readonly>;'], - ])('handles fully readonly arrays', runTests); + ] as const)('handles fully readonly arrays', runTests); // Array - special case. // Note: Methods are mutable but arrays are treated special; hence no failure. it.each([ ['type Test = readonly string[];'], ['type Test = ReadonlyArray;'], - ])('treats readonly arrays as fully readonly', runTests); + ] as const)('treats readonly arrays as fully readonly', runTests); // Set and Map. it.each([ ['type Test = Readonly>;'], ['type Test = Readonly>;'], - ])('handles fully readonly sets and maps', runTests); + ] as const)('handles fully readonly sets and maps', runTests); // Private Identifier. // Note: It can't be accessed from outside of class thus exempt from the checks. @@ -93,7 +93,7 @@ describe('isTypeReadonly', () => { ['class Foo { readonly #readonlyPrivateField = "foo"; }'], ['class Foo { #privateField = "foo"; }'], ['class Foo { #privateMember() {}; }'], - ])('treat private identifier as readonly', runTests); + ] as const)('treat private identifier as readonly', runTests); }); describe('is not readonly', () => { @@ -103,13 +103,13 @@ describe('isTypeReadonly', () => { it.each([ ['type Test = { foo: string; };'], ['type Test = { foo: string; readonly bar: number; };'], - ])('handles non fully readonly records', runTests); + ] as const)('handles non fully readonly records', runTests); // Array. - it.each([['type Test = string[]'], ['type Test = Array']])( - 'handles non fully readonly arrays', - runTests, - ); + it.each([ + ['type Test = string[]'], + ['type Test = Array'], + ] as const)('handles non fully readonly arrays', runTests); // Set and Map. // Note: Methods are mutable for ReadonlySet and ReadonlyMet; hence failure. @@ -118,7 +118,7 @@ describe('isTypeReadonly', () => { ['type Test = Map;'], ['type Test = ReadonlySet;'], ['type Test = ReadonlyMap;'], - ])('handles non fully readonly sets and maps', runTests); + ] as const)('handles non fully readonly sets and maps', runTests); }); }); @@ -131,7 +131,7 @@ describe('isTypeReadonly', () => { [ 'type Test = { readonly [key: string]: { readonly foo: readonly string[]; }; };', ], - ])( + ] as const)( 'handles readonly PropertySignature inside a readonly IndexSignature', runTests, ); @@ -140,13 +140,15 @@ describe('isTypeReadonly', () => { describe('is readonly circular', () => { const runTests = runTestIsReadonly; - it('handles circular readonly PropertySignature inside a readonly IndexSignature', () => - runTests('interface Test { readonly [key: string]: Test };')); + it('handles circular readonly PropertySignature inside a readonly IndexSignature', () => { + runTests('interface Test { readonly [key: string]: Test };'); + }); - it('handles circular readonly PropertySignature inside interdependent objects', () => + it('handles circular readonly PropertySignature inside interdependent objects', () => { runTests( 'interface Test1 { readonly [key: string]: Test } interface Test { readonly [key: string]: Test1 }', - )); + ); + }); }); describe('is not readonly', () => { @@ -155,7 +157,7 @@ describe('isTypeReadonly', () => { it.each([ ['type Test = { [key: string]: string };'], ['type Test = { readonly [key: string]: { foo: string[]; }; };'], - ])( + ] as const)( 'handles mutable PropertySignature inside a readonly IndexSignature', runTests, ); @@ -164,8 +166,9 @@ describe('isTypeReadonly', () => { describe('is not readonly circular', () => { const runTests = runTestIsNotReadonly; - it('handles circular mutable PropertySignature', () => - runTests('interface Test { [key: string]: Test };')); + it('handles circular mutable PropertySignature', () => { + runTests('interface Test { [key: string]: Test };'); + }); it.each([ [ @@ -177,7 +180,7 @@ describe('isTypeReadonly', () => { [ 'interface Test1 { [key: string]: Test } interface Test { [key: string]: Test1 }', ], - ])( + ] as const)( 'handles circular mutable PropertySignature inside interdependent objects', runTests, ); @@ -193,7 +196,7 @@ describe('isTypeReadonly', () => { 'type Test = Readonly<{ foo: string; bar: number; }> & Readonly<{ bar: number; }>;', ], ['type Test = readonly string[] | readonly number[];'], - ])('handles a union of 2 fully readonly types', runTests); + ] as const)('handles a union of 2 fully readonly types', runTests); }); describe('is not readonly', () => { @@ -207,7 +210,7 @@ describe('isTypeReadonly', () => { [ 'type Test = Readonly<{ foo: string; bar: number; }> | { bar: number; };', ], - ])('handles a union of non fully readonly types', runTests); + ] as const)('handles a union of non fully readonly types', runTests); }); }); @@ -219,13 +222,16 @@ describe('isTypeReadonly', () => { [ 'type Test = Readonly<{ foo: string; bar: number; }> & Readonly<{ bar: number; }>;', ], - ])('handles an intersection of 2 fully readonly types', runTests); + ] as const)( + 'handles an intersection of 2 fully readonly types', + runTests, + ); it.each([ [ 'type Test = Readonly<{ foo: string; bar: number; }> & { foo: string; };', ], - ])( + ] as const)( 'handles an intersection of a fully readonly type with a mutable subtype', runTests, ); @@ -237,7 +243,10 @@ describe('isTypeReadonly', () => { [ 'type Test = readonly [string, number] & Readonly<{ foo: string; }>;', ], - ])('handles an intersections involving a readonly array', runTests); + ] as const)( + 'handles an intersections involving a readonly array', + runTests, + ); }); describe('is not readonly', () => { @@ -251,7 +260,10 @@ describe('isTypeReadonly', () => { [ 'type Test = Readonly<{ bar: number; }> & { foo: string; bar: number; };', ], - ])('handles an intersection of non fully readonly types', runTests); + ] as const)( + 'handles an intersection of non fully readonly types', + runTests, + ); }); }); @@ -263,13 +275,16 @@ describe('isTypeReadonly', () => { [ 'type Test = T extends readonly number[] ? readonly string[] : readonly number[];', ], - ])('handles conditional type that are fully readonly', runTests); + ] as const)( + 'handles conditional type that are fully readonly', + runTests, + ); it.each([ [ 'type Test = T extends number[] ? readonly string[] : readonly number[];', ], - ])('should ignore mutable conditions', runTests); + ] as const)('should ignore mutable conditions', runTests); }); describe('is not readonly', () => { @@ -283,7 +298,7 @@ describe('isTypeReadonly', () => { [ 'type Test = T extends number[] ? readonly string[] : number[];', ], - ])('handles non fully readonly conditional types', runTests); + ] as const)('handles non fully readonly conditional types', runTests); }); }); }); @@ -308,7 +323,7 @@ describe('isTypeReadonly', () => { it.each([ ['type Test = ReadonlySet;'], ['type Test = ReadonlyMap;'], - ])('handles non fully readonly sets and maps', runTests); + ] as const)('handles non fully readonly sets and maps', runTests); }); }); @@ -343,7 +358,10 @@ describe('isTypeReadonly', () => { 'interface Foo {prop: RegExp}; type Test = (arg: Readonly) => void;', ], ['interface Foo {prop: string}; type Test = (arg: Foo) => void;'], - ])('correctly marks allowlisted types as readonly', runTestIsReadonly); + ] as const)( + 'correctly marks allowlisted types as readonly', + runTestIsReadonly, + ); }); describe('is not readonly', () => { @@ -352,7 +370,7 @@ describe('isTypeReadonly', () => { 'interface Bar {prop: RegExp}; type Test = (arg: Readonly) => void;', ], ['interface Bar {prop: string}; type Test = (arg: Bar) => void;'], - ])( + ] as const)( 'correctly marks allowlisted types as readonly', runTestIsNotReadonly, ); diff --git a/packages/type-utils/tests/isUnsafeAssignment.test.ts b/packages/type-utils/tests/isUnsafeAssignment.test.ts index b4ea26a58438..af605b73a441 100644 --- a/packages/type-utils/tests/isUnsafeAssignment.test.ts +++ b/packages/type-utils/tests/isUnsafeAssignment.test.ts @@ -7,7 +7,7 @@ import path from 'node:path'; import { isUnsafeAssignment } from '../src/isUnsafeAssignment'; import { expectToHaveParserServices } from './test-utils/expectToHaveParserServices'; -describe('isUnsafeAssignment', () => { +describe(isUnsafeAssignment, () => { const rootDir = path.join(__dirname, 'fixtures'); function getTypes( diff --git a/packages/type-utils/tests/requiresQuoting.test.ts b/packages/type-utils/tests/requiresQuoting.test.ts index 59c7d02e60e4..565743913164 100644 --- a/packages/type-utils/tests/requiresQuoting.test.ts +++ b/packages/type-utils/tests/requiresQuoting.test.ts @@ -1,6 +1,6 @@ import { requiresQuoting } from '../src'; -describe('getDeclaration', () => { +describe(requiresQuoting, () => { describe('valid identifier', () => { it('upper and lower case alphabet', () => { const name = 'c'; diff --git a/packages/type-utils/tests/typeFlagUtils.test.ts b/packages/type-utils/tests/typeFlagUtils.test.ts index 24e66b394158..c5d6fcc4f552 100644 --- a/packages/type-utils/tests/typeFlagUtils.test.ts +++ b/packages/type-utils/tests/typeFlagUtils.test.ts @@ -1,4 +1,5 @@ import type { TSESTree } from '@typescript-eslint/typescript-estree'; +import type { TestContext } from 'vitest'; import { parseForESLint } from '@typescript-eslint/parser'; import path from 'node:path'; @@ -23,33 +24,40 @@ describe('typeFlagUtils', () => { return services.getTypeAtLocation(declaration.id); } - describe('getTypeFlags', () => { + describe(getTypeFlags, () => { function runTestForAliasDeclaration( - code: string, - expected: ts.TypeFlags, + [code, expected]: readonly [code: string, expected: ts.TypeFlags], + { expect }: TestContext, ): void { const type = getType(code); const result = getTypeFlags(type); expect(result).toBe(expected); } - it.each([ + it.for([ ['type Test = any;', 1], ['type Test = unknown;', 2], ['type Test = string;', 4], ['type Test = number;', 8], ['type Test = "text";', 128], ['type Test = 123;', 256], - ['type Test = string | number', 12], + [ + 'type Test = string | number', + ts.TypeFlags.String | ts.TypeFlags.Number, + ], ['type Test = "text" | 123', 384], - ])('when code is "%s", type flags is %d', runTestForAliasDeclaration); + ] as const)( + 'when code is "%s", type flags is %d', + runTestForAliasDeclaration, + ); }); - describe('isTypeFlagSet', () => { + describe(isTypeFlagSet, () => { function runTestForAliasDeclaration( code: string, flagsToCheck: ts.TypeFlags, expected: boolean, + { expect }: TestContext, ): void { const type = getType(code); const result = isTypeFlagSet(type, flagsToCheck); @@ -58,18 +66,21 @@ describe('typeFlagUtils', () => { describe('is type flags set', () => { function runTestIsTypeFlagSet( - code: string, - flagsToCheck: ts.TypeFlags, + [code, flagsToCheck]: readonly [ + code: string, + flagsToCheck: ts.TypeFlags, + ], + testContext: TestContext, ): void { - runTestForAliasDeclaration(code, flagsToCheck, true); + runTestForAliasDeclaration(code, flagsToCheck, true, testContext); } - it.each([ + it.for([ ['type Test = any;', ts.TypeFlags.Any], ['type Test = string;', ts.TypeFlags.String], ['type Test = string | number;', ts.TypeFlags.String], ['type Test = string & { foo: string };', ts.TypeFlags.Intersection], - ])( + ] as const)( 'when code is "%s" and flagsToCheck is %d , returns true', runTestIsTypeFlagSet, ); @@ -77,17 +88,20 @@ describe('typeFlagUtils', () => { describe('is not type flags set', () => { function runTestIsNotTypeFlagSet( - code: string, - flagsToCheck: ts.TypeFlags, + [code, flagsToCheck]: readonly [ + code: string, + flagsToCheck: ts.TypeFlags, + ], + testContext: TestContext, ): void { - runTestForAliasDeclaration(code, flagsToCheck, false); + runTestForAliasDeclaration(code, flagsToCheck, false, testContext); } - it.each([ + it.for([ ['type Test = string', ts.TypeFlags.Any], ['type Test = string | number;', ts.TypeFlags.Any], ['type Test = string & { foo: string }', ts.TypeFlags.String], - ])( + ] as const)( 'when code is "%s" and flagsToCheck is %d , returns false', runTestIsNotTypeFlagSet, ); diff --git a/packages/type-utils/tsconfig.build.json b/packages/type-utils/tsconfig.build.json index f409f6784f7c..821662562d80 100644 --- a/packages/type-utils/tsconfig.build.json +++ b/packages/type-utils/tsconfig.build.json @@ -9,7 +9,7 @@ "types": ["node"] }, "include": ["src/**/*.ts", "typings"], - "exclude": ["jest.config.js", "src/**/*.spec.ts", "src/**/*.test.ts"], + "exclude": ["vitest.config.mts", "src/**/*.spec.ts", "src/**/*.test.ts"], "references": [ { "path": "../types/tsconfig.build.json" diff --git a/packages/type-utils/tsconfig.spec.json b/packages/type-utils/tsconfig.spec.json index 9b6b8b55e093..7ec995aaf7dc 100644 --- a/packages/type-utils/tsconfig.spec.json +++ b/packages/type-utils/tsconfig.spec.json @@ -3,10 +3,12 @@ "compilerOptions": { "outDir": "../../dist/out-tsc/packages/type-utils", "module": "NodeNext", - "types": ["jest", "node"] + "resolveJsonModule": true, + "types": ["node", "vitest/globals", "vitest/importMeta"] }, "include": [ - "jest.config.js", + "vitest.config.mts", + "package.json", "src/**/*.test.ts", "src/**/*.spec.ts", "src/**/*.d.ts", @@ -16,6 +18,9 @@ "references": [ { "path": "./tsconfig.build.json" + }, + { + "path": "../../tsconfig.spec.json" } ] } diff --git a/packages/type-utils/vitest.config.mts b/packages/type-utils/vitest.config.mts new file mode 100644 index 000000000000..674ea2ded3b5 --- /dev/null +++ b/packages/type-utils/vitest.config.mts @@ -0,0 +1,22 @@ +import * as path from 'node:path'; +import { defineProject, mergeConfig } from 'vitest/config'; + +import { vitestBaseConfig } from '../../vitest.config.base.mjs'; +import packageJson from './package.json' with { type: 'json' }; + +const vitestConfig = mergeConfig( + vitestBaseConfig, + + defineProject({ + root: import.meta.dirname, + + test: { + dir: path.join(import.meta.dirname, 'tests'), + name: packageJson.name.replace('@typescript-eslint/', ''), + root: import.meta.dirname, + testTimeout: 10_000, + }, + }), +); + +export default vitestConfig; diff --git a/tools/scripts/postinstall.mts b/tools/scripts/postinstall.mts index ba5dbc9d809e..5d123b1991d5 100644 --- a/tools/scripts/postinstall.mts +++ b/tools/scripts/postinstall.mts @@ -44,5 +44,6 @@ void (async function (): Promise { // Build all the packages ready for use await $`yarn build`; + await $`yarn nx typecheck ast-spec`; } })(); diff --git a/yarn.lock b/yarn.lock index be528cc2a4f9..49b2159800e7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6153,18 +6153,18 @@ __metadata: version: 0.0.0-use.local resolution: "@typescript-eslint/type-utils@workspace:packages/type-utils" dependencies: - "@jest/types": 29.6.3 "@typescript-eslint/parser": 8.29.1 "@typescript-eslint/typescript-estree": 8.29.1 "@typescript-eslint/utils": 8.29.1 + "@vitest/coverage-v8": ^3.1.1 ajv: ^6.12.6 debug: ^4.3.4 downlevel-dts: "*" - jest: 29.7.0 prettier: ^3.2.5 rimraf: "*" ts-api-utils: ^2.0.1 typescript: "*" + vitest: ^3.1.1 peerDependencies: eslint: ^8.57.0 || ^9.0.0 typescript: ">=4.8.4 <5.9.0" pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy