diff --git a/cypress/components/icon-button/icon-button.cy.tsx b/cypress/components/icon-button/icon-button.cy.tsx deleted file mode 100644 index f5c2cc94a7..0000000000 --- a/cypress/components/icon-button/icon-button.cy.tsx +++ /dev/null @@ -1,155 +0,0 @@ -import React from "react"; -import { IconButtonProps } from "components/icon-button"; -import CypressMountWithProviders from "../../support/component-helper/cypress-mount"; -import { icon } from "../../locators"; -import { IconButtonComponent } from "../../../src/components/icon-button/icon-button-test.stories"; -import { CHARACTERS } from "../../support/component-helper/constants"; -import { keyCode } from "../../support/helper"; - -const keyToTrigger = ["Space", "Enter"] as const; - -context("Tests for IconButton component", () => { - describe("when focused", () => { - it("should have the expected styling when the focusRedesignOptOut is false", () => { - CypressMountWithProviders( - - ); - - icon() - .parent() - .focus() - .should( - "have.css", - "box-shadow", - "rgb(255, 188, 25) 0px 0px 0px 3px, rgba(0, 0, 0, 0.9) 0px 0px 0px 6px" - ) - .and("have.css", "outline", "rgba(0, 0, 0, 0) solid 3px"); - }); - - it("should have the expected styling when the focusRedesignOptOut is true", () => { - CypressMountWithProviders( - , - undefined, - undefined, - { - focusRedesignOptOut: true, - } - ); - icon() - .parent() - .focus() - .should("have.css", "outline", "rgb(255, 188, 25) solid 3px"); - }); - }); - describe("check props for IconButton component", () => { - it("should render IconButton with aria-label prop", () => { - CypressMountWithProviders( - - ); - - icon() - .parent() - .should("have.attr", "aria-label", CHARACTERS.STANDARD) - .and("be.visible"); - }); - - it("should render IconButton with children prop", () => { - CypressMountWithProviders(); - - icon().should("be.visible"); - }); - - it("should render IconButton with disabled prop", () => { - CypressMountWithProviders(); - - icon().parent().should("be.disabled").and("have.attr", "disabled"); - }); - }); - - describe("check events for IconButton component", () => { - it("should call onBlur callback when a blur event is triggered", () => { - const callback: IconButtonProps["onBlur"] = cy.stub().as("onBlur"); - CypressMountWithProviders(); - - icon().parent().focus().blur(); - cy.get("@onBlur").should("have.been.calledOnce"); - }); - - it("should call onFocus callback when a focus event is triggered", () => { - const callback: IconButtonProps["onFocus"] = cy.stub().as("onFocus"); - CypressMountWithProviders(); - - icon().parent().focus(); - cy.get("@onFocus").should("have.been.calledOnce"); - }); - - it("should call onMouseEnter callback when a mouseover event is triggered", () => { - const callback: IconButtonProps["onMouseEnter"] = cy - .stub() - .as("onMouseEnter"); - CypressMountWithProviders( - - ); - - icon().parent().trigger("mouseover"); - cy.get("@onMouseEnter").should("have.been.calledOnce"); - }); - - it("should call onMouseLeave callback when a mouseout event is triggered", () => { - const callback: IconButtonProps["onMouseLeave"] = cy - .stub() - .as("onMouseLeave"); - CypressMountWithProviders( - - ); - - icon().parent().trigger("mouseover").trigger("mouseout"); - cy.get("@onMouseLeave").should("have.been.calledOnce"); - }); - - it("should call onClick callback when a click event is triggered", () => { - const callback: IconButtonProps["onClick"] = cy.stub().as("onClick"); - CypressMountWithProviders(); - - icon().parent().click(); - cy.get("@onClick").should("have.been.calledOnce"); - }); - - it.each([...keyToTrigger])( - "should call onClick callback when a keydown event is triggered with %s", - (key) => { - const callback: IconButtonProps["onClick"] = cy.stub().as("onClick"); - CypressMountWithProviders(); - - icon().parent().trigger("keydown", keyCode(key)); - cy.get("@onClick").should("have.been.calledOnce"); - } - ); - }); - - describe("check accessibility tests for IconButton component", () => { - it("should pass accessibility tests for aria-label prop", () => { - CypressMountWithProviders( - - ); - cy.checkAccessibility(); - }); - - it("should pass accessibility tests for children prop", () => { - CypressMountWithProviders(); - cy.checkAccessibility(); - }); - - it("should pass accessibility tests for disabled prop", () => { - CypressMountWithProviders(); - cy.checkAccessibility(); - }); - }); - - it("render with the expected border radius when roundness is %s", () => { - CypressMountWithProviders(); - - icon().parent().focus(); - icon().parent().should("have.css", "border-radius", "4px"); - }); -}); diff --git a/playwright/components/index.ts b/playwright/components/index.ts index d98765264b..2949a58c58 100644 --- a/playwright/components/index.ts +++ b/playwright/components/index.ts @@ -11,6 +11,7 @@ import { STICKY_FOOTER, COMMMON_DATA_ELEMENT_INPUT, PORTAL, + BUTTON, } from "./locators"; export const icon = (page: Page) => { @@ -25,6 +26,10 @@ export const commonDataElementInputPreview = (page: Page) => { return page.locator(COMMMON_DATA_ELEMENT_INPUT); }; +export const button = (page: Page) => { + return page.locator(BUTTON); +}; + export const closeIconButton = (page: Page) => { return page.locator(CLOSE_ICON_BUTTON); }; diff --git a/src/components/icon-button/component.test-pw.tsx b/src/components/icon-button/component.test-pw.tsx new file mode 100644 index 0000000000..18683a59d4 --- /dev/null +++ b/src/components/icon-button/component.test-pw.tsx @@ -0,0 +1,13 @@ +import React from "react"; +import IconButton, { IconButtonProps } from "."; +import Icon from "../icon"; + +const IconButtonComponent = (props: Partial) => { + return ( + {}} {...props}> + + + ); +}; + +export default IconButtonComponent; diff --git a/src/components/icon-button/icon-button-test.stories.tsx b/src/components/icon-button/icon-button-test.stories.tsx index c0ef019e97..1852d0d483 100644 --- a/src/components/icon-button/icon-button-test.stories.tsx +++ b/src/components/icon-button/icon-button-test.stories.tsx @@ -22,11 +22,3 @@ export const Default = (props: IconButtonProps) => { }; Default.storyName = "default"; - -export const IconButtonComponent = (props: Partial) => { - return ( - {}} {...props}> - - - ); -}; diff --git a/src/components/icon-button/icon-button.pw.tsx b/src/components/icon-button/icon-button.pw.tsx new file mode 100644 index 0000000000..e32dd4b970 --- /dev/null +++ b/src/components/icon-button/icon-button.pw.tsx @@ -0,0 +1,215 @@ +import React from "react"; +import { test, expect } from "@playwright/experimental-ct-react17"; +import IconButtonComponent from "./component.test-pw"; +import { button as iconButton } from "../../../playwright/components/index"; +import { CHARACTERS } from "../../../playwright/support/constants"; +import { HooksConfig } from "../../../playwright"; +import { checkAccessibility } from "../../../playwright/support/helper"; + +test.describe( + "check IconButton component focus outlines and border radius", + () => { + test(`should have the expected styling when the focusRedesignOptOut is false`, async ({ + mount, + page, + }) => { + await mount(); + + await iconButton(page).focus(); + await expect(iconButton(page)).toHaveCSS( + "box-shadow", + "rgb(255, 188, 25) 0px 0px 0px 3px, rgba(0, 0, 0, 0.9) 0px 0px 0px 6px" + ); + + await expect(iconButton(page)).toHaveCSS( + "outline", + "rgba(0, 0, 0, 0) solid 3px" + ); + }); + + test(`should have the expected styling when the focusRedesignOptOut is true`, async ({ + mount, + page, + }) => { + await mount(, { + hooksConfig: { focusRedesignOptOut: true }, + }); + + await iconButton(page).focus(); + await expect(iconButton(page)).toHaveCSS( + "outline", + "rgb(255, 188, 25) solid 3px" + ); + }); + + test(`should render with the expected border radius`, async ({ + mount, + page, + }) => { + await mount(); + + await iconButton(page).focus(); + await expect(iconButton(page)).toHaveCSS("border-radius", "4px"); + }); + } +); + +test.describe("check props for IconButton component", () => { + test(`should render with aria-label prop`, async ({ mount, page }) => { + await mount(); + + await expect(iconButton(page)).toHaveAttribute( + "aria-label", + CHARACTERS.STANDARD + ); + await expect(iconButton(page)).toBeVisible(); + }); + + test(`should render with a child`, async ({ mount, page }) => { + await mount(); + + await expect(iconButton(page)).toBeVisible(); + }); + + test(`should render with disabled prop`, async ({ mount, page }) => { + await mount(); + + await expect(iconButton(page)).toBeDisabled(); + }); +}); + +test.describe("check events for IconButton component", () => { + test(`should call onBlur callback when a blur event is triggered`, async ({ + mount, + page, + }) => { + let callbackCount = 0; + await mount( + { + callbackCount += 1; + }} + /> + ); + + await iconButton(page).focus(); + await iconButton(page).blur(); + expect(callbackCount).toBe(1); + }); + + test(`should call onFocus callback when a focus event is triggered`, async ({ + mount, + page, + }) => { + let callbackCount = 0; + await mount( + { + callbackCount += 1; + }} + /> + ); + + await iconButton(page).focus(); + expect(callbackCount).toBe(1); + }); + + test(`should call onMouseEnter callback when a mouseover event is triggered`, async ({ + mount, + page, + }) => { + let callbackCount = 0; + await mount( + { + callbackCount += 1; + }} + /> + ); + + await iconButton(page).hover(); + expect(callbackCount).toBe(1); + }); + + test(`should call onMouseLeave callback when a mouseout event is triggered`, async ({ + mount, + page, + }) => { + let callbackCount = 0; + await mount( + { + callbackCount += 1; + }} + /> + ); + + await iconButton(page).hover(); + await page.mouse.move(100, 0); + expect(callbackCount).toBe(1); + }); + + test(`should call onClick callback when a click event is triggered`, async ({ + mount, + page, + }) => { + let callbackCount = 0; + await mount( + { + callbackCount += 1; + }} + /> + ); + await iconButton(page).click(); + expect(callbackCount).toBe(1); + }); + + ["Enter", "Space"].forEach((key) => { + test(`should call onClick callback when ${key} key is triggered`, async ({ + mount, + page, + }) => { + let callbackCount = 0; + await mount( + { + callbackCount += 1; + }} + /> + ); + + await iconButton(page).press(key); + expect(callbackCount).toBe(1); + }); + }); +}); + +test.describe("check accessibility tests for IconButton component", () => { + test(`should pass accessibility tests when rendered with an aria-label`, async ({ + mount, + page, + }) => { + await mount(); + + await checkAccessibility(page); + }); + + test(`should pass accessibility tests when rendered with a child`, async ({ + mount, + page, + }) => { + await mount(); + + await checkAccessibility(page); + }); + + test(`should pass accessibility tests when disabled`, async ({ + mount, + page, + }) => { + await mount(); + + await checkAccessibility(page); + }); +});