Skip to content

Commit

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

Release: Prerelease alpha 8.5.0-alpha.21
  • Loading branch information
valentinpalkovic authored Dec 12, 2024
2 parents a0b8f06 + 2de3b7a commit f0d6f29
Show file tree
Hide file tree
Showing 23 changed files with 289 additions and 84 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.prerelease.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
## 8.5.0-alpha.21

- Addon A11y: Add typesVersions support for TypeScript definitions in a11y package - [#30005](https://github.com/storybookjs/storybook/pull/30005), thanks @valentinpalkovic!
- Addon A11y: Refactor environment variable handling for Vitest integration - [#30022](https://github.com/storybookjs/storybook/pull/30022), thanks @valentinpalkovic!
- Addon A11y: Run the a11y automigration on postInstall - [#30004](https://github.com/storybookjs/storybook/pull/30004), thanks @kasperpeulen!
- Addon A11y: Update accessibility status handling in TestProviderRender - [#30027](https://github.com/storybookjs/storybook/pull/30027), thanks @valentinpalkovic!
- Addon Onboarding: Prebundle react-confetti - [#29996](https://github.com/storybookjs/storybook/pull/29996), thanks @yannbf!
- Addon Test: Correctly stop Storybook when Vitest closes - [#30012](https://github.com/storybookjs/storybook/pull/30012), thanks @JReinhold!
- Addon Test: Show sub test provider toggle state in main testing module - [#30019](https://github.com/storybookjs/storybook/pull/30019), thanks @ghengeveld!
- Addon Test: Wrap sub-paths exported with `require.resolve` - [#30026](https://github.com/storybookjs/storybook/pull/30026), thanks @ndelangen!
- Core: Fix bundling of React - [#30003](https://github.com/storybookjs/storybook/pull/30003), thanks @yannbf!

## 8.5.0-alpha.20

- Addon Test: Add `@vitest/coverage-v8` during postinstall if no coverage reporter is installed - [#29993](https://github.com/storybookjs/storybook/pull/29993), thanks @ghengeveld!
Expand Down
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ In the event of a high-risk vulnerability, we may backport the security fixes to

## Reporting a Vulnerability

To report a vulnerability, you can reach out to the maintainers directly on Twitter: https://twitter.com/storybookjs
To report a vulnerability, you can reach out to the maintainers directly on Twitter: https://twitter.com/storybookjs or Bluesky: https://bsky.app/profile/storybook.js.org

When we fix a security issue, we will post a security advisory on Github/NPM, describe the change in the [release notes](https://github.com/storybookjs/storybook/releases), and also announce notify the community on [our Discord](https://discord.gg/storybook).
17 changes: 16 additions & 1 deletion code/addons/a11y/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,22 @@
},
"./manager": "./dist/manager.js",
"./register": "./dist/manager.js",
"./package.json": "./package.json"
"./package.json": "./package.json",
"./postinstall": "./dist/postinstall.js"
},
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"typesVersions": {
"*": {
"*": [
"dist/index.d.ts"
],
"preview": [
"dist/preview.d.ts"
]
}
},
"files": [
"dist/**/*",
"README.md",
Expand All @@ -64,6 +75,7 @@
"@storybook/global": "^5.0.0",
"@storybook/icons": "^1.2.12",
"@testing-library/react": "^14.0.0",
"execa": "^9.5.2",
"picocolors": "^1.1.0",
"pretty-format": "^29.7.0",
"react": "^18.2.0",
Expand All @@ -87,6 +99,9 @@
],
"previewEntries": [
"./src/preview.tsx"
],
"nodeEntries": [
"./src/postinstall.ts"
]
},
"gitHead": "e6a7fd8a655c69780bc20b9749c2699e44beae16",
Expand Down
15 changes: 15 additions & 0 deletions code/addons/a11y/src/postinstall.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { PostinstallOptions } from '@storybook/cli/src/add';

// eslint-disable-next-line depend/ban-dependencies
import { execa } from 'execa';

const $ = execa({
preferLocal: true,
stdio: 'inherit',
// we stream the stderr to the console
reject: false,
});

export default async function postinstall(options: PostinstallOptions) {
await $`storybook automigrate addonA11yAddonTest ${options.yes ? '--yes' : ''}`;
}
24 changes: 8 additions & 16 deletions code/addons/a11y/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,17 @@
export function getIsVitestStandaloneRun() {
try {
return process.env.VITEST_STORYBOOK === 'false';
} catch {
try {
// @ts-expect-error Suppress TypeScript warning about wrong setting. Doesn't matter, because we don't use tsc for bundling.
return import.meta.env.VITEST_STORYBOOK === 'false';
} catch (e) {
return false;
}
// @ts-expect-error Suppress TypeScript warning about wrong setting. Doesn't matter, because we don't use tsc for bundling.
return import.meta.env.VITEST_STORYBOOK === 'false';
} catch (e) {
return false;
}
}

export function getIsVitestRunning() {
try {
return process?.env.MODE === 'test';
} catch {
try {
// @ts-expect-error Suppress TypeScript warning about wrong setting. Doesn't matter, because we don't use tsc for bundling.
return import.meta.env.MODE === 'test';
} catch (e) {
return false;
}
// @ts-expect-error Suppress TypeScript warning about wrong setting. Doesn't matter, because we don't use tsc for bundling.
return import.meta.env.MODE === 'test';
} catch (e) {
return false;
}
}
4 changes: 1 addition & 3 deletions code/addons/onboarding/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,13 @@
"check": "jiti ../../../scripts/prepare/check.ts",
"prep": "jiti ../../../scripts/prepare/addon-bundle.ts"
},
"dependencies": {
"react-confetti": "^6.1.0"
},
"devDependencies": {
"@radix-ui/react-dialog": "^1.0.5",
"@storybook/icons": "^1.2.12",
"@storybook/react": "workspace:*",
"framer-motion": "^11.0.3",
"react": "^18.2.0",
"react-confetti": "^6.1.0",
"react-dom": "^18.2.0",
"react-joyride": "^2.8.2",
"react-use-measure": "^2.1.1",
Expand Down
1 change: 1 addition & 0 deletions code/addons/test/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
"slash": "^5.0.0",
"strip-ansi": "^7.1.0",
"tinyglobby": "^0.2.10",
"tree-kill": "^1.2.2",
"ts-dedent": "^2.2.0",
"typescript": "^5.3.2",
"vitest": "^2.1.3"
Expand Down
2 changes: 1 addition & 1 deletion code/addons/test/src/components/ContextMenuItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export const ContextMenuItem: FC<{
padding="small"
disabled={state.crashed || isDisabled}
>
<Icon fill={theme.barTextColor} />
<Icon fill={theme.textMutedColor} />
</Button>
}
/>
Expand Down
2 changes: 1 addition & 1 deletion code/addons/test/src/components/Description.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const Wrapper = styled.div(({ theme }) => ({
whiteSpace: 'nowrap',
textOverflow: 'ellipsis',
fontSize: theme.typography.size.s1,
color: theme.barTextColor,
color: theme.textMutedColor,
}));

const PositiveText = styled.span(({ theme }) => ({
Expand Down
32 changes: 25 additions & 7 deletions code/addons/test/src/components/TestProviderRender.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ const StopIcon = styled(StopAltIcon)({
width: 10,
});

const ItemTitle = styled.span<{ enabled?: boolean }>(
({ enabled, theme }) =>
!enabled && {
color: theme.textMutedColor,
'&:after': {
content: '" (disabled)"',
},
}
);

const statusOrder: TestStatus[] = ['failed', 'warning', 'pending', 'passed', 'skipped'];
const statusMap: Record<TestStatus, ComponentProps<typeof TestStatusIcon>['status']> = {
failed: 'negative',
Expand Down Expand Up @@ -118,6 +128,10 @@ export const TestProviderRender: FC<
}, [isA11yAddon, state.details?.testResults, entryId]);

const a11yStatus = useMemo<'positive' | 'warning' | 'negative' | 'unknown'>(() => {
if (state.running) {
return 'unknown';
}

if (!isA11yAddon || config.a11y === false) {
return 'unknown';
}
Expand All @@ -136,7 +150,7 @@ export const TestProviderRender: FC<
}

return 'positive';
}, [a11yResults, isA11yAddon, config.a11y]);
}, [state.running, isA11yAddon, config.a11y, a11yResults]);

const a11yNotPassedAmount = a11yResults?.filter(
(result) => result?.status === 'failed' || result?.status === 'warning'
Expand All @@ -154,7 +168,11 @@ export const TestProviderRender: FC<
})
.sort((a, b) => statusOrder.indexOf(a.status) - statusOrder.indexOf(b.status));

const status = (state.failed ? 'failed' : results[0]?.status) || 'unknown';
const status = state.running
? 'unknown'
: state.failed
? 'failed'
: (results[0]?.status ?? 'unknown');

const openPanel = (id: string, panelId: string) => {
api.selectStory(id);
Expand Down Expand Up @@ -233,7 +251,7 @@ export const TestProviderRender: FC<
/>
<ListItem
as="label"
title="Coverage"
title={<ItemTitle enabled={config.coverage}>Coverage</ItemTitle>}
icon={<ShieldIcon color={theme.textMutedColor} />}
right={
<Checkbox
Expand All @@ -247,7 +265,7 @@ export const TestProviderRender: FC<
{isA11yAddon && (
<ListItem
as="label"
title="Accessibility"
title={<ItemTitle enabled={config.a11y}>Accessibility</ItemTitle>}
icon={<AccessibilityIcon color={theme.textMutedColor} />}
right={
<Checkbox
Expand Down Expand Up @@ -285,7 +303,7 @@ export const TestProviderRender: FC<
/>
{coverageSummary ? (
<ListItem
title="Coverage"
title={<ItemTitle enabled={config.coverage}>Coverage</ItemTitle>}
href={'/coverage/index.html'}
// @ts-expect-error ListItem doesn't include all anchor attributes in types, but it is an achor element
target="_blank"
Expand All @@ -300,13 +318,13 @@ export const TestProviderRender: FC<
/>
) : (
<ListItem
title="Coverage"
title={<ItemTitle enabled={config.coverage}>Coverage</ItemTitle>}
icon={<TestStatusIcon status="unknown" aria-label={`status: unknown`} />}
/>
)}
{isA11yAddon && (
<ListItem
title="Accessibility"
title={<ItemTitle enabled={config.a11y}>Accessibility</ItemTitle>}
onClick={
(a11yStatus === 'negative' || a11yStatus === 'warning') && a11yResults.length
? () => {
Expand Down
6 changes: 4 additions & 2 deletions code/addons/test/src/node/vitest-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import type { TestingModuleRunRequestPayload } from 'storybook/internal/core-eve

import type { DocsIndexEntry, StoryIndex, StoryIndexEntry } from '@storybook/types';

import path, { normalize } from 'pathe';
import path, { dirname, join, normalize } from 'pathe';
import slash from 'slash';

import { COVERAGE_DIRECTORY, type Config } from '../constants';
Expand All @@ -29,6 +29,8 @@ type TagsFilter = {
skip: string[];
};

const packageDir = dirname(require.resolve('@storybook/experimental-addon-test/package.json'));

export class VitestManager {
vitest: Vitest | null = null;

Expand All @@ -44,7 +46,7 @@ export class VitestManager {
const { createVitest } = await import('vitest/node');

const storybookCoverageReporter: [string, StorybookCoverageReporterOptions] = [
'@storybook/experimental-addon-test/internal/coverage-reporter',
join(packageDir, 'dist/node/coverage-reporter.js'),
{
testManager: this.testManager,
coverageOptions: this.vitest?.config?.coverage as ResolvedCoverageOptions<'v8'>,
Expand Down
27 changes: 16 additions & 11 deletions code/addons/test/src/vitest-plugin/global-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import type { GlobalSetupContext } from 'vitest/node';

import { logger } from 'storybook/internal/node-logger';

import treeKill from 'tree-kill';

let storybookProcess: ChildProcess | null = null;

const getIsVitestStandaloneRun = () => {
Expand Down Expand Up @@ -59,23 +61,26 @@ const startStorybookIfNotRunning = async () => {
}
};

const killProcess = (process: ChildProcess) => {
return new Promise((resolve, reject) => {
process.on('close', resolve);
process.on('error', reject);
process.kill();
});
};

export const setup = async ({ config }: GlobalSetupContext) => {
if (config.watch && isVitestStandaloneRun) {
await startStorybookIfNotRunning();
}
};

export const teardown = async () => {
if (storybookProcess) {
logger.verbose('Stopping Storybook process');
await killProcess(storybookProcess);
if (!storybookProcess) {
return;
}
logger.verbose('Stopping Storybook process');
await new Promise<void>((resolve, reject) => {
// Storybook starts multiple child processes, so we need to kill the whole tree
treeKill(storybookProcess.pid, 'SIGTERM', (error) => {
if (error) {
logger.error('Failed to stop Storybook process:');
reject(error);
return;
}
resolve();
});
});
};
22 changes: 13 additions & 9 deletions code/addons/test/src/vitest-plugin/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/* eslint-disable no-underscore-dangle */
import { dirname } from 'node:path';

import type { Plugin } from 'vitest/config';
import { mergeConfig } from 'vitest/config';
import type { ViteUserConfig } from 'vitest/config';
Expand All @@ -23,7 +25,6 @@ import sirv from 'sirv';
import { convertPathToPattern } from 'tinyglobby';
import { dedent } from 'ts-dedent';

import { TestManager } from '../node/test-manager';
import type { InternalOptions, UserOptions } from './types';

const WORKING_DIR = process.cwd();
Expand Down Expand Up @@ -63,6 +64,8 @@ const getStoryGlobsAndFiles = async (
};
};

const packageDir = dirname(require.resolve('@storybook/experimental-addon-test/package.json'));

export const storybookTest = async (options?: UserOptions): Promise<Plugin> => {
const finalOptions = {
...defaultOptions,
Expand Down Expand Up @@ -143,28 +146,31 @@ export const storybookTest = async (options?: UserOptions): Promise<Plugin> => {
// plugin.name?.startsWith('vitest:browser')
// )

// We signal the test runner that we are not running it via Storybook
// We are overriding the environment variable to 'true' if vitest runs via @storybook/addon-test's backend
const vitestStorybook = process.env.VITEST_STORYBOOK ?? 'false';

const baseConfig: Omit<ViteUserConfig, 'plugins'> = {
test: {
setupFiles: [
'@storybook/experimental-addon-test/internal/setup-file',
join(packageDir, 'dist/vitest-plugin/setup-file.mjs'),
// if the existing setupFiles is a string, we have to include it otherwise we're overwriting it
typeof inputConfig_DoNotMutate.test?.setupFiles === 'string' &&
inputConfig_DoNotMutate.test?.setupFiles,
].filter(Boolean),
].filter(Boolean) as string[],

...(finalOptions.storybookScript
? {
globalSetup: ['@storybook/experimental-addon-test/internal/global-setup'],
globalSetup: [join(packageDir, 'dist/vitest-plugin/global-setup.mjs')],
}
: {}),

env: {
...storybookEnv,
// To be accessed by the setup file
__STORYBOOK_URL__: finalOptions.storybookUrl,
// We signal the test runner that we are not running it via Storybook
// We are overriding the environment variable to 'true' if vitest runs via @storybook/addon-test's backend
VITEST_STORYBOOK: 'false',

VITEST_STORYBOOK: vitestStorybook,
__VITEST_INCLUDE_TAGS__: finalOptions.tags.include.join(','),
__VITEST_EXCLUDE_TAGS__: finalOptions.tags.exclude.join(','),
__VITEST_SKIP_TAGS__: finalOptions.tags.skip.join(','),
Expand Down Expand Up @@ -239,8 +245,6 @@ export const storybookTest = async (options?: UserOptions): Promise<Plugin> => {
},

define: {
// polyfilling process.env.VITEST_STORYBOOK to 'false' in the browser
'process.env.VITEST_STORYBOOK': JSON.stringify('false'),
...(frameworkName?.includes('vue3')
? { __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: 'false' }
: {}),
Expand Down
Loading

0 comments on commit f0d6f29

Please sign in to comment.