feat(testing): add ability to split jest tests (#22662)
This commit is contained in:
parent
4cd1808e48
commit
fd7cf38c20
@ -40,6 +40,54 @@ npm add -D @nx/jest
|
|||||||
{% /tab %}
|
{% /tab %}
|
||||||
{% /tabs %}
|
{% /tabs %}
|
||||||
|
|
||||||
|
#### Configuring @nx/jest/plugin for both E2E and Unit Tests
|
||||||
|
|
||||||
|
While Jest is most often used for unit tests, there are cases where it can be used for e2e tests as well as unit tests
|
||||||
|
within the same workspace. In this case, you can configure the `@nx/jest/plugin` twice for the different cases.
|
||||||
|
|
||||||
|
```json {% fileName="nx.json" %}
|
||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"plugin": "@nx/jest/plugin",
|
||||||
|
"exclude": ["e2e/**/*"],
|
||||||
|
"options": {
|
||||||
|
"targetName": "test"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"plugin": "@nx/jest/plugin",
|
||||||
|
"include": ["e2e/**/*"],
|
||||||
|
"options": {
|
||||||
|
"targetName": "e2e-local",
|
||||||
|
"ciTargetName": "e2e-ci"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Splitting E2E Tests
|
||||||
|
|
||||||
|
If Jest is used to run E2E tests, you can enable [splitting the tasks](/ci/features/split-e2e-tasks) by file to get
|
||||||
|
improved caching, distribution, and retrying flaky tests. Enable this, by providing a `ciTargetName`. This will create a
|
||||||
|
target with that name which can be used in CI to run the tests for each file in a distributed fashion.
|
||||||
|
|
||||||
|
```json {% fileName="nx.json" %}
|
||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"plugin": "@nx/jest/plugin",
|
||||||
|
"include": ["e2e/**/*"],
|
||||||
|
"options": {
|
||||||
|
"targetName": "e2e-local",
|
||||||
|
"ciTargetName": "e2e-ci"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### How @nx/jest Infers Tasks
|
### How @nx/jest Infers Tasks
|
||||||
|
|
||||||
{% callout type="note" title="Inferred Tasks" %}
|
{% callout type="note" title="Inferred Tasks" %}
|
||||||
|
|||||||
@ -11,7 +11,7 @@ You could manually address these problems by splitting your e2e tests into small
|
|||||||
|
|
||||||
## Set up
|
## Set up
|
||||||
|
|
||||||
To enable automatically split e2e tasks, you need to turn on [inferred tasks](/concepts/inferred-tasks#existing-nx-workspaces) for the [@nx/cypress](/nx-api/cypress) or [@nx/playwright](/nx-api/playwright) plugins. Run this command to set up inferred tasks:
|
To enable automatically split e2e tasks, you need to turn on [inferred tasks](/concepts/inferred-tasks#existing-nx-workspaces) for the [@nx/cypress](/nx-api/cypress), [@nx/playwright](/nx-api/playwright), or [@nx/playwright](/nx-api/jest) plugins. Run this command to set up inferred tasks:
|
||||||
|
|
||||||
{% tabs %}
|
{% tabs %}
|
||||||
{% tab label="Cypress" %}
|
{% tab label="Cypress" %}
|
||||||
@ -27,6 +27,13 @@ nx add @nx/cypress
|
|||||||
nx add @nx/playwright
|
nx add @nx/playwright
|
||||||
```
|
```
|
||||||
|
|
||||||
|
{% /tab %}
|
||||||
|
{% tab label="Jest" %}
|
||||||
|
|
||||||
|
```shell {% skipRescope=true %}
|
||||||
|
nx add @nx/jest
|
||||||
|
```
|
||||||
|
|
||||||
{% /tab %}
|
{% /tab %}
|
||||||
{% /tabs %}
|
{% /tabs %}
|
||||||
|
|
||||||
@ -34,10 +41,11 @@ This command will register the appropriate plugin in the `plugins` array of `nx.
|
|||||||
|
|
||||||
## Manual Configuration
|
## Manual Configuration
|
||||||
|
|
||||||
If you are already using the `@nx/cypress` or `@nx/playwright` plugin, you need to manually add the appropriate configuration to the `plugins` array of `nx.json`. Follow the instructions for the plugin you are using:
|
If you are already using the `@nx/cypress`, `@nx/playwright`, or `@nx/jest` plugin, you need to manually add the appropriate configuration to the `plugins` array of `nx.json`. Follow the instructions for the plugin you are using:
|
||||||
|
|
||||||
- [Configure Cypress Task Splitting](/nx-api/cypress#nxcypress-configuration)
|
- [Configure Cypress Task Splitting](/nx-api/cypress#nxcypress-configuration)
|
||||||
- [Configure Playwright Task Splitting](/nx-api/playwright#nxplaywright-configuration)
|
- [Configure Playwright Task Splitting](/nx-api/playwright#nxplaywright-configuration)
|
||||||
|
- [Configure Jest Task Splitting](/nx-api/jest#splitting-e2e-tests)
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
|||||||
@ -40,6 +40,54 @@ npm add -D @nx/jest
|
|||||||
{% /tab %}
|
{% /tab %}
|
||||||
{% /tabs %}
|
{% /tabs %}
|
||||||
|
|
||||||
|
#### Configuring @nx/jest/plugin for both E2E and Unit Tests
|
||||||
|
|
||||||
|
While Jest is most often used for unit tests, there are cases where it can be used for e2e tests as well as unit tests
|
||||||
|
within the same workspace. In this case, you can configure the `@nx/jest/plugin` twice for the different cases.
|
||||||
|
|
||||||
|
```json {% fileName="nx.json" %}
|
||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"plugin": "@nx/jest/plugin",
|
||||||
|
"exclude": ["e2e/**/*"],
|
||||||
|
"options": {
|
||||||
|
"targetName": "test"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"plugin": "@nx/jest/plugin",
|
||||||
|
"include": ["e2e/**/*"],
|
||||||
|
"options": {
|
||||||
|
"targetName": "e2e-local",
|
||||||
|
"ciTargetName": "e2e-ci"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Splitting E2E Tests
|
||||||
|
|
||||||
|
If Jest is used to run E2E tests, you can enable [splitting the tasks](/ci/features/split-e2e-tasks) by file to get
|
||||||
|
improved caching, distribution, and retrying flaky tests. Enable this, by providing a `ciTargetName`. This will create a
|
||||||
|
target with that name which can be used in CI to run the tests for each file in a distributed fashion.
|
||||||
|
|
||||||
|
```json {% fileName="nx.json" %}
|
||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"plugin": "@nx/jest/plugin",
|
||||||
|
"include": ["e2e/**/*"],
|
||||||
|
"options": {
|
||||||
|
"targetName": "e2e-local",
|
||||||
|
"ciTargetName": "e2e-ci"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### How @nx/jest Infers Tasks
|
### How @nx/jest Infers Tasks
|
||||||
|
|
||||||
{% callout type="note" title="Inferred Tasks" %}
|
{% callout type="note" title="Inferred Tasks" %}
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import {
|
|||||||
runCLIAsync,
|
runCLIAsync,
|
||||||
uniq,
|
uniq,
|
||||||
updateFile,
|
updateFile,
|
||||||
|
updateJson,
|
||||||
} from '@nx/e2e/utils';
|
} from '@nx/e2e/utils';
|
||||||
|
|
||||||
describe('Jest', () => {
|
describe('Jest', () => {
|
||||||
@ -147,4 +148,19 @@ describe('Jest', () => {
|
|||||||
'Test Suites: 1 passed, 1 total'
|
'Test Suites: 1 passed, 1 total'
|
||||||
);
|
);
|
||||||
}, 90000);
|
}, 90000);
|
||||||
|
|
||||||
|
it('should be able to run e2e tests split by tasks', async () => {
|
||||||
|
const libName = uniq('lib');
|
||||||
|
runCLI(`generate @nx/js:lib ${libName} --unitTestRunner=jest`);
|
||||||
|
updateJson('nx.json', (json) => {
|
||||||
|
const jestPlugin = json.plugins.find(
|
||||||
|
(plugin) => plugin.plugin === '@nx/jest/plugin'
|
||||||
|
);
|
||||||
|
|
||||||
|
jestPlugin.options.ciTargetName = 'e2e-ci';
|
||||||
|
return json;
|
||||||
|
});
|
||||||
|
|
||||||
|
await runCLIAsync(`e2e-ci ${libName}`);
|
||||||
|
}, 90000);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -104,7 +104,7 @@ describe('Remix E2E Tests', () => {
|
|||||||
expect(result).toContain(`Successfully ran target test`);
|
expect(result).toContain(`Successfully ran target test`);
|
||||||
|
|
||||||
const reactResult = runCLI(`test ${reactapp}`);
|
const reactResult = runCLI(`test ${reactapp}`);
|
||||||
expect(result).toContain(`Successfully ran target test`);
|
expect(reactResult).toContain(`Successfully ran target test`);
|
||||||
}, 120_000);
|
}, 120_000);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -206,6 +206,7 @@
|
|||||||
"jest-environment-jsdom": "29.4.3",
|
"jest-environment-jsdom": "29.4.3",
|
||||||
"jest-environment-node": "^29.4.1",
|
"jest-environment-node": "^29.4.1",
|
||||||
"jest-resolve": "^29.4.1",
|
"jest-resolve": "^29.4.1",
|
||||||
|
"jest-runtime": "^29.4.1",
|
||||||
"jest-util": "^29.4.1",
|
"jest-util": "^29.4.1",
|
||||||
"js-tokens": "^4.0.0",
|
"js-tokens": "^4.0.0",
|
||||||
"js-yaml": "4.1.0",
|
"js-yaml": "4.1.0",
|
||||||
|
|||||||
@ -24,7 +24,9 @@ describe('@nx/jest/plugin', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
await tempFs.createFiles({
|
await tempFs.createFiles({
|
||||||
'proj/jest.config.js': '',
|
'proj/jest.config.js': `module.exports = {}`,
|
||||||
|
'proj/src/unit.spec.ts': '',
|
||||||
|
'proj/src/ignore.spec.ts': '',
|
||||||
'proj/project.json': '{}',
|
'proj/project.json': '{}',
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -50,6 +52,7 @@ describe('@nx/jest/plugin', () => {
|
|||||||
|
|
||||||
expect(nodes.projects.proj).toMatchInlineSnapshot(`
|
expect(nodes.projects.proj).toMatchInlineSnapshot(`
|
||||||
{
|
{
|
||||||
|
"metadata": undefined,
|
||||||
"root": "proj",
|
"root": "proj",
|
||||||
"targets": {
|
"targets": {
|
||||||
"test": {
|
"test": {
|
||||||
@ -64,6 +67,122 @@ describe('@nx/jest/plugin', () => {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Run Jest Tests",
|
||||||
|
"technologies": [
|
||||||
|
"jest",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "proj",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{workspaceRoot}/coverage",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create test-ci targets based on jest.config.ts', async () => {
|
||||||
|
mockJestConfig(
|
||||||
|
{
|
||||||
|
coverageDirectory: '../coverage',
|
||||||
|
testMatch: ['**/*.spec.ts'],
|
||||||
|
testPathIgnorePatterns: ['ignore.spec.ts'],
|
||||||
|
},
|
||||||
|
context
|
||||||
|
);
|
||||||
|
const nodes = await createNodesFunction(
|
||||||
|
'proj/jest.config.js',
|
||||||
|
{
|
||||||
|
targetName: 'test',
|
||||||
|
ciTargetName: 'test-ci',
|
||||||
|
},
|
||||||
|
context
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(nodes.projects.proj).toMatchInlineSnapshot(`
|
||||||
|
{
|
||||||
|
"metadata": {
|
||||||
|
"targetGroups": {
|
||||||
|
"E2E (CI)": [
|
||||||
|
"test-ci",
|
||||||
|
"test-ci--src/unit.spec.ts",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"root": "proj",
|
||||||
|
"targets": {
|
||||||
|
"test": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "jest",
|
||||||
|
"inputs": [
|
||||||
|
"default",
|
||||||
|
"^production",
|
||||||
|
{
|
||||||
|
"externalDependencies": [
|
||||||
|
"jest",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Run Jest Tests",
|
||||||
|
"technologies": [
|
||||||
|
"jest",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"cwd": "proj",
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{workspaceRoot}/coverage",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"test-ci": {
|
||||||
|
"cache": true,
|
||||||
|
"dependsOn": [
|
||||||
|
"test-ci--src/unit.spec.ts",
|
||||||
|
],
|
||||||
|
"executor": "nx:noop",
|
||||||
|
"inputs": [
|
||||||
|
"default",
|
||||||
|
"^production",
|
||||||
|
{
|
||||||
|
"externalDependencies": [
|
||||||
|
"jest",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Run Jest Tests in CI",
|
||||||
|
"technologies": [
|
||||||
|
"jest",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"outputs": [
|
||||||
|
"{workspaceRoot}/coverage",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"test-ci--src/unit.spec.ts": {
|
||||||
|
"cache": true,
|
||||||
|
"command": "jest src/unit.spec.ts",
|
||||||
|
"inputs": [
|
||||||
|
"default",
|
||||||
|
"^production",
|
||||||
|
{
|
||||||
|
"externalDependencies": [
|
||||||
|
"jest",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"description": "Run Jest Tests in src/unit.spec.ts",
|
||||||
|
"technologies": [
|
||||||
|
"jest",
|
||||||
|
],
|
||||||
|
},
|
||||||
"options": {
|
"options": {
|
||||||
"cwd": "proj",
|
"cwd": "proj",
|
||||||
},
|
},
|
||||||
|
|||||||
@ -4,13 +4,13 @@ import {
|
|||||||
CreateNodesContext,
|
CreateNodesContext,
|
||||||
joinPathFragments,
|
joinPathFragments,
|
||||||
NxJsonConfiguration,
|
NxJsonConfiguration,
|
||||||
|
ProjectConfiguration,
|
||||||
readJsonFile,
|
readJsonFile,
|
||||||
TargetConfiguration,
|
TargetConfiguration,
|
||||||
writeJsonFile,
|
writeJsonFile,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { dirname, join, relative, resolve } from 'path';
|
import { dirname, join, normalize, relative, resolve } from 'path';
|
||||||
|
|
||||||
import { readTargetDefaultsForTarget } from 'nx/src/project-graph/utils/project-configuration-utils';
|
|
||||||
import { getNamedInputs } from '@nx/devkit/src/utils/get-named-inputs';
|
import { getNamedInputs } from '@nx/devkit/src/utils/get-named-inputs';
|
||||||
import { existsSync, readdirSync, readFileSync } from 'fs';
|
import { existsSync, readdirSync, readFileSync } from 'fs';
|
||||||
import { readConfig } from 'jest-config';
|
import { readConfig } from 'jest-config';
|
||||||
@ -22,26 +22,21 @@ import { minimatch } from 'minimatch';
|
|||||||
|
|
||||||
export interface JestPluginOptions {
|
export interface JestPluginOptions {
|
||||||
targetName?: string;
|
targetName?: string;
|
||||||
|
ciTargetName?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cachePath = join(projectGraphCacheDirectory, 'jest.hash');
|
const cachePath = join(projectGraphCacheDirectory, 'jest.hash');
|
||||||
const targetsCache = existsSync(cachePath) ? readTargetsCache() : {};
|
const targetsCache = existsSync(cachePath) ? readTargetsCache() : {};
|
||||||
|
|
||||||
const calculatedTargets: Record<
|
type JestTargets = Awaited<ReturnType<typeof buildJestTargets>>;
|
||||||
string,
|
|
||||||
Record<string, TargetConfiguration>
|
|
||||||
> = {};
|
|
||||||
|
|
||||||
function readTargetsCache(): Record<
|
const calculatedTargets: JestTargets = {};
|
||||||
string,
|
|
||||||
Record<string, TargetConfiguration>
|
function readTargetsCache(): Record<string, JestTargets> {
|
||||||
> {
|
|
||||||
return readJsonFile(cachePath);
|
return readJsonFile(cachePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
function writeTargetsToCache(
|
function writeTargetsToCache(targets: JestTargets) {
|
||||||
targets: Record<string, Record<string, TargetConfiguration>>
|
|
||||||
) {
|
|
||||||
writeJsonFile(cachePath, targets);
|
writeJsonFile(cachePath, targets);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,17 +91,18 @@ export const createNodes: CreateNodes<JestPluginOptions> = [
|
|||||||
options = normalizeOptions(options);
|
options = normalizeOptions(options);
|
||||||
|
|
||||||
const hash = calculateHashForCreateNodes(projectRoot, options, context);
|
const hash = calculateHashForCreateNodes(projectRoot, options, context);
|
||||||
const targets =
|
const { targets, metadata } =
|
||||||
targetsCache[hash] ??
|
targetsCache[hash] ??
|
||||||
(await buildJestTargets(configFilePath, projectRoot, options, context));
|
(await buildJestTargets(configFilePath, projectRoot, options, context));
|
||||||
|
|
||||||
calculatedTargets[hash] = targets;
|
calculatedTargets[hash] = { targets, metadata };
|
||||||
|
|
||||||
return {
|
return {
|
||||||
projects: {
|
projects: {
|
||||||
[projectRoot]: {
|
[projectRoot]: {
|
||||||
root: projectRoot,
|
root: projectRoot,
|
||||||
targets: targets,
|
targets,
|
||||||
|
metadata,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -118,7 +114,7 @@ async function buildJestTargets(
|
|||||||
projectRoot: string,
|
projectRoot: string,
|
||||||
options: JestPluginOptions,
|
options: JestPluginOptions,
|
||||||
context: CreateNodesContext
|
context: CreateNodesContext
|
||||||
) {
|
): Promise<Pick<ProjectConfiguration, 'targets' | 'metadata'>> {
|
||||||
const config = await readConfig(
|
const config = await readConfig(
|
||||||
{
|
{
|
||||||
_: [],
|
_: [],
|
||||||
@ -127,12 +123,6 @@ async function buildJestTargets(
|
|||||||
resolve(context.workspaceRoot, configFilePath)
|
resolve(context.workspaceRoot, configFilePath)
|
||||||
);
|
);
|
||||||
|
|
||||||
const targetDefaults = readTargetDefaultsForTarget(
|
|
||||||
options.targetName,
|
|
||||||
context.nxJsonConfiguration.targetDefaults,
|
|
||||||
'nx:run-commands'
|
|
||||||
);
|
|
||||||
|
|
||||||
const namedInputs = getNamedInputs(projectRoot, context);
|
const namedInputs = getNamedInputs(projectRoot, context);
|
||||||
|
|
||||||
const targets: Record<string, TargetConfiguration> = {};
|
const targets: Record<string, TargetConfiguration> = {};
|
||||||
@ -142,19 +132,84 @@ async function buildJestTargets(
|
|||||||
options: {
|
options: {
|
||||||
cwd: projectRoot,
|
cwd: projectRoot,
|
||||||
},
|
},
|
||||||
|
metadata: {
|
||||||
|
technologies: ['jest'],
|
||||||
|
description: 'Run Jest Tests',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!targetDefaults?.cache) {
|
const cache = (target.cache = true);
|
||||||
target.cache = true;
|
const inputs = (target.inputs = getInputs(namedInputs));
|
||||||
|
const outputs = (target.outputs = getOutputs(projectRoot, config, context));
|
||||||
|
|
||||||
|
let metadata: ProjectConfiguration['metadata'];
|
||||||
|
if (options?.ciTargetName) {
|
||||||
|
// Resolve the version of `jest-runtime` that `jest` is using.
|
||||||
|
const jestPath = require.resolve('jest');
|
||||||
|
const jest = require(jestPath) as typeof import('jest');
|
||||||
|
// nx-ignore-next-line
|
||||||
|
const { default: Runtime } = require(require.resolve('jest-runtime', {
|
||||||
|
paths: [dirname(jestPath)],
|
||||||
|
// nx-ignore-next-line
|
||||||
|
})) as typeof import('jest-runtime');
|
||||||
|
|
||||||
|
const context = await Runtime.createContext(config.projectConfig, {
|
||||||
|
maxWorkers: 1,
|
||||||
|
watchman: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const source = new jest.SearchSource(context);
|
||||||
|
|
||||||
|
const specs = await source.getTestPaths(config.globalConfig);
|
||||||
|
|
||||||
|
const testPaths = new Set(specs.tests.map(({ path }) => path));
|
||||||
|
|
||||||
|
if (testPaths.size > 0) {
|
||||||
|
const groupName = 'E2E (CI)';
|
||||||
|
const targetGroup = [];
|
||||||
|
metadata = {
|
||||||
|
targetGroups: {
|
||||||
|
[groupName]: targetGroup,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const dependsOn: string[] = [];
|
||||||
|
|
||||||
|
targets[options.ciTargetName] = {
|
||||||
|
executor: 'nx:noop',
|
||||||
|
cache: true,
|
||||||
|
inputs,
|
||||||
|
outputs,
|
||||||
|
dependsOn,
|
||||||
|
metadata: {
|
||||||
|
technologies: ['jest'],
|
||||||
|
description: 'Run Jest Tests in CI',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
targetGroup.push(options.ciTargetName);
|
||||||
|
|
||||||
|
for (const testPath of testPaths) {
|
||||||
|
const relativePath = normalize(relative(projectRoot, testPath));
|
||||||
|
const targetName = `${options.ciTargetName}--${relativePath}`;
|
||||||
|
dependsOn.push(targetName);
|
||||||
|
targets[targetName] = {
|
||||||
|
command: `jest ${relativePath}`,
|
||||||
|
cache,
|
||||||
|
inputs,
|
||||||
|
outputs,
|
||||||
|
options: {
|
||||||
|
cwd: projectRoot,
|
||||||
|
},
|
||||||
|
metadata: {
|
||||||
|
technologies: ['jest'],
|
||||||
|
description: `Run Jest Tests in ${relativePath}`,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
targetGroup.push(targetName);
|
||||||
}
|
}
|
||||||
if (!targetDefaults?.inputs) {
|
|
||||||
target.inputs = getInputs(namedInputs);
|
|
||||||
}
|
}
|
||||||
if (!targetDefaults?.outputs) {
|
|
||||||
target.outputs = getOutputs(projectRoot, config, context);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return targets;
|
return { targets, metadata };
|
||||||
}
|
}
|
||||||
|
|
||||||
function getInputs(
|
function getInputs(
|
||||||
@ -200,6 +255,7 @@ function getOutputs(
|
|||||||
|
|
||||||
return outputs;
|
return outputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalizeOptions(options: JestPluginOptions): JestPluginOptions {
|
function normalizeOptions(options: JestPluginOptions): JestPluginOptions {
|
||||||
options ??= {};
|
options ??= {};
|
||||||
options.targetName ??= 'test';
|
options.targetName ??= 'test';
|
||||||
|
|||||||
708
pnpm-lock.yaml
generated
708
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user