## Description - Remove the config objects from widget and config maps from the widget factory. - Introduce methods in widget development API to dynamically fetch this items. - freeze the widget configuration. #### PR fixes following issue(s) Fixes https://github.com/appsmithorg/appsmith/issues/26008 > if no issue exists, please create an issue and ask the maintainers about this first > > #### Media > A video or a GIF is preferred. when using Loom, don’t embed because it looks like it’s a GIF. instead, just link to the video > > #### Type of change > Please delete options that are not relevant. - Bug fix (non-breaking change which fixes an issue) - New feature (non-breaking change which adds functionality) - Breaking change (fix or feature that would cause existing functionality to not work as expected) - Chore (housekeeping or task changes that don't impact user perception) - This change requires a documentation update > > > ## Testing > #### How Has This Been Tested? > Please describe the tests that you ran to verify your changes. Also list any relevant details for your test configuration. > Delete anything that is not relevant - [x] Manual - [ ] Jest - [ ] Cypress > > #### Test Plan > Add Testsmith test cases links that relate to this PR > > #### Issues raised during DP testing > Link issues raised during DP testing for better visiblity and tracking (copy link from comments dropped on this PR) > > > ## Checklist: #### Dev activity - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] PR is being merged under a feature flag #### QA activity: - [ ] [Speedbreak features](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#speedbreakers-) have been covered - [x] Test plan covers all impacted features and [areas of interest](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans#areas-of-interest-) - [ ] Test plan has been peer reviewed by project stakeholders and other QA members - [x] Manually tested functionality on DP - [ ] We had an implementation alignment call with stakeholders post QA Round 2 - [ ] Cypress test cases have been added and approved by SDET/manual QA - [ ] Added `Test Plan Approved` label after Cypress tests were reviewed - [ ] Added `Test Plan Approved` label after JUnit tests were reviewed
1820 lines
46 KiB
TypeScript
1820 lines
46 KiB
TypeScript
import type { OccupiedSpace } from "constants/CanvasEditorConstants";
|
|
import { klona } from "klona";
|
|
import { get } from "lodash";
|
|
import type { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer";
|
|
import type { WidgetProps } from "widgets/BaseWidget";
|
|
import type { FlattenedWidgetProps } from "WidgetProvider/constants";
|
|
import type { CopiedWidgetGroup } from "./WidgetOperationUtils";
|
|
import {
|
|
handleIfParentIsListWidgetWhilePasting,
|
|
handleSpecificCasesWhilePasting,
|
|
doesTriggerPathsContainPropertyPath,
|
|
getSelectedWidgetIfPastingIntoListWidget,
|
|
checkForListWidgetInCopiedWidgets,
|
|
updateListWidgetPropertiesOnChildDelete,
|
|
purgeOrphanedDynamicPaths,
|
|
getBoundariesFromSelectedWidgets,
|
|
getSnappedGrid,
|
|
changeIdsOfPastePositions,
|
|
getVerticallyAdjustedPositions,
|
|
getNewPositionsForCopiedWidgets,
|
|
getPastePositionMapFromMousePointer,
|
|
getReflowedPositions,
|
|
getWidgetsFromIds,
|
|
getValueFromTree,
|
|
resizePublishedMainCanvasToLowestWidget,
|
|
} from "./WidgetOperationUtils";
|
|
|
|
describe("WidgetOperationSaga", () => {
|
|
it("should returns widgets after executing handleIfParentIsListWidgetWhilePasting", async () => {
|
|
expect(
|
|
doesTriggerPathsContainPropertyPath(false, "trigger-path-1", [
|
|
"trigger-path-1",
|
|
]),
|
|
).toBe(true);
|
|
|
|
expect(
|
|
doesTriggerPathsContainPropertyPath(false, "trigger-path-1", [
|
|
"trigger-path-2",
|
|
]),
|
|
).toBe(false);
|
|
|
|
expect(
|
|
doesTriggerPathsContainPropertyPath(true, "trigger-path-1", [
|
|
"trigger-path-2",
|
|
]),
|
|
).toBe(true);
|
|
});
|
|
|
|
it("should return widgets after executing handleIfParentIsListWidgetWhilePasting", async () => {
|
|
const result = handleIfParentIsListWidgetWhilePasting(
|
|
{
|
|
widgetId: "text1",
|
|
type: "TEXT_WIDGET",
|
|
widgetName: "Text1",
|
|
parentId: "list1",
|
|
renderMode: "CANVAS",
|
|
parentColumnSpace: 2,
|
|
parentRowSpace: 3,
|
|
leftColumn: 2,
|
|
rightColumn: 3,
|
|
topRow: 1,
|
|
bottomRow: 3,
|
|
isLoading: false,
|
|
listData: [],
|
|
text: "{{currentItem.text}}",
|
|
version: 16,
|
|
disablePropertyPane: false,
|
|
},
|
|
{
|
|
list1: {
|
|
widgetId: "list1",
|
|
type: "LIST_WIDGET",
|
|
widgetName: "List1",
|
|
parentId: "0",
|
|
renderMode: "CANVAS",
|
|
parentColumnSpace: 2,
|
|
parentRowSpace: 3,
|
|
leftColumn: 2,
|
|
rightColumn: 3,
|
|
topRow: 1,
|
|
bottomRow: 3,
|
|
isLoading: false,
|
|
listData: [],
|
|
version: 16,
|
|
disablePropertyPane: false,
|
|
template: {},
|
|
},
|
|
0: {
|
|
image: "",
|
|
defaultImage: "",
|
|
widgetId: "0",
|
|
type: "CANVAS_WIDGET",
|
|
widgetName: "MainContainer",
|
|
renderMode: "CANVAS",
|
|
parentColumnSpace: 2,
|
|
parentRowSpace: 3,
|
|
leftColumn: 2,
|
|
rightColumn: 3,
|
|
topRow: 1,
|
|
bottomRow: 3,
|
|
isLoading: false,
|
|
listData: [],
|
|
version: 16,
|
|
disablePropertyPane: false,
|
|
template: {},
|
|
},
|
|
},
|
|
);
|
|
|
|
expect(result.list1.template["Text1"].text).toStrictEqual(
|
|
"{{List1.listData.map((currentItem) => (currentItem.text))}}",
|
|
);
|
|
expect(get(result, "list1.dynamicBindingPathList.0.key")).toStrictEqual(
|
|
"template.Text1.text",
|
|
);
|
|
});
|
|
|
|
it("should returns widgets after executing handleSpecificCasesWhilePasting", async () => {
|
|
const result = handleSpecificCasesWhilePasting(
|
|
{
|
|
widgetId: "text2",
|
|
type: "TEXT_WIDGET",
|
|
widgetName: "Text2",
|
|
parentId: "list2",
|
|
renderMode: "CANVAS",
|
|
parentColumnSpace: 2,
|
|
parentRowSpace: 3,
|
|
leftColumn: 2,
|
|
rightColumn: 3,
|
|
topRow: 1,
|
|
bottomRow: 3,
|
|
isLoading: false,
|
|
listData: [],
|
|
text: "{{currentItem.text}}",
|
|
version: 16,
|
|
disablePropertyPane: false,
|
|
},
|
|
{
|
|
list1: {
|
|
widgetId: "list1",
|
|
type: "LIST_WIDGET",
|
|
widgetName: "List1",
|
|
parentId: "0",
|
|
renderMode: "CANVAS",
|
|
parentColumnSpace: 2,
|
|
parentRowSpace: 3,
|
|
leftColumn: 2,
|
|
rightColumn: 3,
|
|
topRow: 1,
|
|
bottomRow: 3,
|
|
isLoading: false,
|
|
listData: [],
|
|
version: 16,
|
|
disablePropertyPane: false,
|
|
template: {},
|
|
},
|
|
0: {
|
|
image: "",
|
|
defaultImage: "",
|
|
widgetId: "0",
|
|
type: "CANVAS_WIDGET",
|
|
widgetName: "MainContainer",
|
|
renderMode: "CANVAS",
|
|
parentColumnSpace: 2,
|
|
parentRowSpace: 3,
|
|
leftColumn: 2,
|
|
rightColumn: 3,
|
|
topRow: 1,
|
|
bottomRow: 3,
|
|
isLoading: false,
|
|
listData: [],
|
|
version: 16,
|
|
disablePropertyPane: false,
|
|
template: {},
|
|
},
|
|
list2: {
|
|
widgetId: "list2",
|
|
type: "LIST_WIDGET",
|
|
widgetName: "List2",
|
|
parentId: "0",
|
|
renderMode: "CANVAS",
|
|
parentColumnSpace: 2,
|
|
parentRowSpace: 3,
|
|
leftColumn: 2,
|
|
rightColumn: 3,
|
|
topRow: 1,
|
|
bottomRow: 3,
|
|
isLoading: false,
|
|
listData: [],
|
|
version: 16,
|
|
disablePropertyPane: false,
|
|
template: {},
|
|
},
|
|
},
|
|
{
|
|
List1: "List2",
|
|
},
|
|
[
|
|
{
|
|
widgetId: "list2",
|
|
type: "LIST_WIDGET",
|
|
widgetName: "List2",
|
|
parentId: "0",
|
|
renderMode: "CANVAS",
|
|
parentColumnSpace: 2,
|
|
parentRowSpace: 3,
|
|
leftColumn: 2,
|
|
rightColumn: 3,
|
|
topRow: 1,
|
|
bottomRow: 3,
|
|
isLoading: false,
|
|
listData: [],
|
|
version: 16,
|
|
disablePropertyPane: false,
|
|
template: {},
|
|
},
|
|
],
|
|
);
|
|
|
|
expect(result.list2.template["Text2"].text).toStrictEqual(
|
|
"{{List2.listData.map((currentItem) => (currentItem.text))}}",
|
|
);
|
|
expect(get(result, "list2.dynamicBindingPathList.0.key")).toStrictEqual(
|
|
"template.Text2.text",
|
|
);
|
|
});
|
|
|
|
it("handleSpecificCasesWhilePasting should rename dynamicTriggerPathList template keys for a copied list widget", async () => {
|
|
const result = handleSpecificCasesWhilePasting(
|
|
{
|
|
widgetId: "list2",
|
|
type: "LIST_WIDGET",
|
|
widgetName: "List2",
|
|
parentId: "0",
|
|
renderMode: "CANVAS",
|
|
parentColumnSpace: 2,
|
|
parentRowSpace: 3,
|
|
leftColumn: 2,
|
|
rightColumn: 3,
|
|
topRow: 1,
|
|
bottomRow: 3,
|
|
isLoading: false,
|
|
listData: [],
|
|
version: 16,
|
|
disablePropertyPane: false,
|
|
template: {
|
|
Image1: {
|
|
widgetId: "image1",
|
|
type: "Image_WIDGET",
|
|
widgetName: "Image1",
|
|
parentId: "list2",
|
|
renderMode: "CANVAS",
|
|
parentColumnSpace: 2,
|
|
parentRowSpace: 3,
|
|
leftColumn: 2,
|
|
rightColumn: 3,
|
|
topRow: 1,
|
|
bottomRow: 3,
|
|
isLoading: false,
|
|
listData: [],
|
|
version: 16,
|
|
disablePropertyPane: false,
|
|
dynamicTriggerPathList: [{ key: "onClick" }],
|
|
},
|
|
},
|
|
dynamicTriggerPathList: [{ key: "template.Image1.onClick" }],
|
|
},
|
|
{},
|
|
{
|
|
Image1: "Image1Copy",
|
|
},
|
|
[],
|
|
);
|
|
expect(get(result, "list2.dynamicTriggerPathList.0.key")).toStrictEqual(
|
|
"template.Image1Copy.onClick",
|
|
);
|
|
});
|
|
|
|
it("should return correct close modal reference name after executing handleSpecificCasesWhilePasting", async () => {
|
|
const result = handleSpecificCasesWhilePasting(
|
|
{
|
|
widgetName: "Modal1Copy",
|
|
rightColumn: 24,
|
|
detachFromLayout: true,
|
|
widgetId: "k441huwm77",
|
|
topRow: 34,
|
|
bottomRow: 58,
|
|
parentRowSpace: 10,
|
|
canOutsideClickClose: true,
|
|
type: "MODAL_WIDGET",
|
|
canEscapeKeyClose: true,
|
|
version: 1,
|
|
parentId: "0",
|
|
shouldScrollContents: true,
|
|
isLoading: false,
|
|
parentColumnSpace: 17.21875,
|
|
size: "MODAL_SMALL",
|
|
leftColumn: 0,
|
|
children: ["ihxw5r23hd"],
|
|
renderMode: "CANVAS",
|
|
},
|
|
{
|
|
k441huwm77: {
|
|
widgetName: "Modal1Copy",
|
|
rightColumn: 24,
|
|
detachFromLayout: true,
|
|
widgetId: "k441huwm77",
|
|
topRow: 34,
|
|
bottomRow: 58,
|
|
parentRowSpace: 10,
|
|
canOutsideClickClose: true,
|
|
type: "MODAL_WIDGET",
|
|
canEscapeKeyClose: true,
|
|
version: 1,
|
|
parentId: "0",
|
|
shouldScrollContents: true,
|
|
isLoading: false,
|
|
parentColumnSpace: 17.21875,
|
|
size: "MODAL_SMALL",
|
|
leftColumn: 0,
|
|
children: ["ihxw5r23hd"],
|
|
renderMode: "CANVAS",
|
|
},
|
|
suhkuyfpk3: {
|
|
widgetName: "Icon1Copy",
|
|
rightColumn: 64,
|
|
onClick: "{{closeModal('Modal1')}}",
|
|
color: "#040627",
|
|
iconName: "cross",
|
|
widgetId: "suhkuyfpk3",
|
|
topRow: 1,
|
|
bottomRow: 5,
|
|
isVisible: true,
|
|
type: "ICON_WIDGET",
|
|
version: 1,
|
|
parentId: "ihxw5r23hd",
|
|
isLoading: false,
|
|
leftColumn: 56,
|
|
iconSize: 24,
|
|
renderMode: "CANVAS",
|
|
parentColumnSpace: 2,
|
|
parentRowSpace: 3,
|
|
},
|
|
twnxjwy3r1: {
|
|
widgetName: "Button1Copy",
|
|
rightColumn: 48,
|
|
onClick: "{{closeModal('Modal1')}}",
|
|
isDefaultClickDisabled: true,
|
|
widgetId: "twnxjwy3r1",
|
|
buttonStyle: "SECONDARY_BUTTON",
|
|
topRow: 16,
|
|
bottomRow: 20,
|
|
isVisible: true,
|
|
type: "BUTTON_WIDGET",
|
|
version: 1,
|
|
parentId: "ihxw5r23hd",
|
|
isLoading: false,
|
|
dynamicTriggerPathList: [
|
|
{
|
|
key: "onClick",
|
|
},
|
|
],
|
|
leftColumn: 36,
|
|
dynamicBindingPathList: [],
|
|
text: "Cancel",
|
|
isDisabled: false,
|
|
renderMode: "CANVAS",
|
|
parentColumnSpace: 2,
|
|
parentRowSpace: 3,
|
|
},
|
|
},
|
|
{
|
|
Modal1: "Modal1Copy",
|
|
Canvas1: "Canvas1Copy",
|
|
Icon1: "Icon1Copy",
|
|
Text1: "Text1Copy",
|
|
Button1: "Button1Copy",
|
|
Button2: "Button2Copy",
|
|
},
|
|
[
|
|
{
|
|
widgetName: "Modal1Copy",
|
|
rightColumn: 24,
|
|
detachFromLayout: true,
|
|
widgetId: "k441huwm77",
|
|
topRow: 34,
|
|
bottomRow: 58,
|
|
parentRowSpace: 10,
|
|
canOutsideClickClose: true,
|
|
type: "MODAL_WIDGET",
|
|
canEscapeKeyClose: true,
|
|
version: 1,
|
|
parentId: "0",
|
|
shouldScrollContents: true,
|
|
isLoading: false,
|
|
parentColumnSpace: 17.21875,
|
|
size: "MODAL_SMALL",
|
|
leftColumn: 0,
|
|
children: ["ihxw5r23hd"],
|
|
renderMode: "CANVAS",
|
|
},
|
|
{
|
|
widgetName: "Icon1Copy",
|
|
rightColumn: 64,
|
|
onClick: "{{closeModal('Modal1')}}",
|
|
color: "#040627",
|
|
iconName: "cross",
|
|
widgetId: "suhkuyfpk3",
|
|
topRow: 1,
|
|
bottomRow: 5,
|
|
isVisible: true,
|
|
type: "ICON_WIDGET",
|
|
version: 1,
|
|
parentId: "ihxw5r23hd",
|
|
isLoading: false,
|
|
leftColumn: 56,
|
|
iconSize: 24,
|
|
renderMode: "CANVAS",
|
|
parentColumnSpace: 2,
|
|
parentRowSpace: 3,
|
|
},
|
|
{
|
|
widgetName: "Button1Copy",
|
|
rightColumn: 48,
|
|
onClick: "{{closeModal('Modal1')}}",
|
|
isDefaultClickDisabled: true,
|
|
widgetId: "twnxjwy3r1",
|
|
buttonStyle: "SECONDARY_BUTTON",
|
|
topRow: 16,
|
|
bottomRow: 20,
|
|
isVisible: true,
|
|
type: "BUTTON_WIDGET",
|
|
version: 1,
|
|
parentId: "ihxw5r23hd",
|
|
isLoading: false,
|
|
dynamicTriggerPathList: [
|
|
{
|
|
key: "onClick",
|
|
},
|
|
],
|
|
leftColumn: 36,
|
|
dynamicBindingPathList: [],
|
|
text: "Cancel",
|
|
isDisabled: false,
|
|
renderMode: "CANVAS",
|
|
parentColumnSpace: 2,
|
|
parentRowSpace: 3,
|
|
},
|
|
],
|
|
);
|
|
expect(result["suhkuyfpk3"].onClick).toStrictEqual(
|
|
"{{closeModal('Modal1Copy')}}",
|
|
);
|
|
expect(result["twnxjwy3r1"].onClick).toStrictEqual(
|
|
"{{closeModal('Modal1Copy')}}",
|
|
);
|
|
});
|
|
|
|
it("should returns widgets after executing getSelectedWidgetIfPastingIntoListWidget", async () => {
|
|
const result = getSelectedWidgetIfPastingIntoListWidget(
|
|
{
|
|
list2: {
|
|
widgetId: "list2",
|
|
type: "LIST_WIDGET",
|
|
widgetName: "List2",
|
|
parentId: "0",
|
|
renderMode: "CANVAS",
|
|
parentColumnSpace: 2,
|
|
parentRowSpace: 3,
|
|
leftColumn: 2,
|
|
rightColumn: 3,
|
|
topRow: 1,
|
|
bottomRow: 3,
|
|
isLoading: false,
|
|
listData: [],
|
|
version: 16,
|
|
disablePropertyPane: false,
|
|
template: {},
|
|
},
|
|
},
|
|
{
|
|
widgetId: "list2",
|
|
type: "LIST_WIDGET",
|
|
widgetName: "List2",
|
|
parentId: "0",
|
|
renderMode: "CANVAS",
|
|
parentColumnSpace: 2,
|
|
parentRowSpace: 3,
|
|
leftColumn: 2,
|
|
rightColumn: 3,
|
|
topRow: 1,
|
|
bottomRow: 3,
|
|
isLoading: false,
|
|
listData: [],
|
|
version: 16,
|
|
disablePropertyPane: false,
|
|
template: {},
|
|
},
|
|
[
|
|
{
|
|
widgetId: "list2",
|
|
parentId: "0",
|
|
list: [
|
|
{
|
|
widgetId: "list2",
|
|
type: "LIST_WIDGET",
|
|
widgetName: "List2",
|
|
parentId: "0",
|
|
renderMode: "CANVAS",
|
|
parentColumnSpace: 2,
|
|
parentRowSpace: 3,
|
|
leftColumn: 2,
|
|
rightColumn: 3,
|
|
topRow: 1,
|
|
bottomRow: 3,
|
|
isLoading: false,
|
|
listData: [],
|
|
version: 16,
|
|
disablePropertyPane: false,
|
|
template: {},
|
|
},
|
|
],
|
|
},
|
|
],
|
|
);
|
|
|
|
expect(result?.type).toStrictEqual("LIST_WIDGET");
|
|
});
|
|
|
|
it("should return widgets after executing updateListWidgetPropertiesOnChildDelete", () => {
|
|
const result = updateListWidgetPropertiesOnChildDelete(
|
|
{
|
|
list1: {
|
|
widgetId: "list1",
|
|
type: "LIST_WIDGET",
|
|
widgetName: "List1",
|
|
parentId: "0",
|
|
renderMode: "CANVAS",
|
|
parentColumnSpace: 2,
|
|
parentRowSpace: 3,
|
|
leftColumn: 2,
|
|
rightColumn: 3,
|
|
topRow: 1,
|
|
bottomRow: 3,
|
|
isLoading: false,
|
|
listData: [],
|
|
version: 16,
|
|
disablePropertyPane: false,
|
|
template: {},
|
|
enhancements: {},
|
|
dynamicBindingPathList: [{ key: "template.ButtonWidget1.text" }],
|
|
dynamicTriggerPathList: [
|
|
{
|
|
key: "template.ButtonWidget1.onClick",
|
|
},
|
|
],
|
|
},
|
|
buttonWidget1: {
|
|
type: "BUTTON_WIDGET",
|
|
widgetId: "buttonWidget1",
|
|
widgetName: "buttonWidget1",
|
|
version: 16,
|
|
parentColumnSpace: 2,
|
|
parentRowSpace: 3,
|
|
leftColumn: 2,
|
|
rightColumn: 3,
|
|
topRow: 1,
|
|
bottomRow: 3,
|
|
renderMode: "CANVAS",
|
|
isLoading: false,
|
|
parentId: "list1",
|
|
},
|
|
0: {
|
|
type: "CANVAS_WIDGET",
|
|
widgetId: "0",
|
|
widgetName: "MainContainer",
|
|
version: 16,
|
|
parentColumnSpace: 2,
|
|
parentRowSpace: 3,
|
|
leftColumn: 2,
|
|
rightColumn: 3,
|
|
topRow: 1,
|
|
bottomRow: 3,
|
|
renderMode: "CANVAS",
|
|
isLoading: false,
|
|
parentId: "list1",
|
|
},
|
|
},
|
|
"buttonWidget1",
|
|
"ButtonWidget1",
|
|
);
|
|
|
|
const expected = updateListWidgetPropertiesOnChildDelete(
|
|
{
|
|
list1: {
|
|
widgetId: "list1",
|
|
type: "LIST_WIDGET",
|
|
widgetName: "List1",
|
|
parentId: "0",
|
|
renderMode: "CANVAS",
|
|
parentColumnSpace: 2,
|
|
parentRowSpace: 3,
|
|
leftColumn: 2,
|
|
rightColumn: 3,
|
|
topRow: 1,
|
|
bottomRow: 3,
|
|
isLoading: false,
|
|
listData: [],
|
|
version: 16,
|
|
disablePropertyPane: false,
|
|
template: {},
|
|
enhancements: {},
|
|
dynamicBindingPathList: [],
|
|
dynamicTriggerPathList: [],
|
|
},
|
|
buttonWidget1: {
|
|
type: "BUTTON_WIDGET",
|
|
widgetId: "buttonWidget1",
|
|
widgetName: "buttonWidget1",
|
|
version: 16,
|
|
parentColumnSpace: 2,
|
|
parentRowSpace: 3,
|
|
leftColumn: 2,
|
|
rightColumn: 3,
|
|
topRow: 1,
|
|
bottomRow: 3,
|
|
renderMode: "CANVAS",
|
|
isLoading: false,
|
|
parentId: "list1",
|
|
},
|
|
0: {
|
|
type: "CANVAS_WIDGET",
|
|
widgetId: "0",
|
|
widgetName: "MainContainer",
|
|
version: 16,
|
|
parentColumnSpace: 2,
|
|
parentRowSpace: 3,
|
|
leftColumn: 2,
|
|
rightColumn: 3,
|
|
topRow: 1,
|
|
bottomRow: 3,
|
|
renderMode: "CANVAS",
|
|
isLoading: false,
|
|
parentId: "list1",
|
|
},
|
|
},
|
|
"buttonWidget1",
|
|
"ButtonWidget1",
|
|
);
|
|
|
|
expect(result).toStrictEqual(expected);
|
|
});
|
|
|
|
it("should purge orphaned dynamicTriggerPaths and dynamicBindingPaths from widget", () => {
|
|
const input = {
|
|
dynamicBindingPathList: [
|
|
{ key: "primaryColumns.name.computedValue" },
|
|
{ key: "primaryColumns.name.fontStyle" },
|
|
{ key: "primaryColumns.name.nonExistentPath" },
|
|
{ key: "nonExistentKey" },
|
|
],
|
|
dynamicTriggerPathList: [
|
|
{ key: "primaryColumns.name.onClick" },
|
|
{ key: "primaryColumns.name.nonExistentPath" },
|
|
{ key: "nonExistentKey" },
|
|
],
|
|
primaryColumns: {
|
|
name: {
|
|
computedValue: "{{currentRow.something}}",
|
|
fontStyle: "bold",
|
|
onClick: "{{showAlert('message', 'error')}}",
|
|
},
|
|
},
|
|
};
|
|
const expected = {
|
|
dynamicBindingPathList: [
|
|
{ key: "primaryColumns.name.computedValue" },
|
|
{ key: "primaryColumns.name.fontStyle" },
|
|
],
|
|
dynamicTriggerPathList: [{ key: "primaryColumns.name.onClick" }],
|
|
primaryColumns: {
|
|
name: {
|
|
computedValue: "{{currentRow.something}}",
|
|
fontStyle: "bold",
|
|
onClick: "{{showAlert('message', 'error')}}",
|
|
},
|
|
},
|
|
};
|
|
const result = purgeOrphanedDynamicPaths(input as any as WidgetProps);
|
|
expect(result).toStrictEqual(expected);
|
|
});
|
|
it("should return boundaries of selected Widgets", () => {
|
|
const selectedWidgets = [
|
|
{
|
|
id: "1234",
|
|
topRow: 10,
|
|
leftColumn: 20,
|
|
rightColumn: 45,
|
|
bottomRow: 40,
|
|
},
|
|
{
|
|
id: "1233",
|
|
topRow: 45,
|
|
leftColumn: 30,
|
|
rightColumn: 60,
|
|
bottomRow: 70,
|
|
},
|
|
] as any as WidgetProps[];
|
|
expect(getBoundariesFromSelectedWidgets(selectedWidgets)).toEqual({
|
|
totalWidth: 40,
|
|
totalHeight: 60,
|
|
maxThickness: 30,
|
|
topMostRow: 10,
|
|
leftMostColumn: 20,
|
|
});
|
|
});
|
|
describe("test getSnappedGrid", () => {
|
|
it("should return snapGrids for a ContainerWidget", () => {
|
|
const canvasWidget = {
|
|
widgetId: "1234",
|
|
type: "CONTAINER_WIDGET",
|
|
noPad: true,
|
|
} as any as WidgetProps;
|
|
expect(getSnappedGrid(canvasWidget, 250)).toEqual({
|
|
padding: 4,
|
|
snapGrid: {
|
|
snapColumnSpace: 3.78125,
|
|
snapRowSpace: 10,
|
|
},
|
|
});
|
|
});
|
|
it("should return snapGrids for non ContainerWidget", () => {
|
|
const canvasWidget = {
|
|
widgetId: "1234",
|
|
type: "LIST_WIDGET",
|
|
noPad: false,
|
|
} as any as WidgetProps;
|
|
expect(getSnappedGrid(canvasWidget, 250)).toEqual({
|
|
padding: 10,
|
|
snapGrid: {
|
|
snapColumnSpace: 3.59375,
|
|
snapRowSpace: 10,
|
|
},
|
|
});
|
|
});
|
|
});
|
|
it("should test changeIdsOfPastePositions", () => {
|
|
const newPastingPositionMap = {
|
|
"1234": {
|
|
id: "1234",
|
|
left: 10,
|
|
right: 20,
|
|
top: 10,
|
|
bottom: 20,
|
|
},
|
|
"1235": {
|
|
id: "1235",
|
|
left: 11,
|
|
right: 22,
|
|
top: 11,
|
|
bottom: 22,
|
|
},
|
|
};
|
|
expect(changeIdsOfPastePositions(newPastingPositionMap)).toEqual([
|
|
{
|
|
id: "1",
|
|
left: 10,
|
|
right: 20,
|
|
top: 10,
|
|
bottom: 20,
|
|
},
|
|
{
|
|
id: "2",
|
|
left: 11,
|
|
right: 22,
|
|
top: 11,
|
|
bottom: 22,
|
|
},
|
|
]);
|
|
});
|
|
|
|
it("should offset widgets vertically so that it doesn't overlap with selected widgets", () => {
|
|
const selectedWidgets = [
|
|
{
|
|
id: "1234",
|
|
top: 10,
|
|
left: 20,
|
|
right: 45,
|
|
bottom: 40,
|
|
},
|
|
{
|
|
id: "1233",
|
|
top: 45,
|
|
left: 30,
|
|
right: 60,
|
|
bottom: 70,
|
|
},
|
|
{
|
|
id: "1235",
|
|
topRow: 80,
|
|
left: 10,
|
|
right: 50,
|
|
bottom: 100,
|
|
},
|
|
] as OccupiedSpace[];
|
|
const copiedWidgets = [
|
|
{
|
|
id: "1234",
|
|
top: 10,
|
|
left: 20,
|
|
right: 45,
|
|
bottom: 40,
|
|
},
|
|
{
|
|
id: "1233",
|
|
top: 45,
|
|
left: 30,
|
|
right: 60,
|
|
bottom: 70,
|
|
},
|
|
] as any as OccupiedSpace[];
|
|
expect(
|
|
getVerticallyAdjustedPositions(copiedWidgets, selectedWidgets, 30),
|
|
).toEqual({
|
|
"1234": {
|
|
id: "1234",
|
|
top: 71,
|
|
left: 20,
|
|
right: 45,
|
|
bottom: 101,
|
|
},
|
|
"1233": {
|
|
id: "1233",
|
|
top: 106,
|
|
left: 30,
|
|
right: 60,
|
|
bottom: 131,
|
|
},
|
|
});
|
|
});
|
|
it("should test getNewPositionsForCopiedWidgets", () => {
|
|
const copiedGroups = [
|
|
{
|
|
widgetId: "1234",
|
|
list: [
|
|
{
|
|
topRow: 10,
|
|
leftColumn: 20,
|
|
rightColumn: 45,
|
|
bottomRow: 40,
|
|
},
|
|
],
|
|
},
|
|
{
|
|
widgetId: "1235",
|
|
list: [
|
|
{
|
|
topRow: 45,
|
|
leftColumn: 25,
|
|
rightColumn: 40,
|
|
bottomRow: 80,
|
|
},
|
|
],
|
|
},
|
|
] as any as CopiedWidgetGroup[];
|
|
expect(
|
|
getNewPositionsForCopiedWidgets(copiedGroups, 10, 40, 20, 10),
|
|
).toEqual([
|
|
{
|
|
id: "1234",
|
|
top: 40,
|
|
left: 10,
|
|
right: 35,
|
|
bottom: 70,
|
|
},
|
|
{
|
|
id: "1235",
|
|
top: 75,
|
|
left: 15,
|
|
right: 30,
|
|
bottom: 110,
|
|
},
|
|
]);
|
|
});
|
|
it("should test getPastePositionMapFromMousePointer", () => {
|
|
const copiedGroups = [
|
|
{
|
|
widgetId: "1234",
|
|
list: [
|
|
{
|
|
topRow: 10,
|
|
leftColumn: 20,
|
|
rightColumn: 45,
|
|
bottomRow: 40,
|
|
},
|
|
],
|
|
},
|
|
{
|
|
widgetId: "1235",
|
|
list: [
|
|
{
|
|
topRow: 45,
|
|
leftColumn: 25,
|
|
rightColumn: 40,
|
|
bottomRow: 80,
|
|
},
|
|
],
|
|
},
|
|
] as any as CopiedWidgetGroup[];
|
|
expect(
|
|
getPastePositionMapFromMousePointer(copiedGroups, 10, 40, 20, 10),
|
|
).toEqual({
|
|
"1234": {
|
|
id: "1234",
|
|
top: 40,
|
|
left: 10,
|
|
right: 35,
|
|
bottom: 70,
|
|
},
|
|
"1235": {
|
|
id: "1235",
|
|
top: 75,
|
|
left: 15,
|
|
right: 30,
|
|
bottom: 110,
|
|
},
|
|
});
|
|
});
|
|
it("should test getReflowedPositions", () => {
|
|
const widgets = {
|
|
"1234": {
|
|
widgetId: "1234",
|
|
topRow: 40,
|
|
leftColumn: 10,
|
|
rightColumn: 35,
|
|
bottomRow: 70,
|
|
} as FlattenedWidgetProps,
|
|
"1233": {
|
|
widgetId: "1233",
|
|
topRow: 45,
|
|
leftColumn: 30,
|
|
rightColumn: 60,
|
|
bottomRow: 70,
|
|
} as FlattenedWidgetProps,
|
|
"1235": {
|
|
widgetId: "1235",
|
|
topRow: 75,
|
|
leftColumn: 15,
|
|
rightColumn: 30,
|
|
bottomRow: 110,
|
|
} as FlattenedWidgetProps,
|
|
};
|
|
|
|
const gridProps = {
|
|
parentRowSpace: 10,
|
|
parentColumnSpace: 10,
|
|
maxGridColumns: 64,
|
|
};
|
|
|
|
const reflowingWidgets = {
|
|
"1234": {
|
|
X: 30,
|
|
width: 200,
|
|
},
|
|
"1235": {
|
|
X: 40,
|
|
width: 250,
|
|
Y: 50,
|
|
height: 250,
|
|
},
|
|
};
|
|
|
|
expect(getReflowedPositions(widgets, gridProps, reflowingWidgets)).toEqual({
|
|
"1234": {
|
|
widgetId: "1234",
|
|
topRow: 40,
|
|
leftColumn: 13,
|
|
rightColumn: 33,
|
|
bottomRow: 70,
|
|
},
|
|
"1233": {
|
|
widgetId: "1233",
|
|
topRow: 45,
|
|
leftColumn: 30,
|
|
rightColumn: 60,
|
|
bottomRow: 70,
|
|
},
|
|
"1235": {
|
|
widgetId: "1235",
|
|
topRow: 80,
|
|
leftColumn: 19,
|
|
rightColumn: 44,
|
|
bottomRow: 105,
|
|
},
|
|
});
|
|
});
|
|
it("should test getWidgetsFromIds", () => {
|
|
const widgets = {
|
|
"1234": {
|
|
widgetId: "1234",
|
|
topRow: 40,
|
|
leftColumn: 10,
|
|
rightColumn: 35,
|
|
bottomRow: 70,
|
|
} as FlattenedWidgetProps,
|
|
"1233": {
|
|
widgetId: "1233",
|
|
topRow: 45,
|
|
leftColumn: 30,
|
|
rightColumn: 60,
|
|
bottomRow: 70,
|
|
} as FlattenedWidgetProps,
|
|
"1235": {
|
|
widgetId: "1235",
|
|
topRow: 75,
|
|
leftColumn: 15,
|
|
rightColumn: 30,
|
|
bottomRow: 110,
|
|
} as FlattenedWidgetProps,
|
|
};
|
|
expect(getWidgetsFromIds(["1235", "1234", "1237"], widgets)).toEqual([
|
|
{
|
|
widgetId: "1235",
|
|
topRow: 75,
|
|
leftColumn: 15,
|
|
rightColumn: 30,
|
|
bottomRow: 110,
|
|
},
|
|
{
|
|
widgetId: "1234",
|
|
topRow: 40,
|
|
leftColumn: 10,
|
|
rightColumn: 35,
|
|
bottomRow: 70,
|
|
},
|
|
]);
|
|
});
|
|
it("should test checkForListWidgetInCopiedWidgets", () => {
|
|
//if copying list widget onto list widget
|
|
expect(
|
|
checkForListWidgetInCopiedWidgets([
|
|
{
|
|
widgetId: "list2",
|
|
parentId: "0",
|
|
list: [
|
|
{
|
|
widgetId: "list2",
|
|
type: "LIST_WIDGET",
|
|
widgetName: "List2",
|
|
parentId: "0",
|
|
renderMode: "CANVAS",
|
|
parentColumnSpace: 2,
|
|
parentRowSpace: 3,
|
|
leftColumn: 2,
|
|
rightColumn: 3,
|
|
topRow: 1,
|
|
bottomRow: 3,
|
|
isLoading: false,
|
|
listData: [],
|
|
version: 16,
|
|
disablePropertyPane: false,
|
|
template: {},
|
|
},
|
|
],
|
|
},
|
|
]),
|
|
).toBe(true);
|
|
|
|
//if copying container widget onto list widget
|
|
expect(
|
|
checkForListWidgetInCopiedWidgets([
|
|
{
|
|
widgetId: "container",
|
|
parentId: "0",
|
|
list: [
|
|
{
|
|
widgetId: "container",
|
|
type: "CONTAINER_WIDGET",
|
|
widgetName: "container",
|
|
parentId: "0",
|
|
renderMode: "CANVAS",
|
|
parentColumnSpace: 2,
|
|
parentRowSpace: 3,
|
|
leftColumn: 2,
|
|
rightColumn: 3,
|
|
topRow: 1,
|
|
bottomRow: 3,
|
|
isLoading: false,
|
|
listData: [],
|
|
version: 16,
|
|
disablePropertyPane: false,
|
|
template: {},
|
|
},
|
|
],
|
|
},
|
|
]),
|
|
).toBe(false);
|
|
});
|
|
});
|
|
|
|
describe("getValueFromTree - ", () => {
|
|
it("should test that value is correctly plucked from a valid path when object keys do not have dot", () => {
|
|
[
|
|
//Path that has a primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
path1: {
|
|
path2: "value",
|
|
},
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path2",
|
|
output: "value",
|
|
defaultValue: "will not be returned",
|
|
},
|
|
//Path that has a non primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
path1: {
|
|
path2: {
|
|
path3: "value",
|
|
},
|
|
},
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path2",
|
|
output: {
|
|
path3: "value",
|
|
},
|
|
defaultValue: "will not be returned",
|
|
},
|
|
//Path that traverse through an array with a primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
path1: [
|
|
{
|
|
path2: "value",
|
|
},
|
|
],
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.0.path2",
|
|
output: "value",
|
|
defaultValue: "will not be returned",
|
|
},
|
|
//Path that traverse through an array with a non primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
path1: [
|
|
{
|
|
path2: {
|
|
path3: "value",
|
|
},
|
|
},
|
|
],
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.0.path2",
|
|
output: {
|
|
path3: "value",
|
|
},
|
|
defaultValue: "will not be returned",
|
|
},
|
|
].forEach((testObj: any) => {
|
|
expect(
|
|
getValueFromTree(testObj.inputObj, testObj.path, testObj.defaultValue),
|
|
).toEqual(testObj.output);
|
|
});
|
|
});
|
|
|
|
it("should test that default value is returned for invalid path when object keys do not have dot", () => {
|
|
[
|
|
//Path that has a primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
path1: {
|
|
path2: "value",
|
|
},
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path4",
|
|
output: "value",
|
|
defaultValue: "will be returned",
|
|
},
|
|
//Path that has a non primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
path1: {
|
|
path2: {
|
|
path3: "value",
|
|
},
|
|
},
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path4.path2",
|
|
output: {
|
|
path3: "value",
|
|
},
|
|
defaultValue: "will be returned",
|
|
},
|
|
//Path that traverse through an array with a primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
path1: [
|
|
{
|
|
path2: "value",
|
|
someotherPath: "testValue",
|
|
},
|
|
],
|
|
},
|
|
path: "path1.1.path2",
|
|
output: "value",
|
|
defaultValue: "will be returned",
|
|
},
|
|
//Path that traverse through an array with a non primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
path1: [
|
|
{
|
|
path2: {
|
|
path3: "value",
|
|
},
|
|
},
|
|
],
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.1.path2",
|
|
output: {
|
|
path3: "value",
|
|
},
|
|
defaultValue: "will be returned",
|
|
},
|
|
].forEach((testObj: any) => {
|
|
expect(
|
|
getValueFromTree(testObj.inputObj, testObj.path, testObj.defaultValue),
|
|
).toEqual(testObj.defaultValue);
|
|
});
|
|
});
|
|
|
|
it("should test that value is correctly plucked from a valid path when object keys have dot", () => {
|
|
[
|
|
//Path that has a primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
"path1.path2.path3": "value",
|
|
},
|
|
path: "path1.path2.path3",
|
|
output: "value",
|
|
defaultValue: "will not be returned",
|
|
},
|
|
//Path that has a primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
"path1.path2": {
|
|
path3: "value",
|
|
},
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path2.path3",
|
|
output: "value",
|
|
defaultValue: "will not be returned",
|
|
},
|
|
//Path that has a primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
path1: {
|
|
"path2.path3": "value",
|
|
},
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path2.path3",
|
|
output: "value",
|
|
defaultValue: "will not be returned",
|
|
},
|
|
//Path that has a primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
path1: {
|
|
path2: {
|
|
"path3.path4": "value",
|
|
},
|
|
},
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path2.path3.path4",
|
|
output: "value",
|
|
defaultValue: "will not be returned",
|
|
},
|
|
//Path that has a primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
"path1.path2": {
|
|
"path3.path4": "value",
|
|
},
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path2.path3.path4",
|
|
output: "value",
|
|
defaultValue: "will not be returned",
|
|
},
|
|
//Path that has a non primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
"path1.path2.path3": {
|
|
path4: "value",
|
|
},
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path2.path3",
|
|
output: {
|
|
path4: "value",
|
|
},
|
|
defaultValue: "will not be returned",
|
|
},
|
|
//Path that has a non primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
path1: {
|
|
"path2.path3": {
|
|
path4: "value",
|
|
},
|
|
},
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path2.path3",
|
|
output: {
|
|
path4: "value",
|
|
},
|
|
defaultValue: "will not be returned",
|
|
},
|
|
//Path that has a non primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
path1: {
|
|
path2: {
|
|
"path3.path4": {
|
|
path5: "value",
|
|
},
|
|
},
|
|
},
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path2.path3.path4",
|
|
output: {
|
|
path5: "value",
|
|
},
|
|
defaultValue: "will not be returned",
|
|
},
|
|
//Path that traverse through an array with a primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
"path1.path2": [
|
|
{
|
|
path3: "value",
|
|
},
|
|
],
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path2.0.path3",
|
|
output: "value",
|
|
defaultValue: "will not be returned",
|
|
},
|
|
//Path that traverse through an array with a primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
"path1.path2": [
|
|
{
|
|
path3: {
|
|
path4: "value",
|
|
},
|
|
},
|
|
],
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path2.0.path3.path4",
|
|
output: "value",
|
|
defaultValue: "will not be returned",
|
|
},
|
|
//Path that traverse through an array with a primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
"path1.path2": [
|
|
{
|
|
"path3.path4": "value",
|
|
},
|
|
],
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path2.0.path3.path4",
|
|
output: "value",
|
|
defaultValue: "will not be returned",
|
|
},
|
|
//Path that traverse through an array with a primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
"path1.path2": [
|
|
{
|
|
path3: [
|
|
{
|
|
path4: "value",
|
|
},
|
|
],
|
|
},
|
|
],
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path2.0.path3.0.path4",
|
|
output: "value",
|
|
defaultValue: "will not be returned",
|
|
},
|
|
//Path that traverse through an array with a non primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
"path1.path2": [
|
|
{
|
|
path3: {
|
|
path4: "value",
|
|
},
|
|
},
|
|
],
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path2.0.path3",
|
|
output: {
|
|
path4: "value",
|
|
},
|
|
defaultValue: "will not be returned",
|
|
},
|
|
//Path that traverse through an array with a non primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
"path1.path2.path3": [
|
|
{
|
|
path4: "value",
|
|
},
|
|
],
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path2.path3.0",
|
|
output: {
|
|
path4: "value",
|
|
},
|
|
defaultValue: "will not be returned",
|
|
},
|
|
//Path that traverse through an array with a non primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
"path1.path2.path3": [
|
|
{
|
|
path4: [
|
|
{
|
|
path5: "value",
|
|
},
|
|
],
|
|
},
|
|
],
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path2.path3.0.path4.0",
|
|
output: {
|
|
path5: "value",
|
|
},
|
|
defaultValue: "will not be returned",
|
|
},
|
|
//Path that traverse through an array with a non primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
"path1.path2.path3": [
|
|
{
|
|
"path4.path5": [
|
|
{
|
|
path6: "value",
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
path: "path1.path2.path3.0.path4.path5.0",
|
|
output: {
|
|
path6: "value",
|
|
},
|
|
defaultValue: "will not be returned",
|
|
},
|
|
{
|
|
inputObj: {
|
|
"path1.path2.path3": [
|
|
{
|
|
".path4.path5": [
|
|
{
|
|
path6: "value",
|
|
},
|
|
],
|
|
},
|
|
],
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path2.path3.0..path4.path5.0",
|
|
output: {
|
|
path6: "value",
|
|
},
|
|
defaultValue: "will not be returned",
|
|
},
|
|
].forEach((testObj: any) => {
|
|
expect(
|
|
getValueFromTree(testObj.inputObj, testObj.path, testObj.defaultValue),
|
|
).toEqual(testObj.output);
|
|
});
|
|
});
|
|
|
|
it("should test that default value is returned for an invalid path when object keys have dot", () => {
|
|
[
|
|
//Path that has a primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
"path1.path2.path3": "value",
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path2.path4",
|
|
output: "value",
|
|
defaultValue: "will be returned",
|
|
},
|
|
//Path that has a primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
"path1.path2": {
|
|
path3: "value",
|
|
},
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path3.path4",
|
|
output: "value",
|
|
defaultValue: "will be returned",
|
|
},
|
|
//Path that has a primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
path1: {
|
|
"path2.path3": "value",
|
|
},
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path2",
|
|
output: "value",
|
|
defaultValue: "will be returned",
|
|
},
|
|
//Path that has a primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
path1: {
|
|
path2: {
|
|
"path3.path4": "value",
|
|
},
|
|
},
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path2.path3",
|
|
output: "value",
|
|
defaultValue: "will be returned",
|
|
},
|
|
//Path that has a primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
"path1.path2": {
|
|
"path3.path4": "value",
|
|
},
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path3.path4",
|
|
output: "value",
|
|
defaultValue: "will be returned",
|
|
},
|
|
//Path that has a non primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
"path1.path2.path3": {
|
|
path4: "value",
|
|
},
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path2",
|
|
output: {
|
|
path4: "value",
|
|
},
|
|
defaultValue: "will be returned",
|
|
},
|
|
//Path that has a non primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
path1: {
|
|
"path2.path3": {
|
|
path4: "value",
|
|
},
|
|
},
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path2",
|
|
output: {
|
|
path4: "value",
|
|
},
|
|
defaultValue: "will be returned",
|
|
},
|
|
//Path that has a non primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
path1: {
|
|
path2: {
|
|
"path3.path4": {
|
|
path5: "value",
|
|
},
|
|
},
|
|
},
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path2.path3.path4",
|
|
output: {
|
|
path5: "value",
|
|
},
|
|
defaultValue: "will be returned",
|
|
},
|
|
//Path that traverse through an array with a primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
"path1.path2": [
|
|
{
|
|
path3: "value",
|
|
},
|
|
],
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path2.1.path3",
|
|
output: "value",
|
|
defaultValue: "will be returned",
|
|
},
|
|
//Path that traverse through an array with a primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
"path1.path2": [
|
|
{
|
|
path3: {
|
|
path4: "value",
|
|
},
|
|
},
|
|
],
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path2.1.path3.path4",
|
|
output: "value",
|
|
defaultValue: "will be returned",
|
|
},
|
|
//Path that traverse through an array with a primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
"path1.path2": [
|
|
{
|
|
"path3.path4": "value",
|
|
},
|
|
],
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path2.1.path3.path4",
|
|
output: "value",
|
|
defaultValue: "will be returned",
|
|
},
|
|
//Path that traverse through an array with a primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
"path1.path2": [
|
|
{
|
|
path3: [
|
|
{
|
|
path4: "value",
|
|
},
|
|
],
|
|
},
|
|
],
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.path2.2.path3.0.path4",
|
|
output: "value",
|
|
defaultValue: "will be returned",
|
|
},
|
|
//Path that traverse through an array with a non primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
"path1.path2": [
|
|
{
|
|
path3: {
|
|
path4: "value",
|
|
},
|
|
},
|
|
],
|
|
someotherPath: "testValue",
|
|
},
|
|
path: "path1.0.path3",
|
|
output: {
|
|
path4: "value",
|
|
},
|
|
defaultValue: "will be returned",
|
|
},
|
|
//Path that traverse through an array with a non primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
"path1.path2.path3": [
|
|
{
|
|
path4: "value",
|
|
},
|
|
],
|
|
},
|
|
path: "path1.path2.0",
|
|
output: {
|
|
path4: "value",
|
|
},
|
|
defaultValue: "will be returned",
|
|
},
|
|
//Path that traverse through an array with a non primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
"path1.path2.path3": [
|
|
{
|
|
path4: [
|
|
{
|
|
path5: "value",
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
path: "path1.path2.0.path4.0",
|
|
output: {
|
|
path5: "value",
|
|
},
|
|
defaultValue: "will be returned",
|
|
},
|
|
//Path that traverse through an array with a non primitive value as leaf node
|
|
{
|
|
inputObj: {
|
|
"path1.path2.path3": [
|
|
{
|
|
"path4.path5": [
|
|
{
|
|
path6: "value",
|
|
},
|
|
],
|
|
},
|
|
],
|
|
},
|
|
path: "path1.path2.path3.0.path4.0",
|
|
output: {
|
|
path6: "value",
|
|
},
|
|
defaultValue: "will be returned",
|
|
},
|
|
].forEach((testObj: any) => {
|
|
expect(
|
|
getValueFromTree(testObj.inputObj, testObj.path, testObj.defaultValue),
|
|
).toEqual(testObj.defaultValue);
|
|
});
|
|
});
|
|
|
|
it("should check that invalid path strucutre should return defaultValue", () => {
|
|
[
|
|
{
|
|
inputObj: {
|
|
path1: {
|
|
path2: {
|
|
path3: "value",
|
|
},
|
|
},
|
|
},
|
|
path: "path1.path2..path3",
|
|
output: {
|
|
path6: "value",
|
|
},
|
|
defaultValue: "will be returned",
|
|
},
|
|
{
|
|
inputObj: {
|
|
path1: {
|
|
path2: [
|
|
{
|
|
path3: "value",
|
|
},
|
|
],
|
|
},
|
|
},
|
|
path: "path1.path2.0..path3",
|
|
output: {
|
|
path6: "value",
|
|
},
|
|
defaultValue: "will be returned",
|
|
},
|
|
].forEach((testObj: any) => {
|
|
expect(
|
|
getValueFromTree(testObj.inputObj, testObj.path, testObj.defaultValue),
|
|
).toEqual(testObj.defaultValue);
|
|
});
|
|
});
|
|
|
|
describe("test resizeCanvasToLowestWidget and resizePublishedMainCanvasToLowestWidget", () => {
|
|
const widgets = {
|
|
0: { bottomRow: 100, children: ["1", "2"], type: "CANVAS_WIDGET" },
|
|
1: {
|
|
bottomRow: 10,
|
|
children: ["3", "4"],
|
|
type: "CANVAS_WIDGET",
|
|
minHeight: 260,
|
|
},
|
|
2: { bottomRow: 35, children: [] },
|
|
3: { bottomRow: 15, children: [] },
|
|
4: { bottomRow: 20, children: [] },
|
|
} as unknown as CanvasWidgetsReduxState;
|
|
|
|
it("should trim canvas close to the lowest bottomRow of it's children widget", () => {
|
|
const currentWidgets = klona(widgets);
|
|
resizePublishedMainCanvasToLowestWidget(currentWidgets);
|
|
expect(currentWidgets["0"].bottomRow).toEqual(400);
|
|
});
|
|
});
|
|
});
|