@nx/cypress 23.1.0 → 23.1.2
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/generators/configuration/configuration.d.ts +4 -0
- package/dist/src/generators/configuration/schema.json +8 -2
- package/dist/src/generators/init/init.js +6 -0
- package/dist/src/plugins/plugin.js +4 -8
- package/dist/src/utils/add-linter.d.ts +4 -0
- package/dist/src/utils/add-linter.js +21 -14
- package/dist/src/utils/config.js +4 -1
- package/dist/src/utils/ct-helpers.js +5 -7
- package/dist/src/utils/find-target-options.js +3 -4
- package/dist/src/utils/start-dev-server.js +3 -3
- package/package.json +5 -5
|
@@ -6,6 +6,10 @@ export interface CypressE2EConfigSchema {
|
|
|
6
6
|
directory?: string;
|
|
7
7
|
js?: boolean;
|
|
8
8
|
skipFormat?: boolean;
|
|
9
|
+
enableTypedLinting?: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* @deprecated Use `enableTypedLinting` instead. This option will be removed in Nx v24.
|
|
12
|
+
*/
|
|
9
13
|
setParserOptionsProject?: boolean;
|
|
10
14
|
skipPackageJson?: boolean;
|
|
11
15
|
bundler?: 'webpack' | 'vite' | 'none';
|
|
@@ -60,11 +60,17 @@
|
|
|
60
60
|
"default": false,
|
|
61
61
|
"x-priority": "internal"
|
|
62
62
|
},
|
|
63
|
-
"
|
|
63
|
+
"enableTypedLinting": {
|
|
64
64
|
"type": "boolean",
|
|
65
|
-
"description": "Whether
|
|
65
|
+
"description": "Whether to enable typed linting. For flat configs, this configures the recommended `parserOptions.projectService` and `tsconfigRootDir`. For legacy `.eslintrc` configs, this configures `parserOptions.project`. We do not enable this by default for lint performance reasons.",
|
|
66
66
|
"default": false
|
|
67
67
|
},
|
|
68
|
+
"setParserOptionsProject": {
|
|
69
|
+
"type": "boolean",
|
|
70
|
+
"description": "Deprecated alias for `enableTypedLinting`.",
|
|
71
|
+
"default": false,
|
|
72
|
+
"x-deprecated": "Use `enableTypedLinting` instead. This option will be removed in Nx v24."
|
|
73
|
+
},
|
|
68
74
|
"skipPackageJson": {
|
|
69
75
|
"type": "boolean",
|
|
70
76
|
"default": false,
|
|
@@ -50,6 +50,12 @@ function updateDependencies(tree, options) {
|
|
|
50
50
|
};
|
|
51
51
|
if (!(0, versions_1.getInstalledCypressVersion)(tree)) {
|
|
52
52
|
devDependencies.cypress = versions_1.cypressVersion;
|
|
53
|
+
// The user explicitly asked for cypress, and its postinstall downloads
|
|
54
|
+
// the binary it needs to run at all, so enable it — npm and yarn run it
|
|
55
|
+
// unconditionally. Transitive deps stay denied.
|
|
56
|
+
(0, internal_1.acknowledgeBuildScripts)(tree, (0, devkit_1.detectPackageManager)(tree.root), {
|
|
57
|
+
cypress: true,
|
|
58
|
+
});
|
|
53
59
|
}
|
|
54
60
|
tasks.push((0, devkit_1.addDependenciesToPackageJson)(tree, {}, devDependencies, undefined, options.keepExistingVersions ?? true));
|
|
55
61
|
return (0, devkit_1.runTasksInSerial)(...tasks);
|
|
@@ -5,10 +5,6 @@ const internal_1 = require("@nx/devkit/internal");
|
|
|
5
5
|
const devkit_1 = require("@nx/devkit");
|
|
6
6
|
const js_1 = require("@nx/js");
|
|
7
7
|
const fs_1 = require("fs");
|
|
8
|
-
const devkit_internals_1 = require("nx/src/devkit-internals");
|
|
9
|
-
const cache_directory_1 = require("nx/src/utils/cache-directory");
|
|
10
|
-
const plugin_cache_utils_1 = require("nx/src/utils/plugin-cache-utils");
|
|
11
|
-
const workspace_context_1 = require("nx/src/utils/workspace-context");
|
|
12
8
|
const path_1 = require("path");
|
|
13
9
|
const constants_1 = require("../utils/constants");
|
|
14
10
|
const cypressConfigGlob = '**/cypress.config.{js,ts,mjs,cjs}';
|
|
@@ -25,9 +21,9 @@ const defaultPatterns = {
|
|
|
25
21
|
exports.createNodes = [
|
|
26
22
|
cypressConfigGlob,
|
|
27
23
|
async (configFiles, options, context) => {
|
|
28
|
-
const optionsHash = (0,
|
|
29
|
-
const cachePath = (0, path_1.join)(
|
|
30
|
-
const pluginCache = new
|
|
24
|
+
const optionsHash = (0, internal_1.hashObject)(options);
|
|
25
|
+
const cachePath = (0, path_1.join)(internal_1.workspaceDataDirectory, `cypress-${optionsHash}.hash`);
|
|
26
|
+
const pluginCache = new internal_1.PluginCache(cachePath);
|
|
31
27
|
const packageManager = (0, devkit_1.detectPackageManager)(context.workspaceRoot);
|
|
32
28
|
const pmc = (0, devkit_1.getPackageManagerCommand)(packageManager);
|
|
33
29
|
const lockFileName = (0, js_1.getLockFileName)(packageManager);
|
|
@@ -490,7 +486,7 @@ async function getSpecFilesAndPatternsForTestType(cypressConfig, testType, works
|
|
|
490
486
|
const excludeSpecPatterns = Array.isArray(excludeSpecPattern)
|
|
491
487
|
? excludeSpecPattern.map((p) => (0, path_1.join)(projectRoot, p))
|
|
492
488
|
: [(0, path_1.join)(projectRoot, excludeSpecPattern)];
|
|
493
|
-
const specFiles = await (0,
|
|
489
|
+
const specFiles = await (0, internal_1.globWithWorkspaceContext)(workspaceRoot, specPatterns, excludeSpecPatterns);
|
|
494
490
|
return { specFiles, specPatterns, excludeSpecPatterns };
|
|
495
491
|
}
|
|
496
492
|
async function filterCypressConfigs(configFiles, context) {
|
|
@@ -3,6 +3,10 @@ import { Linter, LinterType } from '@nx/eslint';
|
|
|
3
3
|
export interface CyLinterOptions {
|
|
4
4
|
project: string;
|
|
5
5
|
linter: Linter | LinterType;
|
|
6
|
+
enableTypedLinting?: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* @deprecated Use `enableTypedLinting` instead. This option will be removed in Nx v24.
|
|
9
|
+
*/
|
|
6
10
|
setParserOptionsProject?: boolean;
|
|
7
11
|
skipPackageJson?: boolean;
|
|
8
12
|
rootProject?: boolean;
|
|
@@ -12,13 +12,14 @@ async function addLinterToCyProject(tree, options) {
|
|
|
12
12
|
const tasks = [];
|
|
13
13
|
const projectConfig = (0, devkit_1.readProjectConfiguration)(tree, options.project);
|
|
14
14
|
const eslintFile = (0, internal_1.findEslintFile)(tree, projectConfig.root);
|
|
15
|
+
const enableTypedLinting = (0, internal_1.isTypedLintingEnabled)(options);
|
|
15
16
|
if (!eslintFile) {
|
|
16
17
|
tasks.push(await (0, eslint_1.lintProjectGenerator)(tree, {
|
|
17
18
|
project: options.project,
|
|
18
19
|
linter: options.linter,
|
|
19
20
|
skipFormat: true,
|
|
20
21
|
tsConfigPaths: [(0, devkit_1.joinPathFragments)(projectConfig.root, 'tsconfig.json')],
|
|
21
|
-
|
|
22
|
+
enableTypedLinting,
|
|
22
23
|
skipPackageJson: options.skipPackageJson,
|
|
23
24
|
rootProject: options.rootProject,
|
|
24
25
|
addPlugin: options.addPlugin,
|
|
@@ -35,7 +36,8 @@ async function addLinterToCyProject(tree, options) {
|
|
|
35
36
|
if ((0, internal_1.isEslintConfigSupported)(tree, projectConfig.root) ||
|
|
36
37
|
(0, internal_1.isEslintConfigSupported)(tree)) {
|
|
37
38
|
const overrides = [];
|
|
38
|
-
|
|
39
|
+
const isFlatConfig = (0, internal_1.useFlatConfig)(tree);
|
|
40
|
+
if (isFlatConfig) {
|
|
39
41
|
(0, internal_1.addPredefinedConfigToFlatLintConfig)(tree, projectConfig.root, 'recommended', {
|
|
40
42
|
moduleName: 'cypress',
|
|
41
43
|
moduleImportPath: 'eslint-plugin-cypress/flat',
|
|
@@ -67,39 +69,44 @@ async function addLinterToCyProject(tree, options) {
|
|
|
67
69
|
'no-undef': 'off',
|
|
68
70
|
},
|
|
69
71
|
};
|
|
72
|
+
// For flat configs typed linting is handled by `lintProjectGenerator` via
|
|
73
|
+
// `parserOptions.projectService`, so we don't emit `parserOptions.project`
|
|
74
|
+
// here. Legacy `.eslintrc` configs are JSON, which can't express the
|
|
75
|
+
// `__dirname` that `tsconfigRootDir` needs, so they keep `project`.
|
|
76
|
+
const legacyParserOptions = !isFlatConfig && enableTypedLinting
|
|
77
|
+
? { project: `${projectConfig.root}/tsconfig.*?.json` }
|
|
78
|
+
: undefined;
|
|
70
79
|
if (options.overwriteExisting) {
|
|
71
80
|
overrides.unshift({
|
|
72
|
-
files:
|
|
81
|
+
files: isFlatConfig
|
|
73
82
|
? // For flat configs we don't need to specify the files
|
|
74
83
|
undefined
|
|
75
84
|
: ['*.ts', '*.tsx', '*.js', '*.jsx'],
|
|
76
|
-
parserOptions:
|
|
77
|
-
? undefined
|
|
78
|
-
: {
|
|
79
|
-
project: `${projectConfig.root}/tsconfig.*?.json`,
|
|
80
|
-
},
|
|
85
|
+
parserOptions: legacyParserOptions,
|
|
81
86
|
rules: {},
|
|
82
87
|
});
|
|
83
88
|
(0, internal_1.replaceOverridesInLintConfig)(tree, projectConfig.root, overrides);
|
|
84
89
|
}
|
|
85
90
|
else {
|
|
86
91
|
overrides.unshift({
|
|
87
|
-
files:
|
|
92
|
+
files: isFlatConfig
|
|
88
93
|
? // For flat configs we don't need to specify the files
|
|
89
94
|
undefined
|
|
90
95
|
: [
|
|
91
96
|
'*.cy.{ts,js,tsx,jsx}',
|
|
92
97
|
`${options.cypressDir}/**/*.{ts,js,tsx,jsx}`,
|
|
93
98
|
],
|
|
94
|
-
parserOptions:
|
|
95
|
-
? undefined
|
|
96
|
-
: {
|
|
97
|
-
project: `${projectConfig.root}/tsconfig.*?.json`,
|
|
98
|
-
},
|
|
99
|
+
parserOptions: legacyParserOptions,
|
|
99
100
|
rules: {},
|
|
100
101
|
});
|
|
101
102
|
overrides.forEach((override) => (0, internal_1.addOverrideToLintConfig)(tree, projectConfig.root, override));
|
|
102
103
|
}
|
|
104
|
+
// `lintProjectGenerator` only sets up the projectService block when it
|
|
105
|
+
// creates the config, and `replaceOverridesInLintConfig` strips it. For a
|
|
106
|
+
// flat config, re-add it here when typed linting is enabled.
|
|
107
|
+
if (isFlatConfig && enableTypedLinting) {
|
|
108
|
+
(0, internal_1.addTypedLintingToFlatConfig)(tree, projectConfig.root);
|
|
109
|
+
}
|
|
103
110
|
}
|
|
104
111
|
return (0, devkit_1.runTasksInSerial)(...tasks);
|
|
105
112
|
}
|
package/dist/src/utils/config.js
CHANGED
|
@@ -131,7 +131,10 @@ ${jitComment}
|
|
|
131
131
|
}`;
|
|
132
132
|
});
|
|
133
133
|
}
|
|
134
|
-
|
|
134
|
+
// Re-running the generator must not prepend a second declaration - Cypress
|
|
135
|
+
// loads TS configs through esbuild, which rejects duplicate bindings.
|
|
136
|
+
const isPresetAlreadyDeclared = tsquery.query(updatedConfigContents, ':matches(ImportSpecifier, BindingElement) Identifier[name="nxComponentTestingPreset"]').length > 0;
|
|
137
|
+
if (presetImportPath && !isPresetAlreadyDeclared) {
|
|
135
138
|
// Use the path verbatim - callers pass the public exported subpath. Don't
|
|
136
139
|
// append `.js`: @nx/react and @nx/angular's package exports only declare
|
|
137
140
|
// the bare `./plugins/component-testing` subpath, so a `.js` suffix
|
|
@@ -8,9 +8,7 @@ exports.createExecutorContext = createExecutorContext;
|
|
|
8
8
|
const devkit_1 = require("@nx/devkit");
|
|
9
9
|
const path_1 = require("path");
|
|
10
10
|
const fs_1 = require("fs");
|
|
11
|
-
const
|
|
12
|
-
const project_graph_1 = require("nx/src/project-graph/project-graph");
|
|
13
|
-
const configuration_1 = require("nx/src/config/configuration");
|
|
11
|
+
const internal_1 = require("@nx/devkit/internal");
|
|
14
12
|
exports.CY_FILE_MATCHER = new RegExp(/\.cy\.[tj]sx?$/);
|
|
15
13
|
/**
|
|
16
14
|
* return a path to a temp css file
|
|
@@ -55,8 +53,8 @@ function getProjectConfigByPath(graph, configPath) {
|
|
|
55
53
|
const normalizedPathFromWorkspaceRoot = (0, devkit_1.normalizePath)((0, fs_1.lstatSync)(configPath).isFile()
|
|
56
54
|
? configFileFromWorkspaceRoot.replace((0, path_1.extname)(configPath), '')
|
|
57
55
|
: configFileFromWorkspaceRoot);
|
|
58
|
-
const projectRootMappings = (0,
|
|
59
|
-
const componentTestingProjectName = (0,
|
|
56
|
+
const projectRootMappings = (0, internal_1.createProjectRootMappings)(graph.nodes);
|
|
57
|
+
const componentTestingProjectName = (0, internal_1.findProjectForPath)(normalizedPathFromWorkspaceRoot, projectRootMappings);
|
|
60
58
|
if (!componentTestingProjectName ||
|
|
61
59
|
!graph.nodes[componentTestingProjectName]?.data) {
|
|
62
60
|
throw new Error((0, devkit_1.stripIndents) `Unable to find the project configuration that includes ${normalizedPathFromWorkspaceRoot}.
|
|
@@ -69,8 +67,8 @@ function getProjectConfigByPath(graph, configPath) {
|
|
|
69
67
|
return graph.nodes[componentTestingProjectName].data;
|
|
70
68
|
}
|
|
71
69
|
function createExecutorContext(graph, targets, projectName, targetName, configurationName) {
|
|
72
|
-
const projectsConfigurations = (0,
|
|
73
|
-
const nxJsonConfiguration = (0,
|
|
70
|
+
const projectsConfigurations = (0, devkit_1.readProjectsConfigurationFromProjectGraph)(graph);
|
|
71
|
+
const nxJsonConfiguration = (0, internal_1.readNxJsonFromDisk)();
|
|
74
72
|
return {
|
|
75
73
|
cwd: process.cwd(),
|
|
76
74
|
projectGraph: graph,
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.findBuildConfig = findBuildConfig;
|
|
4
4
|
const devkit_1 = require("@nx/devkit");
|
|
5
|
-
const
|
|
6
|
-
const project_graph_1 = require("nx/src/project-graph/project-graph");
|
|
5
|
+
const internal_1 = require("@nx/devkit/internal");
|
|
7
6
|
async function findBuildConfig(tree, options) {
|
|
8
7
|
try {
|
|
9
8
|
// attempt to use the provided target
|
|
@@ -118,8 +117,8 @@ function findTargetOptionsInProject(tree, graph, projectName, options) {
|
|
|
118
117
|
}
|
|
119
118
|
}
|
|
120
119
|
function createExecutorContext(graph, targets, projectName, targetName, configurationName) {
|
|
121
|
-
const nxJsonConfiguration = (0,
|
|
122
|
-
const projectsConfigurations = (0,
|
|
120
|
+
const nxJsonConfiguration = (0, internal_1.readNxJsonFromDisk)();
|
|
121
|
+
const projectsConfigurations = (0, devkit_1.readProjectsConfigurationFromProjectGraph)(graph);
|
|
123
122
|
return {
|
|
124
123
|
cwd: process.cwd(),
|
|
125
124
|
projectGraph: graph,
|
|
@@ -5,9 +5,9 @@ const tslib_1 = require("tslib");
|
|
|
5
5
|
const devkit_1 = require("@nx/devkit");
|
|
6
6
|
const path_1 = require("path");
|
|
7
7
|
const detect_port_1 = tslib_1.__importDefault(require("detect-port"));
|
|
8
|
-
const executor_utils_1 = require("nx/src/command-line/run/executor-utils");
|
|
9
8
|
const fs_1 = require("fs");
|
|
10
9
|
const os_1 = require("os");
|
|
10
|
+
const internal_1 = require("@nx/devkit/internal");
|
|
11
11
|
const PORT_LOCK_DIR = (0, path_1.join)((0, os_1.tmpdir)(), 'nx-cypress-port-locks');
|
|
12
12
|
async function* startDevServer(opts, context) {
|
|
13
13
|
// no dev server, return the provisioned base url
|
|
@@ -136,8 +136,8 @@ ${e.message || e}`);
|
|
|
136
136
|
// so we double check the schema if readTargetOptions didn't return a value for the property
|
|
137
137
|
const projectConfig = context.projectsConfigurations?.projects?.[target.project];
|
|
138
138
|
const targetConfig = projectConfig.targets[target.target];
|
|
139
|
-
const [collection, executor] = (0,
|
|
140
|
-
const { schema } = (0,
|
|
139
|
+
const [collection, executor] = (0, internal_1.parseExecutor)(targetConfig.executor);
|
|
140
|
+
const { schema } = (0, internal_1.getExecutorInformation)(collection, executor, context.root, context.projectsConfigurations.projects);
|
|
141
141
|
// NOTE: schema won't have a default since readTargetOptions would have
|
|
142
142
|
// already set that and this check wouldn't need to be made
|
|
143
143
|
targetHasOpt = Object.keys(schema.properties).includes(property);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nx/cypress",
|
|
3
|
-
"version": "23.1.
|
|
3
|
+
"version": "23.1.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"files": [
|
|
@@ -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.1.
|
|
93
|
-
"@nx/eslint": "23.1.
|
|
94
|
-
"@nx/js": "23.1.
|
|
92
|
+
"@nx/devkit": "23.1.2",
|
|
93
|
+
"@nx/eslint": "23.1.2",
|
|
94
|
+
"@nx/js": "23.1.2"
|
|
95
95
|
},
|
|
96
96
|
"devDependencies": {
|
|
97
|
-
"nx": "23.1.
|
|
97
|
+
"nx": "23.1.2"
|
|
98
98
|
},
|
|
99
99
|
"peerDependencies": {
|
|
100
100
|
"cypress": ">= 13 < 16"
|