diff --git a/packages/design/src/Form/components/Repeater/Repeater.stories.tsx b/packages/design/src/Form/components/Repeater/Repeater.stories.tsx index 064999f9..305ec9d6 100644 --- a/packages/design/src/Form/components/Repeater/Repeater.stories.tsx +++ b/packages/design/src/Form/components/Repeater/Repeater.stories.tsx @@ -1,10 +1,58 @@ import type { Meta, StoryObj } from '@storybook/react'; import React from 'react'; import Repeater from './index.js'; -// import { expect, userEvent } from '@storybook/test'; import { FormProvider, useForm } from 'react-hook-form'; +import { defaultPatternComponents } from '../index.js'; +import type { + DateOfBirthProps, + EmailInputProps, + RepeaterProps, +} from '@atj/forms'; +import { expect, within } from '@storybook/test'; -// TODO: Add tests for the repeater once it's fully implemented +const defaultArgs = { + legend: 'Default Heading', + _patternId: 'test-id', + type: 'repeater', +} satisfies RepeaterProps; + +const mockChildComponents = (index: number, withError = false) => [ + { + props: { + _patternId: `3fdb2cb6-5d65-4de1-b773-3fb8636f5d09.${index}.a6c217f0-fe84-44ef-b606-69142ecb3365`, + type: 'date-of-birth', + label: 'Date of Birth', + hint: 'For example: January 19 2000', + dayId: `3fdb2cb6-5d65-4de1-b773-3fb8636f5d09.${index}.a6c217f0-fe84-44ef-b606-69142ecb3365.day`, + monthId: `3fdb2cb6-5d65-4de1-b773-3fb8636f5d09.${index}.a6c217f0-fe84-44ef-b606-69142ecb3365.month`, + yearId: `3fdb2cb6-5d65-4de1-b773-3fb8636f5d09.${index}.a6c217f0-fe84-44ef-b606-69142ecb3365.year`, + required: false, + error: withError + ? { + type: 'custom', + message: 'Invalid date of birth', + } + : undefined, + } as DateOfBirthProps, + children: [], + }, + { + props: { + _patternId: `3fdb2cb6-5d65-4de1-b773-3fb8636f5d09.${index}.7d5df1c1-ca92-488c-81ca-8bb180f952b6`, + type: 'email-input', + label: 'Email Input', + emailId: `3fdb2cb6-5d65-4de1-b773-3fb8636f5d09.${index}.7d5df1c1-ca92-488c-81ca-8bb180f952b6.email`, + required: false, + error: withError + ? { + type: 'custom', + message: 'Invalid email address', + } + : undefined, + } as EmailInputProps, + children: [], + }, +]; export default { title: 'patterns/Repeater', @@ -15,7 +63,9 @@ export default { const formMethods = useForm(); return ( - +
+ +
); }; @@ -25,43 +75,76 @@ export default { tags: ['autodocs'], } satisfies Meta; -const defaultArgs = { - legend: 'Default Heading', - _patternId: 'test-id', -}; - export const Default = { args: { ...defaultArgs, - type: 'repeater', }, } satisfies StoryObj; -// export const WithContents = { -// play: async ({ mount, args }) => { -// const canvas = await mount(); +export const WithContents = { + args: { + ...defaultArgs, + childComponents: mockChildComponents(0), + context: { + components: { + 'date-of-birth': defaultPatternComponents['date-of-birth'], + 'email-input': defaultPatternComponents['email-input'], + }, + config: { + patterns: {}, + }, + uswdsRoot: '/uswds/', + }, + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const legend = await canvas.findByText('Default Heading'); + expect(legend).toBeInTheDocument(); -// const addButton = canvas.getByRole('button', { name: /Add new item/ }); -// const deleteButton = canvas.getByRole('button', { name: /Delete item/ }); -// await userEvent.click(addButton); + const listItems = canvas.getAllByRole('list'); + expect(listItems.length).toBe(1); -// let inputs = canvas.queryAllByRole('textbox'); -// await expect(inputs).toHaveLength(1); + const dobLabel = await canvas.findByText('Date of Birth'); + expect(dobLabel).toBeInTheDocument(); -// await userEvent.click(deleteButton); -// inputs = canvas.queryAllByRole('textbox'); -// await expect(inputs).toHaveLength(0); -// }, -// args: { -// ...defaultArgs, -// type: 'repeater', -// children: [ -//
-// -// -//
, -// ], -// }, -// } satisfies StoryObj; + const emailLabel = await canvas.findByText('Email Input'); + expect(emailLabel).toBeInTheDocument(); + }, +} satisfies StoryObj; + +export const ErrorState = { + args: { + ...defaultArgs, + childComponents: mockChildComponents(0, true), + error: { + type: 'custom', + message: 'This field has an error', + }, + context: { + components: { + 'date-of-birth': defaultPatternComponents['date-of-birth'], + 'email-input': defaultPatternComponents['email-input'], + }, + config: { + patterns: {}, + }, + uswdsRoot: '/uswds/', + }, + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + const legend = await canvas.findByText('Default Heading'); + expect(legend).toBeInTheDocument(); + + const listItems = canvas.getAllByRole('list'); + expect(listItems.length).toBe(1); + + const dobError = await canvas.findByText('Invalid date of birth'); + expect(dobError).toBeInTheDocument(); + + const emailError = await canvas.findByText('Invalid email address'); + expect(emailError).toBeInTheDocument(); + }, +} satisfies StoryObj; diff --git a/packages/design/src/Form/components/Repeater/index.tsx b/packages/design/src/Form/components/Repeater/index.tsx index 2e5ff5ee..3f11494d 100644 --- a/packages/design/src/Form/components/Repeater/index.tsx +++ b/packages/design/src/Form/components/Repeater/index.tsx @@ -1,9 +1,6 @@ import React, { Children, useMemo } from 'react'; import { useFieldArray } from 'react-hook-form'; -import { - type RepeaterProps, - type PromptComponent, -} from '@atj/forms'; +import { type RepeaterProps, type PromptComponent } from '@atj/forms'; import { type PatternComponent } from '../../index.js'; import { renderPromptComponents } from '../../form-common.js';