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:
@@ -255,6 +255,13 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"mock:generate": {
|
||||
"executor": "nx:run-commands",
|
||||
"options": {
|
||||
"cwd": "{projectRoot}",
|
||||
"command": "dotenv npx tsx scripts/generate-mock-data.ts"
|
||||
}
|
||||
},
|
||||
"chromatic": {
|
||||
"configurations": {
|
||||
"ci": {}
|
||||
|
||||
@@ -0,0 +1,284 @@
|
||||
/* eslint-disable no-console */
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
|
||||
|
||||
const SERVER_BASE_URL =
|
||||
process.env.REACT_APP_SERVER_BASE_URL ?? 'http://localhost:3000';
|
||||
const AUTH_EMAIL = 'tim@apple.dev';
|
||||
const AUTH_PASSWORD = 'tim@apple.dev';
|
||||
const WORKSPACE_SUBDOMAIN = 'apple';
|
||||
|
||||
const serverUrl = new URL(SERVER_BASE_URL);
|
||||
const WORKSPACE_ORIGIN = `${serverUrl.protocol}//${WORKSPACE_SUBDOMAIN}.${serverUrl.host}`;
|
||||
|
||||
const currentDir = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
const OUTPUT_DIR = path.resolve(
|
||||
currentDir,
|
||||
'../src/testing/mock-data/generated',
|
||||
);
|
||||
|
||||
const graphqlRequest = async (
|
||||
endpoint: string,
|
||||
query: string,
|
||||
token?: string,
|
||||
): Promise<unknown> => {
|
||||
const headers: Record<string, string> = {
|
||||
'Content-Type': 'application/json',
|
||||
Origin: WORKSPACE_ORIGIN,
|
||||
};
|
||||
|
||||
if (token !== undefined) {
|
||||
headers['Authorization'] = `Bearer ${token}`;
|
||||
}
|
||||
|
||||
const response = await fetch(`${SERVER_BASE_URL}${endpoint}`, {
|
||||
method: 'POST',
|
||||
headers,
|
||||
body: JSON.stringify({ query }),
|
||||
});
|
||||
|
||||
const json = (await response.json()) as {
|
||||
data?: unknown;
|
||||
errors?: { message: string }[];
|
||||
};
|
||||
|
||||
if (
|
||||
json.errors !== undefined &&
|
||||
json.errors !== null &&
|
||||
json.errors.length > 0
|
||||
) {
|
||||
const errorDetails = json.errors.map((error) => error.message).join(', ');
|
||||
throw new Error(`GraphQL error on ${endpoint}: ${errorDetails}`);
|
||||
}
|
||||
|
||||
return json.data;
|
||||
};
|
||||
|
||||
const authenticate = async (): Promise<string> => {
|
||||
console.log(
|
||||
`Authenticating as ${AUTH_EMAIL} on workspace ${WORKSPACE_SUBDOMAIN}...`,
|
||||
);
|
||||
|
||||
const loginData = (await graphqlRequest(
|
||||
'/metadata',
|
||||
`mutation GetLoginTokenFromCredentials {
|
||||
getLoginTokenFromCredentials(
|
||||
email: "${AUTH_EMAIL}",
|
||||
password: "${AUTH_PASSWORD}",
|
||||
origin: "${WORKSPACE_ORIGIN}"
|
||||
) {
|
||||
loginToken { token }
|
||||
}
|
||||
}`,
|
||||
)) as {
|
||||
getLoginTokenFromCredentials: { loginToken: { token: string } };
|
||||
};
|
||||
|
||||
const loginToken = loginData.getLoginTokenFromCredentials.loginToken.token;
|
||||
|
||||
const authData = (await graphqlRequest(
|
||||
'/metadata',
|
||||
`mutation GetAuthTokensFromLoginToken {
|
||||
getAuthTokensFromLoginToken(
|
||||
loginToken: "${loginToken}",
|
||||
origin: "${WORKSPACE_ORIGIN}"
|
||||
) {
|
||||
tokens {
|
||||
accessOrWorkspaceAgnosticToken { token }
|
||||
}
|
||||
}
|
||||
}`,
|
||||
)) as {
|
||||
getAuthTokensFromLoginToken: {
|
||||
tokens: { accessOrWorkspaceAgnosticToken: { token: string } };
|
||||
};
|
||||
};
|
||||
|
||||
const accessToken =
|
||||
authData.getAuthTokensFromLoginToken.tokens.accessOrWorkspaceAgnosticToken
|
||||
.token;
|
||||
|
||||
console.log('Authenticated successfully.');
|
||||
return accessToken;
|
||||
};
|
||||
|
||||
// Apollo Client automatically adds __typename to every object level;
|
||||
// raw fetch does not, so we include it explicitly here.
|
||||
const METADATA_QUERY = `
|
||||
query ObjectMetadataItems {
|
||||
objects(paging: { first: 1000 }) {
|
||||
__typename
|
||||
edges {
|
||||
__typename
|
||||
node {
|
||||
__typename
|
||||
id
|
||||
universalIdentifier
|
||||
nameSingular
|
||||
namePlural
|
||||
labelSingular
|
||||
labelPlural
|
||||
description
|
||||
icon
|
||||
isCustom
|
||||
isRemote
|
||||
isActive
|
||||
isSystem
|
||||
isUIReadOnly
|
||||
createdAt
|
||||
updatedAt
|
||||
labelIdentifierFieldMetadataId
|
||||
imageIdentifierFieldMetadataId
|
||||
applicationId
|
||||
shortcut
|
||||
isLabelSyncedWithName
|
||||
isSearchable
|
||||
duplicateCriteria
|
||||
indexMetadataList {
|
||||
__typename
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
name
|
||||
indexWhereClause
|
||||
indexType
|
||||
isUnique
|
||||
isCustom
|
||||
indexFieldMetadataList {
|
||||
__typename
|
||||
id
|
||||
fieldMetadataId
|
||||
createdAt
|
||||
updatedAt
|
||||
order
|
||||
}
|
||||
}
|
||||
fieldsList {
|
||||
__typename
|
||||
id
|
||||
universalIdentifier
|
||||
type
|
||||
name
|
||||
label
|
||||
description
|
||||
icon
|
||||
isCustom
|
||||
isActive
|
||||
isSystem
|
||||
isUIReadOnly
|
||||
isNullable
|
||||
isUnique
|
||||
createdAt
|
||||
updatedAt
|
||||
defaultValue
|
||||
options
|
||||
settings
|
||||
isLabelSyncedWithName
|
||||
morphId
|
||||
applicationId
|
||||
relation {
|
||||
__typename
|
||||
type
|
||||
sourceObjectMetadata {
|
||||
__typename
|
||||
id
|
||||
nameSingular
|
||||
namePlural
|
||||
}
|
||||
targetObjectMetadata {
|
||||
__typename
|
||||
id
|
||||
nameSingular
|
||||
namePlural
|
||||
}
|
||||
sourceFieldMetadata {
|
||||
__typename
|
||||
id
|
||||
name
|
||||
}
|
||||
targetFieldMetadata {
|
||||
__typename
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
morphRelations {
|
||||
__typename
|
||||
type
|
||||
sourceObjectMetadata {
|
||||
__typename
|
||||
id
|
||||
nameSingular
|
||||
namePlural
|
||||
}
|
||||
targetObjectMetadata {
|
||||
__typename
|
||||
id
|
||||
nameSingular
|
||||
namePlural
|
||||
}
|
||||
sourceFieldMetadata {
|
||||
__typename
|
||||
id
|
||||
name
|
||||
}
|
||||
targetFieldMetadata {
|
||||
__typename
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pageInfo {
|
||||
__typename
|
||||
hasNextPage
|
||||
hasPreviousPage
|
||||
startCursor
|
||||
endCursor
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const main = async () => {
|
||||
console.log(`Server: ${SERVER_BASE_URL}`);
|
||||
console.log(`Output: ${OUTPUT_DIR}`);
|
||||
console.log('');
|
||||
|
||||
const token = await authenticate();
|
||||
|
||||
console.log('Fetching object metadata from /metadata ...');
|
||||
const metadata = await graphqlRequest('/metadata', METADATA_QUERY, token);
|
||||
|
||||
fs.mkdirSync(OUTPUT_DIR, { recursive: true });
|
||||
|
||||
const filePath = path.join(OUTPUT_DIR, 'mock-metadata-query-result.ts');
|
||||
const content = [
|
||||
'/* eslint-disable */',
|
||||
'// @ts-nocheck',
|
||||
"import { ObjectMetadataItemsQuery } from '~/generated-metadata/graphql';",
|
||||
'',
|
||||
'// This file was automatically generated by scripts/generate-mock-data.ts',
|
||||
'// Do not edit this file manually.',
|
||||
'',
|
||||
'// prettier-ignore',
|
||||
'export const mockedStandardObjectMetadataQueryResult: ObjectMetadataItemsQuery =',
|
||||
JSON.stringify(metadata, null, 2) + ';',
|
||||
'',
|
||||
].join('\n');
|
||||
|
||||
fs.writeFileSync(filePath, content, 'utf-8');
|
||||
console.log(`Written: ${filePath}`);
|
||||
console.log('Done!');
|
||||
};
|
||||
|
||||
main().catch((error) => {
|
||||
console.error('Fatal error:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -5527,7 +5527,7 @@ export type UpdateOneApplicationVariableMutationVariables = Exact<{
|
||||
|
||||
export type UpdateOneApplicationVariableMutation = { __typename?: 'Mutation', updateOneApplicationVariable: boolean };
|
||||
|
||||
export type ApplicationFieldsFragment = { __typename?: 'Application', id: string, name: string, description: string, version: string, universalIdentifier: string, canBeUninstalled: boolean, defaultRoleId?: string | null, availablePackages: any, applicationVariables: Array<{ __typename?: 'ApplicationVariable', id: string, key: string, value: string, description: string, isSecret: boolean }>, agents: Array<{ __typename?: 'Agent', id: string, name: string, label: string, description?: string | null, icon?: string | null, prompt: string, modelId: string, responseFormat?: any | null, roleId?: string | null, isCustom: boolean, modelConfiguration?: any | null, evaluationInputs: Array<string>, applicationId?: string | null, createdAt: string, updatedAt: string }>, objects: Array<{ __typename?: 'Object', id: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, isCustom: boolean, isRemote: boolean, isActive: boolean, isSystem: boolean, isUIReadOnly: boolean, createdAt: string, updatedAt: string, labelIdentifierFieldMetadataId?: string | null, imageIdentifierFieldMetadataId?: string | null, applicationId: string, shortcut?: string | null, isLabelSyncedWithName: boolean, isSearchable: boolean, duplicateCriteria?: Array<Array<string>> | null, indexMetadataList: Array<{ __typename?: 'Index', id: string, createdAt: string, updatedAt: string, name: string, indexWhereClause?: string | null, indexType: IndexType, isUnique: boolean, isCustom?: boolean | null, indexFieldMetadataList: Array<{ __typename?: 'IndexField', id: string, fieldMetadataId: string, createdAt: string, updatedAt: string, order: number }> }>, fieldsList: Array<{ __typename?: 'Field', id: string, type: FieldMetadataType, name: string, label: string, description?: string | null, icon?: string | null, isCustom?: boolean | null, isActive?: boolean | null, isSystem?: boolean | null, isUIReadOnly?: boolean | null, isNullable?: boolean | null, isUnique?: boolean | null, createdAt: string, updatedAt: string, defaultValue?: any | null, options?: any | null, settings?: any | null, isLabelSyncedWithName?: boolean | null, morphId?: string | null, applicationId: string, relation?: { __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } } | null, morphRelations?: Array<{ __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } }> | null }> }>, logicFunctions: Array<{ __typename?: 'LogicFunction', id: string, name: string, description?: string | null, runtime: string, timeoutSeconds: number, sourceHandlerPath: string, handlerName: string, toolInputSchema?: any | null, isTool: boolean, applicationId?: string | null, createdAt: string, updatedAt: string }> };
|
||||
export type ApplicationFieldsFragment = { __typename?: 'Application', id: string, name: string, description: string, version: string, universalIdentifier: string, canBeUninstalled: boolean, defaultRoleId?: string | null, availablePackages: any, applicationVariables: Array<{ __typename?: 'ApplicationVariable', id: string, key: string, value: string, description: string, isSecret: boolean }>, agents: Array<{ __typename?: 'Agent', id: string, name: string, label: string, description?: string | null, icon?: string | null, prompt: string, modelId: string, responseFormat?: any | null, roleId?: string | null, isCustom: boolean, modelConfiguration?: any | null, evaluationInputs: Array<string>, applicationId?: string | null, createdAt: string, updatedAt: string }>, objects: Array<{ __typename?: 'Object', id: string, universalIdentifier: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, isCustom: boolean, isRemote: boolean, isActive: boolean, isSystem: boolean, isUIReadOnly: boolean, createdAt: string, updatedAt: string, labelIdentifierFieldMetadataId?: string | null, imageIdentifierFieldMetadataId?: string | null, applicationId: string, shortcut?: string | null, isLabelSyncedWithName: boolean, isSearchable: boolean, duplicateCriteria?: Array<Array<string>> | null, indexMetadataList: Array<{ __typename?: 'Index', id: string, createdAt: string, updatedAt: string, name: string, indexWhereClause?: string | null, indexType: IndexType, isUnique: boolean, isCustom?: boolean | null, indexFieldMetadataList: Array<{ __typename?: 'IndexField', id: string, fieldMetadataId: string, createdAt: string, updatedAt: string, order: number }> }>, fieldsList: Array<{ __typename?: 'Field', id: string, universalIdentifier: string, type: FieldMetadataType, name: string, label: string, description?: string | null, icon?: string | null, isCustom?: boolean | null, isActive?: boolean | null, isSystem?: boolean | null, isUIReadOnly?: boolean | null, isNullable?: boolean | null, isUnique?: boolean | null, createdAt: string, updatedAt: string, defaultValue?: any | null, options?: any | null, settings?: any | null, isLabelSyncedWithName?: boolean | null, morphId?: string | null, applicationId: string, relation?: { __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } } | null, morphRelations?: Array<{ __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } }> | null }> }>, logicFunctions: Array<{ __typename?: 'LogicFunction', id: string, name: string, description?: string | null, runtime: string, timeoutSeconds: number, sourceHandlerPath: string, handlerName: string, toolInputSchema?: any | null, isTool: boolean, applicationId?: string | null, createdAt: string, updatedAt: string }> };
|
||||
|
||||
export type FindManyApplicationsQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
@@ -5539,7 +5539,7 @@ export type FindOneApplicationQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type FindOneApplicationQuery = { __typename?: 'Query', findOneApplication: { __typename?: 'Application', id: string, name: string, description: string, version: string, universalIdentifier: string, canBeUninstalled: boolean, defaultRoleId?: string | null, availablePackages: any, applicationVariables: Array<{ __typename?: 'ApplicationVariable', id: string, key: string, value: string, description: string, isSecret: boolean }>, agents: Array<{ __typename?: 'Agent', id: string, name: string, label: string, description?: string | null, icon?: string | null, prompt: string, modelId: string, responseFormat?: any | null, roleId?: string | null, isCustom: boolean, modelConfiguration?: any | null, evaluationInputs: Array<string>, applicationId?: string | null, createdAt: string, updatedAt: string }>, objects: Array<{ __typename?: 'Object', id: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, isCustom: boolean, isRemote: boolean, isActive: boolean, isSystem: boolean, isUIReadOnly: boolean, createdAt: string, updatedAt: string, labelIdentifierFieldMetadataId?: string | null, imageIdentifierFieldMetadataId?: string | null, applicationId: string, shortcut?: string | null, isLabelSyncedWithName: boolean, isSearchable: boolean, duplicateCriteria?: Array<Array<string>> | null, indexMetadataList: Array<{ __typename?: 'Index', id: string, createdAt: string, updatedAt: string, name: string, indexWhereClause?: string | null, indexType: IndexType, isUnique: boolean, isCustom?: boolean | null, indexFieldMetadataList: Array<{ __typename?: 'IndexField', id: string, fieldMetadataId: string, createdAt: string, updatedAt: string, order: number }> }>, fieldsList: Array<{ __typename?: 'Field', id: string, type: FieldMetadataType, name: string, label: string, description?: string | null, icon?: string | null, isCustom?: boolean | null, isActive?: boolean | null, isSystem?: boolean | null, isUIReadOnly?: boolean | null, isNullable?: boolean | null, isUnique?: boolean | null, createdAt: string, updatedAt: string, defaultValue?: any | null, options?: any | null, settings?: any | null, isLabelSyncedWithName?: boolean | null, morphId?: string | null, applicationId: string, relation?: { __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } } | null, morphRelations?: Array<{ __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } }> | null }> }>, logicFunctions: Array<{ __typename?: 'LogicFunction', id: string, name: string, description?: string | null, runtime: string, timeoutSeconds: number, sourceHandlerPath: string, handlerName: string, toolInputSchema?: any | null, isTool: boolean, applicationId?: string | null, createdAt: string, updatedAt: string }> } };
|
||||
export type FindOneApplicationQuery = { __typename?: 'Query', findOneApplication: { __typename?: 'Application', id: string, name: string, description: string, version: string, universalIdentifier: string, canBeUninstalled: boolean, defaultRoleId?: string | null, availablePackages: any, applicationVariables: Array<{ __typename?: 'ApplicationVariable', id: string, key: string, value: string, description: string, isSecret: boolean }>, agents: Array<{ __typename?: 'Agent', id: string, name: string, label: string, description?: string | null, icon?: string | null, prompt: string, modelId: string, responseFormat?: any | null, roleId?: string | null, isCustom: boolean, modelConfiguration?: any | null, evaluationInputs: Array<string>, applicationId?: string | null, createdAt: string, updatedAt: string }>, objects: Array<{ __typename?: 'Object', id: string, universalIdentifier: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, isCustom: boolean, isRemote: boolean, isActive: boolean, isSystem: boolean, isUIReadOnly: boolean, createdAt: string, updatedAt: string, labelIdentifierFieldMetadataId?: string | null, imageIdentifierFieldMetadataId?: string | null, applicationId: string, shortcut?: string | null, isLabelSyncedWithName: boolean, isSearchable: boolean, duplicateCriteria?: Array<Array<string>> | null, indexMetadataList: Array<{ __typename?: 'Index', id: string, createdAt: string, updatedAt: string, name: string, indexWhereClause?: string | null, indexType: IndexType, isUnique: boolean, isCustom?: boolean | null, indexFieldMetadataList: Array<{ __typename?: 'IndexField', id: string, fieldMetadataId: string, createdAt: string, updatedAt: string, order: number }> }>, fieldsList: Array<{ __typename?: 'Field', id: string, universalIdentifier: string, type: FieldMetadataType, name: string, label: string, description?: string | null, icon?: string | null, isCustom?: boolean | null, isActive?: boolean | null, isSystem?: boolean | null, isUIReadOnly?: boolean | null, isNullable?: boolean | null, isUnique?: boolean | null, createdAt: string, updatedAt: string, defaultValue?: any | null, options?: any | null, settings?: any | null, isLabelSyncedWithName?: boolean | null, morphId?: string | null, applicationId: string, relation?: { __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } } | null, morphRelations?: Array<{ __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } }> | null }> }>, logicFunctions: Array<{ __typename?: 'LogicFunction', id: string, name: string, description?: string | null, runtime: string, timeoutSeconds: number, sourceHandlerPath: string, handlerName: string, toolInputSchema?: any | null, isTool: boolean, applicationId?: string | null, createdAt: string, updatedAt: string }> } };
|
||||
|
||||
export type UploadFileMutationVariables = Exact<{
|
||||
file: Scalars['Upload'];
|
||||
@@ -6008,7 +6008,7 @@ export type FindOneNavigationMenuItemQueryVariables = Exact<{
|
||||
|
||||
export type FindOneNavigationMenuItemQuery = { __typename?: 'Query', navigationMenuItem?: { __typename?: 'NavigationMenuItem', id: string, userWorkspaceId?: string | null, targetRecordId?: string | null, targetObjectMetadataId?: string | null, viewId?: string | null, folderId?: string | null, name?: string | null, link?: string | null, icon?: string | null, position: number, applicationId?: string | null, createdAt: string, updatedAt: string, targetRecordIdentifier?: { __typename?: 'RecordIdentifier', id: string, labelIdentifier: string, imageIdentifier?: string | null } | null } | null };
|
||||
|
||||
export type ObjectMetadataFieldsFragment = { __typename?: 'Object', id: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, isCustom: boolean, isRemote: boolean, isActive: boolean, isSystem: boolean, isUIReadOnly: boolean, createdAt: string, updatedAt: string, labelIdentifierFieldMetadataId?: string | null, imageIdentifierFieldMetadataId?: string | null, applicationId: string, shortcut?: string | null, isLabelSyncedWithName: boolean, isSearchable: boolean, duplicateCriteria?: Array<Array<string>> | null, indexMetadataList: Array<{ __typename?: 'Index', id: string, createdAt: string, updatedAt: string, name: string, indexWhereClause?: string | null, indexType: IndexType, isUnique: boolean, isCustom?: boolean | null, indexFieldMetadataList: Array<{ __typename?: 'IndexField', id: string, fieldMetadataId: string, createdAt: string, updatedAt: string, order: number }> }>, fieldsList: Array<{ __typename?: 'Field', id: string, type: FieldMetadataType, name: string, label: string, description?: string | null, icon?: string | null, isCustom?: boolean | null, isActive?: boolean | null, isSystem?: boolean | null, isUIReadOnly?: boolean | null, isNullable?: boolean | null, isUnique?: boolean | null, createdAt: string, updatedAt: string, defaultValue?: any | null, options?: any | null, settings?: any | null, isLabelSyncedWithName?: boolean | null, morphId?: string | null, applicationId: string, relation?: { __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } } | null, morphRelations?: Array<{ __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } }> | null }> };
|
||||
export type ObjectMetadataFieldsFragment = { __typename?: 'Object', id: string, universalIdentifier: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, isCustom: boolean, isRemote: boolean, isActive: boolean, isSystem: boolean, isUIReadOnly: boolean, createdAt: string, updatedAt: string, labelIdentifierFieldMetadataId?: string | null, imageIdentifierFieldMetadataId?: string | null, applicationId: string, shortcut?: string | null, isLabelSyncedWithName: boolean, isSearchable: boolean, duplicateCriteria?: Array<Array<string>> | null, indexMetadataList: Array<{ __typename?: 'Index', id: string, createdAt: string, updatedAt: string, name: string, indexWhereClause?: string | null, indexType: IndexType, isUnique: boolean, isCustom?: boolean | null, indexFieldMetadataList: Array<{ __typename?: 'IndexField', id: string, fieldMetadataId: string, createdAt: string, updatedAt: string, order: number }> }>, fieldsList: Array<{ __typename?: 'Field', id: string, universalIdentifier: string, type: FieldMetadataType, name: string, label: string, description?: string | null, icon?: string | null, isCustom?: boolean | null, isActive?: boolean | null, isSystem?: boolean | null, isUIReadOnly?: boolean | null, isNullable?: boolean | null, isUnique?: boolean | null, createdAt: string, updatedAt: string, defaultValue?: any | null, options?: any | null, settings?: any | null, isLabelSyncedWithName?: boolean | null, morphId?: string | null, applicationId: string, relation?: { __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } } | null, morphRelations?: Array<{ __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } }> | null }> };
|
||||
|
||||
export type CreateOneObjectMetadataItemMutationVariables = Exact<{
|
||||
input: CreateOneObjectInput;
|
||||
@@ -6057,7 +6057,7 @@ export type DeleteOneFieldMetadataItemMutation = { __typename?: 'Mutation', dele
|
||||
export type ObjectMetadataItemsQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type ObjectMetadataItemsQuery = { __typename?: 'Query', objects: { __typename?: 'ObjectConnection', edges: Array<{ __typename?: 'ObjectEdge', node: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, isCustom: boolean, isRemote: boolean, isActive: boolean, isSystem: boolean, isUIReadOnly: boolean, createdAt: string, updatedAt: string, labelIdentifierFieldMetadataId?: string | null, imageIdentifierFieldMetadataId?: string | null, applicationId: string, shortcut?: string | null, isLabelSyncedWithName: boolean, isSearchable: boolean, duplicateCriteria?: Array<Array<string>> | null, indexMetadataList: Array<{ __typename?: 'Index', id: string, createdAt: string, updatedAt: string, name: string, indexWhereClause?: string | null, indexType: IndexType, isUnique: boolean, isCustom?: boolean | null, indexFieldMetadataList: Array<{ __typename?: 'IndexField', id: string, fieldMetadataId: string, createdAt: string, updatedAt: string, order: number }> }>, fieldsList: Array<{ __typename?: 'Field', id: string, type: FieldMetadataType, name: string, label: string, description?: string | null, icon?: string | null, isCustom?: boolean | null, isActive?: boolean | null, isSystem?: boolean | null, isUIReadOnly?: boolean | null, isNullable?: boolean | null, isUnique?: boolean | null, createdAt: string, updatedAt: string, defaultValue?: any | null, options?: any | null, settings?: any | null, isLabelSyncedWithName?: boolean | null, morphId?: string | null, applicationId: string, relation?: { __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } } | null, morphRelations?: Array<{ __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } }> | null }> } }>, pageInfo: { __typename?: 'PageInfo', hasNextPage?: boolean | null, hasPreviousPage?: boolean | null, startCursor?: any | null, endCursor?: any | null } } };
|
||||
export type ObjectMetadataItemsQuery = { __typename?: 'Query', objects: { __typename?: 'ObjectConnection', edges: Array<{ __typename?: 'ObjectEdge', node: { __typename?: 'Object', id: string, universalIdentifier: string, nameSingular: string, namePlural: string, labelSingular: string, labelPlural: string, description?: string | null, icon?: string | null, isCustom: boolean, isRemote: boolean, isActive: boolean, isSystem: boolean, isUIReadOnly: boolean, createdAt: string, updatedAt: string, labelIdentifierFieldMetadataId?: string | null, imageIdentifierFieldMetadataId?: string | null, applicationId: string, shortcut?: string | null, isLabelSyncedWithName: boolean, isSearchable: boolean, duplicateCriteria?: Array<Array<string>> | null, indexMetadataList: Array<{ __typename?: 'Index', id: string, createdAt: string, updatedAt: string, name: string, indexWhereClause?: string | null, indexType: IndexType, isUnique: boolean, isCustom?: boolean | null, indexFieldMetadataList: Array<{ __typename?: 'IndexField', id: string, fieldMetadataId: string, createdAt: string, updatedAt: string, order: number }> }>, fieldsList: Array<{ __typename?: 'Field', id: string, universalIdentifier: string, type: FieldMetadataType, name: string, label: string, description?: string | null, icon?: string | null, isCustom?: boolean | null, isActive?: boolean | null, isSystem?: boolean | null, isUIReadOnly?: boolean | null, isNullable?: boolean | null, isUnique?: boolean | null, createdAt: string, updatedAt: string, defaultValue?: any | null, options?: any | null, settings?: any | null, isLabelSyncedWithName?: boolean | null, morphId?: string | null, applicationId: string, relation?: { __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } } | null, morphRelations?: Array<{ __typename?: 'Relation', type: RelationType, sourceObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, targetObjectMetadata: { __typename?: 'Object', id: string, nameSingular: string, namePlural: string }, sourceFieldMetadata: { __typename?: 'Field', id: string, name: string }, targetFieldMetadata: { __typename?: 'Field', id: string, name: string } }> | null }> } }>, pageInfo: { __typename?: 'PageInfo', hasNextPage?: boolean | null, hasPreviousPage?: boolean | null, startCursor?: any | null, endCursor?: any | null } } };
|
||||
|
||||
export type ObjectRecordCountsQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
@@ -7034,6 +7034,7 @@ export const AgentFieldsFragmentDoc = gql`
|
||||
export const ObjectMetadataFieldsFragmentDoc = gql`
|
||||
fragment ObjectMetadataFields on Object {
|
||||
id
|
||||
universalIdentifier
|
||||
nameSingular
|
||||
namePlural
|
||||
labelSingular
|
||||
@@ -7073,6 +7074,7 @@ export const ObjectMetadataFieldsFragmentDoc = gql`
|
||||
}
|
||||
fieldsList {
|
||||
id
|
||||
universalIdentifier
|
||||
type
|
||||
name
|
||||
label
|
||||
|
||||
+13
-10
@@ -21,10 +21,10 @@ const taskTarget = {
|
||||
id: '89bb825c-171e-4bcc-9cf7-43448d6fb300',
|
||||
createdAt: '2023-04-26T10:12:42.33625+00:00',
|
||||
updatedAt: '2023-04-26T10:23:42.33625+00:00',
|
||||
companyId: null,
|
||||
company: null,
|
||||
personId: '89bb825c-171e-4bcc-9cf7-43448d6fb280',
|
||||
person: {
|
||||
targetCompanyId: null,
|
||||
targetCompany: null,
|
||||
targetPersonId: '89bb825c-171e-4bcc-9cf7-43448d6fb280',
|
||||
targetPerson: {
|
||||
id: '89bb825c-171e-4bcc-9cf7-43448d6fb280',
|
||||
createdAt: '2023-04-26T10:12:42.33625+00:00',
|
||||
updatedAt: '2023-04-26T10:23:42.33625+00:00',
|
||||
@@ -58,21 +58,24 @@ cache.writeFragment({
|
||||
__typename
|
||||
updatedAt
|
||||
createdAt
|
||||
personId
|
||||
targetPersonId
|
||||
taskId
|
||||
companyId
|
||||
targetCompanyId
|
||||
id
|
||||
task {
|
||||
__typename
|
||||
createdAt
|
||||
title
|
||||
updatedAt
|
||||
body
|
||||
bodyV2 {
|
||||
blocknote
|
||||
markdown
|
||||
}
|
||||
dueAt
|
||||
id
|
||||
assigneeId
|
||||
}
|
||||
person {
|
||||
targetPerson {
|
||||
__typename
|
||||
id
|
||||
createdAt
|
||||
@@ -83,7 +86,7 @@ cache.writeFragment({
|
||||
lastName
|
||||
}
|
||||
}
|
||||
company {
|
||||
targetCompany {
|
||||
__typename
|
||||
id
|
||||
createdAt
|
||||
@@ -164,7 +167,7 @@ describe('useActivityTargetObjectRecords', () => {
|
||||
expect(activityTargetObjectRecords).toHaveLength(1);
|
||||
expect(activityTargetObjectRecords[0].activityTarget).toEqual(taskTarget);
|
||||
expect(activityTargetObjectRecords[0].targetObject).toEqual(
|
||||
taskTarget.person,
|
||||
taskTarget.targetPerson,
|
||||
);
|
||||
expect(
|
||||
activityTargetObjectRecords[0].targetObjectMetadataItem.nameSingular,
|
||||
|
||||
+33
-63
@@ -1,11 +1,14 @@
|
||||
import { type MockedResponse } from '@apollo/client/testing';
|
||||
import { act, renderHook } from '@testing-library/react';
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
import { createOneActivityOperationSignatureFactory } from '@/activities/graphql/operation-signatures/factories/createOneActivityOperationSignatureFactory';
|
||||
import { useCreateActivityInDB } from '@/activities/hooks/useCreateActivityInDB';
|
||||
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
|
||||
import { generateCreateOneRecordMutation } from '@/object-metadata/utils/generateCreateOneRecordMutation';
|
||||
import { getJestMetadataAndApolloMocksWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksWrapper';
|
||||
import { mockedTasks } from '~/testing/mock-data/tasks';
|
||||
import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockObjectMetadataItems';
|
||||
import { getMockObjectMetadataItemOrThrow } from '~/testing/utils/getMockObjectMetadataItemOrThrow';
|
||||
|
||||
const mockedDate = '2024-03-15T12:00:00.000Z';
|
||||
const toISOStringMock = jest.fn(() => mockedDate);
|
||||
@@ -21,74 +24,41 @@ const mockedActivity = {
|
||||
updatedAt: mockedDate,
|
||||
};
|
||||
|
||||
const taskMetadataItem = getMockObjectMetadataItemOrThrow('task');
|
||||
|
||||
const operationSignature = createOneActivityOperationSignatureFactory({
|
||||
objectNameSingular: CoreObjectNameSingular.Task,
|
||||
});
|
||||
|
||||
const createOneTaskMutation = generateCreateOneRecordMutation({
|
||||
objectMetadataItem: taskMetadataItem,
|
||||
objectMetadataItems: generatedMockObjectMetadataItems,
|
||||
recordGqlFields: operationSignature.fields,
|
||||
objectPermissionsByObjectMetadataId: {},
|
||||
});
|
||||
|
||||
const mockResult = jest.fn(() => ({
|
||||
data: {
|
||||
createTask: {
|
||||
...mockedActivity,
|
||||
__typename: 'Activity',
|
||||
assigneeId: '',
|
||||
authorId: '1',
|
||||
reminderAt: null,
|
||||
createdAt: mockedDate,
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
const mocks: MockedResponse[] = [
|
||||
{
|
||||
request: {
|
||||
query: gql`
|
||||
mutation CreateOneTask($input: TaskCreateInput!) {
|
||||
createTask(data: $input) {
|
||||
__typename
|
||||
assignee {
|
||||
__typename
|
||||
id
|
||||
name {
|
||||
firstName
|
||||
lastName
|
||||
}
|
||||
}
|
||||
assigneeId
|
||||
attachments {
|
||||
edges {
|
||||
node {
|
||||
__typename
|
||||
authorId
|
||||
companyId
|
||||
createdAt
|
||||
deletedAt
|
||||
fullPath
|
||||
id
|
||||
name
|
||||
noteId
|
||||
opportunityId
|
||||
personId
|
||||
petId
|
||||
rocketId
|
||||
surveyResultId
|
||||
taskId
|
||||
type
|
||||
updatedAt
|
||||
}
|
||||
}
|
||||
}
|
||||
bodyV2 {
|
||||
blocknote
|
||||
markdown
|
||||
}
|
||||
createdAt
|
||||
dueAt
|
||||
id
|
||||
status
|
||||
title
|
||||
updatedAt
|
||||
}
|
||||
}
|
||||
`,
|
||||
query: createOneTaskMutation,
|
||||
variables: {
|
||||
input: mockedActivity,
|
||||
},
|
||||
},
|
||||
result: jest.fn(() => ({
|
||||
data: {
|
||||
createTask: {
|
||||
...mockedActivity,
|
||||
__typename: 'Activity',
|
||||
assigneeId: '',
|
||||
authorId: '1',
|
||||
reminderAt: null,
|
||||
createdAt: mockedDate,
|
||||
},
|
||||
},
|
||||
})),
|
||||
result: mockResult,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -114,6 +84,6 @@ describe('useCreateActivityInDB', () => {
|
||||
});
|
||||
});
|
||||
|
||||
expect(mocks[0].result).toHaveBeenCalled();
|
||||
expect(mockResult).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -8,7 +8,7 @@ import { ToolStepRenderer } from '@/ai/components/ToolStepRenderer';
|
||||
import { groupContiguousThinkingStepParts } from '@/ai/utils/groupContiguousThinkingStepParts';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { isStaticToolUIPart } from 'ai';
|
||||
import { isToolUIPart, type ToolUIPart } from 'ai';
|
||||
import { type ExtendedUIMessagePart } from 'twenty-shared/ai';
|
||||
|
||||
const StyledMessagePartsContainer = styled.div`
|
||||
@@ -67,8 +67,13 @@ const MessagePartRenderer = ({
|
||||
/>
|
||||
);
|
||||
default:
|
||||
if (isStaticToolUIPart(part) === true) {
|
||||
return <ToolStepRenderer toolPart={part} isStreaming={isStreaming} />;
|
||||
if (isToolUIPart(part) === true && part.type !== 'dynamic-tool') {
|
||||
return (
|
||||
<ToolStepRenderer
|
||||
toolPart={part as ToolUIPart}
|
||||
isStreaming={isStreaming}
|
||||
/>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { isStaticToolUIPart } from 'ai';
|
||||
import { isToolUIPart } from 'ai';
|
||||
import { type ExtendedUIMessagePart } from 'twenty-shared/ai';
|
||||
|
||||
import { type ThinkingStepPart } from '@/ai/utils/thinkingStepPart';
|
||||
@@ -10,5 +10,5 @@ export const isThinkingStepPart = (
|
||||
return true;
|
||||
}
|
||||
|
||||
return isStaticToolUIPart(part) && part.type !== 'tool-code_interpreter';
|
||||
return isToolUIPart(part) && part.type !== 'tool-code_interpreter';
|
||||
};
|
||||
|
||||
+38
-231
@@ -1,7 +1,10 @@
|
||||
import { renderHook, waitFor } from '@testing-library/react';
|
||||
|
||||
import { fetchAllThreadMessagesOperationSignatureFactory } from '@/activities/emails/graphql/operation-signatures/factories/fetchAllThreadMessagesOperationSignatureFactory';
|
||||
import { useEmailThreadInCommandMenu } from '@/command-menu/pages/message-thread/hooks/useEmailThreadInCommandMenu';
|
||||
import { viewableRecordIdComponentState } from '@/command-menu/pages/record-page/states/viewableRecordIdComponentState';
|
||||
import { CommandMenuPageComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuPageComponentInstanceContext';
|
||||
import { generateFindManyRecordsQuery } from '@/object-record/utils/generateFindManyRecordsQuery';
|
||||
import gql from 'graphql-tag';
|
||||
import {
|
||||
QUERY_DEFAULT_LIMIT_RECORDS,
|
||||
@@ -10,7 +13,39 @@ import {
|
||||
import { MessageParticipantRole } from 'twenty-shared/types';
|
||||
import { generateEmptyJestRecordNode } from '~/testing/jest/generateEmptyJestRecordNode';
|
||||
import { getJestMetadataAndApolloMocksWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksWrapper';
|
||||
import { useEmailThreadInCommandMenu } from '@/command-menu/pages/message-thread/hooks/useEmailThreadInCommandMenu';
|
||||
import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockObjectMetadataItems';
|
||||
import { getMockObjectMetadataItemOrThrow } from '~/testing/utils/getMockObjectMetadataItemOrThrow';
|
||||
|
||||
const messageMetadataItem = getMockObjectMetadataItemOrThrow('message');
|
||||
const messageParticipantMetadataItem =
|
||||
getMockObjectMetadataItemOrThrow('messageParticipant');
|
||||
|
||||
const messageOperationSignature =
|
||||
fetchAllThreadMessagesOperationSignatureFactory({
|
||||
messageThreadId: '1',
|
||||
});
|
||||
|
||||
const findManyMessagesQuery = generateFindManyRecordsQuery({
|
||||
objectMetadataItem: messageMetadataItem,
|
||||
objectMetadataItems: generatedMockObjectMetadataItems,
|
||||
recordGqlFields: messageOperationSignature.fields,
|
||||
objectPermissionsByObjectMetadataId: {},
|
||||
});
|
||||
|
||||
const findManyMessageParticipantsQuery = generateFindManyRecordsQuery({
|
||||
objectMetadataItem: messageParticipantMetadataItem,
|
||||
objectMetadataItems: generatedMockObjectMetadataItems,
|
||||
recordGqlFields: {
|
||||
id: true,
|
||||
role: true,
|
||||
displayName: true,
|
||||
messageId: true,
|
||||
handle: true,
|
||||
person: true,
|
||||
workspaceMember: true,
|
||||
},
|
||||
objectPermissionsByObjectMetadataId: {},
|
||||
});
|
||||
|
||||
const mocks = [
|
||||
{
|
||||
@@ -36,129 +71,7 @@ const mocks = [
|
||||
},
|
||||
{
|
||||
request: {
|
||||
query: gql`
|
||||
query FindManyMessages(
|
||||
$filter: MessageFilterInput
|
||||
$orderBy: [MessageOrderByInput]
|
||||
$lastCursor: String
|
||||
$limit: Int
|
||||
$offset: Int
|
||||
) {
|
||||
messages(
|
||||
filter: $filter
|
||||
orderBy: $orderBy
|
||||
first: $limit
|
||||
after: $lastCursor
|
||||
offset: $offset
|
||||
) {
|
||||
edges {
|
||||
node {
|
||||
__typename
|
||||
createdAt
|
||||
headerMessageId
|
||||
id
|
||||
messageParticipants {
|
||||
edges {
|
||||
node {
|
||||
__typename
|
||||
displayName
|
||||
handle
|
||||
id
|
||||
person {
|
||||
__typename
|
||||
avatarUrl
|
||||
city
|
||||
companyId
|
||||
createdAt
|
||||
createdBy {
|
||||
source
|
||||
workspaceMemberId
|
||||
name
|
||||
context
|
||||
}
|
||||
deletedAt
|
||||
emails {
|
||||
primaryEmail
|
||||
additionalEmails
|
||||
}
|
||||
id
|
||||
intro
|
||||
jobTitle
|
||||
linkedinLink {
|
||||
primaryLinkUrl
|
||||
primaryLinkLabel
|
||||
secondaryLinks
|
||||
}
|
||||
name {
|
||||
firstName
|
||||
lastName
|
||||
}
|
||||
performanceRating
|
||||
phones {
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
primaryPhoneCallingCode
|
||||
additionalPhones
|
||||
}
|
||||
position
|
||||
updatedAt
|
||||
whatsapp {
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
primaryPhoneCallingCode
|
||||
additionalPhones
|
||||
}
|
||||
workPreference
|
||||
xLink {
|
||||
primaryLinkUrl
|
||||
primaryLinkLabel
|
||||
secondaryLinks
|
||||
}
|
||||
}
|
||||
role
|
||||
workspaceMember {
|
||||
__typename
|
||||
avatarUrl
|
||||
colorScheme
|
||||
createdAt
|
||||
dateFormat
|
||||
deletedAt
|
||||
id
|
||||
locale
|
||||
name {
|
||||
firstName
|
||||
lastName
|
||||
}
|
||||
position
|
||||
timeFormat
|
||||
timeZone
|
||||
updatedAt
|
||||
userEmail
|
||||
userId
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
messageThread {
|
||||
__typename
|
||||
id
|
||||
}
|
||||
receivedAt
|
||||
subject
|
||||
text
|
||||
}
|
||||
cursor
|
||||
}
|
||||
pageInfo {
|
||||
hasNextPage
|
||||
hasPreviousPage
|
||||
startCursor
|
||||
endCursor
|
||||
}
|
||||
totalCount
|
||||
}
|
||||
}
|
||||
`,
|
||||
query: findManyMessagesQuery,
|
||||
variables: {
|
||||
filter: { messageThreadId: { eq: '1' } },
|
||||
orderBy: [{ receivedAt: 'AscNullsLast' }],
|
||||
@@ -206,113 +119,7 @@ const mocks = [
|
||||
},
|
||||
{
|
||||
request: {
|
||||
query: gql`
|
||||
query FindManyMessageParticipants(
|
||||
$filter: MessageParticipantFilterInput
|
||||
$orderBy: [MessageParticipantOrderByInput]
|
||||
$lastCursor: String
|
||||
$limit: Int
|
||||
$offset: Int
|
||||
) {
|
||||
messageParticipants(
|
||||
filter: $filter
|
||||
orderBy: $orderBy
|
||||
first: $limit
|
||||
after: $lastCursor
|
||||
offset: $offset
|
||||
) {
|
||||
edges {
|
||||
node {
|
||||
__typename
|
||||
displayName
|
||||
handle
|
||||
id
|
||||
messageId
|
||||
person {
|
||||
__typename
|
||||
avatarUrl
|
||||
city
|
||||
companyId
|
||||
createdAt
|
||||
createdBy {
|
||||
source
|
||||
workspaceMemberId
|
||||
name
|
||||
context
|
||||
}
|
||||
deletedAt
|
||||
emails {
|
||||
primaryEmail
|
||||
additionalEmails
|
||||
}
|
||||
id
|
||||
intro
|
||||
jobTitle
|
||||
linkedinLink {
|
||||
primaryLinkUrl
|
||||
primaryLinkLabel
|
||||
secondaryLinks
|
||||
}
|
||||
name {
|
||||
firstName
|
||||
lastName
|
||||
}
|
||||
performanceRating
|
||||
phones {
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
primaryPhoneCallingCode
|
||||
additionalPhones
|
||||
}
|
||||
position
|
||||
updatedAt
|
||||
whatsapp {
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
primaryPhoneCallingCode
|
||||
additionalPhones
|
||||
}
|
||||
workPreference
|
||||
xLink {
|
||||
primaryLinkUrl
|
||||
primaryLinkLabel
|
||||
secondaryLinks
|
||||
}
|
||||
}
|
||||
role
|
||||
workspaceMember {
|
||||
__typename
|
||||
avatarUrl
|
||||
colorScheme
|
||||
createdAt
|
||||
dateFormat
|
||||
deletedAt
|
||||
id
|
||||
locale
|
||||
name {
|
||||
firstName
|
||||
lastName
|
||||
}
|
||||
position
|
||||
timeFormat
|
||||
timeZone
|
||||
updatedAt
|
||||
userEmail
|
||||
userId
|
||||
}
|
||||
}
|
||||
cursor
|
||||
}
|
||||
pageInfo {
|
||||
hasNextPage
|
||||
hasPreviousPage
|
||||
startCursor
|
||||
endCursor
|
||||
}
|
||||
totalCount
|
||||
}
|
||||
}
|
||||
`,
|
||||
query: findManyMessageParticipantsQuery,
|
||||
variables: {
|
||||
filter: {
|
||||
messageId: { in: ['1', '2'] },
|
||||
|
||||
@@ -66,30 +66,30 @@ export const initialFavorites: Favorite[] = [
|
||||
|
||||
export const sortedFavorites = [
|
||||
{
|
||||
id: '1',
|
||||
recordId: '1',
|
||||
position: 0,
|
||||
avatarType: 'rounded',
|
||||
avatarUrl: '',
|
||||
labelIdentifier: ' ',
|
||||
link: '/object/person/1',
|
||||
objectNameSingular: 'person',
|
||||
forWorkspaceMemberId: '1',
|
||||
favoriteFolderId: '1',
|
||||
__typename: 'Favorite',
|
||||
avatarType: 'squared',
|
||||
avatarUrl: undefined,
|
||||
favoriteFolderId: '1',
|
||||
forWorkspaceMemberId: '1',
|
||||
id: '1',
|
||||
labelIdentifier: 'ABC Corp',
|
||||
link: '/object/company/2',
|
||||
objectNameSingular: 'company',
|
||||
position: 0,
|
||||
recordId: '2',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
recordId: '3',
|
||||
position: 1,
|
||||
avatarType: 'rounded',
|
||||
avatarUrl: '',
|
||||
labelIdentifier: ' ',
|
||||
link: '/object/person/3',
|
||||
objectNameSingular: 'person',
|
||||
forWorkspaceMemberId: '1',
|
||||
favoriteFolderId: '1',
|
||||
__typename: 'Favorite',
|
||||
avatarType: 'squared',
|
||||
avatarUrl: undefined,
|
||||
favoriteFolderId: '1',
|
||||
forWorkspaceMemberId: '1',
|
||||
id: '2',
|
||||
labelIdentifier: 'Company Test',
|
||||
link: '/object/company/4',
|
||||
objectNameSingular: 'company',
|
||||
position: 1,
|
||||
recordId: '4',
|
||||
},
|
||||
{
|
||||
__typename: 'Favorite',
|
||||
|
||||
+1
-1
@@ -90,6 +90,6 @@ describe('useColumnDefinitionsFromObjectMetadata', () => {
|
||||
|
||||
const { columnDefinitions } = result.current;
|
||||
|
||||
expect(columnDefinitions.length).toBe(22);
|
||||
expect(columnDefinitions.length).toBe(25);
|
||||
});
|
||||
});
|
||||
|
||||
+2
-2
@@ -36,12 +36,12 @@ describe('useGetObjectRecordIdentifierByNameSingular', () => {
|
||||
wrapper: Wrapper,
|
||||
initialProps: {
|
||||
record: { id: 'recordId' } as any,
|
||||
objectNameSingular: 'viewSort',
|
||||
objectNameSingular: 'blocklist',
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
expect(result.current.linkToShowPage).toBe('/object/viewSort/recordId');
|
||||
expect(result.current.linkToShowPage).toBe('/object/blocklist/recordId');
|
||||
|
||||
rerender({
|
||||
record: { id: 'recordId', avatarUrl: 'https://fake-url.com' },
|
||||
|
||||
-2
@@ -25,10 +25,8 @@ export const mapPaginatedObjectMetadataItemsToObjectMetadataItems = ({
|
||||
object.node;
|
||||
|
||||
return {
|
||||
universalIdentifier: object.node.id,
|
||||
...objectWithoutFieldsList,
|
||||
fields: fieldsList.map((field) => ({
|
||||
universalIdentifier: field.id,
|
||||
...field,
|
||||
})),
|
||||
labelIdentifierFieldMetadataId,
|
||||
|
||||
+31
-29
@@ -6,6 +6,33 @@ import { FieldMetadataType, RelationType } from '~/generated-metadata/graphql';
|
||||
import { camelCaseStringSchema } from '~/utils/validation-schemas/camelCaseStringSchema';
|
||||
|
||||
export const fieldMetadataItemSchema = (existingLabels?: string[]) => {
|
||||
const relationObjectSchema = z.object({
|
||||
__typename: z.literal('Relation').optional(),
|
||||
type: z.enum(RelationType),
|
||||
sourceFieldMetadata: z.object({
|
||||
__typename: z.literal('Field').optional(),
|
||||
id: z.uuid(),
|
||||
name: z.string().trim().min(1),
|
||||
}),
|
||||
sourceObjectMetadata: z.object({
|
||||
__typename: z.literal('Object').optional(),
|
||||
id: z.uuid(),
|
||||
namePlural: z.string().trim().min(1),
|
||||
nameSingular: z.string().trim().min(1),
|
||||
}),
|
||||
targetFieldMetadata: z.object({
|
||||
__typename: z.literal('Field').optional(),
|
||||
id: z.uuid(),
|
||||
name: z.string().trim().min(1),
|
||||
}),
|
||||
targetObjectMetadata: z.object({
|
||||
__typename: z.literal('Object').optional(),
|
||||
id: z.uuid(),
|
||||
namePlural: z.string().trim().min(1),
|
||||
nameSingular: z.string().trim().min(1),
|
||||
}),
|
||||
});
|
||||
|
||||
return z.object({
|
||||
__typename: z.literal('Field').optional(),
|
||||
createdAt: z.iso.datetime(),
|
||||
@@ -16,6 +43,7 @@ export const fieldMetadataItemSchema = (existingLabels?: string[]) => {
|
||||
.nullable()
|
||||
.optional(),
|
||||
id: z.uuid(),
|
||||
universalIdentifier: z.string(),
|
||||
applicationId: z.uuid(),
|
||||
isActive: z.boolean(),
|
||||
isCustom: z.boolean(),
|
||||
@@ -25,6 +53,8 @@ export const fieldMetadataItemSchema = (existingLabels?: string[]) => {
|
||||
isUIReadOnly: z.boolean(),
|
||||
label: metadataLabelSchema(existingLabels),
|
||||
isLabelSyncedWithName: z.boolean(),
|
||||
morphId: z.string().nullable().optional(),
|
||||
morphRelations: z.array(relationObjectSchema).nullable().optional(),
|
||||
name: camelCaseStringSchema,
|
||||
options: z
|
||||
.array(
|
||||
@@ -39,35 +69,7 @@ export const fieldMetadataItemSchema = (existingLabels?: string[]) => {
|
||||
.nullable()
|
||||
.optional(),
|
||||
settings: z.any().optional(),
|
||||
relation: z
|
||||
.object({
|
||||
__typename: z.literal('Relation').optional(),
|
||||
type: z.enum(RelationType),
|
||||
sourceFieldMetadata: z.object({
|
||||
__typename: z.literal('Field').optional(),
|
||||
id: z.uuid(),
|
||||
name: z.string().trim().min(1),
|
||||
}),
|
||||
sourceObjectMetadata: z.object({
|
||||
__typename: z.literal('Object').optional(),
|
||||
id: z.uuid(),
|
||||
namePlural: z.string().trim().min(1),
|
||||
nameSingular: z.string().trim().min(1),
|
||||
}),
|
||||
targetFieldMetadata: z.object({
|
||||
__typename: z.literal('Field').optional(),
|
||||
id: z.uuid(),
|
||||
name: z.string().trim().min(1),
|
||||
}),
|
||||
targetObjectMetadata: z.object({
|
||||
__typename: z.literal('Object').optional(),
|
||||
id: z.uuid(),
|
||||
namePlural: z.string().trim().min(1),
|
||||
nameSingular: z.string().trim().min(1),
|
||||
}),
|
||||
})
|
||||
.nullable()
|
||||
.optional(),
|
||||
relation: relationObjectSchema.nullable().optional(),
|
||||
type: z.enum(FieldMetadataType),
|
||||
updatedAt: z.iso.datetime(),
|
||||
});
|
||||
|
||||
+1
@@ -14,5 +14,6 @@ export const indexMetadataItemSchema = z.object({
|
||||
indexType: z.enum(IndexType),
|
||||
indexWhereClause: z.string().nullable(),
|
||||
isUnique: z.boolean(),
|
||||
isCustom: z.boolean().nullable().optional(),
|
||||
objectMetadata: z.any(),
|
||||
}) satisfies z.ZodType<IndexMetadataItem>;
|
||||
|
||||
+2
-1
@@ -16,7 +16,8 @@ export const objectMetadataItemSchema = z.object({
|
||||
icon: z.string().startsWith('Icon').trim(),
|
||||
applicationId: z.uuid(),
|
||||
id: z.uuid(),
|
||||
duplicateCriteria: z.array(z.array(z.string())),
|
||||
universalIdentifier: z.string(),
|
||||
duplicateCriteria: z.array(z.array(z.string())).nullable(),
|
||||
imageIdentifierFieldMetadataId: z.uuid().nullable(),
|
||||
isActive: z.boolean(),
|
||||
isCustom: z.boolean(),
|
||||
|
||||
+147
-59
@@ -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,
|
||||
}
|
||||
`;
|
||||
|
||||
+19
-2
@@ -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,
|
||||
|
||||
+8
-1
@@ -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,
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
export const PERSON_FRAGMENT_WITH_DEPTH_ZERO_RELATIONS = `
|
||||
__typename
|
||||
avatarFile {
|
||||
fileId
|
||||
label
|
||||
extension
|
||||
url
|
||||
}
|
||||
avatarUrl
|
||||
city
|
||||
companyId
|
||||
@@ -36,6 +42,12 @@ export const PERSON_FRAGMENT_WITH_DEPTH_ZERO_RELATIONS = `
|
||||
}
|
||||
position
|
||||
updatedAt
|
||||
updatedBy {
|
||||
source
|
||||
workspaceMemberId
|
||||
name
|
||||
context
|
||||
}
|
||||
whatsapp {
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
@@ -61,6 +73,12 @@ export const PERSON_FRAGMENT_WITH_DEPTH_ONE_RELATIONS = `
|
||||
}
|
||||
}
|
||||
}
|
||||
avatarFile {
|
||||
fileId
|
||||
label
|
||||
extension
|
||||
url
|
||||
}
|
||||
avatarUrl
|
||||
calendarEventParticipants {
|
||||
edges {
|
||||
@@ -71,6 +89,19 @@ export const PERSON_FRAGMENT_WITH_DEPTH_ONE_RELATIONS = `
|
||||
}
|
||||
}
|
||||
}
|
||||
caredForPets {
|
||||
edges {
|
||||
node {
|
||||
__typename
|
||||
id
|
||||
pet {
|
||||
__typename
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
city
|
||||
company {
|
||||
__typename
|
||||
@@ -154,6 +185,24 @@ export const PERSON_FRAGMENT_WITH_DEPTH_ONE_RELATIONS = `
|
||||
}
|
||||
}
|
||||
position
|
||||
previousCompanies {
|
||||
edges {
|
||||
node {
|
||||
__typename
|
||||
company {
|
||||
__typename
|
||||
domainName {
|
||||
primaryLinkUrl
|
||||
primaryLinkLabel
|
||||
secondaryLinks
|
||||
}
|
||||
id
|
||||
name
|
||||
}
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
taskTargets {
|
||||
edges {
|
||||
node {
|
||||
@@ -172,10 +221,17 @@ export const PERSON_FRAGMENT_WITH_DEPTH_ONE_RELATIONS = `
|
||||
node {
|
||||
__typename
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
updatedAt
|
||||
updatedBy {
|
||||
source
|
||||
workspaceMemberId
|
||||
name
|
||||
context
|
||||
}
|
||||
whatsapp {
|
||||
primaryPhoneNumber
|
||||
primaryPhoneCountryCode
|
||||
|
||||
+7
-7
@@ -32,7 +32,7 @@ import { getFieldInputEventContextProviderWithJestMocks } from './utils/getField
|
||||
const RelationWorkspaceSetterEffect = () => {
|
||||
const setRecordFieldInputLayoutDirectionLoading = useSetAtomComponentState(
|
||||
recordFieldInputLayoutDirectionLoadingComponentState,
|
||||
'relation-to-one-field-input-123-Relation',
|
||||
'relation-to-one-field-input-123-company',
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -75,18 +75,18 @@ const RelationManyToOneFieldInputWithContext = ({
|
||||
<FieldContext.Provider
|
||||
value={{
|
||||
fieldDefinition: {
|
||||
fieldMetadataId: 'e82262eb-7f58-4167-a23c-fc51ec584d1b',
|
||||
label: 'Relation',
|
||||
fieldMetadataId: 'f6be42ac-ccb8-4df0-8c22-a9627d655c76',
|
||||
label: 'Company',
|
||||
type: FieldMetadataType.RELATION,
|
||||
iconName: 'IconLink',
|
||||
metadata: {
|
||||
fieldName: 'Relation',
|
||||
fieldName: 'company',
|
||||
relationObjectMetadataNamePlural: 'companies',
|
||||
relationObjectMetadataNameSingular:
|
||||
CoreObjectNameSingular.Company,
|
||||
relationObjectMetadataId: '4a45f524-b8cb-40e8-8450-28e402b442cf',
|
||||
relationObjectMetadataId: '69e0aa5d-a9c5-486b-a99d-fe191195a19d',
|
||||
objectMetadataNameSingular: 'person',
|
||||
relationFieldMetadataId: '3c211c59-02a1-4904-ad0f-5bb30b736461',
|
||||
relationFieldMetadataId: '94902a74-b8ca-4a56-8573-7469f0b664f6',
|
||||
},
|
||||
},
|
||||
recordId: recordId,
|
||||
@@ -96,7 +96,7 @@ const RelationManyToOneFieldInputWithContext = ({
|
||||
>
|
||||
<RecordFieldComponentInstanceContext.Provider
|
||||
value={{
|
||||
instanceId: 'relation-to-one-field-input-123-Relation',
|
||||
instanceId: 'relation-to-one-field-input-123-company',
|
||||
}}
|
||||
>
|
||||
<FieldInputEventContextProviderWithJestMocks>
|
||||
|
||||
+5
-5
@@ -39,17 +39,17 @@ const RelationOneToManyFieldInputWithContext = () => {
|
||||
|
||||
const fieldDefinition = useMemo(
|
||||
() => ({
|
||||
fieldMetadataId: 'e82262eb-7f58-4167-a23c-fc51ec584d1b',
|
||||
fieldMetadataId: '94902a74-b8ca-4a56-8573-7469f0b664f6',
|
||||
label: 'People',
|
||||
type: FieldMetadataType.RELATION,
|
||||
iconName: 'IconLink',
|
||||
metadata: {
|
||||
fieldName: 'people',
|
||||
relationType: RelationType.ONE_TO_MANY,
|
||||
relationObjectMetadataNamePlural: 'companies',
|
||||
relationObjectMetadataNameSingular: CoreObjectNameSingular.Company,
|
||||
objectMetadataNameSingular: 'person',
|
||||
relationFieldMetadataId: '3c211c59-02a1-4904-ad0f-5bb30b736461',
|
||||
relationObjectMetadataNamePlural: 'people',
|
||||
relationObjectMetadataNameSingular: CoreObjectNameSingular.Person,
|
||||
objectMetadataNameSingular: 'company',
|
||||
relationFieldMetadataId: 'f6be42ac-ccb8-4df0-8c22-a9627d655c76',
|
||||
},
|
||||
}),
|
||||
[],
|
||||
|
||||
+4
-15
@@ -21,18 +21,7 @@ const DEFAULT_ACTION = {
|
||||
objectName: 'person',
|
||||
objectRecordId: '',
|
||||
objectRecord: {},
|
||||
fieldsToUpdate: [
|
||||
'updatedAt',
|
||||
'averageEstimatedNumberOfAtomsInTheUniverse',
|
||||
'comments',
|
||||
'createdAt',
|
||||
'deletedAt',
|
||||
'name',
|
||||
'participants',
|
||||
'percentageOfCompletion',
|
||||
'score',
|
||||
'shortNotes',
|
||||
],
|
||||
fieldsToUpdate: ['city', 'emails', 'jobTitle', 'name', 'phones'],
|
||||
},
|
||||
outputSchema: {},
|
||||
errorHandlingOptions: {
|
||||
@@ -107,7 +96,7 @@ export const DisabledWithEmptyValues: Story = {
|
||||
|
||||
const firstSelectedUpdatableField = await within(
|
||||
await canvas.findByTestId('workflow-fields-multi-select'),
|
||||
).findByText('Creation date');
|
||||
).findByText('City');
|
||||
|
||||
await userEvent.click(firstSelectedUpdatableField);
|
||||
|
||||
@@ -164,7 +153,7 @@ export const DisabledWithDefaultStaticValues: Story = {
|
||||
|
||||
const firstSelectedUpdatableField = await within(
|
||||
await canvas.findByTestId('workflow-fields-multi-select'),
|
||||
).findByText('Creation date');
|
||||
).findByText('City');
|
||||
|
||||
await userEvent.click(firstSelectedUpdatableField);
|
||||
|
||||
@@ -215,7 +204,7 @@ export const DisabledWithDefaultVariableValues: Story = {
|
||||
|
||||
const firstSelectedUpdatableField = await within(
|
||||
await canvas.findByTestId('workflow-fields-multi-select'),
|
||||
).findByText('Creation date');
|
||||
).findByText('City');
|
||||
|
||||
await userEvent.click(firstSelectedUpdatableField);
|
||||
|
||||
|
||||
+24293
-17771
File diff suppressed because it is too large
Load Diff
@@ -4,16 +4,6 @@ import { objectMetadataItemSchema } from '@/object-metadata/validation-schemas/o
|
||||
|
||||
import { mockedStandardObjectMetadataQueryResult } from '~/testing/mock-data/generated/mock-metadata-query-result';
|
||||
|
||||
// TODO: remove once we have a way to generate the mocks against a seeded workspace
|
||||
const addUniversalIdentifierToField = (
|
||||
field: Record<string, unknown>,
|
||||
): FieldMetadataItem => ({
|
||||
...(field as FieldMetadataItem),
|
||||
universalIdentifier:
|
||||
(field as { universalIdentifier?: string }).universalIdentifier ??
|
||||
(field as { id: string }).id,
|
||||
});
|
||||
|
||||
export const generatedMockObjectMetadataItems: ObjectMetadataItem[] =
|
||||
mockedStandardObjectMetadataQueryResult.objects.edges.map((edge) => {
|
||||
const labelIdentifierFieldMetadataId =
|
||||
@@ -24,20 +14,21 @@ export const generatedMockObjectMetadataItems: ObjectMetadataItem[] =
|
||||
const { fieldsList, indexMetadataList, ...objectWithoutFieldsList } =
|
||||
edge.node;
|
||||
|
||||
const fields = fieldsList.map(addUniversalIdentifierToField);
|
||||
const fields = fieldsList.map(
|
||||
(field) => field as unknown as FieldMetadataItem,
|
||||
);
|
||||
|
||||
return {
|
||||
...objectWithoutFieldsList,
|
||||
universalIdentifier:
|
||||
(objectWithoutFieldsList as { universalIdentifier?: string })
|
||||
.universalIdentifier ?? objectWithoutFieldsList.id,
|
||||
fields,
|
||||
readableFields: fields,
|
||||
updatableFields: fields,
|
||||
labelIdentifierFieldMetadataId,
|
||||
indexMetadatas: indexMetadataList.map((index) => ({
|
||||
...index,
|
||||
indexFieldMetadatas: [],
|
||||
})),
|
||||
indexMetadatas: indexMetadataList.map(
|
||||
({ indexFieldMetadataList, ...index }) => ({
|
||||
...index,
|
||||
indexFieldMetadatas: indexFieldMetadataList,
|
||||
}),
|
||||
),
|
||||
};
|
||||
});
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
"src/**/*.d.ts",
|
||||
"src/**/*.ts",
|
||||
"src/**/*.tsx",
|
||||
"scripts/**/*.ts",
|
||||
".storybook/*.ts",
|
||||
".storybook/*.tsx",
|
||||
"lingui.config.ts",
|
||||
|
||||
Reference in New Issue
Block a user