@cfpb/cfpb-design-system
Version:
CFPB's UI framework
151 lines (126 loc) • 4.31 kB
text/typescript
/// <reference types="vite/client" />
import { html } from 'lit';
import type { Meta, StoryObj } from '@storybook/web-components-vite';
import { fn, userEvent, expect } from 'storybook/test';
import { getStorybookHelpers } from '@wc-toolkit/storybook-helpers';
import type { CfpbExpandableProps } from '../../../../../storybook/custom-elements-types';
import { CfpbExpandable } from './index.js';
CfpbExpandable.init();
const { args, argTypes } = getStorybookHelpers<CfpbExpandableProps>(
'cfpb-expandable',
{ excludeCategories: ['methods'] },
);
type ExpandableStoryArgs = CfpbExpandableProps & {
'header-slot'?: string;
'content-slot'?: string;
};
const meta: Meta<ExpandableStoryArgs> = {
title: 'Web Components/cfpb-expandable',
component: 'cfpb-expandable',
tags: ['autodocs'],
args: {
...args,
'header-slot': 'Section header',
'content-slot': 'Expandable section content',
},
argTypes,
render: ({ open, 'header-slot': header, 'content-slot': content }) =>
html`<cfpb-expandable ?open="${open}">
<span slot="header">${header}</span>
<p slot="content">${content}</p>
</cfpb-expandable>`,
};
export default meta;
type Story = StoryObj<ExpandableStoryArgs>;
export const Default: Story = {
args: { open: false },
};
export const ExpandBegin: Story = {
tags: ['!dev', '!autodocs'],
play: async ({ canvasElement }) => {
const expandable = canvasElement.querySelector(
'cfpb-expandable',
) as CfpbExpandable;
const spy = fn();
expandable.addEventListener('expandbegin', spy);
const button = expandable.shadowRoot!.querySelector('button')!;
await userEvent.click(button);
await expect(spy).toHaveBeenCalledOnce();
},
};
export const Expanded: Story = {
args: { open: true },
};
export const CollapseOnClick: Story = {
tags: ['!dev', '!autodocs'],
args: { open: true },
play: async ({ canvasElement }) => {
const expandable = canvasElement.querySelector(
'cfpb-expandable',
) as CfpbExpandable;
const spy = fn();
expandable.addEventListener('collapseend', spy);
const button = expandable.shadowRoot!.querySelector('button')!;
const content = expandable.shadowRoot!.querySelector(
'.o-expandable__content',
)!;
await userEvent.click(button);
// BaseTransition registers on 'webketTransitionEnd' in Chromium (first match
// in its prefix map), so the synthetic event must use that name (not transitioned)
content.dispatchEvent(
new TransitionEvent('webkitTransitionEnd', {
propertyName: 'max-height',
}),
);
await expect(spy).toHaveBeenCalledOnce();
},
};
export const CollapseProgrammatically: Story = {
tags: ['!dev', '!autodocs'],
args: { open: true },
play: async ({ canvasElement }) => {
const expandable = canvasElement.querySelector(
'cfpb-expandable',
) as CfpbExpandable;
const button = expandable.shadowRoot!.querySelector('button')!;
expandable.isExpanded = false;
await expandable.updateComplete;
await expect(expandable.isExpanded).toBe(false);
await expect(button.getAttribute('aria-expanded')).toBe('false');
},
};
export const ExpandEnd: Story = {
tags: ['!dev', '!autodocs'],
play: async ({ canvasElement }) => {
const expandable = canvasElement.querySelector(
'cfpb-expandable',
) as CfpbExpandable;
const spy = fn();
expandable.addEventListener('expandend', spy);
const button = expandable.shadowRoot!.querySelector('button')!;
const content = expandable.shadowRoot!.querySelector(
'.o-expandable__content',
)!;
await userEvent.click(button);
content.dispatchEvent(
new TransitionEvent('webkitTransitionEnd', {
propertyName: 'max-height',
}),
);
await expect(spy).toHaveBeenCalledOnce();
},
};
export const CollapseBegin: Story = {
tags: ['!dev', '!autodocs'],
args: { open: true },
play: async ({ canvasElement }) => {
const expandable = canvasElement.querySelector(
'cfpb-expandable',
) as CfpbExpandable;
const spy = fn();
expandable.addEventListener('collapsebegin', spy);
const button = expandable.shadowRoot!.querySelector('button')!;
await userEvent.click(button);
await expect(spy).toHaveBeenCalledOnce();
},
};