mirror of
https://github.com/twentyhq/twenty.git
synced 2024-12-25 04:55:30 +03:00
Add jest tests for twenty-front (#2983)
* Add jest tests for twenty-front Co-authored-by: v1b3m <vibenjamin6@gmail.com> * Fix tests --------- 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:
parent
af9d3fb217
commit
5f7442cf23
@ -14,7 +14,7 @@ export default {
|
|||||||
global: {
|
global: {
|
||||||
statements: 10,
|
statements: 10,
|
||||||
lines: 10,
|
lines: 10,
|
||||||
functions: 10,
|
functions: 7,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
collectCoverage: true,
|
collectCoverage: true,
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { renderHook } from '@testing-library/react';
|
||||||
|
|
||||||
|
import { useCombinedRefs } from '~/hooks/useCombinedRefs';
|
||||||
|
|
||||||
|
describe('useCombinedRefs', () => {
|
||||||
|
it('should combine refs', () => {
|
||||||
|
const { result } = renderHook(() => {
|
||||||
|
const ref1 = React.useRef<string>(null);
|
||||||
|
const ref2 = React.useRef<string>(null);
|
||||||
|
const refCallback = useCombinedRefs(ref1, ref2);
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
refCallback('test');
|
||||||
|
}, [refCallback]);
|
||||||
|
|
||||||
|
return [ref1, ref2];
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result.current[0].current).toBe('test');
|
||||||
|
expect(result.current[1].current).toBe('test');
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,23 @@
|
|||||||
|
import { renderHook } from '@testing-library/react';
|
||||||
|
|
||||||
|
import { useFirstMountState } from '~/hooks/useFirstMountState';
|
||||||
|
|
||||||
|
describe('useFirstMountState', () => {
|
||||||
|
it('should return true on first mount', () => {
|
||||||
|
const { result } = renderHook(() => {
|
||||||
|
return useFirstMountState();
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result.current).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false on second mount', () => {
|
||||||
|
const { result, rerender } = renderHook(() => {
|
||||||
|
return useFirstMountState();
|
||||||
|
});
|
||||||
|
|
||||||
|
rerender();
|
||||||
|
|
||||||
|
expect(result.current).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,39 @@
|
|||||||
|
import { MemoryRouter } from 'react-router-dom';
|
||||||
|
import { renderHook } from '@testing-library/react';
|
||||||
|
|
||||||
|
import { useIsMatchingLocation } from '~/hooks/useIsMatchingLocation';
|
||||||
|
|
||||||
|
const Wrapper = ({ children }: { children: React.ReactNode }) => (
|
||||||
|
<MemoryRouter
|
||||||
|
initialEntries={['/one', '/two', { pathname: '/three' }]}
|
||||||
|
initialIndex={1}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</MemoryRouter>
|
||||||
|
);
|
||||||
|
|
||||||
|
describe('useIsMatchingLocation', () => {
|
||||||
|
it('should return true for a matching location', () => {
|
||||||
|
const { result } = renderHook(
|
||||||
|
() => {
|
||||||
|
const checkMatchingLocation = useIsMatchingLocation();
|
||||||
|
return checkMatchingLocation('/two');
|
||||||
|
},
|
||||||
|
{ wrapper: Wrapper },
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result.current).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false for a non-matching location', () => {
|
||||||
|
const { result } = renderHook(
|
||||||
|
() => {
|
||||||
|
const checkMatchingLocation = useIsMatchingLocation();
|
||||||
|
return checkMatchingLocation('/four');
|
||||||
|
},
|
||||||
|
{ wrapper: Wrapper },
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(result.current).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,18 @@
|
|||||||
|
import { renderHook } from '@testing-library/react';
|
||||||
|
|
||||||
|
import { useUpdateEffect } from '~/hooks/useUpdateEffect';
|
||||||
|
|
||||||
|
describe('useUpdateEffect', () => {
|
||||||
|
it('should call the effect callback on update', () => {
|
||||||
|
const effect = jest.fn();
|
||||||
|
const { rerender } = renderHook(() => {
|
||||||
|
useUpdateEffect(effect);
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(effect).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
rerender();
|
||||||
|
|
||||||
|
expect(effect).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
});
|
@ -3,6 +3,7 @@ import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
|
|||||||
|
|
||||||
import { ActivityTargetableEntity } from '../../types/ActivityTargetableEntity';
|
import { ActivityTargetableEntity } from '../../types/ActivityTargetableEntity';
|
||||||
|
|
||||||
|
// do we need to test this?
|
||||||
export const useAttachments = (entity: ActivityTargetableEntity) => {
|
export const useAttachments = (entity: ActivityTargetableEntity) => {
|
||||||
const { records: attachments } = useFindManyRecords({
|
const { records: attachments } = useFindManyRecords({
|
||||||
objectNameSingular: 'attachment',
|
objectNameSingular: 'attachment',
|
||||||
|
@ -0,0 +1,43 @@
|
|||||||
|
import { downloadFile } from '../downloadFile';
|
||||||
|
|
||||||
|
// Mock fetch
|
||||||
|
global.fetch = jest.fn(() =>
|
||||||
|
Promise.resolve({
|
||||||
|
status: 200,
|
||||||
|
blob: jest.fn(),
|
||||||
|
} as unknown as Response),
|
||||||
|
);
|
||||||
|
|
||||||
|
window.URL.createObjectURL = jest.fn(() => 'mock-url');
|
||||||
|
window.URL.revokeObjectURL = jest.fn();
|
||||||
|
|
||||||
|
// FIXME: jest is behaving weirdly here, it's not finding the element
|
||||||
|
// Also the document's innerHTML is empty
|
||||||
|
// `global.fetch` and `window.fetch` are also undefined
|
||||||
|
describe.skip('downloadFile', () => {
|
||||||
|
it('should download a file', () => {
|
||||||
|
// Call downloadFile
|
||||||
|
downloadFile('path/to/file.pdf', 'file.pdf');
|
||||||
|
|
||||||
|
// Assert on fetch
|
||||||
|
expect(fetch).toHaveBeenCalledWith(
|
||||||
|
process.env.REACT_APP_SERVER_BASE_URL + '/files/path/to/file.pdf',
|
||||||
|
);
|
||||||
|
|
||||||
|
// Assert on element creation
|
||||||
|
const link = document.querySelector(
|
||||||
|
'a[href="mock-url"][download="file.pdf"]',
|
||||||
|
);
|
||||||
|
console.log(document.body.innerHTML, link);
|
||||||
|
expect(link).not.toBeNull();
|
||||||
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||||
|
// @ts-ignore
|
||||||
|
expect(link?.style?.display).toBe('none');
|
||||||
|
|
||||||
|
// Assert on element click
|
||||||
|
expect(link).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
|
// Clean up mocks
|
||||||
|
jest.clearAllMocks();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,13 @@
|
|||||||
|
import { getFileType } from '../getFileType';
|
||||||
|
|
||||||
|
describe('getFileType', () => {
|
||||||
|
it('should return the correct file type for a given file name', () => {
|
||||||
|
expect(getFileType('test.doc')).toBe('TextDocument');
|
||||||
|
expect(getFileType('test.xls')).toBe('Spreadsheet');
|
||||||
|
expect(getFileType('test.ppt')).toBe('Presentation');
|
||||||
|
expect(getFileType('test.png')).toBe('Image');
|
||||||
|
expect(getFileType('test.mp4')).toBe('Video');
|
||||||
|
expect(getFileType('test.mp3')).toBe('Audio');
|
||||||
|
expect(getFileType('test.zip')).toBe('Archive');
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,22 @@
|
|||||||
|
import { ActivityForDrawer } from '@/activities/types/ActivityForDrawer';
|
||||||
|
import { mockedActivities } from '~/testing/mock-data/activities';
|
||||||
|
|
||||||
|
import { groupActivitiesByMonth } from '../groupActivitiesByMonth';
|
||||||
|
|
||||||
|
describe('groupActivitiesByMonth', () => {
|
||||||
|
it('should group activities by month', () => {
|
||||||
|
const grouped = groupActivitiesByMonth(
|
||||||
|
mockedActivities as unknown as ActivityForDrawer[],
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(grouped).toHaveLength(2);
|
||||||
|
expect(grouped[0].items).toHaveLength(1);
|
||||||
|
expect(grouped[1].items).toHaveLength(1);
|
||||||
|
|
||||||
|
expect(grouped[0].year).toBe(2023);
|
||||||
|
expect(grouped[1].year).toBe(2023);
|
||||||
|
|
||||||
|
expect(grouped[0].month).toBe(11);
|
||||||
|
expect(grouped[1].month).toBe(3);
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,27 @@
|
|||||||
|
import { EntityForSelect } from '@/object-record/relation-picker/types/EntityForSelect';
|
||||||
|
|
||||||
|
import { flatMapAndSortEntityForSelectArrayOfArrayByName } from '../flatMapAndSortEntityForSelectArrayByName';
|
||||||
|
|
||||||
|
describe('flatMapAndSortEntityForSelectArrayOfArrayByName', () => {
|
||||||
|
it('should return the correct value', () => {
|
||||||
|
const entityForSelectArray = [
|
||||||
|
[
|
||||||
|
{ id: 1, name: 'xRya' },
|
||||||
|
{ id: 2, name: 'BrcA' },
|
||||||
|
],
|
||||||
|
[
|
||||||
|
{ id: 3, name: 'aCxd' },
|
||||||
|
{ id: 4, name: 'kp7u' },
|
||||||
|
],
|
||||||
|
] as unknown as EntityForSelect[][];
|
||||||
|
|
||||||
|
const res =
|
||||||
|
flatMapAndSortEntityForSelectArrayOfArrayByName(entityForSelectArray);
|
||||||
|
|
||||||
|
expect(res).toHaveLength(4);
|
||||||
|
expect(res[0].id).toBe(3);
|
||||||
|
expect(res[1].id).toBe(2);
|
||||||
|
expect(res[2].id).toBe(4);
|
||||||
|
expect(res[3].id).toBe(1);
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,47 @@
|
|||||||
|
import { ActivityTargetableEntity } from '@/activities/types/ActivityTargetableEntity';
|
||||||
|
import { getTargetableEntitiesWithParents } from '@/activities/utils/getTargetableEntitiesWithParents';
|
||||||
|
|
||||||
|
describe('getTargetableEntitiesWithParents', () => {
|
||||||
|
it('should return the correct value', () => {
|
||||||
|
const entities: ActivityTargetableEntity[] = [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
type: 'Person',
|
||||||
|
relatedEntities: [
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
type: 'Company',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '4',
|
||||||
|
type: 'Company',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
type: 'Custom',
|
||||||
|
relatedEntities: [
|
||||||
|
{
|
||||||
|
id: '6',
|
||||||
|
type: 'Person',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '5',
|
||||||
|
type: 'Company',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const res = getTargetableEntitiesWithParents(entities);
|
||||||
|
|
||||||
|
expect(res).toHaveLength(6);
|
||||||
|
expect(res[0].id).toBe('1');
|
||||||
|
expect(res[1].id).toBe('2');
|
||||||
|
expect(res[2].id).toBe('4');
|
||||||
|
expect(res[3].id).toBe('3');
|
||||||
|
expect(res[4].id).toBe('6');
|
||||||
|
expect(res[5].id).toBe('5');
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,21 @@
|
|||||||
|
import { expect } from '@storybook/test';
|
||||||
|
|
||||||
|
import { OperationType } from '@/apollo/types/operation-type';
|
||||||
|
|
||||||
|
import formatTitle from '../format-title';
|
||||||
|
|
||||||
|
describe('formatTitle', () => {
|
||||||
|
it('should correctly format the title', () => {
|
||||||
|
const res = formatTitle(
|
||||||
|
OperationType.Query,
|
||||||
|
'default',
|
||||||
|
'GetCurrentUser',
|
||||||
|
1000,
|
||||||
|
);
|
||||||
|
const title = res[0];
|
||||||
|
|
||||||
|
expect(title).toBe(
|
||||||
|
'%c apollo %cquery %cdefault::%cGetCurrentUser %c(in 1000 ms)',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,4 @@
|
|||||||
|
// More work needed here
|
||||||
|
describe.skip('loggerLink', () => {
|
||||||
|
it('should log the correct message', () => {});
|
||||||
|
});
|
@ -0,0 +1,121 @@
|
|||||||
|
import { CurrentWorkspace } from '@/auth/states/currentWorkspaceState';
|
||||||
|
import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember';
|
||||||
|
|
||||||
|
import { getOnboardingStatus } from '../getOnboardingStatus';
|
||||||
|
|
||||||
|
describe('getOnboardingStatus', () => {
|
||||||
|
it('should return the correct status', () => {
|
||||||
|
const ongoingUserCreation = getOnboardingStatus({
|
||||||
|
isLoggedIn: false,
|
||||||
|
currentWorkspaceMember: null,
|
||||||
|
currentWorkspace: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
const unknownStatus = getOnboardingStatus({
|
||||||
|
isLoggedIn: true,
|
||||||
|
currentWorkspaceMember: null,
|
||||||
|
currentWorkspace: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
const ongoingWorkspaceCreation = getOnboardingStatus({
|
||||||
|
isLoggedIn: true,
|
||||||
|
currentWorkspaceMember: {
|
||||||
|
id: '1',
|
||||||
|
name: {
|
||||||
|
firstName: 'John',
|
||||||
|
lastName: 'Doe',
|
||||||
|
},
|
||||||
|
} as WorkspaceMember,
|
||||||
|
currentWorkspace: {
|
||||||
|
id: '1',
|
||||||
|
displayName: null,
|
||||||
|
} as CurrentWorkspace,
|
||||||
|
});
|
||||||
|
|
||||||
|
const ongoingProfileCreation = getOnboardingStatus({
|
||||||
|
isLoggedIn: true,
|
||||||
|
currentWorkspaceMember: {
|
||||||
|
id: '1',
|
||||||
|
name: {},
|
||||||
|
} as WorkspaceMember,
|
||||||
|
currentWorkspace: {
|
||||||
|
id: '1',
|
||||||
|
displayName: 'My Workspace',
|
||||||
|
} as CurrentWorkspace,
|
||||||
|
});
|
||||||
|
|
||||||
|
const completed = getOnboardingStatus({
|
||||||
|
isLoggedIn: true,
|
||||||
|
currentWorkspaceMember: {
|
||||||
|
id: '1',
|
||||||
|
name: {
|
||||||
|
firstName: 'John',
|
||||||
|
lastName: 'Doe',
|
||||||
|
},
|
||||||
|
} as WorkspaceMember,
|
||||||
|
currentWorkspace: {
|
||||||
|
id: '1',
|
||||||
|
displayName: 'My Workspace',
|
||||||
|
} as CurrentWorkspace,
|
||||||
|
});
|
||||||
|
|
||||||
|
const incomplete = getOnboardingStatus({
|
||||||
|
isLoggedIn: true,
|
||||||
|
currentWorkspaceMember: {
|
||||||
|
id: '1',
|
||||||
|
name: {
|
||||||
|
firstName: 'John',
|
||||||
|
lastName: 'Doe',
|
||||||
|
},
|
||||||
|
} as WorkspaceMember,
|
||||||
|
currentWorkspace: {
|
||||||
|
id: '1',
|
||||||
|
displayName: 'My Workspace',
|
||||||
|
subscriptionStatus: 'incomplete',
|
||||||
|
} as CurrentWorkspace,
|
||||||
|
isBillingEnabled: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const incompleteButBillingDisabled = getOnboardingStatus({
|
||||||
|
isLoggedIn: true,
|
||||||
|
currentWorkspaceMember: {
|
||||||
|
id: '1',
|
||||||
|
name: {
|
||||||
|
firstName: 'John',
|
||||||
|
lastName: 'Doe',
|
||||||
|
},
|
||||||
|
} as WorkspaceMember,
|
||||||
|
currentWorkspace: {
|
||||||
|
id: '1',
|
||||||
|
displayName: 'My Workspace',
|
||||||
|
subscriptionStatus: 'incomplete',
|
||||||
|
} as CurrentWorkspace,
|
||||||
|
});
|
||||||
|
|
||||||
|
const canceled = getOnboardingStatus({
|
||||||
|
isLoggedIn: true,
|
||||||
|
currentWorkspaceMember: {
|
||||||
|
id: '1',
|
||||||
|
name: {
|
||||||
|
firstName: 'John',
|
||||||
|
lastName: 'Doe',
|
||||||
|
},
|
||||||
|
} as WorkspaceMember,
|
||||||
|
currentWorkspace: {
|
||||||
|
id: '1',
|
||||||
|
displayName: 'My Workspace',
|
||||||
|
subscriptionStatus: 'canceled',
|
||||||
|
} as CurrentWorkspace,
|
||||||
|
isBillingEnabled: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(ongoingUserCreation).toBe('ongoing_user_creation');
|
||||||
|
expect(unknownStatus).toBe(undefined);
|
||||||
|
expect(ongoingWorkspaceCreation).toBe('ongoing_workspace_creation');
|
||||||
|
expect(ongoingProfileCreation).toBe('ongoing_profile_creation');
|
||||||
|
expect(completed).toBe('completed');
|
||||||
|
expect(incomplete).toBe('incomplete');
|
||||||
|
expect(canceled).toBe('canceled');
|
||||||
|
expect(incompleteButBillingDisabled).toBe('completed');
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,49 @@
|
|||||||
|
import { mapBoardFieldDefinitionsToViewFields } from '@/companies/utils/mapBoardFieldDefinitionsToViewFields';
|
||||||
|
import { FieldMetadata } from '@/object-record/field/types/FieldMetadata';
|
||||||
|
import { BoardFieldDefinition } from '@/object-record/record-board/types/BoardFieldDefinition';
|
||||||
|
|
||||||
|
describe('mapBoardFieldDefinitionsToViewFields', () => {
|
||||||
|
it('should map board field definitions to view fields', () => {
|
||||||
|
const fieldDefinitions: BoardFieldDefinition<FieldMetadata>[] = [
|
||||||
|
{
|
||||||
|
fieldMetadataId: 'fieldMetadataId',
|
||||||
|
label: 'label',
|
||||||
|
iconName: 'iconName',
|
||||||
|
type: 'BOOLEAN',
|
||||||
|
metadata: {
|
||||||
|
objectMetadataNameSingular: 'objectMetadataNameSingular',
|
||||||
|
fieldName: 'fieldName',
|
||||||
|
},
|
||||||
|
position: 0,
|
||||||
|
isVisible: true,
|
||||||
|
viewFieldId: 'viewFieldId',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldMetadataId: 'fieldMetadataId1',
|
||||||
|
label: 'label1',
|
||||||
|
iconName: 'iconName1',
|
||||||
|
type: 'NUMBER',
|
||||||
|
metadata: {
|
||||||
|
objectMetadataNameSingular: 'objectMetadataNameSingular1',
|
||||||
|
fieldName: 'fieldName1',
|
||||||
|
placeHolder: 'placeHolder1',
|
||||||
|
isPositive: true,
|
||||||
|
},
|
||||||
|
position: 1,
|
||||||
|
isVisible: false,
|
||||||
|
viewFieldId: 'viewFieldId1',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const viewFields = mapBoardFieldDefinitionsToViewFields(fieldDefinitions);
|
||||||
|
|
||||||
|
expect(viewFields).toHaveLength(2);
|
||||||
|
|
||||||
|
expect(viewFields[0]).toHaveProperty('id');
|
||||||
|
expect(viewFields[0]).toHaveProperty('size');
|
||||||
|
expect(viewFields[0]).toHaveProperty('position');
|
||||||
|
expect(viewFields[0]).toHaveProperty('isVisible');
|
||||||
|
|
||||||
|
expect(viewFields[0].definition).toEqual(fieldDefinitions[0]);
|
||||||
|
expect(viewFields[1].definition).toEqual(fieldDefinitions[1]);
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,50 @@
|
|||||||
|
import { mapFavorites } from '../mapFavorites';
|
||||||
|
|
||||||
|
describe('mapFavorites', () => {
|
||||||
|
it('should return the correct value', () => {
|
||||||
|
const favorites = [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
person: {
|
||||||
|
id: '2',
|
||||||
|
name: {
|
||||||
|
firstName: 'John',
|
||||||
|
lastName: 'Doe',
|
||||||
|
},
|
||||||
|
avatarUrl: 'https://example.com/avatar.png',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
company: {
|
||||||
|
id: '4',
|
||||||
|
name: 'My Company',
|
||||||
|
domainName: 'example.com',
|
||||||
|
},
|
||||||
|
position: 1,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const res = mapFavorites(favorites);
|
||||||
|
|
||||||
|
expect(res).toHaveLength(2);
|
||||||
|
|
||||||
|
// Person
|
||||||
|
expect(res[0].id).toBe('1');
|
||||||
|
expect(res[0].labelIdentifier).toBe('John Doe');
|
||||||
|
expect(res[0].avatarUrl).toBe('https://example.com/avatar.png');
|
||||||
|
expect(res[0].avatarType).toBe('rounded');
|
||||||
|
expect(res[0].link).toBe('/object/person/2');
|
||||||
|
expect(res[0].recordId).toBe('2');
|
||||||
|
expect(res[0].position).toBeUndefined();
|
||||||
|
|
||||||
|
// Company
|
||||||
|
expect(res[1].id).toBe('3');
|
||||||
|
expect(res[1].labelIdentifier).toBe('My Company');
|
||||||
|
expect(res[1].avatarUrl).toBe('https://favicon.twenty.com/example.com');
|
||||||
|
expect(res[1].avatarType).toBe('squared');
|
||||||
|
expect(res[1].link).toBe('/object/company/4');
|
||||||
|
expect(res[1].recordId).toBe('4');
|
||||||
|
expect(res[1].position).toBe(1);
|
||||||
|
});
|
||||||
|
});
|
19
packages/twenty-front/src/utils/__tests__/assert.test.ts
Normal file
19
packages/twenty-front/src/utils/__tests__/assert.test.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { assertNotNull } from '~/utils/assert';
|
||||||
|
|
||||||
|
describe('assert', () => {
|
||||||
|
it('should return true for a NonNullable value', () => {
|
||||||
|
expect(assertNotNull(1)).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true for a NonNullable value', () => {
|
||||||
|
expect(assertNotNull('')).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false for a null value', () => {
|
||||||
|
expect(assertNotNull(null)).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false for an undefined value', () => {
|
||||||
|
expect(assertNotNull(undefined)).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,35 @@
|
|||||||
|
import {
|
||||||
|
convertCurrencyMicrosToCurrency,
|
||||||
|
convertCurrencyToCurrencyMicros,
|
||||||
|
} from '~/utils/convert-currency-amount';
|
||||||
|
|
||||||
|
describe('convertCurrencyToCurrencyMicros', () => {
|
||||||
|
it('should return null if currencyAmount is null', () => {
|
||||||
|
expect(convertCurrencyToCurrencyMicros(null)).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw an error if currencyAmount converted to micros is not a whole number', () => {
|
||||||
|
expect(() => convertCurrencyToCurrencyMicros(1.023)).toThrow(
|
||||||
|
'Cannot convert 1.023 to micros',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should convert currencyAmount to micros', () => {
|
||||||
|
expect(convertCurrencyToCurrencyMicros(1)).toBe(1000000);
|
||||||
|
expect(convertCurrencyToCurrencyMicros(1.5)).toBe(1500000);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('convertCurrencyMicrosToCurrency', () => {
|
||||||
|
it('should return null if currencyAmountMicros is null', () => {
|
||||||
|
expect(convertCurrencyMicrosToCurrency(null)).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return null if currencyAmountMicros is undefined', () => {
|
||||||
|
expect(convertCurrencyMicrosToCurrency(undefined)).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should convert currency micros to currency', () => {
|
||||||
|
expect(convertCurrencyMicrosToCurrency(24000000)).toBe(24);
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,26 @@
|
|||||||
|
import { cookieStorage } from '~/utils/cookie-storage';
|
||||||
|
|
||||||
|
describe('cookieStorage', () => {
|
||||||
|
it('should be able to set and get a cookie', () => {
|
||||||
|
cookieStorage.setItem('foo', 'bar');
|
||||||
|
expect(cookieStorage.getItem('foo')).toBe('bar');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return undefined for a non-existent cookie', () => {
|
||||||
|
expect(cookieStorage.getItem('non-existent')).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to remove a cookie', () => {
|
||||||
|
cookieStorage.setItem('foo', 'bar');
|
||||||
|
cookieStorage.removeItem('foo');
|
||||||
|
expect(cookieStorage.getItem('foo')).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to clear all cookies', () => {
|
||||||
|
cookieStorage.setItem('foo', 'bar');
|
||||||
|
cookieStorage.setItem('baz', 'qux');
|
||||||
|
cookieStorage.clear();
|
||||||
|
expect(cookieStorage.getItem('foo')).toBeUndefined();
|
||||||
|
expect(cookieStorage.getItem('baz')).toBeUndefined();
|
||||||
|
});
|
||||||
|
});
|
20
packages/twenty-front/src/utils/__tests__/debounce.test.ts
Normal file
20
packages/twenty-front/src/utils/__tests__/debounce.test.ts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { debounce } from '../debounce';
|
||||||
|
|
||||||
|
describe('debounce', () => {
|
||||||
|
it('should debounce a function', () => {
|
||||||
|
jest.useFakeTimers();
|
||||||
|
|
||||||
|
const func = jest.fn();
|
||||||
|
const debouncedFunc = debounce(func, 1000);
|
||||||
|
|
||||||
|
debouncedFunc();
|
||||||
|
debouncedFunc();
|
||||||
|
debouncedFunc();
|
||||||
|
|
||||||
|
expect(func).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
jest.runAllTimers();
|
||||||
|
|
||||||
|
expect(func).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
});
|
19
packages/twenty-front/src/utils/__tests__/isDefined.test.ts
Normal file
19
packages/twenty-front/src/utils/__tests__/isDefined.test.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { isDefined } from '~/utils/isDefined';
|
||||||
|
|
||||||
|
describe('isDefined', () => {
|
||||||
|
it('should return true for a NonNullable value', () => {
|
||||||
|
expect(isDefined(1)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return true for a NonNullable value', () => {
|
||||||
|
expect(isDefined('')).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false for a null value', () => {
|
||||||
|
expect(isDefined(null)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false for an undefined value', () => {
|
||||||
|
expect(isDefined(undefined)).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,19 @@
|
|||||||
|
import { isNonEmptyArray } from '../isNonEmptyArray';
|
||||||
|
|
||||||
|
describe('isNonEmptyArray', () => {
|
||||||
|
it('should return true for a non empty array', () => {
|
||||||
|
expect(isNonEmptyArray([1])).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false for an empty array', () => {
|
||||||
|
expect(isNonEmptyArray([])).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false for a null value', () => {
|
||||||
|
expect(isNonEmptyArray(null)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return false for an undefined value', () => {
|
||||||
|
expect(isNonEmptyArray(undefined)).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,7 @@
|
|||||||
|
import { stringToHslColor } from '../string-to-hsl';
|
||||||
|
|
||||||
|
describe('stringToHslColor', () => {
|
||||||
|
it('should return a color based on a string', () => {
|
||||||
|
expect(stringToHslColor('red', 70, 90)).toBe('hsl(105, 70%, 90%)');
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,26 @@
|
|||||||
|
import { getPageTitleFromPath } from '../title-utils';
|
||||||
|
|
||||||
|
describe('title-utils', () => {
|
||||||
|
it('should return the correct title for a given path', () => {
|
||||||
|
expect(getPageTitleFromPath('/verify')).toBe('Verify');
|
||||||
|
expect(getPageTitleFromPath('/sign-in')).toBe('Sign In');
|
||||||
|
expect(getPageTitleFromPath('/sign-up')).toBe('Sign Up');
|
||||||
|
expect(getPageTitleFromPath('/invite/:workspaceInviteHash')).toBe('Invite');
|
||||||
|
expect(getPageTitleFromPath('/create/workspace')).toBe('Create Workspace');
|
||||||
|
expect(getPageTitleFromPath('/create/profile')).toBe('Create Profile');
|
||||||
|
expect(getPageTitleFromPath('/tasks')).toBe('Tasks');
|
||||||
|
expect(getPageTitleFromPath('/objects/opportunities')).toBe(
|
||||||
|
'Opportunities',
|
||||||
|
);
|
||||||
|
expect(getPageTitleFromPath('/settings/profile')).toBe('Profile');
|
||||||
|
expect(getPageTitleFromPath('/settings/profile/appearance')).toBe(
|
||||||
|
'Appearance',
|
||||||
|
);
|
||||||
|
expect(getPageTitleFromPath('/settings/workspace-members')).toBe(
|
||||||
|
'Workspace Members',
|
||||||
|
);
|
||||||
|
expect(getPageTitleFromPath('/settings/workspace')).toBe('Workspace');
|
||||||
|
expect(getPageTitleFromPath('/')).toBe('Twenty');
|
||||||
|
expect(getPageTitleFromPath('/random')).toBe('Twenty');
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,7 @@
|
|||||||
|
import { arrayToChunks } from '~/utils/array/array-to-chunks';
|
||||||
|
|
||||||
|
describe('arrayToChunks', () => {
|
||||||
|
it('should split an array into subarrays of a given size', () => {
|
||||||
|
expect(arrayToChunks([1, 2, 3, 4, 5], 2)).toEqual([[1, 2], [3, 4], [5]]);
|
||||||
|
});
|
||||||
|
});
|
@ -1 +1,2 @@
|
|||||||
export const formatNumber = (value: number): string => value.toLocaleString();
|
export const formatNumber = (value: number): string =>
|
||||||
|
value.toLocaleString('en-US');
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
import { capitalize } from '../capitalize';
|
||||||
|
|
||||||
|
describe('capitalize', () => {
|
||||||
|
it('should capitalize a string', () => {
|
||||||
|
expect(capitalize('test')).toBe('Test');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return an empty string if input is an empty string', () => {
|
||||||
|
expect(capitalize('')).toBe('');
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user