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

Release: Prerelease 8.5.0-alpha.20 #29999

Merged
merged 69 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
86e4c96
always run vitest in watch mode
JReinhold Nov 29, 2024
92ef7bf
Merge branch 'jeppe/vitest-coverage-backend' into jeppe/always-watch-…
JReinhold Nov 29, 2024
e5fb87d
fix coverage mode toggling
JReinhold Dec 2, 2024
81a48a3
merge viteFinal config into vitest config
ndelangen Dec 4, 2024
b49ef5d
add support for preview-head.html files from storybook
ndelangen Dec 4, 2024
681f82b
Merge branch 'next' into norbert/custom-vitest-config-support
ndelangen Dec 4, 2024
a124e49
Merge branch 'norbert/custom-vitest-config-support' into norbert/vite…
ndelangen Dec 4, 2024
5eb5af5
prompt user to switch to the experimental-nextjs-vite framework when …
ndelangen Dec 4, 2024
c24084b
support for monorepo framework setting
ndelangen Dec 5, 2024
abf295d
Merge branch 'next' into norbert/test-addon-asking-for-experimental-f…
ndelangen Dec 5, 2024
6ee76a3
fix compile
ndelangen Dec 5, 2024
03e235b
copy WIP from E2E branch
JReinhold Dec 5, 2024
f1bd0ba
make plugin async & await load storybook options
ndelangen Dec 6, 2024
47101c6
add coverage unit tests
JReinhold Dec 6, 2024
b7b3116
add a delay to continue after mimicking a HMR
ndelangen Dec 6, 2024
50bfe4a
Merge branch 'next' into jeppe/always-watch-vitest
JReinhold Dec 6, 2024
5a04476
Merge branch 'next' into norbert/custom-vitest-config-support
JReinhold Dec 6, 2024
df88bcb
Merge branch 'norbert/custom-vitest-config-support' into norbert/vite…
JReinhold Dec 6, 2024
8dfbc95
Merge branch 'next' into norbert/test-addon-asking-for-experimental-f…
ndelangen Dec 6, 2024
042cc7d
Merge branch 'next' into norbert/test-addon-asking-for-experimental-f…
ndelangen Dec 6, 2024
0756bc3
Merge branch 'next' into norbert/test-addon-asking-for-experimental-f…
ndelangen Dec 9, 2024
fb2f874
add a prerequisiteCheck for custom webpack config & improve messaging…
ndelangen Dec 9, 2024
36ce345
Merge branch 'next' into norbert/custom-vitest-config-support
ndelangen Dec 9, 2024
7c9f43d
Make component tests status row link to the story's tests panel
ghengeveld Dec 9, 2024
f184644
simplify code
ndelangen Dec 9, 2024
9e0fa3a
Merge branch 'norbert/custom-vitest-config-support' into norbert/vite…
ndelangen Dec 9, 2024
3e3a6a7
do work in parallel
ndelangen Dec 9, 2024
d26fe10
on CI just go ahead and migrate upon init
ndelangen Dec 9, 2024
860edea
Detect presence of coverage reporter and install coverage-v8 if none …
ghengeveld Dec 9, 2024
b837ec6
add debugging
ndelangen Dec 9, 2024
ce1fd01
remove redundant check & remove linting problem
ndelangen Dec 9, 2024
f65dfe1
Merge branch 'next' into link-to-tests-panel
ghengeveld Dec 9, 2024
9c968ff
Cleanup
ghengeveld Dec 9, 2024
57efbcb
Link to Vitest docs for more info
ghengeveld Dec 9, 2024
8d5fe59
Add missing import
ghengeveld Dec 9, 2024
142c19e
improve / debug
ndelangen Dec 9, 2024
685a3e8
Merge branch 'next' of github.com:storybookjs/storybook into jeppe/al…
JReinhold Dec 10, 2024
b6c10f4
Use ProgressSpinner in testing module
ghengeveld Dec 10, 2024
f124fad
Merge remote-tracking branch 'origin/next' into link-to-tests-panel
valentinpalkovic Dec 10, 2024
761bba6
Avoid division by zero
ghengeveld Dec 10, 2024
ec8dbd3
Merge branch 'next' into norbert/test-addon-asking-for-experimental-f…
ndelangen Dec 10, 2024
940dbd7
Consistency
ghengeveld Dec 10, 2024
9c005ef
correct spelling mistake
ndelangen Dec 10, 2024
cd0087d
Handle undefined storyId
ghengeveld Dec 10, 2024
57cb78b
update yarn.lock
JReinhold Dec 10, 2024
12179c1
Merge branch 'next' of github.com:storybookjs/storybook into jeppe/al…
JReinhold Dec 10, 2024
92eec54
fix problem, manual test, the postinstall runs correctly
ndelangen Dec 10, 2024
fa52f3b
Refactor TestProviderRender to support multiple panels and improve ac…
valentinpalkovic Dec 10, 2024
a9ea51e
cleanup vite config handling
JReinhold Dec 10, 2024
49db3b8
Merge branch 'norbert/custom-vitest-config-support' of github.com:sto…
JReinhold Dec 10, 2024
2949bf9
fix cleanup
JReinhold Dec 10, 2024
e255f6d
Merge pull request #29997 from storybookjs/replace-stop-button
ghengeveld Dec 10, 2024
26838bf
Merge branch 'next' into fix-undefined
ghengeveld Dec 10, 2024
464f367
Merge branch 'next' into 29797-test-addon-should-install-coverage-pro…
ghengeveld Dec 10, 2024
a1082cd
Improve panel opening logic in TestProviderRender for better handling…
valentinpalkovic Dec 10, 2024
171304c
Merge pull request #29998 from storybookjs/fix-undefined
ghengeveld Dec 10, 2024
b60cec0
install correct version of framework
ndelangen Dec 10, 2024
2c17aef
Merge pull request #29993 from storybookjs/29797-test-addon-should-in…
ghengeveld Dec 10, 2024
f367d6b
Merge branch 'next' of github.com:storybookjs/storybook into norbert/…
JReinhold Dec 10, 2024
dc9b515
Merge branch 'norbert/custom-vitest-config-support' of github.com:sto…
JReinhold Dec 10, 2024
7389774
Merge pull request #29992 from storybookjs/link-to-tests-panel
valentinpalkovic Dec 10, 2024
7141d6d
Filter out falsy test results in TestProviderRender for improved data…
valentinpalkovic Dec 10, 2024
76ce9db
Merge pull request #29749 from storybookjs/jeppe/always-watch-vitest
JReinhold Dec 10, 2024
46743b4
cleanup
JReinhold Dec 10, 2024
8872560
Merge pull request #29806 from storybookjs/norbert/custom-vitest-conf…
JReinhold Dec 10, 2024
cf80d5c
Merge pull request #29808 from storybookjs/norbert/vitest-support-pre…
JReinhold Dec 10, 2024
f4a084d
Merge pull request #30001 from storybookjs/valentin/fix-undefined-issue
valentinpalkovic Dec 10, 2024
190107d
Merge pull request #29814 from storybookjs/norbert/test-addon-asking-…
ndelangen Dec 10, 2024
28e19d0
Write changelog for 8.5.0-alpha.20 [skip ci]
storybook-bot Dec 10, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.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!
- Addon Test: Add support for previewHead - [#29808](https://github.com/storybookjs/storybook/pull/29808), thanks @ndelangen!
- Addon Test: Always run Vitest in watch mode internally - [#29749](https://github.com/storybookjs/storybook/pull/29749), thanks @JReinhold!
- Addon Test: Filter out falsy test results in TestProviderRender - [#30001](https://github.com/storybookjs/storybook/pull/30001), thanks @valentinpalkovic!
- Addon Test: Handle undefined storyId - [#29998](https://github.com/storybookjs/storybook/pull/29998), thanks @ghengeveld!
- Addon Test: Make component tests status row link to the story's tests panel - [#29992](https://github.com/storybookjs/storybook/pull/29992), thanks @ghengeveld!
- Addon Test: Merge viteFinal config into vitest config - [#29806](https://github.com/storybookjs/storybook/pull/29806), thanks @ndelangen!
- Addon Test: Prompt switch to `experimental-nextjs-vite` - [#29814](https://github.com/storybookjs/storybook/pull/29814), thanks @ndelangen!
- Addon Test: Use ProgressSpinner for stop button in Testing Module - [#29997](https://github.com/storybookjs/storybook/pull/29997), thanks @ghengeveld!

## 8.5.0-alpha.19

- Addon A11y: Create a11y test provider and revamp a11y addon - [#29643](https://github.com/storybookjs/storybook/pull/29643), thanks @valentinpalkovic!
Expand Down
1 change: 0 additions & 1 deletion code/addons/test/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,6 @@
"@storybook/icons": "^1.2.12",
"@storybook/instrumenter": "workspace:*",
"@storybook/test": "workspace:*",
"@storybook/theming": "workspace:*",
"polished": "^4.2.2",
"prompts": "^2.4.0",
"ts-dedent": "^2.2.0"
Expand Down
59 changes: 51 additions & 8 deletions code/addons/test/src/components/TestProviderRender.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { type ComponentProps, type FC, useCallback, useMemo, useRef, useState } from 'react';

import { Button, ListItem } from 'storybook/internal/components';
import { Button, ListItem, ProgressSpinner } from 'storybook/internal/components';
import {
TESTING_MODULE_CONFIG_CHANGE,
type TestProviderConfig,
Expand All @@ -17,15 +17,17 @@ import {
PlayHollowIcon,
PointerHandIcon,
ShieldIcon,
StopAltHollowIcon,
StopAltIcon,
} from '@storybook/icons';

import { isEqual } from 'es-toolkit';
import { debounce } from 'es-toolkit/compat';

// Relatively importing from a11y to get the ADDON_ID
import { ADDON_ID as A11Y_ADDON_ID } from '../../../a11y/src/constants';
import { type Config, type Details } from '../constants';
import {
ADDON_ID as A11Y_ADDON_ID,
PANEL_ID as A11y_ADDON_PANEL_ID,
} from '../../../a11y/src/constants';
import { type Config, type Details, PANEL_ID } from '../constants';
import { type TestStatus } from '../node/reporter';
import { Description } from './Description';
import { TestStatusIcon } from './TestStatusIcon';
Expand Down Expand Up @@ -66,6 +68,14 @@ const Checkbox = styled.input({
},
});

const Progress = styled(ProgressSpinner)({
margin: 2,
});

const StopIcon = styled(StopAltIcon)({
width: 10,
});

const statusOrder: TestStatus[] = ['failed', 'warning', 'pending', 'passed', 'skipped'];
const statusMap: Record<TestStatus, ComponentProps<typeof TestStatusIcon>['status']> = {
failed: 'negative',
Expand Down Expand Up @@ -101,7 +111,8 @@ export const TestProviderRender: FC<

return state.details?.testResults?.flatMap((result) =>
result.results
.filter((it) => !entryId || it.storyId === entryId || it.storyId.startsWith(`${entryId}-`))
.filter(Boolean)
.filter((r) => !entryId || r.storyId === entryId || r.storyId?.startsWith(`${entryId}-`))
.map((r) => r.reports.find((report) => report.type === 'a11y'))
);
}, [isA11yAddon, state.details?.testResults, entryId]);
Expand Down Expand Up @@ -145,6 +156,12 @@ export const TestProviderRender: FC<

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

const openPanel = (id: string, panelId: string) => {
api.selectStory(id);
api.setSelectedPanel(panelId);
api.togglePanel(true);
};

return (
<Container {...props}>
<Heading>
Expand Down Expand Up @@ -182,11 +199,13 @@ export const TestProviderRender: FC<
<Button
aria-label={`Stop ${state.name}`}
variant="ghost"
padding="small"
padding="none"
onClick={() => api.cancelTestProvider(state.id)}
disabled={state.cancelling}
>
<StopAltHollowIcon />
<Progress percentage={state.progress?.percentageCompleted}>
<StopIcon />
</Progress>
</Button>
) : (
<Button
Expand Down Expand Up @@ -244,6 +263,16 @@ export const TestProviderRender: FC<
<Extras>
<ListItem
title="Component tests"
onClick={
(status === 'failed' || status === 'warning') && results.length
? () => {
const firstNotPassed = results.find(
(r) => r.status === 'failed' || r.status === 'warning'
);
openPanel(firstNotPassed.storyId, PANEL_ID);
}
: null
}
icon={
state.crashed ? (
<TestStatusIcon status="critical" aria-label="status: crashed" />
Expand Down Expand Up @@ -278,6 +307,20 @@ export const TestProviderRender: FC<
{isA11yAddon && (
<ListItem
title="Accessibility"
onClick={
(a11yStatus === 'negative' || a11yStatus === 'warning') && a11yResults.length
? () => {
const firstNotPassed = results.find((r) =>
r.reports
.filter((report) => report.type === 'a11y')
.find(
(report) => report.status === 'failed' || report.status === 'warning'
)
);
openPanel(firstNotPassed.storyId, A11y_ADDON_PANEL_ID);
}
: null
}
icon={<TestStatusIcon status={a11yStatus} aria-label={`status: ${a11yStatus}`} />}
right={a11yNotPassedAmount || null}
/>
Expand Down
14 changes: 7 additions & 7 deletions code/addons/test/src/manager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const statusMap: Record<TestStatus, API_StatusValue> = {
addons.register(ADDON_ID, (api) => {
const storybookBuilder = (globalThis as any).STORYBOOK_BUILDER || '';
if (storybookBuilder.includes('vite')) {
const openAddonPanel = () => {
const openTestsPanel = () => {
api.setSelectedPanel(PANEL_ID);
api.togglePanel(true);
};
Expand Down Expand Up @@ -94,9 +94,9 @@ addons.register(ADDON_ID, (api) => {
? rest.failureMessages.join('\n')
: '',
data: { testRunId },
onClick: openAddonPanel,
onClick: openTestsPanel,
sidebarContextMenu: false,
} as API_StatusObject,
} satisfies API_StatusObject,
])
)
)
Expand All @@ -108,12 +108,12 @@ addons.register(ADDON_ID, (api) => {
update.details.testResults.flatMap((testResult) =>
testResult.results
.filter(({ storyId }) => storyId)
.map(({ storyId, status, testRunId, reports, ...rest }) => {
.map(({ storyId, testRunId, reports }) => {
const a11yReport = reports.find((r: any) => r.type === 'a11y');
return [
storyId,
a11yReport
? {
? ({
title: 'Accessibility tests',
description: '',
status: statusMap[a11yReport.status],
Expand All @@ -123,9 +123,9 @@ addons.register(ADDON_ID, (api) => {
api.togglePanel(true);
},
sidebarContextMenu: false,
}
} satisfies API_StatusObject)
: null,
] as const;
];
})
)
)
Expand Down
9 changes: 7 additions & 2 deletions code/addons/test/src/node/reporter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export type TestResultResult =
reports: Report[];
}
| {
status: Extract<TestStatus, 'failed'>;
status: Extract<TestStatus, 'failed' | 'warning'>;
storyId: string;
duration: number;
testRunId: string;
Expand All @@ -39,7 +39,7 @@ export type TestResult = {
results: TestResultResult[];
startTime: number;
endTime: number;
status: Extract<TestStatus, 'passed' | 'failed'>;
status: Extract<TestStatus, 'passed' | 'failed' | 'warning'>;
message?: string;
};

Expand Down Expand Up @@ -165,6 +165,11 @@ export class StorybookReporter implements Reporter {
numTotalTests,
startedAt: this.start,
finishedAt,
percentageCompleted: finishedAt
? 100
: numTotalTests
? ((numPassedTests + numFailedTests) / numTotalTests) * 100
: 0,
} as TestingModuleProgressReportProgress,
details: {
testResults,
Expand Down
58 changes: 56 additions & 2 deletions code/addons/test/src/node/test-manager.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, expect, it, vi } from 'vitest';
import { createVitest } from 'vitest/node';
import { createVitest as actualCreateVitest } from 'vitest/node';

import { Channel, type ChannelTransport } from '@storybook/core/channels';
import type { StoryIndex } from '@storybook/types';
Expand Down Expand Up @@ -34,6 +34,7 @@ const vitest = vi.hoisted(() => ({
vi.mock('vitest/node', () => ({
createVitest: vi.fn(() => Promise.resolve(vitest)),
}));
const createVitest = vi.mocked(actualCreateVitest);

const transport = { setHandler: vi.fn(), send: vi.fn() } satisfies ChannelTransport;
const mockChannel = new Channel({ transport });
Expand Down Expand Up @@ -109,7 +110,7 @@ describe('TestManager', () => {

await testManager.handleWatchModeRequest({ providerId: TEST_PROVIDER_ID, watchMode: true });
expect(testManager.watchMode).toBe(true);
expect(createVitest).toHaveBeenCalledTimes(2);
expect(createVitest).toHaveBeenCalledTimes(1); // shouldn't restart vitest
});

it('should handle run request', async () => {
Expand Down Expand Up @@ -145,4 +146,57 @@ describe('TestManager', () => {
expect(setTestNamePattern).toHaveBeenCalledWith(/^One$/);
expect(vitest.runFiles).toHaveBeenCalledWith(tests.slice(0, 1), true);
});

it('should handle coverage toggling', async () => {
const testManager = await TestManager.start(mockChannel, options);
expect(testManager.coverage).toBe(false);
expect(createVitest).toHaveBeenCalledTimes(1);
createVitest.mockClear();

await testManager.handleConfigChange({
providerId: TEST_PROVIDER_ID,
config: { coverage: true, a11y: false },
});
expect(testManager.coverage).toBe(true);
expect(createVitest).toHaveBeenCalledTimes(1);
createVitest.mockClear();

await testManager.handleConfigChange({
providerId: TEST_PROVIDER_ID,
config: { coverage: false, a11y: false },
});
expect(testManager.coverage).toBe(false);
expect(createVitest).toHaveBeenCalledTimes(1);
});

it('should temporarily disable coverage on focused tests', async () => {
vitest.globTestSpecs.mockImplementation(() => tests);
const testManager = await TestManager.start(mockChannel, options);
expect(testManager.coverage).toBe(false);
expect(createVitest).toHaveBeenCalledTimes(1);

await testManager.handleConfigChange({
providerId: TEST_PROVIDER_ID,
config: { coverage: true, a11y: false },
});
expect(testManager.coverage).toBe(true);
expect(createVitest).toHaveBeenCalledTimes(2);

await testManager.handleRunRequest({
providerId: TEST_PROVIDER_ID,
indexUrl: 'http://localhost:6006/index.json',
storyIds: ['button--primary', 'button--secondary'],
});
// expect vitest to be restarted twice, without and with coverage
expect(createVitest).toHaveBeenCalledTimes(4);
expect(vitest.runFiles).toHaveBeenCalledWith([], true);

await testManager.handleRunRequest({
providerId: TEST_PROVIDER_ID,
indexUrl: 'http://localhost:6006/index.json',
});
// don't expect vitest to be restarted, as we're running all tests
expect(createVitest).toHaveBeenCalledTimes(4);
expect(vitest.runFiles).toHaveBeenCalledWith(tests, true);
});
});
Loading
Loading