diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-entity/utils/__tests__/__snapshots__/compare-two-flat-entity.util.spec.ts.snap b/packages/twenty-server/src/engine/metadata-modules/flat-entity/utils/__tests__/__snapshots__/compare-two-flat-entity.util.spec.ts.snap new file mode 100644 index 0000000000..a1d2c54191 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-entity/utils/__tests__/__snapshots__/compare-two-flat-entity.util.spec.ts.snap @@ -0,0 +1,21 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`compareTwoFlatEntity It should detect flat field metadata isActive diff from true to false 1`] = ` +[ + { + "from": true, + "property": "isActive", + "to": false, + }, +] +`; + +exports[`compareTwoFlatEntity It should detect flat field metadata isActive diff from true to false 2`] = ` +[ + { + "from": false, + "property": "isActive", + "to": true, + }, +] +`; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-entity/utils/__tests__/compare-two-flat-entity.util.spec.ts b/packages/twenty-server/src/engine/metadata-modules/flat-entity/utils/__tests__/compare-two-flat-entity.util.spec.ts new file mode 100644 index 0000000000..5b03ae39eb --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-entity/utils/__tests__/compare-two-flat-entity.util.spec.ts @@ -0,0 +1,80 @@ +import { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any'; +import { type AllMetadataName } from 'twenty-shared/metadata'; +import { + eachTestingContextFilter, + type EachTestingContext, +} from 'twenty-shared/testing'; +import { FieldMetadataType, type FromTo } from 'twenty-shared/types'; + +import { ALL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY } from 'src/engine/metadata-modules/flat-entity/constant/all-flat-entity-properties-to-compare-and-stringify.constant'; +import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type'; +import { compareTwoFlatEntity } from 'src/engine/metadata-modules/flat-entity/utils/compare-two-flat-entity.util'; +import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock'; + +type TestContext = FromTo< + MetadataFlatEntity, + 'flatEntity' +> & { metadataName: T }; + +describe('compareTwoFlatEntity', () => { + const testCases = [ + { + title: + 'It should detect flat field metadata isActive diff from true to false', + context: { + fromFlatEntity: getFlatFieldMetadataMock({ + objectMetadataId: 'object-metadata-id', + type: FieldMetadataType.TEXT, + universalIdentifier: 'universal-identifier', + isActive: true, + }), + metadataName: 'fieldMetadata', + toFlatEntity: getFlatFieldMetadataMock({ + objectMetadataId: 'object-metadata-id', + type: FieldMetadataType.TEXT, + universalIdentifier: 'universal-identifier', + isActive: false, + }), + }, + }, + { + title: + 'It should detect flat field metadata isActive diff from true to false', + context: { + fromFlatEntity: getFlatFieldMetadataMock({ + objectMetadataId: 'object-metadata-id', + type: FieldMetadataType.TEXT, + universalIdentifier: 'universal-identifier', + isActive: false, + }), + metadataName: 'fieldMetadata', + toFlatEntity: getFlatFieldMetadataMock({ + objectMetadataId: 'object-metadata-id', + type: FieldMetadataType.TEXT, + universalIdentifier: 'universal-identifier', + isActive: true, + }), + }, + }, + ] as const satisfies EachTestingContext[]; + + test.each(eachTestingContextFilter(testCases))( + '$title', + ({ context: { metadataName, fromFlatEntity, toFlatEntity } }) => { + const result = compareTwoFlatEntity({ + fromFlatEntity, + propertiesToCompare: + ALL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY[metadataName] + .propertiesToCompare as any, + propertiesToStringify: + ALL_FLAT_ENTITY_PROPERTIES_TO_COMPARE_AND_STRINGIFY[metadataName] + .propertiesToStringify as any, + toFlatEntity, + }); + + expect(result).toMatchSnapshot( + extractRecordIdsAndDatesAsExpectAny(result), + ); + }, + ); +}); diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/__tests__/__snapshots__/flat-entity-deleted-created-updated-matrix-dispatcher.util.spec.ts.snap b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/__tests__/__snapshots__/flat-entity-deleted-created-updated-matrix-dispatcher.util.spec.ts.snap new file mode 100644 index 0000000000..5f25e913fc --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/__tests__/__snapshots__/flat-entity-deleted-created-updated-matrix-dispatcher.util.spec.ts.snap @@ -0,0 +1,275 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect a created entity 1`] = ` +{ + "createdFlatEntityMaps": { + "byId": { + "field-id-1": { + "applicationId": "application-id-1", + "calendarViewIds": [], + "createdAt": 2024-01-01T00:00:00.000Z, + "defaultValue": null, + "description": "default flat field metadata description", + "icon": "icon", + "id": "field-id-1", + "isActive": true, + "isCustom": true, + "isLabelSyncedWithName": false, + "isNullable": true, + "isSystem": false, + "isUIReadOnly": false, + "isUnique": false, + "kanbanAggregateOperationViewIds": [], + "label": "flat field metadata label", + "morphId": null, + "name": "flatFieldMetadataName", + "objectMetadataId": "object-metadata-id-1", + "options": null, + "relationTargetFieldMetadataId": null, + "relationTargetObjectMetadataId": null, + "settings": null, + "standardId": null, + "standardOverrides": null, + "type": "TEXT", + "universalIdentifier": "universal-identifier-1", + "updatedAt": 2024-01-01T00:00:00.000Z, + "viewFieldIds": [], + "viewFilterIds": [], + "viewGroupIds": [], + "workspaceId": "workspace-id-1", + }, + }, + "idByUniversalIdentifier": { + "universal-identifier-1": "field-id-1", + }, + "universalIdentifiersByApplicationId": { + "application-id-1": [ + "universal-identifier-1", + ], + }, + }, + "deletedFlatEntityMaps": { + "byId": {}, + "idByUniversalIdentifier": {}, + "universalIdentifiersByApplicationId": {}, + }, + "updatedFlatEntityMaps": { + "byId": {}, + }, +} +`; + +exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect a deleted entity 1`] = ` +{ + "createdFlatEntityMaps": { + "byId": {}, + "idByUniversalIdentifier": {}, + "universalIdentifiersByApplicationId": {}, + }, + "deletedFlatEntityMaps": { + "byId": { + "field-id-1": { + "applicationId": "application-id-1", + "calendarViewIds": [], + "createdAt": 2024-01-01T00:00:00.000Z, + "defaultValue": null, + "description": "default flat field metadata description", + "icon": "icon", + "id": "field-id-1", + "isActive": true, + "isCustom": true, + "isLabelSyncedWithName": false, + "isNullable": true, + "isSystem": false, + "isUIReadOnly": false, + "isUnique": false, + "kanbanAggregateOperationViewIds": [], + "label": "flat field metadata label", + "morphId": null, + "name": "flatFieldMetadataName", + "objectMetadataId": "object-metadata-id-1", + "options": null, + "relationTargetFieldMetadataId": null, + "relationTargetObjectMetadataId": null, + "settings": null, + "standardId": null, + "standardOverrides": null, + "type": "TEXT", + "universalIdentifier": "universal-identifier-1", + "updatedAt": 2024-01-01T00:00:00.000Z, + "viewFieldIds": [], + "viewFilterIds": [], + "viewGroupIds": [], + "workspaceId": "workspace-id-1", + }, + }, + "idByUniversalIdentifier": { + "universal-identifier-1": "field-id-1", + }, + "universalIdentifiersByApplicationId": { + "application-id-1": [ + "universal-identifier-1", + ], + }, + }, + "updatedFlatEntityMaps": { + "byId": {}, + }, +} +`; + +exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect an updated entity 1`] = ` +{ + "createdFlatEntityMaps": { + "byId": {}, + "idByUniversalIdentifier": {}, + "universalIdentifiersByApplicationId": {}, + }, + "deletedFlatEntityMaps": { + "byId": {}, + "idByUniversalIdentifier": {}, + "universalIdentifiersByApplicationId": {}, + }, + "updatedFlatEntityMaps": { + "byId": { + "field-id-1": { + "updates": [ + { + "from": false, + "property": "isActive", + "to": true, + }, + ], + }, + }, + }, +} +`; + +exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should detect created, deleted and updated entities 1`] = ` +{ + "createdFlatEntityMaps": { + "byId": { + "field-id-3": { + "applicationId": "application-id-1", + "calendarViewIds": [], + "createdAt": 2024-01-01T00:00:00.000Z, + "defaultValue": null, + "description": "default flat field metadata description", + "icon": "icon", + "id": "field-id-3", + "isActive": true, + "isCustom": true, + "isLabelSyncedWithName": false, + "isNullable": true, + "isSystem": false, + "isUIReadOnly": false, + "isUnique": false, + "kanbanAggregateOperationViewIds": [], + "label": "flat field metadata label", + "morphId": null, + "name": "flatFieldMetadataName", + "objectMetadataId": "object-metadata-id-1", + "options": null, + "relationTargetFieldMetadataId": null, + "relationTargetObjectMetadataId": null, + "settings": null, + "standardId": null, + "standardOverrides": null, + "type": "TEXT", + "universalIdentifier": "universal-identifier-3", + "updatedAt": 2024-01-01T00:00:00.000Z, + "viewFieldIds": [], + "viewFilterIds": [], + "viewGroupIds": [], + "workspaceId": "workspace-id-1", + }, + }, + "idByUniversalIdentifier": { + "universal-identifier-3": "field-id-3", + }, + "universalIdentifiersByApplicationId": { + "application-id-1": [ + "universal-identifier-3", + ], + }, + }, + "deletedFlatEntityMaps": { + "byId": { + "field-id-2": { + "applicationId": "application-id-1", + "calendarViewIds": [], + "createdAt": 2024-01-01T00:00:00.000Z, + "defaultValue": null, + "description": "default flat field metadata description", + "icon": "icon", + "id": "field-id-2", + "isActive": true, + "isCustom": true, + "isLabelSyncedWithName": false, + "isNullable": true, + "isSystem": false, + "isUIReadOnly": false, + "isUnique": false, + "kanbanAggregateOperationViewIds": [], + "label": "flat field metadata label", + "morphId": null, + "name": "flatFieldMetadataName", + "objectMetadataId": "object-metadata-id-1", + "options": null, + "relationTargetFieldMetadataId": null, + "relationTargetObjectMetadataId": null, + "settings": null, + "standardId": null, + "standardOverrides": null, + "type": "TEXT", + "universalIdentifier": "universal-identifier-2", + "updatedAt": 2024-01-01T00:00:00.000Z, + "viewFieldIds": [], + "viewFilterIds": [], + "viewGroupIds": [], + "workspaceId": "workspace-id-1", + }, + }, + "idByUniversalIdentifier": { + "universal-identifier-2": "field-id-2", + }, + "universalIdentifiersByApplicationId": { + "application-id-1": [ + "universal-identifier-2", + ], + }, + }, + "updatedFlatEntityMaps": { + "byId": { + "field-id-1": { + "updates": [ + { + "from": true, + "property": "isActive", + "to": false, + }, + ], + }, + }, + }, +} +`; + +exports[`flatEntityDeletedCreatedUpdatedMatrixDispatcher It should not detect deleted entities when inferDeletionFromMissingEntities is false 1`] = ` +{ + "createdFlatEntityMaps": { + "byId": {}, + "idByUniversalIdentifier": {}, + "universalIdentifiersByApplicationId": {}, + }, + "deletedFlatEntityMaps": { + "byId": {}, + "idByUniversalIdentifier": {}, + "universalIdentifiersByApplicationId": {}, + }, + "updatedFlatEntityMaps": { + "byId": {}, + }, +} +`; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/__tests__/flat-entity-deleted-created-updated-matrix-dispatcher.util.spec.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/__tests__/flat-entity-deleted-created-updated-matrix-dispatcher.util.spec.ts new file mode 100644 index 0000000000..7cb5abbb55 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/utils/__tests__/flat-entity-deleted-created-updated-matrix-dispatcher.util.spec.ts @@ -0,0 +1,196 @@ +import { + eachTestingContextFilter, + type EachTestingContext, +} from 'twenty-shared/testing'; +import { FieldMetadataType, type FromTo } from 'twenty-shared/types'; + +import { type MetadataFlatEntity } from 'src/engine/metadata-modules/flat-entity/types/metadata-flat-entity.type'; +import { getFlatFieldMetadataMock } from 'src/engine/metadata-modules/flat-field-metadata/__mocks__/get-flat-field-metadata.mock'; +import { flatEntityDeletedCreatedUpdatedMatrixDispatcher } from 'src/engine/workspace-manager/workspace-migration-v2/utils/flat-entity-deleted-created-updated-matrix-dispatcher.util'; +import { type WorkspaceMigrationBuilderOptions } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-builder-options.type'; + +type TestContext = FromTo[]> & { + metadataName: 'fieldMetadata'; + buildOptions: WorkspaceMigrationBuilderOptions; +}; + +describe('flatEntityDeletedCreatedUpdatedMatrixDispatcher', () => { + const testCases = [ + { + title: 'It should detect a created entity', + context: { + from: [], + to: [ + getFlatFieldMetadataMock({ + objectMetadataId: 'object-metadata-id-1', + type: FieldMetadataType.TEXT, + universalIdentifier: 'universal-identifier-1', + id: 'field-id-1', + workspaceId: 'workspace-id-1', + applicationId: 'application-id-1', + createdAt: new Date('2024-01-01T00:00:00.000Z'), + updatedAt: new Date('2024-01-01T00:00:00.000Z'), + }), + ], + metadataName: 'fieldMetadata', + buildOptions: { + inferDeletionFromMissingEntities: { fieldMetadata: false }, + isSystemBuild: false, + }, + }, + }, + { + title: 'It should detect a deleted entity', + context: { + from: [ + getFlatFieldMetadataMock({ + objectMetadataId: 'object-metadata-id-1', + type: FieldMetadataType.TEXT, + universalIdentifier: 'universal-identifier-1', + id: 'field-id-1', + workspaceId: 'workspace-id-1', + applicationId: 'application-id-1', + createdAt: new Date('2024-01-01T00:00:00.000Z'), + updatedAt: new Date('2024-01-01T00:00:00.000Z'), + }), + ], + to: [], + metadataName: 'fieldMetadata', + buildOptions: { + inferDeletionFromMissingEntities: { fieldMetadata: true }, + isSystemBuild: false, + }, + }, + }, + { + title: 'It should detect an updated entity', + context: { + from: [ + getFlatFieldMetadataMock({ + objectMetadataId: 'object-metadata-id-1', + type: FieldMetadataType.TEXT, + universalIdentifier: 'universal-identifier-1', + id: 'field-id-1', + workspaceId: 'workspace-id-1', + applicationId: 'application-id-1', + createdAt: new Date('2024-01-01T00:00:00.000Z'), + updatedAt: new Date('2024-01-01T00:00:00.000Z'), + isActive: false, + }), + ], + to: [ + getFlatFieldMetadataMock({ + objectMetadataId: 'object-metadata-id-1', + type: FieldMetadataType.TEXT, + universalIdentifier: 'universal-identifier-1', + id: 'field-id-1', + workspaceId: 'workspace-id-1', + applicationId: 'application-id-1', + createdAt: new Date('2024-01-01T00:00:00.000Z'), + updatedAt: new Date('2024-01-01T00:00:00.000Z'), + isActive: true, + }), + ], + metadataName: 'fieldMetadata', + buildOptions: { + inferDeletionFromMissingEntities: { fieldMetadata: false }, + isSystemBuild: false, + }, + }, + }, + { + title: 'It should detect created, deleted and updated entities', + context: { + from: [ + getFlatFieldMetadataMock({ + objectMetadataId: 'object-metadata-id-1', + type: FieldMetadataType.TEXT, + universalIdentifier: 'universal-identifier-1', + id: 'field-id-1', + workspaceId: 'workspace-id-1', + applicationId: 'application-id-1', + createdAt: new Date('2024-01-01T00:00:00.000Z'), + updatedAt: new Date('2024-01-01T00:00:00.000Z'), + isActive: true, + }), + getFlatFieldMetadataMock({ + objectMetadataId: 'object-metadata-id-1', + type: FieldMetadataType.TEXT, + universalIdentifier: 'universal-identifier-2', + id: 'field-id-2', + workspaceId: 'workspace-id-1', + applicationId: 'application-id-1', + createdAt: new Date('2024-01-01T00:00:00.000Z'), + updatedAt: new Date('2024-01-01T00:00:00.000Z'), + }), + ], + to: [ + getFlatFieldMetadataMock({ + objectMetadataId: 'object-metadata-id-1', + type: FieldMetadataType.TEXT, + universalIdentifier: 'universal-identifier-1', + id: 'field-id-1', + workspaceId: 'workspace-id-1', + applicationId: 'application-id-1', + createdAt: new Date('2024-01-01T00:00:00.000Z'), + updatedAt: new Date('2024-01-01T00:00:00.000Z'), + isActive: false, + }), + getFlatFieldMetadataMock({ + objectMetadataId: 'object-metadata-id-1', + type: FieldMetadataType.TEXT, + universalIdentifier: 'universal-identifier-3', + id: 'field-id-3', + workspaceId: 'workspace-id-1', + applicationId: 'application-id-1', + createdAt: new Date('2024-01-01T00:00:00.000Z'), + updatedAt: new Date('2024-01-01T00:00:00.000Z'), + }), + ], + metadataName: 'fieldMetadata', + buildOptions: { + inferDeletionFromMissingEntities: { fieldMetadata: true }, + isSystemBuild: false, + }, + }, + }, + { + title: + 'It should not detect deleted entities when inferDeletionFromMissingEntities is false', + context: { + from: [ + getFlatFieldMetadataMock({ + objectMetadataId: 'object-metadata-id-1', + type: FieldMetadataType.TEXT, + universalIdentifier: 'universal-identifier-1', + id: 'field-id-1', + workspaceId: 'workspace-id-1', + applicationId: 'application-id-1', + createdAt: new Date('2024-01-01T00:00:00.000Z'), + updatedAt: new Date('2024-01-01T00:00:00.000Z'), + }), + ], + to: [], + metadataName: 'fieldMetadata', + buildOptions: { + inferDeletionFromMissingEntities: { fieldMetadata: false }, + isSystemBuild: false, + }, + }, + }, + ] as EachTestingContext[]; + + test.each(eachTestingContextFilter(testCases))( + '$title', + ({ context: { from, to, metadataName, buildOptions } }) => { + const result = flatEntityDeletedCreatedUpdatedMatrixDispatcher({ + from: from as any, + to: to as any, + metadataName, + buildOptions, + }); + + expect(result).toMatchSnapshot(); + }, + ); +}); diff --git a/packages/twenty-server/test/integration/metadata/suites/field-metadata/__snapshots__/successful-update-one-standard-field-metadata.integration-spec.ts.snap b/packages/twenty-server/test/integration/metadata/suites/field-metadata/__snapshots__/successful-update-one-standard-field-metadata.integration-spec.ts.snap index b2cdef322e..36e72c090d 100644 --- a/packages/twenty-server/test/integration/metadata/suites/field-metadata/__snapshots__/successful-update-one-standard-field-metadata.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/metadata/suites/field-metadata/__snapshots__/successful-update-one-standard-field-metadata.integration-spec.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`Standard field metadata update should succeed when setting isActive to false 1`] = ` +exports[`Standard field metadata update should succeed Atomic update test suite when setting isActive to false 1`] = ` { "defaultValue": "'NEW'", "description": "Opportunity stage", @@ -51,7 +51,7 @@ exports[`Standard field metadata update should succeed when setting isActive to } `; -exports[`Standard field metadata update should succeed when updating defaultValue 1`] = ` +exports[`Standard field metadata update should succeed Atomic update test suite when updating defaultValue 1`] = ` { "defaultValue": "'SCREENING'", "description": "Opportunity stage", @@ -102,7 +102,7 @@ exports[`Standard field metadata update should succeed when updating defaultValu } `; -exports[`Standard field metadata update should succeed when updating description 1`] = ` +exports[`Standard field metadata update should succeed Atomic update test suite when updating description 1`] = ` { "defaultValue": "'NEW'", "description": "Opportunity stage", @@ -157,7 +157,7 @@ exports[`Standard field metadata update should succeed when updating description } `; -exports[`Standard field metadata update should succeed when updating icon 1`] = ` +exports[`Standard field metadata update should succeed Atomic update test suite when updating icon 1`] = ` { "defaultValue": "'NEW'", "description": "Opportunity stage", @@ -212,7 +212,7 @@ exports[`Standard field metadata update should succeed when updating icon 1`] = } `; -exports[`Standard field metadata update should succeed when updating label 1`] = ` +exports[`Standard field metadata update should succeed Atomic update test suite when updating label 1`] = ` { "defaultValue": "'NEW'", "description": "Opportunity stage", @@ -267,7 +267,7 @@ exports[`Standard field metadata update should succeed when updating label 1`] = } `; -exports[`Standard field metadata update should succeed when updating options 1`] = ` +exports[`Standard field metadata update should succeed Atomic update test suite when updating options 1`] = ` { "defaultValue": "'NEW'", "description": "Opportunity stage", diff --git a/packages/twenty-server/test/integration/metadata/suites/field-metadata/successful-update-one-standard-field-metadata.integration-spec.ts b/packages/twenty-server/test/integration/metadata/suites/field-metadata/successful-update-one-standard-field-metadata.integration-spec.ts index 254b12b5d1..70828c32c0 100644 --- a/packages/twenty-server/test/integration/metadata/suites/field-metadata/successful-update-one-standard-field-metadata.integration-spec.ts +++ b/packages/twenty-server/test/integration/metadata/suites/field-metadata/successful-update-one-standard-field-metadata.integration-spec.ts @@ -77,7 +77,9 @@ const successfulUpdateTestsUseCase: UpdateOneStandardFieldMetadataTestingContext ]; describe('Standard field metadata update should succeed', () => { - let originalStageFieldMetadata: FieldMetadataDTO; + const opportunityObjectFields: FieldMetadataDTO[] = []; + let originalFieldMetadataToRestore: FieldMetadataDTO[] = []; + let originalStageFieldMetadata: FieldMetadataDTO | undefined; beforeAll(async () => { const { objects } = await findManyObjectMetadata({ @@ -114,42 +116,91 @@ describe('Standard field metadata update should succeed', () => { (o) => o.nameSingular === 'opportunity', ); - jestExpectToBeDefined(opportunityObject); + jestExpectToBeDefined(opportunityObject?.fieldsList); - const opportunityStageField = opportunityObject.fieldsList?.find( + opportunityObjectFields.push(...opportunityObject.fieldsList); + + originalStageFieldMetadata = opportunityObjectFields.find( (field) => field.name === 'stage' && !field.isCustom, ); - - jestExpectToBeDefined(opportunityStageField); - originalStageFieldMetadata = opportunityStageField; }); afterEach(async () => { - await updateOneFieldMetadata({ - expectToFail: false, - input: { - idToUpdate: originalStageFieldMetadata.id, - updatePayload: { - label: originalStageFieldMetadata.label, - description: originalStageFieldMetadata.description, - icon: originalStageFieldMetadata.icon, - isActive: originalStageFieldMetadata.isActive, - options: originalStageFieldMetadata.options, - defaultValue: originalStageFieldMetadata.defaultValue, + for (const originalFieldMetadata of originalFieldMetadataToRestore) { + await updateOneFieldMetadata({ + expectToFail: false, + input: { + idToUpdate: originalFieldMetadata.id, + updatePayload: { + label: originalFieldMetadata.label, + description: originalFieldMetadata.description, + icon: originalFieldMetadata.icon, + isActive: originalFieldMetadata.isActive, + options: originalFieldMetadata.options, + defaultValue: originalFieldMetadata.defaultValue, + }, }, - }, - }); + }); + } + + originalFieldMetadataToRestore = []; }); - it.each(eachTestingContextFilter(successfulUpdateTestsUseCase))( - '$title', - async ({ context }) => { - const updatePayload = context; + describe('Atomic update test suite', () => { + it.each(eachTestingContextFilter(successfulUpdateTestsUseCase))( + '$title', + async ({ context }) => { + jestExpectToBeDefined(originalStageFieldMetadata); + originalFieldMetadataToRestore.push(originalStageFieldMetadata); + const updatePayload = context; + const { data } = await updateOneFieldMetadata({ + input: { + idToUpdate: (originalStageFieldMetadata as FieldMetadataDTO).id, + updatePayload, + }, + expectToFail: false, + gqlFields: ` + id + name + label + description + icon + isActive + isCustom + options + defaultValue + standardOverrides { + label + description + icon + } + `, + }); - const { data } = await updateOneFieldMetadata({ + expect(data.updateOneField.id).toBe(originalStageFieldMetadata.id); + expect(data.updateOneField).toMatchSnapshot( + extractRecordIdsAndDatesAsExpectAny({ ...data.updateOneField }), + ); + }, + ); + }); + + it.failing( + 'Should deactivate and reactivate standard field successfully', + async () => { + const deletedAtField = opportunityObjectFields.find( + (field) => field.name === 'deletedAt', + ); + + jestExpectToBeDefined(deletedAtField); + expect(deletedAtField.isActive).toBe(true); + + const { data: firstUpdateData } = await updateOneFieldMetadata({ input: { - idToUpdate: originalStageFieldMetadata.id, - updatePayload, + idToUpdate: deletedAtField.id, + updatePayload: { + isActive: false, + }, }, expectToFail: false, gqlFields: ` @@ -170,10 +221,35 @@ describe('Standard field metadata update should succeed', () => { `, }); - expect(data.updateOneField.id).toBe(originalStageFieldMetadata.id); - expect(data.updateOneField).toMatchSnapshot( - extractRecordIdsAndDatesAsExpectAny({ ...data.updateOneField }), - ); + expect(firstUpdateData.updateOneField.isActive).toBe(false); + + const { data: secondUpdateData } = await updateOneFieldMetadata({ + input: { + idToUpdate: deletedAtField.id, + updatePayload: { + isActive: true, + }, + }, + expectToFail: false, + gqlFields: ` + id + name + label + description + icon + isActive + isCustom + options + defaultValue + standardOverrides { + label + description + icon + } + `, + }); + + expect(secondUpdateData.updateOneField.isActive).toBe(true); }, ); });