Skip to content

Commit

Permalink
feat(misc): use @swc/jest instead of ts-jest for the ts solution …
Browse files Browse the repository at this point in the history
…setup
  • Loading branch information
leosvelperez committed Jan 23, 2025
1 parent a0cfe88 commit f8020ea
Show file tree
Hide file tree
Showing 25 changed files with 968 additions and 84 deletions.
31 changes: 31 additions & 0 deletions docs/generated/packages/jest/documents/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,9 @@ export default async function () {

If you're using `@swc/jest` and a global setup/teardown file, you have to set the `noInterop: false` and use dynamic imports within the setup function:

{% tabs %}
{% tab label="Using the config from .swcrc" %}

```typescript {% fileName="apps/<your-project>/jest.config.ts" %}
/* eslint-disable */
import { readFileSync } from 'fs';
Expand Down Expand Up @@ -344,6 +347,34 @@ export default {
};
```

{% /tab %}

{% tab label="Using the config from .spec.swcrc" %}

```typescript {% fileName="apps/<your-project>/jest.config.ts" %}
/* eslint-disable */
import { readFileSync } from 'fs';

// Reading the SWC compilation config for the spec files
const swcJestConfig = JSON.parse(
readFileSync(`${__dirname}/.spec.swcrc`, 'utf-8')
);

// Disable .swcrc look-up by SWC core because we're passing in swcJestConfig ourselves
swcJestConfig.swcrc = false;

export default {
globalSetup: '<rootDir>/src/global-setup-swc.ts',
transform: {
'^.+\\.[tj]s$': ['@swc/jest', swcJestConfig],
},
// other settings
};
```

{% /tab %}
{% /tabs %}

```typescript {% fileName="global-setup-swc.ts" %}
import { registerTsProject } from '@nx/js/src/internal';
const cleanupRegisteredPaths = registerTsProject('./tsconfig.base.json');
Expand Down
3 changes: 1 addition & 2 deletions docs/generated/packages/node/generators/application.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,7 @@
},
"swcJest": {
"type": "boolean",
"description": "Use `@swc/jest` instead `ts-jest` for faster test compilation.",
"default": false
"description": "Use `@swc/jest` instead `ts-jest` for faster test compilation."
},
"babelJest": {
"type": "boolean",
Expand Down
31 changes: 31 additions & 0 deletions docs/shared/packages/jest/jest-plugin.md
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,9 @@ export default async function () {

If you're using `@swc/jest` and a global setup/teardown file, you have to set the `noInterop: false` and use dynamic imports within the setup function:

{% tabs %}
{% tab label="Using the config from .swcrc" %}

```typescript {% fileName="apps/<your-project>/jest.config.ts" %}
/* eslint-disable */
import { readFileSync } from 'fs';
Expand Down Expand Up @@ -344,6 +347,34 @@ export default {
};
```

{% /tab %}

{% tab label="Using the config from .spec.swcrc" %}

```typescript {% fileName="apps/<your-project>/jest.config.ts" %}
/* eslint-disable */
import { readFileSync } from 'fs';

// Reading the SWC compilation config for the spec files
const swcJestConfig = JSON.parse(
readFileSync(`${__dirname}/.spec.swcrc`, 'utf-8')
);

// Disable .swcrc look-up by SWC core because we're passing in swcJestConfig ourselves
swcJestConfig.swcrc = false;

export default {
globalSetup: '<rootDir>/src/global-setup-swc.ts',
transform: {
'^.+\\.[tj]s$': ['@swc/jest', swcJestConfig],
},
// other settings
};
```

{% /tab %}
{% /tabs %}

```typescript {% fileName="global-setup-swc.ts" %}
import { registerTsProject } from '@nx/js/src/internal';
const cleanupRegisteredPaths = registerTsProject('./tsconfig.base.json');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
readJson,
Tree,
updateJson,
writeJson,
} from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import {
Expand Down Expand Up @@ -70,10 +71,24 @@ describe('@nx/eslint:workspace-rules-project', () => {
expect(tsConfig.extends).toBe('../../tsconfig.json');
});

it('should create a project with a test target', async () => {
it('should create the jest config using ts-jest', async () => {
await lintWorkspaceRulesProjectGenerator(tree);

expect(tree.exists('tools/eslint-rules/jest.config.ts')).toBeTruthy();
expect(tree.read('tools/eslint-rules/jest.config.ts', 'utf-8'))
.toMatchInlineSnapshot(`
"export default {
displayName: 'eslint-rules',
preset: '../../jest.preset.js',
transform: {
'^.+\\\\.[tj]s$': ['ts-jest', { tsconfig: '<rootDir>/tsconfig.spec.json' }],
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../coverage/tools/eslint-rules',
};
"
`);
expect(tree.exists('tools/eslint-rules/.spec.swcrc')).toBeFalsy();
});

it('should not update the required files if the project already exists', async () => {
Expand Down Expand Up @@ -104,4 +119,79 @@ describe('@nx/eslint:workspace-rules-project', () => {
customTsconfigContents
);
});

describe('TS solution setup', () => {
beforeEach(() => {
tree = createTreeWithEmptyWorkspace();
updateJson(tree, 'package.json', (json) => {
json.workspaces = ['packages/*'];
return json;
});
writeJson(tree, 'tsconfig.base.json', {
compilerOptions: { composite: true },
});
writeJson(tree, 'tsconfig.json', {
extends: './tsconfig.base.json',
files: [],
references: [],
});
});

it('should create the jest config using @swc/jest', async () => {
await lintWorkspaceRulesProjectGenerator(tree);

expect(tree.exists('tools/eslint-rules/jest.config.ts')).toBeTruthy();
expect(tree.read('tools/eslint-rules/jest.config.ts', 'utf-8'))
.toMatchInlineSnapshot(`
"/* eslint-disable */
import { readFileSync } from 'fs';
// Reading the SWC compilation config for the spec files
const swcJestConfig = JSON.parse(
readFileSync(\`\${__dirname}/.spec.swcrc\`, 'utf-8')
);
// Disable .swcrc look-up by SWC core because we're passing in swcJestConfig ourselves
swcJestConfig.swcrc = false;
export default {
displayName: 'eslint-rules',
preset: '../../jest.preset.js',
transform: {
'^.+\\\\.[tj]s$': ['@swc/jest', swcJestConfig],
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: 'test-output/jest/coverage',
};
"
`);
expect(tree.exists('tools/eslint-rules/.spec.swcrc')).toBeTruthy();
expect(tree.read('tools/eslint-rules/.spec.swcrc', 'utf-8'))
.toMatchInlineSnapshot(`
"{
"jsc": {
"target": "es2017",
"parser": {
"syntax": "typescript",
"decorators": true,
"dynamicImport": true
},
"transform": {
"decoratorMetadata": true,
"legacyDecorator": true
},
"keepClassNames": true,
"externalHelpers": true,
"loose": true
},
"module": {
"type": "es6"
},
"sourceMaps": true,
"exclude": []
}
"
`);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
} from '@nx/devkit';
import { getRelativePathToRootTsConfig } from '@nx/js';
import { addSwcRegisterDependencies } from '@nx/js/src/utils/swc/add-swc-dependencies';
import { isUsingTsSolutionSetup } from '@nx/js/src/utils/typescript/ts-solution-setup';
import { join } from 'path';
import { nxVersion, typescriptESLintVersion } from '../../utils/versions';
import { workspaceLintPluginDir } from '../../utils/workspace-lint-rules';
Expand Down Expand Up @@ -80,7 +81,7 @@ export async function lintWorkspaceRulesProjectGenerator(
supportTsx: false,
skipSerializers: true,
setupFile: 'none',
compiler: 'tsc',
compiler: isUsingTsSolutionSetup(tree) ? 'swc' : 'tsc',
skipFormat: true,
})
);
Expand Down
Loading

0 comments on commit f8020ea

Please sign in to comment.