From da288b1998e47f3e1c396f12fc0f6ebbabb3c21d Mon Sep 17 00:00:00 2001 From: Paul Rastoin <45004772+prastoin@users.noreply.github.com> Date: Tue, 2 Sep 2025 10:15:01 +0200 Subject: [PATCH] V2 integ test sequential operations testing (#14228) Wil need to add a morph relation field in a new test suite Especially searching for enum collision --- ...ate-object-metadata-v2.integration-spec.ts | 189 ++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 packages/twenty-server/test/integration/metadata/suites/object-metadata/create-delete-and-create-object-metadata-v2.integration-spec.ts diff --git a/packages/twenty-server/test/integration/metadata/suites/object-metadata/create-delete-and-create-object-metadata-v2.integration-spec.ts b/packages/twenty-server/test/integration/metadata/suites/object-metadata/create-delete-and-create-object-metadata-v2.integration-spec.ts new file mode 100644 index 0000000000..86b7474edc --- /dev/null +++ b/packages/twenty-server/test/integration/metadata/suites/object-metadata/create-delete-and-create-object-metadata-v2.integration-spec.ts @@ -0,0 +1,189 @@ +import { type CreateOneFieldFactoryInput } from 'test/integration/metadata/suites/field-metadata/utils/create-one-field-metadata-query-factory.util'; +import { createOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/create-one-field-metadata.util'; +import { deleteOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/delete-one-field-metadata.util'; +import { CUSTOM_OBJECT_DISHES } from 'test/integration/metadata/suites/object-metadata/constants/custom-object-dishes.constants'; +import { type CreateOneObjectFactoryInput } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata-query-factory.util'; +import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util'; +import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util'; +import { updateOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata.util'; +import { updateFeatureFlag } from 'test/integration/metadata/suites/utils/update-feature-flag.util'; +import { FieldMetadataType } from 'twenty-shared/types'; +import { isDefined } from 'twenty-shared/utils'; +import { updateOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/update-one-field-metadata.util'; + +import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; + +describe('Handle same object sequential operations test suite', () => { + let createdObjectMetadataId: string | undefined = undefined; + + beforeAll(async () => { + await updateFeatureFlag({ + expectToFail: false, + featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED, + value: true, + }); + }); + afterAll(async () => { + await updateFeatureFlag({ + expectToFail: false, + featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED, + value: false, + }); + }); + afterEach(async () => { + if (!isDefined(createdObjectMetadataId)) { + return; + } + await updateOneObjectMetadata({ + expectToFail: false, + input: { + idToUpdate: createdObjectMetadataId, + updatePayload: { + isActive: false, + }, + }, + }); + + await deleteOneObjectMetadata({ + input: { idToDelete: createdObjectMetadataId }, + expectToFail: false, + }); + + createdObjectMetadataId = undefined; + }); + it('It should handle creation deletion and creation of the same metadata entity gracefully', async () => { + const { + labelPlural, + description, + labelSingular, + namePlural, + nameSingular, + } = CUSTOM_OBJECT_DISHES; + const createObjectInput: CreateOneObjectFactoryInput = { + labelPlural, + description, + labelSingular, + namePlural, + nameSingular, + icon: 'IconBuildingSkyscraper', + isLabelSyncedWithName: false, + }; + const objectCreationGqlFields = ` + id + labelPlural + description + labelSingular + namePlural + nameSingular + icon + isLabelSyncedWithName +`; + const fieldCreationGqlFields = ` + id + label + name + type + description +`; + const { + data: { createOneObject }, + } = await createOneObjectMetadata({ + expectToFail: false, + input: createObjectInput, + gqlFields: objectCreationGqlFields, + }); + + createdObjectMetadataId = createOneObject.id; + expect(createOneObject).toMatchObject(createObjectInput); + + const createFieldInput: Omit< + CreateOneFieldFactoryInput, + 'objectMetadataId' + > = { + label: 'field label', + name: 'fieldName', + type: FieldMetadataType.TEXT, + description: 'custom description', + }; + const { + data: { createOneField }, + } = await createOneFieldMetadata({ + input: { + ...createFieldInput, + objectMetadataId: createdObjectMetadataId, + }, + expectToFail: false, + gqlFields: fieldCreationGqlFields, + }); + + expect(createOneField).toMatchObject(createFieldInput); + + await updateOneFieldMetadata({ + expectToFail: false, + input: { + idToUpdate: createOneField.id, + updatePayload: { + isActive: false, + }, + }, + }); + await deleteOneFieldMetadata({ + input: { + idToDelete: createOneField.id, + }, + expectToFail: false, + }); + + const { + data: { createOneField: secondCreateOneField }, + } = await createOneFieldMetadata({ + input: { + ...createFieldInput, + objectMetadataId: createdObjectMetadataId, + }, + expectToFail: false, + gqlFields: fieldCreationGqlFields, + }); + + expect(secondCreateOneField).toMatchObject(createFieldInput); + + await updateOneObjectMetadata({ + expectToFail: false, + input: { + idToUpdate: createdObjectMetadataId, + updatePayload: { + isActive: false, + }, + }, + }); + await deleteOneObjectMetadata({ + input: { idToDelete: createdObjectMetadataId }, + expectToFail: false, + }); + createdObjectMetadataId = undefined; + + const { + data: { createOneObject: secondCreateOneObject }, + } = await createOneObjectMetadata({ + expectToFail: false, + input: createObjectInput, + gqlFields: objectCreationGqlFields, + }); + + createdObjectMetadataId = secondCreateOneObject.id; + expect(secondCreateOneObject).toMatchObject(createObjectInput); + + const { + data: { createOneField: thirdCreateOneField }, + } = await createOneFieldMetadata({ + input: { + ...createFieldInput, + objectMetadataId: createdObjectMetadataId, + }, + expectToFail: false, + gqlFields: fieldCreationGqlFields, + }); + + expect(thirdCreateOneField).toMatchObject(createFieldInput); + }); +});