Skip to content

Commit

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

Release: Prerelease 8.5.0-alpha.12
  • Loading branch information
yannbf authored Nov 28, 2024
2 parents da1f1a0 + 69de98c commit 021d6bf
Show file tree
Hide file tree
Showing 27 changed files with 520 additions and 190 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.prerelease.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## 8.5.0-alpha.12

- Core / Addon Test: Add config UI to Testing Module - [#29708](https://github.com/storybookjs/storybook/pull/29708), thanks @ghengeveld!
- Manager: Add tags property to GroupEntry objects - [#29672](https://github.com/storybookjs/storybook/pull/29672), thanks @Sidnioulz!
- Svelte: Support `@sveltejs/vite-plugin-svelte` v5 - [#29731](https://github.com/storybookjs/storybook/pull/29731), thanks @JReinhold!
- Toolbars: Suppress deprecation warning when using dynamic icons - [#29545](https://github.com/storybookjs/storybook/pull/29545), thanks @ValeraS!

## 8.5.0-alpha.11

- Core + Addon Test: Refactor test API and fix total test count - [#29656](https://github.com/storybookjs/storybook/pull/29656), thanks @ghengeveld!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export function GuidedTour({
const theme = useTheme();

useEffect(() => {
let timeout: NodeJS.Timeout;
let timeout: ReturnType<typeof setTimeout>;
setStepIndex((current) => {
const index = steps.findIndex(({ key }) => key === step);

Expand Down
25 changes: 22 additions & 3 deletions code/addons/test/src/components/Description.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from 'react';
import React, { useEffect } from 'react';

import { Link as LinkComponent } from 'storybook/internal/components';
import { type TestProviderConfig, type TestProviderState } from 'storybook/internal/core-events';
Expand All @@ -11,6 +11,10 @@ export const DescriptionStyle = styled.div(({ theme }) => ({
color: theme.barTextColor,
}));

const PositiveText = styled.span(({ theme }) => ({
color: theme.color.positiveText,
}));

export function Description({
errorMessage,
setIsModalOpen,
Expand All @@ -20,9 +24,24 @@ export function Description({
errorMessage: string;
setIsModalOpen: React.Dispatch<React.SetStateAction<boolean>>;
}) {
let description: string | React.ReactNode = 'Not run';
const isMounted = React.useRef(false);
const [isUpdated, setUpdated] = React.useState(false);

if (state.running) {
useEffect(() => {
if (isMounted.current) {
setUpdated(true);
const timeout = setTimeout(setUpdated, 2000, false);
return () => {
clearTimeout(timeout);
};
}
isMounted.current = true;
}, [state.config]);

let description: string | React.ReactNode = 'Not run';
if (isUpdated) {
description = <PositiveText>Settings updated</PositiveText>;
} else if (state.running) {
description = state.progress
? `Testing... ${state.progress.numPassedTests}/${state.progress.numTotalTests}`
: 'Starting...';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ const managerContext: any = {
},
},
api: {
getDocsUrl: fn().mockName('api::getDocsUrl'),
getDocsUrl: fn(({ subpath }) => `https://storybook.js.org/docs/${subpath}`).mockName(
'api::getDocsUrl'
),
emit: fn().mockName('api::emit'),
updateTestProviderState: fn().mockName('api::updateTestProviderState'),
},
Expand Down Expand Up @@ -98,6 +100,9 @@ export default {
</ManagerContext.Provider>
),
],
parameters: {
layout: 'fullscreen',
},
} as Meta<typeof TestProviderRender>;

export const Default: Story = {
Expand Down Expand Up @@ -153,6 +158,6 @@ export const EnableEditing: Story = {
play: async ({ canvasElement }) => {
const screen = within(canvasElement);

screen.getByLabelText('Edit').click();
screen.getByLabelText(/Open settings/).click();
},
};
185 changes: 123 additions & 62 deletions code/addons/test/src/components/TestProviderRender.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,43 @@
import React, { type FC, Fragment, useCallback, useRef, useState } from 'react';
import React, { type FC, useCallback, useRef, useState } from 'react';

import { Button } from 'storybook/internal/components';
import { Button, ListItem } from 'storybook/internal/components';
import {
TESTING_MODULE_CONFIG_CHANGE,
type TestProviderConfig,
type TestProviderState,
type TestingModuleConfigChangePayload,
} from 'storybook/internal/core-events';
import type { API } from 'storybook/internal/manager-api';
import { styled } from 'storybook/internal/theming';
import { styled, useTheme } from 'storybook/internal/theming';

import { EditIcon, EyeIcon, PlayHollowIcon, StopAltHollowIcon } from '@storybook/icons';
import {
AccessibilityIcon,
EditIcon,
EyeIcon,
PlayHollowIcon,
PointerHandIcon,
ShieldIcon,
StopAltHollowIcon,
} from '@storybook/icons';

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

import { type Config, type Details, TEST_PROVIDER_ID } from '../constants';
import { Description } from './Description';
import { GlobalErrorModal } from './GlobalErrorModal';
import { TestStatusIcon } from './TestStatusIcon';

const Container = styled.div({
display: 'flex',
flexDirection: 'column',
});

const Heading = styled.div({
display: 'flex',
justifyContent: 'space-between',
padding: '8px 2px',
gap: 6,
});

const Info = styled.div({
display: 'flex',
Expand All @@ -33,32 +56,37 @@ const Actions = styled.div({
gap: 6,
});

const Head = styled.div({
display: 'flex',
justifyContent: 'space-between',
gap: 6,
const Extras = styled.div({
marginBottom: 2,
});

const Checkbox = styled.input({
margin: 0,
'&:enabled': {
cursor: 'pointer',
},
});

export const TestProviderRender: FC<{
api: API;
state: TestProviderConfig & TestProviderState<Details, Config>;
}> = ({ state, api }) => {
const [isEditing, setIsEditing] = useState(false);
const [isModalOpen, setIsModalOpen] = useState(false);
const theme = useTheme();

const title = state.crashed || state.failed ? 'Component tests failed' : 'Component tests';
const title = state.crashed || state.failed ? 'Local tests failed' : 'Run local tests';
const errorMessage = state.error?.message;

const [config, changeConfig] = useConfig(
const [config, updateConfig] = useConfig(
api,
state.id,
state.config || { a11y: false, coverage: false },
api
state.config || { a11y: false, coverage: false }
);

const [isEditing, setIsEditing] = useState(false);

return (
<Fragment>
<Head>
<Container>
<Heading>
<Info>
<Title crashed={state.crashed} id="testing-module-title">
{title}
Expand All @@ -68,11 +96,11 @@ export const TestProviderRender: FC<{

<Actions>
<Button
aria-label={`Edit`}
aria-label={`${isEditing ? 'Close' : 'Open'} settings for ${state.name}`}
variant="ghost"
padding="small"
active={isEditing}
onClick={() => setIsEditing((v) => !v)}
onClick={() => setIsEditing(!isEditing)}
>
<EditIcon />
</Button>
Expand Down Expand Up @@ -105,7 +133,7 @@ export const TestProviderRender: FC<{
aria-label={`Start ${state.name}`}
variant="ghost"
padding="small"
onClick={() => api.runTestProvider(state.id, {})}
onClick={() => api.runTestProvider(state.id)}
disabled={state.crashed || state.running}
>
<PlayHollowIcon />
Expand All @@ -114,29 +142,60 @@ export const TestProviderRender: FC<{
</>
)}
</Actions>
</Head>

{!isEditing ? (
<Fragment>
{Object.entries(config).map(([key, value]) => (
<div key={key}>
{key}: {value ? 'ON' : 'OFF'}
</div>
))}
</Fragment>
</Heading>

{isEditing ? (
<Extras>
<ListItem
as="label"
title="Component tests"
icon={<PointerHandIcon color={theme.textMutedColor} />}
right={<Checkbox type="checkbox" checked disabled />}
/>
<ListItem
as="label"
title="Coverage"
icon={<ShieldIcon color={theme.textMutedColor} />}
right={
<Checkbox
type="checkbox"
disabled // TODO: Implement coverage
checked={config.coverage}
onChange={() => updateConfig({ coverage: !config.coverage })}
/>
}
/>
<ListItem
as="label"
title="Accessibility"
icon={<AccessibilityIcon color={theme.textMutedColor} />}
right={
<Checkbox
type="checkbox"
disabled // TODO: Implement a11y
checked={config.a11y}
onChange={() => updateConfig({ a11y: !config.a11y })}
/>
}
/>
</Extras>
) : (
<Fragment>
{Object.entries(config).map(([key, value]) => (
<div
key={key}
onClick={() => {
changeConfig({ [key]: !value });
}}
>
{key}: {value ? 'ON' : 'OFF'}
</div>
))}
</Fragment>
<Extras>
<ListItem
title="Component tests"
icon={<TestStatusIcon status="positive" aria-label="status: passed" />}
/>
<ListItem
title="Coverage"
icon={<TestStatusIcon percentage={60} status="warning" aria-label="status: warning" />}
right={`60%`}
/>
<ListItem
title="Accessibility"
icon={<TestStatusIcon status="negative" aria-label="status: failed" />}
right={73}
/>
</Extras>
)}

<GlobalErrorModal
Expand All @@ -150,33 +209,35 @@ export const TestProviderRender: FC<{
api.runTestProvider(TEST_PROVIDER_ID);
}}
/>
</Fragment>
</Container>
);
};

function useConfig(id: string, config: Config, api: API) {
const data = useRef<Config>(config);
data.current = config || {
a11y: false,
coverage: false,
};
function useConfig(api: API, providerId: string, initialConfig: Config) {
const [currentConfig, setConfig] = useState<Config>(initialConfig);
const lastConfig = useRef(initialConfig);

const saveConfig = useCallback(
debounce((config: Config) => {
if (!isEqual(config, lastConfig.current)) {
api.updateTestProviderState(providerId, { config });
api.emit(TESTING_MODULE_CONFIG_CHANGE, { providerId, config });
lastConfig.current = config;
}
}, 500),
[api, providerId]
);

const changeConfig = useCallback(
const updateConfig = useCallback(
(update: Partial<Config>) => {
const newConfig = {
...data.current,
...update,
};
api.updateTestProviderState(id, {
config: newConfig,
setConfig((value) => {
const updated = { ...value, ...update };
saveConfig(updated);
return updated;
});
api.emit(TESTING_MODULE_CONFIG_CHANGE, {
providerId: id,
config: newConfig,
} as TestingModuleConfigChangePayload);
},
[api, id]
[saveConfig]
);

return [data.current, changeConfig] as const;
return [currentConfig, updateConfig] as const;
}
Loading

0 comments on commit 021d6bf

Please sign in to comment.