diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/DefaultActionsConfigV2.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/DefaultActionsConfigV2.ts index 13cc89a19..33467717e 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/DefaultActionsConfigV2.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/DefaultActionsConfigV2.ts @@ -1,4 +1,5 @@ import { useDeleteMultipleRecordsAction } from '@/action-menu/actions/record-actions/multiple-records/hooks/useDeleteMultipleRecordsAction'; +import { useDestroyMultipleRecordsAction } from '@/action-menu/actions/record-actions/multiple-records/hooks/useDestroyMultipleRecordsAction'; import { useExportMultipleRecordsAction } from '@/action-menu/actions/record-actions/multiple-records/hooks/useExportMultipleRecordsAction'; import { MultipleRecordsActionKeys } from '@/action-menu/actions/record-actions/multiple-records/types/MultipleRecordsActionKeys'; import { useCreateNewTableRecordNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/hooks/useCreateNewTableRecordNoSelectionRecordAction'; @@ -184,4 +185,17 @@ export const DEFAULT_ACTIONS_CONFIG_V2: Record< availableOn: [ActionViewType.SHOW_PAGE], useAction: useNavigateToNextRecordSingleRecordAction, }, + destroyMultipleRecords: { + type: ActionMenuEntryType.Standard, + scope: ActionMenuEntryScope.RecordSelection, + key: MultipleRecordsActionKeys.DESTROY, + label: msg`Permanently destroy records`, + shortLabel: msg`Destroy`, + position: 10, + Icon: IconTrashX, + accent: 'danger', + isPinned: true, + availableOn: [ActionViewType.INDEX_PAGE_BULK_SELECTION], + useAction: useDestroyMultipleRecordsAction, + }, }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/__tests__/useDestroyMultipleRecordsAction.test.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/__tests__/useDestroyMultipleRecordsAction.test.tsx new file mode 100644 index 000000000..21117eac1 --- /dev/null +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/__tests__/useDestroyMultipleRecordsAction.test.tsx @@ -0,0 +1,145 @@ +import { DestroyManyRecordsProps } from '@/object-record/hooks/useDestroyManyRecords'; +import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; +import { ViewFilterOperand } from '@/views/types/ViewFilterOperand'; +import { expect } from '@storybook/test'; +import { renderHook, waitFor } from '@testing-library/react'; +import { act } from 'react'; +import { + GetJestMetadataAndApolloMocksAndActionMenuWrapperProps, + getJestMetadataAndApolloMocksAndActionMenuWrapper, +} from '~/testing/jest/getJestMetadataAndApolloMocksAndContextStoreWrapper'; +import { generatedMockObjectMetadataItems } from '~/testing/mock-data/generatedMockObjectMetadataItems'; +import { getPeopleMock } from '~/testing/mock-data/people'; +import { useDestroyMultipleRecordsAction } from '../useDestroyMultipleRecordsAction'; + +const personMockObjectMetadataItem = generatedMockObjectMetadataItems.find( + (item) => item.nameSingular === 'person', +)!; +const personMockObjectMetadataItemDeletedAtField = + personMockObjectMetadataItem.fields.find((el) => el.name === 'deletedAt'); +if (personMockObjectMetadataItemDeletedAtField === undefined) + throw new Error('Should never occurs'); + +const [firstPeopleMock, secondPeopleMock] = getPeopleMock().map((record) => ({ + ...record, + deletedAt: new Date().toISOString(), +})); + +const destroyManyRecordsMock = jest.fn(); +const resetTableRowSelectionMock = jest.fn(); + +jest.mock('@/object-record/hooks/useDestroyManyRecords', () => ({ + useDestroyManyRecords: () => ({ + destroyManyRecords: destroyManyRecordsMock, + }), +})); + +jest.mock('@/object-record/hooks/useLazyFetchAllRecords', () => ({ + useLazyFetchAllRecords: () => { + return { + fetchAllRecords: () => [firstPeopleMock, secondPeopleMock], + }; + }, +})); + +jest.mock('@/object-record/record-table/hooks/useRecordTable', () => ({ + useRecordTable: () => ({ + resetTableRowSelection: resetTableRowSelectionMock, + }), +})); + +const getWrapper = ( + overrides?: Partial, +) => + getJestMetadataAndApolloMocksAndActionMenuWrapper({ + apolloMocks: [], + componentInstanceId: '1', + contextStoreCurrentObjectMetadataNameSingular: + personMockObjectMetadataItem.nameSingular, + contextStoreTargetedRecordsRule: { + mode: 'selection', + selectedRecordIds: [firstPeopleMock.id, secondPeopleMock.id], + }, + contextStoreFilters: [], + contextStoreNumberOfSelectedRecords: 2, + onInitializeRecoilSnapshot: (snapshot) => { + snapshot.set(recordStoreFamilyState(firstPeopleMock.id), firstPeopleMock); + snapshot.set( + recordStoreFamilyState(secondPeopleMock.id), + secondPeopleMock, + ); + }, + ...overrides, + }); + +const defaultWrapper = getWrapper(); + +describe('useDestroyMultipleRecordsAction', () => { + it('should call destroyManyRecords on click if records are filtered by deletedAt', async () => { + const { result } = renderHook( + () => + useDestroyMultipleRecordsAction({ + objectMetadataItem: personMockObjectMetadataItem, + }), + { + wrapper: getWrapper({ + contextStoreFilters: [ + { + id: '1553cda7-893d-4d89-b7ab-04969a4c2927', + fieldMetadataId: personMockObjectMetadataItemDeletedAtField.id, + value: '', + displayValue: '', + operand: ViewFilterOperand.IsNotEmpty, + definition: { + label: 'Deleted', + iconName: 'IconTrash', + fieldMetadataId: personMockObjectMetadataItemDeletedAtField.id, + type: 'DATE_TIME', + }, + }, + ], + }), + }, + ); + + expect(result.current.ConfirmationModal?.props?.isOpen).toBeFalsy(); + + act(() => { + result.current.onClick(); + }); + + expect(result.current.ConfirmationModal?.props?.isOpen).toBe(true); + + act(() => { + result.current.ConfirmationModal?.props?.onConfirmClick(); + }); + + const expectedParams: DestroyManyRecordsProps = { + recordIdsToDestroy: [firstPeopleMock.id, secondPeopleMock.id], + }; + await waitFor(() => { + expect(resetTableRowSelectionMock).toHaveBeenCalled(); + expect(destroyManyRecordsMock).toHaveBeenCalledWith(expectedParams); + }); + }); + + it('should not call destroyManyRecords on click if records are not filtered by deletedAt', async () => { + const { result } = renderHook( + () => + useDestroyMultipleRecordsAction({ + objectMetadataItem: personMockObjectMetadataItem, + }), + { + wrapper: defaultWrapper, + }, + ); + + expect(result.current.ConfirmationModal?.props?.isOpen).toBeFalsy(); + + act(() => { + result.current.onClick(); + }); + + expect(result.current.ConfirmationModal?.props?.isOpen).toBeFalsy(); + }); +}); diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/useDeleteMultipleRecordsAction.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/useDeleteMultipleRecordsAction.tsx index df752634b..ba7769eeb 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/useDeleteMultipleRecordsAction.tsx +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/useDeleteMultipleRecordsAction.tsx @@ -4,8 +4,8 @@ import { contextStoreFiltersComponentState } from '@/context-store/states/contex import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters'; +import { BACKEND_BATCH_REQUEST_MAX_COUNT } from '@/object-record/constants/BackendBatchRequestMaxCount'; import { DEFAULT_QUERY_PAGE_SIZE } from '@/object-record/constants/DefaultQueryPageSize'; -import { DELETE_MAX_COUNT } from '@/object-record/constants/DeleteMaxCount'; import { useDeleteManyRecords } from '@/object-record/hooks/useDeleteManyRecords'; import { useLazyFetchAllRecords } from '@/object-record/hooks/useLazyFetchAllRecords'; import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies'; @@ -84,7 +84,7 @@ export const useDeleteMultipleRecordsAction: ActionHookWithObjectMetadataItem = !isRemoteObject && !isDeletedFilterActive && isDefined(contextStoreNumberOfSelectedRecords) && - contextStoreNumberOfSelectedRecords < DELETE_MAX_COUNT && + contextStoreNumberOfSelectedRecords < BACKEND_BATCH_REQUEST_MAX_COUNT && contextStoreNumberOfSelectedRecords > 0; const onClick = () => { diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/useDestroyMultipleRecordsAction.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/useDestroyMultipleRecordsAction.tsx new file mode 100644 index 000000000..68bbc1c5f --- /dev/null +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/hooks/useDestroyMultipleRecordsAction.tsx @@ -0,0 +1,121 @@ +import { ActionHookWithObjectMetadataItem } from '@/action-menu/actions/types/ActionHook'; + +import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState'; +import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; +import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; +import { computeContextStoreFilters } from '@/context-store/utils/computeContextStoreFilters'; +import { BACKEND_BATCH_REQUEST_MAX_COUNT } from '@/object-record/constants/BackendBatchRequestMaxCount'; +import { DEFAULT_QUERY_PAGE_SIZE } from '@/object-record/constants/DefaultQueryPageSize'; +import { RecordGqlOperationFilter } from '@/object-record/graphql/types/RecordGqlOperationFilter'; +import { useDestroyManyRecords } from '@/object-record/hooks/useDestroyManyRecords'; +import { useLazyFetchAllRecords } from '@/object-record/hooks/useLazyFetchAllRecords'; +import { useFilterValueDependencies } from '@/object-record/record-filter/hooks/useFilterValueDependencies'; +import { RecordFilterOperand } from '@/object-record/record-filter/types/RecordFilterOperand'; +import { useRecordTable } from '@/object-record/record-table/hooks/useRecordTable'; +import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { useCallback, useState } from 'react'; +import { isDefined } from 'twenty-shared'; + +export const useDestroyMultipleRecordsAction: ActionHookWithObjectMetadataItem = + ({ objectMetadataItem }) => { + const [isDestroyRecordsModalOpen, setIsDestroyRecordsModalOpen] = + useState(false); + + const { resetTableRowSelection } = useRecordTable({ + recordTableId: objectMetadataItem.namePlural, + }); + + const { destroyManyRecords } = useDestroyManyRecords({ + objectNameSingular: objectMetadataItem.nameSingular, + }); + + const contextStoreNumberOfSelectedRecords = useRecoilComponentValueV2( + contextStoreNumberOfSelectedRecordsComponentState, + ); + + const contextStoreTargetedRecordsRule = useRecoilComponentValueV2( + contextStoreTargetedRecordsRuleComponentState, + ); + + const contextStoreFilters = useRecoilComponentValueV2( + contextStoreFiltersComponentState, + ); + + const { filterValueDependencies } = useFilterValueDependencies(); + + const deletedAtFilter: RecordGqlOperationFilter = { + deletedAt: { is: 'NOT_NULL' }, + }; + const graphqlFilter = { + ...computeContextStoreFilters( + contextStoreTargetedRecordsRule, + contextStoreFilters, + objectMetadataItem, + filterValueDependencies, + ), + ...deletedAtFilter, + }; + + const deletedAtFieldMetadata = objectMetadataItem.fields.find( + (field) => field.name === 'deletedAt', + ); + + const isDeletedFilterActive = contextStoreFilters.some( + (filter) => + filter.fieldMetadataId === deletedAtFieldMetadata?.id && + filter.operand === RecordFilterOperand.IsNotEmpty, + ); + + const { fetchAllRecords: fetchAllRecordIds } = useLazyFetchAllRecords({ + objectNameSingular: objectMetadataItem.nameSingular, + filter: graphqlFilter, + limit: DEFAULT_QUERY_PAGE_SIZE, + recordGqlFields: { id: true }, + }); + + const handleDestroyClick = useCallback(async () => { + const recordsToDestroy = await fetchAllRecordIds(); + const recordIdsToDestroy = recordsToDestroy.map((record) => record.id); + + resetTableRowSelection(); + + await destroyManyRecords({ recordIdsToDestroy }); + }, [destroyManyRecords, fetchAllRecordIds, resetTableRowSelection]); + + const isRemoteObject = objectMetadataItem.isRemote; + + const shouldBeRegistered = + !isRemoteObject && + isDeletedFilterActive && + isDefined(contextStoreNumberOfSelectedRecords) && + contextStoreNumberOfSelectedRecords < BACKEND_BATCH_REQUEST_MAX_COUNT && + contextStoreNumberOfSelectedRecords > 0; + + const onClick = () => { + if (!shouldBeRegistered) { + return; + } + + setIsDestroyRecordsModalOpen(true); + }; + + const confirmationModal = ( + + ); + + return { + shouldBeRegistered, + onClick, + ConfirmationModal: confirmationModal, + }; + }; diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/types/MultipleRecordsActionKeys.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/types/MultipleRecordsActionKeys.ts index 9ecbb5b23..2c52d9eab 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/types/MultipleRecordsActionKeys.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/types/MultipleRecordsActionKeys.ts @@ -1,4 +1,5 @@ export enum MultipleRecordsActionKeys { DELETE = 'delete-multiple-records', EXPORT = 'export-multiple-records', + DESTROY = 'destroy-multiple-records', } diff --git a/packages/twenty-front/src/modules/action-menu/actions/types/ActionHook.ts b/packages/twenty-front/src/modules/action-menu/actions/types/ActionHook.ts index 2add89e61..a76bdb368 100644 --- a/packages/twenty-front/src/modules/action-menu/actions/types/ActionHook.ts +++ b/packages/twenty-front/src/modules/action-menu/actions/types/ActionHook.ts @@ -7,8 +7,9 @@ export type ActionHook = export type ActionHookWithoutObjectMetadataItem = () => ActionHookResult; -export type ActionHookWithObjectMetadataItem = ({ - objectMetadataItem, -}: { +type ActionHookWithObjectMetadataItemParams = { objectMetadataItem: ObjectMetadataItem; -}) => ActionHookResult; +}; +export type ActionHookWithObjectMetadataItem = ( + params: ActionHookWithObjectMetadataItemParams, +) => ActionHookResult; diff --git a/packages/twenty-front/src/modules/object-record/constants/BackendBatchRequestMaxCount.ts b/packages/twenty-front/src/modules/object-record/constants/BackendBatchRequestMaxCount.ts new file mode 100644 index 000000000..cad92aaaa --- /dev/null +++ b/packages/twenty-front/src/modules/object-record/constants/BackendBatchRequestMaxCount.ts @@ -0,0 +1 @@ +export const BACKEND_BATCH_REQUEST_MAX_COUNT = 10000; diff --git a/packages/twenty-front/src/modules/object-record/constants/DeleteMaxCount.ts b/packages/twenty-front/src/modules/object-record/constants/DeleteMaxCount.ts deleted file mode 100644 index 0f1b3a7c3..000000000 --- a/packages/twenty-front/src/modules/object-record/constants/DeleteMaxCount.ts +++ /dev/null @@ -1 +0,0 @@ -export const DELETE_MAX_COUNT = 10000; diff --git a/packages/twenty-front/src/modules/object-record/hooks/useDestroyManyRecords.ts b/packages/twenty-front/src/modules/object-record/hooks/useDestroyManyRecords.ts index b434efa94..3cc39f2b3 100644 --- a/packages/twenty-front/src/modules/object-record/hooks/useDestroyManyRecords.ts +++ b/packages/twenty-front/src/modules/object-record/hooks/useDestroyManyRecords.ts @@ -19,7 +19,8 @@ type useDestroyManyRecordProps = { refetchFindManyQuery?: boolean; }; -type DestroyManyRecordsOptions = { +export type DestroyManyRecordsProps = { + recordIdsToDestroy: string[]; skipOptimisticEffect?: boolean; delayInMsBetweenRequests?: number; }; @@ -56,16 +57,19 @@ export const useDestroyManyRecords = ({ objectMetadataItem.namePlural, ); - const destroyManyRecords = async ( - idsToDestroy: string[], - options?: DestroyManyRecordsOptions, - ) => { - const numberOfBatches = Math.ceil(idsToDestroy.length / mutationPageSize); + const destroyManyRecords = async ({ + recordIdsToDestroy, + delayInMsBetweenRequests, + skipOptimisticEffect = false, + }: DestroyManyRecordsProps) => { + const numberOfBatches = Math.ceil( + recordIdsToDestroy.length / mutationPageSize, + ); const destroyedRecords = []; for (let batchIndex = 0; batchIndex < numberOfBatches; batchIndex++) { - const batchedIdToDestroy = idsToDestroy.slice( + const batchedIdToDestroy = recordIdsToDestroy.slice( batchIndex * mutationPageSize, (batchIndex + 1) * mutationPageSize, ); @@ -80,7 +84,7 @@ export const useDestroyManyRecords = ({ variables: { filter: { id: { in: batchedIdToDestroy } }, }, - optimisticResponse: options?.skipOptimisticEffect + optimisticResponse: skipOptimisticEffect ? undefined : { [mutationResponseField]: batchedIdToDestroy.map( @@ -90,7 +94,7 @@ export const useDestroyManyRecords = ({ }), ), }, - update: options?.skipOptimisticEffect + update: skipOptimisticEffect ? undefined : (cache, { data }) => { const records = data?.[mutationResponseField]; @@ -126,8 +130,8 @@ export const useDestroyManyRecords = ({ destroyedRecords.push(...destroyedRecordsForThisBatch); - if (isDefined(options?.delayInMsBetweenRequests)) { - await sleep(options.delayInMsBetweenRequests); + if (isDefined(delayInMsBetweenRequests)) { + await sleep(delayInMsBetweenRequests); } } diff --git a/packages/twenty-front/src/modules/views/hooks/internal/usePersistViewGroupRecords.ts b/packages/twenty-front/src/modules/views/hooks/internal/usePersistViewGroupRecords.ts index 5207d7364..b006b7f04 100644 --- a/packages/twenty-front/src/modules/views/hooks/internal/usePersistViewGroupRecords.ts +++ b/packages/twenty-front/src/modules/views/hooks/internal/usePersistViewGroupRecords.ts @@ -87,9 +87,12 @@ export const usePersistViewGroupRecords = () => { async (viewGroupsToDelete: ViewGroup[]) => { if (!viewGroupsToDelete.length) return; - return destroyManyRecords( - viewGroupsToDelete.map((viewGroup) => viewGroup.id), + const recordIdsToDestroy = viewGroupsToDelete.map( + (viewGroup) => viewGroup.id, ); + return destroyManyRecords({ + recordIdsToDestroy, + }); }, [destroyManyRecords], ); diff --git a/packages/twenty-front/src/testing/jest/JestContextStoreSetter.tsx b/packages/twenty-front/src/testing/jest/JestContextStoreSetter.tsx index f08377a19..b54dedf39 100644 --- a/packages/twenty-front/src/testing/jest/JestContextStoreSetter.tsx +++ b/packages/twenty-front/src/testing/jest/JestContextStoreSetter.tsx @@ -1,14 +1,25 @@ -import { ReactNode, useEffect, useState } from 'react'; +import { PropsWithChildren, useEffect, useState } from 'react'; import { contextStoreCurrentObjectMetadataIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataIdComponentState'; +import { contextStoreFiltersComponentState } from '@/context-store/states/contextStoreFiltersComponentState'; import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState'; import { ContextStoreTargetedRecordsRule, contextStoreTargetedRecordsRuleComponentState, } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; +import { RecordFilter } from '@/object-record/record-filter/types/RecordFilter'; import { useSetRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentStateV2'; +export type JestContextStoreSetterMocks = { + contextStoreTargetedRecordsRule?: ContextStoreTargetedRecordsRule; + contextStoreNumberOfSelectedRecords?: number; + contextStoreFilters?: RecordFilter[]; + contextStoreCurrentObjectMetadataNameSingular?: string; +}; + +type JestContextStoreSetterProps = + PropsWithChildren; export const JestContextStoreSetter = ({ contextStoreTargetedRecordsRule = { mode: 'selection', @@ -16,13 +27,9 @@ export const JestContextStoreSetter = ({ }, contextStoreNumberOfSelectedRecords = 0, contextStoreCurrentObjectMetadataNameSingular = '', + contextStoreFilters = [], children, -}: { - contextStoreTargetedRecordsRule?: ContextStoreTargetedRecordsRule; - contextStoreNumberOfSelectedRecords?: number; - contextStoreCurrentObjectMetadataNameSingular?: string; - children: ReactNode; -}) => { +}: JestContextStoreSetterProps) => { const setContextStoreTargetedRecordsRule = useSetRecoilComponentStateV2( contextStoreTargetedRecordsRuleComponentState, ); @@ -35,6 +42,10 @@ export const JestContextStoreSetter = ({ contextStoreNumberOfSelectedRecordsComponentState, ); + const setcontextStoreFiltersComponentState = useSetRecoilComponentStateV2( + contextStoreFiltersComponentState, + ); + const { objectMetadataItem } = useObjectMetadataItem({ objectNameSingular: contextStoreCurrentObjectMetadataNameSingular, }); @@ -46,6 +57,8 @@ export const JestContextStoreSetter = ({ setContextStoreTargetedRecordsRule(contextStoreTargetedRecordsRule); setContextStoreCurrentObjectMetadataId(contextStoreCurrentObjectMetadataId); setContextStoreNumberOfSelectedRecords(contextStoreNumberOfSelectedRecords); + setcontextStoreFiltersComponentState(contextStoreFilters); + setIsLoaded(true); }, [ setContextStoreTargetedRecordsRule, @@ -54,6 +67,8 @@ export const JestContextStoreSetter = ({ contextStoreCurrentObjectMetadataId, setContextStoreNumberOfSelectedRecords, contextStoreNumberOfSelectedRecords, + setcontextStoreFiltersComponentState, + contextStoreFilters, ]); return isLoaded ? <>{children} : null; diff --git a/packages/twenty-front/src/testing/jest/getJestMetadataAndApolloMocksAndContextStoreWrapper.tsx b/packages/twenty-front/src/testing/jest/getJestMetadataAndApolloMocksAndContextStoreWrapper.tsx index 894cd7795..b01c98be4 100644 --- a/packages/twenty-front/src/testing/jest/getJestMetadataAndApolloMocksAndContextStoreWrapper.tsx +++ b/packages/twenty-front/src/testing/jest/getJestMetadataAndApolloMocksAndContextStoreWrapper.tsx @@ -1,23 +1,22 @@ import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext'; import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext'; -import { ContextStoreTargetedRecordsRule } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState'; import { RecordFiltersComponentInstanceContext } from '@/object-record/record-filter/states/context/RecordFiltersComponentInstanceContext'; import { MockedResponse } from '@apollo/client/testing'; import { ReactNode } from 'react'; import { MutableSnapshot } from 'recoil'; import { getJestMetadataAndApolloMocksWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksWrapper'; -import { JestContextStoreSetter } from '~/testing/jest/JestContextStoreSetter'; +import { + JestContextStoreSetter, + JestContextStoreSetterMocks, +} from '~/testing/jest/JestContextStoreSetter'; export type GetJestMetadataAndApolloMocksAndActionMenuWrapperProps = { apolloMocks: | readonly MockedResponse, Record>[] | undefined; onInitializeRecoilSnapshot?: (snapshot: MutableSnapshot) => void; - contextStoreTargetedRecordsRule?: ContextStoreTargetedRecordsRule; - contextStoreNumberOfSelectedRecords?: number; - contextStoreCurrentObjectMetadataNameSingular?: string; componentInstanceId: string; -}; +} & JestContextStoreSetterMocks; export const getJestMetadataAndApolloMocksAndActionMenuWrapper = ({ apolloMocks, @@ -25,6 +24,7 @@ export const getJestMetadataAndApolloMocksAndActionMenuWrapper = ({ contextStoreTargetedRecordsRule, contextStoreNumberOfSelectedRecords, contextStoreCurrentObjectMetadataNameSingular, + contextStoreFilters, componentInstanceId, }: GetJestMetadataAndApolloMocksAndActionMenuWrapperProps) => { const Wrapper = getJestMetadataAndApolloMocksWrapper({ @@ -48,6 +48,7 @@ export const getJestMetadataAndApolloMocksAndActionMenuWrapper = ({ }} >