feat(storybook): remove cypress options for e2e testing (#27850)
- feat(storybook): remove cypress options from configuration generator - feat(react): remove cypress options from storybook-configuration - feat(react): remove cypress options from stories generator - feat(react): remove component-cypress-spec generator - chore(storybook): restore @nx/cypress dep - feat(remix): remove cypress options from storybook - feat(angular): remove cypress options from storybook-configuration - feat(angular): remove cypress options from stories generator - feat(angular): remove component-cypress-spec generator - feat(vue): remove cypress options from stories generator <!-- Please make sure you have read the submission guidelines before posting an PR --> <!-- https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr --> <!-- Please make sure that your commit message follows our format --> <!-- Example: `fix(nx): must begin with lowercase` --> <!-- If this is a particularly complex change or feature addition, you can request a dedicated Nx release for this pull request branch. Mention someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they will confirm if the PR warrants its own release for testing purposes, and generate it for you if appropriate. --> ## Current Behavior <!-- This is the behavior we have today --> With Storybook Interaction Testing, there's no longer a need to setup Cypress to specifically test storybook instances ## Expected Behavior <!-- This is the behavior we should expect with the changes in this PR --> Remove cypress options for creating an e2e project specifically for testing storybook instances. Use Storybook Interaction Testing instead ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes #
This commit is contained in:
parent
72cd1c15e6
commit
8290969cb7
@ -7028,14 +7028,6 @@
|
|||||||
"isExternal": false,
|
"isExternal": false,
|
||||||
"disableCollapsible": false
|
"disableCollapsible": false
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "component-cypress-spec",
|
|
||||||
"path": "/nx-api/angular/generators/component-cypress-spec",
|
|
||||||
"name": "component-cypress-spec",
|
|
||||||
"children": [],
|
|
||||||
"isExternal": false,
|
|
||||||
"disableCollapsible": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "component-story",
|
"id": "component-story",
|
||||||
"path": "/nx-api/angular/generators/component-story",
|
"path": "/nx-api/angular/generators/component-story",
|
||||||
@ -9222,14 +9214,6 @@
|
|||||||
"isExternal": false,
|
"isExternal": false,
|
||||||
"disableCollapsible": false
|
"disableCollapsible": false
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"id": "component-cypress-spec",
|
|
||||||
"path": "/nx-api/react/generators/component-cypress-spec",
|
|
||||||
"name": "component-cypress-spec",
|
|
||||||
"children": [],
|
|
||||||
"isExternal": false,
|
|
||||||
"disableCollapsible": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"id": "hook",
|
"id": "hook",
|
||||||
"path": "/nx-api/react/generators/hook",
|
"path": "/nx-api/react/generators/hook",
|
||||||
|
|||||||
@ -181,15 +181,6 @@
|
|||||||
"path": "/nx-api/angular/generators/component",
|
"path": "/nx-api/angular/generators/component",
|
||||||
"type": "generator"
|
"type": "generator"
|
||||||
},
|
},
|
||||||
"/nx-api/angular/generators/component-cypress-spec": {
|
|
||||||
"description": "Creates a Cypress spec for a UI component that has a story.",
|
|
||||||
"file": "generated/packages/angular/generators/component-cypress-spec.json",
|
|
||||||
"hidden": true,
|
|
||||||
"name": "component-cypress-spec",
|
|
||||||
"originalFilePath": "/packages/angular/src/generators/component-cypress-spec/schema.json",
|
|
||||||
"path": "/nx-api/angular/generators/component-cypress-spec",
|
|
||||||
"type": "generator"
|
|
||||||
},
|
|
||||||
"/nx-api/angular/generators/component-story": {
|
"/nx-api/angular/generators/component-story": {
|
||||||
"description": "Creates a stories.ts file for a component.",
|
"description": "Creates a stories.ts file for a component.",
|
||||||
"file": "generated/packages/angular/generators/component-story.json",
|
"file": "generated/packages/angular/generators/component-story.json",
|
||||||
@ -2358,15 +2349,6 @@
|
|||||||
"path": "/nx-api/react/generators/stories",
|
"path": "/nx-api/react/generators/stories",
|
||||||
"type": "generator"
|
"type": "generator"
|
||||||
},
|
},
|
||||||
"/nx-api/react/generators/component-cypress-spec": {
|
|
||||||
"description": "Create a Cypress spec for a UI component that has a story.",
|
|
||||||
"file": "generated/packages/react/generators/component-cypress-spec.json",
|
|
||||||
"hidden": false,
|
|
||||||
"name": "component-cypress-spec",
|
|
||||||
"originalFilePath": "/packages/react/src/generators/component-cypress-spec/schema.json",
|
|
||||||
"path": "/nx-api/react/generators/component-cypress-spec",
|
|
||||||
"type": "generator"
|
|
||||||
},
|
|
||||||
"/nx-api/react/generators/hook": {
|
"/nx-api/react/generators/hook": {
|
||||||
"description": "Create a hook.",
|
"description": "Create a hook.",
|
||||||
"file": "generated/packages/react/generators/hook.json",
|
"file": "generated/packages/react/generators/hook.json",
|
||||||
|
|||||||
@ -176,15 +176,6 @@
|
|||||||
"path": "angular/generators/component",
|
"path": "angular/generators/component",
|
||||||
"type": "generator"
|
"type": "generator"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"description": "Creates a Cypress spec for a UI component that has a story.",
|
|
||||||
"file": "generated/packages/angular/generators/component-cypress-spec.json",
|
|
||||||
"hidden": true,
|
|
||||||
"name": "component-cypress-spec",
|
|
||||||
"originalFilePath": "/packages/angular/src/generators/component-cypress-spec/schema.json",
|
|
||||||
"path": "angular/generators/component-cypress-spec",
|
|
||||||
"type": "generator"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"description": "Creates a stories.ts file for a component.",
|
"description": "Creates a stories.ts file for a component.",
|
||||||
"file": "generated/packages/angular/generators/component-story.json",
|
"file": "generated/packages/angular/generators/component-story.json",
|
||||||
@ -2332,15 +2323,6 @@
|
|||||||
"path": "react/generators/stories",
|
"path": "react/generators/stories",
|
||||||
"type": "generator"
|
"type": "generator"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"description": "Create a Cypress spec for a UI component that has a story.",
|
|
||||||
"file": "generated/packages/react/generators/component-cypress-spec.json",
|
|
||||||
"hidden": false,
|
|
||||||
"name": "component-cypress-spec",
|
|
||||||
"originalFilePath": "/packages/react/src/generators/component-cypress-spec/schema.json",
|
|
||||||
"path": "react/generators/component-cypress-spec",
|
|
||||||
"type": "generator"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"description": "Create a hook.",
|
"description": "Create a hook.",
|
||||||
"file": "generated/packages/react/generators/hook.json",
|
"file": "generated/packages/react/generators/hook.json",
|
||||||
|
|||||||
@ -1,75 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "component-cypress-spec",
|
|
||||||
"factory": "./src/generators/component-cypress-spec/component-cypress-spec",
|
|
||||||
"schema": {
|
|
||||||
"$schema": "https://json-schema.org/schema",
|
|
||||||
"$id": "NxAngularComponentCypressSpecGenerator",
|
|
||||||
"type": "object",
|
|
||||||
"cli": "nx",
|
|
||||||
"description": "Creates a Storybook Cypress spec for a UI component that has a story.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20.",
|
|
||||||
"properties": {
|
|
||||||
"projectName": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the project.",
|
|
||||||
"$default": { "$source": "projectName" },
|
|
||||||
"examples": ["ui-samples"],
|
|
||||||
"x-priority": "important"
|
|
||||||
},
|
|
||||||
"projectPath": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Path to the project.",
|
|
||||||
"examples": ["libs/ui-samples"],
|
|
||||||
"x-priority": "important"
|
|
||||||
},
|
|
||||||
"componentName": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Class name of the component.",
|
|
||||||
"examples": ["AwesomeComponent"],
|
|
||||||
"x-priority": "important"
|
|
||||||
},
|
|
||||||
"componentPath": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Relative path to the component file from the project root.",
|
|
||||||
"examples": ["awesome"],
|
|
||||||
"x-priority": "important"
|
|
||||||
},
|
|
||||||
"componentFileName": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Component file name without the `.ts` extension.",
|
|
||||||
"examples": ["awesome.component"],
|
|
||||||
"x-priority": "important"
|
|
||||||
},
|
|
||||||
"cypressProject": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The Cypress project to generate the stories under. By default, inferred from `projectName`."
|
|
||||||
},
|
|
||||||
"specDirectory": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Directory where to place the generated spec file. By default matches the value of the `componentPath` option."
|
|
||||||
},
|
|
||||||
"skipFormat": {
|
|
||||||
"description": "Skip formatting files.",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false,
|
|
||||||
"x-priority": "internal"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": [
|
|
||||||
"projectName",
|
|
||||||
"projectPath",
|
|
||||||
"componentName",
|
|
||||||
"componentPath",
|
|
||||||
"componentFileName"
|
|
||||||
],
|
|
||||||
"examplesFile": "## Examples\n\n{% tabs %}\n\n{% tab label=\"Basic Usage\" %}\n\nCreate a cypress spec for a component that is set up with Storybook.\n\n```bash\nnx g @nx/angular:component-cypress-spec --componentName=MyButtonComponent --componentPath=libs/ui/src/lib/button/button.component.ts --componentFileName=button.component --projectName=ui --projectPath=libs/ui\n```\n\n{% /tab %}\n\n{% /tabs %}\n",
|
|
||||||
"presets": []
|
|
||||||
},
|
|
||||||
"description": "Creates a Cypress spec for a UI component that has a story.",
|
|
||||||
"hidden": true,
|
|
||||||
"implementation": "/packages/angular/src/generators/component-cypress-spec/component-cypress-spec.ts",
|
|
||||||
"aliases": [],
|
|
||||||
"path": "/packages/angular/src/generators/component-cypress-spec/schema.json",
|
|
||||||
"type": "generator"
|
|
||||||
}
|
|
||||||
@ -25,16 +25,6 @@
|
|||||||
"x-priority": "important",
|
"x-priority": "important",
|
||||||
"default": true
|
"default": true
|
||||||
},
|
},
|
||||||
"generateCypressSpecs": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Specifies whether to automatically generate `*.spec.ts` files in the Cypress e2e app generated by the `cypress-configure` generator.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"cypressProject": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The Cypress project to generate the stories under. This is inferred from `name` by default.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"skipFormat": {
|
"skipFormat": {
|
||||||
"description": "Skip formatting files.",
|
"description": "Skip formatting files.",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
|
|||||||
@ -26,11 +26,6 @@
|
|||||||
"x-priority": "important",
|
"x-priority": "important",
|
||||||
"default": true
|
"default": true
|
||||||
},
|
},
|
||||||
"configureCypress": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Specifies whether to configure Cypress or not.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"generateStories": {
|
"generateStories": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Specifies whether to automatically generate `*.stories.ts` files for components declared in this project or not.",
|
"description": "Specifies whether to automatically generate `*.stories.ts` files for components declared in this project or not.",
|
||||||
@ -38,11 +33,6 @@
|
|||||||
"default": true,
|
"default": true,
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"generateCypressSpecs": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Specifies whether to automatically generate test files in the generated Cypress e2e app.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"configureStaticServe": {
|
"configureStaticServe": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Specifies whether to configure a static file server target for serving storybook. Helpful for speeding up CI build/test times.",
|
"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 @@
|
|||||||
"default": true,
|
"default": true,
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"cypressDirectory": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A directory where the Cypress project will be placed. Placed at the root by default.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"linter": {
|
"linter": {
|
||||||
"description": "The tool to use for running lint checks.",
|
"description": "The tool to use for running lint checks.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|||||||
@ -1,53 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "component-cypress-spec",
|
|
||||||
"factory": "./src/generators/component-cypress-spec/component-cypress-spec#componentCypressGenerator",
|
|
||||||
"schema": {
|
|
||||||
"$schema": "https://json-schema.org/schema",
|
|
||||||
"cli": "nx",
|
|
||||||
"$id": "NxReactComponentCypressSpec",
|
|
||||||
"title": "Create component Cypress spec",
|
|
||||||
"description": "Create a Storybook Cypress spec for a UI component that has a story.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20.",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"project": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The project name for which to generate tests.",
|
|
||||||
"examples": ["shared-ui-component"],
|
|
||||||
"$default": { "$source": "projectName", "index": 0 },
|
|
||||||
"x-prompt": "What's name of the project for which to generate tests?",
|
|
||||||
"x-priority": "important"
|
|
||||||
},
|
|
||||||
"componentPath": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Relative path to the component file from the library root?",
|
|
||||||
"examples": ["lib/components"],
|
|
||||||
"x-prompt": "What's path of the component relative to the project's lib root for which to generate a test?",
|
|
||||||
"x-priority": "important"
|
|
||||||
},
|
|
||||||
"js": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Generate JavaScript files rather than TypeScript files.",
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"cypressProject": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The Cypress project to generate the stories under. By default, inferred from `project`."
|
|
||||||
},
|
|
||||||
"skipFormat": {
|
|
||||||
"description": "Skip formatting files.",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false,
|
|
||||||
"x-priority": "internal"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["project", "componentPath"],
|
|
||||||
"presets": []
|
|
||||||
},
|
|
||||||
"description": "Create a Cypress spec for a UI component that has a story.",
|
|
||||||
"hidden": false,
|
|
||||||
"implementation": "/packages/react/src/generators/component-cypress-spec/component-cypress-spec#componentCypressGenerator.ts",
|
|
||||||
"aliases": [],
|
|
||||||
"path": "/packages/react/src/generators/component-cypress-spec/schema.json",
|
|
||||||
"type": "generator"
|
|
||||||
}
|
|
||||||
@ -17,16 +17,6 @@
|
|||||||
"x-prompt": "For which project do you want to generate stories?",
|
"x-prompt": "For which project do you want to generate stories?",
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"generateCypressSpecs": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Automatically generate `*.spec.ts` files in the cypress e2e app generated by the cypress-configure generator.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"cypressProject": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The Cypress project to generate the stories under. This is inferred from `project` by default.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"interactionTests": {
|
"interactionTests": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Set up Storybook interaction tests.",
|
"description": "Set up Storybook interaction tests.",
|
||||||
|
|||||||
@ -26,11 +26,6 @@
|
|||||||
"alias": ["configureTestRunner"],
|
"alias": ["configureTestRunner"],
|
||||||
"default": true
|
"default": true
|
||||||
},
|
},
|
||||||
"configureCypress": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Run the cypress-configure generator.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"generateStories": {
|
"generateStories": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Automatically generate `*.stories.ts` files for components declared in this project?",
|
"description": "Automatically generate `*.stories.ts` files for components declared in this project?",
|
||||||
@ -38,11 +33,6 @@
|
|||||||
"default": true,
|
"default": true,
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"generateCypressSpecs": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Automatically generate test files in the Cypress E2E app generated by the `cypress-configure` generator.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"configureStaticServe": {
|
"configureStaticServe": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Specifies whether to configure a static file server target for serving storybook. Helpful for speeding up CI build/test times.",
|
"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 @@
|
|||||||
"default": true,
|
"default": true,
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"cypressDirectory": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A directory where the Cypress project will be placed. Placed at the root by default.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"js": {
|
"js": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Generate JavaScript story files rather than TypeScript story files.",
|
"description": "Generate JavaScript story files rather than TypeScript story files.",
|
||||||
|
|||||||
@ -26,11 +26,6 @@
|
|||||||
"alias": ["configureTestRunner"],
|
"alias": ["configureTestRunner"],
|
||||||
"default": true
|
"default": true
|
||||||
},
|
},
|
||||||
"configureCypress": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Run the cypress-configure generator.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"generateStories": {
|
"generateStories": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Automatically generate `*.stories.ts` files for components declared in this project?",
|
"description": "Automatically generate `*.stories.ts` files for components declared in this project?",
|
||||||
@ -38,11 +33,6 @@
|
|||||||
"default": true,
|
"default": true,
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"generateCypressSpecs": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Automatically generate test files in the Cypress E2E app generated by the `cypress-configure` generator.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"configureStaticServe": {
|
"configureStaticServe": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Specifies whether to configure a static file server target for serving storybook. Helpful for speeding up CI build/test times.",
|
"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 @@
|
|||||||
"default": true,
|
"default": true,
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"cypressDirectory": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A directory where the Cypress project will be placed. Placed at the root by default.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"js": {
|
"js": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Generate JavaScript story files rather than TypeScript story files.",
|
"description": "Generate JavaScript story files rather than TypeScript story files.",
|
||||||
|
|||||||
@ -25,16 +25,6 @@
|
|||||||
"alias": ["configureTestRunner"],
|
"alias": ["configureTestRunner"],
|
||||||
"default": true
|
"default": true
|
||||||
},
|
},
|
||||||
"configureCypress": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Run the cypress-configure generator.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"cypressDirectory": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A directory where the Cypress project will be placed. Added at root by default.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"linter": {
|
"linter": {
|
||||||
"description": "The tool to use for running lint checks.",
|
"description": "The tool to use for running lint checks.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|||||||
@ -17,16 +17,6 @@
|
|||||||
"x-prompt": "For which project do you want to generate stories?",
|
"x-prompt": "For which project do you want to generate stories?",
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"generateCypressSpecs": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Automatically generate `*.spec.ts` files in the cypress e2e app generated by the cypress-configure generator.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"cypressProject": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The Cypress project to generate the stories under. This is inferred from `project` by default.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"interactionTests": {
|
"interactionTests": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Set up Storybook interaction tests.",
|
"description": "Set up Storybook interaction tests.",
|
||||||
|
|||||||
@ -347,7 +347,6 @@
|
|||||||
- [add-linting](/nx-api/angular/generators/add-linting)
|
- [add-linting](/nx-api/angular/generators/add-linting)
|
||||||
- [application](/nx-api/angular/generators/application)
|
- [application](/nx-api/angular/generators/application)
|
||||||
- [component](/nx-api/angular/generators/component)
|
- [component](/nx-api/angular/generators/component)
|
||||||
- [component-cypress-spec](/nx-api/angular/generators/component-cypress-spec)
|
|
||||||
- [component-story](/nx-api/angular/generators/component-story)
|
- [component-story](/nx-api/angular/generators/component-story)
|
||||||
- [component-test](/nx-api/angular/generators/component-test)
|
- [component-test](/nx-api/angular/generators/component-test)
|
||||||
- [convert-to-application-executor](/nx-api/angular/generators/convert-to-application-executor)
|
- [convert-to-application-executor](/nx-api/angular/generators/convert-to-application-executor)
|
||||||
@ -613,7 +612,6 @@
|
|||||||
- [storybook-configuration](/nx-api/react/generators/storybook-configuration)
|
- [storybook-configuration](/nx-api/react/generators/storybook-configuration)
|
||||||
- [component-story](/nx-api/react/generators/component-story)
|
- [component-story](/nx-api/react/generators/component-story)
|
||||||
- [stories](/nx-api/react/generators/stories)
|
- [stories](/nx-api/react/generators/stories)
|
||||||
- [component-cypress-spec](/nx-api/react/generators/component-cypress-spec)
|
|
||||||
- [hook](/nx-api/react/generators/hook)
|
- [hook](/nx-api/react/generators/hook)
|
||||||
- [host](/nx-api/react/generators/host)
|
- [host](/nx-api/react/generators/host)
|
||||||
- [remote](/nx-api/react/generators/remote)
|
- [remote](/nx-api/react/generators/remote)
|
||||||
|
|||||||
@ -15,10 +15,6 @@ const pages: Array<{ title: string; path: string }> = [
|
|||||||
title: '@nx/angular:component',
|
title: '@nx/angular:component',
|
||||||
path: '/packages/angular/generators/component',
|
path: '/packages/angular/generators/component',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: '@nx/angular:component-cypress-spec',
|
|
||||||
path: '/packages/angular/generators/component-cypress-spec',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: '@nx/angular:component-story',
|
title: '@nx/angular:component-story',
|
||||||
path: '/packages/angular/generators/component-story',
|
path: '/packages/angular/generators/component-story',
|
||||||
@ -298,10 +294,6 @@ const pages: Array<{ title: string; path: string }> = [
|
|||||||
title: '@nx/react:stories',
|
title: '@nx/react:stories',
|
||||||
path: '/packages/react/generators/stories',
|
path: '/packages/react/generators/stories',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: '@nx/react:component-cypress-spec',
|
|
||||||
path: '/packages/react/generators/component-cypress-spec',
|
|
||||||
},
|
|
||||||
{ title: '@nx/react:hook', path: '/packages/react/generators/hook' },
|
{ title: '@nx/react:hook', path: '/packages/react/generators/hook' },
|
||||||
{ title: '@nx/react:host', path: '/packages/react/generators/host' },
|
{ title: '@nx/react:host', path: '/packages/react/generators/host' },
|
||||||
{ title: '@nx/react:remote', path: '/packages/react/generators/remote' },
|
{ title: '@nx/react:remote', path: '/packages/react/generators/remote' },
|
||||||
|
|||||||
@ -22,12 +22,6 @@
|
|||||||
"aliases": ["c"],
|
"aliases": ["c"],
|
||||||
"description": "Generate an Angular Component."
|
"description": "Generate an Angular Component."
|
||||||
},
|
},
|
||||||
"component-cypress-spec": {
|
|
||||||
"factory": "./src/generators/component-cypress-spec/component-cypress-spec",
|
|
||||||
"schema": "./src/generators/component-cypress-spec/schema.json",
|
|
||||||
"description": "Creates a Cypress spec for a UI component that has a story.",
|
|
||||||
"hidden": true
|
|
||||||
},
|
|
||||||
"component-story": {
|
"component-story": {
|
||||||
"factory": "./src/generators/component-story/component-story",
|
"factory": "./src/generators/component-story/component-story",
|
||||||
"schema": "./src/generators/component-story/schema.json",
|
"schema": "./src/generators/component-story/schema.json",
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
export * from './src/generators/add-linting/add-linting';
|
export * from './src/generators/add-linting/add-linting';
|
||||||
export * from './src/generators/application/application';
|
export * from './src/generators/application/application';
|
||||||
export * from './src/generators/component-cypress-spec/component-cypress-spec';
|
|
||||||
export * from './src/generators/component-story/component-story';
|
export * from './src/generators/component-story/component-story';
|
||||||
export * from './src/generators/component/component';
|
export * from './src/generators/component/component';
|
||||||
export * from './src/generators/directive/directive';
|
export * from './src/generators/directive/directive';
|
||||||
|
|||||||
@ -1,31 +0,0 @@
|
|||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
||||||
|
|
||||||
exports[`componentCypressSpec generator should generate .spec.ts when using cypress.json 1`] = `
|
|
||||||
"describe('ng-app1', () => {
|
|
||||||
beforeEach(() =>
|
|
||||||
cy.visit(
|
|
||||||
'/iframe.html?id=testbuttoncomponent--primary&args=buttonType:button;style:default;age;isOn:false;'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
it('should render the component', () => {
|
|
||||||
cy.get('proj-test-button').should('exist');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
"
|
|
||||||
`;
|
|
||||||
|
|
||||||
exports[`componentCypressSpec generator should generate the component spec file 1`] = `
|
|
||||||
"describe('ng-app1', () => {
|
|
||||||
beforeEach(() =>
|
|
||||||
cy.visit(
|
|
||||||
'/iframe.html?id=testbuttoncomponent--primary&args=buttonType:button;style:default;age;isOn:false;'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
it('should render the component', () => {
|
|
||||||
cy.get('proj-test-button').should('exist');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
"
|
|
||||||
`;
|
|
||||||
@ -1,112 +0,0 @@
|
|||||||
import 'nx/src/internal-testing-utils/mock-project-graph';
|
|
||||||
|
|
||||||
import { installedCypressVersion } from '@nx/cypress/src/utils/cypress-version';
|
|
||||||
import type { Tree } from '@nx/devkit';
|
|
||||||
import * as devkit from '@nx/devkit';
|
|
||||||
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
|
||||||
import { componentGenerator } from '../component/component';
|
|
||||||
import * as storybookUtils from '../utils/storybook-ast/storybook-inputs';
|
|
||||||
import { generateTestApplication } from '../utils/testing';
|
|
||||||
import { componentCypressSpecGenerator } from './component-cypress-spec';
|
|
||||||
import { E2eTestRunner } from '../../utils/test-runners';
|
|
||||||
|
|
||||||
// need to mock cypress otherwise it'll use the nx installed version from package.json
|
|
||||||
// which is v9 while we are testing for the new v10 version
|
|
||||||
jest.mock('@nx/cypress/src/utils/cypress-version');
|
|
||||||
|
|
||||||
describe('componentCypressSpec generator', () => {
|
|
||||||
let tree: Tree;
|
|
||||||
const appName = 'ng-app1';
|
|
||||||
const specFile = `${appName}-e2e/src/e2e/test-button/test-button.component.cy.ts`;
|
|
||||||
let mockedInstalledCypressVersion: jest.Mock<
|
|
||||||
ReturnType<typeof installedCypressVersion>
|
|
||||||
> = installedCypressVersion as never;
|
|
||||||
beforeEach(async () => {
|
|
||||||
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
|
||||||
|
|
||||||
await generateTestApplication(tree, {
|
|
||||||
name: appName,
|
|
||||||
skipFormat: true,
|
|
||||||
e2eTestRunner: E2eTestRunner.Cypress,
|
|
||||||
});
|
|
||||||
await componentGenerator(tree, {
|
|
||||||
name: 'test-button',
|
|
||||||
directory: `${appName}/src/app/test-button`,
|
|
||||||
skipFormat: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
tree.write(
|
|
||||||
`${appName}/src/app/test-button/test-button.component.ts`,
|
|
||||||
`import { Component, Input } from '@angular/core';
|
|
||||||
|
|
||||||
export type ButtonStyle = 'default' | 'primary' | 'accent';
|
|
||||||
|
|
||||||
@Component({
|
|
||||||
selector: 'proj-test-button',
|
|
||||||
templateUrl: './test-button.component.html',
|
|
||||||
styleUrls: ['./test-button.component.css']
|
|
||||||
})
|
|
||||||
export class TestButtonComponent {
|
|
||||||
@Input('buttonType') type = 'button';
|
|
||||||
@Input() style: ButtonStyle = 'default';
|
|
||||||
@Input() age?: number;
|
|
||||||
@Input() isOn = false;
|
|
||||||
}`
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not generate the component spec file when it already exists', async () => {
|
|
||||||
mockedInstalledCypressVersion.mockReturnValue(10);
|
|
||||||
jest.spyOn(storybookUtils, 'getComponentProps');
|
|
||||||
jest.spyOn(devkit, 'generateFiles');
|
|
||||||
tree.write(specFile, '');
|
|
||||||
|
|
||||||
await componentCypressSpecGenerator(tree, {
|
|
||||||
componentFileName: 'test-button.component',
|
|
||||||
componentName: 'TestButtonComponent',
|
|
||||||
componentPath: `test-button`,
|
|
||||||
projectPath: `${appName}/src/app`,
|
|
||||||
projectName: appName,
|
|
||||||
skipFormat: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(storybookUtils.getComponentProps).not.toHaveBeenCalled();
|
|
||||||
expect(devkit.generateFiles).not.toHaveBeenCalled();
|
|
||||||
expect(tree.read(specFile).toString()).toBe('');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should generate the component spec file', async () => {
|
|
||||||
mockedInstalledCypressVersion.mockReturnValue(10);
|
|
||||||
await componentCypressSpecGenerator(tree, {
|
|
||||||
componentFileName: 'test-button.component',
|
|
||||||
componentName: 'TestButtonComponent',
|
|
||||||
componentPath: `test-button`,
|
|
||||||
projectPath: `${appName}/src/app`,
|
|
||||||
projectName: appName,
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(tree.exists(specFile)).toBe(true);
|
|
||||||
const specFileContent = tree.read(specFile).toString();
|
|
||||||
expect(specFileContent).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should generate .spec.ts when using cypress.json', async () => {
|
|
||||||
mockedInstalledCypressVersion.mockReturnValue(9);
|
|
||||||
const v9SpecFile = `${appName}-e2e/src/integration/test-button/test-button.component.spec.ts`;
|
|
||||||
tree.delete(`${appName}-e2e/cypress.config.ts`);
|
|
||||||
tree.write(`${appName}-e2e/cypress.json`, `{}`);
|
|
||||||
|
|
||||||
await componentCypressSpecGenerator(tree, {
|
|
||||||
componentFileName: 'test-button.component',
|
|
||||||
componentName: 'TestButtonComponent',
|
|
||||||
componentPath: `test-button`,
|
|
||||||
projectPath: `${appName}/src/app`,
|
|
||||||
projectName: appName,
|
|
||||||
skipFormat: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(tree.exists(v9SpecFile)).toBe(true);
|
|
||||||
const specFileContent = tree.read(v9SpecFile).toString();
|
|
||||||
expect(specFileContent).toMatchSnapshot();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -1,72 +0,0 @@
|
|||||||
import type { Tree } from '@nx/devkit';
|
|
||||||
import {
|
|
||||||
formatFiles,
|
|
||||||
generateFiles,
|
|
||||||
joinPathFragments,
|
|
||||||
readProjectConfiguration,
|
|
||||||
} from '@nx/devkit';
|
|
||||||
import { getComponentProps } from '../utils/storybook-ast/storybook-inputs';
|
|
||||||
import { getArgsDefaultValue } from './lib/get-args-default-value';
|
|
||||||
import { getComponentSelector } from './lib/get-component-selector';
|
|
||||||
import type { ComponentCypressSpecGeneratorOptions } from './schema';
|
|
||||||
|
|
||||||
export async function componentCypressSpecGenerator(
|
|
||||||
tree: Tree,
|
|
||||||
options: ComponentCypressSpecGeneratorOptions
|
|
||||||
): Promise<void> {
|
|
||||||
const {
|
|
||||||
cypressProject,
|
|
||||||
projectName,
|
|
||||||
projectPath,
|
|
||||||
componentPath,
|
|
||||||
componentFileName,
|
|
||||||
componentName,
|
|
||||||
specDirectory,
|
|
||||||
} = options;
|
|
||||||
const e2eProjectName = cypressProject || `${projectName}-e2e`;
|
|
||||||
const { sourceRoot, root } = readProjectConfiguration(tree, e2eProjectName);
|
|
||||||
const isCypressV10 = tree.exists(
|
|
||||||
joinPathFragments(root, 'cypress.config.ts')
|
|
||||||
);
|
|
||||||
const e2eLibIntegrationFolderPath = joinPathFragments(
|
|
||||||
sourceRoot,
|
|
||||||
isCypressV10 ? 'e2e' : 'integration'
|
|
||||||
);
|
|
||||||
|
|
||||||
const templatesDir = joinPathFragments(__dirname, 'files');
|
|
||||||
const destinationDir = joinPathFragments(
|
|
||||||
e2eLibIntegrationFolderPath,
|
|
||||||
specDirectory ?? componentPath
|
|
||||||
);
|
|
||||||
const storyFile = joinPathFragments(
|
|
||||||
destinationDir,
|
|
||||||
`${componentFileName}.${isCypressV10 ? 'cy' : 'spec'}.ts`
|
|
||||||
);
|
|
||||||
|
|
||||||
if (tree.exists(storyFile)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const fullComponentPath = joinPathFragments(
|
|
||||||
projectPath,
|
|
||||||
componentPath,
|
|
||||||
`${componentFileName}.ts`
|
|
||||||
);
|
|
||||||
const props = getComponentProps(tree, fullComponentPath, getArgsDefaultValue);
|
|
||||||
const componentSelector = getComponentSelector(tree, fullComponentPath);
|
|
||||||
|
|
||||||
generateFiles(tree, templatesDir, destinationDir, {
|
|
||||||
projectName,
|
|
||||||
componentFileName,
|
|
||||||
componentName,
|
|
||||||
componentSelector,
|
|
||||||
props,
|
|
||||||
fileExt: isCypressV10 ? 'cy.ts' : 'spec.ts',
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!options.skipFormat) {
|
|
||||||
await formatFiles(tree);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default componentCypressSpecGenerator;
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
describe('<%=projectName%>', () => {
|
|
||||||
beforeEach(() =>
|
|
||||||
cy.visit(
|
|
||||||
'/iframe.html?id=<%= componentName.toLowerCase() %>--primary<% if ( props && props.length > 0 ) { %>&args=<% } %><%
|
|
||||||
for(let prop of props) {
|
|
||||||
%><%=prop.name%><%
|
|
||||||
if(prop.defaultValue !== undefined && (prop.defaultValue || prop.defaultValue === false)) {
|
|
||||||
%>:<%=prop.defaultValue%><%
|
|
||||||
} %>;<%
|
|
||||||
}%>'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
it('should render the component', () => {
|
|
||||||
cy.get('<%=componentSelector%>').should('exist');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
import { ensureTypescript } from '@nx/js/src/utils/typescript/ensure-typescript';
|
|
||||||
import type { PropertyDeclaration } from 'typescript';
|
|
||||||
|
|
||||||
let tsModule: typeof import('typescript');
|
|
||||||
|
|
||||||
export function getArgsDefaultValue(
|
|
||||||
property: PropertyDeclaration
|
|
||||||
): string | undefined {
|
|
||||||
if (!property.initializer) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
if (!tsModule) {
|
|
||||||
tsModule = ensureTypescript();
|
|
||||||
}
|
|
||||||
switch (property.initializer.kind) {
|
|
||||||
case tsModule.SyntaxKind.StringLiteral:
|
|
||||||
const returnString = property.initializer.getText().slice(1, -1);
|
|
||||||
return returnString.replace(/\s/g, '+');
|
|
||||||
case tsModule.SyntaxKind.NumericLiteral:
|
|
||||||
case tsModule.SyntaxKind.TrueKeyword:
|
|
||||||
case tsModule.SyntaxKind.FalseKeyword:
|
|
||||||
return property.initializer.getText();
|
|
||||||
default:
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,38 +0,0 @@
|
|||||||
import type { Tree } from '@nx/devkit';
|
|
||||||
import { ensureTypescript } from '@nx/js/src/utils/typescript/ensure-typescript';
|
|
||||||
import { findNodes } from '@nx/js';
|
|
||||||
import type { PropertyAssignment } from 'typescript';
|
|
||||||
|
|
||||||
import {
|
|
||||||
getDecoratorMetadata,
|
|
||||||
getTsSourceFile,
|
|
||||||
} from '../../../utils/nx-devkit/ast-utils';
|
|
||||||
|
|
||||||
let tsModule: typeof import('typescript');
|
|
||||||
|
|
||||||
export function getComponentSelector(tree: Tree, path: string): string {
|
|
||||||
if (!tsModule) {
|
|
||||||
tsModule = ensureTypescript();
|
|
||||||
}
|
|
||||||
const file = getTsSourceFile(tree, path);
|
|
||||||
|
|
||||||
const componentDecorators = getDecoratorMetadata(
|
|
||||||
file,
|
|
||||||
'Component',
|
|
||||||
'@angular/core'
|
|
||||||
);
|
|
||||||
if (componentDecorators.length === 0) {
|
|
||||||
throw new Error(`No @Component decorator in ${path}.`);
|
|
||||||
}
|
|
||||||
const componentDecorator = componentDecorators[0];
|
|
||||||
const selectorNode = <PropertyAssignment>(
|
|
||||||
findNodes(componentDecorator, tsModule.SyntaxKind.PropertyAssignment).find(
|
|
||||||
(node: PropertyAssignment) => node.name.getText() === 'selector'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
if (!selectorNode) {
|
|
||||||
throw new Error(`No selector defined for the component in ${path}.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return selectorNode.initializer.getText().slice(1, -1);
|
|
||||||
}
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
export interface ComponentCypressSpecGeneratorOptions {
|
|
||||||
projectName: string;
|
|
||||||
projectPath: string;
|
|
||||||
componentName: string;
|
|
||||||
componentPath: string;
|
|
||||||
componentFileName: string;
|
|
||||||
cypressProject?: string;
|
|
||||||
specDirectory?: string;
|
|
||||||
skipFormat?: boolean;
|
|
||||||
}
|
|
||||||
@ -1,66 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://json-schema.org/schema",
|
|
||||||
"$id": "NxAngularComponentCypressSpecGenerator",
|
|
||||||
"type": "object",
|
|
||||||
"cli": "nx",
|
|
||||||
"description": "Creates a Storybook Cypress spec for a UI component that has a story.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20.",
|
|
||||||
"properties": {
|
|
||||||
"projectName": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The name of the project.",
|
|
||||||
"$default": {
|
|
||||||
"$source": "projectName"
|
|
||||||
},
|
|
||||||
"examples": ["ui-samples"],
|
|
||||||
"x-priority": "important"
|
|
||||||
},
|
|
||||||
"projectPath": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Path to the project.",
|
|
||||||
"examples": ["libs/ui-samples"],
|
|
||||||
"x-priority": "important"
|
|
||||||
},
|
|
||||||
"componentName": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Class name of the component.",
|
|
||||||
"examples": ["AwesomeComponent"],
|
|
||||||
"x-priority": "important"
|
|
||||||
},
|
|
||||||
"componentPath": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Relative path to the component file from the project root.",
|
|
||||||
"examples": ["awesome"],
|
|
||||||
"x-priority": "important"
|
|
||||||
},
|
|
||||||
"componentFileName": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Component file name without the `.ts` extension.",
|
|
||||||
"examples": ["awesome.component"],
|
|
||||||
"x-priority": "important"
|
|
||||||
},
|
|
||||||
"cypressProject": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The Cypress project to generate the stories under. By default, inferred from `projectName`."
|
|
||||||
},
|
|
||||||
"specDirectory": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Directory where to place the generated spec file. By default matches the value of the `componentPath` option."
|
|
||||||
},
|
|
||||||
"skipFormat": {
|
|
||||||
"description": "Skip formatting files.",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false,
|
|
||||||
"x-priority": "internal"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"additionalProperties": false,
|
|
||||||
"required": [
|
|
||||||
"projectName",
|
|
||||||
"projectPath",
|
|
||||||
"componentName",
|
|
||||||
"componentPath",
|
|
||||||
"componentFileName"
|
|
||||||
],
|
|
||||||
"examplesFile": "../../../docs/component-cypress-spec-examples.md"
|
|
||||||
}
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
import type { ProjectConfiguration, Tree } from '@nx/devkit';
|
|
||||||
import { readProjectConfiguration } from '@nx/devkit';
|
|
||||||
|
|
||||||
export function getE2EProject(
|
|
||||||
tree: Tree,
|
|
||||||
e2eProjectName: string
|
|
||||||
): ProjectConfiguration {
|
|
||||||
let e2eProject: ProjectConfiguration;
|
|
||||||
try {
|
|
||||||
e2eProject = readProjectConfiguration(tree, e2eProjectName);
|
|
||||||
} catch {
|
|
||||||
e2eProject = undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
return e2eProject;
|
|
||||||
}
|
|
||||||
@ -3,6 +3,4 @@ export interface StoriesGeneratorOptions {
|
|||||||
interactionTests?: boolean;
|
interactionTests?: boolean;
|
||||||
skipFormat?: boolean;
|
skipFormat?: boolean;
|
||||||
ignorePaths?: string[];
|
ignorePaths?: string[];
|
||||||
cypressProject?: string;
|
|
||||||
generateCypressSpecs?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,16 +25,6 @@
|
|||||||
"x-priority": "important",
|
"x-priority": "important",
|
||||||
"default": true
|
"default": true
|
||||||
},
|
},
|
||||||
"generateCypressSpecs": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Specifies whether to automatically generate `*.spec.ts` files in the Cypress e2e app generated by the `cypress-configure` generator.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"cypressProject": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The Cypress project to generate the stories under. This is inferred from `name` by default.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"skipFormat": {
|
"skipFormat": {
|
||||||
"description": "Skip formatting files.",
|
"description": "Skip formatting files.",
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import 'nx/src/internal-testing-utils/mock-project-graph';
|
import 'nx/src/internal-testing-utils/mock-project-graph';
|
||||||
|
|
||||||
import { installedCypressVersion } from '@nx/cypress/src/utils/cypress-version';
|
|
||||||
import type { Tree } from '@nx/devkit';
|
import type { Tree } from '@nx/devkit';
|
||||||
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
||||||
import { componentGenerator } from '../component/component';
|
import { componentGenerator } from '../component/component';
|
||||||
@ -9,21 +8,11 @@ import { generateTestApplication } from '../utils/testing';
|
|||||||
import { angularStoriesGenerator } from './stories';
|
import { angularStoriesGenerator } from './stories';
|
||||||
import { stripIndents } from '@nx/devkit';
|
import { stripIndents } from '@nx/devkit';
|
||||||
|
|
||||||
// need to mock cypress otherwise it'll use the nx installed version from package.json
|
|
||||||
// which is v9 while we are testing for the new v10 version
|
|
||||||
jest.mock('@nx/cypress/src/utils/cypress-version');
|
|
||||||
|
|
||||||
// TODO(katerina): Nx 19 -> remove Cypress
|
|
||||||
|
|
||||||
describe('angularStories generator: applications', () => {
|
describe('angularStories generator: applications', () => {
|
||||||
let tree: Tree;
|
let tree: Tree;
|
||||||
const appName = 'test-app';
|
const appName = 'test-app';
|
||||||
let mockedInstalledCypressVersion: jest.Mock<
|
|
||||||
ReturnType<typeof installedCypressVersion>
|
|
||||||
> = installedCypressVersion as never;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockedInstalledCypressVersion.mockReturnValue(10);
|
|
||||||
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
|
||||||
await generateTestApplication(tree, {
|
await generateTestApplication(tree, {
|
||||||
name: appName,
|
name: appName,
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import 'nx/src/internal-testing-utils/mock-project-graph';
|
import 'nx/src/internal-testing-utils/mock-project-graph';
|
||||||
|
|
||||||
import { installedCypressVersion } from '@nx/cypress/src/utils/cypress-version';
|
|
||||||
import { Tree } from '@nx/devkit';
|
import { Tree } from '@nx/devkit';
|
||||||
import { writeJson } from '@nx/devkit';
|
import { writeJson } from '@nx/devkit';
|
||||||
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
||||||
@ -13,20 +12,8 @@ import {
|
|||||||
} from '../utils/testing';
|
} from '../utils/testing';
|
||||||
import { angularStoriesGenerator } from './stories';
|
import { angularStoriesGenerator } from './stories';
|
||||||
|
|
||||||
// need to mock cypress otherwise it'll use the nx installed version from package.json
|
|
||||||
// which is v9 while we are testing for the new v10 version
|
|
||||||
jest.mock('@nx/cypress/src/utils/cypress-version');
|
|
||||||
// TODO(katerina): Nx 19 -> remove Cypress
|
|
||||||
|
|
||||||
describe('angularStories generator: libraries', () => {
|
describe('angularStories generator: libraries', () => {
|
||||||
const libName = 'test-ui-lib';
|
const libName = 'test-ui-lib';
|
||||||
let mockedInstalledCypressVersion: jest.Mock<
|
|
||||||
ReturnType<typeof installedCypressVersion>
|
|
||||||
> = installedCypressVersion as never;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
mockedInstalledCypressVersion.mockReturnValue(10);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('Stories for empty Angular library', () => {
|
describe('Stories for empty Angular library', () => {
|
||||||
let tree: Tree;
|
let tree: Tree;
|
||||||
|
|||||||
@ -4,12 +4,10 @@ import {
|
|||||||
formatFiles,
|
formatFiles,
|
||||||
GeneratorCallback,
|
GeneratorCallback,
|
||||||
joinPathFragments,
|
joinPathFragments,
|
||||||
logger,
|
|
||||||
readProjectConfiguration,
|
readProjectConfiguration,
|
||||||
runTasksInSerial,
|
runTasksInSerial,
|
||||||
Tree,
|
Tree,
|
||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import componentCypressSpecGenerator from '../component-cypress-spec/component-cypress-spec';
|
|
||||||
import componentStoryGenerator from '../component-story/component-story';
|
import componentStoryGenerator from '../component-story/component-story';
|
||||||
import type { ComponentInfo } from '../utils/storybook-ast/component-info';
|
import type { ComponentInfo } from '../utils/storybook-ast/component-info';
|
||||||
import {
|
import {
|
||||||
@ -17,7 +15,6 @@ import {
|
|||||||
getStandaloneComponentsInfo,
|
getStandaloneComponentsInfo,
|
||||||
} from '../utils/storybook-ast/component-info';
|
} from '../utils/storybook-ast/component-info';
|
||||||
import { getProjectEntryPoints } from '../utils/storybook-ast/entry-point';
|
import { getProjectEntryPoints } from '../utils/storybook-ast/entry-point';
|
||||||
import { getE2EProject } from './lib/get-e2e-project';
|
|
||||||
import { getModuleFilePaths } from '../utils/storybook-ast/module-info';
|
import { getModuleFilePaths } from '../utils/storybook-ast/module-info';
|
||||||
import type { StoriesGeneratorOptions } from './schema';
|
import type { StoriesGeneratorOptions } from './schema';
|
||||||
import { minimatch } from 'minimatch';
|
import { minimatch } from 'minimatch';
|
||||||
@ -27,8 +24,6 @@ export async function angularStoriesGenerator(
|
|||||||
tree: Tree,
|
tree: Tree,
|
||||||
options: StoriesGeneratorOptions
|
options: StoriesGeneratorOptions
|
||||||
): Promise<GeneratorCallback> {
|
): Promise<GeneratorCallback> {
|
||||||
const e2eProjectName = options.cypressProject ?? `${options.name}-e2e`;
|
|
||||||
const e2eProject = getE2EProject(tree, e2eProjectName);
|
|
||||||
const entryPoints = getProjectEntryPoints(tree, options.name);
|
const entryPoints = getProjectEntryPoints(tree, options.name);
|
||||||
const componentsInfo: ComponentInfo[] = [];
|
const componentsInfo: ComponentInfo[] = [];
|
||||||
for (const entryPoint of entryPoints) {
|
for (const entryPoint of entryPoints) {
|
||||||
@ -39,12 +34,6 @@ export async function angularStoriesGenerator(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.generateCypressSpecs && !e2eProject) {
|
|
||||||
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.`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const componentInfos = componentsInfo.filter(
|
const componentInfos = componentsInfo.filter(
|
||||||
(f) =>
|
(f) =>
|
||||||
!options.ignorePaths?.some((pattern) => {
|
!options.ignorePaths?.some((pattern) => {
|
||||||
@ -73,19 +62,6 @@ export async function angularStoriesGenerator(
|
|||||||
interactionTests: options.interactionTests ?? true,
|
interactionTests: options.interactionTests ?? true,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (options.generateCypressSpecs && e2eProject) {
|
|
||||||
await componentCypressSpecGenerator(tree, {
|
|
||||||
projectName: options.name,
|
|
||||||
projectPath: info.moduleFolderPath,
|
|
||||||
cypressProject: options.cypressProject,
|
|
||||||
componentName: info.name,
|
|
||||||
componentPath: info.path,
|
|
||||||
componentFileName: info.componentFileName,
|
|
||||||
specDirectory: joinPathFragments(info.entryPointName, info.path),
|
|
||||||
skipFormat: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
const tasks: GeneratorCallback[] = [];
|
const tasks: GeneratorCallback[] = [];
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import type { Tree } from '@nx/devkit';
|
import type { Tree } from '@nx/devkit';
|
||||||
import { ensurePackage, readProjectConfiguration } from '@nx/devkit';
|
import { readProjectConfiguration } from '@nx/devkit';
|
||||||
import { nxVersion } from '../../../utils/versions';
|
|
||||||
import { angularStoriesGenerator } from '../../stories/stories';
|
import { angularStoriesGenerator } from '../../stories/stories';
|
||||||
import type { StorybookConfigurationOptions } from '../schema';
|
import type { StorybookConfigurationOptions } from '../schema';
|
||||||
|
|
||||||
@ -9,21 +8,9 @@ export async function generateStories(
|
|||||||
options: StorybookConfigurationOptions
|
options: StorybookConfigurationOptions
|
||||||
) {
|
) {
|
||||||
const project = readProjectConfiguration(tree, options.project);
|
const project = readProjectConfiguration(tree, options.project);
|
||||||
ensurePackage('@nx/cypress', nxVersion);
|
|
||||||
const { getE2eProjectName } = <
|
|
||||||
typeof import('@nx/cypress/src/utils/project-name')
|
|
||||||
>require('@nx/cypress/src/utils/project-name');
|
|
||||||
const e2eProjectName = getE2eProjectName(
|
|
||||||
options.project,
|
|
||||||
project.root,
|
|
||||||
options.cypressDirectory
|
|
||||||
);
|
|
||||||
|
|
||||||
await angularStoriesGenerator(tree, {
|
await angularStoriesGenerator(tree, {
|
||||||
name: options.project,
|
name: options.project,
|
||||||
generateCypressSpecs:
|
|
||||||
options.configureCypress && options.generateCypressSpecs,
|
|
||||||
cypressProject: e2eProjectName,
|
|
||||||
ignorePaths: options.ignorePaths,
|
ignorePaths: options.ignorePaths,
|
||||||
interactionTests: options.interactionTests,
|
interactionTests: options.interactionTests,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
|
|||||||
@ -12,9 +12,7 @@ export async function generateStorybookConfiguration(
|
|||||||
return await configurationGenerator(tree, {
|
return await configurationGenerator(tree, {
|
||||||
project: options.project,
|
project: options.project,
|
||||||
uiFramework: '@storybook/angular',
|
uiFramework: '@storybook/angular',
|
||||||
configureCypress: options.configureCypress,
|
|
||||||
linter: options.linter,
|
linter: options.linter,
|
||||||
cypressDirectory: options.cypressDirectory,
|
|
||||||
tsConfiguration: options.tsConfiguration,
|
tsConfiguration: options.tsConfiguration,
|
||||||
interactionTests: options.interactionTests,
|
interactionTests: options.interactionTests,
|
||||||
configureStaticServe: options.configureStaticServe,
|
configureStaticServe: options.configureStaticServe,
|
||||||
|
|||||||
@ -1,9 +0,0 @@
|
|||||||
import type { StorybookConfigurationOptions } from '../schema';
|
|
||||||
|
|
||||||
export function validateOptions(options: StorybookConfigurationOptions): void {
|
|
||||||
if (options.generateCypressSpecs && !options.generateStories) {
|
|
||||||
throw new Error(
|
|
||||||
'Cannot set generateCypressSpecs to true when generateStories is set to false.'
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -9,7 +9,4 @@ export interface StorybookConfigurationOptions {
|
|||||||
skipFormat?: boolean;
|
skipFormat?: boolean;
|
||||||
ignorePaths?: string[];
|
ignorePaths?: string[];
|
||||||
interactionTests?: boolean;
|
interactionTests?: boolean;
|
||||||
configureCypress?: boolean;
|
|
||||||
generateCypressSpecs?: boolean;
|
|
||||||
cypressDirectory?: string;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,11 +26,6 @@
|
|||||||
"x-priority": "important",
|
"x-priority": "important",
|
||||||
"default": true
|
"default": true
|
||||||
},
|
},
|
||||||
"configureCypress": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Specifies whether to configure Cypress or not.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"generateStories": {
|
"generateStories": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Specifies whether to automatically generate `*.stories.ts` files for components declared in this project or not.",
|
"description": "Specifies whether to automatically generate `*.stories.ts` files for components declared in this project or not.",
|
||||||
@ -38,11 +33,6 @@
|
|||||||
"default": true,
|
"default": true,
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"generateCypressSpecs": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Specifies whether to automatically generate test files in the generated Cypress e2e app.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"configureStaticServe": {
|
"configureStaticServe": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Specifies whether to configure a static file server target for serving storybook. Helpful for speeding up CI build/test times.",
|
"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 @@
|
|||||||
"default": true,
|
"default": true,
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"cypressDirectory": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A directory where the Cypress project will be placed. Placed at the root by default.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"linter": {
|
"linter": {
|
||||||
"description": "The tool to use for running lint checks.",
|
"description": "The tool to use for running lint checks.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|||||||
@ -1,4 +1,3 @@
|
|||||||
import { installedCypressVersion } from '@nx/cypress/src/utils/cypress-version';
|
|
||||||
import type { Tree } from '@nx/devkit';
|
import type { Tree } from '@nx/devkit';
|
||||||
import { readJson, writeJson } from '@nx/devkit';
|
import { readJson, writeJson } from '@nx/devkit';
|
||||||
import { Linter } from '@nx/eslint/src/generators/utils/linter';
|
import { Linter } from '@nx/eslint/src/generators/utils/linter';
|
||||||
@ -11,10 +10,7 @@ import {
|
|||||||
import type { StorybookConfigurationOptions } from './schema';
|
import type { StorybookConfigurationOptions } from './schema';
|
||||||
import { storybookConfigurationGenerator } from './storybook-configuration';
|
import { storybookConfigurationGenerator } from './storybook-configuration';
|
||||||
|
|
||||||
// need to mock cypress otherwise it'll use the nx installed version from package.json
|
// nested code imports graph from the repo, which might have inaccurate graph version
|
||||||
// which is v9 while we are testing for the new v10 version
|
|
||||||
jest.mock('@nx/cypress/src/utils/cypress-version');
|
|
||||||
// nested code imports graph from the repo, which might have innacurate graph version
|
|
||||||
jest.mock('nx/src/project-graph/project-graph', () => ({
|
jest.mock('nx/src/project-graph/project-graph', () => ({
|
||||||
...jest.requireActual<any>('nx/src/project-graph/project-graph'),
|
...jest.requireActual<any>('nx/src/project-graph/project-graph'),
|
||||||
createProjectGraphAsync: jest
|
createProjectGraphAsync: jest
|
||||||
@ -36,12 +32,8 @@ function listFiles(tree: Tree): string[] {
|
|||||||
describe('StorybookConfiguration generator', () => {
|
describe('StorybookConfiguration generator', () => {
|
||||||
let tree: Tree;
|
let tree: Tree;
|
||||||
const libName = 'test-ui-lib';
|
const libName = 'test-ui-lib';
|
||||||
let mockedInstalledCypressVersion: jest.Mock<
|
|
||||||
ReturnType<typeof installedCypressVersion>
|
|
||||||
> = installedCypressVersion as never;
|
|
||||||
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockedInstalledCypressVersion.mockReturnValue(10);
|
|
||||||
tree = await createStorybookTestWorkspaceForLib(libName);
|
tree = await createStorybookTestWorkspaceForLib(libName);
|
||||||
|
|
||||||
jest.resetModules();
|
jest.resetModules();
|
||||||
|
|||||||
@ -8,16 +8,13 @@ import { updateAppEditorTsConfigExcludedFiles } from '../utils/update-app-editor
|
|||||||
import { assertCompatibleStorybookVersion } from './lib/assert-compatible-storybook-version';
|
import { assertCompatibleStorybookVersion } from './lib/assert-compatible-storybook-version';
|
||||||
import { generateStories } from './lib/generate-stories';
|
import { generateStories } from './lib/generate-stories';
|
||||||
import { generateStorybookConfiguration } from './lib/generate-storybook-configuration';
|
import { generateStorybookConfiguration } from './lib/generate-storybook-configuration';
|
||||||
import { validateOptions } from './lib/validate-options';
|
|
||||||
import type { StorybookConfigurationOptions } from './schema';
|
import type { StorybookConfigurationOptions } from './schema';
|
||||||
|
|
||||||
// TODO(katerina): Nx 19 -> remove Cypress
|
|
||||||
export async function storybookConfigurationGenerator(
|
export async function storybookConfigurationGenerator(
|
||||||
tree: Tree,
|
tree: Tree,
|
||||||
options: StorybookConfigurationOptions
|
options: StorybookConfigurationOptions
|
||||||
): Promise<GeneratorCallback> {
|
): Promise<GeneratorCallback> {
|
||||||
assertCompatibleStorybookVersion();
|
assertCompatibleStorybookVersion();
|
||||||
validateOptions(options);
|
|
||||||
|
|
||||||
const storybookGeneratorInstallTask = await generateStorybookConfiguration(
|
const storybookGeneratorInstallTask = await generateStorybookConfiguration(
|
||||||
tree,
|
tree,
|
||||||
|
|||||||
@ -54,12 +54,6 @@
|
|||||||
"description": "Create stories/specs for all components declared in an app or library.",
|
"description": "Create stories/specs for all components declared in an app or library.",
|
||||||
"hidden": false
|
"hidden": false
|
||||||
},
|
},
|
||||||
"component-cypress-spec": {
|
|
||||||
"factory": "./src/generators/component-cypress-spec/component-cypress-spec#componentCypressGenerator",
|
|
||||||
"schema": "./src/generators/component-cypress-spec/schema.json",
|
|
||||||
"description": "Create a Cypress spec for a UI component that has a story.",
|
|
||||||
"hidden": false
|
|
||||||
},
|
|
||||||
"hook": {
|
"hook": {
|
||||||
"factory": "./src/generators/hook/hook",
|
"factory": "./src/generators/hook/hook",
|
||||||
"schema": "./src/generators/hook/schema.json",
|
"schema": "./src/generators/hook/schema.json",
|
||||||
|
|||||||
@ -14,7 +14,6 @@ export { reactDomVersion, reactVersion } from './src/utils/versions';
|
|||||||
export { applicationGenerator } from './src/generators/application/application';
|
export { applicationGenerator } from './src/generators/application/application';
|
||||||
export { componentGenerator } from './src/generators/component/component';
|
export { componentGenerator } from './src/generators/component/component';
|
||||||
export { hookGenerator } from './src/generators/hook/hook';
|
export { hookGenerator } from './src/generators/hook/hook';
|
||||||
export { componentCypressGenerator } from './src/generators/component-cypress-spec/component-cypress-spec';
|
|
||||||
export { componentStoryGenerator } from './src/generators/component-story/component-story';
|
export { componentStoryGenerator } from './src/generators/component-story/component-story';
|
||||||
export { libraryGenerator } from './src/generators/library/library';
|
export { libraryGenerator } from './src/generators/library/library';
|
||||||
export { reactInitGenerator } from './src/generators/init/init';
|
export { reactInitGenerator } from './src/generators/init/init';
|
||||||
|
|||||||
@ -1,235 +0,0 @@
|
|||||||
import 'nx/src/internal-testing-utils/mock-project-graph';
|
|
||||||
|
|
||||||
import { Tree } from '@nx/devkit';
|
|
||||||
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
|
||||||
import { Linter } from '@nx/eslint';
|
|
||||||
import { formatFile } from '../../utils/format-file';
|
|
||||||
import applicationGenerator from '../application/application';
|
|
||||||
import libraryGenerator from '../library/library';
|
|
||||||
import componentCypressSpecGenerator from './component-cypress-spec';
|
|
||||||
|
|
||||||
describe('react:component-cypress-spec', () => {
|
|
||||||
let appTree: Tree;
|
|
||||||
|
|
||||||
[
|
|
||||||
{
|
|
||||||
plainJS: false,
|
|
||||||
testCmpSrcWithProps: `import React from 'react';
|
|
||||||
|
|
||||||
import './test.scss';
|
|
||||||
|
|
||||||
export interface TestProps {
|
|
||||||
name: string;
|
|
||||||
displayAge: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const Test = (props: TestProps) => {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<h1>Welcome to test component, {props.name}</h1>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Test;
|
|
||||||
`,
|
|
||||||
testCmpSrcWithoutProps: `import React from 'react';
|
|
||||||
|
|
||||||
import './test.scss';
|
|
||||||
|
|
||||||
export const Test = () => {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<h1>Welcome to test component</h1>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Test;
|
|
||||||
`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
plainJS: true,
|
|
||||||
testCmpSrcWithProps: `import React from 'react';
|
|
||||||
|
|
||||||
import './test.scss';
|
|
||||||
export const Test = (props: TestProps) => {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<h1>Welcome to test component, {props.name}</h1>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Test;
|
|
||||||
`,
|
|
||||||
testCmpSrcWithoutProps: `import React from 'react';
|
|
||||||
import './test.scss';
|
|
||||||
export const Test = () => {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<h1>Welcome to test component</h1>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Test;
|
|
||||||
`,
|
|
||||||
},
|
|
||||||
].forEach((testConfig) => {
|
|
||||||
let fileCmpExt = testConfig.plainJS ? 'js' : 'tsx';
|
|
||||||
let fileExt = testConfig.plainJS ? 'js' : 'ts';
|
|
||||||
|
|
||||||
describe(`using ${
|
|
||||||
testConfig.plainJS ? 'plain JS' : 'TypeScript'
|
|
||||||
} setup`, () => {
|
|
||||||
let cmpPath = `test-ui-lib/src/lib/test-ui-lib.${fileCmpExt}`;
|
|
||||||
let cypressStorySpecFilePath = `test-ui-lib-e2e/src/integration/test-ui-lib/test-ui-lib.spec.${fileExt}`;
|
|
||||||
|
|
||||||
if (!testConfig.plainJS) {
|
|
||||||
// hacky, but we should do this check only if we run with TypeScript,
|
|
||||||
// detecting component props in plain JS is "not possible"
|
|
||||||
describe('component with properties', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
appTree = await createTestUILib('test-ui-lib', testConfig.plainJS);
|
|
||||||
|
|
||||||
appTree.write(cmpPath, testConfig.testCmpSrcWithProps);
|
|
||||||
|
|
||||||
await componentCypressSpecGenerator(appTree, {
|
|
||||||
componentPath: `lib/test-ui-lib.${fileCmpExt}`,
|
|
||||||
project: 'test-ui-lib',
|
|
||||||
js: testConfig.plainJS,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should properly set up the spec', () => {
|
|
||||||
expect(
|
|
||||||
formatFile`${appTree.read(cypressStorySpecFilePath, 'utf-8')}`
|
|
||||||
)
|
|
||||||
.toContain(formatFile`describe('test-ui-lib: Test component', () => {
|
|
||||||
beforeEach(() => cy.visit('/iframe.html?id=test--primary&args=name;displayAge:false;'));
|
|
||||||
|
|
||||||
it('should render the component', () => {
|
|
||||||
cy.get('h1').should('contain', 'Welcome to Test!');
|
|
||||||
});
|
|
||||||
})
|
|
||||||
`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
describe('component without properties', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
appTree = await createTestUILib('test-ui-lib', testConfig.plainJS);
|
|
||||||
|
|
||||||
appTree.write(cmpPath, testConfig.testCmpSrcWithoutProps);
|
|
||||||
|
|
||||||
await componentCypressSpecGenerator(appTree, {
|
|
||||||
componentPath: `lib/test-ui-lib.${fileCmpExt}`,
|
|
||||||
project: 'test-ui-lib',
|
|
||||||
js: testConfig.plainJS,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should properly set up the spec', () => {
|
|
||||||
expect(formatFile`${appTree.read(cypressStorySpecFilePath, 'utf-8')}`)
|
|
||||||
.toContain(formatFile`describe('test-ui-lib: Test component', () => {
|
|
||||||
beforeEach(() => cy.visit('/iframe.html?id=test--primary'));
|
|
||||||
|
|
||||||
it('should render the component', () => {
|
|
||||||
cy.get('h1').should('contain', 'Welcome to Test!');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
`);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should target the correct cypress suite', async () => {
|
|
||||||
appTree = await createTestUILib('test-ui-lib');
|
|
||||||
await applicationGenerator(appTree, {
|
|
||||||
e2eTestRunner: 'none',
|
|
||||||
linter: Linter.EsLint,
|
|
||||||
name: `other-e2e`,
|
|
||||||
skipFormat: true,
|
|
||||||
style: 'css',
|
|
||||||
unitTestRunner: 'none',
|
|
||||||
});
|
|
||||||
// since other-e2e isn't a real cypress project we mock the v10 cypress config
|
|
||||||
appTree.write('other-e2e/cypress.config.ts', `export default {}`);
|
|
||||||
await componentCypressSpecGenerator(appTree, {
|
|
||||||
componentPath: `lib/test-ui-lib.tsx`,
|
|
||||||
project: 'test-ui-lib',
|
|
||||||
cypressProject: 'other-e2e',
|
|
||||||
});
|
|
||||||
expect(
|
|
||||||
appTree.exists('other-e2e/src/e2e/test-ui-lib/test-ui-lib.cy.ts')
|
|
||||||
).toBeTruthy();
|
|
||||||
expect(
|
|
||||||
appTree.exists('test-ui-lib/src/e2e/test-ui-lib/test-ui-lib.cy.ts')
|
|
||||||
).toBeFalsy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should generate a .spec.ts file with cypress.json', async () => {
|
|
||||||
appTree = await createTestUILib('test-ui-lib');
|
|
||||||
await applicationGenerator(appTree, {
|
|
||||||
e2eTestRunner: 'none',
|
|
||||||
linter: Linter.EsLint,
|
|
||||||
name: `other-e2e`,
|
|
||||||
skipFormat: true,
|
|
||||||
style: 'css',
|
|
||||||
unitTestRunner: 'none',
|
|
||||||
});
|
|
||||||
appTree.delete(`other-e2e/cypress.config.ts`);
|
|
||||||
appTree.write(`other-e2e/cypress.json`, '{}');
|
|
||||||
await componentCypressSpecGenerator(appTree, {
|
|
||||||
componentPath: `lib/test-ui-lib.tsx`,
|
|
||||||
project: 'test-ui-lib',
|
|
||||||
cypressProject: 'other-e2e',
|
|
||||||
});
|
|
||||||
expect(
|
|
||||||
appTree.exists(
|
|
||||||
'other-e2e/src/integration/test-ui-lib/test-ui-lib.spec.ts'
|
|
||||||
)
|
|
||||||
).toBeTruthy();
|
|
||||||
expect(
|
|
||||||
appTree.exists(
|
|
||||||
'test-ui-lib/src/integration/test-ui-lib/test-ui-lib.spec.ts'
|
|
||||||
)
|
|
||||||
).toBeFalsy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
export async function createTestUILib(
|
|
||||||
libName: string,
|
|
||||||
plainJS = false
|
|
||||||
): Promise<Tree> {
|
|
||||||
let appTree = createTreeWithEmptyWorkspace();
|
|
||||||
await libraryGenerator(appTree, {
|
|
||||||
name: libName,
|
|
||||||
linter: Linter.EsLint,
|
|
||||||
js: plainJS,
|
|
||||||
component: true,
|
|
||||||
skipFormat: true,
|
|
||||||
skipTsConfig: false,
|
|
||||||
style: 'css',
|
|
||||||
unitTestRunner: 'jest',
|
|
||||||
projectNameAndRootFormat: 'as-provided',
|
|
||||||
});
|
|
||||||
|
|
||||||
// create some Nx app that we'll use to generate the cypress
|
|
||||||
// spec into it. We don't need a real Cypress setup
|
|
||||||
await applicationGenerator(appTree, {
|
|
||||||
js: plainJS,
|
|
||||||
e2eTestRunner: 'none',
|
|
||||||
linter: Linter.EsLint,
|
|
||||||
name: `${libName}-e2e`,
|
|
||||||
skipFormat: true,
|
|
||||||
style: 'css',
|
|
||||||
unitTestRunner: 'none',
|
|
||||||
projectNameAndRootFormat: 'as-provided',
|
|
||||||
});
|
|
||||||
|
|
||||||
return appTree;
|
|
||||||
}
|
|
||||||
@ -1,184 +0,0 @@
|
|||||||
import {
|
|
||||||
formatFiles,
|
|
||||||
generateFiles,
|
|
||||||
getProjects,
|
|
||||||
joinPathFragments,
|
|
||||||
Tree,
|
|
||||||
} from '@nx/devkit';
|
|
||||||
import { basename, join } from 'path';
|
|
||||||
import type * as ts from 'typescript';
|
|
||||||
import {
|
|
||||||
findExportDeclarationsForJsx,
|
|
||||||
getComponentNode,
|
|
||||||
parseComponentPropsInfo,
|
|
||||||
} from '../../utils/ast-utils';
|
|
||||||
import { ensureTypescript } from '@nx/js/src/utils/typescript/ensure-typescript';
|
|
||||||
|
|
||||||
let tsModule: typeof import('typescript');
|
|
||||||
|
|
||||||
export interface CreateComponentSpecFileSchema {
|
|
||||||
project: string;
|
|
||||||
componentPath: string;
|
|
||||||
js?: boolean;
|
|
||||||
cypressProject?: string;
|
|
||||||
skipFormat?: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function componentCypressGenerator(
|
|
||||||
host: Tree,
|
|
||||||
schema: CreateComponentSpecFileSchema
|
|
||||||
) {
|
|
||||||
createComponentSpecFile(host, schema);
|
|
||||||
|
|
||||||
if (!schema.skipFormat) {
|
|
||||||
await formatFiles(host);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: candidate to refactor with the angular component story
|
|
||||||
export function getArgsDefaultValue(property: ts.SyntaxKind): string {
|
|
||||||
if (!tsModule) {
|
|
||||||
tsModule = ensureTypescript();
|
|
||||||
}
|
|
||||||
const typeNameToDefault: Record<number, any> = {
|
|
||||||
[tsModule.SyntaxKind.StringKeyword]: '',
|
|
||||||
[tsModule.SyntaxKind.NumberKeyword]: 0,
|
|
||||||
[tsModule.SyntaxKind.BooleanKeyword]: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
const resolvedValue = typeNameToDefault[property];
|
|
||||||
if (resolvedValue === undefined) {
|
|
||||||
return '';
|
|
||||||
} else if (typeof resolvedValue === 'string') {
|
|
||||||
return resolvedValue.replace(/\s/g, '+');
|
|
||||||
} else {
|
|
||||||
return resolvedValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createComponentSpecFile(
|
|
||||||
tree: Tree,
|
|
||||||
{ project, componentPath, js, cypressProject }: CreateComponentSpecFileSchema
|
|
||||||
) {
|
|
||||||
if (!tsModule) {
|
|
||||||
tsModule = ensureTypescript();
|
|
||||||
}
|
|
||||||
const e2eProjectName = cypressProject || `${project}-e2e`;
|
|
||||||
const projects = getProjects(tree);
|
|
||||||
const e2eProject = projects.get(e2eProjectName);
|
|
||||||
// cypress >= v10 will have a cypress.config.ts < v10 will have a cypress.json
|
|
||||||
const isCypressV10 = tree.exists(join(e2eProject.root, 'cypress.config.ts'));
|
|
||||||
|
|
||||||
const e2eLibIntegrationFolderPath = join(
|
|
||||||
e2eProject.sourceRoot,
|
|
||||||
isCypressV10 ? 'e2e' : 'integration'
|
|
||||||
);
|
|
||||||
|
|
||||||
const proj = projects.get(project);
|
|
||||||
const componentFilePath = joinPathFragments(proj.sourceRoot, componentPath);
|
|
||||||
const componentName = componentFilePath
|
|
||||||
.slice(componentFilePath.lastIndexOf('/') + 1)
|
|
||||||
.replace('.tsx', '')
|
|
||||||
.replace('.jsx', '')
|
|
||||||
.replace('.js', '');
|
|
||||||
|
|
||||||
const contents = tree.read(componentFilePath, 'utf-8');
|
|
||||||
if (contents === null) {
|
|
||||||
throw new Error(`Failed to read ${componentFilePath}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const sourceFile = tsModule.createSourceFile(
|
|
||||||
componentFilePath,
|
|
||||||
contents,
|
|
||||||
tsModule.ScriptTarget.Latest,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
const cmpDeclaration = getComponentNode(sourceFile);
|
|
||||||
if (!cmpDeclaration) {
|
|
||||||
const componentNodes = findExportDeclarationsForJsx(sourceFile);
|
|
||||||
if (componentNodes?.length) {
|
|
||||||
componentNodes.forEach((declaration) => {
|
|
||||||
findPropsAndGenerateFileForCypress(
|
|
||||||
tree,
|
|
||||||
sourceFile,
|
|
||||||
declaration,
|
|
||||||
e2eLibIntegrationFolderPath,
|
|
||||||
componentName,
|
|
||||||
project,
|
|
||||||
js,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
throw new Error(
|
|
||||||
`Could not find any React component in file ${componentFilePath}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
findPropsAndGenerateFileForCypress(
|
|
||||||
tree,
|
|
||||||
sourceFile,
|
|
||||||
cmpDeclaration,
|
|
||||||
e2eLibIntegrationFolderPath,
|
|
||||||
componentName,
|
|
||||||
project,
|
|
||||||
js
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function findPropsAndGenerateFileForCypress(
|
|
||||||
tree: Tree,
|
|
||||||
sourceFile: ts.SourceFile,
|
|
||||||
cmpDeclaration: ts.Node,
|
|
||||||
e2eLibIntegrationFolderPath: string,
|
|
||||||
componentName: string,
|
|
||||||
project: string,
|
|
||||||
js: boolean,
|
|
||||||
fromNodeArray?: boolean
|
|
||||||
) {
|
|
||||||
const info = parseComponentPropsInfo(sourceFile, cmpDeclaration);
|
|
||||||
|
|
||||||
let props: {
|
|
||||||
name: string;
|
|
||||||
defaultValue: any;
|
|
||||||
}[] = [];
|
|
||||||
|
|
||||||
if (info) {
|
|
||||||
if (!tsModule) {
|
|
||||||
tsModule = ensureTypescript();
|
|
||||||
}
|
|
||||||
|
|
||||||
props = info.props.map((member) => {
|
|
||||||
return {
|
|
||||||
name: (member.name as ts.Identifier).text,
|
|
||||||
defaultValue: tsModule.isBindingElement(member)
|
|
||||||
? getArgsDefaultValue(member.kind)
|
|
||||||
: getArgsDefaultValue(member.type.kind),
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const isCypressV10 = basename(e2eLibIntegrationFolderPath) === 'e2e';
|
|
||||||
const cyFilePrefix = isCypressV10 ? 'cy' : 'spec';
|
|
||||||
|
|
||||||
generateFiles(
|
|
||||||
tree,
|
|
||||||
joinPathFragments(__dirname, './files'),
|
|
||||||
`${e2eLibIntegrationFolderPath}/${
|
|
||||||
fromNodeArray
|
|
||||||
? componentName + '--' + (cmpDeclaration as any).name.text
|
|
||||||
: componentName
|
|
||||||
}`,
|
|
||||||
{
|
|
||||||
projectName: project,
|
|
||||||
componentName,
|
|
||||||
componentSelector: (cmpDeclaration as any).name.text,
|
|
||||||
props,
|
|
||||||
fileExt: js ? `${cyFilePrefix}.js` : `${cyFilePrefix}.ts`,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default componentCypressGenerator;
|
|
||||||
@ -1,13 +0,0 @@
|
|||||||
describe('<%=projectName%>: <%= componentSelector %> component', () => {
|
|
||||||
beforeEach(() => cy.visit('/iframe.html?id=<%= componentSelector.toLowerCase() %>--primary<% if ( props && props.length > 0 ) { %>&args=<% } %><%
|
|
||||||
for(let prop of props) {
|
|
||||||
%><%=prop.name%><%
|
|
||||||
if(prop.defaultValue !== undefined && (prop.defaultValue || prop.defaultValue === false)) {
|
|
||||||
%>:<%=prop.defaultValue%><%
|
|
||||||
} %>;<%
|
|
||||||
}%>'));
|
|
||||||
|
|
||||||
it('should render the component', () => {
|
|
||||||
cy.get('h1').should('contain', 'Welcome to <%=componentSelector%>!');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@ -1,45 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://json-schema.org/schema",
|
|
||||||
"cli": "nx",
|
|
||||||
"$id": "NxReactComponentCypressSpec",
|
|
||||||
"title": "Create component Cypress spec",
|
|
||||||
"description": "Create a Storybook Cypress spec for a UI component that has a story.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20.",
|
|
||||||
"type": "object",
|
|
||||||
"properties": {
|
|
||||||
"project": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The project name for which to generate tests.",
|
|
||||||
"examples": ["shared-ui-component"],
|
|
||||||
"$default": {
|
|
||||||
"$source": "projectName",
|
|
||||||
"index": 0
|
|
||||||
},
|
|
||||||
"x-prompt": "What's name of the project for which to generate tests?",
|
|
||||||
"x-priority": "important"
|
|
||||||
},
|
|
||||||
"componentPath": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "Relative path to the component file from the library root?",
|
|
||||||
"examples": ["lib/components"],
|
|
||||||
"x-prompt": "What's path of the component relative to the project's lib root for which to generate a test?",
|
|
||||||
"x-priority": "important"
|
|
||||||
},
|
|
||||||
"js": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Generate JavaScript files rather than TypeScript files.",
|
|
||||||
"default": false
|
|
||||||
},
|
|
||||||
"cypressProject": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The Cypress project to generate the stories under. By default, inferred from `project`."
|
|
||||||
},
|
|
||||||
"skipFormat": {
|
|
||||||
"description": "Skip formatting files.",
|
|
||||||
"type": "boolean",
|
|
||||||
"default": false,
|
|
||||||
"x-priority": "internal"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": ["project", "componentPath"]
|
|
||||||
}
|
|
||||||
@ -17,16 +17,6 @@
|
|||||||
"x-prompt": "For which project do you want to generate stories?",
|
"x-prompt": "For which project do you want to generate stories?",
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"generateCypressSpecs": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Automatically generate `*.spec.ts` files in the cypress e2e app generated by the cypress-configure generator.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"cypressProject": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The Cypress project to generate the stories under. This is inferred from `project` by default.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"interactionTests": {
|
"interactionTests": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Set up Storybook interaction tests.",
|
"description": "Set up Storybook interaction tests.",
|
||||||
|
|||||||
@ -1,21 +1,15 @@
|
|||||||
import 'nx/src/internal-testing-utils/mock-project-graph';
|
import 'nx/src/internal-testing-utils/mock-project-graph';
|
||||||
|
|
||||||
import { installedCypressVersion } from '@nx/cypress/src/utils/cypress-version';
|
|
||||||
import { Tree } from '@nx/devkit';
|
import { Tree } from '@nx/devkit';
|
||||||
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
||||||
import { Linter } from '@nx/eslint';
|
import { Linter } from '@nx/eslint';
|
||||||
import applicationGenerator from '../application/application';
|
import applicationGenerator from '../application/application';
|
||||||
import storiesGenerator from './stories';
|
import storiesGenerator from './stories';
|
||||||
// need to mock cypress otherwise it'll use the nx installed version from package.json
|
|
||||||
// which is v9 while we are testing for the new v10 version
|
|
||||||
jest.mock('@nx/cypress/src/utils/cypress-version');
|
|
||||||
describe('react:stories for applications', () => {
|
describe('react:stories for applications', () => {
|
||||||
let appTree: Tree;
|
let appTree: Tree;
|
||||||
let mockedInstalledCypressVersion: jest.Mock<
|
|
||||||
ReturnType<typeof installedCypressVersion>
|
|
||||||
> = installedCypressVersion as never;
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockedInstalledCypressVersion.mockReturnValue(10);
|
|
||||||
appTree = await createTestUIApp('test-ui-app');
|
appTree = await createTestUIApp('test-ui-app');
|
||||||
|
|
||||||
// create another component
|
// create another component
|
||||||
|
|||||||
@ -3,7 +3,6 @@ import 'nx/src/internal-testing-utils/mock-project-graph';
|
|||||||
import { Tree } from '@nx/devkit';
|
import { Tree } from '@nx/devkit';
|
||||||
import storiesGenerator from './stories';
|
import storiesGenerator from './stories';
|
||||||
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
||||||
import applicationGenerator from '../application/application';
|
|
||||||
import { Linter } from '@nx/eslint';
|
import { Linter } from '@nx/eslint';
|
||||||
import libraryGenerator from '../library/library';
|
import libraryGenerator from '../library/library';
|
||||||
|
|
||||||
@ -244,18 +243,5 @@ export async function createTestUILib(
|
|||||||
projectNameAndRootFormat: 'as-provided',
|
projectNameAndRootFormat: 'as-provided',
|
||||||
});
|
});
|
||||||
|
|
||||||
// create some Nx app that we'll use to generate the cypress
|
|
||||||
// spec into it. We don't need a real Cypress setup
|
|
||||||
|
|
||||||
await applicationGenerator(appTree, {
|
|
||||||
e2eTestRunner: 'none',
|
|
||||||
linter: Linter.EsLint,
|
|
||||||
skipFormat: true,
|
|
||||||
style: 'css',
|
|
||||||
unitTestRunner: 'none',
|
|
||||||
name: `${libName}-e2e`,
|
|
||||||
js: plainJS,
|
|
||||||
projectNameAndRootFormat: 'as-provided',
|
|
||||||
});
|
|
||||||
return appTree;
|
return appTree;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
import componentStoryGenerator from '../component-story/component-story';
|
import componentStoryGenerator from '../component-story/component-story';
|
||||||
import componentCypressSpecGenerator from '../component-cypress-spec/component-cypress-spec';
|
|
||||||
import {
|
import {
|
||||||
findExportDeclarationsForJsx,
|
findExportDeclarationsForJsx,
|
||||||
getComponentNode,
|
getComponentNode,
|
||||||
@ -11,7 +10,6 @@ import {
|
|||||||
GeneratorCallback,
|
GeneratorCallback,
|
||||||
getProjects,
|
getProjects,
|
||||||
joinPathFragments,
|
joinPathFragments,
|
||||||
logger,
|
|
||||||
ProjectConfiguration,
|
ProjectConfiguration,
|
||||||
runTasksInSerial,
|
runTasksInSerial,
|
||||||
Tree,
|
Tree,
|
||||||
@ -30,8 +28,6 @@ export interface StorybookStoriesSchema {
|
|||||||
js?: boolean;
|
js?: boolean;
|
||||||
ignorePaths?: string[];
|
ignorePaths?: string[];
|
||||||
skipFormat?: boolean;
|
skipFormat?: boolean;
|
||||||
cypressProject?: string;
|
|
||||||
generateCypressSpecs?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function projectRootPath(
|
export async function projectRootPath(
|
||||||
@ -88,8 +84,6 @@ export async function createAllStories(
|
|||||||
js: boolean,
|
js: boolean,
|
||||||
projects: Map<string, ProjectConfiguration>,
|
projects: Map<string, ProjectConfiguration>,
|
||||||
projectConfiguration: ProjectConfiguration,
|
projectConfiguration: ProjectConfiguration,
|
||||||
generateCypressSpecs?: boolean,
|
|
||||||
cypressProject?: string,
|
|
||||||
ignorePaths?: string[]
|
ignorePaths?: string[]
|
||||||
) {
|
) {
|
||||||
const { isTheFileAStory } = await import('@nx/storybook/src/utils/utilities');
|
const { isTheFileAStory } = await import('@nx/storybook/src/utils/utilities');
|
||||||
@ -123,15 +117,6 @@ export async function createAllStories(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const e2eProjectName = cypressProject || `${projectName}-e2e`;
|
|
||||||
const e2eProject = projects.get(e2eProjectName);
|
|
||||||
|
|
||||||
if (generateCypressSpecs && !e2eProject) {
|
|
||||||
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`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
componentPaths.map(async (componentPath) => {
|
componentPaths.map(async (componentPath) => {
|
||||||
const relativeCmpDir = componentPath.replace(join(sourceRoot, '/'), '');
|
const relativeCmpDir = componentPath.replace(join(sourceRoot, '/'), '');
|
||||||
@ -146,16 +131,6 @@ export async function createAllStories(
|
|||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
interactionTests,
|
interactionTests,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (generateCypressSpecs && e2eProject) {
|
|
||||||
await componentCypressSpecGenerator(tree, {
|
|
||||||
project: projectName,
|
|
||||||
componentPath: relativeCmpDir,
|
|
||||||
js,
|
|
||||||
cypressProject,
|
|
||||||
skipFormat: true,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -174,8 +149,6 @@ export async function storiesGenerator(
|
|||||||
schema.js,
|
schema.js,
|
||||||
projects,
|
projects,
|
||||||
projectConfiguration,
|
projectConfiguration,
|
||||||
schema.generateCypressSpecs,
|
|
||||||
schema.cypressProject,
|
|
||||||
schema.ignorePaths
|
schema.ignorePaths
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,3 @@
|
|||||||
// TODO(katerina): Nx 19 -> remove Cypress
|
|
||||||
import { installedCypressVersion } from '@nx/cypress/src/utils/cypress-version';
|
|
||||||
import { logger, Tree } from '@nx/devkit';
|
import { logger, Tree } from '@nx/devkit';
|
||||||
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
|
||||||
import { Linter } from '@nx/eslint';
|
import { Linter } from '@nx/eslint';
|
||||||
@ -7,9 +5,7 @@ import applicationGenerator from '../application/application';
|
|||||||
import componentGenerator from '../component/component';
|
import componentGenerator from '../component/component';
|
||||||
import libraryGenerator from '../library/library';
|
import libraryGenerator from '../library/library';
|
||||||
import storybookConfigurationGenerator from './configuration';
|
import storybookConfigurationGenerator from './configuration';
|
||||||
// need to mock cypress otherwise it'll use the nx installed version from package.json
|
|
||||||
// which is v9 while we are testing for the new v10 version
|
|
||||||
jest.mock('@nx/cypress/src/utils/cypress-version');
|
|
||||||
// nested code imports graph from the repo, which might have innacurate graph version
|
// nested code imports graph from the repo, which might have innacurate graph version
|
||||||
jest.mock('nx/src/project-graph/project-graph', () => ({
|
jest.mock('nx/src/project-graph/project-graph', () => ({
|
||||||
...jest.requireActual<any>('nx/src/project-graph/project-graph'),
|
...jest.requireActual<any>('nx/src/project-graph/project-graph'),
|
||||||
@ -20,11 +16,8 @@ jest.mock('nx/src/project-graph/project-graph', () => ({
|
|||||||
|
|
||||||
describe('react:storybook-configuration', () => {
|
describe('react:storybook-configuration', () => {
|
||||||
let appTree;
|
let appTree;
|
||||||
let mockedInstalledCypressVersion: jest.Mock<
|
|
||||||
ReturnType<typeof installedCypressVersion>
|
|
||||||
> = installedCypressVersion as never;
|
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
mockedInstalledCypressVersion.mockReturnValue(10);
|
|
||||||
jest.spyOn(logger, 'warn').mockImplementation(() => {});
|
jest.spyOn(logger, 'warn').mockImplementation(() => {});
|
||||||
jest.spyOn(logger, 'debug').mockImplementation(() => {});
|
jest.spyOn(logger, 'debug').mockImplementation(() => {});
|
||||||
});
|
});
|
||||||
|
|||||||
@ -14,23 +14,11 @@ import {
|
|||||||
import { nxVersion, reactViteVersion } from '../../utils/versions';
|
import { nxVersion, reactViteVersion } from '../../utils/versions';
|
||||||
|
|
||||||
async function generateStories(host: Tree, schema: StorybookConfigureSchema) {
|
async function generateStories(host: Tree, schema: StorybookConfigureSchema) {
|
||||||
// TODO(katerina): Nx 19 -> remove Cypress
|
|
||||||
ensurePackage('@nx/cypress', nxVersion);
|
|
||||||
const { getE2eProjectName } = await import(
|
|
||||||
'@nx/cypress/src/utils/project-name'
|
|
||||||
);
|
|
||||||
const projectConfig = readProjectConfiguration(host, schema.project);
|
const projectConfig = readProjectConfiguration(host, schema.project);
|
||||||
const cypressProject = getE2eProjectName(
|
|
||||||
schema.project,
|
|
||||||
projectConfig.root,
|
|
||||||
schema.cypressDirectory
|
|
||||||
);
|
|
||||||
await storiesGenerator(host, {
|
await storiesGenerator(host, {
|
||||||
project: schema.project,
|
project: schema.project,
|
||||||
generateCypressSpecs:
|
|
||||||
schema.configureCypress && schema.generateCypressSpecs,
|
|
||||||
js: schema.js,
|
js: schema.js,
|
||||||
cypressProject,
|
|
||||||
ignorePaths: schema.ignorePaths,
|
ignorePaths: schema.ignorePaths,
|
||||||
skipFormat: true,
|
skipFormat: true,
|
||||||
interactionTests: schema.interactionTests ?? true,
|
interactionTests: schema.interactionTests ?? true,
|
||||||
@ -85,10 +73,8 @@ export async function storybookConfigurationGeneratorInternal(
|
|||||||
|
|
||||||
const installTask = await configurationGenerator(host, {
|
const installTask = await configurationGenerator(host, {
|
||||||
project: schema.project,
|
project: schema.project,
|
||||||
configureCypress: schema.configureCypress,
|
|
||||||
js: schema.js,
|
js: schema.js,
|
||||||
linter: schema.linter,
|
linter: schema.linter,
|
||||||
cypressDirectory: schema.cypressDirectory,
|
|
||||||
tsConfiguration: schema.tsConfiguration ?? true, // default is true
|
tsConfiguration: schema.tsConfiguration ?? true, // default is true
|
||||||
interactionTests: schema.interactionTests ?? true, // default is true
|
interactionTests: schema.interactionTests ?? true, // default is true
|
||||||
configureStaticServe: schema.configureStaticServe,
|
configureStaticServe: schema.configureStaticServe,
|
||||||
|
|||||||
@ -9,8 +9,5 @@ export interface StorybookConfigureSchema {
|
|||||||
linter?: Linter | LinterType;
|
linter?: Linter | LinterType;
|
||||||
ignorePaths?: string[];
|
ignorePaths?: string[];
|
||||||
configureStaticServe?: boolean;
|
configureStaticServe?: boolean;
|
||||||
configureCypress?: boolean;
|
|
||||||
generateCypressSpecs?: boolean;
|
|
||||||
cypressDirectory?: string;
|
|
||||||
addPlugin?: boolean;
|
addPlugin?: boolean;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,11 +26,6 @@
|
|||||||
"alias": ["configureTestRunner"],
|
"alias": ["configureTestRunner"],
|
||||||
"default": true
|
"default": true
|
||||||
},
|
},
|
||||||
"configureCypress": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Run the cypress-configure generator.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"generateStories": {
|
"generateStories": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Automatically generate `*.stories.ts` files for components declared in this project?",
|
"description": "Automatically generate `*.stories.ts` files for components declared in this project?",
|
||||||
@ -38,11 +33,6 @@
|
|||||||
"default": true,
|
"default": true,
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"generateCypressSpecs": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Automatically generate test files in the Cypress E2E app generated by the `cypress-configure` generator.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"configureStaticServe": {
|
"configureStaticServe": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Specifies whether to configure a static file server target for serving storybook. Helpful for speeding up CI build/test times.",
|
"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 @@
|
|||||||
"default": true,
|
"default": true,
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"cypressDirectory": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A directory where the Cypress project will be placed. Placed at the root by default.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"js": {
|
"js": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Generate JavaScript story files rather than TypeScript story files.",
|
"description": "Generate JavaScript story files rather than TypeScript story files.",
|
||||||
|
|||||||
@ -3,13 +3,10 @@ import { Linter, LinterType } from '@nx/eslint';
|
|||||||
export interface StorybookConfigurationSchema {
|
export interface StorybookConfigurationSchema {
|
||||||
project: string;
|
project: string;
|
||||||
interactionTests?: boolean;
|
interactionTests?: boolean;
|
||||||
configureCypress: boolean;
|
|
||||||
generateStories?: boolean;
|
generateStories?: boolean;
|
||||||
generateCypressSpecs?: boolean;
|
|
||||||
js?: boolean;
|
js?: boolean;
|
||||||
tsConfiguration?: boolean;
|
tsConfiguration?: boolean;
|
||||||
linter?: Linter | LinterType;
|
linter?: Linter | LinterType;
|
||||||
cypressDirectory?: string;
|
|
||||||
ignorePaths?: string[];
|
ignorePaths?: string[];
|
||||||
configureTestRunner?: boolean;
|
configureTestRunner?: boolean;
|
||||||
configureStaticServe?: boolean;
|
configureStaticServe?: boolean;
|
||||||
|
|||||||
@ -26,11 +26,6 @@
|
|||||||
"alias": ["configureTestRunner"],
|
"alias": ["configureTestRunner"],
|
||||||
"default": true
|
"default": true
|
||||||
},
|
},
|
||||||
"configureCypress": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Run the cypress-configure generator.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"generateStories": {
|
"generateStories": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Automatically generate `*.stories.ts` files for components declared in this project?",
|
"description": "Automatically generate `*.stories.ts` files for components declared in this project?",
|
||||||
@ -38,11 +33,6 @@
|
|||||||
"default": true,
|
"default": true,
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"generateCypressSpecs": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Automatically generate test files in the Cypress E2E app generated by the `cypress-configure` generator.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"configureStaticServe": {
|
"configureStaticServe": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Specifies whether to configure a static file server target for serving storybook. Helpful for speeding up CI build/test times.",
|
"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 @@
|
|||||||
"default": true,
|
"default": true,
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"cypressDirectory": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A directory where the Cypress project will be placed. Placed at the root by default.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"js": {
|
"js": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Generate JavaScript story files rather than TypeScript story files.",
|
"description": "Generate JavaScript story files rather than TypeScript story files.",
|
||||||
|
|||||||
@ -22,7 +22,6 @@ describe('Storybook Configuration', () => {
|
|||||||
// ACT
|
// ACT
|
||||||
await storybookConfigurationGenerator(tree, {
|
await storybookConfigurationGenerator(tree, {
|
||||||
project: 'storybook-test',
|
project: 'storybook-test',
|
||||||
configureCypress: false,
|
|
||||||
configureStaticServe: false,
|
configureStaticServe: false,
|
||||||
generateStories: true,
|
generateStories: true,
|
||||||
addPlugin: true,
|
addPlugin: true,
|
||||||
|
|||||||
@ -17,7 +17,7 @@ import { nxVersion, storybookVersion } from '../../utils/versions';
|
|||||||
import configurationGenerator from './configuration';
|
import configurationGenerator from './configuration';
|
||||||
import * as variousProjects from './test-configs/various-projects.json';
|
import * as variousProjects from './test-configs/various-projects.json';
|
||||||
|
|
||||||
// nested code imports graph from the repo, which might have innacurate graph version
|
// nested code imports graph from the repo, which might have inaccurate graph version
|
||||||
jest.mock('nx/src/project-graph/project-graph', () => ({
|
jest.mock('nx/src/project-graph/project-graph', () => ({
|
||||||
...jest.requireActual<any>('nx/src/project-graph/project-graph'),
|
...jest.requireActual<any>('nx/src/project-graph/project-graph'),
|
||||||
createProjectGraphAsync: jest
|
createProjectGraphAsync: jest
|
||||||
|
|||||||
@ -10,7 +10,6 @@ import {
|
|||||||
} from '@nx/devkit';
|
} from '@nx/devkit';
|
||||||
import { initGenerator as jsInitGenerator } from '@nx/js';
|
import { initGenerator as jsInitGenerator } from '@nx/js';
|
||||||
|
|
||||||
import { cypressProjectGenerator } from '../cypress-project/cypress-project';
|
|
||||||
import { StorybookConfigureSchema } from './schema';
|
import { StorybookConfigureSchema } from './schema';
|
||||||
import { initGenerator } from '../init/init';
|
import { initGenerator } from '../init/init';
|
||||||
|
|
||||||
@ -29,7 +28,6 @@ import {
|
|||||||
findMetroConfig,
|
findMetroConfig,
|
||||||
findNextConfig,
|
findNextConfig,
|
||||||
findViteConfig,
|
findViteConfig,
|
||||||
getE2EProjectName,
|
|
||||||
projectIsRootProjectInStandaloneWorkspace,
|
projectIsRootProjectInStandaloneWorkspace,
|
||||||
updateLintConfig,
|
updateLintConfig,
|
||||||
} from './lib/util-functions';
|
} from './lib/util-functions';
|
||||||
@ -197,29 +195,6 @@ export async function configurationGeneratorInternal(
|
|||||||
devDeps['storybook'] = storybookVersion;
|
devDeps['storybook'] = storybookVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(katerina): Nx 19 -> remove Cypress
|
|
||||||
if (schema.configureCypress) {
|
|
||||||
const e2eProject = await getE2EProjectName(tree, schema.project);
|
|
||||||
if (!e2eProject) {
|
|
||||||
const cypressTask = await cypressProjectGenerator(tree, {
|
|
||||||
name: schema.project,
|
|
||||||
js: schema.js,
|
|
||||||
linter: schema.linter,
|
|
||||||
directory: schema.cypressDirectory,
|
|
||||||
standaloneConfig: schema.standaloneConfig,
|
|
||||||
ciTargetName: schema.configureStaticServe
|
|
||||||
? 'static-storybook'
|
|
||||||
: undefined,
|
|
||||||
skipFormat: true,
|
|
||||||
});
|
|
||||||
tasks.push(cypressTask);
|
|
||||||
} else {
|
|
||||||
logger.warn(
|
|
||||||
`There is already an e2e project setup for ${schema.project}, called ${e2eProject}.`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (schema.tsConfiguration) {
|
if (schema.tsConfiguration) {
|
||||||
devDeps['ts-node'] = tsNodeVersion;
|
devDeps['ts-node'] = tsNodeVersion;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -681,36 +681,6 @@ export function rootFileIsTs(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getE2EProjectName(
|
|
||||||
tree: Tree,
|
|
||||||
mainProject: string
|
|
||||||
): Promise<string | undefined> {
|
|
||||||
let e2eProject: string;
|
|
||||||
const graph = await createProjectGraphAsync();
|
|
||||||
forEachExecutorOptions(
|
|
||||||
tree,
|
|
||||||
'@nx/cypress:cypress',
|
|
||||||
(options, projectName) => {
|
|
||||||
if (e2eProject) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (options['devServerTarget']) {
|
|
||||||
const { project, target } = parseTargetString(
|
|
||||||
options['devServerTarget'],
|
|
||||||
graph
|
|
||||||
);
|
|
||||||
if (
|
|
||||||
(project === mainProject && target === 'serve') ||
|
|
||||||
(project === mainProject && target === 'storybook')
|
|
||||||
) {
|
|
||||||
e2eProject = projectName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
return e2eProject;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function findViteConfig(
|
export function findViteConfig(
|
||||||
tree: Tree,
|
tree: Tree,
|
||||||
projectRoot: string
|
projectRoot: string
|
||||||
|
|||||||
@ -11,14 +11,6 @@ export interface StorybookConfigureSchema {
|
|||||||
standaloneConfig?: boolean;
|
standaloneConfig?: boolean;
|
||||||
configureStaticServe?: boolean;
|
configureStaticServe?: boolean;
|
||||||
skipFormat?: boolean;
|
skipFormat?: boolean;
|
||||||
/**
|
|
||||||
* @deprecated Use interactionTests instead. This option will be removed in v20.
|
|
||||||
*/
|
|
||||||
configureCypress?: boolean;
|
|
||||||
/**
|
|
||||||
* @deprecated Use interactionTests instead. This option will be removed in v20.
|
|
||||||
*/
|
|
||||||
cypressDirectory?: string;
|
|
||||||
addPlugin?: boolean;
|
addPlugin?: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -25,16 +25,6 @@
|
|||||||
"alias": ["configureTestRunner"],
|
"alias": ["configureTestRunner"],
|
||||||
"default": true
|
"default": true
|
||||||
},
|
},
|
||||||
"configureCypress": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Run the cypress-configure generator.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"cypressDirectory": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "A directory where the Cypress project will be placed. Added at root by default.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"linter": {
|
"linter": {
|
||||||
"description": "The tool to use for running lint checks.",
|
"description": "The tool to use for running lint checks.",
|
||||||
"type": "string",
|
"type": "string",
|
||||||
|
|||||||
@ -17,16 +17,6 @@
|
|||||||
"x-prompt": "For which project do you want to generate stories?",
|
"x-prompt": "For which project do you want to generate stories?",
|
||||||
"x-priority": "important"
|
"x-priority": "important"
|
||||||
},
|
},
|
||||||
"generateCypressSpecs": {
|
|
||||||
"type": "boolean",
|
|
||||||
"description": "Automatically generate `*.spec.ts` files in the cypress e2e app generated by the cypress-configure generator.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"cypressProject": {
|
|
||||||
"type": "string",
|
|
||||||
"description": "The Cypress project to generate the stories under. This is inferred from `project` by default.",
|
|
||||||
"x-deprecated": "Use interactionTests instead. This option will be removed in v20."
|
|
||||||
},
|
|
||||||
"interactionTests": {
|
"interactionTests": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Set up Storybook interaction tests.",
|
"description": "Set up Storybook interaction tests.",
|
||||||
|
|||||||
@ -21,8 +21,6 @@ export interface StorybookStoriesSchema {
|
|||||||
js?: boolean;
|
js?: boolean;
|
||||||
ignorePaths?: string[];
|
ignorePaths?: string[];
|
||||||
skipFormat?: boolean;
|
skipFormat?: boolean;
|
||||||
cypressProject?: string;
|
|
||||||
generateCypressSpecs?: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function createAllStories(
|
export async function createAllStories(
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user