@nx/cypress 21.6.1-beta.1 → 21.6.1-beta.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/cypress",
3
- "version": "21.6.1-beta.1",
3
+ "version": "21.6.1-beta.2",
4
4
  "private": false,
5
5
  "description": "The Nx Plugin for Cypress contains executors and generators allowing your workspace to use the powerful Cypress integration testing capabilities.",
6
6
  "repository": {
@@ -36,9 +36,9 @@
36
36
  "migrations": "./migrations.json"
37
37
  },
38
38
  "dependencies": {
39
- "@nx/devkit": "21.6.1-beta.1",
40
- "@nx/eslint": "21.6.1-beta.1",
41
- "@nx/js": "21.6.1-beta.1",
39
+ "@nx/devkit": "21.6.1-beta.2",
40
+ "@nx/eslint": "21.6.1-beta.2",
41
+ "@nx/js": "21.6.1-beta.2",
42
42
  "@phenomnomnominal/tsquery": "~5.0.1",
43
43
  "detect-port": "^1.5.1",
44
44
  "semver": "^7.6.3",
@@ -46,7 +46,7 @@
46
46
  "tslib": "^2.3.0"
47
47
  },
48
48
  "devDependencies": {
49
- "nx": "21.6.1-beta.1"
49
+ "nx": "21.6.1-beta.2"
50
50
  },
51
51
  "peerDependencies": {
52
52
  "cypress": ">= 3 < 15"
@@ -1,9 +1,10 @@
1
- import { CreateNodes, CreateNodesV2 } from '@nx/devkit';
1
+ import { type CreateNodes, type CreateNodesV2 } from '@nx/devkit';
2
2
  export interface CypressPluginOptions {
3
3
  ciTargetName?: string;
4
4
  targetName?: string;
5
5
  openTargetName?: string;
6
6
  componentTestingTargetName?: string;
7
+ ciComponentTestingTargetName?: string;
7
8
  }
8
9
  export declare const createNodesV2: CreateNodesV2<CypressPluginOptions>;
9
10
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../../../packages/cypress/src/plugins/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EAGX,aAAa,EAWd,MAAM,YAAY,CAAC;AAepB,MAAM,WAAW,oBAAoB;IACnC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,0BAA0B,CAAC,EAAE,MAAM,CAAC;CACrC;AAoBD,eAAO,MAAM,aAAa,EAAE,aAAa,CAAC,oBAAoB,CAqB7D,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,WAAW,CAAC,oBAAoB,CAQzD,CAAC"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../../../../../packages/cypress/src/plugins/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,WAAW,EAGhB,KAAK,aAAa,EAWnB,MAAM,YAAY,CAAC;AAYpB,MAAM,WAAW,oBAAoB;IACnC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,0BAA0B,CAAC,EAAE,MAAM,CAAC;IACpC,4BAA4B,CAAC,EAAE,MAAM,CAAC;CACvC;AA8BD,eAAO,MAAM,aAAa,EAAE,aAAa,CAAC,oBAAoB,CAqB7D,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,WAAW,EAAE,WAAW,CAAC,oBAAoB,CAQzD,CAAC"}
@@ -2,16 +2,16 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createNodes = exports.createNodesV2 = void 0;
4
4
  const devkit_1 = require("@nx/devkit");
5
- const path_1 = require("path");
6
- const js_1 = require("@nx/js");
7
- const get_named_inputs_1 = require("@nx/devkit/src/utils/get-named-inputs");
8
- const fs_1 = require("fs");
9
5
  const calculate_hash_for_create_nodes_1 = require("@nx/devkit/src/utils/calculate-hash-for-create-nodes");
10
- const cache_directory_1 = require("nx/src/utils/cache-directory");
11
- const constants_1 = require("../utils/constants");
12
6
  const config_utils_1 = require("@nx/devkit/src/utils/config-utils");
7
+ const get_named_inputs_1 = require("@nx/devkit/src/utils/get-named-inputs");
8
+ const js_1 = require("@nx/js");
9
+ const fs_1 = require("fs");
13
10
  const devkit_internals_1 = require("nx/src/devkit-internals");
11
+ const cache_directory_1 = require("nx/src/utils/cache-directory");
14
12
  const workspace_context_1 = require("nx/src/utils/workspace-context");
13
+ const path_1 = require("path");
14
+ const constants_1 = require("../utils/constants");
15
15
  function readTargetsCache(cachePath) {
16
16
  try {
17
17
  return process.env.NX_CACHE_PROJECT_GRAPH !== 'false'
@@ -26,6 +26,16 @@ function writeTargetsToCache(cachePath, results) {
26
26
  (0, devkit_1.writeJsonFile)(cachePath, results);
27
27
  }
28
28
  const cypressConfigGlob = '**/cypress.config.{js,ts,mjs,cjs}';
29
+ const defaultPatterns = {
30
+ e2e: {
31
+ specPattern: 'cypress/e2e/**/*.cy.{js,jsx,ts,tsx}',
32
+ excludeSpecPattern: '*.hot-update.js',
33
+ },
34
+ component: {
35
+ specPattern: '**/*.cy.{js,jsx,ts,tsx}',
36
+ excludeSpecPattern: ['/snapshots/*', '/image_snapshots/*'],
37
+ },
38
+ };
29
39
  const pmc = (0, devkit_1.getPackageManagerCommand)();
30
40
  exports.createNodesV2 = [
31
41
  cypressConfigGlob,
@@ -214,16 +224,7 @@ async function buildCypressTargets(configFilePath, projectRoot, options, context
214
224
  }
215
225
  const ciWebServerCommand = pluginPresetOptions?.ciWebServerCommand;
216
226
  if (ciWebServerCommand) {
217
- const specPatterns = Array.isArray(cypressConfig.e2e.specPattern)
218
- ? cypressConfig.e2e.specPattern.map((p) => (0, path_1.join)(projectRoot, p))
219
- : [(0, path_1.join)(projectRoot, cypressConfig.e2e.specPattern)];
220
- const excludeSpecPatterns = !cypressConfig.e2e
221
- .excludeSpecPattern
222
- ? cypressConfig.e2e.excludeSpecPattern
223
- : Array.isArray(cypressConfig.e2e.excludeSpecPattern)
224
- ? cypressConfig.e2e.excludeSpecPattern.map((p) => (0, path_1.join)(projectRoot, p))
225
- : [(0, path_1.join)(projectRoot, cypressConfig.e2e.excludeSpecPattern)];
226
- const specFiles = await (0, workspace_context_1.globWithWorkspaceContext)(context.workspaceRoot, specPatterns, excludeSpecPatterns);
227
+ const { specFiles, specPatterns, excludeSpecPatterns } = await getSpecFilesAndPatternsForTestType(cypressConfig, 'e2e', context.workspaceRoot, projectRoot);
227
228
  const ciBaseUrl = pluginPresetOptions?.ciBaseUrl;
228
229
  const dependsOn = [];
229
230
  const outputs = getOutputs(projectRoot, cypressConfig, 'e2e');
@@ -314,6 +315,8 @@ async function buildCypressTargets(configFilePath, projectRoot, options, context
314
315
  }
315
316
  }
316
317
  if ('component' in cypressConfig) {
318
+ const inputs = getInputs(namedInputs);
319
+ const outputs = getOutputs(projectRoot, cypressConfig, 'component');
317
320
  // This will not override the e2e target if it is the same
318
321
  targets[options.componentTestingTargetName] ??= {
319
322
  command: `cypress run --component`,
@@ -322,8 +325,8 @@ async function buildCypressTargets(configFilePath, projectRoot, options, context
322
325
  env: { TS_NODE_COMPILER_OPTIONS: tsNodeCompilerOptions },
323
326
  },
324
327
  cache: true,
325
- inputs: getInputs(namedInputs),
326
- outputs: getOutputs(projectRoot, cypressConfig, 'component'),
328
+ inputs,
329
+ outputs,
327
330
  metadata: {
328
331
  technologies: ['cypress'],
329
332
  description: 'Runs Cypress Component Tests',
@@ -335,6 +338,82 @@ async function buildCypressTargets(configFilePath, projectRoot, options, context
335
338
  },
336
339
  },
337
340
  };
341
+ if (options.ciComponentTestingTargetName) {
342
+ const { specFiles, specPatterns, excludeSpecPatterns } = await getSpecFilesAndPatternsForTestType(cypressConfig, 'component', context.workspaceRoot, projectRoot);
343
+ const dependsOn = [];
344
+ const groupName = 'Component Testing (CI)';
345
+ metadata ??= {};
346
+ metadata.targetGroups ??= {};
347
+ metadata.targetGroups[groupName] ??= [];
348
+ const ctCiTargetGroup = metadata.targetGroups[groupName];
349
+ for (const file of specFiles) {
350
+ const relativeSpecFilePath = (0, devkit_1.normalizePath)((0, path_1.relative)(projectRoot, file));
351
+ if (relativeSpecFilePath.includes('../')) {
352
+ throw new Error('@nx/cypress/plugin attempted to run tests outside of the project root. This is not supported and should not happen. Please open an issue at https://github.com/nrwl/nx/issues/new/choose with the following information:\n\n' +
353
+ `\n\n${JSON.stringify({
354
+ projectRoot,
355
+ relativeSpecFilePath,
356
+ specFiles,
357
+ context,
358
+ excludeSpecPatterns,
359
+ specPatterns,
360
+ }, null, 2)}`);
361
+ }
362
+ const targetName = options.ciComponentTestingTargetName + '--' + relativeSpecFilePath;
363
+ const outputSubfolder = relativeSpecFilePath
364
+ .replace(/[\/\\]/g, '-')
365
+ .replace(/\./g, '-');
366
+ ctCiTargetGroup.push(targetName);
367
+ targets[targetName] = {
368
+ outputs: getTargetOutputs(outputs, outputSubfolder),
369
+ inputs,
370
+ cache: true,
371
+ command: `cypress run --component --spec ${relativeSpecFilePath} --config=${getTargetConfig(cypressConfig, outputSubfolder)}`,
372
+ options: {
373
+ cwd: projectRoot,
374
+ env: { TS_NODE_COMPILER_OPTIONS: tsNodeCompilerOptions },
375
+ },
376
+ // Cypress handles starting the server, there's no separate server
377
+ // target we can use as continuous, so we need to disable parallelism
378
+ // to avoid port conflicts
379
+ parallelism: false,
380
+ metadata: {
381
+ technologies: ['cypress'],
382
+ description: `Runs Cypress Component Tests for ${relativeSpecFilePath} in CI`,
383
+ help: {
384
+ command: `${pmc.exec} cypress run --help`,
385
+ example: {
386
+ args: ['--dev', '--headed'],
387
+ },
388
+ },
389
+ },
390
+ };
391
+ dependsOn.push({
392
+ target: targetName,
393
+ projects: 'self',
394
+ params: 'forward',
395
+ });
396
+ }
397
+ targets[options.ciComponentTestingTargetName] = {
398
+ executor: 'nx:noop',
399
+ cache: true,
400
+ inputs,
401
+ outputs,
402
+ dependsOn,
403
+ metadata: {
404
+ technologies: ['cypress'],
405
+ description: 'Runs Cypress Component Tests in CI',
406
+ nonAtomizedTarget: options.componentTestingTargetName,
407
+ help: {
408
+ command: `${pmc.exec} cypress run --help`,
409
+ example: {
410
+ args: ['--dev', '--headed'],
411
+ },
412
+ },
413
+ },
414
+ };
415
+ ctCiTargetGroup.push(options.ciComponentTestingTargetName);
416
+ }
338
417
  }
339
418
  targets[options.openTargetName] = {
340
419
  command: `cypress open`,
@@ -361,6 +440,8 @@ function normalizeOptions(options) {
361
440
  options.openTargetName ??= 'open-cypress';
362
441
  options.componentTestingTargetName ??= 'component-test';
363
442
  options.ciTargetName ??= 'e2e-ci';
443
+ // must be explicitly provided to opt-in to atomized component testing
444
+ options.ciComponentTestingTargetName;
364
445
  return options;
365
446
  }
366
447
  function getInputs(namedInputs) {
@@ -388,3 +469,17 @@ function parseTaskFromCommand(command) {
388
469
  }
389
470
  return null;
390
471
  }
472
+ async function getSpecFilesAndPatternsForTestType(cypressConfig, testType, workspaceRoot, projectRoot) {
473
+ const specPattern = cypressConfig[testType].specPattern ??
474
+ defaultPatterns[testType].specPattern;
475
+ const specPatterns = Array.isArray(specPattern)
476
+ ? specPattern.map((p) => (0, path_1.join)(projectRoot, p))
477
+ : [(0, path_1.join)(projectRoot, specPattern)];
478
+ const excludeSpecPattern = cypressConfig[testType].excludeSpecPattern ??
479
+ defaultPatterns[testType].excludeSpecPattern;
480
+ const excludeSpecPatterns = Array.isArray(excludeSpecPattern)
481
+ ? excludeSpecPattern.map((p) => (0, path_1.join)(projectRoot, p))
482
+ : [(0, path_1.join)(projectRoot, excludeSpecPattern)];
483
+ const specFiles = await (0, workspace_context_1.globWithWorkspaceContext)(workspaceRoot, specPatterns, excludeSpecPatterns);
484
+ return { specFiles, specPatterns, excludeSpecPatterns };
485
+ }