followup: centralize widget common properties and add widget bulk update integration tests (#18225)
followup https://github.com/twentyhq/twenty/pull/18015#pullrequestreview-3818929035
This commit is contained in:
+56
@@ -0,0 +1,56 @@
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
|
||||
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
|
||||
import { type CreatePageLayoutWidgetInput } from 'src/engine/metadata-modules/page-layout-widget/dtos/inputs/create-page-layout-widget.input';
|
||||
|
||||
export const buildFlatPageLayoutWidgetCommonProperties = ({
|
||||
widgetInput,
|
||||
flatPageLayoutTabMaps,
|
||||
flatObjectMetadataMaps,
|
||||
}: {
|
||||
widgetInput: Pick<
|
||||
CreatePageLayoutWidgetInput,
|
||||
| 'pageLayoutTabId'
|
||||
| 'title'
|
||||
| 'type'
|
||||
| 'objectMetadataId'
|
||||
| 'gridPosition'
|
||||
| 'position'
|
||||
>;
|
||||
} & Pick<
|
||||
AllFlatEntityMaps,
|
||||
'flatPageLayoutTabMaps' | 'flatObjectMetadataMaps'
|
||||
>): Pick<
|
||||
FlatPageLayoutWidget,
|
||||
| 'pageLayoutTabId'
|
||||
| 'pageLayoutTabUniversalIdentifier'
|
||||
| 'title'
|
||||
| 'type'
|
||||
| 'objectMetadataId'
|
||||
| 'objectMetadataUniversalIdentifier'
|
||||
| 'gridPosition'
|
||||
| 'position'
|
||||
> => {
|
||||
const {
|
||||
pageLayoutTabUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
} = resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'pageLayoutWidget',
|
||||
foreignKeyValues: {
|
||||
pageLayoutTabId: widgetInput.pageLayoutTabId,
|
||||
objectMetadataId: widgetInput.objectMetadataId,
|
||||
},
|
||||
flatEntityMaps: { flatPageLayoutTabMaps, flatObjectMetadataMaps },
|
||||
});
|
||||
|
||||
return {
|
||||
pageLayoutTabId: widgetInput.pageLayoutTabId,
|
||||
pageLayoutTabUniversalIdentifier,
|
||||
title: widgetInput.title,
|
||||
type: widgetInput.type,
|
||||
objectMetadataId: widgetInput.objectMetadataId ?? null,
|
||||
objectMetadataUniversalIdentifier,
|
||||
gridPosition: widgetInput.gridPosition,
|
||||
position: widgetInput.position ?? null,
|
||||
};
|
||||
};
|
||||
+10
-16
@@ -3,8 +3,8 @@ import { v4 } from 'uuid';
|
||||
|
||||
import { type FlatApplication } from 'src/engine/core-modules/application/types/flat-application.type';
|
||||
import { type AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types/all-flat-entity-maps.type';
|
||||
import { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
|
||||
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
|
||||
import { buildFlatPageLayoutWidgetCommonProperties } from 'src/engine/metadata-modules/flat-page-layout-widget/utils/build-flat-page-layout-widget-common-properties.util';
|
||||
import { fromPageLayoutWidgetConfigurationToUniversalConfiguration } from 'src/engine/metadata-modules/flat-page-layout-widget/utils/from-page-layout-widget-configuration-to-universal-configuration.util';
|
||||
import { type CreatePageLayoutWidgetInput } from 'src/engine/metadata-modules/page-layout-widget/dtos/inputs/create-page-layout-widget.input';
|
||||
import { validateWidgetConfigurationInput } from 'src/engine/metadata-modules/page-layout-widget/utils/validate-widget-configuration-input.util';
|
||||
@@ -48,33 +48,27 @@ export const fromCreatePageLayoutWidgetInputToFlatPageLayoutWidgetToCreate = ({
|
||||
const createdAt = new Date().toISOString();
|
||||
const pageLayoutWidgetId = v4();
|
||||
|
||||
const {
|
||||
pageLayoutTabUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
} = resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'pageLayoutWidget',
|
||||
foreignKeyValues: {
|
||||
const commonProperties = buildFlatPageLayoutWidgetCommonProperties({
|
||||
widgetInput: {
|
||||
pageLayoutTabId,
|
||||
title: createPageLayoutWidgetInput.title,
|
||||
type: createPageLayoutWidgetInput.type,
|
||||
objectMetadataId: createPageLayoutWidgetInput.objectMetadataId,
|
||||
gridPosition: createPageLayoutWidgetInput.gridPosition,
|
||||
position: createPageLayoutWidgetInput.position,
|
||||
},
|
||||
flatEntityMaps: { flatPageLayoutTabMaps, flatObjectMetadataMaps },
|
||||
flatPageLayoutTabMaps,
|
||||
flatObjectMetadataMaps,
|
||||
});
|
||||
|
||||
return {
|
||||
id: pageLayoutWidgetId,
|
||||
pageLayoutTabId,
|
||||
pageLayoutTabUniversalIdentifier,
|
||||
...commonProperties,
|
||||
workspaceId,
|
||||
createdAt,
|
||||
updatedAt: createdAt,
|
||||
deletedAt: null,
|
||||
universalIdentifier: pageLayoutWidgetId,
|
||||
title: createPageLayoutWidgetInput.title,
|
||||
type: createPageLayoutWidgetInput.type,
|
||||
objectMetadataId: createPageLayoutWidgetInput.objectMetadataId ?? null,
|
||||
objectMetadataUniversalIdentifier,
|
||||
gridPosition: createPageLayoutWidgetInput.gridPosition,
|
||||
position: createPageLayoutWidgetInput.position ?? null,
|
||||
configuration: createPageLayoutWidgetInput.configuration,
|
||||
applicationId: flatApplication.id,
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
|
||||
+17
-61
@@ -10,12 +10,12 @@ import { AllFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/types
|
||||
import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/add-flat-entity-to-flat-entity-maps-or-throw.util';
|
||||
import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util';
|
||||
import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util';
|
||||
import { resolveEntityRelationUniversalIdentifiers } from 'src/engine/metadata-modules/flat-entity/utils/resolve-entity-relation-universal-identifiers.util';
|
||||
import { FLAT_PAGE_LAYOUT_TAB_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-page-layout-tab/constants/flat-page-layout-tab-editable-properties.constant';
|
||||
import { type FlatPageLayoutTabMaps } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab-maps.type';
|
||||
import { type FlatPageLayoutTab } from 'src/engine/metadata-modules/flat-page-layout-tab/types/flat-page-layout-tab.type';
|
||||
import { FLAT_PAGE_LAYOUT_WIDGET_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-page-layout-widget/constants/flat-page-layout-widget-editable-properties.constant';
|
||||
import { type FlatPageLayoutWidget } from 'src/engine/metadata-modules/flat-page-layout-widget/types/flat-page-layout-widget.type';
|
||||
import { buildFlatPageLayoutWidgetCommonProperties } from 'src/engine/metadata-modules/flat-page-layout-widget/utils/build-flat-page-layout-widget-common-properties.util';
|
||||
import { fromPageLayoutWidgetConfigurationToUniversalConfiguration } from 'src/engine/metadata-modules/flat-page-layout-widget/utils/from-page-layout-widget-configuration-to-universal-configuration.util';
|
||||
import { type FlatPageLayout } from 'src/engine/metadata-modules/flat-page-layout/types/flat-page-layout.type';
|
||||
import { reconstructFlatPageLayoutWithTabsAndWidgets } from 'src/engine/metadata-modules/flat-page-layout/utils/reconstruct-flat-page-layout-with-tabs-and-widgets.util';
|
||||
@@ -476,32 +476,18 @@ export class PageLayoutUpdateService {
|
||||
});
|
||||
|
||||
const now = new Date();
|
||||
|
||||
const widgetsToCreate: FlatPageLayoutWidget[] = entitiesToCreate.map(
|
||||
(widgetInput) => {
|
||||
const widgetId = widgetInput.id ?? v4();
|
||||
|
||||
const {
|
||||
pageLayoutTabUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
} = resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'pageLayoutWidget',
|
||||
foreignKeyValues: {
|
||||
pageLayoutTabId: widgetInput.pageLayoutTabId,
|
||||
objectMetadataId: widgetInput.objectMetadataId,
|
||||
},
|
||||
flatEntityMaps: { flatPageLayoutTabMaps, flatObjectMetadataMaps },
|
||||
});
|
||||
|
||||
return {
|
||||
id: widgetId,
|
||||
pageLayoutTabId: widgetInput.pageLayoutTabId,
|
||||
pageLayoutTabUniversalIdentifier,
|
||||
title: widgetInput.title,
|
||||
type: widgetInput.type,
|
||||
objectMetadataId: widgetInput.objectMetadataId ?? null,
|
||||
objectMetadataUniversalIdentifier,
|
||||
gridPosition: widgetInput.gridPosition,
|
||||
position: widgetInput.position ?? null,
|
||||
...buildFlatPageLayoutWidgetCommonProperties({
|
||||
widgetInput,
|
||||
flatPageLayoutTabMaps,
|
||||
flatObjectMetadataMaps,
|
||||
}),
|
||||
configuration: widgetInput.configuration,
|
||||
workspaceId,
|
||||
createdAt: now.toISOString(),
|
||||
@@ -536,28 +522,13 @@ export class PageLayoutUpdateService {
|
||||
|
||||
const updatedConfiguration = widgetInput.configuration ?? null;
|
||||
|
||||
const {
|
||||
pageLayoutTabUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
} = resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'pageLayoutWidget',
|
||||
foreignKeyValues: {
|
||||
pageLayoutTabId: widgetInput.pageLayoutTabId,
|
||||
objectMetadataId: widgetInput.objectMetadataId,
|
||||
},
|
||||
flatEntityMaps: { flatPageLayoutTabMaps, flatObjectMetadataMaps },
|
||||
});
|
||||
|
||||
return {
|
||||
...existingWidget,
|
||||
pageLayoutTabId: widgetInput.pageLayoutTabId,
|
||||
pageLayoutTabUniversalIdentifier,
|
||||
title: widgetInput.title,
|
||||
type: widgetInput.type,
|
||||
objectMetadataId: widgetInput.objectMetadataId ?? null,
|
||||
objectMetadataUniversalIdentifier,
|
||||
gridPosition: widgetInput.gridPosition,
|
||||
position: widgetInput.position ?? null,
|
||||
...buildFlatPageLayoutWidgetCommonProperties({
|
||||
widgetInput,
|
||||
flatPageLayoutTabMaps,
|
||||
flatObjectMetadataMaps,
|
||||
}),
|
||||
configuration: updatedConfiguration,
|
||||
updatedAt: now.toISOString(),
|
||||
...(isDefined(updatedConfiguration) && {
|
||||
@@ -587,28 +558,13 @@ export class PageLayoutUpdateService {
|
||||
|
||||
const restoredConfiguration = widgetInput.configuration ?? null;
|
||||
|
||||
const {
|
||||
pageLayoutTabUniversalIdentifier,
|
||||
objectMetadataUniversalIdentifier,
|
||||
} = resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'pageLayoutWidget',
|
||||
foreignKeyValues: {
|
||||
pageLayoutTabId: widgetInput.pageLayoutTabId,
|
||||
objectMetadataId: widgetInput.objectMetadataId,
|
||||
},
|
||||
flatEntityMaps: { flatPageLayoutTabMaps, flatObjectMetadataMaps },
|
||||
});
|
||||
|
||||
return {
|
||||
...existingWidget,
|
||||
pageLayoutTabId: widgetInput.pageLayoutTabId,
|
||||
pageLayoutTabUniversalIdentifier,
|
||||
title: widgetInput.title,
|
||||
type: widgetInput.type,
|
||||
objectMetadataId: widgetInput.objectMetadataId ?? null,
|
||||
objectMetadataUniversalIdentifier,
|
||||
gridPosition: widgetInput.gridPosition,
|
||||
position: widgetInput.position ?? null,
|
||||
...buildFlatPageLayoutWidgetCommonProperties({
|
||||
widgetInput,
|
||||
flatPageLayoutTabMaps,
|
||||
flatObjectMetadataMaps,
|
||||
}),
|
||||
configuration: restoredConfiguration,
|
||||
deletedAt: null,
|
||||
updatedAt: now.toISOString(),
|
||||
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
|
||||
|
||||
exports[`Page layout widget restore via bulk update should succeed should create, delete, and restore a widget via bulk update 1`] = `
|
||||
{
|
||||
"createdAt": Any<String>,
|
||||
"defaultTabToFocusOnMobileAndSidePanelId": null,
|
||||
"deletedAt": null,
|
||||
"id": Any<String>,
|
||||
"name": "Test Layout For Widget Restore",
|
||||
"objectMetadataId": null,
|
||||
"tabs": [
|
||||
{
|
||||
"applicationId": Any<String>,
|
||||
"createdAt": Any<String>,
|
||||
"deletedAt": null,
|
||||
"icon": null,
|
||||
"id": Any<String>,
|
||||
"layoutMode": "GRID",
|
||||
"pageLayoutId": Any<String>,
|
||||
"position": 0,
|
||||
"title": "Test Tab For Widget Restore",
|
||||
"updatedAt": Any<String>,
|
||||
"widgets": [
|
||||
{
|
||||
"configuration": {
|
||||
"aggregateFieldMetadataId": Any<String>,
|
||||
"aggregateOperation": "SUM",
|
||||
"configurationType": "AGGREGATE_CHART",
|
||||
"description": null,
|
||||
"displayDataLabel": true,
|
||||
"filter": null,
|
||||
"firstDayOfTheWeek": 1,
|
||||
"format": null,
|
||||
"label": null,
|
||||
"prefix": null,
|
||||
"suffix": null,
|
||||
"timezone": "UTC",
|
||||
},
|
||||
"createdAt": Any<String>,
|
||||
"deletedAt": null,
|
||||
"gridPosition": {
|
||||
"column": 0,
|
||||
"columnSpan": 1,
|
||||
"row": 0,
|
||||
"rowSpan": 1,
|
||||
},
|
||||
"id": Any<String>,
|
||||
"objectMetadataId": Any<String>,
|
||||
"pageLayoutTabId": Any<String>,
|
||||
"title": "Restored Graph Widget",
|
||||
"type": "GRAPH",
|
||||
"updatedAt": Any<String>,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "RECORD_PAGE",
|
||||
"updatedAt": Any<String>,
|
||||
}
|
||||
`;
|
||||
|
||||
exports[`Page layout widget restore via bulk update should succeed should handle mixed create, update, and restore in a single call 1`] = `
|
||||
{
|
||||
"createdAt": Any<String>,
|
||||
"defaultTabToFocusOnMobileAndSidePanelId": null,
|
||||
"deletedAt": null,
|
||||
"id": Any<String>,
|
||||
"name": "Test Layout For Widget Restore",
|
||||
"objectMetadataId": null,
|
||||
"tabs": [
|
||||
{
|
||||
"applicationId": Any<String>,
|
||||
"createdAt": Any<String>,
|
||||
"deletedAt": null,
|
||||
"icon": null,
|
||||
"id": Any<String>,
|
||||
"layoutMode": "GRID",
|
||||
"pageLayoutId": Any<String>,
|
||||
"position": 0,
|
||||
"title": "Test Tab For Widget Restore",
|
||||
"updatedAt": Any<String>,
|
||||
"widgets": [
|
||||
{
|
||||
"configuration": {
|
||||
"configurationType": "IFRAME",
|
||||
"url": "https://new.example.com",
|
||||
},
|
||||
"createdAt": Any<String>,
|
||||
"deletedAt": null,
|
||||
"gridPosition": {
|
||||
"column": 0,
|
||||
"columnSpan": 1,
|
||||
"row": 2,
|
||||
"rowSpan": 1,
|
||||
},
|
||||
"id": Any<String>,
|
||||
"objectMetadataId": null,
|
||||
"pageLayoutTabId": Any<String>,
|
||||
"title": "Brand New Widget",
|
||||
"type": "IFRAME",
|
||||
"updatedAt": Any<String>,
|
||||
},
|
||||
{
|
||||
"configuration": {
|
||||
"configurationType": "IFRAME",
|
||||
"url": "https://updated.example.com",
|
||||
},
|
||||
"createdAt": Any<String>,
|
||||
"deletedAt": null,
|
||||
"gridPosition": {
|
||||
"column": 0,
|
||||
"columnSpan": 2,
|
||||
"row": 0,
|
||||
"rowSpan": 2,
|
||||
},
|
||||
"id": Any<String>,
|
||||
"objectMetadataId": null,
|
||||
"pageLayoutTabId": Any<String>,
|
||||
"title": "Updated Widget Title",
|
||||
"type": "IFRAME",
|
||||
"updatedAt": Any<String>,
|
||||
},
|
||||
{
|
||||
"configuration": {
|
||||
"aggregateFieldMetadataId": Any<String>,
|
||||
"aggregateOperation": "SUM",
|
||||
"configurationType": "AGGREGATE_CHART",
|
||||
"description": null,
|
||||
"displayDataLabel": true,
|
||||
"filter": null,
|
||||
"firstDayOfTheWeek": 1,
|
||||
"format": null,
|
||||
"label": null,
|
||||
"prefix": null,
|
||||
"suffix": null,
|
||||
"timezone": "UTC",
|
||||
},
|
||||
"createdAt": Any<String>,
|
||||
"deletedAt": null,
|
||||
"gridPosition": {
|
||||
"column": 0,
|
||||
"columnSpan": 1,
|
||||
"row": 1,
|
||||
"rowSpan": 1,
|
||||
},
|
||||
"id": Any<String>,
|
||||
"objectMetadataId": Any<String>,
|
||||
"pageLayoutTabId": Any<String>,
|
||||
"title": "Restored Widget",
|
||||
"type": "GRAPH",
|
||||
"updatedAt": Any<String>,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
"type": "RECORD_PAGE",
|
||||
"updatedAt": Any<String>,
|
||||
}
|
||||
`;
|
||||
+395
@@ -0,0 +1,395 @@
|
||||
import { createOnePageLayoutTab } from 'test/integration/metadata/suites/page-layout-tab/utils/create-one-page-layout-tab.util';
|
||||
import { destroyOnePageLayoutTab } from 'test/integration/metadata/suites/page-layout-tab/utils/destroy-one-page-layout-tab.util';
|
||||
import { fetchTestFieldMetadataIds } from 'test/integration/metadata/suites/page-layout-widget/utils/fetch-test-field-metadata-ids.util';
|
||||
import { createOnePageLayout } from 'test/integration/metadata/suites/page-layout/utils/create-one-page-layout.util';
|
||||
import { destroyOnePageLayout } from 'test/integration/metadata/suites/page-layout/utils/destroy-one-page-layout.util';
|
||||
import { updateOnePageLayoutWithTabsAndWidgets } from 'test/integration/metadata/suites/page-layout/utils/update-one-page-layout-with-tabs-and-widgets.util';
|
||||
import { extractRecordIdsAndDatesAsExpectAny } from 'test/utils/extract-record-ids-and-dates-as-expect-any';
|
||||
import { AggregateOperations } from 'twenty-shared/types';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { WidgetConfigurationType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-configuration-type.type';
|
||||
import { WidgetType } from 'src/engine/metadata-modules/page-layout-widget/enums/widget-type.enum';
|
||||
import { PageLayoutType } from 'src/engine/metadata-modules/page-layout/enums/page-layout-type.enum';
|
||||
|
||||
describe('Page layout widget restore via bulk update should succeed', () => {
|
||||
let testFieldMetadataIds: {
|
||||
objectMetadataId: string;
|
||||
fieldMetadataId1: string;
|
||||
fieldMetadataId2: string;
|
||||
};
|
||||
let testPageLayoutId: string;
|
||||
let testTabId: string;
|
||||
|
||||
beforeAll(async () => {
|
||||
const allFieldMetadataIds = await fetchTestFieldMetadataIds();
|
||||
|
||||
testFieldMetadataIds = {
|
||||
objectMetadataId: allFieldMetadataIds.objectMetadataId,
|
||||
fieldMetadataId1: allFieldMetadataIds.fieldMetadataId1,
|
||||
fieldMetadataId2: allFieldMetadataIds.fieldMetadataId2,
|
||||
};
|
||||
|
||||
const { data: layoutData } = await createOnePageLayout({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
name: 'Test Layout For Widget Restore',
|
||||
type: PageLayoutType.RECORD_PAGE,
|
||||
},
|
||||
});
|
||||
|
||||
testPageLayoutId = layoutData.createPageLayout.id;
|
||||
|
||||
const { data: tabData } = await createOnePageLayoutTab({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
title: 'Test Tab For Widget Restore',
|
||||
pageLayoutId: testPageLayoutId,
|
||||
},
|
||||
});
|
||||
|
||||
testTabId = tabData.createPageLayoutTab.id;
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await destroyOnePageLayoutTab({
|
||||
expectToFail: false,
|
||||
input: { id: testTabId },
|
||||
});
|
||||
await destroyOnePageLayout({
|
||||
expectToFail: false,
|
||||
input: { id: testPageLayoutId },
|
||||
});
|
||||
});
|
||||
|
||||
it('should create, delete, and restore a widget via bulk update', async () => {
|
||||
const widgetId = v4();
|
||||
|
||||
const { data: createData } = await updateOnePageLayoutWithTabsAndWidgets({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
id: testPageLayoutId,
|
||||
name: 'Test Layout For Widget Restore',
|
||||
type: PageLayoutType.RECORD_PAGE,
|
||||
objectMetadataId: null,
|
||||
tabs: [
|
||||
{
|
||||
id: testTabId,
|
||||
title: 'Test Tab For Widget Restore',
|
||||
position: 0,
|
||||
widgets: [
|
||||
{
|
||||
id: widgetId,
|
||||
pageLayoutTabId: testTabId,
|
||||
title: 'Graph Widget',
|
||||
type: WidgetType.GRAPH,
|
||||
objectMetadataId: testFieldMetadataIds.objectMetadataId,
|
||||
gridPosition: {
|
||||
row: 0,
|
||||
column: 0,
|
||||
rowSpan: 1,
|
||||
columnSpan: 1,
|
||||
},
|
||||
configuration: {
|
||||
configurationType: WidgetConfigurationType.PIE_CHART,
|
||||
aggregateFieldMetadataId:
|
||||
testFieldMetadataIds.fieldMetadataId1,
|
||||
aggregateOperation: AggregateOperations.COUNT,
|
||||
groupByFieldMetadataId: testFieldMetadataIds.fieldMetadataId2,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const createdTab = createData.updatePageLayoutWithTabsAndWidgets.tabs![0];
|
||||
|
||||
expect(createdTab.widgets).toHaveLength(1);
|
||||
expect(createdTab.widgets![0].id).toBe(widgetId);
|
||||
|
||||
const { data: deleteData } = await updateOnePageLayoutWithTabsAndWidgets({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
id: testPageLayoutId,
|
||||
name: 'Test Layout For Widget Restore',
|
||||
type: PageLayoutType.RECORD_PAGE,
|
||||
objectMetadataId: null,
|
||||
tabs: [
|
||||
{
|
||||
id: testTabId,
|
||||
title: 'Test Tab For Widget Restore',
|
||||
position: 0,
|
||||
widgets: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const deletedTab = deleteData.updatePageLayoutWithTabsAndWidgets.tabs![0];
|
||||
|
||||
expect(deletedTab.widgets).toHaveLength(0);
|
||||
|
||||
const { data: restoreData } = await updateOnePageLayoutWithTabsAndWidgets({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
id: testPageLayoutId,
|
||||
name: 'Test Layout For Widget Restore',
|
||||
type: PageLayoutType.RECORD_PAGE,
|
||||
objectMetadataId: null,
|
||||
tabs: [
|
||||
{
|
||||
id: testTabId,
|
||||
title: 'Test Tab For Widget Restore',
|
||||
position: 0,
|
||||
widgets: [
|
||||
{
|
||||
id: widgetId,
|
||||
pageLayoutTabId: testTabId,
|
||||
title: 'Restored Graph Widget',
|
||||
type: WidgetType.GRAPH,
|
||||
objectMetadataId: testFieldMetadataIds.objectMetadataId,
|
||||
gridPosition: {
|
||||
row: 0,
|
||||
column: 0,
|
||||
rowSpan: 1,
|
||||
columnSpan: 1,
|
||||
},
|
||||
configuration: {
|
||||
configurationType: WidgetConfigurationType.AGGREGATE_CHART,
|
||||
aggregateFieldMetadataId:
|
||||
testFieldMetadataIds.fieldMetadataId1,
|
||||
aggregateOperation: AggregateOperations.SUM,
|
||||
displayDataLabel: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const restoredTab = restoreData.updatePageLayoutWithTabsAndWidgets.tabs![0];
|
||||
|
||||
expect(restoredTab.widgets).toHaveLength(1);
|
||||
expect(restoredTab.widgets![0]).toMatchObject({
|
||||
id: widgetId,
|
||||
title: 'Restored Graph Widget',
|
||||
deletedAt: null,
|
||||
});
|
||||
|
||||
expect(restoreData.updatePageLayoutWithTabsAndWidgets).toMatchSnapshot(
|
||||
extractRecordIdsAndDatesAsExpectAny({
|
||||
...restoreData.updatePageLayoutWithTabsAndWidgets,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle mixed create, update, and restore in a single call', async () => {
|
||||
const widgetToUpdateId = v4();
|
||||
const widgetToRestoreId = v4();
|
||||
|
||||
await updateOnePageLayoutWithTabsAndWidgets({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
id: testPageLayoutId,
|
||||
name: 'Test Layout For Widget Restore',
|
||||
type: PageLayoutType.RECORD_PAGE,
|
||||
objectMetadataId: null,
|
||||
tabs: [
|
||||
{
|
||||
id: testTabId,
|
||||
title: 'Test Tab For Widget Restore',
|
||||
position: 0,
|
||||
widgets: [
|
||||
{
|
||||
id: widgetToUpdateId,
|
||||
pageLayoutTabId: testTabId,
|
||||
title: 'Widget To Update',
|
||||
type: WidgetType.IFRAME,
|
||||
objectMetadataId: null,
|
||||
gridPosition: {
|
||||
row: 0,
|
||||
column: 0,
|
||||
rowSpan: 1,
|
||||
columnSpan: 1,
|
||||
},
|
||||
configuration: {
|
||||
configurationType: WidgetConfigurationType.IFRAME,
|
||||
url: 'https://example.com',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: widgetToRestoreId,
|
||||
pageLayoutTabId: testTabId,
|
||||
title: 'Widget To Restore',
|
||||
type: WidgetType.GRAPH,
|
||||
objectMetadataId: testFieldMetadataIds.objectMetadataId,
|
||||
gridPosition: {
|
||||
row: 1,
|
||||
column: 0,
|
||||
rowSpan: 1,
|
||||
columnSpan: 1,
|
||||
},
|
||||
configuration: {
|
||||
configurationType: WidgetConfigurationType.AGGREGATE_CHART,
|
||||
aggregateFieldMetadataId:
|
||||
testFieldMetadataIds.fieldMetadataId1,
|
||||
aggregateOperation: AggregateOperations.COUNT,
|
||||
displayDataLabel: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
await updateOnePageLayoutWithTabsAndWidgets({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
id: testPageLayoutId,
|
||||
name: 'Test Layout For Widget Restore',
|
||||
type: PageLayoutType.RECORD_PAGE,
|
||||
objectMetadataId: null,
|
||||
tabs: [
|
||||
{
|
||||
id: testTabId,
|
||||
title: 'Test Tab For Widget Restore',
|
||||
position: 0,
|
||||
widgets: [
|
||||
{
|
||||
id: widgetToUpdateId,
|
||||
pageLayoutTabId: testTabId,
|
||||
title: 'Widget To Update',
|
||||
type: WidgetType.IFRAME,
|
||||
objectMetadataId: null,
|
||||
gridPosition: {
|
||||
row: 0,
|
||||
column: 0,
|
||||
rowSpan: 1,
|
||||
columnSpan: 1,
|
||||
},
|
||||
configuration: {
|
||||
configurationType: WidgetConfigurationType.IFRAME,
|
||||
url: 'https://example.com',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const newWidgetId = v4();
|
||||
|
||||
const { data: mixedData } = await updateOnePageLayoutWithTabsAndWidgets({
|
||||
expectToFail: false,
|
||||
input: {
|
||||
id: testPageLayoutId,
|
||||
name: 'Test Layout For Widget Restore',
|
||||
type: PageLayoutType.RECORD_PAGE,
|
||||
objectMetadataId: null,
|
||||
tabs: [
|
||||
{
|
||||
id: testTabId,
|
||||
title: 'Test Tab For Widget Restore',
|
||||
position: 0,
|
||||
widgets: [
|
||||
{
|
||||
id: widgetToUpdateId,
|
||||
pageLayoutTabId: testTabId,
|
||||
title: 'Updated Widget Title',
|
||||
type: WidgetType.IFRAME,
|
||||
objectMetadataId: null,
|
||||
gridPosition: {
|
||||
row: 0,
|
||||
column: 0,
|
||||
rowSpan: 2,
|
||||
columnSpan: 2,
|
||||
},
|
||||
configuration: {
|
||||
configurationType: WidgetConfigurationType.IFRAME,
|
||||
url: 'https://updated.example.com',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: widgetToRestoreId,
|
||||
pageLayoutTabId: testTabId,
|
||||
title: 'Restored Widget',
|
||||
type: WidgetType.GRAPH,
|
||||
objectMetadataId: testFieldMetadataIds.objectMetadataId,
|
||||
gridPosition: {
|
||||
row: 1,
|
||||
column: 0,
|
||||
rowSpan: 1,
|
||||
columnSpan: 1,
|
||||
},
|
||||
configuration: {
|
||||
configurationType: WidgetConfigurationType.AGGREGATE_CHART,
|
||||
aggregateFieldMetadataId:
|
||||
testFieldMetadataIds.fieldMetadataId1,
|
||||
aggregateOperation: AggregateOperations.SUM,
|
||||
displayDataLabel: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
id: newWidgetId,
|
||||
pageLayoutTabId: testTabId,
|
||||
title: 'Brand New Widget',
|
||||
type: WidgetType.IFRAME,
|
||||
objectMetadataId: null,
|
||||
gridPosition: {
|
||||
row: 2,
|
||||
column: 0,
|
||||
rowSpan: 1,
|
||||
columnSpan: 1,
|
||||
},
|
||||
configuration: {
|
||||
configurationType: WidgetConfigurationType.IFRAME,
|
||||
url: 'https://new.example.com',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
const mixedTab = mixedData.updatePageLayoutWithTabsAndWidgets.tabs![0];
|
||||
|
||||
expect(mixedTab.widgets).toHaveLength(3);
|
||||
|
||||
const updatedWidget = mixedTab.widgets!.find(
|
||||
(w: { id: string }) => w.id === widgetToUpdateId,
|
||||
);
|
||||
const restoredWidget = mixedTab.widgets!.find(
|
||||
(w: { id: string }) => w.id === widgetToRestoreId,
|
||||
);
|
||||
const newWidget = mixedTab.widgets!.find(
|
||||
(w: { id: string }) => w.id === newWidgetId,
|
||||
);
|
||||
|
||||
expect(updatedWidget).toMatchObject({
|
||||
title: 'Updated Widget Title',
|
||||
deletedAt: null,
|
||||
});
|
||||
|
||||
expect(restoredWidget).toMatchObject({
|
||||
title: 'Restored Widget',
|
||||
deletedAt: null,
|
||||
});
|
||||
|
||||
expect(newWidget).toMatchObject({
|
||||
title: 'Brand New Widget',
|
||||
deletedAt: null,
|
||||
});
|
||||
|
||||
expect(mixedData.updatePageLayoutWithTabsAndWidgets).toMatchSnapshot(
|
||||
extractRecordIdsAndDatesAsExpectAny({
|
||||
...mixedData.updatePageLayoutWithTabsAndWidgets,
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user