From 3c2b5b5fd592168ab78eb2e18a17107d688b3849 Mon Sep 17 00:00:00 2001 From: gitstart-twenty Date: Mon, 21 Oct 2024 22:43:39 +0000 Subject: [PATCH] [Server Integration tests] Enrich integration GraphQL API tests #3 --- .../graphql/integration.constants.ts | 1 + ...participants-resolvers.integration-spec.ts | 480 +++++++++++++++++ ...ted-accounts-resolvers.integration-spec.ts | 420 +++++++++++++++ ...ll-favorites-resolvers.integration-spec.ts | 409 +++++++++++++++ ...associations-resolvers.integration-spec.ts | 493 ++++++++++++++++++ ...age-channels-resolvers.integration-spec.ts | 455 ++++++++++++++++ ...participants-resolvers.integration-spec.ts | 466 +++++++++++++++++ ...sage-threads-resolvers.integration-spec.ts | 397 ++++++++++++++ ...note-targets-resolvers.integration-spec.ts | 444 ++++++++++++++++ .../all-notes-resolvers.integration-spec.ts | 403 ++++++++++++++ ...pportunities-resolvers.integration-spec.ts | 414 +++++++++++++++ 11 files changed, 4382 insertions(+) create mode 100644 packages/twenty-server/test/integration/graphql/integration.constants.ts create mode 100644 packages/twenty-server/test/integration/graphql/suites/all-calendar-event-participants-resolvers.integration-spec.ts create mode 100644 packages/twenty-server/test/integration/graphql/suites/all-connected-accounts-resolvers.integration-spec.ts create mode 100644 packages/twenty-server/test/integration/graphql/suites/all-favorites-resolvers.integration-spec.ts create mode 100644 packages/twenty-server/test/integration/graphql/suites/all-message-channel-message-associations-resolvers.integration-spec.ts create mode 100644 packages/twenty-server/test/integration/graphql/suites/all-message-channels-resolvers.integration-spec.ts create mode 100644 packages/twenty-server/test/integration/graphql/suites/all-message-participants-resolvers.integration-spec.ts create mode 100644 packages/twenty-server/test/integration/graphql/suites/all-message-threads-resolvers.integration-spec.ts create mode 100644 packages/twenty-server/test/integration/graphql/suites/all-note-targets-resolvers.integration-spec.ts create mode 100644 packages/twenty-server/test/integration/graphql/suites/all-notes-resolvers.integration-spec.ts create mode 100644 packages/twenty-server/test/integration/graphql/suites/all-opportunities-resolvers.integration-spec.ts diff --git a/packages/twenty-server/test/integration/graphql/integration.constants.ts b/packages/twenty-server/test/integration/graphql/integration.constants.ts new file mode 100644 index 000000000000..e5391d40b110 --- /dev/null +++ b/packages/twenty-server/test/integration/graphql/integration.constants.ts @@ -0,0 +1 @@ +export const TIM_ACCOUNT_ID = '20202020-0687-4c41-b707-ed1bfca972a7'; diff --git a/packages/twenty-server/test/integration/graphql/suites/all-calendar-event-participants-resolvers.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/all-calendar-event-participants-resolvers.integration-spec.ts new file mode 100644 index 000000000000..93d50a56601e --- /dev/null +++ b/packages/twenty-server/test/integration/graphql/suites/all-calendar-event-participants-resolvers.integration-spec.ts @@ -0,0 +1,480 @@ +import { createManyOperationFactory } from 'test/integration/graphql/utils/create-many-operation-factory.util'; +import { createOneOperationFactory } from 'test/integration/graphql/utils/create-one-operation-factory.util'; +import { deleteManyOperationFactory } from 'test/integration/graphql/utils/delete-many-operation-factory.util'; +import { deleteOneOperationFactory } from 'test/integration/graphql/utils/delete-one-operation-factory.util'; +import { destroyManyOperationFactory } from 'test/integration/graphql/utils/destroy-many-operation-factory.util'; +import { destroyOneOperationFactory } from 'test/integration/graphql/utils/destroy-one-operation-factory.util'; +import { findManyOperationFactory } from 'test/integration/graphql/utils/find-many-operation-factory.util'; +import { findOneOperationFactory } from 'test/integration/graphql/utils/find-one-operation-factory.util'; +import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.util'; +import { updateManyOperationFactory } from 'test/integration/graphql/utils/update-many-operation-factory.util'; +import { updateOneOperationFactory } from 'test/integration/graphql/utils/update-one-operation-factory.util'; +import { generateRecordName } from 'test/integration/utils/generate-record-name'; + +const CALENDAR_EVENT_PARTICIPANT_1_ID = '777a8457-eb2d-40ac-a707-551b615b6987'; +const CALENDAR_EVENT_PARTICIPANT_2_ID = '777a8457-eb2d-40ac-a707-551b615b6988'; +const CALENDAR_EVENT_PARTICIPANT_3_ID = '777a8457-eb2d-40ac-a707-551b615b6989'; +const CALENDAR_EVENT_ID = '777a8457-eb2d-40ac-a707-441b615b6989'; +const CALENDAR_EVENT_PARTICIPANT_GQL_FIELDS = ` + id + handle + displayName + isOrganizer + responseStatus + deletedAt +`; + +describe('calendarEventParticipants resolvers (integration)', () => { + beforeAll(async () => { + const calendarEventTitle = generateRecordName(CALENDAR_EVENT_ID); + const graphqlOperation = createOneOperationFactory({ + objectMetadataSingularName: 'calendarEvent', + gqlFields: `id`, + data: { + id: CALENDAR_EVENT_ID, + title: calendarEventTitle, + }, + }); + + await makeGraphqlAPIRequest(graphqlOperation); + }); + + afterAll(async () => { + const graphqlOperation = destroyOneOperationFactory({ + objectMetadataSingularName: 'calendarEvent', + gqlFields: `id`, + recordId: CALENDAR_EVENT_ID, + }); + + await makeGraphqlAPIRequest(graphqlOperation); + }); + + it('1. should create and return calendarEventParticipants', async () => { + const calendarEventParticipantDisplayName1 = generateRecordName( + CALENDAR_EVENT_PARTICIPANT_1_ID, + ); + const calendarEventParticipantDisplayName2 = generateRecordName( + CALENDAR_EVENT_PARTICIPANT_2_ID, + ); + + const graphqlOperation = createManyOperationFactory({ + objectMetadataSingularName: 'calendarEventParticipant', + objectMetadataPluralName: 'calendarEventParticipants', + gqlFields: CALENDAR_EVENT_PARTICIPANT_GQL_FIELDS, + data: [ + { + id: CALENDAR_EVENT_PARTICIPANT_1_ID, + displayName: calendarEventParticipantDisplayName1, + calendarEventId: CALENDAR_EVENT_ID, + }, + { + id: CALENDAR_EVENT_PARTICIPANT_2_ID, + displayName: calendarEventParticipantDisplayName2, + calendarEventId: CALENDAR_EVENT_ID, + }, + ], + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.createCalendarEventParticipants).toHaveLength(2); + + response.body.data.createCalendarEventParticipants.forEach( + (calendarEventParticipant) => { + expect(calendarEventParticipant).toHaveProperty('displayName'); + expect([ + calendarEventParticipantDisplayName1, + calendarEventParticipantDisplayName2, + ]).toContain(calendarEventParticipant.displayName); + + expect(calendarEventParticipant).toHaveProperty('id'); + expect(calendarEventParticipant).toHaveProperty('handle'); + expect(calendarEventParticipant).toHaveProperty('isOrganizer'); + expect(calendarEventParticipant).toHaveProperty('responseStatus'); + expect(calendarEventParticipant).toHaveProperty('deletedAt'); + }, + ); + }); + + it('1b. should create and return one calendarEventParticipant', async () => { + const calendarEventParticipantDisplayName = generateRecordName( + CALENDAR_EVENT_PARTICIPANT_3_ID, + ); + + const graphqlOperation = createOneOperationFactory({ + objectMetadataSingularName: 'calendarEventParticipant', + gqlFields: CALENDAR_EVENT_PARTICIPANT_GQL_FIELDS, + data: { + id: CALENDAR_EVENT_PARTICIPANT_3_ID, + displayName: calendarEventParticipantDisplayName, + calendarEventId: CALENDAR_EVENT_ID, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const createdCalendarEventParticipant = + response.body.data.createCalendarEventParticipant; + + expect(createdCalendarEventParticipant).toHaveProperty('displayName'); + expect(createdCalendarEventParticipant.displayName).toEqual( + calendarEventParticipantDisplayName, + ); + + expect(createdCalendarEventParticipant).toHaveProperty('displayName'); + expect(createdCalendarEventParticipant).toHaveProperty('id'); + expect(createdCalendarEventParticipant).toHaveProperty('handle'); + expect(createdCalendarEventParticipant).toHaveProperty('isOrganizer'); + expect(createdCalendarEventParticipant).toHaveProperty('responseStatus'); + expect(createdCalendarEventParticipant).toHaveProperty('deletedAt'); + }); + + it('2. should find many calendarEventParticipants', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'calendarEventParticipant', + objectMetadataPluralName: 'calendarEventParticipants', + gqlFields: CALENDAR_EVENT_PARTICIPANT_GQL_FIELDS, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const data = response.body.data.calendarEventParticipants; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const calendarEventParticipants = edges[0].node; + + expect(calendarEventParticipants).toHaveProperty('displayName'); + expect(calendarEventParticipants).toHaveProperty('id'); + expect(calendarEventParticipants).toHaveProperty('handle'); + expect(calendarEventParticipants).toHaveProperty('isOrganizer'); + expect(calendarEventParticipants).toHaveProperty('responseStatus'); + expect(calendarEventParticipants).toHaveProperty('deletedAt'); + } + }); + + it('2b. should find one calendarEventParticipant', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'calendarEventParticipant', + gqlFields: CALENDAR_EVENT_PARTICIPANT_GQL_FIELDS, + filter: { + id: { + eq: CALENDAR_EVENT_PARTICIPANT_3_ID, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const calendarEventParticipant = + response.body.data.calendarEventParticipant; + + expect(calendarEventParticipant).toHaveProperty('displayName'); + + expect(calendarEventParticipant).toHaveProperty('id'); + expect(calendarEventParticipant).toHaveProperty('handle'); + expect(calendarEventParticipant).toHaveProperty('isOrganizer'); + expect(calendarEventParticipant).toHaveProperty('responseStatus'); + expect(calendarEventParticipant).toHaveProperty('deletedAt'); + }); + + it('3. should update many calendarEventParticipants', async () => { + const graphqlOperation = updateManyOperationFactory({ + objectMetadataSingularName: 'calendarEventParticipant', + objectMetadataPluralName: 'calendarEventParticipants', + gqlFields: CALENDAR_EVENT_PARTICIPANT_GQL_FIELDS, + data: { + displayName: 'New DisplayName', + }, + filter: { + id: { + in: [ + CALENDAR_EVENT_PARTICIPANT_1_ID, + CALENDAR_EVENT_PARTICIPANT_2_ID, + ], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const updatedcalendarEventParticipants = + response.body.data.updateCalendarEventParticipants; + + expect(updatedcalendarEventParticipants).toHaveLength(2); + + updatedcalendarEventParticipants.forEach((calendarEventParticipant) => { + expect(calendarEventParticipant.displayName).toEqual('New DisplayName'); + }); + }); + + it('3b. should update one calendarEventParticipant', async () => { + const graphqlOperation = updateOneOperationFactory({ + objectMetadataSingularName: 'calendarEventParticipant', + gqlFields: CALENDAR_EVENT_PARTICIPANT_GQL_FIELDS, + data: { + displayName: 'Updated DisplayName', + }, + recordId: CALENDAR_EVENT_PARTICIPANT_3_ID, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const updatedcalendarEventParticipant = + response.body.data.updateCalendarEventParticipant; + + expect(updatedcalendarEventParticipant.displayName).toEqual( + 'Updated DisplayName', + ); + }); + + it('4. should find many calendarEventParticipants with updated displayName', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'calendarEventParticipant', + objectMetadataPluralName: 'calendarEventParticipants', + gqlFields: CALENDAR_EVENT_PARTICIPANT_GQL_FIELDS, + filter: { + displayName: { + eq: 'New DisplayName', + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.calendarEventParticipants.edges).toHaveLength(2); + }); + + it('4b. should find one calendarEventParticipant with updated displayName', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'calendarEventParticipant', + gqlFields: CALENDAR_EVENT_PARTICIPANT_GQL_FIELDS, + filter: { + displayName: { + eq: 'Updated DisplayName', + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.calendarEventParticipant.displayName).toEqual( + 'Updated DisplayName', + ); + }); + + it('5. should delete many calendarEventParticipants', async () => { + const graphqlOperation = deleteManyOperationFactory({ + objectMetadataSingularName: 'calendarEventParticipant', + objectMetadataPluralName: 'calendarEventParticipants', + gqlFields: CALENDAR_EVENT_PARTICIPANT_GQL_FIELDS, + filter: { + id: { + in: [ + CALENDAR_EVENT_PARTICIPANT_1_ID, + CALENDAR_EVENT_PARTICIPANT_2_ID, + ], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const deleteCalendarEventParticipants = + response.body.data.deleteCalendarEventParticipants; + + expect(deleteCalendarEventParticipants).toHaveLength(2); + + deleteCalendarEventParticipants.forEach((calendarEventParticipant) => { + expect(calendarEventParticipant.deletedAt).toBeTruthy(); + }); + }); + + it('5b. should delete one calendarEventParticipant', async () => { + const graphqlOperation = deleteOneOperationFactory({ + objectMetadataSingularName: 'calendarEventParticipant', + gqlFields: CALENDAR_EVENT_PARTICIPANT_GQL_FIELDS, + recordId: CALENDAR_EVENT_PARTICIPANT_3_ID, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect( + response.body.data.deleteCalendarEventParticipant.deletedAt, + ).toBeTruthy(); + }); + + it('6. should not find many calendarEventParticipants anymore', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'calendarEventParticipant', + objectMetadataPluralName: 'calendarEventParticipants', + gqlFields: CALENDAR_EVENT_PARTICIPANT_GQL_FIELDS, + filter: { + id: { + in: [ + CALENDAR_EVENT_PARTICIPANT_1_ID, + CALENDAR_EVENT_PARTICIPANT_2_ID, + ], + }, + }, + }); + + const findCalendarEventParticipantsResponse = + await makeGraphqlAPIRequest(graphqlOperation); + + expect( + findCalendarEventParticipantsResponse.body.data.calendarEventParticipants + .edges, + ).toHaveLength(0); + }); + + it('6b. should not find one calendarEventParticipant anymore', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'calendarEventParticipant', + gqlFields: CALENDAR_EVENT_PARTICIPANT_GQL_FIELDS, + filter: { + id: { + eq: CALENDAR_EVENT_PARTICIPANT_3_ID, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.calendarEventParticipant).toBeNull(); + }); + + it('7. should find many deleted calendarEventParticipants with deletedAt filter', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'calendarEventParticipant', + objectMetadataPluralName: 'calendarEventParticipants', + gqlFields: CALENDAR_EVENT_PARTICIPANT_GQL_FIELDS, + filter: { + id: { + in: [ + CALENDAR_EVENT_PARTICIPANT_1_ID, + CALENDAR_EVENT_PARTICIPANT_2_ID, + ], + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.calendarEventParticipants.edges).toHaveLength(2); + }); + + it('7b. should find one deleted calendarEventParticipant with deletedAt filter', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'calendarEventParticipant', + gqlFields: CALENDAR_EVENT_PARTICIPANT_GQL_FIELDS, + filter: { + id: { + eq: CALENDAR_EVENT_PARTICIPANT_3_ID, + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.calendarEventParticipant.id).toEqual( + CALENDAR_EVENT_PARTICIPANT_3_ID, + ); + }); + + it('8. should destroy many calendarEventParticipants', async () => { + const graphqlOperation = destroyManyOperationFactory({ + objectMetadataSingularName: 'calendarEventParticipant', + objectMetadataPluralName: 'calendarEventParticipants', + gqlFields: CALENDAR_EVENT_PARTICIPANT_GQL_FIELDS, + filter: { + id: { + in: [ + CALENDAR_EVENT_PARTICIPANT_1_ID, + CALENDAR_EVENT_PARTICIPANT_2_ID, + ], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.destroyCalendarEventParticipants).toHaveLength(2); + }); + + it('8b. should destroy one calendarEventParticipant', async () => { + const graphqlOperation = destroyOneOperationFactory({ + objectMetadataSingularName: 'calendarEventParticipant', + gqlFields: CALENDAR_EVENT_PARTICIPANT_GQL_FIELDS, + recordId: CALENDAR_EVENT_PARTICIPANT_3_ID, + }); + + const destroyCalendarEventParticipantResponse = + await makeGraphqlAPIRequest(graphqlOperation); + + expect( + destroyCalendarEventParticipantResponse.body.data + .destroyCalendarEventParticipant, + ).toBeTruthy(); + }); + + it('9. should not find many calendarEventParticipants anymore', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'calendarEventParticipant', + objectMetadataPluralName: 'calendarEventParticipants', + gqlFields: CALENDAR_EVENT_PARTICIPANT_GQL_FIELDS, + filter: { + id: { + in: [ + CALENDAR_EVENT_PARTICIPANT_1_ID, + CALENDAR_EVENT_PARTICIPANT_2_ID, + ], + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.calendarEventParticipants.edges).toHaveLength(0); + }); + + it('9b. should not find one calendarEventParticipant anymore', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'calendarEventParticipant', + gqlFields: CALENDAR_EVENT_PARTICIPANT_GQL_FIELDS, + filter: { + id: { + eq: CALENDAR_EVENT_PARTICIPANT_3_ID, + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.calendarEventParticipant).toBeNull(); + }); +}); diff --git a/packages/twenty-server/test/integration/graphql/suites/all-connected-accounts-resolvers.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/all-connected-accounts-resolvers.integration-spec.ts new file mode 100644 index 000000000000..d64e55900687 --- /dev/null +++ b/packages/twenty-server/test/integration/graphql/suites/all-connected-accounts-resolvers.integration-spec.ts @@ -0,0 +1,420 @@ +import { TIM_ACCOUNT_ID } from 'test/integration/graphql/integration.constants'; +import { createManyOperationFactory } from 'test/integration/graphql/utils/create-many-operation-factory.util'; +import { createOneOperationFactory } from 'test/integration/graphql/utils/create-one-operation-factory.util'; +import { deleteManyOperationFactory } from 'test/integration/graphql/utils/delete-many-operation-factory.util'; +import { deleteOneOperationFactory } from 'test/integration/graphql/utils/delete-one-operation-factory.util'; +import { destroyManyOperationFactory } from 'test/integration/graphql/utils/destroy-many-operation-factory.util'; +import { destroyOneOperationFactory } from 'test/integration/graphql/utils/destroy-one-operation-factory.util'; +import { findManyOperationFactory } from 'test/integration/graphql/utils/find-many-operation-factory.util'; +import { findOneOperationFactory } from 'test/integration/graphql/utils/find-one-operation-factory.util'; +import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.util'; +import { updateManyOperationFactory } from 'test/integration/graphql/utils/update-many-operation-factory.util'; +import { updateOneOperationFactory } from 'test/integration/graphql/utils/update-one-operation-factory.util'; +import { generateRecordName } from 'test/integration/utils/generate-record-name'; + +const CONNECTED_ACCOUNT_1_ID = '777a8457-eb2d-40ac-a707-551b615b6987'; +const CONNECTED_ACCOUNT_2_ID = '777a8457-eb2d-40ac-a707-551b615b6988'; +const CONNECTED_ACCOUNT_3_ID = '777a8457-eb2d-40ac-a707-551b615b6989'; +const CONNECTED_ACCOUNT_GQL_FIELDS = ` + id + handle + deletedAt + createdAt + provider + accessToken + scopes +`; + +describe('connectedAccounts resolvers (integration)', () => { + it('1. should create and return connectedAccounts', async () => { + const connectedAccountHandle1 = generateRecordName(CONNECTED_ACCOUNT_1_ID); + const connectedAccountHandle2 = generateRecordName(CONNECTED_ACCOUNT_2_ID); + + const graphqlOperation = createManyOperationFactory({ + objectMetadataSingularName: 'connectedAccount', + objectMetadataPluralName: 'connectedAccounts', + gqlFields: CONNECTED_ACCOUNT_GQL_FIELDS, + data: [ + { + id: CONNECTED_ACCOUNT_1_ID, + handle: connectedAccountHandle1, + accountOwnerId: TIM_ACCOUNT_ID, + }, + { + id: CONNECTED_ACCOUNT_2_ID, + handle: connectedAccountHandle2, + accountOwnerId: TIM_ACCOUNT_ID, + }, + ], + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.createConnectedAccounts).toHaveLength(2); + + response.body.data.createConnectedAccounts.forEach((connectedAccount) => { + expect(connectedAccount).toHaveProperty('handle'); + expect([connectedAccountHandle1, connectedAccountHandle2]).toContain( + connectedAccount.handle, + ); + + expect(connectedAccount).toHaveProperty('id'); + expect(connectedAccount).toHaveProperty('deletedAt'); + expect(connectedAccount).toHaveProperty('createdAt'); + expect(connectedAccount).toHaveProperty('provider'); + expect(connectedAccount).toHaveProperty('accessToken'); + expect(connectedAccount).toHaveProperty('scopes'); + }); + }); + + it('1b. should create and return one connectedAccount', async () => { + const connectedAccountHandle = generateRecordName(CONNECTED_ACCOUNT_3_ID); + + const graphqlOperation = createOneOperationFactory({ + objectMetadataSingularName: 'connectedAccount', + gqlFields: CONNECTED_ACCOUNT_GQL_FIELDS, + data: { + id: CONNECTED_ACCOUNT_3_ID, + handle: connectedAccountHandle, + accountOwnerId: TIM_ACCOUNT_ID, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const createdConnectedAccount = response.body.data.createConnectedAccount; + + expect(createdConnectedAccount).toHaveProperty('handle'); + expect(createdConnectedAccount.handle).toEqual(connectedAccountHandle); + + expect(createdConnectedAccount).toHaveProperty('id'); + expect(createdConnectedAccount).toHaveProperty('deletedAt'); + expect(createdConnectedAccount).toHaveProperty('createdAt'); + expect(createdConnectedAccount).toHaveProperty('provider'); + expect(createdConnectedAccount).toHaveProperty('accessToken'); + expect(createdConnectedAccount).toHaveProperty('scopes'); + }); + + it('2. should find many connectedAccounts', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'connectedAccount', + objectMetadataPluralName: 'connectedAccounts', + gqlFields: CONNECTED_ACCOUNT_GQL_FIELDS, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const data = response.body.data.connectedAccounts; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const connectedAccounts = edges[0].node; + + expect(connectedAccounts).toHaveProperty('handle'); + expect(connectedAccounts).toHaveProperty('id'); + expect(connectedAccounts).toHaveProperty('deletedAt'); + expect(connectedAccounts).toHaveProperty('createdAt'); + expect(connectedAccounts).toHaveProperty('provider'); + expect(connectedAccounts).toHaveProperty('accessToken'); + expect(connectedAccounts).toHaveProperty('scopes'); + } + }); + + it('2b. should find one connectedAccount', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'connectedAccount', + gqlFields: CONNECTED_ACCOUNT_GQL_FIELDS, + filter: { + id: { + eq: CONNECTED_ACCOUNT_3_ID, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const connectedAccount = response.body.data.connectedAccount; + + expect(connectedAccount).toHaveProperty('handle'); + + expect(connectedAccount).toHaveProperty('id'); + expect(connectedAccount).toHaveProperty('deletedAt'); + expect(connectedAccount).toHaveProperty('createdAt'); + expect(connectedAccount).toHaveProperty('provider'); + expect(connectedAccount).toHaveProperty('accessToken'); + expect(connectedAccount).toHaveProperty('scopes'); + }); + + it('3. should update many connectedAccounts', async () => { + const graphqlOperation = updateManyOperationFactory({ + objectMetadataSingularName: 'connectedAccount', + objectMetadataPluralName: 'connectedAccounts', + gqlFields: CONNECTED_ACCOUNT_GQL_FIELDS, + data: { + handle: 'New Handle', + }, + filter: { + id: { + in: [CONNECTED_ACCOUNT_1_ID, CONNECTED_ACCOUNT_2_ID], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const updatedconnectedAccounts = response.body.data.updateConnectedAccounts; + + expect(updatedconnectedAccounts).toHaveLength(2); + + updatedconnectedAccounts.forEach((connectedAccount) => { + expect(connectedAccount.handle).toEqual('New Handle'); + }); + }); + + it('3b. should update one connectedAccount', async () => { + const graphqlOperation = updateOneOperationFactory({ + objectMetadataSingularName: 'connectedAccount', + gqlFields: CONNECTED_ACCOUNT_GQL_FIELDS, + data: { + handle: 'Updated Handle', + }, + recordId: CONNECTED_ACCOUNT_3_ID, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const updatedconnectedAccount = response.body.data.updateConnectedAccount; + + expect(updatedconnectedAccount.handle).toEqual('Updated Handle'); + }); + + it('4. should find many connectedAccounts with updated handle', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'connectedAccount', + objectMetadataPluralName: 'connectedAccounts', + gqlFields: CONNECTED_ACCOUNT_GQL_FIELDS, + filter: { + handle: { + eq: 'New Handle', + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.connectedAccounts.edges).toHaveLength(2); + }); + + it('4b. should find one connectedAccount with updated handle', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'connectedAccount', + gqlFields: CONNECTED_ACCOUNT_GQL_FIELDS, + filter: { + handle: { + eq: 'Updated Handle', + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.connectedAccount.handle).toEqual( + 'Updated Handle', + ); + }); + + it('5. should delete many connectedAccounts', async () => { + const graphqlOperation = deleteManyOperationFactory({ + objectMetadataSingularName: 'connectedAccount', + objectMetadataPluralName: 'connectedAccounts', + gqlFields: CONNECTED_ACCOUNT_GQL_FIELDS, + filter: { + id: { + in: [CONNECTED_ACCOUNT_1_ID, CONNECTED_ACCOUNT_2_ID], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const deleteConnectedAccounts = response.body.data.deleteConnectedAccounts; + + expect(deleteConnectedAccounts).toHaveLength(2); + + deleteConnectedAccounts.forEach((connectedAccount) => { + expect(connectedAccount.deletedAt).toBeTruthy(); + }); + }); + + it('5b. should delete one connectedAccount', async () => { + const graphqlOperation = deleteOneOperationFactory({ + objectMetadataSingularName: 'connectedAccount', + gqlFields: CONNECTED_ACCOUNT_GQL_FIELDS, + recordId: CONNECTED_ACCOUNT_3_ID, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.deleteConnectedAccount.deletedAt).toBeTruthy(); + }); + + it('6. should not find many connectedAccounts anymore', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'connectedAccount', + objectMetadataPluralName: 'connectedAccounts', + gqlFields: CONNECTED_ACCOUNT_GQL_FIELDS, + filter: { + id: { + in: [CONNECTED_ACCOUNT_1_ID, CONNECTED_ACCOUNT_2_ID], + }, + }, + }); + + const findConnectedAccountsResponse = + await makeGraphqlAPIRequest(graphqlOperation); + + expect( + findConnectedAccountsResponse.body.data.connectedAccounts.edges, + ).toHaveLength(0); + }); + + it('6b. should not find one connectedAccount anymore', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'connectedAccount', + gqlFields: CONNECTED_ACCOUNT_GQL_FIELDS, + filter: { + id: { + eq: CONNECTED_ACCOUNT_3_ID, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.connectedAccount).toBeNull(); + }); + + it('7. should find many deleted connectedAccounts with deletedAt filter', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'connectedAccount', + objectMetadataPluralName: 'connectedAccounts', + gqlFields: CONNECTED_ACCOUNT_GQL_FIELDS, + filter: { + id: { + in: [CONNECTED_ACCOUNT_1_ID, CONNECTED_ACCOUNT_2_ID], + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.connectedAccounts.edges).toHaveLength(2); + }); + + it('7b. should find one deleted connectedAccount with deletedAt filter', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'connectedAccount', + gqlFields: CONNECTED_ACCOUNT_GQL_FIELDS, + filter: { + id: { + eq: CONNECTED_ACCOUNT_3_ID, + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.connectedAccount.id).toEqual( + CONNECTED_ACCOUNT_3_ID, + ); + }); + + it('8. should destroy many connectedAccounts', async () => { + const graphqlOperation = destroyManyOperationFactory({ + objectMetadataSingularName: 'connectedAccount', + objectMetadataPluralName: 'connectedAccounts', + gqlFields: CONNECTED_ACCOUNT_GQL_FIELDS, + filter: { + id: { + in: [CONNECTED_ACCOUNT_1_ID, CONNECTED_ACCOUNT_2_ID], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.destroyConnectedAccounts).toHaveLength(2); + }); + + it('8b. should destroy one connectedAccount', async () => { + const graphqlOperation = destroyOneOperationFactory({ + objectMetadataSingularName: 'connectedAccount', + gqlFields: CONNECTED_ACCOUNT_GQL_FIELDS, + recordId: CONNECTED_ACCOUNT_3_ID, + }); + + const destroyConnectedAccountResponse = + await makeGraphqlAPIRequest(graphqlOperation); + + expect( + destroyConnectedAccountResponse.body.data.destroyConnectedAccount, + ).toBeTruthy(); + }); + + it('9. should not find many connectedAccounts anymore', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'connectedAccount', + objectMetadataPluralName: 'connectedAccounts', + gqlFields: CONNECTED_ACCOUNT_GQL_FIELDS, + filter: { + id: { + in: [CONNECTED_ACCOUNT_1_ID, CONNECTED_ACCOUNT_2_ID], + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.connectedAccounts.edges).toHaveLength(0); + }); + + it('9b. should not find one connectedAccount anymore', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'connectedAccount', + gqlFields: CONNECTED_ACCOUNT_GQL_FIELDS, + filter: { + id: { + eq: CONNECTED_ACCOUNT_3_ID, + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.connectedAccount).toBeNull(); + }); +}); diff --git a/packages/twenty-server/test/integration/graphql/suites/all-favorites-resolvers.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/all-favorites-resolvers.integration-spec.ts new file mode 100644 index 000000000000..bbf092a81169 --- /dev/null +++ b/packages/twenty-server/test/integration/graphql/suites/all-favorites-resolvers.integration-spec.ts @@ -0,0 +1,409 @@ +import { createManyOperationFactory } from 'test/integration/graphql/utils/create-many-operation-factory.util'; +import { createOneOperationFactory } from 'test/integration/graphql/utils/create-one-operation-factory.util'; +import { deleteManyOperationFactory } from 'test/integration/graphql/utils/delete-many-operation-factory.util'; +import { deleteOneOperationFactory } from 'test/integration/graphql/utils/delete-one-operation-factory.util'; +import { destroyManyOperationFactory } from 'test/integration/graphql/utils/destroy-many-operation-factory.util'; +import { destroyOneOperationFactory } from 'test/integration/graphql/utils/destroy-one-operation-factory.util'; +import { findManyOperationFactory } from 'test/integration/graphql/utils/find-many-operation-factory.util'; +import { findOneOperationFactory } from 'test/integration/graphql/utils/find-one-operation-factory.util'; +import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.util'; +import { updateManyOperationFactory } from 'test/integration/graphql/utils/update-many-operation-factory.util'; +import { updateOneOperationFactory } from 'test/integration/graphql/utils/update-one-operation-factory.util'; + +const FAVORITE_1_ID = '777a8457-eb2d-40ac-a707-551b615b6987'; +const FAVORITE_2_ID = '777a8457-eb2d-40ac-a707-551b615b6988'; +const FAVORITE_3_ID = '777a8457-eb2d-40ac-a707-551b615b6989'; +const INITIAL_FAVORITE_POSITION_1 = 1111111; +const INITIAL_FAVORITE_POSITION_2 = 2222222; +const INITIAL_FAVORITE_POSITION_3 = 3333333; +const NEW_FAVORITE_POSITION_1 = 4444444; +const NEW_FAVORITE_POSITION_2 = 5555555; +const FAVORITE_GQL_FIELDS = ` + id + position + createdAt + updatedAt + deletedAt + companyId + personId +`; + +describe('favorites resolvers (integration)', () => { + it('1. should create and return favorites', async () => { + const graphqlOperation = createManyOperationFactory({ + objectMetadataSingularName: 'favorite', + objectMetadataPluralName: 'favorites', + gqlFields: FAVORITE_GQL_FIELDS, + data: [ + { + id: FAVORITE_1_ID, + position: INITIAL_FAVORITE_POSITION_1, + }, + { + id: FAVORITE_2_ID, + position: INITIAL_FAVORITE_POSITION_2, + }, + ], + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.createFavorites).toHaveLength(2); + + response.body.data.createFavorites.forEach((favorite) => { + expect(favorite).toHaveProperty('position'); + expect([ + INITIAL_FAVORITE_POSITION_1, + INITIAL_FAVORITE_POSITION_2, + ]).toContain(favorite.position); + + expect(favorite).toHaveProperty('id'); + expect(favorite).toHaveProperty('createdAt'); + expect(favorite).toHaveProperty('updatedAt'); + expect(favorite).toHaveProperty('deletedAt'); + expect(favorite).toHaveProperty('companyId'); + expect(favorite).toHaveProperty('personId'); + }); + }); + + it('1b. should create and return one favorite', async () => { + const graphqlOperation = createOneOperationFactory({ + objectMetadataSingularName: 'favorite', + gqlFields: FAVORITE_GQL_FIELDS, + data: { + id: FAVORITE_3_ID, + position: INITIAL_FAVORITE_POSITION_3, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const createdFavorite = response.body.data.createFavorite; + + expect(createdFavorite).toHaveProperty('position'); + expect(createdFavorite.position).toEqual(INITIAL_FAVORITE_POSITION_3); + + expect(createdFavorite).toHaveProperty('id'); + expect(createdFavorite).toHaveProperty('createdAt'); + expect(createdFavorite).toHaveProperty('updatedAt'); + expect(createdFavorite).toHaveProperty('deletedAt'); + expect(createdFavorite).toHaveProperty('companyId'); + expect(createdFavorite).toHaveProperty('personId'); + }); + + it('2. should find many favorites', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'favorite', + objectMetadataPluralName: 'favorites', + gqlFields: FAVORITE_GQL_FIELDS, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const data = response.body.data.favorites; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const favorite = edges[0].node; + + expect(favorite).toHaveProperty('position'); + expect(favorite).toHaveProperty('id'); + expect(favorite).toHaveProperty('createdAt'); + expect(favorite).toHaveProperty('updatedAt'); + expect(favorite).toHaveProperty('deletedAt'); + expect(favorite).toHaveProperty('companyId'); + expect(favorite).toHaveProperty('personId'); + } + }); + + it('2b. should find one favorite', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'favorite', + gqlFields: FAVORITE_GQL_FIELDS, + filter: { + id: { + eq: FAVORITE_3_ID, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const favorite = response.body.data.favorite; + + expect(favorite).toHaveProperty('position'); + + expect(favorite).toHaveProperty('id'); + expect(favorite).toHaveProperty('createdAt'); + expect(favorite).toHaveProperty('updatedAt'); + expect(favorite).toHaveProperty('deletedAt'); + expect(favorite).toHaveProperty('companyId'); + expect(favorite).toHaveProperty('personId'); + }); + + it('3. should update many favorites', async () => { + const graphqlOperation = updateManyOperationFactory({ + objectMetadataSingularName: 'favorite', + objectMetadataPluralName: 'favorites', + gqlFields: FAVORITE_GQL_FIELDS, + data: { + position: NEW_FAVORITE_POSITION_1, + }, + filter: { + id: { + in: [FAVORITE_1_ID, FAVORITE_2_ID], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const updatedfavorites = response.body.data.updateFavorites; + + expect(updatedfavorites).toHaveLength(2); + + updatedfavorites.forEach((favorite) => { + expect(favorite.position).toEqual(NEW_FAVORITE_POSITION_1); + }); + }); + + it('3b. should update one favorite', async () => { + const graphqlOperation = updateOneOperationFactory({ + objectMetadataSingularName: 'favorite', + gqlFields: FAVORITE_GQL_FIELDS, + data: { + position: NEW_FAVORITE_POSITION_2, + }, + recordId: FAVORITE_3_ID, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const updatedfavorite = response.body.data.updateFavorite; + + expect(updatedfavorite.position).toEqual(NEW_FAVORITE_POSITION_2); + }); + + it('4. should find many favorites with updated position', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'favorite', + objectMetadataPluralName: 'favorites', + gqlFields: FAVORITE_GQL_FIELDS, + filter: { + position: { + eq: NEW_FAVORITE_POSITION_1, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.favorites.edges).toHaveLength(2); + }); + + it('4b. should find one favorite with updated position', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'favorite', + gqlFields: FAVORITE_GQL_FIELDS, + filter: { + position: { + eq: NEW_FAVORITE_POSITION_2, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.favorite.position).toEqual( + NEW_FAVORITE_POSITION_2, + ); + }); + + it('5. should delete many favorites', async () => { + const graphqlOperation = deleteManyOperationFactory({ + objectMetadataSingularName: 'favorite', + objectMetadataPluralName: 'favorites', + gqlFields: FAVORITE_GQL_FIELDS, + filter: { + id: { + in: [FAVORITE_1_ID, FAVORITE_2_ID], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const deleteFavorites = response.body.data.deleteFavorites; + + expect(deleteFavorites).toHaveLength(2); + + deleteFavorites.forEach((favorite) => { + expect(favorite.deletedAt).toBeTruthy(); + }); + }); + + it('5b. should delete one favorite', async () => { + const graphqlOperation = deleteOneOperationFactory({ + objectMetadataSingularName: 'favorite', + gqlFields: FAVORITE_GQL_FIELDS, + recordId: FAVORITE_3_ID, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.deleteFavorite.deletedAt).toBeTruthy(); + }); + + it('6. should not find many favorites anymore', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'favorite', + objectMetadataPluralName: 'favorites', + gqlFields: FAVORITE_GQL_FIELDS, + filter: { + id: { + in: [FAVORITE_1_ID, FAVORITE_2_ID], + }, + }, + }); + + const findFavoritesResponse = await makeGraphqlAPIRequest(graphqlOperation); + + expect(findFavoritesResponse.body.data.favorites.edges).toHaveLength(0); + }); + + it('6b. should not find one favorite anymore', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'favorite', + gqlFields: FAVORITE_GQL_FIELDS, + filter: { + id: { + eq: FAVORITE_3_ID, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.favorite).toBeNull(); + }); + + it('7. should find many deleted favorites with deletedAt filter', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'favorite', + objectMetadataPluralName: 'favorites', + gqlFields: FAVORITE_GQL_FIELDS, + filter: { + id: { + in: [FAVORITE_1_ID, FAVORITE_2_ID], + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.favorites.edges).toHaveLength(2); + }); + + it('7b. should find one deleted favorite with deletedAt filter', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'favorite', + gqlFields: FAVORITE_GQL_FIELDS, + filter: { + id: { + eq: FAVORITE_3_ID, + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.favorite.id).toEqual(FAVORITE_3_ID); + }); + + it('8. should destroy many favorites', async () => { + const graphqlOperation = destroyManyOperationFactory({ + objectMetadataSingularName: 'favorite', + objectMetadataPluralName: 'favorites', + gqlFields: FAVORITE_GQL_FIELDS, + filter: { + id: { + in: [FAVORITE_1_ID, FAVORITE_2_ID], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.destroyFavorites).toHaveLength(2); + }); + + it('8b. should destroy one favorite', async () => { + const graphqlOperation = destroyOneOperationFactory({ + objectMetadataSingularName: 'favorite', + gqlFields: FAVORITE_GQL_FIELDS, + recordId: FAVORITE_3_ID, + }); + + const destroyFavoriteResponse = + await makeGraphqlAPIRequest(graphqlOperation); + + expect(destroyFavoriteResponse.body.data.destroyFavorite).toBeTruthy(); + }); + + it('9. should not find many favorites anymore', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'favorite', + objectMetadataPluralName: 'favorites', + gqlFields: FAVORITE_GQL_FIELDS, + filter: { + id: { + in: [FAVORITE_1_ID, FAVORITE_2_ID], + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.favorites.edges).toHaveLength(0); + }); + + it('9b. should not find one favorite anymore', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'favorite', + gqlFields: FAVORITE_GQL_FIELDS, + filter: { + id: { + eq: FAVORITE_3_ID, + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.favorite).toBeNull(); + }); +}); diff --git a/packages/twenty-server/test/integration/graphql/suites/all-message-channel-message-associations-resolvers.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/all-message-channel-message-associations-resolvers.integration-spec.ts new file mode 100644 index 000000000000..2613311067cb --- /dev/null +++ b/packages/twenty-server/test/integration/graphql/suites/all-message-channel-message-associations-resolvers.integration-spec.ts @@ -0,0 +1,493 @@ +import { createManyOperationFactory } from 'test/integration/graphql/utils/create-many-operation-factory.util'; +import { createOneOperationFactory } from 'test/integration/graphql/utils/create-one-operation-factory.util'; +import { deleteManyOperationFactory } from 'test/integration/graphql/utils/delete-many-operation-factory.util'; +import { deleteOneOperationFactory } from 'test/integration/graphql/utils/delete-one-operation-factory.util'; +import { destroyManyOperationFactory } from 'test/integration/graphql/utils/destroy-many-operation-factory.util'; +import { destroyOneOperationFactory } from 'test/integration/graphql/utils/destroy-one-operation-factory.util'; +import { findManyOperationFactory } from 'test/integration/graphql/utils/find-many-operation-factory.util'; +import { findOneOperationFactory } from 'test/integration/graphql/utils/find-one-operation-factory.util'; +import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.util'; +import { updateManyOperationFactory } from 'test/integration/graphql/utils/update-many-operation-factory.util'; +import { updateOneOperationFactory } from 'test/integration/graphql/utils/update-one-operation-factory.util'; +import { generateRecordName } from 'test/integration/utils/generate-record-name'; + +const MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_1_ID = + '777a8457-eb2d-40ac-a707-551b615b6987'; +const MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_2_ID = + '777a8457-eb2d-40ac-a707-551b615b6988'; +const MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_3_ID = + '777a8457-eb2d-40ac-a707-551b615b6989'; + +const MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_GQL_FIELDS = ` + id + messageExternalId + createdAt + updatedAt + deletedAt + messageChannelId + messageId + direction +`; + +describe('messageChannelMessageAssociations resolvers (integration)', () => { + it('1. should create and return messageChannelMessageAssociations', async () => { + const messageExternalId1 = generateRecordName( + MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_1_ID, + ); + const messageExternalId2 = generateRecordName( + MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_2_ID, + ); + const graphqlOperation = createManyOperationFactory({ + objectMetadataSingularName: 'messageChannelMessageAssociation', + objectMetadataPluralName: 'messageChannelMessageAssociations', + gqlFields: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_GQL_FIELDS, + data: [ + { + id: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_1_ID, + messageExternalId: messageExternalId1, + }, + { + id: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_2_ID, + messageExternalId: messageExternalId2, + }, + ], + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect( + response.body.data.createMessageChannelMessageAssociations, + ).toHaveLength(2); + + response.body.data.createMessageChannelMessageAssociations.forEach( + (messageChannelMessageAssociation) => { + expect(messageChannelMessageAssociation).toHaveProperty( + 'messageExternalId', + ); + expect([messageExternalId1, messageExternalId2]).toContain( + messageChannelMessageAssociation.messageExternalId, + ); + + expect(messageChannelMessageAssociation).toHaveProperty('id'); + expect(messageChannelMessageAssociation).toHaveProperty('createdAt'); + expect(messageChannelMessageAssociation).toHaveProperty('updatedAt'); + expect(messageChannelMessageAssociation).toHaveProperty('deletedAt'); + expect(messageChannelMessageAssociation).toHaveProperty( + 'messageChannelId', + ); + expect(messageChannelMessageAssociation).toHaveProperty('messageId'); + expect(messageChannelMessageAssociation).toHaveProperty('direction'); + }, + ); + }); + + it('1b. should create and return one messageChannelMessageAssociation', async () => { + const messageExternalId3 = generateRecordName( + MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_3_ID, + ); + + const graphqlOperation = createOneOperationFactory({ + objectMetadataSingularName: 'messageChannelMessageAssociation', + gqlFields: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_GQL_FIELDS, + data: { + id: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_3_ID, + messageExternalId: messageExternalId3, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const createdMessageChannelMessageAssociation = + response.body.data.createMessageChannelMessageAssociation; + + expect(createdMessageChannelMessageAssociation).toHaveProperty( + 'messageExternalId', + ); + expect(createdMessageChannelMessageAssociation.messageExternalId).toEqual( + messageExternalId3, + ); + + expect(createdMessageChannelMessageAssociation).toHaveProperty('id'); + expect(createdMessageChannelMessageAssociation).toHaveProperty('createdAt'); + expect(createdMessageChannelMessageAssociation).toHaveProperty('updatedAt'); + expect(createdMessageChannelMessageAssociation).toHaveProperty('deletedAt'); + expect(createdMessageChannelMessageAssociation).toHaveProperty( + 'messageChannelId', + ); + expect(createdMessageChannelMessageAssociation).toHaveProperty('messageId'); + expect(createdMessageChannelMessageAssociation).toHaveProperty('direction'); + }); + + it('2. should find many messageChannelMessageAssociations', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'messageChannelMessageAssociation', + objectMetadataPluralName: 'messageChannelMessageAssociations', + gqlFields: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_GQL_FIELDS, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const data = response.body.data.messageChannelMessageAssociations; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const messageChannelMessageAssociation = edges[0].node; + + expect(messageChannelMessageAssociation).toHaveProperty( + 'messageExternalId', + ); + expect(messageChannelMessageAssociation).toHaveProperty('id'); + expect(messageChannelMessageAssociation).toHaveProperty('createdAt'); + expect(messageChannelMessageAssociation).toHaveProperty('updatedAt'); + expect(messageChannelMessageAssociation).toHaveProperty('deletedAt'); + expect(messageChannelMessageAssociation).toHaveProperty( + 'messageChannelId', + ); + expect(messageChannelMessageAssociation).toHaveProperty('messageId'); + expect(messageChannelMessageAssociation).toHaveProperty('direction'); + } + }); + + it('2b. should find one messageChannelMessageAssociation', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'messageChannelMessageAssociation', + gqlFields: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_GQL_FIELDS, + filter: { + id: { + eq: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_3_ID, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const messageChannelMessageAssociation = + response.body.data.messageChannelMessageAssociation; + + expect(messageChannelMessageAssociation).toHaveProperty( + 'messageExternalId', + ); + + expect(messageChannelMessageAssociation).toHaveProperty('id'); + expect(messageChannelMessageAssociation).toHaveProperty('createdAt'); + expect(messageChannelMessageAssociation).toHaveProperty('updatedAt'); + expect(messageChannelMessageAssociation).toHaveProperty('deletedAt'); + expect(messageChannelMessageAssociation).toHaveProperty('messageChannelId'); + expect(messageChannelMessageAssociation).toHaveProperty('messageId'); + expect(messageChannelMessageAssociation).toHaveProperty('direction'); + }); + + it('3. should update many messageChannelMessageAssociations', async () => { + const graphqlOperation = updateManyOperationFactory({ + objectMetadataSingularName: 'messageChannelMessageAssociation', + objectMetadataPluralName: 'messageChannelMessageAssociations', + gqlFields: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_GQL_FIELDS, + data: { + messageExternalId: 'updated-message-external-id', + }, + filter: { + id: { + in: [ + MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_1_ID, + MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_2_ID, + ], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const updatedmessageChannelMessageAssociations = + response.body.data.updateMessageChannelMessageAssociations; + + expect(updatedmessageChannelMessageAssociations).toHaveLength(2); + + updatedmessageChannelMessageAssociations.forEach( + (messageChannelMessageAssociation) => { + expect(messageChannelMessageAssociation.messageExternalId).toEqual( + 'updated-message-external-id', + ); + }, + ); + }); + + it('3b. should update one messageChannelMessageAssociation', async () => { + const graphqlOperation = updateOneOperationFactory({ + objectMetadataSingularName: 'messageChannelMessageAssociation', + gqlFields: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_GQL_FIELDS, + data: { + messageExternalId: 'new-message-external-id', + }, + recordId: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_3_ID, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const updatedmessageChannelMessageAssociation = + response.body.data.updateMessageChannelMessageAssociation; + + expect(updatedmessageChannelMessageAssociation.messageExternalId).toEqual( + 'new-message-external-id', + ); + }); + + it('4. should find many messageChannelMessageAssociations with updated messageExternalId', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'messageChannelMessageAssociation', + objectMetadataPluralName: 'messageChannelMessageAssociations', + gqlFields: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_GQL_FIELDS, + filter: { + messageExternalId: { + eq: 'updated-message-external-id', + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect( + response.body.data.messageChannelMessageAssociations.edges, + ).toHaveLength(2); + }); + + it('4b. should find one messageChannelMessageAssociation with updated messageExternalId', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'messageChannelMessageAssociation', + gqlFields: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_GQL_FIELDS, + filter: { + messageExternalId: { + eq: 'new-message-external-id', + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect( + response.body.data.messageChannelMessageAssociation.messageExternalId, + ).toEqual('new-message-external-id'); + }); + + it('5. should delete many messageChannelMessageAssociations', async () => { + const graphqlOperation = deleteManyOperationFactory({ + objectMetadataSingularName: 'messageChannelMessageAssociation', + objectMetadataPluralName: 'messageChannelMessageAssociations', + gqlFields: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_GQL_FIELDS, + filter: { + id: { + in: [ + MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_1_ID, + MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_2_ID, + ], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const deleteMessageChannelMessageAssociations = + response.body.data.deleteMessageChannelMessageAssociations; + + expect(deleteMessageChannelMessageAssociations).toHaveLength(2); + + deleteMessageChannelMessageAssociations.forEach( + (messageChannelMessageAssociation) => { + expect(messageChannelMessageAssociation.deletedAt).toBeTruthy(); + }, + ); + }); + + it('5b. should delete one messageChannelMessageAssociation', async () => { + const graphqlOperation = deleteOneOperationFactory({ + objectMetadataSingularName: 'messageChannelMessageAssociation', + gqlFields: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_GQL_FIELDS, + recordId: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_3_ID, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect( + response.body.data.deleteMessageChannelMessageAssociation.deletedAt, + ).toBeTruthy(); + }); + + it('6. should not find many messageChannelMessageAssociations anymore', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'messageChannelMessageAssociation', + objectMetadataPluralName: 'messageChannelMessageAssociations', + gqlFields: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_GQL_FIELDS, + filter: { + id: { + in: [ + MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_1_ID, + MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_2_ID, + ], + }, + }, + }); + + const findMessageChannelMessageAssociationsResponse = + await makeGraphqlAPIRequest(graphqlOperation); + + expect( + findMessageChannelMessageAssociationsResponse.body.data + .messageChannelMessageAssociations.edges, + ).toHaveLength(0); + }); + + it('6b. should not find one messageChannelMessageAssociation anymore', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'messageChannelMessageAssociation', + gqlFields: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_GQL_FIELDS, + filter: { + id: { + eq: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_3_ID, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.messageChannelMessageAssociation).toBeNull(); + }); + + it('7. should find many deleted messageChannelMessageAssociations with deletedAt filter', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'messageChannelMessageAssociation', + objectMetadataPluralName: 'messageChannelMessageAssociations', + gqlFields: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_GQL_FIELDS, + filter: { + id: { + in: [ + MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_1_ID, + MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_2_ID, + ], + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect( + response.body.data.messageChannelMessageAssociations.edges, + ).toHaveLength(2); + }); + + it('7b. should find one deleted messageChannelMessageAssociation with deletedAt filter', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'messageChannelMessageAssociation', + gqlFields: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_GQL_FIELDS, + filter: { + id: { + eq: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_3_ID, + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.messageChannelMessageAssociation.id).toEqual( + MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_3_ID, + ); + }); + + it('8. should destroy many messageChannelMessageAssociations', async () => { + const graphqlOperation = destroyManyOperationFactory({ + objectMetadataSingularName: 'messageChannelMessageAssociation', + objectMetadataPluralName: 'messageChannelMessageAssociations', + gqlFields: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_GQL_FIELDS, + filter: { + id: { + in: [ + MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_1_ID, + MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_2_ID, + ], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect( + response.body.data.destroyMessageChannelMessageAssociations, + ).toHaveLength(2); + }); + + it('8b. should destroy one messageChannelMessageAssociation', async () => { + const graphqlOperation = destroyOneOperationFactory({ + objectMetadataSingularName: 'messageChannelMessageAssociation', + gqlFields: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_GQL_FIELDS, + recordId: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_3_ID, + }); + + const destroyMessageChannelMessageAssociationResponse = + await makeGraphqlAPIRequest(graphqlOperation); + + expect( + destroyMessageChannelMessageAssociationResponse.body.data + .destroyMessageChannelMessageAssociation, + ).toBeTruthy(); + }); + + it('9. should not find many messageChannelMessageAssociations anymore', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'messageChannelMessageAssociation', + objectMetadataPluralName: 'messageChannelMessageAssociations', + gqlFields: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_GQL_FIELDS, + filter: { + id: { + in: [ + MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_1_ID, + MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_2_ID, + ], + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect( + response.body.data.messageChannelMessageAssociations.edges, + ).toHaveLength(0); + }); + + it('9b. should not find one messageChannelMessageAssociation anymore', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'messageChannelMessageAssociation', + gqlFields: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_GQL_FIELDS, + filter: { + id: { + eq: MESSAGE_CHANNEL_MESSAGE_ASSOCIATION_3_ID, + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.messageChannelMessageAssociation).toBeNull(); + }); +}); diff --git a/packages/twenty-server/test/integration/graphql/suites/all-message-channels-resolvers.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/all-message-channels-resolvers.integration-spec.ts new file mode 100644 index 000000000000..effc793ca76a --- /dev/null +++ b/packages/twenty-server/test/integration/graphql/suites/all-message-channels-resolvers.integration-spec.ts @@ -0,0 +1,455 @@ +import { TIM_ACCOUNT_ID } from 'test/integration/graphql/integration.constants'; +import { createManyOperationFactory } from 'test/integration/graphql/utils/create-many-operation-factory.util'; +import { createOneOperationFactory } from 'test/integration/graphql/utils/create-one-operation-factory.util'; +import { deleteManyOperationFactory } from 'test/integration/graphql/utils/delete-many-operation-factory.util'; +import { deleteOneOperationFactory } from 'test/integration/graphql/utils/delete-one-operation-factory.util'; +import { destroyManyOperationFactory } from 'test/integration/graphql/utils/destroy-many-operation-factory.util'; +import { destroyOneOperationFactory } from 'test/integration/graphql/utils/destroy-one-operation-factory.util'; +import { findManyOperationFactory } from 'test/integration/graphql/utils/find-many-operation-factory.util'; +import { findOneOperationFactory } from 'test/integration/graphql/utils/find-one-operation-factory.util'; +import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.util'; +import { updateManyOperationFactory } from 'test/integration/graphql/utils/update-many-operation-factory.util'; +import { updateOneOperationFactory } from 'test/integration/graphql/utils/update-one-operation-factory.util'; +import { generateRecordName } from 'test/integration/utils/generate-record-name'; + +const MESSAGE_CHANNEL_1_ID = '777a8457-eb2d-40ac-a707-551b615b6987'; +const MESSAGE_CHANNEL_2_ID = '777a8457-eb2d-40ac-a707-551b615b6988'; +const MESSAGE_CHANNEL_3_ID = '777a8457-eb2d-40ac-a707-551b615b6989'; +const CONNECTED_ACCOUNT_ID = '777a8457-eb2d-40ac-a707-441b615b6989'; + +const MESSAGE_CHANNEL_GQL_FIELDS = ` + id + handle + deletedAt + createdAt + contactAutoCreationPolicy + isContactAutoCreationEnabled + isSyncEnabled + syncCursor + type +`; + +describe('messageChannels resolvers (integration)', () => { + beforeAll(async () => { + const connectedAccountHandle = generateRecordName(CONNECTED_ACCOUNT_ID); + const graphqlOperation = createOneOperationFactory({ + objectMetadataSingularName: 'connectedAccount', + gqlFields: `id`, + data: { + id: CONNECTED_ACCOUNT_ID, + accountOwnerId: TIM_ACCOUNT_ID, + handle: connectedAccountHandle, + }, + }); + + await makeGraphqlAPIRequest(graphqlOperation); + }); + + afterAll(async () => { + const graphqlOperation = destroyOneOperationFactory({ + objectMetadataSingularName: 'connectedAccount', + gqlFields: `id`, + recordId: CONNECTED_ACCOUNT_ID, + }); + + await makeGraphqlAPIRequest(graphqlOperation); + }); + + it('1. should create and return messageChannels', async () => { + const messageChannelHandle1 = generateRecordName(MESSAGE_CHANNEL_1_ID); + const messageChannelHandle2 = generateRecordName(MESSAGE_CHANNEL_2_ID); + + const graphqlOperation = createManyOperationFactory({ + objectMetadataSingularName: 'messageChannel', + objectMetadataPluralName: 'messageChannels', + gqlFields: MESSAGE_CHANNEL_GQL_FIELDS, + data: [ + { + id: MESSAGE_CHANNEL_1_ID, + handle: messageChannelHandle1, + connectedAccountId: CONNECTED_ACCOUNT_ID, + }, + { + id: MESSAGE_CHANNEL_2_ID, + handle: messageChannelHandle2, + connectedAccountId: CONNECTED_ACCOUNT_ID, + }, + ], + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.createMessageChannels).toHaveLength(2); + + response.body.data.createMessageChannels.forEach((messageChannel) => { + expect(messageChannel).toHaveProperty('handle'); + expect([messageChannelHandle1, messageChannelHandle2]).toContain( + messageChannel.handle, + ); + + expect(messageChannel).toHaveProperty('id'); + expect(messageChannel).toHaveProperty('deletedAt'); + expect(messageChannel).toHaveProperty('createdAt'); + expect(messageChannel).toHaveProperty('contactAutoCreationPolicy'); + expect(messageChannel).toHaveProperty('isContactAutoCreationEnabled'); + expect(messageChannel).toHaveProperty('isSyncEnabled'); + expect(messageChannel).toHaveProperty('syncCursor'); + expect(messageChannel).toHaveProperty('type'); + }); + }); + + it('1b. should create and return one messageChannel', async () => { + const messageChannelHandle = generateRecordName(MESSAGE_CHANNEL_3_ID); + + const graphqlOperation = createOneOperationFactory({ + objectMetadataSingularName: 'messageChannel', + gqlFields: MESSAGE_CHANNEL_GQL_FIELDS, + data: { + id: MESSAGE_CHANNEL_3_ID, + handle: messageChannelHandle, + connectedAccountId: CONNECTED_ACCOUNT_ID, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const createdMessageChannel = response.body.data.createMessageChannel; + + expect(createdMessageChannel).toHaveProperty('handle'); + expect(createdMessageChannel.handle).toEqual(messageChannelHandle); + + expect(createdMessageChannel).toHaveProperty('id'); + expect(createdMessageChannel).toHaveProperty('deletedAt'); + expect(createdMessageChannel).toHaveProperty('createdAt'); + expect(createdMessageChannel).toHaveProperty('contactAutoCreationPolicy'); + expect(createdMessageChannel).toHaveProperty( + 'isContactAutoCreationEnabled', + ); + expect(createdMessageChannel).toHaveProperty('isSyncEnabled'); + expect(createdMessageChannel).toHaveProperty('syncCursor'); + expect(createdMessageChannel).toHaveProperty('type'); + }); + + it('2. should find many messageChannels', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'messageChannel', + objectMetadataPluralName: 'messageChannels', + gqlFields: MESSAGE_CHANNEL_GQL_FIELDS, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const data = response.body.data.messageChannels; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const messageChannel = edges[0].node; + + expect(messageChannel).toHaveProperty('handle'); + expect(messageChannel).toHaveProperty('id'); + expect(messageChannel).toHaveProperty('deletedAt'); + expect(messageChannel).toHaveProperty('createdAt'); + expect(messageChannel).toHaveProperty('contactAutoCreationPolicy'); + expect(messageChannel).toHaveProperty('isContactAutoCreationEnabled'); + expect(messageChannel).toHaveProperty('isSyncEnabled'); + expect(messageChannel).toHaveProperty('syncCursor'); + expect(messageChannel).toHaveProperty('type'); + } + }); + + it('2b. should find one messageChannel', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'messageChannel', + gqlFields: MESSAGE_CHANNEL_GQL_FIELDS, + filter: { + id: { + eq: MESSAGE_CHANNEL_3_ID, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const messageChannel = response.body.data.messageChannel; + + expect(messageChannel).toHaveProperty('handle'); + + expect(messageChannel).toHaveProperty('id'); + expect(messageChannel).toHaveProperty('deletedAt'); + expect(messageChannel).toHaveProperty('createdAt'); + expect(messageChannel).toHaveProperty('contactAutoCreationPolicy'); + expect(messageChannel).toHaveProperty('isContactAutoCreationEnabled'); + expect(messageChannel).toHaveProperty('isSyncEnabled'); + expect(messageChannel).toHaveProperty('syncCursor'); + expect(messageChannel).toHaveProperty('type'); + }); + + it('3. should update many messageChannels', async () => { + const graphqlOperation = updateManyOperationFactory({ + objectMetadataSingularName: 'messageChannel', + objectMetadataPluralName: 'messageChannels', + gqlFields: MESSAGE_CHANNEL_GQL_FIELDS, + data: { + handle: 'New Handle', + }, + filter: { + id: { + in: [MESSAGE_CHANNEL_1_ID, MESSAGE_CHANNEL_2_ID], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const updatedmessageChannels = response.body.data.updateMessageChannels; + + expect(updatedmessageChannels).toHaveLength(2); + + updatedmessageChannels.forEach((messageChannel) => { + expect(messageChannel.handle).toEqual('New Handle'); + }); + }); + + it('3b. should update one messageChannel', async () => { + const graphqlOperation = updateOneOperationFactory({ + objectMetadataSingularName: 'messageChannel', + gqlFields: MESSAGE_CHANNEL_GQL_FIELDS, + data: { + handle: 'Updated Handle', + }, + recordId: MESSAGE_CHANNEL_3_ID, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const updatedmessageChannel = response.body.data.updateMessageChannel; + + expect(updatedmessageChannel.handle).toEqual('Updated Handle'); + }); + + it('4. should find many messageChannels with updated handle', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'messageChannel', + objectMetadataPluralName: 'messageChannels', + gqlFields: MESSAGE_CHANNEL_GQL_FIELDS, + filter: { + handle: { + eq: 'New Handle', + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.messageChannels.edges).toHaveLength(2); + }); + + it('4b. should find one messageChannel with updated handle', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'messageChannel', + gqlFields: MESSAGE_CHANNEL_GQL_FIELDS, + filter: { + handle: { + eq: 'Updated Handle', + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.messageChannel.handle).toEqual('Updated Handle'); + }); + + it('5. should delete many messageChannels', async () => { + const graphqlOperation = deleteManyOperationFactory({ + objectMetadataSingularName: 'messageChannel', + objectMetadataPluralName: 'messageChannels', + gqlFields: MESSAGE_CHANNEL_GQL_FIELDS, + filter: { + id: { + in: [MESSAGE_CHANNEL_1_ID, MESSAGE_CHANNEL_2_ID], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const deleteMessageChannels = response.body.data.deleteMessageChannels; + + expect(deleteMessageChannels).toHaveLength(2); + + deleteMessageChannels.forEach((messageChannel) => { + expect(messageChannel.deletedAt).toBeTruthy(); + }); + }); + + it('5b. should delete one messageChannel', async () => { + const graphqlOperation = deleteOneOperationFactory({ + objectMetadataSingularName: 'messageChannel', + gqlFields: MESSAGE_CHANNEL_GQL_FIELDS, + recordId: MESSAGE_CHANNEL_3_ID, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.deleteMessageChannel.deletedAt).toBeTruthy(); + }); + + it('6. should not find many messageChannels anymore', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'messageChannel', + objectMetadataPluralName: 'messageChannels', + gqlFields: MESSAGE_CHANNEL_GQL_FIELDS, + filter: { + id: { + in: [MESSAGE_CHANNEL_1_ID, MESSAGE_CHANNEL_2_ID], + }, + }, + }); + + const findMessageChannelsResponse = + await makeGraphqlAPIRequest(graphqlOperation); + + expect( + findMessageChannelsResponse.body.data.messageChannels.edges, + ).toHaveLength(0); + }); + + it('6b. should not find one messageChannel anymore', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'messageChannel', + gqlFields: MESSAGE_CHANNEL_GQL_FIELDS, + filter: { + id: { + eq: MESSAGE_CHANNEL_3_ID, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.messageChannel).toBeNull(); + }); + + it('7. should find many deleted messageChannels with deletedAt filter', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'messageChannel', + objectMetadataPluralName: 'messageChannels', + gqlFields: MESSAGE_CHANNEL_GQL_FIELDS, + filter: { + id: { + in: [MESSAGE_CHANNEL_1_ID, MESSAGE_CHANNEL_2_ID], + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.messageChannels.edges).toHaveLength(2); + }); + + it('7b. should find one deleted messageChannel with deletedAt filter', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'messageChannel', + gqlFields: MESSAGE_CHANNEL_GQL_FIELDS, + filter: { + id: { + eq: MESSAGE_CHANNEL_3_ID, + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.messageChannel.id).toEqual(MESSAGE_CHANNEL_3_ID); + }); + + it('8. should destroy many messageChannels', async () => { + const graphqlOperation = destroyManyOperationFactory({ + objectMetadataSingularName: 'messageChannel', + objectMetadataPluralName: 'messageChannels', + gqlFields: MESSAGE_CHANNEL_GQL_FIELDS, + filter: { + id: { + in: [MESSAGE_CHANNEL_1_ID, MESSAGE_CHANNEL_2_ID], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.destroyMessageChannels).toHaveLength(2); + }); + + it('8b. should destroy one messageChannel', async () => { + const graphqlOperation = destroyOneOperationFactory({ + objectMetadataSingularName: 'messageChannel', + gqlFields: MESSAGE_CHANNEL_GQL_FIELDS, + recordId: MESSAGE_CHANNEL_3_ID, + }); + + const destroyMessageChannelResponse = + await makeGraphqlAPIRequest(graphqlOperation); + + expect( + destroyMessageChannelResponse.body.data.destroyMessageChannel, + ).toBeTruthy(); + }); + + it('9. should not find many messageChannels anymore', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'messageChannel', + objectMetadataPluralName: 'messageChannels', + gqlFields: MESSAGE_CHANNEL_GQL_FIELDS, + filter: { + id: { + in: [MESSAGE_CHANNEL_1_ID, MESSAGE_CHANNEL_2_ID], + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.messageChannels.edges).toHaveLength(0); + }); + + it('9b. should not find one messageChannel anymore', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'messageChannel', + gqlFields: MESSAGE_CHANNEL_GQL_FIELDS, + filter: { + id: { + eq: MESSAGE_CHANNEL_3_ID, + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.messageChannel).toBeNull(); + }); +}); diff --git a/packages/twenty-server/test/integration/graphql/suites/all-message-participants-resolvers.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/all-message-participants-resolvers.integration-spec.ts new file mode 100644 index 000000000000..3c064564b576 --- /dev/null +++ b/packages/twenty-server/test/integration/graphql/suites/all-message-participants-resolvers.integration-spec.ts @@ -0,0 +1,466 @@ +import { createManyOperationFactory } from 'test/integration/graphql/utils/create-many-operation-factory.util'; +import { createOneOperationFactory } from 'test/integration/graphql/utils/create-one-operation-factory.util'; +import { deleteManyOperationFactory } from 'test/integration/graphql/utils/delete-many-operation-factory.util'; +import { deleteOneOperationFactory } from 'test/integration/graphql/utils/delete-one-operation-factory.util'; +import { destroyManyOperationFactory } from 'test/integration/graphql/utils/destroy-many-operation-factory.util'; +import { destroyOneOperationFactory } from 'test/integration/graphql/utils/destroy-one-operation-factory.util'; +import { findManyOperationFactory } from 'test/integration/graphql/utils/find-many-operation-factory.util'; +import { findOneOperationFactory } from 'test/integration/graphql/utils/find-one-operation-factory.util'; +import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.util'; +import { updateManyOperationFactory } from 'test/integration/graphql/utils/update-many-operation-factory.util'; +import { updateOneOperationFactory } from 'test/integration/graphql/utils/update-one-operation-factory.util'; +import { generateRecordName } from 'test/integration/utils/generate-record-name'; + +const MESSAGE_PARTICIPANT_1_ID = '777a8457-eb2d-40ac-a707-551b615b6987'; +const MESSAGE_PARTICIPANT_2_ID = '777a8457-eb2d-40ac-a707-551b615b6988'; +const MESSAGE_PARTICIPANT_3_ID = '777a8457-eb2d-40ac-a707-551b615b6989'; +const MESSAGE_ID = '777a8457-eb2d-40ac-a707-441b615b6989'; +const MESSAGE_PARTICIPANT_GQL_FIELDS = ` + id + displayName + handle + role + messageId + workspaceMemberId + createdAt + deletedAt +`; + +describe('messageParticipants resolvers (integration)', () => { + beforeAll(async () => { + const messageSubject = generateRecordName(MESSAGE_ID); + const graphqlOperation = createOneOperationFactory({ + objectMetadataSingularName: 'message', + gqlFields: `id`, + data: { + id: MESSAGE_ID, + subject: messageSubject, + }, + }); + + await makeGraphqlAPIRequest(graphqlOperation); + }); + + afterAll(async () => { + const graphqlOperation = destroyOneOperationFactory({ + objectMetadataSingularName: 'message', + gqlFields: `id`, + recordId: MESSAGE_ID, + }); + + await makeGraphqlAPIRequest(graphqlOperation); + }); + + it('1. should create and return messageParticipants', async () => { + const messageParticipantDisplayName1 = generateRecordName( + MESSAGE_PARTICIPANT_1_ID, + ); + const messageParticipantDisplayName2 = generateRecordName( + MESSAGE_PARTICIPANT_2_ID, + ); + + const graphqlOperation = createManyOperationFactory({ + objectMetadataSingularName: 'messageParticipant', + objectMetadataPluralName: 'messageParticipants', + gqlFields: MESSAGE_PARTICIPANT_GQL_FIELDS, + data: [ + { + id: MESSAGE_PARTICIPANT_1_ID, + displayName: messageParticipantDisplayName1, + messageId: MESSAGE_ID, + }, + { + id: MESSAGE_PARTICIPANT_2_ID, + displayName: messageParticipantDisplayName2, + messageId: MESSAGE_ID, + }, + ], + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.createMessageParticipants).toHaveLength(2); + + response.body.data.createMessageParticipants.forEach( + (messageParticipant) => { + expect(messageParticipant).toHaveProperty('displayName'); + expect([ + messageParticipantDisplayName1, + messageParticipantDisplayName2, + ]).toContain(messageParticipant.displayName); + + expect(messageParticipant).toHaveProperty('id'); + expect(messageParticipant).toHaveProperty('handle'); + expect(messageParticipant).toHaveProperty('role'); + expect(messageParticipant).toHaveProperty('messageId'); + expect(messageParticipant).toHaveProperty('workspaceMemberId'); + expect(messageParticipant).toHaveProperty('createdAt'); + expect(messageParticipant).toHaveProperty('deletedAt'); + }, + ); + }); + + it('1b. should create and return one messageParticipant', async () => { + const messageParticipantDisplayName = generateRecordName( + MESSAGE_PARTICIPANT_3_ID, + ); + + const graphqlOperation = createOneOperationFactory({ + objectMetadataSingularName: 'messageParticipant', + gqlFields: MESSAGE_PARTICIPANT_GQL_FIELDS, + data: { + id: MESSAGE_PARTICIPANT_3_ID, + displayName: messageParticipantDisplayName, + messageId: MESSAGE_ID, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const createdMessageParticipant = + response.body.data.createMessageParticipant; + + expect(createdMessageParticipant).toHaveProperty('displayName'); + expect(createdMessageParticipant.displayName).toEqual( + messageParticipantDisplayName, + ); + + expect(createdMessageParticipant).toHaveProperty('id'); + expect(createdMessageParticipant).toHaveProperty('handle'); + expect(createdMessageParticipant).toHaveProperty('role'); + expect(createdMessageParticipant).toHaveProperty('messageId'); + expect(createdMessageParticipant).toHaveProperty('workspaceMemberId'); + expect(createdMessageParticipant).toHaveProperty('createdAt'); + expect(createdMessageParticipant).toHaveProperty('deletedAt'); + }); + + it('2. should find many messageParticipants', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'messageParticipant', + objectMetadataPluralName: 'messageParticipants', + gqlFields: MESSAGE_PARTICIPANT_GQL_FIELDS, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const data = response.body.data.messageParticipants; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const messageParticipant = edges[0].node; + + expect(messageParticipant).toHaveProperty('displayName'); + expect(messageParticipant).toHaveProperty('id'); + expect(messageParticipant).toHaveProperty('handle'); + expect(messageParticipant).toHaveProperty('role'); + expect(messageParticipant).toHaveProperty('messageId'); + expect(messageParticipant).toHaveProperty('workspaceMemberId'); + expect(messageParticipant).toHaveProperty('createdAt'); + expect(messageParticipant).toHaveProperty('deletedAt'); + } + }); + + it('2b. should find one messageParticipant', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'messageParticipant', + gqlFields: MESSAGE_PARTICIPANT_GQL_FIELDS, + filter: { + id: { + eq: MESSAGE_PARTICIPANT_3_ID, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const messageParticipant = response.body.data.messageParticipant; + + expect(messageParticipant).toHaveProperty('displayName'); + + expect(messageParticipant).toHaveProperty('id'); + expect(messageParticipant).toHaveProperty('handle'); + expect(messageParticipant).toHaveProperty('role'); + expect(messageParticipant).toHaveProperty('messageId'); + expect(messageParticipant).toHaveProperty('workspaceMemberId'); + expect(messageParticipant).toHaveProperty('createdAt'); + expect(messageParticipant).toHaveProperty('deletedAt'); + }); + + it('3. should update many messageParticipants', async () => { + const graphqlOperation = updateManyOperationFactory({ + objectMetadataSingularName: 'messageParticipant', + objectMetadataPluralName: 'messageParticipants', + gqlFields: MESSAGE_PARTICIPANT_GQL_FIELDS, + data: { + displayName: 'New DisplayName', + }, + filter: { + id: { + in: [MESSAGE_PARTICIPANT_1_ID, MESSAGE_PARTICIPANT_2_ID], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const updatedmessageParticipants = + response.body.data.updateMessageParticipants; + + expect(updatedmessageParticipants).toHaveLength(2); + + updatedmessageParticipants.forEach((messageParticipant) => { + expect(messageParticipant.displayName).toEqual('New DisplayName'); + }); + }); + + it('3b. should update one messageParticipant', async () => { + const graphqlOperation = updateOneOperationFactory({ + objectMetadataSingularName: 'messageParticipant', + gqlFields: MESSAGE_PARTICIPANT_GQL_FIELDS, + data: { + displayName: 'Updated DisplayName', + }, + recordId: MESSAGE_PARTICIPANT_3_ID, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const updatedmessageParticipant = + response.body.data.updateMessageParticipant; + + expect(updatedmessageParticipant.displayName).toEqual( + 'Updated DisplayName', + ); + }); + + it('4. should find many messageParticipants with updated displayName', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'messageParticipant', + objectMetadataPluralName: 'messageParticipants', + gqlFields: MESSAGE_PARTICIPANT_GQL_FIELDS, + filter: { + displayName: { + eq: 'New DisplayName', + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.messageParticipants.edges).toHaveLength(2); + }); + + it('4b. should find one messageParticipant with updated displayName', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'messageParticipant', + gqlFields: MESSAGE_PARTICIPANT_GQL_FIELDS, + filter: { + displayName: { + eq: 'Updated DisplayName', + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.messageParticipant.displayName).toEqual( + 'Updated DisplayName', + ); + }); + + it('5. should delete many messageParticipants', async () => { + const graphqlOperation = deleteManyOperationFactory({ + objectMetadataSingularName: 'messageParticipant', + objectMetadataPluralName: 'messageParticipants', + gqlFields: MESSAGE_PARTICIPANT_GQL_FIELDS, + filter: { + id: { + in: [MESSAGE_PARTICIPANT_1_ID, MESSAGE_PARTICIPANT_2_ID], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const deleteMessageParticipants = + response.body.data.deleteMessageParticipants; + + expect(deleteMessageParticipants).toHaveLength(2); + + deleteMessageParticipants.forEach((messageParticipant) => { + expect(messageParticipant.deletedAt).toBeTruthy(); + }); + }); + + it('5b. should delete one messageParticipant', async () => { + const graphqlOperation = deleteOneOperationFactory({ + objectMetadataSingularName: 'messageParticipant', + gqlFields: MESSAGE_PARTICIPANT_GQL_FIELDS, + recordId: MESSAGE_PARTICIPANT_3_ID, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.deleteMessageParticipant.deletedAt).toBeTruthy(); + }); + + it('6. should not find many messageParticipants anymore', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'messageParticipant', + objectMetadataPluralName: 'messageParticipants', + gqlFields: MESSAGE_PARTICIPANT_GQL_FIELDS, + filter: { + id: { + in: [MESSAGE_PARTICIPANT_1_ID, MESSAGE_PARTICIPANT_2_ID], + }, + }, + }); + + const findMessageParticipantsResponse = + await makeGraphqlAPIRequest(graphqlOperation); + + expect( + findMessageParticipantsResponse.body.data.messageParticipants.edges, + ).toHaveLength(0); + }); + + it('6b. should not find one messageParticipant anymore', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'messageParticipant', + gqlFields: MESSAGE_PARTICIPANT_GQL_FIELDS, + filter: { + id: { + eq: MESSAGE_PARTICIPANT_3_ID, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.messageParticipant).toBeNull(); + }); + + it('7. should find many deleted messageParticipants with deletedAt filter', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'messageParticipant', + objectMetadataPluralName: 'messageParticipants', + gqlFields: MESSAGE_PARTICIPANT_GQL_FIELDS, + filter: { + id: { + in: [MESSAGE_PARTICIPANT_1_ID, MESSAGE_PARTICIPANT_2_ID], + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.messageParticipants.edges).toHaveLength(2); + }); + + it('7b. should find one deleted messageParticipant with deletedAt filter', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'messageParticipant', + gqlFields: MESSAGE_PARTICIPANT_GQL_FIELDS, + filter: { + id: { + eq: MESSAGE_PARTICIPANT_3_ID, + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.messageParticipant.id).toEqual( + MESSAGE_PARTICIPANT_3_ID, + ); + }); + + it('8. should destroy many messageParticipants', async () => { + const graphqlOperation = destroyManyOperationFactory({ + objectMetadataSingularName: 'messageParticipant', + objectMetadataPluralName: 'messageParticipants', + gqlFields: MESSAGE_PARTICIPANT_GQL_FIELDS, + filter: { + id: { + in: [MESSAGE_PARTICIPANT_1_ID, MESSAGE_PARTICIPANT_2_ID], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.destroyMessageParticipants).toHaveLength(2); + }); + + it('8b. should destroy one messageParticipant', async () => { + const graphqlOperation = destroyOneOperationFactory({ + objectMetadataSingularName: 'messageParticipant', + gqlFields: MESSAGE_PARTICIPANT_GQL_FIELDS, + recordId: MESSAGE_PARTICIPANT_3_ID, + }); + + const destroyMessageParticipantResponse = + await makeGraphqlAPIRequest(graphqlOperation); + + expect( + destroyMessageParticipantResponse.body.data.destroyMessageParticipant, + ).toBeTruthy(); + }); + + it('9. should not find many messageParticipants anymore', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'messageParticipant', + objectMetadataPluralName: 'messageParticipants', + gqlFields: MESSAGE_PARTICIPANT_GQL_FIELDS, + filter: { + id: { + in: [MESSAGE_PARTICIPANT_1_ID, MESSAGE_PARTICIPANT_2_ID], + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.messageParticipants.edges).toHaveLength(0); + }); + + it('9b. should not find one messageParticipant anymore', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'messageParticipant', + gqlFields: MESSAGE_PARTICIPANT_GQL_FIELDS, + filter: { + id: { + eq: MESSAGE_PARTICIPANT_3_ID, + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.messageParticipant).toBeNull(); + }); +}); diff --git a/packages/twenty-server/test/integration/graphql/suites/all-message-threads-resolvers.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/all-message-threads-resolvers.integration-spec.ts new file mode 100644 index 000000000000..a2d905cd9078 --- /dev/null +++ b/packages/twenty-server/test/integration/graphql/suites/all-message-threads-resolvers.integration-spec.ts @@ -0,0 +1,397 @@ +import { createManyOperationFactory } from 'test/integration/graphql/utils/create-many-operation-factory.util'; +import { createOneOperationFactory } from 'test/integration/graphql/utils/create-one-operation-factory.util'; +import { deleteManyOperationFactory } from 'test/integration/graphql/utils/delete-many-operation-factory.util'; +import { deleteOneOperationFactory } from 'test/integration/graphql/utils/delete-one-operation-factory.util'; +import { destroyManyOperationFactory } from 'test/integration/graphql/utils/destroy-many-operation-factory.util'; +import { destroyOneOperationFactory } from 'test/integration/graphql/utils/destroy-one-operation-factory.util'; +import { findManyOperationFactory } from 'test/integration/graphql/utils/find-many-operation-factory.util'; +import { findOneOperationFactory } from 'test/integration/graphql/utils/find-one-operation-factory.util'; +import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.util'; +import { updateManyOperationFactory } from 'test/integration/graphql/utils/update-many-operation-factory.util'; +import { updateOneOperationFactory } from 'test/integration/graphql/utils/update-one-operation-factory.util'; + +const MESSAGE_THREAD_1_ID = '777a8457-eb2d-40ac-a707-551b615b6987'; +const MESSAGE_THREAD_2_ID = '777a8457-eb2d-40ac-a707-551b615b6988'; +const MESSAGE_THREAD_3_ID = '777a8457-eb2d-40ac-a707-551b615b6989'; +const UPDATED_AT_1 = new Date('10/10/2024'); +const UPDATED_AT_2 = new Date('10/20/2024'); + +const MESSAGE_THREAD_GQL_FIELDS = ` + id + updatedAt + createdAt + deletedAt + messages{ + edges{ + node{ + id + } + } + } +`; + +describe('messageThreads resolvers (integration)', () => { + it('1. should create and return messageThreads', async () => { + const graphqlOperation = createManyOperationFactory({ + objectMetadataSingularName: 'messageThread', + objectMetadataPluralName: 'messageThreads', + gqlFields: MESSAGE_THREAD_GQL_FIELDS, + data: [ + { + id: MESSAGE_THREAD_1_ID, + }, + { + id: MESSAGE_THREAD_2_ID, + }, + ], + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.createMessageThreads).toHaveLength(2); + + response.body.data.createMessageThreads.forEach((messageThread) => { + expect(messageThread).toHaveProperty('id'); + expect(messageThread).toHaveProperty('updatedAt'); + expect(messageThread).toHaveProperty('createdAt'); + expect(messageThread).toHaveProperty('deletedAt'); + expect(messageThread).toHaveProperty('messages'); + }); + }); + + it('1b. should create and return one messageThread', async () => { + const graphqlOperation = createOneOperationFactory({ + objectMetadataSingularName: 'messageThread', + gqlFields: MESSAGE_THREAD_GQL_FIELDS, + data: { + id: MESSAGE_THREAD_3_ID, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const createdMessageThread = response.body.data.createMessageThread; + + expect(createdMessageThread).toHaveProperty('id'); + expect(createdMessageThread).toHaveProperty('updatedAt'); + expect(createdMessageThread).toHaveProperty('createdAt'); + expect(createdMessageThread).toHaveProperty('deletedAt'); + expect(createdMessageThread).toHaveProperty('messages'); + }); + + it('2. should find many messageThreads', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'messageThread', + objectMetadataPluralName: 'messageThreads', + gqlFields: MESSAGE_THREAD_GQL_FIELDS, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const data = response.body.data.messageThreads; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const messageThread = edges[0].node; + + expect(messageThread).toHaveProperty('id'); + expect(messageThread).toHaveProperty('updatedAt'); + expect(messageThread).toHaveProperty('createdAt'); + expect(messageThread).toHaveProperty('deletedAt'); + expect(messageThread).toHaveProperty('messages'); + } + }); + + it('2b. should find one messageThread', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'messageThread', + gqlFields: MESSAGE_THREAD_GQL_FIELDS, + filter: { + id: { + eq: MESSAGE_THREAD_3_ID, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const messageThread = response.body.data.messageThread; + + expect(messageThread).toHaveProperty('id'); + expect(messageThread).toHaveProperty('updatedAt'); + expect(messageThread).toHaveProperty('createdAt'); + expect(messageThread).toHaveProperty('deletedAt'); + expect(messageThread).toHaveProperty('messages'); + }); + + it('3. should update many messageThreads', async () => { + const graphqlOperation = updateManyOperationFactory({ + objectMetadataSingularName: 'messageThread', + objectMetadataPluralName: 'messageThreads', + gqlFields: MESSAGE_THREAD_GQL_FIELDS, + data: { + updatedAt: UPDATED_AT_1, + }, + filter: { + id: { + in: [MESSAGE_THREAD_1_ID, MESSAGE_THREAD_2_ID], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const updatedMessageThreads = response.body.data.updateMessageThreads; + + expect(updatedMessageThreads).toHaveLength(2); + + updatedMessageThreads.forEach((messageThread) => { + expect(messageThread.updatedAt).toEqual(UPDATED_AT_1.toISOString()); + }); + }); + + it('3b. should update one messageThread', async () => { + const graphqlOperation = updateOneOperationFactory({ + objectMetadataSingularName: 'messageThread', + gqlFields: MESSAGE_THREAD_GQL_FIELDS, + data: { + updatedAt: UPDATED_AT_2, + }, + recordId: MESSAGE_THREAD_3_ID, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const updatedMessageThread = response.body.data.updateMessageThread; + + expect(updatedMessageThread.updatedAt).toEqual(UPDATED_AT_2.toISOString()); + }); + + it('4. should find many messageThreads with updated updatedAt', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'messageThread', + objectMetadataPluralName: 'messageThreads', + gqlFields: MESSAGE_THREAD_GQL_FIELDS, + filter: { + updatedAt: { + eq: UPDATED_AT_1, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.messageThreads.edges).toHaveLength(2); + }); + + it('4b. should find one messageThread with updated updatedAt', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'messageThread', + gqlFields: MESSAGE_THREAD_GQL_FIELDS, + filter: { + updatedAt: { + eq: UPDATED_AT_2, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.messageThread.updatedAt).toEqual( + UPDATED_AT_2.toISOString(), + ); + }); + + it('5. should delete many messageThreads', async () => { + const graphqlOperation = deleteManyOperationFactory({ + objectMetadataSingularName: 'messageThread', + objectMetadataPluralName: 'messageThreads', + gqlFields: MESSAGE_THREAD_GQL_FIELDS, + filter: { + id: { + in: [MESSAGE_THREAD_1_ID, MESSAGE_THREAD_2_ID], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const deleteMessageThreads = response.body.data.deleteMessageThreads; + + expect(deleteMessageThreads).toHaveLength(2); + + deleteMessageThreads.forEach((messageThread) => { + expect(messageThread.deletedAt).toBeTruthy(); + }); + }); + + it('5b. should delete one messageThread', async () => { + const graphqlOperation = deleteOneOperationFactory({ + objectMetadataSingularName: 'messageThread', + gqlFields: MESSAGE_THREAD_GQL_FIELDS, + recordId: MESSAGE_THREAD_3_ID, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.deleteMessageThread.deletedAt).toBeTruthy(); + }); + + it('6. should not find many messageThreads anymore', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'messageThread', + objectMetadataPluralName: 'messageThreads', + gqlFields: MESSAGE_THREAD_GQL_FIELDS, + filter: { + id: { + in: [MESSAGE_THREAD_1_ID, MESSAGE_THREAD_2_ID], + }, + }, + }); + + const findMessageThreadsResponse = + await makeGraphqlAPIRequest(graphqlOperation); + + expect( + findMessageThreadsResponse.body.data.messageThreads.edges, + ).toHaveLength(0); + }); + + it('6b. should not find one messageThread anymore', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'messageThread', + gqlFields: MESSAGE_THREAD_GQL_FIELDS, + filter: { + id: { + eq: MESSAGE_THREAD_3_ID, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.messageThread).toBeNull(); + }); + + it('7. should find many deleted messageThreads with deletedAt filter', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'messageThread', + objectMetadataPluralName: 'messageThreads', + gqlFields: MESSAGE_THREAD_GQL_FIELDS, + filter: { + id: { + in: [MESSAGE_THREAD_1_ID, MESSAGE_THREAD_2_ID], + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.messageThreads.edges).toHaveLength(2); + }); + + it('7b. should find one deleted messageThread with deletedAt filter', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'messageThread', + gqlFields: MESSAGE_THREAD_GQL_FIELDS, + filter: { + id: { + eq: MESSAGE_THREAD_3_ID, + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.messageThread.id).toEqual(MESSAGE_THREAD_3_ID); + }); + + it('8. should destroy many messageThreads', async () => { + const graphqlOperation = destroyManyOperationFactory({ + objectMetadataSingularName: 'messageThread', + objectMetadataPluralName: 'messageThreads', + gqlFields: MESSAGE_THREAD_GQL_FIELDS, + filter: { + id: { + in: [MESSAGE_THREAD_1_ID, MESSAGE_THREAD_2_ID], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.destroyMessageThreads).toHaveLength(2); + }); + + it('8b. should destroy one messageThread', async () => { + const graphqlOperation = destroyOneOperationFactory({ + objectMetadataSingularName: 'messageThread', + gqlFields: MESSAGE_THREAD_GQL_FIELDS, + recordId: MESSAGE_THREAD_3_ID, + }); + + const destroyMessageThreadsResponse = + await makeGraphqlAPIRequest(graphqlOperation); + + expect( + destroyMessageThreadsResponse.body.data.destroyMessageThread, + ).toBeTruthy(); + }); + + it('9. should not find many messageThreads anymore', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'messageThread', + objectMetadataPluralName: 'messageThreads', + gqlFields: MESSAGE_THREAD_GQL_FIELDS, + filter: { + id: { + in: [MESSAGE_THREAD_1_ID, MESSAGE_THREAD_2_ID], + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.messageThreads.edges).toHaveLength(0); + }); + + it('9b. should not find one messageThread anymore', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'messageThread', + gqlFields: MESSAGE_THREAD_GQL_FIELDS, + filter: { + id: { + eq: MESSAGE_THREAD_3_ID, + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.messageThread).toBeNull(); + }); +}); diff --git a/packages/twenty-server/test/integration/graphql/suites/all-note-targets-resolvers.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/all-note-targets-resolvers.integration-spec.ts new file mode 100644 index 000000000000..9b4d9fa0aa9e --- /dev/null +++ b/packages/twenty-server/test/integration/graphql/suites/all-note-targets-resolvers.integration-spec.ts @@ -0,0 +1,444 @@ +import { createManyOperationFactory } from 'test/integration/graphql/utils/create-many-operation-factory.util'; +import { createOneOperationFactory } from 'test/integration/graphql/utils/create-one-operation-factory.util'; +import { deleteManyOperationFactory } from 'test/integration/graphql/utils/delete-many-operation-factory.util'; +import { deleteOneOperationFactory } from 'test/integration/graphql/utils/delete-one-operation-factory.util'; +import { destroyManyOperationFactory } from 'test/integration/graphql/utils/destroy-many-operation-factory.util'; +import { destroyOneOperationFactory } from 'test/integration/graphql/utils/destroy-one-operation-factory.util'; +import { findManyOperationFactory } from 'test/integration/graphql/utils/find-many-operation-factory.util'; +import { findOneOperationFactory } from 'test/integration/graphql/utils/find-one-operation-factory.util'; +import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.util'; +import { updateManyOperationFactory } from 'test/integration/graphql/utils/update-many-operation-factory.util'; +import { updateOneOperationFactory } from 'test/integration/graphql/utils/update-one-operation-factory.util'; +import { generateRecordName } from 'test/integration/utils/generate-record-name'; + +const NOTE_TARGET_1_ID = '777a8457-eb2d-40ac-a707-551b615b6987'; +const NOTE_TARGET_2_ID = '777a8457-eb2d-40ac-a707-551b615b6988'; +const NOTE_TARGET_3_ID = '777a8457-eb2d-40ac-a707-551b615b6989'; +const PERSON_1_ID = '777a8457-eb2d-40ac-a707-441b615b6989'; +const PERSON_2_ID = '777a8457-eb2d-40ac-a707-331b615b6989'; +const NOTE_TARGET_GQL_FIELDS = ` + id + createdAt + deletedAt + noteId + personId + companyId + opportunityId + person{ + id + } +`; + +describe('noteTargets resolvers (integration)', () => { + beforeAll(async () => { + const personName1 = generateRecordName(PERSON_1_ID); + const personName2 = generateRecordName(PERSON_2_ID); + const graphqlOperation = createManyOperationFactory({ + objectMetadataSingularName: 'person', + objectMetadataPluralName: 'people', + gqlFields: `id`, + data: [ + { + id: PERSON_1_ID, + name: { + firstName: personName1, + lastName: personName1, + }, + }, + { + id: PERSON_2_ID, + name: { + firstName: personName2, + lastName: personName2, + }, + }, + ], + }); + + await makeGraphqlAPIRequest(graphqlOperation); + }); + + afterAll(async () => { + const graphqlOperation = destroyManyOperationFactory({ + objectMetadataSingularName: 'person', + objectMetadataPluralName: 'people', + gqlFields: `id`, + filter: { + id: { + in: [PERSON_1_ID, PERSON_2_ID], + }, + }, + }); + + await makeGraphqlAPIRequest(graphqlOperation); + }); + it('1. should create and return noteTargets', async () => { + const graphqlOperation = createManyOperationFactory({ + objectMetadataSingularName: 'noteTarget', + objectMetadataPluralName: 'noteTargets', + gqlFields: NOTE_TARGET_GQL_FIELDS, + data: [ + { + id: NOTE_TARGET_1_ID, + }, + { + id: NOTE_TARGET_2_ID, + }, + ], + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.createNoteTargets).toHaveLength(2); + + response.body.data.createNoteTargets.forEach((noteTarget) => { + expect(noteTarget).toHaveProperty('id'); + expect(noteTarget).toHaveProperty('createdAt'); + expect(noteTarget).toHaveProperty('deletedAt'); + expect(noteTarget).toHaveProperty('noteId'); + expect(noteTarget).toHaveProperty('personId'); + expect(noteTarget).toHaveProperty('companyId'); + expect(noteTarget).toHaveProperty('opportunityId'); + expect(noteTarget).toHaveProperty('person'); + }); + }); + + it('1b. should create and return one noteTarget', async () => { + const graphqlOperation = createOneOperationFactory({ + objectMetadataSingularName: 'noteTarget', + gqlFields: NOTE_TARGET_GQL_FIELDS, + data: { + id: NOTE_TARGET_3_ID, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const createdNoteTarget = response.body.data.createNoteTarget; + + expect(createdNoteTarget).toHaveProperty('id'); + expect(createdNoteTarget).toHaveProperty('createdAt'); + expect(createdNoteTarget).toHaveProperty('deletedAt'); + expect(createdNoteTarget).toHaveProperty('noteId'); + expect(createdNoteTarget).toHaveProperty('personId'); + expect(createdNoteTarget).toHaveProperty('companyId'); + expect(createdNoteTarget).toHaveProperty('opportunityId'); + expect(createdNoteTarget).toHaveProperty('person'); + }); + + it('2. should find many noteTargets', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'noteTarget', + objectMetadataPluralName: 'noteTargets', + gqlFields: NOTE_TARGET_GQL_FIELDS, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const data = response.body.data.noteTargets; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const noteTarget = edges[0].node; + + expect(noteTarget).toHaveProperty('id'); + expect(noteTarget).toHaveProperty('createdAt'); + expect(noteTarget).toHaveProperty('deletedAt'); + expect(noteTarget).toHaveProperty('noteId'); + expect(noteTarget).toHaveProperty('personId'); + expect(noteTarget).toHaveProperty('companyId'); + expect(noteTarget).toHaveProperty('opportunityId'); + expect(noteTarget).toHaveProperty('person'); + } + }); + + it('2b. should find one noteTarget', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'noteTarget', + gqlFields: NOTE_TARGET_GQL_FIELDS, + filter: { + id: { + eq: NOTE_TARGET_3_ID, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const noteTarget = response.body.data.noteTarget; + + expect(noteTarget).toHaveProperty('id'); + expect(noteTarget).toHaveProperty('createdAt'); + expect(noteTarget).toHaveProperty('deletedAt'); + expect(noteTarget).toHaveProperty('noteId'); + expect(noteTarget).toHaveProperty('personId'); + expect(noteTarget).toHaveProperty('companyId'); + expect(noteTarget).toHaveProperty('opportunityId'); + expect(noteTarget).toHaveProperty('person'); + }); + + it('3. should update many noteTargets', async () => { + const graphqlOperation = updateManyOperationFactory({ + objectMetadataSingularName: 'noteTarget', + objectMetadataPluralName: 'noteTargets', + gqlFields: NOTE_TARGET_GQL_FIELDS, + data: { + personId: PERSON_1_ID, + }, + filter: { + id: { + in: [NOTE_TARGET_1_ID, NOTE_TARGET_2_ID], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const updatedNoteTargets = response.body.data.updateNoteTargets; + + expect(updatedNoteTargets).toHaveLength(2); + + updatedNoteTargets.forEach((noteTarget) => { + expect(noteTarget.person.id).toEqual(PERSON_1_ID); + }); + }); + + it('3b. should update one noteTarget', async () => { + const graphqlOperation = updateOneOperationFactory({ + objectMetadataSingularName: 'noteTarget', + gqlFields: NOTE_TARGET_GQL_FIELDS, + data: { + personId: PERSON_2_ID, + }, + recordId: NOTE_TARGET_3_ID, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const updatedNoteTarget = response.body.data.updateNoteTarget; + + expect(updatedNoteTarget.person.id).toEqual(PERSON_2_ID); + }); + + it('4. should find many noteTargets with updated personId', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'noteTarget', + objectMetadataPluralName: 'noteTargets', + gqlFields: NOTE_TARGET_GQL_FIELDS, + filter: { + personId: { + eq: PERSON_1_ID, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.noteTargets.edges).toHaveLength(2); + }); + + it('4b. should find one noteTarget with updated personId', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'noteTarget', + gqlFields: NOTE_TARGET_GQL_FIELDS, + filter: { + personId: { + eq: PERSON_2_ID, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.noteTarget.person.id).toEqual(PERSON_2_ID); + }); + + it('5. should delete many noteTargets', async () => { + const graphqlOperation = deleteManyOperationFactory({ + objectMetadataSingularName: 'noteTarget', + objectMetadataPluralName: 'noteTargets', + gqlFields: NOTE_TARGET_GQL_FIELDS, + filter: { + id: { + in: [NOTE_TARGET_1_ID, NOTE_TARGET_2_ID], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const deleteNoteTargets = response.body.data.deleteNoteTargets; + + expect(deleteNoteTargets).toHaveLength(2); + + deleteNoteTargets.forEach((noteTarget) => { + expect(noteTarget.deletedAt).toBeTruthy(); + }); + }); + + it('5b. should delete one noteTarget', async () => { + const graphqlOperation = deleteOneOperationFactory({ + objectMetadataSingularName: 'noteTarget', + gqlFields: NOTE_TARGET_GQL_FIELDS, + recordId: NOTE_TARGET_3_ID, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.deleteNoteTarget.deletedAt).toBeTruthy(); + }); + + it('6. should not find many noteTargets anymore', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'noteTarget', + objectMetadataPluralName: 'noteTargets', + gqlFields: NOTE_TARGET_GQL_FIELDS, + filter: { + id: { + in: [NOTE_TARGET_1_ID, NOTE_TARGET_2_ID], + }, + }, + }); + + const findNoteTargetsResponse = + await makeGraphqlAPIRequest(graphqlOperation); + + expect(findNoteTargetsResponse.body.data.noteTargets.edges).toHaveLength(0); + }); + + it('6b. should not find one noteTarget anymore', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'noteTarget', + gqlFields: NOTE_TARGET_GQL_FIELDS, + filter: { + id: { + eq: NOTE_TARGET_3_ID, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.noteTarget).toBeNull(); + }); + + it('7. should find many deleted noteTargets with deletedAt filter', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'noteTarget', + objectMetadataPluralName: 'noteTargets', + gqlFields: NOTE_TARGET_GQL_FIELDS, + filter: { + id: { + in: [NOTE_TARGET_1_ID, NOTE_TARGET_2_ID], + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.noteTargets.edges).toHaveLength(2); + }); + + it('7b. should find one deleted noteTarget with deletedAt filter', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'noteTarget', + gqlFields: NOTE_TARGET_GQL_FIELDS, + filter: { + id: { + eq: NOTE_TARGET_3_ID, + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.noteTarget.id).toEqual(NOTE_TARGET_3_ID); + }); + + it('8. should destroy many noteTargets', async () => { + const graphqlOperation = destroyManyOperationFactory({ + objectMetadataSingularName: 'noteTarget', + objectMetadataPluralName: 'noteTargets', + gqlFields: NOTE_TARGET_GQL_FIELDS, + filter: { + id: { + in: [NOTE_TARGET_1_ID, NOTE_TARGET_2_ID], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.destroyNoteTargets).toHaveLength(2); + }); + + it('8b. should destroy one noteTarget', async () => { + const graphqlOperation = destroyOneOperationFactory({ + objectMetadataSingularName: 'noteTarget', + gqlFields: NOTE_TARGET_GQL_FIELDS, + recordId: NOTE_TARGET_3_ID, + }); + + const destroyNoteTargetsResponse = + await makeGraphqlAPIRequest(graphqlOperation); + + expect(destroyNoteTargetsResponse.body.data.destroyNoteTarget).toBeTruthy(); + }); + + it('9. should not find many noteTargets anymore', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'noteTarget', + objectMetadataPluralName: 'noteTargets', + gqlFields: NOTE_TARGET_GQL_FIELDS, + filter: { + id: { + in: [NOTE_TARGET_1_ID, NOTE_TARGET_2_ID], + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.noteTargets.edges).toHaveLength(0); + }); + + it('9b. should not find one noteTarget anymore', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'noteTarget', + gqlFields: NOTE_TARGET_GQL_FIELDS, + filter: { + id: { + eq: NOTE_TARGET_3_ID, + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.noteTarget).toBeNull(); + }); +}); diff --git a/packages/twenty-server/test/integration/graphql/suites/all-notes-resolvers.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/all-notes-resolvers.integration-spec.ts new file mode 100644 index 000000000000..29fbe7602d01 --- /dev/null +++ b/packages/twenty-server/test/integration/graphql/suites/all-notes-resolvers.integration-spec.ts @@ -0,0 +1,403 @@ +import { createManyOperationFactory } from 'test/integration/graphql/utils/create-many-operation-factory.util'; +import { createOneOperationFactory } from 'test/integration/graphql/utils/create-one-operation-factory.util'; +import { deleteManyOperationFactory } from 'test/integration/graphql/utils/delete-many-operation-factory.util'; +import { deleteOneOperationFactory } from 'test/integration/graphql/utils/delete-one-operation-factory.util'; +import { destroyManyOperationFactory } from 'test/integration/graphql/utils/destroy-many-operation-factory.util'; +import { destroyOneOperationFactory } from 'test/integration/graphql/utils/destroy-one-operation-factory.util'; +import { findManyOperationFactory } from 'test/integration/graphql/utils/find-many-operation-factory.util'; +import { findOneOperationFactory } from 'test/integration/graphql/utils/find-one-operation-factory.util'; +import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.util'; +import { updateManyOperationFactory } from 'test/integration/graphql/utils/update-many-operation-factory.util'; +import { updateOneOperationFactory } from 'test/integration/graphql/utils/update-one-operation-factory.util'; +import { generateRecordName } from 'test/integration/utils/generate-record-name'; + +const NOTE_1_ID = '777a8457-eb2d-40ac-a707-551b615b6987'; +const NOTE_2_ID = '777a8457-eb2d-40ac-a707-551b615b6988'; +const NOTE_3_ID = '777a8457-eb2d-40ac-a707-551b615b6989'; + +const NOTE_GQL_FIELDS = ` + id + title + createdAt + updatedAt + deletedAt + body + position +`; + +describe('notes resolvers (integration)', () => { + it('1. should create and return notes', async () => { + const noteTitle1 = generateRecordName(NOTE_1_ID); + const noteTitle2 = generateRecordName(NOTE_2_ID); + const graphqlOperation = createManyOperationFactory({ + objectMetadataSingularName: 'note', + objectMetadataPluralName: 'notes', + gqlFields: NOTE_GQL_FIELDS, + data: [ + { + id: NOTE_1_ID, + title: noteTitle1, + }, + { + id: NOTE_2_ID, + title: noteTitle2, + }, + ], + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.createNotes).toHaveLength(2); + + response.body.data.createNotes.forEach((note) => { + expect(note).toHaveProperty('title'); + expect([noteTitle1, noteTitle2]).toContain(note.title); + + expect(note).toHaveProperty('id'); + expect(note).toHaveProperty('createdAt'); + expect(note).toHaveProperty('updatedAt'); + expect(note).toHaveProperty('deletedAt'); + expect(note).toHaveProperty('body'); + expect(note).toHaveProperty('position'); + }); + }); + + it('1b. should create and return one note', async () => { + const noteTitle3 = generateRecordName(NOTE_3_ID); + + const graphqlOperation = createOneOperationFactory({ + objectMetadataSingularName: 'note', + gqlFields: NOTE_GQL_FIELDS, + data: { + id: NOTE_3_ID, + title: noteTitle3, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const createdNote = response.body.data.createNote; + + expect(createdNote).toHaveProperty('title'); + expect(createdNote.title).toEqual(noteTitle3); + + expect(createdNote).toHaveProperty('id'); + expect(createdNote).toHaveProperty('createdAt'); + expect(createdNote).toHaveProperty('updatedAt'); + expect(createdNote).toHaveProperty('deletedAt'); + expect(createdNote).toHaveProperty('body'); + expect(createdNote).toHaveProperty('position'); + }); + + it('2. should find many notes', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'note', + objectMetadataPluralName: 'notes', + gqlFields: NOTE_GQL_FIELDS, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const data = response.body.data.notes; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const note = edges[0].node; + + expect(note).toHaveProperty('id'); + expect(note).toHaveProperty('createdAt'); + expect(note).toHaveProperty('updatedAt'); + expect(note).toHaveProperty('deletedAt'); + expect(note).toHaveProperty('body'); + expect(note).toHaveProperty('position'); + } + }); + + it('2b. should find one note', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'note', + gqlFields: NOTE_GQL_FIELDS, + filter: { + id: { + eq: NOTE_3_ID, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const note = response.body.data.note; + + expect(note).toHaveProperty('title'); + + expect(note).toHaveProperty('id'); + expect(note).toHaveProperty('createdAt'); + expect(note).toHaveProperty('updatedAt'); + expect(note).toHaveProperty('deletedAt'); + expect(note).toHaveProperty('body'); + expect(note).toHaveProperty('position'); + }); + + it('3. should update many notes', async () => { + const graphqlOperation = updateManyOperationFactory({ + objectMetadataSingularName: 'note', + objectMetadataPluralName: 'notes', + gqlFields: NOTE_GQL_FIELDS, + data: { + title: 'Updated Title', + }, + filter: { + id: { + in: [NOTE_1_ID, NOTE_2_ID], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const updatedNotes = response.body.data.updateNotes; + + expect(updatedNotes).toHaveLength(2); + + updatedNotes.forEach((note) => { + expect(note.title).toEqual('Updated Title'); + }); + }); + + it('3b. should update one note', async () => { + const graphqlOperation = updateOneOperationFactory({ + objectMetadataSingularName: 'note', + gqlFields: NOTE_GQL_FIELDS, + data: { + title: 'New Title', + }, + recordId: NOTE_3_ID, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const updatedNote = response.body.data.updateNote; + + expect(updatedNote.title).toEqual('New Title'); + }); + + it('4. should find many notes with updated title', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'note', + objectMetadataPluralName: 'notes', + gqlFields: NOTE_GQL_FIELDS, + filter: { + title: { + eq: 'Updated Title', + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.notes.edges).toHaveLength(2); + }); + + it('4b. should find one note with updated title', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'note', + gqlFields: NOTE_GQL_FIELDS, + filter: { + title: { + eq: 'New Title', + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.note.title).toEqual('New Title'); + }); + + it('5. should delete many notes', async () => { + const graphqlOperation = deleteManyOperationFactory({ + objectMetadataSingularName: 'note', + objectMetadataPluralName: 'notes', + gqlFields: NOTE_GQL_FIELDS, + filter: { + id: { + in: [NOTE_1_ID, NOTE_2_ID], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const deleteNotes = response.body.data.deleteNotes; + + expect(deleteNotes).toHaveLength(2); + + deleteNotes.forEach((note) => { + expect(note.deletedAt).toBeTruthy(); + }); + }); + + it('5b. should delete one note', async () => { + const graphqlOperation = deleteOneOperationFactory({ + objectMetadataSingularName: 'note', + gqlFields: NOTE_GQL_FIELDS, + recordId: NOTE_3_ID, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.deleteNote.deletedAt).toBeTruthy(); + }); + + it('6. should not find many notes anymore', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'note', + objectMetadataPluralName: 'notes', + gqlFields: NOTE_GQL_FIELDS, + filter: { + id: { + in: [NOTE_1_ID, NOTE_2_ID], + }, + }, + }); + + const findNotesResponse = await makeGraphqlAPIRequest(graphqlOperation); + + expect(findNotesResponse.body.data.notes.edges).toHaveLength(0); + }); + + it('6b. should not find one note anymore', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'note', + gqlFields: NOTE_GQL_FIELDS, + filter: { + id: { + eq: NOTE_3_ID, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.note).toBeNull(); + }); + + it('7. should find many deleted notes with deletedAt filter', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'note', + objectMetadataPluralName: 'notes', + gqlFields: NOTE_GQL_FIELDS, + filter: { + id: { + in: [NOTE_1_ID, NOTE_2_ID], + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.notes.edges).toHaveLength(2); + }); + + it('7b. should find one deleted note with deletedAt filter', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'note', + gqlFields: NOTE_GQL_FIELDS, + filter: { + id: { + eq: NOTE_3_ID, + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.note.id).toEqual(NOTE_3_ID); + }); + + it('8. should destroy many notes', async () => { + const graphqlOperation = destroyManyOperationFactory({ + objectMetadataSingularName: 'note', + objectMetadataPluralName: 'notes', + gqlFields: NOTE_GQL_FIELDS, + filter: { + id: { + in: [NOTE_1_ID, NOTE_2_ID], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.destroyNotes).toHaveLength(2); + }); + + it('8b. should destroy one note', async () => { + const graphqlOperation = destroyOneOperationFactory({ + objectMetadataSingularName: 'note', + gqlFields: NOTE_GQL_FIELDS, + recordId: NOTE_3_ID, + }); + + const destroyNotesResponse = await makeGraphqlAPIRequest(graphqlOperation); + + expect(destroyNotesResponse.body.data.destroyNote).toBeTruthy(); + }); + + it('9. should not find many notes anymore', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'note', + objectMetadataPluralName: 'notes', + gqlFields: NOTE_GQL_FIELDS, + filter: { + id: { + in: [NOTE_1_ID, NOTE_2_ID], + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.notes.edges).toHaveLength(0); + }); + + it('9b. should not find one note anymore', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'note', + gqlFields: NOTE_GQL_FIELDS, + filter: { + id: { + eq: NOTE_3_ID, + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.note).toBeNull(); + }); +}); diff --git a/packages/twenty-server/test/integration/graphql/suites/all-opportunities-resolvers.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/all-opportunities-resolvers.integration-spec.ts new file mode 100644 index 000000000000..6c1a279be475 --- /dev/null +++ b/packages/twenty-server/test/integration/graphql/suites/all-opportunities-resolvers.integration-spec.ts @@ -0,0 +1,414 @@ +import { createManyOperationFactory } from 'test/integration/graphql/utils/create-many-operation-factory.util'; +import { createOneOperationFactory } from 'test/integration/graphql/utils/create-one-operation-factory.util'; +import { deleteManyOperationFactory } from 'test/integration/graphql/utils/delete-many-operation-factory.util'; +import { deleteOneOperationFactory } from 'test/integration/graphql/utils/delete-one-operation-factory.util'; +import { destroyManyOperationFactory } from 'test/integration/graphql/utils/destroy-many-operation-factory.util'; +import { destroyOneOperationFactory } from 'test/integration/graphql/utils/destroy-one-operation-factory.util'; +import { findManyOperationFactory } from 'test/integration/graphql/utils/find-many-operation-factory.util'; +import { findOneOperationFactory } from 'test/integration/graphql/utils/find-one-operation-factory.util'; +import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.util'; +import { updateManyOperationFactory } from 'test/integration/graphql/utils/update-many-operation-factory.util'; +import { updateOneOperationFactory } from 'test/integration/graphql/utils/update-one-operation-factory.util'; +import { generateRecordName } from 'test/integration/utils/generate-record-name'; + +const OPPORTUNITY_1_ID = '777a8457-eb2d-40ac-a707-551b615b6987'; +const OPPORTUNITY_2_ID = '777a8457-eb2d-40ac-a707-551b615b6988'; +const OPPORTUNITY_3_ID = '777a8457-eb2d-40ac-a707-551b615b6989'; + +const OPPORTUNITY_GQL_FIELDS = ` + id + name + createdAt + updatedAt + deletedAt + searchVector + stage + position +`; + +describe('opportunities resolvers (integration)', () => { + it('1. should create and return opportunities', async () => { + const opportunityName1 = generateRecordName(OPPORTUNITY_1_ID); + const opportunityName2 = generateRecordName(OPPORTUNITY_2_ID); + const graphqlOperation = createManyOperationFactory({ + objectMetadataSingularName: 'opportunity', + objectMetadataPluralName: 'opportunities', + gqlFields: OPPORTUNITY_GQL_FIELDS, + data: [ + { + id: OPPORTUNITY_1_ID, + name: opportunityName1, + }, + { + id: OPPORTUNITY_2_ID, + name: opportunityName2, + }, + ], + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.createOpportunities).toHaveLength(2); + + response.body.data.createOpportunities.forEach((opportunity) => { + expect(opportunity).toHaveProperty('name'); + expect([opportunityName1, opportunityName2]).toContain(opportunity.name); + + expect(opportunity).toHaveProperty('id'); + expect(opportunity).toHaveProperty('createdAt'); + expect(opportunity).toHaveProperty('updatedAt'); + expect(opportunity).toHaveProperty('deletedAt'); + expect(opportunity).toHaveProperty('searchVector'); + expect(opportunity).toHaveProperty('stage'); + expect(opportunity).toHaveProperty('position'); + }); + }); + + it('1b. should create and return one opportunity', async () => { + const opportunityName3 = generateRecordName(OPPORTUNITY_3_ID); + + const graphqlOperation = createOneOperationFactory({ + objectMetadataSingularName: 'opportunity', + gqlFields: OPPORTUNITY_GQL_FIELDS, + data: { + id: OPPORTUNITY_3_ID, + name: opportunityName3, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const createdOpportunity = response.body.data.createOpportunity; + + expect(createdOpportunity).toHaveProperty('name'); + expect(createdOpportunity.name).toEqual(opportunityName3); + + expect(createdOpportunity).toHaveProperty('id'); + expect(createdOpportunity).toHaveProperty('createdAt'); + expect(createdOpportunity).toHaveProperty('updatedAt'); + expect(createdOpportunity).toHaveProperty('deletedAt'); + expect(createdOpportunity).toHaveProperty('searchVector'); + expect(createdOpportunity).toHaveProperty('stage'); + expect(createdOpportunity).toHaveProperty('position'); + }); + + it('2. should find many opportunities', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'opportunity', + objectMetadataPluralName: 'opportunities', + gqlFields: OPPORTUNITY_GQL_FIELDS, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const data = response.body.data.opportunities; + + expect(data).toBeDefined(); + expect(Array.isArray(data.edges)).toBe(true); + + const edges = data.edges; + + if (edges.length > 0) { + const opportunity = edges[0].node; + + expect(opportunity).toHaveProperty('id'); + expect(opportunity).toHaveProperty('createdAt'); + expect(opportunity).toHaveProperty('updatedAt'); + expect(opportunity).toHaveProperty('deletedAt'); + expect(opportunity).toHaveProperty('searchVector'); + expect(opportunity).toHaveProperty('stage'); + expect(opportunity).toHaveProperty('position'); + } + }); + + it('2b. should find one opportunity', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'opportunity', + gqlFields: OPPORTUNITY_GQL_FIELDS, + filter: { + id: { + eq: OPPORTUNITY_3_ID, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const opportunity = response.body.data.opportunity; + + expect(opportunity).toHaveProperty('name'); + + expect(opportunity).toHaveProperty('id'); + expect(opportunity).toHaveProperty('createdAt'); + expect(opportunity).toHaveProperty('updatedAt'); + expect(opportunity).toHaveProperty('deletedAt'); + expect(opportunity).toHaveProperty('searchVector'); + expect(opportunity).toHaveProperty('stage'); + expect(opportunity).toHaveProperty('position'); + }); + + it('3. should update many opportunities', async () => { + const graphqlOperation = updateManyOperationFactory({ + objectMetadataSingularName: 'opportunity', + objectMetadataPluralName: 'opportunities', + gqlFields: OPPORTUNITY_GQL_FIELDS, + data: { + name: 'Updated Name', + }, + filter: { + id: { + in: [OPPORTUNITY_1_ID, OPPORTUNITY_2_ID], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const updatedOpportunities = response.body.data.updateOpportunities; + + expect(updatedOpportunities).toHaveLength(2); + + updatedOpportunities.forEach((opportunity) => { + expect(opportunity.name).toEqual('Updated Name'); + }); + }); + + it('3b. should update one opportunity', async () => { + const graphqlOperation = updateOneOperationFactory({ + objectMetadataSingularName: 'opportunity', + gqlFields: OPPORTUNITY_GQL_FIELDS, + data: { + name: 'New Name', + }, + recordId: OPPORTUNITY_3_ID, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const updatedOpportunity = response.body.data.updateOpportunity; + + expect(updatedOpportunity.name).toEqual('New Name'); + }); + + it('4. should find many opportunities with updated name', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'opportunity', + objectMetadataPluralName: 'opportunities', + gqlFields: OPPORTUNITY_GQL_FIELDS, + filter: { + name: { + eq: 'Updated Name', + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.opportunities.edges).toHaveLength(2); + }); + + it('4b. should find one opportunity with updated name', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'opportunity', + gqlFields: OPPORTUNITY_GQL_FIELDS, + filter: { + name: { + eq: 'New Name', + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.opportunity.name).toEqual('New Name'); + }); + + it('5. should delete many opportunities', async () => { + const graphqlOperation = deleteManyOperationFactory({ + objectMetadataSingularName: 'opportunity', + objectMetadataPluralName: 'opportunities', + gqlFields: OPPORTUNITY_GQL_FIELDS, + filter: { + id: { + in: [OPPORTUNITY_1_ID, OPPORTUNITY_2_ID], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + const deleteOpportunities = response.body.data.deleteOpportunities; + + expect(deleteOpportunities).toHaveLength(2); + + deleteOpportunities.forEach((opportunity) => { + expect(opportunity.deletedAt).toBeTruthy(); + }); + }); + + it('5b. should delete one opportunity', async () => { + const graphqlOperation = deleteOneOperationFactory({ + objectMetadataSingularName: 'opportunity', + gqlFields: OPPORTUNITY_GQL_FIELDS, + recordId: OPPORTUNITY_3_ID, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.deleteOpportunity.deletedAt).toBeTruthy(); + }); + + it('6. should not find many opportunities anymore', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'opportunity', + objectMetadataPluralName: 'opportunities', + gqlFields: OPPORTUNITY_GQL_FIELDS, + filter: { + id: { + in: [OPPORTUNITY_1_ID, OPPORTUNITY_2_ID], + }, + }, + }); + + const findOpportunitiesResponse = + await makeGraphqlAPIRequest(graphqlOperation); + + expect( + findOpportunitiesResponse.body.data.opportunities.edges, + ).toHaveLength(0); + }); + + it('6b. should not find one opportunity anymore', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'opportunity', + gqlFields: OPPORTUNITY_GQL_FIELDS, + filter: { + id: { + eq: OPPORTUNITY_3_ID, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.opportunity).toBeNull(); + }); + + it('7. should find many deleted opportunities with deletedAt filter', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'opportunity', + objectMetadataPluralName: 'opportunities', + gqlFields: OPPORTUNITY_GQL_FIELDS, + filter: { + id: { + in: [OPPORTUNITY_1_ID, OPPORTUNITY_2_ID], + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.opportunities.edges).toHaveLength(2); + }); + + it('7b. should find one deleted opportunity with deletedAt filter', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'opportunity', + gqlFields: OPPORTUNITY_GQL_FIELDS, + filter: { + id: { + eq: OPPORTUNITY_3_ID, + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.opportunity.id).toEqual(OPPORTUNITY_3_ID); + }); + + it('8. should destroy many opportunities', async () => { + const graphqlOperation = destroyManyOperationFactory({ + objectMetadataSingularName: 'opportunity', + objectMetadataPluralName: 'opportunities', + gqlFields: OPPORTUNITY_GQL_FIELDS, + filter: { + id: { + in: [OPPORTUNITY_1_ID, OPPORTUNITY_2_ID], + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.destroyOpportunities).toHaveLength(2); + }); + + it('8b. should destroy one opportunity', async () => { + const graphqlOperation = destroyOneOperationFactory({ + objectMetadataSingularName: 'opportunity', + gqlFields: OPPORTUNITY_GQL_FIELDS, + recordId: OPPORTUNITY_3_ID, + }); + + const destroyOpportunitiesResponse = + await makeGraphqlAPIRequest(graphqlOperation); + + expect( + destroyOpportunitiesResponse.body.data.destroyOpportunity, + ).toBeTruthy(); + }); + + it('9. should not find many opportunities anymore', async () => { + const graphqlOperation = findManyOperationFactory({ + objectMetadataSingularName: 'opportunity', + objectMetadataPluralName: 'opportunities', + gqlFields: OPPORTUNITY_GQL_FIELDS, + filter: { + id: { + in: [OPPORTUNITY_1_ID, OPPORTUNITY_2_ID], + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.opportunities.edges).toHaveLength(0); + }); + + it('9b. should not find one opportunity anymore', async () => { + const graphqlOperation = findOneOperationFactory({ + objectMetadataSingularName: 'opportunity', + gqlFields: OPPORTUNITY_GQL_FIELDS, + filter: { + id: { + eq: OPPORTUNITY_3_ID, + }, + not: { + deletedAt: { + is: 'NULL', + }, + }, + }, + }); + + const response = await makeGraphqlAPIRequest(graphqlOperation); + + expect(response.body.data.opportunity).toBeNull(); + }); +});