Some checks failed
App Prod-Parity E2E Dispatch / dispatch (push) Failing after 10s
CD Storybook UI / build (push) Failing after 3m25s
CD Storybook UI / dispatch (push) Has been skipped
CD deploy main / website-changed-files (push) Successful in 18m8s
CI Agent Skills / changed-files-check (push) Successful in 18m9s
CI Create App E2E minimal / changed-files-check (push) Successful in 24s
CI Create App / changed-files-check (push) Successful in 26s
CI Docs / changed-files-check (push) Successful in 26s
CI Emails / changed-files-check (push) Successful in 28s
CI Example App Hello World / changed-files-check (push) Successful in 23s
CI Front / changed-files-check (push) Has been skipped
CI Example App Postcard / changed-files-check (push) Successful in 27s
CI UI / changed-files-check (push) Has been skipped
CI Utils Test / changed-files-check (push) Successful in 45s
CI Twenty Apps / discover (push) Successful in 1m3s
CD deploy main / deploy-main (push) Failing after 3s
CI Agent Skills / agent-skills-validate (push) Has been skipped
CI Create App / create-app-test (lint) (push) Has been skipped
CI Emails / emails-test (push) Has been skipped
CI Front / front-task (lingui:compile) (push) Has been skipped
CI Front / front-task (lint) (push) Has been skipped
CI Example App Postcard / example-app-postcard (push) Has been skipped
CI UI / ui-task (lint) (push) Has been skipped
CI UI / ui-task (pack-size) (push) Has been skipped
CI UI / ui-task (size) (push) Has been skipped
CI UI / ui-task (test) (push) Has been skipped
CI UI / ui-task (typecheck) (push) Has been skipped
CI Utils Test / utils-test (push) Has been skipped
CI Twenty Apps / ${{ matrix.app.name }} (push) Has been skipped
CI Emails / ci-emails-status-check (push) Successful in 2s
CI Example App Hello World / ci-example-app-hello-world-status-check (push) Successful in 2s
CI Example App Postcard / ci-example-app-postcard-status-check (push) Successful in 3s
CI UI / ui-sb-test (push) Has been skipped
CI Utils Test / ci-utils-test-status-check (push) Successful in 2s
CI Twenty Apps / ci-twenty-apps-status-check (push) Successful in 2s
CI UI / ci-ui-status-check (push) Successful in 2s
CI Desktop / desktop (push) Failing after 1m8s
Push docs to Crowdin / Push documentation to Crowdin (push) Failing after 55s
Push translations to Crowdin / Extract and upload translations (push) Failing after 5s
Push website translations to Crowdin / Extract and upload website translations (push) Failing after 5s
CI Create App / create-app-test (test) (push) Has been skipped
CI Create App / create-app-test (typecheck) (push) Has been skipped
CI Docs / docs-lint (push) Has been skipped
CI Example App Hello World / example-app-hello-world (push) Has been skipped
CI Front / front-task (lingui:extract) (push) Has been skipped
CI Front / front-task (test) (push) Has been skipped
CI Front / front-task (typecheck) (push) Has been skipped
CI UI / ui-sb-build (push) Failing after 1m32s
CI Twenty Apps / ${{ matrix.app.name }} (${{ matrix.server-source }}) (push) Has been skipped
CI Agent Skills / agent-skills-publish (push) Has been skipped
CI Create App / ci-create-app-status-check (push) Successful in 2s
CI Agent Skills / agent-skills-remote-source (push) Has been skipped
CI Create App E2E minimal / create-app-e2e-minimal (push) Has been cancelled
CI E2E Main / e2e-test (push) Has been cancelled
CI Front / front-sb-build (push) Has been cancelled
CI Front / front-build (push) Has been cancelled
CI Create App E2E minimal / ci-create-app-e2e-minimal-status-check (push) Has been cancelled
CI E2E Main / ci-e2e-main-status-check (push) Has been cancelled
CI E2E Main / notify-main-ci-failure (push) Has been cancelled
CI E2E Main / qa-scout-comment (push) Has been cancelled
CI Front / front-sb-test (push) Has been cancelled
CI Front / front-sb-screenshots (push) Has been cancelled
CI Front / ci-front-status-check (push) Has been cancelled
DPA Sub-Processor Sync / sync-subprocessors (push) Failing after 3s
AI Catalog Sync / sync-catalog (push) Failing after 3s
170 lines
5.6 KiB
TypeScript
170 lines
5.6 KiB
TypeScript
import '@fontsource/dm-mono/400.css';
|
|
import '@fontsource/dm-mono/500.css';
|
|
import '@fontsource/inter/400.css';
|
|
import '@fontsource/inter/500.css';
|
|
import '@fontsource/inter/600.css';
|
|
import '@fontsource/inter/700.css';
|
|
|
|
import { i18n } from '@lingui/core';
|
|
import { I18nProvider } from '@lingui/react';
|
|
import { type Preview } from '@storybook/react-vite';
|
|
import { http, HttpResponse } from 'msw';
|
|
import { initialize, mswLoader } from 'msw-storybook-addon';
|
|
import { SOURCE_LOCALE } from 'twenty-shared/translations';
|
|
|
|
// oxlint-disable-next-line no-restricted-imports
|
|
import { DateFormat } from '../src/modules/localization/constants/DateFormat';
|
|
// oxlint-disable-next-line no-restricted-imports
|
|
import { TimeFormat } from '../src/modules/localization/constants/TimeFormat';
|
|
// oxlint-disable-next-line no-restricted-imports
|
|
import { FileUploadProvider } from '../src/modules/file-upload/components/FileUploadProvider';
|
|
// oxlint-disable-next-line no-restricted-imports
|
|
import { RootDecorator } from '../src/testing/decorators/RootDecorator';
|
|
// oxlint-disable-next-line no-restricted-imports
|
|
import { resetJotaiStore } from '../src/modules/ui/utilities/state/jotai/jotaiStore';
|
|
// oxlint-disable-next-line no-restricted-imports
|
|
import { UserContext } from '../src/modules/users/contexts/UserContext';
|
|
// Stories rendering CodeEditor / GraphiQL need Monaco's worker factory, which
|
|
// the app normally sets up in src/index.tsx.
|
|
// oxlint-disable-next-line no-restricted-imports
|
|
import '../src/modules/app/utils/setupMonacoEnvironment';
|
|
|
|
import 'react-loading-skeleton/dist/skeleton.css';
|
|
import 'twenty-ui/style.css';
|
|
import 'twenty-ui/theme-light.css';
|
|
import 'twenty-ui/theme-dark.css';
|
|
import { ThemeProvider } from 'twenty-ui/theme-constants';
|
|
// oxlint-disable-next-line no-restricted-imports
|
|
import { messages as enMessages } from '../src/locales/generated/en';
|
|
|
|
i18n.load({ [SOURCE_LOCALE]: enMessages });
|
|
i18n.activate(SOURCE_LOCALE);
|
|
// oxlint-disable-next-line no-restricted-imports
|
|
import { ClickOutsideListenerContext } from '../src/modules/ui/utilities/pointer-event/contexts/ClickOutsideListenerContext';
|
|
|
|
const MOCK_IMAGE_SVG =
|
|
'<svg xmlns="http://www.w3.org/2000/svg" width="192" height="192"><rect width="192" height="192" fill="#d9d9d9"/></svg>';
|
|
|
|
const respondWithMockImage = () =>
|
|
new HttpResponse(MOCK_IMAGE_SVG, {
|
|
headers: { 'Content-Type': 'image/svg+xml' },
|
|
});
|
|
|
|
const remoteImageMockHandlers = [
|
|
http.get('https://picsum.photos/*', respondWithMockImage),
|
|
http.get('https://twenty-icons.com/*', respondWithMockImage),
|
|
http.get('https://twentyhq.github.io/*', respondWithMockImage),
|
|
http.get('https://via.placeholder.com/*', respondWithMockImage),
|
|
http.get(
|
|
'https://twenty-front-screenshots.s3.eu-west-3.amazonaws.com/*',
|
|
respondWithMockImage,
|
|
),
|
|
];
|
|
|
|
initialize(
|
|
{
|
|
onUnhandledRequest: async (request: Request) => {
|
|
const fileExtensionsToIgnore =
|
|
/\.(ts|tsx|js|jsx|svg|css|png|woff2)(\?v=[a-zA-Z0-9]+)?/;
|
|
|
|
if (fileExtensionsToIgnore.test(request.url)) {
|
|
return;
|
|
}
|
|
|
|
if (request.url.startsWith('http://localhost:3000/files/')) {
|
|
return;
|
|
}
|
|
|
|
try {
|
|
const requestBody = await request.json();
|
|
|
|
// oxlint-disable-next-line no-console
|
|
console.warn(`Unhandled ${request.method} request to ${request.url}
|
|
with payload ${JSON.stringify(requestBody)}\n
|
|
This request should be mocked with MSW`);
|
|
} catch (error) {
|
|
// oxlint-disable-next-line no-console
|
|
console.error(`Cannot parse msw request body : ${error}`);
|
|
}
|
|
|
|
// oxlint-disable-next-line no-console
|
|
console.warn(
|
|
`Unhandled ${request.method} request to ${request.url} \n This request should be mocked with MSW`,
|
|
);
|
|
},
|
|
quiet: true,
|
|
},
|
|
remoteImageMockHandlers,
|
|
);
|
|
|
|
// Mirrors production's MinimalMetadataGater so any story rendering a
|
|
// date-aware component (DateTimeDisplay, etc.) sees a real IANA timeZone
|
|
// instead of UserContext's default `{}`. Stories needing a specific timezone
|
|
// can still override by nesting their own UserContext.Provider.
|
|
const STORYBOOK_DEFAULT_USER_CONTEXT = {
|
|
dateFormat: DateFormat.DAY_FIRST,
|
|
timeFormat: TimeFormat.HOUR_24,
|
|
timeZone: 'UTC',
|
|
};
|
|
|
|
const INTER_FONT_WEIGHTS = ['400', '500', '600'];
|
|
|
|
const waitForInterFontLoadedBeforeScreenshot = async () => {
|
|
await Promise.all(
|
|
INTER_FONT_WEIGHTS.map((weight) =>
|
|
document.fonts.load(`${weight} 1em Inter`),
|
|
),
|
|
);
|
|
await document.fonts.ready;
|
|
};
|
|
|
|
const preview: Preview = {
|
|
decorators: [
|
|
(Story) => {
|
|
return (
|
|
<I18nProvider i18n={i18n}>
|
|
<ThemeProvider colorScheme="light">
|
|
<FileUploadProvider>
|
|
<ClickOutsideListenerContext.Provider
|
|
value={{ excludedClickOutsideId: undefined }}
|
|
>
|
|
<UserContext.Provider value={STORYBOOK_DEFAULT_USER_CONTEXT}>
|
|
<Story />
|
|
</UserContext.Provider>
|
|
</ClickOutsideListenerContext.Provider>
|
|
</FileUploadProvider>
|
|
</ThemeProvider>
|
|
</I18nProvider>
|
|
);
|
|
},
|
|
RootDecorator,
|
|
],
|
|
|
|
beforeEach: () => {
|
|
resetJotaiStore();
|
|
},
|
|
|
|
loaders: [mswLoader, waitForInterFontLoadedBeforeScreenshot],
|
|
|
|
parameters: {
|
|
argos: {
|
|
// CSS zoom combined with viewport-sized stories makes the iframe grow during capture.
|
|
fitToContent: { zoom: 1 },
|
|
},
|
|
controls: {
|
|
matchers: {
|
|
color: /(background|color)$/i,
|
|
date: /Date$/,
|
|
},
|
|
},
|
|
mockingDate: new Date('2024-03-12T09:30:00.000Z'),
|
|
options: {
|
|
storySort: {
|
|
order: ['UI', 'Modules', 'Pages'],
|
|
},
|
|
},
|
|
},
|
|
};
|
|
|
|
export default preview;
|