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 -->
This commit is contained in:
parent
78df6b5e52
commit
dbffbb81c7
|
|
@ -0,0 +1,116 @@
|
|||
import { getCurrentWorkspaceId } from "@appsmith/selectors/selectedWorkspaceSelectors";
|
||||
import type { DragDetails } from "reducers/uiReducers/dragResizeReducer";
|
||||
import type { CallEffect, PutEffect, SelectEffect } from "redux-saga/effects";
|
||||
import { call, select } from "redux-saga/effects";
|
||||
import { addWidgetAndMoveWidgetsSaga } from "sagas/CanvasSagas/DraggingCanvasSagas";
|
||||
import { getDragDetails, getWidgetByName } from "sagas/selectors";
|
||||
import { getCurrentApplicationId } from "selectors/editorSelectors";
|
||||
import { initiateBuildingBlockDropEvent } from "utils/buildingBlockUtils";
|
||||
import {
|
||||
addAndMoveBuildingBlockToCanvasSaga,
|
||||
loadBuildingBlocksIntoApplication,
|
||||
} from "../BuildingBlockAdditionSagas";
|
||||
import { actionPayload, skeletonWidget } from "./fixtures";
|
||||
|
||||
type GeneratorType = Generator<
|
||||
CallEffect | SelectEffect | PutEffect,
|
||||
void,
|
||||
unknown
|
||||
>;
|
||||
|
||||
describe("addAndMoveBuildingBlockToCanvasSaga", () => {
|
||||
it("1. should add a skeleton widget and move existing widgets appropriately", () => {
|
||||
const generator: GeneratorType =
|
||||
addAndMoveBuildingBlockToCanvasSaga(actionPayload);
|
||||
|
||||
// Step 1: select getCurrentApplicationId
|
||||
let result = generator.next();
|
||||
expect(result.value).toEqual(select(getCurrentApplicationId));
|
||||
|
||||
// Mock return value of getCurrentApplicationId
|
||||
const applicationId = "app1";
|
||||
result = generator.next(applicationId);
|
||||
expect(result.value).toEqual(select(getCurrentWorkspaceId));
|
||||
|
||||
// Step 2: select getCurrentWorkspaceId
|
||||
const workspaceId = "workspace1";
|
||||
result = generator.next(workspaceId);
|
||||
expect(result.value).toEqual(select(getDragDetails));
|
||||
|
||||
// Step 3: select getDragDetails
|
||||
const dragDetails: DragDetails = {
|
||||
newWidget: {
|
||||
displayName: "TestWidget",
|
||||
},
|
||||
};
|
||||
result = generator.next(dragDetails);
|
||||
|
||||
// Generating the skeletonWidgetName
|
||||
const buildingblockName = dragDetails.newWidget.displayName;
|
||||
const skeletonWidgetName = `loading_${buildingblockName.toLowerCase().replace(/ /g, "_")}`;
|
||||
|
||||
const updatedActionPayload = {
|
||||
...actionPayload,
|
||||
payload: {
|
||||
...actionPayload.payload,
|
||||
shouldReplay: false,
|
||||
newWidget: {
|
||||
...actionPayload.payload.newWidget,
|
||||
type: "SKELETON_WIDGET",
|
||||
widgetName: skeletonWidgetName,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// Step 4: call addWidgetAndMoveWidgetsSaga
|
||||
expect(result.value).toEqual(
|
||||
call(addWidgetAndMoveWidgetsSaga, updatedActionPayload),
|
||||
);
|
||||
|
||||
// Step 5: call initiateBuildingBlockDropEvent
|
||||
result = generator.next();
|
||||
expect(result.value).toEqual(
|
||||
call(initiateBuildingBlockDropEvent, {
|
||||
applicationId,
|
||||
workspaceId,
|
||||
buildingblockName,
|
||||
}),
|
||||
);
|
||||
|
||||
// Step 6: select getWidgetByName
|
||||
result = generator.next();
|
||||
expect(result.value).toEqual(select(getWidgetByName, skeletonWidgetName));
|
||||
|
||||
result = generator.next(skeletonWidget);
|
||||
|
||||
// Step 7: call loadBuildingBlocksIntoApplication
|
||||
expect(result.value).toEqual(
|
||||
call(
|
||||
loadBuildingBlocksIntoApplication,
|
||||
{
|
||||
...actionPayload.payload.newWidget,
|
||||
widgetId: actionPayload.payload.canvasId,
|
||||
},
|
||||
skeletonWidget.widgetId,
|
||||
),
|
||||
);
|
||||
|
||||
// Complete the generator
|
||||
result = generator.next();
|
||||
expect(result.done).toBe(true);
|
||||
});
|
||||
|
||||
it("2. should handle errors gracefully", () => {
|
||||
const generator: GeneratorType =
|
||||
addAndMoveBuildingBlockToCanvasSaga(actionPayload);
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
import type { CallEffect, PutEffect, SelectEffect } from "redux-saga/effects";
|
||||
import { call, select } from "redux-saga/effects";
|
||||
import {
|
||||
addBuildingBlockToCanvasSaga,
|
||||
loadBuildingBlocksIntoApplication,
|
||||
} from "../BuildingBlockAdditionSagas";
|
||||
import type { ReduxAction } from "@appsmith/constants/ReduxActionConstants";
|
||||
import { getCurrentWorkspaceId } from "@appsmith/selectors/selectedWorkspaceSelectors";
|
||||
import type { WidgetAddChild } from "actions/pageActions";
|
||||
import { addChildSaga } from "sagas/WidgetAdditionSagas";
|
||||
import { getDragDetails, getWidgetByName } from "sagas/selectors";
|
||||
import { getCurrentApplicationId } from "selectors/editorSelectors";
|
||||
import { initiateBuildingBlockDropEvent } from "utils/buildingBlockUtils";
|
||||
import { addEntityAction, skeletonWidget } from "./fixtures";
|
||||
|
||||
type GeneratorType = Generator<
|
||||
CallEffect | SelectEffect | PutEffect,
|
||||
void,
|
||||
unknown
|
||||
>;
|
||||
|
||||
describe("addBuildingBlockToCanvasSaga", () => {
|
||||
it("1. should add a skeleton widget and initiate a building block drop", () => {
|
||||
const generator: GeneratorType =
|
||||
addBuildingBlockToCanvasSaga(addEntityAction);
|
||||
|
||||
// Step 1: select getCurrentApplicationId
|
||||
let result = generator.next();
|
||||
expect(result.value).toEqual(select(getCurrentApplicationId));
|
||||
|
||||
// Mock return value of getCurrentApplicationId
|
||||
const applicationId = "app1";
|
||||
result = generator.next(applicationId);
|
||||
expect(result.value).toEqual(select(getCurrentWorkspaceId));
|
||||
|
||||
// Step 2: select getCurrentWorkspaceId
|
||||
const workspaceId = "workspace1";
|
||||
result = generator.next(workspaceId);
|
||||
expect(result.value).toEqual(select(getDragDetails));
|
||||
|
||||
// Step 3: select getDragDetails
|
||||
const dragDetails = {
|
||||
newWidget: {
|
||||
displayName: "TestWidget",
|
||||
},
|
||||
};
|
||||
result = generator.next(dragDetails);
|
||||
|
||||
// Generating the skeletonWidgetName
|
||||
const buildingblockName = dragDetails.newWidget.displayName;
|
||||
const skeletonWidgetName = `loading_${buildingblockName.toLowerCase().replace(/ /g, "_")}`;
|
||||
|
||||
const addSkeletonWidgetAction: ReduxAction<
|
||||
WidgetAddChild & { shouldReplay: boolean }
|
||||
> = {
|
||||
...addEntityAction,
|
||||
payload: {
|
||||
...addEntityAction.payload,
|
||||
type: "SKELETON_WIDGET",
|
||||
widgetName: skeletonWidgetName,
|
||||
shouldReplay: false,
|
||||
},
|
||||
};
|
||||
|
||||
// Step 4: call initiateBuildingBlockDropEvent
|
||||
expect(result.value).toEqual(
|
||||
call(initiateBuildingBlockDropEvent, {
|
||||
applicationId,
|
||||
workspaceId,
|
||||
buildingblockName,
|
||||
}),
|
||||
);
|
||||
|
||||
// Step 5: call addChildSaga
|
||||
result = generator.next();
|
||||
expect(result.value).toEqual(call(addChildSaga, addSkeletonWidgetAction));
|
||||
|
||||
// Step 6: select getWidgetByName
|
||||
result = generator.next();
|
||||
expect(result.value).toEqual(select(getWidgetByName, skeletonWidgetName));
|
||||
|
||||
result = generator.next(skeletonWidget);
|
||||
|
||||
// Step 7: call loadBuildingBlocksIntoApplication
|
||||
expect(result.value).toEqual(
|
||||
call(
|
||||
loadBuildingBlocksIntoApplication,
|
||||
addEntityAction.payload,
|
||||
skeletonWidget.widgetId,
|
||||
),
|
||||
);
|
||||
|
||||
// Complete the generator
|
||||
result = generator.next();
|
||||
expect(result.done).toBe(true);
|
||||
});
|
||||
|
||||
it("2. should handle errors gracefully", () => {
|
||||
const generator: GeneratorType =
|
||||
addBuildingBlockToCanvasSaga(addEntityAction);
|
||||
|
||||
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);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -5,7 +5,7 @@ import type {
|
|||
SelectEffect,
|
||||
} from "redux-saga/effects";
|
||||
import { call, select } from "redux-saga/effects";
|
||||
import { pasteBuildingBlockWidgetsSaga } from "./BuildingBlockAdditionSagas";
|
||||
import { pasteBuildingBlockWidgetsSaga } from "../BuildingBlockAdditionSagas";
|
||||
import { getCopiedWidgets } from "utils/storage";
|
||||
import type { FlexLayer } from "layoutSystems/autolayout/utils/types";
|
||||
import { getWidgets } from "sagas/selectors";
|
||||
|
|
@ -21,7 +21,7 @@ import {
|
|||
copiedWidgets,
|
||||
leftMostWidget,
|
||||
topMostWidget,
|
||||
} from "./pasteWidgetAddition.fixture";
|
||||
} from "../pasteWidgetAddition.fixture";
|
||||
import type { NewPastePositionVariables } from "sagas/WidgetOperationUtils";
|
||||
|
||||
// Mock data for testing
|
||||
103
app/client/src/sagas/BuildingBlockSagas/tests/fixtures.ts
Normal file
103
app/client/src/sagas/BuildingBlockSagas/tests/fixtures.ts
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
import type { WidgetAddChild } from "actions/pageActions";
|
||||
import type { ReduxAction } from "@appsmith/constants/ReduxActionConstants";
|
||||
import type { WidgetDraggingUpdateParams } from "layoutSystems/common/canvasArenas/ArenaTypes";
|
||||
import type { FlattenedWidgetProps } from "reducers/entityReducers/canvasWidgetsReducer";
|
||||
|
||||
// Mock return value of getWidgetByName
|
||||
export const skeletonWidget: FlattenedWidgetProps = {
|
||||
needsErrorInfo: false,
|
||||
mobileBottomRow: 69,
|
||||
widgetName: "loading_table_lookup",
|
||||
displayName: "Skeleton",
|
||||
topRow: 6,
|
||||
bottomRow: 69,
|
||||
parentRowSpace: 10,
|
||||
type: "SKELETON_WIDGET",
|
||||
hideCard: true,
|
||||
mobileRightColumn: 46,
|
||||
parentColumnSpace: 13.40625,
|
||||
leftColumn: 15,
|
||||
dynamicBindingPathList: [],
|
||||
key: "k0u7iidinm",
|
||||
isDeprecated: false,
|
||||
rightColumn: 46,
|
||||
widgetId: "ndw2y4zajv",
|
||||
onCanvasUI: {
|
||||
selectionBGCSSVar: "--on-canvas-ui-widget-selection",
|
||||
focusBGCSSVar: "--on-canvas-ui-widget-focus",
|
||||
selectionColorCSSVar: "--on-canvas-ui-widget-focus",
|
||||
focusColorCSSVar: "--on-canvas-ui-widget-selection",
|
||||
disableParentSelection: false,
|
||||
},
|
||||
isVisible: true,
|
||||
version: 1,
|
||||
parentId: "0",
|
||||
isLoading: false,
|
||||
renderMode: "CANVAS",
|
||||
mobileTopRow: 6,
|
||||
mobileLeftColumn: 15,
|
||||
};
|
||||
|
||||
export const actionPayload: ReduxAction<{
|
||||
newWidget: WidgetAddChild;
|
||||
draggedBlocksToUpdate: WidgetDraggingUpdateParams[];
|
||||
canvasId: string;
|
||||
}> = {
|
||||
type: "WIDGETS_ADD_CHILD_AND_MOVE",
|
||||
payload: {
|
||||
newWidget: {
|
||||
type: "BUILDING_BLOCK",
|
||||
leftColumn: 21,
|
||||
topRow: 147,
|
||||
columns: 31,
|
||||
rows: 63,
|
||||
parentRowSpace: 10,
|
||||
parentColumnSpace: 13.40625,
|
||||
newWidgetId: "9lg3rb7mi2",
|
||||
widgetId: "0",
|
||||
tabId: "0",
|
||||
},
|
||||
draggedBlocksToUpdate: [
|
||||
{
|
||||
left: 388.78125,
|
||||
top: 1430,
|
||||
width: 214.5,
|
||||
height: 40,
|
||||
columnWidth: 13.40625,
|
||||
rowHeight: 10,
|
||||
widgetId: "6b6kauwlxa",
|
||||
isNotColliding: true,
|
||||
type: "BUTTON_WIDGET",
|
||||
updateWidgetParams: {
|
||||
operation: "MOVE",
|
||||
widgetId: "6b6kauwlxa",
|
||||
payload: {
|
||||
leftColumn: 29,
|
||||
topRow: 143,
|
||||
bottomRow: 147,
|
||||
rightColumn: 45,
|
||||
parentId: "0",
|
||||
newParentId: "0",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
canvasId: "0",
|
||||
},
|
||||
};
|
||||
|
||||
export const addEntityAction: ReduxAction<WidgetAddChild> = {
|
||||
type: "WIDGET_ADD_CHILD",
|
||||
payload: {
|
||||
widgetId: "0",
|
||||
type: "BUILDING_BLOCK",
|
||||
leftColumn: 15,
|
||||
topRow: 6,
|
||||
columns: 31,
|
||||
rows: 63,
|
||||
parentRowSpace: 10,
|
||||
parentColumnSpace: 13.40625,
|
||||
newWidgetId: "ndw2y4zajv",
|
||||
tabId: "0",
|
||||
},
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user