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: Error when addon interactions exists #29434

1 change: 0 additions & 1 deletion code/.storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ const config: StorybookConfig = {
addons: [
'@storybook/addon-themes',
'@storybook/addon-essentials',
'@storybook/addon-interactions',
'@storybook/addon-storysource',
'@storybook/addon-designs',
'@storybook/experimental-addon-test',
Expand Down
3 changes: 3 additions & 0 deletions code/addons/interactions/src/preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,6 @@ export const checkActionsLoaded = (configDir: string) => {
getConfig: (configFile) => serverRequire(configFile),
});
};

// This annotation is read by addon-test, so it can throw an error if both addons are used
export const ADDON_INTERACTIONS_IN_USE = true;
ghengeveld marked this conversation as resolved.
Show resolved Hide resolved
33 changes: 32 additions & 1 deletion code/addons/test/src/preset.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
TESTING_MODULE_WATCH_MODE_REQUEST,
} from 'storybook/internal/core-events';
import { oneWayHash, telemetry } from 'storybook/internal/telemetry';
import type { Options, StoryId } from 'storybook/internal/types';
import type { Options, PresetProperty, StoryId } from 'storybook/internal/types';

import picocolors from 'picocolors';
import { dedent } from 'ts-dedent';
Expand Down Expand Up @@ -99,3 +99,34 @@ export const experimental_serverChannel = async (channel: Channel, options: Opti

return channel;
};

export const previewAnnotations: PresetProperty<'previewAnnotations'> = async (
entry = [],
options
) => {
checkActionsLoaded(options.configDir);
return entry;
};

export const managerEntries: PresetProperty<'managerEntries'> = async (entry = [], options) => {
// Throw an error when addon-interactions is used.
// This is done by reading an annotation defined in addon-interactions, which although not ideal,
// is a way to handle addon conflict without having to worry about the order of which they are registered
const annotation = await options.presets.apply('ADDON_INTERACTIONS_IN_USE', false);
if (annotation) {
// eslint-disable-next-line local-rules/no-uncategorized-errors
const error = new Error(
dedent`
You have both addon-interactions and addon-test enabled, which is not allowed.

addon-test is a replacement for addon-interactions, please uninstall and remove addon-interactions from the addons list in your main config at ${options.configDir}.
`
);
error.name = 'AddonConflictError';

throw error;
}

// for whatever reason seems like the return type of managerEntries is not correct (it expects never instead of string[])
return entry as never;
};
2 changes: 1 addition & 1 deletion scripts/task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import { createOptions, getCommand, getOptionsOrPrompt } from './utils/options';

const sandboxDir = process.env.SANDBOX_ROOT || SANDBOX_DIRECTORY;

export const extraAddons = ['a11y', 'storysource'];
export const extraAddons = ['@storybook/addon-a11y', '@storybook/addon-storysource'];

export type Path = string;
export type TemplateDetails = {
Expand Down
13 changes: 2 additions & 11 deletions scripts/tasks/sandbox-parts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import { detectLanguage } from '../../code/core/src/cli/detect';
import { SupportedLanguage } from '../../code/core/src/cli/project_types';
import {
JsPackageManagerFactory,
removeAddon,
versions as storybookPackages,
} from '../../code/core/src/common';
import type { ConfigFile } from '../../code/core/src/csf-tools';
Expand Down Expand Up @@ -181,8 +180,7 @@ export const init: Task['run'] = async (

if (!skipTemplateStories) {
for (const addon of addons) {
const addonName = `@storybook/addon-${addon}`;
await executeCLIStep(steps.add, { argument: addonName, cwd, dryRun, debug });
await executeCLIStep(steps.add, { argument: addon, cwd, dryRun, debug, optionValues: { yes: true } });
}
}
};
Expand Down Expand Up @@ -395,13 +393,6 @@ const getVitestPluginInfo = (details: TemplateDetails) => {

export async function setupVitest(details: TemplateDetails, options: PassedOptionValues) {
const { sandboxDir, template } = details;
// Remove interactions addon to avoid issues with Vitest
// TODO: add an if statement when we introduce a sandbox that tests interactions
await removeAddon('@storybook/addon-interactions', {
cwd: details.sandboxDir,
configDir: join(details.sandboxDir, '.storybook'),
});

const packageJsonPath = join(sandboxDir, 'package.json');
const packageJson = await readJson(packageJsonPath);

Expand Down Expand Up @@ -804,7 +795,7 @@ export const extendMain: Task['run'] = async ({ template, sandboxDir, key }, { d
}

const addons = mainConfig.getFieldValue(['addons']);
mainConfig.setFieldValue(['addons'], [...addons, '@storybook/experimental-addon-test']);
mainConfig.setFieldValue(['addons'], [...addons]);
ghengeveld marked this conversation as resolved.
Show resolved Hide resolved

if (template.expected.builder === '@storybook/builder-vite') {
setSandboxViteFinal(mainConfig);
Expand Down
56 changes: 34 additions & 22 deletions scripts/tasks/sandbox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,39 @@ export const sandbox: Task = {
setupVitest,
} = await import('./sandbox-parts');

const extraDeps = [
...(details.template.modifications?.extraDependencies ?? []),
// The storybook package forwards some CLI commands to @storybook/cli with npx.
// Adding the dep makes sure that even npx will use the linked workspace version.
'@storybook/cli',
];

const shouldAddVitestIntegration = !details.template.skipTasks?.includes('vitest-integration')

if (shouldAddVitestIntegration) {
extraDeps.push(
'happy-dom',
'vitest',
'playwright',
'@vitest/browser',
);

if (details.template.expected.framework.includes('nextjs')) {
extraDeps.push('@storybook/experimental-nextjs-vite', 'jsdom');
}

// if (details.template.expected.renderer === '@storybook/svelte') {
// extraDeps.push(`@testing-library/svelte`);
// }
//
// if (details.template.expected.framework === '@storybook/angular') {
// extraDeps.push('@testing-library/angular', '@analogjs/vitest-angular');
// }
valentinpalkovic marked this conversation as resolved.
Show resolved Hide resolved

options.addon = [...options.addon, '@storybook/experimental-addon-test'];
}


let startTime = now();
await create(details, options);
const createTime = now() - startTime;
Expand Down Expand Up @@ -83,28 +116,7 @@ export const sandbox: Task = {
await addStories(details, options);
}

const extraDeps = [
...(details.template.modifications?.extraDependencies ?? []),
// The storybook package forwards some CLI commands to @storybook/cli with npx.
// Adding the dep makes sure that even npx will use the linked workspace version.
'@storybook/cli',
'@storybook/experimental-addon-test',
];
if (!details.template.skipTasks?.includes('vitest-integration')) {
extraDeps.push('happy-dom', 'vitest', 'playwright', '@vitest/browser');

if (details.template.expected.framework.includes('nextjs')) {
extraDeps.push('@storybook/experimental-nextjs-vite', 'jsdom');
}

// if (details.template.expected.renderer === '@storybook/svelte') {
// extraDeps.push(`@testing-library/svelte`);
// }
//
// if (details.template.expected.framework === '@storybook/angular') {
// extraDeps.push('@testing-library/angular', '@analogjs/vitest-angular');
// }

if(shouldAddVitestIntegration) {
await setupVitest(details, options);
}

Expand Down
4 changes: 3 additions & 1 deletion scripts/utils/cli-step.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ export const steps = {
description: 'Adding addon',
icon: '+',
hasArgument: true,
options: createOptions({}),
options: createOptions({
yes: { type: 'boolean' },
}),
},
link: {
command: 'link',
Expand Down