Files
twenty/packages/twenty-server/test/integration/graphql/utils/create-one-operation.util.ts
Paul Rastoin 97d4ec96af Fix view filter update and deletion propagation (#12082)
# Introduction

Diff description: ~500 tests and +500 additions

close https://github.com/twentyhq/core-team-issues/issues/731

## What has been done here
In a nutshell on a field metadata type ( `SELECT MULTI_SELECT` ) update,
we will be browsing all `ViewFilters` in a post hook searching for some
referencing related updated `fieldMetadata` select. In order to update
or delete the `viewFilter` depending on the associated mutations.

## How to test:
- Add FieldMetadata `SELECT | MULTI_SELECT` to an existing or a new
`objectMetadata`
- Create a filtered view on created `fieldMetadata` with any options you
would like
- Remove some options ( in the best of the world some that are selected
by the filter ) from the `fieldMetadata` settings page
- Go back to the filtered view, removed or updated options should have
been hydrated in the `displayValue` and the filtered data should make
sense

## All filtered options are deleted edge case
If an update implies that a viewFilter does not have any existing
related options anymore, then we remove the viewFilter

## Testing
```sh 
PASS  test/integration/metadata/suites/field-metadata/update-one-field-metadata-related-record.integration-spec.ts (27 s)
  update-one-field-metadata-related-record
    SELECT
      ✓ should delete related view filter if all select field options got deleted (2799 ms)
      ✓ should update related multi selected options view filter (1244 ms)
      ✓ should update related solo selected option view filter (1235 ms)
      ✓ should handle partial deletion of selected options in view filter (1210 ms)
      ✓ should handle reordering of options while maintaining view filter values (1487 ms)
      ✓ should handle no changes update of options while maintaining existing view filter values (1174 ms)
      ✓ should handle adding new options while maintaining existing view filter (1174 ms)
      ✓ should update display value with options label if less than 3 options are selected (1249 ms)
      ✓ should throw error if view filter value is not a stringified JSON array (1300 ms)
    MULTI_SELECT
      ✓ should delete related view filter if all select field options got deleted (1127 ms)
      ✓ should update related multi selected options view filter (1215 ms)
      ✓ should update related solo selected option view filter (1404 ms)
      ✓ should handle partial deletion of selected options in view filter (1936 ms)
      ✓ should handle reordering of options while maintaining view filter values (1261 ms)
      ✓ should handle no changes update of options while maintaining existing view filter values (1831 ms)
      ✓ should handle adding new options while maintaining existing view filter (1610 ms)
      ✓ should update display value with options label if less than 3 options are selected (1889 ms)
      ✓ should throw error if view filter value is not a stringified JSON array (1365 ms)

Test Suites: 1 passed, 1 total
Tests:       18 passed, 18 total
Snapshots:   18 passed, 18 total
Time:        27.039 s
```
## Out of scope
- We should handle ViewFilter validation when extracting its definition
from the metadata
https://github.com/twentyhq/core-team-issues/issues/1009

## Concerns
- Are we able through the api to update an RATING fieldMetadata ? ( if
yes than that's an issue and we should handle RATING the same way than
for SELECT and MULTI_SELECT )
- It's not possible to group a view from a MULTI_SELECT field

The above points create a double nor a triple "lecture" to the post hook
effect:
- ViewGroup -> only SELECT
- VIewFilter -> only SELECT || MULTI_SELECT
- Rating nothing
I think we should determine the scope of all of that

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2025-05-28 10:22:28 +00:00

44 lines
1.6 KiB
TypeScript

import { createOneOperationFactory } from 'test/integration/graphql/utils/create-one-operation-factory.util';
import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.util';
import { CommonResponseBody } from 'test/integration/metadata/types/common-response-body.type';
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';
import { capitalize } from 'twenty-shared/utils';
import { ObjectRecord } from 'src/engine/api/graphql/workspace-query-builder/interfaces/object-record.interface';
type CreateOneOperationArgs<T> = PerformMetadataQueryParams<T> & {
objectMetadataSingularName: string;
};
export const createOneOperation = async <T = object>({
input,
gqlFields = 'id',
objectMetadataSingularName,
expectToFail = false,
}: CreateOneOperationArgs<T>): CommonResponseBody<{
createOneResponse: ObjectRecord;
}> => {
const graphqlOperation = createOneOperationFactory({
data: input as object, // TODO default generic does not work
objectMetadataSingularName,
gqlFields,
});
const response = await makeGraphqlAPIRequest(graphqlOperation);
if (expectToFail) {
warnIfNoErrorButExpectedToFail({
response,
errorMessage: 'Create one operation should have failed but did not',
});
}
return {
data: {
createOneResponse:
response.body.data[`create${capitalize(objectMetadataSingularName)}`],
},
errors: response.body.errors,
};
};