fieldmetadatatype + featurelfag creation (#13021)

Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
Guillim
2025-07-08 12:23:28 +02:00
committed by GitHub
parent 56607c0449
commit a5deddaffd
47 changed files with 1447 additions and 793 deletions

View File

@ -1,8 +1,14 @@
import { 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 { findManyFieldsMetadataQueryFactory } from 'test/integration/metadata/suites/field-metadata/utils/find-many-fields-metadata-query-factory.util';
import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util';
import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util';
import { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util';
import { FieldMetadataType } from 'twenty-shared/types';
import { RelationType } from 'src/engine/metadata-modules/field-metadata/interfaces/relation-type.interface';
describe('createOne', () => {
describe('FieldMetadataService name/label sync', () => {
let createdObjectMetadataId = '';
@ -107,4 +113,184 @@ describe('createOne', () => {
);
});
});
describe('FieldMetadataService relation fields', () => {
let createdObjectMetadataPersonId = '';
let createdObjectMetadataOpportunityId = '';
let createdObjectMetadataCompanyId = '';
beforeEach(async () => {
const {
data: {
createOneObject: { id: objectMetadataPersonId },
},
} = await createOneObjectMetadata({
input: {
nameSingular: 'personForRelation',
namePlural: 'peopleForRelation',
labelSingular: 'Person For Relation',
labelPlural: 'People For Relation',
icon: 'IconPerson',
},
});
createdObjectMetadataPersonId = objectMetadataPersonId;
const {
data: {
createOneObject: { id: objectMetadataCompanyId },
},
} = await createOneObjectMetadata({
input: {
nameSingular: 'companyForRelation',
namePlural: 'companiesForRelation',
labelSingular: 'Company For Relation',
labelPlural: 'Companies For Relation',
icon: 'IconCompany',
},
});
createdObjectMetadataCompanyId = objectMetadataCompanyId;
const {
data: {
createOneObject: { id: objectMetadataOpportunityId },
},
} = await createOneObjectMetadata({
input: {
nameSingular: 'opportunityForRelation',
namePlural: 'opportunitiesForRelation',
labelSingular: 'Opportunity For Relation',
labelPlural: 'Opportunities For Relation',
icon: 'IconOpportunity',
},
});
createdObjectMetadataOpportunityId = objectMetadataOpportunityId;
});
afterEach(async () => {
await deleteOneObjectMetadata({
input: { idToDelete: createdObjectMetadataPersonId },
});
await deleteOneObjectMetadata({
input: { idToDelete: createdObjectMetadataOpportunityId },
});
await deleteOneObjectMetadata({
input: { idToDelete: createdObjectMetadataCompanyId },
});
});
it('should create a RELATION field type', async () => {
const createFieldInput: CreateOneFieldFactoryInput = {
name: 'person',
label: 'person field',
type: FieldMetadataType.RELATION,
objectMetadataId: createdObjectMetadataOpportunityId,
isLabelSyncedWithName: false,
relationCreationPayload: {
targetObjectMetadataId: createdObjectMetadataPersonId,
targetFieldLabel: 'opportunity',
targetFieldIcon: 'IconListOpportunity',
type: RelationType.MANY_TO_ONE,
},
};
const { data: createdFieldPerson } = await createOneFieldMetadata({
input: createFieldInput,
gqlFields: `
id
name
label
isLabelSyncedWithName
`,
expectToFail: false,
});
expect(createdFieldPerson.createOneField.name).toBe('person');
// TODO : find a way to filter by objectmetadataid toavoid loading all fieldMetadata objects
const findOpportunityOperation = findManyFieldsMetadataQueryFactory({
gqlFields: `
id
name
object {
id
nameSingular
}
relation {
type
}
settings
`,
input: {
filter: {},
paging: { first: 10000 },
},
});
const opportunityFieldsResponse = await makeMetadataAPIRequest(
findOpportunityOperation,
);
const allFields = opportunityFieldsResponse.body.data.fields.edges;
const opportunityFieldOnPerson = allFields.find(
(field: any) =>
field.node?.object?.id === createdObjectMetadataPersonId &&
field.node?.name ===
createFieldInput.relationCreationPayload?.targetFieldLabel,
).node;
expect(opportunityFieldOnPerson.object.nameSingular).toBe(
'personForRelation',
);
expect(opportunityFieldOnPerson.relation.type).toBe(
RelationType.ONE_TO_MANY,
);
await deleteOneFieldMetadata({
input: { idToDelete: createdFieldPerson.createOneField.id },
});
});
// TODO: replace xit by it once the Morph works
xit('should create a MORPH_RELATION field type', async () => {
const createFieldInput: CreateOneFieldFactoryInput = {
name: 'owner',
label: 'owner field',
type: FieldMetadataType.MORPH_RELATION,
objectMetadataId: createdObjectMetadataOpportunityId,
isLabelSyncedWithName: false,
morphRelationsCreationPayload: [
{
targetObjectMetadataId: createdObjectMetadataPersonId,
targetFieldLabel: 'opportunity',
targetFieldIcon: 'IconListOpportunity',
type: RelationType.MANY_TO_ONE,
},
{
targetObjectMetadataId: createdObjectMetadataCompanyId,
targetFieldLabel: 'opportunity',
targetFieldIcon: 'IconListOpportunity',
type: RelationType.MANY_TO_ONE,
},
],
};
const { data: createdFieldOwner } = await createOneFieldMetadata({
input: createFieldInput,
gqlFields: `
id
name
label
isLabelSyncedWithName
`,
expectToFail: false,
});
// expect(createdFieldOwner.createOneField.name).toBe('owner');
await deleteOneFieldMetadata({
input: { idToDelete: createdFieldOwner.createOneField.id },
});
});
});
});