fix(testing): deprecate cypress tsconfig option (#17165)
This commit is contained in:
parent
5af50b966e
commit
f74ff4bddc
@ -32,6 +32,7 @@
|
||||
"default": false
|
||||
},
|
||||
"tsConfig": {
|
||||
"x-deprecated": "This option no longer has any effect. Cypress supports typescript out of the box. Add any options directly to <projectRoot>/tsconfig.json or <projectRoot>/cypress/tsconfig.json",
|
||||
"type": "string",
|
||||
"description": "The path of the Cypress tsconfig configuration json file.",
|
||||
"x-completion-type": "file",
|
||||
|
||||
@ -53,6 +53,12 @@
|
||||
"version": "16.2.0-beta.0",
|
||||
"description": "Normalize tsconfig.cy.json files to be located at '<projectRoot>/cypress/tsconfig.json'",
|
||||
"implementation": "./src/migrations/update-16-2-0/update-cy-tsconfig"
|
||||
},
|
||||
"update-16-3-0-remove-old-tsconfigs": {
|
||||
"cli": "nx",
|
||||
"version": "16.4.0-beta.10",
|
||||
"description": "Remove tsconfig.e2e.json and add settings to project tsconfig.json. tsConfigs executor option is now deprecated. The project level tsconfig.json file should be used instead.",
|
||||
"implementation": "./src/migrations/update-16-4-0/tsconfig-sourcemaps"
|
||||
}
|
||||
},
|
||||
"packageJsonUpdates": {
|
||||
|
||||
@ -24,7 +24,6 @@ export type Json = { [k: string]: any };
|
||||
export interface CypressExecutorOptions extends Json {
|
||||
cypressConfig: string;
|
||||
watch?: boolean;
|
||||
tsConfig?: string;
|
||||
devServerTarget?: string;
|
||||
headed?: boolean;
|
||||
/**
|
||||
@ -91,11 +90,6 @@ function normalizeOptions(
|
||||
context: ExecutorContext
|
||||
): NormalizedCypressExecutorOptions {
|
||||
options.env = options.env || {};
|
||||
if (options.tsConfig) {
|
||||
const tsConfigPath = join(context.root, options.tsConfig);
|
||||
options.env.tsConfig = tsConfigPath;
|
||||
process.env.TS_NODE_PROJECT = tsConfigPath;
|
||||
}
|
||||
if (options.testingType === 'component') {
|
||||
const project = context?.projectGraph?.nodes?.[context.projectName];
|
||||
if (project?.data?.root) {
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
"default": false
|
||||
},
|
||||
"tsConfig": {
|
||||
"x-deprecated": "This option no longer has any effect. Cypress supports typescript out of the box. Add any options directly to <projectRoot>/tsconfig.json or <projectRoot>/cypress/tsconfig.json",
|
||||
"type": "string",
|
||||
"description": "The path of the Cypress tsconfig configuration json file.",
|
||||
"x-completion-type": "file",
|
||||
|
||||
@ -0,0 +1,175 @@
|
||||
import {
|
||||
Tree,
|
||||
addProjectConfiguration,
|
||||
readJson,
|
||||
readProjectConfiguration,
|
||||
updateJson,
|
||||
updateProjectConfiguration,
|
||||
} from '@nx/devkit';
|
||||
import { createTreeWithEmptyWorkspace } from 'nx/src/devkit-testing-exports';
|
||||
import { fixLegacyCypressTsconfig } from './tsconfig-sourcemaps';
|
||||
|
||||
describe('Cypress Migration: tsconfig-sourcemaps', () => {
|
||||
let tree: Tree;
|
||||
|
||||
beforeEach(() => {
|
||||
tree = createTreeWithEmptyWorkspace();
|
||||
});
|
||||
|
||||
it('should remove tsconfig.e2e.json and update tsconfig.json', async () => {
|
||||
addLegacyProject(tree);
|
||||
|
||||
await fixLegacyCypressTsconfig(tree);
|
||||
expect(readProjectConfiguration(tree, 'legacy-e2e').targets.e2e)
|
||||
.toMatchInlineSnapshot(`
|
||||
{
|
||||
"configurations": {
|
||||
"production": {
|
||||
"devServerTarget": "legacy-e2e:serve:production",
|
||||
},
|
||||
},
|
||||
"executor": "@nx/cypress:cypress",
|
||||
"options": {
|
||||
"cypressConfig": "apps/legacy-e2e/cypress.config.ts",
|
||||
"devServerTarget": "legacy-e2e:serve",
|
||||
"testingType": "e2e",
|
||||
},
|
||||
}
|
||||
`);
|
||||
expect(readJson(tree, 'apps/legacy-e2e/tsconfig.json'))
|
||||
.toMatchInlineSnapshot(`
|
||||
{
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"resolveJsonModule": true,
|
||||
"sourceMap": false,
|
||||
"strict": true,
|
||||
"types": [
|
||||
"cypress",
|
||||
"node",
|
||||
],
|
||||
},
|
||||
"exclude": [],
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"files": [],
|
||||
"include": [
|
||||
"cypress.ci.1.config.ts",
|
||||
"cypress.ci.2.config.ts",
|
||||
"cypress.ci.3.config.ts",
|
||||
"cypress.ci.4.config.ts",
|
||||
"src/**/*.ts",
|
||||
"cypress.config.ts",
|
||||
],
|
||||
"references": [],
|
||||
}
|
||||
`);
|
||||
expect(tree.exists('apps/legacy-e2e/tsconfig.e2e.json')).toBeFalsy();
|
||||
expect(tree.exists('apps/legacy-e2e/tsconfig.e2e.prod.json')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should do nothing if tsconfig option is not used', async () => {
|
||||
addLegacyProject(tree);
|
||||
|
||||
tree.delete('apps/legacy-e2e/tsconfig.e2e.json');
|
||||
tree.delete('apps/legacy-e2e/tsconfig.e2e.prod.json');
|
||||
const pc = readProjectConfiguration(tree, 'legacy-e2e');
|
||||
|
||||
delete pc.targets.e2e.options.tsConfig;
|
||||
delete pc.targets.e2e.configurations;
|
||||
|
||||
const existingProjectConfig = pc.targets.e2e;
|
||||
|
||||
updateProjectConfiguration(tree, 'legacy-e2e', pc);
|
||||
|
||||
updateJson(tree, 'apps/legacy-e2e/tsconfig.json', (json) => {
|
||||
json.references = [];
|
||||
return json;
|
||||
});
|
||||
|
||||
const existingTsConfig = readJson(tree, 'apps/legacy-e2e/tsconfig.json');
|
||||
|
||||
await fixLegacyCypressTsconfig(tree);
|
||||
|
||||
expect(readProjectConfiguration(tree, 'legacy-e2e').targets.e2e).toEqual(
|
||||
existingProjectConfig
|
||||
);
|
||||
expect(readJson(tree, 'apps/legacy-e2e/tsconfig.json')).toEqual(
|
||||
existingTsConfig
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
function addLegacyProject(tree: Tree) {
|
||||
addProjectConfiguration(tree, 'legacy-e2e', {
|
||||
root: 'apps/legacy-e2e',
|
||||
sourceRoot: 'apps/legacy-e2e/src',
|
||||
targets: {
|
||||
e2e: {
|
||||
executor: '@nx/cypress:cypress',
|
||||
options: {
|
||||
cypressConfig: 'apps/legacy-e2e/cypress.config.ts',
|
||||
tsConfig: 'apps/legacy-e2e/tsconfig.e2e.json',
|
||||
devServerTarget: 'legacy-e2e:serve',
|
||||
testingType: 'e2e',
|
||||
},
|
||||
configurations: {
|
||||
production: {
|
||||
devServerTarget: 'legacy-e2e:serve:production',
|
||||
tsConfig: 'apps/legacy-e2e/tsconfig.e2e.prod.json',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
tree.write(
|
||||
'apps/legacy-e2e/tsconfig.e2e.json',
|
||||
JSON.stringify({
|
||||
extends: './tsconfig.json',
|
||||
compilerOptions: {
|
||||
sourceMap: false,
|
||||
outDir: '../../dist/out-tsc',
|
||||
types: ['cypress', 'node'],
|
||||
},
|
||||
include: ['src/**/*.ts', 'cypress.config.ts'],
|
||||
})
|
||||
);
|
||||
tree.write(
|
||||
'apps/legacy-e2e/tsconfig.e2e.prod.json',
|
||||
JSON.stringify({
|
||||
extends: './tsconfig.e2e.json',
|
||||
compilerOptions: {
|
||||
sourceMap: false,
|
||||
outDir: '../../dist/out-tsc',
|
||||
types: ['cypress', 'node'],
|
||||
strict: true,
|
||||
},
|
||||
include: ['src/**/*.ts', 'cypress.config.ts'],
|
||||
})
|
||||
);
|
||||
tree.write(
|
||||
'apps/legacy-e2e/tsconfig.json',
|
||||
JSON.stringify({
|
||||
extends: '../../tsconfig.base.json',
|
||||
compilerOptions: {
|
||||
types: ['cypress', 'node'],
|
||||
resolveJsonModule: true,
|
||||
},
|
||||
include: [
|
||||
'cypress.ci.1.config.ts',
|
||||
'cypress.ci.2.config.ts',
|
||||
'cypress.ci.3.config.ts',
|
||||
'cypress.ci.4.config.ts',
|
||||
],
|
||||
files: [],
|
||||
references: [
|
||||
{
|
||||
path: './tsconfig.e2e.json',
|
||||
},
|
||||
{
|
||||
path: './tsconfig.e2e.prod.json',
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
}
|
||||
@ -0,0 +1,102 @@
|
||||
import { forEachExecutorOptions } from '@nx/devkit/src/generators/executor-options-utils';
|
||||
import { CypressExecutorOptions } from '../../executors/cypress/cypress.impl';
|
||||
import {
|
||||
updateJson,
|
||||
Tree,
|
||||
getProjects,
|
||||
joinPathFragments,
|
||||
readJson,
|
||||
updateProjectConfiguration,
|
||||
formatFiles,
|
||||
} from '@nx/devkit';
|
||||
import { posix } from 'path';
|
||||
|
||||
export async function fixLegacyCypressTsconfig(tree: Tree) {
|
||||
const projects = getProjects(tree);
|
||||
forEachExecutorOptions<CypressExecutorOptions>(
|
||||
tree,
|
||||
'@nx/cypress:cypress',
|
||||
(options, projectName, targetName, configName) => {
|
||||
const projectConfig = projects.get(projectName);
|
||||
|
||||
if (
|
||||
options.testingType !== 'e2e' &&
|
||||
projectConfig.targets[targetName]?.options?.testingType !== 'e2e'
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tsconfigToRemove =
|
||||
options.tsConfig ??
|
||||
joinPathFragments(projectConfig.root, 'tsconfig.e2e.json');
|
||||
|
||||
const projectLevelConfigPath = joinPathFragments(
|
||||
projectConfig.root,
|
||||
'tsconfig.json'
|
||||
);
|
||||
|
||||
if (
|
||||
!tree.exists(projectLevelConfigPath) ||
|
||||
!tree.exists(tsconfigToRemove)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (tsconfigToRemove === projectLevelConfigPath) {
|
||||
updateJson(tree, projectLevelConfigPath, (json) => {
|
||||
json.compilerOptions = {
|
||||
sourceMap: false,
|
||||
...json.compilerOptions,
|
||||
};
|
||||
return json;
|
||||
});
|
||||
} else {
|
||||
const e2eConfig = readJson(tree, tsconfigToRemove);
|
||||
|
||||
updateJson(tree, projectLevelConfigPath, (json) => {
|
||||
json.compilerOptions = {
|
||||
sourceMap: false,
|
||||
...json.compilerOptions,
|
||||
...e2eConfig.compilerOptions,
|
||||
};
|
||||
json.files = Array.from(
|
||||
new Set([...(json.files ?? []), ...(e2eConfig.files ?? [])])
|
||||
);
|
||||
json.include = Array.from(
|
||||
new Set([...(json.include ?? []), ...(e2eConfig.include ?? [])])
|
||||
);
|
||||
json.exclude = Array.from(
|
||||
new Set([...(json.exclude ?? []), ...(e2eConfig.exclude ?? [])])
|
||||
);
|
||||
|
||||
// these paths will always be 'unix style'
|
||||
// and on windows relative will not work on these paths
|
||||
const tsConfigFromProjRoot = posix.relative(
|
||||
projectConfig.root,
|
||||
tsconfigToRemove
|
||||
);
|
||||
|
||||
json.references = (json.references ?? []).filter(
|
||||
({ path }) => !path.includes(tsConfigFromProjRoot)
|
||||
);
|
||||
return json;
|
||||
});
|
||||
|
||||
tree.delete(tsconfigToRemove);
|
||||
}
|
||||
|
||||
if (configName) {
|
||||
delete projectConfig.targets[targetName].configurations[configName]
|
||||
.tsConfig;
|
||||
} else {
|
||||
delete projectConfig.targets[targetName].options.tsConfig;
|
||||
}
|
||||
|
||||
updateProjectConfiguration(tree, projectName, projectConfig);
|
||||
}
|
||||
);
|
||||
|
||||
await formatFiles(tree);
|
||||
}
|
||||
|
||||
export default fixLegacyCypressTsconfig;
|
||||
Loading…
x
Reference in New Issue
Block a user