Skip to content

Commit 474dfd7

Browse files
authored
fix: fix Apollo client cache update error for Links field (#5473)
Fixes #5437
1 parent d1cbd70 commit 474dfd7

File tree

8 files changed

+159
-15
lines changed

8 files changed

+159
-15
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import { ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
2+
import {
3+
mockedObjectMetadataItems,
4+
mockedPersonObjectMetadataItem,
5+
} from '~/testing/mock-data/metadata';
6+
import { mockedPeopleData } from '~/testing/mock-data/people';
7+
8+
import { getRecordNodeFromRecord } from '../getRecordNodeFromRecord';
9+
10+
describe('getRecordNodeFromRecord', () => {
11+
it('computes relation records cache references by default', () => {
12+
// Given
13+
const objectMetadataItems: ObjectMetadataItem[] = mockedObjectMetadataItems;
14+
const objectMetadataItem: Pick<
15+
ObjectMetadataItem,
16+
'fields' | 'namePlural' | 'nameSingular'
17+
> = mockedPersonObjectMetadataItem;
18+
const recordGqlFields = {
19+
name: true,
20+
company: true,
21+
};
22+
const record = mockedPeopleData[0];
23+
24+
// When
25+
const result = getRecordNodeFromRecord({
26+
objectMetadataItems,
27+
objectMetadataItem,
28+
recordGqlFields,
29+
record,
30+
});
31+
32+
// Then
33+
expect(result).toEqual({
34+
__typename: 'Person',
35+
company: {
36+
__ref: 'Company:5c21e19e-e049-4393-8c09-3e3f8fb09ecb',
37+
},
38+
name: {
39+
__typename: 'FullName',
40+
firstName: 'Alexandre',
41+
lastName: 'Prot',
42+
},
43+
});
44+
});
45+
46+
it('does not compute relation records cache references when `computeReferences` is false', () => {
47+
// Given
48+
const objectMetadataItems: ObjectMetadataItem[] = mockedObjectMetadataItems;
49+
const objectMetadataItem: Pick<
50+
ObjectMetadataItem,
51+
'fields' | 'namePlural' | 'nameSingular'
52+
> = mockedPersonObjectMetadataItem;
53+
const recordGqlFields = {
54+
name: true,
55+
company: true,
56+
};
57+
const record = mockedPeopleData[0];
58+
const computeReferences = false;
59+
60+
// When
61+
const result = getRecordNodeFromRecord({
62+
objectMetadataItems,
63+
objectMetadataItem,
64+
recordGqlFields,
65+
record,
66+
computeReferences,
67+
});
68+
69+
// Then
70+
expect(result).toEqual({
71+
__typename: 'Person',
72+
company: record.company,
73+
name: {
74+
__typename: 'FullName',
75+
firstName: 'Alexandre',
76+
lastName: 'Prot',
77+
},
78+
});
79+
});
80+
});

packages/twenty-front/src/modules/object-record/cache/utils/getRecordNodeFromRecord.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
RelationDefinitionType,
1212
} from '~/generated-metadata/graphql';
1313
import { isDefined } from '~/utils/isDefined';
14-
import { lowerAndCapitalize } from '~/utils/string/lowerAndCapitalize';
14+
import { pascalCase } from '~/utils/string/pascalCase';
1515

1616
export const getRecordNodeFromRecord = <T extends ObjectRecord>({
1717
objectMetadataItems,
@@ -129,14 +129,15 @@ export const getRecordNodeFromRecord = <T extends ObjectRecord>({
129129
];
130130
}
131131
case FieldMetadataType.Link:
132+
case FieldMetadataType.Links:
132133
case FieldMetadataType.Address:
133134
case FieldMetadataType.FullName:
134135
case FieldMetadataType.Currency: {
135136
return [
136137
fieldName,
137138
{
138139
...value,
139-
__typename: lowerAndCapitalize(field.type),
140+
__typename: pascalCase(field.type),
140141
},
141142
];
142143
}

packages/twenty-front/src/modules/object-record/hooks/__mocks__/useFindDuplicateRecords.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,11 @@ export const responseData = {
4949
personDuplicates: {
5050
edges: [
5151
{
52-
node: { __typename: 'Person', ...mockedPeopleData[0], updatedAt: '' },
52+
node: { ...mockedPeopleData[0], updatedAt: '' },
5353
cursor: 'cursor1',
5454
},
5555
{
56-
node: { __typename: 'Person', ...mockedPeopleData[1], updatedAt: '' },
56+
node: { ...mockedPeopleData[1], updatedAt: '' },
5757
cursor: 'cursor2',
5858
},
5959
],

packages/twenty-front/src/modules/object-record/utils/generateEmptyFieldValue.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export const generateEmptyFieldValue = (
1919
};
2020
}
2121
case FieldMetadataType.Links: {
22-
return { primaryLinkUrl: '', primaryLinkLabel: '' };
22+
return { primaryLinkUrl: '', primaryLinkLabel: '', secondaryLinks: null };
2323
}
2424
case FieldMetadataType.FullName: {
2525
return {

packages/twenty-front/src/testing/mock-data/people.ts

+10-1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ type RequiredAndNotNull<T> = {
88
type MockedPerson = RequiredAndNotNull<
99
Pick<
1010
Person,
11+
| '__typename'
1112
| 'id'
1213
| 'name'
1314
| 'linkedinLink'
@@ -20,12 +21,13 @@ type MockedPerson = RequiredAndNotNull<
2021
| 'createdAt'
2122
| 'companyId'
2223
> & {
23-
company: Pick<Company, 'id' | 'name' | 'domainName'>;
24+
company: Pick<Company, '__typename' | 'id' | 'name' | 'domainName'>;
2425
}
2526
>;
2627

2728
export const mockedPeopleData: MockedPerson[] = [
2829
{
30+
__typename: 'Person',
2931
id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6b',
3032
name: {
3133
firstName: 'Alexandre',
@@ -45,6 +47,7 @@ export const mockedPeopleData: MockedPerson[] = [
4547
jobTitle: 'CEO',
4648
companyId: '5c21e19e-e049-4393-8c09-3e3f8fb09ecb',
4749
company: {
50+
__typename: 'Company',
4851
id: '5c21e19e-e049-4393-8c09-3e3f8fb09ecb',
4952
name: 'Qonto',
5053
domainName: 'qonto.com',
@@ -54,6 +57,7 @@ export const mockedPeopleData: MockedPerson[] = [
5457
city: 'Paris',
5558
},
5659
{
60+
__typename: 'Person',
5761
id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6d',
5862
name: { firstName: 'John', lastName: 'Doe' },
5963
linkedinLink: {
@@ -69,6 +73,7 @@ export const mockedPeopleData: MockedPerson[] = [
6973
7074
companyId: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6e',
7175
company: {
76+
__typename: 'Company',
7277
id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6e',
7378
name: 'LinkedIn',
7479
domainName: 'linkedin.com',
@@ -78,6 +83,7 @@ export const mockedPeopleData: MockedPerson[] = [
7883
city: 'Paris',
7984
},
8085
{
86+
__typename: 'Person',
8187
id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6f',
8288
name: {
8389
firstName: 'Jane',
@@ -96,6 +102,7 @@ export const mockedPeopleData: MockedPerson[] = [
96102
97103
companyId: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6g',
98104
company: {
105+
__typename: 'Company',
99106
id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6g',
100107
name: 'Sequoia',
101108
domainName: 'sequoiacap.com',
@@ -105,6 +112,7 @@ export const mockedPeopleData: MockedPerson[] = [
105112
city: 'Paris',
106113
},
107114
{
115+
__typename: 'Person',
108116
id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6h',
109117
name: {
110118
firstName: 'Janice',
@@ -123,6 +131,7 @@ export const mockedPeopleData: MockedPerson[] = [
123131
jobTitle: 'CEO',
124132
companyId: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6i',
125133
company: {
134+
__typename: 'Company',
126135
id: '7dfbc3f7-6e5e-4128-957e-8d86808cdf6i',
127136
name: 'Facebook',
128137
domainName: 'facebook.com',
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { pascalCase } from '../pascalCase';
2+
3+
describe('pascalCase', () => {
4+
it('converts a string to pascal case', () => {
5+
// Given
6+
const input = 'HELLO_WORLD';
7+
8+
// When
9+
const result = pascalCase(input);
10+
11+
// Then
12+
expect(result).toBe('HelloWorld');
13+
});
14+
15+
it('handles empty strings', () => {
16+
// Given
17+
const input = '';
18+
19+
// When
20+
const result = pascalCase(input);
21+
22+
// Then
23+
expect(result).toBe('');
24+
});
25+
26+
it('handles strings with only one word', () => {
27+
// Given
28+
const input = 'hello';
29+
30+
// When
31+
const result = pascalCase(input);
32+
33+
// Then
34+
expect(result).toBe('Hello');
35+
});
36+
37+
it('handles strings with several words, spaces and special characters', () => {
38+
// Given
39+
const input = '& Hello world! How are you today? #';
40+
41+
// When
42+
const result = pascalCase(input);
43+
44+
// Then
45+
expect(result).toBe('HelloWorldHowAreYouToday');
46+
});
47+
48+
it('handles strings with leading and trailing spaces', () => {
49+
// Given
50+
const input = ' hello_world ';
51+
52+
// When
53+
const result = pascalCase(input);
54+
55+
// Then
56+
expect(result).toBe('HelloWorld');
57+
});
58+
});

packages/twenty-front/src/utils/string/lowerAndCapitalize.ts

-9
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import camelCase from 'lodash.camelcase';
2+
3+
import { capitalize } from '~/utils/string/capitalize';
4+
5+
export const pascalCase = (str: string) => capitalize(camelCase(str));

0 commit comments

Comments
 (0)