Skip to content

Commit

Permalink
feat(storybook): version 7 executors (#14255)
Browse files Browse the repository at this point in the history
  • Loading branch information
mandarini authored Jan 11, 2023
1 parent b4dbdf6 commit 9f75f7c
Show file tree
Hide file tree
Showing 13 changed files with 928 additions and 281 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@
"@storybook/core-server": "^6.5.15",
"@storybook/manager-webpack5": "^6.5.15",
"@storybook/react": "^6.5.15",
"@storybook/types": "^7.0.0-alpha.44",
"@svgr/rollup": "^6.1.2",
"@svgr/webpack": "^6.1.2",
"@swc-node/register": "^1.4.2",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
import { ExecutorContext, logger } from '@nrwl/devkit';
import { join } from 'path';
jest.mock('@storybook/core-server/standalone', () =>
jest.fn().mockImplementation(() => Promise.resolve())
);
import * as storybook from '@storybook/core-server/standalone';
import storybookBuilder, {
StorybookBuilderOptions,
} from './build-storybook.impl';
import * as executorContext from '../../utils/test-configs/executor-context.json';
jest.mock('@storybook/core-server', () => {
const buildStaticStandalone = jest
.fn()
.mockImplementation(() => Promise.resolve());
return {
buildStaticStandalone,
};
});
import * as build from '@storybook/core-server';

describe('Build storybook', () => {
let context: ExecutorContext;
Expand All @@ -16,85 +22,39 @@ describe('Build storybook', () => {
let config: StorybookBuilderOptions['config'];

beforeEach(async () => {
uiFramework = '@storybook/react';
outputPath = '/root/dist/storybook';
config = {
pluginPath: join(
__dirname,
`/../../generators/configuration/root-files/.storybook/main.js`
),
configFolder: join(
__dirname,
`/../../generators/configuration/root-files/.storybook`
`/../../utils/test-configs/.storybook/main.js`
),
configFolder: join(__dirname, `/../../utils/test-configs/.storybook`),
srcRoot: join(
__dirname,
`/../../generators/configuration/root-files/.storybook/tsconfig.json`
`/../../utils/test-configs/.storybook/tsconfig.json`
),
};
options = {
uiFramework,
outputPath,
config,
uiFramework: '@storybook/react',
};

context = {
root: '/root',
cwd: '/root',
projectName: 'proj',
targetName: 'storybook',
projectsConfigurations: {
version: 2,
projects: {
proj: {
root: '',
sourceRoot: 'src',
targets: {
build: {
executor: '@nrwl/web:webpack',
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: {
executor: '@nrwl/storybook:build-storybook',
options,
},
},
},
},
},
nxJsonConfiguration: {
npmScope: 'test',
},
isVerbose: false,
};
context = executorContext as ExecutorContext;
});

it('should call the storybook static standalone build', async () => {
jest.spyOn(logger, 'info');
it('should call the storybook buildStaticStandalone', async () => {
const loggerSpy = jest.spyOn(logger, 'info');

const standaloneSpy = jest
.spyOn(build, 'buildStaticStandalone')
.mockImplementation(() => Promise.resolve());

const result = await storybookBuilder(options, context);

expect(storybook).toHaveBeenCalled();
expect(logger.info).toHaveBeenCalledWith(
expect(standaloneSpy).toHaveBeenCalled();
expect(loggerSpy).toHaveBeenCalledWith(
`NX Storybook files available in ${outputPath}`
);

expect(logger.info).toHaveBeenCalledWith(`NX ui framework: ${uiFramework}`);
expect(loggerSpy).toHaveBeenCalledWith(`NX ui framework: @storybook/react`);
expect(result.success).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
import { ExecutorContext, logger } from '@nrwl/devkit';
import * as build from '@storybook/core-server/standalone';
import {
ExecutorContext,
logger,
readJsonFile,
workspaceRoot,
} from '@nrwl/devkit';
import * as build from '@storybook/core-server';
import {
CLIOptions,
LoadOptions,
BuilderOptions,
PackageJson,
} from '@storybook/types'; // TODO (katerina): Remove when Storybook 7
import 'dotenv/config';
import path = require('path');
import { storybookConfigExists } from '../../utils/utilities';
import { CommonNxStorybookConfig } from '../models';
import {
getStorybookFrameworkPath,
isStorybookV7,
resolveCommonStorybookOptionMapper,
runStorybookSetupCheck,
} from '../utils';
Expand All @@ -13,43 +27,89 @@ export interface StorybookBuilderOptions extends CommonNxStorybookConfig {
outputPath?: string;
docsMode?: boolean;
}

export default async function buildStorybookExecutor(
options: StorybookBuilderOptions,
context: ExecutorContext
) {
logger.info(`NX ui framework: ${options.uiFramework}`);
const storybook7 = isStorybookV7();
if (storybook7) {
storybookConfigExists(options.config, context.projectName);
const packageJson = readJsonFile(
path.join(workspaceRoot, 'package.json')
) as PackageJson;
const buildOptions = {
...options,
workspaceRoot: context.root,
configDir: options.config.configFolder,
packageJson,
watch: false,
mode: options?.['mode'] ?? 'static',
outputDir:
(options?.['outputDir'] || options?.['output-dir']) ??
options.outputPath,
ignorePreview: options['ignorePreview'] ?? false,
cache: options['cache'] ?? false,
} as CLIOptions &
LoadOptions &
BuilderOptions & {
outputDir: string;
};

logger.info(`NX Storybook builder starting ...`);
await runInstance(buildOptions);
logger.info(`NX Storybook builder finished ...`);
logger.info(`NX Storybook files available in ${options.outputPath}`);
return { success: true };
} else {
// TODO (katerina): Remove when Storybook 7
logger.info(`NX ui framework: ${options.uiFramework}`);

const frameworkPath = getStorybookFrameworkPath(options.uiFramework);
const { default: frameworkOptions } = await import(frameworkPath);
const frameworkPath = getStorybookFrameworkPath(options.uiFramework);
const { default: frameworkOptions } = await import(frameworkPath);

const option = storybookOptionMapper(options, frameworkOptions, context);
const buildOptions = storybookOptionMapper(
options,
frameworkOptions,
context
);

// print warnings
runStorybookSetupCheck(options);
// print warnings
runStorybookSetupCheck(options);

logger.info(`NX Storybook builder starting ...`);
await runInstance(option);
logger.info(`NX Storybook builder finished ...`);
logger.info(`NX Storybook files available in ${options.outputPath}`);
return { success: true };
logger.info(`NX Storybook builder starting ...`);
await runInstance(buildOptions);
logger.info(`NX Storybook builder finished ...`);
logger.info(`NX Storybook files available in ${options.outputPath}`);
return { success: true };
}
}

function runInstance(options: StorybookBuilderOptions): Promise<void> {
function runInstance(
options: CLIOptions &
LoadOptions &
BuilderOptions & {
outputDir: string;
}
): Promise<void> {
const env = process.env.NODE_ENV ?? 'production';
process.env.NODE_ENV = env;
return build({

return build.buildStaticStandalone({
...options,
ci: true,
configType: env.toUpperCase(),
});
} as any); // TODO (katerina): Change to actual types when Storybook 7
}

// TODO (katerina): Remove when Storybook 7
function storybookOptionMapper(
builderOptions: StorybookBuilderOptions,
frameworkOptions: any,
context: ExecutorContext
) {
): CLIOptions &
LoadOptions &
BuilderOptions & {
outputDir: string;
} {
const storybookOptions = {
...builderOptions,
...resolveCommonStorybookOptionMapper(
Expand Down
39 changes: 30 additions & 9 deletions packages/storybook/src/executors/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,35 @@ export interface StorybookConfig {
}

export interface CommonNxStorybookConfig {
uiFramework:
| '@storybook/angular'
| '@storybook/react'
| '@storybook/html'
| '@storybook/web-components'
| '@storybook/vue'
| '@storybook/vue3'
| '@storybook/svelte'
| '@storybook/react-native';
uiFramework?: UiFramework;
uiFramework7?: UiFramework7;
config: StorybookConfig;
}

export type UiFramework7 =
| '@storybook/angular'
| '@storybook/html-webpack5'
| '@storybook/next'
| '@storybook/preact-webpack5'
| '@storybook/react-webpack5'
| '@storybook/react-vite'
| '@storybook/server-webpack5'
| '@storybook/svelte-webpack5'
| '@storybook/svelte-vite'
| '@storybook/sveltekit'
| '@storybook/vue-webpack5'
| '@storybook/vue-vite'
| '@storybook/vue3-webpack5'
| '@storybook/vue3-vite'
| '@storybook/web-components-webpack5'
| '@storybook/web-components-vite';

export type UiFramework =
| '@storybook/angular'
| '@storybook/react'
| '@storybook/html'
| '@storybook/web-components'
| '@storybook/vue'
| '@storybook/vue3'
| '@storybook/svelte'
| '@storybook/react-native';
Loading

0 comments on commit 9f75f7c

Please sign in to comment.