PromucFlow_constructor/app/client/src/sagas/WidgetSelectUtils.test.ts

219 lines
5.6 KiB
TypeScript
Raw Normal View History

refactor: Widget Selection (#19643) ## Description This change is a refactor of widget selection logic. It consolidates all the business logic to make it easy to maintain. It also improves the performance a bit. It touched a lot of features as we heavily rely on this ``` Select one Select multiple with drag Select multiple with shift Select multiple with cmd/ctrl Selections should be on the same level of hierarchy Unselect all by clicking on the canvas Unselect all by pressing esc Select all with cmd + a Paste in main container Paste in another container Undo Redo Modal Selection Modal child selection Context switching cmd click snipping mode new widget suggestion onboarding ``` > Refactor widget selection logic Fixes #19570 ## Type of change - Refactor ## How Has This Been Tested? All existing tests should pass ### Test Plan > Add Testsmith test cases links that relate to this PR ### Issues raised during DP testing https://github.com/appsmithorg/appsmith/pull/19643#issuecomment-1383570810 https://github.com/appsmithorg/appsmith/pull/19643#issuecomment-1383607820 https://github.com/appsmithorg/appsmith/pull/19643#issuecomment-1385095478 [Bug bash issues](https://www.notion.so/appsmith/610aa302f3e146a7b090b7dc6bc63ef9?v=0d277a9b07bf4aac9d717bcaf138c33a) ## Checklist: ### Dev activity - [ ] My code follows the style guidelines of this project - [ ] I have performed a self-review of my own code - [ ] I have commented my code, particularly in hard-to-understand areas - [ ] I have made corresponding changes to the documentation - [ ] My changes generate no new warnings - [ ] I have added tests that prove my fix is effective or that my feature works - [ ] New and existing unit tests pass locally with my changes - [ ] PR is being merged under a feature flag ### QA activity: - [ ] Test plan has been approved by relevant developers - [ ] Test plan has been peer reviewed by QA - [ ] Cypress test cases have been added and approved by either SDET or manual QA - [ ] Organized project review call with relevant stakeholders after Round 1/2 of QA - [ ] Added Test Plan Approved label after reveiwing all Cypress test
2023-01-28 02:17:06 +00:00
import { CanvasWidgetsReduxState } from "reducers/entityReducers/canvasWidgetsReducer";
import {
deselectAll,
pushPopWidgetSelection,
selectMultipleWidgets,
selectOneWidget,
shiftSelectWidgets,
unselectWidget,
} from "./WidgetSelectUtils";
describe("Wigdet selection methods", () => {
const allWidgetsMock: CanvasWidgetsReduxState = {
widgetId1: {
widgetId: "widgetId1",
parentId: "0",
type: "BUTTON_WIDGET",
widgetName: "Button1",
version: 0,
renderMode: "CANVAS",
parentColumnSpace: 0,
parentRowSpace: 0,
leftColumn: 0,
rightColumn: 0,
topRow: 0,
bottomRow: 0,
isLoading: false,
},
widgetId2: {
widgetId: "widgetId2",
parentId: "0",
type: "BUTTON_WIDGET",
widgetName: "Button2",
version: 0,
renderMode: "CANVAS",
parentColumnSpace: 0,
parentRowSpace: 0,
leftColumn: 0,
rightColumn: 0,
topRow: 0,
bottomRow: 0,
isLoading: false,
},
widgetId3: {
widgetId: "widgetId3",
parentId: "1",
type: "BUTTON_WIDGET",
widgetName: "Button3",
version: 0,
renderMode: "CANVAS",
parentColumnSpace: 0,
parentRowSpace: 0,
leftColumn: 0,
rightColumn: 0,
topRow: 0,
bottomRow: 0,
isLoading: false,
},
};
describe("Deselect", () => {
it("returns an empty selection", () => {
const result = deselectAll([]);
expect(result).toMatchObject({ widgets: [], lastWidgetSelected: "" });
});
it("will error out when request has any widgets", () => {
expect(() => deselectAll(["any"])).toThrow("Wrong payload supplied");
});
});
describe("Select One", () => {
it("returns a selection", () => {
const result = selectOneWidget(["widgetId"]);
expect(result).toMatchObject({
widgets: ["widgetId"],
lastWidgetSelected: "widgetId",
});
});
it("will error out when wrong payload supplied", () => {
expect(() => selectOneWidget([])).toThrow("Wrong payload supplied");
expect(() => selectOneWidget(["widgetId1", "widgetId2"])).toThrow(
"Wrong payload supplied",
);
});
});
describe("Select Multiple", () => {
it("returns a selection", () => {
const result = selectMultipleWidgets(
["widgetId1", "widgetId2"],
allWidgetsMock,
);
expect(result).toMatchObject({
widgets: ["widgetId1", "widgetId2"],
lastWidgetSelected: "widgetId1",
});
});
it("returns no selection if widgets are not siblings", () => {
const result = selectMultipleWidgets(
["widgetId1", "widgetId3"],
allWidgetsMock,
);
expect(result).toBeUndefined();
});
});
describe("Shift Select", () => {
it("forward selection", () => {
const result = shiftSelectWidgets(
["w5"],
["w1", "w2", "w3", "w4", "w5"],
["w1"],
"w1",
);
expect(result).toMatchObject({
widgets: ["w5", "w1", "w2", "w3", "w4"],
lastWidgetSelected: "w5",
});
});
it("backwards selection", () => {
const result = shiftSelectWidgets(
["w2"],
["w1", "w2", "w3", "w4", "w5"],
["w5"],
"w5",
);
expect(result).toMatchObject({
widgets: ["w2", "w5", "w3", "w4"],
lastWidgetSelected: "w2",
});
});
it("appended selection on overlap", () => {
const result = shiftSelectWidgets(
["w1"],
["w1", "w2", "w3", "w4", "w5"],
["w5", "w3"],
"w5",
);
expect(result).toMatchObject({
widgets: ["w1", "w5", "w3", "w2", "w4"],
lastWidgetSelected: "w1",
});
});
it("a single selection when last selected is not a sibling", () => {
const result = shiftSelectWidgets(
["w2"],
["w1", "w2", "w3", "w4", "w5"],
["w7"],
"w7",
);
expect(result).toMatchObject({
widgets: ["w2"],
lastWidgetSelected: "w2",
});
});
it("unselect when already selected", () => {
const result = shiftSelectWidgets(
["w2"],
["w1", "w2", "w3", "w4", "w5"],
["w1", "w2"],
"w2",
);
expect(result).toMatchObject({ widgets: ["w1"], lastWidgetSelected: "" });
});
});
describe("Push Pop Select", () => {
it("adds a selection", () => {
const result = pushPopWidgetSelection(
["w1"],
["w2", "w3"],
["w1", "w2", "w3"],
);
expect(result).toMatchObject({
widgets: ["w2", "w3", "w1"],
lastWidgetSelected: "w1",
});
});
it("removes a selection", () => {
const result = pushPopWidgetSelection(
["w1"],
["w2", "w1"],
["w1", "w2", "w3"],
);
expect(result).toMatchObject({ widgets: ["w2"], lastWidgetSelected: "" });
});
it("removes other if new selection is not a sibling", () => {
const result = pushPopWidgetSelection(["w1"], ["w3", "w4"], ["w1", "w2"]);
expect(result).toMatchObject({
widgets: ["w1"],
lastWidgetSelected: "w1",
});
});
});
describe("UnSelect", () => {
it("returns selection without the widget", () => {
const result = unselectWidget(["w1"], ["w1", "w2", "w3"]);
expect(result).toMatchObject({
widgets: ["w2", "w3"],
lastWidgetSelected: "w2",
});
});
it("returns selection even if not selected", () => {
const result = unselectWidget(["w1"], ["w2", "w3"]);
expect(result).toMatchObject({
widgets: ["w2", "w3"],
lastWidgetSelected: "w2",
});
});
});
});