2024-05-27 06:41:59 +00:00
|
|
|
import type {
|
|
|
|
|
AllEffect,
|
|
|
|
|
CallEffect,
|
|
|
|
|
PutEffect,
|
|
|
|
|
SelectEffect,
|
|
|
|
|
} from "redux-saga/effects";
|
|
|
|
|
import { call, select } from "redux-saga/effects";
|
2024-06-13 07:46:45 +00:00
|
|
|
import { pasteBuildingBlockWidgetsSaga } from "../BuildingBlockAdditionSagas";
|
2024-05-27 06:41:59 +00:00
|
|
|
import { getCopiedWidgets } from "utils/storage";
|
|
|
|
|
import type { FlexLayer } from "layoutSystems/autolayout/utils/types";
|
|
|
|
|
import { getWidgets } from "sagas/selectors";
|
|
|
|
|
import {
|
|
|
|
|
getCanvasWidth,
|
|
|
|
|
getIsAutoLayoutMobileBreakPoint,
|
|
|
|
|
} from "selectors/editorSelectors";
|
|
|
|
|
import { getNewPositions } from "sagas/PasteWidgetUtils";
|
|
|
|
|
import { executeWidgetBlueprintBeforeOperations } from "sagas/WidgetBlueprintSagas";
|
|
|
|
|
import { BlueprintOperationTypes } from "WidgetProvider/constants";
|
|
|
|
|
import { cloneDeep } from "lodash";
|
|
|
|
|
import {
|
|
|
|
|
copiedWidgets,
|
|
|
|
|
leftMostWidget,
|
|
|
|
|
topMostWidget,
|
2024-06-13 07:46:45 +00:00
|
|
|
} from "../pasteWidgetAddition.fixture";
|
2024-05-27 06:41:59 +00:00
|
|
|
import type { NewPastePositionVariables } from "sagas/WidgetOperationUtils";
|
|
|
|
|
|
|
|
|
|
// Mock data for testing
|
|
|
|
|
const gridPosition = { top: 50, left: 500 };
|
|
|
|
|
const parentWidgetId = "parentWidgetId";
|
|
|
|
|
|
|
|
|
|
const totalWidth = 31;
|
|
|
|
|
const flexLayers: FlexLayer[] = [];
|
|
|
|
|
type GeneratorType = Generator<
|
|
|
|
|
| CallEffect<NewPastePositionVariables>
|
|
|
|
|
| SelectEffect
|
|
|
|
|
| Promise<any>
|
|
|
|
|
| CallEffect<void>
|
|
|
|
|
| AllEffect<any>
|
|
|
|
|
| PutEffect<any>,
|
|
|
|
|
void,
|
|
|
|
|
unknown
|
|
|
|
|
>;
|
|
|
|
|
|
|
|
|
|
describe("pasteBuildingBlockWidgetsSaga", () => {
|
|
|
|
|
const copiedWidgetsResponse = { widgets: copiedWidgets, flexLayers };
|
2024-06-05 07:46:49 +00:00
|
|
|
it("1. should handle pasting into a valid parent widget", () => {
|
2024-05-27 06:41:59 +00:00
|
|
|
const generator: GeneratorType = pasteBuildingBlockWidgetsSaga(
|
|
|
|
|
gridPosition,
|
|
|
|
|
parentWidgetId,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Step 1: call getCopiedWidgets()
|
|
|
|
|
let result = generator.next();
|
|
|
|
|
expect(result.value).toEqual(getCopiedWidgets());
|
|
|
|
|
|
|
|
|
|
// Step 2: select getWidgets
|
|
|
|
|
result = generator.next(copiedWidgetsResponse);
|
|
|
|
|
expect(result.value).toEqual(select(getWidgets));
|
|
|
|
|
|
|
|
|
|
// Step 3: select getIsAutoLayoutMobileBreakPoint
|
|
|
|
|
const initialCanvasWidgets = {}; // Mock initial canvas widgets
|
|
|
|
|
result = generator.next(initialCanvasWidgets);
|
|
|
|
|
expect(result.value).toEqual(select(getIsAutoLayoutMobileBreakPoint));
|
|
|
|
|
|
|
|
|
|
// Step 4: select getCanvasWidth
|
|
|
|
|
result = generator.next(false); // Assume it's not the mobile breakpoint
|
|
|
|
|
expect(result.value).toEqual(select(getCanvasWidth));
|
|
|
|
|
|
|
|
|
|
// Mock data for the rest of the saga generator
|
|
|
|
|
const mainCanvasWidth = 1200;
|
|
|
|
|
const boundaryWidgets = {
|
|
|
|
|
leftMostWidget,
|
|
|
|
|
topMostWidget,
|
|
|
|
|
totalWidth,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const newPastingPositionMap = {
|
|
|
|
|
ppci5prygm: {
|
|
|
|
|
id: "ppci5prygm",
|
|
|
|
|
top: 1,
|
|
|
|
|
left: 10,
|
|
|
|
|
bottom: 65,
|
|
|
|
|
right: 41,
|
|
|
|
|
type: "CONTAINER_WIDGET",
|
|
|
|
|
},
|
|
|
|
|
};
|
|
|
|
|
const reflowedMovementMap = undefined;
|
|
|
|
|
const gridProps = {
|
|
|
|
|
parentColumnSpace: 12.828080177307129,
|
|
|
|
|
parentRowSpace: 10,
|
|
|
|
|
maxGridColumns: 64,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Step 5: compute getNewPositions
|
|
|
|
|
result = generator.next(mainCanvasWidth);
|
|
|
|
|
expect(result.value).toEqual(
|
|
|
|
|
call(
|
|
|
|
|
getNewPositions,
|
|
|
|
|
copiedWidgets,
|
|
|
|
|
boundaryWidgets.totalWidth,
|
|
|
|
|
boundaryWidgets.topMostWidget.topRow,
|
|
|
|
|
boundaryWidgets.leftMostWidget.leftColumn,
|
|
|
|
|
{ gridPosition },
|
2024-06-05 07:46:49 +00:00
|
|
|
parentWidgetId,
|
2024-05-27 06:41:59 +00:00
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Step 6: execute blueprint operations before paste
|
|
|
|
|
for (const widgetGroup of copiedWidgetsResponse.widgets) {
|
|
|
|
|
result = generator.next({
|
|
|
|
|
gridProps,
|
|
|
|
|
newPastingPositionMap,
|
|
|
|
|
reflowedMovementMap,
|
|
|
|
|
});
|
|
|
|
|
expect(result.value).toEqual(
|
|
|
|
|
call(
|
|
|
|
|
executeWidgetBlueprintBeforeOperations,
|
|
|
|
|
BlueprintOperationTypes.BEFORE_PASTE,
|
|
|
|
|
{
|
|
|
|
|
parentId: parentWidgetId,
|
|
|
|
|
widgetId: widgetGroup.widgetId,
|
|
|
|
|
widgets: initialCanvasWidgets,
|
|
|
|
|
widgetType: widgetGroup.list[0].type,
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const newWidgetList = cloneDeep(copiedWidgets[0].list);
|
|
|
|
|
|
|
|
|
|
// Step 7: mock the entire copied widget handling logic
|
|
|
|
|
for (let i = 0; i < newWidgetList.length; i++) {
|
2024-06-11 09:44:54 +00:00
|
|
|
result = generator.next("0123456789abcdef00000000");
|
2024-05-27 06:41:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result = generator.next();
|
|
|
|
|
expect(result.done).toBe(true);
|
|
|
|
|
});
|
|
|
|
|
|
2024-06-05 07:46:49 +00:00
|
|
|
it("2. should handle errors gracefully", () => {
|
2024-05-27 06:41:59 +00:00
|
|
|
const generator: GeneratorType = pasteBuildingBlockWidgetsSaga(
|
|
|
|
|
{ left: 0, top: 0 },
|
|
|
|
|
"testParentId",
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
generator.next();
|
|
|
|
|
// Introduce an error by throwing one manually
|
|
|
|
|
const error = new Error("Something went wrong");
|
|
|
|
|
try {
|
|
|
|
|
generator.throw(error);
|
|
|
|
|
} catch (err) {
|
|
|
|
|
expect(err).toBe(error);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
});
|