From 99fa93d61e89a8df01bc22cd1abfd8527b4e73ac Mon Sep 17 00:00:00 2001 From: Ashok Kumar M <35134347+marks0351@users.noreply.github.com> Date: Mon, 10 Jun 2024 16:37:50 +0530 Subject: [PATCH] chore: Adding specs/tests for space distribution and copy paste sagas (#34063) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit [![workerB](https://img.shields.io/endpoint?url=https%3A%2F%2Fworkerb.linearb.io%2Fv2%2Fbadge%2Fprivate%2FU2FsdGVkX1992iLVivcpoDwVtCrlTUPBIEmtU4nlPs%2Fcollaboration.svg%3FcacheSeconds%3D60)](https://workerb.linearb.io/v2/badge/collaboration-page?magicLinkId=mFGYFxI) ## Description - Adding additional specs for space distribution and section deletion. - Adding unit tests for anvil pasting. Fixes #33739 _or_ Fixes `Issue URL` > [!WARNING] > _If no issue exists, please create an issue first, and check with the maintainers if the issue is valid._ ## Automation /ok-to-test tags="@tag.Anvil" ### :mag: Cypress test results > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: > Commit: 4a770670aaf2f00d175066b597680345d840cd60 > Cypress dashboard url: Click here! ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [ ] No ## Summary by CodeRabbit - **New Features** - Added new test cases for verifying section removal and visual aspects of background-less zones in the Anvil layout system. - Introduced methods to handle mouse events for space distribution within sections. - Added mock data generation functionality for widgets, sections, zones, and layouts. - **Tests** - Implemented tests for paste operations in the Anvil layout system, including various mock functions and scenarios. --- .../Anvil/AnvilSectionsAndZones_spec.ts | 21 +- .../Anvil/AnvilSpaceDistribution_spec.ts | 52 +++- .../Pages/Anvil/AnvilSectionsZonesHelper.ts | 16 ++ .../{pasteSagas.ts => pasteSagas/index.ts} | 10 +- .../sagas/pasteSagas/pasteSagas.test.ts | 228 ++++++++++++++++++ .../destinationUtils/destinationUtils.test.ts | 45 ++++ .../index.ts} | 6 +- .../paste/destinationUtils/mockData.helper.ts | 86 +++++++ 8 files changed, 453 insertions(+), 11 deletions(-) rename app/client/src/layoutSystems/anvil/integrations/sagas/{pasteSagas.ts => pasteSagas/index.ts} (96%) create mode 100644 app/client/src/layoutSystems/anvil/integrations/sagas/pasteSagas/pasteSagas.test.ts create mode 100644 app/client/src/layoutSystems/anvil/utils/paste/destinationUtils/destinationUtils.test.ts rename app/client/src/layoutSystems/anvil/utils/paste/{destinationUtils.ts => destinationUtils/index.ts} (96%) create mode 100644 app/client/src/layoutSystems/anvil/utils/paste/destinationUtils/mockData.helper.ts diff --git a/app/client/cypress/e2e/Regression/ClientSide/Anvil/AnvilSectionsAndZones_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/Anvil/AnvilSectionsAndZones_spec.ts index d4ce8ffe9c..f022ded070 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Anvil/AnvilSectionsAndZones_spec.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/Anvil/AnvilSectionsAndZones_spec.ts @@ -1,4 +1,8 @@ -import { agHelper, anvilLayout } from "../../../../support/Objects/ObjectsCore"; +import { + agHelper, + anvilLayout, + propPane, +} from "../../../../support/Objects/ObjectsCore"; import { ANVIL_EDITOR_TEST } from "../../../../support/Constants"; import { featureFlagIntercept } from "../../../../support/Objects/FeatureFlags"; import { anvilLocators } from "../../../../support/Pages/Anvil/Locators"; @@ -78,5 +82,20 @@ describe( anvilLayout.verifyWidgetDoesNotExist("Section1"); anvilLayout.sections.verifyZoneCount("Section2", 2); }); + + it("3. Verify removing a section through the property pane of a section", () => { + // create a new section with a Zone widget + anvilLayout.dnd.DragDropNewAnvilWidgetNVerify( + anvilLocators.ZONE, + 10, + 10, + { + skipWidgetSearch: true, + }, + ); + // delete the section via the property pane + propPane.DeleteWidgetFromPropertyPane("Section1"); + anvilLayout.verifyWidgetDoesNotExist("Section1"); + }); }, ); diff --git a/app/client/cypress/e2e/Regression/ClientSide/Anvil/AnvilSpaceDistribution_spec.ts b/app/client/cypress/e2e/Regression/ClientSide/Anvil/AnvilSpaceDistribution_spec.ts index 9dc90f88ea..dddad3451e 100644 --- a/app/client/cypress/e2e/Regression/ClientSide/Anvil/AnvilSpaceDistribution_spec.ts +++ b/app/client/cypress/e2e/Regression/ClientSide/Anvil/AnvilSpaceDistribution_spec.ts @@ -1,4 +1,8 @@ -import { agHelper, anvilLayout } from "../../../../support/Objects/ObjectsCore"; +import { + agHelper, + anvilLayout, + propPane, +} from "../../../../support/Objects/ObjectsCore"; import { ANVIL_EDITOR_TEST } from "../../../../support/Constants"; import { featureFlagIntercept } from "../../../../support/Objects/FeatureFlags"; import { anvilLocators } from "../../../../support/Pages/Anvil/Locators"; @@ -147,5 +151,51 @@ describe( anvilLayout.sections.moveDistributionHandle("right", "Section1", 1, 7); anvilLayout.sections.verifySectionDistribution("Section1", [10, 2]); }); + it("4. Verify visual check for background less zones and resize indicators", () => { + // create a new section with a button widget + anvilLayout.dnd.DragDropNewAnvilWidgetNVerify( + anvilLocators.WDSBUTTON, + 10, + 10, + { + skipWidgetSearch: true, + }, + ); + // create a new zone within the section + anvilLayout.dnd.DragDropNewAnvilWidgetNVerify( + anvilLocators.ZONE, + 10, + 10, + { + skipWidgetSearch: true, + dropTargetDetails: { + name: "Section1", + }, + }, + ); + + const zone1Selector = anvilLocators.anvilWidgetNameSelector("Zone1"); + anvilLayout.sections.mouseDownSpaceDistributionHandle("Section1", 1); + // outline color of zone while distributing space should be transparent + cy.get(zone1Selector).should( + "have.css", + "outline-color", + "rgba(0, 0, 0, 0)", + ); + anvilLayout.sections.mouseUpSpaceDistributionHandle("Section1", 1); + // select zone1 + agHelper.GetNClick(zone1Selector); + // go to style tab + propPane.MoveToTab("Style"); + // toggle visual separation off on property pane + propPane.TogglePropertyState("Visual Separation", "Off"); + anvilLayout.sections.mouseDownSpaceDistributionHandle("Section1", 1); + // outline color of background less zone while distributing space should not be transparent + cy.get(zone1Selector).should( + "not.have.css", + "outline-color", + "rgba(0, 0, 0, 0)", + ); + }); }, ); diff --git a/app/client/cypress/support/Pages/Anvil/AnvilSectionsZonesHelper.ts b/app/client/cypress/support/Pages/Anvil/AnvilSectionsZonesHelper.ts index 74148f6d78..57d7c38d60 100644 --- a/app/client/cypress/support/Pages/Anvil/AnvilSectionsZonesHelper.ts +++ b/app/client/cypress/support/Pages/Anvil/AnvilSectionsZonesHelper.ts @@ -29,6 +29,22 @@ export class AnvilSectionsZonesHelper { }); } + public mouseDownSpaceDistributionHandle( + sectionName: string, + distributionHandleIndex: number, + ) { + const distributionHandleSelector = `${anvilLocators.anvilWidgetNameSelector(sectionName)} ${anvilLocators.anvilSectionDistributionHandle}:nth-child(${distributionHandleIndex})`; + cy.get(distributionHandleSelector).trigger("mousedown"); + } + + public mouseUpSpaceDistributionHandle( + sectionName: string, + distributionHandleIndex: number, + ) { + const distributionHandleSelector = `${anvilLocators.anvilWidgetNameSelector(sectionName)} ${anvilLocators.anvilSectionDistributionHandle}:nth-child(${distributionHandleIndex})`; + cy.get(distributionHandleSelector).trigger("mouseup"); + } + public verifyZoneCount( sectionOrZoneName: string, zoneCount: number, diff --git a/app/client/src/layoutSystems/anvil/integrations/sagas/pasteSagas.ts b/app/client/src/layoutSystems/anvil/integrations/sagas/pasteSagas/index.ts similarity index 96% rename from app/client/src/layoutSystems/anvil/integrations/sagas/pasteSagas.ts rename to app/client/src/layoutSystems/anvil/integrations/sagas/pasteSagas/index.ts index 12b794bb2c..a3a45a00d5 100644 --- a/app/client/src/layoutSystems/anvil/integrations/sagas/pasteSagas.ts +++ b/app/client/src/layoutSystems/anvil/integrations/sagas/pasteSagas/index.ts @@ -3,7 +3,7 @@ import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidg import { all, call, put, select, takeLeading } from "redux-saga/effects"; import { getSelectedWidgetWhenPasting } from "sagas/WidgetOperationUtils"; import { getWidgets } from "sagas/selectors"; -import { updateAndSaveAnvilLayout } from "../../utils/anvilChecksUtils"; +import { updateAndSaveAnvilLayout } from "../../../utils/anvilChecksUtils"; import { builderURL } from "@appsmith/RouteBuilder"; import { getCurrentPageId } from "selectors/editorSelectors"; import { @@ -18,13 +18,13 @@ import type { CopiedWidgetData, PasteDestinationInfo, PastePayload, -} from "../../utils/paste/types"; +} from "../../../utils/paste/types"; import { getCopiedWidgets } from "utils/storage"; import { getDestinedParent } from "layoutSystems/anvil/utils/paste/destinationUtils"; import { pasteWidgetsIntoMainCanvas } from "layoutSystems/anvil/utils/paste/mainCanvasPasteUtils"; import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants"; import WidgetFactory from "WidgetProvider/factory"; -import { getIsAnvilLayout } from "../selectors"; +import { getIsAnvilLayout } from "../../selectors"; import { widgetHierarchy } from "layoutSystems/anvil/utils/constants"; function* pasteAnvilModalWidgets( @@ -50,7 +50,7 @@ function* pasteAnvilModalWidgets( return res; } -function* pasteWidgetSagas() { +export function* pasteWidgetSagas() { try { const { widgets: copiedWidgets, @@ -69,7 +69,6 @@ function* pasteWidgetSagas() { const selectedWidget: FlattenedWidgetProps = yield getSelectedWidgetWhenPasting(); - if (!selectedWidget) return; let allWidgets: CanvasWidgetsReduxState = yield select(getWidgets); @@ -117,7 +116,6 @@ function* pasteWidgetSagas() { widgetIdMap = res.widgetIdMap; reverseWidgetIdMap = res.reverseWidgetIdMap; } - if (modalWidgets.length > 0) { // paste into main canvas const res: PastePayload = yield call( diff --git a/app/client/src/layoutSystems/anvil/integrations/sagas/pasteSagas/pasteSagas.test.ts b/app/client/src/layoutSystems/anvil/integrations/sagas/pasteSagas/pasteSagas.test.ts new file mode 100644 index 0000000000..686690727b --- /dev/null +++ b/app/client/src/layoutSystems/anvil/integrations/sagas/pasteSagas/pasteSagas.test.ts @@ -0,0 +1,228 @@ +import { select } from "redux-saga/effects"; +import { expectSaga } from "redux-saga-test-plan"; +import { pasteWidgetSagas } from "."; +import { ReduxActionTypes } from "@appsmith/constants/ReduxActionConstants"; +import { getCopiedWidgets } from "utils/storage"; +import { + getNextWidgetName, + getSelectedWidgetWhenPasting, +} from "sagas/WidgetOperationUtils"; +import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants"; +import { getWidgets } from "sagas/selectors"; +import { getCurrentPageId } from "selectors/editorSelectors"; +import { SelectionRequestType } from "sagas/WidgetSelectUtils"; +import { getDataTree } from "selectors/dataTreeSelectors"; +import { generateReactKey } from "utils/generators"; +import { LayoutComponentTypes } from "layoutSystems/anvil/utils/anvilTypes"; +import { registerLayoutComponents } from "layoutSystems/anvil/utils/layouts/layoutUtils"; +import { getLayoutSystemType } from "selectors/layoutSystemSelectors"; + +const cleanAllMocks = () => { + jest.resetModules(); // Reset the module registry + jest.clearAllMocks(); // Clears any mocked calls + jest.restoreAllMocks(); // Restores initial implementations +}; + +// Mock the getCopiedWidgets function +jest.mock("utils/storage", () => ({ + ...jest.requireActual("utils/storage"), + getCopiedWidgets: jest.fn(), +})); +// Mock the getSelectedWidgetWhenPasting function +jest.mock("sagas/WidgetOperationUtils", () => ({ + ...jest.requireActual("sagas/WidgetOperationUtils"), + getNextWidgetName: jest.fn(), + getSelectedWidgetWhenPasting: jest.fn(), +})); +// Mock only getDataTree +jest.mock("selectors/dataTreeSelectors", () => ({ + ...jest.requireActual("selectors/dataTreeSelectors"), + getDataTree: jest.fn(), +})); +// Mock getLayoutSystemType of layoutSystemSelector +jest.mock("selectors/layoutSystemSelectors", () => ({ + ...jest.requireActual("selectors/layoutSystemSelectors"), + getLayoutSystemType: jest.fn(), +})); +describe("pasteSagas", () => { + const pageId = "pageId"; + + beforeAll(() => { + registerLayoutComponents(); + }); + beforeEach(() => { + cleanAllMocks(); + (getLayoutSystemType as jest.Mock).mockReturnValue("ANVIL"); + }); + it("should perform paste operation with all necessary effects", async () => { + // create mock data for copiedWidgets, selectedWidget, allWidgets + const copiedWidgets: any = { + widgets: [ + { + list: [ + { + widgetId: "widgetId", + widgetName: "widgetName", + type: "type", + }, + ], + widgetId: "widgetId", + }, + ], + }; + const selectedWidget: any = { widgetId: MAIN_CONTAINER_WIDGET_ID }; + const allWidgets: any = { + widget1: { widgetId: "widget1", parentId: MAIN_CONTAINER_WIDGET_ID }, + [MAIN_CONTAINER_WIDGET_ID]: { + widgetId: MAIN_CONTAINER_WIDGET_ID, + layout: [ + { + layoutId: generateReactKey(), + layoutType: LayoutComponentTypes.ALIGNED_LAYOUT_COLUMN, + layout: [], + }, + ], + }, + }; + // mock the return values of the functions + (getCopiedWidgets as jest.Mock).mockResolvedValue(copiedWidgets); + (getSelectedWidgetWhenPasting as jest.Mock).mockReturnValue( + selectedWidget, + ); + (getDataTree as jest.Mock).mockReturnValue({ + widget1: { + widgetName: "widget1", + }, + }); + (getNextWidgetName as jest.Mock).mockReturnValue( + "widgetNamecopy", + ); + // run the saga + const { effects } = await expectSaga(pasteWidgetSagas as any) + .provide([ + [select(getWidgets), allWidgets], + [select(getCurrentPageId), pageId], + ]) + .run(); + // check the effects + expect(effects.put).toHaveLength(3); + const updateLayoutPut = effects.put[0].payload.action; + expect(updateLayoutPut.type).toBe(ReduxActionTypes.UPDATE_LAYOUT); + // check if a new widget is added to main canvas based on widget count on update + expect(Object.keys(updateLayoutPut.payload.widgets).length).toBe( + Object.keys(allWidgets).length + 1, + ); + const recordRecentlyAddedWidgetPut = effects.put[1].payload.action; + expect(recordRecentlyAddedWidgetPut.type).toBe( + ReduxActionTypes.RECORD_RECENTLY_ADDED_WIDGET, + ); + expect(recordRecentlyAddedWidgetPut.payload.length).toEqual(1); + const selectWidgetInitActionPut = effects.put[2].payload.action; + expect(selectWidgetInitActionPut.type).toBe( + ReduxActionTypes.SELECT_WIDGET_INIT, + ); + expect(selectWidgetInitActionPut.payload.selectionRequestType).toEqual( + SelectionRequestType.Multiple, + ); + expect(selectWidgetInitActionPut.payload.payload.length).toEqual(1); + }); + it("should paste copied modals only to Main canvas", async () => { + // Mock copiedWidgets data + const copiedWidgets = { + widgets: [ + { + hierarchy: 2, + list: [ + { + widgetId: "1", + widgetName: "1", + detachFromLayout: true, + type: "WDS_MODAL_WIDGET", + }, + ], + widgetId: "1", + }, + { + hierarchy: 1, + list: [ + { + widgetId: "2", + widgetName: "2", + type: "WDS_INPUT_WIDGET", + }, + ], + widgetId: "2", + }, + ], + }; + + // Mock selectedWidget data + const selectedWidget = { widgetId: "3", hierarchy: "WDS_INPUT_WIDGET" }; + + // Mock getWidgets selector + const allWidgets: any = { + 1: { + widgetId: "1", + detachFromLayout: true, + parentId: MAIN_CONTAINER_WIDGET_ID, + }, + 2: { widgetId: "2", parentId: MAIN_CONTAINER_WIDGET_ID }, + 3: { widgetId: "3", parentId: MAIN_CONTAINER_WIDGET_ID }, + [MAIN_CONTAINER_WIDGET_ID]: { + widgetId: MAIN_CONTAINER_WIDGET_ID, + children: ["1", "2", "3"], + layout: [ + { + layoutId: generateReactKey(), + layoutType: LayoutComponentTypes.ALIGNED_LAYOUT_COLUMN, + layout: [], + }, + ], + }, + }; + // Mock the return values of the functions + (getCopiedWidgets as jest.Mock).mockResolvedValue(copiedWidgets); + (getSelectedWidgetWhenPasting as jest.Mock).mockReturnValue( + selectedWidget, + ); + (getDataTree as jest.Mock).mockReturnValue({ + 1: { + widgetName: "1", + }, + 2: { + widgetName: "2", + }, + 3: { + widgetName: "3", + }, + }); + (getNextWidgetName as jest.Mock).mockReturnValue( + Math.random() + "widgetNamecopy", + ); + // Run the saga + const { effects } = await expectSaga(pasteWidgetSagas as any) + .provide([ + [select(getWidgets), allWidgets], + [select(getCurrentPageId), pageId], + ]) + .run(); + // Check the effects + expect(effects.put).toHaveLength(3); + const updateLayoutPut = effects.put[0].payload.action; + expect(updateLayoutPut.type).toBe(ReduxActionTypes.UPDATE_LAYOUT); + // check if a new widget is added to main canvas based on widget count on update + expect(Object.keys(updateLayoutPut.payload.widgets).length).toBe( + Object.keys(allWidgets).length + 2, + ); + const allUpdatedWidgets = Object.values(updateLayoutPut.payload.widgets); + const allUpdatedModals = allUpdatedWidgets.filter( + (widget: any) => widget.type === "WDS_MODAL_WIDGET", + ); + // Check if all modals are added to Main canvas + expect( + allUpdatedModals.every( + (each: any) => each.parentId === MAIN_CONTAINER_WIDGET_ID, + ), + ).toBe(true); + }); +}); diff --git a/app/client/src/layoutSystems/anvil/utils/paste/destinationUtils/destinationUtils.test.ts b/app/client/src/layoutSystems/anvil/utils/paste/destinationUtils/destinationUtils.test.ts new file mode 100644 index 0000000000..9cd6c1de6a --- /dev/null +++ b/app/client/src/layoutSystems/anvil/utils/paste/destinationUtils/destinationUtils.test.ts @@ -0,0 +1,45 @@ +import { FlexLayerAlignment } from "layoutSystems/common/utils/constants"; +import { registerLayoutComponents } from "../../layouts/layoutUtils"; +import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants"; +import { getDestinedParent } from "."; +import { generateMockDataWithSectionAndZone } from "./mockData.helper"; + +describe("paste destination utils tests", () => { + beforeAll(() => { + registerLayoutComponents(); + }); + it("should correctly identify the parent hierarchy for a copied widget when no widget is selected", () => { + const { allWidgets, copiedWidgets } = generateMockDataWithSectionAndZone(); + const selectedWidget: any = allWidgets[MAIN_CONTAINER_WIDGET_ID]; + const generator = getDestinedParent( + allWidgets, + copiedWidgets, + selectedWidget, + ); + const result = generator.next().value; + expect(result.parentOrder).toEqual([MAIN_CONTAINER_WIDGET_ID]); + // correctly identifies the parent hierarchy for a single copied widget + expect(result.alignment).toEqual(FlexLayerAlignment.Start); + // target adding to the main canvas layout + expect(result.layoutOrder).toEqual( + allWidgets[MAIN_CONTAINER_WIDGET_ID].layout, + ); + // target adding to the main canvas layout in position 1 + expect(result.rowIndex).toEqual([1]); + }); + it("should correctly identify the parent hierarchy for a copied widget when a widget is selected", () => { + const { allWidgets, copiedWidgets, mockWidgetId } = + generateMockDataWithSectionAndZone(); + const selectedWidget = allWidgets[mockWidgetId]; + const generator = getDestinedParent( + allWidgets, + copiedWidgets, + selectedWidget, + ); + const result = generator.next().value; + // correctly identifies the parent hierarchy for copied widgets + expect(result.parentOrder).toEqual(["widget-mock", "zone-mock"]); + expect(result.alignment).toEqual(FlexLayerAlignment.Start); + expect(result.rowIndex).toEqual([1, 1, 1]); + }); +}); diff --git a/app/client/src/layoutSystems/anvil/utils/paste/destinationUtils.ts b/app/client/src/layoutSystems/anvil/utils/paste/destinationUtils/index.ts similarity index 96% rename from app/client/src/layoutSystems/anvil/utils/paste/destinationUtils.ts rename to app/client/src/layoutSystems/anvil/utils/paste/destinationUtils/index.ts index 32b53136a1..f3305630de 100644 --- a/app/client/src/layoutSystems/anvil/utils/paste/destinationUtils.ts +++ b/app/client/src/layoutSystems/anvil/utils/paste/destinationUtils/index.ts @@ -1,12 +1,12 @@ import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer"; -import type { CopiedWidgetData, PasteDestinationInfo } from "./types"; import type { FlattenedWidgetProps } from "WidgetProvider/constants"; -import { getWidgetHierarchy } from "./utils"; import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants"; -import type { LayoutProps, WidgetLayoutProps } from "../anvilTypes"; import LayoutFactory from "layoutSystems/anvil/layoutComponents/LayoutFactory"; import type BaseLayoutComponent from "layoutSystems/anvil/layoutComponents/BaseLayoutComponent"; import { FlexLayerAlignment } from "layoutSystems/common/utils/constants"; +import type { CopiedWidgetData, PasteDestinationInfo } from "../types"; +import { getWidgetHierarchy } from "../utils"; +import type { LayoutProps, WidgetLayoutProps } from "../../anvilTypes"; export function* getDestinedParent( allWidgets: CanvasWidgetsReduxState, diff --git a/app/client/src/layoutSystems/anvil/utils/paste/destinationUtils/mockData.helper.ts b/app/client/src/layoutSystems/anvil/utils/paste/destinationUtils/mockData.helper.ts new file mode 100644 index 0000000000..68b94b2a37 --- /dev/null +++ b/app/client/src/layoutSystems/anvil/utils/paste/destinationUtils/mockData.helper.ts @@ -0,0 +1,86 @@ +import { FlexLayerAlignment } from "layoutSystems/common/utils/constants"; +import { LayoutComponentTypes } from "../../anvilTypes"; +import { MAIN_CONTAINER_WIDGET_ID } from "constants/WidgetConstants"; + +export function generateMockDataWithSectionAndZone() { + const mockWidgetId = "widget-mock"; + const mockSectionId = "section-mock"; + const mockZoneId = "zone-mock"; + const alignedRowWithWidgets = { + layoutType: LayoutComponentTypes.ALIGNED_WIDGET_ROW, + layout: [ + { + alignment: FlexLayerAlignment.Start, + widgetId: mockWidgetId, + widgetType: "WDS_BUTTON_WIDGET", + }, + ], + }; + const zoneLayout = { + layoutType: LayoutComponentTypes.ZONE, + layout: [alignedRowWithWidgets], + }; + const sectionLayout = { + layoutType: LayoutComponentTypes.SECTION, + layout: [ + { + widgetId: mockZoneId, + alignment: FlexLayerAlignment.Start, + widgetType: "ZONE_WIDGET", + }, + ], + }; + const mainCanvasLayout = { + layoutType: LayoutComponentTypes.ALIGNED_LAYOUT_COLUMN, + layout: [ + { + layoutType: LayoutComponentTypes.WIDGET_ROW, + layout: [ + { + widgetId: mockSectionId, + alignment: FlexLayerAlignment.Start, + widgetType: "SECTION_WIDGET", + }, + ], + }, + ], + }; + const allWidgets: any = { + [mockWidgetId]: { + widgetId: mockWidgetId, + type: "WDS_BUTTON_WIDGET", + parentId: mockZoneId, + }, + [mockZoneId]: { + widgetId: mockZoneId, + type: "ZONE_WIDGET", + parentId: mockSectionId, + layout: [zoneLayout], + }, + [mockSectionId]: { + widgetId: mockSectionId, + type: "SECTION_WIDGET", + parentId: MAIN_CONTAINER_WIDGET_ID, + layout: [sectionLayout], + }, + [MAIN_CONTAINER_WIDGET_ID]: { + widgetId: MAIN_CONTAINER_WIDGET_ID, + type: "MAIN_CONTAINER", + parentId: "", + layout: [mainCanvasLayout], + }, + }; + const copiedWidgets: any = [ + { + list: [allWidgets[mockWidgetId]], + hierarchy: 4, + }, + ]; + return { + allWidgets, + copiedWidgets, + mockWidgetId, + mockSectionId, + mockZoneId, + }; +}