Revert "feat(repo): update storybook to v7 (#16174)" (#16264)

This commit is contained in:
Jason Jean 2023-04-12 11:46:56 -04:00 committed by GitHub
parent e5b48ac956
commit d2f855502a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 4943 additions and 1935 deletions

View File

@ -6,7 +6,7 @@
}, },
"ignorePatterns": ["**/*.ts"], "ignorePatterns": ["**/*.ts"],
"plugins": ["@typescript-eslint", "@nrwl/nx"], "plugins": ["@typescript-eslint", "@nrwl/nx"],
"extends": ["plugin:storybook/recommended"], "extends": [],
"rules": { "rules": {
"@typescript-eslint/explicit-module-boundary-types": "off", "@typescript-eslint/explicit-module-boundary-types": "off",
"no-restricted-imports": ["error", "create-nx-workspace"] "no-restricted-imports": ["error", "create-nx-workspace"]

View File

@ -15,7 +15,7 @@ describe('Storybook executors for Angular', () => {
const angularStorybookLib = uniq('test-ui-ng-lib'); const angularStorybookLib = uniq('test-ui-ng-lib');
beforeAll(() => { beforeAll(() => {
newProject(); newProject();
runCLI(`g @nrwl/angular:library ${angularStorybookLib} --no-interactive`); createTestUILib(angularStorybookLib);
runCLI( runCLI(
`generate @nrwl/angular:storybook-configuration ${angularStorybookLib} --configureCypress --generateStories --generateCypressSpecs --no-interactive` `generate @nrwl/angular:storybook-configuration ${angularStorybookLib} --configureCypress --generateStories --generateCypressSpecs --no-interactive`
); );
@ -25,7 +25,8 @@ describe('Storybook executors for Angular', () => {
cleanupProject(); cleanupProject();
}); });
describe('serve and build storybook', () => { // TODO: Enable on SB7
xdescribe('serve and build storybook', () => {
afterAll(() => killPorts()); afterAll(() => killPorts());
it('should serve an Angular based Storybook setup', async () => { it('should serve an Angular based Storybook setup', async () => {
@ -48,7 +49,6 @@ describe('Storybook executors for Angular', () => {
xdescribe('run cypress tests using storybook', () => { xdescribe('run cypress tests using storybook', () => {
it('should execute e2e tests using Cypress running against Storybook', async () => { it('should execute e2e tests using Cypress running against Storybook', async () => {
if (runCypressTests()) { if (runCypressTests()) {
addTestButtonToUILib(angularStorybookLib);
writeFileSync( writeFileSync(
tmpProjPath( tmpProjPath(
`apps/${angularStorybookLib}-e2e/src/e2e/test-button/test-button.component.cy.ts` `apps/${angularStorybookLib}-e2e/src/e2e/test-button/test-button.component.cy.ts`
@ -82,7 +82,8 @@ describe('Storybook executors for Angular', () => {
}); });
}); });
function addTestButtonToUILib(libName: string): void { export function createTestUILib(libName: string): void {
runCLI(`g @nrwl/angular:library ${libName} --no-interactive`);
runCLI( runCLI(
`g @nrwl/angular:component test-button --project=${libName} --no-interactive` `g @nrwl/angular:component test-button --project=${libName} --no-interactive`
); );

View File

@ -1,7 +1,6 @@
import { import {
checkFilesExist, checkFilesExist,
cleanupProject, cleanupProject,
getSelectedPackageManager,
killPorts, killPorts,
readJson, readJson,
runCLI, runCLI,
@ -11,7 +10,6 @@ import {
uniq, uniq,
} from '@nrwl/e2e/utils'; } from '@nrwl/e2e/utils';
import { writeFileSync } from 'fs'; import { writeFileSync } from 'fs';
import { createFileSync } from 'fs-extra';
describe('Storybook generators and executors for standalone workspaces - using React + Vite', () => { describe('Storybook generators and executors for standalone workspaces - using React + Vite', () => {
const wsName = uniq('react'); const wsName = uniq('react');
@ -24,7 +22,6 @@ describe('Storybook generators and executors for standalone workspaces - using R
appName, appName,
style: 'css', style: 'css',
bundler: 'vite', bundler: 'vite',
packageManager: getSelectedPackageManager(),
}); });
runCLI( runCLI(
@ -53,7 +50,8 @@ describe('Storybook generators and executors for standalone workspaces - using R
}); });
}); });
describe('serve storybook', () => { // TODO: Use --storybook7Configuration and re-enable this test - or else it NEEDS NODE 16
xdescribe('serve storybook', () => {
afterEach(() => killPorts()); afterEach(() => killPorts());
it('should serve a React based Storybook setup that uses Vite', async () => { it('should serve a React based Storybook setup that uses Vite', async () => {
@ -61,86 +59,73 @@ describe('Storybook generators and executors for standalone workspaces - using R
return /Storybook.*started/gi.test(output); return /Storybook.*started/gi.test(output);
}); });
p.kill(); p.kill();
}, 60000); }, 40000);
}); });
describe('build storybook', () => { // TODO: Use --storybook7Configuration and re-enable this test - or else it NEEDS NODE 16
xdescribe('build storybook', () => {
it('should build a React based storybook that uses Vite', () => { it('should build a React based storybook that uses Vite', () => {
runCLI(`run ${appName}:build-storybook --verbose`); runCLI(`run ${appName}:build-storybook --verbose`);
checkFilesExist(`dist/storybook/${appName}/index.html`); checkFilesExist(`dist/storybook/${appName}/index.html`);
}, 60000); }, 40000);
// This needs fixing on the Storybook side // This test makes sure path resolution works
// vite paths resolution is not working on standalone
xit('should build a React based storybook that references another lib and uses Vite', () => { xit('should build a React based storybook that references another lib and uses Vite', () => {
const anotherReactLib = uniq('test-another-lib-react'); const reactLib = uniq('test-lib-react');
runCLI(`generate @nrwl/react:lib ${anotherReactLib} --no-interactive`); runCLI(`generate @nrwl/react:lib ${reactLib} --no-interactive`);
// create a React component we can reference // create a React component we can reference
createFileSync(tmpProjPath(`${anotherReactLib}/src/lib/mytestcmp.tsx`));
writeFileSync( writeFileSync(
tmpProjPath(`${anotherReactLib}/src/lib/mytestcmp.tsx`), tmpProjPath(`${reactLib}/src/lib/mytestcmp.tsx`),
` `
export function MyTestCmp() { import React from 'react';
return (
<div> /* eslint-disable-next-line */
<h1>Welcome to OtherLib!</h1> export interface MyTestCmpProps {}
</div>
); export const MyTestCmp = (props: MyTestCmpProps) => {
} return (
<div>
export default MyTestCmp; <h1>Welcome to test cmp!</h1>
</div>
);
};
export default MyTestCmp;
` `
); );
// update index.ts and export it // update index.ts and export it
writeFileSync( writeFileSync(
tmpProjPath(`${anotherReactLib}/src/index.ts`), tmpProjPath(`${reactLib}/src/index.ts`),
` `
export * from './lib/mytestcmp'; export * from './lib/mytestcmp';
` `
); );
// create a component and a story in the first lib to reference the cmp from the 2nd lib
createFileSync(tmpProjPath(`src/app/test-button.tsx`));
writeFileSync(
tmpProjPath(`src/app/test-button.tsx`),
`
import { MyTestCmp } from '@${wsName}/${anotherReactLib}';
export function TestButton() {
return (
<div>
<MyTestCmp />
</div>
);
}
export default TestButton;
`
);
// create a story in the first lib to reference the cmp from the 2nd lib // create a story in the first lib to reference the cmp from the 2nd lib
createFileSync(tmpProjPath(`src/app/test-button.stories.tsx`));
writeFileSync( writeFileSync(
tmpProjPath(`src/app/test-button.stories.tsx`), tmpProjPath(`${reactLib}/src/lib/myteststory.stories.tsx`),
`
import React from 'react';
import { MyTestCmp, MyTestCmpProps } from '@${wsName}/${reactLib}';
export default {
component: MyTestCmp,
title: 'MyTestCmp',
};
export const primary = () => {
/* eslint-disable-next-line */
const props: MyTestCmpProps = {};
return <MyTestCmp />;
};
` `
import type { Meta } from '@storybook/react';
import { TestButton } from './test-button';
const Story: Meta<typeof TestButton> = {
component: TestButton,
title: 'TestButton',
};
export default Story;
export const Primary = {
args: {},
};
`
); );
// build React lib // build React lib
runCLI(`run ${appName}:build-storybook --verbose`); runCLI(`run ${reactLib}:build-storybook --verbose`);
checkFilesExist(`dist/storybook/${appName}/index.html`); checkFilesExist(`dist/storybook/${reactLib}/index.html`);
}, 60000); }, 40000);
}); });
}); });

View File

@ -2,28 +2,47 @@ import {
checkFilesExist, checkFilesExist,
cleanupProject, cleanupProject,
killPorts, killPorts,
newProject,
runCLI, runCLI,
runCommandUntil, runCommandUntil,
tmpProjPath, tmpProjPath,
uniq, uniq,
getPackageManagerCommand,
runCommand,
newProject,
updateJson,
} from '@nrwl/e2e/utils'; } from '@nrwl/e2e/utils';
import { writeFileSync } from 'fs'; import { writeFileSync } from 'fs';
// TODO: re-enable once the issue is fixed with long build times describe('Storybook generators and executors for monorepos', () => {
describe.skip('Storybook generators and executors for monorepos', () => { const previousPM = process.env.SELECTED_PM;
const reactStorybookLib = uniq('test-ui-lib-react'); const reactStorybookLib = uniq('test-ui-lib-react');
let proj; let proj;
beforeAll(() => { beforeAll(() => {
proj = newProject(); process.env.SELECTED_PM = 'yarn';
proj = newProject({
packageManager: 'yarn',
});
runCLI(`generate @nrwl/react:lib ${reactStorybookLib} --no-interactive`); runCLI(`generate @nrwl/react:lib ${reactStorybookLib} --no-interactive`);
runCLI( runCLI(
`generate @nrwl/react:storybook-configuration ${reactStorybookLib} --generateStories --no-interactive --bundler=webpack` `generate @nrwl/react:storybook-configuration ${reactStorybookLib} --generateStories --no-interactive --bundler=webpack`
); );
// 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);
}); });
afterAll(() => { afterAll(() => {
cleanupProject(); cleanupProject();
process.env.SELECTED_PM = previousPM;
}); });
describe('serve and build storybook', () => { describe('serve and build storybook', () => {
@ -38,13 +57,13 @@ describe.skip('Storybook generators and executors for monorepos', () => {
} }
); );
p.kill(); p.kill();
}, 60000); }, 50000);
it('should build a React based storybook setup that uses webpack', () => { it('should build a React based storybook setup that uses webpack', () => {
// build // build
runCLI(`run ${reactStorybookLib}:build-storybook --verbose`); runCLI(`run ${reactStorybookLib}:build-storybook --verbose`);
checkFilesExist(`dist/storybook/${reactStorybookLib}/index.html`); checkFilesExist(`dist/storybook/${reactStorybookLib}/index.html`);
}, 60000); }, 50000);
// This test makes sure path resolution works // This test makes sure path resolution works
it('should build a React based storybook that references another lib and uses webpack', () => { it('should build a React based storybook that references another lib and uses webpack', () => {
@ -98,6 +117,6 @@ describe.skip('Storybook generators and executors for monorepos', () => {
// build React lib // build React lib
runCLI(`run ${reactStorybookLib}:build-storybook --verbose`); runCLI(`run ${reactStorybookLib}:build-storybook --verbose`);
checkFilesExist(`dist/storybook/${reactStorybookLib}/index.html`); checkFilesExist(`dist/storybook/${reactStorybookLib}/index.html`);
}, 60000); }, 50000);
}); });
}); });

View File

@ -1,16 +1,12 @@
/* eslint-disable storybook/no-uninstalled-addons */
module.exports = { module.exports = {
stories: ['../src/app/**/*.stories.@(mdx|js|jsx|ts|tsx)'], core: { builder: 'webpack5' },
stories: [
'../src/app/**/*.stories.mdx',
'../src/app/**/*.stories.@(js|jsx|ts|tsx)',
],
addons: [ addons: [
'@storybook/addon-essentials', '@storybook/addon-essentials',
'@nrwl/react/plugins/storybook', '@nrwl/react/plugins/storybook',
'storybook-dark-mode', 'storybook-dark-mode',
], ],
framework: {
name: '@storybook/react-webpack5',
options: {},
},
docs: {
autodocs: true,
},
}; };

View File

@ -245,6 +245,7 @@
"storybook": { "storybook": {
"executor": "@nrwl/storybook:storybook", "executor": "@nrwl/storybook:storybook",
"options": { "options": {
"uiFramework": "@storybook/react",
"port": 4400, "port": 4400,
"configDir": "graph/client/.storybook" "configDir": "graph/client/.storybook"
}, },
@ -258,6 +259,7 @@
"executor": "@nrwl/storybook:build", "executor": "@nrwl/storybook:build",
"outputs": ["{options.outputDir}"], "outputs": ["{options.outputDir}"],
"options": { "options": {
"uiFramework": "@storybook/react",
"configDir": "graph/client/.storybook", "configDir": "graph/client/.storybook",
"outputDir": "dist/storybook/graph-client" "outputDir": "dist/storybook/graph-client"
}, },

View File

@ -1,12 +1,8 @@
/* eslint-disable storybook/no-uninstalled-addons */
module.exports = { module.exports = {
stories: ['../src/lib/**/*.stories.@(mdx|js|jsx|ts|tsx)'], core: { builder: 'webpack5' },
stories: [
'../src/lib/**/*.stories.mdx',
'../src/lib/**/*.stories.@(js|jsx|ts|tsx)',
],
addons: ['@storybook/addon-essentials', '@nrwl/react/plugins/storybook'], addons: ['@storybook/addon-essentials', '@nrwl/react/plugins/storybook'],
framework: {
name: '@storybook/react-webpack5',
options: {},
},
docs: {
autodocs: true,
},
}; };

View File

@ -10,6 +10,7 @@
"storybook": { "storybook": {
"executor": "@nrwl/storybook:storybook", "executor": "@nrwl/storybook:storybook",
"options": { "options": {
"uiFramework": "@storybook/react",
"port": 4400, "port": 4400,
"configDir": "graph/ui-components/.storybook" "configDir": "graph/ui-components/.storybook"
}, },
@ -23,6 +24,7 @@
"executor": "@nrwl/storybook:build", "executor": "@nrwl/storybook:build",
"outputs": ["{options.outputDir}"], "outputs": ["{options.outputDir}"],
"options": { "options": {
"uiFramework": "@storybook/react",
"configDir": "graph/ui-components/.storybook", "configDir": "graph/ui-components/.storybook",
"outputDir": "dist/storybook/graph-ui-components" "outputDir": "dist/storybook/graph-ui-components"
}, },

View File

@ -1,12 +1,8 @@
/* eslint-disable storybook/no-uninstalled-addons */
module.exports = { module.exports = {
stories: ['../src/lib/**/*.stories.@(mdx|js|jsx|ts|tsx)'], core: { builder: 'webpack5' },
stories: [
'../src/lib/**/*.stories.mdx',
'../src/lib/**/*.stories.@(js|jsx|ts|tsx)',
],
addons: ['@storybook/addon-essentials', '@nrwl/react/plugins/storybook'], addons: ['@storybook/addon-essentials', '@nrwl/react/plugins/storybook'],
framework: {
name: '@storybook/react-webpack5',
options: {},
},
docs: {
autodocs: true,
},
}; };

View File

@ -10,6 +10,7 @@
"storybook": { "storybook": {
"executor": "@nrwl/storybook:storybook", "executor": "@nrwl/storybook:storybook",
"options": { "options": {
"uiFramework": "@storybook/react",
"port": 4400, "port": 4400,
"configDir": "graph/ui-graph/.storybook" "configDir": "graph/ui-graph/.storybook"
}, },
@ -23,6 +24,7 @@
"executor": "@nrwl/storybook:build", "executor": "@nrwl/storybook:build",
"outputs": ["{options.outputDir}"], "outputs": ["{options.outputDir}"],
"options": { "options": {
"uiFramework": "@storybook/react",
"configDir": "graph/ui-graph/.storybook", "configDir": "graph/ui-graph/.storybook",
"outputDir": "dist/storybook/graph-ui-graph" "outputDir": "dist/storybook/graph-ui-graph"
}, },

View File

@ -1,12 +1,8 @@
/* eslint-disable storybook/no-uninstalled-addons */
module.exports = { module.exports = {
stories: ['../src/lib/**/*.stories.@(mdx|js|jsx|ts|tsx)'], core: { builder: 'webpack5' },
stories: [
'../src/lib/**/*.stories.mdx',
'../src/lib/**/*.stories.@(js|jsx|ts|tsx)',
],
addons: ['@storybook/addon-essentials', '@nrwl/react/plugins/storybook'], addons: ['@storybook/addon-essentials', '@nrwl/react/plugins/storybook'],
framework: {
name: '@storybook/react-webpack5',
options: {},
},
docs: {
autodocs: true,
},
}; };

View File

@ -10,6 +10,7 @@
"storybook": { "storybook": {
"executor": "@nrwl/storybook:storybook", "executor": "@nrwl/storybook:storybook",
"options": { "options": {
"uiFramework": "@storybook/react",
"port": 4400, "port": 4400,
"configDir": "graph/ui-tooltips/.storybook" "configDir": "graph/ui-tooltips/.storybook"
}, },
@ -23,6 +24,7 @@
"executor": "@nrwl/storybook:build", "executor": "@nrwl/storybook:build",
"outputs": ["{options.outputDir}"], "outputs": ["{options.outputDir}"],
"options": { "options": {
"uiFramework": "@storybook/react",
"configDir": "graph/ui-tooltips/.storybook", "configDir": "graph/ui-tooltips/.storybook",
"outputDir": "dist/storybook/graph-ui-tooltips" "outputDir": "dist/storybook/graph-ui-tooltips"
}, },

View File

@ -82,12 +82,13 @@
"@rollup/plugin-node-resolve": "^13.0.4", "@rollup/plugin-node-resolve": "^13.0.4",
"@rollup/plugin-url": "^7.0.0", "@rollup/plugin-url": "^7.0.0",
"@schematics/angular": "~15.2.0", "@schematics/angular": "~15.2.0",
"@storybook/addon-essentials": "^7.0.2", "@storybook/addon-essentials": "^6.5.15",
"@storybook/angular": "^7.0.2", "@storybook/angular": "^6.5.15",
"@storybook/core-server": "^7.0.2", "@storybook/builder-webpack5": "^6.5.15",
"@storybook/react": "^7.0.2", "@storybook/core-server": "^6.5.15",
"@storybook/react-webpack5": "^7.0.2", "@storybook/manager-webpack5": "^6.5.15",
"@storybook/types": "^7.0.2", "@storybook/react": "^6.5.15",
"@storybook/types": "^7.0.0-alpha.44",
"@svgr/rollup": "^6.1.2", "@svgr/rollup": "^6.1.2",
"@svgr/webpack": "^6.1.2", "@svgr/webpack": "^6.1.2",
"@swc-node/register": "^1.4.2", "@swc-node/register": "^1.4.2",
@ -158,7 +159,6 @@
"eslint-plugin-jsx-a11y": "6.6.1", "eslint-plugin-jsx-a11y": "6.6.1",
"eslint-plugin-react": "7.31.11", "eslint-plugin-react": "7.31.11",
"eslint-plugin-react-hooks": "4.6.0", "eslint-plugin-react-hooks": "4.6.0",
"eslint-plugin-storybook": "^0.6.11",
"express": "^4.18.1", "express": "^4.18.1",
"fast-xml-parser": "^4.0.9", "fast-xml-parser": "^4.0.9",
"file-loader": "^6.2.0", "file-loader": "^6.2.0",
@ -232,7 +232,7 @@
"source-map": "0.7.3", "source-map": "0.7.3",
"source-map-loader": "^3.0.0", "source-map-loader": "^3.0.0",
"source-map-support": "0.5.19", "source-map-support": "0.5.19",
"storybook-dark-mode": "^3.0.0", "storybook-dark-mode": "^1.1.2",
"style-loader": "^3.3.0", "style-loader": "^3.3.0",
"styled-components": "5.3.6", "styled-components": "5.3.6",
"stylus": "^0.55.0", "stylus": "^0.55.0",

View File

@ -1,17 +1,12 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP // Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`StorybookConfiguration generator should configure storybook to use webpack 5 1`] = ` exports[`StorybookConfiguration generator should configure storybook to use webpack 5 1`] = `
"const config = { "module.exports = {
stories: ['../**/*.stories.@(js|jsx|ts|tsx|mdx)'], core: { builder: 'webpack5' },
stories: ['../**/*.stories.mdx', '../**/*.stories.@(js|jsx|ts|tsx)'],
addons: ['@storybook/addon-essentials'], addons: ['@storybook/addon-essentials'],
framework: {
name: '@storybook/angular',
options: {},
},
}; };
export default config;
// To customize your webpack configuration you can use the webpackFinal field. // To customize your webpack configuration you can use the webpackFinal field.
// Check https://storybook.js.org/docs/react/builders/webpack#extending-storybooks-webpack-config // Check https://storybook.js.org/docs/react/builders/webpack#extending-storybooks-webpack-config
// and https://nx.dev/packages/storybook/documents/custom-builder-configs // and https://nx.dev/packages/storybook/documents/custom-builder-configs

View File

@ -24,35 +24,27 @@ describe('Build storybook', () => {
beforeEach(async () => { beforeEach(async () => {
options = { options = {
configDir: join(__dirname, `/../../utils/test-configs/.storybook`), configDir: join(__dirname, `/../../utils/test-configs/.storybook`),
uiFramework: '@storybook/react',
outputDir: `/root/dist/storybook`, outputDir: `/root/dist/storybook`,
}; };
context = executorContext as ExecutorContext; context = executorContext as ExecutorContext;
}); });
it('should call the storybook build', async () => { it('should call the storybook buildStaticStandalone', async () => {
const loggerSpy = jest.spyOn(logger, 'info'); const loggerSpy = jest.spyOn(logger, 'info');
const buildSpy = jest const standaloneSpy = jest
.spyOn(build, 'build') .spyOn(build, 'buildStaticStandalone')
.mockImplementation(() => Promise.resolve()); .mockImplementation(() => Promise.resolve());
const result = await storybookBuilder(options, context); const result = await storybookBuilder(options, context);
expect(buildSpy).toHaveBeenCalled(); expect(standaloneSpy).toHaveBeenCalled();
expect(loggerSpy).toHaveBeenNthCalledWith( expect(loggerSpy).toHaveBeenCalledWith(`NX ui framework: @storybook/react`);
1, expect(loggerSpy).toHaveBeenCalledWith(
'NX Storybook builder starting ...' `NX Storybook files available in /root/dist/storybook`
); );
expect(loggerSpy).toHaveBeenNthCalledWith(
2,
'NX Storybook builder finished ...'
);
expect(loggerSpy).toHaveBeenNthCalledWith(
3,
'NX Storybook files available in /root/dist/storybook'
);
expect(result.success).toBeTruthy(); expect(result.success).toBeTruthy();
}); });
}); });

View File

@ -51,22 +51,15 @@ export default async function buildStorybookExecutor(
} }
} }
function runInstance( function runInstance(options: CLIOptions, storybook7: boolean): Promise<void> {
options: CLIOptions,
storybook7: boolean
): Promise<void | {
port: number;
address: string;
networkAddress: string;
}> {
const env = process.env.NODE_ENV ?? 'production'; const env = process.env.NODE_ENV ?? 'production';
process.env.NODE_ENV = env; process.env.NODE_ENV = env;
if (storybook7) { if (storybook7) {
return build.build({ return build['build']({
...options, ...options,
mode: 'static', mode: 'static',
}); } as any); // TODO(katerina): Change to actual types when Storybook 7
} else { } else {
const nodeVersion = process.version.slice(1).split('.'); const nodeVersion = process.version.slice(1).split('.');
if (+nodeVersion[0] === 18) { if (+nodeVersion[0] === 18) {

View File

@ -1,31 +1,45 @@
import { fs as fsMock, vol } from 'memfs';
import * as fs from 'fs';
import { ExecutorContext } from '@nrwl/devkit'; import { ExecutorContext } from '@nrwl/devkit';
jest.mock('@storybook/core-server', () => ({ jest.mock('@storybook/core-server', () => ({
buildDev: jest.fn().mockImplementation(() => Promise.resolve()), buildDev: jest.fn().mockImplementation(() => Promise.resolve()),
build: jest.fn().mockImplementation(() => build: jest.fn().mockImplementation(() => Promise.resolve()),
Promise.resolve({
port: 4400,
})
),
})); }));
import { build } from '@storybook/core-server'; import { buildDev } from '@storybook/core-server';
import storybookExecutor from './storybook.impl'; import storybookExecutor from './storybook.impl';
import { join } from 'path'; import { join } from 'path';
import { readFileSync } from 'fs-extra';
import { CLIOptions } from '@storybook/types'; import { CLIOptions } from '@storybook/types';
import { CommonNxStorybookConfig } from '../../utils/models'; import { CommonNxStorybookConfig } from '../../utils/models';
// TODO(katerina): Update when Storybook 7
describe('@nrwl/storybook:storybook', () => { describe('@nrwl/storybook:storybook', () => {
let context: ExecutorContext; let context: ExecutorContext;
let options: CLIOptions & CommonNxStorybookConfig; let options: CLIOptions & CommonNxStorybookConfig;
beforeEach(() => { beforeEach(() => {
// preserve original package.json file to memory
const rootPath = join(__dirname, `../../../../../`); const rootPath = join(__dirname, `../../../../../`);
const packageJsonPath = join(
rootPath,
`node_modules/@storybook/react/package.json`
);
const storybookPath = join(rootPath, '.storybook');
options = { options = {
uiFramework: '@storybook/react',
port: 4400, port: 4400,
configDir: join(__dirname, `/../../utils/test-configs/.storybook`), configDir: storybookPath,
}; };
vol.fromJSON({
[packageJsonPath]: readFileSync(packageJsonPath).toString(),
});
vol.mkdirSync(storybookPath, {
recursive: true,
});
context = { context = {
root: rootPath, root: rootPath,
cwd: rootPath, cwd: rootPath,
@ -40,7 +54,22 @@ describe('@nrwl/storybook:storybook', () => {
targets: { targets: {
build: { build: {
executor: '@nrwl/web:webpack', executor: '@nrwl/web:webpack',
options: {}, options: {
compiler: 'babel',
outputPath: 'dist/apps/webre',
index: 'apps/webre/src/index.html',
baseHref: '/',
main: 'apps/webre/src/main.tsx',
polyfills: 'apps/webre/src/polyfills.ts',
tsConfig: 'apps/webre/tsconfig.app.json',
assets: [
'apps/webre/src/favicon.ico',
'apps/webre/src/assets',
],
styles: ['apps/webre/src/styles.css'],
scripts: [],
webpackConfig: '@nrwl/react/plugins/webpack',
},
}, },
storybook: { storybook: {
executor: '@nrwl/storybook:storybook', executor: '@nrwl/storybook:storybook',
@ -53,18 +82,16 @@ describe('@nrwl/storybook:storybook', () => {
nxJsonConfiguration: {}, nxJsonConfiguration: {},
isVerbose: false, isVerbose: false,
}; };
jest.mock('fs', () => fsMock);
jest.spyOn(fs, 'statSync').mockReturnValue({
isDirectory: () => true,
} as fs.Stats);
}); });
it('should provide options to storybook', async () => { it('should provide options to storybook', async () => {
const iterator = storybookExecutor(options, context); const iterator = storybookExecutor(options, context);
const { value } = await iterator.next(); const { value } = await iterator.next();
expect(value).toEqual({ expect(value).toEqual({ success: true });
success: true, expect(buildDev).toHaveBeenCalled();
info: {
baseUrl: 'http://localhost:4400',
port: 4400,
},
});
expect(build).toHaveBeenCalled();
}); });
}); });

View File

@ -24,14 +24,17 @@ export default async function* storybookExecutor(
storybookConfigExistsCheck(options.configDir, context.projectName); storybookConfigExistsCheck(options.configDir, context.projectName);
if (storybook7) { if (storybook7) {
const buildOptions: CLIOptions = options; const buildOptions: CLIOptions = options;
const result = await runInstance(buildOptions, storybook7); const result: { port: number } = await runInstance(
buildOptions,
storybook7
);
yield { yield {
success: true, success: true,
info: { info: {
port: result?.['port'], port: result?.port,
baseUrl: `${options.https ? 'https' : 'http'}://${ baseUrl: `${options.https ? 'https' : 'http'}://${
options.host ?? 'localhost' options.host ?? 'localhost'
}:${result?.['port']}`, }:${result?.port}`,
}, },
}; };
await new Promise<{ success: boolean }>(() => {}); await new Promise<{ success: boolean }>(() => {});
@ -55,24 +58,18 @@ export default async function* storybookExecutor(
} }
} }
function runInstance( function runInstance(options: CLIOptions, storybook7: boolean) {
options: CLIOptions,
storybook7: boolean
): Promise<void | {
port: number;
address: string;
networkAddress: string;
}> {
const env = process.env.NODE_ENV ?? 'development'; const env = process.env.NODE_ENV ?? 'development';
process.env.NODE_ENV = env; process.env.NODE_ENV = env;
if (storybook7) { if (storybook7) {
return build.build({ return build['build']({
...options, ...options,
mode: 'dev', mode: 'dev',
}); } as any); // TODO(katerina): Change to actual types when Storybook 7
} else { } else {
// TODO(katerina): Remove when Storybook 7 // TODO(katerina): Remove when Storybook 7
return build['buildDev']({ return build.buildDev({
...options, ...options,
configType: env.toUpperCase(), configType: env.toUpperCase(),
mode: 'dev', mode: 'dev',

View File

@ -53,7 +53,7 @@ export async function configurationGenerator(
*/ */
let storybook7 = let storybook7 =
storybookMajorVersion() === 7 || rawSchema.storybook7Configuration; storybookMajorVersion() === 7 ?? rawSchema.storybook7Configuration;
if (storybookMajorVersion() === 6 && rawSchema.storybook7Configuration) { if (storybookMajorVersion() === 6 && rawSchema.storybook7Configuration) {
logger.error( logger.error(

View File

@ -1,7 +1,6 @@
import { import {
addDependenciesToPackageJson, addDependenciesToPackageJson,
convertNxGenerator, convertNxGenerator,
detectPackageManager,
GeneratorCallback, GeneratorCallback,
readJson, readJson,
readNxJson, readNxJson,
@ -63,16 +62,6 @@ function checkDependenciesInstalled(host: Tree, schema: Schema) {
devDependencies['@storybook/react-native'] = storybookReactNativeVersion; devDependencies['@storybook/react-native'] = storybookReactNativeVersion;
} else { } else {
devDependencies[schema.uiFramework] = storybook7Version; devDependencies[schema.uiFramework] = storybook7Version;
const isPnpm = detectPackageManager(host.root) === 'pnpm';
if (isPnpm) {
// If it's pnpm, it needs the framework without the builder
// as a dependency too (eg. @storybook/react)
const matchResult = schema.uiFramework?.match(/^@storybook\/(\w+)/);
const uiFrameworkWithoutBuilder = matchResult ? matchResult[0] : null;
if (uiFrameworkWithoutBuilder) {
devDependencies[uiFrameworkWithoutBuilder] = storybook7Version;
}
}
} }
devDependencies['@storybook/core-server'] = storybook7Version; devDependencies['@storybook/core-server'] = storybook7Version;
devDependencies['@storybook/addon-essentials'] = storybook7Version; devDependencies['@storybook/addon-essentials'] = storybook7Version;

View File

@ -9,7 +9,7 @@ import { storybookVersion } from './versions';
import { statSync } from 'fs'; import { statSync } from 'fs';
import { findNodes } from 'nx/src/utils/typescript'; import { findNodes } from 'nx/src/utils/typescript';
import ts = require('typescript'); import ts = require('typescript');
import { gte, major } from 'semver'; import { gte, lt, major } from 'semver';
import { join } from 'path'; import { join } from 'path';
export const Constants = { export const Constants = {

6500
yarn.lock

File diff suppressed because it is too large Load Diff