Introduce npx nx mock:generate twenty-front (#18237)

## Add codegen script for frontend test mock data

### Summary

- Adds a new `npx nx mock:generate twenty-front` and
`generate-mock-data.ts` script that fetches object metadata from a
running server's `/metadata` endpoint, authenticates with default seeds,
and writes the result to a generated TypeScript file
(`src/testing/mock-data/generated/mock-metadata-query-result.ts`). This
replaces hand-maintained mock metadata with server-sourced data,
ensuring tests always reflect the real schema.
- Updates all frontend tests to be compatible with the newly generated
metadata, fixing hard-coded GraphQL queries, Zod validation schemas,
snapshot expectations, and Apollo mock mismatches.

### What changed

**New files**
- `scripts/generate-mock-data.ts` — codegen script that authenticates
against the server, queries `/metadata` for all object metadata (with
explicit `__typename` at every level), and writes a typed `.ts` file.
- `project.json` — added `mock:generate` Nx target (`dotenv npx tsx
scripts/generate-mock-data.ts`).

**Schema validation updates**
- `objectMetadataItemSchema.ts` — added `universalIdentifier`, made
`duplicateCriteria` nullable.
- `fieldMetadataItemSchema.ts` — added `universalIdentifier`, `morphId`,
`morphRelations`, restructured relation schema.
- `indexMetadataItemSchema.ts` — added optional `isCustom` field.
This commit is contained in:
Charles Bochet
2026-02-25 21:40:05 +01:00
committed by GitHub
parent 50be97422d
commit e01b641a05
25 changed files with 24997 additions and 18246 deletions
@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`generateActivityTargetGqlFields snapshot tests should match snapshot for Note with loadRelations="activity" 1`] = `
{
@@ -12,13 +12,8 @@ exports[`generateActivityTargetGqlFields snapshot tests should match snapshot fo
exports[`generateActivityTargetGqlFields snapshot tests should match snapshot for Note with loadRelations="both" 1`] = `
{
"company": {
"domainName": true,
"id": true,
"name": true,
},
"companyId": true,
"createdAt": true,
"createdBy": true,
"deletedAt": true,
"id": true,
"note": {
@@ -26,54 +21,103 @@ exports[`generateActivityTargetGqlFields snapshot tests should match snapshot fo
"title": true,
},
"noteId": true,
"opportunity": {
"position": true,
"searchVector": true,
"targetCompany": {
"id": true,
"name": true,
},
"opportunityId": true,
"person": {
"avatarUrl": true,
"targetCompanyId": true,
"targetEmploymentHistory": {
"id": true,
"name": true,
},
"personId": true,
"pet": {
"targetEmploymentHistoryId": true,
"targetOpportunity": {
"id": true,
"name": true,
},
"petId": true,
"rocket": {
"targetOpportunityId": true,
"targetPerson": {
"id": true,
"name": true,
},
"rocketId": true,
"surveyResult": {
"targetPersonId": true,
"targetPet": {
"id": true,
"name": true,
},
"surveyResultId": true,
"targetPetCareAgreement": {
"id": true,
"name": true,
},
"targetPetCareAgreementId": true,
"targetPetId": true,
"targetRocket": {
"id": true,
"name": true,
},
"targetRocketId": true,
"targetSurveyResult": {
"id": true,
"name": true,
},
"targetSurveyResultId": true,
"updatedAt": true,
"updatedBy": true,
}
`;
exports[`generateActivityTargetGqlFields snapshot tests should match snapshot for Note with loadRelations="relations" 1`] = `
{
"company": true,
"companyId": true,
"createdAt": true,
"createdBy": true,
"deletedAt": true,
"id": true,
"opportunity": true,
"opportunityId": true,
"person": true,
"personId": true,
"pet": true,
"petId": true,
"rocket": true,
"rocketId": true,
"surveyResult": true,
"surveyResultId": true,
"position": true,
"searchVector": true,
"targetCompany": {
"id": true,
"name": true,
},
"targetCompanyId": true,
"targetEmploymentHistory": {
"id": true,
"name": true,
},
"targetEmploymentHistoryId": true,
"targetOpportunity": {
"id": true,
"name": true,
},
"targetOpportunityId": true,
"targetPerson": {
"id": true,
"name": true,
},
"targetPersonId": true,
"targetPet": {
"id": true,
"name": true,
},
"targetPetCareAgreement": {
"id": true,
"name": true,
},
"targetPetCareAgreementId": true,
"targetPetId": true,
"targetRocket": {
"id": true,
"name": true,
},
"targetRocketId": true,
"targetSurveyResult": {
"id": true,
"name": true,
},
"targetSurveyResultId": true,
"updatedAt": true,
"updatedBy": true,
}
`;
@@ -89,67 +133,111 @@ exports[`generateActivityTargetGqlFields snapshot tests should match snapshot fo
exports[`generateActivityTargetGqlFields snapshot tests should match snapshot for Task with loadRelations="both" 1`] = `
{
"company": {
"domainName": true,
"id": true,
"name": true,
},
"companyId": true,
"createdAt": true,
"createdBy": true,
"deletedAt": true,
"id": true,
"opportunity": {
"position": true,
"searchVector": true,
"targetCompany": {
"id": true,
"name": true,
},
"opportunityId": true,
"person": {
"avatarUrl": true,
"targetCompanyId": true,
"targetEmploymentHistory": {
"id": true,
"name": true,
},
"personId": true,
"pet": {
"targetEmploymentHistoryId": true,
"targetOpportunity": {
"id": true,
"name": true,
},
"petId": true,
"rocket": {
"targetOpportunityId": true,
"targetPerson": {
"id": true,
"name": true,
},
"rocketId": true,
"surveyResult": {
"targetPersonId": true,
"targetPet": {
"id": true,
"name": true,
},
"surveyResultId": true,
"targetPetCareAgreement": {
"id": true,
"name": true,
},
"targetPetCareAgreementId": true,
"targetPetId": true,
"targetRocket": {
"id": true,
"name": true,
},
"targetRocketId": true,
"targetSurveyResult": {
"id": true,
"name": true,
},
"targetSurveyResultId": true,
"task": {
"id": true,
"title": true,
},
"taskId": true,
"updatedAt": true,
"updatedBy": true,
}
`;
exports[`generateActivityTargetGqlFields snapshot tests should match snapshot for Task with loadRelations="relations" 1`] = `
{
"company": true,
"companyId": true,
"createdAt": true,
"createdBy": true,
"deletedAt": true,
"id": true,
"opportunity": true,
"opportunityId": true,
"person": true,
"personId": true,
"pet": true,
"petId": true,
"rocket": true,
"rocketId": true,
"surveyResult": true,
"surveyResultId": true,
"position": true,
"searchVector": true,
"targetCompany": {
"id": true,
"name": true,
},
"targetCompanyId": true,
"targetEmploymentHistory": {
"id": true,
"name": true,
},
"targetEmploymentHistoryId": true,
"targetOpportunity": {
"id": true,
"name": true,
},
"targetOpportunityId": true,
"targetPerson": {
"id": true,
"name": true,
},
"targetPersonId": true,
"targetPet": {
"id": true,
"name": true,
},
"targetPetCareAgreement": {
"id": true,
"name": true,
},
"targetPetCareAgreementId": true,
"targetPetId": true,
"targetRocket": {
"id": true,
"name": true,
},
"targetRocketId": true,
"targetSurveyResult": {
"id": true,
"name": true,
},
"targetSurveyResultId": true,
"updatedAt": true,
"updatedBy": true,
}
`;
@@ -1,9 +1,8 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`generateDepthRecordGqlFieldsFromObject should generate depth one record gql fields from object 1`] = `
{
"accountOwner": {
"avatarUrl": true,
"id": true,
"name": true,
},
@@ -14,6 +13,13 @@ exports[`generateDepthRecordGqlFieldsFromObject should generate depth one record
"id": true,
"name": true,
},
"caredForPets": {
"id": true,
"pet": {
"id": true,
"name": true,
},
},
"createdAt": true,
"createdBy": true,
"deletedAt": true,
@@ -44,6 +50,14 @@ exports[`generateDepthRecordGqlFieldsFromObject should generate depth one record
"name": true,
},
"position": true,
"previousEmployees": {
"id": true,
"person": {
"avatarUrl": true,
"id": true,
"name": true,
},
},
"searchVector": true,
"tagline": true,
"taskTargets": {
@@ -55,8 +69,10 @@ exports[`generateDepthRecordGqlFieldsFromObject should generate depth one record
},
"timelineActivities": {
"id": true,
"name": true,
},
"updatedAt": true,
"updatedBy": true,
"visaSponsorship": true,
"workPolicy": true,
"xLink": true,
@@ -82,6 +98,7 @@ exports[`generateDepthRecordGqlFieldsFromObject should generate depth zero recor
"searchVector": true,
"tagline": true,
"updatedAt": true,
"updatedBy": true,
"visaSponsorship": true,
"workPolicy": true,
"xLink": true,
@@ -1,4 +1,4 @@
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`generateDepthRecordGqlFieldsFromRecord should generate depth one record gql fields from empty record 1`] = `
{
@@ -7,6 +7,7 @@ exports[`generateDepthRecordGqlFieldsFromRecord should generate depth one record
"address": false,
"annualRecurringRevenue": false,
"attachments": false,
"caredForPets": false,
"createdAt": false,
"createdBy": false,
"deletedAt": false,
@@ -22,11 +23,13 @@ exports[`generateDepthRecordGqlFieldsFromRecord should generate depth one record
"opportunities": false,
"people": false,
"position": false,
"previousEmployees": false,
"searchVector": false,
"tagline": false,
"taskTargets": false,
"timelineActivities": false,
"updatedAt": false,
"updatedBy": false,
"visaSponsorship": false,
"workPolicy": false,
"xLink": false,
@@ -40,6 +43,7 @@ exports[`generateDepthRecordGqlFieldsFromRecord should generate depth one record
"address": false,
"annualRecurringRevenue": false,
"attachments": false,
"caredForPets": false,
"createdAt": false,
"createdBy": false,
"deletedAt": false,
@@ -55,11 +59,13 @@ exports[`generateDepthRecordGqlFieldsFromRecord should generate depth one record
"opportunities": false,
"people": false,
"position": false,
"previousEmployees": false,
"searchVector": false,
"tagline": false,
"taskTargets": false,
"timelineActivities": false,
"updatedAt": false,
"updatedBy": false,
"visaSponsorship": false,
"workPolicy": false,
"xLink": false,
@@ -85,6 +91,7 @@ exports[`generateDepthRecordGqlFieldsFromRecord should generate depth zero recor
"searchVector": false,
"tagline": false,
"updatedAt": false,
"updatedBy": false,
"visaSponsorship": false,
"workPolicy": false,
"xLink": false,