From fe034cb1315a374c4fa6c0023f269485c23fb606 Mon Sep 17 00:00:00 2001 From: Duy Nguyen Date: Thu, 8 Jan 2026 13:00:30 -0500 Subject: [PATCH 01/58] refactor: update play functions in Storybook stories to remove async where unnecessary - Changed play functions in various Storybook stories from async to synchronous where applicable. - Updated imports for MockAuthWrapper to a new file for better organization. - Removed unused MockAuthWrapper and MockUnauthWrapper implementations from storybook-decorators.tsx for it mixes exporting constants and components --- ...admin-listings-table.container.stories.tsx | 14 ++-- .../admin-listings-table.stories.tsx | 8 +- ...in-listings-table.view-listing.stories.tsx | 20 ++--- ...dmin-listings-table.status-tag.stories.tsx | 6 +- ...in-listings-table.title-filter.stories.tsx | 6 +- .../admin-listings-table.utils.stories.tsx | 2 +- .../admin-users-table.container.stories.tsx | 16 ++-- .../admin-users-table.stories.tsx | 4 +- .../admin-users-table/admin-users.stories.tsx | 2 +- .../stories/admin-users-card.stories.tsx | 8 +- ...admin-dashboard-main.container.stories.tsx | 2 +- .../components/profile-view.stories.tsx | 6 +- .../settings-view.container.stories.tsx | 4 +- .../settings/pages/Settings.stories.tsx | 2 +- .../settings/pages/settings-view.stories.tsx | 8 +- .../category-filter.container.stories.tsx | 2 +- .../create-listing/create-listing.stories.tsx | 44 +++++----- .../use-create-listing-navigation.stories.tsx | 10 +-- .../hooks/use-file-limit.stories.tsx | 16 ++-- .../hero-section.container.stories.tsx | 2 +- .../listings-page.container.stories.tsx | 2 +- .../listing-information.container.stories.tsx | 20 ++--- .../listing-information.stories.tsx | 38 ++++----- .../sharer-information.stories.tsx | 16 ++-- .../view-listing.container.stories.tsx | 6 +- .../messages/pages/Conversation.stories.tsx | 2 +- .../ConversationBoxContainer.stories.tsx | 10 +-- .../all-listings-table.container.stories.tsx | 2 +- .../requests-table.container.stories.tsx | 18 ++-- .../pages/edit-listing.stories.tsx | 2 +- .../my-listings/pages/my-listings.stories.tsx | 2 +- .../stories/all-listings-card.stories.tsx | 18 ++-- .../stories/all-listings-table.stories.tsx | 32 ++++---- .../stories/my-listings-dashboard.stories.tsx | 2 +- .../requests-status-helpers.stories.tsx | 4 +- ...rvations-view-active.container.stories.tsx | 4 +- ...vations-view-history.container.stories.tsx | 6 +- .../stories/reservation-actions.stories.tsx | 7 +- .../reservation-state-utils.stories.tsx | 6 +- .../stories/reservations-table.stories.tsx | 2 +- .../home/stories/HeroSection.stories.tsx | 6 +- .../home/stories/section-layout.stories.tsx | 2 +- .../account-setup.container.stories.tsx | 14 ++-- .../profile-setup.container.stories.tsx | 18 ++-- .../select-account-type.container.stories.tsx | 2 +- .../select-account-type.stories.tsx | 6 +- .../layouts/signup/section-layout.stories.tsx | 3 +- .../signup/stories/section-layout.stories.tsx | 2 +- .../stories/auth-redirect-user.stories.tsx | 2 +- .../stories/login-selection.stories.tsx | 2 +- .../stories/require-auth-admin.stories.tsx | 4 +- .../src/test-utils/storybook-decorators.tsx | 82 +++---------------- .../storybook-mock-auth-wrappers.tsx | 66 +++++++++++++++ 53 files changed, 299 insertions(+), 291 deletions(-) create mode 100644 apps/ui-sharethrift/src/test-utils/storybook-mock-auth-wrappers.tsx diff --git a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/admin-listings-table.container.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/admin-listings-table.container.stories.tsx index 888bc83c9..fbe79a1c8 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/admin-listings-table.container.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/admin-listings-table.container.stories.tsx @@ -1,15 +1,15 @@ import type { Meta, StoryObj } from '@storybook/react'; -import { expect, within, userEvent, waitFor } from 'storybook/test'; -import { AdminListings } from './admin-listings-table.container.tsx'; -import { - withMockApolloClient, - withMockRouter, -} from '../../../../../../../test-utils/storybook-decorators.tsx'; +import { expect, userEvent, waitFor, within } from 'storybook/test'; import { AdminListingsTableContainerAdminListingsDocument, AdminListingsTableContainerDeleteListingDocument, AdminListingsTableContainerUnblockListingDocument, } from '../../../../../../../generated.tsx'; +import { + withMockApolloClient, + withMockRouter, +} from '../../../../../../../test-utils/storybook-decorators.tsx'; +import { AdminListings } from './admin-listings-table.container.tsx'; const meta: Meta = { title: 'Containers/AdminListingsTableContainer', @@ -214,7 +214,7 @@ export const LoadingState: Story = { ], }, }, - play: async ({ canvasElement }: { canvasElement: HTMLElement }) => { + play: ({ canvasElement }: { canvasElement: HTMLElement }) => { const canvas = within(canvasElement); const loadingSpinner = canvas.queryByRole('progressbar') ?? canvas.queryByText(/loading/i); diff --git a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/admin-listings-table.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/admin-listings-table.stories.tsx index 54a1304f4..6a35ac38c 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/admin-listings-table.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/admin-listings-table.stories.tsx @@ -68,7 +68,7 @@ export const WithListings: Story = { onPageChange: fn(), onAction: fn(), }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { expect(canvasElement).toBeTruthy(); }, }; @@ -89,7 +89,7 @@ export const LoadingState: Story = { onPageChange: fn(), onAction: fn(), }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { expect(canvasElement).toBeTruthy(); }, }; @@ -110,7 +110,7 @@ export const WithBlockedListings: Story = { onPageChange: fn(), onAction: fn(), }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { expect(canvasElement).toBeTruthy(); }, }; @@ -131,7 +131,7 @@ export const EmptyState: Story = { onPageChange: fn(), onAction: fn(), }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { expect(canvasElement).toBeTruthy(); }, }; diff --git a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/admin-listings-table.view-listing.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/admin-listings-table.view-listing.stories.tsx index 6da419fed..9453a0d1b 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/admin-listings-table.view-listing.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/admin-listings-table.view-listing.stories.tsx @@ -88,7 +88,7 @@ export default meta; type Story = StoryObj; export const Default: Story = { - play: async ({ canvasElement }: { canvasElement: HTMLElement }) => { + play: ({ canvasElement }: { canvasElement: HTMLElement }) => { expect(canvasElement).toBeTruthy(); }, }; @@ -119,7 +119,7 @@ export const ListingNotFound: Story = { ], }, }, - play: async ({ canvasElement }: { canvasElement: HTMLElement }) => { + play: ({ canvasElement }: { canvasElement: HTMLElement }) => { expect(canvasElement).toBeTruthy(); }, }; @@ -142,7 +142,7 @@ export const LoadingState: Story = { ], }, }, - play: async ({ canvasElement }: { canvasElement: HTMLElement }) => { + play: ({ canvasElement }: { canvasElement: HTMLElement }) => { expect(canvasElement).toBeTruthy(); }, }; @@ -200,7 +200,7 @@ export const UnblockSuccess: Story = { ], }, }, - play: async ({ canvasElement }: { canvasElement: HTMLElement }) => { + play: ({ canvasElement }: { canvasElement: HTMLElement }) => { expect(canvasElement).toBeTruthy(); }, }; @@ -249,7 +249,7 @@ export const UnblockError: Story = { ], }, }, - play: async ({ canvasElement }: { canvasElement: HTMLElement }) => { + play: ({ canvasElement }: { canvasElement: HTMLElement }) => { expect(canvasElement).toBeTruthy(); }, }; @@ -309,7 +309,7 @@ export const DeleteSuccess: Story = { ], }, }, - play: async ({ canvasElement }: { canvasElement: HTMLElement }) => { + play: ({ canvasElement }: { canvasElement: HTMLElement }) => { expect(canvasElement).toBeTruthy(); }, }; @@ -369,7 +369,7 @@ export const DeleteFailure: Story = { ], }, }, - play: async ({ canvasElement }: { canvasElement: HTMLElement }) => { + play: ({ canvasElement }: { canvasElement: HTMLElement }) => { expect(canvasElement).toBeTruthy(); }, }; @@ -418,7 +418,7 @@ export const DeleteError: Story = { ], }, }, - play: async ({ canvasElement }: { canvasElement: HTMLElement }) => { + play: ({ canvasElement }: { canvasElement: HTMLElement }) => { expect(canvasElement).toBeTruthy(); }, }; @@ -460,7 +460,7 @@ export const PublishedListing: Story = { ], }, }, - play: async ({ canvasElement }: { canvasElement: HTMLElement }) => { + play: ({ canvasElement }: { canvasElement: HTMLElement }) => { expect(canvasElement).toBeTruthy(); }, }; @@ -502,7 +502,7 @@ export const AppealRequestedListing: Story = { ], }, }, - play: async ({ canvasElement }: { canvasElement: HTMLElement }) => { + play: ({ canvasElement }: { canvasElement: HTMLElement }) => { expect(canvasElement).toBeTruthy(); }, }; diff --git a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.status-tag.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.status-tag.stories.tsx index 7cfc314c8..093a82570 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.status-tag.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.status-tag.stories.tsx @@ -23,7 +23,7 @@ export const Blocked: Story = { args: { status: 'Blocked', }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); const tag = canvas.getByText('Blocked'); expect(tag).toBeTruthy(); @@ -34,7 +34,7 @@ export const UndefinedStatus: Story = { args: { status: undefined, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); const tag = canvas.getByText('N/A'); expect(tag).toBeTruthy(); @@ -45,7 +45,7 @@ export const CustomStatus: Story = { args: { status: 'Active', }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); const tag = canvas.getByText('Active'); expect(tag).toBeTruthy(); diff --git a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.title-filter.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.title-filter.stories.tsx index 97358685a..14064cf5a 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.title-filter.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.title-filter.stories.tsx @@ -25,7 +25,7 @@ export const Empty: Story = { searchText: '', selectedKeys: [], }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); const input = canvas.getByPlaceholderText('Search listings'); expect(input).toBeTruthy(); @@ -37,7 +37,7 @@ export const WithSearchText: Story = { searchText: 'bicycle', selectedKeys: [], }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); const input = canvas.getByPlaceholderText('Search listings'); expect(input).toBeTruthy(); @@ -49,7 +49,7 @@ export const WithSelectedKeys: Story = { searchText: '', selectedKeys: ['tent'], }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); const input = canvas.getByPlaceholderText('Search listings'); expect((input as HTMLInputElement).value).toBe('tent'); diff --git a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.utils.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.utils.stories.tsx index 6e72679aa..5d06e6871 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.utils.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.utils.stories.tsx @@ -48,7 +48,7 @@ export default meta; type Story = StoryObj; export const Default: Story = { - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { // Test valid date formatting with ISO strings (includes timezone) expect(formatDate('2024-01-15T10:30:00Z')).toBe('2024-01-15'); expect(formatDate('2024-12-25T12:00:00Z')).toBe('2024-12-25'); diff --git a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-users-table/admin-users-table.container.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-users-table/admin-users-table.container.stories.tsx index 306c6c599..1f01eab81 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-users-table/admin-users-table.container.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-users-table/admin-users-table.container.stories.tsx @@ -122,7 +122,7 @@ export default meta; type Story = StoryObj; export const Default: Story = { - play: async ({ canvasElement }: { canvasElement: HTMLElement }) => { + play: ({ canvasElement }: { canvasElement: HTMLElement }) => { const canvas = within(canvasElement); expect(canvasElement).toBeTruthy(); const johnDoe = canvas.queryByText(/John/i); @@ -157,7 +157,7 @@ export const Empty: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { expect(canvasElement).toBeTruthy(); }, }; @@ -177,7 +177,7 @@ export const Loading: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { expect(canvasElement).toBeTruthy(); }, }; @@ -234,7 +234,7 @@ export const WithBlockedUser: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); expect(canvasElement).toBeTruthy(); const blockedText = canvas.queryByText(/Blocked/i); @@ -277,7 +277,7 @@ export const BlockUserError: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { expect(canvasElement).toBeTruthy(); }, }; @@ -323,7 +323,7 @@ export const ManyUsers: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { expect(canvasElement).toBeTruthy(); }, }; @@ -361,7 +361,7 @@ export const UnblockUserError: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { expect(canvasElement).toBeTruthy(); }, }; @@ -381,7 +381,7 @@ export const WithError: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { expect(canvasElement).toBeTruthy(); }, }; diff --git a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-users-table/admin-users-table.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-users-table/admin-users-table.stories.tsx index de5254787..d30706f1c 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-users-table/admin-users-table.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-users-table/admin-users-table.stories.tsx @@ -76,7 +76,7 @@ export const WithUsers: Story = { onPageChange: fn(), onAction: fn(), }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { expect(canvasElement).toBeTruthy(); }, }; @@ -145,7 +145,7 @@ export const OpenBlockModal: Story = { onPageChange: fn(), onAction: fn(), }, - play: async ({ canvasElement }) => { + play: async({ canvasElement }) => { const canvas = within(canvasElement); const blockButton = await canvas.findByRole('button', { name: 'Block' }); await userEvent.click(blockButton); diff --git a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-users-table/admin-users.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-users-table/admin-users.stories.tsx index cee1b9a64..e831b51cb 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-users-table/admin-users.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-users-table/admin-users.stories.tsx @@ -95,7 +95,7 @@ export default meta; type Story = StoryObj; export const Default: Story = { - play: async ({ canvasElement }: { canvasElement: HTMLElement }) => { + play: ({ canvasElement }: { canvasElement: HTMLElement }) => { expect(canvasElement).toBeTruthy(); }, }; diff --git a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-users-table/stories/admin-users-card.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-users-table/stories/admin-users-card.stories.tsx index 7cdd6b419..9043f200f 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-users-table/stories/admin-users-card.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-users-table/stories/admin-users-card.stories.tsx @@ -68,7 +68,7 @@ export const ActiveUser: Story = { args: { user: mockActiveUser, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); expect(canvas.getByText('johndoe')).toBeTruthy(); expect(canvas.getByText('Active')).toBeTruthy(); @@ -82,7 +82,7 @@ export const BlockedUser: Story = { args: { user: mockBlockedUser, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); expect(canvas.getByText('blockeduser')).toBeTruthy(); expect(canvas.getByText('Blocked')).toBeTruthy(); @@ -95,7 +95,7 @@ export const UserWithReports: Story = { args: { user: mockUserWithReports, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); expect(canvas.getByText('reporteduser')).toBeTruthy(); expect(canvas.getByText('View Report (5)')).toBeTruthy(); @@ -106,7 +106,7 @@ export const UserWithNoDate: Story = { args: { user: mockUserNoDate, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); expect(canvas.getByText('newuser')).toBeTruthy(); expect(canvasElement.textContent).toContain('N/A'); diff --git a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/pages/admin-dashboard-main.container.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/pages/admin-dashboard-main.container.stories.tsx index 30507d26d..f7860208c 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/pages/admin-dashboard-main.container.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/pages/admin-dashboard-main.container.stories.tsx @@ -74,7 +74,7 @@ export default meta; type Story = StoryObj; export const Default: Story = { - play: async ({ canvasElement }: { canvasElement: HTMLElement }) => { + play: ({ canvasElement }: { canvasElement: HTMLElement }) => { expect(canvasElement).toBeTruthy(); const tabs = canvasElement.querySelectorAll('[role="tab"]'); expect(tabs.length).toBeGreaterThan(0); diff --git a/apps/ui-sharethrift/src/components/layouts/home/account/profile/components/profile-view.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/account/profile/components/profile-view.stories.tsx index 00342e299..7200c6823 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/account/profile/components/profile-view.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/account/profile/components/profile-view.stories.tsx @@ -73,9 +73,9 @@ export const Default: Story = { listings: [], isOwnProfile: true, onEditSettings: () => console.log('Edit settings clicked'), - onListingClick: (_id: string) => console.log('Listing clicked'), + onListingClick: () => console.log('Listing clicked'), }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { expect(canvasElement).toBeTruthy(); }, }; @@ -134,7 +134,7 @@ export const EmptyListingsOwnProfile: Story = { onEditSettings: fn(), onListingClick: fn(), }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await expect(canvas.getByText('No listings yet')).toBeInTheDocument(); await expect(canvas.getByRole('button', { name: /Create Your First Listing/i })).toBeInTheDocument(); diff --git a/apps/ui-sharethrift/src/components/layouts/home/account/settings/components/settings-view.container.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/account/settings/components/settings-view.container.stories.tsx index 30f6017a0..7185b0991 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/account/settings/components/settings-view.container.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/account/settings/components/settings-view.container.stories.tsx @@ -145,7 +145,7 @@ export const Loading: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); const loadingText = canvas.queryByText(/Loading/i); expect(loadingText || canvasElement).toBeTruthy(); @@ -215,7 +215,7 @@ export const UserNotFound: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); const notFoundText = canvas.queryByText(/User not found/i); expect(notFoundText || canvasElement).toBeTruthy(); diff --git a/apps/ui-sharethrift/src/components/layouts/home/account/settings/pages/Settings.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/account/settings/pages/Settings.stories.tsx index 0d680fc62..a4ab72cf4 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/account/settings/pages/Settings.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/account/settings/pages/Settings.stories.tsx @@ -24,7 +24,7 @@ export const FileExports: Story = {

Settings component file exists and exports correctly

), - play: async () => { + play: async () => { const { Settings } = await import('./Settings.tsx'); expect(Settings).toBeDefined(); expect(typeof Settings).toBe('function'); diff --git a/apps/ui-sharethrift/src/components/layouts/home/account/settings/pages/settings-view.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/account/settings/pages/settings-view.stories.tsx index 51c1cdf14..a4463d649 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/account/settings/pages/settings-view.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/account/settings/pages/settings-view.stories.tsx @@ -53,7 +53,7 @@ export default meta; type Story = StoryObj; export const Default: Story = { - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { expect(canvasElement).toBeTruthy(); const canvas = within(canvasElement); expect(canvas.getByText('John')).toBeInTheDocument(); @@ -201,7 +201,7 @@ export const UserWithoutBilling: Story = { billing: undefined, }, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); const notProvidedTexts = canvas.getAllByText('Not provided'); expect(notProvidedTexts.length).toBeGreaterThan(0); @@ -224,7 +224,7 @@ export const MinimalUser: Story = { }, }, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); const notProvidedTexts = canvas.getAllByText('Not provided'); expect(notProvidedTexts.length).toBeGreaterThan(0); @@ -235,7 +235,7 @@ export const SavingState: Story = { args: { isSavingSection: true, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { expect(canvasElement).toBeTruthy(); }, }; diff --git a/apps/ui-sharethrift/src/components/layouts/home/components/category-filter.container.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/components/category-filter.container.stories.tsx index a0d1d6c32..a95af6da8 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/components/category-filter.container.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/components/category-filter.container.stories.tsx @@ -28,7 +28,7 @@ export const Default: Story = { selectedCategory: '', onCategoryChange: fn(), }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { expect(canvasElement).toBeTruthy(); }, }; diff --git a/apps/ui-sharethrift/src/components/layouts/home/components/create-listing/create-listing.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/components/create-listing/create-listing.stories.tsx index b7165a657..d0fe2f3e6 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/components/create-listing/create-listing.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/components/create-listing/create-listing.stories.tsx @@ -57,7 +57,7 @@ export const Default: Story = { onImageAdd: fn(), onImageRemove: fn(), }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await expect(canvasElement).toBeTruthy(); const header = canvas.queryByText(/Create a Listing/i); @@ -78,7 +78,7 @@ export const WithImages: Story = { onCancel: fn(), onImageRemove: fn(), }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; @@ -88,7 +88,7 @@ export const FormInteraction: Story = { onSubmit: fn(), onCancel: fn(), }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await expect(canvasElement).toBeTruthy(); const titleInput = canvas.queryByLabelText(/Title/i); @@ -102,7 +102,7 @@ export const ClickBackButton: Story = { args: { onCancel: fn(), }, - play: async ({ canvasElement, args }) => { + play: async ({ canvasElement, args }) => { const canvas = within(canvasElement); await expect(canvasElement).toBeTruthy(); const backButton = canvas.queryByRole('button', { name: /Back/i }); @@ -118,7 +118,7 @@ export const ClickSaveAsDraft: Story = { onSubmit: fn(), uploadedImages: [], }, - play: async ({ canvasElement, args }) => { + play: async ({ canvasElement, args }) => { const canvas = within(canvasElement); await expect(canvasElement).toBeTruthy(); const draftButton = canvas.queryByRole('button', { name: /Save as Draft/i }); @@ -134,7 +134,7 @@ export const ClickPublish: Story = { onSubmit: fn(), uploadedImages: ['/assets/item-images/bike.png'], }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await expect(canvasElement).toBeTruthy(); const publishButton = canvas.queryByRole('button', { name: /Publish/i }); @@ -150,7 +150,7 @@ export const Loading: Story = { onSubmit: fn(), onCancel: fn(), }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; @@ -161,7 +161,7 @@ export const ShowPublishedSuccess: Story = { onViewListing: fn(), onModalClose: fn(), }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; @@ -172,7 +172,7 @@ export const ShowDraftSuccess: Story = { onViewDraft: fn(), onModalClose: fn(), }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; @@ -183,7 +183,7 @@ export const PublishWithValidForm: Story = { onCancel: fn(), uploadedImages: ['/assets/item-images/bike.png'], }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); const titleInput = canvas.getByLabelText(/Title/i); @@ -203,7 +203,7 @@ export const SaveDraftWithPartialData: Story = { onCancel: fn(), uploadedImages: [], }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); const titleInput = canvas.getByLabelText(/Title/i); @@ -221,7 +221,7 @@ export const RemoveImage: Story = { onSubmit: fn(), onCancel: fn(), }, - play: async ({ canvasElement, args }) => { + play: async ({ canvasElement, args }) => { const canvas = within(canvasElement); const removeButtons = canvas.queryAllByRole('button', { name: /remove/i }); @@ -242,7 +242,7 @@ export const LoadingToPublished: Story = { onModalClose: fn(), uploadedImages: ['/assets/item-images/bike.png'], }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; @@ -256,7 +256,7 @@ export const LoadingToDraft: Story = { onModalClose: fn(), uploadedImages: [], }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; @@ -267,7 +267,7 @@ export const MaxCharacterLimitDescription: Story = { onCancel: fn(), uploadedImages: [], }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; @@ -278,7 +278,7 @@ export const CategorySelection: Story = { onCancel: fn(), uploadedImages: [], }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); const categorySelect = canvas.queryByRole('combobox', { name: /Category/i }); if (categorySelect) { @@ -294,7 +294,7 @@ export const EmptyCategories: Story = { onCancel: fn(), uploadedImages: [], }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; @@ -305,7 +305,7 @@ export const DateRangePicker: Story = { onCancel: fn(), uploadedImages: [], }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); const dateInputs = canvas.queryAllByRole('textbox'); await expect(dateInputs.length).toBeGreaterThan(0); @@ -318,7 +318,7 @@ export const FormValidationError: Story = { onCancel: fn(), uploadedImages: [], }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); const publishButton = canvas.getByRole('button', { name: /Publish/i }); await userEvent.click(publishButton); @@ -332,7 +332,7 @@ export const LocationInput: Story = { onCancel: fn(), uploadedImages: [], }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); const locationInput = canvas.getByLabelText(/Location/i); await userEvent.type(locationInput, 'Toronto, ON'); @@ -346,7 +346,7 @@ export const ImageAdd: Story = { onImageAdd: fn(), uploadedImages: [], }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; @@ -364,7 +364,7 @@ export const MultipleImages: Story = { onCancel: fn(), onImageRemove: fn(), }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; diff --git a/apps/ui-sharethrift/src/components/layouts/home/components/create-listing/hooks/use-create-listing-navigation.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/components/create-listing/hooks/use-create-listing-navigation.stories.tsx index 7e8dc3352..40f322341 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/components/create-listing/hooks/use-create-listing-navigation.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/components/create-listing/hooks/use-create-listing-navigation.stories.tsx @@ -2,16 +2,16 @@ import type { Meta, StoryObj } from '@storybook/react'; import { expect, userEvent, within } from 'storybook/test'; import { MemoryRouter } from 'react-router-dom'; import { useCreateListingNavigation } from './use-create-listing-navigation.ts'; -import { MockAuthWrapper } from '../../../../../../test-utils/storybook-decorators.tsx'; import { AuthContext } from 'react-oidc-context'; import { createMockAuth, createMockUser } from '../../../../../../test/utils/mockAuth.ts'; +import { MockAuthWrapper } from '../../../../../../test-utils/storybook-mock-auth-wrappers.tsx'; const NavigationTestComponent = () => { const handleCreateListing = useCreateListingNavigation(); return (
-
@@ -36,7 +36,7 @@ export const HookTest: Story = { ), - play: async () => { + play: () => { expect(typeof useCreateListingNavigation).toBe('function'); }, }; @@ -56,7 +56,7 @@ export const AuthenticatedNavigation: Story = { ); }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); const button = canvas.getByTestId('create-listing-btn'); @@ -81,7 +81,7 @@ export const UnauthenticatedNavigation: Story = { ); }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); const button = canvas.getByTestId('create-listing-btn'); diff --git a/apps/ui-sharethrift/src/components/layouts/home/components/create-listing/hooks/use-file-limit.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/components/create-listing/hooks/use-file-limit.stories.tsx index 2013646d3..80d7c69c7 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/components/create-listing/hooks/use-file-limit.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/components/create-listing/hooks/use-file-limit.stories.tsx @@ -90,7 +90,7 @@ type Story = StoryObj; export const HookTest: Story = { render: () => , - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); expect(typeof useFileLimit).toBe('function'); const container = canvas.getByTestId('file-limit-container'); @@ -100,7 +100,7 @@ export const HookTest: Story = { export const WithZeroFiles: Story = { render: () => , - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); const countElement = canvas.getByTestId('current-count'); expect(countElement).toHaveTextContent('Current count: 0'); @@ -111,7 +111,7 @@ export const WithZeroFiles: Story = { export const NearMaxLimit: Story = { render: () => , - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); const countElement = canvas.getByTestId('current-count'); expect(countElement).toHaveTextContent('Current count: 4'); @@ -122,7 +122,7 @@ export const NearMaxLimit: Story = { export const AtMaxLimit: Story = { render: () => , - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); const countElement = canvas.getByTestId('current-count'); expect(countElement).toHaveTextContent('Current count: 5'); @@ -131,7 +131,7 @@ export const AtMaxLimit: Story = { export const CustomMaxLimit: Story = { render: () => , - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); const countElement = canvas.getByTestId('current-count'); expect(countElement).toHaveTextContent('Current count: 3'); @@ -148,7 +148,7 @@ export const FileSelectionWithinLimit: Story = { filesToSelect={2} /> ), - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await new Promise((resolve) => setTimeout(resolve, 100)); const triggered = canvas.getByTestId('triggered'); @@ -164,7 +164,7 @@ export const FileSelectionAtLimit: Story = { filesToSelect={2} /> ), - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await new Promise((resolve) => setTimeout(resolve, 100)); const triggered = canvas.getByTestId('triggered'); @@ -180,7 +180,7 @@ export const FileSelectionExceedsLimit: Story = { filesToSelect={5} /> ), - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await new Promise((resolve) => setTimeout(resolve, 100)); const triggered = canvas.getByTestId('triggered'); diff --git a/apps/ui-sharethrift/src/components/layouts/home/components/hero-section.container.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/components/hero-section.container.stories.tsx index a9333e894..5427516bd 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/components/hero-section.container.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/components/hero-section.container.stories.tsx @@ -27,7 +27,7 @@ export const Default: Story = { onSearchChange: fn(), onSearch: fn(), }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { expect(canvasElement).toBeTruthy(); }, }; diff --git a/apps/ui-sharethrift/src/components/layouts/home/components/listings-page.container.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/components/listings-page.container.stories.tsx index 17429a1d5..6ed703ab6 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/components/listings-page.container.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/components/listings-page.container.stories.tsx @@ -146,7 +146,7 @@ export const Loading: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); const loadingSpinner = canvas.queryByRole('progressbar') ?? canvas.queryByText(/loading/i); diff --git a/apps/ui-sharethrift/src/components/layouts/home/components/view-listing/listing-information/listing-information.container.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/components/view-listing/listing-information/listing-information.container.stories.tsx index 488749dff..4857cbc6e 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/components/view-listing/listing-information/listing-information.container.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/components/view-listing/listing-information/listing-information.container.stories.tsx @@ -98,7 +98,7 @@ export const AuthenticatedUser: Story = { onLoginClick: fn(), onSignUpClick: fn(), }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { @@ -125,7 +125,7 @@ export const UnauthenticatedUser: Story = { onLoginClick: fn(), onSignUpClick: fn(), }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { @@ -162,7 +162,7 @@ export const SharerView: Story = { onLoginClick: fn(), onSignUpClick: fn(), }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { @@ -190,7 +190,7 @@ export const WithExistingReservation: Story = { onLoginClick: fn(), onSignUpClick: fn(), }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { @@ -235,7 +235,7 @@ export const QueryLoadingState: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); const loadingSpinner = canvas.queryByRole('progressbar') ?? canvas.queryByText(/loading/i); @@ -275,7 +275,7 @@ export const QueryError: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { @@ -325,7 +325,7 @@ export const NoCurrentUser: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { @@ -381,7 +381,7 @@ export const MutationError: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { @@ -448,7 +448,7 @@ export const WithExistingOtherReservations: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { @@ -489,7 +489,7 @@ export const SkipQuery: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { diff --git a/apps/ui-sharethrift/src/components/layouts/home/components/view-listing/listing-information/listing-information.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/components/view-listing/listing-information/listing-information.stories.tsx index 95a6264e8..1b9155d69 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/components/view-listing/listing-information/listing-information.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/components/view-listing/listing-information/listing-information.stories.tsx @@ -60,7 +60,7 @@ export default meta; type Story = StoryObj; export const Default: Story = { - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); await expect(canvasElement.querySelector('.title42')).toBeTruthy(); }, @@ -70,7 +70,7 @@ export const Unauthenticated: Story = { args: { isAuthenticated: false, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; @@ -79,7 +79,7 @@ export const SharerView: Story = { args: { userIsSharer: true, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; @@ -94,7 +94,7 @@ export const WithPendingRequest: Story = { reservationPeriodEnd: '1739145600000', }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; @@ -106,7 +106,7 @@ export const WithDatesSelected: Story = { endDate: new Date('2025-02-10'), }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; @@ -118,7 +118,7 @@ export const ListingNotPublished: Story = { state: 'Draft' as const, }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); await expect(canvasElement.textContent).toContain('Listing Not Available'); }, @@ -128,7 +128,7 @@ export const LoadingOtherReservations: Story = { args: { otherReservationsLoading: true, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; @@ -141,7 +141,7 @@ export const ReservationLoading: Story = { endDate: new Date('2025-02-10'), }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; @@ -150,7 +150,7 @@ export const WithOtherReservations: Story = { args: { otherReservations: mockOtherReservations, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; @@ -159,7 +159,7 @@ export const WithReservationError: Story = { args: { otherReservationsError: new Error('Failed to load reservations'), }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; @@ -172,7 +172,7 @@ export const ClickReserveButton: Story = { endDate: new Date('2025-02-10'), }, }, - play: async ({ canvasElement, args }) => { + play: async ({ canvasElement, args }) => { const canvas = within(canvasElement); await expect(canvasElement).toBeTruthy(); const reserveButton = canvas.queryByRole('button', { name: /Reserve/i }); @@ -194,7 +194,7 @@ export const ClickCancelButton: Story = { reservationPeriodEnd: '1739145600000', }, }, - play: async ({ canvasElement, args }) => { + play: async ({ canvasElement, args }) => { const canvas = within(canvasElement); await expect(canvasElement).toBeTruthy(); const cancelButton = canvas.queryByRole('button', { name: /Cancel/i }); @@ -210,7 +210,7 @@ export const UnauthenticatedLoginClick: Story = { isAuthenticated: false, onLoginClick: fn(), }, - play: async ({ canvasElement, args }) => { + play: async ({ canvasElement, args }) => { const canvas = within(canvasElement); await expect(canvasElement).toBeTruthy(); const loginButton = canvas.queryByRole('button', { name: /Login/i }); @@ -226,7 +226,7 @@ export const UnauthenticatedSignUpClick: Story = { isAuthenticated: false, onSignUpClick: fn(), }, - play: async ({ canvasElement, args }) => { + play: async ({ canvasElement, args }) => { const canvas = within(canvasElement); await expect(canvasElement).toBeTruthy(); const signUpButton = canvas.queryByRole('button', { name: /Sign Up/i }); @@ -247,7 +247,7 @@ export const WithApprovedReservation: Story = { reservationPeriodEnd: '1739145600000', }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; @@ -257,7 +257,7 @@ export const DateRangeWithOverlap: Story = { otherReservations: mockOtherReservations, onReservationDatesChange: fn(), }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await expect(canvasElement).toBeTruthy(); const dateInputs = canvas.getAllByPlaceholderText(/date/i); @@ -272,7 +272,7 @@ export const ClickLoginToReserve: Story = { args: { isAuthenticated: false, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await expect(canvasElement).toBeTruthy(); const loginButton = canvas.queryByRole('button', { name: /Log in to Reserve/i }); @@ -287,7 +287,7 @@ export const SelectDatesInDatePicker: Story = { otherReservations: [], onReservationDatesChange: fn(), }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await expect(canvasElement).toBeTruthy(); const dateInputs = canvas.getAllByPlaceholderText(/date/i); @@ -306,7 +306,7 @@ export const ClearDateSelection: Story = { }, onReservationDatesChange: fn(), }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; diff --git a/apps/ui-sharethrift/src/components/layouts/home/components/view-listing/sharer-information/sharer-information.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/components/view-listing/sharer-information/sharer-information.stories.tsx index 3772aa7e2..1c3906ba3 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/components/view-listing/sharer-information/sharer-information.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/components/view-listing/sharer-information/sharer-information.stories.tsx @@ -72,7 +72,7 @@ export default meta; type Story = StoryObj; export const Default: Story = { - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; @@ -82,7 +82,7 @@ export const OwnerView: Story = { isOwner: true, currentUserId: 'user-1', }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; @@ -91,7 +91,7 @@ export const WithoutCurrentUser: Story = { args: { currentUserId: null, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; @@ -100,7 +100,7 @@ export const RecentlyShared: Story = { args: { sharedTimeAgo: '1h ago', }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; @@ -109,13 +109,13 @@ export const LongTimeAgo: Story = { args: { sharedTimeAgo: '3 months ago', }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; export const ClickMessageButton: Story = { - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await expect(canvasElement).toBeTruthy(); const messageButton = canvas.queryByRole('button', { name: /Message/i }); @@ -160,7 +160,7 @@ export const MessageButtonWithError: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await expect(canvasElement).toBeTruthy(); const messageButton = canvas.queryByRole('button', { name: /Message/i }); @@ -176,7 +176,7 @@ export const MobileView: Story = { defaultViewport: 'mobile1', }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; diff --git a/apps/ui-sharethrift/src/components/layouts/home/components/view-listing/view-listing.container.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/components/view-listing/view-listing.container.stories.tsx index 49001e521..2fdc36761 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/components/view-listing/view-listing.container.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/components/view-listing/view-listing.container.stories.tsx @@ -91,7 +91,7 @@ export const Authenticated: Story = { args: { isAuthenticated: true, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await waitFor( () => { // Component rendered @@ -123,7 +123,7 @@ export const Unauthenticated: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await waitFor( () => { // Component rendered @@ -151,7 +151,7 @@ export const Loading: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); const loadingSpinner = canvas.queryByRole('progressbar') ?? canvas.queryByText(/loading/i); diff --git a/apps/ui-sharethrift/src/components/layouts/home/messages/pages/Conversation.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/messages/pages/Conversation.stories.tsx index 1bce2d8d3..22e6526dc 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/messages/pages/Conversation.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/messages/pages/Conversation.stories.tsx @@ -20,7 +20,7 @@ type Story = StoryObj; export const Default: Story = { name: 'Default', - play: async ({ canvasElement }: { canvasElement: HTMLElement }) => { + play: ({ canvasElement }: { canvasElement: HTMLElement }) => { expect(canvasElement).toBeTruthy(); const content = canvasElement.textContent; expect(content).toContain('Conversation Page'); diff --git a/apps/ui-sharethrift/src/components/layouts/home/messages/stories/ConversationBoxContainer.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/messages/stories/ConversationBoxContainer.stories.tsx index 280adb972..1d9371450 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/messages/stories/ConversationBoxContainer.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/messages/stories/ConversationBoxContainer.stories.tsx @@ -110,7 +110,7 @@ export const Default: Story = { mocks: defaultMocks, }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); // ListingBanner shows "{firstName}'s Listing" await expect( @@ -128,7 +128,7 @@ export const SendMessageSuccess: Story = { mocks: sendMessageSuccessMocks, }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); const textArea = await canvas.findByPlaceholderText(/Type a message/i); await userEvent.type(textArea, 'Test message'); @@ -146,7 +146,7 @@ export const SendMessageError: Story = { mocks: sendMessageErrorMocks, }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); const textArea = await canvas.findByPlaceholderText(/Type a message/i); await userEvent.type(textArea, 'This will fail'); @@ -164,7 +164,7 @@ export const SendMessageNetworkError: Story = { mocks: sendMessageNetworkErrorMocks, }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); const textArea = await canvas.findByPlaceholderText(/Type a message/i); await userEvent.type(textArea, 'Network will fail'); @@ -182,7 +182,7 @@ export const CacheUpdateOnSuccess: Story = { mocks: cacheUpdateMocks, }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); const textArea = await canvas.findByPlaceholderText(/Type a message/i); await userEvent.type(textArea, 'First message'); diff --git a/apps/ui-sharethrift/src/components/layouts/home/my-listings/components/all-listings-table.container.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/my-listings/components/all-listings-table.container.stories.tsx index 7a4b7d9c1..026888dcf 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/my-listings/components/all-listings-table.container.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/my-listings/components/all-listings-table.container.stories.tsx @@ -169,7 +169,7 @@ export const Loading: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); // Check for loading state const loadingSpinner = diff --git a/apps/ui-sharethrift/src/components/layouts/home/my-listings/components/requests-table.container.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/my-listings/components/requests-table.container.stories.tsx index f5923b739..493498892 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/my-listings/components/requests-table.container.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/my-listings/components/requests-table.container.stories.tsx @@ -72,7 +72,7 @@ export const Default: Story = { currentPage: 1, onPageChange: fn(), }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { @@ -114,7 +114,7 @@ export const Empty: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { @@ -151,7 +151,7 @@ export const Loading: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); const loadingSpinner = canvas.queryByRole('progressbar') ?? canvas.queryByText(/loading/i); @@ -184,7 +184,7 @@ export const ErrorState: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { @@ -224,7 +224,7 @@ export const WithSearchFilter: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { @@ -268,7 +268,7 @@ export const WithStatusFilter: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { @@ -304,7 +304,7 @@ export const WithSorting: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { @@ -354,7 +354,7 @@ export const Pagination: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { @@ -395,7 +395,7 @@ export const NoData: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { diff --git a/apps/ui-sharethrift/src/components/layouts/home/my-listings/pages/edit-listing.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/my-listings/pages/edit-listing.stories.tsx index 1945d6e88..7d8aa861a 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/my-listings/pages/edit-listing.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/my-listings/pages/edit-listing.stories.tsx @@ -20,7 +20,7 @@ type Story = StoryObj; export const Default: Story = { name: 'Default', - play: async ({ canvasElement }: { canvasElement: HTMLElement }) => { + play: ({ canvasElement }: { canvasElement: HTMLElement }) => { expect(canvasElement).toBeTruthy(); const content = canvasElement.textContent; expect(content).toContain('Edit Listing Page'); diff --git a/apps/ui-sharethrift/src/components/layouts/home/my-listings/pages/my-listings.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/my-listings/pages/my-listings.stories.tsx index d844b21fc..c61d0eb66 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/my-listings/pages/my-listings.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/my-listings/pages/my-listings.stories.tsx @@ -136,7 +136,7 @@ export const EmptyListings: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { expect(canvasElement).toBeTruthy(); }, }; diff --git a/apps/ui-sharethrift/src/components/layouts/home/my-listings/stories/all-listings-card.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/my-listings/stories/all-listings-card.stories.tsx index 4b7eba5e8..bc8c0b103 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/my-listings/stories/all-listings-card.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/my-listings/stories/all-listings-card.stories.tsx @@ -93,7 +93,7 @@ export const Default: Story = { args: { listing: MOCK_LISTING_PAUSED, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); const title = canvas.getByText(/Electric Guitar/i); @@ -121,7 +121,7 @@ export const ActiveListing: Story = { args: { listing: MOCK_LISTING_ACTIVE, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); expect(canvas.getByText(/Cordless Drill/i)).toBeInTheDocument(); const pauseBtn = canvas.queryByRole('button', { name: /pause/i }); @@ -133,7 +133,7 @@ export const PausedListing: Story = { args: { listing: MOCK_LISTING_PAUSED, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); expect(canvas.getByText(/Electric Guitar/i)).toBeInTheDocument(); const reinstateBtn = canvas.queryByRole('button', { name: /reinstate/i }); @@ -145,7 +145,7 @@ export const BlockedListing: Story = { args: { listing: MOCK_LISTING_BLOCKED, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); expect(canvas.getByText(/Blocked Item/i)).toBeInTheDocument(); const appealBtn = canvas.queryByRole('button', { name: /appeal/i }); @@ -157,7 +157,7 @@ export const DraftListing: Story = { args: { listing: MOCK_LISTING_DRAFT, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); expect(canvas.getByText(/Draft Listing/i)).toBeInTheDocument(); const publishBtn = canvas.queryByRole('button', { name: /publish/i }); @@ -169,7 +169,7 @@ export const ExpiredListing: Story = { args: { listing: MOCK_LISTING_EXPIRED, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); expect(canvas.getByText(/Expired Item/i)).toBeInTheDocument(); const reinstateBtn = canvas.queryByRole('button', { name: /reinstate/i }); @@ -181,7 +181,7 @@ export const ReservedListing: Story = { args: { listing: MOCK_LISTING_RESERVED, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); expect(canvas.getByText(/Reserved Item/i)).toBeInTheDocument(); const pauseBtn = canvas.queryByRole('button', { name: /pause/i }); @@ -193,7 +193,7 @@ export const NoImageListing: Story = { args: { listing: MOCK_LISTING_NO_IMAGE, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); expect(canvas.getByText(/No Image Listing/i)).toBeInTheDocument(); }, @@ -205,7 +205,7 @@ export const WithPendingRequests: Story = { onViewPendingRequests: fn(), onAction: fn(), }, - play: async ({ canvasElement, args }) => { + play: async({ canvasElement, args }) => { const canvas = within(canvasElement); const title = canvas.getByText(/Cordless Drill/i); diff --git a/apps/ui-sharethrift/src/components/layouts/home/my-listings/stories/all-listings-table.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/my-listings/stories/all-listings-table.stories.tsx index 87de3f57c..c95ce3a04 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/my-listings/stories/all-listings-table.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/my-listings/stories/all-listings-table.stories.tsx @@ -62,7 +62,7 @@ export default meta; type Story = StoryObj; export const Default: Story = { - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); // Use getAllByText as Dashboard renders both table and card views await expect(canvas.getAllByText('Cordless Drill').length).toBeGreaterThan(0); @@ -76,7 +76,7 @@ export const AllStatusTypes: Story = { data: ALL_STATUS_LISTINGS, total: ALL_STATUS_LISTINGS.length, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); // Use getAllByText as Dashboard renders both table and card views await expect(canvas.getAllByText('Active Listing').length).toBeGreaterThan(0); @@ -96,7 +96,7 @@ export const ClickPauseButton: Story = { total: 1, onAction: fn(), }, - play: async ({ canvasElement, args }) => { + play: async ({ canvasElement, args }) => { const canvas = within(canvasElement); const pauseButton = await canvas.findByRole('button', { name: 'Pause' }); await userEvent.click(pauseButton); @@ -111,7 +111,7 @@ export const ClickEditButton: Story = { total: 1, onAction: fn(), }, - play: async ({ canvasElement, args }) => { + play: async ({ canvasElement, args }) => { const canvas = within(canvasElement); const editButton = await canvas.findByRole('button', { name: 'Edit' }); await userEvent.click(editButton); @@ -126,7 +126,7 @@ export const ClickReinstateButton: Story = { total: 1, onAction: fn(), }, - play: async ({ canvasElement, args }) => { + play: async ({ canvasElement, args }) => { const canvas = within(canvasElement); const reinstateButton = await canvas.findByRole('button', { name: 'Reinstate' }); await userEvent.click(reinstateButton); @@ -141,7 +141,7 @@ export const ClickPublishButton: Story = { total: 1, onAction: fn(), }, - play: async ({ canvasElement, args }) => { + play: async ({ canvasElement, args }) => { const canvas = within(canvasElement); const publishButton = await canvas.findByRole('button', { name: 'Publish' }); await userEvent.click(publishButton); @@ -156,7 +156,7 @@ export const ClickCancelWithConfirmation: Story = { total: 1, onAction: fn(), }, - play: async ({ canvasElement, args }) => { + play: async ({ canvasElement, args }) => { const canvas = within(canvasElement); const cancelButton = await canvas.findByRole('button', { name: 'Cancel' }); await userEvent.click(cancelButton); @@ -178,7 +178,7 @@ export const ClickDeleteWithConfirmation: Story = { total: 1, onAction: fn(), }, - play: async ({ canvasElement, args }) => { + play: async ({ canvasElement, args }) => { const canvas = within(canvasElement); const deleteButton = await canvas.findByRole('button', { name: 'Delete' }); await userEvent.click(deleteButton); @@ -200,7 +200,7 @@ export const ClickAppealWithConfirmation: Story = { total: 1, onAction: fn(), }, - play: async ({ canvasElement, args }) => { + play: async ({ canvasElement, args }) => { const canvas = within(canvasElement); const appealButton = await canvas.findByRole('button', { name: 'Appeal' }); await userEvent.click(appealButton); @@ -222,7 +222,7 @@ export const ReservedListing: Story = { total: 1, onAction: fn(), }, - play: async ({ canvasElement, args }) => { + play: async ({ canvasElement, args }) => { const canvas = within(canvasElement); const pauseButton = await canvas.findByRole('button', { name: 'Pause' }); await userEvent.click(pauseButton); @@ -237,7 +237,7 @@ export const ExpiredListing: Story = { total: 1, onAction: fn(), }, - play: async ({ canvasElement, args }) => { + play: async ({ canvasElement, args }) => { const canvas = within(canvasElement); const reinstateButton = await canvas.findByRole('button', { name: 'Reinstate' }); await userEvent.click(reinstateButton); @@ -260,7 +260,7 @@ export const ListingWithoutDates: Story = { }], total: 1, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); // Use getAllByText as Dashboard renders both table and card views await expect(canvas.getAllByText('No Dates Item').length).toBeGreaterThan(0); @@ -276,7 +276,7 @@ export const WithSortingApplied: Story = { data: MOCK_LISTINGS, sorter: { field: 'createdAt', order: 'ascend' }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; @@ -288,7 +288,7 @@ export const Loading: Story = { total: 0, loading: true, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; @@ -299,7 +299,7 @@ export const WithStatusFilters: Story = { data: MOCK_LISTINGS, statusFilters: ['Active', 'Paused'], }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; @@ -310,7 +310,7 @@ export const WithSearchText: Story = { data: MOCK_LISTINGS, searchText: 'Drill', }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; diff --git a/apps/ui-sharethrift/src/components/layouts/home/my-listings/stories/my-listings-dashboard.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/my-listings/stories/my-listings-dashboard.stories.tsx index a3c86dd91..c50257c48 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/my-listings/stories/my-listings-dashboard.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/my-listings/stories/my-listings-dashboard.stories.tsx @@ -82,7 +82,7 @@ export default meta; type Story = StoryObj; export const Default: Story = { - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; diff --git a/apps/ui-sharethrift/src/components/layouts/home/my-listings/stories/requests-status-helpers.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/my-listings/stories/requests-status-helpers.stories.tsx index 08f628c5a..b8737693c 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/my-listings/stories/requests-status-helpers.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/my-listings/stories/requests-status-helpers.stories.tsx @@ -43,7 +43,7 @@ export default meta; type Story = StoryObj; export const StatusTagClasses: Story = { - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { expect(getStatusTagClass('Accepted')).toBe('requestAcceptedTag'); expect(getStatusTagClass('Rejected')).toBe('requestRejectedTag'); expect(getStatusTagClass('Closed')).toBe('expiredTag'); @@ -131,7 +131,7 @@ const ActionButtonsTest = () => { export const ActionButtons: Story = { render: () => , - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const pendingSection = canvasElement.querySelector('[data-testid="pending-buttons"]'); expect(pendingSection?.textContent).toContain('Accept'); expect(pendingSection?.textContent).toContain('Reject'); diff --git a/apps/ui-sharethrift/src/components/layouts/home/my-reservations/components/reservations-view-active.container.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/my-reservations/components/reservations-view-active.container.stories.tsx index 58a59c8a0..84b16de93 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/my-reservations/components/reservations-view-active.container.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/my-reservations/components/reservations-view-active.container.stories.tsx @@ -172,7 +172,7 @@ export const Loading: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); const loadingSpinner = canvas.queryByRole('progressbar') ?? canvas.queryByText(/loading/i); @@ -532,7 +532,7 @@ export const ReservationsLoading: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); const loadingSpinner = canvas.queryByRole('progressbar') ?? canvas.queryByText(/loading/i); diff --git a/apps/ui-sharethrift/src/components/layouts/home/my-reservations/components/reservations-view-history.container.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/my-reservations/components/reservations-view-history.container.stories.tsx index 435d1b66a..b46cda98e 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/my-reservations/components/reservations-view-history.container.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/my-reservations/components/reservations-view-history.container.stories.tsx @@ -100,7 +100,7 @@ export default meta; type Story = StoryObj; export const Default: Story = { - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; @@ -133,7 +133,7 @@ export const Empty: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; @@ -151,7 +151,7 @@ export const Loading: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { await expect(canvasElement).toBeTruthy(); }, }; diff --git a/apps/ui-sharethrift/src/components/layouts/home/my-reservations/stories/reservation-actions.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/my-reservations/stories/reservation-actions.stories.tsx index f98f2d282..4bdd3c425 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/my-reservations/stories/reservation-actions.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/my-reservations/stories/reservation-actions.stories.tsx @@ -36,7 +36,7 @@ export const Requested: Story = { onClose: fn(), onMessage: fn(), }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); // Verify action buttons are present @@ -57,7 +57,7 @@ export const Accepted: Story = { onClose: fn(), onMessage: fn(), }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); // Verify buttons are rendered for accepted state @@ -85,6 +85,7 @@ export const ButtonInteraction: Story = { await userEvent.click(buttons[0]); // Verify the callback was called const callbacks = [args.onCancel, args.onClose, args.onMessage]; + // eslint-disable-next-line @typescript-eslint/no-explicit-any const called = callbacks.some(cb => cb && (cb as any).mock?.calls?.length > 0); expect(called || true).toBe(true); // Allow pass if callbacks are called } @@ -117,7 +118,7 @@ export const LoadingStates: Story = { onMessage: fn(), cancelLoading: true, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); // Verify loading state is rendered diff --git a/apps/ui-sharethrift/src/components/layouts/home/my-reservations/stories/reservation-state-utils.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/my-reservations/stories/reservation-state-utils.stories.tsx index 391dc8c76..9ffb7fba9 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/my-reservations/stories/reservation-state-utils.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/my-reservations/stories/reservation-state-utils.stories.tsx @@ -44,7 +44,7 @@ export default meta; type Story = StoryObj; export const Constants: Story = { - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { expect(ACTIVE_RESERVATION_STATES).toContain('Accepted'); expect(ACTIVE_RESERVATION_STATES).toContain('Requested'); expect(ACTIVE_RESERVATION_STATES.length).toBe(2); @@ -62,7 +62,7 @@ export const Constants: Story = { }; export const ActiveStateChecker: Story = { - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { expect(isActiveReservationState('Accepted')).toBe(true); expect(isActiveReservationState('Requested')).toBe(true); @@ -77,7 +77,7 @@ export const ActiveStateChecker: Story = { }; export const InactiveStateChecker: Story = { - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { expect(isInactiveReservationState('Cancelled')).toBe(true); expect(isInactiveReservationState('Closed')).toBe(true); expect(isInactiveReservationState('Rejected')).toBe(true); diff --git a/apps/ui-sharethrift/src/components/layouts/home/my-reservations/stories/reservations-table.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/my-reservations/stories/reservations-table.stories.tsx index d557f154c..5cbafee11 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/my-reservations/stories/reservations-table.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/my-reservations/stories/reservations-table.stories.tsx @@ -30,7 +30,7 @@ type Story = StoryObj; export const AllReservations: Story = { args: { reservations: storyReservationsAll }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await expect(canvas.getByRole('table')).toBeInTheDocument(); }, diff --git a/apps/ui-sharethrift/src/components/layouts/home/stories/HeroSection.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/stories/HeroSection.stories.tsx index eb9f4a7ed..9e496efcf 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/stories/HeroSection.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/stories/HeroSection.stories.tsx @@ -15,7 +15,7 @@ type Story = StoryObj; export const Default: Story = { render: () => , - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); const heading = canvas.getByRole('heading'); @@ -33,7 +33,7 @@ export const Default: Story = { export const WithInteraction: Story = { render: () => , - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); const heading = canvas.getByRole('heading'); @@ -42,7 +42,7 @@ export const WithInteraction: Story = { const buttons = canvasElement.querySelectorAll('button, a[class*="button"]'); expect(buttons.length).toBeGreaterThanOrEqual(0); - const textContent = canvasElement.textContent; + const {textContent} = canvasElement; expect(textContent).toBeTruthy(); }, }; diff --git a/apps/ui-sharethrift/src/components/layouts/home/stories/section-layout.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/stories/section-layout.stories.tsx index 015a51b52..8733fceb7 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/stories/section-layout.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/stories/section-layout.stories.tsx @@ -4,8 +4,8 @@ import { MemoryRouter } from 'react-router-dom'; import { ApolloClient, InMemoryCache } from '@apollo/client'; import { ApolloProvider } from '@apollo/client/react'; import { MockLink } from '@apollo/client/testing'; -import { MockAuthWrapper } from '../../../../test-utils/storybook-decorators.tsx'; import { SectionLayout } from '../section-layout.tsx'; +import { MockAuthWrapper } from '../../../../test-utils/storybook-mock-auth-wrappers.tsx'; // Mock Apollo Client with MockLink const mockApolloClient = new ApolloClient({ diff --git a/apps/ui-sharethrift/src/components/layouts/signup/components/account-setup.container.stories.tsx b/apps/ui-sharethrift/src/components/layouts/signup/components/account-setup.container.stories.tsx index 1d336b120..d5eea3352 100644 --- a/apps/ui-sharethrift/src/components/layouts/signup/components/account-setup.container.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/signup/components/account-setup.container.stories.tsx @@ -78,7 +78,7 @@ export default meta; type Story = StoryObj; export const Default: Story = { - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { @@ -104,7 +104,7 @@ export const Loading: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); const loadingSpinner = canvas.queryByRole('progressbar') ?? canvas.queryByText(/loading/i); @@ -126,7 +126,7 @@ export const WithError: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { @@ -178,7 +178,7 @@ export const UpdateSuccess: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { @@ -230,7 +230,7 @@ export const UpdateFailure: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { @@ -270,7 +270,7 @@ export const UpdateError: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { @@ -302,7 +302,7 @@ export const WithMissingUserData: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { // Component should handle null user gracefully expect(canvasElement).toBeTruthy(); }, diff --git a/apps/ui-sharethrift/src/components/layouts/signup/components/profile-setup.container.stories.tsx b/apps/ui-sharethrift/src/components/layouts/signup/components/profile-setup.container.stories.tsx index 4d1572640..79cf62685 100644 --- a/apps/ui-sharethrift/src/components/layouts/signup/components/profile-setup.container.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/signup/components/profile-setup.container.stories.tsx @@ -77,7 +77,7 @@ export default meta; type Story = StoryObj; export const Default: Story = { - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { @@ -105,7 +105,7 @@ export const LoadingState: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); const loadingSpinner = canvas.queryByRole('progressbar') ?? canvas.queryByText(/loading/i); @@ -127,7 +127,7 @@ export const QueryError: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { @@ -159,7 +159,7 @@ export const NoUserData: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { // Component should handle null user gracefully expect(canvasElement).toBeTruthy(); }, @@ -203,7 +203,7 @@ export const UpdateSuccess: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { @@ -257,7 +257,7 @@ export const UpdateFailure: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { @@ -299,7 +299,7 @@ export const UpdateError: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { @@ -344,7 +344,7 @@ export const EmptyProfile: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { @@ -383,7 +383,7 @@ export const UpdateLoading: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: async ({ canvasElement }) => { const canvas = within(canvasElement); await waitFor( () => { diff --git a/apps/ui-sharethrift/src/components/layouts/signup/components/select-account-type.container.stories.tsx b/apps/ui-sharethrift/src/components/layouts/signup/components/select-account-type.container.stories.tsx index 02c71387b..e1272bed6 100644 --- a/apps/ui-sharethrift/src/components/layouts/signup/components/select-account-type.container.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/signup/components/select-account-type.container.stories.tsx @@ -196,7 +196,7 @@ export const Loading: Story = { ], }, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); const loadingSpinner = canvas.queryByRole('progressbar') ?? canvas.queryByText(/loading/i); diff --git a/apps/ui-sharethrift/src/components/layouts/signup/components/select-account-type.stories.tsx b/apps/ui-sharethrift/src/components/layouts/signup/components/select-account-type.stories.tsx index b4b20f6db..8d368faf1 100644 --- a/apps/ui-sharethrift/src/components/layouts/signup/components/select-account-type.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/signup/components/select-account-type.stories.tsx @@ -78,7 +78,7 @@ export default meta; type Story = StoryObj; export const Default: Story = { - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); expect(canvas.getByText('Account Type and Plan')).toBeTruthy(); expect(canvas.getByText('Non-Verified Personal')).toBeTruthy(); @@ -96,7 +96,7 @@ export const WithExistingAccountType: Story = { }, } as Parameters[0]['currentUserData'], }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); expect(canvas.getByText('Account Type and Plan')).toBeTruthy(); }, @@ -106,7 +106,7 @@ export const Loading: Story = { args: { loading: true, }, - play: async ({ canvasElement }) => { + play: ({ canvasElement }) => { const canvas = within(canvasElement); const saveButton = canvas.getByText('Save and Continue'); // Button should have loading state (ant-btn-loading class) diff --git a/apps/ui-sharethrift/src/components/layouts/signup/section-layout.stories.tsx b/apps/ui-sharethrift/src/components/layouts/signup/section-layout.stories.tsx index ed6d63de2..982add050 100644 --- a/apps/ui-sharethrift/src/components/layouts/signup/section-layout.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/signup/section-layout.stories.tsx @@ -2,7 +2,8 @@ import type { Meta, StoryObj } from '@storybook/react'; import { expect, within, userEvent } from 'storybook/test'; import { SectionLayout } from './section-layout.tsx'; import { MemoryRouter, Routes, Route } from 'react-router-dom'; -import { MockAuthWrapper, withMockApolloClient } from '../../../test-utils/storybook-decorators.tsx'; +import { withMockApolloClient } from '../../../test-utils/storybook-decorators.tsx'; +import { MockAuthWrapper } from '../../../test-utils/storybook-mock-auth-wrappers.tsx'; const meta: Meta = { title: 'Layouts/SectionLayout', diff --git a/apps/ui-sharethrift/src/components/layouts/signup/stories/section-layout.stories.tsx b/apps/ui-sharethrift/src/components/layouts/signup/stories/section-layout.stories.tsx index 959bf1914..683555f5e 100644 --- a/apps/ui-sharethrift/src/components/layouts/signup/stories/section-layout.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/signup/stories/section-layout.stories.tsx @@ -4,8 +4,8 @@ import { MemoryRouter } from 'react-router-dom'; import { ApolloClient, InMemoryCache } from '@apollo/client'; import { ApolloProvider } from '@apollo/client/react'; import { MockLink } from '@apollo/client/testing'; -import { MockAuthWrapper } from '../../../../test-utils/storybook-decorators.tsx'; import { SectionLayout } from '../section-layout.tsx'; +import { MockAuthWrapper } from '../../../../test-utils/storybook-mock-auth-wrappers.tsx'; const mockApolloClient = new ApolloClient({ link: new MockLink([]), diff --git a/apps/ui-sharethrift/src/components/shared/stories/auth-redirect-user.stories.tsx b/apps/ui-sharethrift/src/components/shared/stories/auth-redirect-user.stories.tsx index 4a32d49bd..12816e432 100644 --- a/apps/ui-sharethrift/src/components/shared/stories/auth-redirect-user.stories.tsx +++ b/apps/ui-sharethrift/src/components/shared/stories/auth-redirect-user.stories.tsx @@ -1,8 +1,8 @@ import type { Meta, StoryObj } from '@storybook/react'; import { expect } from 'storybook/test'; import { MemoryRouter } from 'react-router-dom'; -import { MockAuthWrapper } from '../../../test-utils/storybook-decorators.tsx'; import { AuthRedirectUser } from '../auth-redirect-user.tsx'; +import { MockAuthWrapper } from '../../../test-utils/storybook-mock-auth-wrappers.tsx'; const meta: Meta = { title: 'Shared/AuthRedirectUser', diff --git a/apps/ui-sharethrift/src/components/shared/stories/login-selection.stories.tsx b/apps/ui-sharethrift/src/components/shared/stories/login-selection.stories.tsx index 9e1b7ab44..658633182 100644 --- a/apps/ui-sharethrift/src/components/shared/stories/login-selection.stories.tsx +++ b/apps/ui-sharethrift/src/components/shared/stories/login-selection.stories.tsx @@ -1,8 +1,8 @@ import type { Meta, StoryObj } from '@storybook/react'; import { expect, within, userEvent } from 'storybook/test'; import { MemoryRouter } from 'react-router-dom'; -import { MockAuthWrapper } from '../../../test-utils/storybook-decorators.tsx'; import { LoginSelection } from '../login-selection.tsx'; +import { MockAuthWrapper } from '../../../test-utils/storybook-mock-auth-wrappers.tsx'; const meta: Meta = { title: 'Shared/LoginSelection', diff --git a/apps/ui-sharethrift/src/components/shared/stories/require-auth-admin.stories.tsx b/apps/ui-sharethrift/src/components/shared/stories/require-auth-admin.stories.tsx index d5c111ccd..d5ba30b51 100644 --- a/apps/ui-sharethrift/src/components/shared/stories/require-auth-admin.stories.tsx +++ b/apps/ui-sharethrift/src/components/shared/stories/require-auth-admin.stories.tsx @@ -2,7 +2,6 @@ import type { Meta, StoryObj } from '@storybook/react'; import { expect } from 'storybook/test'; import { withMockApolloClient, - MockAuthWrapper, } from '../../../test-utils/storybook-decorators.tsx'; import { MemoryRouter } from 'react-router-dom'; import { AuthContext } from 'react-oidc-context'; @@ -10,6 +9,7 @@ import { RequireAuthAdmin } from '../require-auth-admin.tsx'; import { UseUserIsAdminDocument } from '../../../generated.tsx'; import { createMockAuth } from '../../../test/utils/mockAuth.ts'; import { vi } from 'vitest'; +import { MockAuthWrapper } from '../../../test-utils/storybook-mock-auth-wrappers.tsx'; const meta: Meta = { title: 'Shared/RequireAuthAdmin', @@ -172,7 +172,7 @@ export const UnauthenticatedWithError: Story = { ); }, ], - play: async ({ canvasElement }) => { + play: async({ canvasElement }) => { // Should redirect on error await expect(canvasElement).toBeTruthy(); }, diff --git a/apps/ui-sharethrift/src/test-utils/storybook-decorators.tsx b/apps/ui-sharethrift/src/test-utils/storybook-decorators.tsx index 835d7ae26..2763aaa5c 100644 --- a/apps/ui-sharethrift/src/test-utils/storybook-decorators.tsx +++ b/apps/ui-sharethrift/src/test-utils/storybook-decorators.tsx @@ -1,12 +1,10 @@ -import { type ReactNode, type ReactElement, useMemo } from 'react'; -import { MemoryRouter, Route, Routes } from 'react-router-dom'; -import { AuthContext } from 'react-oidc-context'; import { ApolloClient, InMemoryCache } from '@apollo/client'; import { ApolloProvider } from '@apollo/client/react'; import { MockLink } from '@apollo/client/testing'; import type { Decorator, StoryContext } from '@storybook/react'; -import { createMockAuth, createMockUser } from '../test/utils/mockAuth.ts'; +import { MemoryRouter, Route, Routes } from 'react-router-dom'; import { UserIdProvider } from '../components/shared/user-context.tsx'; +import { MockAuthWrapper } from './storybook-mock-auth-wrappers.tsx'; /** * Reusable Apollo Client decorator for Storybook stories. @@ -25,81 +23,23 @@ import { UserIdProvider } from '../components/shared/user-context.tsx'; * } as Meta; * ``` */ -export const withMockApolloClient: Decorator = (Story, context: StoryContext) => { +export const withMockApolloClient: Decorator = ( + Story, + context: StoryContext, +) => { const mocks = context.parameters?.['apolloClient']?.['mocks'] || []; - const showWarnings = context.parameters?.['apolloClient']?.['showWarnings'] ?? false; + const showWarnings = + context.parameters?.['apolloClient']?.['showWarnings'] ?? false; const mockLink = new MockLink(mocks, showWarnings); const client = new ApolloClient({ link: mockLink, cache: new InMemoryCache(), }); - return ( - - - - ); -}; - -/** - * Mock authentication wrapper component for Storybook stories. - * Provides a mocked AuthContext that simulates an authenticated user. - * - * NOTE: We cannot use AuthProvider directly because it requires a real OIDC server. - * AuthProvider from react-oidc-context attempts to connect to the authority URL, - * perform OAuth2/OIDC flows, and validate tokens. Since we're using a fake authority - * in Storybook, the authentication fails and useAuth() returns isAuthenticated: false. - * Instead, we use AuthContext.Provider directly with a mocked auth object. - * - * When any child component calls useAuth(), it uses React's useContext(AuthContext) internally. - * By wrapping with , we provide the mock data to - * that context, so components receive our mockAuth object with isAuthenticated: true. - * - * IMPLEMENTATION NOTE: This component uses createMockAuth() and createMockUser() utilities - * from '../test/utils/mockAuth.ts' instead of manually constructing the auth object. - * This eliminates TypeScript 'any' types, ensures type safety, and reuses the shared - * mock implementation that properly types all required OIDC fields (profile, tokens, events, etc.). - */ -export const MockAuthWrapper = ({ - children, -}: { - children: ReactNode; -}): ReactElement => { - const mockAuth = useMemo( - () => - createMockAuth({ - isAuthenticated: true, - user: createMockUser(), - }), - [], - ); - - return {children}; -}; - -/** - * Mock unauthenticated wrapper component for Storybook stories. - * Provides a mocked AuthContext that simulates an unauthenticated user. - * - * Use this when testing components that show different UI for logged-out users - * (e.g., Login/Sign Up buttons in headers). - */ -export const MockUnauthWrapper = ({ - children, -}: { - children: ReactNode; -}): ReactElement => { - const mockAuth = useMemo( - () => - createMockAuth({ - isAuthenticated: false, - user: null, - }), - [], - ); - return ( - {children} + + + ); }; diff --git a/apps/ui-sharethrift/src/test-utils/storybook-mock-auth-wrappers.tsx b/apps/ui-sharethrift/src/test-utils/storybook-mock-auth-wrappers.tsx new file mode 100644 index 000000000..ba25dbc72 --- /dev/null +++ b/apps/ui-sharethrift/src/test-utils/storybook-mock-auth-wrappers.tsx @@ -0,0 +1,66 @@ +import { type ReactElement, type ReactNode, useMemo } from 'react'; +import { AuthContext } from 'react-oidc-context'; +import { createMockAuth, createMockUser } from '../test/utils/mockAuth.ts'; + +/** + * Mock unauthenticated wrapper component for Storybook stories. + * Provides a mocked AuthContext that simulates an unauthenticated user. + * + * Use this when testing components that show different UI for logged-out users + * (e.g., Login/Sign Up buttons in headers). + */ +export const MockUnauthWrapper = ({ + children, +}: { + children: ReactNode; +}): ReactElement => { + const mockAuth = useMemo( + () => + createMockAuth({ + isAuthenticated: false, + user: null, + }), + [], + ); + + return ( + {children} + ); +}; + + +/** + * Mock authentication wrapper component for Storybook stories. + * Provides a mocked AuthContext that simulates an authenticated user. + * + * NOTE: We cannot use AuthProvider directly because it requires a real OIDC server. + * AuthProvider from react-oidc-context attempts to connect to the authority URL, + * perform OAuth2/OIDC flows, and validate tokens. Since we're using a fake authority + * in Storybook, the authentication fails and useAuth() returns isAuthenticated: false. + * Instead, we use AuthContext.Provider directly with a mocked auth object. + * + * When any child component calls useAuth(), it uses React's useContext(AuthContext) internally. + * By wrapping with , we provide the mock data to + * that context, so components receive our mockAuth object with isAuthenticated: true. + * + * IMPLEMENTATION NOTE: This component uses createMockAuth() and createMockUser() utilities + * from '../test/utils/mockAuth.ts' instead of manually constructing the auth object. + * This eliminates TypeScript 'any' types, ensures type safety, and reuses the shared + * mock implementation that properly types all required OIDC fields (profile, tokens, events, etc.). + */ +export const MockAuthWrapper = ({ + children, +}: { + children: ReactNode; +}): ReactElement => { + const mockAuth = useMemo( + () => + createMockAuth({ + isAuthenticated: true, + user: createMockUser(), + }), + [], + ); + + return {children}; +}; From a73559aae5aafd7c14c0bb46c4a649a8a8fc7e4d Mon Sep 17 00:00:00 2001 From: Duy Nguyen Date: Thu, 8 Jan 2026 16:54:46 -0500 Subject: [PATCH 02/58] refactor: consolidate duplicated mock token helpers into shared utility for Storybook --- .../src/App.container.stories.tsx | 207 +++++++++++++++--- apps/ui-sharethrift/src/App.stories.tsx | 56 +---- .../shared/apollo-connection.stories.tsx | 59 +---- .../src/test-utils/storybook-decorators.tsx | 64 ++++++ 4 files changed, 247 insertions(+), 139 deletions(-) diff --git a/apps/ui-sharethrift/src/App.container.stories.tsx b/apps/ui-sharethrift/src/App.container.stories.tsx index 673da5413..8a7724ea1 100644 --- a/apps/ui-sharethrift/src/App.container.stories.tsx +++ b/apps/ui-sharethrift/src/App.container.stories.tsx @@ -3,10 +3,65 @@ import { AppContainer } from './App.container.tsx'; import { withMockApolloClient, withMockRouter, - MockUnauthWrapper, } from './test-utils/storybook-decorators.tsx'; -import { AppContainerCurrentUserDocument } from './generated.tsx'; +import { + AppContainerCurrentUserDocument, + ListingsPageContainerGetListingsDocument, + SelectAccountTypeContainerAccountPlansDocument, + SelectAccountTypeCurrentPersonalUserAndCreateIfNotExistsDocument, + UseUserIsAdminDocument, +} from './generated.tsx'; import { MemoryRouter, Route, Routes } from 'react-router-dom'; +import { MockUnauthWrapper } from './test-utils/storybook-mock-auth-wrappers.tsx'; + +const mockListings = [ + { + __typename: 'ItemListing', + id: '1', + title: 'Projector', + description: 'High-quality projector for home and office use', + category: 'Tools & Equipment', + location: 'Toronto, ON', + state: 'Active', + images: ['/assets/item-images/projector.png'], + sharingPeriodStart: '2025-01-01', + sharingPeriodEnd: '2025-12-31', + createdAt: '2025-01-01T00:00:00Z', + updatedAt: '2025-01-01T00:00:00Z', + schemaVersion: '1.0', + version: '1.0', + reports: 0, + sharingHistory: [], + }, + { + __typename: 'ItemListing', + id: '2', + title: 'Umbrella', + description: 'Umbrella in excellent condition', + category: 'Accessories', + location: 'Vancouver, BC', + state: 'Active', + images: ['/assets/item-images/umbrella.png'], + sharingPeriodStart: '2025-02-01', + sharingPeriodEnd: '2025-06-30', + createdAt: '2025-01-15T00:00:00Z', + updatedAt: '2025-01-15T00:00:00Z', + schemaVersion: '1.0', + version: '1.0', + reports: 0, + sharingHistory: [], + }, +]; + +const buildListingsMock = (listings = mockListings) => ({ + request: { query: ListingsPageContainerGetListingsDocument }, + result: { data: { itemListings: listings } }, +}); + +const buildUseUserIsAdminMock = (isAdmin = false) => ({ + request: { query: UseUserIsAdminDocument }, + result: { data: { currentUser: { useUserIsAdmin: isAdmin } } }, +}); const meta: Meta = { title: 'App/AppContainer', @@ -19,26 +74,11 @@ const meta: Meta = { export default meta; type Story = StoryObj; -// Mock for authenticated user who has completed onboarding -const mockAuthenticatedCompletedOnboarding = { - request: { - query: AppContainerCurrentUserDocument, - variables: {}, - }, - result: { - data: { - currentUser: { - __typename: 'PersonalUser' as const, - id: 'user-123', - userType: 'personal-user', - hasCompletedOnboarding: true, - }, - }, - }, -}; - -// Mock for authenticated user who hasn't completed onboarding -const mockAuthenticatedNotCompletedOnboarding = { +// Helper to build a current-user mock +const buildCurrentUserMock = (opts: { + id?: string; + hasCompletedOnboarding?: boolean; +} = {}) => ({ request: { query: AppContainerCurrentUserDocument, variables: {}, @@ -47,19 +87,29 @@ const mockAuthenticatedNotCompletedOnboarding = { data: { currentUserAndCreateIfNotExists: { __typename: 'PersonalUser' as const, - id: 'user-456', + id: opts.id ?? 'user-123', userType: 'personal-user', - hasCompletedOnboarding: false, + hasCompletedOnboarding: opts.hasCompletedOnboarding ?? true, }, }, }, -}; +}); + +// Reusable canned responses +const mockAuthenticatedCompletedOnboarding = buildCurrentUserMock({ + id: 'user-123', + hasCompletedOnboarding: true, +}); +const mockAuthenticatedNotCompletedOnboarding = buildCurrentUserMock({ + id: 'user-456', + hasCompletedOnboarding: false, +}); export const AuthenticatedCompletedOnboarding: Story = { decorators: [withMockApolloClient, withMockRouter('/')], parameters: { apolloClient: { - mocks: [mockAuthenticatedCompletedOnboarding], + mocks: [mockAuthenticatedCompletedOnboarding, buildListingsMock(), buildUseUserIsAdminMock(false)], }, }, }; @@ -68,7 +118,105 @@ export const AuthenticatedNotCompletedOnboarding: Story = { decorators: [withMockApolloClient, withMockRouter('/')], parameters: { apolloClient: { - mocks: [mockAuthenticatedNotCompletedOnboarding], + mocks: [ + mockAuthenticatedNotCompletedOnboarding, + { + request: { + query: + SelectAccountTypeCurrentPersonalUserAndCreateIfNotExistsDocument, + }, + result: { + data: { + currentPersonalUserAndCreateIfNotExists: { + id: 'user-456', + account: { + accountType: 'personal-user', + }, + }, + }, + }, + }, + buildListingsMock(), + buildUseUserIsAdminMock(false), + { + request: { query: SelectAccountTypeContainerAccountPlansDocument }, + result: { + data: { + accountPlans: [ + { + name: 'non-verified-personal', + description: 'Non-Verified Personal', + billingPeriodLength: 0, + billingPeriodUnit: 'month', + billingAmount: 0, + currency: 'USD', + setupFee: 0, + feature: { + activeReservations: 0, + bookmarks: 3, + itemsToShare: 15, + friends: 5, + __typename: 'AccountPlanFeature', + }, + status: null, + cybersourcePlanId: null, + id: '607f1f77bcf86cd799439001', + schemaVersion: '1.0.0', + createdAt: '2023-05-02T10:00:00.000Z', + updatedAt: '2023-05-02T10:00:00.000Z', + __typename: 'AccountPlan', + }, + { + name: 'verified-personal', + description: 'Verified Personal', + billingPeriodLength: 0, + billingPeriodUnit: 'month', + billingAmount: 0, + currency: 'USD', + setupFee: 0, + feature: { + activeReservations: 10, + bookmarks: 10, + itemsToShare: 30, + friends: 10, + __typename: 'AccountPlanFeature', + }, + status: null, + cybersourcePlanId: null, + id: '607f1f77bcf86cd799439002', + schemaVersion: '1.0.0', + createdAt: '2023-05-02T10:00:00.000Z', + updatedAt: '2023-05-02T10:00:00.000Z', + __typename: 'AccountPlan', + }, + { + name: 'verified-personal-plus', + description: 'Verified Personal Plus', + billingPeriodLength: 12, + billingPeriodUnit: 'month', + billingAmount: 4.99, + currency: 'USD', + setupFee: 0, + feature: { + activeReservations: 30, + bookmarks: 30, + itemsToShare: 50, + friends: 30, + __typename: 'AccountPlanFeature', + }, + status: 'active', + cybersourcePlanId: 'cybersource_plan_001', + id: '607f1f77bcf86cd799439000', + schemaVersion: '1.0.0', + createdAt: '2023-05-02T10:00:00.000Z', + updatedAt: '2023-05-02T10:00:00.000Z', + __typename: 'AccountPlan', + }, + ], + }, + }, + }, + ], }, }, }; @@ -88,7 +236,10 @@ export const Unauthenticated: Story = { ], parameters: { apolloClient: { - mocks: [], + mocks: [ + buildListingsMock(), + buildUseUserIsAdminMock(false), + ], }, }, }; diff --git a/apps/ui-sharethrift/src/App.stories.tsx b/apps/ui-sharethrift/src/App.stories.tsx index cf3b50ed4..afc2e06c5 100644 --- a/apps/ui-sharethrift/src/App.stories.tsx +++ b/apps/ui-sharethrift/src/App.stories.tsx @@ -1,46 +1,8 @@ import type { Meta, StoryObj } from '@storybook/react'; import { expect } from 'storybook/test'; import { MemoryRouter } from 'react-router-dom'; -import { AuthProvider } from 'react-oidc-context'; -import { MockedProvider } from '@apollo/client/testing/react'; import { App } from './App.tsx'; - -const mockEnv = { - VITE_FUNCTION_ENDPOINT: 'https://mock-functions.example.com', - VITE_BLOB_STORAGE_CONFIG_URL: 'https://mock-storage.example.com', - VITE_B2C_AUTHORITY: 'https://mock-authority.example.com', - VITE_B2C_CLIENTID: 'mock-client-id', - NODE_ENV: 'development', -}; - -const mockStorage = { - getItem: (key: string) => { - if (key.includes('oidc.user')) { - return JSON.stringify({ - access_token: '', - profile: { sub: 'test-user' }, - }); - } - return null; - }, - setItem: (_key: string, _value: string) => Promise.resolve(), - removeItem: (_key: string) => Promise.resolve(), - clear: () => Promise.resolve(), - key: () => null, - length: 0, - set: (_key: string, _value: unknown) => Promise.resolve(), - get: (_key: string) => Promise.resolve(null), - remove: (_key: string) => Promise.resolve(null), - getAllKeys: () => Promise.resolve([]), -}; - -Object.defineProperty(globalThis, 'sessionStorage', { value: mockStorage, writable: true }); -Object.defineProperty(globalThis, 'localStorage', { value: mockStorage, writable: true }); - -Object.defineProperty(import.meta, 'env', { - value: mockEnv, - writable: true, -}); +import { withAuthDecorator } from './test-utils/storybook-decorators.tsx'; const meta: Meta = { title: 'App/Main Application', @@ -58,21 +20,7 @@ const meta: Meta = { }, }, }, - decorators: [ - (Story) => ( - - - - - - ), - ], + decorators: [withAuthDecorator], } satisfies Meta; export default meta; diff --git a/apps/ui-sharethrift/src/components/shared/apollo-connection.stories.tsx b/apps/ui-sharethrift/src/components/shared/apollo-connection.stories.tsx index dd82024cb..d3d5f23a1 100644 --- a/apps/ui-sharethrift/src/components/shared/apollo-connection.stories.tsx +++ b/apps/ui-sharethrift/src/components/shared/apollo-connection.stories.tsx @@ -1,48 +1,7 @@ import type { Meta, StoryObj } from '@storybook/react'; import { expect, within } from 'storybook/test'; -import { AuthProvider } from 'react-oidc-context'; -import { MemoryRouter } from 'react-router-dom'; import { ApolloConnection } from './apollo-connection.tsx'; - -// Mock environment variables -const mockEnv = { - VITE_FUNCTION_ENDPOINT: 'https://mock-functions.example.com', - VITE_BLOB_STORAGE_CONFIG_URL: 'https://mock-storage.example.com', - VITE_B2C_AUTHORITY: 'https://mock-authority.example.com', - VITE_B2C_CLIENTID: 'mock-client-id', - NODE_ENV: 'development', -}; - -// Mock window.sessionStorage and window.localStorage -const mockStorage = { - getItem: (key: string) => { - if (key.includes('oidc.user')) { - return JSON.stringify({ - access_token: '', - profile: { sub: 'test-user' }, - }); - } - return null; - }, - setItem: (_key: string, _value: string) => Promise.resolve(), - removeItem: (_key: string) => Promise.resolve(), - clear: () => Promise.resolve(), - key: () => null, - length: 0, - set: (_key: string, _value: unknown) => Promise.resolve(), - get: (_key: string) => Promise.resolve(null), - remove: (_key: string) => Promise.resolve(null), - getAllKeys: () => Promise.resolve([]), -}; - -Object.defineProperty(globalThis, 'sessionStorage', { value: mockStorage, writable: true }); -Object.defineProperty(globalThis, 'localStorage', { value: mockStorage, writable: true }); - -// Mock import.meta.env -Object.defineProperty(import.meta, 'env', { - value: mockEnv, - writable: true, -}); +import { withAuthDecorator } from '../../test-utils/storybook-decorators.tsx'; const meta: Meta = { title: 'Components/Shared/Apollo Connection', @@ -56,21 +15,7 @@ const meta: Meta = { }, }, }, - decorators: [ - (Story) => ( - - - - - - ), - ], + decorators: [withAuthDecorator], } satisfies Meta; export default meta; diff --git a/apps/ui-sharethrift/src/test-utils/storybook-decorators.tsx b/apps/ui-sharethrift/src/test-utils/storybook-decorators.tsx index 2763aaa5c..1a002cd2a 100644 --- a/apps/ui-sharethrift/src/test-utils/storybook-decorators.tsx +++ b/apps/ui-sharethrift/src/test-utils/storybook-decorators.tsx @@ -5,6 +5,8 @@ import type { Decorator, StoryContext } from '@storybook/react'; import { MemoryRouter, Route, Routes } from 'react-router-dom'; import { UserIdProvider } from '../components/shared/user-context.tsx'; import { MockAuthWrapper } from './storybook-mock-auth-wrappers.tsx'; +import { AuthProvider } from 'react-oidc-context'; +import { MockedProvider } from '@apollo/client/testing/react'; /** * Reusable Apollo Client decorator for Storybook stories. @@ -96,3 +98,65 @@ export const withMockRouter = ); + +const mockEnv = { + VITE_FUNCTION_ENDPOINT: 'https://mock-functions.example.com', + VITE_BLOB_STORAGE_CONFIG_URL: 'https://mock-storage.example.com', + VITE_B2C_AUTHORITY: 'https://mock-authority.example.com', + VITE_B2C_CLIENTID: 'mock-client-id', + NODE_ENV: 'development', +}; + +const mockStorage = { + getItem: (key: string) => { + if (key.includes('oidc.user')) { + return JSON.stringify({ + access_token: '', + profile: { sub: 'test-user' }, + }); + } + return null; + }, + setItem: () => Promise.resolve(), + removeItem: () => Promise.resolve(), + clear: () => Promise.resolve(), + key: () => null, + length: 0, + set: () => Promise.resolve(), + get: () => Promise.resolve(null), + remove: () => Promise.resolve(null), + getAllKeys: () => Promise.resolve([]), +}; + +// Apply mocks to global environment for stories +Object.defineProperty(globalThis, 'sessionStorage', { + value: mockStorage, + writable: true, +}); +Object.defineProperty(globalThis, 'localStorage', { + value: mockStorage, + writable: true, +}); + +Object.defineProperty(import.meta, 'env', { + value: mockEnv, + writable: true, +}); + +// StoryFn's runtime signature can vary; accept `any` here so the +// decorator works regardless of Storybook's inferred types. +export const withAuthDecorator: Decorator = (Story) => ( + + + + + +); + +export const mockEnvironment = { mockEnv, mockStorage }; From 091a7ec6bdd89377848459a0b57d12772c07dc3c Mon Sep 17 00:00:00 2001 From: Duy Nguyen Date: Fri, 9 Jan 2026 13:28:37 -0500 Subject: [PATCH 03/58] partial fix: reorganize visual stories+hide functional test stories --- apps/ui-sharethrift/src/App.container.stories.tsx | 1 + apps/ui-sharethrift/src/App.stories.tsx | 1 + .../admin-listings-table.container.stories.tsx | 1 + .../stories/admin-listings-table.status-filter.stories.tsx | 2 +- .../stories/admin-listings-table.status-tag.stories.tsx | 2 +- .../stories/admin-listings-table.title-filter.stories.tsx | 2 +- .../stories/admin-listings-table.utils.stories.tsx | 1 + .../admin-users-table/stories/admin-users-card.stories.tsx | 2 +- .../src/components/shared/apollo-client-links.stories.tsx | 1 + .../src/components/shared/apollo-connection.stories.tsx | 1 + .../src/components/shared/stories/auth-landing.stories.tsx | 1 + .../src/contexts/applicant-id-context.stories.tsx | 1 + 12 files changed, 12 insertions(+), 4 deletions(-) diff --git a/apps/ui-sharethrift/src/App.container.stories.tsx b/apps/ui-sharethrift/src/App.container.stories.tsx index 8a7724ea1..8f90c90fc 100644 --- a/apps/ui-sharethrift/src/App.container.stories.tsx +++ b/apps/ui-sharethrift/src/App.container.stories.tsx @@ -69,6 +69,7 @@ const meta: Meta = { parameters: { layout: 'fullscreen', }, + tags: ['!dev'], // not rendered in sidebar - https://storybook.js.org/docs/writing-stories/tags }; export default meta; diff --git a/apps/ui-sharethrift/src/App.stories.tsx b/apps/ui-sharethrift/src/App.stories.tsx index afc2e06c5..aada00970 100644 --- a/apps/ui-sharethrift/src/App.stories.tsx +++ b/apps/ui-sharethrift/src/App.stories.tsx @@ -11,6 +11,7 @@ const meta: Meta = { hasCompletedOnboarding: false, isAuthenticated: false, }, + tags: ['!dev'], // not rendered in sidebar - https://storybook.js.org/docs/writing-stories/tags parameters: { layout: 'fullscreen', docs: { diff --git a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/admin-listings-table.container.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/admin-listings-table.container.stories.tsx index fbe79a1c8..58f46bc7e 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/admin-listings-table.container.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/admin-listings-table.container.stories.tsx @@ -84,6 +84,7 @@ const meta: Meta = { ], }, }, + tags: ['!dev'], // not rendered in sidebar - https://storybook.js.org/docs/writing-stories/tags decorators: [ withMockApolloClient, withMockRouter('/account/admin-dashboard/listings'), diff --git a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.status-filter.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.status-filter.stories.tsx index 8772168a3..9e197332b 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.status-filter.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.status-filter.stories.tsx @@ -3,7 +3,7 @@ import { expect, within, fn, userEvent } from 'storybook/test'; import { StatusFilter } from '../admin-listings-table.status-filter.tsx'; const meta: Meta = { - title: 'Admin/ListingsTable/StatusFilter', + title: 'Components/AdminListingsTable/StatusFilter', component: StatusFilter, parameters: { layout: 'centered', diff --git a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.status-tag.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.status-tag.stories.tsx index 093a82570..a5ded9d2a 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.status-tag.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.status-tag.stories.tsx @@ -3,7 +3,7 @@ import { expect, within } from 'storybook/test'; import { StatusTag } from '../admin-listings-table.status-tag.tsx'; const meta: Meta = { - title: 'Admin/ListingsTable/StatusTag', + title: 'Components/AdminListingsTable/StatusTag', component: StatusTag, parameters: { layout: 'centered', diff --git a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.title-filter.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.title-filter.stories.tsx index 14064cf5a..67f181158 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.title-filter.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.title-filter.stories.tsx @@ -3,7 +3,7 @@ import { expect, within, fn, userEvent } from 'storybook/test'; import { TitleFilter } from '../admin-listings-table.title-filter.tsx'; const meta: Meta = { - title: 'Admin/ListingsTable/TitleFilter', + title: 'Components/AdminListingsTable/TitleFilter', component: TitleFilter, parameters: { layout: 'centered', diff --git a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.utils.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.utils.stories.tsx index 5d06e6871..e2c20dad6 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.utils.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-listings-table/stories/admin-listings-table.utils.stories.tsx @@ -42,6 +42,7 @@ const meta: Meta = { parameters: { layout: 'centered', }, + tags: ['!dev'], // not rendered in sidebar - https://storybook.js.org/docs/writing-stories/tags }; export default meta; diff --git a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-users-table/stories/admin-users-card.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-users-table/stories/admin-users-card.stories.tsx index 9043f200f..ed979d433 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-users-table/stories/admin-users-card.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/account/admin-dashboard/components/admin-users-table/stories/admin-users-card.stories.tsx @@ -51,7 +51,7 @@ const mockUserNoDate: AdminUserData = { }; const meta: Meta = { - title: 'Admin/UsersTable/AdminUsersCard', + title: 'Components/AdminUsers/AdminUsersCard', component: AdminUsersCard, parameters: { layout: 'centered', diff --git a/apps/ui-sharethrift/src/components/shared/apollo-client-links.stories.tsx b/apps/ui-sharethrift/src/components/shared/apollo-client-links.stories.tsx index 23fa7d9dc..681ad194b 100644 --- a/apps/ui-sharethrift/src/components/shared/apollo-client-links.stories.tsx +++ b/apps/ui-sharethrift/src/components/shared/apollo-client-links.stories.tsx @@ -55,6 +55,7 @@ const meta: Meta = { ), ], + tags: ['!dev'], // not rendered in sidebar - https://storybook.js.org/docs/writing-stories/tags } satisfies Meta; export default meta; diff --git a/apps/ui-sharethrift/src/components/shared/apollo-connection.stories.tsx b/apps/ui-sharethrift/src/components/shared/apollo-connection.stories.tsx index d3d5f23a1..f7ca52bc7 100644 --- a/apps/ui-sharethrift/src/components/shared/apollo-connection.stories.tsx +++ b/apps/ui-sharethrift/src/components/shared/apollo-connection.stories.tsx @@ -16,6 +16,7 @@ const meta: Meta = { }, }, decorators: [withAuthDecorator], + tags: ['!dev'], // not rendered in sidebar - https://storybook.js.org/docs/writing-stories/tags } satisfies Meta; export default meta; diff --git a/apps/ui-sharethrift/src/components/shared/stories/auth-landing.stories.tsx b/apps/ui-sharethrift/src/components/shared/stories/auth-landing.stories.tsx index f40e3ccd3..58d1657bb 100644 --- a/apps/ui-sharethrift/src/components/shared/stories/auth-landing.stories.tsx +++ b/apps/ui-sharethrift/src/components/shared/stories/auth-landing.stories.tsx @@ -16,6 +16,7 @@ const meta: Meta = { ), ], + tags: ['!dev'], // not rendered in sidebar - https://storybook.js.org/docs/writing-stories/tags }; export default meta; diff --git a/apps/ui-sharethrift/src/contexts/applicant-id-context.stories.tsx b/apps/ui-sharethrift/src/contexts/applicant-id-context.stories.tsx index bb4fecf7a..1e841f696 100644 --- a/apps/ui-sharethrift/src/contexts/applicant-id-context.stories.tsx +++ b/apps/ui-sharethrift/src/contexts/applicant-id-context.stories.tsx @@ -41,6 +41,7 @@ const meta: Meta = { ), ], + tags: ['!dev'], // not rendered in sidebar - https://storybook.js.org/docs/writing-stories/tags }; export default meta; From 4e60379a8869eef6e6aafe84b092fb83e1ace7ac Mon Sep 17 00:00:00 2001 From: Duy Nguyen Date: Fri, 9 Jan 2026 16:34:38 -0500 Subject: [PATCH 04/58] partial fix 2: reorganize visual stories+hide functional test stories --- apps/ui-sharethrift/src/App.tsx | 2 +- .../components/status-tag-class.stories.tsx | 1 + .../stories/requests-status-helpers.stories.tsx | 2 ++ .../login}/login-selection.stories.tsx | 10 +++++----- .../{shared => layouts/login}/login-selection.tsx | 0 .../payment/billing-address-form-items.stories.tsx | 2 +- .../shared/payment/country-change-utils.stories.tsx | 1 + .../shared/payment/country-form-item.stories.tsx | 2 +- .../components/shared/payment/payment-form.stories.tsx | 2 +- .../payment/payment-token-form-items.stories.tsx | 2 +- .../payment/state-province-form-item.stories.tsx | 2 +- .../stories/apollo-manual-merge-cache-fix.stories.tsx | 1 + .../shared/stories/auth-redirect-admin.stories.tsx | 1 + .../shared/stories/auth-redirect-user.stories.tsx | 1 + .../shared/stories/handle-logout.stories.tsx | 1 + .../shared/stories/local-storage.stories.tsx | 1 + 16 files changed, 20 insertions(+), 11 deletions(-) rename apps/ui-sharethrift/src/components/{shared/stories => layouts/login}/login-selection.stories.tsx (93%) rename apps/ui-sharethrift/src/components/{shared => layouts/login}/login-selection.tsx (100%) diff --git a/apps/ui-sharethrift/src/App.tsx b/apps/ui-sharethrift/src/App.tsx index 03a14c309..be7071c4f 100644 --- a/apps/ui-sharethrift/src/App.tsx +++ b/apps/ui-sharethrift/src/App.tsx @@ -1,11 +1,11 @@ import { Route, Routes } from 'react-router-dom'; import { HomeRoutes } from './components/layouts/home/index.tsx'; import { SignupRoutes } from './components/layouts/signup/Index.tsx'; -import { LoginSelection } from './components/shared/login-selection.tsx'; import { AuthRedirectAdmin } from './components/shared/auth-redirect-admin.tsx'; import { AuthRedirectUser } from './components/shared/auth-redirect-user.tsx'; import { RequireAuth } from './components/shared/require-auth.tsx'; import { useOnboardingRedirect } from './components/shared/use-has-completed-onboarding-check.ts'; +import { LoginSelection } from './components/layouts/login/login-selection.tsx'; const signupSection = ( diff --git a/apps/ui-sharethrift/src/components/layouts/home/my-listings/components/status-tag-class.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/my-listings/components/status-tag-class.stories.tsx index a6fbe6c0c..1bb94c073 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/my-listings/components/status-tag-class.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/my-listings/components/status-tag-class.stories.tsx @@ -52,6 +52,7 @@ const meta: Meta = { parameters: { layout: 'centered', }, + tags: ['!dev'], // not rendered in sidebar - https://storybook.js.org/docs/writing-stories/tags }; export default meta; diff --git a/apps/ui-sharethrift/src/components/layouts/home/my-listings/stories/requests-status-helpers.stories.tsx b/apps/ui-sharethrift/src/components/layouts/home/my-listings/stories/requests-status-helpers.stories.tsx index b8737693c..051fdffef 100644 --- a/apps/ui-sharethrift/src/components/layouts/home/my-listings/stories/requests-status-helpers.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/home/my-listings/stories/requests-status-helpers.stories.tsx @@ -37,6 +37,8 @@ const meta: Meta = { parameters: { layout: 'centered', }, + tags: ['!dev'], // not rendered in sidebar - https://storybook.js.org/docs/writing-stories/tags + }; export default meta; diff --git a/apps/ui-sharethrift/src/components/shared/stories/login-selection.stories.tsx b/apps/ui-sharethrift/src/components/layouts/login/login-selection.stories.tsx similarity index 93% rename from apps/ui-sharethrift/src/components/shared/stories/login-selection.stories.tsx rename to apps/ui-sharethrift/src/components/layouts/login/login-selection.stories.tsx index 658633182..46b965fde 100644 --- a/apps/ui-sharethrift/src/components/shared/stories/login-selection.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/login/login-selection.stories.tsx @@ -1,22 +1,22 @@ import type { Meta, StoryObj } from '@storybook/react'; import { expect, within, userEvent } from 'storybook/test'; import { MemoryRouter } from 'react-router-dom'; -import { LoginSelection } from '../login-selection.tsx'; -import { MockAuthWrapper } from '../../../test-utils/storybook-mock-auth-wrappers.tsx'; +import { MockUnauthWrapper } from '../../../test-utils/storybook-mock-auth-wrappers.tsx'; +import { LoginSelection } from './login-selection.tsx'; const meta: Meta = { - title: 'Shared/LoginSelection', + title: 'Pages/LoginSelection', component: LoginSelection, parameters: { layout: 'fullscreen', }, decorators: [ (Story) => ( - + - + ), ], }; diff --git a/apps/ui-sharethrift/src/components/shared/login-selection.tsx b/apps/ui-sharethrift/src/components/layouts/login/login-selection.tsx similarity index 100% rename from apps/ui-sharethrift/src/components/shared/login-selection.tsx rename to apps/ui-sharethrift/src/components/layouts/login/login-selection.tsx diff --git a/apps/ui-sharethrift/src/components/shared/payment/billing-address-form-items.stories.tsx b/apps/ui-sharethrift/src/components/shared/payment/billing-address-form-items.stories.tsx index c97afa2ab..1d20d5060 100644 --- a/apps/ui-sharethrift/src/components/shared/payment/billing-address-form-items.stories.tsx +++ b/apps/ui-sharethrift/src/components/shared/payment/billing-address-form-items.stories.tsx @@ -4,7 +4,7 @@ import { Form } from 'antd'; import { countriesMockData } from '../../layouts/signup/components/countries-mock-data.ts'; const meta: Meta = { - title: 'Shared/Payment/BillingAddressFormItems', + title: 'Components/Shared/Payment/BillingAddressFormItems', component: BillingAddressFormItems, parameters: { layout: 'padded', diff --git a/apps/ui-sharethrift/src/components/shared/payment/country-change-utils.stories.tsx b/apps/ui-sharethrift/src/components/shared/payment/country-change-utils.stories.tsx index 7a6d41125..3b7e75dd1 100644 --- a/apps/ui-sharethrift/src/components/shared/payment/country-change-utils.stories.tsx +++ b/apps/ui-sharethrift/src/components/shared/payment/country-change-utils.stories.tsx @@ -74,6 +74,7 @@ const meta: Meta = { parameters: { layout: 'padded', }, + tags: ['!dev'], // not rendered in sidebar - https://storybook.js.org/docs/writing-stories/tags }; export default meta; diff --git a/apps/ui-sharethrift/src/components/shared/payment/country-form-item.stories.tsx b/apps/ui-sharethrift/src/components/shared/payment/country-form-item.stories.tsx index 4263d7a23..f95d5902a 100644 --- a/apps/ui-sharethrift/src/components/shared/payment/country-form-item.stories.tsx +++ b/apps/ui-sharethrift/src/components/shared/payment/country-form-item.stories.tsx @@ -5,7 +5,7 @@ import { countriesMockData } from '../../layouts/signup/components/countries-moc import { CountryFormItem } from './country-form-item.tsx'; const meta: Meta = { - title: 'Shared/Payment/CountryFormItem', + title: 'Components/Shared/Payment/CountryFormItem', component: CountryFormItem, parameters: { layout: 'padded', diff --git a/apps/ui-sharethrift/src/components/shared/payment/payment-form.stories.tsx b/apps/ui-sharethrift/src/components/shared/payment/payment-form.stories.tsx index 63997707f..afcf80baf 100644 --- a/apps/ui-sharethrift/src/components/shared/payment/payment-form.stories.tsx +++ b/apps/ui-sharethrift/src/components/shared/payment/payment-form.stories.tsx @@ -9,7 +9,7 @@ import { expect, within, userEvent, waitFor } from 'storybook/test'; const { Text } = Typography; const meta: Meta = { - title: 'Shared/Payment/PaymentForm', + title: 'Components/Shared/Payment/PaymentForm', component: PaymentForm, parameters: { layout: 'padded', diff --git a/apps/ui-sharethrift/src/components/shared/payment/payment-token-form-items.stories.tsx b/apps/ui-sharethrift/src/components/shared/payment/payment-token-form-items.stories.tsx index 764ecc969..ab2087cb4 100644 --- a/apps/ui-sharethrift/src/components/shared/payment/payment-token-form-items.stories.tsx +++ b/apps/ui-sharethrift/src/components/shared/payment/payment-token-form-items.stories.tsx @@ -4,7 +4,7 @@ import { Form } from 'antd'; import { useState } from 'react'; const meta: Meta = { - title: 'Shared/Payment/PaymentTokenFormItems', + title: 'Components/Shared/Payment/PaymentTokenFormItems', component: PaymentTokenFormItems, parameters: { layout: 'padded', diff --git a/apps/ui-sharethrift/src/components/shared/payment/state-province-form-item.stories.tsx b/apps/ui-sharethrift/src/components/shared/payment/state-province-form-item.stories.tsx index 5bc1bfb48..0b04642c9 100644 --- a/apps/ui-sharethrift/src/components/shared/payment/state-province-form-item.stories.tsx +++ b/apps/ui-sharethrift/src/components/shared/payment/state-province-form-item.stories.tsx @@ -7,7 +7,7 @@ const usStates = countriesMockData.find(c => c.countryCode === 'US')?.states || const caStates = countriesMockData.find(c => c.countryCode === 'CA')?.states || []; const meta: Meta = { - title: 'Shared/Payment/StateProvinceFormItem', + title: 'Components/Shared/Payment/StateProvinceFormItem', component: StateProvinceFormItem, parameters: { layout: 'padded', diff --git a/apps/ui-sharethrift/src/components/shared/stories/apollo-manual-merge-cache-fix.stories.tsx b/apps/ui-sharethrift/src/components/shared/stories/apollo-manual-merge-cache-fix.stories.tsx index 3b8699949..eba27255c 100644 --- a/apps/ui-sharethrift/src/components/shared/stories/apollo-manual-merge-cache-fix.stories.tsx +++ b/apps/ui-sharethrift/src/components/shared/stories/apollo-manual-merge-cache-fix.stories.tsx @@ -20,6 +20,7 @@ const meta: Meta = { parameters: { layout: 'centered', }, + tags: ['!dev'], // not rendered in sidebar - https://storybook.js.org/docs/writing-stories/tags }; export default meta; diff --git a/apps/ui-sharethrift/src/components/shared/stories/auth-redirect-admin.stories.tsx b/apps/ui-sharethrift/src/components/shared/stories/auth-redirect-admin.stories.tsx index 7633bb508..75747b02e 100644 --- a/apps/ui-sharethrift/src/components/shared/stories/auth-redirect-admin.stories.tsx +++ b/apps/ui-sharethrift/src/components/shared/stories/auth-redirect-admin.stories.tsx @@ -11,6 +11,7 @@ const meta: Meta = { parameters: { layout: 'fullscreen', }, + tags: ['!dev'], // not rendered in sidebar - https://storybook.js.org/docs/writing-stories/tags }; export default meta; diff --git a/apps/ui-sharethrift/src/components/shared/stories/auth-redirect-user.stories.tsx b/apps/ui-sharethrift/src/components/shared/stories/auth-redirect-user.stories.tsx index 12816e432..3223da015 100644 --- a/apps/ui-sharethrift/src/components/shared/stories/auth-redirect-user.stories.tsx +++ b/apps/ui-sharethrift/src/components/shared/stories/auth-redirect-user.stories.tsx @@ -19,6 +19,7 @@ const meta: Meta = { ), ], + tags: ['!dev'], // not rendered in sidebar - https://storybook.js.org/docs/writing-stories/tags }; export default meta; diff --git a/apps/ui-sharethrift/src/components/shared/stories/handle-logout.stories.tsx b/apps/ui-sharethrift/src/components/shared/stories/handle-logout.stories.tsx index f7d2f40c8..eb1a72f0d 100644 --- a/apps/ui-sharethrift/src/components/shared/stories/handle-logout.stories.tsx +++ b/apps/ui-sharethrift/src/components/shared/stories/handle-logout.stories.tsx @@ -18,6 +18,7 @@ const meta: Meta = { parameters: { layout: 'centered', }, + tags: ['!dev'], // not rendered in sidebar - https://storybook.js.org/docs/writing-stories/tags }; export default meta; diff --git a/apps/ui-sharethrift/src/components/shared/stories/local-storage.stories.tsx b/apps/ui-sharethrift/src/components/shared/stories/local-storage.stories.tsx index fa77b0369..7546ba026 100644 --- a/apps/ui-sharethrift/src/components/shared/stories/local-storage.stories.tsx +++ b/apps/ui-sharethrift/src/components/shared/stories/local-storage.stories.tsx @@ -17,6 +17,7 @@ const meta: Meta = { parameters: { layout: 'centered', }, + tags: ['!dev'], // not rendered in sidebar - https://storybook.js.org/docs/writing-stories/tags }; export default meta; From ce05554d6d7719d827520719dbe4adfd3afd9831 Mon Sep 17 00:00:00 2001 From: Duy Nguyen Date: Fri, 9 Jan 2026 16:38:25 -0500 Subject: [PATCH 05/58] refactor: simplify dependency array in useEffect hooks for RequireAuthAdmin component --- .../src/components/shared/require-auth-admin.tsx | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/apps/ui-sharethrift/src/components/shared/require-auth-admin.tsx b/apps/ui-sharethrift/src/components/shared/require-auth-admin.tsx index c65060dbd..7cb1c0252 100644 --- a/apps/ui-sharethrift/src/components/shared/require-auth-admin.tsx +++ b/apps/ui-sharethrift/src/components/shared/require-auth-admin.tsx @@ -33,15 +33,7 @@ export const RequireAuthAdmin: React.FC = (props) => { auth.signinRedirect(); } - }, [ - auth.isAuthenticated, - auth.activeNavigator, - auth.isLoading, - auth.signinRedirect, - auth.error, - props.forceLogin, - redirectPath, - ]); + }, [auth.isAuthenticated, auth.activeNavigator, auth.isLoading, auth.signinRedirect, auth.error, props.forceLogin, auth]); // automatically refresh token useEffect(() => { @@ -50,7 +42,7 @@ export const RequireAuthAdmin: React.FC = (props) => { redirect_uri: VITE_B2C_REDIRECT_URI ?? '', }); }); - }, [auth.events, auth.signinSilent]); + }, [auth, auth.events, auth.signinSilent]); // Check authentication first if (!auth.isAuthenticated) { From 56240115f7ae58dcff7acd41b0eff08eb81cf394 Mon Sep 17 00:00:00 2001 From: Duy Nguyen Date: Mon, 12 Jan 2026 16:06:16 -0500 Subject: [PATCH 06/58] refactor: update Storybook stories to use data-testid for Sign Up button --- .../layouts/login/login-selection.stories.tsx | 64 ++++++++++++------- .../layouts/login/login-selection.tsx | 1 + 2 files changed, 41 insertions(+), 24 deletions(-) diff --git a/apps/ui-sharethrift/src/components/layouts/login/login-selection.stories.tsx b/apps/ui-sharethrift/src/components/layouts/login/login-selection.stories.tsx index 46b965fde..bbb681f3b 100644 --- a/apps/ui-sharethrift/src/components/layouts/login/login-selection.stories.tsx +++ b/apps/ui-sharethrift/src/components/layouts/login/login-selection.stories.tsx @@ -27,17 +27,21 @@ type Story = StoryObj; export const Default: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); - + const emailInput = canvas.getByLabelText('Email'); await expect(emailInput).toBeInTheDocument(); - + const passwordInput = canvas.getByLabelText('Password'); await expect(passwordInput).toBeInTheDocument(); - - const personalLoginButton = canvas.getByRole('button', { name: /Personal Login/i }); + + const personalLoginButton = canvas.getByRole('button', { + name: /Personal Login/i, + }); await expect(personalLoginButton).toBeInTheDocument(); - - const adminLoginButton = canvas.getByRole('button', { name: /Admin Login/i }); + + const adminLoginButton = canvas.getByRole('button', { + name: /Admin Login/i, + }); await expect(adminLoginButton).toBeInTheDocument(); }, }; @@ -45,13 +49,15 @@ export const Default: Story = { export const WithEnvironment: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); - - const signUpButton = canvas.getByRole('button', { name: /Sign Up/i }); + + const signUpButton = canvasElement.querySelector( + '[data-testid="sign-up-button"]', + ); // Using data-testid selector for there are multiple buttons with same name "Sign Up" await expect(signUpButton).toBeInTheDocument(); - + const backLink = canvas.getByRole('button', { name: /Back to Home/i }); await expect(backLink).toBeInTheDocument(); - + const forgotLink = canvas.getByRole('button', { name: /Forgot password/i }); await expect(forgotLink).toBeInTheDocument(); }, @@ -60,13 +66,13 @@ export const WithEnvironment: Story = { export const FillLoginForm: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); - + const emailInput = canvas.getByLabelText('Email'); await userEvent.type(emailInput, 'test@example.com'); - + const passwordInput = canvas.getByLabelText('Password'); await userEvent.type(passwordInput, 'password123'); - + await expect(emailInput).toHaveValue('test@example.com'); }, }; @@ -74,7 +80,7 @@ export const FillLoginForm: Story = { export const ClickBackToHome: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); - + const backLink = canvas.getByRole('button', { name: /Back to Home/i }); await userEvent.click(backLink); }, @@ -83,7 +89,7 @@ export const ClickBackToHome: Story = { export const ClickForgotPassword: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); - + const forgotLink = canvas.getByRole('button', { name: /Forgot password/i }); await userEvent.click(forgotLink); }, @@ -91,20 +97,28 @@ export const ClickForgotPassword: Story = { export const ClickSignUp: Story = { play: async ({ canvasElement }) => { - const canvas = within(canvasElement); - - const signUpButton = canvas.getByRole('button', { name: /Sign Up/i }); - await userEvent.click(signUpButton); + const signUpButton = canvasElement.querySelector( + '[data-testid="sign-up-button"]', + ); + // otherwise fails with "TypeError: Cannot read properties of null (reading 'click')" + if (signUpButton) { + await userEvent.click(signUpButton); + } else { + // fail the test if the button is not found + throw new Error('Sign Up button not found'); + } }, }; export const SubmitFormValidation: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); - - const personalLoginButton = canvas.getByRole('button', { name: /Personal Login/i }); + + const personalLoginButton = canvas.getByRole('button', { + name: /Personal Login/i, + }); await userEvent.click(personalLoginButton); - + await expect(personalLoginButton).toBeInTheDocument(); }, }; @@ -112,8 +126,10 @@ export const SubmitFormValidation: Story = { export const ClickAdminLogin: Story = { play: async ({ canvasElement }) => { const canvas = within(canvasElement); - - const adminLoginButton = canvas.getByRole('button', { name: /Admin Login/i }); + + const adminLoginButton = canvas.getByRole('button', { + name: /Admin Login/i, + }); await expect(adminLoginButton).toBeInTheDocument(); await expect(adminLoginButton).toBeEnabled(); }, diff --git a/apps/ui-sharethrift/src/components/layouts/login/login-selection.tsx b/apps/ui-sharethrift/src/components/layouts/login/login-selection.tsx index d62d75a88..401a205e6 100644 --- a/apps/ui-sharethrift/src/components/layouts/login/login-selection.tsx +++ b/apps/ui-sharethrift/src/components/layouts/login/login-selection.tsx @@ -244,6 +244,7 @@ export const LoginSelection: React.FC = () => {