feat(testing): add convert-to-inferred migration generator for jest (#26259)
<!-- Please make sure you have read the submission guidelines before posting an PR --> <!-- https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr --> <!-- Please make sure that your commit message follows our format --> <!-- Example: `fix(nx): must begin with lowercase` --> ## Current Behavior <!-- This is the behavior we have today --> ## Expected Behavior <!-- This is the behavior we should expect with the changes in this PR --> ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes #
This commit is contained in:
parent
e5d7805d4b
commit
df3c7522ea
@ -7749,6 +7749,14 @@
|
|||||||
"children": [],
|
"children": [],
|
||||||
"isExternal": false,
|
"isExternal": false,
|
||||||
"disableCollapsible": false
|
"disableCollapsible": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "convert-to-inferred",
|
||||||
|
"path": "/nx-api/jest/generators/convert-to-inferred",
|
||||||
|
"name": "convert-to-inferred",
|
||||||
|
"children": [],
|
||||||
|
"isExternal": false,
|
||||||
|
"disableCollapsible": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"isExternal": false,
|
"isExternal": false,
|
||||||
|
|||||||
@ -1130,6 +1130,15 @@
|
|||||||
"originalFilePath": "/packages/jest/src/generators/configuration/schema.json",
|
"originalFilePath": "/packages/jest/src/generators/configuration/schema.json",
|
||||||
"path": "/nx-api/jest/generators/configuration",
|
"path": "/nx-api/jest/generators/configuration",
|
||||||
"type": "generator"
|
"type": "generator"
|
||||||
|
},
|
||||||
|
"/nx-api/jest/generators/convert-to-inferred": {
|
||||||
|
"description": "Convert existing Jest project(s) using `@nx/jest:jest` executor to use `@nx/jest/plugin`.",
|
||||||
|
"file": "generated/packages/jest/generators/convert-to-inferred.json",
|
||||||
|
"hidden": false,
|
||||||
|
"name": "convert-to-inferred",
|
||||||
|
"originalFilePath": "/packages/jest/src/generators/convert-to-inferred/schema.json",
|
||||||
|
"path": "/nx-api/jest/generators/convert-to-inferred",
|
||||||
|
"type": "generator"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"path": "/nx-api/jest"
|
"path": "/nx-api/jest"
|
||||||
|
|||||||
@ -1113,6 +1113,15 @@
|
|||||||
"originalFilePath": "/packages/jest/src/generators/configuration/schema.json",
|
"originalFilePath": "/packages/jest/src/generators/configuration/schema.json",
|
||||||
"path": "jest/generators/configuration",
|
"path": "jest/generators/configuration",
|
||||||
"type": "generator"
|
"type": "generator"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"description": "Convert existing Jest project(s) using `@nx/jest:jest` executor to use `@nx/jest/plugin`.",
|
||||||
|
"file": "generated/packages/jest/generators/convert-to-inferred.json",
|
||||||
|
"hidden": false,
|
||||||
|
"name": "convert-to-inferred",
|
||||||
|
"originalFilePath": "/packages/jest/src/generators/convert-to-inferred/schema.json",
|
||||||
|
"path": "jest/generators/convert-to-inferred",
|
||||||
|
"type": "generator"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"githubRoot": "https://github.com/nrwl/nx/blob/master",
|
"githubRoot": "https://github.com/nrwl/nx/blob/master",
|
||||||
|
|||||||
@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"name": "convert-to-inferred",
|
||||||
|
"factory": "./src/generators/convert-to-inferred/convert-to-inferred",
|
||||||
|
"schema": {
|
||||||
|
"$schema": "https://json-schema.org/schema",
|
||||||
|
"$id": "NxJestConvertToInferred",
|
||||||
|
"description": "Convert existing Jest project(s) using `@nx/jest:jest` executor to use `@nx/jest/plugin`.",
|
||||||
|
"title": "Convert Jest project from executor to plugin",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"project": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The project to convert from using the `@nx/jest:jest` executor to use `@nx/jest/plugin`. If not provided, all projects using the `@nx/jest:jest` executor will be converted.",
|
||||||
|
"x-priority": "important"
|
||||||
|
},
|
||||||
|
"skipFormat": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to format files.",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"presets": []
|
||||||
|
},
|
||||||
|
"description": "Convert existing Jest project(s) using `@nx/jest:jest` executor to use `@nx/jest/plugin`.",
|
||||||
|
"implementation": "/packages/jest/src/generators/convert-to-inferred/convert-to-inferred.ts",
|
||||||
|
"aliases": [],
|
||||||
|
"hidden": false,
|
||||||
|
"path": "/packages/jest/src/generators/convert-to-inferred/schema.json",
|
||||||
|
"type": "generator"
|
||||||
|
}
|
||||||
@ -452,6 +452,7 @@
|
|||||||
- [generators](/nx-api/jest/generators)
|
- [generators](/nx-api/jest/generators)
|
||||||
- [init](/nx-api/jest/generators/init)
|
- [init](/nx-api/jest/generators/init)
|
||||||
- [configuration](/nx-api/jest/generators/configuration)
|
- [configuration](/nx-api/jest/generators/configuration)
|
||||||
|
- [convert-to-inferred](/nx-api/jest/generators/convert-to-inferred)
|
||||||
- [js](/nx-api/js)
|
- [js](/nx-api/js)
|
||||||
- [documents](/nx-api/js/documents)
|
- [documents](/nx-api/js/documents)
|
||||||
- [Overview](/nx-api/js/documents/overview)
|
- [Overview](/nx-api/js/documents/overview)
|
||||||
|
|||||||
@ -35,7 +35,7 @@ type PostTargetTransformer = (
|
|||||||
tree: Tree,
|
tree: Tree,
|
||||||
projectDetails: { projectName: string; root: string },
|
projectDetails: { projectName: string; root: string },
|
||||||
inferredTargetConfiguration: TargetConfiguration
|
inferredTargetConfiguration: TargetConfiguration
|
||||||
) => TargetConfiguration;
|
) => TargetConfiguration | Promise<TargetConfiguration>;
|
||||||
type SkipTargetFilter = (
|
type SkipTargetFilter = (
|
||||||
targetConfiguration: TargetConfiguration
|
targetConfiguration: TargetConfiguration
|
||||||
) => [boolean, string];
|
) => [boolean, string];
|
||||||
@ -85,7 +85,7 @@ class ExecutorToPluginMigrator<T> {
|
|||||||
await this.#init();
|
await this.#init();
|
||||||
if (this.#targetAndProjectsToMigrate.size > 0) {
|
if (this.#targetAndProjectsToMigrate.size > 0) {
|
||||||
for (const targetName of this.#targetAndProjectsToMigrate.keys()) {
|
for (const targetName of this.#targetAndProjectsToMigrate.keys()) {
|
||||||
this.#migrateTarget(targetName);
|
await this.#migrateTarget(targetName);
|
||||||
}
|
}
|
||||||
await this.#addPlugins();
|
await this.#addPlugins();
|
||||||
}
|
}
|
||||||
@ -105,12 +105,12 @@ class ExecutorToPluginMigrator<T> {
|
|||||||
await this.#getCreateNodesResults();
|
await this.#getCreateNodesResults();
|
||||||
}
|
}
|
||||||
|
|
||||||
#migrateTarget(targetName: string) {
|
async #migrateTarget(targetName: string) {
|
||||||
const include: string[] = [];
|
const include: string[] = [];
|
||||||
for (const projectName of this.#targetAndProjectsToMigrate.get(
|
for (const projectName of this.#targetAndProjectsToMigrate.get(
|
||||||
targetName
|
targetName
|
||||||
)) {
|
)) {
|
||||||
include.push(this.#migrateProject(projectName, targetName));
|
include.push(await this.#migrateProject(projectName, targetName));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.#pluginToAddForTarget.set(targetName, {
|
this.#pluginToAddForTarget.set(targetName, {
|
||||||
@ -120,7 +120,7 @@ class ExecutorToPluginMigrator<T> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#migrateProject(projectName: string, targetName: string) {
|
async #migrateProject(projectName: string, targetName: string) {
|
||||||
const projectFromGraph = this.#projectGraph.nodes[projectName];
|
const projectFromGraph = this.#projectGraph.nodes[projectName];
|
||||||
const projectConfig = readProjectConfiguration(this.tree, projectName);
|
const projectConfig = readProjectConfiguration(this.tree, projectName);
|
||||||
|
|
||||||
@ -141,7 +141,7 @@ class ExecutorToPluginMigrator<T> {
|
|||||||
this.#mergeInputs(projectTarget, createdTarget);
|
this.#mergeInputs(projectTarget, createdTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
projectTarget = this.#postTargetTransformer(
|
projectTarget = await this.#postTargetTransformer(
|
||||||
projectTarget,
|
projectTarget,
|
||||||
this.tree,
|
this.tree,
|
||||||
{ projectName, root: projectFromGraph.data.root },
|
{ projectName, root: projectFromGraph.data.root },
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import type { TargetConfiguration } from 'nx/src/devkit-exports';
|
import { relative, resolve } from 'node:path/posix';
|
||||||
|
import { workspaceRoot, type TargetConfiguration } from 'nx/src/devkit-exports';
|
||||||
import { interpolate } from 'nx/src/devkit-internals';
|
import { interpolate } from 'nx/src/devkit-internals';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -128,6 +129,24 @@ export function processTargetOutputs(
|
|||||||
target.outputs = targetOutputs;
|
target.outputs = targetOutputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function toProjectRelativePath(
|
||||||
|
path: string,
|
||||||
|
projectRoot: string
|
||||||
|
): string {
|
||||||
|
if (projectRoot === '.') {
|
||||||
|
// workspace and project root are the same, we add a leading './' which is
|
||||||
|
// required by some tools (e.g. Jest)
|
||||||
|
return path.startsWith('.') ? path : `./${path}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const relativePath = relative(
|
||||||
|
resolve(workspaceRoot, projectRoot),
|
||||||
|
resolve(workspaceRoot, path)
|
||||||
|
);
|
||||||
|
|
||||||
|
return relativePath.startsWith('.') ? relativePath : `./${relativePath}`;
|
||||||
|
}
|
||||||
|
|
||||||
function updateOutputRenamingOption(
|
function updateOutputRenamingOption(
|
||||||
output: string,
|
output: string,
|
||||||
option: string,
|
option: string,
|
||||||
|
|||||||
@ -14,6 +14,11 @@
|
|||||||
"schema": "./src/generators/configuration/schema.json",
|
"schema": "./src/generators/configuration/schema.json",
|
||||||
"description": "Add Jest configuration to a project.",
|
"description": "Add Jest configuration to a project.",
|
||||||
"hidden": true
|
"hidden": true
|
||||||
|
},
|
||||||
|
"convert-to-inferred": {
|
||||||
|
"factory": "./src/generators/convert-to-inferred/convert-to-inferred",
|
||||||
|
"schema": "./src/generators/convert-to-inferred/schema.json",
|
||||||
|
"description": "Convert existing Jest project(s) using `@nx/jest:jest` executor to use `@nx/jest/plugin`."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,337 @@
|
|||||||
|
import type { Config } from '@jest/types';
|
||||||
|
import {
|
||||||
|
createProjectGraphAsync,
|
||||||
|
formatFiles,
|
||||||
|
type TargetConfiguration,
|
||||||
|
type Tree,
|
||||||
|
} from '@nx/devkit';
|
||||||
|
import { migrateExecutorToPlugin } from '@nx/devkit/src/generators/plugin-migrations/executor-to-plugin-migrator';
|
||||||
|
import {
|
||||||
|
processTargetOutputs,
|
||||||
|
toProjectRelativePath,
|
||||||
|
} from '@nx/devkit/src/generators/plugin-migrations/plugin-migration-utils';
|
||||||
|
import { readConfig } from 'jest-config';
|
||||||
|
import { join, normalize, posix } from 'node:path';
|
||||||
|
import { createNodesV2, type JestPluginOptions } from '../../plugins/plugin';
|
||||||
|
import { jestConfigExtensions } from '../../utils/config/config-file';
|
||||||
|
|
||||||
|
interface Schema {
|
||||||
|
project?: string;
|
||||||
|
skipFormat?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function convertToInferred(tree: Tree, options: Schema) {
|
||||||
|
const projectGraph = await createProjectGraphAsync();
|
||||||
|
const migratedProjectsModern =
|
||||||
|
await migrateExecutorToPlugin<JestPluginOptions>(
|
||||||
|
tree,
|
||||||
|
projectGraph,
|
||||||
|
'@nx/jest:jest',
|
||||||
|
'@nx/jest/plugin',
|
||||||
|
(targetName) => ({ targetName }),
|
||||||
|
postTargetTransformer,
|
||||||
|
createNodesV2,
|
||||||
|
options.project
|
||||||
|
);
|
||||||
|
|
||||||
|
const migratedProjectsLegacy =
|
||||||
|
await migrateExecutorToPlugin<JestPluginOptions>(
|
||||||
|
tree,
|
||||||
|
projectGraph,
|
||||||
|
'@nrwl/jest:jest',
|
||||||
|
'@nx/jest/plugin',
|
||||||
|
(targetName) => ({ targetName }),
|
||||||
|
postTargetTransformer,
|
||||||
|
createNodesV2,
|
||||||
|
options.project
|
||||||
|
);
|
||||||
|
|
||||||
|
const migratedProjects =
|
||||||
|
migratedProjectsModern.size + migratedProjectsLegacy.size;
|
||||||
|
|
||||||
|
if (migratedProjects === 0) {
|
||||||
|
throw new Error('Could not find any targets to migrate.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!options.skipFormat) {
|
||||||
|
await formatFiles(tree);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function postTargetTransformer(
|
||||||
|
target: TargetConfiguration,
|
||||||
|
tree: Tree,
|
||||||
|
projectDetails: { projectName: string; root: string },
|
||||||
|
inferredTarget: TargetConfiguration
|
||||||
|
): Promise<TargetConfiguration> {
|
||||||
|
const jestConfigPath = jestConfigExtensions
|
||||||
|
.map((ext) => `jest.config.${ext}`)
|
||||||
|
.find((configFileName) =>
|
||||||
|
tree.exists(posix.join(projectDetails.root, configFileName))
|
||||||
|
);
|
||||||
|
|
||||||
|
if (target.options) {
|
||||||
|
await updateOptions(
|
||||||
|
target.options,
|
||||||
|
projectDetails.root,
|
||||||
|
tree.root,
|
||||||
|
jestConfigPath
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target.configurations) {
|
||||||
|
for (const [configName, config] of Object.entries(target.configurations)) {
|
||||||
|
await updateOptions(
|
||||||
|
config,
|
||||||
|
projectDetails.root,
|
||||||
|
tree.root,
|
||||||
|
jestConfigPath
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!Object.keys(config).length) {
|
||||||
|
delete target.configurations[configName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Object.keys(target.configurations).length) {
|
||||||
|
delete target.defaultConfiguration;
|
||||||
|
delete target.configurations;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
'defaultConfiguration' in target &&
|
||||||
|
!target.configurations?.[target.defaultConfiguration]
|
||||||
|
) {
|
||||||
|
delete target.defaultConfiguration;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (target.outputs) {
|
||||||
|
processTargetOutputs(target, [], inferredTarget, {
|
||||||
|
projectName: projectDetails.projectName,
|
||||||
|
projectRoot: projectDetails.root,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default convertToInferred;
|
||||||
|
|
||||||
|
async function updateOptions(
|
||||||
|
targetOptions: any,
|
||||||
|
projectRoot: string,
|
||||||
|
workspaceRoot: string,
|
||||||
|
defaultJestConfigPath: string | undefined
|
||||||
|
) {
|
||||||
|
const jestConfigPath = targetOptions.jestConfig ?? defaultJestConfigPath;
|
||||||
|
// inferred targets are only identified after known files that Jest would
|
||||||
|
// pick up, so we can safely remove the config options
|
||||||
|
delete targetOptions.jestConfig;
|
||||||
|
delete targetOptions.config;
|
||||||
|
|
||||||
|
// deprecated and unused
|
||||||
|
delete targetOptions.tsConfig;
|
||||||
|
|
||||||
|
if ('codeCoverage' in targetOptions) {
|
||||||
|
targetOptions.coverage = targetOptions.codeCoverage;
|
||||||
|
delete targetOptions.codeCoverage;
|
||||||
|
}
|
||||||
|
|
||||||
|
const testPathPatterns: string[] = [];
|
||||||
|
if ('testFile' in targetOptions) {
|
||||||
|
testPathPatterns.push(
|
||||||
|
toProjectRelativeRegexPath(targetOptions.testFile, projectRoot)
|
||||||
|
);
|
||||||
|
delete targetOptions.testFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('testPathPattern' in targetOptions) {
|
||||||
|
testPathPatterns.push(
|
||||||
|
...targetOptions.testPathPattern.map((pattern: string) =>
|
||||||
|
toProjectRelativeRegexPath(pattern, projectRoot)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (testPathPatterns.length > 1) {
|
||||||
|
targetOptions.testPathPattern = `\"${testPathPatterns.join('|')}\"`;
|
||||||
|
} else if (testPathPatterns.length === 1) {
|
||||||
|
targetOptions.testPathPattern = testPathPatterns[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('testPathIgnorePatterns' in targetOptions) {
|
||||||
|
if (targetOptions.testPathIgnorePatterns.length > 1) {
|
||||||
|
targetOptions.testPathIgnorePatterns = `\"${targetOptions.testPathIgnorePatterns
|
||||||
|
.map((pattern: string) =>
|
||||||
|
toProjectRelativeRegexPath(pattern, projectRoot)
|
||||||
|
)
|
||||||
|
.join('|')}\"`;
|
||||||
|
} else if (targetOptions.testPathIgnorePatterns.length === 1) {
|
||||||
|
targetOptions.testPathIgnorePatterns = toProjectRelativeRegexPath(
|
||||||
|
targetOptions.testPathIgnorePatterns[0],
|
||||||
|
projectRoot
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('testMatch' in targetOptions) {
|
||||||
|
targetOptions.testMatch = targetOptions.testMatch
|
||||||
|
.map(
|
||||||
|
(pattern: string) =>
|
||||||
|
`"${toProjectRelativeGlobPath(pattern, projectRoot)}"`
|
||||||
|
)
|
||||||
|
.join(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('findRelatedTests' in targetOptions) {
|
||||||
|
// the executor accepts a comma-separated string, while jest accepts a space-separated string
|
||||||
|
const parsedSourceFiles = targetOptions.findRelatedTests
|
||||||
|
.split(',')
|
||||||
|
.map((s: string) => toProjectRelativePath(s.trim(), projectRoot))
|
||||||
|
.join(' ');
|
||||||
|
targetOptions.args = [`--findRelatedTests ${parsedSourceFiles}`];
|
||||||
|
delete targetOptions.findRelatedTests;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('setupFile' in targetOptions) {
|
||||||
|
const setupFiles = await processSetupFiles(
|
||||||
|
targetOptions.setupFile,
|
||||||
|
targetOptions.setupFilesAfterEnv,
|
||||||
|
projectRoot,
|
||||||
|
workspaceRoot,
|
||||||
|
jestConfigPath
|
||||||
|
);
|
||||||
|
if (setupFiles.length > 1) {
|
||||||
|
targetOptions.setupFilesAfterEnv = setupFiles
|
||||||
|
.map((sf) => `"${sf}"`)
|
||||||
|
.join(' ');
|
||||||
|
} else if (setupFiles.length === 1) {
|
||||||
|
targetOptions.setupFilesAfterEnv = setupFiles[0];
|
||||||
|
} else {
|
||||||
|
// if there are no setup files, it means they are already defined in the
|
||||||
|
// jest config, so we can remove the option
|
||||||
|
delete targetOptions.setupFilesAfterEnv;
|
||||||
|
}
|
||||||
|
delete targetOptions.setupFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('outputFile' in targetOptions) {
|
||||||
|
// update the output file to be relative to the project root
|
||||||
|
targetOptions.outputFile = toProjectRelativePath(
|
||||||
|
targetOptions.outputFile,
|
||||||
|
projectRoot
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if ('coverageDirectory' in targetOptions) {
|
||||||
|
// update the coverage directory to be relative to the project root
|
||||||
|
targetOptions.coverageDirectory = toProjectRelativePath(
|
||||||
|
targetOptions.coverageDirectory,
|
||||||
|
projectRoot
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function processSetupFiles(
|
||||||
|
setupFile: string,
|
||||||
|
setupFilesAfterEnv: string[] | undefined,
|
||||||
|
projectRoot: string,
|
||||||
|
workspaceRoot: string,
|
||||||
|
jestConfigPath: string | undefined
|
||||||
|
): Promise<string[]> {
|
||||||
|
// the jest executor merges the setupFile with the setupFilesAfterEnv, so
|
||||||
|
// to keep the task working as before we resolve the setupFilesAfterEnv
|
||||||
|
// from the options or the jest config and add the setupFile to it
|
||||||
|
// https://github.com/nrwl/nx/blob/bdd3375256613340899f649eb800d22abcc9f507/packages/jest/src/executors/jest/jest.impl.ts#L107-L113
|
||||||
|
const configSetupFilesAfterEnv: string[] = [];
|
||||||
|
if (jestConfigPath) {
|
||||||
|
const jestConfig = await readConfig(
|
||||||
|
<Config.Argv>{ setupFilesAfterEnv },
|
||||||
|
join(workspaceRoot, jestConfigPath)
|
||||||
|
);
|
||||||
|
if (jestConfig.projectConfig.setupFilesAfterEnv) {
|
||||||
|
configSetupFilesAfterEnv.push(
|
||||||
|
...jestConfig.projectConfig.setupFilesAfterEnv.map((file: string) =>
|
||||||
|
toProjectRelativePath(file, projectRoot)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!configSetupFilesAfterEnv.length) {
|
||||||
|
return [toProjectRelativePath(setupFile, projectRoot)];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
isSetupFileInConfig(
|
||||||
|
configSetupFilesAfterEnv,
|
||||||
|
setupFile,
|
||||||
|
projectRoot,
|
||||||
|
workspaceRoot
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
// the setupFile is already included in the setupFilesAfterEnv
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
...configSetupFilesAfterEnv,
|
||||||
|
toProjectRelativePath(setupFile, projectRoot),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
function isSetupFileInConfig(
|
||||||
|
setupFilesAfterEnv: string[],
|
||||||
|
setupFile: string,
|
||||||
|
projectRoot: string,
|
||||||
|
workspaceRoot: string
|
||||||
|
): boolean {
|
||||||
|
const normalizePath = (f: string) =>
|
||||||
|
f.startsWith('<rootDir>')
|
||||||
|
? posix.join(workspaceRoot, projectRoot, f.slice('<rootDir>'.length))
|
||||||
|
: posix.join(workspaceRoot, projectRoot, f);
|
||||||
|
|
||||||
|
const normalizedSetupFiles = new Set(setupFilesAfterEnv.map(normalizePath));
|
||||||
|
|
||||||
|
return normalizedSetupFiles.has(
|
||||||
|
normalizePath(toProjectRelativePath(setupFile, projectRoot))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function toProjectRelativeRegexPath(path: string, projectRoot: string): string {
|
||||||
|
if (projectRoot === '.') {
|
||||||
|
// workspace and project root are the same, keep the path as is
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalizedRoot = normalize(projectRoot);
|
||||||
|
if (
|
||||||
|
new RegExp(`^(?:\\.[\\/\\\\])?${normalizedRoot}(?:[\\/\\\\])?$`).test(path)
|
||||||
|
) {
|
||||||
|
// path includes everything inside project root
|
||||||
|
return '.*';
|
||||||
|
}
|
||||||
|
|
||||||
|
const normalizedPath = normalize(path);
|
||||||
|
const startWithProjectRootRegex = new RegExp(
|
||||||
|
`^(?:\\.[\\/\\\\])?${normalizedRoot}[\\/\\\\]`
|
||||||
|
);
|
||||||
|
|
||||||
|
return startWithProjectRootRegex.test(normalizedPath)
|
||||||
|
? normalizedPath.replace(startWithProjectRootRegex, '')
|
||||||
|
: path;
|
||||||
|
}
|
||||||
|
|
||||||
|
function toProjectRelativeGlobPath(path: string, projectRoot: string): string {
|
||||||
|
if (projectRoot === '.') {
|
||||||
|
// workspace and project root are the same, keep the path as is
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// globs use forward slashes, so we make sure to normalize the path
|
||||||
|
const normalizedRoot = posix.normalize(projectRoot);
|
||||||
|
|
||||||
|
return path
|
||||||
|
.replace(new RegExp(`\/${normalizedRoot}\/`), '/')
|
||||||
|
.replace(/\*\*\/\*\*/g, '**');
|
||||||
|
}
|
||||||
19
packages/jest/src/generators/convert-to-inferred/schema.json
Normal file
19
packages/jest/src/generators/convert-to-inferred/schema.json
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json-schema.org/schema",
|
||||||
|
"$id": "NxJestConvertToInferred",
|
||||||
|
"description": "Convert existing Jest project(s) using `@nx/jest:jest` executor to use `@nx/jest/plugin`.",
|
||||||
|
"title": "Convert Jest project from executor to plugin",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"project": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The project to convert from using the `@nx/jest:jest` executor to use `@nx/jest/plugin`. If not provided, all projects using the `@nx/jest:jest` executor will be converted.",
|
||||||
|
"x-priority": "important"
|
||||||
|
},
|
||||||
|
"skipFormat": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to format files.",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user