@nx/react 20.0.0-beta.1 → 20.0.0-canary.20240925-6182d20

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/generators.json CHANGED
@@ -54,12 +54,6 @@
54
54
  "description": "Create stories/specs for all components declared in an app or library.",
55
55
  "hidden": false
56
56
  },
57
- "component-cypress-spec": {
58
- "factory": "./src/generators/component-cypress-spec/component-cypress-spec#componentCypressGenerator",
59
- "schema": "./src/generators/component-cypress-spec/schema.json",
60
- "description": "Create a Cypress spec for a UI component that has a story.",
61
- "hidden": false
62
- },
63
57
  "hook": {
64
58
  "factory": "./src/generators/hook/hook",
65
59
  "schema": "./src/generators/hook/schema.json",
package/index.d.ts CHANGED
@@ -8,7 +8,6 @@ export { reactDomVersion, reactVersion } from './src/utils/versions';
8
8
  export { applicationGenerator } from './src/generators/application/application';
9
9
  export { componentGenerator } from './src/generators/component/component';
10
10
  export { hookGenerator } from './src/generators/hook/hook';
11
- export { componentCypressGenerator } from './src/generators/component-cypress-spec/component-cypress-spec';
12
11
  export { componentStoryGenerator } from './src/generators/component-story/component-story';
13
12
  export { libraryGenerator } from './src/generators/library/library';
14
13
  export { reactInitGenerator } from './src/generators/init/init';
package/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.setupTailwindGenerator = exports.componentTestGenerator = exports.cypressComponentConfigGenerator = exports.remoteGenerator = exports.hostGenerator = exports.storybookConfigurationGenerator = exports.storiesGenerator = exports.reduxGenerator = exports.reactInitGenerator = exports.libraryGenerator = exports.componentStoryGenerator = exports.componentCypressGenerator = exports.hookGenerator = exports.componentGenerator = exports.applicationGenerator = exports.reactVersion = exports.reactDomVersion = exports.assertValidStyle = exports.cssInJsDependenciesBabel = exports.extendReactEslintJson = exports.extraEslintDependencies = exports.NxReactWebpackPlugin = void 0;
3
+ exports.setupTailwindGenerator = exports.componentTestGenerator = exports.cypressComponentConfigGenerator = exports.remoteGenerator = exports.hostGenerator = exports.storybookConfigurationGenerator = exports.storiesGenerator = exports.reduxGenerator = exports.reactInitGenerator = exports.libraryGenerator = exports.componentStoryGenerator = exports.hookGenerator = exports.componentGenerator = exports.applicationGenerator = exports.reactVersion = exports.reactDomVersion = exports.assertValidStyle = exports.cssInJsDependenciesBabel = exports.extendReactEslintJson = exports.extraEslintDependencies = exports.NxReactWebpackPlugin = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const nx_react_webpack_plugin_1 = require("./plugins/nx-react-webpack-plugin/nx-react-webpack-plugin");
6
6
  // TODO(v20): Remove this in favor of deep imports in order to load configs faster (150-200ms faster).
@@ -22,8 +22,6 @@ var component_1 = require("./src/generators/component/component");
22
22
  Object.defineProperty(exports, "componentGenerator", { enumerable: true, get: function () { return component_1.componentGenerator; } });
23
23
  var hook_1 = require("./src/generators/hook/hook");
24
24
  Object.defineProperty(exports, "hookGenerator", { enumerable: true, get: function () { return hook_1.hookGenerator; } });
25
- var component_cypress_spec_1 = require("./src/generators/component-cypress-spec/component-cypress-spec");
26
- Object.defineProperty(exports, "componentCypressGenerator", { enumerable: true, get: function () { return component_cypress_spec_1.componentCypressGenerator; } });
27
25
  var component_story_1 = require("./src/generators/component-story/component-story");
28
26
  Object.defineProperty(exports, "componentStoryGenerator", { enumerable: true, get: function () { return component_story_1.componentStoryGenerator; } });
29
27
  var library_1 = require("./src/generators/library/library");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nx/react",
3
- "version": "20.0.0-beta.1",
3
+ "version": "20.0.0-canary.20240925-6182d20",
4
4
  "private": false,
5
5
  "description": "The React plugin for Nx contains executors and generators for managing React applications and libraries within an Nx workspace. It provides:\n\n\n- Integration with libraries such as Jest, Vitest, Playwright, Cypress, and Storybook.\n\n- Generators for applications, libraries, components, hooks, and more.\n\n- Library build support for publishing packages to npm or other registries.\n\n- Utilities for automatic workspace refactoring.",
6
6
  "repository": {
@@ -39,13 +39,13 @@
39
39
  "minimatch": "9.0.3",
40
40
  "tslib": "^2.3.0",
41
41
  "@module-federation/enhanced": "~0.6.0",
42
- "@nx/devkit": "20.0.0-beta.1",
43
- "@nx/js": "20.0.0-beta.1",
44
- "@nx/eslint": "20.0.0-beta.1",
45
- "@nx/web": "20.0.0-beta.1",
42
+ "@nx/devkit": "20.0.0-canary.20240925-6182d20",
43
+ "@nx/js": "20.0.0-canary.20240925-6182d20",
44
+ "@nx/eslint": "20.0.0-canary.20240925-6182d20",
45
+ "@nx/web": "20.0.0-canary.20240925-6182d20",
46
46
  "express": "^4.19.2",
47
47
  "http-proxy-middleware": "^3.0.0",
48
- "@nrwl/react": "20.0.0-beta.1"
48
+ "@nrwl/react": "20.0.0-canary.20240925-6182d20"
49
49
  },
50
50
  "publishConfig": {
51
51
  "access": "public"
@@ -17,16 +17,6 @@
17
17
  "x-prompt": "For which project do you want to generate stories?",
18
18
  "x-priority": "important"
19
19
  },
20
- "generateCypressSpecs": {
21
- "type": "boolean",
22
- "description": "Automatically generate `*.spec.ts` files in the cypress e2e app generated by the cypress-configure generator.",
23
- "x-deprecated": "Use interactionTests instead. This option will be removed in v20."
24
- },
25
- "cypressProject": {
26
- "type": "string",
27
- "description": "The Cypress project to generate the stories under. This is inferred from `project` by default.",
28
- "x-deprecated": "Use interactionTests instead. This option will be removed in v20."
29
- },
30
20
  "interactionTests": {
31
21
  "type": "boolean",
32
22
  "description": "Set up Storybook interaction tests.",
@@ -5,11 +5,9 @@ export interface StorybookStoriesSchema {
5
5
  js?: boolean;
6
6
  ignorePaths?: string[];
7
7
  skipFormat?: boolean;
8
- cypressProject?: string;
9
- generateCypressSpecs?: boolean;
10
8
  }
11
9
  export declare function projectRootPath(tree: Tree, config: ProjectConfiguration): Promise<string>;
12
10
  export declare function containsComponentDeclaration(tree: Tree, componentPath: string): boolean;
13
- export declare function createAllStories(tree: Tree, projectName: string, interactionTests: boolean, js: boolean, projects: Map<string, ProjectConfiguration>, projectConfiguration: ProjectConfiguration, generateCypressSpecs?: boolean, cypressProject?: string, ignorePaths?: string[]): Promise<void>;
11
+ export declare function createAllStories(tree: Tree, projectName: string, interactionTests: boolean, js: boolean, projects: Map<string, ProjectConfiguration>, projectConfiguration: ProjectConfiguration, ignorePaths?: string[]): Promise<void>;
14
12
  export declare function storiesGenerator(host: Tree, schema: StorybookStoriesSchema): Promise<GeneratorCallback>;
15
13
  export default storiesGenerator;
@@ -5,7 +5,6 @@ exports.containsComponentDeclaration = containsComponentDeclaration;
5
5
  exports.createAllStories = createAllStories;
6
6
  exports.storiesGenerator = storiesGenerator;
7
7
  const component_story_1 = require("../component-story/component-story");
8
- const component_cypress_spec_1 = require("../component-cypress-spec/component-cypress-spec");
9
8
  const ast_utils_1 = require("../../utils/ast-utils");
10
9
  const devkit_1 = require("@nx/devkit");
11
10
  const path_1 = require("path");
@@ -44,7 +43,7 @@ function containsComponentDeclaration(tree, componentPath) {
44
43
  return !!((0, ast_utils_1.getComponentNode)(sourceFile) ||
45
44
  (0, ast_utils_1.findExportDeclarationsForJsx)(sourceFile)?.length);
46
45
  }
47
- async function createAllStories(tree, projectName, interactionTests, js, projects, projectConfiguration, generateCypressSpecs, cypressProject, ignorePaths) {
46
+ async function createAllStories(tree, projectName, interactionTests, js, projects, projectConfiguration, ignorePaths) {
48
47
  const { isTheFileAStory } = await Promise.resolve().then(() => require('@nx/storybook/src/utils/utilities'));
49
48
  const { sourceRoot, root } = projectConfiguration;
50
49
  let componentPaths = [];
@@ -70,11 +69,6 @@ async function createAllStories(tree, projectName, interactionTests, js, project
70
69
  }
71
70
  }
72
71
  });
73
- const e2eProjectName = cypressProject || `${projectName}-e2e`;
74
- const e2eProject = projects.get(e2eProjectName);
75
- if (generateCypressSpecs && !e2eProject) {
76
- devkit_1.logger.info(`There was no e2e project "${e2eProjectName}" found, so cypress specs will not be generated. Pass "--cypressProject" to specify a different e2e project name`);
77
- }
78
72
  await Promise.all(componentPaths.map(async (componentPath) => {
79
73
  const relativeCmpDir = componentPath.replace((0, path_1.join)(sourceRoot, '/'), '');
80
74
  if (!containsComponentDeclaration(tree, componentPath)) {
@@ -86,22 +80,13 @@ async function createAllStories(tree, projectName, interactionTests, js, project
86
80
  skipFormat: true,
87
81
  interactionTests,
88
82
  });
89
- if (generateCypressSpecs && e2eProject) {
90
- await (0, component_cypress_spec_1.default)(tree, {
91
- project: projectName,
92
- componentPath: relativeCmpDir,
93
- js,
94
- cypressProject,
95
- skipFormat: true,
96
- });
97
- }
98
83
  }));
99
84
  }
100
85
  async function storiesGenerator(host, schema) {
101
86
  const projects = (0, devkit_1.getProjects)(host);
102
87
  const projectConfiguration = projects.get(schema.project);
103
88
  schema.interactionTests = schema.interactionTests ?? true;
104
- await createAllStories(host, schema.project, schema.interactionTests, schema.js, projects, projectConfiguration, schema.generateCypressSpecs, schema.cypressProject, schema.ignorePaths);
89
+ await createAllStories(host, schema.project, schema.interactionTests, schema.js, projects, projectConfiguration, schema.ignorePaths);
105
90
  const tasks = [];
106
91
  if (schema.interactionTests) {
107
92
  const { interactionTestsDependencies, addInteractionsInAddons } = (0, devkit_1.ensurePackage)('@nx/storybook', versions_1.nxVersion);
@@ -7,16 +7,10 @@ const stories_1 = require("../stories/stories");
7
7
  const devkit_1 = require("@nx/devkit");
8
8
  const versions_1 = require("../../utils/versions");
9
9
  async function generateStories(host, schema) {
10
- // TODO(katerina): Nx 19 -> remove Cypress
11
- (0, devkit_1.ensurePackage)('@nx/cypress', versions_1.nxVersion);
12
- const { getE2eProjectName } = await Promise.resolve().then(() => require('@nx/cypress/src/utils/project-name'));
13
10
  const projectConfig = (0, devkit_1.readProjectConfiguration)(host, schema.project);
14
- const cypressProject = getE2eProjectName(schema.project, projectConfig.root, schema.cypressDirectory);
15
11
  await (0, stories_1.default)(host, {
16
12
  project: schema.project,
17
- generateCypressSpecs: schema.configureCypress && schema.generateCypressSpecs,
18
13
  js: schema.js,
19
- cypressProject,
20
14
  ignorePaths: schema.ignorePaths,
21
15
  skipFormat: true,
22
16
  interactionTests: schema.interactionTests ?? true,
@@ -48,10 +42,8 @@ async function storybookConfigurationGeneratorInternal(host, schema) {
48
42
  }
49
43
  const installTask = await configurationGenerator(host, {
50
44
  project: schema.project,
51
- configureCypress: schema.configureCypress,
52
45
  js: schema.js,
53
46
  linter: schema.linter,
54
- cypressDirectory: schema.cypressDirectory,
55
47
  tsConfiguration: schema.tsConfiguration ?? true, // default is true
56
48
  interactionTests: schema.interactionTests ?? true, // default is true
57
49
  configureStaticServe: schema.configureStaticServe,
@@ -9,8 +9,5 @@ export interface StorybookConfigureSchema {
9
9
  linter?: Linter | LinterType;
10
10
  ignorePaths?: string[];
11
11
  configureStaticServe?: boolean;
12
- configureCypress?: boolean;
13
- generateCypressSpecs?: boolean;
14
- cypressDirectory?: string;
15
12
  addPlugin?: boolean;
16
13
  }
@@ -26,11 +26,6 @@
26
26
  "alias": ["configureTestRunner"],
27
27
  "default": true
28
28
  },
29
- "configureCypress": {
30
- "type": "boolean",
31
- "description": "Run the cypress-configure generator.",
32
- "x-deprecated": "Use interactionTests instead. This option will be removed in v20."
33
- },
34
29
  "generateStories": {
35
30
  "type": "boolean",
36
31
  "description": "Automatically generate `*.stories.ts` files for components declared in this project?",
@@ -38,11 +33,6 @@
38
33
  "default": true,
39
34
  "x-priority": "important"
40
35
  },
41
- "generateCypressSpecs": {
42
- "type": "boolean",
43
- "description": "Automatically generate test files in the Cypress E2E app generated by the `cypress-configure` generator.",
44
- "x-deprecated": "Use interactionTests instead. This option will be removed in v20."
45
- },
46
36
  "configureStaticServe": {
47
37
  "type": "boolean",
48
38
  "description": "Specifies whether to configure a static file server target for serving storybook. Helpful for speeding up CI build/test times.",
@@ -50,11 +40,6 @@
50
40
  "default": true,
51
41
  "x-priority": "important"
52
42
  },
53
- "cypressDirectory": {
54
- "type": "string",
55
- "description": "A directory where the Cypress project will be placed. Placed at the root by default.",
56
- "x-deprecated": "Use interactionTests instead. This option will be removed in v20."
57
- },
58
43
  "js": {
59
44
  "type": "boolean",
60
45
  "description": "Generate JavaScript story files rather than TypeScript story files.",
@@ -1,13 +0,0 @@
1
- import { Tree } from '@nx/devkit';
2
- import type * as ts from 'typescript';
3
- export interface CreateComponentSpecFileSchema {
4
- project: string;
5
- componentPath: string;
6
- js?: boolean;
7
- cypressProject?: string;
8
- skipFormat?: boolean;
9
- }
10
- export declare function componentCypressGenerator(host: Tree, schema: CreateComponentSpecFileSchema): Promise<void>;
11
- export declare function getArgsDefaultValue(property: ts.SyntaxKind): string;
12
- export declare function createComponentSpecFile(tree: Tree, { project, componentPath, js, cypressProject }: CreateComponentSpecFileSchema): void;
13
- export default componentCypressGenerator;
@@ -1,104 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.componentCypressGenerator = componentCypressGenerator;
4
- exports.getArgsDefaultValue = getArgsDefaultValue;
5
- exports.createComponentSpecFile = createComponentSpecFile;
6
- const devkit_1 = require("@nx/devkit");
7
- const path_1 = require("path");
8
- const ast_utils_1 = require("../../utils/ast-utils");
9
- const ensure_typescript_1 = require("@nx/js/src/utils/typescript/ensure-typescript");
10
- let tsModule;
11
- async function componentCypressGenerator(host, schema) {
12
- createComponentSpecFile(host, schema);
13
- if (!schema.skipFormat) {
14
- await (0, devkit_1.formatFiles)(host);
15
- }
16
- }
17
- // TODO: candidate to refactor with the angular component story
18
- function getArgsDefaultValue(property) {
19
- if (!tsModule) {
20
- tsModule = (0, ensure_typescript_1.ensureTypescript)();
21
- }
22
- const typeNameToDefault = {
23
- [tsModule.SyntaxKind.StringKeyword]: '',
24
- [tsModule.SyntaxKind.NumberKeyword]: 0,
25
- [tsModule.SyntaxKind.BooleanKeyword]: false,
26
- };
27
- const resolvedValue = typeNameToDefault[property];
28
- if (resolvedValue === undefined) {
29
- return '';
30
- }
31
- else if (typeof resolvedValue === 'string') {
32
- return resolvedValue.replace(/\s/g, '+');
33
- }
34
- else {
35
- return resolvedValue;
36
- }
37
- }
38
- function createComponentSpecFile(tree, { project, componentPath, js, cypressProject }) {
39
- if (!tsModule) {
40
- tsModule = (0, ensure_typescript_1.ensureTypescript)();
41
- }
42
- const e2eProjectName = cypressProject || `${project}-e2e`;
43
- const projects = (0, devkit_1.getProjects)(tree);
44
- const e2eProject = projects.get(e2eProjectName);
45
- // cypress >= v10 will have a cypress.config.ts < v10 will have a cypress.json
46
- const isCypressV10 = tree.exists((0, path_1.join)(e2eProject.root, 'cypress.config.ts'));
47
- const e2eLibIntegrationFolderPath = (0, path_1.join)(e2eProject.sourceRoot, isCypressV10 ? 'e2e' : 'integration');
48
- const proj = projects.get(project);
49
- const componentFilePath = (0, devkit_1.joinPathFragments)(proj.sourceRoot, componentPath);
50
- const componentName = componentFilePath
51
- .slice(componentFilePath.lastIndexOf('/') + 1)
52
- .replace('.tsx', '')
53
- .replace('.jsx', '')
54
- .replace('.js', '');
55
- const contents = tree.read(componentFilePath, 'utf-8');
56
- if (contents === null) {
57
- throw new Error(`Failed to read ${componentFilePath}`);
58
- }
59
- const sourceFile = tsModule.createSourceFile(componentFilePath, contents, tsModule.ScriptTarget.Latest, true);
60
- const cmpDeclaration = (0, ast_utils_1.getComponentNode)(sourceFile);
61
- if (!cmpDeclaration) {
62
- const componentNodes = (0, ast_utils_1.findExportDeclarationsForJsx)(sourceFile);
63
- if (componentNodes?.length) {
64
- componentNodes.forEach((declaration) => {
65
- findPropsAndGenerateFileForCypress(tree, sourceFile, declaration, e2eLibIntegrationFolderPath, componentName, project, js, true);
66
- });
67
- }
68
- else {
69
- throw new Error(`Could not find any React component in file ${componentFilePath}`);
70
- }
71
- }
72
- else {
73
- findPropsAndGenerateFileForCypress(tree, sourceFile, cmpDeclaration, e2eLibIntegrationFolderPath, componentName, project, js);
74
- }
75
- }
76
- function findPropsAndGenerateFileForCypress(tree, sourceFile, cmpDeclaration, e2eLibIntegrationFolderPath, componentName, project, js, fromNodeArray) {
77
- const info = (0, ast_utils_1.parseComponentPropsInfo)(sourceFile, cmpDeclaration);
78
- let props = [];
79
- if (info) {
80
- if (!tsModule) {
81
- tsModule = (0, ensure_typescript_1.ensureTypescript)();
82
- }
83
- props = info.props.map((member) => {
84
- return {
85
- name: member.name.text,
86
- defaultValue: tsModule.isBindingElement(member)
87
- ? getArgsDefaultValue(member.kind)
88
- : getArgsDefaultValue(member.type.kind),
89
- };
90
- });
91
- }
92
- const isCypressV10 = (0, path_1.basename)(e2eLibIntegrationFolderPath) === 'e2e';
93
- const cyFilePrefix = isCypressV10 ? 'cy' : 'spec';
94
- (0, devkit_1.generateFiles)(tree, (0, devkit_1.joinPathFragments)(__dirname, './files'), `${e2eLibIntegrationFolderPath}/${fromNodeArray
95
- ? componentName + '--' + cmpDeclaration.name.text
96
- : componentName}`, {
97
- projectName: project,
98
- componentName,
99
- componentSelector: cmpDeclaration.name.text,
100
- props,
101
- fileExt: js ? `${cyFilePrefix}.js` : `${cyFilePrefix}.ts`,
102
- });
103
- }
104
- exports.default = componentCypressGenerator;
@@ -1,13 +0,0 @@
1
- describe('<%=projectName%>: <%= componentSelector %> component', () => {
2
- beforeEach(() => cy.visit('/iframe.html?id=<%= componentSelector.toLowerCase() %>--primary<% if ( props && props.length > 0 ) { %>&args=<% } %><%
3
- for(let prop of props) {
4
- %><%=prop.name%><%
5
- if(prop.defaultValue !== undefined && (prop.defaultValue || prop.defaultValue === false)) {
6
- %>:<%=prop.defaultValue%><%
7
- } %>;<%
8
- }%>'));
9
-
10
- it('should render the component', () => {
11
- cy.get('h1').should('contain', 'Welcome to <%=componentSelector%>!');
12
- });
13
- });
@@ -1,45 +0,0 @@
1
- {
2
- "$schema": "https://json-schema.org/schema",
3
- "cli": "nx",
4
- "$id": "NxReactComponentCypressSpec",
5
- "title": "Create component Cypress spec",
6
- "description": "Create a Storybook Cypress spec for a UI component that has a story.",
7
- "x-deprecated": "Use interactionTests instead. This option will be removed in v20.",
8
- "type": "object",
9
- "properties": {
10
- "project": {
11
- "type": "string",
12
- "description": "The project name for which to generate tests.",
13
- "examples": ["shared-ui-component"],
14
- "$default": {
15
- "$source": "projectName",
16
- "index": 0
17
- },
18
- "x-prompt": "What's name of the project for which to generate tests?",
19
- "x-priority": "important"
20
- },
21
- "componentPath": {
22
- "type": "string",
23
- "description": "Relative path to the component file from the library root?",
24
- "examples": ["lib/components"],
25
- "x-prompt": "What's path of the component relative to the project's lib root for which to generate a test?",
26
- "x-priority": "important"
27
- },
28
- "js": {
29
- "type": "boolean",
30
- "description": "Generate JavaScript files rather than TypeScript files.",
31
- "default": false
32
- },
33
- "cypressProject": {
34
- "type": "string",
35
- "description": "The Cypress project to generate the stories under. By default, inferred from `project`."
36
- },
37
- "skipFormat": {
38
- "description": "Skip formatting files.",
39
- "type": "boolean",
40
- "default": false,
41
- "x-priority": "internal"
42
- }
43
- },
44
- "required": ["project", "componentPath"]
45
- }