@nx/cypress 20.7.2 → 20.8.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/migrations.json +57 -0
- package/package.json +6 -5
- package/src/executors/cypress/cypress.impl.js +17 -17
- package/src/generators/component-configuration/component-configuration.d.ts +1 -1
- package/src/generators/component-configuration/component-configuration.js +14 -11
- package/src/generators/configuration/configuration.js +8 -8
- package/src/generators/migrate-to-cypress-11/migrate-to-cypress-11.js +3 -3
- package/src/migrations/update-18-1-0/update-cypress-version-13-6-6.js +2 -2
- package/src/migrations/update-20-8-0/remove-experimental-fetch-polyfill.d.ts +2 -0
- package/src/migrations/update-20-8-0/remove-experimental-fetch-polyfill.js +48 -0
- package/src/migrations/update-20-8-0/replace-experimental-just-in-time-compile.d.ts +2 -0
- package/src/migrations/update-20-8-0/replace-experimental-just-in-time-compile.js +94 -0
- package/src/migrations/update-20-8-0/set-inject-document-domain.d.ts +2 -0
- package/src/migrations/update-20-8-0/set-inject-document-domain.js +160 -0
- package/src/migrations/update-20-8-0/update-component-testing-mount-imports.d.ts +2 -0
- package/src/migrations/update-20-8-0/update-component-testing-mount-imports.js +151 -0
- package/src/utils/add-linter.js +7 -7
- package/src/utils/config.d.ts +2 -0
- package/src/utils/config.js +46 -0
- package/src/utils/cypress-version.d.ts +6 -0
- package/src/utils/cypress-version.js +6 -0
- package/src/utils/migrations.d.ts +13 -0
- package/src/utils/migrations.js +71 -0
- package/src/utils/versions.d.ts +17 -4
- package/src/utils/versions.js +83 -4
package/migrations.json
CHANGED
|
@@ -11,6 +11,42 @@
|
|
|
11
11
|
"version": "19.6.0-beta.4",
|
|
12
12
|
"description": "Update ciWebServerCommand to use static serve for the application.",
|
|
13
13
|
"implementation": "./src/migrations/update-19-6-0/update-ci-webserver-for-static-serve"
|
|
14
|
+
},
|
|
15
|
+
"set-inject-document-domain": {
|
|
16
|
+
"cli": "nx",
|
|
17
|
+
"version": "20.8.0-beta.0",
|
|
18
|
+
"requires": {
|
|
19
|
+
"cypress": ">=14.0.0"
|
|
20
|
+
},
|
|
21
|
+
"description": "Replaces the `experimentalSkipDomainInjection` configuration option with the new `injectDocumentDomain` configuration option.",
|
|
22
|
+
"implementation": "./src/migrations/update-20-8-0/set-inject-document-domain"
|
|
23
|
+
},
|
|
24
|
+
"remove-experimental-fetch-polyfill": {
|
|
25
|
+
"cli": "nx",
|
|
26
|
+
"version": "20.8.0-beta.0",
|
|
27
|
+
"requires": {
|
|
28
|
+
"cypress": ">=14.0.0"
|
|
29
|
+
},
|
|
30
|
+
"description": "Removes the `experimentalFetchPolyfill` configuration option.",
|
|
31
|
+
"implementation": "./src/migrations/update-20-8-0/remove-experimental-fetch-polyfill"
|
|
32
|
+
},
|
|
33
|
+
"replace-experimental-just-in-time-compile": {
|
|
34
|
+
"cli": "nx",
|
|
35
|
+
"version": "20.8.0-beta.0",
|
|
36
|
+
"requires": {
|
|
37
|
+
"cypress": ">=14.0.0"
|
|
38
|
+
},
|
|
39
|
+
"description": "Replaces the `experimentalJustInTimeCompile` configuration option with the new `justInTimeCompile` configuration option.",
|
|
40
|
+
"implementation": "./src/migrations/update-20-8-0/replace-experimental-just-in-time-compile"
|
|
41
|
+
},
|
|
42
|
+
"update-component-testing-mount-imports": {
|
|
43
|
+
"cli": "nx",
|
|
44
|
+
"version": "20.8.0-beta.0",
|
|
45
|
+
"requires": {
|
|
46
|
+
"cypress": ">=14.0.0"
|
|
47
|
+
},
|
|
48
|
+
"description": "Updates the module specifier for the Component Testing `mount` function.",
|
|
49
|
+
"implementation": "./src/migrations/update-20-8-0/update-component-testing-mount-imports"
|
|
14
50
|
}
|
|
15
51
|
},
|
|
16
52
|
"packageJsonUpdates": {
|
|
@@ -59,6 +95,27 @@
|
|
|
59
95
|
"alwaysAddToPackageJson": false
|
|
60
96
|
}
|
|
61
97
|
}
|
|
98
|
+
},
|
|
99
|
+
"20.8.0": {
|
|
100
|
+
"version": "20.8.0-beta.0",
|
|
101
|
+
"x-prompt": "Do you want to update the Cypress version to v14?",
|
|
102
|
+
"requires": {
|
|
103
|
+
"cypress": ">=13.0.0 <14.0.0"
|
|
104
|
+
},
|
|
105
|
+
"packages": {
|
|
106
|
+
"cypress": {
|
|
107
|
+
"version": "^14.2.1",
|
|
108
|
+
"alwaysAddToPackageJson": false
|
|
109
|
+
},
|
|
110
|
+
"@cypress/vite-dev-server": {
|
|
111
|
+
"version": "^6.0.3",
|
|
112
|
+
"alwaysAddToPackageJson": false
|
|
113
|
+
},
|
|
114
|
+
"@cypress/webpack-dev-server": {
|
|
115
|
+
"version": "^4.0.2",
|
|
116
|
+
"alwaysAddToPackageJson": false
|
|
117
|
+
}
|
|
118
|
+
}
|
|
62
119
|
}
|
|
63
120
|
}
|
|
64
121
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nx/cypress",
|
|
3
|
-
"version": "20.
|
|
3
|
+
"version": "20.8.0-beta.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "The Nx Plugin for Cypress contains executors and generators allowing your workspace to use the powerful Cypress integration testing capabilities.",
|
|
6
6
|
"repository": {
|
|
@@ -36,15 +36,16 @@
|
|
|
36
36
|
"migrations": "./migrations.json"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@nx/devkit": "20.
|
|
40
|
-
"@nx/eslint": "20.
|
|
41
|
-
"@nx/js": "20.
|
|
39
|
+
"@nx/devkit": "20.8.0-beta.0",
|
|
40
|
+
"@nx/eslint": "20.8.0-beta.0",
|
|
41
|
+
"@nx/js": "20.8.0-beta.0",
|
|
42
42
|
"@phenomnomnominal/tsquery": "~5.0.1",
|
|
43
43
|
"detect-port": "^1.5.1",
|
|
44
|
+
"semver": "^7.6.3",
|
|
44
45
|
"tslib": "^2.3.0"
|
|
45
46
|
},
|
|
46
47
|
"peerDependencies": {
|
|
47
|
-
"cypress": ">= 3 <
|
|
48
|
+
"cypress": ">= 3 < 15"
|
|
48
49
|
},
|
|
49
50
|
"peerDependenciesMeta": {
|
|
50
51
|
"cypress": {
|
|
@@ -5,11 +5,12 @@ const devkit_1 = require("@nx/devkit");
|
|
|
5
5
|
const fs_1 = require("fs");
|
|
6
6
|
const path_1 = require("path");
|
|
7
7
|
const ct_helpers_1 = require("../../utils/ct-helpers");
|
|
8
|
-
const
|
|
8
|
+
const versions_1 = require("../../utils/versions");
|
|
9
9
|
const start_dev_server_1 = require("../../utils/start-dev-server");
|
|
10
10
|
const Cypress = require('cypress'); // @NOTE: Importing via ES6 messes the whole test dependencies.
|
|
11
11
|
async function cypressExecutor(options, context) {
|
|
12
|
-
|
|
12
|
+
const installedCypressMajorVersion = (0, versions_1.getInstalledCypressMajorVersion)();
|
|
13
|
+
options = normalizeOptions(options, context, installedCypressMajorVersion);
|
|
13
14
|
// this is used by cypress component testing presets to build the executor contexts with the correct configuration options.
|
|
14
15
|
process.env.NX_CYPRESS_TARGET_CONFIGURATION = context.configurationName;
|
|
15
16
|
let success;
|
|
@@ -19,7 +20,7 @@ async function cypressExecutor(options, context) {
|
|
|
19
20
|
success = await runCypress(devServerValues.baseUrl, {
|
|
20
21
|
...options,
|
|
21
22
|
portLockFilePath: devServerValues.portLockFilePath,
|
|
22
|
-
});
|
|
23
|
+
}, installedCypressMajorVersion);
|
|
23
24
|
if (!options.watch) {
|
|
24
25
|
generatorInstance.return();
|
|
25
26
|
break;
|
|
@@ -34,7 +35,7 @@ async function cypressExecutor(options, context) {
|
|
|
34
35
|
}
|
|
35
36
|
return { success };
|
|
36
37
|
}
|
|
37
|
-
function normalizeOptions(options, context) {
|
|
38
|
+
function normalizeOptions(options, context, installedCypressMajorVersion) {
|
|
38
39
|
options.env = options.env || {};
|
|
39
40
|
if (options.testingType === 'component') {
|
|
40
41
|
const project = context?.projectGraph?.nodes?.[context.projectName];
|
|
@@ -42,17 +43,17 @@ function normalizeOptions(options, context) {
|
|
|
42
43
|
options.ctTailwindPath = (0, ct_helpers_1.getTempTailwindPath)(context);
|
|
43
44
|
}
|
|
44
45
|
}
|
|
45
|
-
checkSupportedBrowser(options);
|
|
46
|
-
warnDeprecatedHeadless(options);
|
|
47
|
-
warnDeprecatedCypressVersion();
|
|
46
|
+
checkSupportedBrowser(options, installedCypressMajorVersion);
|
|
47
|
+
warnDeprecatedHeadless(options, installedCypressMajorVersion);
|
|
48
|
+
warnDeprecatedCypressVersion(installedCypressMajorVersion);
|
|
48
49
|
return options;
|
|
49
50
|
}
|
|
50
|
-
function checkSupportedBrowser({ browser }) {
|
|
51
|
+
function checkSupportedBrowser({ browser }, installedCypressMajorVersion) {
|
|
51
52
|
// Browser was not passed in as an option, cypress will use whatever default it has set and we dont need to check it
|
|
52
53
|
if (!browser) {
|
|
53
54
|
return;
|
|
54
55
|
}
|
|
55
|
-
if (
|
|
56
|
+
if (installedCypressMajorVersion >= 4 && browser == 'canary') {
|
|
56
57
|
devkit_1.logger.warn((0, devkit_1.stripIndents) `
|
|
57
58
|
Warning:
|
|
58
59
|
You are using a browser that is not supported by cypress v4+.
|
|
@@ -63,7 +64,7 @@ function checkSupportedBrowser({ browser }) {
|
|
|
63
64
|
return;
|
|
64
65
|
}
|
|
65
66
|
const supportedV3Browsers = ['electron', 'chrome', 'canary', 'chromium'];
|
|
66
|
-
if (
|
|
67
|
+
if (installedCypressMajorVersion <= 3 &&
|
|
67
68
|
!supportedV3Browsers.includes(browser)) {
|
|
68
69
|
devkit_1.logger.warn((0, devkit_1.stripIndents) `
|
|
69
70
|
Warning:
|
|
@@ -72,8 +73,8 @@ function checkSupportedBrowser({ browser }) {
|
|
|
72
73
|
return;
|
|
73
74
|
}
|
|
74
75
|
}
|
|
75
|
-
function warnDeprecatedHeadless({ headless }) {
|
|
76
|
-
if (
|
|
76
|
+
function warnDeprecatedHeadless({ headless }, installedCypressMajorVersion) {
|
|
77
|
+
if (installedCypressMajorVersion < 8 || headless === undefined) {
|
|
77
78
|
return;
|
|
78
79
|
}
|
|
79
80
|
if (headless) {
|
|
@@ -83,8 +84,8 @@ function warnDeprecatedHeadless({ headless }) {
|
|
|
83
84
|
devkit_1.logger.warn(deprecatedMsg);
|
|
84
85
|
}
|
|
85
86
|
}
|
|
86
|
-
function warnDeprecatedCypressVersion() {
|
|
87
|
-
if (
|
|
87
|
+
function warnDeprecatedCypressVersion(installedCypressMajorVersion) {
|
|
88
|
+
if (installedCypressMajorVersion < 10) {
|
|
88
89
|
devkit_1.logger.warn((0, devkit_1.stripIndents) `
|
|
89
90
|
NOTE:
|
|
90
91
|
Support for Cypress versions < 10 is deprecated. Please upgrade to at least Cypress version 10.
|
|
@@ -97,8 +98,7 @@ A generator to migrate from v8 to v10 is provided. See https://nx.dev/cypress/v1
|
|
|
97
98
|
* By default, Cypress will run tests from the CLI without the GUI and provide directly the results in the console output.
|
|
98
99
|
* If `watch` is `true`: Open Cypress in the interactive GUI to interact directly with the application.
|
|
99
100
|
*/
|
|
100
|
-
async function runCypress(baseUrl, opts) {
|
|
101
|
-
const cypressVersion = (0, cypress_version_1.installedCypressVersion)();
|
|
101
|
+
async function runCypress(baseUrl, opts, installedCypressMajorVersion) {
|
|
102
102
|
// Cypress expects the folder where a cypress config is present
|
|
103
103
|
const projectFolderPath = (0, path_1.dirname)(opts.cypressConfig);
|
|
104
104
|
const options = {
|
|
@@ -134,7 +134,7 @@ async function runCypress(baseUrl, opts) {
|
|
|
134
134
|
options.ciBuildId = opts.ciBuildId?.toString();
|
|
135
135
|
options.group = opts.group;
|
|
136
136
|
// renamed in cy 10
|
|
137
|
-
if (
|
|
137
|
+
if (installedCypressMajorVersion >= 10) {
|
|
138
138
|
options.config ??= {};
|
|
139
139
|
options.config[opts.testingType] = {
|
|
140
140
|
excludeSpecPattern: opts.ignoreTestFiles,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ProjectConfiguration, Tree
|
|
1
|
+
import { GeneratorCallback, ProjectConfiguration, Tree } from '@nx/devkit';
|
|
2
2
|
import { CypressComponentConfigurationSchema } from './schema';
|
|
3
3
|
export declare function componentConfigurationGenerator(tree: Tree, options: CypressComponentConfigurationSchema): Promise<GeneratorCallback>;
|
|
4
4
|
export declare function componentConfigurationGeneratorInternal(tree: Tree, options: CypressComponentConfigurationSchema): Promise<GeneratorCallback>;
|
|
@@ -5,7 +5,6 @@ exports.componentConfigurationGeneratorInternal = componentConfigurationGenerato
|
|
|
5
5
|
exports.updateTsConfigForComponentTesting = updateTsConfigForComponentTesting;
|
|
6
6
|
const devkit_1 = require("@nx/devkit");
|
|
7
7
|
const ts_solution_setup_1 = require("@nx/js/src/utils/typescript/ts-solution-setup");
|
|
8
|
-
const cypress_version_1 = require("../../utils/cypress-version");
|
|
9
8
|
const versions_1 = require("../../utils/versions");
|
|
10
9
|
const base_setup_1 = require("../base-setup/base-setup");
|
|
11
10
|
const init_1 = require("../init/init");
|
|
@@ -19,10 +18,12 @@ async function componentConfigurationGeneratorInternal(tree, options) {
|
|
|
19
18
|
(0, ts_solution_setup_1.assertNotUsingTsSolutionSetup)(tree, 'cypress', 'component-configuration');
|
|
20
19
|
const tasks = [];
|
|
21
20
|
const opts = normalizeOptions(tree, options);
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
if (!(0, versions_1.getInstalledCypressMajorVersion)(tree)) {
|
|
22
|
+
tasks.push(await (0, init_1.default)(tree, {
|
|
23
|
+
...opts,
|
|
24
|
+
skipFormat: true,
|
|
25
|
+
}));
|
|
26
|
+
}
|
|
26
27
|
const nxJson = (0, devkit_1.readNxJson)(tree);
|
|
27
28
|
const hasPlugin = nxJson.plugins?.some((p) => typeof p === 'string'
|
|
28
29
|
? p === '@nx/cypress/plugin'
|
|
@@ -41,7 +42,7 @@ async function componentConfigurationGeneratorInternal(tree, options) {
|
|
|
41
42
|
return (0, devkit_1.runTasksInSerial)(...tasks);
|
|
42
43
|
}
|
|
43
44
|
function normalizeOptions(tree, options) {
|
|
44
|
-
const cyVersion = (0,
|
|
45
|
+
const cyVersion = (0, versions_1.getInstalledCypressMajorVersion)(tree);
|
|
45
46
|
if (cyVersion && cyVersion < 10) {
|
|
46
47
|
throw new Error('Cypress version of 10 or higher is required to use component testing. See the migration guide to upgrade. https://nx.dev/cypress/v11-migration-guide');
|
|
47
48
|
}
|
|
@@ -56,17 +57,19 @@ function normalizeOptions(tree, options) {
|
|
|
56
57
|
};
|
|
57
58
|
}
|
|
58
59
|
function updateDeps(tree, opts) {
|
|
60
|
+
const pkgVersions = (0, versions_1.versions)(tree);
|
|
59
61
|
const devDeps = {
|
|
60
|
-
cypress:
|
|
62
|
+
cypress: pkgVersions.cypressVersion,
|
|
61
63
|
};
|
|
62
64
|
if (opts.bundler === 'vite') {
|
|
63
|
-
devDeps['@cypress/vite-dev-server'] =
|
|
65
|
+
devDeps['@cypress/vite-dev-server'] =
|
|
66
|
+
pkgVersions.cypressViteDevServerVersion;
|
|
64
67
|
}
|
|
65
68
|
else {
|
|
66
|
-
devDeps['@cypress/webpack-dev-server'] =
|
|
67
|
-
devDeps['html-webpack-plugin'] =
|
|
69
|
+
devDeps['@cypress/webpack-dev-server'] = pkgVersions.cypressWebpackVersion;
|
|
70
|
+
devDeps['html-webpack-plugin'] = pkgVersions.htmlWebpackPluginVersion;
|
|
68
71
|
}
|
|
69
|
-
return (0, devkit_1.addDependenciesToPackageJson)(tree, {}, devDeps);
|
|
72
|
+
return (0, devkit_1.addDependenciesToPackageJson)(tree, {}, devDeps, undefined, true);
|
|
70
73
|
}
|
|
71
74
|
function addProjectFiles(tree, projectConfig, opts) {
|
|
72
75
|
(0, base_setup_1.addBaseCypressSetup)(tree, {
|
|
@@ -4,6 +4,7 @@ exports.configurationGenerator = configurationGenerator;
|
|
|
4
4
|
exports.configurationGeneratorInternal = configurationGeneratorInternal;
|
|
5
5
|
const devkit_1 = require("@nx/devkit");
|
|
6
6
|
const project_name_and_root_utils_1 = require("@nx/devkit/src/generators/project-name-and-root-utils");
|
|
7
|
+
const prompt_1 = require("@nx/devkit/src/generators/prompt");
|
|
7
8
|
const js_1 = require("@nx/js");
|
|
8
9
|
const generator_prompts_1 = require("@nx/js/src/utils/generator-prompts");
|
|
9
10
|
const package_manager_workspaces_1 = require("@nx/js/src/utils/package-manager-workspaces");
|
|
@@ -11,11 +12,9 @@ const ts_solution_setup_1 = require("@nx/js/src/utils/typescript/ts-solution-set
|
|
|
11
12
|
const path_1 = require("path");
|
|
12
13
|
const add_linter_1 = require("../../utils/add-linter");
|
|
13
14
|
const config_1 = require("../../utils/config");
|
|
14
|
-
const cypress_version_1 = require("../../utils/cypress-version");
|
|
15
15
|
const versions_1 = require("../../utils/versions");
|
|
16
16
|
const base_setup_1 = require("../base-setup/base-setup");
|
|
17
17
|
const init_1 = require("../init/init");
|
|
18
|
-
const prompt_1 = require("@nx/devkit/src/generators/prompt");
|
|
19
18
|
function configurationGenerator(tree, options) {
|
|
20
19
|
return configurationGeneratorInternal(tree, {
|
|
21
20
|
addPlugin: false,
|
|
@@ -26,7 +25,7 @@ async function configurationGeneratorInternal(tree, options) {
|
|
|
26
25
|
const opts = await normalizeOptions(tree, options);
|
|
27
26
|
const tasks = [];
|
|
28
27
|
const projectGraph = await (0, devkit_1.createProjectGraphAsync)();
|
|
29
|
-
if (!(0,
|
|
28
|
+
if (!(0, versions_1.getInstalledCypressMajorVersion)(tree)) {
|
|
30
29
|
tasks.push(await (0, js_1.initGenerator)(tree, { ...options, skipFormat: true }));
|
|
31
30
|
tasks.push(await (0, init_1.default)(tree, {
|
|
32
31
|
...opts,
|
|
@@ -92,13 +91,14 @@ async function configurationGeneratorInternal(tree, options) {
|
|
|
92
91
|
return (0, devkit_1.runTasksInSerial)(...tasks);
|
|
93
92
|
}
|
|
94
93
|
function ensureDependencies(tree, options) {
|
|
94
|
+
const pkgVersions = (0, versions_1.versions)(tree);
|
|
95
95
|
const devDependencies = {
|
|
96
|
-
'@types/node':
|
|
96
|
+
'@types/node': pkgVersions.typesNodeVersion,
|
|
97
97
|
};
|
|
98
98
|
if (options.bundler === 'vite') {
|
|
99
|
-
devDependencies['vite'] =
|
|
99
|
+
devDependencies['vite'] = pkgVersions.viteVersion;
|
|
100
100
|
}
|
|
101
|
-
return (0, devkit_1.addDependenciesToPackageJson)(tree, {}, devDependencies);
|
|
101
|
+
return (0, devkit_1.addDependenciesToPackageJson)(tree, {}, devDependencies, undefined, true);
|
|
102
102
|
}
|
|
103
103
|
async function normalizeOptions(tree, options) {
|
|
104
104
|
const linter = await (0, generator_prompts_1.normalizeLinterOption)(tree, options.linter);
|
|
@@ -164,7 +164,7 @@ async function promptForMissingServeData(projectName) {
|
|
|
164
164
|
}
|
|
165
165
|
async function addFiles(tree, options, projectGraph, hasPlugin) {
|
|
166
166
|
const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, options.project);
|
|
167
|
-
const cyVersion = (0,
|
|
167
|
+
const cyVersion = (0, versions_1.getInstalledCypressMajorVersion)(tree);
|
|
168
168
|
const filesToUse = cyVersion && cyVersion < 10 ? 'v9' : 'v10';
|
|
169
169
|
const hasTsConfig = tree.exists((0, devkit_1.joinPathFragments)(projectConfig.root, 'tsconfig.json'));
|
|
170
170
|
const offsetFromProjectRoot = options.directory
|
|
@@ -245,7 +245,7 @@ async function addFiles(tree, options, projectGraph, hasPlugin) {
|
|
|
245
245
|
}
|
|
246
246
|
function addTarget(tree, opts, projectGraph) {
|
|
247
247
|
const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, opts.project);
|
|
248
|
-
const cyVersion = (0,
|
|
248
|
+
const cyVersion = (0, versions_1.getInstalledCypressMajorVersion)(tree);
|
|
249
249
|
projectConfig.targets ??= {};
|
|
250
250
|
projectConfig.targets.e2e = {
|
|
251
251
|
executor: '@nx/cypress:cypress',
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.migrateCypressProject = migrateCypressProject;
|
|
4
|
-
const cypress_version_1 = require("../../utils/cypress-version");
|
|
5
4
|
const devkit_1 = require("@nx/devkit");
|
|
6
5
|
const executor_options_utils_1 = require("@nx/devkit/src/generators/executor-options-utils");
|
|
6
|
+
const versions_1 = require("../../utils/versions");
|
|
7
7
|
const conversion_util_1 = require("./conversion.util");
|
|
8
8
|
function migrateCypressExecutorOptions(tree, projectName, target, configuration, previousCypressConfigs) {
|
|
9
9
|
try {
|
|
@@ -57,8 +57,8 @@ https://nx.dev/cypress/v10-migration-guide
|
|
|
57
57
|
}
|
|
58
58
|
}
|
|
59
59
|
async function migrateCypressProject(tree) {
|
|
60
|
-
(0,
|
|
61
|
-
if ((0,
|
|
60
|
+
(0, versions_1.assertMinimumCypressVersion)(8);
|
|
61
|
+
if ((0, versions_1.getInstalledCypressMajorVersion)(tree) >= 10) {
|
|
62
62
|
devkit_1.logger.info('NX This workspace is already using Cypress v10+');
|
|
63
63
|
return;
|
|
64
64
|
}
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.default = default_1;
|
|
4
4
|
const devkit_1 = require("@nx/devkit");
|
|
5
|
-
const
|
|
5
|
+
const versions_1 = require("../../utils/versions");
|
|
6
6
|
async function default_1(tree) {
|
|
7
|
-
if ((0,
|
|
7
|
+
if ((0, versions_1.getInstalledCypressMajorVersion)(tree) < 13) {
|
|
8
8
|
return;
|
|
9
9
|
}
|
|
10
10
|
(0, devkit_1.addDependenciesToPackageJson)(tree, {}, { cypress: '^13.6.6' });
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = default_1;
|
|
4
|
+
const devkit_1 = require("@nx/devkit");
|
|
5
|
+
const ensure_typescript_1 = require("@nx/js/src/utils/typescript/ensure-typescript");
|
|
6
|
+
const tsquery_1 = require("@phenomnomnominal/tsquery");
|
|
7
|
+
const config_1 = require("../../utils/config");
|
|
8
|
+
const migrations_1 = require("../../utils/migrations");
|
|
9
|
+
let printer;
|
|
10
|
+
let ts;
|
|
11
|
+
// https://docs.cypress.io/app/references/changelog#:~:text=The%20experimentalFetchPolyfill%20configuration%20option%20was,cy.intercept()%20for%20handling%20fetch%20requests
|
|
12
|
+
async function default_1(tree) {
|
|
13
|
+
for await (const { cypressConfigPath } of (0, migrations_1.cypressProjectConfigs)(tree)) {
|
|
14
|
+
if (!tree.exists(cypressConfigPath)) {
|
|
15
|
+
// cypress config file doesn't exist, so skip
|
|
16
|
+
continue;
|
|
17
|
+
}
|
|
18
|
+
ts ??= (0, ensure_typescript_1.ensureTypescript)();
|
|
19
|
+
printer ??= ts.createPrinter();
|
|
20
|
+
const cypressConfig = tree.read(cypressConfigPath, 'utf-8');
|
|
21
|
+
const updatedConfig = removeExperimentalFetchPolyfill(cypressConfig);
|
|
22
|
+
tree.write(cypressConfigPath, updatedConfig);
|
|
23
|
+
}
|
|
24
|
+
await (0, devkit_1.formatFiles)(tree);
|
|
25
|
+
}
|
|
26
|
+
function removeExperimentalFetchPolyfill(cypressConfig) {
|
|
27
|
+
const config = (0, config_1.resolveCypressConfigObject)(cypressConfig);
|
|
28
|
+
if (!config) {
|
|
29
|
+
// couldn't find the config object, leave as is
|
|
30
|
+
return cypressConfig;
|
|
31
|
+
}
|
|
32
|
+
const sourceFile = tsquery_1.tsquery.ast(cypressConfig);
|
|
33
|
+
const updatedConfig = ts.factory.updateObjectLiteralExpression(config, config.properties
|
|
34
|
+
// remove the experimentalFetchPolyfill property from the top level config object
|
|
35
|
+
.filter((p) => !ts.isPropertyAssignment(p) ||
|
|
36
|
+
p.name.getText() !== 'experimentalFetchPolyfill')
|
|
37
|
+
.map((p) => {
|
|
38
|
+
if (ts.isPropertyAssignment(p) &&
|
|
39
|
+
['component', 'e2e'].includes(p.name.getText()) &&
|
|
40
|
+
ts.isObjectLiteralExpression(p.initializer)) {
|
|
41
|
+
// remove the experimentalFetchPolyfill property from the component or e2e config object
|
|
42
|
+
return ts.factory.updatePropertyAssignment(p, p.name, ts.factory.updateObjectLiteralExpression(p.initializer, p.initializer.properties.filter((ip) => !ts.isPropertyAssignment(ip) ||
|
|
43
|
+
ip.name.getText() !== 'experimentalFetchPolyfill')));
|
|
44
|
+
}
|
|
45
|
+
return p;
|
|
46
|
+
}));
|
|
47
|
+
return cypressConfig.replace(config.getText(), printer.printNode(ts.EmitHint.Unspecified, updatedConfig, sourceFile));
|
|
48
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = default_1;
|
|
4
|
+
const devkit_1 = require("@nx/devkit");
|
|
5
|
+
const config_utils_1 = require("@nx/devkit/src/utils/config-utils");
|
|
6
|
+
const ensure_typescript_1 = require("@nx/js/src/utils/typescript/ensure-typescript");
|
|
7
|
+
const tsquery_1 = require("@phenomnomnominal/tsquery");
|
|
8
|
+
const node_path_1 = require("node:path");
|
|
9
|
+
const config_1 = require("../../utils/config");
|
|
10
|
+
const migrations_1 = require("../../utils/migrations");
|
|
11
|
+
let printer;
|
|
12
|
+
let ts;
|
|
13
|
+
// https://docs.cypress.io/app/references/migration-guide#CT-Just-in-Time-Compile-changes
|
|
14
|
+
async function default_1(tree) {
|
|
15
|
+
for await (const { cypressConfigPath } of (0, migrations_1.cypressProjectConfigs)(tree)) {
|
|
16
|
+
if (!tree.exists(cypressConfigPath)) {
|
|
17
|
+
// cypress config file doesn't exist, so skip
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
const updatedConfig = await updateCtJustInTimeCompile(tree, cypressConfigPath);
|
|
21
|
+
tree.write(cypressConfigPath, updatedConfig);
|
|
22
|
+
}
|
|
23
|
+
await (0, devkit_1.formatFiles)(tree);
|
|
24
|
+
}
|
|
25
|
+
async function updateCtJustInTimeCompile(tree, cypressConfigPath) {
|
|
26
|
+
const cypressConfig = tree.read(cypressConfigPath, 'utf-8');
|
|
27
|
+
const config = (0, config_1.resolveCypressConfigObject)(cypressConfig);
|
|
28
|
+
if (!config) {
|
|
29
|
+
// couldn't find the config object, leave as is
|
|
30
|
+
return cypressConfig;
|
|
31
|
+
}
|
|
32
|
+
if (!(0, migrations_1.getObjectProperty)(config, 'component')) {
|
|
33
|
+
// no component config, leave as is
|
|
34
|
+
return cypressConfig;
|
|
35
|
+
}
|
|
36
|
+
ts ??= (0, ensure_typescript_1.ensureTypescript)();
|
|
37
|
+
printer ??= ts.createPrinter();
|
|
38
|
+
const sourceFile = tsquery_1.tsquery.ast(cypressConfig);
|
|
39
|
+
let updatedConfig = config;
|
|
40
|
+
const bundler = await resolveBundler(updatedConfig, cypressConfigPath);
|
|
41
|
+
const isViteBundler = bundler === 'vite';
|
|
42
|
+
const existingJustInTimeCompileProperty = (0, migrations_1.getObjectProperty)(updatedConfig, 'experimentalJustInTimeCompile');
|
|
43
|
+
if (existingJustInTimeCompileProperty) {
|
|
44
|
+
if (isViteBundler ||
|
|
45
|
+
existingJustInTimeCompileProperty.initializer.kind ===
|
|
46
|
+
ts.SyntaxKind.TrueKeyword) {
|
|
47
|
+
// if it's using vite or it's set to true (the new default value), remove it
|
|
48
|
+
updatedConfig = (0, migrations_1.removeObjectProperty)(updatedConfig, existingJustInTimeCompileProperty);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
// rename to justInTimeCompile
|
|
52
|
+
updatedConfig = (0, migrations_1.updateObjectProperty)(updatedConfig, existingJustInTimeCompileProperty, { newName: 'justInTimeCompile' });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
const componentProperty = (0, migrations_1.getObjectProperty)(updatedConfig, 'component');
|
|
56
|
+
if (componentProperty &&
|
|
57
|
+
ts.isObjectLiteralExpression(componentProperty.initializer)) {
|
|
58
|
+
const componentConfigObject = componentProperty.initializer;
|
|
59
|
+
const existingJustInTimeCompileProperty = (0, migrations_1.getObjectProperty)(componentConfigObject, 'experimentalJustInTimeCompile');
|
|
60
|
+
if (existingJustInTimeCompileProperty) {
|
|
61
|
+
if (isViteBundler ||
|
|
62
|
+
existingJustInTimeCompileProperty.initializer.kind ===
|
|
63
|
+
ts.SyntaxKind.TrueKeyword) {
|
|
64
|
+
// if it's using vite or it's set to true (the new default value), remove it
|
|
65
|
+
updatedConfig = (0, migrations_1.updateObjectProperty)(updatedConfig, componentProperty, {
|
|
66
|
+
newValue: (0, migrations_1.removeObjectProperty)(componentConfigObject, existingJustInTimeCompileProperty),
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
// rename to justInTimeCompile
|
|
71
|
+
updatedConfig = (0, migrations_1.updateObjectProperty)(updatedConfig, componentProperty, {
|
|
72
|
+
newValue: (0, migrations_1.updateObjectProperty)(componentConfigObject, existingJustInTimeCompileProperty, { newName: 'justInTimeCompile' }),
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return cypressConfig.replace(config.getText(), printer.printNode(ts.EmitHint.Unspecified, updatedConfig, sourceFile));
|
|
78
|
+
}
|
|
79
|
+
async function resolveBundler(config, cypressConfigPath) {
|
|
80
|
+
const bundlerProperty = tsquery_1.tsquery.query(config, 'PropertyAssignment:has(Identifier[name=component]) PropertyAssignment:has(Identifier[name=devServer]) PropertyAssignment:has(Identifier[name=bundler])')[0];
|
|
81
|
+
if (bundlerProperty) {
|
|
82
|
+
return ts.isStringLiteral(bundlerProperty.initializer)
|
|
83
|
+
? bundlerProperty.initializer.getText().replace(/['"`]/g, '')
|
|
84
|
+
: null;
|
|
85
|
+
}
|
|
86
|
+
try {
|
|
87
|
+
// we can't statically resolve the bundler from the config, so we load the config
|
|
88
|
+
const cypressConfig = await (0, config_utils_1.loadConfigFile)((0, node_path_1.join)(devkit_1.workspaceRoot, cypressConfigPath));
|
|
89
|
+
return cypressConfig.component?.devServer?.bundler;
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = default_1;
|
|
4
|
+
const devkit_1 = require("@nx/devkit");
|
|
5
|
+
const ensure_typescript_1 = require("@nx/js/src/utils/typescript/ensure-typescript");
|
|
6
|
+
const tsquery_1 = require("@phenomnomnominal/tsquery");
|
|
7
|
+
const config_1 = require("../../utils/config");
|
|
8
|
+
const migrations_1 = require("../../utils/migrations");
|
|
9
|
+
let printer;
|
|
10
|
+
let ts;
|
|
11
|
+
// https://docs.cypress.io/app/references/migration-guide#Changes-to-cyorigin
|
|
12
|
+
// https://docs.cypress.io/app/references/changelog#:~:text=The%20experimentalSkipDomainInjection%20configuration%20has%20been,injectDocumentDomain%20configuration
|
|
13
|
+
async function default_1(tree) {
|
|
14
|
+
for await (const { cypressConfigPath } of (0, migrations_1.cypressProjectConfigs)(tree)) {
|
|
15
|
+
if (!tree.exists(cypressConfigPath)) {
|
|
16
|
+
// cypress config file doesn't exist, so skip
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
ts ??= (0, ensure_typescript_1.ensureTypescript)();
|
|
20
|
+
printer ??= ts.createPrinter();
|
|
21
|
+
const cypressConfig = tree.read(cypressConfigPath, 'utf-8');
|
|
22
|
+
const updatedConfig = setInjectDocumentDomain(cypressConfig);
|
|
23
|
+
tree.write(cypressConfigPath, updatedConfig);
|
|
24
|
+
}
|
|
25
|
+
await (0, devkit_1.formatFiles)(tree);
|
|
26
|
+
}
|
|
27
|
+
function setInjectDocumentDomain(cypressConfig) {
|
|
28
|
+
const config = (0, config_1.resolveCypressConfigObject)(cypressConfig);
|
|
29
|
+
if (!config) {
|
|
30
|
+
// couldn't find the config object, leave as is
|
|
31
|
+
return cypressConfig;
|
|
32
|
+
}
|
|
33
|
+
const sourceFile = tsquery_1.tsquery.ast(cypressConfig);
|
|
34
|
+
let e2eProperty = (0, migrations_1.getObjectProperty)(config, 'e2e');
|
|
35
|
+
let componentProperty = (0, migrations_1.getObjectProperty)(config, 'component');
|
|
36
|
+
let updatedConfig = config;
|
|
37
|
+
const topLevelExperimentalSkipDomainInjectionProperty = (0, migrations_1.getObjectProperty)(updatedConfig, 'experimentalSkipDomainInjection');
|
|
38
|
+
const topLevelSkipDomainState = !topLevelExperimentalSkipDomainInjectionProperty
|
|
39
|
+
? 'not-set'
|
|
40
|
+
: !ts.isArrayLiteralExpression(topLevelExperimentalSkipDomainInjectionProperty.initializer) ||
|
|
41
|
+
topLevelExperimentalSkipDomainInjectionProperty.initializer.elements
|
|
42
|
+
.length > 0
|
|
43
|
+
? 'skipping'
|
|
44
|
+
: 'not-skipping';
|
|
45
|
+
let e2eSkipDomainState = 'not-set';
|
|
46
|
+
if (e2eProperty) {
|
|
47
|
+
let experimentalSkipDomainInjectionProperty;
|
|
48
|
+
let isObjectLiteral = false;
|
|
49
|
+
if (ts.isObjectLiteralExpression(e2eProperty.initializer)) {
|
|
50
|
+
experimentalSkipDomainInjectionProperty = (0, migrations_1.getObjectProperty)(e2eProperty.initializer, 'experimentalSkipDomainInjection');
|
|
51
|
+
isObjectLiteral = true;
|
|
52
|
+
}
|
|
53
|
+
if (experimentalSkipDomainInjectionProperty) {
|
|
54
|
+
e2eSkipDomainState =
|
|
55
|
+
!ts.isArrayLiteralExpression(experimentalSkipDomainInjectionProperty.initializer) ||
|
|
56
|
+
experimentalSkipDomainInjectionProperty.initializer.elements.length > 0
|
|
57
|
+
? 'skipping'
|
|
58
|
+
: 'not-skipping';
|
|
59
|
+
}
|
|
60
|
+
if (e2eSkipDomainState === 'not-set' &&
|
|
61
|
+
topLevelSkipDomainState === 'not-set') {
|
|
62
|
+
updatedConfig = (0, migrations_1.updateObjectProperty)(updatedConfig, e2eProperty, {
|
|
63
|
+
newValue: setInjectDocumentDomainInObject(e2eProperty.initializer),
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
else if (e2eSkipDomainState === 'not-skipping') {
|
|
67
|
+
updatedConfig = (0, migrations_1.updateObjectProperty)(updatedConfig, e2eProperty, {
|
|
68
|
+
newValue: replaceExperimentalSkipDomainInjectionInObject(e2eProperty.initializer),
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
else if (e2eSkipDomainState === 'skipping') {
|
|
72
|
+
updatedConfig = (0, migrations_1.updateObjectProperty)(updatedConfig, e2eProperty, {
|
|
73
|
+
newValue: (0, migrations_1.removeObjectProperty)(
|
|
74
|
+
// we only determine that it's skipping if it's an object literal
|
|
75
|
+
e2eProperty.initializer, (0, migrations_1.getObjectProperty)(e2eProperty.initializer, 'experimentalSkipDomainInjection')),
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
let componentSkipDomainState = 'not-set';
|
|
80
|
+
if (componentProperty) {
|
|
81
|
+
let experimentalSkipDomainInjectionProperty;
|
|
82
|
+
let isObjectLiteral = false;
|
|
83
|
+
if (ts.isObjectLiteralExpression(componentProperty.initializer)) {
|
|
84
|
+
experimentalSkipDomainInjectionProperty = (0, migrations_1.getObjectProperty)(componentProperty.initializer, 'experimentalSkipDomainInjection');
|
|
85
|
+
isObjectLiteral = true;
|
|
86
|
+
}
|
|
87
|
+
if (experimentalSkipDomainInjectionProperty) {
|
|
88
|
+
componentSkipDomainState =
|
|
89
|
+
!ts.isArrayLiteralExpression(experimentalSkipDomainInjectionProperty.initializer) ||
|
|
90
|
+
experimentalSkipDomainInjectionProperty.initializer.elements.length > 0
|
|
91
|
+
? 'skipping'
|
|
92
|
+
: 'not-skipping';
|
|
93
|
+
}
|
|
94
|
+
if (componentSkipDomainState === 'not-set' &&
|
|
95
|
+
topLevelSkipDomainState === 'not-set') {
|
|
96
|
+
updatedConfig = (0, migrations_1.updateObjectProperty)(updatedConfig, componentProperty, {
|
|
97
|
+
newValue: setInjectDocumentDomainInObject(componentProperty.initializer),
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
else if (componentSkipDomainState === 'not-skipping') {
|
|
101
|
+
updatedConfig = (0, migrations_1.updateObjectProperty)(updatedConfig, componentProperty, {
|
|
102
|
+
newValue: replaceExperimentalSkipDomainInjectionInObject(componentProperty.initializer),
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
else if (componentSkipDomainState === 'skipping') {
|
|
106
|
+
updatedConfig = (0, migrations_1.updateObjectProperty)(updatedConfig, componentProperty, {
|
|
107
|
+
newValue: (0, migrations_1.removeObjectProperty)(
|
|
108
|
+
// we only determine that it's skipping if it's an object literal
|
|
109
|
+
componentProperty.initializer, (0, migrations_1.getObjectProperty)(componentProperty.initializer, 'experimentalSkipDomainInjection')),
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (topLevelSkipDomainState === 'not-set' &&
|
|
114
|
+
!e2eProperty &&
|
|
115
|
+
!componentProperty) {
|
|
116
|
+
updatedConfig = setInjectDocumentDomainInObject(updatedConfig);
|
|
117
|
+
}
|
|
118
|
+
else if (topLevelSkipDomainState === 'not-skipping') {
|
|
119
|
+
updatedConfig =
|
|
120
|
+
replaceExperimentalSkipDomainInjectionInObject(updatedConfig);
|
|
121
|
+
}
|
|
122
|
+
else if (topLevelSkipDomainState === 'skipping') {
|
|
123
|
+
updatedConfig = (0, migrations_1.removeObjectProperty)(updatedConfig, topLevelExperimentalSkipDomainInjectionProperty);
|
|
124
|
+
}
|
|
125
|
+
return cypressConfig.replace(config.getText(), printer.printNode(ts.EmitHint.Unspecified, updatedConfig, sourceFile));
|
|
126
|
+
}
|
|
127
|
+
function setInjectDocumentDomainInObject(config) {
|
|
128
|
+
let configToUpdate;
|
|
129
|
+
if (ts.isObjectLiteralExpression(config)) {
|
|
130
|
+
configToUpdate = config;
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
// spread the current expression into a new object literal
|
|
134
|
+
configToUpdate = ts.factory.createObjectLiteralExpression([
|
|
135
|
+
ts.factory.createSpreadAssignment(config),
|
|
136
|
+
]);
|
|
137
|
+
}
|
|
138
|
+
return ts.factory.updateObjectLiteralExpression(configToUpdate, ts.factory.createNodeArray([
|
|
139
|
+
...configToUpdate.properties,
|
|
140
|
+
getInjectDocumentDomainPropertyAssignment(),
|
|
141
|
+
]));
|
|
142
|
+
}
|
|
143
|
+
function replaceExperimentalSkipDomainInjectionInObject(config) {
|
|
144
|
+
let configToUpdate;
|
|
145
|
+
if (ts.isObjectLiteralExpression(config)) {
|
|
146
|
+
configToUpdate = config;
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
// spread the current expression into a new object literal
|
|
150
|
+
configToUpdate = ts.factory.createObjectLiteralExpression([
|
|
151
|
+
ts.factory.createSpreadAssignment(config),
|
|
152
|
+
]);
|
|
153
|
+
}
|
|
154
|
+
return ts.factory.updateObjectLiteralExpression(configToUpdate, configToUpdate.properties.map((property) => property.name?.getText() === 'experimentalSkipDomainInjection'
|
|
155
|
+
? getInjectDocumentDomainPropertyAssignment()
|
|
156
|
+
: property));
|
|
157
|
+
}
|
|
158
|
+
function getInjectDocumentDomainPropertyAssignment() {
|
|
159
|
+
return ts.addSyntheticLeadingComment(ts.addSyntheticLeadingComment(ts.factory.createPropertyAssignment(ts.factory.createIdentifier('injectDocumentDomain'), ts.factory.createTrue()), ts.SyntaxKind.SingleLineCommentTrivia, ' Please ensure you use `cy.origin()` when navigating between domains and remove this option.'), ts.SyntaxKind.SingleLineCommentTrivia, ' See https://docs.cypress.io/app/references/migration-guide#Changes-to-cyorigin');
|
|
160
|
+
}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = default_1;
|
|
4
|
+
const devkit_1 = require("@nx/devkit");
|
|
5
|
+
const ensure_typescript_1 = require("@nx/js/src/utils/typescript/ensure-typescript");
|
|
6
|
+
const tsquery_1 = require("@phenomnomnominal/tsquery");
|
|
7
|
+
const semver_1 = require("semver");
|
|
8
|
+
const config_1 = require("../../utils/config");
|
|
9
|
+
const migrations_1 = require("../../utils/migrations");
|
|
10
|
+
let printer;
|
|
11
|
+
let ts;
|
|
12
|
+
async function default_1(tree) {
|
|
13
|
+
const projectGraph = await (0, devkit_1.createProjectGraphAsync)();
|
|
14
|
+
for await (const { cypressConfigPath, projectName, projectConfig, } of (0, migrations_1.cypressProjectConfigs)(tree)) {
|
|
15
|
+
if (!tree.exists(cypressConfigPath)) {
|
|
16
|
+
// cypress config file doesn't exist, so skip
|
|
17
|
+
continue;
|
|
18
|
+
}
|
|
19
|
+
ts ??= (0, ensure_typescript_1.ensureTypescript)();
|
|
20
|
+
printer ??= ts.createPrinter();
|
|
21
|
+
const migrationInfo = parseMigrationInfo(tree, cypressConfigPath, projectName, projectGraph);
|
|
22
|
+
if (!migrationInfo) {
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
if (migrationInfo.framework === 'angular') {
|
|
26
|
+
migrateAngularFramework(tree, projectConfig, migrationInfo.isLegacyVersion);
|
|
27
|
+
}
|
|
28
|
+
else if (migrationInfo.framework === 'react') {
|
|
29
|
+
migrateReactFramework(tree, projectConfig);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
await (0, devkit_1.formatFiles)(tree);
|
|
33
|
+
}
|
|
34
|
+
function parseMigrationInfo(tree, cypressConfigPath, projectName, projectGraph) {
|
|
35
|
+
const cypressConfig = tree.read(cypressConfigPath, 'utf-8');
|
|
36
|
+
const config = (0, config_1.resolveCypressConfigObject)(cypressConfig);
|
|
37
|
+
if (!config) {
|
|
38
|
+
// couldn't find the config object, leave as is
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
if (!(0, migrations_1.getObjectProperty)(config, 'component')) {
|
|
42
|
+
// no component config, leave as is
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
const framework = resolveFramework(cypressConfig, config, projectName, projectGraph);
|
|
46
|
+
if (framework === 'react') {
|
|
47
|
+
return { framework: 'react' };
|
|
48
|
+
}
|
|
49
|
+
if (framework === 'angular') {
|
|
50
|
+
const angularCoreDep = projectGraph.dependencies[projectName].find((d) =>
|
|
51
|
+
// account for possible different versions of angular core
|
|
52
|
+
d.target.startsWith('npm:@angular/core'));
|
|
53
|
+
if (angularCoreDep) {
|
|
54
|
+
const angularVersion = projectGraph.externalNodes?.[angularCoreDep.target]?.data?.version;
|
|
55
|
+
if ((0, semver_1.valid)(angularVersion) && (0, semver_1.lt)(angularVersion, '17.2.0')) {
|
|
56
|
+
return {
|
|
57
|
+
framework: 'angular',
|
|
58
|
+
isLegacyVersion: true,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
framework: 'angular',
|
|
64
|
+
isLegacyVersion: false,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
function resolveFramework(cypressConfig, config, projectName, projectGraph) {
|
|
70
|
+
const frameworkProperty = tsquery_1.tsquery.query(config, 'PropertyAssignment:has(Identifier[name=component]) PropertyAssignment:has(Identifier[name=devServer]) PropertyAssignment:has(Identifier[name=framework])')[0];
|
|
71
|
+
if (frameworkProperty) {
|
|
72
|
+
return ts.isStringLiteral(frameworkProperty.initializer)
|
|
73
|
+
? frameworkProperty.initializer.getText().replace(/['"`]/g, '')
|
|
74
|
+
: null;
|
|
75
|
+
}
|
|
76
|
+
// component might be assigned to an Nx preset function call, so we try to
|
|
77
|
+
// infer the framework from the Nx preset import
|
|
78
|
+
const sourceFile = tsquery_1.tsquery.ast(cypressConfig);
|
|
79
|
+
const nxPresetModuleSpecifiers = [
|
|
80
|
+
'@nx/angular/plugins/component-testing',
|
|
81
|
+
'@nx/react/plugins/component-testing',
|
|
82
|
+
'@nx/next/plugins/component-testing',
|
|
83
|
+
'@nx/remix/plugins/component-testing',
|
|
84
|
+
];
|
|
85
|
+
const nxPresetImportModuleSpecifier = sourceFile.statements
|
|
86
|
+
.find((s) => ts.isImportDeclaration(s) &&
|
|
87
|
+
nxPresetModuleSpecifiers.includes(s.moduleSpecifier.getText().replace(/['"`]/g, '')))
|
|
88
|
+
?.moduleSpecifier.getText()
|
|
89
|
+
.replace(/['"`]/g, '');
|
|
90
|
+
if (nxPresetImportModuleSpecifier) {
|
|
91
|
+
const plugin = nxPresetImportModuleSpecifier.split('/').at(1);
|
|
92
|
+
return plugin === 'angular' ? 'angular' : 'react';
|
|
93
|
+
}
|
|
94
|
+
// it might be set to something else, so we fall back to checking the
|
|
95
|
+
// project dependencies
|
|
96
|
+
if (projectGraph.dependencies[projectName]?.some((d) => d.target.startsWith('npm:@angular/core'))) {
|
|
97
|
+
return 'angular';
|
|
98
|
+
}
|
|
99
|
+
if (projectGraph.dependencies[projectName]?.some((d) => d.target.startsWith('npm:react') || d.target.startsWith('npm:next'))) {
|
|
100
|
+
return 'react';
|
|
101
|
+
}
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
// https://docs.cypress.io/app/references/migration-guide#Angular-1720-CT-no-longer-supported
|
|
105
|
+
function migrateAngularFramework(tree, projectConfig, isLegacyVersion) {
|
|
106
|
+
(0, devkit_1.visitNotIgnoredFiles)(tree, projectConfig.root, (filePath) => {
|
|
107
|
+
if (!isJsTsFile(filePath)) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const content = tree.read(filePath, 'utf-8');
|
|
111
|
+
let updatedFileContent;
|
|
112
|
+
if (isLegacyVersion) {
|
|
113
|
+
let needPackage = false;
|
|
114
|
+
updatedFileContent = tsquery_1.tsquery.replace(content, 'ImportDeclaration', importTransformerFactory(content, 'cypress/angular', '@cypress/angular', () => {
|
|
115
|
+
needPackage = true;
|
|
116
|
+
}));
|
|
117
|
+
if (needPackage) {
|
|
118
|
+
(0, devkit_1.addDependenciesToPackageJson)(tree, {}, { '@cypress/angular': '^2.1.0' }, undefined, true);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
updatedFileContent = tsquery_1.tsquery.replace(content, 'ImportDeclaration', importTransformerFactory(content, 'cypress/angular-signals', 'cypress/angular'));
|
|
123
|
+
}
|
|
124
|
+
tree.write(filePath, updatedFileContent);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
// https://docs.cypress.io/app/references/migration-guide#React-18-CT-no-longer-supported
|
|
128
|
+
function migrateReactFramework(tree, projectConfig) {
|
|
129
|
+
(0, devkit_1.visitNotIgnoredFiles)(tree, projectConfig.root, (filePath) => {
|
|
130
|
+
if (!isJsTsFile(filePath)) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
const content = tree.read(filePath, 'utf-8');
|
|
134
|
+
const updatedContent = tsquery_1.tsquery.replace(content, 'ImportDeclaration', importTransformerFactory(content, 'cypress/react18', 'cypress/react'));
|
|
135
|
+
tree.write(filePath, updatedContent);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
function importTransformerFactory(fileContent, sourceModuleSpecifier, targetModuleSpecifier, matchImportCallback) {
|
|
139
|
+
return (node) => {
|
|
140
|
+
if (node.moduleSpecifier.getText().replace(/['"`]/g, '') ===
|
|
141
|
+
sourceModuleSpecifier) {
|
|
142
|
+
matchImportCallback?.();
|
|
143
|
+
const updatedImport = ts.factory.updateImportDeclaration(node, node.modifiers, node.importClause, ts.factory.createStringLiteral(targetModuleSpecifier), node.attributes);
|
|
144
|
+
return printer.printNode(ts.EmitHint.Unspecified, updatedImport, tsquery_1.tsquery.ast(fileContent));
|
|
145
|
+
}
|
|
146
|
+
return node.getText();
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
function isJsTsFile(filePath) {
|
|
150
|
+
return /\.[cm]?[jt]sx?$/.test(filePath);
|
|
151
|
+
}
|
package/src/utils/add-linter.js
CHANGED
|
@@ -3,11 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.addLinterToCyProject = addLinterToCyProject;
|
|
4
4
|
const devkit_1 = require("@nx/devkit");
|
|
5
5
|
const eslint_1 = require("@nx/eslint");
|
|
6
|
-
const cypress_version_1 = require("./cypress-version");
|
|
7
|
-
const versions_1 = require("./versions");
|
|
8
|
-
const eslint_file_1 = require("@nx/eslint/src/generators/utils/eslint-file");
|
|
9
6
|
const global_eslint_config_1 = require("@nx/eslint/src/generators/init/global-eslint-config");
|
|
7
|
+
const eslint_file_1 = require("@nx/eslint/src/generators/utils/eslint-file");
|
|
10
8
|
const flat_config_1 = require("@nx/eslint/src/utils/flat-config");
|
|
9
|
+
const versions_1 = require("./versions");
|
|
11
10
|
async function addLinterToCyProject(tree, options) {
|
|
12
11
|
if (options.linter === eslint_1.Linter.None) {
|
|
13
12
|
return () => { };
|
|
@@ -31,9 +30,10 @@ async function addLinterToCyProject(tree, options) {
|
|
|
31
30
|
return (0, devkit_1.runTasksInSerial)(...tasks);
|
|
32
31
|
}
|
|
33
32
|
options.overwriteExisting = options.overwriteExisting || !eslintFile;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
if (!options.skipPackageJson) {
|
|
34
|
+
const pkgVersions = (0, versions_1.versions)(tree);
|
|
35
|
+
tasks.push((0, devkit_1.addDependenciesToPackageJson)(tree, {}, { 'eslint-plugin-cypress': pkgVersions.eslintPluginCypressVersion }));
|
|
36
|
+
}
|
|
37
37
|
if ((0, eslint_file_1.isEslintConfigSupported)(tree, projectConfig.root) ||
|
|
38
38
|
(0, eslint_file_1.isEslintConfigSupported)(tree)) {
|
|
39
39
|
const overrides = [];
|
|
@@ -53,7 +53,7 @@ async function addLinterToCyProject(tree, options) {
|
|
|
53
53
|
const addExtendsTask = (0, eslint_file_1.addExtendsToLintConfig)(tree, projectConfig.root, 'plugin:cypress/recommended');
|
|
54
54
|
tasks.push(addExtendsTask);
|
|
55
55
|
}
|
|
56
|
-
const cyVersion = (0,
|
|
56
|
+
const cyVersion = (0, versions_1.getInstalledCypressMajorVersion)(tree);
|
|
57
57
|
/**
|
|
58
58
|
* We need this override because we enabled allowJS in the tsconfig to allow for JS based Cypress tests.
|
|
59
59
|
* That however leads to issues with the CommonJS Cypress plugin file.
|
package/src/utils/config.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type Tree } from '@nx/devkit';
|
|
2
|
+
import type { ObjectLiteralExpression } from 'typescript';
|
|
2
3
|
import type { NxComponentTestingOptions, NxCypressE2EPresetOptions } from '../../plugins/cypress-preset';
|
|
3
4
|
export declare const CYPRESS_CONFIG_FILE_NAME_PATTERN = "cypress.config.{js,ts,mjs,cjs}";
|
|
4
5
|
export declare function addDefaultE2EConfig(cyConfigContents: string, options: NxCypressE2EPresetOptions, baseUrl: string): Promise<string>;
|
|
@@ -15,3 +16,4 @@ export declare function addDefaultCTConfig(cyConfigContents: string, options?: N
|
|
|
15
16
|
**/
|
|
16
17
|
export declare function addMountDefinition(cmpCommandFileContents: string): Promise<string>;
|
|
17
18
|
export declare function getProjectCypressConfigPath(tree: Tree, projectRoot: string): string;
|
|
19
|
+
export declare function resolveCypressConfigObject(cypressConfigContents: string): ObjectLiteralExpression | null;
|
package/src/utils/config.js
CHANGED
|
@@ -5,7 +5,9 @@ exports.addDefaultE2EConfig = addDefaultE2EConfig;
|
|
|
5
5
|
exports.addDefaultCTConfig = addDefaultCTConfig;
|
|
6
6
|
exports.addMountDefinition = addMountDefinition;
|
|
7
7
|
exports.getProjectCypressConfigPath = getProjectCypressConfigPath;
|
|
8
|
+
exports.resolveCypressConfigObject = resolveCypressConfigObject;
|
|
8
9
|
const devkit_1 = require("@nx/devkit");
|
|
10
|
+
const ensure_typescript_1 = require("@nx/js/src/utils/typescript/ensure-typescript");
|
|
9
11
|
exports.CYPRESS_CONFIG_FILE_NAME_PATTERN = 'cypress.config.{js,ts,mjs,cjs}';
|
|
10
12
|
const TS_QUERY_COMMON_JS_EXPORT_SELECTOR = 'BinaryExpression:has(Identifier[name="module"]):has(Identifier[name="exports"])';
|
|
11
13
|
const TS_QUERY_EXPORT_CONFIG_PREFIX = `:matches(ExportAssignment, ${TS_QUERY_COMMON_JS_EXPORT_SELECTOR}) `;
|
|
@@ -117,3 +119,47 @@ function getProjectCypressConfigPath(tree, projectRoot) {
|
|
|
117
119
|
}
|
|
118
120
|
return cypressConfigPaths[0];
|
|
119
121
|
}
|
|
122
|
+
function resolveCypressConfigObject(cypressConfigContents) {
|
|
123
|
+
const ts = (0, ensure_typescript_1.ensureTypescript)();
|
|
124
|
+
const { tsquery } = (require('@phenomnomnominal/tsquery'));
|
|
125
|
+
const sourceFile = tsquery.ast(cypressConfigContents);
|
|
126
|
+
const exportDefaultStatement = sourceFile.statements.find((statement) => ts.isExportAssignment(statement));
|
|
127
|
+
if (exportDefaultStatement) {
|
|
128
|
+
return resolveCypressConfigObjectFromExportExpression(exportDefaultStatement.expression, sourceFile);
|
|
129
|
+
}
|
|
130
|
+
const moduleExportsStatement = sourceFile.statements.find((statement) => ts.isExpressionStatement(statement) &&
|
|
131
|
+
ts.isBinaryExpression(statement.expression) &&
|
|
132
|
+
statement.expression.left.getText() === 'module.exports');
|
|
133
|
+
if (moduleExportsStatement) {
|
|
134
|
+
return resolveCypressConfigObjectFromExportExpression(moduleExportsStatement.expression.right, sourceFile);
|
|
135
|
+
}
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
function resolveCypressConfigObjectFromExportExpression(exportExpression, sourceFile) {
|
|
139
|
+
const ts = (0, ensure_typescript_1.ensureTypescript)();
|
|
140
|
+
if (ts.isObjectLiteralExpression(exportExpression)) {
|
|
141
|
+
return exportExpression;
|
|
142
|
+
}
|
|
143
|
+
if (ts.isIdentifier(exportExpression)) {
|
|
144
|
+
// try to locate the identifier in the source file
|
|
145
|
+
const variableStatements = sourceFile.statements.filter((statement) => ts.isVariableStatement(statement));
|
|
146
|
+
for (const variableStatement of variableStatements) {
|
|
147
|
+
for (const declaration of variableStatement.declarationList
|
|
148
|
+
.declarations) {
|
|
149
|
+
if (ts.isIdentifier(declaration.name) &&
|
|
150
|
+
declaration.name.getText() === exportExpression.getText() &&
|
|
151
|
+
ts.isObjectLiteralExpression(declaration.initializer)) {
|
|
152
|
+
return declaration.initializer;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return null;
|
|
157
|
+
}
|
|
158
|
+
if (ts.isCallExpression(exportExpression) &&
|
|
159
|
+
ts.isIdentifier(exportExpression.expression) &&
|
|
160
|
+
exportExpression.expression.getText() === 'defineConfig' &&
|
|
161
|
+
ts.isObjectLiteralExpression(exportExpression.arguments[0])) {
|
|
162
|
+
return exportExpression.arguments[0];
|
|
163
|
+
}
|
|
164
|
+
return null;
|
|
165
|
+
}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @deprecated use the `getInstalledCypressMajorVersion` exported from
|
|
3
|
+
* `@nx/cypress/src/utils/versions` instead. It will be removed in v22.
|
|
4
|
+
*/
|
|
1
5
|
export declare function installedCypressVersion(): number;
|
|
2
6
|
/**
|
|
3
7
|
* will not throw if cypress is not installed
|
|
8
|
+
* @deprecated use the `assertMinimumCypressVersion` exported from
|
|
9
|
+
* `@nx/cypress/src/utils/versions` instead. It will be removed in v22.
|
|
4
10
|
*/
|
|
5
11
|
export declare function assertMinimumCypressVersion(minVersion: number): void;
|
|
@@ -4,6 +4,10 @@ exports.installedCypressVersion = installedCypressVersion;
|
|
|
4
4
|
exports.assertMinimumCypressVersion = assertMinimumCypressVersion;
|
|
5
5
|
let cypressPackageJson;
|
|
6
6
|
let loadedCypress = false;
|
|
7
|
+
/**
|
|
8
|
+
* @deprecated use the `getInstalledCypressMajorVersion` exported from
|
|
9
|
+
* `@nx/cypress/src/utils/versions` instead. It will be removed in v22.
|
|
10
|
+
*/
|
|
7
11
|
function installedCypressVersion() {
|
|
8
12
|
if (!loadedCypress) {
|
|
9
13
|
try {
|
|
@@ -23,6 +27,8 @@ function installedCypressVersion() {
|
|
|
23
27
|
}
|
|
24
28
|
/**
|
|
25
29
|
* will not throw if cypress is not installed
|
|
30
|
+
* @deprecated use the `assertMinimumCypressVersion` exported from
|
|
31
|
+
* `@nx/cypress/src/utils/versions` instead. It will be removed in v22.
|
|
26
32
|
*/
|
|
27
33
|
function assertMinimumCypressVersion(minVersion) {
|
|
28
34
|
const version = installedCypressVersion();
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ProjectConfiguration, type Tree } from '@nx/devkit';
|
|
2
|
+
import type { Expression, ObjectLiteralExpression, PropertyAssignment } from 'typescript';
|
|
3
|
+
export declare function cypressProjectConfigs(tree: Tree): AsyncGenerator<{
|
|
4
|
+
projectName: string;
|
|
5
|
+
projectConfig: ProjectConfiguration;
|
|
6
|
+
cypressConfigPath: string;
|
|
7
|
+
}>;
|
|
8
|
+
export declare function getObjectProperty(config: ObjectLiteralExpression, name: string): PropertyAssignment | undefined;
|
|
9
|
+
export declare function removeObjectProperty(config: ObjectLiteralExpression, property: PropertyAssignment): ObjectLiteralExpression;
|
|
10
|
+
export declare function updateObjectProperty(config: ObjectLiteralExpression, property: PropertyAssignment, { newName, newValue }: {
|
|
11
|
+
newName?: string;
|
|
12
|
+
newValue?: Expression;
|
|
13
|
+
}): ObjectLiteralExpression;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.cypressProjectConfigs = cypressProjectConfigs;
|
|
4
|
+
exports.getObjectProperty = getObjectProperty;
|
|
5
|
+
exports.removeObjectProperty = removeObjectProperty;
|
|
6
|
+
exports.updateObjectProperty = updateObjectProperty;
|
|
7
|
+
const devkit_1 = require("@nx/devkit");
|
|
8
|
+
const ensure_typescript_1 = require("@nx/js/src/utils/typescript/ensure-typescript");
|
|
9
|
+
const path_1 = require("path");
|
|
10
|
+
const config_1 = require("./config");
|
|
11
|
+
let ts;
|
|
12
|
+
async function* cypressProjectConfigs(tree) {
|
|
13
|
+
const projects = (0, devkit_1.getProjects)(tree);
|
|
14
|
+
for (const [projectName, projectConfig] of projects) {
|
|
15
|
+
const targetWithExecutor = Object.values(projectConfig.targets ?? {}).find((target) => target.executor === '@nx/cypress:cypress');
|
|
16
|
+
if (targetWithExecutor) {
|
|
17
|
+
for (const [, options] of allTargetOptions(targetWithExecutor)) {
|
|
18
|
+
if (options.cypressConfig) {
|
|
19
|
+
yield {
|
|
20
|
+
projectName,
|
|
21
|
+
projectConfig,
|
|
22
|
+
cypressConfigPath: options.cypressConfig,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
// might be using the crystal plugin
|
|
29
|
+
const result = await (0, devkit_1.globAsync)(tree, [
|
|
30
|
+
path_1.posix.join(projectConfig.root, config_1.CYPRESS_CONFIG_FILE_NAME_PATTERN),
|
|
31
|
+
]);
|
|
32
|
+
if (result.length > 0) {
|
|
33
|
+
yield {
|
|
34
|
+
projectName,
|
|
35
|
+
projectConfig,
|
|
36
|
+
cypressConfigPath: result[0],
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function getObjectProperty(config, name) {
|
|
43
|
+
ts ??= (0, ensure_typescript_1.ensureTypescript)();
|
|
44
|
+
return config.properties.find((p) => ts.isPropertyAssignment(p) && p.name.getText() === name);
|
|
45
|
+
}
|
|
46
|
+
function removeObjectProperty(config, property) {
|
|
47
|
+
ts ??= (0, ensure_typescript_1.ensureTypescript)();
|
|
48
|
+
return ts.factory.updateObjectLiteralExpression(config, config.properties.filter((p) => p !== property));
|
|
49
|
+
}
|
|
50
|
+
function updateObjectProperty(config, property, { newName, newValue }) {
|
|
51
|
+
ts ??= (0, ensure_typescript_1.ensureTypescript)();
|
|
52
|
+
if (!newName && !newValue) {
|
|
53
|
+
throw new Error('newName or newValue must be provided');
|
|
54
|
+
}
|
|
55
|
+
return ts.factory.updateObjectLiteralExpression(config, config.properties.map((p) => p === property
|
|
56
|
+
? ts.factory.updatePropertyAssignment(p, newName ? ts.factory.createIdentifier(newName) : p.name, newValue ? newValue : p.initializer)
|
|
57
|
+
: p));
|
|
58
|
+
}
|
|
59
|
+
function* allTargetOptions(target) {
|
|
60
|
+
if (target.options) {
|
|
61
|
+
yield [undefined, target.options];
|
|
62
|
+
}
|
|
63
|
+
if (!target.configurations) {
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
for (const [name, options] of Object.entries(target.configurations)) {
|
|
67
|
+
if (options !== undefined) {
|
|
68
|
+
yield [name, options];
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
package/src/utils/versions.d.ts
CHANGED
|
@@ -1,8 +1,21 @@
|
|
|
1
|
+
import { type Tree } from '@nx/devkit';
|
|
1
2
|
export declare const nxVersion: any;
|
|
2
3
|
export declare const eslintPluginCypressVersion = "^3.5.0";
|
|
3
4
|
export declare const typesNodeVersion = "18.16.9";
|
|
4
|
-
export declare const cypressViteDevServerVersion = "^
|
|
5
|
-
export declare const cypressVersion = "^
|
|
6
|
-
export declare const cypressWebpackVersion = "^
|
|
7
|
-
export declare const viteVersion = "
|
|
5
|
+
export declare const cypressViteDevServerVersion = "^6.0.3";
|
|
6
|
+
export declare const cypressVersion = "^14.2.1";
|
|
7
|
+
export declare const cypressWebpackVersion = "^4.0.2";
|
|
8
|
+
export declare const viteVersion = "^6.0.0";
|
|
8
9
|
export declare const htmlWebpackPluginVersion = "^5.5.0";
|
|
10
|
+
export declare function versions(tree: Tree, cypressMajorVersion?: number): Omit<typeof import("./versions"), "versions" | "getInstalledCypressMajorVersion" | "assertMinimumCypressVersion"> | {
|
|
11
|
+
nxVersion: any;
|
|
12
|
+
eslintPluginCypressVersion: string;
|
|
13
|
+
typesNodeVersion: string;
|
|
14
|
+
cypressViteDevServerVersion: string;
|
|
15
|
+
cypressVersion: string;
|
|
16
|
+
cypressWebpackVersion: string;
|
|
17
|
+
viteVersion: string;
|
|
18
|
+
htmlWebpackPluginVersion: string;
|
|
19
|
+
};
|
|
20
|
+
export declare function getInstalledCypressMajorVersion(tree?: Tree): number | null;
|
|
21
|
+
export declare function assertMinimumCypressVersion(minVersion: number, tree?: Tree): void;
|
package/src/utils/versions.js
CHANGED
|
@@ -1,11 +1,90 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.htmlWebpackPluginVersion = exports.viteVersion = exports.cypressWebpackVersion = exports.cypressVersion = exports.cypressViteDevServerVersion = exports.typesNodeVersion = exports.eslintPluginCypressVersion = exports.nxVersion = void 0;
|
|
4
|
+
exports.versions = versions;
|
|
5
|
+
exports.getInstalledCypressMajorVersion = getInstalledCypressMajorVersion;
|
|
6
|
+
exports.assertMinimumCypressVersion = assertMinimumCypressVersion;
|
|
7
|
+
const devkit_1 = require("@nx/devkit");
|
|
8
|
+
const semver_1 = require("semver");
|
|
4
9
|
exports.nxVersion = require('../../package.json').version;
|
|
5
10
|
exports.eslintPluginCypressVersion = '^3.5.0';
|
|
6
11
|
exports.typesNodeVersion = '18.16.9';
|
|
7
|
-
exports.cypressViteDevServerVersion = '^
|
|
8
|
-
exports.cypressVersion = '^
|
|
9
|
-
exports.cypressWebpackVersion = '^
|
|
10
|
-
exports.viteVersion = '
|
|
12
|
+
exports.cypressViteDevServerVersion = '^6.0.3';
|
|
13
|
+
exports.cypressVersion = '^14.2.1';
|
|
14
|
+
exports.cypressWebpackVersion = '^4.0.2';
|
|
15
|
+
exports.viteVersion = '^6.0.0';
|
|
11
16
|
exports.htmlWebpackPluginVersion = '^5.5.0';
|
|
17
|
+
const latestVersions = {
|
|
18
|
+
nxVersion: exports.nxVersion,
|
|
19
|
+
eslintPluginCypressVersion: exports.eslintPluginCypressVersion,
|
|
20
|
+
typesNodeVersion: exports.typesNodeVersion,
|
|
21
|
+
cypressViteDevServerVersion: exports.cypressViteDevServerVersion,
|
|
22
|
+
cypressVersion: exports.cypressVersion,
|
|
23
|
+
cypressWebpackVersion: exports.cypressWebpackVersion,
|
|
24
|
+
viteVersion: exports.viteVersion,
|
|
25
|
+
htmlWebpackPluginVersion: exports.htmlWebpackPluginVersion,
|
|
26
|
+
};
|
|
27
|
+
function versions(tree, cypressMajorVersion = getInstalledCypressMajorVersion(tree)) {
|
|
28
|
+
if (!cypressMajorVersion) {
|
|
29
|
+
return latestVersions;
|
|
30
|
+
}
|
|
31
|
+
if (cypressMajorVersion > 14) {
|
|
32
|
+
throw new Error(`Unsupported Cypress version: ${exports.cypressVersion}`);
|
|
33
|
+
}
|
|
34
|
+
if (cypressMajorVersion === 14) {
|
|
35
|
+
return latestVersions;
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
nxVersion: exports.nxVersion,
|
|
39
|
+
eslintPluginCypressVersion: '^3.5.0',
|
|
40
|
+
typesNodeVersion: '18.16.9',
|
|
41
|
+
cypressViteDevServerVersion: '^2.2.1',
|
|
42
|
+
cypressVersion: '^13.13.0',
|
|
43
|
+
cypressWebpackVersion: '^3.8.0',
|
|
44
|
+
viteVersion: '~5.0.0',
|
|
45
|
+
htmlWebpackPluginVersion: '^5.5.0',
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function getInstalledCypressMajorVersion(tree) {
|
|
49
|
+
try {
|
|
50
|
+
let version;
|
|
51
|
+
if (tree) {
|
|
52
|
+
version = getCypressVersionFromTree(tree);
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
version = getCypressVersionFromFileSystem();
|
|
56
|
+
}
|
|
57
|
+
return version ? (0, semver_1.major)(version) : null;
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
function assertMinimumCypressVersion(minVersion, tree) {
|
|
64
|
+
const version = getInstalledCypressMajorVersion(tree);
|
|
65
|
+
if (version && version < minVersion) {
|
|
66
|
+
throw new Error(`Cypress version of ${minVersion} or higher is not installed. Expected Cypress v${minVersion}+, found Cypress v${version} instead.`);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function getCypressVersionFromTree(tree) {
|
|
70
|
+
const packageJson = (0, devkit_1.readJson)(tree, 'package.json');
|
|
71
|
+
const installedVersion = packageJson.devDependencies?.cypress ?? packageJson.dependencies?.cypress;
|
|
72
|
+
if (!installedVersion) {
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
if (installedVersion === 'latest' || installedVersion === 'next') {
|
|
76
|
+
return (0, semver_1.clean)(exports.cypressVersion) ?? (0, semver_1.coerce)(exports.cypressVersion)?.version;
|
|
77
|
+
}
|
|
78
|
+
return (0, semver_1.clean)(installedVersion) ?? (0, semver_1.coerce)(installedVersion)?.version;
|
|
79
|
+
}
|
|
80
|
+
function getCypressVersionFromFileSystem() {
|
|
81
|
+
let packageJson;
|
|
82
|
+
try {
|
|
83
|
+
packageJson = require('cypress/package.json');
|
|
84
|
+
}
|
|
85
|
+
catch { }
|
|
86
|
+
if (!packageJson) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
return packageJson.version;
|
|
90
|
+
}
|