PromucFlow_constructor/app/client/src/sagas/WidgetOperationUtils.test.ts
rahulramesha 27d5ae8b77
fix: Avoid pasting list widget inside another list widget (#13719)
* fix for stopping list widget from copying onto itself

* remove duplicate comment

* verify selected widgets are not inside list widget if list widget is to be pasted
2022-05-11 14:46:22 +05:30

1744 lines
43 KiB
TypeScript

import { OccupiedSpace } from "constants/CanvasEditorConstants";
import { get } from "lodash";
import { WidgetProps } from "widgets/BaseWidget";
import { FlattenedWidgetProps } from "widgets/constants";
import {
handleIfParentIsListWidgetWhilePasting,
handleSpecificCasesWhilePasting,
doesTriggerPathsContainPropertyPath,
getSelectedWidgetIfPastingIntoListWidget,
checkForListWidgetInCopiedWidgets,
updateListWidgetPropertiesOnChildDelete,
purgeOrphanedDynamicPaths,
getBoundariesFromSelectedWidgets,
getSnappedGrid,
changeIdsOfPastePositions,
getVerticallyAdjustedPositions,
getNewPositionsForCopiedWidgets,
CopiedWidgetGroup,
getPastePositionMapFromMousePointer,
getReflowedPositions,
getWidgetsFromIds,
getValueFromTree,
} 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("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,
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);
});
});
});