Skip to content

Commit

Permalink
Merge pull request #29808 from storybookjs/norbert/vitest-support-pre…
Browse files Browse the repository at this point in the history
…view-html

AddonTest: Add support for previewHead
  • Loading branch information
JReinhold authored Dec 10, 2024
2 parents 8872560 + dc9b515 commit cf80d5c
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 5 deletions.
21 changes: 16 additions & 5 deletions code/addons/test/src/vitest-plugin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@ import type { ViteUserConfig } from 'vitest/config';

import {
getInterpretedFile,
loadAllPresets,
normalizeStories,
validateConfigurationFiles,
} from 'storybook/internal/common';
import { StoryIndexGenerator, mapStaticDir } from 'storybook/internal/core-server';
import {
StoryIndexGenerator,
experimental_loadStorybook,
mapStaticDir,
} from 'storybook/internal/core-server';
import { readConfig, vitestTransform } from 'storybook/internal/csf-tools';
import { MainFileMissingError } from 'storybook/internal/server-errors';
import type { Presets } from 'storybook/internal/types';
Expand Down Expand Up @@ -87,10 +90,8 @@ export const storybookTest = async (options?: UserOptions): Promise<Plugin> => {
workingDir: WORKING_DIR,
};

const presets = await loadAllPresets({
const { presets } = await experimental_loadStorybook({
configDir: finalOptions.configDir,
corePresets: [],
overridePresets: [],
packageJson: {},
});

Expand All @@ -113,6 +114,16 @@ export const storybookTest = async (options?: UserOptions): Promise<Plugin> => {
return {
name: 'vite-plugin-storybook-test',
enforce: 'pre',
async transformIndexHtml(html) {
const [headHtmlSnippet, bodyHtmlSnippet] = await Promise.all([
presets.apply('previewHead'),
presets.apply('previewBody'),
]);

return html
.replace('</head>', `${headHtmlSnippet ?? ''}</head>`)
.replace('<body>', `<body>${bodyHtmlSnippet ?? ''}`);
},
async config(inputConfig_DoNotMutate) {
// ! We're not mutating the input config, instead we're returning a new partial config
// ! see https://vite.dev/guide/api-plugin.html#config
Expand Down
2 changes: 2 additions & 0 deletions code/core/src/core-server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,5 @@ export * from './withTelemetry';
export { default as build } from './standalone';
export { mapStaticDir } from './utils/server-statics';
export { StoryIndexGenerator } from './utils/StoryIndexGenerator';

export { loadStorybook as experimental_loadStorybook } from './load';
83 changes: 83 additions & 0 deletions code/core/src/core-server/load.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { join, relative, resolve } from 'node:path';

import {
getProjectRoot,
loadAllPresets,
loadMainConfig,
resolveAddonName,
validateFrameworkName,
} from '@storybook/core/common';
import { oneWayHash } from '@storybook/core/telemetry';
import type { BuilderOptions, CLIOptions, LoadOptions, Options } from '@storybook/core/types';
import { global } from '@storybook/global';

export async function loadStorybook(
options: CLIOptions &
LoadOptions &
BuilderOptions & {
storybookVersion?: string;
previewConfigPath?: string;
}
): Promise<Options> {
const configDir = resolve(options.configDir);

const rootDir = getProjectRoot();
const cacheKey = oneWayHash(relative(rootDir, configDir));

options.configType = 'DEVELOPMENT';
options.configDir = configDir;
options.cacheKey = cacheKey;

const config = await loadMainConfig(options);
const { framework } = config;
const corePresets = [];

let frameworkName = typeof framework === 'string' ? framework : framework?.name;
if (!options.ignorePreview) {
validateFrameworkName(frameworkName);
}
if (frameworkName) {
corePresets.push(join(frameworkName, 'preset'));
}

frameworkName = frameworkName || 'custom';

// Load first pass: We need to determine the builder
// We need to do this because builders might introduce 'overridePresets' which we need to take into account
// We hope to remove this in SB8

let presets = await loadAllPresets({
corePresets,
overridePresets: [
require.resolve('@storybook/core/core-server/presets/common-override-preset'),
],
...options,
isCritical: true,
});

const { renderer } = await presets.apply('core', {});
const resolvedRenderer = renderer && resolveAddonName(options.configDir, renderer, options);

// Load second pass: all presets are applied in order

presets = await loadAllPresets({
corePresets: [
require.resolve('@storybook/core/core-server/presets/common-preset'),
...(resolvedRenderer ? [resolvedRenderer] : []),
...corePresets,
],
overridePresets: [
require.resolve('@storybook/core/core-server/presets/common-override-preset'),
],
...options,
});

const features = await presets.apply('features');
global.FEATURES = features;

return {
...options,
presets,
features,
} as Options;
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,11 @@ const config: StorybookConfig = {
core: {
disableWhatsNewNotifications: true
},
previewHead: (head = '') => `${head}
<style>
body {
border: 1px solid red;
}
</style>`,
};
export default config;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<style>
body {
background-color: rgb(250, 250, 210);
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ const setForceFailureFlag = async (value: boolean) => {

// Write the updated content back to the file asynchronously
await fs.writeFile(testStoryPath, updatedContent);

// the file change causes a HMR event, which causes a browser reload,and that can take a few seconds
await new Promise((resolve) => setTimeout(resolve, 2000));
};

test.describe("component testing", () => {
Expand Down

0 comments on commit cf80d5c

Please sign in to comment.