@nx/cypress 0.0.0-pr-22179-271588f

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.
Files changed (116) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +68 -0
  3. package/executors.json +9 -0
  4. package/generators.json +37 -0
  5. package/index.d.ts +11 -0
  6. package/index.js +20 -0
  7. package/migrations.json +111 -0
  8. package/package.json +58 -0
  9. package/plugin.d.ts +1 -0
  10. package/plugin.js +6 -0
  11. package/plugins/cypress-preset.d.ts +69 -0
  12. package/plugins/cypress-preset.js +154 -0
  13. package/src/executors/cypress/cypress.impl.d.ts +40 -0
  14. package/src/executors/cypress/cypress.impl.js +182 -0
  15. package/src/executors/cypress/schema.json +186 -0
  16. package/src/generators/base-setup/base-setup.d.ts +12 -0
  17. package/src/generators/base-setup/base-setup.js +80 -0
  18. package/src/generators/base-setup/files/common/__directory__/fixtures/example.json +5 -0
  19. package/src/generators/base-setup/files/common/__directory__/support/commands.ts__ext__ +35 -0
  20. package/src/generators/base-setup/files/common/__directory__/tsconfig.json__ext__ +20 -0
  21. package/src/generators/base-setup/files/config-js-cjs/__directory__/support/commands.js__ext__ +35 -0
  22. package/src/generators/base-setup/files/config-js-cjs/cypress.config.js__ext__ +3 -0
  23. package/src/generators/base-setup/files/config-js-esm/__directory__/support/commands.js__ext__ +35 -0
  24. package/src/generators/base-setup/files/config-js-esm/cypress.config.js__ext__ +3 -0
  25. package/src/generators/base-setup/files/config-ts/__directory__/support/commands.ts__ext__ +35 -0
  26. package/src/generators/base-setup/files/config-ts/cypress.config.ts__ext__ +3 -0
  27. package/src/generators/component-configuration/component-configuration.d.ts +6 -0
  28. package/src/generators/component-configuration/component-configuration.js +165 -0
  29. package/src/generators/component-configuration/files/__directory__/support/component-index.html +16 -0
  30. package/src/generators/component-configuration/files/__directory__/support/component.ts__ext__ +27 -0
  31. package/src/generators/component-configuration/schema.d.ts +14 -0
  32. package/src/generators/component-configuration/schema.json +43 -0
  33. package/src/generators/configuration/configuration.d.ts +23 -0
  34. package/src/generators/configuration/configuration.js +220 -0
  35. package/src/generators/configuration/files/v10/__directory__/e2e/app.cy.ts__tmpl__ +13 -0
  36. package/src/generators/configuration/files/v10/__directory__/support/app.po.ts__tmpl__ +1 -0
  37. package/src/generators/configuration/files/v10/__directory__/support/e2e.ts__tmpl__ +17 -0
  38. package/src/generators/configuration/files/v9/__directory__/fixtures/example.json__tmpl__ +4 -0
  39. package/src/generators/configuration/files/v9/__directory__/integration/app.spec.ts__tmpl__ +13 -0
  40. package/src/generators/configuration/files/v9/__directory__/plugins/index.js +22 -0
  41. package/src/generators/configuration/files/v9/__directory__/support/app.po.ts__tmpl__ +1 -0
  42. package/src/generators/configuration/files/v9/__directory__/support/commands.ts__tmpl__ +33 -0
  43. package/src/generators/configuration/files/v9/__directory__/support/index.ts__tmpl__ +17 -0
  44. package/src/generators/configuration/files/v9/__directory__/tsconfig.json +10 -0
  45. package/src/generators/configuration/files/v9/cypress.json +12 -0
  46. package/src/generators/configuration/schema.json +96 -0
  47. package/src/generators/cypress-project/cypress-project.d.ts +16 -0
  48. package/src/generators/cypress-project/cypress-project.js +213 -0
  49. package/src/generators/cypress-project/files/v10-and-after/cypress.config.ts__tmpl__ +10 -0
  50. package/src/generators/cypress-project/files/v10-and-after/src/e2e/app.cy.ts__tmpl__ +13 -0
  51. package/src/generators/cypress-project/files/v10-and-after/src/fixtures/example.json__tmpl__ +4 -0
  52. package/src/generators/cypress-project/files/v10-and-after/src/support/app.po.ts__tmpl__ +1 -0
  53. package/src/generators/cypress-project/files/v10-and-after/src/support/commands.ts__tmpl__ +33 -0
  54. package/src/generators/cypress-project/files/v10-and-after/src/support/e2e.ts__tmpl__ +17 -0
  55. package/src/generators/cypress-project/files/v10-and-after/tsconfig.json +10 -0
  56. package/src/generators/cypress-project/files/v9-and-under/cypress.json +12 -0
  57. package/src/generators/cypress-project/files/v9-and-under/src/fixtures/example.json__tmpl__ +4 -0
  58. package/src/generators/cypress-project/files/v9-and-under/src/integration/app.spec.ts__tmpl__ +13 -0
  59. package/src/generators/cypress-project/files/v9-and-under/src/plugins/index.js +22 -0
  60. package/src/generators/cypress-project/files/v9-and-under/src/support/app.po.ts__tmpl__ +1 -0
  61. package/src/generators/cypress-project/files/v9-and-under/src/support/commands.ts__tmpl__ +33 -0
  62. package/src/generators/cypress-project/files/v9-and-under/src/support/index.ts__tmpl__ +17 -0
  63. package/src/generators/cypress-project/files/v9-and-under/tsconfig.json +10 -0
  64. package/src/generators/cypress-project/schema.d.ts +17 -0
  65. package/src/generators/cypress-project/schema.json +78 -0
  66. package/src/generators/init/init.d.ts +6 -0
  67. package/src/generators/init/init.js +97 -0
  68. package/src/generators/init/schema.d.ts +7 -0
  69. package/src/generators/init/schema.json +34 -0
  70. package/src/generators/migrate-to-cypress-11/conversion.util.d.ts +39 -0
  71. package/src/generators/migrate-to-cypress-11/conversion.util.js +246 -0
  72. package/src/generators/migrate-to-cypress-11/migrate-to-cypress-11.d.ts +3 -0
  73. package/src/generators/migrate-to-cypress-11/migrate-to-cypress-11.js +93 -0
  74. package/src/generators/migrate-to-cypress-11/schema.json +15 -0
  75. package/src/migrations/update-15-0-0/add-cypress-inputs.d.ts +2 -0
  76. package/src/migrations/update-15-0-0/add-cypress-inputs.js +42 -0
  77. package/src/migrations/update-15-0-0/update-cy-mount-usage.d.ts +5 -0
  78. package/src/migrations/update-15-0-0/update-cy-mount-usage.js +119 -0
  79. package/src/migrations/update-15-1-0/cypress-11.d.ts +6 -0
  80. package/src/migrations/update-15-1-0/cypress-11.js +114 -0
  81. package/src/migrations/update-15-5-0/helpers.d.ts +3 -0
  82. package/src/migrations/update-15-5-0/helpers.js +39 -0
  83. package/src/migrations/update-15-5-0/update-to-cypress-12.d.ts +24 -0
  84. package/src/migrations/update-15-5-0/update-to-cypress-12.js +180 -0
  85. package/src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages.d.ts +2 -0
  86. package/src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages.js +9 -0
  87. package/src/migrations/update-16-2-0/update-cy-tsconfig.d.ts +3 -0
  88. package/src/migrations/update-16-2-0/update-cy-tsconfig.js +77 -0
  89. package/src/migrations/update-16-4-0/tsconfig-sourcemaps.d.ts +3 -0
  90. package/src/migrations/update-16-4-0/tsconfig-sourcemaps.js +62 -0
  91. package/src/migrations/update-16-8-0/cypress-13.d.ts +7 -0
  92. package/src/migrations/update-16-8-0/cypress-13.js +179 -0
  93. package/src/migrations/update-18-1-0/update-cypress-version-13-6-6.d.ts +2 -0
  94. package/src/migrations/update-18-1-0/update-cypress-version-13-6-6.js +12 -0
  95. package/src/plugins/plugin.d.ts +8 -0
  96. package/src/plugins/plugin.js +195 -0
  97. package/src/plugins/preprocessor-vite.d.ts +32 -0
  98. package/src/plugins/preprocessor-vite.js +97 -0
  99. package/src/utils/add-linter.d.ts +22 -0
  100. package/src/utils/add-linter.js +93 -0
  101. package/src/utils/config.d.ts +17 -0
  102. package/src/utils/config.js +115 -0
  103. package/src/utils/constants.d.ts +4 -0
  104. package/src/utils/constants.js +7 -0
  105. package/src/utils/ct-helpers.d.ts +16 -0
  106. package/src/utils/ct-helpers.js +86 -0
  107. package/src/utils/cypress-version.d.ts +5 -0
  108. package/src/utils/cypress-version.js +33 -0
  109. package/src/utils/find-target-options.d.ts +17 -0
  110. package/src/utils/find-target-options.js +136 -0
  111. package/src/utils/project-name.d.ts +3 -0
  112. package/src/utils/project-name.js +19 -0
  113. package/src/utils/start-dev-server.d.ts +9 -0
  114. package/src/utils/start-dev-server.js +157 -0
  115. package/src/utils/versions.d.ts +9 -0
  116. package/src/utils/versions.js +12 -0
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.updateCyFile = exports.addMountCommand = exports.updateCyMountUsage = void 0;
4
+ const ct_helpers_1 = require("../../utils/ct-helpers");
5
+ const cypress_version_1 = require("../../utils/cypress-version");
6
+ const devkit_1 = require("@nx/devkit");
7
+ const executor_options_utils_1 = require("@nx/devkit/src/generators/executor-options-utils");
8
+ const semver_1 = require("@nx/devkit/src/utils/semver");
9
+ const tsquery_1 = require("@phenomnomnominal/tsquery");
10
+ const semver_2 = require("semver");
11
+ async function updateCyMountUsage(tree) {
12
+ if ((0, cypress_version_1.installedCypressVersion)() < 10) {
13
+ return;
14
+ }
15
+ const projects = (0, devkit_1.getProjects)(tree);
16
+ const graph = await (0, devkit_1.createProjectGraphAsync)();
17
+ (0, executor_options_utils_1.forEachExecutorOptions)(tree, '@nrwl/cypress:cypress', (options, projectName) => {
18
+ if (options.testingType !== 'component' || !options.devServerTarget) {
19
+ return;
20
+ }
21
+ const parsed = (0, devkit_1.parseTargetString)(options.devServerTarget, graph);
22
+ if (!parsed?.project || !parsed?.target) {
23
+ return;
24
+ }
25
+ const buildProjectConfig = projects.get(parsed.project);
26
+ const framework = getFramework(tree, parsed.configuration
27
+ ? buildProjectConfig.targets[parsed.target].configurations[parsed.configuration]
28
+ : buildProjectConfig.targets[parsed.target]);
29
+ const ctProjectConfig = projects.get(projectName);
30
+ addMountCommand(tree, ctProjectConfig.root, framework);
31
+ (0, devkit_1.visitNotIgnoredFiles)(tree, ctProjectConfig.sourceRoot, (filePath) => {
32
+ if (ct_helpers_1.CY_FILE_MATCHER.test(filePath)) {
33
+ updateCyFile(tree, filePath, framework);
34
+ }
35
+ });
36
+ });
37
+ await (0, devkit_1.formatFiles)(tree);
38
+ }
39
+ exports.updateCyMountUsage = updateCyMountUsage;
40
+ function addMountCommand(tree, projectRoot, framework) {
41
+ const commandFilePath = (0, devkit_1.joinPathFragments)(projectRoot, 'cypress', 'support', 'commands.ts');
42
+ if (!tree.exists(commandFilePath)) {
43
+ return;
44
+ }
45
+ const commandFile = tree.read(commandFilePath, 'utf-8');
46
+ const mountCommand = tsquery_1.tsquery.query(commandFile, 'CallExpression:has(StringLiteral[value="mount"]) PropertyAccessExpression:has(Identifier[name="add"])');
47
+ if (mountCommand?.length > 0) {
48
+ return;
49
+ }
50
+ const existingCommands = tsquery_1.tsquery.query(commandFile, 'InterfaceDeclaration:has(Identifier[name="Chainable"]) > MethodSignature, InterfaceDeclaration:has(Identifier[name="Chainable"]) > PropertySignature');
51
+ const isGlobalDeclaration = tsquery_1.tsquery.query(commandFile, 'ModuleDeclaration > Identifier[name="global"]');
52
+ const updatedInterface = tsquery_1.tsquery.replace(commandFile, 'ModuleDeclaration:has(Identifier[name="Cypress"])', (node) => {
53
+ const newModuleDelcaration = `declare global {
54
+ // eslint-disable-next-line @typescript-eslint/no-namespace
55
+ namespace Cypress {
56
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
57
+ interface Chainable<Subject> {
58
+ ${existingCommands.map((c) => c.getText()).join('\n')}
59
+ mount: typeof mount;
60
+ }
61
+ }
62
+ }`;
63
+ /*
64
+ * this is to prevent the change being applied twice since
65
+ * declare global { 1
66
+ * interface Cypress { 2
67
+ * }
68
+ * }
69
+ * matches twice.
70
+ * i.e. if there is no global declaration, then add it
71
+ * or if the node is the global declaration, then add it,
72
+ * but not to the cypress module declaration inside the global declaration
73
+ */
74
+ if (isGlobalDeclaration?.length === 0 ||
75
+ node.name.getText() === 'global') {
76
+ return newModuleDelcaration;
77
+ }
78
+ });
79
+ const updatedCommandFile = `import { mount } from 'cypress/${framework}'\n${updatedInterface}\nCypress.Commands.add('mount', mount);`;
80
+ tree.write(commandFilePath, updatedCommandFile);
81
+ }
82
+ exports.addMountCommand = addMountCommand;
83
+ function getFramework(tree, target) {
84
+ if (target.executor === '@nrwl/angular:webpack-browser' ||
85
+ target.executor === '@angular-devkit/build-angular:browser') {
86
+ return 'angular';
87
+ }
88
+ const pkgJson = (0, devkit_1.readJson)(tree, 'package.json');
89
+ const reactDomVersion = pkgJson?.dependencies?.['react-dom'];
90
+ const hasReact18 = reactDomVersion &&
91
+ (0, semver_2.gte)((0, semver_1.checkAndCleanWithSemver)('react-dom', reactDomVersion), '18.0.0');
92
+ if (hasReact18) {
93
+ return 'react18';
94
+ }
95
+ return 'react';
96
+ }
97
+ function updateCyFile(tree, filePath, framework) {
98
+ if (!tree.exists(filePath)) {
99
+ return;
100
+ }
101
+ const contents = tree.read(filePath, 'utf-8');
102
+ const withCyMount = tsquery_1.tsquery.replace(contents, ':matches(CallExpression>Identifier[name="mount"])', (node) => {
103
+ return `cy.mount`;
104
+ });
105
+ const withUpdatedImports = tsquery_1.tsquery.replace(withCyMount, ':matches(ImportDeclaration, VariableStatement):has(Identifier[name="mount"]):has(StringLiteral[value="cypress/react"], StringLiteral[value="cypress/angular"], StringLiteral[value="cypress/react18"])', (node) => {
106
+ switch (framework) {
107
+ case 'angular':
108
+ return `import { MountConfig } from 'cypress/angular';`;
109
+ case 'react18':
110
+ case 'react':
111
+ return ' '; // have to return non falsy string to remove the node
112
+ default:
113
+ return node.getText().replace('mount', '');
114
+ }
115
+ });
116
+ tree.write(filePath, withUpdatedImports);
117
+ }
118
+ exports.updateCyFile = updateCyFile;
119
+ exports.default = updateCyMountUsage;
@@ -0,0 +1,6 @@
1
+ import { Tree } from '@nx/devkit';
2
+ export declare function updateToCypress11(tree: Tree): Promise<() => void>;
3
+ export declare function updateMountHookUsage(tree: Tree, filePath: string): void;
4
+ export declare function updateUnmountUsage(tree: Tree, filePath: string): void;
5
+ export declare function updateProviderUsage(tree: Tree, filePath: string): void;
6
+ export default updateToCypress11;
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.updateProviderUsage = exports.updateUnmountUsage = exports.updateMountHookUsage = exports.updateToCypress11 = void 0;
4
+ const ct_helpers_1 = require("../../utils/ct-helpers");
5
+ const devkit_1 = require("@nx/devkit");
6
+ const executor_options_utils_1 = require("@nx/devkit/src/generators/executor-options-utils");
7
+ const tsquery_1 = require("@phenomnomnominal/tsquery");
8
+ const path_1 = require("path");
9
+ const ts = require("typescript");
10
+ const cypress_version_1 = require("../../utils/cypress-version");
11
+ const versions_1 = require("../../utils/versions");
12
+ async function updateToCypress11(tree) {
13
+ const installedVersion = (0, cypress_version_1.installedCypressVersion)();
14
+ if (installedVersion < 10) {
15
+ return;
16
+ }
17
+ const projects = (0, devkit_1.getProjects)(tree);
18
+ (0, executor_options_utils_1.forEachExecutorOptions)(tree, '@nrwl/cypress:cypress', (options, projectName, targetName, configurationName) => {
19
+ if (options.testingType !== 'component' ||
20
+ !(options.cypressConfig && tree.exists(options.cypressConfig))) {
21
+ return;
22
+ }
23
+ const projectConfig = projects.get(projectName);
24
+ const commandsFile = (0, devkit_1.joinPathFragments)(projectConfig.root, 'cypress', 'support', 'commands.ts');
25
+ const framework = getFramework(tree.exists(commandsFile)
26
+ ? tree.read(commandsFile, 'utf-8')
27
+ : tree.read(options.cypressConfig, 'utf-8'));
28
+ (0, devkit_1.visitNotIgnoredFiles)(tree, projectConfig.sourceRoot, (filePath) => {
29
+ if (!ct_helpers_1.CY_FILE_MATCHER.test(filePath)) {
30
+ return;
31
+ }
32
+ const frameworkFromFile = getFramework(tree.read(filePath, 'utf-8'));
33
+ if (framework === 'react' || frameworkFromFile === 'react') {
34
+ updateUnmountUsage(tree, filePath);
35
+ updateMountHookUsage(tree, filePath);
36
+ }
37
+ if (framework === 'angular' || frameworkFromFile === 'angular') {
38
+ updateProviderUsage(tree, filePath);
39
+ }
40
+ });
41
+ });
42
+ const installTask = (0, devkit_1.addDependenciesToPackageJson)(tree, {}, { cypress: versions_1.cypressVersion });
43
+ await (0, devkit_1.formatFiles)(tree);
44
+ return () => {
45
+ installTask();
46
+ };
47
+ }
48
+ exports.updateToCypress11 = updateToCypress11;
49
+ function updateMountHookUsage(tree, filePath) {
50
+ const originalContents = tree.read(filePath, 'utf-8');
51
+ const commentedMountHook = tsquery_1.tsquery.replace(originalContents, ':matches(ImportDeclaration, VariableStatement):has(Identifier[name="mountHook"]):has(StringLiteral[value="cypress/react"], StringLiteral[value="cypress/react18"])', (node) => {
52
+ return `/** TODO: mountHook is deprecate.
53
+ * Use a wrapper component instead.
54
+ * See post for details: https://www.cypress.io/blog/2022/11/04/upcoming-changes-to-component-testing/#reactmounthook-removed
55
+ * */\n${node.getText()}`;
56
+ });
57
+ tree.write(filePath, commentedMountHook);
58
+ }
59
+ exports.updateMountHookUsage = updateMountHookUsage;
60
+ function updateUnmountUsage(tree, filePath) {
61
+ const reactDomImport = (0, path_1.extname)(filePath).includes('ts')
62
+ ? `import ReactDom from 'react-dom'`
63
+ : `const ReactDom = require('react-dom')`;
64
+ const originalContents = tree.read(filePath, 'utf-8');
65
+ const updatedImports = tsquery_1.tsquery.replace(originalContents, ':matches(ImportDeclaration, VariableStatement):has(Identifier[name="unmount"]):has(StringLiteral[value="cypress/react"], StringLiteral[value="cypress/react18"])', (node) => {
66
+ return `${node.getText().replace('unmount', 'getContainerEl')}
67
+ ${reactDomImport}`;
68
+ });
69
+ const updatedUnmountApi = tsquery_1.tsquery.replace(updatedImports, 'ExpressionStatement > CallExpression:has(Identifier[name="unmount"])', (node) => {
70
+ if (node.expression.getText() === 'unmount') {
71
+ return `cy.then(() => ReactDom.unmountComponentAtNode(getContainerEl()))`;
72
+ }
73
+ });
74
+ tree.write(filePath, updatedUnmountApi);
75
+ }
76
+ exports.updateUnmountUsage = updateUnmountUsage;
77
+ function updateProviderUsage(tree, filePath) {
78
+ const originalContents = tree.read(filePath, 'utf-8');
79
+ const isTestBedImported = tsquery_1.tsquery.query(originalContents, ':matches(ImportDeclaration, VariableStatement):has(Identifier[name="TestBed"]):has(StringLiteral[value="@angular/core/testing"])')?.length > 0;
80
+ let updatedProviders = tsquery_1.tsquery.replace(originalContents, 'CallExpression:has(PropertyAccessExpression:has(Identifier[name="mount"]))', (node) => {
81
+ const expressionName = node.expression.getText();
82
+ if (expressionName === 'cy.mount' && node?.arguments?.length > 1) {
83
+ const component = node.arguments[0].getText();
84
+ if (ts.isObjectLiteralExpression(node.arguments[1])) {
85
+ const providers = node.arguments[1]?.properties
86
+ ?.find((p) => p.name?.getText() === 'providers')
87
+ ?.getText();
88
+ const noProviders = tsquery_1.tsquery.replace(node.getText(), 'PropertyAssignment:has(Identifier[name="providers"])', (n) => {
89
+ // set it to undefined so we don't run into a hanging comma causing invalid syntax
90
+ return 'providers: undefined';
91
+ });
92
+ return `TestBed.overrideComponent(${component}, { add: { ${providers} }});\n${noProviders}`;
93
+ }
94
+ else {
95
+ return `TestBed.overrideComponent(${component}, {add: { providers: ${node.arguments[1].getText()}.providers}});\n${node.getText()}`;
96
+ }
97
+ }
98
+ });
99
+ tree.write(filePath, `${isTestBedImported
100
+ ? ''
101
+ : "import {TestBed} from '@angular/core/testing';\n"}${updatedProviders}`);
102
+ }
103
+ exports.updateProviderUsage = updateProviderUsage;
104
+ function getFramework(contents) {
105
+ if (contents.includes('cypress/react') || contents.includes('@nrwl/react')) {
106
+ return 'react';
107
+ }
108
+ if (contents.includes('cypress/angular') ||
109
+ contents.includes('@nrwl/angular')) {
110
+ return 'angular';
111
+ }
112
+ return null;
113
+ }
114
+ exports.default = updateToCypress11;
@@ -0,0 +1,3 @@
1
+ import type { Node } from 'typescript';
2
+ export declare function isAlreadyCommented(node: Node): boolean;
3
+ export declare const BANNED_COMMANDS: string[];
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BANNED_COMMANDS = exports.isAlreadyCommented = void 0;
4
+ function isAlreadyCommented(node) {
5
+ return node.getFullText().includes('TODO(@nrwl/cypress)');
6
+ }
7
+ exports.isAlreadyCommented = isAlreadyCommented;
8
+ exports.BANNED_COMMANDS = [
9
+ 'as',
10
+ 'children',
11
+ 'closest',
12
+ 'contains',
13
+ 'debug',
14
+ 'document',
15
+ 'eq',
16
+ 'filter',
17
+ 'find',
18
+ 'first',
19
+ 'focused',
20
+ 'get',
21
+ 'hash',
22
+ 'its',
23
+ 'last',
24
+ 'location',
25
+ 'next',
26
+ 'nextAll',
27
+ 'not',
28
+ 'parent',
29
+ 'parents',
30
+ 'parentsUntil',
31
+ 'prev',
32
+ 'prevUntil',
33
+ 'root',
34
+ 'shadow',
35
+ 'siblings',
36
+ 'title',
37
+ 'url',
38
+ 'window',
39
+ ];
@@ -0,0 +1,24 @@
1
+ import { GeneratorCallback, Tree } from '@nx/devkit';
2
+ export declare function updateToCypress12(tree: Tree): GeneratorCallback;
3
+ export declare function turnOffTestIsolation(tree: Tree, configPath: string): void;
4
+ /**
5
+ * Leave a comment on all apis that have been removed andsuperseded by cy.intercept
6
+ * stating they these API are now removed and need to update.
7
+ * cy.route, cy.server, Cypress.Server.defaults
8
+ **/
9
+ export declare function shouldUseCyIntercept(tree: Tree, filePath: string): void;
10
+ /**
11
+ * Leave a comment on all apis that have been removed and superseded by cy.session
12
+ * stating they these API are now removed and need to update.
13
+ * Cypress.Cookies.defaults & Cypress.Cookies.preserveOnce
14
+ **/
15
+ export declare function shouldUseCySession(tree: Tree, filePath: string): void;
16
+ /**
17
+ * leave a comment about nested cy commands in a cy.should callback
18
+ * */
19
+ export declare function shouldNotUseCyInShouldCB(tree: Tree, filePath: string): void;
20
+ /**
21
+ * leave a comment on all usages of overriding built-ins that are now banned
22
+ * */
23
+ export declare function shouldNotOverrideCommands(tree: Tree, filePath: string): void;
24
+ export default updateToCypress12;
@@ -0,0 +1,180 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.shouldNotOverrideCommands = exports.shouldNotUseCyInShouldCB = exports.shouldUseCySession = exports.shouldUseCyIntercept = exports.turnOffTestIsolation = exports.updateToCypress12 = void 0;
4
+ const devkit_1 = require("@nx/devkit");
5
+ const executor_options_utils_1 = require("@nx/devkit/src/generators/executor-options-utils");
6
+ const tsquery_1 = require("@phenomnomnominal/tsquery");
7
+ const typescript_1 = require("typescript");
8
+ const cypress_version_1 = require("../../utils/cypress-version");
9
+ const helpers_1 = require("./helpers");
10
+ const JS_TS_FILE_MATCHER = /\.[jt]sx?$/;
11
+ function updateToCypress12(tree) {
12
+ if ((0, cypress_version_1.installedCypressVersion)() < 11) {
13
+ return;
14
+ }
15
+ const projects = (0, devkit_1.getProjects)(tree);
16
+ (0, executor_options_utils_1.forEachExecutorOptions)(tree, '@nrwl/cypress:cypress', (options, projectName, targetName, configName) => {
17
+ if (!(options.cypressConfig && tree.exists(options.cypressConfig))) {
18
+ return;
19
+ }
20
+ const projectConfig = projects.get(projectName);
21
+ turnOffTestIsolation(tree, options.cypressConfig);
22
+ (0, devkit_1.visitNotIgnoredFiles)(tree, projectConfig.root, (filePath) => {
23
+ if (!JS_TS_FILE_MATCHER.test(filePath)) {
24
+ return;
25
+ }
26
+ shouldUseCyIntercept(tree, filePath);
27
+ shouldUseCySession(tree, filePath);
28
+ shouldNotUseCyInShouldCB(tree, filePath);
29
+ shouldNotOverrideCommands(tree, filePath);
30
+ });
31
+ });
32
+ console.warn((0, devkit_1.stripIndents) `Cypress 12 has lots of breaking changes that might subtly break your tests.
33
+ This migration marked known issues that need to be manually migrated,
34
+ but there can still be runtime based errors that were not detected.
35
+ Please consult the offical Cypress v12 migration guide for more info on these changes and the next steps.
36
+ https://docs.cypress.io/guides/references/migration-guide
37
+ `);
38
+ (0, devkit_1.updateJson)(tree, 'package.json', (json) => {
39
+ json.devDependencies.cypress = '^12.2.0';
40
+ return json;
41
+ });
42
+ return () => {
43
+ (0, devkit_1.installPackagesTask)(tree);
44
+ };
45
+ }
46
+ exports.updateToCypress12 = updateToCypress12;
47
+ function turnOffTestIsolation(tree, configPath) {
48
+ const config = tree.read(configPath, 'utf-8');
49
+ const isTestIsolationSet = tsquery_1.tsquery.query(config, 'ExportAssignment ObjectLiteralExpression > PropertyAssignment:has(Identifier[name="testIsolation"])');
50
+ if (isTestIsolationSet.length > 0) {
51
+ return;
52
+ }
53
+ const testIsolationProperty = `/**
54
+ * TODO(@nrwl/cypress): In Cypress v12,the testIsolation option is turned on by default.
55
+ * This can cause tests to start breaking where not indended.
56
+ * You should consider enabling this once you verify tests do not depend on each other
57
+ * More Info: https://docs.cypress.io/guides/references/migration-guide#Test-Isolation
58
+ **/
59
+ testIsolation: false,`;
60
+ const updated = tsquery_1.tsquery.replace(config, 'ExportAssignment ObjectLiteralExpression > PropertyAssignment:has(Identifier[name="e2e"])', (node) => {
61
+ if ((0, typescript_1.isObjectLiteralExpression)(node.initializer)) {
62
+ const listOfProperties = node.initializer.properties
63
+ .map((j) => j.getText())
64
+ .join(',\n ');
65
+ return `e2e: {
66
+ ${listOfProperties},
67
+ ${testIsolationProperty}
68
+ }`;
69
+ }
70
+ return `e2e: {
71
+ ...${node.initializer.getText()},
72
+ ${testIsolationProperty}
73
+ }`;
74
+ });
75
+ tree.write(configPath, updated);
76
+ }
77
+ exports.turnOffTestIsolation = turnOffTestIsolation;
78
+ /**
79
+ * Leave a comment on all apis that have been removed andsuperseded by cy.intercept
80
+ * stating they these API are now removed and need to update.
81
+ * cy.route, cy.server, Cypress.Server.defaults
82
+ **/
83
+ function shouldUseCyIntercept(tree, filePath) {
84
+ const content = tree.read(filePath, 'utf-8');
85
+ const markedRemovedCommands = tsquery_1.tsquery.replace(content, ':matches(PropertyAccessExpression:has(Identifier[name="cy"]):has(Identifier[name="server"], Identifier[name="route"]), PropertyAccessExpression:has(Identifier[name="defaults"]):has(Identifier[name="Cypress"], Identifier[name="Server"]))', (node) => {
86
+ if ((0, helpers_1.isAlreadyCommented)(node)) {
87
+ return;
88
+ }
89
+ const expression = node.expression.getText().trim();
90
+ // prevent extra chaining i.e. cy.route().as() will return 2 results
91
+ // cy.route and cy.route().as
92
+ // only need the first 1 so skip any extra chaining
93
+ if (expression === 'cy' || expression === 'Cypress.Server') {
94
+ return `// TODO(@nrwl/cypress): this command has been removed, use cy.intercept instead. https://docs.cypress.io/guides/references/migration-guide#cy-server-cy-route-and-Cypress-Server-defaults
95
+ ${node.getText()}`;
96
+ }
97
+ });
98
+ tree.write(filePath, markedRemovedCommands);
99
+ }
100
+ exports.shouldUseCyIntercept = shouldUseCyIntercept;
101
+ /**
102
+ * Leave a comment on all apis that have been removed and superseded by cy.session
103
+ * stating they these API are now removed and need to update.
104
+ * Cypress.Cookies.defaults & Cypress.Cookies.preserveOnce
105
+ **/
106
+ function shouldUseCySession(tree, filePath) {
107
+ const content = tree.read(filePath, 'utf-8');
108
+ const markedRemovedCommands = tsquery_1.tsquery.replace(content, ':matches(PropertyAccessExpression:has(Identifier[name="defaults"]):has(Identifier[name="Cypress"], Identifier[name="Cookies"]), PropertyAccessExpression:has(Identifier[name="preserveOnce"]):has(Identifier[name="Cypress"], Identifier[name="Cookies"]))', (node) => {
109
+ if ((0, helpers_1.isAlreadyCommented)(node)) {
110
+ return;
111
+ }
112
+ const expression = node.expression.getText().trim();
113
+ // prevent grabbing other Cypress.<something>.defaults
114
+ if (expression === 'Cypress.Cookies') {
115
+ return `// TODO(@nrwl/cypress): this command has been removed, use cy.session instead. https://docs.cypress.io/guides/references/migration-guide#Command-Cypress-API-Changes
116
+ ${node.getText()}`;
117
+ }
118
+ });
119
+ tree.write(filePath, markedRemovedCommands);
120
+ }
121
+ exports.shouldUseCySession = shouldUseCySession;
122
+ /**
123
+ * leave a comment about nested cy commands in a cy.should callback
124
+ * */
125
+ function shouldNotUseCyInShouldCB(tree, filePath) {
126
+ const content = tree.read(filePath, 'utf-8');
127
+ const markedNestedCyCommands = tsquery_1.tsquery.replace(content, 'CallExpression > PropertyAccessExpression:has(Identifier[name="cy"]):has(Identifier[name="should"])', (node) => {
128
+ if ((0, helpers_1.isAlreadyCommented)(node) ||
129
+ (node.parent && !(0, typescript_1.isCallExpression)(node.parent))) {
130
+ return;
131
+ }
132
+ const parentExpression = node.parent;
133
+ if (parentExpression?.arguments?.[0] &&
134
+ ((0, typescript_1.isArrowFunction)(parentExpression.arguments[0]) ||
135
+ (0, typescript_1.isFunctionExpression)(parentExpression.arguments[0]))) {
136
+ const isUsingNestedCyCommand = tsquery_1.tsquery.query(parentExpression.arguments[0], 'CallExpression > PropertyAccessExpression:has(Identifier[name="cy"])')?.length > 0;
137
+ if (isUsingNestedCyCommand) {
138
+ return `/**
139
+ * TODO(@nrwl/cypress): Nesting Cypress commands in a should assertion now throws.
140
+ * You should use .then() to chain commands instead.
141
+ * More Info: https://docs.cypress.io/guides/references/migration-guide#-should
142
+ **/
143
+ ${node.getText()}`;
144
+ }
145
+ return node.getText();
146
+ }
147
+ });
148
+ tree.write(filePath, markedNestedCyCommands);
149
+ }
150
+ exports.shouldNotUseCyInShouldCB = shouldNotUseCyInShouldCB;
151
+ /**
152
+ * leave a comment on all usages of overriding built-ins that are now banned
153
+ * */
154
+ function shouldNotOverrideCommands(tree, filePath) {
155
+ const content = tree.read(filePath, 'utf-8');
156
+ const markedOverrideUsage = tsquery_1.tsquery.replace(content, 'PropertyAccessExpression:has(Identifier[name="overwrite"]):has(Identifier[name="Cypress"])', (node) => {
157
+ if ((0, helpers_1.isAlreadyCommented)(node)) {
158
+ return;
159
+ }
160
+ const expression = node.expression.getText().trim();
161
+ // prevent grabbing other Cypress.<something>.defaults
162
+ if (expression === 'Cypress.Commands') {
163
+ // get value.
164
+ const overwriteExpression = node.parent;
165
+ const command = overwriteExpression.arguments?.[0]?.text; // need string without quotes
166
+ if (helpers_1.BANNED_COMMANDS.includes(command)) {
167
+ // overwrite
168
+ return `/**
169
+ * TODO(@nrwl/cypress): This command can no longer be overridden
170
+ * Consider using a different name like 'custom_${command}'
171
+ * More info: https://docs.cypress.io/guides/references/migration-guide#Cypress-Commands-overwrite
172
+ **/
173
+ ${node.getText()}`;
174
+ }
175
+ }
176
+ });
177
+ tree.write(filePath, markedOverrideUsage);
178
+ }
179
+ exports.shouldNotOverrideCommands = shouldNotOverrideCommands;
180
+ exports.default = updateToCypress12;
@@ -0,0 +1,2 @@
1
+ import { Tree } from '@nx/devkit';
2
+ export default function replacePackage(tree: Tree): Promise<void>;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const devkit_1 = require("@nx/devkit");
4
+ const replace_package_1 = require("@nx/devkit/src/utils/replace-package");
5
+ async function replacePackage(tree) {
6
+ await (0, replace_package_1.replaceNrwlPackageWithNxPackage)(tree, '@nrwl/cypress', '@nx/cypress');
7
+ await (0, devkit_1.formatFiles)(tree);
8
+ }
9
+ exports.default = replacePackage;
@@ -0,0 +1,3 @@
1
+ import { Tree } from '@nx/devkit';
2
+ export declare function normalizeCyTsConfigNames(tree: Tree): Promise<void>;
3
+ export default normalizeCyTsConfigNames;
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeCyTsConfigNames = void 0;
4
+ const devkit_1 = require("@nx/devkit");
5
+ const executor_options_utils_1 = require("@nx/devkit/src/generators/executor-options-utils");
6
+ async function normalizeCyTsConfigNames(tree) {
7
+ const projects = (0, devkit_1.getProjects)(tree);
8
+ (0, executor_options_utils_1.forEachExecutorOptions)(tree, '@nx/cypress:cypress', (_, projectName) => {
9
+ const projectConfig = projects.get(projectName);
10
+ const newTsConfigPath = (0, devkit_1.joinPathFragments)(projectConfig.root, 'cypress', 'tsconfig.json');
11
+ // if there is already a tsconfig.json in the cypress folder, then assume things are setup already
12
+ if (!tree.exists(newTsConfigPath)) {
13
+ moveProjectTsCyConfig(tree, projectConfig, newTsConfigPath);
14
+ moveCyDirTsCyConfig(tree, projectConfig, newTsConfigPath);
15
+ updateCyDirTsConfigReferences(tree, projectConfig);
16
+ }
17
+ });
18
+ await (0, devkit_1.formatFiles)(tree);
19
+ }
20
+ exports.normalizeCyTsConfigNames = normalizeCyTsConfigNames;
21
+ function moveProjectTsCyConfig(tree, projectConfig, newTsConfigPath) {
22
+ if (tree.exists((0, devkit_1.joinPathFragments)(projectConfig.root, 'tsconfig.cy.json'))) {
23
+ tree.rename((0, devkit_1.joinPathFragments)(projectConfig.root, 'tsconfig.cy.json'), newTsConfigPath);
24
+ (0, devkit_1.updateJson)(tree, newTsConfigPath, (json) => {
25
+ json.extends = '../tsconfig.json';
26
+ json.compilerOptions ??= {};
27
+ json.compilerOptions = {
28
+ ...json.compilerOptions,
29
+ sourceMap: false,
30
+ outDir: '../../../dist/out-tsc',
31
+ };
32
+ json.include ??= [];
33
+ json.include = json.include.map((p) => {
34
+ if (p.startsWith('cypress/')) {
35
+ return p.replace('cypress/', '');
36
+ }
37
+ return `../${p}`;
38
+ });
39
+ return json;
40
+ });
41
+ }
42
+ }
43
+ function moveCyDirTsCyConfig(tree, projectConfig, newTsConfigPath) {
44
+ if (tree.exists((0, devkit_1.joinPathFragments)(projectConfig.root, 'cypress', 'tsconfig.cy.json'))) {
45
+ tree.rename((0, devkit_1.joinPathFragments)(projectConfig.root, 'cypress', 'tsconfig.cy.json'), newTsConfigPath);
46
+ (0, devkit_1.updateJson)(tree, newTsConfigPath, (json) => {
47
+ json.compilerOptions ??= {};
48
+ json.compilerOptions = {
49
+ ...json.compilerOptions,
50
+ sourceMap: false,
51
+ };
52
+ return json;
53
+ });
54
+ }
55
+ }
56
+ function updateCyDirTsConfigReferences(tree, projectConfig) {
57
+ if (!tree.exists((0, devkit_1.joinPathFragments)(projectConfig.root, 'cypress', 'tsconfig.json'))) {
58
+ return;
59
+ }
60
+ (0, devkit_1.updateJson)(tree, (0, devkit_1.joinPathFragments)(projectConfig.root, 'tsconfig.json'), (json) => {
61
+ json.references ??= [];
62
+ if (!json.references) {
63
+ return json;
64
+ }
65
+ const cyFile = json.references.find((p) => p.path.includes('tsconfig.cy.json'));
66
+ if (cyFile) {
67
+ json.references.splice(json.references.indexOf(cyFile), 1);
68
+ }
69
+ if (!json.references.some((r) => r.path === './cypress/tsconfig.json')) {
70
+ json.references.push({
71
+ path: './cypress/tsconfig.json',
72
+ });
73
+ }
74
+ return json;
75
+ });
76
+ }
77
+ exports.default = normalizeCyTsConfigNames;
@@ -0,0 +1,3 @@
1
+ import { Tree } from '@nx/devkit';
2
+ export declare function fixLegacyCypressTsconfig(tree: Tree): Promise<void>;
3
+ export default fixLegacyCypressTsconfig;
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fixLegacyCypressTsconfig = void 0;
4
+ const executor_options_utils_1 = require("@nx/devkit/src/generators/executor-options-utils");
5
+ const devkit_1 = require("@nx/devkit");
6
+ const path_1 = require("path");
7
+ async function fixLegacyCypressTsconfig(tree) {
8
+ const projects = (0, devkit_1.getProjects)(tree);
9
+ (0, executor_options_utils_1.forEachExecutorOptions)(tree, '@nx/cypress:cypress', (options, projectName, targetName, configName) => {
10
+ const projectConfig = projects.get(projectName);
11
+ if (options.testingType !== 'e2e' &&
12
+ projectConfig.targets[targetName]?.options?.testingType !== 'e2e') {
13
+ return;
14
+ }
15
+ const tsconfigToRemove = options.tsConfig ??
16
+ (0, devkit_1.joinPathFragments)(projectConfig.root, 'tsconfig.e2e.json');
17
+ const projectLevelConfigPath = (0, devkit_1.joinPathFragments)(projectConfig.root, 'tsconfig.json');
18
+ if (!tree.exists(projectLevelConfigPath) ||
19
+ !tree.exists(tsconfigToRemove)) {
20
+ return;
21
+ }
22
+ if (tsconfigToRemove === projectLevelConfigPath) {
23
+ (0, devkit_1.updateJson)(tree, projectLevelConfigPath, (json) => {
24
+ json.compilerOptions = {
25
+ sourceMap: false,
26
+ ...json.compilerOptions,
27
+ };
28
+ return json;
29
+ });
30
+ }
31
+ else {
32
+ const e2eConfig = (0, devkit_1.readJson)(tree, tsconfigToRemove);
33
+ (0, devkit_1.updateJson)(tree, projectLevelConfigPath, (json) => {
34
+ json.compilerOptions = {
35
+ sourceMap: false,
36
+ ...json.compilerOptions,
37
+ ...e2eConfig.compilerOptions,
38
+ };
39
+ json.files = Array.from(new Set([...(json.files ?? []), ...(e2eConfig.files ?? [])]));
40
+ json.include = Array.from(new Set([...(json.include ?? []), ...(e2eConfig.include ?? [])]));
41
+ json.exclude = Array.from(new Set([...(json.exclude ?? []), ...(e2eConfig.exclude ?? [])]));
42
+ // these paths will always be 'unix style'
43
+ // and on windows relative will not work on these paths
44
+ const tsConfigFromProjRoot = path_1.posix.relative(projectConfig.root, tsconfigToRemove);
45
+ json.references = (json.references ?? []).filter(({ path }) => !path.includes(tsConfigFromProjRoot));
46
+ return json;
47
+ });
48
+ tree.delete(tsconfigToRemove);
49
+ }
50
+ if (configName) {
51
+ delete projectConfig.targets[targetName].configurations[configName]
52
+ .tsConfig;
53
+ }
54
+ else {
55
+ delete projectConfig.targets[targetName].options.tsConfig;
56
+ }
57
+ (0, devkit_1.updateProjectConfiguration)(tree, projectName, projectConfig);
58
+ });
59
+ await (0, devkit_1.formatFiles)(tree);
60
+ }
61
+ exports.fixLegacyCypressTsconfig = fixLegacyCypressTsconfig;
62
+ exports.default = fixLegacyCypressTsconfig;