@nx/cypress 23.0.0-beta.23 → 23.0.0-beta.25
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/dist/src/migrations/update-23-0-0/migrate-create-nodes-v2-to-create-nodes.d.ts +9 -0
- package/dist/src/migrations/update-23-0-0/migrate-create-nodes-v2-to-create-nodes.js +134 -0
- package/dist/src/migrations/update-23-0-0/migrate-create-nodes-v2-to-create-nodes.md +25 -0
- package/migrations.json +6 -61
- package/package.json +7 -7
- package/dist/src/migrations/update-20-8-0/remove-experimental-fetch-polyfill.d.ts +0 -2
- package/dist/src/migrations/update-20-8-0/remove-experimental-fetch-polyfill.js +0 -48
- package/dist/src/migrations/update-20-8-0/remove-experimental-fetch-polyfill.md +0 -52
- package/dist/src/migrations/update-20-8-0/replace-experimental-just-in-time-compile.d.ts +0 -2
- package/dist/src/migrations/update-20-8-0/replace-experimental-just-in-time-compile.js +0 -94
- package/dist/src/migrations/update-20-8-0/replace-experimental-just-in-time-compile.md +0 -105
- package/dist/src/migrations/update-20-8-0/set-inject-document-domain.d.ts +0 -2
- package/dist/src/migrations/update-20-8-0/set-inject-document-domain.js +0 -128
- package/dist/src/migrations/update-20-8-0/set-inject-document-domain.md +0 -157
- package/dist/src/migrations/update-20-8-0/update-component-testing-mount-imports.d.ts +0 -2
- package/dist/src/migrations/update-20-8-0/update-component-testing-mount-imports.js +0 -151
- package/dist/src/migrations/update-20-8-0/update-component-testing-mount-imports.md +0 -134
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type Tree } from '@nx/devkit';
|
|
2
|
+
export default function migrateCreateNodesV2ToCreateNodes(tree: Tree): Promise<void>;
|
|
3
|
+
/**
|
|
4
|
+
* Rewrites named imports and re-exports of `createNodesV2` to `createNodes`
|
|
5
|
+
* when they come from one of the given module specifiers. Only the named
|
|
6
|
+
* bindings are touched — the module specifier, the `import`/`export` keyword,
|
|
7
|
+
* any `type` modifier, and any default import are left untouched.
|
|
8
|
+
*/
|
|
9
|
+
export declare function rewriteCreateNodesV2Imports(source: string, specifiers: ReadonlySet<string>): string;
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.default = migrateCreateNodesV2ToCreateNodes;
|
|
4
|
+
exports.rewriteCreateNodesV2Imports = rewriteCreateNodesV2Imports;
|
|
5
|
+
const devkit_1 = require("@nx/devkit");
|
|
6
|
+
const TS_EXTENSIONS = ['.ts', '.tsx', '.cts', '.mts'];
|
|
7
|
+
const DEPRECATED_NAME = 'createNodesV2';
|
|
8
|
+
const CANONICAL_NAME = 'createNodes';
|
|
9
|
+
// Module specifiers from which `@nx/cypress` publicly exposes `createNodesV2`.
|
|
10
|
+
// A named import or re-export of `createNodesV2` from one of these is rewritten
|
|
11
|
+
// to the canonical `createNodes` export.
|
|
12
|
+
const TARGET_SPECIFIERS = new Set(['@nx/cypress/plugin']);
|
|
13
|
+
let ts;
|
|
14
|
+
async function migrateCreateNodesV2ToCreateNodes(tree) {
|
|
15
|
+
let touchedCount = 0;
|
|
16
|
+
(0, devkit_1.visitNotIgnoredFiles)(tree, '.', (filePath) => {
|
|
17
|
+
if (!TS_EXTENSIONS.some((ext) => filePath.endsWith(ext))) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const original = tree.read(filePath, 'utf-8');
|
|
21
|
+
if (!original || !original.includes(DEPRECATED_NAME)) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const updated = rewriteCreateNodesV2Imports(original, TARGET_SPECIFIERS);
|
|
25
|
+
if (updated !== original) {
|
|
26
|
+
tree.write(filePath, updated);
|
|
27
|
+
touchedCount += 1;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
if (touchedCount > 0) {
|
|
31
|
+
devkit_1.logger.info(`Renamed \`${DEPRECATED_NAME}\` imports to \`${CANONICAL_NAME}\` in ${touchedCount} file(s).`);
|
|
32
|
+
}
|
|
33
|
+
await (0, devkit_1.formatFiles)(tree);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Rewrites named imports and re-exports of `createNodesV2` to `createNodes`
|
|
37
|
+
* when they come from one of the given module specifiers. Only the named
|
|
38
|
+
* bindings are touched — the module specifier, the `import`/`export` keyword,
|
|
39
|
+
* any `type` modifier, and any default import are left untouched.
|
|
40
|
+
*/
|
|
41
|
+
function rewriteCreateNodesV2Imports(source, specifiers) {
|
|
42
|
+
ts ??= (0, devkit_1.ensurePackage)('typescript', '*');
|
|
43
|
+
const sourceFile = ts.createSourceFile('tmp.ts', source, ts.ScriptTarget.Latest,
|
|
44
|
+
/* setParentNodes */ true, ts.ScriptKind.TSX);
|
|
45
|
+
const changes = [];
|
|
46
|
+
for (const stmt of sourceFile.statements) {
|
|
47
|
+
if (ts.isImportDeclaration(stmt)) {
|
|
48
|
+
collectImportRewrite(sourceFile, stmt, specifiers, changes);
|
|
49
|
+
}
|
|
50
|
+
else if (ts.isExportDeclaration(stmt)) {
|
|
51
|
+
collectExportRewrite(sourceFile, stmt, specifiers, changes);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return changes.length > 0 ? (0, devkit_1.applyChangesToString)(source, changes) : source;
|
|
55
|
+
}
|
|
56
|
+
function isTargetSpecifier(node, specifiers) {
|
|
57
|
+
return ts.isStringLiteral(node) && specifiers.has(node.text);
|
|
58
|
+
}
|
|
59
|
+
function collectImportRewrite(sourceFile, stmt, specifiers, changes) {
|
|
60
|
+
if (!isTargetSpecifier(stmt.moduleSpecifier, specifiers)) {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
const namedBindings = stmt.importClause?.namedBindings;
|
|
64
|
+
// Only `import { ... }` carries renameable named bindings. `import x`,
|
|
65
|
+
// `import * as ns`, and side-effect imports reference the module wholesale
|
|
66
|
+
// and keep working through the `createNodesV2` runtime alias, so we leave
|
|
67
|
+
// them be. A mixed `import def, { createNodesV2 }` still has its named
|
|
68
|
+
// bindings rewritten below — the default binding is untouched.
|
|
69
|
+
if (!namedBindings || !ts.isNamedImports(namedBindings)) {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
rewriteNamedBindings(sourceFile, namedBindings, changes);
|
|
73
|
+
}
|
|
74
|
+
function collectExportRewrite(sourceFile, stmt, specifiers, changes) {
|
|
75
|
+
if (!stmt.moduleSpecifier ||
|
|
76
|
+
!isTargetSpecifier(stmt.moduleSpecifier, specifiers)) {
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
// `export { ... } from '...'` can be rewritten; `export * from '...'` has no
|
|
80
|
+
// named bindings to rename.
|
|
81
|
+
if (!stmt.exportClause || !ts.isNamedExports(stmt.exportClause)) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
rewriteNamedBindings(sourceFile, stmt.exportClause, changes);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Re-renders the `{ ... }` of a named import/export, renaming any
|
|
88
|
+
* `createNodesV2` specifier to `createNodes`. If renaming would collide with a
|
|
89
|
+
* `createNodes` that is already present (e.g. `{ createNodes, createNodesV2 }`),
|
|
90
|
+
* the duplicate is dropped. Returns without recording a change when the binding
|
|
91
|
+
* list contains no `createNodesV2`.
|
|
92
|
+
*/
|
|
93
|
+
function rewriteNamedBindings(sourceFile, namedBindings, changes) {
|
|
94
|
+
const elements = namedBindings.elements;
|
|
95
|
+
const hasDeprecated = elements.some((el) => (el.propertyName ?? el.name).text === DEPRECATED_NAME);
|
|
96
|
+
if (!hasDeprecated) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
const seen = new Set();
|
|
100
|
+
const rendered = [];
|
|
101
|
+
for (const el of elements) {
|
|
102
|
+
const text = renderSpecifier(el);
|
|
103
|
+
if (!seen.has(text)) {
|
|
104
|
+
seen.add(text);
|
|
105
|
+
rendered.push(text);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const start = namedBindings.getStart(sourceFile);
|
|
109
|
+
changes.push({
|
|
110
|
+
type: devkit_1.ChangeType.Delete,
|
|
111
|
+
start,
|
|
112
|
+
length: namedBindings.getEnd() - start,
|
|
113
|
+
}, {
|
|
114
|
+
type: devkit_1.ChangeType.Insert,
|
|
115
|
+
index: start,
|
|
116
|
+
text: `{ ${rendered.join(', ')} }`,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
function renderSpecifier(el) {
|
|
120
|
+
const typePrefix = el.isTypeOnly ? 'type ' : '';
|
|
121
|
+
const rename = (name) => name === DEPRECATED_NAME ? CANONICAL_NAME : name;
|
|
122
|
+
// `{ name }` — no alias, so the local binding follows the rename.
|
|
123
|
+
if (!el.propertyName) {
|
|
124
|
+
return `${typePrefix}${rename(el.name.text)}`;
|
|
125
|
+
}
|
|
126
|
+
// `{ propertyName as name }` — only the imported (left) side is renamed; the
|
|
127
|
+
// local alias is preserved. A now-redundant alias such as
|
|
128
|
+
// `createNodesV2 as createNodes` collapses to `createNodes`.
|
|
129
|
+
const canonicalImported = rename(el.propertyName.text);
|
|
130
|
+
const localName = el.name.text;
|
|
131
|
+
return canonicalImported === localName
|
|
132
|
+
? `${typePrefix}${localName}`
|
|
133
|
+
: `${typePrefix}${canonicalImported} as ${localName}`;
|
|
134
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#### Rename `createNodesV2` imports to `createNodes`
|
|
2
|
+
|
|
3
|
+
`@nx/cypress` renamed its primary inferred-plugin export from `createNodesV2` to `createNodes`. The `createNodesV2` name is preserved as a deprecated alias for now, but new code should use `createNodes`.
|
|
4
|
+
|
|
5
|
+
This migration scans every `.ts`, `.tsx`, `.cts`, and `.mts` file in your workspace and rewrites named imports and re-exports of `createNodesV2` from `@nx/cypress/plugin` to `createNodes`.
|
|
6
|
+
|
|
7
|
+
#### Sample Code Changes
|
|
8
|
+
|
|
9
|
+
##### Before
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { createNodesV2 } from '@nx/cypress/plugin';
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
##### After
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { createNodes } from '@nx/cypress/plugin';
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Aliases are preserved (`createNodesV2 as cn` becomes `createNodes as cn`), and if a file already imports both names (`{ createNodes, createNodesV2 }`) the redundant binding is dropped.
|
|
22
|
+
|
|
23
|
+
#### What is not rewritten
|
|
24
|
+
|
|
25
|
+
Only static `import`/`export` named bindings from `@nx/cypress/plugin` are rewritten. Namespace imports, dynamic `import(...)`, `require(...)` destructuring, and property access such as `plugin.createNodesV2` are left untouched — they keep working through the `createNodesV2` runtime alias. Update those by hand if you want to drop the deprecated name everywhere.
|
package/migrations.json
CHANGED
|
@@ -1,45 +1,5 @@
|
|
|
1
1
|
{
|
|
2
2
|
"generators": {
|
|
3
|
-
"set-inject-document-domain": {
|
|
4
|
-
"cli": "nx",
|
|
5
|
-
"version": "20.8.0-beta.0",
|
|
6
|
-
"requires": {
|
|
7
|
-
"cypress": ">=14.0.0"
|
|
8
|
-
},
|
|
9
|
-
"description": "Replaces the `experimentalSkipDomainInjection` configuration option with the new `injectDocumentDomain` configuration option.",
|
|
10
|
-
"implementation": "./dist/src/migrations/update-20-8-0/set-inject-document-domain",
|
|
11
|
-
"documentation": "./dist/src/migrations/update-20-8-0/set-inject-document-domain.md"
|
|
12
|
-
},
|
|
13
|
-
"remove-experimental-fetch-polyfill": {
|
|
14
|
-
"cli": "nx",
|
|
15
|
-
"version": "20.8.0-beta.0",
|
|
16
|
-
"requires": {
|
|
17
|
-
"cypress": ">=14.0.0"
|
|
18
|
-
},
|
|
19
|
-
"description": "Removes the `experimentalFetchPolyfill` configuration option.",
|
|
20
|
-
"implementation": "./dist/src/migrations/update-20-8-0/remove-experimental-fetch-polyfill",
|
|
21
|
-
"documentation": "./dist/src/migrations/update-20-8-0/remove-experimental-fetch-polyfill.md"
|
|
22
|
-
},
|
|
23
|
-
"replace-experimental-just-in-time-compile": {
|
|
24
|
-
"cli": "nx",
|
|
25
|
-
"version": "20.8.0-beta.0",
|
|
26
|
-
"requires": {
|
|
27
|
-
"cypress": ">=14.0.0"
|
|
28
|
-
},
|
|
29
|
-
"description": "Replaces the `experimentalJustInTimeCompile` configuration option with the new `justInTimeCompile` configuration option.",
|
|
30
|
-
"implementation": "./dist/src/migrations/update-20-8-0/replace-experimental-just-in-time-compile",
|
|
31
|
-
"documentation": "./dist/src/migrations/update-20-8-0/replace-experimental-just-in-time-compile.md"
|
|
32
|
-
},
|
|
33
|
-
"update-component-testing-mount-imports": {
|
|
34
|
-
"cli": "nx",
|
|
35
|
-
"version": "20.8.0-beta.0",
|
|
36
|
-
"requires": {
|
|
37
|
-
"cypress": ">=14.0.0"
|
|
38
|
-
},
|
|
39
|
-
"description": "Updates the module specifier for the Component Testing `mount` function.",
|
|
40
|
-
"implementation": "./dist/src/migrations/update-20-8-0/update-component-testing-mount-imports",
|
|
41
|
-
"documentation": "./dist/src/migrations/update-20-8-0/update-component-testing-mount-imports.md"
|
|
42
|
-
},
|
|
43
3
|
"remove-tsconfig-and-copy-files-options-from-cypress-executor": {
|
|
44
4
|
"version": "21.0.0-beta.10",
|
|
45
5
|
"description": "Removes the `tsConfig` and `copyFiles` options from the `@nx/cypress:cypress` executor.",
|
|
@@ -86,30 +46,15 @@
|
|
|
86
46
|
"version": "23.0.0-beta.19",
|
|
87
47
|
"description": "Rewrites imports from `@nx/cypress/src/*` to either the public `@nx/cypress` entry (for re-exported symbols) or `@nx/cypress/internal` (for everything else). The `./src/*` wildcard was removed from the package's exports map.",
|
|
88
48
|
"implementation": "./dist/src/migrations/update-23-0-0/rewrite-internal-subpath-imports"
|
|
49
|
+
},
|
|
50
|
+
"update-23-0-0-migrate-create-nodes-v2-import": {
|
|
51
|
+
"version": "23.0.0-beta.24",
|
|
52
|
+
"description": "Rename imports of `createNodesV2` from `@nx/cypress/plugin` to the canonical `createNodes` export.",
|
|
53
|
+
"implementation": "./dist/src/migrations/update-23-0-0/migrate-create-nodes-v2-to-create-nodes",
|
|
54
|
+
"documentation": "./dist/src/migrations/update-23-0-0/migrate-create-nodes-v2-to-create-nodes.md"
|
|
89
55
|
}
|
|
90
56
|
},
|
|
91
57
|
"packageJsonUpdates": {
|
|
92
|
-
"20.8.0": {
|
|
93
|
-
"version": "20.8.0-beta.0",
|
|
94
|
-
"x-prompt": "Do you want to update the Cypress version to v14?",
|
|
95
|
-
"requires": {
|
|
96
|
-
"cypress": ">=13.0.0 <14.0.0"
|
|
97
|
-
},
|
|
98
|
-
"packages": {
|
|
99
|
-
"cypress": {
|
|
100
|
-
"version": "^14.2.1",
|
|
101
|
-
"alwaysAddToPackageJson": false
|
|
102
|
-
},
|
|
103
|
-
"@cypress/vite-dev-server": {
|
|
104
|
-
"version": "^6.0.3",
|
|
105
|
-
"alwaysAddToPackageJson": false
|
|
106
|
-
},
|
|
107
|
-
"@cypress/webpack-dev-server": {
|
|
108
|
-
"version": "^4.0.2",
|
|
109
|
-
"alwaysAddToPackageJson": false
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
},
|
|
113
58
|
"22.1.0": {
|
|
114
59
|
"version": "22.1.0-beta.6",
|
|
115
60
|
"x-prompt": "Do you want to update the Cypress version to v15?",
|
package/package.json
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nx/cypress",
|
|
3
|
-
"version": "23.0.0-beta.
|
|
3
|
+
"version": "23.0.0-beta.25",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist",
|
|
8
8
|
"!dist/tsconfig.tsbuildinfo",
|
|
9
|
-
"!dist/spec",
|
|
10
9
|
"migrations.json",
|
|
11
10
|
"executors.json",
|
|
12
11
|
"generators.json"
|
|
@@ -81,7 +80,8 @@
|
|
|
81
80
|
"executors": "./executors.json",
|
|
82
81
|
"ng-update": {
|
|
83
82
|
"requirements": {},
|
|
84
|
-
"migrations": "./migrations.json"
|
|
83
|
+
"migrations": "./migrations.json",
|
|
84
|
+
"supportsOptionalUpdates": true
|
|
85
85
|
},
|
|
86
86
|
"dependencies": {
|
|
87
87
|
"@phenomnomnominal/tsquery": "~6.2.0",
|
|
@@ -89,12 +89,12 @@
|
|
|
89
89
|
"semver": "^7.6.3",
|
|
90
90
|
"tree-kill": "^1.2.2",
|
|
91
91
|
"tslib": "^2.3.0",
|
|
92
|
-
"@nx/devkit": "23.0.0-beta.
|
|
93
|
-
"@nx/eslint": "23.0.0-beta.
|
|
94
|
-
"@nx/js": "23.0.0-beta.
|
|
92
|
+
"@nx/devkit": "23.0.0-beta.25",
|
|
93
|
+
"@nx/eslint": "23.0.0-beta.25",
|
|
94
|
+
"@nx/js": "23.0.0-beta.25"
|
|
95
95
|
},
|
|
96
96
|
"devDependencies": {
|
|
97
|
-
"nx": "23.0.0-beta.
|
|
97
|
+
"nx": "23.0.0-beta.25"
|
|
98
98
|
},
|
|
99
99
|
"peerDependencies": {
|
|
100
100
|
"cypress": ">= 13 < 16"
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.default = default_1;
|
|
4
|
-
const devkit_1 = require("@nx/devkit");
|
|
5
|
-
const internal_1 = require("@nx/js/internal");
|
|
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, internal_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 = (0, tsquery_1.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
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
#### Remove `experimentalFetchPolyfill` Configuration Option
|
|
2
|
-
|
|
3
|
-
Removes the `experimentalFetchPolyfill` configuration option that was removed in Cypress v14. Read more at the [migration notes](<https://docs.cypress.io/app/references/changelog#:~:text=The%20experimentalFetchPolyfill%20configuration%20option%20was,cy.intercept()%20for%20handling%20fetch%20requests>).
|
|
4
|
-
|
|
5
|
-
#### Examples
|
|
6
|
-
|
|
7
|
-
##### Before
|
|
8
|
-
|
|
9
|
-
```ts title="apps/app1-e2e/cypress.config.ts"
|
|
10
|
-
import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset';
|
|
11
|
-
import { defineConfig } from 'cypress';
|
|
12
|
-
|
|
13
|
-
export default defineConfig({
|
|
14
|
-
e2e: {
|
|
15
|
-
...nxE2EPreset(__filename, {
|
|
16
|
-
cypressDir: 'src',
|
|
17
|
-
bundler: 'vite',
|
|
18
|
-
webServerCommands: {
|
|
19
|
-
default: 'pnpm exec nx run app1:dev',
|
|
20
|
-
production: 'pnpm exec nx run app1:dev',
|
|
21
|
-
},
|
|
22
|
-
ciWebServerCommand: 'pnpm exec nx run app1:dev',
|
|
23
|
-
ciBaseUrl: 'http://localhost:4200',
|
|
24
|
-
}),
|
|
25
|
-
baseUrl: 'http://localhost:4200',
|
|
26
|
-
experimentalFetchPolyfill: true,
|
|
27
|
-
},
|
|
28
|
-
});
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
##### After
|
|
32
|
-
|
|
33
|
-
```ts title="apps/app1-e2e/cypress.config.ts"
|
|
34
|
-
import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset';
|
|
35
|
-
import { defineConfig } from 'cypress';
|
|
36
|
-
|
|
37
|
-
export default defineConfig({
|
|
38
|
-
e2e: {
|
|
39
|
-
...nxE2EPreset(__filename, {
|
|
40
|
-
cypressDir: 'src',
|
|
41
|
-
bundler: 'vite',
|
|
42
|
-
webServerCommands: {
|
|
43
|
-
default: 'pnpm exec nx run app1:dev',
|
|
44
|
-
production: 'pnpm exec nx run app1:dev',
|
|
45
|
-
},
|
|
46
|
-
ciWebServerCommand: 'pnpm exec nx run app1:dev',
|
|
47
|
-
ciBaseUrl: 'http://localhost:4200',
|
|
48
|
-
}),
|
|
49
|
-
baseUrl: 'http://localhost:4200',
|
|
50
|
-
},
|
|
51
|
-
});
|
|
52
|
-
```
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.default = default_1;
|
|
4
|
-
const devkit_1 = require("@nx/devkit");
|
|
5
|
-
const internal_1 = require("@nx/devkit/internal");
|
|
6
|
-
const internal_2 = require("@nx/js/internal");
|
|
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, internal_2.ensureTypescript)();
|
|
37
|
-
printer ??= ts.createPrinter();
|
|
38
|
-
const sourceFile = (0, tsquery_1.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 = (0, tsquery_1.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, internal_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
|
-
}
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
#### Replace the `experimentalJustInTimeCompile` Configuration Option with `justInTimeCompile`
|
|
2
|
-
|
|
3
|
-
Replaces the `experimentalJustInTimeCompile` configuration option with the new `justInTimeCompile` configuration option. Read more at the [migration notes](https://docs.cypress.io/app/references/migration-guide#CT-Just-in-Time-Compile-changes).
|
|
4
|
-
|
|
5
|
-
#### Examples
|
|
6
|
-
|
|
7
|
-
If the `experimentalJustInTimeCompile` configuration option is present and set to `true`, the migration will remove it. This is to account for the fact that JIT compilation is the default behavior in Cypress v14.
|
|
8
|
-
|
|
9
|
-
##### Before
|
|
10
|
-
|
|
11
|
-
```ts title="apps/app1/cypress.config.ts"
|
|
12
|
-
import { defineConfig } from 'cypress';
|
|
13
|
-
|
|
14
|
-
export default defineConfig({
|
|
15
|
-
component: {
|
|
16
|
-
devServer: {
|
|
17
|
-
framework: 'angular',
|
|
18
|
-
bundler: 'webpack',
|
|
19
|
-
},
|
|
20
|
-
experimentalJustInTimeCompile: true,
|
|
21
|
-
},
|
|
22
|
-
});
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
##### After
|
|
26
|
-
|
|
27
|
-
```ts title="apps/app1/cypress.config.ts"
|
|
28
|
-
import { defineConfig } from 'cypress';
|
|
29
|
-
|
|
30
|
-
export default defineConfig({
|
|
31
|
-
component: {
|
|
32
|
-
devServer: {
|
|
33
|
-
framework: 'angular',
|
|
34
|
-
bundler: 'webpack',
|
|
35
|
-
},
|
|
36
|
-
},
|
|
37
|
-
});
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
If the `experimentalJustInTimeCompile` configuration option is set to `false` and it is using webpack, the migration will rename it to `justInTimeCompile`.
|
|
41
|
-
|
|
42
|
-
##### Before
|
|
43
|
-
|
|
44
|
-
```ts title="apps/app1/cypress.config.ts"
|
|
45
|
-
import { defineConfig } from 'cypress';
|
|
46
|
-
|
|
47
|
-
export default defineConfig({
|
|
48
|
-
component: {
|
|
49
|
-
devServer: {
|
|
50
|
-
framework: 'angular',
|
|
51
|
-
bundler: 'webpack',
|
|
52
|
-
},
|
|
53
|
-
experimentalJustInTimeCompile: false,
|
|
54
|
-
},
|
|
55
|
-
});
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
##### After
|
|
59
|
-
|
|
60
|
-
```ts title="apps/app1/cypress.config.ts" {9}
|
|
61
|
-
import { defineConfig } from 'cypress';
|
|
62
|
-
|
|
63
|
-
export default defineConfig({
|
|
64
|
-
component: {
|
|
65
|
-
devServer: {
|
|
66
|
-
framework: 'angular',
|
|
67
|
-
bundler: 'webpack',
|
|
68
|
-
},
|
|
69
|
-
justInTimeCompile: false,
|
|
70
|
-
},
|
|
71
|
-
});
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
If the `experimentalJustInTimeCompile` configuration is set to any value and it is using Vite, the migration will remove it. This is to account for the fact that JIT compilation no longer applies to Vite.
|
|
75
|
-
|
|
76
|
-
##### Before
|
|
77
|
-
|
|
78
|
-
```ts title="apps/app1/cypress.config.ts"
|
|
79
|
-
import { defineConfig } from 'cypress';
|
|
80
|
-
|
|
81
|
-
export default defineConfig({
|
|
82
|
-
component: {
|
|
83
|
-
devServer: {
|
|
84
|
-
framework: 'react',
|
|
85
|
-
bundler: 'vite',
|
|
86
|
-
},
|
|
87
|
-
experimentalJustInTimeCompile: false,
|
|
88
|
-
},
|
|
89
|
-
});
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
##### After
|
|
93
|
-
|
|
94
|
-
```ts title="apps/app1/cypress.config.ts"
|
|
95
|
-
import { defineConfig } from 'cypress';
|
|
96
|
-
|
|
97
|
-
export default defineConfig({
|
|
98
|
-
component: {
|
|
99
|
-
devServer: {
|
|
100
|
-
framework: 'react',
|
|
101
|
-
bundler: 'vite',
|
|
102
|
-
},
|
|
103
|
-
},
|
|
104
|
-
});
|
|
105
|
-
```
|
|
@@ -1,128 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.default = default_1;
|
|
4
|
-
const devkit_1 = require("@nx/devkit");
|
|
5
|
-
const internal_1 = require("@nx/js/internal");
|
|
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, internal_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 = (0, tsquery_1.ast)(cypressConfig);
|
|
34
|
-
let e2eProperty = (0, migrations_1.getObjectProperty)(config, 'e2e');
|
|
35
|
-
let hasOtherTopLevelProperties = config.properties.some((p) => ts.isPropertyAssignment(p) &&
|
|
36
|
-
p.name.getText() !== 'e2e' &&
|
|
37
|
-
p.name.getText() !== 'component');
|
|
38
|
-
let updatedConfig = config;
|
|
39
|
-
const topLevelExperimentalSkipDomainInjectionProperty = (0, migrations_1.getObjectProperty)(updatedConfig, 'experimentalSkipDomainInjection');
|
|
40
|
-
const topLevelSkipDomainState = !topLevelExperimentalSkipDomainInjectionProperty
|
|
41
|
-
? 'not-set'
|
|
42
|
-
: !ts.isArrayLiteralExpression(topLevelExperimentalSkipDomainInjectionProperty.initializer) ||
|
|
43
|
-
topLevelExperimentalSkipDomainInjectionProperty.initializer.elements
|
|
44
|
-
.length > 0
|
|
45
|
-
? 'skipping'
|
|
46
|
-
: 'not-skipping';
|
|
47
|
-
let e2eSkipDomainState = 'not-set';
|
|
48
|
-
if (e2eProperty) {
|
|
49
|
-
let experimentalSkipDomainInjectionProperty;
|
|
50
|
-
let isObjectLiteral = false;
|
|
51
|
-
if (ts.isObjectLiteralExpression(e2eProperty.initializer)) {
|
|
52
|
-
experimentalSkipDomainInjectionProperty = (0, migrations_1.getObjectProperty)(e2eProperty.initializer, 'experimentalSkipDomainInjection');
|
|
53
|
-
isObjectLiteral = true;
|
|
54
|
-
}
|
|
55
|
-
if (experimentalSkipDomainInjectionProperty) {
|
|
56
|
-
e2eSkipDomainState =
|
|
57
|
-
!ts.isArrayLiteralExpression(experimentalSkipDomainInjectionProperty.initializer) ||
|
|
58
|
-
experimentalSkipDomainInjectionProperty.initializer.elements.length > 0
|
|
59
|
-
? 'skipping'
|
|
60
|
-
: 'not-skipping';
|
|
61
|
-
}
|
|
62
|
-
if (e2eSkipDomainState === 'not-set' &&
|
|
63
|
-
topLevelSkipDomainState === 'not-set') {
|
|
64
|
-
updatedConfig = (0, migrations_1.updateObjectProperty)(updatedConfig, e2eProperty, {
|
|
65
|
-
newValue: setInjectDocumentDomainInObject(e2eProperty.initializer),
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
else if (e2eSkipDomainState === 'not-skipping') {
|
|
69
|
-
updatedConfig = (0, migrations_1.updateObjectProperty)(updatedConfig, e2eProperty, {
|
|
70
|
-
newValue: replaceExperimentalSkipDomainInjectionInObject(e2eProperty.initializer),
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
else if (e2eSkipDomainState === 'skipping') {
|
|
74
|
-
updatedConfig = (0, migrations_1.updateObjectProperty)(updatedConfig, e2eProperty, {
|
|
75
|
-
newValue: (0, migrations_1.removeObjectProperty)(
|
|
76
|
-
// we only determine that it's skipping if it's an object literal
|
|
77
|
-
e2eProperty.initializer, (0, migrations_1.getObjectProperty)(e2eProperty.initializer, 'experimentalSkipDomainInjection')),
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
if (topLevelSkipDomainState === 'not-set' &&
|
|
82
|
-
!e2eProperty &&
|
|
83
|
-
hasOtherTopLevelProperties) {
|
|
84
|
-
updatedConfig = setInjectDocumentDomainInObject(updatedConfig);
|
|
85
|
-
}
|
|
86
|
-
else if (topLevelSkipDomainState === 'not-skipping') {
|
|
87
|
-
updatedConfig =
|
|
88
|
-
replaceExperimentalSkipDomainInjectionInObject(updatedConfig);
|
|
89
|
-
}
|
|
90
|
-
else if (topLevelSkipDomainState === 'skipping') {
|
|
91
|
-
updatedConfig = (0, migrations_1.removeObjectProperty)(updatedConfig, topLevelExperimentalSkipDomainInjectionProperty);
|
|
92
|
-
}
|
|
93
|
-
return cypressConfig.replace(config.getText(), printer.printNode(ts.EmitHint.Unspecified, updatedConfig, sourceFile));
|
|
94
|
-
}
|
|
95
|
-
function setInjectDocumentDomainInObject(config) {
|
|
96
|
-
let configToUpdate;
|
|
97
|
-
if (ts.isObjectLiteralExpression(config)) {
|
|
98
|
-
configToUpdate = config;
|
|
99
|
-
}
|
|
100
|
-
else {
|
|
101
|
-
// spread the current expression into a new object literal
|
|
102
|
-
configToUpdate = ts.factory.createObjectLiteralExpression([
|
|
103
|
-
ts.factory.createSpreadAssignment(config),
|
|
104
|
-
]);
|
|
105
|
-
}
|
|
106
|
-
return ts.factory.updateObjectLiteralExpression(configToUpdate, ts.factory.createNodeArray([
|
|
107
|
-
...configToUpdate.properties,
|
|
108
|
-
getInjectDocumentDomainPropertyAssignment(),
|
|
109
|
-
]));
|
|
110
|
-
}
|
|
111
|
-
function replaceExperimentalSkipDomainInjectionInObject(config) {
|
|
112
|
-
let configToUpdate;
|
|
113
|
-
if (ts.isObjectLiteralExpression(config)) {
|
|
114
|
-
configToUpdate = config;
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
// spread the current expression into a new object literal
|
|
118
|
-
configToUpdate = ts.factory.createObjectLiteralExpression([
|
|
119
|
-
ts.factory.createSpreadAssignment(config),
|
|
120
|
-
]);
|
|
121
|
-
}
|
|
122
|
-
return ts.factory.updateObjectLiteralExpression(configToUpdate, configToUpdate.properties.map((property) => property.name?.getText() === 'experimentalSkipDomainInjection'
|
|
123
|
-
? getInjectDocumentDomainPropertyAssignment()
|
|
124
|
-
: property));
|
|
125
|
-
}
|
|
126
|
-
function getInjectDocumentDomainPropertyAssignment() {
|
|
127
|
-
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');
|
|
128
|
-
}
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
#### Set `injectDocumentDomain` Configuration Option
|
|
2
|
-
|
|
3
|
-
Replaces the removed `experimentalSkipDomainInjection` configuration option with the new `injectDocumentDomain` configuration option when needed. Skipping domain injection is the default behavior in Cypress v14 and therefore, it is required to use the `cy.origin()` command when navigating between domains. The `injectDocumentDomain` option was introduced to ease the transition to v14, but it is deprecated and will be removed in Cypress v15. Read more at the [migration notes](https://docs.cypress.io/app/references/migration-guide#Changes-to-cyorigin).
|
|
4
|
-
|
|
5
|
-
#### Examples
|
|
6
|
-
|
|
7
|
-
If the `experimentalSkipDomainInjection` configuration option is present, the migration will remove it. This is to account for the fact that skipping domain injection is the default behavior in Cypress v14.
|
|
8
|
-
|
|
9
|
-
##### Before
|
|
10
|
-
|
|
11
|
-
```ts title="apps/app1-e2e/cypress.config.ts"
|
|
12
|
-
import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset';
|
|
13
|
-
import { defineConfig } from 'cypress';
|
|
14
|
-
|
|
15
|
-
export default defineConfig({
|
|
16
|
-
e2e: {
|
|
17
|
-
...nxE2EPreset(__filename, {
|
|
18
|
-
cypressDir: 'src',
|
|
19
|
-
bundler: 'vite',
|
|
20
|
-
webServerCommands: {
|
|
21
|
-
default: 'pnpm exec nx run app1:dev',
|
|
22
|
-
production: 'pnpm exec nx run app1:dev',
|
|
23
|
-
},
|
|
24
|
-
ciWebServerCommand: 'pnpm exec nx run app1:dev',
|
|
25
|
-
ciBaseUrl: 'http://localhost:4200',
|
|
26
|
-
}),
|
|
27
|
-
baseUrl: 'http://localhost:4200',
|
|
28
|
-
experimentalSkipDomainInjection: ['https://example.com'],
|
|
29
|
-
},
|
|
30
|
-
});
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
##### After
|
|
34
|
-
|
|
35
|
-
```ts title="apps/app1-e2e/cypress.config.ts"
|
|
36
|
-
import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset';
|
|
37
|
-
import { defineConfig } from 'cypress';
|
|
38
|
-
|
|
39
|
-
export default defineConfig({
|
|
40
|
-
e2e: {
|
|
41
|
-
...nxE2EPreset(__filename, {
|
|
42
|
-
cypressDir: 'src',
|
|
43
|
-
bundler: 'vite',
|
|
44
|
-
webServerCommands: {
|
|
45
|
-
default: 'pnpm exec nx run app1:dev',
|
|
46
|
-
production: 'pnpm exec nx run app1:dev',
|
|
47
|
-
},
|
|
48
|
-
ciWebServerCommand: 'pnpm exec nx run app1:dev',
|
|
49
|
-
ciBaseUrl: 'http://localhost:4200',
|
|
50
|
-
}),
|
|
51
|
-
baseUrl: 'http://localhost:4200',
|
|
52
|
-
},
|
|
53
|
-
});
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
If the `experimentalSkipDomainInjection` configuration option is present and set to an empty array (no domain injection is skipped), the migration will remove it and will set the `injectDocumentDomain` option to `true`.
|
|
57
|
-
|
|
58
|
-
##### Before
|
|
59
|
-
|
|
60
|
-
```ts title="apps/app1-e2e/cypress.config.ts"
|
|
61
|
-
import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset';
|
|
62
|
-
import { defineConfig } from 'cypress';
|
|
63
|
-
|
|
64
|
-
export default defineConfig({
|
|
65
|
-
e2e: {
|
|
66
|
-
...nxE2EPreset(__filename, {
|
|
67
|
-
cypressDir: 'src',
|
|
68
|
-
bundler: 'vite',
|
|
69
|
-
webServerCommands: {
|
|
70
|
-
default: 'pnpm exec nx run app1:dev',
|
|
71
|
-
production: 'pnpm exec nx run app1:dev',
|
|
72
|
-
},
|
|
73
|
-
ciWebServerCommand: 'pnpm exec nx run app1:dev',
|
|
74
|
-
ciBaseUrl: 'http://localhost:4200',
|
|
75
|
-
}),
|
|
76
|
-
baseUrl: 'http://localhost:4200',
|
|
77
|
-
experimentalSkipDomainInjection: [],
|
|
78
|
-
},
|
|
79
|
-
});
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
##### After
|
|
83
|
-
|
|
84
|
-
```ts title="apps/app1-e2e/cypress.config.ts" {17-19}
|
|
85
|
-
import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset';
|
|
86
|
-
import { defineConfig } from 'cypress';
|
|
87
|
-
|
|
88
|
-
export default defineConfig({
|
|
89
|
-
e2e: {
|
|
90
|
-
...nxE2EPreset(__filename, {
|
|
91
|
-
cypressDir: 'src',
|
|
92
|
-
bundler: 'vite',
|
|
93
|
-
webServerCommands: {
|
|
94
|
-
default: 'pnpm exec nx run app1:dev',
|
|
95
|
-
production: 'pnpm exec nx run app1:dev',
|
|
96
|
-
},
|
|
97
|
-
ciWebServerCommand: 'pnpm exec nx run app1:dev',
|
|
98
|
-
ciBaseUrl: 'http://localhost:4200',
|
|
99
|
-
}),
|
|
100
|
-
baseUrl: 'http://localhost:4200',
|
|
101
|
-
// Please ensure you use `cy.origin()` when navigating between domains and remove this option.
|
|
102
|
-
// See https://docs.cypress.io/app/references/migration-guide#Changes-to-cyorigin
|
|
103
|
-
injectDocumentDomain: true,
|
|
104
|
-
},
|
|
105
|
-
});
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
If the `experimentalSkipDomainInjection` configuration option is not present (no domain injection is skipped), the migration will set the `injectDocumentDomain` option to `true`.
|
|
109
|
-
|
|
110
|
-
##### Before
|
|
111
|
-
|
|
112
|
-
```ts title="apps/app1-e2e/cypress.config.ts"
|
|
113
|
-
import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset';
|
|
114
|
-
import { defineConfig } from 'cypress';
|
|
115
|
-
|
|
116
|
-
export default defineConfig({
|
|
117
|
-
e2e: {
|
|
118
|
-
...nxE2EPreset(__filename, {
|
|
119
|
-
cypressDir: 'src',
|
|
120
|
-
bundler: 'vite',
|
|
121
|
-
webServerCommands: {
|
|
122
|
-
default: 'pnpm exec nx run app1:dev',
|
|
123
|
-
production: 'pnpm exec nx run app1:dev',
|
|
124
|
-
},
|
|
125
|
-
ciWebServerCommand: 'pnpm exec nx run app1:dev',
|
|
126
|
-
ciBaseUrl: 'http://localhost:4200',
|
|
127
|
-
}),
|
|
128
|
-
baseUrl: 'http://localhost:4200',
|
|
129
|
-
},
|
|
130
|
-
});
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
##### After
|
|
134
|
-
|
|
135
|
-
```ts title="apps/app1-e2e/cypress.config.ts" {17-19}
|
|
136
|
-
import { nxE2EPreset } from '@nx/cypress/plugins/cypress-preset';
|
|
137
|
-
import { defineConfig } from 'cypress';
|
|
138
|
-
|
|
139
|
-
export default defineConfig({
|
|
140
|
-
e2e: {
|
|
141
|
-
...nxE2EPreset(__filename, {
|
|
142
|
-
cypressDir: 'src',
|
|
143
|
-
bundler: 'vite',
|
|
144
|
-
webServerCommands: {
|
|
145
|
-
default: 'pnpm exec nx run app1:dev',
|
|
146
|
-
production: 'pnpm exec nx run app1:dev',
|
|
147
|
-
},
|
|
148
|
-
ciWebServerCommand: 'pnpm exec nx run app1:dev',
|
|
149
|
-
ciBaseUrl: 'http://localhost:4200',
|
|
150
|
-
}),
|
|
151
|
-
baseUrl: 'http://localhost:4200',
|
|
152
|
-
// Please ensure you use `cy.origin()` when navigating between domains and remove this option.
|
|
153
|
-
// See https://docs.cypress.io/app/references/migration-guide#Changes-to-cyorigin
|
|
154
|
-
injectDocumentDomain: true,
|
|
155
|
-
},
|
|
156
|
-
});
|
|
157
|
-
```
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.default = default_1;
|
|
4
|
-
const devkit_1 = require("@nx/devkit");
|
|
5
|
-
const internal_1 = require("@nx/js/internal");
|
|
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, internal_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 = (0, tsquery_1.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 = (0, tsquery_1.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 = (0, tsquery_1.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 = (0, tsquery_1.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 = (0, tsquery_1.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, (0, tsquery_1.ast)(fileContent));
|
|
145
|
-
}
|
|
146
|
-
return node.getText();
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
function isJsTsFile(filePath) {
|
|
150
|
-
return /\.[cm]?[jt]sx?$/.test(filePath);
|
|
151
|
-
}
|
|
@@ -1,134 +0,0 @@
|
|
|
1
|
-
#### Update Component Testing `mount` Imports
|
|
2
|
-
|
|
3
|
-
Updates the relevant module specifiers when importing the `mount` function and using the Angular or React frameworks. Read more at the [Angular migration notes](https://docs.cypress.io/app/references/migration-guide#Angular-1720-CT-no-longer-supported) and the [React migration notes](https://docs.cypress.io/app/references/migration-guide#React-18-CT-no-longer-supported).
|
|
4
|
-
|
|
5
|
-
#### Examples
|
|
6
|
-
|
|
7
|
-
If using the Angular framework with a version greater than or equal to v17.2.0 and importing the `mount` function from the `cypress/angular-signals` module, the migration will update the import to use the `cypress/angular` module.
|
|
8
|
-
|
|
9
|
-
##### Before
|
|
10
|
-
|
|
11
|
-
```ts title="apps/app1/cypress/support/component.ts"
|
|
12
|
-
import { mount } from 'cypress/angular-signals';
|
|
13
|
-
import './commands';
|
|
14
|
-
|
|
15
|
-
declare global {
|
|
16
|
-
namespace Cypress {
|
|
17
|
-
interface Chainable<Subject> {
|
|
18
|
-
mount: typeof mount;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
Cypress.Commands.add('mount', mount);
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
##### After
|
|
27
|
-
|
|
28
|
-
```ts title="apps/app1/cypress/support/component.ts" {1}
|
|
29
|
-
import { mount } from 'cypress/angular';
|
|
30
|
-
import './commands';
|
|
31
|
-
|
|
32
|
-
declare global {
|
|
33
|
-
namespace Cypress {
|
|
34
|
-
interface Chainable<Subject> {
|
|
35
|
-
mount: typeof mount;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
Cypress.Commands.add('mount', mount);
|
|
41
|
-
```
|
|
42
|
-
|
|
43
|
-
If using the Angular framework with a version lower than v17.2.0 and importing the `mount` function from the `cypress/angular` module, the migration will install the `@cypress/angular@2` package and update the import to use the `@cypress/angular` module.
|
|
44
|
-
|
|
45
|
-
##### Before
|
|
46
|
-
|
|
47
|
-
```json title="package.json"
|
|
48
|
-
{
|
|
49
|
-
"name": "@my-repo/source",
|
|
50
|
-
"dependencies": {
|
|
51
|
-
...
|
|
52
|
-
"cypress": "^14.2.1"
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
```ts title="apps/app1/cypress/support/component.ts"
|
|
58
|
-
import { mount } from 'cypress/angular';
|
|
59
|
-
import './commands';
|
|
60
|
-
|
|
61
|
-
declare global {
|
|
62
|
-
namespace Cypress {
|
|
63
|
-
interface Chainable<Subject> {
|
|
64
|
-
mount: typeof mount;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
Cypress.Commands.add('mount', mount);
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
##### After
|
|
73
|
-
|
|
74
|
-
```json title="package.json" {6}
|
|
75
|
-
{
|
|
76
|
-
"name": "@my-repo/source",
|
|
77
|
-
"dependencies": {
|
|
78
|
-
...
|
|
79
|
-
"cypress": "^14.2.1",
|
|
80
|
-
"@cypress/angular": "^2.1.0"
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
```ts title="apps/app1/cypress/support/component.ts" {1}
|
|
86
|
-
import { mount } from '@cypress/angular';
|
|
87
|
-
import './commands';
|
|
88
|
-
|
|
89
|
-
declare global {
|
|
90
|
-
namespace Cypress {
|
|
91
|
-
interface Chainable<Subject> {
|
|
92
|
-
mount: typeof mount;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
Cypress.Commands.add('mount', mount);
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
If using the React framework and importing the `mount` function from the `cypress/react18` module, the migration will update the import to use the `cypress/react` module.
|
|
101
|
-
|
|
102
|
-
##### Before
|
|
103
|
-
|
|
104
|
-
```ts title="apps/app1/cypress/support/component.ts"
|
|
105
|
-
import { mount } from 'cypress/react18';
|
|
106
|
-
import './commands';
|
|
107
|
-
|
|
108
|
-
declare global {
|
|
109
|
-
namespace Cypress {
|
|
110
|
-
interface Chainable<Subject> {
|
|
111
|
-
mount: typeof mount;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
Cypress.Commands.add('mount', mount);
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
##### After
|
|
120
|
-
|
|
121
|
-
```ts title="apps/app1/cypress/support/component.ts" {1}
|
|
122
|
-
import { mount } from 'cypress/react';
|
|
123
|
-
import './commands';
|
|
124
|
-
|
|
125
|
-
declare global {
|
|
126
|
-
namespace Cypress {
|
|
127
|
-
interface Chainable<Subject> {
|
|
128
|
-
mount: typeof mount;
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
Cypress.Commands.add('mount', mount);
|
|
134
|
-
```
|