TWNTY-3549 - Add tests for modules/object-record/field (#3572)
* Add tests for `modules/object-record/field` Co-authored-by: v1b3m <vibenjamin6@gmail.com> * Merge main Co-authored-by: v1b3m <vibenjamin6@gmail.com> * Move field definitions to separate file Co-authored-by: v1b3m <vibenjamin6@gmail.com> --------- Co-authored-by: gitstart-twenty <gitstart-twenty@users.noreply.github.com> Co-authored-by: v1b3m <vibenjamin6@gmail.com>
This commit is contained in:
committed by
GitHub
parent
e0943b15c4
commit
2b6d66f1bc
@ -0,0 +1,100 @@
|
||||
import { FieldDefinition } from '@/object-record/field/types/FieldDefinition';
|
||||
import {
|
||||
FieldBooleanMetadata,
|
||||
FieldFullNameMetadata,
|
||||
FieldLinkMetadata,
|
||||
FieldPhoneMetadata,
|
||||
FieldRatingMetadata,
|
||||
FieldRelationMetadata,
|
||||
FieldSelectMetadata,
|
||||
FieldTextMetadata,
|
||||
} from '@/object-record/field/types/FieldMetadata';
|
||||
|
||||
export const fieldMetadataId = 'fieldMetadataId';
|
||||
|
||||
export const textfieldDefinition: FieldDefinition<FieldTextMetadata> = {
|
||||
fieldMetadataId,
|
||||
label: 'User Name',
|
||||
iconName: 'User',
|
||||
type: 'TEXT',
|
||||
metadata: { placeHolder: 'John Doe', fieldName: 'userName' },
|
||||
};
|
||||
|
||||
export const booleanFieldDefinition: FieldDefinition<FieldBooleanMetadata> = {
|
||||
fieldMetadataId,
|
||||
label: 'Is Active?',
|
||||
iconName: 'iconName',
|
||||
type: 'BOOLEAN',
|
||||
metadata: {
|
||||
objectMetadataNameSingular: 'person',
|
||||
fieldName: 'isActive',
|
||||
},
|
||||
};
|
||||
|
||||
export const relationFieldDefinition: FieldDefinition<FieldRelationMetadata> = {
|
||||
fieldMetadataId,
|
||||
label: 'Contact',
|
||||
iconName: 'Phone',
|
||||
type: 'RELATION',
|
||||
metadata: {
|
||||
fieldName: 'contact',
|
||||
relationFieldMetadataId: 'relationFieldMetadataId',
|
||||
relationObjectMetadataNamePlural: 'users',
|
||||
relationObjectMetadataNameSingular: 'user',
|
||||
},
|
||||
};
|
||||
|
||||
export const selectFieldDefinition: FieldDefinition<FieldSelectMetadata> = {
|
||||
fieldMetadataId,
|
||||
label: 'Account Owner',
|
||||
iconName: 'iconName',
|
||||
type: 'SELECT',
|
||||
metadata: {
|
||||
fieldName: 'accountOwner',
|
||||
options: [{ label: 'Elon Musk', color: 'blue', value: 'userId' }],
|
||||
},
|
||||
};
|
||||
|
||||
export const fullNameFieldDefinition: FieldDefinition<FieldFullNameMetadata> = {
|
||||
fieldMetadataId,
|
||||
label: 'Display Name',
|
||||
iconName: 'profile',
|
||||
type: 'FULL_NAME',
|
||||
metadata: {
|
||||
fieldName: 'displayName',
|
||||
placeHolder: 'Mr Miagi',
|
||||
},
|
||||
};
|
||||
|
||||
export const linkFieldDefinition: FieldDefinition<FieldLinkMetadata> = {
|
||||
fieldMetadataId,
|
||||
label: 'LinkedIn URL',
|
||||
iconName: 'url',
|
||||
type: 'LINK',
|
||||
metadata: {
|
||||
fieldName: 'linkedInURL',
|
||||
placeHolder: 'https://linkedin.com/user',
|
||||
},
|
||||
};
|
||||
|
||||
export const phoneFieldDefinition: FieldDefinition<FieldPhoneMetadata> = {
|
||||
fieldMetadataId,
|
||||
label: 'Contact',
|
||||
iconName: 'Phone',
|
||||
type: 'TEXT',
|
||||
metadata: {
|
||||
objectMetadataNameSingular: 'person',
|
||||
placeHolder: '(+256)-712-345-6789',
|
||||
fieldName: 'phone',
|
||||
},
|
||||
};
|
||||
|
||||
export const ratingfieldDefinition: FieldDefinition<FieldRatingMetadata> = {
|
||||
fieldMetadataId,
|
||||
label: 'Rating',
|
||||
iconName: 'iconName',
|
||||
type: 'RATING',
|
||||
metadata: {
|
||||
fieldName: 'rating',
|
||||
},
|
||||
};
|
||||
@ -0,0 +1,62 @@
|
||||
import { ReactNode } from 'react';
|
||||
import { act, renderHook } from '@testing-library/react';
|
||||
import { RecoilRoot, useSetRecoilState } from 'recoil';
|
||||
|
||||
import {
|
||||
fieldMetadataId,
|
||||
textfieldDefinition,
|
||||
} from '@/object-record/field/__mocks__/fieldDefinitions';
|
||||
import { FieldContext } from '@/object-record/field/contexts/FieldContext';
|
||||
import { entityFieldInitialValueFamilyState } from '@/object-record/field/states/entityFieldInitialValueFamilyState';
|
||||
|
||||
import { useFieldInitialValue } from '../useFieldInitialValue';
|
||||
|
||||
const entityId = 'entityId';
|
||||
|
||||
const wrapper = ({ children }: { children: ReactNode }) => (
|
||||
<RecoilRoot>
|
||||
<FieldContext.Provider
|
||||
value={{
|
||||
fieldDefinition: textfieldDefinition,
|
||||
entityId,
|
||||
hotkeyScope: 'hotkeyScope',
|
||||
isLabelIdentifier: false,
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</FieldContext.Provider>
|
||||
</RecoilRoot>
|
||||
);
|
||||
|
||||
describe('useFieldInitialValue', () => {
|
||||
it('should work as expected', () => {
|
||||
const { result } = renderHook(
|
||||
() => {
|
||||
const setFieldInitialValue = useSetRecoilState(
|
||||
entityFieldInitialValueFamilyState({
|
||||
fieldMetadataId,
|
||||
entityId,
|
||||
}),
|
||||
);
|
||||
|
||||
return {
|
||||
setFieldInitialValue,
|
||||
fieldInitialValue: useFieldInitialValue(),
|
||||
};
|
||||
},
|
||||
{
|
||||
wrapper,
|
||||
},
|
||||
);
|
||||
|
||||
expect(result.current.fieldInitialValue).toBeUndefined();
|
||||
|
||||
const initialValue = { isEmpty: false, value: 'Sheldon Cooper' };
|
||||
|
||||
act(() => {
|
||||
result.current.setFieldInitialValue(initialValue);
|
||||
});
|
||||
|
||||
expect(result.current.fieldInitialValue).toEqual(initialValue);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,54 @@
|
||||
import { ReactNode } from 'react';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
|
||||
import {
|
||||
phoneFieldDefinition,
|
||||
relationFieldDefinition,
|
||||
} from '@/object-record/field/__mocks__/fieldDefinitions';
|
||||
import { FieldContext } from '@/object-record/field/contexts/FieldContext';
|
||||
import { useGetButtonIcon } from '@/object-record/field/hooks/useGetButtonIcon';
|
||||
import { FieldDefinition } from '@/object-record/field/types/FieldDefinition';
|
||||
import { FieldMetadata } from '@/object-record/field/types/FieldMetadata';
|
||||
import { IconPencil } from '@/ui/display/icon';
|
||||
|
||||
const entityId = 'entityId';
|
||||
|
||||
const getWrapper =
|
||||
(fieldDefinition: FieldDefinition<FieldMetadata>) =>
|
||||
({ children }: { children: ReactNode }) => (
|
||||
<FieldContext.Provider
|
||||
value={{
|
||||
fieldDefinition,
|
||||
entityId,
|
||||
hotkeyScope: 'hotkeyScope',
|
||||
isLabelIdentifier: false,
|
||||
}}
|
||||
>
|
||||
<RecoilRoot>{children}</RecoilRoot>
|
||||
</FieldContext.Provider>
|
||||
);
|
||||
|
||||
const PhoneWrapper = getWrapper(phoneFieldDefinition);
|
||||
const RelationWrapper = getWrapper(relationFieldDefinition);
|
||||
|
||||
describe('useGetButtonIcon', () => {
|
||||
it('should return undefined', () => {
|
||||
const { result } = renderHook(() => useGetButtonIcon());
|
||||
expect(result.current).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should return icon pencil', () => {
|
||||
const { result } = renderHook(() => useGetButtonIcon(), {
|
||||
wrapper: PhoneWrapper,
|
||||
});
|
||||
expect(result.current).toEqual(IconPencil);
|
||||
});
|
||||
|
||||
it('should return iconPencil for relation field', () => {
|
||||
const { result } = renderHook(() => useGetButtonIcon(), {
|
||||
wrapper: RelationWrapper,
|
||||
});
|
||||
expect(result.current).toEqual(IconPencil);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,52 @@
|
||||
import { ReactNode } from 'react';
|
||||
import { act, renderHook } from '@testing-library/react';
|
||||
import { RecoilRoot, useSetRecoilState } from 'recoil';
|
||||
|
||||
import { phoneFieldDefinition } from '@/object-record/field/__mocks__/fieldDefinitions';
|
||||
import { FieldContext } from '@/object-record/field/contexts/FieldContext';
|
||||
import { useIsFieldEditModeValueEmpty } from '@/object-record/field/hooks/useIsFieldEditModeValueEmpty';
|
||||
import { entityFieldsEditModeValueFamilyState } from '@/object-record/field/states/entityFieldsEditModeValueFamilyState';
|
||||
|
||||
const entityId = 'entityId';
|
||||
|
||||
const Wrapper = ({ children }: { children: ReactNode }) => (
|
||||
<FieldContext.Provider
|
||||
value={{
|
||||
fieldDefinition: phoneFieldDefinition,
|
||||
entityId,
|
||||
hotkeyScope: 'hotkeyScope',
|
||||
isLabelIdentifier: false,
|
||||
}}
|
||||
>
|
||||
<RecoilRoot>{children}</RecoilRoot>
|
||||
</FieldContext.Provider>
|
||||
);
|
||||
|
||||
describe('useIsFieldEditModeValueEmpty', () => {
|
||||
it('should work as expected', () => {
|
||||
const { result } = renderHook(
|
||||
() => {
|
||||
const setFieldEditModeValue = useSetRecoilState(
|
||||
entityFieldsEditModeValueFamilyState(entityId),
|
||||
);
|
||||
return {
|
||||
setFieldEditModeValue,
|
||||
isFieldEditModeValueEmpty: useIsFieldEditModeValueEmpty(),
|
||||
};
|
||||
},
|
||||
{
|
||||
wrapper: Wrapper,
|
||||
},
|
||||
);
|
||||
|
||||
expect(result.current.isFieldEditModeValueEmpty).toBe(true);
|
||||
|
||||
act(() => {
|
||||
result.current.setFieldEditModeValue({
|
||||
phone: '+1 233223',
|
||||
});
|
||||
});
|
||||
|
||||
expect(result.current.isFieldEditModeValueEmpty).toBe(false);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,53 @@
|
||||
import { ReactNode } from 'react';
|
||||
import { act, renderHook } from '@testing-library/react';
|
||||
import { RecoilRoot, useSetRecoilState } from 'recoil';
|
||||
|
||||
import { phoneFieldDefinition } from '@/object-record/field/__mocks__/fieldDefinitions';
|
||||
import { FieldContext } from '@/object-record/field/contexts/FieldContext';
|
||||
import { useIsFieldEmpty } from '@/object-record/field/hooks/useIsFieldEmpty';
|
||||
import { entityFieldsFamilyState } from '@/object-record/field/states/entityFieldsFamilyState';
|
||||
|
||||
const entityId = 'entityId';
|
||||
|
||||
const Wrapper = ({ children }: { children: ReactNode }) => (
|
||||
<FieldContext.Provider
|
||||
value={{
|
||||
fieldDefinition: phoneFieldDefinition,
|
||||
entityId,
|
||||
hotkeyScope: 'hotkeyScope',
|
||||
isLabelIdentifier: false,
|
||||
}}
|
||||
>
|
||||
<RecoilRoot>{children}</RecoilRoot>
|
||||
</FieldContext.Provider>
|
||||
);
|
||||
|
||||
describe('useIsFieldEmpty', () => {
|
||||
it('should work as expected', () => {
|
||||
const { result } = renderHook(
|
||||
() => {
|
||||
const setFieldState = useSetRecoilState(
|
||||
entityFieldsFamilyState(entityId),
|
||||
);
|
||||
return {
|
||||
setFieldState,
|
||||
isFieldEditModeValueEmpty: useIsFieldEmpty(),
|
||||
};
|
||||
},
|
||||
{
|
||||
wrapper: Wrapper,
|
||||
},
|
||||
);
|
||||
|
||||
expect(result.current.isFieldEditModeValueEmpty).toBe(true);
|
||||
|
||||
act(() => {
|
||||
result.current.setFieldState({
|
||||
id: 'id',
|
||||
phone: '+1 233223',
|
||||
});
|
||||
});
|
||||
|
||||
expect(result.current.isFieldEditModeValueEmpty).toBe(false);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,50 @@
|
||||
import { ReactNode } from 'react';
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
|
||||
import {
|
||||
phoneFieldDefinition,
|
||||
ratingfieldDefinition,
|
||||
} from '@/object-record/field/__mocks__/fieldDefinitions';
|
||||
import { FieldContext } from '@/object-record/field/contexts/FieldContext';
|
||||
import { useIsFieldInputOnly } from '@/object-record/field/hooks/useIsFieldInputOnly';
|
||||
import { FieldDefinition } from '@/object-record/field/types/FieldDefinition';
|
||||
import { FieldMetadata } from '@/object-record/field/types/FieldMetadata';
|
||||
|
||||
const entityId = 'entityId';
|
||||
|
||||
const getWrapper =
|
||||
(fieldDefinition: FieldDefinition<FieldMetadata>) =>
|
||||
({ children }: { children: ReactNode }) => (
|
||||
<FieldContext.Provider
|
||||
value={{
|
||||
fieldDefinition,
|
||||
entityId,
|
||||
hotkeyScope: 'hotkeyScope',
|
||||
isLabelIdentifier: false,
|
||||
}}
|
||||
>
|
||||
<RecoilRoot>{children}</RecoilRoot>
|
||||
</FieldContext.Provider>
|
||||
);
|
||||
|
||||
const RatingWrapper = getWrapper(ratingfieldDefinition);
|
||||
const PhoneWrapper = getWrapper(phoneFieldDefinition);
|
||||
|
||||
describe('useIsFieldInputOnly', () => {
|
||||
it('should return true', () => {
|
||||
const { result } = renderHook(() => useIsFieldInputOnly(), {
|
||||
wrapper: RatingWrapper,
|
||||
});
|
||||
|
||||
expect(result.current).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false', () => {
|
||||
const { result } = renderHook(() => useIsFieldInputOnly(), {
|
||||
wrapper: PhoneWrapper,
|
||||
});
|
||||
|
||||
expect(result.current).toBe(false);
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,159 @@
|
||||
import { ReactNode } from 'react';
|
||||
import { gql } from '@apollo/client';
|
||||
import { MockedProvider, MockedResponse } from '@apollo/client/testing';
|
||||
import { act, renderHook, waitFor } from '@testing-library/react';
|
||||
import { RecoilRoot, useRecoilValue } from 'recoil';
|
||||
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import {
|
||||
phoneFieldDefinition,
|
||||
relationFieldDefinition,
|
||||
} from '@/object-record/field/__mocks__/fieldDefinitions';
|
||||
import {
|
||||
FieldContext,
|
||||
RecordUpdateHook,
|
||||
RecordUpdateHookParams,
|
||||
} from '@/object-record/field/contexts/FieldContext';
|
||||
import { usePersistField } from '@/object-record/field/hooks/usePersistField';
|
||||
import { entityFieldsFamilySelector } from '@/object-record/field/states/selectors/entityFieldsFamilySelector';
|
||||
import { FieldDefinition } from '@/object-record/field/types/FieldDefinition';
|
||||
import { FieldMetadata } from '@/object-record/field/types/FieldMetadata';
|
||||
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
|
||||
|
||||
jest.mock('@/object-metadata/hooks/useMapFieldMetadataToGraphQLQuery', () => ({
|
||||
useMapFieldMetadataToGraphQLQuery: () => () => '\n',
|
||||
}));
|
||||
|
||||
const query = gql`
|
||||
mutation UpdateOneWorkspaceMember(
|
||||
$idToUpdate: ID!
|
||||
$input: WorkspaceMemberUpdateInput!
|
||||
) {
|
||||
updateWorkspaceMember(id: $idToUpdate, data: $input) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const mocks: MockedResponse[] = [
|
||||
{
|
||||
request: {
|
||||
query,
|
||||
variables: { idToUpdate: 'entityId', input: { phone: '+1 123 456' } },
|
||||
},
|
||||
result: jest.fn(() => ({
|
||||
data: {
|
||||
updateWorkspaceMember: {
|
||||
id: 'entityId',
|
||||
},
|
||||
},
|
||||
})),
|
||||
},
|
||||
{
|
||||
request: {
|
||||
query,
|
||||
variables: {
|
||||
idToUpdate: 'entityId',
|
||||
input: { contactId: null, contact: { foo: 'bar' } },
|
||||
},
|
||||
},
|
||||
result: jest.fn(() => ({
|
||||
data: {
|
||||
updateWorkspaceMember: {
|
||||
id: 'entityId',
|
||||
},
|
||||
},
|
||||
})),
|
||||
},
|
||||
];
|
||||
|
||||
const entityId = 'entityId';
|
||||
const fieldName = 'phone';
|
||||
|
||||
const getWrapper =
|
||||
(fieldDefinition: FieldDefinition<FieldMetadata>) =>
|
||||
({ children }: { children: ReactNode }) => {
|
||||
const useUpdateOneRecordMutation: RecordUpdateHook = () => {
|
||||
const { updateOneRecord } = useUpdateOneRecord({
|
||||
objectNameSingular: CoreObjectNameSingular.WorkspaceMember,
|
||||
});
|
||||
|
||||
const updateEntity = ({ variables }: RecordUpdateHookParams) => {
|
||||
updateOneRecord?.({
|
||||
idToUpdate: variables.where.id as string,
|
||||
updateOneRecordInput: variables.updateOneRecordInput,
|
||||
});
|
||||
};
|
||||
|
||||
return [updateEntity, { loading: false }];
|
||||
};
|
||||
|
||||
return (
|
||||
<MockedProvider mocks={mocks} addTypename={false}>
|
||||
<FieldContext.Provider
|
||||
value={{
|
||||
fieldDefinition,
|
||||
entityId,
|
||||
hotkeyScope: 'hotkeyScope',
|
||||
isLabelIdentifier: false,
|
||||
useUpdateRecord: useUpdateOneRecordMutation,
|
||||
}}
|
||||
>
|
||||
<RecoilRoot>{children}</RecoilRoot>
|
||||
</FieldContext.Provider>
|
||||
</MockedProvider>
|
||||
);
|
||||
};
|
||||
|
||||
const PhoneWrapper = getWrapper(phoneFieldDefinition);
|
||||
const RelationWrapper = getWrapper(relationFieldDefinition);
|
||||
|
||||
describe('usePersistField', () => {
|
||||
it('should work as expected', async () => {
|
||||
const { result } = renderHook(
|
||||
() => {
|
||||
const entityFields = useRecoilValue(
|
||||
entityFieldsFamilySelector({ entityId, fieldName }),
|
||||
);
|
||||
|
||||
return {
|
||||
persistField: usePersistField(),
|
||||
entityFields,
|
||||
};
|
||||
},
|
||||
{ wrapper: PhoneWrapper },
|
||||
);
|
||||
|
||||
act(() => {
|
||||
result.current.persistField('+1 123 456');
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mocks[0].result).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it('should persist relation field', async () => {
|
||||
const { result } = renderHook(
|
||||
() => {
|
||||
const entityFields = useRecoilValue(
|
||||
entityFieldsFamilySelector({ entityId, fieldName }),
|
||||
);
|
||||
|
||||
return {
|
||||
persistField: usePersistField(),
|
||||
entityFields,
|
||||
};
|
||||
},
|
||||
{ wrapper: RelationWrapper },
|
||||
);
|
||||
|
||||
act(() => {
|
||||
result.current.persistField({ foo: 'bar' });
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mocks[1].result).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,57 @@
|
||||
import { ReactNode } from 'react';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { act, renderHook } from '@testing-library/react';
|
||||
import { RecoilRoot, useRecoilValue } from 'recoil';
|
||||
|
||||
import { phoneFieldDefinition } from '@/object-record/field/__mocks__/fieldDefinitions';
|
||||
import { FieldContext } from '@/object-record/field/contexts/FieldContext';
|
||||
import { useSaveFieldEditModeValue } from '@/object-record/field/hooks/useSaveFieldEditModeValue';
|
||||
import { entityFieldsEditModeValueFamilySelector } from '@/object-record/field/states/selectors/entityFieldsEditModeValueFamilySelector';
|
||||
|
||||
const entityId = 'entityId';
|
||||
const fieldName = 'phone';
|
||||
|
||||
const Wrapper = ({ children }: { children: ReactNode }) => {
|
||||
return (
|
||||
<MockedProvider addTypename={false}>
|
||||
<FieldContext.Provider
|
||||
value={{
|
||||
fieldDefinition: phoneFieldDefinition,
|
||||
entityId,
|
||||
hotkeyScope: 'hotkeyScope',
|
||||
isLabelIdentifier: false,
|
||||
}}
|
||||
>
|
||||
<RecoilRoot>{children}</RecoilRoot>
|
||||
</FieldContext.Provider>
|
||||
</MockedProvider>
|
||||
);
|
||||
};
|
||||
|
||||
describe('useSaveFieldEditModeValue', () => {
|
||||
it('should work as expected', () => {
|
||||
const {
|
||||
result: { current },
|
||||
} = renderHook(
|
||||
() => {
|
||||
const entityFieldsEditModeValue = useRecoilValue(
|
||||
entityFieldsEditModeValueFamilySelector({ entityId, fieldName }),
|
||||
);
|
||||
return {
|
||||
saveFieldEditModeValue: useSaveFieldEditModeValue(),
|
||||
entityFieldsEditModeValue,
|
||||
};
|
||||
},
|
||||
{ wrapper: Wrapper },
|
||||
);
|
||||
|
||||
expect(current.entityFieldsEditModeValue).toBeUndefined();
|
||||
|
||||
act(() => {
|
||||
current.saveFieldEditModeValue('test');
|
||||
});
|
||||
|
||||
// We expect `current.entityFieldsEditModeValue` to be updated
|
||||
// but I think it's async
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,95 @@
|
||||
import { ReactNode } from 'react';
|
||||
import { gql } from '@apollo/client';
|
||||
import { MockedProvider, MockedResponse } from '@apollo/client/testing';
|
||||
import { act, renderHook, waitFor } from '@testing-library/react';
|
||||
import { RecoilRoot } from 'recoil';
|
||||
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { booleanFieldDefinition } from '@/object-record/field/__mocks__/fieldDefinitions';
|
||||
import {
|
||||
FieldContext,
|
||||
RecordUpdateHook,
|
||||
RecordUpdateHookParams,
|
||||
} from '@/object-record/field/contexts/FieldContext';
|
||||
import { useToggleEditOnlyInput } from '@/object-record/field/hooks/useToggleEditOnlyInput';
|
||||
import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord';
|
||||
|
||||
jest.mock('@/object-metadata/hooks/useMapFieldMetadataToGraphQLQuery', () => ({
|
||||
useMapFieldMetadataToGraphQLQuery: () => () => '\n',
|
||||
}));
|
||||
|
||||
const entityId = 'entityId';
|
||||
|
||||
const mocks: MockedResponse[] = [
|
||||
{
|
||||
request: {
|
||||
query: gql`
|
||||
mutation UpdateOnePerson($idToUpdate: ID!, $input: PersonUpdateInput!) {
|
||||
updatePerson(id: $idToUpdate, data: $input) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`,
|
||||
variables: { idToUpdate: 'entityId', input: { isActive: true } },
|
||||
},
|
||||
result: jest.fn(() => ({
|
||||
data: {
|
||||
updateWorkspaceMember: {
|
||||
id: 'entityId',
|
||||
},
|
||||
},
|
||||
})),
|
||||
},
|
||||
];
|
||||
|
||||
const Wrapper = ({ children }: { children: ReactNode }) => {
|
||||
const useUpdateOneRecordMutation: RecordUpdateHook = () => {
|
||||
const { updateOneRecord } = useUpdateOneRecord({
|
||||
objectNameSingular: CoreObjectNameSingular.Person,
|
||||
});
|
||||
|
||||
const updateEntity = ({ variables }: RecordUpdateHookParams) => {
|
||||
updateOneRecord?.({
|
||||
idToUpdate: variables.where.id as string,
|
||||
updateOneRecordInput: variables.updateOneRecordInput,
|
||||
});
|
||||
};
|
||||
|
||||
return [updateEntity, { loading: false }];
|
||||
};
|
||||
|
||||
return (
|
||||
<MockedProvider mocks={mocks} addTypename={false}>
|
||||
<FieldContext.Provider
|
||||
value={{
|
||||
fieldDefinition: booleanFieldDefinition,
|
||||
entityId,
|
||||
hotkeyScope: 'hotkeyScope',
|
||||
isLabelIdentifier: false,
|
||||
useUpdateRecord: useUpdateOneRecordMutation,
|
||||
}}
|
||||
>
|
||||
<RecoilRoot>{children}</RecoilRoot>
|
||||
</FieldContext.Provider>
|
||||
</MockedProvider>
|
||||
);
|
||||
};
|
||||
|
||||
describe('useToggleEditOnlyInput', () => {
|
||||
it('should toggle field', async () => {
|
||||
const { result } = renderHook(
|
||||
() => ({ toggleField: useToggleEditOnlyInput() }),
|
||||
{
|
||||
wrapper: Wrapper,
|
||||
},
|
||||
);
|
||||
|
||||
act(() => {
|
||||
result.current.toggleField();
|
||||
});
|
||||
|
||||
await waitFor(() => {
|
||||
expect(mocks[0].result).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,118 @@
|
||||
import {
|
||||
booleanFieldDefinition,
|
||||
fieldMetadataId,
|
||||
fullNameFieldDefinition,
|
||||
linkFieldDefinition,
|
||||
relationFieldDefinition,
|
||||
selectFieldDefinition,
|
||||
} from '@/object-record/field/__mocks__/fieldDefinitions';
|
||||
import { FieldDefinition } from '@/object-record/field/types/FieldDefinition';
|
||||
import { FieldCurrencyMetadata } from '@/object-record/field/types/FieldMetadata';
|
||||
|
||||
import { isFieldValueEmpty } from '../isFieldValueEmpty';
|
||||
|
||||
describe('isFieldValueEmpty', () => {
|
||||
it('should return correct value for boolean field', () => {
|
||||
expect(
|
||||
isFieldValueEmpty({
|
||||
fieldDefinition: booleanFieldDefinition,
|
||||
fieldValue: null,
|
||||
}),
|
||||
).toBe(true);
|
||||
expect(
|
||||
isFieldValueEmpty({
|
||||
fieldDefinition: booleanFieldDefinition,
|
||||
fieldValue: false,
|
||||
}),
|
||||
).toBe(false);
|
||||
expect(
|
||||
isFieldValueEmpty({
|
||||
fieldDefinition: booleanFieldDefinition,
|
||||
fieldValue: true,
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should return correct value for relation field', () => {
|
||||
expect(
|
||||
isFieldValueEmpty({
|
||||
fieldDefinition: relationFieldDefinition,
|
||||
fieldValue: null,
|
||||
}),
|
||||
).toBe(true);
|
||||
expect(
|
||||
isFieldValueEmpty({
|
||||
fieldDefinition: relationFieldDefinition,
|
||||
fieldValue: { foo: 'bar' },
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should return correct value for select field', () => {
|
||||
// If the value does not match the fieldDefinition, it will always return `false`
|
||||
// Should it return `false` or `true` if the fieldValue doesn't match?
|
||||
expect(
|
||||
isFieldValueEmpty({
|
||||
fieldDefinition: selectFieldDefinition,
|
||||
fieldValue: '',
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should return correct value for currency field', () => {
|
||||
const fieldDefinition: FieldDefinition<FieldCurrencyMetadata> = {
|
||||
fieldMetadataId,
|
||||
label: 'Annual Income',
|
||||
iconName: 'cashCow',
|
||||
type: 'CURRENCY',
|
||||
metadata: {
|
||||
fieldName: 'annualIncome',
|
||||
placeHolder: '100000',
|
||||
isPositive: true,
|
||||
},
|
||||
};
|
||||
|
||||
expect(
|
||||
isFieldValueEmpty({
|
||||
fieldDefinition,
|
||||
fieldValue: { currencyCode: 'USD', amountMicros: 1000000 },
|
||||
}),
|
||||
).toBe(false);
|
||||
expect(
|
||||
isFieldValueEmpty({
|
||||
fieldDefinition,
|
||||
fieldValue: { currencyCode: 'USD' },
|
||||
}),
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
it('should return correct value for fullname field', () => {
|
||||
expect(
|
||||
isFieldValueEmpty({
|
||||
fieldDefinition: fullNameFieldDefinition,
|
||||
fieldValue: { firstName: '', lastName: '' },
|
||||
}),
|
||||
).toBe(true);
|
||||
expect(
|
||||
isFieldValueEmpty({
|
||||
fieldDefinition: fullNameFieldDefinition,
|
||||
fieldValue: { firstName: 'Sheldon', lastName: '' },
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should return correct value for link field', () => {
|
||||
expect(
|
||||
isFieldValueEmpty({
|
||||
fieldDefinition: linkFieldDefinition,
|
||||
fieldValue: { url: '', label: '' },
|
||||
}),
|
||||
).toBe(true);
|
||||
expect(
|
||||
isFieldValueEmpty({
|
||||
fieldDefinition: linkFieldDefinition,
|
||||
fieldValue: { url: 'https://linkedin.com/user-slug', label: '' },
|
||||
}),
|
||||
).toBe(false);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user