Skip to content

Commit

Permalink
Merge pull request #29211 from storybookjs/version-patch-from-8.3.3
Browse files Browse the repository at this point in the history
Release: Patch 8.3.4
  • Loading branch information
shilman authored Sep 28, 2024
2 parents e159e49 + 4387c68 commit a1307dd
Show file tree
Hide file tree
Showing 13 changed files with 114 additions and 16 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 8.3.4

- Addon Test: Support story name as test description - [#29147](https://github.com/storybookjs/storybook/pull/29147), thanks @InfiniteXyy!
- Addon-Interactions: Use ansi-to-html for colored test errors - [#29110](https://github.com/storybookjs/storybook/pull/29110), thanks @kasperpeulen!

## 8.3.3

- CLI: Show constraints in error when getting depndencies - [#29187](https://github.com/storybookjs/storybook/pull/29187), thanks @andrasczeh!
Expand Down
1 change: 1 addition & 0 deletions code/addons/interactions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
"@devtools-ds/object-inspector": "^1.1.2",
"@storybook/icons": "^1.2.5",
"@types/node": "^22.0.0",
"ansi-to-html": "^0.7.2",
"formik": "^2.2.9",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand Down
5 changes: 3 additions & 2 deletions code/addons/interactions/src/components/Interaction.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { type Call, CallStates, type ControlStates } from '@storybook/instrument

import { transparentize } from 'polished';

import { isChaiError, isJestError } from '../utils';
import { isChaiError, isJestError, useAnsiToHtmlFilter } from '../utils';
import type { Controls } from './InteractionsPanel';
import { MatcherResult } from './MatcherResult';
import { MethodCall } from './MethodCall';
Expand Down Expand Up @@ -116,6 +116,7 @@ const RowMessage = styled('div')(({ theme }) => ({
}));

export const Exception = ({ exception }: { exception: Call['exception'] }) => {
const filter = useAnsiToHtmlFilter();
if (isJestError(exception)) {
return <MatcherResult {...exception} />;
}
Expand All @@ -135,7 +136,7 @@ export const Exception = ({ exception }: { exception: Call['exception'] }) => {
const more = paragraphs.length > 1;
return (
<RowMessage>
<pre>{paragraphs[0]}</pre>
<pre dangerouslySetInnerHTML={{ __html: filter.toHtml(paragraphs[0]) }}></pre>
{more && <p>See the full stack trace in the browser console.</p>}
</RowMessage>
);
Expand Down
12 changes: 8 additions & 4 deletions code/addons/interactions/src/components/InteractionsPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { type Call, CallStates, type ControlStates } from '@storybook/instrument

import { transparentize } from 'polished';

import { isTestAssertionError } from '../utils';
import { isTestAssertionError, useAnsiToHtmlFilter } from '../utils';
import { Empty } from './EmptyState';
import { Interaction } from './Interaction';
import { Subnav } from './Subnav';
Expand Down Expand Up @@ -97,6 +97,7 @@ export const InteractionsPanel: React.FC<InteractionsPanelProps> = React.memo(
onScrollToEnd,
endRef,
}) {
const filter = useAnsiToHtmlFilter();
return (
<Container>
{(interactions.length > 0 || hasException) && (
Expand Down Expand Up @@ -131,9 +132,12 @@ export const InteractionsPanel: React.FC<InteractionsPanelProps> = React.memo(
<CaughtExceptionTitle>
Caught exception in <CaughtExceptionCode>play</CaughtExceptionCode> function
</CaughtExceptionTitle>
<CaughtExceptionStack data-chromatic="ignore">
{printSerializedError(caughtException)}
</CaughtExceptionStack>
<CaughtExceptionStack
data-chromatic="ignore"
dangerouslySetInnerHTML={{
__html: filter.toHtml(printSerializedError(caughtException)),
}}
></CaughtExceptionStack>
</CaughtException>
)}
{unhandledErrors && (
Expand Down
10 changes: 9 additions & 1 deletion code/addons/interactions/src/components/MatcherResult.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React from 'react';

import { styled, typography } from 'storybook/internal/theming';

import { useAnsiToHtmlFilter } from '../utils';
import { Node } from './MethodCall';

const getParams = (line: string, fromIndex = 0): string => {
Expand Down Expand Up @@ -59,6 +60,7 @@ export const MatcherResult = ({
message: string;
style?: React.CSSProperties;
}) => {
const filter = useAnsiToHtmlFilter();
const lines = message.split('\n');
return (
<pre
Expand Down Expand Up @@ -131,7 +133,13 @@ export const MatcherResult = ({
];
}

return [<span key={line + index}>{line}</span>, <br key={`br${index}`} />];
return [
<span
key={line + index}
dangerouslySetInnerHTML={{ __html: filter.toHtml(line) }}
></span>,
<br key={`br${index}`} />,
];
})}
</pre>
);
Expand Down
16 changes: 16 additions & 0 deletions code/addons/interactions/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import { type StorybookTheme, useTheme } from 'storybook/internal/theming';

import Filter from 'ansi-to-html';

export function isTestAssertionError(error: unknown) {
return isChaiError(error) || isJestError(error);
}
Expand All @@ -21,3 +25,15 @@ export function isJestError(error: unknown) {
error.message.startsWith('expect(')
);
}

export function createAnsiToHtmlFilter(theme: StorybookTheme) {
return new Filter({
fg: theme.color.defaultText,
bg: theme.background.content,
});
}

export function useAnsiToHtmlFilter() {
const theme = useTheme();
return createAnsiToHtmlFilter(theme);
}
49 changes: 49 additions & 0 deletions code/core/src/csf-tools/vitest-plugin/transformer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,55 @@ describe('transformer', () => {
`);
});

describe("use the story's name as test title", () => {
it('should support CSF v3 via name property', async () => {
const code = `
export default { component: Button }
export const Primary = { name: "custom name" };`;
const result = await transform({ code });

expect(result.code).toMatchInlineSnapshot(`
import { test as _test, expect as _expect } from "vitest";
import { testStory as _testStory } from "@storybook/experimental-addon-test/internal/test-utils";
const _meta = {
component: Button,
title: "automatic/calculated/title"
};
export default _meta;
export const Primary = {
name: "custom name"
};
const _isRunningFromThisFile = import.meta.url.includes(globalThis.__vitest_worker__.filepath ?? _expect.getState().testPath);
if (_isRunningFromThisFile) {
_test("custom name", _testStory("Primary", Primary, _meta, []));
}
`);
});

it('should support CSF v1/v2 via storyName property', async () => {
const code = `
export default { component: Button }
export const Story = () => {}
Story.storyName = 'custom name';`;
const result = await transform({ code: code });
expect(result.code).toMatchInlineSnapshot(`
import { test as _test, expect as _expect } from "vitest";
import { testStory as _testStory } from "@storybook/experimental-addon-test/internal/test-utils";
const _meta = {
component: Button,
title: "automatic/calculated/title"
};
export default _meta;
export const Story = () => {};
Story.storyName = 'custom name';
const _isRunningFromThisFile = import.meta.url.includes(globalThis.__vitest_worker__.filepath ?? _expect.getState().testPath);
if (_isRunningFromThisFile) {
_test("custom name", _testStory("Story", Story, _meta, []));
}
`);
});
});

it('should add test statement to const declared exported stories', async () => {
const code = `
export default {};
Expand Down
11 changes: 6 additions & 5 deletions code/core/src/csf-tools/vitest-plugin/transformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -202,15 +202,17 @@ export async function vitestTransform({

const getTestStatementForStory = ({
exportName,
testTitle,
node,
}: {
exportName: string;
testTitle: string;
node: t.Node;
}): t.ExpressionStatement => {
// Create the _test expression directly using the exportName identifier
const testStoryCall = t.expressionStatement(
t.callExpression(vitestTestId, [
t.stringLiteral(exportName),
t.stringLiteral(testTitle),
t.callExpression(testStoryId, [
t.stringLiteral(exportName),
t.identifier(exportName),
Expand Down Expand Up @@ -239,10 +241,9 @@ export async function vitestTransform({
return;
}

return getTestStatementForStory({
exportName,
node,
});
// use the story's name as the test title for vitest, and fallback to exportName
const testTitle = parsed._stories[exportName].name ?? exportName;
return getTestStatementForStory({ testTitle, exportName, node });
})
.filter((st) => !!st) as t.ExpressionStatement[];

Expand Down
3 changes: 2 additions & 1 deletion code/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -295,5 +295,6 @@
"Dependency Upgrades"
]
]
}
},
"deferredNextVersion": "8.3.4"
}
5 changes: 3 additions & 2 deletions code/renderers/react/src/__test__/portable-stories.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import React from 'react';

import { addons } from 'storybook/internal/preview-api';

import type { Meta } from '@storybook/react';
import type { ProjectAnnotations } from '@storybook/csf';
import type { Meta, ReactRenderer } from '@storybook/react';

import * as addonActionsPreview from '@storybook/addon-actions/preview';

Expand Down Expand Up @@ -124,7 +125,7 @@ describe('projectAnnotations', () => {
const Story = composeStory(
ButtonStories.WithActionArgType,
ButtonStories.default,
addonActionsPreview
addonActionsPreview as ProjectAnnotations<ReactRenderer>
);
expect(Story.args.someActionArg).toHaveProperty('isAction', true);
});
Expand Down
1 change: 1 addition & 0 deletions code/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5492,6 +5492,7 @@ __metadata:
"@storybook/instrumenter": "workspace:*"
"@storybook/test": "workspace:*"
"@types/node": "npm:^22.0.0"
ansi-to-html: "npm:^0.7.2"
formik: "npm:^2.2.9"
polished: "npm:^4.2.2"
react: "npm:^18.2.0"
Expand Down
2 changes: 1 addition & 1 deletion docs/versions/latest.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"version":"8.3.3","info":{"plain":"- CLI: Show constraints in error when getting depndencies - [#29187](https://github.com/storybookjs/storybook/pull/29187), thanks @andrasczeh!\n- React-Vite: Downgrade react-docgen-typescript plugin - [#29184](https://github.com/storybookjs/storybook/pull/29184), thanks @shilman!\n- UI: Fix composed storybook TooltipLinkList bug where href isn't passed forward - [#29175](https://github.com/storybookjs/storybook/pull/29175), thanks @JSMike!"}}
{"version":"8.3.4","info":{"plain":"- Addon Test: Support story name as test description - [#29147](https://github.com/storybookjs/storybook/pull/29147), thanks @InfiniteXyy!\n- Addon-Interactions: Use ansi-to-html for colored test errors - [#29110](https://github.com/storybookjs/storybook/pull/29110), thanks @kasperpeulen!"}}
10 changes: 10 additions & 0 deletions docs/writing-tests/vitest-plugin.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,16 @@ We recommend running tests in a browser using Playwright, but you can use WebDri

We recommend using Chromium, because it is most likely to best match the experience of a majority of your users. However, you can use other browsers by adjusting the [browser name in the Vitest configuration file](https://vitest.dev/config/#browser-name). Note that [Playwright and WebDriverIO support different browsers](https://vitest.dev/guide/browser/#browser-option-types).

### How do I customize a test name?

By default, the export name of a story is mapped to the test name. To create a more descriptive test description, you can provide a `name` property for the story. This allows you to include spaces, brackets, or other special characters.

```js
export const Story = {
name: 'custom, descriptive name'
};
```

## API

### Exports
Expand Down

0 comments on commit a1307dd

Please sign in to comment.