PromucFlow_constructor/app/client/src/sagas/BuildingBlockSagas/tests/PasteBuildingBlockWidgetSaga.test.ts
Jacques Ikot dbffbb81c7
feat: add tests for AddAndMove and AddBuildingBlocks to canvas (#34215)
## 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 -->
2024-06-13 08:46:45 +01:00

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);
}
});
});