Fix CI errored tasks for front (#6806)
In this PR: - revert de-optimization of icons bundle for storybook. This was forcing the browser to load ~3k files while running stories - adding lazy loading on Settings route to improve developer experience (some files will be loaded later) - fix FE tests: unit, modules stories, pages stories --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
committed by
Charles Bochet
parent
a3ea0acd1a
commit
56f8091a42
@ -82,7 +82,9 @@ export const DefaultWithoutSearch: Story = {
|
||||
play: async () => {
|
||||
const canvas = within(document.body);
|
||||
|
||||
expect(await canvas.findByText('Create Task')).toBeInTheDocument();
|
||||
expect(
|
||||
await canvas.findByText('Create Task', undefined, { timeout: 10000 }),
|
||||
).toBeInTheDocument();
|
||||
expect(await canvas.findByText('Go to People')).toBeInTheDocument();
|
||||
expect(await canvas.findByText('Go to Companies')).toBeInTheDocument();
|
||||
expect(await canvas.findByText('Go to Opportunities')).toBeInTheDocument();
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { expect, within } from '@storybook/test';
|
||||
|
||||
import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
|
||||
|
||||
import { useKeyboardShortcutMenu } from '@/keyboard-shortcut-menu/hooks/useKeyboardShortcutMenu';
|
||||
import { useEffect } from 'react';
|
||||
import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator';
|
||||
import { KeyboardShortcutMenu } from '../KeyboardShortcutMenu';
|
||||
|
||||
const meta: Meta<typeof KeyboardShortcutMenu> = {
|
||||
title: 'Modules/KeyboardShortcutMenu/KeyboardShortcutMenu',
|
||||
component: KeyboardShortcutMenu,
|
||||
decorators: [
|
||||
(Story) => {
|
||||
const { openKeyboardShortcutMenu } = useKeyboardShortcutMenu();
|
||||
useEffect(() => {
|
||||
openKeyboardShortcutMenu();
|
||||
}, [openKeyboardShortcutMenu]);
|
||||
return <Story />;
|
||||
},
|
||||
SnackBarDecorator,
|
||||
ComponentWithRouterDecorator,
|
||||
],
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof KeyboardShortcutMenu>;
|
||||
|
||||
export const Default: Story = {
|
||||
play: async () => {
|
||||
const canvas = within(document.body);
|
||||
|
||||
expect(await canvas.findByText('Keyboard shortcuts')).toBeInTheDocument();
|
||||
},
|
||||
};
|
||||
@ -1,6 +1,4 @@
|
||||
import { expect } from '@storybook/jest';
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
import { within } from '@storybook/test';
|
||||
|
||||
import { ComponentWithRecoilScopeDecorator } from '~/testing/decorators/ComponentWithRecoilScopeDecorator';
|
||||
import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator';
|
||||
@ -10,6 +8,7 @@ import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
|
||||
import { NavigationDrawerSectionForObjectMetadataItems } from '@/object-metadata/components/NavigationDrawerSectionForObjectMetadataItems';
|
||||
import { within } from '@storybook/test';
|
||||
import { PrefetchLoadedDecorator } from '~/testing/decorators/PrefetchLoadedDecorator';
|
||||
|
||||
const meta: Meta<typeof NavigationDrawerSectionForObjectMetadataItems> = {
|
||||
@ -32,10 +31,10 @@ export default meta;
|
||||
type Story = StoryObj<typeof NavigationDrawerSectionForObjectMetadataItems>;
|
||||
|
||||
export const Default: Story = {
|
||||
play: async () => {
|
||||
const canvas = within(document.body);
|
||||
expect(await canvas.findByText('People')).toBeInTheDocument();
|
||||
expect(await canvas.findByText('Companies')).toBeInTheDocument();
|
||||
expect(await canvas.findByText('Opportunities')).toBeInTheDocument();
|
||||
play: async ({ canvasElement }) => {
|
||||
const canvas = within(canvasElement);
|
||||
await canvas.findByText('People', undefined, { timeout: 10000 });
|
||||
await canvas.findByText('Companies');
|
||||
await canvas.findByText('Opportunities');
|
||||
},
|
||||
};
|
||||
@ -27,6 +27,7 @@ export const ObjectFilterDropdownDateInput = () => {
|
||||
const [internalDate, setInternalDate] = useState<Date | null>(
|
||||
selectedFilter?.value ? new Date(selectedFilter.value) : new Date(),
|
||||
);
|
||||
|
||||
const handleChange = (date: Date | null) => {
|
||||
setInternalDate(date);
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { useState } from 'react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useState } from 'react';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { useIcons } from 'twenty-ui';
|
||||
|
||||
|
||||
@ -0,0 +1,118 @@
|
||||
import { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { TaskGroups } from '@/activities/tasks/components/TaskGroups';
|
||||
import { MultipleFiltersDropdownButton } from '@/object-record/object-filter-dropdown/components/MultipleFiltersDropdownButton';
|
||||
import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
|
||||
import { ObjectFilterDropdownScope } from '@/object-record/object-filter-dropdown/scopes/ObjectFilterDropdownScope';
|
||||
import { within } from '@storybook/test';
|
||||
import { ComponentDecorator } from 'twenty-ui';
|
||||
import { FieldMetadataType } from '~/generated/graphql';
|
||||
import { IconsProviderDecorator } from '~/testing/decorators/IconsProviderDecorator';
|
||||
import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator';
|
||||
import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
|
||||
|
||||
const meta: Meta<typeof MultipleFiltersDropdownButton> = {
|
||||
title:
|
||||
'Modules/ObjectRecord/ObjectFilterDropdown/MultipleFiltersDropdownButton',
|
||||
component: MultipleFiltersDropdownButton,
|
||||
decorators: [
|
||||
(Story) => {
|
||||
const { setAvailableFilterDefinitions } = useFilterDropdown({
|
||||
filterDropdownId: 'entity-tasks-filter-scope',
|
||||
});
|
||||
setAvailableFilterDefinitions([
|
||||
{
|
||||
fieldMetadataId: '1',
|
||||
iconName: 'IconUser',
|
||||
label: 'Text',
|
||||
type: FieldMetadataType.Text,
|
||||
},
|
||||
{
|
||||
fieldMetadataId: '2',
|
||||
iconName: 'Icon123',
|
||||
label: 'Email',
|
||||
type: FieldMetadataType.Email,
|
||||
},
|
||||
{
|
||||
fieldMetadataId: '3',
|
||||
iconName: 'IconNumber',
|
||||
label: 'Number',
|
||||
type: FieldMetadataType.Number,
|
||||
},
|
||||
{
|
||||
fieldMetadataId: '3',
|
||||
iconName: 'IconCalendar',
|
||||
label: 'Date',
|
||||
type: FieldMetadataType.DateTime,
|
||||
},
|
||||
]);
|
||||
return (
|
||||
<ObjectFilterDropdownScope filterScopeId="entity-tasks-filter-scope">
|
||||
<Story />
|
||||
</ObjectFilterDropdownScope>
|
||||
);
|
||||
},
|
||||
ObjectMetadataItemsDecorator,
|
||||
SnackBarDecorator,
|
||||
ComponentDecorator,
|
||||
IconsProviderDecorator,
|
||||
],
|
||||
args: {
|
||||
hotkeyScope: {
|
||||
scope: 'object-filter-dropdown',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof TaskGroups>;
|
||||
|
||||
export const Default: Story = {
|
||||
play: async () => {
|
||||
const canvas = within(document.body);
|
||||
|
||||
const filterButton = await canvas.findByText('Filter');
|
||||
|
||||
filterButton.click();
|
||||
|
||||
const textFilter = await canvas.findByText('Text');
|
||||
|
||||
textFilter.click();
|
||||
|
||||
const operatorDropdown = await canvas.findByText('Contains');
|
||||
|
||||
operatorDropdown.click();
|
||||
|
||||
const containsOption = await canvas.findByText("Doesn't contain");
|
||||
|
||||
containsOption.click();
|
||||
},
|
||||
};
|
||||
|
||||
export const Date: Story = {
|
||||
play: async () => {
|
||||
const canvas = within(document.body);
|
||||
|
||||
const filterButton = await canvas.findByText('Filter');
|
||||
|
||||
filterButton.click();
|
||||
|
||||
const dateFilter = await canvas.findByText('Date');
|
||||
|
||||
dateFilter.click();
|
||||
},
|
||||
};
|
||||
|
||||
export const Number: Story = {
|
||||
play: async () => {
|
||||
const canvas = within(document.body);
|
||||
|
||||
const filterButton = await canvas.findByText('Filter');
|
||||
|
||||
filterButton.click();
|
||||
|
||||
const dateFilter = await canvas.findByText('Number');
|
||||
|
||||
dateFilter.click();
|
||||
},
|
||||
};
|
||||
@ -29,6 +29,6 @@ export const Default: Story = {};
|
||||
export const Performance = getProfilingStory({
|
||||
componentName: 'RatingFieldDisplay',
|
||||
averageThresholdInMs: 0.5,
|
||||
numberOfRuns: 50,
|
||||
numberOfRuns: 30,
|
||||
numberOfTestsPerRun: 100,
|
||||
});
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import { useEffect } from 'react';
|
||||
import { Decorator, Meta, StoryObj } from '@storybook/react';
|
||||
import {
|
||||
expect,
|
||||
@ -8,6 +7,7 @@ import {
|
||||
waitFor,
|
||||
within,
|
||||
} from '@storybook/test';
|
||||
import { useEffect } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState';
|
||||
@ -141,7 +141,9 @@ export const Submit: Story = {
|
||||
|
||||
expect(submitJestFn).toHaveBeenCalledTimes(0);
|
||||
|
||||
const item = await canvas.findByText('John Wick');
|
||||
const item = await canvas.findByText('John Wick', undefined, {
|
||||
timeout: 3000,
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
userEvent.click(item);
|
||||
@ -156,7 +158,7 @@ export const Cancel: Story = {
|
||||
const canvas = within(canvasElement);
|
||||
|
||||
expect(cancelJestFn).toHaveBeenCalledTimes(0);
|
||||
await canvas.findByText('John Wick');
|
||||
await canvas.findByText('John Wick', undefined, { timeout: 3000 });
|
||||
|
||||
const emptyDiv = canvas.getByTestId('data-field-input-click-outside-div');
|
||||
fireEvent.click(emptyDiv);
|
||||
|
||||
@ -61,12 +61,7 @@ export const useHandleToggleTrashColumnFilter = ({
|
||||
};
|
||||
|
||||
upsertCombinedViewFilter(newFilter);
|
||||
}, [
|
||||
columnDefinitions,
|
||||
objectMetadataItem,
|
||||
objectNameSingular,
|
||||
upsertCombinedViewFilter,
|
||||
]);
|
||||
}, [columnDefinitions, objectMetadataItem, upsertCombinedViewFilter]);
|
||||
|
||||
return handleToggleTrashColumnFilter;
|
||||
};
|
||||
|
||||
@ -13,6 +13,7 @@ import { isDefined } from '~/utils/isDefined';
|
||||
export type TextInputProps = TextInputV2ComponentProps & {
|
||||
disableHotkeys?: boolean;
|
||||
onInputEnter?: () => void;
|
||||
dataTestId?: string;
|
||||
focused?: boolean;
|
||||
};
|
||||
|
||||
@ -22,6 +23,7 @@ export const TextInput = ({
|
||||
onInputEnter,
|
||||
disableHotkeys = false,
|
||||
focused,
|
||||
dataTestId,
|
||||
...props
|
||||
}: TextInputProps) => {
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
@ -103,6 +105,7 @@ export const TextInput = ({
|
||||
ref={inputRef}
|
||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
||||
{...props}
|
||||
dataTestId={dataTestId}
|
||||
onFocus={handleFocus}
|
||||
onBlur={handleBlur}
|
||||
/>
|
||||
|
||||
@ -127,6 +127,7 @@ export type TextInputV2ComponentProps = Omit<
|
||||
LeftIcon?: IconComponent;
|
||||
onKeyDown?: (event: React.KeyboardEvent<HTMLInputElement>) => void;
|
||||
onBlur?: FocusEventHandler<HTMLInputElement>;
|
||||
dataTestId?: string;
|
||||
};
|
||||
|
||||
const TextInputV2Component = (
|
||||
@ -151,6 +152,7 @@ const TextInputV2Component = (
|
||||
LeftIcon,
|
||||
autoComplete,
|
||||
maxLength,
|
||||
dataTestId,
|
||||
}: TextInputV2ComponentProps,
|
||||
// eslint-disable-next-line @nx/workspace-component-props-naming
|
||||
ref: ForwardedRef<HTMLInputElement>,
|
||||
@ -178,6 +180,7 @@ const TextInputV2Component = (
|
||||
</StyledLeftIconContainer>
|
||||
)}
|
||||
<StyledInput
|
||||
data-testId={dataTestId}
|
||||
autoComplete={autoComplete || 'off'}
|
||||
ref={combinedRef}
|
||||
tabIndex={tabIndex ?? 0}
|
||||
|
||||
@ -15,19 +15,23 @@ export const useShowAuthModal = () => {
|
||||
const isLoggedIn = useIsLogged();
|
||||
const onboardingStatus = useOnboardingStatus();
|
||||
const subscriptionStatus = useSubscriptionStatus();
|
||||
|
||||
const isDefaultLayoutAuthModalVisible = useRecoilValue(
|
||||
isDefaultLayoutAuthModalVisibleState,
|
||||
);
|
||||
|
||||
return useMemo(() => {
|
||||
if (isMatchingLocation(AppPath.Verify)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
isMatchingLocation(AppPath.Invite) ||
|
||||
isMatchingLocation(AppPath.ResetPassword)
|
||||
) {
|
||||
return isDefaultLayoutAuthModalVisible;
|
||||
}
|
||||
|
||||
if (
|
||||
!isLoggedIn ||
|
||||
onboardingStatus === OnboardingStatus.PlanRequired ||
|
||||
@ -38,6 +42,7 @@ export const useShowAuthModal = () => {
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isMatchingLocation(AppPath.PlanRequired)) {
|
||||
return (
|
||||
(onboardingStatus === OnboardingStatus.Completed &&
|
||||
@ -45,6 +50,7 @@ export const useShowAuthModal = () => {
|
||||
subscriptionStatus === SubscriptionStatus.Canceled
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
}, [
|
||||
isLoggedIn,
|
||||
|
||||
@ -109,6 +109,7 @@ export const ConfirmationModal = ({
|
||||
{confirmationValue && (
|
||||
<Section>
|
||||
<TextInput
|
||||
dataTestId="confirmation-modal-input"
|
||||
value={inputConfirmationValue}
|
||||
onChange={handleInputConfimrationValueChange}
|
||||
placeholder={confirmationPlaceholder}
|
||||
|
||||
Reference in New Issue
Block a user