Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Anvil on canvas UI tests #35342

Merged
merged 8 commits into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
import { ANVIL_EDITOR_TEST } from "../../../../support/Constants";
import { agHelper, anvilLayout } from "../../../../support/Objects/ObjectsCore";
import { featureFlagIntercept } from "../../../../support/Objects/FeatureFlags";
import { WIDGET } from "../../../../locators/WidgetLocators";
import { anvilLocators } from "../../../../support/Pages/Anvil/Locators";

describe(
`${ANVIL_EDITOR_TEST}: Testing On Canvas UI in Anvil Layout Mode`,
{ tags: ["@tag.Anvil"] },
function () {
before(() => {
// intercept features call for Anvil + WDS tests
featureFlagIntercept({
release_anvil_enabled: true,
});
});
it("1. Widget name component shows and positioned correctly", () => {
// Cleanup the canvas before each test
agHelper.PressEscape();
agHelper.SelectAllWidgets();
agHelper.PressDelete();
ApekshaBhosale marked this conversation as resolved.
Show resolved Hide resolved

// Dnd Button widget into the existing zone
anvilLayout.dnd.DragDropNewAnvilWidgetNVerify(
anvilLocators.WDSBUTTON,
5,
20,
{
skipWidgetSearch: true,
},
);
// Unselect all widgets by clicking on the canvas
agHelper.GetNClick(`${anvilLocators.mainCanvasSelector}`);

// hover over button widget
agHelper.HoverElement(anvilLocators.anvilWidgetNameSelector("Button1"));
// Make sure there is one widget name showing on the canvas
agHelper.AssertElementLength(
anvilLocators.anvilOnCanvasWidgetNameSelector,
1,
);

// Make sure the widget name is positioned above the widget
cy.get(anvilLocators.anvilWidgetNameSelector("Button1")).then(($el) => {
const el = $el[0];
const buttonRect = el.getBoundingClientRect();
cy.get(anvilLocators.anvilOnCanvasWidgetNameSelector).then(
($onCanvasEL) => {
const el = $onCanvasEL[0];
const widgetNameRect = el.getBoundingClientRect();
expect(buttonRect.top).to.equal(widgetNameRect.bottom);
},
);
});
// Dnd Button widget into the existing zone
anvilLayout.dnd.DragDropNewAnvilWidgetNVerify(
anvilLocators.WDSBUTTON,
5,
200,
{
skipWidgetSearch: true,
},
);
// Click on the button widget
agHelper.GetNClick(anvilLocators.anvilWidgetNameSelector("Button1"));
// Make sure there is one widget name showing on the canvas
agHelper.AssertElementLength(
anvilLocators.anvilOnCanvasWidgetNameSelector,
1,
);
// Make sure the widget name is positioned above the widget
cy.get(anvilLocators.anvilWidgetNameSelector("Button1")).then(($el) => {
const el = $el[0];
const buttonRect = el.getBoundingClientRect();
cy.get(anvilLocators.anvilOnCanvasWidgetNameSelector).then(
($onCanvasEL) => {
const el = $onCanvasEL[0];
const widgetNameRect = el.getBoundingClientRect();
expect(buttonRect.top).to.equal(widgetNameRect.bottom);
},
);
});

// Move the widget and check that the widget has moved into a new zone
anvilLayout.dnd.MoveSelectedAnvilWidget(0, 80);
agHelper.AssertAutoSave();
anvilLayout.verifyParentChildRelationship("Zone2", "Button1");
});
it("2. Multiple widget names should show when multiple widgets are selected", () => {
// Cleanup the canvas before each test
agHelper.PressEscape();
agHelper.SelectAllWidgets();
agHelper.PressDelete();

// DnD Switch widget
anvilLayout.dnd.DragDropNewAnvilWidgetNVerify(
anvilLocators.WDSSWITCH,
5,
20,
riodeuno marked this conversation as resolved.
Show resolved Hide resolved
{
skipWidgetSearch: true,
},
);

// DnD Switch widget into the existing zone
anvilLayout.dnd.DragDropNewAnvilWidgetNVerify(
anvilLocators.WDSSWITCH,
5,
20,
{
skipWidgetSearch: true,
dropTargetDetails: {
name: "Zone1",
},
},
);
// Dnd Button widget into the existing zone
anvilLayout.dnd.DragDropNewAnvilWidgetNVerify(
anvilLocators.WDSBUTTON,
5,
20,
{
skipWidgetSearch: true,
dropTargetDetails: {
name: "Zone1",
},
},
);
// Select an existing switch widget
agHelper.GetNClick(
anvilLocators.anvilWidgetNameSelector("Switch1"),
0,
false,
500,
true,
);
// Make sure there are two widget names showing on the canvas
agHelper.AssertElementLength(
anvilLocators.anvilOnCanvasWidgetNameSelector,
2,
);
});
},
);
23 changes: 23 additions & 0 deletions app/client/cypress/support/Pages/Anvil/AnvilDnDHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,27 @@ export class AnvilDnDHelper {
this.agHelper.Sleep(200); //waiting a bit for widget properties to open
});
}

/* If __only one__ widget is selected on the canvas, this function will move the widget to the specified x and y coordinates */
// This function uses the widget name on canvas UI to drag and drop the widget
public MoveSelectedAnvilWidget(
x = 300,
y = 100,
options = {} as DragDropWidgetOptions,
) {
this.agHelper
.AssertElementExist(anvilLocators.mainCanvasSelector)
.then((mainCanvas) => {
const mainCanvasX = mainCanvas.position().left;
const mainCanvasY = mainCanvas.position().top;
const widgetSelector = anvilLocators.anvilOnCanvasWidgetNameSelector;
// perform mouseover to focus the widget before drag to allow dragging
cy.get(widgetSelector).first().trigger("mouseover", { force: true });
cy.get(widgetSelector).first().trigger("dragstart", { force: true });
this.performDnDInAnvil(x + mainCanvasX, y + mainCanvasY, options);
this.agHelper.AssertAutoSave(); //settling time for widget on canvas!
this.agHelper.AssertElementExist(widgetSelector);
this.agHelper.Sleep(200); //waiting a bit for widget properties to open
});
}
}
6 changes: 6 additions & 0 deletions app/client/cypress/support/Pages/Anvil/Locators/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ const anvilModalWidgetSelectors = {
},
};

const anvilOnCanvasUISelectors = {
anvilOnCanvasWidgetNameSelector:
"[data-testid=t--anvil-draggable-widget-name]",
};

// sections and zones based selectors
const anvilSectionAndZonesBasedSelectors = {
anvilZoneDistributionValue: "[data-testid=t--anvil-zone-distribution-value]",
Expand Down Expand Up @@ -68,4 +73,5 @@ export const anvilLocators = {
...anvilWidgetsLocators,
...anvilSectionAndZonesBasedSelectors,
...anvilDnDBasedSelectors,
...anvilOnCanvasUISelectors,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { fireEvent, render, screen } from "@testing-library/react";
import { AnvilWidgetNameComponent } from "./AnvilWidgetNameComponent";
import "@testing-library/jest-dom";
import React from "react";
import { Provider } from "react-redux";
import store from "store";

const handler = {
log: jest.fn(),
};
const logSpy = jest.spyOn(handler, "log");
const props = {
name: "WidgetName",
widgetId: "widgetId",
selectionBGCSSVar: "--something",
selectionColorCSSVar: "--something",
bGCSSVar: "--something",
colorCSSVar: "--something",
disableParentSelection: false,
showError: false,
onDragStart: () => {},
};

describe("AnvilWidgetNameComponent", () => {
it("should show SplitButton", async () => {
render(
<Provider store={store}>
<AnvilWidgetNameComponent {...props} />
</Provider>,
);
expect(screen.getByText("WidgetName")).toBeInTheDocument();
});

it("should show Call the drag event handler on drag", async () => {
const _props = {
...props,
onDragStart: () => {
handler.log("Dragged!");
},
};
render(
<Provider store={store}>
<AnvilWidgetNameComponent {..._props} />
</Provider>,
);

const draggableNameComponent = screen.getByTestId(
"t--anvil-draggable-widget-name",
);
expect(draggableNameComponent).toBeInTheDocument();
fireEvent.dragStart(draggableNameComponent);

expect(logSpy).toHaveBeenCalledWith("Dragged!");
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,19 @@ export function _AnvilWidgetNameComponent(
const { selectWidget } = useWidgetSelection();
const handleSelectParent = useCallback(() => {
parentId && selectWidget(SelectionRequestType.One, [parentId]);
}, [parentId]);
}, [parentId, selectWidget]);

const handleSelectWidget = useCallback(() => {
selectWidget(
SelectionRequestType.One,
[props.widgetId],
NavigationMethod.CanvasClick,
);
}, [props.widgetId]);
}, [props.widgetId, selectWidget]);

const handleDebugClick = useCallback(() => {
dispatch(debugWidget(props.widgetId));
}, [props.widgetId]);
}, [props.widgetId, dispatch]);
/** EO Widget Selection Handlers */

const leftToggle = useMemo(() => {
Expand All @@ -93,7 +93,13 @@ export function _AnvilWidgetNameComponent(
}, [props.showError, handleDebugClick]);

return (
<div draggable onDragStart={props.onDragStart} ref={ref} style={styles}>
<div
data-testid="t--anvil-draggable-widget-name"
draggable
onDragStart={props.onDragStart}
ref={ref}
style={styles}
>
<SplitButton
bGCSSVar={props.bGCSSVar}
colorCSSVar={props.colorCSSVar}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { render, screen } from "@testing-library/react";
import "@testing-library/jest-dom";
import React from "react";
import { SplitButton } from "./SplitButton";
import userEvent from "@testing-library/user-event";

const handler = {
log: jest.fn(),
};
const logSpy = jest.spyOn(handler, "log");

const props = {
text: "widgetName",
onClick: () => handler.log("Clicked!"),
bGCSSVar: "--something",
colorCSSVar: "--something",
leftToggle: {
disable: false,
onClick: () => handler.log("Left Toggle Clicked!"),
title: "Left Toggle Title",
},
rightToggle: {
disable: false,
onClick: () => handler.log("Right Toggle Clicked!"),
title: "Right Toggle Title",
},
};

describe("SplitButton", () => {
it("should show SplitButton", async () => {
render(<SplitButton {...props} />);
expect(screen.getByText("widgetName")).toBeInTheDocument();
expect(screen.queryByTestId("t--splitbutton")).toHaveStyle(
`color: var(--something)`,
);
});

it("should show and call the click event handler on click", async () => {
render(<SplitButton {...props} />);
const clickableButton = screen.getByTestId(
"t--splitbutton-clickable-button",
);
expect(clickableButton).toBeInTheDocument();
await userEvent.click(clickableButton);
expect(logSpy).toHaveBeenCalledWith("Clicked!");
});

it("should show and call the click event handler on click of left toggle", async () => {
render(<SplitButton {...props} />);
const clickableButton = screen.getByTestId("t--splitbutton-left-toggle");
expect(clickableButton).toBeInTheDocument();
await userEvent.click(clickableButton);
expect(logSpy).toHaveBeenCalledWith("Left Toggle Clicked!");
});

it("should show and call the click event handler on click of right toggle", async () => {
render(<SplitButton {...props} />);
const clickableButton = screen.getByTestId("t--splitbutton-right-toggle");
expect(clickableButton).toBeInTheDocument();
await userEvent.click(clickableButton);
expect(logSpy).toHaveBeenCalledWith("Right Toggle Clicked!");
});

it("should hide left and right toggle based on props", async () => {
const _props = {
...props,
leftToggle: { ...props.leftToggle, disable: true },
rightToggle: { ...props.rightToggle, disable: true },
};
render(<SplitButton {..._props} />);
expect(
screen.queryByTestId("t--splitbutton-left-toggle"),
).not.toBeInTheDocument();
expect(
screen.queryByTestId("t--splitbutton-right-toggle"),
).not.toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -117,22 +117,30 @@ export function SplitButton(props: {
$ColorCSSVar={props.colorCSSVar}
$isLeftToggleDisabled={props.leftToggle.disable}
$isRightToggleDisabled={props.rightToggle.disable}
data-testid="t--splitbutton"
>
{!props.leftToggle.disable && (
<span
aria-expanded="false"
aria-haspopup="true"
data-testid="t--splitbutton-left-toggle"
onClick={props.leftToggle.onClick}
title={props.leftToggle.title}
>
<UpArrowSVG />
</span>
)}
<button onClick={props.onClick}>{props.text}</button>
<button
data-testid="t--splitbutton-clickable-button"
onClick={props.onClick}
>
{props.text}
</button>
{!props.rightToggle.disable && (
<span
aria-expanded="false"
aria-haspopup="true"
data-testid="t--splitbutton-right-toggle"
onClick={props.rightToggle.onClick}
title={props.rightToggle.title}
>
Expand Down
Loading
Loading