diff --git a/packages/twenty-server/test/integration/metadata/suites/field-metadata/morph-relation/create-one-field-metadata-morph-relation.integration-spec.ts b/packages/twenty-server/test/integration/metadata/suites/field-metadata/morph-relation/create-one-field-metadata-morph-relation.integration-spec.ts index 509221844..81f965373 100644 --- a/packages/twenty-server/test/integration/metadata/suites/field-metadata/morph-relation/create-one-field-metadata-morph-relation.integration-spec.ts +++ b/packages/twenty-server/test/integration/metadata/suites/field-metadata/morph-relation/create-one-field-metadata-morph-relation.integration-spec.ts @@ -74,24 +74,17 @@ describe('createOne FieldMetadataService morph relation fields', () => { }); type EachTestingContextArray = EachTestingContext< - | { - relationType: RelationType; - objectMetadataId: string; - firstTargetObjectMetadataId: string; - secondTargetObjectMetadataId: string; - type: FieldMetadataType; - } - | ((args: { - objectMetadataId: string; - firstTargetObjectMetadataId: string; - secondTargetObjectMetadataId: string; - }) => { - relationType: RelationType; - objectMetadataId: string; - firstTargetObjectMetadataId: string; - secondTargetObjectMetadataId: string; - type: FieldMetadataType; - }) + (args: { + objectMetadataId: string; + firstTargetObjectMetadataId: string; + secondTargetObjectMetadataId: string; + }) => { + relationType: RelationType; + objectMetadataId: string; + firstTargetObjectMetadataId: string; + secondTargetObjectMetadataId: string; + type: FieldMetadataType; + } >[]; const eachTestingContextArray: EachTestingContextArray = [ diff --git a/packages/twenty-server/test/integration/metadata/suites/field-metadata/relation/create-one-field-metadata-relation.integration-spec.ts b/packages/twenty-server/test/integration/metadata/suites/field-metadata/relation/create-one-field-metadata-relation.integration-spec.ts index 61bea3b02..91daa1b36 100644 --- a/packages/twenty-server/test/integration/metadata/suites/field-metadata/relation/create-one-field-metadata-relation.integration-spec.ts +++ b/packages/twenty-server/test/integration/metadata/suites/field-metadata/relation/create-one-field-metadata-relation.integration-spec.ts @@ -57,18 +57,12 @@ describe('createOne FieldMetadataService relation fields', () => { }); type EachTestingContextArray = EachTestingContext< - | { - relationType: RelationType; - objectMetadataId: string; - targetObjectMetadataId: string; - type: FieldMetadataType.RELATION | FieldMetadataType.MORPH_RELATION; - } - | ((args: { objectMetadataId: string; targetObjectMetadataId: string }) => { - relationType: RelationType; - objectMetadataId: string; - targetObjectMetadataId: string; - type: FieldMetadataType.RELATION | FieldMetadataType.MORPH_RELATION; - }) + (args: { objectMetadataId: string; targetObjectMetadataId: string }) => { + relationType: RelationType; + objectMetadataId: string; + targetObjectMetadataId: string; + type: FieldMetadataType.RELATION | FieldMetadataType.MORPH_RELATION; + } >[]; const eachTestingContextArray: EachTestingContextArray = [ @@ -93,15 +87,14 @@ describe('createOne FieldMetadataService relation fields', () => { ]; it.each(eachTestingContextArray)('$title', async ({ context }) => { - const contextPayload = - typeof context === 'function' - ? context({ - objectMetadataId: createdObjectMetadataOpportunityId, - targetObjectMetadataId: createdObjectMetadataPersonId, - }) - : context; + const contextPayload = context({ + objectMetadataId: createdObjectMetadataOpportunityId, + targetObjectMetadataId: createdObjectMetadataPersonId, + }); - const createdField = await createRelationBetweenObjects({ + const createdField = await createRelationBetweenObjects< + typeof contextPayload.type + >({ objectMetadataId: contextPayload.objectMetadataId, targetObjectMetadataId: contextPayload.targetObjectMetadataId, type: contextPayload.type, diff --git a/packages/twenty-server/test/integration/metadata/suites/object-metadata/morph-relation/delete-one-object-metadata-with-morph-relation.integration-spec.ts b/packages/twenty-server/test/integration/metadata/suites/object-metadata/morph-relation/delete-one-object-metadata-with-morph-relation.integration-spec.ts new file mode 100644 index 000000000..40b84f44c --- /dev/null +++ b/packages/twenty-server/test/integration/metadata/suites/object-metadata/morph-relation/delete-one-object-metadata-with-morph-relation.integration-spec.ts @@ -0,0 +1,5 @@ +describe('Delete Object metadata with morph relation should succeed', () => { + it('should succeed', () => { + // 'TODO guillim : once delete is implemented' + }); +}); diff --git a/packages/twenty-server/test/integration/metadata/suites/object-metadata/relation/delete-one-object-metadata-with-relation.integration-spec.ts b/packages/twenty-server/test/integration/metadata/suites/object-metadata/relation/delete-one-object-metadata-with-relation.integration-spec.ts new file mode 100644 index 000000000..424834df3 --- /dev/null +++ b/packages/twenty-server/test/integration/metadata/suites/object-metadata/relation/delete-one-object-metadata-with-relation.integration-spec.ts @@ -0,0 +1,189 @@ +import { deleteOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/delete-one-field-metadata.util'; +import { findManyFieldsMetadataQueryFactory } from 'test/integration/metadata/suites/field-metadata/utils/find-many-fields-metadata-query-factory.util'; +import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util'; +import { createRelationBetweenObjects } from 'test/integration/metadata/suites/object-metadata/utils/create-relation-between-objects.util'; +import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util'; +import { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util'; +import { EachTestingContext } from 'twenty-shared/testing'; +import { FieldMetadataType } from 'twenty-shared/types'; +import { isDefined } from 'twenty-shared/utils'; + +import { FieldMetadataInterface } from 'src/engine/metadata-modules/field-metadata/interfaces/field-metadata.interface'; +import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface'; + +type DeleteOneObjectMetadataItemTestingContext = EachTestingContext< + (args: { objectMetadataIdToDelete: string; relationFieldId: string }) => { + objectMetadataIdToDelete: string; + relationFieldId: string; + } +>[]; +const successfulDeleteSourceUseCase: DeleteOneObjectMetadataItemTestingContext = + [ + { + title: + 'When deleting source object, the relation on the target should be deleted', + context: ({ objectMetadataIdToDelete, relationFieldId }) => ({ + objectMetadataIdToDelete, + relationFieldId, + }), + }, + ]; + +const successfulDeleteTargetUseCase: DeleteOneObjectMetadataItemTestingContext = + [ + { + title: + 'When deleting target object, the relation on the source should be deleted', + context: ({ objectMetadataIdToDelete, relationFieldId }) => ({ + objectMetadataIdToDelete, + relationFieldId, + }), + }, + ]; + +describe('Delete Object metadata with relation should succeed', () => { + let createdObjectMetadataPersonId = ''; + let createdObjectMetadataOpportunityId = ''; + let createdRelationField: FieldMetadataInterface; + let globalTestContext: { + opportunityMetadataId: string; + personMetadataId: string; + relationField: FieldMetadataInterface; + }; + + beforeEach(async () => { + const { + data: { + createOneObject: { id: objectMetadataPersonId }, + }, + } = await createOneObjectMetadata({ + input: { + nameSingular: 'personForRelation', + namePlural: 'peopleForRelation', + labelSingular: 'Person For Relation', + labelPlural: 'People For Relation', + icon: 'IconPerson', + }, + }); + + createdObjectMetadataPersonId = objectMetadataPersonId; + + const { + data: { + createOneObject: { id: objectMetadataOpportunityId }, + }, + } = await createOneObjectMetadata({ + input: { + nameSingular: 'opportunityForRelation', + namePlural: 'opportunitiesForRelation', + labelSingular: 'Opportunity For Relation', + labelPlural: 'Opportunities For Relation', + icon: 'IconOpportunity', + }, + }); + + createdObjectMetadataOpportunityId = objectMetadataOpportunityId; + + createdRelationField = + await createRelationBetweenObjects({ + objectMetadataId: createdObjectMetadataOpportunityId, + targetObjectMetadataId: createdObjectMetadataPersonId, + type: FieldMetadataType.RELATION, + relationType: RelationType.MANY_TO_ONE, + }); + + globalTestContext = { + opportunityMetadataId: createdObjectMetadataOpportunityId, + personMetadataId: createdObjectMetadataPersonId, + relationField: createdRelationField, + }; + }); + afterEach(async () => { + await deleteOneFieldMetadata({ + input: { idToDelete: createdRelationField.id }, + }); + await deleteOneObjectMetadata({ + input: { idToDelete: createdObjectMetadataPersonId }, + }); + await deleteOneObjectMetadata({ + input: { idToDelete: createdObjectMetadataOpportunityId }, + }); + }); + + it.each(successfulDeleteSourceUseCase)('$title', async ({ context }) => { + const computedContext = context({ + objectMetadataIdToDelete: globalTestContext.personMetadataId, + relationFieldId: globalTestContext.relationField.id, + }); + + await deleteOneObjectMetadata({ + input: { idToDelete: computedContext.objectMetadataIdToDelete }, + }); + + const opportunityFieldOnPersonAfterDeletion = await findFieldMetadata({ + fieldMetadataId: computedContext.relationFieldId, + }); + + expect(opportunityFieldOnPersonAfterDeletion).toBeUndefined(); + }); + + it.each(successfulDeleteTargetUseCase)('$title', async ({ context }) => { + if (!isDefined(globalTestContext.relationField.relation)) { + throw new Error('Relation field relation is undefined'); + } + + const computedContext = context({ + objectMetadataIdToDelete: globalTestContext.opportunityMetadataId, + relationFieldId: + globalTestContext.relationField.relation.targetFieldMetadata.id, + }); + + await deleteOneObjectMetadata({ + input: { idToDelete: computedContext.objectMetadataIdToDelete }, + }); + + const personFieldOnOpportunityAfterDeletion = await findFieldMetadata({ + fieldMetadataId: computedContext.relationFieldId, + }); + + expect(personFieldOnOpportunityAfterDeletion).toBeUndefined(); + }); +}); + +const findFieldMetadata = async ({ + fieldMetadataId, +}: { + fieldMetadataId: string; +}) => { + const operation = findManyFieldsMetadataQueryFactory({ + gqlFields: ` + id + name + object { + id + nameSingular + } + relation { + type + targetFieldMetadata { + id + } + targetObjectMetadata { + id + } + } + settings + `, + input: { + filter: { + id: { eq: fieldMetadataId }, + }, + paging: { first: 1 }, + }, + }); + + const fields = await makeMetadataAPIRequest(operation); + const field = fields.body.data.fields.edges?.[0]?.node; + + return field; +}; diff --git a/packages/twenty-server/test/integration/metadata/suites/object-metadata/utils/create-relation-between-objects.util.ts b/packages/twenty-server/test/integration/metadata/suites/object-metadata/utils/create-relation-between-objects.util.ts index dd28c1249..ef84b479a 100644 --- a/packages/twenty-server/test/integration/metadata/suites/object-metadata/utils/create-relation-between-objects.util.ts +++ b/packages/twenty-server/test/integration/metadata/suites/object-metadata/utils/create-relation-between-objects.util.ts @@ -4,7 +4,9 @@ import { FieldMetadataType } from 'twenty-shared/types'; import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface'; -export const createRelationBetweenObjects = async ({ +export const createRelationBetweenObjects = async < + T extends FieldMetadataType.RELATION | FieldMetadataType.MORPH_RELATION, +>({ objectMetadataId, targetObjectMetadataId, type, @@ -17,7 +19,7 @@ export const createRelationBetweenObjects = async ({ }: { objectMetadataId: string; targetObjectMetadataId: string; - type: FieldMetadataType.RELATION | FieldMetadataType.MORPH_RELATION; + type: T; relationType: RelationType; name?: string; label?: string;