Fix storybook tests (#5487)
Fixes #5486 --------- Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com> Co-authored-by: v1b3m <vibenjamin6@gmail.com> Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@ -1,12 +1,64 @@
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import {
|
||||
createMemoryRouter,
|
||||
createRoutesFromElements,
|
||||
Outlet,
|
||||
Route,
|
||||
RouterProvider,
|
||||
} from 'react-router-dom';
|
||||
import { Decorator } from '@storybook/react';
|
||||
|
||||
import {
|
||||
computeLocation,
|
||||
isRouteParams,
|
||||
} from '~/testing/decorators/PageDecorator';
|
||||
|
||||
import { ComponentStorybookLayout } from '../ComponentStorybookLayout';
|
||||
|
||||
export const ComponentWithRouterDecorator: Decorator = (Story) => (
|
||||
interface StrictArgs {
|
||||
[name: string]: unknown;
|
||||
}
|
||||
|
||||
const Providers = () => (
|
||||
<ComponentStorybookLayout>
|
||||
<MemoryRouter>
|
||||
<Story />
|
||||
</MemoryRouter>
|
||||
<Outlet />
|
||||
</ComponentStorybookLayout>
|
||||
);
|
||||
|
||||
const createRouter = ({
|
||||
Story,
|
||||
args,
|
||||
initialEntries,
|
||||
initialIndex,
|
||||
}: {
|
||||
Story: () => JSX.Element;
|
||||
args: StrictArgs;
|
||||
initialEntries?: {
|
||||
pathname: string;
|
||||
}[];
|
||||
initialIndex?: number;
|
||||
}) =>
|
||||
createMemoryRouter(
|
||||
createRoutesFromElements(
|
||||
<Route element={<Providers />}>
|
||||
<Route path={(args.routePath as string) ?? '*'} element={<Story />} />
|
||||
</Route>,
|
||||
),
|
||||
{ initialEntries, initialIndex },
|
||||
);
|
||||
|
||||
export const ComponentWithRouterDecorator: Decorator = (Story, { args }) => {
|
||||
return (
|
||||
<RouterProvider
|
||||
router={createRouter({
|
||||
Story,
|
||||
args,
|
||||
initialEntries:
|
||||
args.routePath &&
|
||||
typeof args.routePath === 'string' &&
|
||||
(args.routeParams === undefined || isRouteParams(args.routeParams))
|
||||
? [computeLocation(args.routePath, args.routeParams)]
|
||||
: [{ pathname: '/' }],
|
||||
})}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@ -1,5 +1,11 @@
|
||||
import { HelmetProvider } from 'react-helmet-async';
|
||||
import { MemoryRouter, Route, Routes } from 'react-router-dom';
|
||||
import {
|
||||
createMemoryRouter,
|
||||
createRoutesFromElements,
|
||||
Outlet,
|
||||
Route,
|
||||
RouterProvider,
|
||||
} from 'react-router-dom';
|
||||
import { ApolloProvider } from '@apollo/client';
|
||||
import { loadDevMessages } from '@apollo/client/dev';
|
||||
import { Decorator } from '@storybook/react';
|
||||
@ -23,15 +29,26 @@ export type PageDecoratorArgs = {
|
||||
additionalRoutes?: string[];
|
||||
};
|
||||
|
||||
type RouteParams = {
|
||||
export type RouteParams = {
|
||||
[param: string]: string;
|
||||
};
|
||||
|
||||
const computeLocation = (routePath: string, routeParams: RouteParams) => {
|
||||
export const isRouteParams = (obj: any): obj is RouteParams => {
|
||||
if (typeof obj !== 'object' || obj === null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Object.keys(obj).every((key) => typeof obj[key] === 'string');
|
||||
};
|
||||
|
||||
export const computeLocation = (
|
||||
routePath: string,
|
||||
routeParams?: RouteParams,
|
||||
) => {
|
||||
return {
|
||||
pathname: routePath.replace(
|
||||
/:(\w+)/g,
|
||||
(paramName) => routeParams[paramName] ?? '',
|
||||
(paramName) => routeParams?.[paramName] ?? '',
|
||||
),
|
||||
};
|
||||
};
|
||||
@ -42,11 +59,7 @@ const ApolloStorybookDevLogEffect = () => {
|
||||
return <></>;
|
||||
};
|
||||
|
||||
export const PageDecorator: Decorator<{
|
||||
routePath: string;
|
||||
routeParams: RouteParams;
|
||||
additionalRoutes?: string[];
|
||||
}> = (Story, { args }) => {
|
||||
const Providers = () => {
|
||||
return (
|
||||
<RecoilRoot>
|
||||
<ApolloProvider client={mockedApolloClient}>
|
||||
@ -56,32 +69,15 @@ export const PageDecorator: Decorator<{
|
||||
<UserProvider>
|
||||
<ClientConfigProviderEffect />
|
||||
<ClientConfigProvider>
|
||||
<MemoryRouter
|
||||
initialEntries={[
|
||||
computeLocation(args.routePath, args.routeParams),
|
||||
]}
|
||||
>
|
||||
<FullHeightStorybookLayout>
|
||||
<HelmetProvider>
|
||||
<SnackBarProviderScope snackBarManagerScopeId="snack-bar-manager">
|
||||
<ObjectMetadataItemsProvider>
|
||||
<Routes>
|
||||
<Route element={<DefaultLayout />}>
|
||||
<Route path={args.routePath} element={<Story />} />
|
||||
{args.additionalRoutes?.map((route) => (
|
||||
<Route
|
||||
key={route}
|
||||
path={route}
|
||||
element={<div>Navigated to {route}</div>}
|
||||
/>
|
||||
))}
|
||||
</Route>
|
||||
</Routes>
|
||||
</ObjectMetadataItemsProvider>
|
||||
</SnackBarProviderScope>
|
||||
</HelmetProvider>
|
||||
</FullHeightStorybookLayout>
|
||||
</MemoryRouter>
|
||||
<FullHeightStorybookLayout>
|
||||
<HelmetProvider>
|
||||
<SnackBarProviderScope snackBarManagerScopeId="snack-bar-manager">
|
||||
<ObjectMetadataItemsProvider>
|
||||
<Outlet />
|
||||
</ObjectMetadataItemsProvider>
|
||||
</SnackBarProviderScope>
|
||||
</HelmetProvider>
|
||||
</FullHeightStorybookLayout>
|
||||
</ClientConfigProvider>
|
||||
</UserProvider>
|
||||
</ApolloMetadataClientMockedProvider>
|
||||
@ -89,3 +85,54 @@ export const PageDecorator: Decorator<{
|
||||
</RecoilRoot>
|
||||
);
|
||||
};
|
||||
|
||||
const createRouter = ({
|
||||
Story,
|
||||
args,
|
||||
initialEntries,
|
||||
initialIndex,
|
||||
}: {
|
||||
Story: () => JSX.Element;
|
||||
args: {
|
||||
routePath: string;
|
||||
routeParams: RouteParams;
|
||||
additionalRoutes?: string[] | undefined;
|
||||
};
|
||||
initialEntries?: {
|
||||
pathname: string;
|
||||
}[];
|
||||
initialIndex?: number;
|
||||
}) =>
|
||||
createMemoryRouter(
|
||||
createRoutesFromElements(
|
||||
<Route element={<Providers />}>
|
||||
<Route element={<DefaultLayout />}>
|
||||
<Route path={args.routePath} element={<Story />} />
|
||||
{args.additionalRoutes?.map((route) => (
|
||||
<Route
|
||||
key={route}
|
||||
path={route}
|
||||
element={<div>Navigated to {route}</div>}
|
||||
/>
|
||||
))}
|
||||
</Route>
|
||||
</Route>,
|
||||
),
|
||||
{ initialEntries, initialIndex },
|
||||
);
|
||||
|
||||
export const PageDecorator: Decorator<{
|
||||
routePath: string;
|
||||
routeParams: RouteParams;
|
||||
additionalRoutes?: string[];
|
||||
}> = (Story, { args }) => {
|
||||
return (
|
||||
<RouterProvider
|
||||
router={createRouter({
|
||||
Story,
|
||||
args,
|
||||
initialEntries: [computeLocation(args.routePath, args.routeParams)],
|
||||
})}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -49,6 +49,7 @@ const customObjectMetadataItemEdge: ObjectEdge = {
|
||||
isCustom: false,
|
||||
isActive: true,
|
||||
isSystem: true,
|
||||
options: null,
|
||||
isNullable: true,
|
||||
createdAt: '2024-04-08T12:48:49.538Z',
|
||||
updatedAt: '2024-04-08T12:48:49.538Z',
|
||||
@ -93,6 +94,7 @@ const customObjectMetadataItemEdge: ObjectEdge = {
|
||||
nameSingular: 'viewField',
|
||||
namePlural: 'viewFields',
|
||||
isSystem: true,
|
||||
isRemote: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -110,6 +112,7 @@ const customObjectMetadataItemEdge: ObjectEdge = {
|
||||
isCustom: false,
|
||||
isActive: true,
|
||||
isSystem: true,
|
||||
options: null,
|
||||
isNullable: false,
|
||||
createdAt: '2024-04-08T12:48:49.538Z',
|
||||
updatedAt: '2024-04-08T12:48:49.538Z',
|
||||
@ -132,6 +135,7 @@ const customObjectMetadataItemEdge: ObjectEdge = {
|
||||
isCustom: false,
|
||||
isActive: true,
|
||||
isSystem: true,
|
||||
options: null,
|
||||
isNullable: true,
|
||||
createdAt: '2024-04-08T12:48:49.538Z',
|
||||
updatedAt: '2024-04-08T12:48:49.538Z',
|
||||
@ -154,6 +158,7 @@ const customObjectMetadataItemEdge: ObjectEdge = {
|
||||
isCustom: false,
|
||||
isActive: true,
|
||||
isSystem: true,
|
||||
options: null,
|
||||
isNullable: false,
|
||||
createdAt: '2024-04-08T12:48:49.538Z',
|
||||
updatedAt: '2024-04-08T12:48:49.538Z',
|
||||
@ -176,6 +181,7 @@ const customObjectMetadataItemEdge: ObjectEdge = {
|
||||
isCustom: false,
|
||||
isActive: true,
|
||||
isSystem: true,
|
||||
options: null,
|
||||
isNullable: false,
|
||||
createdAt: '2024-04-08T12:48:49.538Z',
|
||||
updatedAt: '2024-04-08T12:48:49.538Z',
|
||||
@ -198,6 +204,7 @@ const customObjectMetadataItemEdge: ObjectEdge = {
|
||||
isCustom: false,
|
||||
isActive: true,
|
||||
isSystem: true,
|
||||
options: null,
|
||||
isNullable: false,
|
||||
createdAt: '2024-04-08T12:48:49.538Z',
|
||||
updatedAt: '2024-04-08T12:48:49.538Z',
|
||||
@ -220,6 +227,7 @@ const customObjectMetadataItemEdge: ObjectEdge = {
|
||||
isCustom: false,
|
||||
isActive: true,
|
||||
isSystem: true,
|
||||
options: null,
|
||||
isNullable: false,
|
||||
createdAt: '2024-04-08T12:48:49.538Z',
|
||||
updatedAt: '2024-04-08T12:48:49.538Z',
|
||||
|
||||
@ -0,0 +1,104 @@
|
||||
import {
|
||||
TimelineCalendarEvent,
|
||||
TimelineCalendarEventVisibility,
|
||||
} from '~/generated-metadata/graphql';
|
||||
|
||||
export const mockedTimelineCalendarEvents: TimelineCalendarEvent[] = [
|
||||
{
|
||||
__typename: 'TimelineCalendarEvent',
|
||||
id: '20202020-2e3f-45a2-ab16-b580ff4f83e7',
|
||||
title: 'Jane',
|
||||
description: 'Tests techniques',
|
||||
location: '',
|
||||
startsAt: '2024-05-16T12:00:00.000Z',
|
||||
endsAt: '2024-05-16T13:00:00.000Z',
|
||||
conferenceLink: {
|
||||
url: 'https://meet.google.com/xxx-xxx-xxx',
|
||||
label: 'Rejoindre la visio',
|
||||
},
|
||||
conferenceSolution: 'GOOGLE_MEET',
|
||||
isCanceled: false,
|
||||
visibility: TimelineCalendarEventVisibility.ShareEverything,
|
||||
isFullDay: false,
|
||||
participants: [
|
||||
{
|
||||
__typename: 'TimelineCalendarEventParticipant',
|
||||
personId: null,
|
||||
workspaceMemberId: '20202020-78c5-4cbb-87a8-f9cd3ad4d8af',
|
||||
firstName: 'Tim',
|
||||
lastName: 'Apple',
|
||||
displayName: 'Tim',
|
||||
avatarUrl: '',
|
||||
handle: 'tim@apple.dev',
|
||||
},
|
||||
{
|
||||
__typename: 'TimelineCalendarEventParticipant',
|
||||
personId: null,
|
||||
workspaceMemberId: '20202020-3cf7-453e-a5f4-28f8412e70f0',
|
||||
firstName: 'Jane',
|
||||
lastName: 'Doe',
|
||||
displayName: 'Jane',
|
||||
avatarUrl: '',
|
||||
handle: 'jane@apple.dev',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
__typename: 'TimelineCalendarEvent',
|
||||
id: '20202020-1020-42d6-8444-541f5e57a7e5',
|
||||
title: '',
|
||||
description: '',
|
||||
location: '',
|
||||
startsAt: '2024-05-08T12:00:00.000Z',
|
||||
endsAt: '2024-05-08T12:25:00.000Z',
|
||||
isFullDay: false,
|
||||
conferenceLink: {
|
||||
url: 'https://meet.google.com/xxx-xxx-xxx',
|
||||
label: 'Rejoindre la visio',
|
||||
},
|
||||
conferenceSolution: 'GOOGLE_MEET',
|
||||
isCanceled: false,
|
||||
visibility: TimelineCalendarEventVisibility.Metadata,
|
||||
participants: [
|
||||
{
|
||||
__typename: 'TimelineCalendarEventParticipant',
|
||||
personId: null,
|
||||
workspaceMemberId: '20202020-78c5-4cbb-87a8-f9cd3ad4d8af',
|
||||
firstName: 'Tim',
|
||||
lastName: 'Apple',
|
||||
displayName: 'Tim',
|
||||
avatarUrl: '',
|
||||
handle: 'tim@apple.dev',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
__typename: 'TimelineCalendarEvent',
|
||||
id: '20202020-fa61-4d82-b47f-90cca16514e3',
|
||||
title: '',
|
||||
description: '',
|
||||
location: '',
|
||||
startsAt: '2024-05-06T12:00:00.000Z',
|
||||
endsAt: '2024-05-06T12:25:00.000Z',
|
||||
isFullDay: false,
|
||||
conferenceLink: {
|
||||
url: 'https://meet.google.com/xxx-xxx-xxx',
|
||||
label: 'Rejoindre la visio',
|
||||
},
|
||||
conferenceSolution: 'GOOGLE_MEET',
|
||||
isCanceled: false,
|
||||
visibility: TimelineCalendarEventVisibility.Metadata,
|
||||
participants: [
|
||||
{
|
||||
__typename: 'TimelineCalendarEventParticipant',
|
||||
personId: null,
|
||||
workspaceMemberId: '20202020-78c5-4cbb-87a8-f9cd3ad4d8af',
|
||||
firstName: 'Tim',
|
||||
lastName: 'Apple',
|
||||
displayName: 'Tim',
|
||||
avatarUrl: '',
|
||||
handle: 'tim@apple.dev',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
Reference in New Issue
Block a user