From 58e1f233cfdc7ae48029a58ad65ef33cbddc3f22 Mon Sep 17 00:00:00 2001 From: Katerina Skroumpelou Date: Wed, 12 Jul 2023 18:02:12 +0300 Subject: [PATCH] feat(storybook): interaction testing init generator (#18051) --- .../generators/storybook-configuration.json | 25 +-- .../generators/storybook-configuration.json | 2 +- .../generators/storybook-configuration.json | 25 +-- .../storybook/generators/configuration.json | 17 +- e2e/storybook/src/storybook-nested.test.ts | 4 +- .../lib/generate-storybook-configuration.ts | 2 +- .../storybook-configuration/schema.d.ts | 2 +- .../storybook-configuration/schema.json | 25 +-- .../storybook-configuration/schema.json | 2 +- .../storybook-configuration/configuration.ts | 3 +- .../storybook-configuration/schema.d.ts | 2 +- .../storybook-configuration/schema.json | 25 +-- .../configuration-nested.spec.ts.snap | 8 +- .../__snapshots__/configuration.spec.ts.snap | 146 +++++++++++++++--- .../configuration-nested.spec.ts | 10 +- .../configuration/configuration.spec.ts | 18 ++- .../generators/configuration/configuration.ts | 17 +- .../configuration/lib/util-functions.ts | 10 +- .../.storybook/main.ts__tmpl__ | 2 +- .../project-files/.storybook/main.js__tmpl__ | 2 +- .../src/generators/configuration/schema.d.ts | 2 +- .../src/generators/configuration/schema.json | 17 +- .../migrate-defaults-5-to-6.ts | 1 + packages/storybook/src/utils/versions.ts | 4 +- 24 files changed, 256 insertions(+), 115 deletions(-) diff --git a/docs/generated/packages/angular/generators/storybook-configuration.json b/docs/generated/packages/angular/generators/storybook-configuration.json index 81f3b4f30f0f1..cda247f442ae7 100644 --- a/docs/generated/packages/angular/generators/storybook-configuration.json +++ b/docs/generated/packages/angular/generators/storybook-configuration.json @@ -18,12 +18,18 @@ "x-dropdown": "projects", "x-priority": "important" }, + "interactionTests": { + "type": "boolean", + "description": "Set up Storybook interaction tests.", + "x-prompt": "Do you want to set up Storybook interaction tests?", + "alias": ["configureTestRunner"], + "x-priority": "important", + "default": true + }, "configureCypress": { "type": "boolean", "description": "Specifies whether to configure Cypress or not.", - "x-prompt": "Configure a Cypress e2e app to run against the storybook instance?", - "default": true, - "x-priority": "important" + "x-deprecated": "Please use Storybook interaction tests instead." }, "generateStories": { "type": "boolean", @@ -35,9 +41,7 @@ "generateCypressSpecs": { "type": "boolean", "description": "Specifies whether to automatically generate test files in the generated Cypress e2e app.", - "x-prompt": "Automatically generate test files in the generated Cypress e2e app?", - "default": true, - "x-priority": "important" + "x-deprecated": "Please use Storybook interaction tests instead." }, "configureStaticServe": { "type": "boolean", @@ -48,7 +52,8 @@ }, "cypressDirectory": { "type": "string", - "description": "A directory where the Cypress project will be placed. Placed at the root by default." + "description": "A directory where the Cypress project will be placed. Placed at the root by default.", + "x-deprecated": "Please use Storybook interaction tests instead." }, "linter": { "description": "The tool to use for running lint checks.", @@ -59,7 +64,7 @@ "tsConfiguration": { "type": "boolean", "description": "Configure your project with TypeScript. Generate main.ts and preview.ts files, instead of main.js and preview.js.", - "default": false, + "default": true, "x-priority": "important" }, "skipFormat": { @@ -79,10 +84,6 @@ "**/**/src/**/*.other.*", "libs/my-lib/src/not-stories/**,**/**/src/**/*.other.*,apps/my-app/**/*.something.ts" ] - }, - "configureTestRunner": { - "type": "boolean", - "description": "Add a Storybook Test-Runner target." } }, "additionalProperties": false, diff --git a/docs/generated/packages/react-native/generators/storybook-configuration.json b/docs/generated/packages/react-native/generators/storybook-configuration.json index 8accbc33edd95..9293ae7b46e3e 100644 --- a/docs/generated/packages/react-native/generators/storybook-configuration.json +++ b/docs/generated/packages/react-native/generators/storybook-configuration.json @@ -32,7 +32,7 @@ "tsConfiguration": { "type": "boolean", "description": "Configure your project with TypeScript. Generate main.ts and preview.ts files, instead of main.js and preview.js.", - "default": false + "default": true }, "linter": { "description": "The tool to use for running lint checks.", diff --git a/docs/generated/packages/react/generators/storybook-configuration.json b/docs/generated/packages/react/generators/storybook-configuration.json index 02e15b30e1d18..decc8cfbd7ed7 100644 --- a/docs/generated/packages/react/generators/storybook-configuration.json +++ b/docs/generated/packages/react/generators/storybook-configuration.json @@ -18,12 +18,18 @@ "x-dropdown": "projects", "x-priority": "important" }, + "interactionTests": { + "type": "boolean", + "description": "Set up Storybook interaction tests.", + "x-prompt": "Do you want to set up Storybook interaction tests?", + "x-priority": "important", + "alias": ["configureTestRunner"], + "default": true + }, "configureCypress": { "type": "boolean", "description": "Run the cypress-configure generator.", - "x-prompt": "Configure a cypress e2e app to run against the storybook instance?", - "default": true, - "x-priority": "important" + "x-deprecated": "Please use Storybook interaction tests instead." }, "generateStories": { "type": "boolean", @@ -35,9 +41,7 @@ "generateCypressSpecs": { "type": "boolean", "description": "Automatically generate test files in the Cypress E2E app generated by the `cypress-configure` generator.", - "x-prompt": "Automatically generate test files in the Cypress E2E app generated by the cypress-configure generator?", - "default": true, - "x-priority": "important" + "x-deprecated": "Please use Storybook interaction tests instead." }, "configureStaticServe": { "type": "boolean", @@ -48,7 +52,8 @@ }, "cypressDirectory": { "type": "string", - "description": "A directory where the Cypress project will be placed. Placed at the root by default." + "description": "A directory where the Cypress project will be placed. Placed at the root by default.", + "x-deprecated": "Please use Storybook interaction tests instead." }, "js": { "type": "boolean", @@ -58,7 +63,7 @@ "tsConfiguration": { "type": "boolean", "description": "Configure your project with TypeScript. Generate main.ts and preview.ts files, instead of main.js and preview.js.", - "default": false + "default": true }, "linter": { "description": "The tool to use for running lint checks.", @@ -77,10 +82,6 @@ "**/**/src/**/*.other.*", "libs/my-lib/src/not-stories/**,**/**/src/**/*.other.*,apps/my-app/**/*.something.ts" ] - }, - "configureTestRunner": { - "type": "boolean", - "description": "Add a Storybook Test-Runner target." } }, "required": ["name"], diff --git a/docs/generated/packages/storybook/generators/configuration.json b/docs/generated/packages/storybook/generators/configuration.json index a3223720d7820..7c3c8b104361e 100644 --- a/docs/generated/packages/storybook/generators/configuration.json +++ b/docs/generated/packages/storybook/generators/configuration.json @@ -18,15 +18,22 @@ "x-dropdown": "projects", "x-priority": "important" }, + "interactionTests": { + "type": "boolean", + "description": "Set up Storybook interaction tests.", + "x-prompt": "Do you want to set up Storybook interaction tests?", + "alias": ["configureTestRunner"], + "default": true + }, "configureCypress": { "type": "boolean", "description": "Run the cypress-configure generator.", - "x-prompt": "Configure a cypress e2e app to run against the storybook instance?", - "x-priority": "important" + "x-deprecated": "Please use Storybook interaction tests instead." }, "cypressDirectory": { "type": "string", - "description": "A directory where the Cypress project will be placed. Added at root by default." + "description": "A directory where the Cypress project will be placed. Added at root by default.", + "x-deprecated": "Please use Storybook interaction tests instead." }, "linter": { "description": "The tool to use for running lint checks.", @@ -56,10 +63,6 @@ "description": "Add a static-storybook to serve the static storybook built files.", "default": false }, - "configureTestRunner": { - "type": "boolean", - "description": "Add a Storybook Test-Runner target." - }, "bundler": { "description": "The Storybook builder to use.", "type": "string", diff --git a/e2e/storybook/src/storybook-nested.test.ts b/e2e/storybook/src/storybook-nested.test.ts index dc581dffcaa9d..c4377052361bc 100644 --- a/e2e/storybook/src/storybook-nested.test.ts +++ b/e2e/storybook/src/storybook-nested.test.ts @@ -40,8 +40,8 @@ describe('Storybook generators and executors for standalone workspaces - using R describe('Storybook generated files', () => { it('should generate storybook files', () => { checkFilesExist( - '.storybook/main.js', - '.storybook/preview.js', + '.storybook/main.ts', + '.storybook/preview.ts', 'tsconfig.storybook.json' ); }); diff --git a/packages/angular/src/generators/storybook-configuration/lib/generate-storybook-configuration.ts b/packages/angular/src/generators/storybook-configuration/lib/generate-storybook-configuration.ts index 0f914169e29b1..65a040546d564 100644 --- a/packages/angular/src/generators/storybook-configuration/lib/generate-storybook-configuration.ts +++ b/packages/angular/src/generators/storybook-configuration/lib/generate-storybook-configuration.ts @@ -14,7 +14,7 @@ export async function generateStorybookConfiguration( linter: options.linter, cypressDirectory: options.cypressDirectory, tsConfiguration: options.tsConfiguration, - configureTestRunner: options.configureTestRunner, + interactionTests: options.interactionTests, configureStaticServe: options.configureStaticServe, skipFormat: true, }); diff --git a/packages/angular/src/generators/storybook-configuration/schema.d.ts b/packages/angular/src/generators/storybook-configuration/schema.d.ts index 01f6af061f76a..9c8867f4627a6 100644 --- a/packages/angular/src/generators/storybook-configuration/schema.d.ts +++ b/packages/angular/src/generators/storybook-configuration/schema.d.ts @@ -11,5 +11,5 @@ export interface StorybookConfigurationOptions { tsConfiguration?: boolean; skipFormat?: boolean; ignorePaths?: string[]; - configureTestRunner?: boolean; + interactionTests?: boolean; } diff --git a/packages/angular/src/generators/storybook-configuration/schema.json b/packages/angular/src/generators/storybook-configuration/schema.json index 419c4e3bd8e91..2d00d3817d3b7 100644 --- a/packages/angular/src/generators/storybook-configuration/schema.json +++ b/packages/angular/src/generators/storybook-configuration/schema.json @@ -18,12 +18,18 @@ "x-dropdown": "projects", "x-priority": "important" }, + "interactionTests": { + "type": "boolean", + "description": "Set up Storybook interaction tests.", + "x-prompt": "Do you want to set up Storybook interaction tests?", + "alias": ["configureTestRunner"], + "x-priority": "important", + "default": true + }, "configureCypress": { "type": "boolean", "description": "Specifies whether to configure Cypress or not.", - "x-prompt": "Configure a Cypress e2e app to run against the storybook instance?", - "default": true, - "x-priority": "important" + "x-deprecated": "Please use Storybook interaction tests instead." }, "generateStories": { "type": "boolean", @@ -35,9 +41,7 @@ "generateCypressSpecs": { "type": "boolean", "description": "Specifies whether to automatically generate test files in the generated Cypress e2e app.", - "x-prompt": "Automatically generate test files in the generated Cypress e2e app?", - "default": true, - "x-priority": "important" + "x-deprecated": "Please use Storybook interaction tests instead." }, "configureStaticServe": { "type": "boolean", @@ -48,7 +52,8 @@ }, "cypressDirectory": { "type": "string", - "description": "A directory where the Cypress project will be placed. Placed at the root by default." + "description": "A directory where the Cypress project will be placed. Placed at the root by default.", + "x-deprecated": "Please use Storybook interaction tests instead." }, "linter": { "description": "The tool to use for running lint checks.", @@ -59,7 +64,7 @@ "tsConfiguration": { "type": "boolean", "description": "Configure your project with TypeScript. Generate main.ts and preview.ts files, instead of main.js and preview.js.", - "default": false, + "default": true, "x-priority": "important" }, "skipFormat": { @@ -82,10 +87,6 @@ "**/**/src/**/*.other.*", "libs/my-lib/src/not-stories/**,**/**/src/**/*.other.*,apps/my-app/**/*.something.ts" ] - }, - "configureTestRunner": { - "type": "boolean", - "description": "Add a Storybook Test-Runner target." } }, "additionalProperties": false, diff --git a/packages/react-native/src/generators/storybook-configuration/schema.json b/packages/react-native/src/generators/storybook-configuration/schema.json index 3b5b1826b7528..4acf4b867de1c 100644 --- a/packages/react-native/src/generators/storybook-configuration/schema.json +++ b/packages/react-native/src/generators/storybook-configuration/schema.json @@ -32,7 +32,7 @@ "tsConfiguration": { "type": "boolean", "description": "Configure your project with TypeScript. Generate main.ts and preview.ts files, instead of main.js and preview.js.", - "default": false + "default": true }, "linter": { "description": "The tool to use for running lint checks.", diff --git a/packages/react/src/generators/storybook-configuration/configuration.ts b/packages/react/src/generators/storybook-configuration/configuration.ts index 9cc7223a36ff2..16d9f81d33aa9 100644 --- a/packages/react/src/generators/storybook-configuration/configuration.ts +++ b/packages/react/src/generators/storybook-configuration/configuration.ts @@ -10,6 +10,7 @@ import { import { nxVersion } from '../../utils/versions'; async function generateStories(host: Tree, schema: StorybookConfigureSchema) { + // TODO(katerina): Remove cypress stuff for Nx 17? ensurePackage('@nx/cypress', nxVersion); const { getE2eProjectName } = await import( '@nx/cypress/src/utils/project-name' @@ -57,7 +58,7 @@ export async function storybookConfigurationGenerator( linter: schema.linter, cypressDirectory: schema.cypressDirectory, tsConfiguration: schema.tsConfiguration, - configureTestRunner: schema.configureTestRunner, + interactionTests: schema.interactionTests, configureStaticServe: schema.configureStaticServe, uiFramework: bundler === 'vite' diff --git a/packages/react/src/generators/storybook-configuration/schema.d.ts b/packages/react/src/generators/storybook-configuration/schema.d.ts index 6d96bbc903da6..0094e3b656097 100644 --- a/packages/react/src/generators/storybook-configuration/schema.d.ts +++ b/packages/react/src/generators/storybook-configuration/schema.d.ts @@ -10,6 +10,6 @@ export interface StorybookConfigureSchema { linter?: Linter; cypressDirectory?: string; ignorePaths?: string[]; - configureTestRunner?: boolean; + interactionTests?: boolean; configureStaticServe?: boolean; } diff --git a/packages/react/src/generators/storybook-configuration/schema.json b/packages/react/src/generators/storybook-configuration/schema.json index 76bc6452b1441..599e0eb854e47 100644 --- a/packages/react/src/generators/storybook-configuration/schema.json +++ b/packages/react/src/generators/storybook-configuration/schema.json @@ -18,12 +18,18 @@ "x-dropdown": "projects", "x-priority": "important" }, + "interactionTests": { + "type": "boolean", + "description": "Set up Storybook interaction tests.", + "x-prompt": "Do you want to set up Storybook interaction tests?", + "x-priority": "important", + "alias": ["configureTestRunner"], + "default": true + }, "configureCypress": { "type": "boolean", "description": "Run the cypress-configure generator.", - "x-prompt": "Configure a cypress e2e app to run against the storybook instance?", - "default": true, - "x-priority": "important" + "x-deprecated": "Please use Storybook interaction tests instead." }, "generateStories": { "type": "boolean", @@ -35,9 +41,7 @@ "generateCypressSpecs": { "type": "boolean", "description": "Automatically generate test files in the Cypress E2E app generated by the `cypress-configure` generator.", - "x-prompt": "Automatically generate test files in the Cypress E2E app generated by the cypress-configure generator?", - "default": true, - "x-priority": "important" + "x-deprecated": "Please use Storybook interaction tests instead." }, "configureStaticServe": { "type": "boolean", @@ -48,7 +52,8 @@ }, "cypressDirectory": { "type": "string", - "description": "A directory where the Cypress project will be placed. Placed at the root by default." + "description": "A directory where the Cypress project will be placed. Placed at the root by default.", + "x-deprecated": "Please use Storybook interaction tests instead." }, "js": { "type": "boolean", @@ -58,7 +63,7 @@ "tsConfiguration": { "type": "boolean", "description": "Configure your project with TypeScript. Generate main.ts and preview.ts files, instead of main.js and preview.js.", - "default": false + "default": true }, "linter": { "description": "The tool to use for running lint checks.", @@ -80,10 +85,6 @@ "**/**/src/**/*.other.*", "libs/my-lib/src/not-stories/**,**/**/src/**/*.other.*,apps/my-app/**/*.something.ts" ] - }, - "configureTestRunner": { - "type": "boolean", - "description": "Add a Storybook Test-Runner target." } }, "required": ["name"], diff --git a/packages/storybook/src/generators/configuration/__snapshots__/configuration-nested.spec.ts.snap b/packages/storybook/src/generators/configuration/__snapshots__/configuration-nested.spec.ts.snap index 38665f14b0f16..82909b11da730 100644 --- a/packages/storybook/src/generators/configuration/__snapshots__/configuration-nested.spec.ts.snap +++ b/packages/storybook/src/generators/configuration/__snapshots__/configuration-nested.spec.ts.snap @@ -5,7 +5,7 @@ exports[`@nx/storybook:configuration for workspaces with Root project basic func const config: StorybookConfig = { stories: ['../src/app/**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials'], + addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'], framework: { name: '@storybook/react-vite', options: { @@ -66,7 +66,11 @@ exports[`@nx/storybook:configuration for workspaces with Root project basic func const config: StorybookConfig = { stories: ['../src/app/**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials', '@nx/react/plugins/storybook'], + addons: [ + '@storybook/addon-essentials', + '@storybook/addon-interactions', + '@nx/react/plugins/storybook', + ], framework: { name: '@storybook/react-webpack5', options: {}, diff --git a/packages/storybook/src/generators/configuration/__snapshots__/configuration.spec.ts.snap b/packages/storybook/src/generators/configuration/__snapshots__/configuration.spec.ts.snap index 9a518eefde082..5e62759551bf0 100644 --- a/packages/storybook/src/generators/configuration/__snapshots__/configuration.spec.ts.snap +++ b/packages/storybook/src/generators/configuration/__snapshots__/configuration.spec.ts.snap @@ -5,7 +5,7 @@ exports[`@nx/storybook:configuration for Storybook v7 basic functionalities shou const config: StorybookConfig = { stories: ['../**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials'], + addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'], framework: { name: '@storybook/angular', options: {}, @@ -87,6 +87,12 @@ exports[`@nx/storybook:configuration for Storybook v7 basic functionalities shou "{workspaceRoot}/coverage/{projectRoot}", ], }, + "test-storybook": { + "executor": "nx:run-commands", + "options": { + "command": "test-storybook -c libs/test-ui-lib/.storybook --url=http://localhost:4400", + }, + }, }, } `; @@ -98,7 +104,7 @@ exports[`@nx/storybook:configuration for Storybook v7 basic functionalities shou const config: StorybookConfig = { stories: ['../**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials'], + addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'], framework: { name: '@storybook/angular', options: {}, @@ -151,7 +157,7 @@ exports[`@nx/storybook:configuration for Storybook v7 basic functionalities shou exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/main-vite/.storybook/" 1`] = ` "const config = { stories: ['../src/app/**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials'], + addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'], framework: { name: '@storybook/react-vite', options: { @@ -177,7 +183,7 @@ exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configu const config: StorybookConfig = { stories: ['../src/app/**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials'], + addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'], framework: { name: '@storybook/react-vite', options: { @@ -199,9 +205,15 @@ export default config; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/main-vite-ts/.storybook/" 2`] = `null`; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/main-webpack/.storybook/" 1`] = ` -"const config = { +"import type { StorybookConfig } from '@storybook/react-webpack5'; + +const config: StorybookConfig = { stories: ['../src/app/**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials', '@nx/react/plugins/storybook'], + addons: [ + '@storybook/addon-essentials', + '@storybook/addon-interactions', + '@nx/react/plugins/storybook', + ], framework: { name: '@storybook/react-webpack5', options: {}, @@ -219,9 +231,11 @@ export default config; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/main-webpack/.storybook/" 2`] = `null`; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/nextapp/.storybook/" 1`] = ` -"const config = { +"import type { StorybookConfig } from '@storybook/nextjs'; + +const config: StorybookConfig = { stories: ['../components/**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials'], + addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'], framework: { name: '@storybook/nextjs', options: {}, @@ -239,9 +253,15 @@ export default config; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/nextapp/.storybook/" 2`] = `null`; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/react-swc/.storybook/" 1`] = ` -"const config = { +"import type { StorybookConfig } from '@storybook/react-webpack5'; + +const config: StorybookConfig = { stories: ['../src/app/**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials', '@nx/react/plugins/storybook'], + addons: [ + '@storybook/addon-essentials', + '@storybook/addon-interactions', + '@nx/react/plugins/storybook', + ], framework: { name: '@storybook/react-webpack5', options: {}, @@ -261,7 +281,7 @@ exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configu exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/reapp/.storybook/" 1`] = ` "const config = { stories: ['../src/app/**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials'], + addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'], framework: { name: '@storybook/react-vite', options: { @@ -283,9 +303,15 @@ export default config; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/reapp/.storybook/" 2`] = `null`; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/reappw/.storybook/" 1`] = ` -"const config = { +"import type { StorybookConfig } from '@storybook/react-webpack5'; + +const config: StorybookConfig = { stories: ['../src/app/**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials', '@nx/react/plugins/storybook'], + addons: [ + '@storybook/addon-essentials', + '@storybook/addon-interactions', + '@nx/react/plugins/storybook', + ], framework: { name: '@storybook/react-webpack5', options: {}, @@ -303,9 +329,11 @@ export default config; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/reappw/.storybook/" 2`] = `null`; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/wv1/.storybook/" 1`] = ` -"const config = { +"import type { StorybookConfig } from '@storybook/web-components-vite'; + +const config: StorybookConfig = { stories: ['../src/app/**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials'], + addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'], framework: { name: '@storybook/web-components-vite', options: { @@ -327,9 +355,11 @@ export default config; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/wv1/.storybook/" 2`] = `null`; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/ww1/.storybook/" 1`] = ` -"const config = { +"import type { StorybookConfig } from '@storybook/web-components-webpack5'; + +const config: StorybookConfig = { stories: ['../src/app/**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials'], + addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'], framework: { name: '@storybook/web-components-webpack5', options: {}, @@ -347,9 +377,15 @@ export default config; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "apps/ww1/.storybook/" 2`] = `null`; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "libs/react-rollup/.storybook/" 1`] = ` -"const config = { +"import type { StorybookConfig } from '@storybook/react-webpack5'; + +const config: StorybookConfig = { stories: ['../src/lib/**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials', '@nx/react/plugins/storybook'], + addons: [ + '@storybook/addon-essentials', + '@storybook/addon-interactions', + '@nx/react/plugins/storybook', + ], framework: { name: '@storybook/react-webpack5', options: {}, @@ -367,9 +403,11 @@ export default config; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "libs/react-rollup/.storybook/" 2`] = `null`; exports[`@nx/storybook:configuration for Storybook v7 generate Storybook configuration for all types of projects should contain the correct configuration in "libs/react-vite/.storybook/" 1`] = ` -"const config = { +"import type { StorybookConfig } from '@storybook/react-vite'; + +const config: StorybookConfig = { stories: ['../src/lib/**/*.stories.@(js|jsx|ts|tsx|mdx)'], - addons: ['@storybook/addon-essentials'], + addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'], framework: { name: '@storybook/react-vite', options: { @@ -484,6 +522,12 @@ Map { "coverage/apps/main-vite", ], }, + "test-storybook": { + "executor": "nx:run-commands", + "options": { + "command": "test-storybook -c apps/main-vite/.storybook --url=http://localhost:4400", + }, + }, }, }, "main-vite-e2e" => { @@ -615,6 +659,12 @@ Map { "coverage/apps/main-vite-ts", ], }, + "test-storybook": { + "executor": "nx:run-commands", + "options": { + "command": "test-storybook -c apps/main-vite-ts/.storybook --url=http://localhost:4400", + }, + }, }, }, "main-vite-ts-e2e" => { @@ -774,6 +824,12 @@ Map { "{workspaceRoot}/coverage/{projectRoot}", ], }, + "test-storybook": { + "executor": "nx:run-commands", + "options": { + "command": "test-storybook -c apps/main-webpack/.storybook --url=http://localhost:4400", + }, + }, }, }, "main-webpack-e2e" => { @@ -930,6 +986,12 @@ Map { "{workspaceRoot}/coverage/{projectRoot}", ], }, + "test-storybook": { + "executor": "nx:run-commands", + "options": { + "command": "test-storybook -c apps/nextapp/.storybook --url=http://localhost:4400", + }, + }, }, }, "nextapp-e2e" => { @@ -1330,6 +1392,12 @@ Map { "{workspaceRoot}/coverage/{projectRoot}", ], }, + "test-storybook": { + "executor": "nx:run-commands", + "options": { + "command": "test-storybook -c apps/react-swc/.storybook --url=http://localhost:4400", + }, + }, }, }, "react-swc-e2e" => { @@ -1498,6 +1566,12 @@ Map { "coverage/apps/reapp", ], }, + "test-storybook": { + "executor": "nx:run-commands", + "options": { + "command": "test-storybook -c apps/reapp/.storybook --url=http://localhost:4400", + }, + }, }, }, "reapp-e2e" => { @@ -1656,6 +1730,12 @@ Map { "{workspaceRoot}/coverage/{projectRoot}", ], }, + "test-storybook": { + "executor": "nx:run-commands", + "options": { + "command": "test-storybook -c apps/reappw/.storybook --url=http://localhost:4400", + }, + }, }, }, "reappw-e2e" => { @@ -1787,6 +1867,12 @@ Map { "{workspaceRoot}/coverage/{projectRoot}", ], }, + "test-storybook": { + "executor": "nx:run-commands", + "options": { + "command": "test-storybook -c apps/wv1/.storybook --url=http://localhost:4400", + }, + }, }, }, "wv1-e2e" => { @@ -1933,6 +2019,12 @@ Map { "{workspaceRoot}/coverage/{projectRoot}", ], }, + "test-storybook": { + "executor": "nx:run-commands", + "options": { + "command": "test-storybook -c apps/ww1/.storybook --url=http://localhost:4400", + }, + }, }, }, "ww1-e2e" => { @@ -2197,6 +2289,12 @@ Map { "{workspaceRoot}/coverage/{projectRoot}", ], }, + "test-storybook": { + "executor": "nx:run-commands", + "options": { + "command": "test-storybook -c libs/react-rollup/.storybook --url=http://localhost:4400", + }, + }, }, }, "react-rollup-2" => { @@ -2328,6 +2426,12 @@ Map { "coverage/libs/react-vite", ], }, + "test-storybook": { + "executor": "nx:run-commands", + "options": { + "command": "test-storybook -c libs/react-vite/.storybook --url=http://localhost:4400", + }, + }, }, }, "react-vite-2" => { diff --git a/packages/storybook/src/generators/configuration/configuration-nested.spec.ts b/packages/storybook/src/generators/configuration/configuration-nested.spec.ts index 8e3780c55bd1d..124d6560b67b5 100644 --- a/packages/storybook/src/generators/configuration/configuration-nested.spec.ts +++ b/packages/storybook/src/generators/configuration/configuration-nested.spec.ts @@ -19,13 +19,6 @@ jest.mock('nx/src/project-graph/project-graph', () => ({ })); describe('@nx/storybook:configuration for workspaces with Root project', () => { - beforeAll(() => { - process.env.NX_INTERACTIVE = 'true'; - }); - afterAll(() => { - // cleanup - delete process.env.NX_INTERACTIVE; - }); describe('basic functionalities', () => { let tree: Tree; beforeEach(async () => { @@ -93,6 +86,7 @@ describe('@nx/storybook:configuration for workspaces with Root project', () => { await configurationGenerator(tree, { name: 'web', uiFramework: '@storybook/react-webpack5', + tsConfiguration: false, }); expect(tree.exists('.storybook/main.js')).toBeTruthy(); @@ -106,7 +100,6 @@ describe('@nx/storybook:configuration for workspaces with Root project', () => { await configurationGenerator(tree, { name: 'reapp', uiFramework: '@storybook/react-webpack5', - tsConfiguration: true, }); expect(tree.exists('.storybook/main.ts')).toBeFalsy(); @@ -120,7 +113,6 @@ describe('@nx/storybook:configuration for workspaces with Root project', () => { await configurationGenerator(tree, { name: 'web', uiFramework: '@storybook/react-vite', - tsConfiguration: true, }); expect(tree.exists('.storybook/main.ts')).toBeTruthy(); diff --git a/packages/storybook/src/generators/configuration/configuration.spec.ts b/packages/storybook/src/generators/configuration/configuration.spec.ts index f9f20b6875553..96c34ec3b37ef 100644 --- a/packages/storybook/src/generators/configuration/configuration.spec.ts +++ b/packages/storybook/src/generators/configuration/configuration.spec.ts @@ -189,7 +189,7 @@ describe('@nx/storybook:configuration for Storybook v7', () => { it('should add test-storybook target', async () => { await configurationGenerator(tree, { name: 'test-ui-lib', - configureTestRunner: true, + interactionTests: true, uiFramework: '@storybook/react-webpack5', }); @@ -197,6 +197,22 @@ describe('@nx/storybook:configuration for Storybook v7', () => { readJson(tree, 'package.json').devDependencies['@storybook/test-runner'] ).toBeTruthy(); + expect( + readJson(tree, 'package.json').devDependencies[ + '@storybook/testing-library' + ] + ).toBeTruthy(); + + expect( + readJson(tree, 'package.json').devDependencies['@storybook/jest'] + ).toBeTruthy(); + + expect( + readJson(tree, 'package.json').devDependencies[ + '@storybook/addon-interactions' + ] + ).toBeTruthy(); + const project = readProjectConfiguration(tree, 'test-ui-lib'); expect(project.targets['test-storybook']).toEqual({ executor: 'nx:run-commands', diff --git a/packages/storybook/src/generators/configuration/configuration.ts b/packages/storybook/src/generators/configuration/configuration.ts index ee2b66361d6b9..0365434575086 100644 --- a/packages/storybook/src/generators/configuration/configuration.ts +++ b/packages/storybook/src/generators/configuration/configuration.ts @@ -36,6 +36,8 @@ import { } from '../../utils/utilities'; import { nxVersion, + storybookJestVersion, + storybookTestingLibraryVersion, storybookTestRunnerVersion, storybookVersion, tsNodeVersion, @@ -109,6 +111,7 @@ export async function configurationGenerator( root, projectType, projectIsRootProjectInStandaloneWorkspace(root), + schema.interactionTests, mainDir, !!nextBuildTarget, compiler === 'swc', @@ -133,13 +136,13 @@ export async function configurationGenerator( addStorybookToNamedInputs(tree); if (schema.uiFramework === '@storybook/angular') { - addAngularStorybookTask(tree, schema.name, schema.configureTestRunner); + addAngularStorybookTask(tree, schema.name, schema.interactionTests); } else { addStorybookTask( tree, schema.name, schema.uiFramework, - schema.configureTestRunner + schema.interactionTests ); } @@ -147,6 +150,7 @@ export async function configurationGenerator( addStaticTarget(tree, schema); } + // TODO(katerina): remove this feature in 17? if (schema.configureCypress) { const e2eProject = await getE2EProjectName(tree, schema.name); if (!e2eProject) { @@ -176,9 +180,13 @@ export async function configurationGenerator( devDeps['ts-node'] = tsNodeVersion; } - if (schema.configureTestRunner === true) { + if (schema.interactionTests) { devDeps['@storybook/test-runner'] = storybookTestRunnerVersion; + devDeps['@storybook/addon-interactions'] = storybookVersion; + devDeps['@storybook/testing-library'] = storybookTestingLibraryVersion; + devDeps['@storybook/jest'] = storybookJestVersion; } + if (schema.configureStaticServe) { devDeps['@nx/web'] = nxVersion; } @@ -196,9 +204,10 @@ function normalizeSchema( schema: StorybookConfigureSchema ): StorybookConfigureSchema { const defaults = { - configureCypress: true, + interactionTests: true, linter: Linter.EsLint, js: false, + tsConfiguration: true, }; return { ...defaults, diff --git a/packages/storybook/src/generators/configuration/lib/util-functions.ts b/packages/storybook/src/generators/configuration/lib/util-functions.ts index 5aa9d786bf7a8..550d5ae485fd1 100644 --- a/packages/storybook/src/generators/configuration/lib/util-functions.ts +++ b/packages/storybook/src/generators/configuration/lib/util-functions.ts @@ -35,7 +35,7 @@ export function addStorybookTask( tree: Tree, projectName: string, uiFramework: string, - configureTestRunner: boolean + interactionTests: boolean ) { if (uiFramework === '@storybook/react-native') { return; @@ -68,7 +68,7 @@ export function addStorybookTask( }, }; - if (configureTestRunner === true) { + if (interactionTests === true) { projectConfig.targets['test-storybook'] = { executor: 'nx:run-commands', options: { @@ -83,7 +83,7 @@ export function addStorybookTask( export function addAngularStorybookTask( tree: Tree, projectName: string, - configureTestRunner: boolean + interactionTests: boolean ) { const projectConfig = readProjectConfiguration(tree, projectName); const { ngBuildTarget } = findStorybookAndBuildTargetsAndCompiler( @@ -124,7 +124,7 @@ export function addAngularStorybookTask( }, }; - if (configureTestRunner === true) { + if (interactionTests === true) { projectConfig.targets['test-storybook'] = { executor: 'nx:run-commands', options: { @@ -497,6 +497,7 @@ export function createProjectStorybookDir( root: string, projectType: string, projectIsRootProjectInStandaloneWorkspace: boolean, + interactionTests: boolean, mainDir?: string, isNextJs?: boolean, usesSwc?: boolean, @@ -533,6 +534,7 @@ export function createProjectStorybookDir( offsetFromRoot: offsetFromRoot(root), projectDirectory, projectType, + interactionTests, mainDir, isNextJs: isNextJs && projectType === 'application', usesSwc, diff --git a/packages/storybook/src/generators/configuration/project-files-ts/.storybook/main.ts__tmpl__ b/packages/storybook/src/generators/configuration/project-files-ts/.storybook/main.ts__tmpl__ index 77e672c8f748e..0e8a45f81a532 100644 --- a/packages/storybook/src/generators/configuration/project-files-ts/.storybook/main.ts__tmpl__ +++ b/packages/storybook/src/generators/configuration/project-files-ts/.storybook/main.ts__tmpl__ @@ -6,7 +6,7 @@ const config: StorybookConfig = { '../**/*.stories.@(js|jsx|ts|tsx|mdx)' <% } else { %> '../<%= projectDirectory %>/**/*.stories.@(js|jsx|ts|tsx|mdx)' <% } %>], - addons: ['@storybook/addon-essentials' <% if(uiFramework === '@storybook/react-webpack5') { %>, '@nx/react/plugins/storybook' <% } %><% if(uiFramework === '@storybook/react-native') { %>, '@storybook/addon-ondevice-actions', '@storybook/addon-ondevice-backgrounds', '@storybook/addon-ondevice-controls', '@storybook/addon-ondevice-notes' <% } %>], + addons: ['@storybook/addon-essentials' <% if(interactionTests) { %>, '@storybook/addon-interactions' <% } %><% if(uiFramework === '@storybook/react-webpack5') { %>, '@nx/react/plugins/storybook' <% } %><% if(uiFramework === '@storybook/react-native') { %>, '@storybook/addon-ondevice-actions', '@storybook/addon-ondevice-backgrounds', '@storybook/addon-ondevice-controls', '@storybook/addon-ondevice-notes' <% } %>], framework: { name: '<%= uiFramework %>', options: { diff --git a/packages/storybook/src/generators/configuration/project-files/.storybook/main.js__tmpl__ b/packages/storybook/src/generators/configuration/project-files/.storybook/main.js__tmpl__ index 1ff156c232267..67a0e00d9b5b4 100644 --- a/packages/storybook/src/generators/configuration/project-files/.storybook/main.js__tmpl__ +++ b/packages/storybook/src/generators/configuration/project-files/.storybook/main.js__tmpl__ @@ -4,7 +4,7 @@ const config = { '../**/*.stories.@(js|jsx|ts|tsx|mdx)' <% } else { %> '../<%= projectDirectory %>/**/*.stories.@(js|jsx|ts|tsx|mdx)' <% } %>], - addons: ['@storybook/addon-essentials' <% if(uiFramework === '@storybook/react-webpack5') { %>, '@nx/react/plugins/storybook' <% } %><% if(uiFramework === '@storybook/react-native') { %>, '@storybook/addon-ondevice-actions', '@storybook/addon-ondevice-backgrounds', '@storybook/addon-ondevice-controls', '@storybook/addon-ondevice-notes' <% } %>], + addons: ['@storybook/addon-essentials' <% if(interactionTests) { %>, '@storybook/addon-interactions' <% } %><% if(uiFramework === '@storybook/react-webpack5') { %>, '@nx/react/plugins/storybook' <% } %><% if(uiFramework === '@storybook/react-native') { %>, '@storybook/addon-ondevice-actions', '@storybook/addon-ondevice-backgrounds', '@storybook/addon-ondevice-controls', '@storybook/addon-ondevice-notes' <% } %>], framework: { name: '<%= uiFramework %>', options: { diff --git a/packages/storybook/src/generators/configuration/schema.d.ts b/packages/storybook/src/generators/configuration/schema.d.ts index d839c71d70aad..c41c2523a5c8d 100644 --- a/packages/storybook/src/generators/configuration/schema.d.ts +++ b/packages/storybook/src/generators/configuration/schema.d.ts @@ -7,10 +7,10 @@ export interface StorybookConfigureSchema { configureCypress?: boolean; linter?: Linter; js?: boolean; + interactionTests?: boolean; tsConfiguration?: boolean; cypressDirectory?: string; standaloneConfig?: boolean; - configureTestRunner?: boolean; configureStaticServe?: boolean; skipFormat?: boolean; } diff --git a/packages/storybook/src/generators/configuration/schema.json b/packages/storybook/src/generators/configuration/schema.json index db29da5ad7a58..34190a94b6393 100644 --- a/packages/storybook/src/generators/configuration/schema.json +++ b/packages/storybook/src/generators/configuration/schema.json @@ -18,15 +18,22 @@ "x-dropdown": "projects", "x-priority": "important" }, + "interactionTests": { + "type": "boolean", + "description": "Set up Storybook interaction tests.", + "x-prompt": "Do you want to set up Storybook interaction tests?", + "alias": ["configureTestRunner"], + "default": true + }, "configureCypress": { "type": "boolean", "description": "Run the cypress-configure generator.", - "x-prompt": "Configure a cypress e2e app to run against the storybook instance?", - "x-priority": "important" + "x-deprecated": "Please use Storybook interaction tests instead." }, "cypressDirectory": { "type": "string", - "description": "A directory where the Cypress project will be placed. Added at root by default." + "description": "A directory where the Cypress project will be placed. Added at root by default.", + "x-deprecated": "Please use Storybook interaction tests instead." }, "linter": { "description": "The tool to use for running lint checks.", @@ -56,10 +63,6 @@ "description": "Add a static-storybook to serve the static storybook built files.", "default": false }, - "configureTestRunner": { - "type": "boolean", - "description": "Add a Storybook Test-Runner target." - }, "bundler": { "description": "The Storybook builder to use.", "type": "string", diff --git a/packages/storybook/src/migrations/update-14-0-0/migrate-defaults-5-to-6/migrate-defaults-5-to-6.ts b/packages/storybook/src/migrations/update-14-0-0/migrate-defaults-5-to-6/migrate-defaults-5-to-6.ts index de840cafb23cb..6d20313448739 100644 --- a/packages/storybook/src/migrations/update-14-0-0/migrate-defaults-5-to-6/migrate-defaults-5-to-6.ts +++ b/packages/storybook/src/migrations/update-14-0-0/migrate-defaults-5-to-6/migrate-defaults-5-to-6.ts @@ -196,6 +196,7 @@ function migrateProjectLevelStorybookInstance( root, projectType, false, + false, mainDir, !!nextBuildTarget, compiler === 'swc' diff --git a/packages/storybook/src/utils/versions.ts b/packages/storybook/src/utils/versions.ts index 83633c1779fe4..e62270f770354 100644 --- a/packages/storybook/src/utils/versions.ts +++ b/packages/storybook/src/utils/versions.ts @@ -1,7 +1,9 @@ export const nxVersion = require('../../package.json').version; export const storybookReactNativeVersion = '^6.5.3'; export const reactNativeStorybookLoader = '^2.0.5'; -export const storybookTestRunnerVersion = '^0.7.2'; +export const storybookTestRunnerVersion = '^0.11.0'; +export const storybookTestingLibraryVersion = '~0.2.0'; +export const storybookJestVersion = '~0.1.0'; export const litVersion = '^2.6.1'; export const tsNodeVersion = '10.9.1';