From 67dfa1864cbba928bc7f8236a1966ddfc66db2a2 Mon Sep 17 00:00:00 2001 From: ZhuoyuJin Date: Tue, 5 Dec 2023 15:02:27 +0000 Subject: [PATCH] test(switch): playwright refactor --- cypress/components/switch/switch.cy.tsx | 855 -------------- playwright/components/switch/index.ts | 24 + playwright/components/switch/locators.ts | 4 + src/components/switch/components.test-pw.tsx | 39 + src/components/switch/switch-test.stories.tsx | 41 - src/components/switch/switch.pw.tsx | 1029 +++++++++++++++++ 6 files changed, 1096 insertions(+), 896 deletions(-) delete mode 100644 cypress/components/switch/switch.cy.tsx create mode 100644 playwright/components/switch/index.ts create mode 100644 playwright/components/switch/locators.ts create mode 100644 src/components/switch/components.test-pw.tsx create mode 100644 src/components/switch/switch.pw.tsx diff --git a/cypress/components/switch/switch.cy.tsx b/cypress/components/switch/switch.cy.tsx deleted file mode 100644 index 5ce15ffbfd..0000000000 --- a/cypress/components/switch/switch.cy.tsx +++ /dev/null @@ -1,855 +0,0 @@ -import React from "react"; -import Box from "../../../src/components/box"; -import Switch, { SwitchProps } from "../../../src/components/switch"; -import { WithMargin } from "../../../src/components/switch/switch.stories"; -import { - SwitchComponent, - SwitchComponentValidations, -} from "../../../src/components/switch/switch-test.stories"; -import { - switchDataComponent, - switchInput, - switchLabel, - switchIcon, - switchHelpIcon, - switchLoading, -} from "../../locators/switch/index"; -import CypressMountWithProviders from "../../support/component-helper/cypress-mount"; -import { - getComponent, - fieldHelpPreview, - tooltipPreview, - getDataElementByValue, -} from "../../locators/index"; -import { keyCode } from "../../support/helper"; -import { - assertCssValueIsApproximately, - verifyRequiredAsteriskForLabel, -} from "../../support/component-helper/common-steps"; -import { - CHARACTERS, - VALIDATION, - SIZE, -} from "../../support/component-helper/constants"; -import { ICON } from "../../locators/locators"; - -const testCypress = CHARACTERS.STANDARD; -const validationTypes = [ - ["error", VALIDATION.ERROR], - ["warning", VALIDATION.WARNING], - ["info", VALIDATION.INFO], -] as [string, string][]; - -const verifyBorderColor = ( - element: Cypress.Chainable>, - color: string -) => - element.then(($els: JQuery) => { - // get Window reference from element - const win = $els[0].ownerDocument.defaultView; - // use getComputedStyle to read the pseudo selector - const after = win?.getComputedStyle($els[0], "before"); - // read the value of the `content` CSS property - const contentValue = after?.getPropertyValue("color"); - // the returned value will have double quotes around it, but this is correct - cy.wrap(contentValue).should("equal", color); - }); - -context("Testing Switch component", () => { - describe("when focused", () => { - it("should have the expected styling when the focusRedesignOptOut is false", () => { - CypressMountWithProviders(); - switchInput() - .focus() - .next() - .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, - }); - switchInput() - .focus() - .next() - .should("have.css", "outline", "rgb(255, 188, 25) solid 3px"); - }); - }); - - describe("check props for Switch component", () => { - it.each([ - CHARACTERS.STANDARD, - CHARACTERS.DIACRITICS, - CHARACTERS.SPECIALCHARACTERS, - ])("verify Switch component with %s as fieldHelp", (fieldHelp) => { - CypressMountWithProviders(); - - fieldHelpPreview().should("have.text", fieldHelp); - }); - - it.each([ - CHARACTERS.STANDARD, - CHARACTERS.DIACRITICS, - CHARACTERS.SPECIALCHARACTERS, - ])("verify Switch component with %s as a label", (label) => { - CypressMountWithProviders(); - - switchLabel().should("have.text", label); - }); - - it.each([ - [true, "have.attr", "have.attr"], - [false, "not.have.attr", "not.exist"], - ])( - "verify Switch component with loading prop %s", - (boolVal, attribute, component) => { - CypressMountWithProviders(); - - switchInput().should(attribute, "disabled"); - switchLoading().should(component, "data-component", "loader"); - } - ); - - it("verify Switch component with data-component", () => { - CypressMountWithProviders( - - ); - - getComponent(CHARACTERS.STANDARD).should( - "have.attr", - "data-component", - CHARACTERS.STANDARD - ); - }); - - it("verify Switch component with data-element", () => { - CypressMountWithProviders( - - ); - - switchDataComponent().should( - "have.attr", - "data-element", - CHARACTERS.STANDARD - ); - }); - - it("verify Switch component with data-role", () => { - CypressMountWithProviders( - - ); - - switchDataComponent().should( - "have.attr", - "data-role", - CHARACTERS.STANDARD - ); - }); - - it("verify Switch component with autoFocus", () => { - CypressMountWithProviders(); - - switchInput().should("be.focused"); - }); - - it.each([ - [true, "be.checked"], - [false, "not.be.checked"], - ])( - "verify Switch component with checked state set to %s", - (boolVal, assertion) => { - CypressMountWithProviders(); - - switchInput().should(assertion); - } - ); - - it.each([ - [true, "have.attr"], - [false, "not.have.attr"], - ])("verify Switch with disabled prop %s", (boolVal, attribute) => { - CypressMountWithProviders(); - - switchInput().should(attribute, "disabled"); - switchLabel().should(attribute, "disabled"); - }); - - it.each([true, false])( - "verify Switch component with inline fieldHelp", - (boolVal) => { - CypressMountWithProviders( - - ); - - if (boolVal === true) { - switchDataComponent() - .children() - .children() - .children() - .children() - .eq(1) - .should("have.attr", "data-element", "help"); - } else { - switchDataComponent() - .children() - .children() - .children() - .eq(1) - .should("have.attr", "data-element", "help"); - } - } - ); - - it("verify Switch component with id", () => { - CypressMountWithProviders(); - - switchInput().should("have.id", CHARACTERS.STANDARD); - }); - - it.each([ - [true, "have.css", 24, 0, 8], - [false, "not.have.css", 16, 8, 0], - ])( - "verify Switch component with labelInline prop %s", - (boolVal, have, height, margin, padding) => { - CypressMountWithProviders(); - - switchLabel() - .parent() - .should(have, "box-sizing", "border-box") - .then(($el) => { - assertCssValueIsApproximately($el, "height", height); - assertCssValueIsApproximately($el, "margin-bottom", margin); - assertCssValueIsApproximately($el, "padding-right", padding); - }); - } - ); - - it.each([ - [10, 130], - [30, 390], - [80, 1041], - ] as [SwitchProps["labelWidth"], number][])( - "verify Switch with labelWidth %s and render it with correct label width ratio", - (labelWidth, labelRatio) => { - CypressMountWithProviders(); - - switchLabel() - .parent() - .then(($el) => { - assertCssValueIsApproximately($el, "width", labelRatio); - }); - } - ); - - it.each([ - [90, 1171], - [70, 911], - [20, 260], - ] as [SwitchProps["inputWidth"], number][])( - "verify Switch with inputWidth %s and render it with correct input width ratio", - (inputWidth, inputRatio) => { - CypressMountWithProviders( - - ); - - switchInput() - .parent() - .then(($el) => { - assertCssValueIsApproximately($el, "width", inputRatio); - }); - } - ); - - // skipped because of https://jira.sage.com/browse/FE-5530 - it.skip("verify Switch component with labelAlign %s", () => { - CypressMountWithProviders(); - - switchLabel().parent().should("have.css", "align-items", "right"); - }); - - it("verify Switch component with labelHelp", () => { - CypressMountWithProviders( - - ); - - switchIcon().trigger("mouseover"); - tooltipPreview().should("have.text", "Label Help"); - }); - - it.each([ - [1, 8], - [2, 17], - ] as [SwitchProps["labelSpacing"], number][])( - "verify Switch component with labelSpacing %s", - (spacing, padding) => { - CypressMountWithProviders( - - ); - - switchLabel() - .parent() - .then(($el) => { - assertCssValueIsApproximately($el, "padding-right", padding); - }); - } - ); - - it("verify Switch component with name", () => { - CypressMountWithProviders(); - - switchInput().should("have.attr", "name", CHARACTERS.STANDARD); - }); - - it.each([ - ["error", VALIDATION.ERROR], - ["warning", VALIDATION.WARNING], - ["info", VALIDATION.INFO], - ])( - "verify Switch component is verified with appropriate border color for validations", - (type, validation) => { - CypressMountWithProviders(); - - verifyBorderColor(getDataElementByValue(type), validation); - } - ); - - it.each(["error", "warning", "info"])( - "verify Switch component with validation icon", - (validation) => { - CypressMountWithProviders(); - - getDataElementByValue(validation).should( - "have.attr", - "data-component", - "icon" - ); - } - ); - - it.each(["error", "warning", "info"])( - "verify Switch component with validation has %s as tooltip message", - (type) => { - CypressMountWithProviders(); - - getDataElementByValue(type).trigger("mouseover"); - tooltipPreview().should("have.text", type); - } - ); - - it.each([ - ["error", 0], - ["warning", 1], - ["info", 2], - ])( - "verify Switch component with validation on label", - (validation, position) => { - CypressMountWithProviders( - - ); - - switchLabel() - .eq(position) - .parent() - .find(ICON) - .and("have.attr", "data-element", validation); - } - ); - - it.each([ - [true, "have.attr", "not.have.attr"], - [false, "not.have.attr", "have.attr"], - ])( - "verify Switch component reverse set to %s", - (boolVal, condition1, condition2) => { - CypressMountWithProviders(); - - switchDataComponent() - .children() - .children() - .children() - .children() - .children() - .should(condition1, "data-element", "label") - .and(condition2, "role", "switch"); - } - ); - - it.each([ - [SIZE.SMALL, 60, 24], - [SIZE.LARGE, 82, 44], - ] as [SwitchProps["size"], number, number][])( - "verify Switch component with size set to %s", - (size, width, height) => { - CypressMountWithProviders(); - - switchInput().then(($el) => { - assertCssValueIsApproximately($el, "height", height); - assertCssValueIsApproximately($el, "width", width); - }); - } - ); - - it("verify Switch component with value prop", () => { - CypressMountWithProviders(); - switchInput().should("have.value", "switchvalue"); - }); - - it.each([ - [399, "have.css", 24], - [400, "have.css", 24], - [401, "not.have.css", 16], - ])( - "check Switch label is %s with adaptiveLabelBreakpoint %s and viewport 400", - (breakpoint, attribute, height) => { - cy.viewport(400, 300); - - CypressMountWithProviders( - - ); - - switchLabel() - .parent() - .should(attribute, "box-sizing", "border-box") - .then(($el) => { - assertCssValueIsApproximately($el, "height", height); - }); - } - ); - - it("verify Switch component as a required field", () => { - CypressMountWithProviders(); - - verifyRequiredAsteriskForLabel(); - }); - - it.each([ - "bottom", - "left", - "right", - "top", - ] as SwitchProps["tooltipPosition"][])( - "verify Switch component with tooltip positioned to the %s", - (position) => { - CypressMountWithProviders( - - - - ); - switchIcon().trigger("mouseover"); - tooltipPreview() - .should("have.text", "Switch info") - .should("have.attr", "data-placement", `${position}`); - } - ); - - it("verify Switch component with helpAriaLabel", () => { - CypressMountWithProviders( - - ); - - switchIcon().trigger("mouseover"); - switchHelpIcon().should( - "have.attr", - "aria-label", - "This text provides more information for the label" - ); - }); - - it.each([ - [true, "on"], - [false, "off"], - ])("verify Switch component with defaultChecked %s", (boolVal, state) => { - CypressMountWithProviders( - - ); - - switchInput() - .parent() - .children() - .eq(1) - .children() - .should("have.attr", "type", state); - }); - }); - - describe("verify Switch component for event tests", () => { - it("should call onChange callback when a click event is triggered", () => { - const callback: SwitchProps["onChange"] = cy.stub().as("onChange"); - CypressMountWithProviders(); - - switchInput().click(); - cy.get("@onChange").should("have.been.calledOnce"); - }); - - // skipped because of https://jira.sage.com/browse/FE-5534 - it.skip("should call onChange callback when a keyboard event is triggered", () => { - const callback: SwitchProps["onChange"] = cy.stub().as("onChange"); - CypressMountWithProviders( - - ); - - switchInput().focus().trigger("keydown", keyCode("Space")); - cy.get("@onChange").should("have.been.calledOnce"); - }); - - it("should call onBlur callback when a blur event is triggered", () => { - const callback: SwitchProps["onBlur"] = cy.stub().as("onBlur"); - CypressMountWithProviders(); - - switchInput().focus().blur({ force: true }); - cy.get("@onBlur").should("have.been.calledOnce"); - }); - - it("should call onFocus callback when a focus event is triggered", () => { - const callback: SwitchProps["onFocus"] = cy.stub().as("onFocus"); - CypressMountWithProviders(); - - switchInput().focus(); - cy.get("@onFocus").should("have.been.calledOnce"); - }); - - it("should call onClick callback when a click event is triggered", () => { - const callback: SwitchProps["onClick"] = cy.stub().as("onClick"); - CypressMountWithProviders(); - - switchInput().click(); - cy.get("@onClick").should("have.been.calledOnce"); - }); - }); - - describe("Accessibility tests for Switch", () => { - it.each([ - CHARACTERS.STANDARD, - CHARACTERS.DIACRITICS, - CHARACTERS.SPECIALCHARACTERS, - ])( - "check Switch component accessibility with %s as fieldHelp", - (fieldHelp) => { - CypressMountWithProviders(); - - cy.checkAccessibility(); - } - ); - - it.each([ - CHARACTERS.STANDARD, - CHARACTERS.DIACRITICS, - CHARACTERS.SPECIALCHARACTERS, - ])("check Switch component accessibility with %s as a label", (label) => { - CypressMountWithProviders(); - - cy.checkAccessibility(); - }); - - it.each([true, false])( - "check Switch component accessibility with loading prop %s", - (boolVal) => { - CypressMountWithProviders(); - - cy.checkAccessibility(); - } - ); - - it("check Switch component accessibility with data-component", () => { - CypressMountWithProviders( - - ); - - cy.checkAccessibility(); - }); - - it("check Switch component accessibility with data-element", () => { - CypressMountWithProviders( - - ); - - cy.checkAccessibility(); - }); - - it("check Switch component accessibility with data-role", () => { - CypressMountWithProviders( - - ); - - cy.checkAccessibility(); - }); - - it("check Switch component accessibility with autoFocus", () => { - CypressMountWithProviders(); - - cy.checkAccessibility(); - }); - - it.each([true, false])( - "check Switch component accessibility with checked state set to %s", - (boolVal) => { - CypressMountWithProviders(); - - cy.checkAccessibility(); - } - ); - - it.each([true, false])( - "check Switch component accessibility with disabled prop %s", - (boolVal) => { - CypressMountWithProviders(); - - cy.checkAccessibility(); - } - ); - - it.each([true, false])( - "check Switch component accessibility with inline fieldHelp is %s", - (boolVal) => { - CypressMountWithProviders( - - ); - - cy.checkAccessibility(); - } - ); - - it("check Switch component accessibility with id", () => { - CypressMountWithProviders(); - - cy.checkAccessibility(); - }); - - it.each([true, false])( - "check Switch component accessibility with labelInline prop %s", - (boolVal) => { - CypressMountWithProviders(); - - cy.checkAccessibility(); - } - ); - - it.each([10, 30, 80] as SwitchProps["labelWidth"][])( - "check Switch component accessibility with labelWidth %s", - (labelWidth) => { - CypressMountWithProviders(); - - cy.checkAccessibility(); - } - ); - - it.each([90, 70, 20] as SwitchProps["inputWidth"][])( - "check Switch component accessibility with inputWidth %s", - (inputWidth) => { - CypressMountWithProviders( - - ); - - cy.checkAccessibility(); - } - ); - - it("check Switch component accessibility with labelAlign to right", () => { - CypressMountWithProviders(); - - cy.checkAccessibility(); - }); - - it("check Switch component accessibility with labelHelp", () => { - CypressMountWithProviders( - - ); - - cy.checkAccessibility(); - }); - - it.each([1, 2] as SwitchProps["labelSpacing"][])( - "check Switch component accessibility with labelSpacing %s", - (spacing) => { - CypressMountWithProviders( - - ); - - cy.checkAccessibility(); - } - ); - - it("check Switch component accessibility with name", () => { - CypressMountWithProviders(); - - cy.checkAccessibility(); - }); - - it("check Switch component accessibility with validation", () => { - CypressMountWithProviders(); - - cy.checkAccessibility(); - }); - - it("check Switch component accessibility with validation on label", () => { - CypressMountWithProviders( - - ); - - cy.checkAccessibility(); - }); - - it.each(validationTypes)( - "should check accessibility for Switch and set type to %s as string", - (type) => { - CypressMountWithProviders( - - ); - - cy.checkAccessibility(); - } - ); - - it.each([ - "top", - "bottom", - "left", - "right", - ] as SwitchProps["tooltipPosition"][])( - "should check accessibility for Switch with the tooltip in the %s position", - (tooltipPositionValue) => { - CypressMountWithProviders( - -
- -
-
- ); - - cy.checkAccessibility(); - } - ); - - it.each([true, false])( - "check Switch component accessibility reverse set to %s", - (boolVal) => { - CypressMountWithProviders(); - - cy.checkAccessibility(); - } - ); - - it.each([SIZE.SMALL, SIZE.LARGE] as SwitchProps["size"][])( - "check Switch component accessibility with size set to %s", - (size) => { - CypressMountWithProviders(); - - cy.checkAccessibility(); - } - ); - - it("check Switch component accessibility with value prop", () => { - CypressMountWithProviders(); - - cy.checkAccessibility(); - }); - - it.each([399, 400, 401])( - "check Switch component accessibility when label is inline with adaptiveLabelBreakpoint %s", - (breakpoint) => { - cy.viewport(400, 300); - - CypressMountWithProviders( - - ); - - cy.checkAccessibility(); - } - ); - - it("check Switch component accessibility as a required field", () => { - CypressMountWithProviders(); - - cy.checkAccessibility(); - }); - - it.each([ - "bottom", - "left", - "right", - "top", - ] as SwitchProps["tooltipPosition"][])( - "check Switch component accessibility with tooltip positioned to the %s", - (position) => { - CypressMountWithProviders( - - - - ); - - cy.checkAccessibility(); - } - ); - - it("check Switch component accessibility with helpAriaLabel", () => { - CypressMountWithProviders( - - ); - - cy.checkAccessibility(); - }); - - it.each([true, false])( - "check Switch component accessibility with defaultChecked %s", - (boolVal) => { - CypressMountWithProviders( - - ); - - cy.checkAccessibility(); - } - ); - - it.each(validationTypes)( - "should check accessibility for Switch and set type to %s as boolean", - (type) => { - CypressMountWithProviders(); - - cy.checkAccessibility(); - } - ); - - it("check Switch component accessibility with Margin", () => { - CypressMountWithProviders(); - - cy.checkAccessibility(); - }); - }); - - it("renders with the expected border radius", () => { - CypressMountWithProviders(); - - switchInput().next().should("have.css", "border-radius", "32px"); - }); -}); diff --git a/playwright/components/switch/index.ts b/playwright/components/switch/index.ts new file mode 100644 index 0000000000..8106b33f7d --- /dev/null +++ b/playwright/components/switch/index.ts @@ -0,0 +1,24 @@ +import { Page } from "@playwright/test"; +import SWITCH_DATA_COMPONENT from "./locators"; + +// component preview locators +export const switchDataComponent = (page: Page) => + page.locator(SWITCH_DATA_COMPONENT); +export const switchInput = (page: Page) => + switchDataComponent(page).locator("input"); +export const switchStyling = (page: Page) => + switchDataComponent(page).locator("div > div > div > div > span"); +export const switchLoading = (page: Page) => + switchDataComponent(page) + .locator("div > div > div > div > span > div") + .nth(0); +export const switchLabel = (page: Page) => + switchDataComponent(page).locator("label"); +export const switchLabelParent = (page: Page) => + switchLabel(page).locator(".."); +export const switchHelpIcon = (page: Page) => + switchDataComponent(page).locator("[data-component='help']"); +export const switchIcon = (page: Page) => + switchDataComponent(page).locator("span[data-component='icon']"); +export const switchSvg = (page: Page) => + switchDataComponent(page).locator("svg"); diff --git a/playwright/components/switch/locators.ts b/playwright/components/switch/locators.ts new file mode 100644 index 0000000000..69296fddde --- /dev/null +++ b/playwright/components/switch/locators.ts @@ -0,0 +1,4 @@ +// component preview locators +const SWITCH_DATA_COMPONENT = '[data-component="switch"]'; + +export default SWITCH_DATA_COMPONENT; diff --git a/src/components/switch/components.test-pw.tsx b/src/components/switch/components.test-pw.tsx new file mode 100644 index 0000000000..225e184be3 --- /dev/null +++ b/src/components/switch/components.test-pw.tsx @@ -0,0 +1,39 @@ +import React from "react"; +import Switch, { SwitchProps } from "./switch.component"; +import Box from "../box"; + +export const SwitchComponent = (props: Partial) => { + const [isChecked, setIsChecked] = React.useState(false); + return ( + <> + + setIsChecked(e.target.checked)} + {...props} + /> + + + ); +}; + +export const SwitchComponentValidations = (props: Partial) => { + const [, setIsChecked] = React.useState(false); + return ( + + {["error", "warning", "info"].map((type) => ( + setIsChecked((state) => !state)} + {...props} + /> + ))} + + ); +}; diff --git a/src/components/switch/switch-test.stories.tsx b/src/components/switch/switch-test.stories.tsx index a551d9d9b8..70c4e713e7 100644 --- a/src/components/switch/switch-test.stories.tsx +++ b/src/components/switch/switch-test.stories.tsx @@ -141,44 +141,3 @@ NewDefault.args = { disabled: false, size: "small", }; - -export const SwitchComponent = (props: Partial) => { - const [isChecked, setIsChecked] = React.useState(false); - return ( - <> -
- setIsChecked(e.target.checked)} - {...props} - /> -
- - ); -}; - -export const SwitchComponentValidations = (props: Partial) => { - const [, setIsChecked] = React.useState(false); - return ( -
- {["error", "warning", "info"].map((type) => ( - setIsChecked((state) => !state)} - {...props} - /> - ))} -
- ); -}; diff --git a/src/components/switch/switch.pw.tsx b/src/components/switch/switch.pw.tsx new file mode 100644 index 0000000000..b84d3b39b9 --- /dev/null +++ b/src/components/switch/switch.pw.tsx @@ -0,0 +1,1029 @@ +import React from "react"; +import { test, expect } from "@playwright/experimental-ct-react17"; +import type { HooksConfig } from "../../../playwright/index"; +import Box from "../box"; +import Switch, { SwitchProps } from "."; +import { WithMargin } from "./switch.stories"; +import { + SwitchComponent, + SwitchComponentValidations, +} from "./components.test-pw"; +import { + switchDataComponent, + switchInput, + switchStyling, + switchLabel, + switchLabelParent, + switchIcon, + switchHelpIcon, + switchLoading, +} from "../../../playwright/components/switch/index"; +import { + getComponent, + fieldHelpPreview, + tooltipPreview, + getDataElementByValue, +} from "../../../playwright/components/index"; +import { + assertCssValueIsApproximately, + verifyRequiredAsteriskForLabel, + checkAccessibility, +} from "../../../playwright/support/helper"; +import { + CHARACTERS, + VALIDATION, + SIZE, +} from "../../../playwright/support/constants"; + +const testData = CHARACTERS.STANDARD; + +test.describe("Prop tests for Switch component", () => { + test("should have the expected styling when focused and the focusRedesignOptOut is false", async ({ + mount, + page, + }) => { + await mount(, { + hooksConfig: { focusRedesignOptOut: false }, + }); + + await switchInput(page).click(); + + await expect(switchStyling(page)).toHaveCSS( + "box-shadow", + "rgb(255, 188, 25) 0px 0px 0px 3px, rgba(0, 0, 0, 0.9) 0px 0px 0px 6px" + ); + + await expect(switchStyling(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 switchInput(page).click(); + + await expect(switchStyling(page)).toHaveCSS( + "outline", + "rgb(255, 188, 25) solid 3px" + ); + }); + + [ + CHARACTERS.STANDARD, + CHARACTERS.DIACRITICS, + CHARACTERS.SPECIALCHARACTERS, + ].forEach((fieldHelp) => { + test(`should render with ${fieldHelp} as fieldHelp`, async ({ + mount, + page, + }) => { + await mount(); + + await expect(fieldHelpPreview(page)).toHaveText(fieldHelp); + }); + }); + + [ + CHARACTERS.STANDARD, + CHARACTERS.DIACRITICS, + CHARACTERS.SPECIALCHARACTERS, + ].forEach((label) => { + test(`should render with ${label} as label`, async ({ mount, page }) => { + await mount(); + + await expect(switchLabel(page)).toHaveText(label); + }); + }); + + [true, false].forEach((boolVal) => { + test(`should render properly with loading prop set as ${boolVal}`, async ({ + mount, + page, + }) => { + await mount(); + + if (boolVal) { + await expect(switchInput(page)).toBeDisabled(); + + await expect(page.getByRole("progressbar")).toHaveAttribute( + "data-component", + "loader" + ); + } else { + await expect(switchInput(page)).not.toBeDisabled(); + } + }); + }); + + test("should render with data-component", async ({ mount, page }) => { + await mount(); + + await expect(getComponent(page, CHARACTERS.STANDARD)).toHaveAttribute( + "data-component", + CHARACTERS.STANDARD + ); + }); + + test("should render with data-element", async ({ mount, page }) => { + await mount(); + + await expect(switchDataComponent(page)).toHaveAttribute( + "data-element", + CHARACTERS.STANDARD + ); + }); + + test("should render with data-role", async ({ mount, page }) => { + await mount(); + + await expect(switchDataComponent(page)).toHaveAttribute( + "data-role", + CHARACTERS.STANDARD + ); + }); + + test("should render with autoFocus prop", async ({ mount, page }) => { + await mount(); + + await expect(switchInput(page)).toBeFocused(); + }); + + [true, false].forEach((boolVal) => { + test(`should render with checked state set to ${boolVal}`, async ({ + mount, + page, + }) => { + await mount(); + + if (boolVal) { + await expect(switchInput(page)).toBeChecked(); + } else { + await expect(switchInput(page)).not.toBeChecked(); + } + }); + }); + + [true, false].forEach((boolVal) => { + test(`should check with disabled state set to ${boolVal}`, async ({ + mount, + page, + }) => { + await mount(); + + if (boolVal) { + await expect(switchInput(page)).toBeDisabled(); + + await expect(switchLabel(page)).toBeDisabled(); + } else { + await expect(switchInput(page)).not.toBeDisabled(); + + await expect(switchLabel(page)).not.toBeDisabled(); + } + }); + }); + + [true, false].forEach((boolVal) => { + test(`should render with fieldHelpInline set to ${boolVal}`, async ({ + mount, + page, + }) => { + await mount( + + ); + + const switchFiledHelp1 = switchDataComponent(page).locator("div > div"); + + const switchFiledHelp2 = switchDataComponent(page).locator("div"); + if (boolVal) { + await expect(switchFiledHelp1.locator("span").nth(0)).toHaveAttribute( + "data-element", + "help" + ); + } else { + await expect(switchFiledHelp2.locator("span").nth(1)).toHaveAttribute( + "data-element", + "help" + ); + } + }); + }); + + test("should render with id", async ({ mount, page }) => { + await mount(); + + await expect(switchInput(page)).toHaveId(CHARACTERS.STANDARD); + }); + + ([ + [true, 24, 0, 8], + [false, 16, 8, 0], + ] as [SwitchProps["labelInline"], number, number, number][]).forEach( + ([boolVal, height, margin, padding]) => { + test(`should render with labelInline prop set to ${boolVal}`, async ({ + mount, + page, + }) => { + await mount(); + + if (boolVal) { + await expect(switchLabelParent(page)).toHaveCSS( + "box-sizing", + "border-box" + ); + } else { + await expect(switchLabelParent(page)).not.toHaveCSS( + "box-sizing", + "border-box" + ); + } + await assertCssValueIsApproximately( + switchLabelParent(page), + "height", + height + ); + + await assertCssValueIsApproximately( + switchLabelParent(page), + "margin-bottom", + margin + ); + + await assertCssValueIsApproximately( + switchLabelParent(page), + "padding-right", + padding + ); + }); + } + ); + + ([ + [10, 130], + [30, 390], + [80, 1041], + ] as [SwitchProps["labelWidth"], number][]).forEach( + ([labelWidth, labelRatio]) => { + test(`should render with labelWidth prop set to ${labelWidth} and with correct label width ratio`, async ({ + mount, + page, + }) => { + await mount(); + + const label = switchLabelParent(page); + await assertCssValueIsApproximately(label, "width", labelRatio); + }); + } + ); + + ([ + [90, 1171], + [70, 911], + [20, 260], + ] as [SwitchProps["inputWidth"], number][]).forEach( + ([inputWidth, inputRatio]) => { + test(`should render with inputWidth prop set to ${inputWidth} and with correct input width ratio`, async ({ + mount, + page, + }) => { + await mount(); + + const input = switchDataComponent(page) + .locator("div > div > div > div") + .nth(1); + await assertCssValueIsApproximately(input, "width", inputRatio); + }); + } + ); + + // skipped because of https://jira.sage.com/browse/FE-5530 + test.skip("should render with labelAlign set to right", async ({ + mount, + page, + }) => { + await mount(); + + await expect(switchLabel(page)).toHaveCSS("align-items", "right"); + }); + + test("should render with labelHelp", async ({ mount, page }) => { + await mount( + + ); + + await switchIcon(page).hover(); + + await expect(tooltipPreview(page)).toHaveText("Label Help"); + }); + + ([ + [1, 8], + [2, 17], + ] as [SwitchProps["labelSpacing"], number][]).forEach( + ([spacing, padding]) => { + test(`should render with labelSpacing prop set to ${spacing}`, async ({ + mount, + page, + }) => { + await mount( + + ); + + await assertCssValueIsApproximately( + switchLabelParent(page), + "padding-right", + padding + ); + }); + } + ); + + test("should render with name", async ({ mount, page }) => { + await mount(); + + await expect(switchInput(page)).toHaveAttribute( + "name", + CHARACTERS.STANDARD + ); + }); + + test("should render with error", async ({ mount, page }) => { + await mount(); + + const boxSvg = switchStyling(page); + await expect(boxSvg).toHaveCSS("border-color", VALIDATION.ERROR); + }); + + test("should render with warning", async ({ mount, page }) => { + await mount(); + + const boxSvg = switchStyling(page); + await expect(boxSvg).toHaveCSS("border-color", VALIDATION.WARNING); + }); + + test("should render with info", async ({ mount, page }) => { + await mount(); + + const boxSvg = switchStyling(page); + await expect(boxSvg).toHaveCSS("border-color", "rgb(102, 132, 148)"); + }); + + ["error", "warning", "info"].forEach((validation) => { + test(`should render with ${validation} validation icon`, async ({ + mount, + page, + }) => { + await mount(); + + const validate = getDataElementByValue(page, validation); + await expect(validate).toHaveAttribute("data-component", "icon"); + }); + }); + + ["error", "warning", "info"].forEach((type) => { + test(`should render with ${type} validation as tooltip message`, async ({ + mount, + page, + }) => { + await mount(); + + await getDataElementByValue(page, type).hover(); + await expect(tooltipPreview(page)).toHaveText(type); + }); + }); + + ["error", "warning", "info"].forEach((validation) => { + test(`should render with validation on label as ${validation}`, async ({ + mount, + page, + }) => { + await mount(); + + const validate = getDataElementByValue(page, validation); + await expect(validate).toHaveAttribute("data-component", "icon"); + }); + }); + + [true, false].forEach((boolVal) => { + test(`should render with reverse set to ${boolVal}`, async ({ + mount, + page, + }) => { + await mount(); + + if (boolVal) { + const switchWithLabel = page.locator('[data-element="label"]'); + + await expect(switchWithLabel).not.toHaveAttribute("role", "switch"); + } else { + await expect(switchInput(page)).not.toHaveAttribute( + "data-element", + "label" + ); + + await expect(switchInput(page)).toHaveAttribute("role", "switch"); + } + }); + }); + + ([ + [SIZE.SMALL, 60, 24], + [SIZE.LARGE, 82, 44], + ] as [SwitchProps["size"], number, number][]).forEach( + ([size, width, height]) => { + test(`should render with size set to ${size}`, async ({ + mount, + page, + }) => { + await mount(); + + await assertCssValueIsApproximately( + switchInput(page), + "height", + height + ); + + await assertCssValueIsApproximately(switchInput(page), "width", width); + }); + } + ); + + test("should render with value prop", async ({ mount, page }) => { + await mount(); + + await expect(switchInput(page)).toHaveValue("switchvalue"); + }); + + [ + [399, 24], + [400, 24], + [401, 16], + ].forEach(([breakpoint, height]) => { + test(`should render properly with adaptiveLabelBreakpoint set to ${breakpoint}`, async ({ + mount, + page, + }) => { + await page.setViewportSize({ width: 400, height: 300 }); + + await mount( + + ); + + if (breakpoint <= 400) { + await expect(switchLabelParent(page)).toHaveCSS( + "box-sizing", + "border-box" + ); + } else { + await expect(switchLabelParent(page)).not.toHaveCSS( + "box-sizing", + "border-box" + ); + } + + await assertCssValueIsApproximately( + switchLabelParent(page), + "height", + height + ); + }); + }); + + test("verify Switch component as a required field", async ({ + mount, + page, + }) => { + await mount(); + + await verifyRequiredAsteriskForLabel(page); + }); + + ([ + "bottom", + "left", + "right", + "top", + ] as SwitchProps["tooltipPosition"][]).forEach((position) => { + test(`should render with tooltip positioned to the ${position}`, async ({ + mount, + page, + }) => { + await mount( + + + + ); + + await switchIcon(page).hover(); + + await expect(tooltipPreview(page)).toHaveText("Switch info"); + + await expect(tooltipPreview(page)).toHaveAttribute( + "data-placement", + `${position}` + ); + }); + }); + + test("should render with helpAriaLabel", async ({ mount, page }) => { + await mount( + + ); + + await switchIcon(page).hover(); + await expect(switchHelpIcon(page)).toHaveAttribute( + "aria-label", + "This text provides more information for the label" + ); + }); + + [true, false].forEach((boolVal) => { + test(`should have proper state when defaultChecked set to ${boolVal}`, async ({ + mount, + page, + }) => { + await mount( + + ); + + if (boolVal) { + await expect(switchLoading(page)).toHaveAttribute("type", "on"); + } else { + await expect(switchLoading(page)).toHaveAttribute("type", "off"); + } + }); + }); + + test("renders with the expected border radius", async ({ mount, page }) => { + await mount(); + + await expect(switchStyling(page)).toHaveCSS("border-radius", "32px"); + }); +}); + +test.describe("Event tests", () => { + test("should call onChange callback when a click event is triggered", async ({ + mount, + page, + }) => { + let callbackCount = 0; + + await mount( + { + callbackCount += 1; + }} + /> + ); + + await switchInput(page).click(); + + expect(callbackCount).toBe(1); + }); + + // skipped because of https://jira.sage.com/browse/FE-5534 + test.skip("should call onChange callback when a keyboard event is triggered", async ({ + mount, + page, + }) => { + let callbackCount = 0; + await mount( + { + callbackCount += 1; + }} + /> + ); + + await switchInput(page).focus(); + + await page.keyboard.down("Space"); + + expect(callbackCount).toBe(1); + }); + + test("should call onBlur callback when a blur event is triggered", async ({ + mount, + page, + }) => { + let callbackCount = 0; + await mount( + { + callbackCount += 1; + }} + /> + ); + + await switchInput(page).focus(); + await switchInput(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 switchInput(page).focus(); + + 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 switchInput(page).click(); + expect(callbackCount).toBe(1); + }); +}); + +test.describe("Accessibility tests", () => { + [ + CHARACTERS.STANDARD, + CHARACTERS.DIACRITICS, + CHARACTERS.SPECIALCHARACTERS, + ].forEach((fieldHelp) => { + test(`check accessibility with ${fieldHelp} as fieldHelp`, async ({ + mount, + page, + }) => { + await mount(); + + await checkAccessibility(page); + }); + }); + + [ + CHARACTERS.STANDARD, + CHARACTERS.DIACRITICS, + CHARACTERS.SPECIALCHARACTERS, + ].forEach((label) => { + test(`check accessibility with ${label} as label`, async ({ + mount, + page, + }) => { + await mount(); + + await checkAccessibility(page); + }); + }); + + [true, false].forEach((boolVal) => { + test(`check accessibility when loading prop is ${boolVal}`, async ({ + mount, + page, + }) => { + await mount(); + + await checkAccessibility(page); + }); + }); + + test("check accessibility with data-component prop set", async ({ + mount, + page, + }) => { + await mount(); + + await checkAccessibility(page); + }); + + test("check accessibility with data-element prop set", async ({ + mount, + page, + }) => { + await mount(); + + await checkAccessibility(page); + }); + + test("check accessibility with data-role prop set", async ({ + mount, + page, + }) => { + await mount(); + + await checkAccessibility(page); + }); + + test("check accessibility with autoFocus prop set", async ({ + mount, + page, + }) => { + await mount(); + + await checkAccessibility(page); + }); + + [true, false].forEach((boolVal) => { + test(`check accessibility with checked prop set to ${boolVal}`, async ({ + mount, + page, + }) => { + await mount(); + + await checkAccessibility(page); + }); + }); + + [true, false].forEach((boolVal) => { + test(`check accessibility with disabled prop set to ${boolVal}`, async ({ + mount, + page, + }) => { + await mount(); + + await checkAccessibility(page); + }); + }); + + [true, false].forEach((boolVal) => { + test(`check accessibility with inline fieldHelp prop set to ${boolVal}`, async ({ + mount, + page, + }) => { + await mount( + + ); + + await checkAccessibility(page); + }); + }); + + test("check accessibility with id prop set", async ({ mount, page }) => { + await mount(); + + await checkAccessibility(page); + }); + + [true, false].forEach((boolVal) => { + test(`check accessibility when labelInline prop is set to ${boolVal}`, async ({ + mount, + page, + }) => { + await mount(); + + await checkAccessibility(page); + }); + }); + + ([10, 30, 80] as SwitchProps["labelWidth"][]).forEach((labelWidth) => { + test(`check accessibility with labelWidth set to ${labelWidth}`, async ({ + mount, + page, + }) => { + await mount(); + + await checkAccessibility(page); + }); + }); + + ([90, 70, 20] as SwitchProps["inputWidth"][]).forEach((inputWidth) => { + test(`check accessibility with inputWidth set to ${inputWidth}`, async ({ + mount, + page, + }) => { + await mount(); + + await checkAccessibility(page); + }); + }); + + test("check accessibility with labelAlign to right", async ({ + mount, + page, + }) => { + await mount(); + + await checkAccessibility(page); + }); + + test("check accessibility with labelHelp", async ({ mount, page }) => { + await mount( + + ); + + await checkAccessibility(page); + }); + + ([1, 2] as SwitchProps["labelSpacing"][]).forEach((spacing) => { + test(`check accessibility with labelSpacing set to ${spacing}`, async ({ + mount, + page, + }) => { + await mount( + + ); + + await checkAccessibility(page); + }); + }); + + test("check accessibility with name prop", async ({ mount, page }) => { + await mount(); + + await checkAccessibility(page); + }); + + test("check accessibility with validation prop", async ({ mount, page }) => { + await mount(); + + await checkAccessibility(page); + }); + + test("check accessibility with validation on label", async ({ + mount, + page, + }) => { + await mount(); + + await checkAccessibility(page); + }); + + ["error", "warning", "info"].forEach((type) => { + test(`check accessibility with validations set to ${type} as string`, async ({ + mount, + page, + }) => { + await mount(); + + await checkAccessibility(page); + }); + }); + + ([ + "top", + "bottom", + "left", + "right", + ] as SwitchProps["tooltipPosition"][]).forEach((tooltipPositionValue) => { + test(`check accessibility with tooltip set to ${tooltipPositionValue} position`, async ({ + mount, + page, + }) => { + await mount( + + + + + + ); + + await checkAccessibility(page); + }); + }); + + [true, false].forEach((boolVal) => { + test(`check accessibility with reverse set to ${boolVal}`, async ({ + mount, + page, + }) => { + await mount(); + + await checkAccessibility(page); + }); + }); + + ([SIZE.SMALL, SIZE.LARGE] as SwitchProps["size"][]).forEach((size) => { + test(`check accessibility with size set to ${size}`, async ({ + mount, + page, + }) => { + await mount(); + + await checkAccessibility(page); + }); + }); + + test("check accessibility with value prop", async ({ mount, page }) => { + await mount(); + + await checkAccessibility(page); + }); + + [399, 400, 401].forEach((breakpoint) => { + test(`check accessibility when label is inline with adaptiveLabelBreakpoint set to ${breakpoint}`, async ({ + mount, + page, + }) => { + await page.setViewportSize({ width: 400, height: 300 }); + + await mount( + + ); + await checkAccessibility(page); + }); + }); + + test("check accessibility with required prop", async ({ mount, page }) => { + await mount(); + + await checkAccessibility(page); + }); + + ([ + "bottom", + "left", + "right", + "top", + ] as SwitchProps["tooltipPosition"][]).forEach((position) => { + test(`check accessibility with tooltip positioned to the ${position}`, async ({ + mount, + page, + }) => { + await mount( + + + + ); + + await checkAccessibility(page); + }); + }); + + test("check accessibility with helpAriaLabel prop", async ({ + mount, + page, + }) => { + await mount( + + ); + + await checkAccessibility(page); + }); + + [true, false].forEach((boolVal) => { + test(`check accessibility when defaultChecked is ${boolVal}`, async ({ + mount, + page, + }) => { + await mount( + + ); + + await checkAccessibility(page); + }); + }); + + ["error", "warning", "info"].forEach((type) => { + test(`check accessibility with validation set to ${type} as a boolean`, async ({ + mount, + page, + }) => { + await mount(); + + await checkAccessibility(page); + }); + }); + + test("check accessibility for withMargin example", async ({ + mount, + page, + }) => { + await mount(); + + await checkAccessibility(page); + }); +});