Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Addon Test: Add support for previewHead #29808

Merged
merged 10 commits into from
Dec 10, 2024
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 @@ -88,10 +91,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 @@ -114,6 +115,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
Loading