UNPKG

@cfpb/cfpb-design-system

Version:
143 lines (119 loc) 4.14 kB
/// <reference types="vite/client" /> 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(); /** * `properties` is excluded here. See `cfpb-button.stories.ts` for the reason. * Specifically here `isExpanded` and `open` both describe once piece of state. * `template()` binds both applying the prop _after_ the attribute. Leaving them in * lets `isExpanded` default collapse the Expanded story. The prop still works on the * element. See the behavior tests..... */ const { args, argTypes, template } = getStorybookHelpers<CfpbExpandableProps>( 'cfpb-expandable', { excludeCategories: ['methods', 'properties'] }, ); 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': '<p>Expandable section content</p>', }, argTypes, render: (args) => template(args), }; 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(); }, }; /** * Programatic expand/collapse is covered in index.spec.js * The event tests below stay here because they are driven * by user interaction. */ 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(); }, };