## Description Ad unit tests for adding and moving building blocks saga. Fixes #34146 ## Automation /ok-to-test tags="@tag.Sanity" ### 🔍 Cypress test results <!-- This is an auto-generated comment: Cypress test results --> > [!TIP] > 🟢 🟢 🟢 All cypress tests have passed! 🎉 🎉 🎉 > Workflow run: <https://github.com/appsmithorg/appsmith/actions/runs/9494392536> > Commit: c6b9b1b679f284458cc6500729408ddb015adb62 > Cypress dashboard url: <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=9494392536&attempt=1" target="_blank">Click here!</a> <!-- end of auto-generated comment: Cypress test results --> ## Communication Should the DevRel and Marketing teams inform users about this change? - [ ] Yes - [x] No <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Tests** - Added comprehensive tests for adding and moving building blocks on the canvas. - Updated import paths for consistency in test files. - Introduced new test suites for sagas handling building block operations. - **New Fixtures** - Added mock data and constants for testing building block functionalities. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
156 lines
4.5 KiB
TypeScript
156 lines
4.5 KiB
TypeScript
import type {
|
|
AllEffect,
|
|
CallEffect,
|
|
PutEffect,
|
|
SelectEffect,
|
|
} from "redux-saga/effects";
|
|
import { call, select } from "redux-saga/effects";
|
|
import { pasteBuildingBlockWidgetsSaga } from "../BuildingBlockAdditionSagas";
|
|
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,
|
|
} from "../pasteWidgetAddition.fixture";
|
|
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 };
|
|
it("1. should handle pasting into a valid parent widget", () => {
|
|
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 },
|
|
parentWidgetId,
|
|
),
|
|
);
|
|
|
|
// 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++) {
|
|
result = generator.next("0123456789abcdef00000000");
|
|
}
|
|
|
|
result = generator.next();
|
|
expect(result.done).toBe(true);
|
|
});
|
|
|
|
it("2. should handle errors gracefully", () => {
|
|
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);
|
|
}
|
|
});
|
|
});
|