mirror of
https://github.com/storybookjs/storybook.git
synced 2025-03-31 05:03:21 +08:00
Add specs
This commit is contained in:
parent
64716db698
commit
097ad6fae5
@ -88,8 +88,8 @@ export interface SidebarProps {
|
||||
enableShortcuts?: boolean;
|
||||
}
|
||||
|
||||
export const Sidebar: FunctionComponent<SidebarProps> = React.memo(
|
||||
({
|
||||
export const Sidebar: FunctionComponent<SidebarProps> = React.memo((props) => {
|
||||
const {
|
||||
storyId = null,
|
||||
refId = DEFAULT_REF_ID,
|
||||
stories: storiesHash,
|
||||
@ -99,78 +99,78 @@ export const Sidebar: FunctionComponent<SidebarProps> = React.memo(
|
||||
menuHighlighted = false,
|
||||
enableShortcuts = true,
|
||||
refs = {},
|
||||
}) => {
|
||||
const collapseFn = DOCS_MODE ? collapseAllStories : collapseDocsOnlyStories;
|
||||
const selected: Selection = useMemo(() => storyId && { storyId, refId }, [storyId, refId]);
|
||||
const stories = useMemo(() => collapseFn(storiesHash), [DOCS_MODE, storiesHash]);
|
||||
} = props;
|
||||
|
||||
const adaptedRefs = useMemo(() => {
|
||||
return Object.entries(refs).reduce((acc: Refs, [id, ref]: [string, ComposedRef]) => {
|
||||
if (ref.stories) {
|
||||
acc[id] = {
|
||||
...ref,
|
||||
stories: collapseFn(ref.stories),
|
||||
};
|
||||
} else {
|
||||
acc[id] = ref;
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
}, [DOCS_MODE, refs]);
|
||||
const collapseFn = DOCS_MODE ? collapseAllStories : collapseDocsOnlyStories;
|
||||
const selected: Selection = useMemo(() => storyId && { storyId, refId }, [storyId, refId]);
|
||||
const stories = useMemo(() => collapseFn(storiesHash), [DOCS_MODE, storiesHash]);
|
||||
|
||||
const dataset = useCombination(stories, storiesConfigured, storiesFailed, adaptedRefs);
|
||||
const isLoading = !dataset.hash[DEFAULT_REF_ID].ready;
|
||||
const lastViewedProps = useLastViewed(selected);
|
||||
const adaptedRefs = useMemo(() => {
|
||||
return Object.entries(refs).reduce((acc: Refs, [id, ref]: [string, ComposedRef]) => {
|
||||
if (ref.stories) {
|
||||
acc[id] = {
|
||||
...ref,
|
||||
stories: collapseFn(ref.stories),
|
||||
};
|
||||
} else {
|
||||
acc[id] = ref;
|
||||
}
|
||||
return acc;
|
||||
}, {});
|
||||
}, [DOCS_MODE, refs]);
|
||||
|
||||
return (
|
||||
<Container className="container sidebar-container">
|
||||
<CustomScrollArea vertical>
|
||||
<StyledSpaced row={1.6}>
|
||||
<Heading
|
||||
className="sidebar-header"
|
||||
menuHighlighted={menuHighlighted}
|
||||
menu={menu}
|
||||
skipLinkHref="#storybook-preview-wrapper"
|
||||
/>
|
||||
const dataset = useCombination(stories, storiesConfigured, storiesFailed, adaptedRefs);
|
||||
const isLoading = !dataset.hash[DEFAULT_REF_ID].ready;
|
||||
const lastViewedProps = useLastViewed(selected);
|
||||
|
||||
<Search
|
||||
dataset={dataset}
|
||||
isLoading={isLoading}
|
||||
enableShortcuts={enableShortcuts}
|
||||
{...lastViewedProps}
|
||||
>
|
||||
{({
|
||||
query,
|
||||
results,
|
||||
isBrowsing,
|
||||
closeMenu,
|
||||
getMenuProps,
|
||||
getItemProps,
|
||||
highlightedIndex,
|
||||
}) => (
|
||||
<Swap condition={isBrowsing}>
|
||||
<Explorer
|
||||
dataset={dataset}
|
||||
selected={selected}
|
||||
isLoading={isLoading}
|
||||
isBrowsing={isBrowsing}
|
||||
/>
|
||||
<SearchResults
|
||||
query={query}
|
||||
results={results}
|
||||
closeMenu={closeMenu}
|
||||
getMenuProps={getMenuProps}
|
||||
getItemProps={getItemProps}
|
||||
highlightedIndex={highlightedIndex}
|
||||
enableShortcuts={enableShortcuts}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
</Swap>
|
||||
)}
|
||||
</Search>
|
||||
</StyledSpaced>
|
||||
</CustomScrollArea>
|
||||
</Container>
|
||||
);
|
||||
}
|
||||
);
|
||||
return (
|
||||
<Container className="container sidebar-container">
|
||||
<CustomScrollArea vertical>
|
||||
<StyledSpaced row={1.6}>
|
||||
<Heading
|
||||
className="sidebar-header"
|
||||
menuHighlighted={menuHighlighted}
|
||||
menu={menu}
|
||||
skipLinkHref="#storybook-preview-wrapper"
|
||||
/>
|
||||
|
||||
<Search
|
||||
dataset={dataset}
|
||||
isLoading={isLoading}
|
||||
enableShortcuts={enableShortcuts}
|
||||
{...lastViewedProps}
|
||||
>
|
||||
{({
|
||||
query,
|
||||
results,
|
||||
isBrowsing,
|
||||
closeMenu,
|
||||
getMenuProps,
|
||||
getItemProps,
|
||||
highlightedIndex,
|
||||
}) => (
|
||||
<Swap condition={isBrowsing}>
|
||||
<Explorer
|
||||
dataset={dataset}
|
||||
selected={selected}
|
||||
isLoading={isLoading}
|
||||
isBrowsing={isBrowsing}
|
||||
/>
|
||||
<SearchResults
|
||||
query={query}
|
||||
results={results}
|
||||
closeMenu={closeMenu}
|
||||
getMenuProps={getMenuProps}
|
||||
getItemProps={getItemProps}
|
||||
highlightedIndex={highlightedIndex}
|
||||
enableShortcuts={enableShortcuts}
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
</Swap>
|
||||
)}
|
||||
</Search>
|
||||
</StyledSpaced>
|
||||
</CustomScrollArea>
|
||||
</Container>
|
||||
);
|
||||
});
|
||||
|
107
lib/ui/src/components/sidebar/__tests__/Sidebar.test.tsx
Normal file
107
lib/ui/src/components/sidebar/__tests__/Sidebar.test.tsx
Normal file
@ -0,0 +1,107 @@
|
||||
import React from 'react';
|
||||
import { render, screen, fireEvent } from '@testing-library/react';
|
||||
import { ThemeProvider, ensure, themes } from '@storybook/theming';
|
||||
|
||||
import type { Story, StoriesHash } from '@storybook/api';
|
||||
import type { Theme } from '@storybook/theming';
|
||||
import { Sidebar } from '../Sidebar';
|
||||
|
||||
global.DOCS_MODE = false;
|
||||
|
||||
const factory = (props) => {
|
||||
const theme: Theme = ensure(themes.light);
|
||||
|
||||
return render(
|
||||
<ThemeProvider theme={theme}>
|
||||
<Sidebar storiesConfigured menu={[]} stories={{}} viewMode="docs" {...props} />
|
||||
</ThemeProvider>
|
||||
);
|
||||
};
|
||||
|
||||
const generateStories: StoriesHash = ({ kind, refId }) => {
|
||||
const [root, storyName] = kind.split('/');
|
||||
const rootId = root.toLowerCase().replace(/\s+/g, '-');
|
||||
const hypenatedstoryName = storyName.toLowerCase().replace(/\s+/g, '-');
|
||||
const storyId = `${rootId}-${hypenatedstoryName}`;
|
||||
const pageId = `${rootId}-${hypenatedstoryName}--page`;
|
||||
|
||||
const storyBase = [
|
||||
{
|
||||
id: rootId,
|
||||
name: root,
|
||||
children: [storyId],
|
||||
startCollapsed: false,
|
||||
},
|
||||
{
|
||||
id: storyId,
|
||||
name: storyName,
|
||||
children: [pageId],
|
||||
isComponent: true,
|
||||
parent: rootId,
|
||||
},
|
||||
{
|
||||
id: pageId,
|
||||
name: 'Page',
|
||||
story: 'Page',
|
||||
kind,
|
||||
componentId: storyId,
|
||||
parent: storyId,
|
||||
title: kind,
|
||||
},
|
||||
];
|
||||
|
||||
return storyBase.reduce((accumulator: StoriesHash, current: any, index: number) => {
|
||||
const { id, name } = current;
|
||||
const isRoot = index === 0;
|
||||
|
||||
const story: Story = {
|
||||
...current,
|
||||
depth: index,
|
||||
isRoot,
|
||||
isLeaf: name === 'Page',
|
||||
refId,
|
||||
};
|
||||
|
||||
if (!isRoot) {
|
||||
story.parameters = {};
|
||||
story.parameters.docsOnly = true;
|
||||
}
|
||||
|
||||
accumulator[id] = story;
|
||||
|
||||
return accumulator;
|
||||
}, {});
|
||||
};
|
||||
|
||||
describe('Sidebar', () => {
|
||||
test("should not render an extra nested 'Page'", async () => {
|
||||
const refId = 'next';
|
||||
const kind = 'Getting Started/Install';
|
||||
const refStories = generateStories({ refId, kind });
|
||||
const internalStories = generateStories({ kind: 'Welcome/Example' });
|
||||
const lastStoryId = Object.keys(refStories)[Object.keys(refStories).length - 1];
|
||||
|
||||
const refs = {
|
||||
[refId]: {
|
||||
stories: refStories,
|
||||
id: refId,
|
||||
ready: true,
|
||||
title: refId,
|
||||
},
|
||||
};
|
||||
|
||||
factory({
|
||||
refs,
|
||||
lastStoryId,
|
||||
refId,
|
||||
stories: internalStories,
|
||||
});
|
||||
|
||||
fireEvent.click(screen.getByText('Install'));
|
||||
fireEvent.click(screen.getByText('Example'));
|
||||
|
||||
const pageItems = await screen.queryAllByText('Page');
|
||||
|
||||
expect(pageItems).toHaveLength(0);
|
||||
});
|
||||
});
|
@ -1,5 +1,5 @@
|
||||
import type { StoriesHash } from '@storybook/api';
|
||||
import { collapseDocsOnlyStories, collapseAllStories } from './data';
|
||||
import { collapseDocsOnlyStories, collapseAllStories } from '../data';
|
||||
|
||||
type Item = StoriesHash[keyof StoriesHash];
|
||||
|
Loading…
x
Reference in New Issue
Block a user