Fix deactivate objects impacts (#11185)

In this PR:
- Remove deactivated objects from ActivityTargetInlineCell record picker
- Prevent users to deactivate createdAt, updatedAt, deletedAt fields on
any objects

Still left:
- write unit tests on the assert utils
- write integration tests on field metadata service
- prevent users to deactivate createdAt, updatedAt, deletedAt on FE
This commit is contained in:
Charles Bochet
2025-03-26 20:45:46 +01:00
committed by GitHub
parent 90e884d33f
commit 5bd10d40cb
49 changed files with 861 additions and 531 deletions

View File

@ -1,24 +0,0 @@
import gql from 'graphql-tag';
import { CreateObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/create-object.input';
type CreateOneObjectFactoryParams = {
gqlFields: string;
input?: { object: Omit<CreateObjectInput, 'workspaceId' | 'dataSourceId'> };
};
export const createOneObjectMetadataFactory = ({
gqlFields,
input,
}: CreateOneObjectFactoryParams) => ({
query: gql`
mutation CreateOneObjectMetadataItem($input: CreateOneObjectInput!) {
createOneObject(input: $input) {
${gqlFields}
}
}
`,
variables: {
input,
},
});

View File

@ -0,0 +1,25 @@
import gql from 'graphql-tag';
import { PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type';
import { CreateObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/create-object.input';
export type CreateOneObjectFactoryInput = Omit<
CreateObjectInput,
'workspaceId' | 'dataSourceId'
>;
export const createOneObjectMetadataQueryFactory = ({
input,
gqlFields = 'id',
}: PerformMetadataQueryParams<CreateOneObjectFactoryInput>) => ({
query: gql`
mutation CreateOneObjectMetadataItem($input: CreateOneObjectInput!) {
createOneObject(input: $input) {
${gqlFields}
}
}
`,
variables: {
input: { object: input },
},
});

View File

@ -0,0 +1,29 @@
import {
CreateOneObjectFactoryInput,
createOneObjectMetadataQueryFactory,
} from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata-query-factory.util';
import { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util';
import { PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type';
import { warnIfNoErrorButExpectedToFail } from 'test/integration/metadata/utils/warn-if-no-error-but-expected-to-fail.util';
export const createOneObjectMetadata = async ({
input,
gqlFields,
expectToFail = false,
}: PerformMetadataQueryParams<CreateOneObjectFactoryInput>) => {
const graphqlOperation = createOneObjectMetadataQueryFactory({
input,
gqlFields,
});
const response = await makeMetadataAPIRequest(graphqlOperation);
if (expectToFail) {
warnIfNoErrorButExpectedToFail({
response,
errorMessage: 'Object Metadata creation should have failed but did not',
});
}
return { data: response.body.data, errors: response.body.errors };
};

View File

@ -1,32 +0,0 @@
import {
LISTING_NAME_PLURAL,
LISTING_NAME_SINGULAR,
} from 'test/integration/metadata/suites/object-metadata/constants/test-object-names.constant';
import { createOneObjectMetadataFactory } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata-factory.util';
import { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util';
const LISTING_OBJECT = {
namePlural: LISTING_NAME_PLURAL,
nameSingular: LISTING_NAME_SINGULAR,
labelPlural: 'Listings',
labelSingular: 'Listing',
description: 'Listing object',
icon: 'IconListNumbers',
isLabelSyncedWithName: false,
};
export const createListingCustomObject = async () => {
const createObjectOperation = createOneObjectMetadataFactory({
input: { object: LISTING_OBJECT },
gqlFields: `
id
nameSingular
`,
});
const response = await makeMetadataAPIRequest(createObjectOperation);
return {
objectMetadataId: response.body.data.createOneObject.id,
};
};

View File

@ -1,20 +0,0 @@
import gql from 'graphql-tag';
type DeleteOneObjectFactoryParams = {
idToDelete: string;
};
export const deleteOneObjectMetadataItemFactory = ({
idToDelete,
}: DeleteOneObjectFactoryParams) => ({
query: gql`
mutation DeleteOneObjectMetadataItem($idToDelete: UUID!) {
deleteOneObject(input: { id: $idToDelete }) {
id
}
}
`,
variables: {
idToDelete,
},
});

View File

@ -0,0 +1,22 @@
import gql from 'graphql-tag';
import { PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type';
export type DeleteOneObjectFactoryInput = {
idToDelete: string;
};
export const deleteOneObjectMetadataQueryFactory = ({
input,
gqlFields = 'id',
}: PerformMetadataQueryParams<DeleteOneObjectFactoryInput>) => ({
query: gql`
mutation DeleteOneObjectMetadataItem($idToDelete: UUID!) {
deleteOneObject(input: { id: $idToDelete }) {
${gqlFields}
}
}
`,
variables: {
idToDelete: input.idToDelete,
},
});

View File

@ -1,12 +1,29 @@
import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.util';
import { deleteOneObjectMetadataItemFactory } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata-factory.util';
import {
DeleteOneObjectFactoryInput,
deleteOneObjectMetadataQueryFactory,
} from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata-query-factory.util';
import { PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type';
import { warnIfNoErrorButExpectedToFail } from 'test/integration/metadata/utils/warn-if-no-error-but-expected-to-fail.util';
export const deleteOneObjectMetadataItem = async (
objectMetadataItemId: string,
) => {
const graphqlOperation = deleteOneObjectMetadataItemFactory({
idToDelete: objectMetadataItemId,
export const deleteOneObjectMetadata = async ({
input,
gqlFields,
expectToFail = false,
}: PerformMetadataQueryParams<DeleteOneObjectFactoryInput>) => {
const graphqlOperation = deleteOneObjectMetadataQueryFactory({
input,
gqlFields,
});
await makeGraphqlAPIRequest(graphqlOperation);
const response = await makeGraphqlAPIRequest(graphqlOperation);
if (expectToFail) {
warnIfNoErrorButExpectedToFail({
response,
errorMessage: 'Object Metadata deletion should have failed but did not',
});
}
return { data: response.body.data, errors: response.body.errors };
};

View File

@ -1,17 +1,15 @@
import gql from 'graphql-tag';
import { PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type';
type ObjectsFactoryParams = {
gqlFields: string;
input: {
filter: object;
paging: object;
};
export type FindManyObjectMetadataFactoryInput = {
filter: object;
paging: object;
};
export const objectsMetadataFactory = ({
gqlFields,
export const findManyObjectMetadataQueryFactory = ({
gqlFields = 'id',
input,
}: ObjectsFactoryParams) => ({
}: PerformMetadataQueryParams<FindManyObjectMetadataFactoryInput>) => ({
query: gql`
query ObjectsMetadata($filter: ObjectFilter!, $paging: CursorPaging!) {
objects(filter: $filter, paging: $paging) {

View File

@ -0,0 +1,29 @@
import {
FindManyObjectMetadataFactoryInput,
findManyObjectMetadataQueryFactory,
} from 'test/integration/metadata/suites/object-metadata/utils/find-many-object-metadata-query-factory.util';
import { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util';
import { PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type';
import { warnIfNoErrorButExpectedToFail } from 'test/integration/metadata/utils/warn-if-no-error-but-expected-to-fail.util';
export const findManyObjectMetadata = async ({
input,
gqlFields,
expectToFail = false,
}: PerformMetadataQueryParams<FindManyObjectMetadataFactoryInput>) => {
const graphqlOperation = findManyObjectMetadataQueryFactory({
input,
gqlFields,
});
const response = await makeMetadataAPIRequest(graphqlOperation);
if (expectToFail) {
warnIfNoErrorButExpectedToFail({
response,
errorMessage: 'Object Metadata retrieval should have failed but did not',
});
}
return response.body.data.objects.edges.map((edge) => edge.node);
};

View File

@ -1,28 +0,0 @@
import gql from 'graphql-tag';
import { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util';
export const findManyObjectsMetadataItems = async () => {
const query = {
query: gql`
query ObjectMetadataItems {
objects(paging: { first: 1000 }) {
edges {
node {
id
nameSingular
namePlural
}
}
}
}
`,
};
const response = await makeMetadataAPIRequest(query);
return response.body.data.objects.edges.map((edge) => edge.node) as {
id: string;
nameSingular: string;
namePlural: string;
}[];
};

View File

@ -0,0 +1,15 @@
import { CreateObjectInput } from 'src/engine/metadata-modules/object-metadata/dtos/create-object.input';
// TODO would tend to use faker
export const getMockCreateObjectInput = (
overrides?: Partial<Omit<CreateObjectInput, 'workspaceId' | 'dataSourceId'>>,
) => ({
namePlural: 'listingas',
nameSingular: 'listinga',
labelPlural: 'Listings',
labelSingular: 'Listing',
description: 'Listing object',
icon: 'IconListNumbers',
isLabelSyncedWithName: false,
...overrides,
});

View File

@ -1,28 +0,0 @@
import gql from 'graphql-tag';
import { UpdateObjectPayload } from 'src/engine/metadata-modules/object-metadata/dtos/update-object.input';
type UpdateOneObjectFactoryParams = {
gqlFields: string;
input: {
idToUpdate: string;
updatePayload: UpdateObjectPayload;
};
};
export const updateOneObjectMetadataItemFactory = ({
gqlFields,
input,
}: UpdateOneObjectFactoryParams) => ({
query: gql`
mutation UpdateOneObjectMetadataItem($idToUpdate: UUID!, $updatePayload: UpdateObjectPayload!) {
updateOneObject(input: {id: $idToUpdate, update: $updatePayload}) {
${gqlFields}
}
}
`,
variables: {
idToUpdate: input.idToUpdate,
updatePayload: input.updatePayload,
},
});

View File

@ -0,0 +1,26 @@
import gql from 'graphql-tag';
import { PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type';
import { UpdateObjectPayload } from 'src/engine/metadata-modules/object-metadata/dtos/update-object.input';
export type UpdateOneObjectFactoryInput = {
idToUpdate: string;
updatePayload: UpdateObjectPayload;
};
export const updateOneObjectMetadataQueryFactory = ({
gqlFields = 'id',
input,
}: PerformMetadataQueryParams<UpdateOneObjectFactoryInput>) => ({
query: gql`
mutation UpdateOneObjectMetadataItem($idToUpdate: UUID!, $updatePayload: UpdateObjectPayload!) {
updateOneObject(input: {id: $idToUpdate, update: $updatePayload}) {
${gqlFields}
}
}
`,
variables: {
idToUpdate: input.idToUpdate,
updatePayload: input.updatePayload,
},
});

View File

@ -0,0 +1,29 @@
import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.util';
import {
UpdateOneObjectFactoryInput,
updateOneObjectMetadataQueryFactory,
} from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata-query-factory.util';
import { PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type';
import { warnIfNoErrorButExpectedToFail } from 'test/integration/metadata/utils/warn-if-no-error-but-expected-to-fail.util';
export const updateOneObjectMetadata = async ({
input,
gqlFields,
expectToFail = false,
}: PerformMetadataQueryParams<UpdateOneObjectFactoryInput>) => {
const graphqlOperation = updateOneObjectMetadataQueryFactory({
input,
gqlFields,
});
const response = await makeGraphqlAPIRequest(graphqlOperation);
if (expectToFail) {
warnIfNoErrorButExpectedToFail({
response,
errorMessage: 'Object Metadata update should have failed but did not',
});
}
return { data: response.body.data, errors: response.body.errors };
};