Skip to content

Commit

Permalink
Merge pull request #28938 from storybookjs/version-non-patch-from-8.3…
Browse files Browse the repository at this point in the history
….0-alpha.8

Release: Prerelease alpha 8.3.0-alpha.9
  • Loading branch information
kasperpeulen authored Aug 23, 2024
2 parents f9d8ccf + befba4f commit 006e4bc
Show file tree
Hide file tree
Showing 25 changed files with 370 additions and 55 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.prerelease.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
## 8.3.0-alpha.9

- Addon Viewport: Add default options via parameters - [#28944](https://github.com/storybookjs/storybook/pull/28944), thanks @ndelangen!
- CLI: Make PackageJson optional for starting a dev server - [#28594](https://github.com/storybookjs/storybook/pull/28594), thanks @tobiasdiez!
- Svelte: Fix events not being logged in Actions when a story has decorators - [#28247](https://github.com/storybookjs/storybook/pull/28247), thanks @JReinhold!
- Vitest: Fix default viewport - [#28943](https://github.com/storybookjs/storybook/pull/28943), thanks @kasperpeulen!
- Vitest: Implement add command for vitest addon - [#28920](https://github.com/storybookjs/storybook/pull/28920), thanks @kasperpeulen!

## 8.3.0-alpha.8

- Addon Vitest: Improve transformation logic to avoid duplicate tests - [#28929](https://github.com/storybookjs/storybook/pull/28929), thanks @yannbf!
Expand Down
3 changes: 0 additions & 3 deletions code/.storybook/preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -342,9 +342,6 @@ export const parameters = {
'slategray',
],
},
viewport: {
options: MINIMAL_VIEWPORTS,
},
themes: {
disable: true,
},
Expand Down
2 changes: 1 addition & 1 deletion code/addons/viewport/preview.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { globals } from './dist/preview';
export * from './dist/preview';
9 changes: 9 additions & 0 deletions code/addons/viewport/src/preview.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { PARAM_KEY as KEY } from './constants';
import { MINIMAL_VIEWPORTS } from './defaults';
import type { GlobalState } from './types';

const modern: Record<string, GlobalState> = {
Expand All @@ -9,3 +10,11 @@ const modern: Record<string, GlobalState> = {
const legacy = { viewport: 'reset', viewportRotated: false };

export const initialGlobals = FEATURES?.viewportStoryGlobals ? modern : legacy;

export const parameters = FEATURES?.viewportStoryGlobals
? {
[KEY]: {
options: MINIMAL_VIEWPORTS,
},
}
: {};
3 changes: 3 additions & 0 deletions code/addons/vitest/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@
},
"devDependencies": {
"@vitest/browser": "^2.0.0",
"find-up": "^7.0.0",
"tinyrainbow": "^1.2.0",
"ts-dedent": "^2.2.0",
"vitest": "^2.0.0"
},
"peerDependencies": {
Expand Down
3 changes: 3 additions & 0 deletions code/addons/vitest/src/plugin/viewports.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/* eslint-disable no-underscore-dangle */
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

import { INITIAL_VIEWPORTS } from '@storybook/addon-viewport';

import { page } from '@vitest/browser/context';

import { DEFAULT_VIEWPORT_DIMENSIONS, type ViewportsParam, setViewport } from './viewports';
Expand Down Expand Up @@ -42,6 +44,7 @@ describe('setViewport', () => {

it('should set the dimensions of viewport from INITIAL_VIEWPORTS', async () => {
const viewportsParam: any = {
viewports: INITIAL_VIEWPORTS,
// supported by default in addon viewports
defaultViewport: 'ipad',
};
Expand Down
6 changes: 3 additions & 3 deletions code/addons/vitest/src/plugin/viewports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { UnsupportedViewportDimensionError } from 'storybook/internal/preview-er

import { page } from '@vitest/browser/context';

import { INITIAL_VIEWPORTS } from '../../../viewport/src/defaults';
import { MINIMAL_VIEWPORTS } from '../../../viewport/src/defaults';
import type { ViewportMap, ViewportStyles } from '../../../viewport/src/types';

declare global {
Expand Down Expand Up @@ -50,12 +50,12 @@ const parseDimension = (value: string, dimension: 'width' | 'height') => {
export const setViewport = async (viewportsParam: ViewportsParam = {} as ViewportsParam) => {
const defaultViewport = viewportsParam.defaultViewport;

if (!page || !globalThis.__vitest_browser__ || !defaultViewport) {
if (!page || !globalThis.__vitest_browser__) {
return;
}

const viewports = {
...INITIAL_VIEWPORTS,
...MINIMAL_VIEWPORTS,
...viewportsParam.viewports,
};

Expand Down
255 changes: 253 additions & 2 deletions code/addons/vitest/src/postinstall.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,254 @@
export default async function postinstall(context: any) {
console.log('[addon-vitest] postinstall with', context);
import { existsSync } from 'node:fs';
import * as fs from 'node:fs/promises';
import { writeFile } from 'node:fs/promises';
import { dirname, join, relative, resolve } from 'node:path';
import * as path from 'node:path';

import {
JsPackageManagerFactory,
extractProperFrameworkName,
loadAllPresets,
loadMainConfig,
validateFrameworkName,
} from 'storybook/internal/common';
import { logger } from 'storybook/internal/node-logger';

import { findUp } from 'find-up';
import c from 'tinyrainbow';
import dedent from 'ts-dedent';

import { type PostinstallOptions } from '../../../lib/cli-storybook/src/add';

const extensions = ['.ts', '.mts', '.cts', '.js', '.mjs', '.cjs'];

export default async function postInstall(options: PostinstallOptions) {
const packageManager = JsPackageManagerFactory.getPackageManager({
force: options.packageManager,
});

const info = await getFrameworkInfo(options);

if (
info.frameworkPackageName !== '@storybook/nextjs' &&
info.builderPackageName !== '@storybook/builder-vite'
) {
logger.info(
'The Vitest addon can only be used with a Vite-based Storybook framework or Next.js.'
);
return;
}

const annotationsImport = [
'@storybook/nextjs',
'@storybook/experimental-nextjs-vite',
'@storybook/sveltekit',
].includes(info.frameworkPackageName)
? info.frameworkPackageName
: info.rendererPackageName &&
['@storybook/react', '@storybook/svelte', '@storybook/vue3'].includes(
info.rendererPackageName
)
? info.rendererPackageName
: null;

if (!annotationsImport) {
logger.info('The Vitest addon cannot yet be used with: ' + info.frameworkPackageName);
return;
}

const vitestInfo = getVitestPluginInfo(info.frameworkPackageName);

const packages = ['vitest@latest', '@vitest/browser@latest', 'playwright@latest'];

logger.info(
dedent`
We detected that you're using Next.js.
We will configure the vite-plugin-storybook-nextjs plugin to allow you to run tests in Vitest.
`
);

if (info.frameworkPackageName === '@storybook/nextjs') {
packages.push('vite-plugin-storybook-nextjs@latest');
}
logger.info(c.bold('Installing packages...'));
logger.info(packages.join(', '));
await packageManager.addDependencies({ installAsDevDependencies: true }, packages);

logger.info(c.bold('Executing npx playwright install chromium --with-deps ...'));
await packageManager.executeCommand({
command: 'npx',
args: ['playwright', 'install', 'chromium', '--with-deps'],
});

logger.info(c.bold('Writing .storybook/vitest.setup.ts file...'));

const previewExists = extensions
.map((ext) => path.resolve(path.join(options.configDir, `preview${ext}`)))
.some((config) => existsSync(config));

await writeFile(
resolve(options.configDir, 'vitest.setup.ts'),
dedent`
import { beforeAll } from 'vitest'
import { setProjectAnnotations } from '${annotationsImport}'
${previewExists ? `import * as projectAnnotations from './preview'` : ''}
const project = setProjectAnnotations(${previewExists ? 'projectAnnotations' : '[]'})
beforeAll(project.beforeAll)
`
);

const configFiles = extensions.map((ext) => 'vitest.config' + ext);

const rootConfig = await findUp(configFiles, {
cwd: process.cwd(),
});

if (rootConfig) {
const extname = rootConfig ? path.extname(rootConfig) : '.ts';
const browserWorkspaceFile = resolve(dirname(rootConfig), `vitest.workspace${extname}`);
if (existsSync(browserWorkspaceFile)) {
logger.info(
dedent`
We can not automatically setup the plugin when you use Vitest with workspaces.
Please refer to the documentation to complete the setup manually:
https://storybook.js.org/docs/writing-tests/test-runner-with-vitest#manual
`
);
} else {
logger.info(c.bold('Writing vitest.workspace.ts file...'));
await writeFile(
browserWorkspaceFile,
dedent`
import { defineWorkspace } from 'vitest/config';
import { storybookTest } from '@storybook/experimental-addon-vitest/plugin';
${vitestInfo.frameworkPluginImport ? vitestInfo.frameworkPluginImport + '\n' : ''}
export default defineWorkspace([
'${relative(dirname(browserWorkspaceFile), rootConfig)}',
{
plugins: [
storybookTest(),${vitestInfo.frameworkPluginCall ? '\n' + vitestInfo.frameworkPluginCall : ''}
],
test: {
include: ['**/*.stories.?(m)[jt]s?(x)'],
browser: {
enabled: true,
name: 'chromium',
provider: 'playwright',
headless: true,
},
// Disabling isolation is faster and is similar to how tests are isolated in storybook itself.
// Consider removing this if you are seeing problems with your tests.
isolate: false,
setupFiles: ['./.storybook/vitest.setup.ts'],
},
},
]);
`
);
}
} else {
logger.info(c.bold('Writing vitest.config.ts file...'));
await writeFile(
resolve('vitest.config.ts'),
dedent`
import { defineConfig } from "vitest/config";
import { storybookTest } from "@storybook/experimental-addon-vitest/plugin";
${vitestInfo.frameworkPluginImport ? vitestInfo.frameworkPluginImport + '\n' : ''}
export default defineConfig({
plugins: [
storybookTest(),${vitestInfo.frameworkPluginCall ? '\n' + vitestInfo.frameworkPluginCall : ''}
],
test: {
include: ['**/*.stories.?(m)[jt]s?(x)'],
browser: {
enabled: true,
name: 'chromium',
provider: 'playwright',
headless: true,
},
// Disabling isolation is faster and is similar to how tests are isolated in storybook itself.
// Consider removing this, if you have flaky tests.
isolate: false,
setupFiles: ['./.storybook/vitest.setup.ts'],
},
});
`
);
}

logger.info(
dedent`
The Vitest addon is now configured and you're ready to run your tests!
Check the documentation for more information about its features and options at:
https://storybook.js.org/docs/writing-tests/test-runner-with-vitest
`
);
}

const getVitestPluginInfo = (framework: string) => {
let frameworkPluginImport = '';
let frameworkPluginCall = '';

if (framework === '@storybook/nextjs') {
frameworkPluginImport = "import vitePluginNext from 'vite-plugin-storybook-nextjs'";
frameworkPluginCall = 'vitePluginNext()';
}

if (framework === '@storybook/sveltekit') {
frameworkPluginImport = "import { storybookSveltekitPlugin } from '@storybook/sveltekit/vite'";
frameworkPluginCall = 'storybookSveltekitPlugin()';
}

return { frameworkPluginImport, frameworkPluginCall };
};

async function getFrameworkInfo({ configDir, packageManager: pkgMgr }: PostinstallOptions) {
const packageManager = JsPackageManagerFactory.getPackageManager({ force: pkgMgr });
const packageJson = await packageManager.retrievePackageJson();

const config = await loadMainConfig({ configDir, noCache: true });
const { framework } = config;

const frameworkName = typeof framework === 'string' ? framework : framework?.name;
validateFrameworkName(frameworkName);
const frameworkPackageName = extractProperFrameworkName(frameworkName);

console.log(configDir);
const presets = await loadAllPresets({
corePresets: [join(frameworkName, 'preset')],
overridePresets: [
require.resolve('@storybook/core/core-server/presets/common-override-preset'),
],
configDir,
packageJson,
isCritical: true,
});

const core = await presets.apply('core', {});

const { builder, renderer } = core;

if (!builder) {
throw new Error('Could not detect your Storybook builder.');
}

const builderPackageJson = await fs.readFile(
`${typeof builder === 'string' ? builder : builder.name}/package.json`,
'utf8'
);
const builderPackageName = JSON.parse(builderPackageJson).name;

let rendererPackageName: string | undefined;
if (renderer) {
const rendererPackageJson = await fs.readFile(`${renderer}/package.json`, 'utf8');
rendererPackageName = JSON.parse(rendererPackageJson).name;
}

return {
frameworkPackageName,
builderPackageName,
rendererPackageName,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ export default async (
inject: false,
template,
templateParameters: {
version: packageJson.version,
version: packageJson?.version,
globals: {
CONFIG_TYPE: configType,
LOGLEVEL: logLevel,
Expand Down
Loading

0 comments on commit 006e4bc

Please sign in to comment.