@@ -4,10 +4,10 @@ import { Calendar } from '@lambdacurry/forms/ui/calendar';
44import { Label } from '@lambdacurry/forms/ui/label' ;
55import { Select } from '@lambdacurry/forms/ui/select' ;
66import type { Meta , StoryObj } from '@storybook/react-vite' ;
7+ import { expect , userEvent , within } from '@storybook/test' ;
78import * as React from 'react' ;
89import { type ActionFunctionArgs , Form , useFetcher } from 'react-router' ;
910import { RemixFormProvider , createFormData , getValidatedFormData , useRemixForm } from 'remix-hook-form' ;
10- import { expect , userEvent , within } from 'storybook/test' ;
1111import { z } from 'zod' ;
1212import { withReactRouterStubDecorator } from '../lib/storybook/react-router-stub' ;
1313
@@ -178,9 +178,6 @@ const meta: Meta<typeof CalendarWithMonthYearSelect> = {
178178export default meta ;
179179type Story = StoryObj < typeof meta > ;
180180
181- // Helper function for sleep delays
182- const sleep = ( ms : number ) => new Promise ( ( resolve ) => setTimeout ( resolve , ms ) ) ;
183-
184181export const Default : Story = {
185182 parameters : {
186183 docs : {
@@ -189,51 +186,53 @@ export const Default: Story = {
189186 } ,
190187 } ,
191188 } ,
192- play : async ( { canvasElement } ) => {
189+ play : async ( { canvasElement, step } ) => {
193190 const canvas = within ( canvasElement ) ;
194191
195- // Wait for initial render
196- await sleep ( 500 ) ;
197-
198- // Find the dropdown select button
199- const dropdownSelectButton = await canvas . findByRole ( 'combobox' , { expanded : false } ) ;
200- expect ( dropdownSelectButton ) . toBeInTheDocument ( ) ;
201-
202- // Click to open the dropdown
203- await userEvent . click ( dropdownSelectButton ) ;
204- await sleep ( 500 ) ;
205-
206- // Find and click "Month Only" option - look in the popover content
207- const monthOnlyOption =
208- document . querySelector ( '[data-value="dropdown-months"]' ) || ( await canvas . findByText ( 'Month Only' ) ) ;
209- await userEvent . click ( monthOnlyOption ) ;
210- await sleep ( 300 ) ;
211-
212- // Verify the dropdown closed and selection changed
213- expect ( dropdownSelectButton ) . toHaveTextContent ( 'Month Only' ) ;
214-
215- // Find a day in the calendar to click
216- const dayButtons = await canvas . findAllByRole ( 'gridcell' ) ;
217- const availableDay = dayButtons . find (
218- ( day ) => day . textContent && / ^ \d + $ / . test ( day . textContent . trim ( ) ) && ! day . hasAttribute ( 'aria-disabled' ) ,
219- ) as HTMLElement ;
220-
221- console . log ( '>>>> availableDay' , availableDay ) ;
222-
223- await userEvent . click ( availableDay ) ;
224- await sleep ( 300 ) ;
225-
226- // Find and click the submit button
227- const submitButton = await canvas . findByRole ( 'button' , { name : / s u b m i t / i } ) ;
228- await userEvent . click ( submitButton ) ;
229-
230- // Wait for form submission
231- await sleep ( 1000 ) ;
232-
233- // Verify submission results
234- expect ( canvas . getByText ( 'Submitted with:' ) ) . toBeInTheDocument ( ) ;
235- expect ( canvas . getByText ( / D a t e : / ) ) . toBeInTheDocument ( ) ;
236- expect ( canvas . getByText ( 'Dropdown Type: dropdown-months' ) ) . toBeInTheDocument ( ) ;
192+ await step ( 'Verify initial state' , async ( ) => {
193+ // Verify the dropdown select button is present with default text
194+ const dropdownSelectButton = await canvas . findByText ( 'Month and Year' ) ;
195+ expect ( dropdownSelectButton ) . toBeInTheDocument ( ) ;
196+
197+ // Verify submit button is present but form hasn't been submitted yet
198+ const submitButton = canvas . getByRole ( 'button' , { name : / s u b m i t / i } ) ;
199+ expect ( submitButton ) . toBeInTheDocument ( ) ;
200+ expect ( canvas . queryByText ( 'Submitted with:' ) ) . not . toBeInTheDocument ( ) ;
201+ } ) ;
202+
203+ await step ( 'Change dropdown to Month Only' , async ( ) => {
204+ // Find and click the dropdown select button (use text content)
205+ const dropdownSelectButton = canvas . getByText ( 'Month and Year' ) ;
206+ await userEvent . click ( dropdownSelectButton ) ;
207+
208+ // Find and click "Month Only" option
209+ const monthOnlyOption = await within ( document . body ) . findByText ( 'Month Only' ) ;
210+ await userEvent . click ( monthOnlyOption ) ;
211+
212+ // Verify the dropdown selection changed by checking the new text
213+ expect ( canvas . getByText ( 'Month Only' ) ) . toBeInTheDocument ( ) ;
214+ } ) ;
215+
216+ await step ( 'Navigate calendar and select a date' , async ( ) => {
217+ // Use the calendar's month dropdown to navigate to July (month 7)
218+ const monthDropdown = canvas . getByLabelText ( 'Choose the Month' ) ;
219+ await userEvent . selectOptions ( monthDropdown , '6' ) ; // June is month 6 (0-indexed)
220+
221+ // Find a specific date button using aria-label (includes day of week)
222+ const dateButton = await canvas . findByRole ( 'button' , { name : / 1 5 t h , 2 0 2 5 / i } ) ;
223+ await userEvent . click ( dateButton ) ;
224+ } ) ;
225+
226+ await step ( 'Submit form and verify success' , async ( ) => {
227+ // Submit the form
228+ const submitButton = canvas . getByRole ( 'button' , { name : / s u b m i t / i } ) ;
229+ await userEvent . click ( submitButton ) ;
230+
231+ // Verify submission results with comprehensive assertions
232+ await expect ( canvas . findByText ( 'Submitted with:' ) ) . resolves . toBeInTheDocument ( ) ;
233+ await expect ( canvas . findByText ( / D a t e : / ) ) . resolves . toBeInTheDocument ( ) ;
234+ await expect ( canvas . findByText ( 'Dropdown Type: dropdown-months' ) ) . resolves . toBeInTheDocument ( ) ;
235+ } ) ;
237236 } ,
238237} ;
239238
@@ -245,50 +244,44 @@ export const YearOnlyDropdown: Story = {
245244 } ,
246245 } ,
247246 } ,
248- play : async ( { canvasElement } ) => {
247+ play : async ( { canvasElement, step } ) => {
249248 const canvas = within ( canvasElement ) ;
250249
251- // Wait for initial render
252- await sleep ( 500 ) ;
253-
254- // Find the dropdown select button
255- const dropdownSelectButton = await canvas . findByRole ( 'combobox' , { expanded : false } ) ;
256- expect ( dropdownSelectButton ) . toBeInTheDocument ( ) ;
257-
258- // Click to open the dropdown
259- await userEvent . click ( dropdownSelectButton ) ;
260- await sleep ( 500 ) ;
261-
262- // Find and click "Year Only" option - look in the popover content
263- const yearOnlyOption =
264- document . querySelector ( '[data-value="dropdown-years"]' ) || ( await canvas . findByText ( 'Year Only' ) ) ;
265- await userEvent . click ( yearOnlyOption ) ;
266- await sleep ( 300 ) ;
267-
268- // Verify the dropdown closed and selection changed
269- expect ( dropdownSelectButton ) . toHaveTextContent ( 'Year Only' ) ;
270-
271- // Test calendar interaction with year-only dropdown
272- const dayButtons = await canvas . findAllByRole ( 'gridcell' ) ;
273- const availableDay = dayButtons . find (
274- ( day ) => day . textContent && / ^ \d + $ / . test ( day . textContent . trim ( ) ) && ! day . hasAttribute ( 'aria-disabled' ) ,
275- ) as HTMLElement ;
276-
277- console . log ( '>>>> availableDay' , availableDay ) ;
278-
279- if ( availableDay ) {
280- await userEvent . click ( availableDay ) ;
281- await sleep ( 300 ) ;
282- }
283-
284- // Submit the form
285- const submitButton = await canvas . findByRole ( 'button' , { name : / s u b m i t / i } ) ;
286- await userEvent . click ( submitButton ) ;
287- await sleep ( 1000 ) ;
288-
289- // Verify submission with year-only dropdown
290- expect ( canvas . getByText ( 'Submitted with:' ) ) . toBeInTheDocument ( ) ;
291- expect ( canvas . getByText ( 'Dropdown Type: dropdown-years' ) ) . toBeInTheDocument ( ) ;
250+ await step ( 'Verify initial state and change to Year Only' , async ( ) => {
251+ // Find the dropdown select button (use text content)
252+ const dropdownSelectButton = await canvas . findByText ( 'Month and Year' ) ;
253+ expect ( dropdownSelectButton ) . toBeInTheDocument ( ) ;
254+
255+ // Click to open the dropdown
256+ await userEvent . click ( dropdownSelectButton ) ;
257+
258+ // Find and click "Year Only" option
259+ const yearOnlyOption = await within ( document . body ) . findByText ( 'Year Only' ) ;
260+ await userEvent . click ( yearOnlyOption ) ;
261+
262+ // Verify the dropdown selection changed by checking the new text
263+ expect ( canvas . getByText ( 'Year Only' ) ) . toBeInTheDocument ( ) ;
264+ } ) ;
265+
266+ await step ( 'Navigate calendar and select a date' , async ( ) => {
267+ // With year-only dropdown, we should see the year dropdown
268+ const yearDropdown = canvas . getByLabelText ( 'Choose the Year' ) ;
269+ expect ( yearDropdown ) . toBeInTheDocument ( ) ;
270+
271+ // Find a specific date button using aria-label (includes day of week and year)
272+ const dateButton = await canvas . findByRole ( 'button' , { name : / 1 5 t h , 2 0 2 5 / } ) ;
273+ await userEvent . click ( dateButton ) ;
274+ } ) ;
275+
276+ await step ( 'Submit form and verify success' , async ( ) => {
277+ // Submit the form
278+ const submitButton = canvas . getByRole ( 'button' , { name : / s u b m i t / i } ) ;
279+ await userEvent . click ( submitButton ) ;
280+
281+ // Verify submission with year-only dropdown
282+ await expect ( canvas . findByText ( 'Submitted with:' ) ) . resolves . toBeInTheDocument ( ) ;
283+ await expect ( canvas . findByText ( 'Dropdown Type: dropdown-years' ) ) . resolves . toBeInTheDocument ( ) ;
284+ } ) ;
292285 } ,
293286} ;
294287
@@ -300,41 +293,44 @@ export const MonthAndYearDropdown: Story = {
300293 } ,
301294 } ,
302295 } ,
303- play : async ( { canvasElement } ) => {
296+ play : async ( { canvasElement, step } ) => {
304297 const canvas = within ( canvasElement ) ;
305298
306- // Wait for initial render
307- await sleep ( 500 ) ;
308-
309- // Verify default dropdown selection
310- const dropdownSelectButton = await canvas . findByRole ( 'combobox' , { expanded : false } ) ;
311- expect ( dropdownSelectButton ) . toHaveTextContent ( 'Month and Year' ) ;
312-
313- // Test calendar navigation with month/year dropdowns
314- // Look for month/year dropdown elements in the calendar
315- const calendarDropdowns = document . querySelectorAll ( '[data-slot="calendar"] select' ) ;
316- expect ( calendarDropdowns . length ) . toBeGreaterThan ( 0 ) ;
317-
318- // Select a date
319- const dayButtons = await canvas . findAllByRole ( 'gridcell' ) ;
320- const availableDay = dayButtons . find (
321- ( day ) => day . textContent && / ^ \d + $ / . test ( day . textContent . trim ( ) ) && ! day . hasAttribute ( 'aria-disabled' ) ,
322- ) as HTMLElement ;
323-
324- console . log ( '>>>> availableDay' , availableDay ) ;
325-
326- if ( availableDay ) {
327- await userEvent . click ( availableDay ) ;
328- await sleep ( 300 ) ;
329- }
330-
331- // Submit the form
332- const submitButton = await canvas . findByRole ( 'button' , { name : / s u b m i t / i } ) ;
333- await userEvent . click ( submitButton ) ;
334- await sleep ( 1000 ) ;
335-
336- // Verify submission with default dropdown
337- expect ( canvas . getByText ( 'Submitted with:' ) ) . toBeInTheDocument ( ) ;
338- expect ( canvas . getByText ( 'Dropdown Type: dropdown' ) ) . toBeInTheDocument ( ) ;
299+ await step ( 'Verify initial state with default dropdown' , async ( ) => {
300+ // Verify default dropdown selection (use text content)
301+ const dropdownSelectButton = await canvas . findByText ( 'Month and Year' ) ;
302+ expect ( dropdownSelectButton ) . toBeInTheDocument ( ) ;
303+
304+ // Test calendar navigation with month/year dropdowns
305+ // Verify both month and year dropdowns are present
306+ const monthDropdown = canvas . getByLabelText ( 'Choose the Month' ) ;
307+ const yearDropdown = canvas . getByLabelText ( 'Choose the Year' ) ;
308+ expect ( monthDropdown ) . toBeInTheDocument ( ) ;
309+ expect ( yearDropdown ) . toBeInTheDocument ( ) ;
310+ } ) ;
311+
312+ await step ( 'Navigate calendar and select a date' , async ( ) => {
313+ // Use both month and year dropdowns to navigate
314+ const monthDropdown = canvas . getByLabelText ( 'Choose the Month' ) ;
315+ const yearDropdown = canvas . getByLabelText ( 'Choose the Year' ) ;
316+
317+ // Navigate to July 2025
318+ await userEvent . selectOptions ( monthDropdown , '6' ) ; // June is month 6 (0-indexed)
319+ await userEvent . selectOptions ( yearDropdown , '2025' ) ;
320+
321+ // Find a specific date button using aria-label (includes day of week)
322+ const dateButton = await canvas . findByRole ( 'button' , { name : / 1 5 t h , 2 0 2 5 / i } ) ;
323+ await userEvent . click ( dateButton ) ;
324+ } ) ;
325+
326+ await step ( 'Submit form and verify success' , async ( ) => {
327+ // Submit the form
328+ const submitButton = canvas . getByRole ( 'button' , { name : / s u b m i t / i } ) ;
329+ await userEvent . click ( submitButton ) ;
330+
331+ // Verify submission with default dropdown
332+ await expect ( canvas . findByText ( 'Submitted with:' ) ) . resolves . toBeInTheDocument ( ) ;
333+ await expect ( canvas . findByText ( 'Dropdown Type: dropdown' ) ) . resolves . toBeInTheDocument ( ) ;
334+ } ) ;
339335 } ,
340336} ;
0 commit comments