719be52b53
- add more explicit error message on upsert conflicts - increase MAX_RECORDS_QUERY constant - add soft deleted records when returning upserted records fixes https://github.com/twentyhq/private-issues/issues/300
261 lines
6.9 KiB
TypeScript
261 lines
6.9 KiB
TypeScript
import gql from 'graphql-tag';
|
|
import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.util';
|
|
import { createOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/create-one-field-metadata.util';
|
|
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
|
|
import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util';
|
|
import { FieldMetadataType } from 'twenty-shared/types';
|
|
|
|
const createRecordsQuery = gql`
|
|
mutation CreateRecords(
|
|
$data: [TestRecordObjectCreateInput!]
|
|
$upsert: Boolean
|
|
) {
|
|
createTestRecordObjects(data: $data, upsert: $upsert) {
|
|
id
|
|
firstUniqueTestField
|
|
secondUniqueTestField
|
|
name
|
|
deletedAt
|
|
}
|
|
}
|
|
`;
|
|
|
|
const deleteRecordsQuery = gql`
|
|
mutation DeleteRecords($filter: TestRecordObjectFilterInput!) {
|
|
deleteTestRecordObjects(filter: $filter) {
|
|
id
|
|
firstUniqueTestField
|
|
secondUniqueTestField
|
|
name
|
|
deletedAt
|
|
}
|
|
}
|
|
`;
|
|
|
|
describe('upsert (createMany with upsert:true)', () => {
|
|
let createdObjectMetadataId = '';
|
|
|
|
beforeEach(async () => {
|
|
const {
|
|
data: {
|
|
createOneObject: { id: objectMetadataId },
|
|
},
|
|
} = await createOneObjectMetadata({
|
|
input: {
|
|
nameSingular: 'testRecordObject',
|
|
namePlural: 'testRecordObjects',
|
|
labelSingular: 'Test Record Object',
|
|
labelPlural: 'Test Record Objects',
|
|
icon: 'IconTestRecord',
|
|
},
|
|
});
|
|
|
|
createdObjectMetadataId = objectMetadataId;
|
|
|
|
await createOneFieldMetadata({
|
|
input: {
|
|
name: 'firstUniqueTestField',
|
|
label: 'First Unique Test Field',
|
|
type: FieldMetadataType.TEXT,
|
|
objectMetadataId: createdObjectMetadataId,
|
|
isUnique: true,
|
|
},
|
|
gqlFields: `
|
|
id
|
|
name
|
|
label
|
|
type
|
|
isUnique
|
|
`,
|
|
});
|
|
|
|
await createOneFieldMetadata({
|
|
input: {
|
|
name: 'secondUniqueTestField',
|
|
label: 'Second Unique Test Field',
|
|
type: FieldMetadataType.TEXT,
|
|
objectMetadataId: createdObjectMetadataId,
|
|
isUnique: true,
|
|
},
|
|
gqlFields: `
|
|
id
|
|
name
|
|
label
|
|
type
|
|
isUnique
|
|
`,
|
|
});
|
|
});
|
|
|
|
afterEach(async () => {
|
|
await deleteOneObjectMetadata({
|
|
input: { idToDelete: createdObjectMetadataId },
|
|
});
|
|
});
|
|
|
|
it('should update many records', async () => {
|
|
// Create 2 records
|
|
await makeGraphqlAPIRequest({
|
|
query: createRecordsQuery,
|
|
variables: {
|
|
data: [
|
|
{
|
|
firstUniqueTestField: 'firstUniqueTestField1',
|
|
secondUniqueTestField: 'secondUniqueTestField1',
|
|
name: 'record1',
|
|
},
|
|
{
|
|
firstUniqueTestField: 'firstUniqueTestField2',
|
|
secondUniqueTestField: 'secondUniqueTestField2',
|
|
name: 'record2',
|
|
},
|
|
],
|
|
upsert: false,
|
|
},
|
|
});
|
|
|
|
// Update 2 records using upsert
|
|
const updatedRecordsResponse = await makeGraphqlAPIRequest({
|
|
query: createRecordsQuery,
|
|
variables: {
|
|
data: [
|
|
{
|
|
firstUniqueTestField: 'firstUniqueTestField1',
|
|
name: 'updatedRecord1',
|
|
},
|
|
{
|
|
firstUniqueTestField: 'firstUniqueTestField2',
|
|
name: 'updatedRecord2',
|
|
},
|
|
],
|
|
upsert: true,
|
|
},
|
|
});
|
|
|
|
const updatedRecords =
|
|
updatedRecordsResponse.body.data.createTestRecordObjects;
|
|
|
|
expect(updatedRecords).toHaveLength(2);
|
|
|
|
const record1 = updatedRecords.find(
|
|
(record: any) => record.firstUniqueTestField === 'firstUniqueTestField1',
|
|
);
|
|
const record2 = updatedRecords.find(
|
|
(record: any) => record.firstUniqueTestField === 'firstUniqueTestField2',
|
|
);
|
|
|
|
expect(record1).toEqual({
|
|
id: expect.any(String),
|
|
firstUniqueTestField: 'firstUniqueTestField1',
|
|
secondUniqueTestField: 'secondUniqueTestField1',
|
|
name: 'updatedRecord1',
|
|
deletedAt: null,
|
|
});
|
|
|
|
expect(record2).toEqual({
|
|
id: expect.any(String),
|
|
firstUniqueTestField: 'firstUniqueTestField2',
|
|
secondUniqueTestField: 'secondUniqueTestField2',
|
|
name: 'updatedRecord2',
|
|
deletedAt: null,
|
|
});
|
|
});
|
|
|
|
it('should update soft-deleted records', async () => {
|
|
// Create a record
|
|
const createResponse = await makeGraphqlAPIRequest({
|
|
query: createRecordsQuery,
|
|
variables: {
|
|
data: [
|
|
{
|
|
firstUniqueTestField: 'softDeletedRecord',
|
|
secondUniqueTestField: 'softDeletedSecondField',
|
|
name: 'originalRecord',
|
|
},
|
|
],
|
|
upsert: false,
|
|
},
|
|
});
|
|
|
|
const createdRecord = createResponse.body.data.createTestRecordObjects[0];
|
|
|
|
// Soft delete the record
|
|
await makeGraphqlAPIRequest({
|
|
query: deleteRecordsQuery,
|
|
variables: {
|
|
filter: {
|
|
id: {
|
|
eq: createdRecord.id,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
const upsertResponse = await makeGraphqlAPIRequest({
|
|
query: createRecordsQuery,
|
|
variables: {
|
|
data: [
|
|
{
|
|
firstUniqueTestField: 'softDeletedRecord',
|
|
name: 'restoredRecord',
|
|
},
|
|
],
|
|
upsert: true,
|
|
},
|
|
});
|
|
|
|
const upsertedRecord = upsertResponse.body.data.createTestRecordObjects[0];
|
|
|
|
expect(upsertedRecord).toEqual({
|
|
id: createdRecord.id,
|
|
firstUniqueTestField: 'softDeletedRecord',
|
|
secondUniqueTestField: 'softDeletedSecondField',
|
|
name: 'restoredRecord',
|
|
deletedAt: expect.any(String),
|
|
});
|
|
});
|
|
|
|
it('should throw an error when multiple records with the same unique field values are found', async () => {
|
|
await makeGraphqlAPIRequest({
|
|
query: createRecordsQuery,
|
|
variables: {
|
|
data: [
|
|
{
|
|
firstUniqueTestField: 'firstUniqueTestField1',
|
|
secondUniqueTestField: 'secondUniqueTestField1',
|
|
name: 'record1',
|
|
},
|
|
{
|
|
firstUniqueTestField: 'firstUniqueTestField2',
|
|
secondUniqueTestField: 'secondUniqueTestField2',
|
|
name: 'record2',
|
|
},
|
|
],
|
|
upsert: false,
|
|
},
|
|
});
|
|
|
|
const upsertResponse = await makeGraphqlAPIRequest({
|
|
query: createRecordsQuery,
|
|
variables: {
|
|
data: [
|
|
{
|
|
firstUniqueTestField: 'firstUniqueTestField1',
|
|
secondUniqueTestField: 'secondUniqueTestField2',
|
|
name: 'conflictingRecord',
|
|
},
|
|
],
|
|
upsert: true,
|
|
},
|
|
});
|
|
|
|
expect(upsertResponse.body.errors).toBeDefined();
|
|
expect(upsertResponse.body.errors[0].message).toContain(
|
|
'Multiple records found with the same unique field values',
|
|
);
|
|
expect(upsertResponse.body.errors[0].extensions.code).toBe(
|
|
'BAD_USER_INPUT',
|
|
);
|
|
});
|
|
});
|