Skip to content

Commit 8836ab4

Browse files
committed
Fix Jest config file imports for Jest v30 ESM compatibility
Jest v30 switched to using Node's native ESM loader for config files, which requires explicit file extensions in imports. This change adds support for .ts extensions in Jest config file imports while maintaining proper TypeScript and ESLint integration. Changes: - Created tsconfig.jest-config.json: Separate TypeScript config for Jest config files that enables allowImportingTsExtensions - Updated tsconfig.json: Added project reference to tsconfig.jest-config.json and excluded jest.config*.ts files to prevent overlap - Updated jest.config.*.ts: Changed imports to use explicit .ts extensions (e.g., import from './jest.config.ts') - Updated eslint.config.js: Added specific configuration for Jest config files to use the correct tsconfig and ignore build artifacts - Updated .gitignore: Added .tsbuildinfo/ to ignore TypeScript build output Benefits: - IDE support: IDEs automatically use the correct tsconfig via project references - Clean imports: No @ts-ignore hacks needed - Full type checking: All files properly type-checked - All test scripts work: test-all, test-mutation, test-private Technical details: - Uses TypeScript composite projects with emitDeclarationOnly to satisfy both the composite requirement and allowImportingTsExtensions constraint - Jest config files loaded by Node ESM require .ts extensions - Test files continue to use traditional imports (handled by ts-jest)
1 parent 9332811 commit 8836ab4

7 files changed

Lines changed: 78 additions & 9 deletions

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@
77
/.env
88
/src/graphql
99
/.eslintcache
10+
/.tsbuildinfo

eslint.config.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ module.exports = [
2626
'src/graphql/generated/**',
2727
'bin/**',
2828
'coverage/**',
29+
'.tsbuildinfo/**',
2930
],
3031
},
3132

@@ -57,9 +58,48 @@ module.exports = [
5758
...js.configs.recommended,
5859
},
5960

61+
// Jest config files - use separate tsconfig that allows .ts extensions
62+
{
63+
files: ['jest.config*.ts'],
64+
languageOptions: {
65+
ecmaVersion: 'latest',
66+
sourceType: 'module',
67+
parser: tsparser,
68+
parserOptions: {
69+
project: './tsconfig.jest-config.json',
70+
},
71+
globals: nodeGlobals,
72+
},
73+
plugins: {
74+
'@typescript-eslint': tseslint,
75+
import: importPlugin,
76+
},
77+
rules: {
78+
...js.configs.recommended.rules,
79+
...tseslint.configs.recommended.rules,
80+
'import/order': [
81+
'error',
82+
{
83+
alphabetize: { order: 'asc' },
84+
'newlines-between': 'never',
85+
groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
86+
},
87+
],
88+
'import/no-duplicates': 'error',
89+
'@typescript-eslint/no-explicit-any': 'off',
90+
'@typescript-eslint/no-unused-vars': 'error',
91+
'@typescript-eslint/prefer-nullish-coalescing': 'error',
92+
'@typescript-eslint/prefer-optional-chain': 'error',
93+
'@typescript-eslint/consistent-type-imports': 'error',
94+
'@typescript-eslint/no-floating-promises': 'error',
95+
'no-unused-vars': 'off',
96+
},
97+
},
98+
6099
// TypeScript files
61100
{
62101
files: ['**/*.ts'],
102+
ignores: ['jest.config*.ts'],
63103
languageOptions: {
64104
ecmaVersion: 'latest',
65105
sourceType: 'module',

jest.config.all.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import baseConfig from './jest.config';
1+
import type { Config } from 'jest';
2+
import baseConfig from './jest.config.ts';
23

3-
const config = {
4+
const config: Config = {
45
...baseConfig,
56
modulePathIgnorePatterns: [],
67
};

jest.config.mutation.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import baseConfig from './jest.config';
1+
import type { Config } from 'jest';
2+
import baseConfig from './jest.config.ts';
23

3-
const config = {
4+
const config: Config = {
45
...baseConfig,
56

67
// only include "mutation" tests that cannot run on in parallel (like they are on CI) because they mutate shared state

jest.config.private.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import baseConfig from './jest.config';
1+
import type { Config } from 'jest';
2+
import baseConfig from './jest.config.ts';
23

3-
const config = {
4+
const config: Config = {
45
...baseConfig,
56

67
// only include (private) tests that cannot run on CI because they require credentials and thus exclude external contributors

tsconfig.jest-config.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"compilerOptions": {
3+
"target": "ES2021",
4+
"lib": ["ES2021", "DOM"],
5+
"module": "CommonJS",
6+
"strict": true,
7+
"noImplicitAny": true,
8+
"strictNullChecks": true,
9+
"noImplicitThis": true,
10+
"alwaysStrict": true,
11+
"noUnusedLocals": true,
12+
"esModuleInterop": true,
13+
"useUnknownInCatchVariables": true,
14+
"resolveJsonModule": true,
15+
"forceConsistentCasingInFileNames": true,
16+
"allowImportingTsExtensions": true,
17+
"emitDeclarationOnly": true,
18+
"composite": true,
19+
"outDir": "./.tsbuildinfo/jest-config"
20+
},
21+
"include": ["jest.config*.ts"]
22+
}

tsconfig.json

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,20 @@
11
{
2+
"references": [
3+
{ "path": "./tsconfig.jest-config.json" }
4+
],
25
"plugins": [
36
{
47
"name": "@0no-co/graphqlsp",
58
"schema": "./schema.graphql"
69
}
710
],
811
"include": ["src/**/*"],
9-
"exclude": ["src/graphql/generated/graphql.ts"],
12+
"exclude": ["src/graphql/generated/graphql.ts", "jest.config*.ts"],
1013
"compilerOptions": {
1114
"declaration": true,
1215
"target": "ES2021",
1316
"lib": [
14-
"ES2021",
17+
"ES2021",
1518
"DOM" // needed by wonka
1619
],
1720
"module": "CommonJS",
@@ -29,6 +32,6 @@
2932
"esModuleInterop": true,
3033
"useUnknownInCatchVariables": true,
3134
"sourceMap": true,
32-
"resolveJsonModule": true,
35+
"resolveJsonModule": true
3336
}
3437
}

0 commit comments

Comments
 (0)