Skip to content

Commit

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

Release: Prerelease 8.4.0-alpha.7
  • Loading branch information
shilman authored Oct 12, 2024
2 parents 9e3d960 + 48915df commit 6670dfa
Show file tree
Hide file tree
Showing 16 changed files with 231 additions and 15 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.prerelease.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 8.4.0-alpha.7

- CLI: Install Svelte CSF v5 in Svelte5 projects - [#29323](https://github.com/storybookjs/storybook/pull/29323), thanks @shilman!
- Manager: Add tags property to ComponentEntry objects - [#29343](https://github.com/storybookjs/storybook/pull/29343), thanks @Sidnioulz!

## 8.4.0-alpha.6

- Addon-docs, blocks: Prebundle dependencies - [#29301](https://github.com/storybookjs/storybook/pull/29301), thanks @JReinhold!
Expand Down
14 changes: 14 additions & 0 deletions code/core/src/manager-api/lib/intersect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export default <T>(a: T[], b: T[]): T[] => {
// no point in intersecting if one of the input is ill-defined
if (!a || !b) {
return [];
}

return a.reduce((acc: T[], aValue) => {
if (b.includes(aValue)) {
acc.push(aValue);
}

return acc;
}, []);
};
4 changes: 4 additions & 0 deletions code/core/src/manager-api/lib/stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import memoize from 'memoizerific';
import { dedent } from 'ts-dedent';

import { type API, type State, combineParameters } from '../root';
import intersect from './intersect';
import merge from './merge';

const TITLE_PATH_SEPARATOR = /\s*\/\s*/;
Expand Down Expand Up @@ -273,6 +274,9 @@ export const transformStoryIndexToStoriesHash = (
children: [childId],
}),
});
// merge computes a union of arrays but we want an intersection on this
// specific array property, so it's easier to add it after the merge.
acc[id].tags = intersect(acc[id]?.tags ?? item.tags, item.tags);
} else {
acc[id] = merge<API_GroupEntry>((acc[id] || {}) as API_GroupEntry, {
type: 'group',
Expand Down
44 changes: 44 additions & 0 deletions code/core/src/manager-api/tests/intersect.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { describe, expect, it } from 'vitest';

import intersect from '../lib/intersect';

describe('Manager API utilities - intersect', () => {
it('returns identity when intersecting identity', () => {
const a = ['foo', 'bar'];
expect(intersect(a, a)).toEqual(a);
});

it('returns a when b is a superset of a', () => {
const a = ['foo', 'bar'];
const b = ['a', 'foo', 'b', 'bar', 'c', 'ter'];
expect(intersect(a, b)).toEqual(a);
});

it('returns b when a is a superset of b', () => {
const a = ['a', 'foo', 'b', 'bar', 'c', 'ter'];
const b = ['foo', 'bar'];
expect(intersect(a, b)).toEqual(b);
});

it('returns an intersection', () => {
const a = ['a', 'bar', 'b', 'c'];
const b = ['foo', 'bar', 'ter'];
expect(intersect(a, b)).toEqual(['bar']);
});

it('returns an empty set when there is no overlap', () => {
const a = ['a', 'b', 'c'];
const b = ['foo', 'bar', 'ter'];
expect(intersect(a, b)).toEqual([]);
});

it('returns an empty set if a is undefined', () => {
const b = ['foo', 'bar', 'ter'];
expect(intersect(undefined as unknown as [], b)).toEqual([]);
});

it('returns an empty set if b is undefined', () => {
const a = ['foo', 'bar', 'ter'];
expect(intersect(a, undefined as unknown as [])).toEqual([]);
});
});
54 changes: 54 additions & 0 deletions code/core/src/manager-api/tests/stories.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,57 @@ describe('stories API', () => {
name: '1',
});
});
it('intersects story/docs tags to compute tags for component entries', () => {
const moduleArgs = createMockModuleArgs({});
const { api } = initStories(moduleArgs as unknown as ModuleArgs);
const { store } = moduleArgs;
api.setIndex({
v: 5,
entries: {
'a--1': {
type: 'story',
id: 'a--1',
title: 'a',
name: '1',
tags: ['shared', 'one-specific'],
importPath: './a.ts',
},
'a--2': {
type: 'story',
id: 'a--2',
title: 'a',
name: '2',
tags: ['shared', 'two-specific'],
importPath: './a.ts',
},
},
});
const { index } = store.getState();
// We need exact key ordering, even if in theory JS doesn't guarantee it
expect(Object.keys(index!)).toEqual(['a', 'a--1', 'a--2']);
expect(index!.a).toMatchObject({
type: 'component',
id: 'a',
tags: ['shared'],
children: ['a--1', 'a--2'],
});
expect(index!['a--1']).toMatchObject({
type: 'story',
id: 'a--1',
parent: 'a',
title: 'a',
name: '1',
tags: ['shared', 'one-specific'],
});
expect(index!['a--2']).toMatchObject({
type: 'story',
id: 'a--2',
parent: 'a',
title: 'a',
name: '2',
tags: ['shared', 'two-specific'],
});
});
// Stories can get out of order for a few reasons -- see reproductions on
// https://github.com/storybookjs/storybook/issues/5518
it('does the right thing for out of order stories', async () => {
Expand Down Expand Up @@ -1453,6 +1504,7 @@ describe('stories API', () => {
"name": "a",
"parent": undefined,
"renderLabel": undefined,
"tags": [],
"type": "component",
},
"a--1": {
Expand Down Expand Up @@ -1518,6 +1570,7 @@ describe('stories API', () => {
"name": "a",
"parent": undefined,
"renderLabel": undefined,
"tags": [],
"type": "component",
},
"a--1": {
Expand Down Expand Up @@ -1559,6 +1612,7 @@ describe('stories API', () => {
"name": "a",
"parent": undefined,
"renderLabel": undefined,
"tags": [],
"type": "component",
},
"a--1": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ const generateStories = ({ title, refId }: { title: string; refId?: string }): A
name: componentName,
children: [docsId],
parent: rootId,
tags: [],
},
// @ts-expect-error the missing fields are deprecated and replaced by the type prop
{
Expand Down
1 change: 1 addition & 0 deletions code/core/src/types/modules/api-stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export interface API_ComponentEntry extends API_BaseEntry {
type: 'component';
parent?: StoryId;
children: StoryId[];
tags: Tag[];
}

export interface API_DocsEntry extends API_BaseEntry {
Expand Down
44 changes: 44 additions & 0 deletions code/lib/create-storybook/src/generators/SVELTE/index.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { describe, expect, it } from 'vitest';

import type { JsPackageManager } from '@storybook/core/common';

import { getAddonSvelteCsfVersion } from './index';

describe('installed', () => {
it.each([
['3.0.0', ''],
['4.0.0', '4'],
['5.0.0', '^5.0.0-next.0'],
['6.0.0', ''],
['3.0.0-next.0', ''],
['4.0.0-next.0', '4'],
['4.2.19::__archiveUrl=https%3A%2F%2Fregistry.npmjs.org%2Fsvelte%2F-%2Fsvelte-4.2.19.tgz', '4'],
['5.0.0-next.0', '^5.0.0-next.0'],
['6.0.0-next.0', ''],
])('svelte %s => %s', async (svelteVersion, expectedAddonSpecifier) => {
const packageManager = {
getInstalledVersion: async (pkg: string) => (pkg === 'svelte' ? svelteVersion : undefined),
getAllDependencies: async () => ({ svelte: `^${svelteVersion}` }),
} as any as JsPackageManager;
await expect(getAddonSvelteCsfVersion(packageManager)).resolves.toBe(expectedAddonSpecifier);
});
});

describe('uninstalled', () => {
it.each([
['^3', ''],
['^4', '4'],
['^5', '^5.0.0-next.0'],
['^6', ''],
['^3.0.0-next.0', ''],
['^4.0.0-next.0', '4'],
['^5.0.0-next.0', '^5.0.0-next.0'],
['^6.0.0-next.0', ''],
])('svelte %s => %s', async (svelteSpecifier, expectedAddonSpecifier) => {
const packageManager = {
getInstalledVersion: async (pkg: string) => undefined,
getAllDependencies: async () => ({ svelte: svelteSpecifier }),
} as any as JsPackageManager;
await expect(getAddonSvelteCsfVersion(packageManager)).resolves.toBe(expectedAddonSpecifier);
});
});
40 changes: 39 additions & 1 deletion code/lib/create-storybook/src/generators/SVELTE/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,48 @@
import type { JsPackageManager } from 'storybook/internal/common';

import { coerce, major } from 'semver';

import { baseGenerator } from '../baseGenerator';
import type { Generator } from '../types';

const versionHelper = (svelteMajor?: number) => {
if (svelteMajor === 4) {
return '4';
}
// TODO: update when addon-svelte-csf v5 is released
if (svelteMajor === 5) {
return '^5.0.0-next.0';
}
return '';
};

export const getAddonSvelteCsfVersion = async (packageManager: JsPackageManager) => {
const svelteVersion = await packageManager.getInstalledVersion('svelte');
try {
if (svelteVersion) {
return versionHelper(major(coerce(svelteVersion) || ''));
} else {
const deps = await packageManager.getAllDependencies();
const svelteSpecifier = deps['svelte'];
const coerced = coerce(svelteSpecifier);
if (coerced?.version) {
return versionHelper(major(coerced.version));
}
}
} catch {
// fallback to latest version
}
return '';
};

const generator: Generator = async (packageManager, npmOptions, options) => {
const addonSvelteCsfVersion = await getAddonSvelteCsfVersion(packageManager);

await baseGenerator(packageManager, npmOptions, options, 'svelte', {
extensions: ['js', 'ts', 'svelte'],
extraAddons: ['@storybook/addon-svelte-csf'],
extraAddons: [
`@storybook/addon-svelte-csf${addonSvelteCsfVersion && `@${addonSvelteCsfVersion}`}`,
],
});
};

Expand Down
7 changes: 6 additions & 1 deletion code/lib/create-storybook/src/generators/SVELTEKIT/index.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
import { CoreBuilder } from 'storybook/internal/cli';

import { getAddonSvelteCsfVersion } from '../SVELTE';
import { baseGenerator } from '../baseGenerator';
import type { Generator } from '../types';

const generator: Generator = async (packageManager, npmOptions, options) => {
const addonSvelteCsfVersion = await getAddonSvelteCsfVersion(packageManager);

await baseGenerator(
packageManager,
npmOptions,
{ ...options, builder: CoreBuilder.Vite },
'svelte',
{
extensions: ['js', 'ts', 'svelte'],
extraAddons: ['@storybook/addon-svelte-csf'],
extraAddons: [
`@storybook/addon-svelte-csf${addonSvelteCsfVersion && `@${addonSvelteCsfVersion}`}`,
],
},
'sveltekit'
);
Expand Down
3 changes: 2 additions & 1 deletion code/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -293,5 +293,6 @@
"Dependency Upgrades"
]
]
}
},
"deferredNextVersion": "8.4.0-alpha.7"
}
11 changes: 11 additions & 0 deletions docs/_snippets/storybook-a11y-add.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
```shell renderer="common" language="js" packageManager="npm"
npx storybook add @storybook/addon-a11y
```

```shell renderer="common" language="js" packageManager="pnpm"
pnpm exec storybook add @storybook/addon-a11y
```

```shell renderer="common" language="js" packageManager="yarn"
yarn exec storybook add @storybook/addon-a11y
```
1 change: 0 additions & 1 deletion docs/_snippets/storybook-a11y-install.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,3 @@ pnpm add --save-dev @storybook/addon-a11y
```shell renderer="common" language="js" packageManager="yarn"
yarn add --dev @storybook/addon-a11y
```

1 change: 0 additions & 1 deletion docs/_snippets/storybook-a11y-register.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,3 @@ const config: StorybookConfig = {

export default config;
```

2 changes: 1 addition & 1 deletion docs/versions/next.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"version":"8.4.0-alpha.6","info":{"plain":"- Addon-docs, blocks: Prebundle dependencies - [#29301](https://github.com/storybookjs/storybook/pull/29301), thanks @JReinhold!\n- React: Prebundle all of `renderers/react`'s dependencies - [#29298](https://github.com/storybookjs/storybook/pull/29298), thanks @ndelangen!\n- Vite: Cleanup and prebundle dependencies - [#29302](https://github.com/storybookjs/storybook/pull/29302), thanks @JReinhold!"}}
{"version":"8.4.0-alpha.7","info":{"plain":"- CLI: Install Svelte CSF v5 in Svelte5 projects - [#29323](https://github.com/storybookjs/storybook/pull/29323), thanks @shilman!\n- Manager: Add tags property to ComponentEntry objects - [#29343](https://github.com/storybookjs/storybook/pull/29343), thanks @Sidnioulz!"}}
14 changes: 5 additions & 9 deletions docs/writing-tests/accessibility-testing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,19 @@ Storybook provides an official [a11y addon](https://storybook.js.org/addons/@sto

### Set up the a11y addon

If you want to check accessibility for your stories using the [addon](https://storybook.js.org/addons/@storybook/addon-a11y/), you'll need to install it and add it to your Storybook.

Run the following command to install the addon.
If you want to check accessibility for your stories using the [addon](https://storybook.js.org/addons/@storybook/addon-a11y/), you'll need to add it to your Storybook. You can do this by running the following command:

{/* prettier-ignore-start */}

<CodeSnippets path="storybook-a11y-install.md" />
<CodeSnippets path="storybook-a11y-add.md" />

{/* prettier-ignore-end */}

Update your Storybook configuration (in `.storybook/main.js|ts`) to include the accessibility addon.

{/* prettier-ignore-start */}
<Callout variant="info">

<CodeSnippets path="storybook-a11y-register.md" />
The CLI's [`add`](../api/cli-options.mdx#add) command automates the addon's installation and setup. To install it manually, see our [documentation](../addons/install-addons.mdx#manual-installation) on how to install addons.

{/* prettier-ignore-end */}
</Callout>

Start your Storybook, and you will see some noticeable differences in the UI. A new toolbar icon and the accessibility panel where you can inspect the results of the tests.

Expand Down

0 comments on commit 6670dfa

Please sign in to comment.