-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: Anvil on canvas UI tests (#35342)
## Description ### Unit `index.test.tsx` - (Main connected component that uses floating ui) - [x] Test rendering of widget name component (floating-ui) based on "select", "focus" and "none" states from redux selector - [x] Test rendering of widget name component (floating-ui) based on error count from redux selector `AnvilWidgetNameComponent.test.tsx` (Standalone component that renders content for floating ui to use) - [x] Test rendering of standalone widget name component based on props. - [x] Test calling of `onDragStart` callback from the standalone widget name component. `SplitButton.test.tsx` (Low level UI component - child of `AnvilWidgetNameComponent`) - [x] Test left and right toggle click triggers - [x] Test if component handles props correctly ### E2E - [x] Test Dragging via widget name component - [x] Test widget name component when multiple widgets are selected - [x] Test Hover and Selection to show widget name component Fixes #33979 ## Automation /ok-to-test tags="@tag.All" ### 🔍 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/10349986042> > Commit: 8c9e6b9 > <a href="https://internal.appsmith.com/app/cypress-dashboard/rundetails-65890b3c81d7400d08fa9ee5?branch=master&workflowId=10349986042&attempt=1" target="_blank">Cypress dashboard</a>. > Tags: `@tag.All` > Spec: > <hr>Mon, 12 Aug 2024 11:13:52 UTC <!-- 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 ## Summary by CodeRabbit - **New Features** - Introduced a comprehensive suite of end-to-end tests for the Anvil editor's UI in canvas layout mode. - Enhanced flexibility in widget manipulation on the canvas with an updated method. - Expanded selectors for more precise targeting of UI components. - Added unit tests for the `AnvilWidgetNameComponent` and `SplitButton` components to ensure expected functionality. - **Bug Fixes** - Improved responsiveness of the `AnvilWidgetName` component to state changes. - **Documentation** - Updated comments and structure for clarity in test scenarios and component functionality. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
- Loading branch information
Showing
9 changed files
with
513 additions
and
14 deletions.
There are no files selected for viewing
143 changes: 143 additions & 0 deletions
143
app/client/cypress/e2e/Regression/ClientSide/Anvil/AnvilOnCanvasUI_spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
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", () => { | ||
const horizontalPixelOnCanvasMouseMovement = 5; | ||
let verticalPixelOnCanvasMouseMovement = 20; | ||
// Dnd Button widget into the existing zone | ||
anvilLayout.dnd.DragDropNewAnvilWidgetNVerify( | ||
anvilLocators.WDSBUTTON, | ||
horizontalPixelOnCanvasMouseMovement, | ||
verticalPixelOnCanvasMouseMovement, | ||
{ | ||
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); | ||
}, | ||
); | ||
}); | ||
verticalPixelOnCanvasMouseMovement = 200; | ||
// Dnd Button widget into the existing zone | ||
anvilLayout.dnd.DragDropNewAnvilWidgetNVerify( | ||
anvilLocators.WDSBUTTON, | ||
horizontalPixelOnCanvasMouseMovement, | ||
verticalPixelOnCanvasMouseMovement, | ||
{ | ||
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.MoveAnvilWidget(undefined, 0, 80); | ||
agHelper.AssertAutoSave(); | ||
anvilLayout.verifyParentChildRelationship("Zone2", "Button1"); | ||
}); | ||
it("2. Multiple widget names should show when multiple widgets are selected", () => { | ||
// Cleanup the canvas before test | ||
agHelper.PressEscape(); | ||
agHelper.SelectAllWidgets(); | ||
agHelper.PressDelete(); | ||
const horizontalPixelOnCanvasMouseMovement = 5; | ||
const verticalPixelOnCanvasMouseMovement = 20; | ||
// DnD Switch widget | ||
anvilLayout.dnd.DragDropNewAnvilWidgetNVerify( | ||
anvilLocators.WDSSWITCH, | ||
horizontalPixelOnCanvasMouseMovement, | ||
verticalPixelOnCanvasMouseMovement, | ||
{ | ||
skipWidgetSearch: true, | ||
}, | ||
); | ||
|
||
// DnD Switch widget into the existing zone | ||
anvilLayout.dnd.DragDropNewAnvilWidgetNVerify( | ||
anvilLocators.WDSSWITCH, | ||
horizontalPixelOnCanvasMouseMovement, | ||
verticalPixelOnCanvasMouseMovement, | ||
{ | ||
skipWidgetSearch: true, | ||
dropTargetDetails: { | ||
name: "Zone1", | ||
}, | ||
}, | ||
); | ||
// Dnd Button widget into the existing zone | ||
anvilLayout.dnd.DragDropNewAnvilWidgetNVerify( | ||
anvilLocators.WDSBUTTON, | ||
horizontalPixelOnCanvasMouseMovement, | ||
verticalPixelOnCanvasMouseMovement, | ||
{ | ||
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, | ||
); | ||
}); | ||
}, | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
55 changes: 55 additions & 0 deletions
55
app/client/src/layoutSystems/anvil/editor/AnvilWidgetName/AnvilWidgetNameComponent.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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!"); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
78 changes: 78 additions & 0 deletions
78
app/client/src/layoutSystems/anvil/editor/AnvilWidgetName/SplitButton.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
}); | ||
}); |
Oops, something went wrong.