From 8a310256c65a76072ba90558204138e4eb73699d Mon Sep 17 00:00:00 2001 From: Katerina Skroumpelou Date: Mon, 20 Mar 2023 17:28:33 +0200 Subject: [PATCH] fix(storybook): improve and simplify e2e tests --- .github/workflows/e2e-matrix.yml | 3 - .github/workflows/e2e-windows.yml | 3 - docs/shared/mental-model/large-tasks.json | 107 -------------- e2e/storybook-angular/jest.config.ts | 10 -- e2e/storybook-angular/project.json | 11 -- .../src/storybook-angular.test.ts | 131 ------------------ e2e/storybook-angular/tsconfig.json | 13 -- e2e/storybook-angular/tsconfig.spec.json | 20 --- e2e/storybook/src/storybook-nested.test.ts | 54 ++------ e2e/storybook/src/storybook.test.ts | 131 ++++++++++++++++-- 10 files changed, 128 insertions(+), 355 deletions(-) delete mode 100644 e2e/storybook-angular/jest.config.ts delete mode 100644 e2e/storybook-angular/project.json delete mode 100644 e2e/storybook-angular/src/storybook-angular.test.ts delete mode 100644 e2e/storybook-angular/tsconfig.json delete mode 100644 e2e/storybook-angular/tsconfig.spec.json diff --git a/.github/workflows/e2e-matrix.yml b/.github/workflows/e2e-matrix.yml index 816a34d456a670..65ccc28df08fc6 100644 --- a/.github/workflows/e2e-matrix.yml +++ b/.github/workflows/e2e-matrix.yml @@ -81,7 +81,6 @@ jobs: - e2e-web - e2e-rollup - e2e-storybook - - e2e-storybook-angular - e2e-vite - e2e-webpack - e2e-workspace-create @@ -141,8 +140,6 @@ jobs: codeowners: 'S04SJ6PL98X' - project: e2e-storybook codeowners: 'S04SVQ8H0G5' - - project: e2e-storybook-angular - codeowners: 'S04SVQ8H0G5' - project: e2e-vite codeowners: 'S04SJ6PL98X' - project: e2e-webpack diff --git a/.github/workflows/e2e-windows.yml b/.github/workflows/e2e-windows.yml index db34abf6e1b0b7..adbaa9c708b5fc 100644 --- a/.github/workflows/e2e-windows.yml +++ b/.github/workflows/e2e-windows.yml @@ -69,7 +69,6 @@ jobs: - e2e-web - e2e-rollup - e2e-storybook - - e2e-storybook-angular - e2e-vite - e2e-webpack - e2e-workspace-create @@ -118,8 +117,6 @@ jobs: codeowners: 'S04SJ6PL98X' - project: e2e-storybook codeowners: 'S04SVQ8H0G5' - - project: e2e-storybook-angular - codeowners: 'S04SVQ8H0G5' - project: e2e-vite codeowners: 'S04SJ6PL98X' - project: e2e-webpack diff --git a/docs/shared/mental-model/large-tasks.json b/docs/shared/mental-model/large-tasks.json index 0931876c7fa5cb..0c68713cf7d180 100644 --- a/docs/shared/mental-model/large-tasks.json +++ b/docs/shared/mental-model/large-tasks.json @@ -1968,86 +1968,6 @@ } } }, - { - "name": "e2e-storybook-angular", - "type": "app", - "data": { - "tags": [], - "root": "e2e/storybook-angular", - "files": [ - { - "file": "e2e/storybook-angular/jest.config.ts", - "hash": "f29da5f0b7f58ba5d5ad69ebfc3e81f9bbe64fa0" - }, - { - "file": "e2e/storybook-angular/project.json", - "hash": "0215ebdd9ed974940c842be82cc2a61ad8af5c46" - }, - { - "file": "e2e/storybook-angular/src/storybook-angular.test.ts", - "hash": "6b6e047ea3ac78b26f2cc801092c90834c0ee803", - "deps": [ - "e2e-utils", - "npm:react", - "npm:@storybook/react", - "npm:@storybook/angular", - "npm:@angular/core" - ] - }, - { - "file": "e2e/storybook-angular/tsconfig.json", - "hash": "6d5abf84832009a8c70e7a910c49f332bf1f0612" - }, - { - "file": "e2e/storybook-angular/tsconfig.spec.json", - "hash": "1a24bfb0a13536cd17717808ca5609e15def438f" - } - ], - "targets": { - "e2e": { - "executor": "nx:run-commands", - "options": { - "commands": [ - { - "command": "yarn e2e-start-local-registry" - }, - { - "command": "yarn e2e-build-package-publish" - }, - { - "command": "nx run-e2e-tests e2e-storybook-angular" - } - ], - "parallel": false - }, - "inputs": [ - "default", - "^production", - { - "env": "SELECTED_CLI" - }, - { - "env": "NX_E2E_CI_CACHE_KEY" - } - ] - }, - "run-e2e-tests": { - "executor": "@nrwl/jest:jest", - "options": { - "jestConfig": "e2e/storybook/jest.config.ts", - "passWithNoTests": true, - "runInBand": true - }, - "outputs": ["{workspaceRoot}/coverage/e2e/storybook-angular"], - "inputs": [ - "default", - "^production", - "{workspaceRoot}/jest.preset.js" - ] - } - } - } - }, { "name": "nx-dev-feature-search", "type": "lib", @@ -30203,33 +30123,6 @@ }, "dependencies": { "nx-dev-ui-sponsor-card:test": [] } }, - "e2e-storybook-angular:e2e": { - "roots": ["e2e-storybook-angular:e2e"], - "tasks": { - "e2e-storybook-angular:e2e": { - "id": "e2e-storybook-angular:e2e", - "target": { "project": "e2e-storybook-angular", "target": "e2e" }, - "projectRoot": "e2e/storybook-angular", - "overrides": {} - } - }, - "dependencies": { "e2e-storybook-angular:e2e": [] } - }, - "e2e-storybook-angular:run-e2e-tests": { - "roots": ["e2e-storybook-angular:run-e2e-tests"], - "tasks": { - "e2e-storybook-angular:run-e2e-tests": { - "id": "e2e-storybook-angular:run-e2e-tests", - "target": { - "project": "e2e-storybook-angular", - "target": "run-e2e-tests" - }, - "projectRoot": "e2e/storybook-angular", - "overrides": {} - } - }, - "dependencies": { "e2e-storybook-angular:run-e2e-tests": [] } - }, "nx-dev-feature-search:lint": { "roots": ["nx-dev-feature-search:lint"], "tasks": { diff --git a/e2e/storybook-angular/jest.config.ts b/e2e/storybook-angular/jest.config.ts deleted file mode 100644 index f458af2210dcec..00000000000000 --- a/e2e/storybook-angular/jest.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -export default { - transform: { - '^.+\\.[tj]sx?$': ['ts-jest', { tsconfig: '/tsconfig.spec.json' }], - }, - moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'html'], - maxWorkers: 1, - globals: {}, - displayName: 'e2e-storybook-angular', - preset: '../../jest.preset.js', -}; diff --git a/e2e/storybook-angular/project.json b/e2e/storybook-angular/project.json deleted file mode 100644 index 543913e6b30979..00000000000000 --- a/e2e/storybook-angular/project.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "name": "e2e-storybook-angular", - "$schema": "../../node_modules/nx/schemas/project-schema.json", - "sourceRoot": "e2e/storybook-angular", - "projectType": "application", - "targets": { - "e2e": {}, - "run-e2e-tests": {} - }, - "implicitDependencies": ["storybook"] -} diff --git a/e2e/storybook-angular/src/storybook-angular.test.ts b/e2e/storybook-angular/src/storybook-angular.test.ts deleted file mode 100644 index b5f8e09d80b988..00000000000000 --- a/e2e/storybook-angular/src/storybook-angular.test.ts +++ /dev/null @@ -1,131 +0,0 @@ -import { - checkFilesExist, - cleanupProject, - getPackageManagerCommand, - killPorts, - newProject, - runCLI, - runCommand, - runCypressTests, - tmpProjPath, - uniq, - updateJson, -} from '@nrwl/e2e/utils'; -import { writeFileSync } from 'fs'; - -describe('Storybook for Angular', () => { - const angularStorybookLib = uniq('test-ui-lib'); - beforeAll(() => { - newProject(); - createTestUILib(angularStorybookLib); - runCLI( - `generate @nrwl/angular:storybook-configuration ${angularStorybookLib} --configureCypress --generateStories --generateCypressSpecs --no-interactive` - ); - - // TODO(jack): Overriding enhanced-resolve to 5.10.0 now until the package is fixed. - // TODO: Use --storybook7Configuration and remove this - // See: https://github.com/webpack/enhanced-resolve/issues/362 - updateJson('package.json', (json) => { - json['overrides'] = { - 'enhanced-resolve': '5.10.0', - }; - - return json; - }); - runCommand(getPackageManagerCommand().install); - - console.log('Here is the Nx report: '); - runCLI(`report`); - }); - - afterAll(() => { - cleanupProject(); - }); - - // TODO: Use --storybook7Configuration and re-enable this - xdescribe('Storybook builder', () => { - it('shoud build storybook', () => { - runCLI(`run ${angularStorybookLib}:build-storybook --verbose`); - checkFilesExist(`dist/storybook/${angularStorybookLib}/index.html`); - }); - }); - - // TODO: Use --storybook7Configuration and re-enable this - xdescribe('run cypress tests using storybook', () => { - it('should execute e2e tests using Cypress running against Storybook', async () => { - if (runCypressTests()) { - writeFileSync( - tmpProjPath( - `apps/${angularStorybookLib}-e2e/src/e2e/test-button/test-button.component.cy.ts` - ), - ` - describe('${angularStorybookLib}, () => { - - it('should render the correct text', () => { - cy.visit( - '/iframe.html?id=testbuttoncomponent--primary&args=text:Click+me;color:#ddffdd;disabled:false;' - ) - cy.get('button').should('contain', 'Click me'); - cy.get('button').should('not.be.disabled'); - }); - - it('should adjust the controls', () => { - cy.visit( - '/iframe.html?id=testbuttoncomponent--primary&args=text:Click+me;color:#ddffdd;disabled:true;' - ) - cy.get('button').should('be.disabled'); - }); - }); - ` - ); - - const e2eResults = runCLI(`e2e ${angularStorybookLib}-e2e --no-watch`); - expect(e2eResults).toContain('All specs passed!'); - expect(await killPorts()).toBeTruthy(); - } - }, 1000000); - }); -}); - -export function createTestUILib(libName: string): void { - runCLI(`g @nrwl/angular:library ${libName} --no-interactive`); - runCLI( - `g @nrwl/angular:component test-button --project=${libName} --no-interactive` - ); - - writeFileSync( - tmpProjPath(`libs/${libName}/src/lib/test-button/test-button.component.ts`), - ` - import { Component, Input } from '@angular/core'; - - @Component({ - selector: 'proj-test-button', - templateUrl: './test-button.component.html', - styleUrls: ['./test-button.component.css'], - }) - export class TestButtonComponent { - @Input() text = 'Click me'; - @Input() color = '#ddffdd'; - @Input() disabled = false; - } - ` - ); - - writeFileSync( - tmpProjPath( - `libs/${libName}/src/lib/test-button/test-button.component.html` - ), - ` - - ` - ); - runCLI( - `g @nrwl/angular:component test-other --project=${libName} --no-interactive` - ); -} diff --git a/e2e/storybook-angular/tsconfig.json b/e2e/storybook-angular/tsconfig.json deleted file mode 100644 index 6d5abf84832009..00000000000000 --- a/e2e/storybook-angular/tsconfig.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "types": ["node", "jest"] - }, - "include": [], - "files": [], - "references": [ - { - "path": "./tsconfig.spec.json" - } - ] -} diff --git a/e2e/storybook-angular/tsconfig.spec.json b/e2e/storybook-angular/tsconfig.spec.json deleted file mode 100644 index 1a24bfb0a13536..00000000000000 --- a/e2e/storybook-angular/tsconfig.spec.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "outDir": "../../dist/out-tsc", - "module": "commonjs", - "types": ["jest", "node"] - }, - "include": [ - "**/*.test.ts", - "**/*.spec.ts", - "**/*.spec.tsx", - "**/*.test.tsx", - "**/*.spec.js", - "**/*.test.js", - "**/*.spec.jsx", - "**/*.test.jsx", - "**/*.d.ts", - "jest.config.ts" - ] -} diff --git a/e2e/storybook/src/storybook-nested.test.ts b/e2e/storybook/src/storybook-nested.test.ts index 33e60caf5fbd99..6554e959147547 100644 --- a/e2e/storybook/src/storybook-nested.test.ts +++ b/e2e/storybook/src/storybook-nested.test.ts @@ -1,35 +1,26 @@ import { checkFilesExist, cleanupProject, - getPackageManagerCommand, - getSelectedPackageManager, killPorts, readJson, runCLI, - runCommand, runCommandUntil, runCreateWorkspace, tmpProjPath, uniq, - updateJson, } from '@nrwl/e2e/utils'; import { writeFileSync } from 'fs'; -describe('Storybook generators for nested workspaces', () => { - const previousPM = process.env.SELECTED_PM; +describe('Storybook generators and executors for standalone workspaces - using React + Vite', () => { const wsName = uniq('react'); const appName = uniq('app'); - const packageManager = getSelectedPackageManager() || 'yarn'; beforeAll(() => { - process.env.SELECTED_PM = 'yarn'; - // create a workspace with a single react app at the root runCreateWorkspace(wsName, { preset: 'react-standalone', appName, style: 'css', - packageManager, bundler: 'vite', }); @@ -37,26 +28,11 @@ describe('Storybook generators for nested workspaces', () => { `generate @nrwl/react:storybook-configuration ${appName} --generateStories --no-interactive` ); - // TODO(jack): Overriding enhanced-resolve to 5.10.0 now until the package is fixed. - // TODO: Use --storybook7Configuration and remove this - // See: https://github.com/webpack/enhanced-resolve/issues/362 - updateJson('package.json', (json) => { - json['overrides'] = { - 'enhanced-resolve': '5.10.0', - }; - - return json; - }); - - runCommand(getPackageManagerCommand().install); - - console.log('Here is the Nx report: '); runCLI(`report`); }); afterAll(() => { cleanupProject(); - process.env.SELECTED_PM = previousPM; }); describe('Storybook generated files', () => { @@ -80,39 +56,33 @@ describe('Storybook generators for nested workspaces', () => { `generate @nrwl/react:storybook-configuration ${nestedAppName} --generateStories --no-interactive` ); checkFilesExist( - `${nestedAppName}/.storybook/main.js`, - `${nestedAppName}/.storybook/tsconfig.json` + `apps/${nestedAppName}/.storybook/main.js`, + `apps/${nestedAppName}/.storybook/tsconfig.json` ); }); }); - // TODO: Use --storybook7Configuration and re-enable this test + // TODO: Use --storybook7Configuration and re-enable this test - or else it NEEDS NODE 16 xdescribe('serve storybook', () => { afterEach(() => killPorts()); - it('should run a React based Storybook setup', async () => { - // serve the storybook + it('should serve a React based Storybook setup that uses Vite', async () => { const p = await runCommandUntil(`run ${appName}:storybook`, (output) => { return /Storybook.*started/gi.test(output); }); p.kill(); - }, 1000000); + }, 60000); }); - // TODO: Use --storybook7Configuration and re-enable this test + // TODO: Use --storybook7Configuration and re-enable this test - or else it NEEDS NODE 16 xdescribe('build storybook', () => { - it('should build and lint a React based storybook', () => { - // build + it('should build a React based storybook that uses Vite', () => { runCLI(`run ${appName}:build-storybook --verbose`); checkFilesExist(`dist/storybook/${appName}/index.html`); + }, 60000); - // lint - const output = runCLI(`run ${appName}:lint`); - expect(output).toContain('All files pass linting.'); - }, 1000000); - - // Not sure how much sense this test makes - maybe it's noise? - xit('should build a React based storybook that references another lib', () => { + // This test makes sure path resolution works + xit('should build a React based storybook that references another lib and uses Vite', () => { const reactLib = uniq('test-lib-react'); runCLI(`generate @nrwl/react:lib ${reactLib} --no-interactive`); // create a React component we can reference @@ -168,6 +138,6 @@ describe('Storybook generators for nested workspaces', () => { // build React lib runCLI(`run ${reactLib}:build-storybook --verbose`); checkFilesExist(`dist/storybook/${reactLib}/index.html`); - }, 1000000); + }, 60000); }); }); diff --git a/e2e/storybook/src/storybook.test.ts b/e2e/storybook/src/storybook.test.ts index 98a1942516540a..2bbc8b096800e9 100644 --- a/e2e/storybook/src/storybook.test.ts +++ b/e2e/storybook/src/storybook.test.ts @@ -10,17 +10,28 @@ import { runCommand, newProject, updateJson, + runCypressTests, } from '@nrwl/e2e/utils'; import { writeFileSync } from 'fs'; -describe('Storybook generators for non-angular projects', () => { +describe('Storybook generators and executors for monorepos', () => { + const previousPM = process.env.SELECTED_PM; const reactStorybookLib = uniq('test-ui-lib-react'); + const angularStorybookLib = uniq('test-ui-lib'); let proj; beforeAll(() => { - proj = newProject(); + process.env.SELECTED_PM = 'yarn'; + proj = newProject({ + packageManager: 'yarn', + }); runCLI(`generate @nrwl/react:lib ${reactStorybookLib} --no-interactive`); runCLI( - `generate @nrwl/react:storybook-configuration ${reactStorybookLib} --generateStories --no-interactive` + `generate @nrwl/react:storybook-configuration ${reactStorybookLib} --generateStories --no-interactive --bundler=webpack` + ); + + createTestUILib(angularStorybookLib); + runCLI( + `generate @nrwl/angular:storybook-configuration ${angularStorybookLib} --configureCypress --generateStories --generateCypressSpecs --no-interactive` ); // TODO(jack): Overriding enhanced-resolve to 5.10.0 now until the package is fixed. @@ -41,13 +52,14 @@ describe('Storybook generators for non-angular projects', () => { afterAll(() => { cleanupProject(); + process.env.SELECTED_PM = previousPM; }); // TODO: Use --storybook7Configuration and re-enable this test - xdescribe('serve storybook', () => { + describe('serve storybook', () => { afterEach(() => killPorts()); - it('should run a React based Storybook setup', async () => { + it('should serve a React based Storybook setup that uses webpack', async () => { // serve the storybook const p = await runCommandUntil( `run ${reactStorybookLib}:storybook`, @@ -56,23 +68,34 @@ describe('Storybook generators for non-angular projects', () => { } ); p.kill(); - }, 1000000); + }, 60000); + + it('should serve an Angular based Storybook setup', async () => { + // serve the storybook + const p = await runCommandUntil( + `run ${angularStorybookLib}:storybook`, + (output) => { + return /Storybook.*started/gi.test(output); + } + ); + p.kill(); + }, 60000); }); - // TODO: Use --storybook7Configuration and re-enable this test - xdescribe('build storybook', () => { - it('should build and lint a React based storybook', () => { + describe('build storybook', () => { + it('should build a React based storybook setup that uses webpack', () => { // build runCLI(`run ${reactStorybookLib}:build-storybook --verbose`); checkFilesExist(`dist/storybook/${reactStorybookLib}/index.html`); + }, 60000); - // lint - const output = runCLI(`run ${reactStorybookLib}:lint`); - expect(output).toContain('All files pass linting.'); - }, 1000000); + it('shoud build an Angular based storybook', () => { + runCLI(`run ${angularStorybookLib}:build-storybook --verbose`); + checkFilesExist(`dist/storybook/${angularStorybookLib}/index.html`); + }, 60000); - // I am not sure how much sense this test makes - Maybe it's just adding noise - xit('should build a React based storybook that references another lib', () => { + // This test makes sure path resolution works + it('should build a React based storybook that references another lib and uses webpack', () => { const anotherReactLib = uniq('test-another-lib-react'); runCLI(`generate @nrwl/react:lib ${anotherReactLib} --no-interactive`); // create a React component we can reference @@ -125,4 +148,82 @@ describe('Storybook generators for non-angular projects', () => { checkFilesExist(`dist/storybook/${reactStorybookLib}/index.html`); }, 1000000); }); + + describe('run cypress tests using storybook', () => { + it('should execute e2e tests using Cypress running against Storybook', async () => { + if (runCypressTests()) { + writeFileSync( + tmpProjPath( + `apps/${angularStorybookLib}-e2e/src/e2e/test-button/test-button.component.cy.ts` + ), + ` + describe('${angularStorybookLib}, () => { + + it('should render the correct text', () => { + cy.visit( + '/iframe.html?id=testbuttoncomponent--primary&args=text:Click+me;color:#ddffdd;disabled:false;' + ) + cy.get('button').should('contain', 'Click me'); + cy.get('button').should('not.be.disabled'); + }); + + it('should adjust the controls', () => { + cy.visit( + '/iframe.html?id=testbuttoncomponent--primary&args=text:Click+me;color:#ddffdd;disabled:true;' + ) + cy.get('button').should('be.disabled'); + }); + }); + ` + ); + + const e2eResults = runCLI(`e2e ${angularStorybookLib}-e2e --no-watch`); + expect(e2eResults).toContain('All specs passed!'); + expect(await killPorts()).toBeTruthy(); + } + }, 1000000); + }); }); + +export function createTestUILib(libName: string): void { + runCLI(`g @nrwl/angular:library ${libName} --no-interactive`); + runCLI( + `g @nrwl/angular:component test-button --project=${libName} --no-interactive` + ); + + writeFileSync( + tmpProjPath(`libs/${libName}/src/lib/test-button/test-button.component.ts`), + ` + import { Component, Input } from '@angular/core'; + + @Component({ + selector: 'proj-test-button', + templateUrl: './test-button.component.html', + styleUrls: ['./test-button.component.css'], + }) + export class TestButtonComponent { + @Input() text = 'Click me'; + @Input() color = '#ddffdd'; + @Input() disabled = false; + } + ` + ); + + writeFileSync( + tmpProjPath( + `libs/${libName}/src/lib/test-button/test-button.component.html` + ), + ` + + ` + ); + runCLI( + `g @nrwl/angular:component test-other --project=${libName} --no-interactive` + ); +}