Activate v2 default seed (#14660)
## Introduction After enabling flag by default got following errors: ```ts Test Suites: 48 failed, 1 skipped, 97 passed, 145 of 146 total Tests: 499 failed, 1 skipped, 644 passed, 1144 total Snapshots: 61 failed, 133 passed, 194 total Time: 363.226 s Ran all test suites. ``` ## From <img width="2952" height="1510" alt="image" src="https://github.com/user-attachments/assets/7e3b20c6-2552-40a7-90bb-2d7b3002c895" /> ## To <img width="3134" height="1510" alt="image" src="https://github.com/user-attachments/assets/4fc9ada4-3c14-4333-a1db-11daf87db8d6" /> There's a huge test bundle in the latest shard that we could split up ## Notes - Set as failing morph relation field rename as for the moment we do not handle relation field mutation - fixed the object update and creation validation adding label identifier field metadata id checks - and more Some integrations tests are still on the v1 ( they have before and after all disabling and re-enabling the flat ) but mainly we now have more coverage on the v2 than the v1. Mainly related records, uniqueness have to be migrated the v2 and so tests too
This commit is contained in:
Vendored
+7
-14
@@ -8,11 +8,7 @@
|
||||
"runtimeVersion": "24.5",
|
||||
"request": "launch",
|
||||
"runtimeExecutable": "npx",
|
||||
"runtimeArgs": [
|
||||
"nx",
|
||||
"run",
|
||||
"twenty-server:start"
|
||||
],
|
||||
"runtimeArgs": ["nx", "run", "twenty-server:start"],
|
||||
"outputCapture": "std",
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"console": "internalConsole",
|
||||
@@ -23,11 +19,7 @@
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"runtimeExecutable": "npx",
|
||||
"runtimeArgs": [
|
||||
"nx",
|
||||
"run",
|
||||
"twenty-server:worker"
|
||||
],
|
||||
"runtimeArgs": ["nx", "run", "twenty-server:worker"],
|
||||
"outputCapture": "std",
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"console": "internalConsole",
|
||||
@@ -74,14 +66,15 @@
|
||||
"--",
|
||||
"--config",
|
||||
"./jest-integration.config.ts",
|
||||
"${relativeFile}"
|
||||
"${relativeFile}",
|
||||
"--testTimeout=0"
|
||||
],
|
||||
"cwd": "${workspaceFolder}/packages/twenty-server",
|
||||
"console": "integratedTerminal",
|
||||
"internalConsoleOptions": "neverOpen",
|
||||
"env": {
|
||||
"NODE_ENV": "test"
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "node",
|
||||
@@ -102,7 +95,7 @@
|
||||
"internalConsoleOptions": "neverOpen",
|
||||
"env": {
|
||||
"NODE_ENV": "test"
|
||||
},
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,9 +27,13 @@ rawDataSource
|
||||
);
|
||||
|
||||
await performQuery(
|
||||
`CREATE OR REPLACE FUNCTION unaccent_immutable(text) RETURNS text AS $$
|
||||
SELECT public.unaccent($1)
|
||||
$$ LANGUAGE sql IMMUTABLE;`,
|
||||
`CREATE OR REPLACE FUNCTION public.unaccent_immutable(input text)
|
||||
RETURNS text
|
||||
LANGUAGE sql
|
||||
IMMUTABLE
|
||||
AS $$
|
||||
SELECT public.unaccent('public.unaccent'::regdictionary, input)
|
||||
$$;`,
|
||||
'create immutable unaccent wrapper function',
|
||||
);
|
||||
|
||||
|
||||
+1
@@ -3,5 +3,6 @@ import { type FlatView } from 'src/engine/core-modules/view/flat-view/types/flat
|
||||
|
||||
export const FLAT_VIEW_PROPERTIES_TO_COMPARE = [
|
||||
'key',
|
||||
'deletedAt',
|
||||
...FLAT_VIEW_EDITABLE_PROPERTIES,
|
||||
] as const satisfies (keyof FlatView)[];
|
||||
|
||||
@@ -14,6 +14,7 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service';
|
||||
import { I18nService } from 'src/engine/core-modules/i18n/i18n.service';
|
||||
import { type I18nContext } from 'src/engine/core-modules/i18n/types/i18n-context.type';
|
||||
import { CreateViewInput } from 'src/engine/core-modules/view/dtos/inputs/create-view.input';
|
||||
import { UpdateViewInput } from 'src/engine/core-modules/view/dtos/inputs/update-view.input';
|
||||
@@ -36,7 +37,6 @@ import { type IDataloaders } from 'src/engine/dataloaders/dataloader.interface';
|
||||
import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator';
|
||||
import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard';
|
||||
import { resolveObjectMetadataStandardOverride } from 'src/engine/metadata-modules/object-metadata/utils/resolve-object-metadata-standard-override.util';
|
||||
import { I18nService } from 'src/engine/core-modules/i18n/i18n.service';
|
||||
|
||||
@Resolver(() => ViewDTO)
|
||||
@UseFilters(ViewGraphqlApiExceptionFilter)
|
||||
@@ -161,7 +161,7 @@ export class ViewResolver {
|
||||
|
||||
if (isWorkspaceMigrationV2Enabled) {
|
||||
return await this.viewV2Service.updateOne({
|
||||
updateViewInput: input,
|
||||
updateViewInput: { ...input, id },
|
||||
workspaceId: workspace.id,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -281,17 +281,6 @@ export class ViewV2Service {
|
||||
);
|
||||
}
|
||||
|
||||
const { flatViewMaps: recomputedExistingFlatViewMaps } =
|
||||
await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatEntities: ['flatViewMaps'],
|
||||
},
|
||||
);
|
||||
|
||||
return findFlatEntityByIdInFlatEntityMapsOrThrow({
|
||||
flatEntityId: destroyViewInput.id,
|
||||
flatEntityMaps: recomputedExistingFlatViewMaps,
|
||||
});
|
||||
return flatViewFromDestroyInput;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,7 +337,6 @@ export class DataloaderService {
|
||||
>(async (dataLoaderParams: IndexFieldMetadataLoaderPayload[]) => {
|
||||
const workspaceId = dataLoaderParams[0].workspaceId;
|
||||
|
||||
// This computes the old cache :thinking:
|
||||
const { objectMetadataMaps } =
|
||||
await this.workspaceMetadataCacheService.getExistingOrRecomputeMetadataMaps(
|
||||
{ workspaceId },
|
||||
|
||||
+2
-2
@@ -381,9 +381,9 @@ export class FieldMetadataServiceV2 {
|
||||
|
||||
return this.fieldMetadataRepository.find({
|
||||
where: {
|
||||
name: In(
|
||||
id: In(
|
||||
allTranspiledTranspilationInputs.map(
|
||||
({ result: { flatFieldMetadatas } }) => flatFieldMetadatas[0].name,
|
||||
({ result: { flatFieldMetadatas } }) => flatFieldMetadatas[0].id,
|
||||
),
|
||||
),
|
||||
workspaceId,
|
||||
|
||||
+1
-18
@@ -1,16 +1,13 @@
|
||||
import diff from 'microdiff';
|
||||
import { type FromTo } from 'twenty-shared/types';
|
||||
import { isDefined, parseJson } from 'twenty-shared/utils';
|
||||
import { parseJson } from 'twenty-shared/utils';
|
||||
|
||||
import { FLAT_FIELD_METADATA_JSONB_PROPERTIES } from 'src/engine/metadata-modules/flat-field-metadata/constants/flat-field-metadata-jsonb-properties.constant';
|
||||
import { FLAT_FIELD_METADATA_PROPERTIES_TO_COMPARE } from 'src/engine/metadata-modules/flat-field-metadata/constants/flat-field-metadata-properties-to-compare.constant';
|
||||
import { FLAT_FIELD_METADATA_RELATION_PROPERTIES_TO_COMPARE } from 'src/engine/metadata-modules/flat-field-metadata/constants/flat-field-metadata-relation-properties-to-compare.constant';
|
||||
import { type FlatFieldMetadataPropertiesToCompare } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata-properties-to-compare.type';
|
||||
import { type FlatFieldMetadataRelationPropertiesToCompare } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata-relation-properties-to-compare.type';
|
||||
import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
import { isFlatFieldMetadataJsonbProperty } from 'src/engine/metadata-modules/flat-field-metadata/utils/is-flat-field-metadata-jsonb-property.util';
|
||||
import { isStandardMetadata } from 'src/engine/metadata-modules/utils/is-standard-metadata.util';
|
||||
import { isMorphOrRelationFieldMetadataType } from 'src/engine/utils/is-morph-or-relation-field-metadata-type.util';
|
||||
import { type UpdateFieldAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-field-action-v2';
|
||||
import { transformMetadataForComparison } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/utils/transform-metadata-for-comparison.util';
|
||||
|
||||
@@ -38,20 +35,6 @@ export const compareTwoFlatFieldMetadata = ({
|
||||
return true;
|
||||
}
|
||||
|
||||
// Remove below assertion when we authorize relation edition, see https://github.com/twentyhq/twenty/commit/39f6f3c4bb101272a9014e142a842d0801a3c33b
|
||||
const isMorphOrRelationFieldType =
|
||||
isDefined(fieldMetadata.type) &&
|
||||
isMorphOrRelationFieldMetadataType(fieldMetadata.type);
|
||||
|
||||
if (
|
||||
isMorphOrRelationFieldType &&
|
||||
!FLAT_FIELD_METADATA_RELATION_PROPERTIES_TO_COMPARE.includes(
|
||||
property as FlatFieldMetadataRelationPropertiesToCompare,
|
||||
)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (
|
||||
isStandardMetadata(fieldMetadata) &&
|
||||
property !== 'standardOverrides'
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ export const validateRelationCreationPayload = async ({
|
||||
status: 'fail',
|
||||
error: {
|
||||
code: FieldMetadataExceptionCode.FIELD_METADATA_RELATION_MALFORMED,
|
||||
message: `Relation creation payload is invalid ${JSON.stringify(relationCreationPayload)}`,
|
||||
message: `Relation creation payload is invalid`,
|
||||
userFriendlyMessage: t`Invalid relation creation payload`,
|
||||
value: relationCreationPayload,
|
||||
},
|
||||
|
||||
+61
-1
@@ -1,7 +1,10 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
|
||||
import { t } from '@lingui/core/macro';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import {
|
||||
isDefined,
|
||||
isLabelIdentifierFieldMetadataTypes,
|
||||
} from 'twenty-shared/utils';
|
||||
|
||||
import { FlatFieldMetadataValidatorService } from 'src/engine/metadata-modules/flat-field-metadata/services/flat-field-metadata-validator.service';
|
||||
import { FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type';
|
||||
@@ -73,6 +76,12 @@ export class FlatObjectMetadataValidatorService {
|
||||
...validateFlatObjectMetadataIdentifiers(existingFlatObjectMetadata),
|
||||
);
|
||||
|
||||
validationResult.errors.push(
|
||||
...this.validateFlatObjectMetadataLabelIdentifierFieldMetadataId({
|
||||
flatObjectMetadata: updatedFlatObjectMetadata,
|
||||
}),
|
||||
);
|
||||
|
||||
return validationResult;
|
||||
}
|
||||
|
||||
@@ -188,6 +197,12 @@ export class FlatObjectMetadataValidatorService {
|
||||
});
|
||||
}
|
||||
|
||||
objectValidationResult.errors.push(
|
||||
...this.validateFlatObjectMetadataLabelIdentifierFieldMetadataId({
|
||||
flatObjectMetadata: flatObjectMetadataToValidate,
|
||||
}),
|
||||
);
|
||||
|
||||
objectValidationResult.errors.push(
|
||||
...this.validateFlatObjectMetadataNameAndLabels({
|
||||
existingFlatObjectMetadataMaps,
|
||||
@@ -295,4 +310,49 @@ export class FlatObjectMetadataValidatorService {
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
private validateFlatObjectMetadataLabelIdentifierFieldMetadataId({
|
||||
flatObjectMetadata,
|
||||
}: {
|
||||
flatObjectMetadata: FlatObjectMetadata;
|
||||
}) {
|
||||
const errors: FlatObjectMetadataValidationError[] = [];
|
||||
|
||||
if (!isDefined(flatObjectMetadata.labelIdentifierFieldMetadataId)) {
|
||||
errors.push({
|
||||
code: ObjectMetadataExceptionCode.MISSING_CUSTOM_OBJECT_DEFAULT_LABEL_IDENTIFIER_FIELD,
|
||||
message: t`Label identifier field metadata is required`,
|
||||
userFriendlyMessage: t`Label identifier field metadata is required`,
|
||||
});
|
||||
} else {
|
||||
const relatedFlatFieldMetadata =
|
||||
flatObjectMetadata.flatFieldMetadatas.find(
|
||||
(flatFieldMetadata) =>
|
||||
flatFieldMetadata.id ===
|
||||
flatObjectMetadata.labelIdentifierFieldMetadataId,
|
||||
);
|
||||
|
||||
if (!relatedFlatFieldMetadata) {
|
||||
errors.push({
|
||||
code: ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT,
|
||||
message: t`Label identifier field metadata not found in field metadata list`,
|
||||
userFriendlyMessage: t`Label identifier field metadata not found in field metadata list`,
|
||||
value: flatObjectMetadata.labelIdentifierFieldMetadataId,
|
||||
});
|
||||
} else {
|
||||
if (
|
||||
!isLabelIdentifierFieldMetadataTypes(relatedFlatFieldMetadata.type)
|
||||
) {
|
||||
errors.push({
|
||||
code: ObjectMetadataExceptionCode.INVALID_OBJECT_INPUT,
|
||||
message: t`Label identifier field metadata must be a TEXT or FULL_NAME field type`,
|
||||
userFriendlyMessage: t`Label identifier field metadata must be a TEXT or FULL_NAME field type`,
|
||||
value: relatedFlatFieldMetadata.type,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -68,7 +68,7 @@ export const fromDeleteObjectInputToFlatFieldMetadatasToDelete = ({
|
||||
},
|
||||
);
|
||||
|
||||
// We should maintain a idsByObjectMetadataId maps in the index
|
||||
// TODO We should maintain a idsByObjectMetadataId in the flatIndexMaps
|
||||
const flatIndexMetadataToDelete = Object.values(
|
||||
existingFlatIndexMaps.byId,
|
||||
).filter(
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ type RenameRelatedMorphFieldOnObjectNamesUpdateArgs = FromTo<
|
||||
> & {
|
||||
existingFlatObjectMetadataMaps: FlatObjectMetadataMaps;
|
||||
};
|
||||
// We should recompute each index here too ? YES TODO prastoin
|
||||
// TODO We should recompute each index here too
|
||||
export const renameRelatedMorphFieldOnObjectNamesUpdate = ({
|
||||
fromFlatObjectMetadata,
|
||||
existingFlatObjectMetadataMaps,
|
||||
|
||||
+2
-14
@@ -76,18 +76,6 @@ export class ObjectMetadataServiceV2 {
|
||||
flatIndexMaps: existingFlatIndexMaps,
|
||||
});
|
||||
|
||||
const impactedObjectMetadataIds = [
|
||||
...new Set([
|
||||
optimisticallyUpdatedFlatObjectMetadata.id,
|
||||
...otherObjectFlatFieldMetadatas.map(
|
||||
(flatFieldMetadata) => flatFieldMetadata.objectMetadataId,
|
||||
),
|
||||
]),
|
||||
];
|
||||
const fromFlatObjectMetadataMaps = getSubFlatObjectMetadataMapsOrThrow({
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
objectMetadataIds: impactedObjectMetadataIds,
|
||||
});
|
||||
const toFlatObjectMetadataMaps = otherObjectFlatFieldMetadatas.reduce(
|
||||
(flatObjectMetadataMaps, flatFieldMetadata) =>
|
||||
replaceFlatFieldMetadataInFlatObjectMetadataMapsOrThrow({
|
||||
@@ -96,7 +84,7 @@ export class ObjectMetadataServiceV2 {
|
||||
}),
|
||||
replaceFlatObjectMetadataInFlatObjectMetadataMapsOrThrow({
|
||||
flatObjectMetadata: optimisticallyUpdatedFlatObjectMetadata,
|
||||
flatObjectMetadataMaps: fromFlatObjectMetadataMaps,
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -114,7 +102,7 @@ export class ObjectMetadataServiceV2 {
|
||||
{
|
||||
fromToAllFlatEntityMaps: {
|
||||
flatObjectMetadataMaps: {
|
||||
from: fromFlatObjectMetadataMaps,
|
||||
from: existingFlatObjectMetadataMaps,
|
||||
to: toFlatObjectMetadataMaps,
|
||||
},
|
||||
flatIndexMaps: {
|
||||
|
||||
+1
-1
@@ -53,7 +53,7 @@ export const seedFeatureFlags = async (
|
||||
{
|
||||
key: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
workspaceId: workspaceId,
|
||||
value: false,
|
||||
value: true,
|
||||
},
|
||||
{
|
||||
key: FeatureFlagKey.IS_PAGE_LAYOUT_ENABLED,
|
||||
|
||||
+2
-1
@@ -83,7 +83,8 @@ export const serializeDefaultValueV2 = ({
|
||||
return `ARRAY[${arrayValues}]${castSuffix}[]`;
|
||||
}
|
||||
|
||||
return sanitizeAndAddCastPrefix(`'${JSON.stringify(defaultValue)}'`); // Won't work :thinking: at all will remove every brackets and so on
|
||||
// Default value for objects won't work with sanitization here
|
||||
return sanitizeAndAddCastPrefix(`'${JSON.stringify(defaultValue)}'`);
|
||||
}
|
||||
default: {
|
||||
throw new FieldMetadataException(
|
||||
|
||||
+14
@@ -5,11 +5,21 @@ import { createManyOperationFactory } from 'test/integration/graphql/utils/creat
|
||||
import { makeGraphqlAPIRequestWithApiKey } from 'test/integration/graphql/utils/make-graphql-api-request-with-api-key.util';
|
||||
import { makeGraphqlAPIRequestWithGuestRole } from 'test/integration/graphql/utils/make-graphql-api-request-with-guest-role.util';
|
||||
import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.util';
|
||||
import { deleteRecordsByIds } from 'test/integration/utils/delete-records-by-ids';
|
||||
|
||||
import { ErrorCode } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||
import { PermissionsExceptionMessage } from 'src/engine/metadata-modules/permissions/permissions.exception';
|
||||
|
||||
describe('createManyObjectRecordsPermissions', () => {
|
||||
let createdPersonIds: string[] = [];
|
||||
|
||||
afterEach(async () => {
|
||||
if (createdPersonIds.length > 0) {
|
||||
await deleteRecordsByIds('person', createdPersonIds);
|
||||
createdPersonIds = [];
|
||||
}
|
||||
});
|
||||
|
||||
it('should throw a permission error when user does not have permission (guest role)', async () => {
|
||||
const graphqlOperation = createManyOperationFactory({
|
||||
objectMetadataSingularName: 'person',
|
||||
@@ -55,6 +65,8 @@ describe('createManyObjectRecordsPermissions', () => {
|
||||
|
||||
const response = await makeGraphqlAPIRequest(graphqlOperation);
|
||||
|
||||
createdPersonIds.push(personId1, personId2);
|
||||
|
||||
expect(response.body.data).toBeDefined();
|
||||
expect(response.body.data.createPeople).toBeDefined();
|
||||
expect(response.body.data.createPeople).toHaveLength(2);
|
||||
@@ -88,6 +100,8 @@ describe('createManyObjectRecordsPermissions', () => {
|
||||
|
||||
const response = await makeGraphqlAPIRequestWithApiKey(graphqlOperation);
|
||||
|
||||
createdPersonIds.push(personId1, personId2);
|
||||
|
||||
expect(response.body.data).toBeDefined();
|
||||
expect(response.body.data.createPeople).toBeDefined();
|
||||
expect(response.body.data.createPeople).toHaveLength(2);
|
||||
|
||||
+14
@@ -5,11 +5,21 @@ import { createOneOperationFactory } from 'test/integration/graphql/utils/create
|
||||
import { makeGraphqlAPIRequestWithApiKey } from 'test/integration/graphql/utils/make-graphql-api-request-with-api-key.util';
|
||||
import { makeGraphqlAPIRequestWithGuestRole } from 'test/integration/graphql/utils/make-graphql-api-request-with-guest-role.util';
|
||||
import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.util';
|
||||
import { deleteRecordsByIds } from 'test/integration/utils/delete-records-by-ids';
|
||||
|
||||
import { ErrorCode } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||
import { PermissionsExceptionMessage } from 'src/engine/metadata-modules/permissions/permissions.exception';
|
||||
|
||||
describe('createOneObjectRecordsPermissions', () => {
|
||||
let createdPersonIds: string[] = [];
|
||||
|
||||
afterEach(async () => {
|
||||
if (createdPersonIds.length > 0) {
|
||||
await deleteRecordsByIds('person', createdPersonIds);
|
||||
createdPersonIds = [];
|
||||
}
|
||||
});
|
||||
|
||||
it('should throw a permission error when user does not have permission (guest role)', async () => {
|
||||
const graphqlOperation = createOneOperationFactory({
|
||||
objectMetadataSingularName: 'person',
|
||||
@@ -41,6 +51,8 @@ describe('createOneObjectRecordsPermissions', () => {
|
||||
|
||||
const response = await makeGraphqlAPIRequest(graphqlOperation);
|
||||
|
||||
createdPersonIds.push(personId);
|
||||
|
||||
expect(response.body.data).toBeDefined();
|
||||
expect(response.body.data.createPerson).toBeDefined();
|
||||
expect(response.body.data.createPerson.id).toBe(personId);
|
||||
@@ -58,6 +70,8 @@ describe('createOneObjectRecordsPermissions', () => {
|
||||
|
||||
const response = await makeGraphqlAPIRequestWithApiKey(graphqlOperation);
|
||||
|
||||
createdPersonIds.push(personId);
|
||||
|
||||
expect(response.body.data).toBeDefined();
|
||||
expect(response.body.data.createPerson).toBeDefined();
|
||||
expect(response.body.data.createPerson.id).toBe(personId);
|
||||
|
||||
+12
@@ -6,11 +6,21 @@ import { deleteManyOperationFactory } from 'test/integration/graphql/utils/delet
|
||||
import { makeGraphqlAPIRequestWithApiKey } from 'test/integration/graphql/utils/make-graphql-api-request-with-api-key.util';
|
||||
import { makeGraphqlAPIRequestWithGuestRole } from 'test/integration/graphql/utils/make-graphql-api-request-with-guest-role.util';
|
||||
import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.util';
|
||||
import { deleteRecordsByIds } from 'test/integration/utils/delete-records-by-ids';
|
||||
|
||||
import { ErrorCode } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||
import { PermissionsExceptionMessage } from 'src/engine/metadata-modules/permissions/permissions.exception';
|
||||
|
||||
describe('deleteManyObjectRecordsPermissions', () => {
|
||||
let createdPersonIds: string[] = [];
|
||||
|
||||
afterEach(async () => {
|
||||
if (createdPersonIds.length > 0) {
|
||||
await deleteRecordsByIds('person', createdPersonIds);
|
||||
createdPersonIds = [];
|
||||
}
|
||||
});
|
||||
|
||||
it('should throw a permission error when user does not have permission (guest role)', async () => {
|
||||
const graphqlOperation = deleteManyOperationFactory({
|
||||
objectMetadataSingularName: 'person',
|
||||
@@ -52,6 +62,7 @@ describe('deleteManyObjectRecordsPermissions', () => {
|
||||
});
|
||||
|
||||
await makeGraphqlAPIRequest(createGraphqlOperation);
|
||||
createdPersonIds.push(personId1, personId2);
|
||||
|
||||
const deleteGraphqlOperation = deleteManyOperationFactory({
|
||||
objectMetadataSingularName: 'person',
|
||||
@@ -96,6 +107,7 @@ describe('deleteManyObjectRecordsPermissions', () => {
|
||||
});
|
||||
|
||||
await makeGraphqlAPIRequest(createGraphqlOperation);
|
||||
createdPersonIds.push(personId1, personId2);
|
||||
|
||||
const deleteGraphqlOperation = deleteManyOperationFactory({
|
||||
objectMetadataSingularName: 'person',
|
||||
|
||||
+13
@@ -6,11 +6,21 @@ import { makeGraphqlAPIRequestWithApiKey } from 'test/integration/graphql/utils/
|
||||
import { makeGraphqlAPIRequestWithGuestRole } from 'test/integration/graphql/utils/make-graphql-api-request-with-guest-role.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 { deleteRecordsByIds } from 'test/integration/utils/delete-records-by-ids';
|
||||
|
||||
import { ErrorCode } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||
import { PermissionsExceptionMessage } from 'src/engine/metadata-modules/permissions/permissions.exception';
|
||||
|
||||
describe('updateManyObjectRecordsPermissions', () => {
|
||||
let createdPersonIds: string[] = [];
|
||||
|
||||
afterEach(async () => {
|
||||
if (createdPersonIds.length > 0) {
|
||||
await deleteRecordsByIds('person', createdPersonIds);
|
||||
createdPersonIds = [];
|
||||
}
|
||||
});
|
||||
|
||||
it('should throw a permission error when user does not have permission (guest role)', async () => {
|
||||
const personId1 = randomUUID();
|
||||
const personId2 = randomUUID();
|
||||
@@ -29,6 +39,7 @@ describe('updateManyObjectRecordsPermissions', () => {
|
||||
});
|
||||
|
||||
await makeGraphqlAPIRequest(createGraphqlOperation);
|
||||
createdPersonIds.push(personId1, personId2);
|
||||
|
||||
const updateGraphqlOperation = updateManyOperationFactory({
|
||||
objectMetadataSingularName: 'person',
|
||||
@@ -74,6 +85,7 @@ describe('updateManyObjectRecordsPermissions', () => {
|
||||
});
|
||||
|
||||
await makeGraphqlAPIRequest(createGraphqlOperation);
|
||||
createdPersonIds.push(personId1, personId2);
|
||||
|
||||
const updateGraphqlOperation = updateManyOperationFactory({
|
||||
objectMetadataSingularName: 'person',
|
||||
@@ -118,6 +130,7 @@ describe('updateManyObjectRecordsPermissions', () => {
|
||||
});
|
||||
|
||||
await makeGraphqlAPIRequest(createGraphqlOperation);
|
||||
createdPersonIds.push(personId1, personId2);
|
||||
|
||||
const updateGraphqlOperation = updateManyOperationFactory({
|
||||
objectMetadataSingularName: 'person',
|
||||
|
||||
+19
@@ -15,6 +15,7 @@ import { restorePageLayoutOperationFactory } from 'test/integration/graphql/util
|
||||
import { updatePageLayoutOperationFactory } from 'test/integration/graphql/utils/update-page-layout-operation-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 {
|
||||
assertPageLayoutStructure,
|
||||
cleanupPageLayoutRecords,
|
||||
@@ -49,6 +50,15 @@ describe('Page Layout Resolver', () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: testObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: testObjectMetadataId },
|
||||
});
|
||||
@@ -122,6 +132,15 @@ describe('Page Layout Resolver', () => {
|
||||
objectMetadataId: testObjectMetadataId,
|
||||
});
|
||||
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: objectMetadata2Id,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: objectMetadata2Id },
|
||||
});
|
||||
|
||||
+10
@@ -22,6 +22,7 @@ import { restorePageLayoutTabOperationFactory } from 'test/integration/graphql/u
|
||||
import { updatePageLayoutTabOperationFactory } from 'test/integration/graphql/utils/update-page-layout-tab-operation-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 { assertPageLayoutTabStructure } from 'test/integration/utils/page-layout-tab-test.util';
|
||||
|
||||
import { ErrorCode } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||
@@ -63,6 +64,15 @@ describe('Page Layout Tab Resolver', () => {
|
||||
|
||||
afterAll(async () => {
|
||||
await cleanupPageLayoutRecordsWithGraphQL();
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: testObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: testObjectMetadataId },
|
||||
});
|
||||
|
||||
+10
@@ -14,6 +14,7 @@ import {
|
||||
cleanupPageLayoutRecords,
|
||||
} from 'test/integration/utils/page-layout-test.util';
|
||||
import { cleanupPageLayoutWidgetRecords } from 'test/integration/utils/page-layout-widget-test.util';
|
||||
import { updateOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata.util';
|
||||
|
||||
import { ErrorCode } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||
import { type PageLayoutEntity } from 'src/engine/core-modules/page-layout/entities/page-layout.entity';
|
||||
@@ -53,6 +54,15 @@ describe('Page Layout Update With Tabs And Widgets Integration', () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
input: {
|
||||
idToUpdate: testObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: testObjectMetadataId },
|
||||
});
|
||||
|
||||
+10
@@ -23,6 +23,7 @@ import { restorePageLayoutWidgetOperationFactory } from 'test/integration/graphq
|
||||
import { updatePageLayoutWidgetOperationFactory } from 'test/integration/graphql/utils/update-page-layout-widget-operation-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 { assertPageLayoutWidgetStructure } from 'test/integration/utils/page-layout-widget-test.util';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
@@ -76,6 +77,15 @@ describe('Page Layout Widget Resolver', () => {
|
||||
|
||||
afterAll(async () => {
|
||||
await cleanupPageLayoutRecordsWithGraphQL();
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: testObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: testObjectMetadataId },
|
||||
});
|
||||
|
||||
+19
@@ -7,6 +7,7 @@ import { createOneObjectMetadata } from 'test/integration/metadata/suites/object
|
||||
import { deleteOneObjectMetadataQueryFactory } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata-query-factory.util';
|
||||
import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util';
|
||||
import { updateOneObjectMetadataQueryFactory } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata-query-factory.util';
|
||||
import { updateOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata.util';
|
||||
import { makeMetadataAPIRequestWithMemberRole } from 'test/integration/metadata/suites/utils/make-metadata-api-request-with-member-role.util';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
@@ -43,6 +44,15 @@ describe('datamodel permissions', () => {
|
||||
testFieldId = createdFieldData.createOneField.id;
|
||||
});
|
||||
afterAll(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: listingObjectId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: listingObjectId },
|
||||
});
|
||||
@@ -184,6 +194,15 @@ describe('datamodel permissions', () => {
|
||||
listingObjectId = data.createOneObject.id;
|
||||
});
|
||||
afterAll(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: listingObjectId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: listingObjectId },
|
||||
});
|
||||
|
||||
+10
@@ -2,6 +2,7 @@ import request from 'supertest';
|
||||
import { deleteOneRoleOperationFactory } from 'test/integration/graphql/utils/delete-one-role-operation-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 { fieldTextMock } from 'src/engine/api/__mocks__/object-metadata-item.mock';
|
||||
import { ErrorCode } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||
@@ -466,6 +467,15 @@ describe('roles permissions', () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: listingObjectId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: listingObjectId },
|
||||
|
||||
+10
@@ -3,6 +3,7 @@ import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graph
|
||||
import { createOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/create-one-field-metadata.util';
|
||||
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
|
||||
import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util';
|
||||
import { updateOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata.util';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
const createRecordsQuery = gql`
|
||||
@@ -88,6 +89,15 @@ describe('upsert (createMany with upsert:true)', () => {
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: createdObjectMetadataId },
|
||||
});
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Delete core view should throw an error when deleting non-existent view 1`] = `
|
||||
{
|
||||
"extensions": {
|
||||
"code": "NOT_FOUND",
|
||||
"userFriendlyMessage": "An error occurred.",
|
||||
},
|
||||
"message": "View to delete not found",
|
||||
"name": "NotFoundError",
|
||||
}
|
||||
`;
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Destroy core view should throw an error when destroying non-existent view 1`] = `
|
||||
{
|
||||
"extensions": {
|
||||
"code": "NOT_FOUND",
|
||||
"userFriendlyMessage": "An error occurred.",
|
||||
},
|
||||
"message": "View to destroy not found",
|
||||
"name": "NotFoundError",
|
||||
}
|
||||
`;
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Update core view should throw error when updating non-existent view 1`] = `
|
||||
{
|
||||
"extensions": {
|
||||
"code": "NOT_FOUND",
|
||||
"userFriendlyMessage": "An error occurred.",
|
||||
},
|
||||
"message": "View to update not found",
|
||||
"name": "NotFoundError",
|
||||
}
|
||||
`;
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
import { assertGraphQLSuccessfulResponse } from 'test/integration/graphql/utils/graphql-test-assertions.util';
|
||||
import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.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 {
|
||||
assertViewStructure,
|
||||
cleanupViewRecords,
|
||||
} from 'test/integration/utils/view-test.util';
|
||||
import { createViewOperationFactory } from 'test/integration/graphql/utils/create-view-operation-factory.util';
|
||||
|
||||
import { ViewOpenRecordIn } from 'src/engine/core-modules/view/enums/view-open-record-in';
|
||||
import { ViewType } from 'src/engine/core-modules/view/enums/view-type.enum';
|
||||
|
||||
describe('Create core view', () => {
|
||||
let testObjectMetadataId: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
const {
|
||||
data: {
|
||||
createOneObject: { id: objectMetadataId },
|
||||
},
|
||||
} = await createOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
nameSingular: 'myViewTestObject',
|
||||
namePlural: 'myViewTestObjects',
|
||||
labelSingular: 'My View Test Object',
|
||||
labelPlural: 'My View Test Objects',
|
||||
icon: 'Icon123',
|
||||
},
|
||||
});
|
||||
|
||||
testObjectMetadataId = objectMetadataId;
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: testObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: testObjectMetadataId },
|
||||
});
|
||||
await cleanupViewRecords();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await cleanupViewRecords();
|
||||
});
|
||||
|
||||
it('should create a new view with all properties', async () => {
|
||||
const input = {
|
||||
name: 'Kanban View',
|
||||
objectMetadataId: testObjectMetadataId,
|
||||
icon: 'IconDeal',
|
||||
type: ViewType.KANBAN,
|
||||
key: null,
|
||||
position: 1,
|
||||
isCompact: true,
|
||||
openRecordIn: ViewOpenRecordIn.SIDE_PANEL,
|
||||
};
|
||||
|
||||
const operation = createViewOperationFactory({ data: input });
|
||||
const response = await makeGraphqlAPIRequest(operation);
|
||||
|
||||
assertGraphQLSuccessfulResponse(response);
|
||||
assertViewStructure(response.body.data.createCoreView, {
|
||||
name: input.name,
|
||||
objectMetadataId: input.objectMetadataId,
|
||||
type: input.type,
|
||||
key: null,
|
||||
icon: input.icon,
|
||||
position: input.position,
|
||||
isCompact: input.isCompact,
|
||||
openRecordIn: input.openRecordIn,
|
||||
});
|
||||
});
|
||||
|
||||
it('should create a view with minimum required fields', async () => {
|
||||
const input = {
|
||||
name: 'Minimal View',
|
||||
objectMetadataId: testObjectMetadataId,
|
||||
icon: 'IconList',
|
||||
};
|
||||
|
||||
const operation = createViewOperationFactory({ data: input });
|
||||
const response = await makeGraphqlAPIRequest(operation);
|
||||
|
||||
assertGraphQLSuccessfulResponse(response);
|
||||
assertViewStructure(response.body.data.createCoreView, {
|
||||
name: input.name,
|
||||
objectMetadataId: input.objectMetadataId,
|
||||
icon: input.icon,
|
||||
type: ViewType.TABLE,
|
||||
key: null,
|
||||
position: 0,
|
||||
isCompact: false,
|
||||
openRecordIn: ViewOpenRecordIn.SIDE_PANEL,
|
||||
});
|
||||
});
|
||||
});
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
import { TEST_NOT_EXISTING_VIEW_ID } from 'test/integration/constants/test-view-ids.constants';
|
||||
import { deleteViewOperationFactory } from 'test/integration/graphql/utils/delete-view-operation-factory.util';
|
||||
import { findViewOperationFactory } from 'test/integration/graphql/utils/find-view-operation-factory.util';
|
||||
import {
|
||||
assertGraphQLErrorResponseWithSnapshot,
|
||||
assertGraphQLSuccessfulResponse,
|
||||
} from 'test/integration/graphql/utils/graphql-test-assertions.util';
|
||||
import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.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 { cleanupViewRecords } from 'test/integration/utils/view-test.util';
|
||||
import { createOneCoreView } from 'test/integration/metadata/suites/view/utils/create-one-core-view.util';
|
||||
|
||||
describe('Delete core view', () => {
|
||||
let testObjectMetadataId: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
const {
|
||||
data: {
|
||||
createOneObject: { id: objectMetadataId },
|
||||
},
|
||||
} = await createOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
nameSingular: 'myViewTestObject',
|
||||
namePlural: 'myViewTestObjects',
|
||||
labelSingular: 'My View Test Object',
|
||||
labelPlural: 'My View Test Objects',
|
||||
icon: 'Icon123',
|
||||
},
|
||||
});
|
||||
|
||||
testObjectMetadataId = objectMetadataId;
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: testObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: testObjectMetadataId },
|
||||
});
|
||||
await cleanupViewRecords();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await cleanupViewRecords();
|
||||
});
|
||||
|
||||
it('should delete an existing view', async () => {
|
||||
const {
|
||||
data: { createCoreView: view },
|
||||
} = await createOneCoreView({
|
||||
input: {
|
||||
name: 'View to Delete',
|
||||
objectMetadataId: testObjectMetadataId,
|
||||
icon: '123Icon',
|
||||
},
|
||||
expectToFail: false,
|
||||
});
|
||||
|
||||
const deleteOperation = deleteViewOperationFactory({ viewId: view.id });
|
||||
const deleteResponse = await makeGraphqlAPIRequest(deleteOperation);
|
||||
|
||||
assertGraphQLSuccessfulResponse(deleteResponse);
|
||||
expect(deleteResponse.body.data.deleteCoreView).toBe(true);
|
||||
|
||||
const getOperation = findViewOperationFactory({ viewId: view.id });
|
||||
const getResponse = await makeGraphqlAPIRequest(getOperation);
|
||||
|
||||
expect(getResponse.body.data.getCoreView).toBeNull();
|
||||
});
|
||||
|
||||
it('should throw an error when deleting non-existent view', async () => {
|
||||
const operation = deleteViewOperationFactory({
|
||||
viewId: TEST_NOT_EXISTING_VIEW_ID,
|
||||
});
|
||||
const response = await makeGraphqlAPIRequest(operation);
|
||||
|
||||
assertGraphQLErrorResponseWithSnapshot(response);
|
||||
});
|
||||
});
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
import { TEST_NOT_EXISTING_VIEW_ID } from 'test/integration/constants/test-view-ids.constants';
|
||||
import { deleteViewOperationFactory } from 'test/integration/graphql/utils/delete-view-operation-factory.util';
|
||||
import { destroyViewOperationFactory } from 'test/integration/graphql/utils/destroy-view-operation-factory.util';
|
||||
import { findViewOperationFactory } from 'test/integration/graphql/utils/find-view-operation-factory.util';
|
||||
import {
|
||||
assertGraphQLErrorResponseWithSnapshot,
|
||||
assertGraphQLSuccessfulResponse,
|
||||
} from 'test/integration/graphql/utils/graphql-test-assertions.util';
|
||||
import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.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 { cleanupViewRecords } from 'test/integration/utils/view-test.util';
|
||||
import { createOneCoreView } from 'test/integration/metadata/suites/view/utils/create-one-core-view.util';
|
||||
|
||||
describe('Destroy core view', () => {
|
||||
let testObjectMetadataId: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
const {
|
||||
data: {
|
||||
createOneObject: { id: objectMetadataId },
|
||||
},
|
||||
} = await createOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
nameSingular: 'myViewTestObject',
|
||||
namePlural: 'myViewTestObjects',
|
||||
labelSingular: 'My View Test Object',
|
||||
labelPlural: 'My View Test Objects',
|
||||
icon: 'Icon123',
|
||||
},
|
||||
});
|
||||
|
||||
testObjectMetadataId = objectMetadataId;
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: testObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: testObjectMetadataId },
|
||||
});
|
||||
await cleanupViewRecords();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await cleanupViewRecords();
|
||||
});
|
||||
|
||||
it('should destroy an existing view', async () => {
|
||||
const {
|
||||
data: { createCoreView: view },
|
||||
} = await createOneCoreView({
|
||||
input: {
|
||||
icon: '123Icon',
|
||||
name: 'View to Destroy',
|
||||
objectMetadataId: testObjectMetadataId,
|
||||
},
|
||||
expectToFail: false,
|
||||
});
|
||||
const deleteOperation = deleteViewOperationFactory({ viewId: view.id });
|
||||
const deleteResponse = await makeGraphqlAPIRequest(deleteOperation);
|
||||
|
||||
assertGraphQLSuccessfulResponse(deleteResponse);
|
||||
|
||||
const destroyOperation = destroyViewOperationFactory({ viewId: view.id });
|
||||
const destroyResponse = await makeGraphqlAPIRequest(destroyOperation);
|
||||
|
||||
assertGraphQLSuccessfulResponse(destroyResponse);
|
||||
expect(destroyResponse.body.data.destroyCoreView).toBe(true);
|
||||
|
||||
const getOperation = findViewOperationFactory({ viewId: view.id });
|
||||
const getResponse = await makeGraphqlAPIRequest(getOperation);
|
||||
|
||||
expect(getResponse.body.data.getCoreView).toBeNull();
|
||||
});
|
||||
|
||||
it('should throw an error when destroying non-existent view', async () => {
|
||||
const operation = destroyViewOperationFactory({
|
||||
viewId: TEST_NOT_EXISTING_VIEW_ID,
|
||||
});
|
||||
const response = await makeGraphqlAPIRequest(operation);
|
||||
|
||||
assertGraphQLErrorResponseWithSnapshot(response);
|
||||
});
|
||||
});
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
import { TEST_NOT_EXISTING_VIEW_ID } from 'test/integration/constants/test-view-ids.constants';
|
||||
import {
|
||||
assertGraphQLErrorResponseWithSnapshot,
|
||||
assertGraphQLSuccessfulResponse,
|
||||
} from 'test/integration/graphql/utils/graphql-test-assertions.util';
|
||||
import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.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 { cleanupViewRecords } from 'test/integration/utils/view-test.util';
|
||||
import { updateViewOperationFactory } from 'test/integration/graphql/utils/update-view-operation-factory.util';
|
||||
import { updateViewData } from 'test/integration/graphql/utils/view-data-factory.util';
|
||||
import { createOneCoreView } from 'test/integration/metadata/suites/view/utils/create-one-core-view.util';
|
||||
|
||||
import { ViewType } from 'src/engine/core-modules/view/enums/view-type.enum';
|
||||
|
||||
describe('Update core view', () => {
|
||||
let testObjectMetadataId: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
const {
|
||||
data: {
|
||||
createOneObject: { id: objectMetadataId },
|
||||
},
|
||||
} = await createOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
nameSingular: 'myViewTestObject',
|
||||
namePlural: 'myViewTestObjects',
|
||||
labelSingular: 'My View Test Object',
|
||||
labelPlural: 'My View Test Objects',
|
||||
icon: 'Icon123',
|
||||
},
|
||||
});
|
||||
|
||||
testObjectMetadataId = objectMetadataId;
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: testObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: testObjectMetadataId },
|
||||
});
|
||||
await cleanupViewRecords();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await cleanupViewRecords();
|
||||
});
|
||||
|
||||
it('should update an existing view', async () => {
|
||||
const {
|
||||
data: { createCoreView: view },
|
||||
} = await createOneCoreView({
|
||||
input: {
|
||||
icon: '123Icon',
|
||||
name: 'Original View',
|
||||
type: ViewType.TABLE,
|
||||
isCompact: false,
|
||||
objectMetadataId: testObjectMetadataId,
|
||||
},
|
||||
expectToFail: false,
|
||||
});
|
||||
|
||||
const updateInput = updateViewData({
|
||||
name: 'Updated View',
|
||||
type: ViewType.KANBAN,
|
||||
isCompact: true,
|
||||
});
|
||||
|
||||
const operation = updateViewOperationFactory({
|
||||
viewId: view.id,
|
||||
data: updateInput,
|
||||
});
|
||||
const response = await makeGraphqlAPIRequest(operation);
|
||||
|
||||
assertGraphQLSuccessfulResponse(response);
|
||||
expect(response.body.data.updateCoreView).toMatchObject({
|
||||
id: view.id,
|
||||
...updateInput,
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw error when updating non-existent view', async () => {
|
||||
const operation = updateViewOperationFactory({
|
||||
viewId: TEST_NOT_EXISTING_VIEW_ID,
|
||||
data: { name: 'Non-existent View' },
|
||||
});
|
||||
const response = await makeGraphqlAPIRequest(operation);
|
||||
|
||||
assertGraphQLErrorResponseWithSnapshot(response);
|
||||
});
|
||||
});
|
||||
+12
-29
@@ -2,11 +2,8 @@ import { createOneFieldMetadata } from 'test/integration/metadata/suites/field-m
|
||||
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 { createOneCoreView } from 'test/integration/metadata/suites/view/utils/create-one-core-view.util';
|
||||
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
export type ViewFieldTestSetup = {
|
||||
testViewId: string;
|
||||
@@ -15,12 +12,6 @@ export type ViewFieldTestSetup = {
|
||||
};
|
||||
|
||||
export const setupViewFieldTestV2 = async (): Promise<ViewFieldTestSetup> => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: true,
|
||||
});
|
||||
|
||||
const {
|
||||
data: {
|
||||
createOneObject: { id: objectMetadataId },
|
||||
@@ -80,24 +71,16 @@ export const setupViewFieldTestV2 = async (): Promise<ViewFieldTestSetup> => {
|
||||
export const cleanupViewFieldTestV2 = async (
|
||||
objectMetadataId: string,
|
||||
): Promise<void> => {
|
||||
try {
|
||||
await updateOneObjectMetadata({
|
||||
input: {
|
||||
idToUpdate: objectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
await updateOneObjectMetadata({
|
||||
input: {
|
||||
idToUpdate: objectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: objectMetadataId },
|
||||
});
|
||||
} finally {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: false,
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: objectMetadataId },
|
||||
});
|
||||
};
|
||||
|
||||
+34
-6
@@ -13,28 +13,39 @@ import { createTestViewWithGraphQL } from 'test/integration/graphql/utils/view-g
|
||||
import { createOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/create-one-field-metadata.util';
|
||||
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
|
||||
import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util';
|
||||
import { 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 { createOneCoreViewField } from 'test/integration/metadata/suites/view-field/utils/create-one-core-view-field.util';
|
||||
import { deleteOneCoreViewField } from 'test/integration/metadata/suites/view-field/utils/delete-one-core-view-field.util';
|
||||
import { destroyOneCoreViewField } from 'test/integration/metadata/suites/view-field/utils/destroy-one-core-view-field.util';
|
||||
import { updateOneCoreViewField } from 'test/integration/metadata/suites/view-field/utils/update-one-core-view-field.util';
|
||||
import {
|
||||
assertViewFieldStructure,
|
||||
cleanupViewRecords,
|
||||
} from 'test/integration/utils/view-test.util';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { createOneCoreViewField } from 'test/integration/metadata/suites/view-field/utils/create-one-core-view-field.util';
|
||||
import { deleteOneCoreViewField } from 'test/integration/metadata/suites/view-field/utils/delete-one-core-view-field.util';
|
||||
import { destroyOneCoreViewField } from 'test/integration/metadata/suites/view-field/utils/destroy-one-core-view-field.util';
|
||||
import { updateOneCoreViewField } from 'test/integration/metadata/suites/view-field/utils/update-one-core-view-field.util';
|
||||
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { ErrorCode } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||
import { type CreateViewFieldInput } from 'src/engine/core-modules/view/dtos/inputs/create-view-field.input';
|
||||
import {
|
||||
generateViewFieldExceptionMessage,
|
||||
ViewFieldExceptionMessageKey,
|
||||
} from 'src/engine/core-modules/view/exceptions/view-field.exception';
|
||||
import { type CreateViewFieldInput } from 'src/engine/core-modules/view/dtos/inputs/create-view-field.input';
|
||||
import { ErrorCode } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||
|
||||
describe('View Field Resolver', () => {
|
||||
let testViewId: string;
|
||||
let testObjectMetadataId: string;
|
||||
let testFieldMetadataId: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: false,
|
||||
});
|
||||
});
|
||||
|
||||
beforeAll(async () => {
|
||||
const {
|
||||
data: {
|
||||
@@ -80,6 +91,15 @@ describe('View Field Resolver', () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: testObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: testObjectMetadataId },
|
||||
@@ -87,6 +107,14 @@ describe('View Field Resolver', () => {
|
||||
await cleanupViewRecords();
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: true,
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await cleanupViewRecords();
|
||||
|
||||
|
||||
+10
@@ -17,6 +17,7 @@ import {
|
||||
import { createTestViewWithGraphQL } from 'test/integration/graphql/utils/view-graphql.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 {
|
||||
assertViewFilterGroupStructure,
|
||||
cleanupViewRecords,
|
||||
@@ -54,6 +55,15 @@ describe('View Filter Group Resolver', () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: testObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: testObjectMetadataId },
|
||||
|
||||
+10
@@ -14,6 +14,7 @@ import { createTestViewWithGraphQL } from 'test/integration/graphql/utils/view-g
|
||||
import { createOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/create-one-field-metadata.util';
|
||||
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
|
||||
import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util';
|
||||
import { updateOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata.util';
|
||||
import {
|
||||
assertViewFilterStructure,
|
||||
cleanupViewRecords,
|
||||
@@ -69,6 +70,15 @@ describe('View Filter Resolver', () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: testObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: testObjectMetadataId },
|
||||
|
||||
+10
@@ -17,6 +17,7 @@ import { createTestViewWithGraphQL } from 'test/integration/graphql/utils/view-g
|
||||
import { createOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/create-one-field-metadata.util';
|
||||
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
|
||||
import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util';
|
||||
import { updateOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata.util';
|
||||
import {
|
||||
assertViewGroupStructure,
|
||||
cleanupViewRecords,
|
||||
@@ -71,6 +72,15 @@ describe('View Group Resolver', () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: testObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: testObjectMetadataId },
|
||||
|
||||
-339
@@ -1,339 +0,0 @@
|
||||
import { TEST_NOT_EXISTING_VIEW_ID } from 'test/integration/constants/test-view-ids.constants';
|
||||
import { createViewOperationFactory } from 'test/integration/graphql/utils/create-view-operation-factory.util';
|
||||
import { deleteViewOperationFactory } from 'test/integration/graphql/utils/delete-view-operation-factory.util';
|
||||
import { destroyViewOperationFactory } from 'test/integration/graphql/utils/destroy-view-operation-factory.util';
|
||||
import { findViewOperationFactory } from 'test/integration/graphql/utils/find-view-operation-factory.util';
|
||||
import { findViewsOperationFactory } from 'test/integration/graphql/utils/find-views-operation-factory.util';
|
||||
import {
|
||||
assertGraphQLErrorResponse,
|
||||
assertGraphQLSuccessfulResponse,
|
||||
} from 'test/integration/graphql/utils/graphql-test-assertions.util';
|
||||
import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.util';
|
||||
import { updateViewOperationFactory } from 'test/integration/graphql/utils/update-view-operation-factory.util';
|
||||
import {
|
||||
createViewData,
|
||||
updateViewData,
|
||||
} from 'test/integration/graphql/utils/view-data-factory.util';
|
||||
import { createTestViewWithGraphQL } from 'test/integration/graphql/utils/view-graphql.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 {
|
||||
assertViewStructure,
|
||||
cleanupViewRecords,
|
||||
} from 'test/integration/utils/view-test.util';
|
||||
|
||||
import { ErrorCode } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||
import { ViewOpenRecordIn } from 'src/engine/core-modules/view/enums/view-open-record-in';
|
||||
import { ViewType } from 'src/engine/core-modules/view/enums/view-type.enum';
|
||||
import {
|
||||
ViewExceptionMessageKey,
|
||||
generateViewExceptionMessage,
|
||||
} from 'src/engine/core-modules/view/exceptions/view.exception';
|
||||
|
||||
describe('View Resolver', () => {
|
||||
let testObjectMetadataId: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
const {
|
||||
data: {
|
||||
createOneObject: { id: objectMetadataId },
|
||||
},
|
||||
} = await createOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
nameSingular: 'myViewTestObject',
|
||||
namePlural: 'myViewTestObjects',
|
||||
labelSingular: 'My View Test Object',
|
||||
labelPlural: 'My View Test Objects',
|
||||
icon: 'Icon123',
|
||||
},
|
||||
});
|
||||
|
||||
testObjectMetadataId = objectMetadataId;
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: testObjectMetadataId },
|
||||
});
|
||||
await cleanupViewRecords();
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
await cleanupViewRecords();
|
||||
});
|
||||
|
||||
describe('getCoreViews', () => {
|
||||
it('should return empty array when no views exist', async () => {
|
||||
const operation = findViewsOperationFactory();
|
||||
const response = await makeGraphqlAPIRequest(operation);
|
||||
|
||||
assertGraphQLSuccessfulResponse(response);
|
||||
expect(response.body.data.getCoreViews).toEqual([]);
|
||||
});
|
||||
|
||||
it('should return all views for workspace when no objectMetadataId provided', async () => {
|
||||
const viewName = 'Test View';
|
||||
|
||||
await createTestViewWithGraphQL({
|
||||
name: viewName,
|
||||
objectMetadataId: testObjectMetadataId,
|
||||
});
|
||||
|
||||
const viewData = createViewData({
|
||||
name: viewName,
|
||||
objectMetadataId: testObjectMetadataId,
|
||||
});
|
||||
|
||||
const operation = findViewsOperationFactory();
|
||||
const response = await makeGraphqlAPIRequest(operation);
|
||||
|
||||
assertGraphQLSuccessfulResponse(response);
|
||||
expect(response.body.data.getCoreViews).toHaveLength(1);
|
||||
expect(response.body.data.getCoreViews[0]).toMatchObject(viewData);
|
||||
});
|
||||
|
||||
it('should filter views by objectMetadataId when provided', async () => {
|
||||
const object1ViewName = 'View for Object 1';
|
||||
const object2ViewName = 'View for Object 2';
|
||||
|
||||
const {
|
||||
data: {
|
||||
createOneObject: { id: objectMetadata2Id },
|
||||
},
|
||||
} = await createOneObjectMetadata({
|
||||
input: {
|
||||
nameSingular: 'myTestObject2',
|
||||
namePlural: 'myTestObjects2',
|
||||
labelSingular: 'My Test Object 2',
|
||||
labelPlural: 'My Test Objects 2',
|
||||
icon: 'Icon123',
|
||||
},
|
||||
});
|
||||
|
||||
await Promise.all([
|
||||
createTestViewWithGraphQL({
|
||||
name: object1ViewName,
|
||||
objectMetadataId: testObjectMetadataId,
|
||||
}),
|
||||
createTestViewWithGraphQL({
|
||||
name: object2ViewName,
|
||||
objectMetadataId: objectMetadata2Id,
|
||||
}),
|
||||
]);
|
||||
|
||||
const operation = findViewsOperationFactory({
|
||||
objectMetadataId: testObjectMetadataId,
|
||||
});
|
||||
const response = await makeGraphqlAPIRequest(operation);
|
||||
|
||||
assertGraphQLSuccessfulResponse(response);
|
||||
expect(response.body.data.getCoreViews).toHaveLength(1);
|
||||
expect(response.body.data.getCoreViews[0]).toMatchObject({
|
||||
name: object1ViewName,
|
||||
});
|
||||
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: objectMetadata2Id },
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getCoreView', () => {
|
||||
it('should return null when view does not exist', async () => {
|
||||
const operation = findViewOperationFactory({
|
||||
viewId: TEST_NOT_EXISTING_VIEW_ID,
|
||||
});
|
||||
const response = await makeGraphqlAPIRequest(operation);
|
||||
|
||||
assertGraphQLSuccessfulResponse(response);
|
||||
expect(response.body.data.getCoreView).toBeNull();
|
||||
});
|
||||
|
||||
it('should return view when it exists', async () => {
|
||||
const viewName = 'Test View for Get';
|
||||
|
||||
const view = await createTestViewWithGraphQL({
|
||||
name: viewName,
|
||||
objectMetadataId: testObjectMetadataId,
|
||||
});
|
||||
|
||||
const operation = findViewOperationFactory({ viewId: view.id });
|
||||
const response = await makeGraphqlAPIRequest(operation);
|
||||
|
||||
assertGraphQLSuccessfulResponse(response);
|
||||
assertViewStructure(response.body.data.getCoreView, {
|
||||
id: view.id,
|
||||
name: viewName,
|
||||
objectMetadataId: testObjectMetadataId,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('createCoreView', () => {
|
||||
it('should create a new view with all properties', async () => {
|
||||
const input = {
|
||||
name: 'Kanban View',
|
||||
objectMetadataId: testObjectMetadataId,
|
||||
icon: 'IconDeal',
|
||||
type: ViewType.KANBAN,
|
||||
key: null,
|
||||
position: 1,
|
||||
isCompact: true,
|
||||
openRecordIn: ViewOpenRecordIn.SIDE_PANEL,
|
||||
};
|
||||
|
||||
const operation = createViewOperationFactory({ data: input });
|
||||
const response = await makeGraphqlAPIRequest(operation);
|
||||
|
||||
assertGraphQLSuccessfulResponse(response);
|
||||
assertViewStructure(response.body.data.createCoreView, {
|
||||
name: input.name,
|
||||
objectMetadataId: input.objectMetadataId,
|
||||
type: input.type,
|
||||
key: null,
|
||||
icon: input.icon,
|
||||
position: input.position,
|
||||
isCompact: input.isCompact,
|
||||
openRecordIn: input.openRecordIn,
|
||||
});
|
||||
});
|
||||
|
||||
it('should create a view with minimum required fields', async () => {
|
||||
const input = {
|
||||
name: 'Minimal View',
|
||||
objectMetadataId: testObjectMetadataId,
|
||||
icon: 'IconList',
|
||||
};
|
||||
|
||||
const operation = createViewOperationFactory({ data: input });
|
||||
const response = await makeGraphqlAPIRequest(operation);
|
||||
|
||||
assertGraphQLSuccessfulResponse(response);
|
||||
assertViewStructure(response.body.data.createCoreView, {
|
||||
name: input.name,
|
||||
objectMetadataId: input.objectMetadataId,
|
||||
icon: input.icon,
|
||||
type: ViewType.TABLE,
|
||||
key: null,
|
||||
position: 0,
|
||||
isCompact: false,
|
||||
openRecordIn: ViewOpenRecordIn.SIDE_PANEL,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateCoreView', () => {
|
||||
it('should update an existing view', async () => {
|
||||
const view = await createTestViewWithGraphQL({
|
||||
name: 'Original View',
|
||||
type: ViewType.TABLE,
|
||||
isCompact: false,
|
||||
objectMetadataId: testObjectMetadataId,
|
||||
});
|
||||
|
||||
const updateInput = updateViewData({
|
||||
name: 'Updated View',
|
||||
type: ViewType.KANBAN,
|
||||
isCompact: true,
|
||||
});
|
||||
|
||||
const operation = updateViewOperationFactory({
|
||||
viewId: view.id,
|
||||
data: updateInput,
|
||||
});
|
||||
const response = await makeGraphqlAPIRequest(operation);
|
||||
|
||||
assertGraphQLSuccessfulResponse(response);
|
||||
expect(response.body.data.updateCoreView).toMatchObject({
|
||||
id: view.id,
|
||||
...updateInput,
|
||||
});
|
||||
});
|
||||
|
||||
it('should throw error when updating non-existent view', async () => {
|
||||
const operation = updateViewOperationFactory({
|
||||
viewId: TEST_NOT_EXISTING_VIEW_ID,
|
||||
data: { name: 'Non-existent View' },
|
||||
});
|
||||
const response = await makeGraphqlAPIRequest(operation);
|
||||
|
||||
assertGraphQLErrorResponse(
|
||||
response,
|
||||
ErrorCode.NOT_FOUND,
|
||||
generateViewExceptionMessage(
|
||||
ViewExceptionMessageKey.VIEW_NOT_FOUND,
|
||||
TEST_NOT_EXISTING_VIEW_ID,
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('deleteCoreView', () => {
|
||||
it('should delete an existing view', async () => {
|
||||
const view = await createTestViewWithGraphQL({
|
||||
name: 'View to Delete',
|
||||
objectMetadataId: testObjectMetadataId,
|
||||
});
|
||||
|
||||
const deleteOperation = deleteViewOperationFactory({ viewId: view.id });
|
||||
const deleteResponse = await makeGraphqlAPIRequest(deleteOperation);
|
||||
|
||||
assertGraphQLSuccessfulResponse(deleteResponse);
|
||||
expect(deleteResponse.body.data.deleteCoreView).toBe(true);
|
||||
|
||||
const getOperation = findViewOperationFactory({ viewId: view.id });
|
||||
const getResponse = await makeGraphqlAPIRequest(getOperation);
|
||||
|
||||
expect(getResponse.body.data.getCoreView).toBeNull();
|
||||
});
|
||||
|
||||
it('should throw an error when deleting non-existent view', async () => {
|
||||
const operation = deleteViewOperationFactory({
|
||||
viewId: TEST_NOT_EXISTING_VIEW_ID,
|
||||
});
|
||||
const response = await makeGraphqlAPIRequest(operation);
|
||||
|
||||
assertGraphQLErrorResponse(
|
||||
response,
|
||||
ErrorCode.NOT_FOUND,
|
||||
generateViewExceptionMessage(
|
||||
ViewExceptionMessageKey.VIEW_NOT_FOUND,
|
||||
TEST_NOT_EXISTING_VIEW_ID,
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('destroyCoreView', () => {
|
||||
it('should destroy an existing view', async () => {
|
||||
const view = await createTestViewWithGraphQL({
|
||||
name: 'View to Destroy',
|
||||
objectMetadataId: testObjectMetadataId,
|
||||
});
|
||||
|
||||
const destroyOperation = destroyViewOperationFactory({ viewId: view.id });
|
||||
const destroyResponse = await makeGraphqlAPIRequest(destroyOperation);
|
||||
|
||||
assertGraphQLSuccessfulResponse(destroyResponse);
|
||||
expect(destroyResponse.body.data.destroyCoreView).toBe(true);
|
||||
});
|
||||
|
||||
it('should throw an error when destroying non-existent view', async () => {
|
||||
const operation = destroyViewOperationFactory({
|
||||
viewId: TEST_NOT_EXISTING_VIEW_ID,
|
||||
});
|
||||
const response = await makeGraphqlAPIRequest(operation);
|
||||
|
||||
assertGraphQLErrorResponse(
|
||||
response,
|
||||
ErrorCode.NOT_FOUND,
|
||||
generateViewExceptionMessage(
|
||||
ViewExceptionMessageKey.VIEW_NOT_FOUND,
|
||||
TEST_NOT_EXISTING_VIEW_ID,
|
||||
),
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
+10
@@ -17,6 +17,7 @@ import { createTestViewWithGraphQL } from 'test/integration/graphql/utils/view-g
|
||||
import { createOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/create-one-field-metadata.util';
|
||||
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
|
||||
import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util';
|
||||
import { updateOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata.util';
|
||||
import {
|
||||
assertViewSortStructure,
|
||||
cleanupViewRecords,
|
||||
@@ -72,6 +73,15 @@ describe('View Sort Resolver', () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: testObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: testObjectMetadataId },
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import { jestExpectToBeDefined } from 'test/utils/expect-to-be-defined.util.test';
|
||||
import { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any';
|
||||
|
||||
import {
|
||||
type BaseGraphQLError,
|
||||
type ErrorCode,
|
||||
@@ -43,3 +46,20 @@ export const assertGraphQLErrorResponse = <T extends Record<string, unknown>>(
|
||||
expect(response.body.errors[0].message).toBe(expectedErrorMessage);
|
||||
}
|
||||
};
|
||||
|
||||
export const assertGraphQLErrorResponseWithSnapshot = <
|
||||
T extends Record<string, unknown>,
|
||||
>(
|
||||
response: GraphQLResponse<T>,
|
||||
) => {
|
||||
expect(response.status).toBe(200);
|
||||
jestExpectToBeDefined(response.body.errors);
|
||||
expect(response.body.errors).toHaveLength(1);
|
||||
|
||||
const firstError = response.body.errors[0];
|
||||
|
||||
jestExpectToBeDefined(firstError);
|
||||
expect(firstError).toMatchSnapshot(
|
||||
extractRecordIdsAndDatesAsExpectAny(firstError),
|
||||
);
|
||||
};
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`createOne FieldMetadataService name/label sync should return an error when name and label are not synced but isLabelSyncedWithName is true 1`] = `
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"errors": {
|
||||
"index": [],
|
||||
"objectMetadata": [
|
||||
{
|
||||
"errors": [
|
||||
{
|
||||
"code": "NAME_NOT_SYNCED_WITH_LABEL",
|
||||
"message": "Name is not synced with label",
|
||||
"userFriendlyMessage": "Field name is not synced with field label",
|
||||
"value": "Different Label",
|
||||
},
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "testField",
|
||||
"objectMetadataId": Any<String>,
|
||||
},
|
||||
"type": "create_field",
|
||||
},
|
||||
],
|
||||
"serverlessFunction": [],
|
||||
"view": [],
|
||||
"viewField": [],
|
||||
},
|
||||
"message": "Validation failed for 0 object(s) and 0 field(s)",
|
||||
"summary": {
|
||||
"invalidIndex": 0,
|
||||
"invalidObjectMetadata": 0,
|
||||
"invalidServerlessFunction": 0,
|
||||
"invalidView": 0,
|
||||
"invalidViewField": 0,
|
||||
"totalErrors": 0,
|
||||
},
|
||||
"userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)",
|
||||
},
|
||||
"message": "Multiple validation errors occurred while creating fields",
|
||||
"name": "GraphQLError",
|
||||
}
|
||||
`;
|
||||
+97
@@ -0,0 +1,97 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`updateOne failing update should not update a field name if it is not synced correctly with label and labelSync is true 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"errors": {
|
||||
"index": [],
|
||||
"objectMetadata": [
|
||||
{
|
||||
"errors": [
|
||||
{
|
||||
"code": "FIELD_MUTATION_NOT_ALLOWED",
|
||||
"message": "Name is not synced with label.",
|
||||
"userFriendlyMessage": "Updated field name is not synced with label",
|
||||
},
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "newName",
|
||||
"objectMetadataId": Any<String>,
|
||||
},
|
||||
"type": "update_field",
|
||||
},
|
||||
],
|
||||
"serverlessFunction": [],
|
||||
"view": [],
|
||||
"viewField": [],
|
||||
},
|
||||
"message": "Validation failed for 0 object(s) and 0 field(s)",
|
||||
"summary": {
|
||||
"invalidIndex": 0,
|
||||
"invalidObjectMetadata": 0,
|
||||
"invalidServerlessFunction": 0,
|
||||
"invalidView": 0,
|
||||
"invalidViewField": 0,
|
||||
"totalErrors": 0,
|
||||
},
|
||||
"userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)",
|
||||
},
|
||||
"message": "Multiple validation errors occurred while updating field",
|
||||
"name": "GraphQLError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`updateOne failing update should throw if the field name is not available because of other field with the same name 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"errors": {
|
||||
"index": [],
|
||||
"objectMetadata": [
|
||||
{
|
||||
"errors": [
|
||||
{
|
||||
"code": "NOT_AVAILABLE",
|
||||
"message": "Name "otherTestName" is not available as it is already used by another field",
|
||||
"userFriendlyMessage": "Name "otherTestName" is not available as it is already used by another field",
|
||||
"value": "otherTestName",
|
||||
},
|
||||
{
|
||||
"code": "FIELD_MUTATION_NOT_ALLOWED",
|
||||
"message": "Name is not synced with label.",
|
||||
"userFriendlyMessage": "Updated field name is not synced with label",
|
||||
},
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "otherTestName",
|
||||
"objectMetadataId": Any<String>,
|
||||
},
|
||||
"type": "update_field",
|
||||
},
|
||||
],
|
||||
"serverlessFunction": [],
|
||||
"view": [],
|
||||
"viewField": [],
|
||||
},
|
||||
"message": "Validation failed for 0 object(s) and 0 field(s)",
|
||||
"summary": {
|
||||
"invalidIndex": 0,
|
||||
"invalidObjectMetadata": 0,
|
||||
"invalidServerlessFunction": 0,
|
||||
"invalidView": 0,
|
||||
"invalidViewField": 0,
|
||||
"totalErrors": 0,
|
||||
},
|
||||
"userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)",
|
||||
},
|
||||
"message": "Multiple validation errors occurred while updating field",
|
||||
"name": "GraphQLError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
+17
-3
@@ -1,6 +1,8 @@
|
||||
import { createOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/create-one-field-metadata.util';
|
||||
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
|
||||
import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util';
|
||||
import { updateOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata.util';
|
||||
import { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
describe('createOne FieldMetadataService name/label sync', () => {
|
||||
@@ -24,6 +26,15 @@ describe('createOne FieldMetadataService name/label sync', () => {
|
||||
createdObjectMetadataId = objectMetadataId;
|
||||
});
|
||||
afterEach(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: createdObjectMetadataId },
|
||||
});
|
||||
@@ -89,7 +100,7 @@ describe('createOne FieldMetadataService name/label sync', () => {
|
||||
};
|
||||
|
||||
// Act
|
||||
const { errors } = await createOneFieldMetadata({
|
||||
const response = await createOneFieldMetadata({
|
||||
input: createFieldInput,
|
||||
gqlFields: `
|
||||
id
|
||||
@@ -101,8 +112,11 @@ describe('createOne FieldMetadataService name/label sync', () => {
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(errors[0].message).toBe(
|
||||
'Name is not synced with label. Expected name: "differentLabel", got testField',
|
||||
expect(response.errors.length).toBe(1);
|
||||
const [firstError] = response.errors;
|
||||
|
||||
expect(firstError).toMatchSnapshot(
|
||||
extractRecordIdsAndDatesAsExpectAny(firstError),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
+32
-6
@@ -1,12 +1,9 @@
|
||||
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 { updateOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/update-one-field-metadata.util';
|
||||
import {
|
||||
LISTING_NAME_PLURAL,
|
||||
LISTING_NAME_SINGULAR,
|
||||
} from 'test/integration/metadata/suites/object-metadata/constants/test-object-names.constant';
|
||||
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 {
|
||||
createTestViewWithRestApi,
|
||||
findViewByIdWithRestApi,
|
||||
@@ -14,11 +11,28 @@ import {
|
||||
import { generateRecordName } from 'test/integration/utils/generate-record-name';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { updateFeatureFlag } from 'test/integration/metadata/suites/utils/update-feature-flag.util';
|
||||
|
||||
import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant';
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { ViewType } from 'src/engine/core-modules/view/enums/view-type.enum';
|
||||
|
||||
describe('deleteOne', () => {
|
||||
beforeAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: false,
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: true,
|
||||
});
|
||||
});
|
||||
describe('Kanban aggregate operation', () => {
|
||||
let listingObjectId = '';
|
||||
let testFieldId = '';
|
||||
@@ -28,8 +42,8 @@ describe('deleteOne', () => {
|
||||
const { data } = await createOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
nameSingular: LISTING_NAME_SINGULAR,
|
||||
namePlural: LISTING_NAME_PLURAL,
|
||||
nameSingular: 'listingv2',
|
||||
namePlural: 'listingsv2',
|
||||
labelSingular: 'Listing',
|
||||
labelPlural: 'Listings',
|
||||
icon: 'IconBuildingSkyscraper',
|
||||
@@ -61,11 +75,21 @@ describe('deleteOne', () => {
|
||||
viewId = createdView.id;
|
||||
});
|
||||
afterEach(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: listingObjectId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: listingObjectId },
|
||||
});
|
||||
});
|
||||
|
||||
it('should reset kanban aggregate operation when deleting a field used as kanbanAggregateOperationFieldMetadataId', async () => {
|
||||
const viewThatShouldBeUpdated = await findViewByIdWithRestApi(viewId);
|
||||
|
||||
@@ -79,6 +103,7 @@ describe('deleteOne', () => {
|
||||
expect(viewThatShouldBeUpdated.kanbanAggregateOperation).toBe('MAX');
|
||||
|
||||
await updateOneFieldMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: testFieldId,
|
||||
updatePayload: { isActive: false },
|
||||
@@ -90,6 +115,7 @@ describe('deleteOne', () => {
|
||||
});
|
||||
|
||||
const { data } = await deleteOneFieldMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: testFieldId },
|
||||
});
|
||||
|
||||
|
||||
-461
@@ -516,464 +516,3 @@ exports[`Failing create field metadata MULTI_SELECT tests suite Create should fa
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with an invalid default value 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Default value should be as quoted string",
|
||||
},
|
||||
"message": "Default value should be as quoted string",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with an unknown default value 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Default value "'OPTION_424242'" must be one of the option values",
|
||||
},
|
||||
"message": "Default value "'OPTION_424242'" must be one of the option values",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with comma in option label 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Label must not contain a comma",
|
||||
},
|
||||
"message": "Label must not contain a comma",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with duplicated option ids 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Duplicated option id",
|
||||
},
|
||||
"message": "Duplicated option id",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with duplicated option positions 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Duplicated option position",
|
||||
},
|
||||
"message": "Duplicated option position",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with duplicated option values 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Duplicated option value",
|
||||
},
|
||||
"message": "Duplicated option value",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with duplicated trimmed option values 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Duplicated option value",
|
||||
},
|
||||
"message": "Duplicated option value",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with empty options 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "An error occurred.",
|
||||
},
|
||||
"message": "Options are required for enum fields",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with empty string defaultValue 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Default value should be as quoted string",
|
||||
},
|
||||
"message": "Default value should be as quoted string",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with empty string id 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option id is invalid",
|
||||
},
|
||||
"message": "Option id is invalid",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with empty string label 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option label "" is beneath 1 character",
|
||||
},
|
||||
"message": "Option label "" is beneath 1 character",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with empty string value 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option value "" is beneath 1 character",
|
||||
},
|
||||
"message": "Option value "" is beneath 1 character",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with invalid option id 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option id is invalid",
|
||||
},
|
||||
"message": "Option id is invalid",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with invalid option value format 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Value must be in UPPER_CASE and follow snake_case "Option 1 and some other things, /"",
|
||||
},
|
||||
"message": "Value must be in UPPER_CASE and follow snake_case "Option 1 and some other things, /"",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with not a string defaultValue 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "An error occurred.",
|
||||
},
|
||||
"message": "Default value for multi-select must be a stringified array",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with not a string id 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option id is invalid",
|
||||
},
|
||||
"message": "Option id is invalid",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with not a string label 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "INTERNAL_SERVER_ERROR",
|
||||
"exceptionEventId": "mocked-exception-id",
|
||||
"userFriendlyMessage": "An error occurred.",
|
||||
},
|
||||
"message": "label.includes is not a function",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with not a string value 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Value must be in UPPER_CASE and follow snake_case "22222"",
|
||||
},
|
||||
"message": "Value must be in UPPER_CASE and follow snake_case "22222"",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with null id 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option id is required",
|
||||
},
|
||||
"message": "Option id is required",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with null label 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option label is required",
|
||||
},
|
||||
"message": "Option label is required",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with null options 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "An error occurred.",
|
||||
},
|
||||
"message": "Options are required for enum fields",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with null value 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option value is required",
|
||||
},
|
||||
"message": "Option value is required",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with only white spaces defaultValue 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Default value should be as quoted string",
|
||||
},
|
||||
"message": "Default value should be as quoted string",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with only white spaces id 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option id is invalid",
|
||||
},
|
||||
"message": "Option id is invalid",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with only white spaces label 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option label "" is beneath 1 character",
|
||||
},
|
||||
"message": "Option label "" is beneath 1 character",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with only white spaces value 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option value "" is beneath 1 character",
|
||||
},
|
||||
"message": "Option value "" is beneath 1 character",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with too long defaultValue 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Default value should be as quoted string",
|
||||
},
|
||||
"message": "Default value should be as quoted string",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with too long id 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option id is invalid",
|
||||
},
|
||||
"message": "Option id is invalid",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with too long label 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option label exceeds 63 characters",
|
||||
},
|
||||
"message": "Option label exceeds 63 characters",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with too long value 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option value exceeds 63 characters",
|
||||
},
|
||||
"message": "Option value exceeds 63 characters",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with undefined option label 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option label is required",
|
||||
},
|
||||
"message": "Option label is required",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with undefined option value 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option value is required",
|
||||
},
|
||||
"message": "Option value is required",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata SELECT tests suite Create should fail with undefined options 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "An error occurred.",
|
||||
},
|
||||
"message": "Options are required for enum fields",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
+462
@@ -0,0 +1,462 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with an invalid default value 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Default value should be as quoted string",
|
||||
},
|
||||
"message": "Default value should be as quoted string",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with an unknown default value 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Default value "'OPTION_424242'" must be one of the option values",
|
||||
},
|
||||
"message": "Default value "'OPTION_424242'" must be one of the option values",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with comma in option label 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Label must not contain a comma",
|
||||
},
|
||||
"message": "Label must not contain a comma",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with duplicated option ids 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Duplicated option id",
|
||||
},
|
||||
"message": "Duplicated option id",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with duplicated option positions 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Duplicated option position",
|
||||
},
|
||||
"message": "Duplicated option position",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with duplicated option values 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Duplicated option value",
|
||||
},
|
||||
"message": "Duplicated option value",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with duplicated trimmed option values 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Duplicated option value",
|
||||
},
|
||||
"message": "Duplicated option value",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with empty options 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "An error occurred.",
|
||||
},
|
||||
"message": "Options are required for enum fields",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with empty string defaultValue 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Default value should be as quoted string",
|
||||
},
|
||||
"message": "Default value should be as quoted string",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with empty string id 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option id is invalid",
|
||||
},
|
||||
"message": "Option id is invalid",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with empty string label 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option label "" is beneath 1 character",
|
||||
},
|
||||
"message": "Option label "" is beneath 1 character",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with empty string value 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option value "" is beneath 1 character",
|
||||
},
|
||||
"message": "Option value "" is beneath 1 character",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with invalid option id 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option id is invalid",
|
||||
},
|
||||
"message": "Option id is invalid",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with invalid option value format 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Value must be in UPPER_CASE and follow snake_case "Option 1 and some other things, /"",
|
||||
},
|
||||
"message": "Value must be in UPPER_CASE and follow snake_case "Option 1 and some other things, /"",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with not a string defaultValue 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "An error occurred.",
|
||||
},
|
||||
"message": "Default value for multi-select must be a stringified array",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with not a string id 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option id is invalid",
|
||||
},
|
||||
"message": "Option id is invalid",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with not a string label 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "INTERNAL_SERVER_ERROR",
|
||||
"exceptionEventId": "mocked-exception-id",
|
||||
"userFriendlyMessage": "An error occurred.",
|
||||
},
|
||||
"message": "label.includes is not a function",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with not a string value 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Value must be in UPPER_CASE and follow snake_case "22222"",
|
||||
},
|
||||
"message": "Value must be in UPPER_CASE and follow snake_case "22222"",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with null id 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option id is required",
|
||||
},
|
||||
"message": "Option id is required",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with null label 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option label is required",
|
||||
},
|
||||
"message": "Option label is required",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with null options 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "An error occurred.",
|
||||
},
|
||||
"message": "Options are required for enum fields",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with null value 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option value is required",
|
||||
},
|
||||
"message": "Option value is required",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with only white spaces defaultValue 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Default value should be as quoted string",
|
||||
},
|
||||
"message": "Default value should be as quoted string",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with only white spaces id 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option id is invalid",
|
||||
},
|
||||
"message": "Option id is invalid",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with only white spaces label 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option label "" is beneath 1 character",
|
||||
},
|
||||
"message": "Option label "" is beneath 1 character",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with only white spaces value 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option value "" is beneath 1 character",
|
||||
},
|
||||
"message": "Option value "" is beneath 1 character",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with too long defaultValue 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Default value should be as quoted string",
|
||||
},
|
||||
"message": "Default value should be as quoted string",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with too long id 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option id is invalid",
|
||||
},
|
||||
"message": "Option id is invalid",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with too long label 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option label exceeds 63 characters",
|
||||
},
|
||||
"message": "Option label exceeds 63 characters",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with too long value 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option value exceeds 63 characters",
|
||||
},
|
||||
"message": "Option value exceeds 63 characters",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with undefined option label 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option label is required",
|
||||
},
|
||||
"message": "Option label is required",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with undefined option value 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "Option value is required",
|
||||
},
|
||||
"message": "Option value is required",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Failing create field metadata RATING tests suite Create should fail with undefined options 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "An error occurred.",
|
||||
},
|
||||
"message": "Options are required for enum fields",
|
||||
"name": "UserInputError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
+11
-27
@@ -4,12 +4,10 @@ import { CUSTOM_OBJECT_DISHES } from 'test/integration/metadata/suites/object-me
|
||||
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 { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any';
|
||||
import { eachTestingContextFilter } from 'twenty-shared/testing';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { fieldMetadataEnumTypes } from 'src/engine/metadata-modules/field-metadata/utils/is-enum-field-metadata-type.util';
|
||||
|
||||
describe.each(fieldMetadataEnumTypes)(
|
||||
@@ -25,12 +23,6 @@ describe.each(fieldMetadataEnumTypes)(
|
||||
const { failing: failingTestCases } = testCases;
|
||||
|
||||
beforeAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: true,
|
||||
});
|
||||
|
||||
const {
|
||||
labelPlural,
|
||||
description,
|
||||
@@ -55,25 +47,17 @@ describe.each(fieldMetadataEnumTypes)(
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
try {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataId,
|
||||
updatePayload: { isActive: false },
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: createdObjectMetadataId },
|
||||
});
|
||||
} finally {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: false,
|
||||
});
|
||||
}
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataId,
|
||||
updatePayload: { isActive: false },
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: createdObjectMetadataId },
|
||||
});
|
||||
});
|
||||
|
||||
test.each(eachTestingContextFilter(failingTestCases))(
|
||||
|
||||
-74
@@ -1,74 +0,0 @@
|
||||
import { CREATE_ENUM_FIELD_METADATA_TEST_CASES } from 'test/integration/metadata/suites/field-metadata/enum/common/create-enum-field-metadata-test-cases';
|
||||
import { createOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/create-one-field-metadata.util';
|
||||
import {
|
||||
LISTING_NAME_PLURAL,
|
||||
LISTING_NAME_SINGULAR,
|
||||
} from 'test/integration/metadata/suites/object-metadata/constants/test-object-names.constant';
|
||||
import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
|
||||
|
||||
import { fieldMetadataEnumTypes } from 'src/engine/metadata-modules/field-metadata/utils/is-enum-field-metadata-type.util';
|
||||
|
||||
describe.each(fieldMetadataEnumTypes)(
|
||||
'Failing create field metadata %s tests suite',
|
||||
(testedFieldMetadataType) => {
|
||||
let createdObjectMetadataId: string;
|
||||
const testCases =
|
||||
CREATE_ENUM_FIELD_METADATA_TEST_CASES[testedFieldMetadataType];
|
||||
|
||||
if (!isDefined(testCases)) {
|
||||
return;
|
||||
}
|
||||
const { failing: failingTestCases } = testCases;
|
||||
|
||||
beforeAll(async () => {
|
||||
const { data } = await createOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
labelSingular: LISTING_NAME_SINGULAR,
|
||||
labelPlural: LISTING_NAME_PLURAL,
|
||||
nameSingular: LISTING_NAME_SINGULAR,
|
||||
namePlural: LISTING_NAME_PLURAL,
|
||||
icon: 'IconBuildingSkyscraper',
|
||||
isLabelSyncedWithName: false,
|
||||
},
|
||||
});
|
||||
|
||||
createdObjectMetadataId = data.createOneObject.id;
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: createdObjectMetadataId },
|
||||
});
|
||||
});
|
||||
|
||||
test.each(failingTestCases)(
|
||||
'Create $title',
|
||||
async ({ context: { input } }) => {
|
||||
const { data, errors } = await createOneFieldMetadata({
|
||||
expectToFail: true,
|
||||
input: {
|
||||
objectMetadataId: createdObjectMetadataId,
|
||||
type: testedFieldMetadataType,
|
||||
name: 'testField',
|
||||
label: 'Test Field',
|
||||
isLabelSyncedWithName: false,
|
||||
...input,
|
||||
},
|
||||
gqlFields: `
|
||||
id
|
||||
options
|
||||
defaultValue
|
||||
`,
|
||||
});
|
||||
|
||||
expect(data).toBeNull();
|
||||
expect(errors).toBeDefined();
|
||||
expect(errors).toMatchSnapshot();
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
import { CREATE_ENUM_FIELD_METADATA_TEST_CASES } from 'test/integration/metadata/suites/field-metadata/enum/common/create-enum-field-metadata-test-cases';
|
||||
import { createOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/create-one-field-metadata.util';
|
||||
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
|
||||
import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util';
|
||||
import { updateFeatureFlag } from 'test/integration/metadata/suites/utils/update-feature-flag.util';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
|
||||
describe('Failing create field metadata MULTI_SELECT tests suite', () => {
|
||||
let createdObjectMetadataId: string;
|
||||
const testCases =
|
||||
CREATE_ENUM_FIELD_METADATA_TEST_CASES[FieldMetadataType.MULTI_SELECT];
|
||||
|
||||
if (!isDefined(testCases)) {
|
||||
return;
|
||||
}
|
||||
const { failing: failingTestCases } = testCases;
|
||||
|
||||
beforeAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: false,
|
||||
});
|
||||
});
|
||||
|
||||
beforeAll(async () => {
|
||||
const { data } = await createOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
labelSingular: 'Enum testing v1',
|
||||
labelPlural: 'Enums testings v1',
|
||||
nameSingular: 'enumTestingV1',
|
||||
namePlural: 'enumsTestingsV1',
|
||||
icon: 'IconBuildingSkyscraper',
|
||||
isLabelSyncedWithName: false,
|
||||
},
|
||||
});
|
||||
|
||||
createdObjectMetadataId = data.createOneObject.id;
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: createdObjectMetadataId },
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: true,
|
||||
});
|
||||
});
|
||||
|
||||
test.each(failingTestCases)(
|
||||
'Create $title',
|
||||
async ({ context: { input } }) => {
|
||||
const { data, errors } = await createOneFieldMetadata({
|
||||
expectToFail: true,
|
||||
input: {
|
||||
objectMetadataId: createdObjectMetadataId,
|
||||
type: FieldMetadataType.MULTI_SELECT,
|
||||
name: 'testField',
|
||||
label: 'Test Field',
|
||||
isLabelSyncedWithName: false,
|
||||
...input,
|
||||
},
|
||||
gqlFields: `
|
||||
id
|
||||
options
|
||||
defaultValue
|
||||
`,
|
||||
});
|
||||
|
||||
expect(data).toBeNull();
|
||||
expect(errors).toBeDefined();
|
||||
expect(errors).toMatchSnapshot();
|
||||
},
|
||||
);
|
||||
});
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
import { CREATE_ENUM_FIELD_METADATA_TEST_CASES } from 'test/integration/metadata/suites/field-metadata/enum/common/create-enum-field-metadata-test-cases';
|
||||
import { createOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/create-one-field-metadata.util';
|
||||
import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util';
|
||||
import { updateFeatureFlag } from 'test/integration/metadata/suites/utils/update-feature-flag.util';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
|
||||
describe('Failing create field metadata RATING tests suite', () => {
|
||||
let createdObjectMetadataId: string;
|
||||
const testCases =
|
||||
CREATE_ENUM_FIELD_METADATA_TEST_CASES[FieldMetadataType.SELECT];
|
||||
|
||||
if (!isDefined(testCases)) {
|
||||
return;
|
||||
}
|
||||
const { failing: failingTestCases } = testCases;
|
||||
|
||||
beforeAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: false,
|
||||
});
|
||||
});
|
||||
|
||||
beforeAll(async () => {
|
||||
const { data } = await createOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
labelSingular: 'Enum testing v1',
|
||||
labelPlural: 'Enums testings v1',
|
||||
nameSingular: 'enumTestingV1',
|
||||
namePlural: 'enumsTestingsV1',
|
||||
icon: 'IconBuildingSkyscraper',
|
||||
isLabelSyncedWithName: false,
|
||||
},
|
||||
});
|
||||
|
||||
createdObjectMetadataId = data.createOneObject.id;
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: createdObjectMetadataId },
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: true,
|
||||
});
|
||||
});
|
||||
|
||||
test.each(failingTestCases)(
|
||||
'Create $title',
|
||||
async ({ context: { input } }) => {
|
||||
const { data, errors } = await createOneFieldMetadata({
|
||||
expectToFail: true,
|
||||
input: {
|
||||
objectMetadataId: createdObjectMetadataId,
|
||||
type: FieldMetadataType.SELECT,
|
||||
name: 'testField',
|
||||
label: 'Test Field',
|
||||
isLabelSyncedWithName: false,
|
||||
...input,
|
||||
},
|
||||
gqlFields: `
|
||||
id
|
||||
options
|
||||
defaultValue
|
||||
`,
|
||||
});
|
||||
|
||||
expect(data).toBeNull();
|
||||
expect(errors).toBeDefined();
|
||||
expect(errors).toMatchSnapshot();
|
||||
},
|
||||
);
|
||||
});
|
||||
+14
-30
@@ -6,12 +6,10 @@ import { CUSTOM_OBJECT_DISHES } from 'test/integration/metadata/suites/object-me
|
||||
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 { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any';
|
||||
import { eachTestingContextFilter } from 'twenty-shared/testing';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { fieldMetadataEnumTypes } from 'src/engine/metadata-modules/field-metadata/utils/is-enum-field-metadata-type.util';
|
||||
|
||||
describe.each(fieldMetadataEnumTypes)(
|
||||
@@ -42,12 +40,6 @@ describe.each(fieldMetadataEnumTypes)(
|
||||
];
|
||||
|
||||
beforeAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: true,
|
||||
});
|
||||
|
||||
const {
|
||||
labelPlural,
|
||||
description,
|
||||
@@ -90,30 +82,22 @@ describe.each(fieldMetadataEnumTypes)(
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
try {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
await deleteOneObjectMetadata({
|
||||
input: {
|
||||
idToDelete: createdObjectMetadataId,
|
||||
},
|
||||
expectToFail: false,
|
||||
});
|
||||
} finally {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: false,
|
||||
});
|
||||
}
|
||||
await deleteOneObjectMetadata({
|
||||
input: {
|
||||
idToDelete: createdObjectMetadataId,
|
||||
},
|
||||
expectToFail: false,
|
||||
});
|
||||
});
|
||||
|
||||
test.each(eachTestingContextFilter(failingTestCases))(
|
||||
|
||||
+23
-19
@@ -2,15 +2,12 @@ import { UPDATE_ENUM_FIELD_METADATA_TEST_CASES } from 'test/integration/metadata
|
||||
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 { updateOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/update-one-field-metadata.util';
|
||||
import {
|
||||
LISTING_NAME_PLURAL,
|
||||
LISTING_NAME_SINGULAR,
|
||||
} from 'test/integration/metadata/suites/object-metadata/constants/test-object-names.constant';
|
||||
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 { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { fieldMetadataEnumTypes } from 'src/engine/metadata-modules/field-metadata/utils/is-enum-field-metadata-type.util';
|
||||
|
||||
describe.each(fieldMetadataEnumTypes)(
|
||||
@@ -25,6 +22,15 @@ describe.each(fieldMetadataEnumTypes)(
|
||||
return;
|
||||
}
|
||||
const { failing: failingTestCases } = testCases;
|
||||
|
||||
beforeAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: false,
|
||||
});
|
||||
});
|
||||
|
||||
const initialOptions: CreateOneFieldFactoryInput['options'] = [
|
||||
{
|
||||
label: 'Option 1',
|
||||
@@ -44,10 +50,10 @@ describe.each(fieldMetadataEnumTypes)(
|
||||
const { data } = await createOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
labelSingular: LISTING_NAME_SINGULAR,
|
||||
labelPlural: LISTING_NAME_PLURAL,
|
||||
nameSingular: LISTING_NAME_SINGULAR,
|
||||
namePlural: LISTING_NAME_PLURAL,
|
||||
labelSingular: 'failingUpdateEnumField',
|
||||
labelPlural: 'failingUpdateEnumFields',
|
||||
nameSingular: 'failingUpdateEnumField',
|
||||
namePlural: 'failingUpdateEnumFields',
|
||||
icon: 'IconBuildingSkyscraper',
|
||||
isLabelSyncedWithName: false,
|
||||
},
|
||||
@@ -76,16 +82,6 @@ describe.each(fieldMetadataEnumTypes)(
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await deleteOneObjectMetadata({
|
||||
input: {
|
||||
idToDelete: createdObjectMetadataId,
|
||||
@@ -94,6 +90,14 @@ describe.each(fieldMetadataEnumTypes)(
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: true,
|
||||
});
|
||||
});
|
||||
|
||||
test.each(failingTestCases)(
|
||||
'Update $title',
|
||||
async ({ context: { input } }) => {
|
||||
|
||||
+11
-27
@@ -6,11 +6,9 @@ import { CUSTOM_OBJECT_DISHES } from 'test/integration/metadata/suites/object-me
|
||||
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 { eachTestingContextFilter } from 'twenty-shared/testing';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { fieldMetadataEnumTypes } from 'src/engine/metadata-modules/field-metadata/utils/is-enum-field-metadata-type.util';
|
||||
|
||||
describe.each(fieldMetadataEnumTypes)(
|
||||
@@ -27,12 +25,6 @@ describe.each(fieldMetadataEnumTypes)(
|
||||
const { successful: successfulTestCases } = testCases;
|
||||
|
||||
beforeAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: true,
|
||||
});
|
||||
|
||||
const {
|
||||
labelPlural,
|
||||
description,
|
||||
@@ -57,25 +49,17 @@ describe.each(fieldMetadataEnumTypes)(
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
try {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataId,
|
||||
updatePayload: { isActive: false },
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: createdObjectMetadataId },
|
||||
});
|
||||
} finally {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: false,
|
||||
});
|
||||
}
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataId,
|
||||
updatePayload: { isActive: false },
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: createdObjectMetadataId },
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
|
||||
+22
-8
@@ -1,14 +1,12 @@
|
||||
import { CREATE_ENUM_FIELD_METADATA_TEST_CASES } from 'test/integration/metadata/suites/field-metadata/enum/common/create-enum-field-metadata-test-cases';
|
||||
import { createOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/create-one-field-metadata.util';
|
||||
import {
|
||||
LISTING_NAME_PLURAL,
|
||||
LISTING_NAME_SINGULAR,
|
||||
} from 'test/integration/metadata/suites/object-metadata/constants/test-object-names.constant';
|
||||
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 { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { fieldMetadataEnumTypes } from 'src/engine/metadata-modules/field-metadata/utils/is-enum-field-metadata-type.util';
|
||||
|
||||
describe.each(fieldMetadataEnumTypes)(
|
||||
@@ -23,14 +21,30 @@ describe.each(fieldMetadataEnumTypes)(
|
||||
}
|
||||
const { successful: successfulTestCases } = testCases;
|
||||
|
||||
beforeAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: false,
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: true,
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
const { data } = await createOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
labelSingular: LISTING_NAME_SINGULAR,
|
||||
labelPlural: LISTING_NAME_PLURAL,
|
||||
nameSingular: LISTING_NAME_SINGULAR,
|
||||
namePlural: LISTING_NAME_PLURAL,
|
||||
labelSingular: 'successCreateEnumField',
|
||||
labelPlural: 'successCreateEnumFields',
|
||||
nameSingular: 'successCreateEnumField',
|
||||
namePlural: 'successCreateEnumFields',
|
||||
icon: 'IconBuildingSkyscraper',
|
||||
isLabelSyncedWithName: false,
|
||||
},
|
||||
|
||||
+12
-28
@@ -7,17 +7,15 @@ import { CUSTOM_OBJECT_DISHES } from 'test/integration/metadata/suites/object-me
|
||||
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 { eachTestingContextFilter } from 'twenty-shared/testing';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { fieldMetadataEnumTypes } from 'src/engine/metadata-modules/field-metadata/utils/is-enum-field-metadata-type.util';
|
||||
import {
|
||||
type FieldMetadataComplexOption,
|
||||
type FieldMetadataDefaultOption,
|
||||
} from 'src/engine/metadata-modules/field-metadata/dtos/options.input';
|
||||
import { fieldMetadataEnumTypes } from 'src/engine/metadata-modules/field-metadata/utils/is-enum-field-metadata-type.util';
|
||||
|
||||
describe.each(fieldMetadataEnumTypes)(
|
||||
'Successful update field metadata %s tests suite v2',
|
||||
@@ -47,12 +45,6 @@ describe.each(fieldMetadataEnumTypes)(
|
||||
];
|
||||
|
||||
beforeAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: true,
|
||||
});
|
||||
|
||||
const {
|
||||
labelPlural,
|
||||
description,
|
||||
@@ -76,25 +68,17 @@ describe.each(fieldMetadataEnumTypes)(
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
try {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataId,
|
||||
updatePayload: { isActive: false },
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: createdObjectMetadataId },
|
||||
});
|
||||
} finally {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: false,
|
||||
});
|
||||
}
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataId,
|
||||
updatePayload: { isActive: false },
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: createdObjectMetadataId },
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
|
||||
+23
-8
@@ -2,16 +2,14 @@ import { UPDATE_ENUM_FIELD_METADATA_TEST_CASES } from 'test/integration/metadata
|
||||
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 { updateOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/update-one-field-metadata.util';
|
||||
import {
|
||||
LISTING_NAME_PLURAL,
|
||||
LISTING_NAME_SINGULAR,
|
||||
} from 'test/integration/metadata/suites/object-metadata/constants/test-object-names.constant';
|
||||
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 { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import {
|
||||
type FieldMetadataComplexOption,
|
||||
type FieldMetadataDefaultOption,
|
||||
@@ -30,6 +28,23 @@ describe.each(fieldMetadataEnumTypes)(
|
||||
return;
|
||||
}
|
||||
const { successful: successfulTestCases } = testCases;
|
||||
|
||||
beforeAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: false,
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: true,
|
||||
});
|
||||
});
|
||||
|
||||
const initialOptions: CreateOneFieldFactoryInput['options'] = [
|
||||
{
|
||||
label: 'Option 1',
|
||||
@@ -49,10 +64,10 @@ describe.each(fieldMetadataEnumTypes)(
|
||||
const { data } = await createOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
labelSingular: LISTING_NAME_SINGULAR,
|
||||
labelPlural: LISTING_NAME_PLURAL,
|
||||
nameSingular: LISTING_NAME_SINGULAR,
|
||||
namePlural: LISTING_NAME_PLURAL,
|
||||
labelSingular: 'successUpdateEnumField',
|
||||
labelPlural: 'successUpdateEnumFields',
|
||||
nameSingular: 'successUpdateEnumField',
|
||||
namePlural: 'successUpdateEnumFields',
|
||||
icon: 'IconBuildingSkyscraper',
|
||||
isLabelSyncedWithName: false,
|
||||
},
|
||||
|
||||
+49
@@ -1,6 +1,8 @@
|
||||
import { createMorphRelationBetweenObjects } from 'test/integration/metadata/suites/object-metadata/utils/create-morph-relation-between-objects.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 {
|
||||
eachTestingContextFilter,
|
||||
type EachTestingContext,
|
||||
@@ -9,11 +11,29 @@ import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
|
||||
describe('createOne FieldMetadataService morph relation fields', () => {
|
||||
let createdObjectMetadataPersonId = '';
|
||||
let createdObjectMetadataOpportunityId = '';
|
||||
let createdObjectMetadataCompanyId = '';
|
||||
|
||||
beforeAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: false,
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: true,
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
const {
|
||||
data: {
|
||||
@@ -67,14 +87,43 @@ describe('createOne FieldMetadataService morph relation fields', () => {
|
||||
createdObjectMetadataOpportunityId = objectMetadataOpportunityId;
|
||||
});
|
||||
afterEach(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataPersonId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: createdObjectMetadataPersonId },
|
||||
});
|
||||
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataOpportunityId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: createdObjectMetadataOpportunityId },
|
||||
});
|
||||
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataCompanyId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: createdObjectMetadataCompanyId },
|
||||
|
||||
+30
@@ -3,6 +3,7 @@ import { updateOneFieldMetadata } from 'test/integration/metadata/suites/field-m
|
||||
import { createMorphRelationBetweenObjects } from 'test/integration/metadata/suites/object-metadata/utils/create-morph-relation-between-objects.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 { type EachTestingContext } from 'twenty-shared/testing';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
@@ -63,12 +64,41 @@ describe('deleteOne FieldMetadataService morph relation fields', () => {
|
||||
createdObjectMetadataOpportunityId = objectMetadataOpportunityId;
|
||||
});
|
||||
afterEach(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataPersonId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: createdObjectMetadataPersonId },
|
||||
});
|
||||
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataOpportunityId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: createdObjectMetadataOpportunityId },
|
||||
});
|
||||
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataCompanyId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: createdObjectMetadataCompanyId },
|
||||
});
|
||||
|
||||
+10
-28
@@ -3,7 +3,6 @@ import { createOneFieldMetadata } from 'test/integration/metadata/suites/field-m
|
||||
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 { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any';
|
||||
import {
|
||||
eachTestingContextFilter,
|
||||
@@ -13,9 +12,7 @@ import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { type CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
||||
import { SEED_APPLE_WORKSPACE_ID } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-workspaces.util';
|
||||
|
||||
type FailingTestCases = EachTestingContext<
|
||||
(args: {
|
||||
@@ -351,13 +348,6 @@ describe('failing createOne FieldMetadataService morph relation fields v2', () =
|
||||
let createdObjectMetadataCompanyId: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: true,
|
||||
workspaceId: SEED_APPLE_WORKSPACE_ID,
|
||||
});
|
||||
|
||||
const {
|
||||
data: {
|
||||
createOneObject: { id: objectMetadataPersonId },
|
||||
@@ -417,25 +407,17 @@ describe('failing createOne FieldMetadataService morph relation fields v2', () =
|
||||
createdObjectMetadataCompanyId,
|
||||
];
|
||||
|
||||
try {
|
||||
for (const objectMetadataId of createdObjectMetadataIds) {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: objectMetadataId,
|
||||
updatePayload: { isActive: false },
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: objectMetadataId },
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
await updateFeatureFlag({
|
||||
for (const objectMetadataId of createdObjectMetadataIds) {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: false,
|
||||
input: {
|
||||
idToUpdate: objectMetadataId,
|
||||
updatePayload: { isActive: false },
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: objectMetadataId },
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
+18
@@ -5,9 +5,11 @@ import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object
|
||||
import { getMockCreateObjectInput } from 'test/integration/metadata/suites/object-metadata/utils/generate-mock-create-object-metadata-input';
|
||||
import { type EachTestingContext } from 'twenty-shared/testing';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { updateFeatureFlag } from 'test/integration/metadata/suites/utils/update-feature-flag.util';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { type CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
||||
|
||||
type GlobalTestContext = {
|
||||
@@ -42,6 +44,14 @@ type CreateOneObjectMetadataItemTestingContext = EachTestingContext<
|
||||
| ((context: GlobalTestContext) => TestedRelationCreationPayload)
|
||||
>[];
|
||||
describe('Field metadata morph relation creation should fail', () => {
|
||||
beforeAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: false,
|
||||
});
|
||||
});
|
||||
|
||||
const failingLabelsCreationTestsUseCase: CreateOneObjectMetadataItemTestingContext =
|
||||
[
|
||||
{
|
||||
@@ -147,6 +157,14 @@ describe('Field metadata morph relation creation should fail', () => {
|
||||
}
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: true,
|
||||
});
|
||||
});
|
||||
|
||||
it.each(failingLabelsCreationTestsUseCase)(
|
||||
'relation ONE_TO_MANY $title',
|
||||
async ({ context }) => {
|
||||
|
||||
+30
@@ -4,6 +4,7 @@ import { deleteOneFieldMetadata } from 'test/integration/metadata/suites/field-m
|
||||
import { createMorphRelationBetweenObjects } from 'test/integration/metadata/suites/object-metadata/utils/create-morph-relation-between-objects.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 { type EachTestingContext } from 'twenty-shared/testing';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
@@ -65,12 +66,41 @@ xdescribe('findMany morph relation records', () => {
|
||||
createdObjectMetadataOpportunityId = objectMetadataOpportunityId;
|
||||
});
|
||||
afterEach(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataPersonId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: createdObjectMetadataPersonId },
|
||||
});
|
||||
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataOpportunityId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: createdObjectMetadataOpportunityId },
|
||||
});
|
||||
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataCompanyId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: createdObjectMetadataCompanyId },
|
||||
});
|
||||
|
||||
+10
-28
@@ -4,7 +4,6 @@ import { updateOneFieldMetadata } from 'test/integration/metadata/suites/field-m
|
||||
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 {
|
||||
eachTestingContextFilter,
|
||||
type EachTestingContext,
|
||||
@@ -14,11 +13,9 @@ import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { type CreateFieldInput } from 'src/engine/metadata-modules/field-metadata/dtos/create-field.input';
|
||||
import { type FieldMetadataDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto';
|
||||
import { type RelationDTO } from 'src/engine/metadata-modules/field-metadata/dtos/relation.dto';
|
||||
import { SEED_APPLE_WORKSPACE_ID } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-workspaces.util';
|
||||
|
||||
type EachTestingContextArray = EachTestingContext<
|
||||
(args: {
|
||||
@@ -96,13 +93,6 @@ describe('successful createOne FieldMetadataService morph relation fields v2', (
|
||||
let createdFieldMetadataId: string | undefined = undefined;
|
||||
|
||||
beforeAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: true,
|
||||
workspaceId: SEED_APPLE_WORKSPACE_ID,
|
||||
});
|
||||
|
||||
const {
|
||||
data: {
|
||||
createOneObject: { id: objectMetadataPersonId },
|
||||
@@ -162,25 +152,17 @@ describe('successful createOne FieldMetadataService morph relation fields v2', (
|
||||
createdObjectMetadataCompanyId,
|
||||
];
|
||||
|
||||
try {
|
||||
for (const objectMetadataId of createdObjectMetadataIds) {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: objectMetadataId,
|
||||
updatePayload: { isActive: false },
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: objectMetadataId },
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
await updateFeatureFlag({
|
||||
for (const objectMetadataId of createdObjectMetadataIds) {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: false,
|
||||
input: {
|
||||
idToUpdate: objectMetadataId,
|
||||
updatePayload: { isActive: false },
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: objectMetadataId },
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
+10
-29
@@ -4,14 +4,10 @@ import { updateOneFieldMetadata } from 'test/integration/metadata/suites/field-m
|
||||
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 { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { SEED_APPLE_WORKSPACE_ID } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-workspaces.util';
|
||||
|
||||
describe('updateOne FieldMetadataService morph relation fields v2', () => {
|
||||
let createdObjectMetadataPersonId: string;
|
||||
let createdObjectMetadataOpportunityId: string;
|
||||
@@ -19,13 +15,6 @@ describe('updateOne FieldMetadataService morph relation fields v2', () => {
|
||||
let createdFieldMetadataId: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: true,
|
||||
workspaceId: SEED_APPLE_WORKSPACE_ID,
|
||||
});
|
||||
|
||||
const {
|
||||
data: {
|
||||
createOneObject: { id: objectMetadataPersonId },
|
||||
@@ -85,25 +74,17 @@ describe('updateOne FieldMetadataService morph relation fields v2', () => {
|
||||
createdObjectMetadataCompanyId,
|
||||
];
|
||||
|
||||
try {
|
||||
for (const objectMetadataId of createdObjectMetadataIds) {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: objectMetadataId,
|
||||
updatePayload: { isActive: false },
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: objectMetadataId },
|
||||
});
|
||||
}
|
||||
} finally {
|
||||
await updateFeatureFlag({
|
||||
for (const objectMetadataId of createdObjectMetadataIds) {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: false,
|
||||
input: {
|
||||
idToUpdate: objectMetadataId,
|
||||
updatePayload: { isActive: false },
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: objectMetadataId },
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
+11
-1
@@ -2,10 +2,11 @@ import { faker } from '@faker-js/faker';
|
||||
import { type CountryCode } from 'libphonenumber-js';
|
||||
import { createOneOperation } from 'test/integration/graphql/utils/create-one-operation.util';
|
||||
import { createOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/create-one-field-metadata.util';
|
||||
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
|
||||
import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util';
|
||||
import { updateOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata.util';
|
||||
import { type EachTestingContext } from 'twenty-shared/testing';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
|
||||
|
||||
import {
|
||||
type AdditionalPhoneMetadata,
|
||||
@@ -355,6 +356,15 @@ describe('Phone field metadata tests suite', () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: createdObjectMetadataId },
|
||||
});
|
||||
|
||||
+848
-80
File diff suppressed because it is too large
Load Diff
+124
-8
@@ -5,11 +5,57 @@ exports[`Field metadata relation update should fail relation when name is change
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "An error occurred.",
|
||||
"errors": {
|
||||
"index": [],
|
||||
"objectMetadata": [
|
||||
{
|
||||
"errors": [
|
||||
{
|
||||
"code": "FIELD_MUTATION_NOT_ALLOWED",
|
||||
"message": "Forbidden updated properties for relation field metadata: name",
|
||||
"userFriendlyMessage": "Forbidden updated properties for relation field metadata",
|
||||
},
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "newName",
|
||||
"objectMetadataId": Any<String>,
|
||||
},
|
||||
"type": "update_field",
|
||||
},
|
||||
{
|
||||
"errors": [
|
||||
{
|
||||
"code": "FIELD_MUTATION_NOT_ALLOWED",
|
||||
"message": "Forbidden updated properties for relation field metadata: name",
|
||||
"userFriendlyMessage": "Forbidden updated properties for relation field metadata",
|
||||
},
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "newName",
|
||||
"objectMetadataId": Any<String>,
|
||||
},
|
||||
"type": "update_field",
|
||||
},
|
||||
],
|
||||
"serverlessFunction": [],
|
||||
"view": [],
|
||||
"viewField": [],
|
||||
},
|
||||
"message": "Validation failed for 0 object(s) and 0 field(s)",
|
||||
"summary": {
|
||||
"invalidIndex": 0,
|
||||
"invalidObjectMetadata": 0,
|
||||
"invalidServerlessFunction": 0,
|
||||
"invalidView": 0,
|
||||
"invalidViewField": 0,
|
||||
"totalErrors": 0,
|
||||
},
|
||||
"userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)",
|
||||
},
|
||||
"message": "Name cannot be changed for relation fields",
|
||||
"name": "UserInputError",
|
||||
"message": "Multiple validation errors occurred while updating field",
|
||||
"name": "GraphQLError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
@@ -19,11 +65,81 @@ exports[`Field metadata relation update should fail relation when name is not in
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_FIELD_INPUT",
|
||||
"userFriendlyMessage": "An error occurred.",
|
||||
"errors": {
|
||||
"index": [],
|
||||
"objectMetadata": [
|
||||
{
|
||||
"errors": [
|
||||
{
|
||||
"code": "FIELD_MUTATION_NOT_ALLOWED",
|
||||
"message": "Forbidden updated properties for relation field metadata: name",
|
||||
"userFriendlyMessage": "Forbidden updated properties for relation field metadata",
|
||||
},
|
||||
{
|
||||
"code": "INVALID_FIELD_INPUT",
|
||||
"message": "Name should be in camelCase",
|
||||
"userFriendlyMessage": "Name should be in camelCase",
|
||||
"value": "New Name",
|
||||
},
|
||||
{
|
||||
"code": "INVALID_FIELD_INPUT",
|
||||
"message": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters",
|
||||
"userFriendlyMessage": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters",
|
||||
"value": "New Name",
|
||||
},
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "New Name",
|
||||
"objectMetadataId": Any<String>,
|
||||
},
|
||||
"type": "update_field",
|
||||
},
|
||||
{
|
||||
"errors": [
|
||||
{
|
||||
"code": "FIELD_MUTATION_NOT_ALLOWED",
|
||||
"message": "Forbidden updated properties for relation field metadata: name",
|
||||
"userFriendlyMessage": "Forbidden updated properties for relation field metadata",
|
||||
},
|
||||
{
|
||||
"code": "INVALID_FIELD_INPUT",
|
||||
"message": "Name should be in camelCase",
|
||||
"userFriendlyMessage": "Name should be in camelCase",
|
||||
"value": "New Name",
|
||||
},
|
||||
{
|
||||
"code": "INVALID_FIELD_INPUT",
|
||||
"message": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters",
|
||||
"userFriendlyMessage": "Name is not valid: it must start with lowercase letter and contain only alphanumeric letters",
|
||||
"value": "New Name",
|
||||
},
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"name": "New Name",
|
||||
"objectMetadataId": Any<String>,
|
||||
},
|
||||
"type": "update_field",
|
||||
},
|
||||
],
|
||||
"serverlessFunction": [],
|
||||
"view": [],
|
||||
"viewField": [],
|
||||
},
|
||||
"message": "Validation failed for 0 object(s) and 0 field(s)",
|
||||
"summary": {
|
||||
"invalidIndex": 0,
|
||||
"invalidObjectMetadata": 0,
|
||||
"invalidServerlessFunction": 0,
|
||||
"invalidView": 0,
|
||||
"invalidViewField": 0,
|
||||
"totalErrors": 0,
|
||||
},
|
||||
"userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)",
|
||||
},
|
||||
"message": "New Name should be in camelCase",
|
||||
"name": "UserInputError",
|
||||
"message": "Multiple validation errors occurred while updating field",
|
||||
"name": "GraphQLError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
+81
-69
@@ -1,17 +1,16 @@
|
||||
import { deleteOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/delete-one-field-metadata.util';
|
||||
import { findManyFieldsMetadata } from 'test/integration/metadata/suites/field-metadata/utils/find-many-fields-metadata.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 { type EachTestingContext } from 'twenty-shared/testing';
|
||||
import { updateOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata.util';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { findManyFieldsMetadata } from 'test/integration/metadata/suites/field-metadata/utils/find-many-fields-metadata.util';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
describe('createOne FieldMetadataService relation fields', () => {
|
||||
let createdObjectMetadataPersonId = '';
|
||||
let createdObjectMetadataOpportunityId = '';
|
||||
let createdObjectMetadataPersonId: string;
|
||||
let createdObjectMetadataOpportunityId: string;
|
||||
|
||||
beforeEach(async () => {
|
||||
const {
|
||||
@@ -19,6 +18,7 @@ describe('createOne FieldMetadataService relation fields', () => {
|
||||
createOneObject: { id: objectMetadataPersonId },
|
||||
},
|
||||
} = await createOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
nameSingular: 'personForRelation',
|
||||
namePlural: 'peopleForRelation',
|
||||
@@ -35,6 +35,7 @@ describe('createOne FieldMetadataService relation fields', () => {
|
||||
createOneObject: { id: objectMetadataOpportunityId },
|
||||
},
|
||||
} = await createOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
nameSingular: 'opportunityForRelation',
|
||||
namePlural: 'opportunitiesForRelation',
|
||||
@@ -47,72 +48,50 @@ describe('createOne FieldMetadataService relation fields', () => {
|
||||
createdObjectMetadataOpportunityId = objectMetadataOpportunityId;
|
||||
});
|
||||
afterEach(async () => {
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: createdObjectMetadataPersonId },
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataPersonId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: createdObjectMetadataPersonId },
|
||||
});
|
||||
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataOpportunityId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: createdObjectMetadataOpportunityId },
|
||||
});
|
||||
});
|
||||
|
||||
type EachTestingContextArray = EachTestingContext<
|
||||
(args: { objectMetadataId: string; targetObjectMetadataId: string }) => {
|
||||
relationType: RelationType;
|
||||
objectMetadataId: string;
|
||||
targetObjectMetadataId: string;
|
||||
type: FieldMetadataType.RELATION | FieldMetadataType.MORPH_RELATION;
|
||||
}
|
||||
>[];
|
||||
|
||||
const eachTestingContextArray: EachTestingContextArray = [
|
||||
{
|
||||
title: 'should create a RELATION field type MANY_TO_ONE',
|
||||
context: ({ objectMetadataId, targetObjectMetadataId }) => ({
|
||||
relationType: RelationType.MANY_TO_ONE,
|
||||
objectMetadataId,
|
||||
targetObjectMetadataId,
|
||||
type: FieldMetadataType.RELATION,
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: 'should create a RELATION field type ONE_TO_MANY',
|
||||
context: ({ objectMetadataId, targetObjectMetadataId }) => ({
|
||||
relationType: RelationType.ONE_TO_MANY,
|
||||
objectMetadataId,
|
||||
targetObjectMetadataId,
|
||||
type: FieldMetadataType.RELATION,
|
||||
}),
|
||||
},
|
||||
];
|
||||
|
||||
it.each(eachTestingContextArray)('$title', async ({ context }) => {
|
||||
const contextPayload = context({
|
||||
it('MANY TO ONE field relation creation', async () => {
|
||||
const createdField = await createRelationBetweenObjects({
|
||||
objectMetadataId: createdObjectMetadataOpportunityId,
|
||||
targetObjectMetadataId: createdObjectMetadataPersonId,
|
||||
});
|
||||
|
||||
const createdField = await createRelationBetweenObjects<
|
||||
typeof contextPayload.type
|
||||
>({
|
||||
objectMetadataId: contextPayload.objectMetadataId,
|
||||
targetObjectMetadataId: contextPayload.targetObjectMetadataId,
|
||||
type: contextPayload.type,
|
||||
relationType: contextPayload.relationType,
|
||||
relationType: RelationType.MANY_TO_ONE,
|
||||
type: FieldMetadataType.RELATION,
|
||||
name: 'person',
|
||||
});
|
||||
|
||||
expect(createdField.id).toBeDefined();
|
||||
expect(createdField.name).toBe('person');
|
||||
expect(createdField.relation?.type).toBe(contextPayload.relationType);
|
||||
expect(createdField.relation?.type).toBe(RelationType.MANY_TO_ONE);
|
||||
expect(createdField.relation?.targetFieldMetadata.id).toBeDefined();
|
||||
// TODO: expect(createdField.morphRelations).toBeUndefined();
|
||||
const isManyToOne =
|
||||
contextPayload.relationType === RelationType.MANY_TO_ONE;
|
||||
|
||||
if (isManyToOne) {
|
||||
expect(createdField.settings?.joinColumnName).toBe('personId');
|
||||
} else {
|
||||
expect(createdField.settings?.joinColumnName).toBeUndefined();
|
||||
}
|
||||
expect(createdField.settings?.joinColumnName).toBe('personId');
|
||||
|
||||
if (!isDefined(createdField.relation?.targetFieldMetadata?.id)) {
|
||||
throw new Error('targetFieldMetadata.id is not defined');
|
||||
@@ -126,7 +105,46 @@ describe('createOne FieldMetadataService relation fields', () => {
|
||||
'personForRelation',
|
||||
);
|
||||
expect(opportunityFieldOnPerson.relation.type).toBe(
|
||||
isManyToOne ? RelationType.ONE_TO_MANY : RelationType.MANY_TO_ONE,
|
||||
RelationType.ONE_TO_MANY,
|
||||
);
|
||||
expect(
|
||||
opportunityFieldOnPerson.relation.targetFieldMetadata.id,
|
||||
).toBeDefined();
|
||||
expect(
|
||||
opportunityFieldOnPerson.relation.targetObjectMetadata.id,
|
||||
).toBeDefined();
|
||||
expect(opportunityFieldOnPerson.settings?.joinColumnName).toBeUndefined();
|
||||
});
|
||||
|
||||
it('ONE TO MANY field relation creation', async () => {
|
||||
const createdField = await createRelationBetweenObjects({
|
||||
objectMetadataId: createdObjectMetadataOpportunityId,
|
||||
targetObjectMetadataId: createdObjectMetadataPersonId,
|
||||
relationType: RelationType.ONE_TO_MANY,
|
||||
type: FieldMetadataType.RELATION,
|
||||
name: 'person',
|
||||
});
|
||||
|
||||
expect(createdField.id).toBeDefined();
|
||||
expect(createdField.name).toBe('person');
|
||||
expect(createdField.relation?.type).toBe(RelationType.ONE_TO_MANY);
|
||||
expect(createdField.relation?.targetFieldMetadata.id).toBeDefined();
|
||||
|
||||
expect(createdField.settings?.joinColumnName).toBeUndefined();
|
||||
|
||||
if (!isDefined(createdField.relation?.targetFieldMetadata?.id)) {
|
||||
throw new Error('targetFieldMetadata.id is not defined');
|
||||
}
|
||||
|
||||
const opportunityFieldOnPerson = await findFieldMetadata({
|
||||
fieldMetadataId: createdField.relation.targetFieldMetadata.id,
|
||||
});
|
||||
|
||||
expect(opportunityFieldOnPerson.object.nameSingular).toBe(
|
||||
'personForRelation',
|
||||
);
|
||||
expect(opportunityFieldOnPerson.relation.type).toBe(
|
||||
RelationType.MANY_TO_ONE,
|
||||
);
|
||||
expect(
|
||||
opportunityFieldOnPerson.relation.targetFieldMetadata.id,
|
||||
@@ -135,17 +153,9 @@ describe('createOne FieldMetadataService relation fields', () => {
|
||||
opportunityFieldOnPerson.relation.targetObjectMetadata.id,
|
||||
).toBeDefined();
|
||||
|
||||
if (!isManyToOne) {
|
||||
expect(opportunityFieldOnPerson.settings?.joinColumnName).toBe(
|
||||
'opportunityId',
|
||||
);
|
||||
} else {
|
||||
expect(opportunityFieldOnPerson.settings?.joinColumnName).toBeUndefined();
|
||||
}
|
||||
|
||||
await deleteOneFieldMetadata({
|
||||
input: { idToDelete: createdField.id },
|
||||
}).catch();
|
||||
expect(opportunityFieldOnPerson.settings?.joinColumnName).toBe(
|
||||
'opportunityId',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -181,6 +191,8 @@ const findFieldMetadata = async ({
|
||||
settings
|
||||
`,
|
||||
});
|
||||
|
||||
expect(fields.length).toBe(1);
|
||||
const field = fields[0]?.node;
|
||||
|
||||
return field;
|
||||
|
||||
+17
-2
@@ -3,8 +3,10 @@ import { createOneFieldMetadata } from 'test/integration/metadata/suites/field-m
|
||||
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 { getMockCreateObjectInput } from 'test/integration/metadata/suites/object-metadata/utils/generate-mock-create-object-metadata-input';
|
||||
import { updateOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata.util';
|
||||
import { type EachTestingContext } from 'twenty-shared/testing';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
@@ -232,6 +234,15 @@ describe('Field metadata relation creation should fail', () => {
|
||||
for (const objectMetadataId of Object.values(
|
||||
globalTestContext.objectMetadataIds,
|
||||
)) {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: objectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: {
|
||||
idToDelete: objectMetadataId,
|
||||
@@ -273,7 +284,9 @@ describe('Field metadata relation creation should fail', () => {
|
||||
});
|
||||
|
||||
expect(errors).toBeDefined();
|
||||
expect(errors).toMatchSnapshot();
|
||||
expect(errors).toMatchSnapshot(
|
||||
extractRecordIdsAndDatesAsExpectAny(errors),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
@@ -310,7 +323,9 @@ describe('Field metadata relation creation should fail', () => {
|
||||
});
|
||||
|
||||
expect(errors).toBeDefined();
|
||||
expect(errors).toMatchSnapshot();
|
||||
expect(errors).toMatchSnapshot(
|
||||
extractRecordIdsAndDatesAsExpectAny(errors),
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
+14
-1
@@ -3,8 +3,10 @@ import { updateOneFieldMetadata } from 'test/integration/metadata/suites/field-m
|
||||
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 { getMockCreateObjectInput } from 'test/integration/metadata/suites/object-metadata/utils/generate-mock-create-object-metadata-input';
|
||||
import { updateOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata.util';
|
||||
import { type EachTestingContext } from 'twenty-shared/testing';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
@@ -82,6 +84,15 @@ describe('Field metadata relation update should fail', () => {
|
||||
globalTestContext.employeeObjectId,
|
||||
globalTestContext.enterpriseObjectId,
|
||||
]) {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: objectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: {
|
||||
idToDelete: objectMetadataId,
|
||||
@@ -104,7 +115,9 @@ describe('Field metadata relation update should fail', () => {
|
||||
});
|
||||
|
||||
expect(errors).toBeDefined();
|
||||
expect(errors).toMatchSnapshot();
|
||||
expect(errors).toMatchSnapshot(
|
||||
extractRecordIdsAndDatesAsExpectAny(errors),
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
+10
@@ -3,6 +3,7 @@ import { updateOneFieldMetadata } from 'test/integration/metadata/suites/field-m
|
||||
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 { getMockCreateObjectInput } from 'test/integration/metadata/suites/object-metadata/utils/generate-mock-create-object-metadata-input';
|
||||
import { updateOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata.util';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
@@ -65,6 +66,15 @@ describe('Field metadata relation update should succeed', () => {
|
||||
globalTestContext.employeeObjectId,
|
||||
globalTestContext.enterpriseObjectId,
|
||||
]) {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: objectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: {
|
||||
idToDelete: objectMetadataId,
|
||||
|
||||
+29
@@ -1,11 +1,23 @@
|
||||
import { createOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/create-one-field-metadata.util';
|
||||
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
|
||||
import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util';
|
||||
import { 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 { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
|
||||
describe('create one unique field metadata', () => {
|
||||
let createdObjectMetadataId = '';
|
||||
|
||||
beforeAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: false,
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
const {
|
||||
data: {
|
||||
@@ -25,11 +37,28 @@ describe('create one unique field metadata', () => {
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: createdObjectMetadataId },
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('should create one unique field metadata', async () => {
|
||||
const createFieldInput = {
|
||||
name: 'uniqueTestField',
|
||||
|
||||
+29
@@ -4,8 +4,12 @@ import { createOneFieldMetadata } from 'test/integration/metadata/suites/field-m
|
||||
import { updateOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/update-one-field-metadata.util';
|
||||
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
|
||||
import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util';
|
||||
import { 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 { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
|
||||
const createRecordQuery = gql`
|
||||
mutation CreateFirstRecord($data: TestRecordObjectCreateInput!) {
|
||||
createTestRecordObject(data: $data) {
|
||||
@@ -19,6 +23,22 @@ describe('create records with custom unique fields', () => {
|
||||
let createdObjectMetadataId = '';
|
||||
let uniqueFieldId = '';
|
||||
|
||||
beforeAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: false,
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: true,
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
const {
|
||||
data: {
|
||||
@@ -57,6 +77,15 @@ describe('create records with custom unique fields', () => {
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: createdObjectMetadataId },
|
||||
});
|
||||
|
||||
+29
@@ -3,11 +3,31 @@ import { deleteOneFieldMetadata } from 'test/integration/metadata/suites/field-m
|
||||
import { updateOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/update-one-field-metadata.util';
|
||||
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
|
||||
import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util';
|
||||
import { 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 { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
|
||||
describe('update one unique field metadata', () => {
|
||||
let createdObjectId = '';
|
||||
|
||||
beforeAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: false,
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: true,
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
const {
|
||||
data: {
|
||||
@@ -27,6 +47,15 @@ describe('update one unique field metadata', () => {
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: createdObjectId },
|
||||
});
|
||||
|
||||
+31
@@ -4,6 +4,7 @@ import { updateOneFieldMetadata } from 'test/integration/metadata/suites/field-m
|
||||
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 { getMockCreateObjectInput } from 'test/integration/metadata/suites/object-metadata/utils/generate-mock-create-object-metadata-input';
|
||||
import { updateOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata.util';
|
||||
import {
|
||||
createTestViewFilterWithRestApi,
|
||||
createTestViewWithRestApi,
|
||||
@@ -15,7 +16,9 @@ import {
|
||||
FieldMetadataType,
|
||||
} from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { updateFeatureFlag } from 'test/integration/metadata/suites/utils/update-feature-flag.util';
|
||||
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { ViewFilterOperand } from 'src/engine/core-modules/view/enums/view-filter-operand';
|
||||
import { ViewType } from 'src/engine/core-modules/view/enums/view-type.enum';
|
||||
import { type ViewFilterValue } from 'src/engine/core-modules/view/types/view-filter-value.type';
|
||||
@@ -69,6 +72,22 @@ const testFieldMetadataType: EnumFieldMetadataType[] = [
|
||||
describe('update-one-field-metadata-related-record', () => {
|
||||
let idToDelete: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: false,
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: true,
|
||||
});
|
||||
});
|
||||
|
||||
const createObjectSelectFieldAndView = async ({
|
||||
options,
|
||||
type: fieldMetadataType,
|
||||
@@ -78,6 +97,7 @@ describe('update-one-field-metadata-related-record', () => {
|
||||
const {
|
||||
data: { createOneObject },
|
||||
} = await createOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: getMockCreateObjectInput({
|
||||
labelSingular: singular,
|
||||
labelPlural: plural,
|
||||
@@ -92,6 +112,7 @@ describe('update-one-field-metadata-related-record', () => {
|
||||
const {
|
||||
data: { createOneField },
|
||||
} = await createOneFieldMetadata<typeof fieldMetadataType>({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
objectMetadataId: createOneObject.id,
|
||||
type: fieldMetadataType,
|
||||
@@ -118,7 +139,17 @@ describe('update-one-field-metadata-related-record', () => {
|
||||
|
||||
afterEach(async () => {
|
||||
if (isDefined(idToDelete)) {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: idToDelete,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: idToDelete },
|
||||
});
|
||||
}
|
||||
|
||||
+27
-7
@@ -6,6 +6,8 @@ import {
|
||||
} from 'test/integration/metadata/suites/object-metadata/constants/test-object-names.constant';
|
||||
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 { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
describe('updateOne', () => {
|
||||
@@ -42,6 +44,15 @@ describe('updateOne', () => {
|
||||
testFieldId = createdFieldMetadata.createOneField.id;
|
||||
});
|
||||
afterEach(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: listingObjectId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: listingObjectId },
|
||||
@@ -128,6 +139,15 @@ describe('updateOne', () => {
|
||||
testFieldId = createdFieldMetadata.createOneField.id;
|
||||
});
|
||||
afterAll(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: listingObjectId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: listingObjectId },
|
||||
@@ -153,14 +173,14 @@ describe('updateOne', () => {
|
||||
expectToFail: true,
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(errors[0].message).toBe(
|
||||
'Name is not synced with label. Expected name: "testName", got newName',
|
||||
expect(errors).toMatchSnapshot(
|
||||
extractRecordIdsAndDatesAsExpectAny(errors),
|
||||
);
|
||||
});
|
||||
|
||||
it('should throw if the field name is not available because of other field with the same name', async () => {
|
||||
await createOneFieldMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
objectMetadataId: listingObjectId,
|
||||
type: FieldMetadataType.TEXT,
|
||||
@@ -170,15 +190,15 @@ describe('updateOne', () => {
|
||||
});
|
||||
|
||||
const { errors } = await updateOneFieldMetadata({
|
||||
expectToFail: true,
|
||||
input: {
|
||||
idToUpdate: testFieldId,
|
||||
updatePayload: { name: 'testName' },
|
||||
updatePayload: { name: 'otherTestName' },
|
||||
},
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(errors[0].message).toBe(
|
||||
'Name "testName" is not available, check that it is not duplicating another field\'s name.',
|
||||
expect(errors).toMatchSnapshot(
|
||||
extractRecordIdsAndDatesAsExpectAny(errors),
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
-19
@@ -3,12 +3,9 @@ import { createOneObjectMetadata } from 'test/integration/metadata/suites/object
|
||||
import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util';
|
||||
import { findManyObjectMetadataWithIndexes } from 'test/integration/metadata/suites/object-metadata/utils/find-many-object-metadata-with-indexes.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 { jestExpectToBeDefined } from 'test/utils/expect-to-be-defined.util.test';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
|
||||
const findObjectWithIndex = async ({
|
||||
objectMetadataId,
|
||||
}: {
|
||||
@@ -29,22 +26,6 @@ const findObjectWithIndex = async ({
|
||||
describe('Index metadata creation through object metadata creation v2', () => {
|
||||
let createdObjectId: string;
|
||||
|
||||
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,
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
const {
|
||||
labelPlural,
|
||||
|
||||
+3
-22
@@ -1,39 +1,20 @@
|
||||
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, RelationType } from 'twenty-shared/types';
|
||||
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 { updateOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/update-one-field-metadata.util';
|
||||
import { CUSTOM_OBJECT_DISHES } from 'test/integration/metadata/suites/object-metadata/constants/custom-object-dishes.constants';
|
||||
import { CUSTOM_OBJECT_FOOD } from 'test/integration/metadata/suites/object-metadata/constants/custom-object-food.constants';
|
||||
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 { findManyObjectMetadataWithIndexes } from 'test/integration/metadata/suites/object-metadata/utils/find-many-object-metadata-with-indexes.util';
|
||||
import { updateOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata.util';
|
||||
import { jestExpectToBeDefined } from 'test/utils/expect-to-be-defined.util.test';
|
||||
import { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any';
|
||||
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { FieldMetadataType, RelationType } from 'twenty-shared/types';
|
||||
|
||||
describe('Index metadata creation on relation field creation v2', () => {
|
||||
let createdObjectId: string;
|
||||
let secondCreatedObjectId: string;
|
||||
|
||||
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,
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
const {
|
||||
labelPlural,
|
||||
|
||||
+117
-8
@@ -5,11 +5,43 @@ exports[`Object metadata update should fail when labelIdentifier is not a TEXT o
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_OBJECT_INPUT",
|
||||
"userFriendlyMessage": "An error occurred.",
|
||||
"errors": {
|
||||
"index": [],
|
||||
"objectMetadata": [
|
||||
{
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_OBJECT_INPUT",
|
||||
"message": "Label identifier field metadata must be a TEXT or FULL_NAME field type",
|
||||
"userFriendlyMessage": "Label identifier field metadata must be a TEXT or FULL_NAME field type",
|
||||
"value": "NUMBER",
|
||||
},
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"namePlural": "whatevers",
|
||||
"nameSingular": "whatever",
|
||||
},
|
||||
"type": "update_object",
|
||||
},
|
||||
],
|
||||
"serverlessFunction": [],
|
||||
"view": [],
|
||||
"viewField": [],
|
||||
},
|
||||
"message": "Validation failed for 0 object(s) and 0 field(s)",
|
||||
"summary": {
|
||||
"invalidIndex": 0,
|
||||
"invalidObjectMetadata": 0,
|
||||
"invalidServerlessFunction": 0,
|
||||
"invalidView": 0,
|
||||
"invalidViewField": 0,
|
||||
"totalErrors": 0,
|
||||
},
|
||||
"userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)",
|
||||
},
|
||||
"message": "labelIdentifierFieldMetadataId validation failed: it must be a TEXT or FULL_NAME field metadata type id",
|
||||
"name": "UserInputError",
|
||||
"message": "Multiple validation errors occurred while updating object",
|
||||
"name": "GraphQLError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
@@ -19,11 +51,43 @@ exports[`Object metadata update should fail when labelIdentifier is not a known
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"subCode": "INVALID_OBJECT_INPUT",
|
||||
"userFriendlyMessage": "An error occurred.",
|
||||
"errors": {
|
||||
"index": [],
|
||||
"objectMetadata": [
|
||||
{
|
||||
"errors": [
|
||||
{
|
||||
"code": "INVALID_OBJECT_INPUT",
|
||||
"message": "Label identifier field metadata not found in field metadata list",
|
||||
"userFriendlyMessage": "Label identifier field metadata not found in field metadata list",
|
||||
"value": "42422020-f49c-4159-8751-76a24f47b360",
|
||||
},
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"namePlural": "whatevers",
|
||||
"nameSingular": "whatever",
|
||||
},
|
||||
"type": "update_object",
|
||||
},
|
||||
],
|
||||
"serverlessFunction": [],
|
||||
"view": [],
|
||||
"viewField": [],
|
||||
},
|
||||
"message": "Validation failed for 0 object(s) and 0 field(s)",
|
||||
"summary": {
|
||||
"invalidIndex": 0,
|
||||
"invalidObjectMetadata": 0,
|
||||
"invalidServerlessFunction": 0,
|
||||
"invalidView": 0,
|
||||
"invalidViewField": 0,
|
||||
"totalErrors": 0,
|
||||
},
|
||||
"userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)",
|
||||
},
|
||||
"message": "labelIdentifierFieldMetadataId validation failed: related field metadata not found",
|
||||
"name": "UserInputError",
|
||||
"message": "Multiple validation errors occurred while updating object",
|
||||
"name": "GraphQLError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
@@ -43,3 +107,48 @@ exports[`Object metadata update should fail when labelIdentifier is not a uuid 1
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
exports[`Object metadata update should fail when labelIdentifier is null 1`] = `
|
||||
[
|
||||
{
|
||||
"extensions": {
|
||||
"code": "BAD_USER_INPUT",
|
||||
"errors": {
|
||||
"index": [],
|
||||
"objectMetadata": [
|
||||
{
|
||||
"errors": [
|
||||
{
|
||||
"code": "MISSING_CUSTOM_OBJECT_DEFAULT_LABEL_IDENTIFIER_FIELD",
|
||||
"message": "Label identifier field metadata is required",
|
||||
"userFriendlyMessage": "Label identifier field metadata is required",
|
||||
},
|
||||
],
|
||||
"flatEntityMinimalInformation": {
|
||||
"id": Any<String>,
|
||||
"namePlural": "whatevers",
|
||||
"nameSingular": "whatever",
|
||||
},
|
||||
"type": "update_object",
|
||||
},
|
||||
],
|
||||
"serverlessFunction": [],
|
||||
"view": [],
|
||||
"viewField": [],
|
||||
},
|
||||
"message": "Validation failed for 0 object(s) and 0 field(s)",
|
||||
"summary": {
|
||||
"invalidIndex": 0,
|
||||
"invalidObjectMetadata": 0,
|
||||
"invalidServerlessFunction": 0,
|
||||
"invalidView": 0,
|
||||
"invalidViewField": 0,
|
||||
"totalErrors": 0,
|
||||
},
|
||||
"userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)",
|
||||
},
|
||||
"message": "Multiple validation errors occurred while updating object",
|
||||
"name": "GraphQLError",
|
||||
},
|
||||
]
|
||||
`;
|
||||
|
||||
+1
-18
@@ -1,35 +1,18 @@
|
||||
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 { updateOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/update-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;
|
||||
|
||||
-21
@@ -4,10 +4,6 @@ import { createOneObjectMetadata } from 'test/integration/metadata/suites/object
|
||||
import { getMockCreateObjectInput } from 'test/integration/metadata/suites/object-metadata/utils/generate-mock-create-object-metadata-input';
|
||||
import { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any';
|
||||
import { eachTestingContextFilter } from 'twenty-shared/testing';
|
||||
import { updateFeatureFlag } from 'test/integration/metadata/suites/utils/update-feature-flag.util';
|
||||
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { SEED_APPLE_WORKSPACE_ID } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-workspaces.util';
|
||||
|
||||
const allTestsUseCases = [
|
||||
...OBJECT_METADATA_NAMES_FAILING_TEST_CASES,
|
||||
@@ -15,23 +11,6 @@ const allTestsUseCases = [
|
||||
];
|
||||
|
||||
describe('Object metadata creation should fail v2', () => {
|
||||
beforeAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: true,
|
||||
workspaceId: SEED_APPLE_WORKSPACE_ID,
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: false,
|
||||
workspaceId: SEED_APPLE_WORKSPACE_ID,
|
||||
});
|
||||
});
|
||||
it.each(eachTestingContextFilter(allTestsUseCases))(
|
||||
'$title',
|
||||
async ({ context }) => {
|
||||
|
||||
+23
-2
@@ -1,9 +1,12 @@
|
||||
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
|
||||
import { getMockCreateObjectInput } from 'test/integration/metadata/suites/object-metadata/utils/generate-mock-create-object-metadata-input';
|
||||
import { OBJECT_METADATA_LABEL_FAILING_TEST_CASES } from 'test/integration/metadata/suites/object-metadata/common/object-metadata-label-failing-tests-cases';
|
||||
import { OBJECT_METADATA_NAMES_FAILING_TEST_CASES } from 'test/integration/metadata/suites/object-metadata/common/object-metadata-names-failing-tests-cases';
|
||||
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
|
||||
import { getMockCreateObjectInput } from 'test/integration/metadata/suites/object-metadata/utils/generate-mock-create-object-metadata-input';
|
||||
import { updateFeatureFlag } from 'test/integration/metadata/suites/utils/update-feature-flag.util';
|
||||
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
import { ErrorCode } from 'src/engine/core-modules/graphql/utils/graphql-errors.util';
|
||||
import { SEED_APPLE_WORKSPACE_ID } from 'src/engine/workspace-manager/dev-seeder/core/utils/seed-workspaces.util';
|
||||
|
||||
const allTestsUseCases = [
|
||||
...OBJECT_METADATA_NAMES_FAILING_TEST_CASES,
|
||||
@@ -11,6 +14,24 @@ const allTestsUseCases = [
|
||||
];
|
||||
|
||||
describe('Object metadata creation should fail', () => {
|
||||
beforeAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: false,
|
||||
workspaceId: SEED_APPLE_WORKSPACE_ID,
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateFeatureFlag({
|
||||
expectToFail: false,
|
||||
featureFlag: FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED,
|
||||
value: true,
|
||||
workspaceId: SEED_APPLE_WORKSPACE_ID,
|
||||
});
|
||||
});
|
||||
|
||||
it.each(allTestsUseCases)('$title', async ({ context }) => {
|
||||
const { errors } = await createOneObjectMetadata({
|
||||
input: getMockCreateObjectInput(context),
|
||||
|
||||
+49
-19
@@ -1,10 +1,13 @@
|
||||
import { createOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/create-one-field-metadata.util';
|
||||
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
|
||||
import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util';
|
||||
import { getMockCreateObjectInput } from 'test/integration/metadata/suites/object-metadata/utils/generate-mock-create-object-metadata-input';
|
||||
import { updateOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata.util';
|
||||
import { type EachTestingContext } from 'twenty-shared/testing';
|
||||
import {
|
||||
eachTestingContextFilter,
|
||||
type EachTestingContext,
|
||||
} from 'twenty-shared/testing';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
|
||||
import { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any';
|
||||
|
||||
import { type UpdateObjectPayload } from 'src/engine/metadata-modules/object-metadata/dtos/update-object.input';
|
||||
|
||||
@@ -32,6 +35,12 @@ const labelIdentifierFailingTestsUseCase: CreateOneObjectMetadataItemTestingCont
|
||||
labelIdentifierFieldMetadataId: '42422020-f49c-4159-8751-76a24f47b360',
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'when labelIdentifier is null',
|
||||
context: {
|
||||
labelIdentifierFieldMetadataId: null as any,
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'when labelIdentifier is not a TEXT or NAME field',
|
||||
context: ({ numberFieldMetadataId }) => ({
|
||||
@@ -48,7 +57,13 @@ describe('Object metadata update should fail', () => {
|
||||
|
||||
beforeAll(async () => {
|
||||
const { data } = await createOneObjectMetadata({
|
||||
input: getMockCreateObjectInput(),
|
||||
expectToFail: false,
|
||||
input: {
|
||||
labelPlural: 'whatevers',
|
||||
labelSingular: 'whatever',
|
||||
namePlural: 'whatevers',
|
||||
nameSingular: 'whatever',
|
||||
},
|
||||
});
|
||||
|
||||
objectMetadataId = data.createOneObject.id;
|
||||
@@ -56,6 +71,7 @@ describe('Object metadata update should fail', () => {
|
||||
const {
|
||||
data: { createOneField },
|
||||
} = await createOneFieldMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
objectMetadataId: objectMetadataId,
|
||||
name: 'testName',
|
||||
@@ -69,6 +85,15 @@ describe('Object metadata update should fail', () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: objectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: {
|
||||
idToDelete: objectMetadataId,
|
||||
@@ -76,21 +101,26 @@ describe('Object metadata update should fail', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it.each(allTestsUseCases)('$title', async ({ context }) => {
|
||||
const updatePayload =
|
||||
typeof context === 'function'
|
||||
? context({ numberFieldMetadataId, objectMetadataId })
|
||||
: context;
|
||||
it.each(eachTestingContextFilter(allTestsUseCases))(
|
||||
'$title',
|
||||
async ({ context }) => {
|
||||
const updatePayload =
|
||||
typeof context === 'function'
|
||||
? context({ numberFieldMetadataId, objectMetadataId })
|
||||
: context;
|
||||
|
||||
const { errors } = await updateOneObjectMetadata({
|
||||
input: {
|
||||
idToUpdate: objectMetadataId,
|
||||
updatePayload,
|
||||
},
|
||||
expectToFail: true,
|
||||
});
|
||||
const { errors } = await updateOneObjectMetadata({
|
||||
input: {
|
||||
idToUpdate: objectMetadataId,
|
||||
updatePayload,
|
||||
},
|
||||
expectToFail: true,
|
||||
});
|
||||
|
||||
expect(errors).toBeDefined();
|
||||
expect(errors).toMatchSnapshot();
|
||||
});
|
||||
expect(errors).toBeDefined();
|
||||
expect(errors).toMatchSnapshot(
|
||||
extractRecordIdsAndDatesAsExpectAny(errors),
|
||||
);
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
+49
-3
@@ -1,14 +1,17 @@
|
||||
import { findManyFieldsMetadataQueryFactory } from 'test/integration/metadata/suites/field-metadata/utils/find-many-fields-metadata-query-factory.util';
|
||||
import { createMorphRelationBetweenObjects } from 'test/integration/metadata/suites/object-metadata/utils/create-morph-relation-between-objects.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 { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
|
||||
import { jestExpectToBeDefined } from 'test/utils/expect-to-be-defined.util.test';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
describe('Delete Object metadata with morph relation should succeed', () => {
|
||||
let opportunityId = '';
|
||||
let opportunityId: undefined | string;
|
||||
let personId = '';
|
||||
let companyId = '';
|
||||
let morphRelationField: { id: string };
|
||||
@@ -62,12 +65,45 @@ describe('Delete Object metadata with morph relation should succeed', () => {
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await deleteOneObjectMetadata({ input: { idToDelete: opportunityId } });
|
||||
if (isDefined(opportunityId)) {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: opportunityId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({ input: { idToDelete: opportunityId } });
|
||||
opportunityId = undefined;
|
||||
}
|
||||
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: personId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({ input: { idToDelete: personId } });
|
||||
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: companyId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({ input: { idToDelete: companyId } });
|
||||
});
|
||||
|
||||
it('When deleting source object, the relation on the target should be deleted', async () => {
|
||||
jestExpectToBeDefined(opportunityId);
|
||||
morphRelationField = await createMorphRelationBetweenObjects({
|
||||
objectMetadataId: opportunityId,
|
||||
firstTargetObjectMetadataId: personId,
|
||||
@@ -76,12 +112,22 @@ describe('Delete Object metadata with morph relation should succeed', () => {
|
||||
relationType: RelationType.MANY_TO_ONE,
|
||||
});
|
||||
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: opportunityId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({ input: { idToDelete: opportunityId } });
|
||||
const fieldAfterDeletion = await findFieldMetadata({
|
||||
fieldMetadataId: morphRelationField.id,
|
||||
});
|
||||
|
||||
expect(fieldAfterDeletion).toBeUndefined();
|
||||
opportunityId = undefined;
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+46
-59
@@ -1,37 +1,18 @@
|
||||
import { findManyFieldsMetadataQueryFactory } from 'test/integration/metadata/suites/field-metadata/utils/find-many-fields-metadata-query-factory.util';
|
||||
import { createMorphRelationBetweenObjects } from 'test/integration/metadata/suites/object-metadata/utils/create-morph-relation-between-objects.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 { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util';
|
||||
import { updateFeatureFlag } from 'test/integration/metadata/suites/utils/update-feature-flag.util';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum';
|
||||
|
||||
describe('Rename an object metadata with morph relation should succeed', () => {
|
||||
let createdObjectMetadataPersonId: string;
|
||||
let createdObjectMetadataOpportunityId: string;
|
||||
let createdObjectMetadataCompanyId: string;
|
||||
|
||||
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,
|
||||
});
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
const {
|
||||
data: {
|
||||
@@ -102,57 +83,63 @@ describe('Rename an object metadata with morph relation should succeed', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('should rename custom object, and update both the field name and join column name of the morph relation that contains the object name', async () => {
|
||||
const morphRelationField = await createMorphRelationBetweenObjects({
|
||||
name: 'owner',
|
||||
objectMetadataId: createdObjectMetadataOpportunityId,
|
||||
firstTargetObjectMetadataId: createdObjectMetadataPersonId,
|
||||
secondTargetObjectMetadataId: createdObjectMetadataCompanyId,
|
||||
type: FieldMetadataType.MORPH_RELATION,
|
||||
relationType: RelationType.MANY_TO_ONE,
|
||||
});
|
||||
it.failing(
|
||||
'should rename custom object, and update both the field name and join column name of the morph relation that contains the object name',
|
||||
async () => {
|
||||
const morphRelationField = await createMorphRelationBetweenObjects({
|
||||
name: 'owner',
|
||||
objectMetadataId: createdObjectMetadataOpportunityId,
|
||||
firstTargetObjectMetadataId: createdObjectMetadataPersonId,
|
||||
secondTargetObjectMetadataId: createdObjectMetadataCompanyId,
|
||||
type: FieldMetadataType.MORPH_RELATION,
|
||||
relationType: RelationType.MANY_TO_ONE,
|
||||
});
|
||||
|
||||
expect(morphRelationField.morphRelations.length).toBe(2);
|
||||
expect(morphRelationField.morphRelations.length).toBe(2);
|
||||
|
||||
const { data } = await updateOneObjectMetadata({
|
||||
gqlFields: `
|
||||
const { data } = await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
gqlFields: `
|
||||
nameSingular
|
||||
labelSingular
|
||||
namePlural
|
||||
labelPlural
|
||||
`,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataPersonId,
|
||||
updatePayload: {
|
||||
nameSingular: 'personForRenameSecond2',
|
||||
namePlural: 'peopleForRenameSecond2',
|
||||
labelSingular: 'Person For Rename2',
|
||||
labelPlural: 'People For Rename2',
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataPersonId,
|
||||
updatePayload: {
|
||||
nameSingular: 'personForRenameSecond2',
|
||||
namePlural: 'peopleForRenameSecond2',
|
||||
labelSingular: 'Person For Rename2',
|
||||
labelPlural: 'People For Rename2',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
expect(data.updateOneObject.nameSingular).toBe('personForRenameSecond2');
|
||||
expect(data.updateOneObject.nameSingular).toBe('personForRenameSecond2');
|
||||
|
||||
const ownerFieldMetadataOnPersonId = morphRelationField.morphRelations.find(
|
||||
(morphRelation) =>
|
||||
morphRelation.targetObjectMetadata.id === createdObjectMetadataPersonId,
|
||||
)?.sourceFieldMetadata.id;
|
||||
const ownerFieldMetadataOnPersonId =
|
||||
morphRelationField.morphRelations.find(
|
||||
(morphRelation) =>
|
||||
morphRelation.targetObjectMetadata.id ===
|
||||
createdObjectMetadataPersonId,
|
||||
)?.sourceFieldMetadata.id;
|
||||
|
||||
if (!ownerFieldMetadataOnPersonId) {
|
||||
throw new Error(
|
||||
'Morph Relation Error: Owner field metadata on person not found',
|
||||
if (!ownerFieldMetadataOnPersonId) {
|
||||
throw new Error(
|
||||
'Morph Relation Error: Owner field metadata on person not found',
|
||||
);
|
||||
}
|
||||
|
||||
const fieldAfterRenaming = await findFieldMetadata({
|
||||
fieldMetadataId: ownerFieldMetadataOnPersonId,
|
||||
});
|
||||
|
||||
expect(fieldAfterRenaming.settings.joinColumnName).toBe(
|
||||
'ownerPersonForRenameSecond2Id',
|
||||
);
|
||||
}
|
||||
|
||||
const fieldAfterRenaming = await findFieldMetadata({
|
||||
fieldMetadataId: ownerFieldMetadataOnPersonId,
|
||||
});
|
||||
|
||||
expect(fieldAfterRenaming.settings.joinColumnName).toBe(
|
||||
'ownerPersonForRenameSecondId',
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
const findFieldMetadata = async ({
|
||||
|
||||
+74
-29
@@ -1,10 +1,13 @@
|
||||
import { findManyFieldsMetadataQueryFactory } from 'test/integration/metadata/suites/field-metadata/utils/find-many-fields-metadata-query-factory.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 { updateOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata.util';
|
||||
import { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util';
|
||||
import { type EachTestingContext } from 'twenty-shared/testing';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
|
||||
import { jestExpectToBeDefined } from 'test/utils/expect-to-be-defined.util.test';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
|
||||
|
||||
@@ -42,14 +45,10 @@ const successfulDeleteTargetUseCase: DeleteOneObjectMetadataItemTestingContext =
|
||||
];
|
||||
|
||||
describe('Delete Object metadata with relation should succeed', () => {
|
||||
let createdObjectMetadataPersonId = '';
|
||||
let createdObjectMetadataOpportunityId = '';
|
||||
let globalTestContext: {
|
||||
opportunityMetadataId: string;
|
||||
personMetadataId: string;
|
||||
relationField: FieldMetadataDTO & {
|
||||
relation: RelationDTO;
|
||||
};
|
||||
let createdObjectMetadataPersonId: undefined | string;
|
||||
let createdObjectMetadataOpportunityId: undefined | string;
|
||||
let relationField: FieldMetadataDTO & {
|
||||
relation: RelationDTO;
|
||||
};
|
||||
|
||||
beforeEach(async () => {
|
||||
@@ -58,6 +57,7 @@ describe('Delete Object metadata with relation should succeed', () => {
|
||||
createOneObject: { id: objectMetadataPersonId },
|
||||
},
|
||||
} = await createOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
nameSingular: 'personForRelation',
|
||||
namePlural: 'peopleForRelation',
|
||||
@@ -74,6 +74,7 @@ describe('Delete Object metadata with relation should succeed', () => {
|
||||
createOneObject: { id: objectMetadataOpportunityId },
|
||||
},
|
||||
} = await createOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
nameSingular: 'opportunityForRelation',
|
||||
namePlural: 'opportunitiesForRelation',
|
||||
@@ -85,38 +86,70 @@ describe('Delete Object metadata with relation should succeed', () => {
|
||||
|
||||
createdObjectMetadataOpportunityId = objectMetadataOpportunityId;
|
||||
|
||||
globalTestContext = {
|
||||
opportunityMetadataId: createdObjectMetadataOpportunityId,
|
||||
personMetadataId: createdObjectMetadataPersonId,
|
||||
relationField:
|
||||
await createRelationBetweenObjects<FieldMetadataType.RELATION>({
|
||||
objectMetadataId: createdObjectMetadataOpportunityId,
|
||||
targetObjectMetadataId: createdObjectMetadataPersonId,
|
||||
type: FieldMetadataType.RELATION,
|
||||
relationType: RelationType.MANY_TO_ONE,
|
||||
}),
|
||||
};
|
||||
relationField =
|
||||
await createRelationBetweenObjects<FieldMetadataType.RELATION>({
|
||||
objectMetadataId: createdObjectMetadataOpportunityId,
|
||||
targetObjectMetadataId: createdObjectMetadataPersonId,
|
||||
type: FieldMetadataType.RELATION,
|
||||
relationType: RelationType.MANY_TO_ONE,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: createdObjectMetadataPersonId },
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: createdObjectMetadataOpportunityId },
|
||||
});
|
||||
if (isDefined(createdObjectMetadataPersonId)) {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataPersonId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: createdObjectMetadataPersonId },
|
||||
});
|
||||
}
|
||||
|
||||
if (isDefined(createdObjectMetadataOpportunityId)) {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectMetadataOpportunityId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: createdObjectMetadataOpportunityId },
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
it.each(successfulDeleteSourceUseCase)('$title', async ({ context }) => {
|
||||
jestExpectToBeDefined(createdObjectMetadataPersonId);
|
||||
const computedContext = context({
|
||||
objectMetadataIdToDelete: globalTestContext.personMetadataId,
|
||||
relationFieldId: globalTestContext.relationField.id,
|
||||
objectMetadataIdToDelete: createdObjectMetadataPersonId,
|
||||
relationFieldId: relationField.id,
|
||||
});
|
||||
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: computedContext.objectMetadataIdToDelete,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: computedContext.objectMetadataIdToDelete },
|
||||
});
|
||||
|
||||
createdObjectMetadataPersonId = undefined;
|
||||
const opportunityFieldOnPersonAfterDeletion = await findFieldMetadata({
|
||||
fieldMetadataId: computedContext.relationFieldId,
|
||||
});
|
||||
@@ -125,15 +158,27 @@ describe('Delete Object metadata with relation should succeed', () => {
|
||||
});
|
||||
|
||||
it.each(successfulDeleteTargetUseCase)('$title', async ({ context }) => {
|
||||
jestExpectToBeDefined(createdObjectMetadataOpportunityId);
|
||||
const computedContext = context({
|
||||
objectMetadataIdToDelete: globalTestContext.opportunityMetadataId,
|
||||
relationFieldId: globalTestContext.relationField.id,
|
||||
objectMetadataIdToDelete: createdObjectMetadataOpportunityId,
|
||||
relationFieldId: relationField.id,
|
||||
});
|
||||
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: computedContext.objectMetadataIdToDelete,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: computedContext.objectMetadataIdToDelete },
|
||||
});
|
||||
|
||||
createdObjectMetadataOpportunityId = undefined;
|
||||
const personFieldOnOpportunityAfterDeletion = await findFieldMetadata({
|
||||
fieldMetadataId: computedContext.relationFieldId,
|
||||
});
|
||||
|
||||
+4
-43
@@ -163,58 +163,19 @@ describe('Custom object renaming', () => {
|
||||
expect(data.updateOneObject.namePlural).toBe(HOUSE_NAME_PLURAL);
|
||||
expect(data.updateOneObject.labelSingular).toBe(HOUSE_LABEL_SINGULAR);
|
||||
expect(data.updateOneObject.labelPlural).toBe(HOUSE_LABEL_PLURAL);
|
||||
|
||||
const fieldsResponse = await makeMetadataAPIRequest(fieldsGraphqlOperation);
|
||||
|
||||
const fieldsMetadata = fieldsResponse.body.data.fields.edges.map(
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
(field) => field.node,
|
||||
);
|
||||
|
||||
// standard relations have been updated
|
||||
STANDARD_OBJECT_RELATIONS.forEach((relation) => {
|
||||
// relation field
|
||||
const relationFieldMetadataId =
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
standardObjectRelationsMap[relation].relationFieldMetadataId;
|
||||
|
||||
const updatedRelationFieldMetadata = fieldsMetadata.find(
|
||||
// @ts-expect-error legacy noImplicitAny
|
||||
(field) => field.id === relationFieldMetadataId,
|
||||
);
|
||||
|
||||
expect(updatedRelationFieldMetadata.name).toBe(HOUSE_NAME_SINGULAR);
|
||||
expect(updatedRelationFieldMetadata.label).toBe(HOUSE_LABEL_SINGULAR);
|
||||
});
|
||||
});
|
||||
|
||||
it('3. should fail when trying to rename object to "name"', async () => {
|
||||
// Act & Assert
|
||||
const { errors } = await updateOneObjectMetadata({
|
||||
gqlFields: `
|
||||
nameSingular
|
||||
labelSingular
|
||||
namePlural
|
||||
labelPlural
|
||||
`,
|
||||
it('3. should delete custom object', async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: listingObjectId,
|
||||
updatePayload: {
|
||||
nameSingular: 'name',
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
expectToFail: true,
|
||||
});
|
||||
|
||||
// Assert that an error was thrown
|
||||
expect(errors).toBeDefined();
|
||||
expect(errors).toHaveLength(1);
|
||||
expect(errors[0].extensions.userFriendlyMessage).toContain(
|
||||
'Name "name" is not available',
|
||||
);
|
||||
});
|
||||
|
||||
it('4. should delete custom object', async () => {
|
||||
const { data } = await deleteOneObjectMetadata({
|
||||
input: {
|
||||
idToDelete: listingObjectId,
|
||||
|
||||
+25
-4
@@ -1,7 +1,9 @@
|
||||
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 { getMockCreateObjectInput } from 'test/integration/metadata/suites/object-metadata/utils/generate-mock-create-object-metadata-input';
|
||||
import { updateOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata.util';
|
||||
import { type EachTestingContext } from 'twenty-shared/testing';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { type CreateObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/create-object.input';
|
||||
|
||||
@@ -19,20 +21,39 @@ const successfulObjectMetadataItemCreateOneUseCase: CreateOneObjectMetadataItemT
|
||||
title: 'with basic input',
|
||||
context: {},
|
||||
},
|
||||
// TODO populate
|
||||
];
|
||||
|
||||
const allTestsUseCases = [...successfulObjectMetadataItemCreateOneUseCase];
|
||||
|
||||
describe('Object metadata creation should succeed', () => {
|
||||
let createdObjectId: string | undefined;
|
||||
|
||||
afterEach(async () => {
|
||||
if (!isDefined(createdObjectId)) {
|
||||
return;
|
||||
}
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: createdObjectId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: createdObjectId },
|
||||
});
|
||||
});
|
||||
|
||||
it.each(allTestsUseCases)('$title', async ({ context }) => {
|
||||
const { data } = await createOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: getMockCreateObjectInput(context),
|
||||
});
|
||||
|
||||
expect(data.createOneObject.id).toBeDefined();
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: data.createOneObject.id },
|
||||
}).catch();
|
||||
createdObjectId = data.createOneObject.id;
|
||||
});
|
||||
});
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ import { type ObjectMetadataDTO } from 'src/engine/metadata-modules/object-metad
|
||||
export const createOneObjectMetadata = async ({
|
||||
input,
|
||||
gqlFields,
|
||||
expectToFail,
|
||||
expectToFail = false,
|
||||
}: PerformMetadataQueryParams<CreateOneObjectFactoryInput>): CommonResponseBody<{
|
||||
createOneObject: ObjectMetadataDTO;
|
||||
}> => {
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ import { warnIfNoErrorButExpectedToFail } from 'test/integration/metadata/utils/
|
||||
export const deleteOneObjectMetadata = async ({
|
||||
input,
|
||||
gqlFields,
|
||||
expectToFail,
|
||||
expectToFail = false,
|
||||
}: PerformMetadataQueryParams<DeleteOneObjectFactoryInput>) => {
|
||||
const graphqlOperation = deleteOneObjectMetadataQueryFactory({
|
||||
input,
|
||||
|
||||
+1
@@ -24,6 +24,7 @@ export const forceCreateOneObjectMetadata = async ({
|
||||
input: CreateOneObjectFactoryInput;
|
||||
}) => {
|
||||
const result = await createOneObjectMetadata({
|
||||
expectToFail: null,
|
||||
input: {
|
||||
labelSingular,
|
||||
labelPlural,
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
export type PerformMetadataQueryParams<T> = {
|
||||
input: T;
|
||||
gqlFields?: string;
|
||||
expectToFail?: boolean;
|
||||
expectToFail?: boolean | null;
|
||||
};
|
||||
|
||||
+10
@@ -2,6 +2,7 @@ import { TEST_NOT_EXISTING_PAGE_LAYOUT_ID } from 'test/integration/constants/tes
|
||||
import { TEST_NOT_EXISTING_PAGE_LAYOUT_TAB_ID } from 'test/integration/constants/test-page-layout-tab-ids.constants';
|
||||
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 { makeRestAPIRequest } from 'test/integration/rest/utils/make-rest-api-request.util';
|
||||
import {
|
||||
createTestPageLayoutWithRestApi,
|
||||
@@ -59,6 +60,15 @@ describe('Page Layout Tab REST API', () => {
|
||||
|
||||
afterAll(async () => {
|
||||
await deleteTestPageLayoutWithRestApi(testPageLayoutId);
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: testObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: testObjectMetadataId },
|
||||
});
|
||||
|
||||
+10
@@ -2,6 +2,7 @@ import { TEST_NOT_EXISTING_PAGE_LAYOUT_TAB_ID } from 'test/integration/constants
|
||||
import { TEST_NOT_EXISTING_PAGE_LAYOUT_WIDGET_ID } from 'test/integration/constants/test-page-layout-widget-ids.constants';
|
||||
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 { makeRestAPIRequest } from 'test/integration/rest/utils/make-rest-api-request.util';
|
||||
import {
|
||||
createTestPageLayoutWithRestApi,
|
||||
@@ -74,6 +75,15 @@ describe('Page Layout Widget REST API', () => {
|
||||
afterAll(async () => {
|
||||
await deleteTestPageLayoutTabWithRestApi(testPageLayoutTabId);
|
||||
await deleteTestPageLayoutWithRestApi(testPageLayoutId);
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: testObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: testObjectMetadataId },
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { TEST_NOT_EXISTING_PAGE_LAYOUT_ID } from 'test/integration/constants/test-page-layout-ids.constants';
|
||||
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 { makeRestAPIRequest } from 'test/integration/rest/utils/make-rest-api-request.util';
|
||||
import {
|
||||
createTestPageLayoutWithRestApi,
|
||||
@@ -44,6 +45,15 @@ describe('Page Layout REST API', () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: testObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: testObjectMetadataId },
|
||||
});
|
||||
|
||||
@@ -3,7 +3,9 @@ import {
|
||||
TEST_VIEW_1_ID,
|
||||
} from 'test/integration/constants/test-view-ids.constants';
|
||||
import { createOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/create-one-field-metadata.util';
|
||||
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
|
||||
import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util';
|
||||
import { updateOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata.util';
|
||||
import { makeRestAPIRequest } from 'test/integration/rest/utils/make-rest-api-request.util';
|
||||
import {
|
||||
assertRestApiErrorNotFoundResponse,
|
||||
@@ -20,7 +22,6 @@ import {
|
||||
cleanupViewRecords,
|
||||
} from 'test/integration/utils/view-test.util';
|
||||
import { FieldMetadataType } from 'twenty-shared/types';
|
||||
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
|
||||
|
||||
import {
|
||||
generateViewFieldExceptionMessage,
|
||||
@@ -76,6 +77,15 @@ describe('View Field REST API', () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: testObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: { idToDelete: testObjectMetadataId },
|
||||
|
||||
+10
-4
@@ -4,6 +4,7 @@ import {
|
||||
} from 'test/integration/constants/test-view-ids.constants';
|
||||
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 { makeRestAPIRequest } from 'test/integration/rest/utils/make-rest-api-request.util';
|
||||
import {
|
||||
assertRestApiErrorNotFoundResponse,
|
||||
@@ -31,10 +32,6 @@ describe('View Filter Group REST API', () => {
|
||||
let testObjectMetadataId: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: testObjectMetadataId },
|
||||
});
|
||||
|
||||
const {
|
||||
data: {
|
||||
createOneObject: { id: objectMetadataId },
|
||||
@@ -53,6 +50,15 @@ describe('View Filter Group REST API', () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: testObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: testObjectMetadataId },
|
||||
});
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
import { createOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/create-one-field-metadata.util';
|
||||
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
|
||||
import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util';
|
||||
import { updateOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata.util';
|
||||
import { makeRestAPIRequest } from 'test/integration/rest/utils/make-rest-api-request.util';
|
||||
import {
|
||||
assertRestApiErrorNotFoundResponse,
|
||||
@@ -70,6 +71,15 @@ describe('View Filter REST API', () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: testObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: testObjectMetadataId },
|
||||
});
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
import { createOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/create-one-field-metadata.util';
|
||||
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
|
||||
import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util';
|
||||
import { updateOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata.util';
|
||||
import { makeRestAPIRequest } from 'test/integration/rest/utils/make-rest-api-request.util';
|
||||
import {
|
||||
assertRestApiErrorNotFoundResponse,
|
||||
@@ -34,15 +35,12 @@ describe('View Group REST API', () => {
|
||||
let testFieldMetadataId: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: testObjectMetadataId },
|
||||
});
|
||||
|
||||
const {
|
||||
data: {
|
||||
createOneObject: { id: objectMetadataId },
|
||||
},
|
||||
} = await createOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
nameSingular: 'myTestObject',
|
||||
namePlural: 'myTestObjects',
|
||||
@@ -80,6 +78,15 @@ describe('View Group REST API', () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: testObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: testObjectMetadataId },
|
||||
});
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
import { createOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/create-one-field-metadata.util';
|
||||
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
|
||||
import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util';
|
||||
import { updateOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata.util';
|
||||
import { makeRestAPIRequest } from 'test/integration/rest/utils/make-rest-api-request.util';
|
||||
import {
|
||||
assertRestApiErrorNotFoundResponse,
|
||||
@@ -75,6 +76,15 @@ describe('View Sort REST API', () => {
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await updateOneObjectMetadata({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
idToUpdate: testObjectMetadataId,
|
||||
updatePayload: {
|
||||
isActive: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
await deleteOneObjectMetadata({
|
||||
input: { idToDelete: testObjectMetadataId },
|
||||
});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user