From c994cae7b9a4b954d7385d904d78e5955bd7f2fe Mon Sep 17 00:00:00 2001 From: divya jindel Date: Fri, 20 Oct 2023 17:13:09 +0100 Subject: [PATCH] test(pill): add playwright tests --- cypress/components/pill/pill.cy.tsx | 392 -------------------- playwright/components/pill/index.ts | 7 +- playwright/components/pill/locators.ts | 5 +- src/components/pill/components.test-pw.tsx | 8 + src/components/pill/pill.pw.tsx | 412 +++++++++++++++++++++ 5 files changed, 425 insertions(+), 399 deletions(-) delete mode 100644 cypress/components/pill/pill.cy.tsx create mode 100644 src/components/pill/components.test-pw.tsx create mode 100644 src/components/pill/pill.pw.tsx diff --git a/cypress/components/pill/pill.cy.tsx b/cypress/components/pill/pill.cy.tsx deleted file mode 100644 index 0b8e90cb52..0000000000 --- a/cypress/components/pill/pill.cy.tsx +++ /dev/null @@ -1,392 +0,0 @@ -import React from "react"; -import Pill, { PillProps } from "../../../src/components/pill"; -import { PillComponent } from "../../../src/components/pill/pill-test.stories"; -import { pillPreview, pillCloseIcon } from "../../locators/pill/index"; -import CypressMountWithProviders from "../../support/component-helper/cypress-mount"; -import { checkOutlineCss } from "../../support/component-helper/common-steps"; -import { closeIconButton } from "../../locators/index"; -import { CHARACTERS } from "../../support/component-helper/constants"; - -const specialCharacters = [CHARACTERS.DIACRITICS, CHARACTERS.SPECIALCHARACTERS]; -const testData = CHARACTERS.STANDARD; -const warning = "rgb(242, 133, 51)"; -const neutral = "rgb(51, 91, 112)"; -const negative = "rgb(203, 55, 74)"; -const positive = "rgb(0, 138, 33)"; -const tag = "rgb(0, 126, 69)"; -const status = "rgb(51, 91, 112)"; -const transparent = "rgba(0, 0, 0, 0)"; -const colorsSemanticCaution500 = "rgb(239, 103, 0)"; -const blackOpacity65 = "rgba(0, 0, 0, 0.65)"; -const brilliantGreenShade20 = "rgb(0, 176, 0)"; -const red = "rgb(255, 0, 0)"; -const hexBlue = "#123456"; -const green = "rgb(0, 123, 10)"; -const small = "S"; -const medium = "M"; -const large = "L"; -const extraLarge = "XL"; - -context("Testing Pill component", () => { - describe("when focused", () => { - it.each(["S", "M", "L", "XL"] as PillProps["size"][])( - "should have the expected styling when size is %s and focusRedesignOptOut is false", - (size) => { - CypressMountWithProviders( - {}}> - Pill - - ); - - pillCloseIcon() - .focus() - .then(() => { - pillCloseIcon() - .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.each(["S", "M", "L", "XL"] as PillProps["size"][])( - "should have the expected styling when size is %s and focusRedesignOptOut is true", - (size) => { - CypressMountWithProviders( - {}}> - Pill - , - undefined, - undefined, - { - focusRedesignOptOut: true, - } - ); - pillCloseIcon() - .focus() - .then(() => { - pillCloseIcon().should( - "have.css", - "box-shadow", - "rgb(255, 188, 25) 0px 0px 0px 3px" - ); - }); - } - ); - }); - - describe("should render Pill component with props", () => { - it.each(specialCharacters)( - "should render Pill using %s as label", - (label) => { - CypressMountWithProviders({label}); - - pillPreview().should("have.text", label); - } - ); - - it.each([ - ["warning", warning], - ["neutral", neutral], - ["negative", negative], - ["positive", positive], - ] as [PillProps["colorVariant"], string][])( - "should render Pill component with colorVariant set to %s", - (color, output) => { - CypressMountWithProviders( - - Pill - - ); - - pillPreview() - .then((elem) => { - checkOutlineCss(elem, 1, "border", "solid", output); - }) - .should("have.css", "background-color", transparent); - } - ); - - it("should render Pill component with data-element", () => { - CypressMountWithProviders(); - pillPreview().should("have.attr", "data-element", testData); - }); - - it("should render Pill component with data-role", () => { - CypressMountWithProviders(); - pillPreview().should("have.attr", "data-role", testData); - }); - - it.each([ - ["warning", warning], - ["neutral", neutral], - ["negative", negative], - ["positive", positive], - ] as [PillProps["colorVariant"], string][])( - "should render Pill component with color fill to %s", - (color, output) => { - CypressMountWithProviders( - - Pill - - ); - - pillPreview() - .then((elem) => { - checkOutlineCss(elem, 1, "border", "solid", output); - }) - .should("have.css", "background-color", output); - } - ); - - it.each([ - ["tag", tag], - ["status", status], - ] as [PillProps["pillRole"], string][])( - "should render Pill component with pillRole set to %s", - (role, output) => { - CypressMountWithProviders( - {role} - ); - pillPreview().then((elem) => { - checkOutlineCss(elem, 1, "border", "solid", output); - }); - } - ); - - it.each([ - [ - "colorsSemanticCaution500", - colorsSemanticCaution500, - "rgb(239, 103, 0)", - ], - ["blackOpacity65", blackOpacity65, "rgba(0, 0, 0, 0.65)"], - ["brilliantGreenShade20", brilliantGreenShade20, "rgb(0, 176, 0)"], - ["red", red, "rgb(255, 0, 0)"], - ["#123456", hexBlue, "rgb(18, 52, 86)"], - [green, green, "rgb(0, 123, 10)"], - ])( - "should render Pill component with borderColor set to %s", - (colourDescription, color, output) => { - CypressMountWithProviders( - - Pill - - ); - - pillPreview().then((elem) => { - checkOutlineCss(elem, 1, "border", "solid", output); - }); - } - ); - - it.each(["20px", "100px"])( - "should render Pill component with maxWidth set to %s", - (maxWidth) => { - CypressMountWithProviders( - Pill with a long label - ); - - pillPreview().should("have.css", "max-width", maxWidth); - } - ); - - it.each([ - [small, "16px", "12px", "0px 8px"], - [medium, "20px", "14px", "0px 8px"], - [large, "24px", "14px", "0px 8px"], - [extraLarge, "28px", "16px", "0px 12px"], - ] as [PillProps["size"], string, string, string][])( - "should render Pill component with size set to %s", - (size, height, fontSize, padding) => { - CypressMountWithProviders(Pill); - - pillPreview() - .should("have.css", "min-height", height) - .should("have.css", "line-height", height) - .should("have.css", "font-size", fontSize) - .should("have.css", "padding", padding); - } - ); - - it.each([ - [true, "break-spaces"], - [false, "nowrap"], - ])( - "should render Pill component with wrapText set to %s", - (booleanState, cssValue) => { - CypressMountWithProviders( - - Wrapped pill - - ); - - pillPreview() - .should("have.text", "Wrapped pill") - .should("have.css", "white-space", cssValue); - } - ); - - describe("should render Pill component and check events", () => { - it("should call the delete action after the CloseIcon is clicked", () => { - const callback: PillProps["onDelete"] = cy.stub().as("onDelete"); - - CypressMountWithProviders(); - - closeIconButton().click(); - cy.get("@onDelete").should("have.been.calledOnce"); - }); - - it("should call the click action after the Pill is clicked", () => { - const callback: PillProps["onClick"] = cy.stub().as("onClick"); - - CypressMountWithProviders(); - - pillPreview().click(); - cy.get("@onClick").should("have.been.calledOnce"); - }); - }); - - describe("Accessibility tests for Pill component", () => { - it.each(specialCharacters)( - "should render Pill using %s as label for accessibility tests", - (label) => { - CypressMountWithProviders({label}); - - cy.checkAccessibility(); - } - ); - - it.each([ - "warning", - "neutral", - "negative", - "positive", - ] as PillProps["colorVariant"][])( - "should render Pill component with colorVariant set to %s for accessibility tests", - (color) => { - CypressMountWithProviders( - - Pill - - ); - cy.checkAccessibility(); - } - ); - - it("should render Pill component with data-element for accessibility tests", () => { - CypressMountWithProviders(); - cy.checkAccessibility(); - }); - - it("should render Pill component with data-role for accessibility tests", () => { - CypressMountWithProviders(); - cy.checkAccessibility(); - }); - - it.each([ - "warning", - "neutral", - "negative", - "positive", - ] as PillProps["colorVariant"][])( - "should render Pill component with color fill to %s for accessibility tests", - (color) => { - CypressMountWithProviders( - - Pill - - ); - cy.checkAccessibility(); - } - ); - - it.each(["tag", "status"] as PillProps["pillRole"][])( - "should render Pill component with pillRole set to %s for accessibility tests", - (role) => { - CypressMountWithProviders( - {role} - ); - cy.checkAccessibility(); - } - ); - - it.each(["20px", "100px"])( - "should render Pill component with maxWidth set to %s for accessibility tests", - (maxWidth) => { - CypressMountWithProviders( - Pill with a long label - ); - cy.checkAccessibility(); - } - ); - - it.each([small, medium, large, extraLarge] as PillProps["size"][])( - "should render Pill component with size set to %s for accessibility tests", - (size) => { - CypressMountWithProviders(Pill); - cy.checkAccessibility(); - } - ); - - it.each([ - [true, "break-spaces"], - [false, "nowrap"], - ])( - "should render Pill component with wrapText set to %s for accessibility tests", - (booleanState) => { - CypressMountWithProviders( - - Wrapped pill - - ); - cy.checkAccessibility(); - } - ); - - it.each([ - colorsSemanticCaution500, - blackOpacity65, - brilliantGreenShade20, - red, - hexBlue, - green, - ])( - "should render Pill component with borderColor set to %s for accessibility tests", - (color) => { - CypressMountWithProviders( - - Pill - - ); - cy.checkAccessibility(); - } - ); - }); - }); - - it.each(["S", "M", "L", "XL"] as PillProps["size"][])( - "should have the expected border radius styling when size is %s", - (size) => { - CypressMountWithProviders( - {}}> - Pill - - ); - pillPreview().should("have.css", "border-radius", "2px"); - pillCloseIcon().should("have.css", "border-radius", "0px"); - pillCloseIcon() - .focus() - .then(() => { - pillCloseIcon().should( - "have.css", - "border-radius", - "0px 2px 2px 0px" - ); - }); - } - ); -}); diff --git a/playwright/components/pill/index.ts b/playwright/components/pill/index.ts index bebb06ef8b..ea7e5cec62 100644 --- a/playwright/components/pill/index.ts +++ b/playwright/components/pill/index.ts @@ -1,7 +1,6 @@ import { Page } from "playwright-core"; -import PILL_CLOSE_ICON from "./locators"; +import { PILL_PREVIEW, PILL_CLOSE_ICON } from "./locators"; // component preview locators -const pillCloseIcon = (page: Page) => page.locator(PILL_CLOSE_ICON); - -export default pillCloseIcon; +export const pillPreview = (page: Page) => page.locator(PILL_PREVIEW); +export const pillCloseIcon = (page: Page) => page.locator(PILL_CLOSE_ICON); diff --git a/playwright/components/pill/locators.ts b/playwright/components/pill/locators.ts index 5c38b0af5b..df7ebdb5de 100644 --- a/playwright/components/pill/locators.ts +++ b/playwright/components/pill/locators.ts @@ -1,4 +1,3 @@ // component preview locators -const PILL_CLOSE_ICON = '[data-element="close"]'; - -export default PILL_CLOSE_ICON; +export const PILL_PREVIEW = '[data-component="pill"]'; +export const PILL_CLOSE_ICON = '[data-element="close"]'; diff --git a/src/components/pill/components.test-pw.tsx b/src/components/pill/components.test-pw.tsx new file mode 100644 index 0000000000..fe7ea958a5 --- /dev/null +++ b/src/components/pill/components.test-pw.tsx @@ -0,0 +1,8 @@ +import React from "react"; +import Pill, { PillProps } from "."; + +const PillComponent = ({ children = "noop", ...args }: Partial) => { + return {children}; +}; + +export default PillComponent; diff --git a/src/components/pill/pill.pw.tsx b/src/components/pill/pill.pw.tsx new file mode 100644 index 0000000000..1939d2182a --- /dev/null +++ b/src/components/pill/pill.pw.tsx @@ -0,0 +1,412 @@ +import React from "react"; +import { test, expect } from "@playwright/experimental-ct-react17"; +import PillComponent from "./components.test-pw"; +import Pill, { PillProps } from "."; +import { + pillPreview, + pillCloseIcon, +} from "../../../playwright/components/pill"; +import { + checkCSSOutline, + checkAccessibility, +} from "../../../playwright/support/helper"; +import { CHARACTERS } from "../../../playwright/support/constants"; + +const specialCharacters = [CHARACTERS.DIACRITICS, CHARACTERS.SPECIALCHARACTERS]; +const testData = CHARACTERS.STANDARD; +const warning = "rgb(242, 133, 51)"; +const neutral = "rgb(51, 91, 112)"; +const negative = "rgb(203, 55, 74)"; +const positive = "rgb(0, 138, 33)"; +const tag = "rgb(0, 126, 69)"; +const status = "rgb(51, 91, 112)"; +const transparent = "rgba(0, 0, 0, 0)"; +const colorsSemanticCaution500 = "rgb(239, 103, 0)"; +const blackOpacity65 = "rgba(0, 0, 0, 0.65)"; +const brilliantGreenShade20 = "rgb(0, 176, 0)"; +const red = "rgb(255, 0, 0)"; +const hexBlue = "#123456"; +const green = "rgb(0, 123, 10)"; +const small = "S"; +const medium = "M"; +const large = "L"; +const extraLarge = "XL"; + +test.describe("should render Pill component with props", () => { + specialCharacters.forEach((label) => { + test(`should render label prop as ${label}`, async ({ mount, page }) => { + await mount({label}); + + await expect(pillPreview(page)).toHaveText(label); + }); + }); + + test(`should render data-element tag prop`, async ({ mount, page }) => { + await mount(); + + await expect(pillPreview(page)).toHaveAttribute("data-element", testData); + }); + + test(`should render data-role tag prop`, async ({ mount, page }) => { + await mount(); + + await expect(pillPreview(page)).toHaveAttribute("data-role", testData); + }); + + ([ + ["warning", warning], + ["neutral", neutral], + ["negative", negative], + ["positive", positive], + ] as const).forEach(([color, output]) => { + test(`should render colorVariant prop as ${color}`, async ({ + mount, + page, + }) => { + await mount(); + + await checkCSSOutline( + pillPreview(page), + "2px", + "border", + "solid", + output + ); + await expect(pillPreview(page)).toHaveCSS( + "background-color", + transparent + ); + }); + }); + + ([ + ["warning", warning], + ["neutral", neutral], + ["negative", negative], + ["positive", positive], + ] as const).forEach(([color, output]) => { + test(`should render colorVariant with color fill set as ${color}`, async ({ + mount, + page, + }) => { + await mount( + + ); + + await checkCSSOutline( + pillPreview(page), + "2px", + "border", + "solid", + output + ); + await expect(pillPreview(page)).toHaveCSS("background-color", output); + }); + }); + + ([ + ["tag", tag], + ["status", status], + ] as [PillProps["pillRole"], string][]).forEach(([role, output]) => { + test(`should render pillRole prop set as ${role}`, async ({ + mount, + page, + }) => { + await mount({role}); + + await checkCSSOutline( + pillPreview(page), + "2px", + "border", + "solid", + output + ); + }); + }); + + ([ + [colorsSemanticCaution500, "rgb(239, 103, 0)"], + [blackOpacity65, "rgba(0, 0, 0, 0.65)"], + [brilliantGreenShade20, "rgb(0, 176, 0)"], + [red, "rgb(255, 0, 0)"], + [green, "rgb(0, 123, 10)"], + [hexBlue, "rgb(18, 52, 86)"], + ] as const).forEach(([color, output]) => { + test(`should render borderColor prop set as ${output}`, async ({ + mount, + page, + }) => { + await mount( + + Pill + + ); + + await checkCSSOutline( + pillPreview(page), + "2px", + "border", + "solid", + output + ); + }); + }); + + ["20px", "100px"].forEach((maxWidth) => { + test(`should render maxWidth prop set to ${maxWidth}`, async ({ + mount, + page, + }) => { + await mount(Pill with a long label); + + const elementLocator = pillPreview(page); + await expect(elementLocator).toHaveCSS("max-width", maxWidth); + }); + }); + + ([ + [small, "16px", "12px", "0px 8px"], + [medium, "20px", "14px", "0px 8px"], + [large, "24px", "14px", "0px 8px"], + [extraLarge, "28px", "16px", "0px 12px"], + ] as const).forEach(([size, height, fontSize, padding]) => { + test(`should render size prop set as ${size}`, async ({ mount, page }) => { + await mount(Pill); + + const elementLocator = pillPreview(page); + await expect(elementLocator).toHaveCSS("min-height", height); + await expect(elementLocator).toHaveCSS("line-height", height); + await expect(elementLocator).toHaveCSS("font-size", fontSize); + await expect(elementLocator).toHaveCSS("padding", padding); + }); + }); + + ([ + [true, "break-spaces"], + [false, "nowrap"], + ] as const).forEach(([booleanState, cssValue]) => { + test(`should render wrapText prop set as ${booleanState}`, async ({ + mount, + page, + }) => { + await mount( + + Wrapped pill + + ); + + const elementLocator = pillPreview(page); + await expect(elementLocator).toHaveText("Wrapped pill"); + await expect(elementLocator).toHaveCSS("white-space", cssValue); + }); + }); +}); + +test.describe("should check focus outlines and border radius", () => { + ([small, medium, large, extraLarge] as PillProps["size"][]).forEach( + (size) => { + test(`should have the expected styling when size is ${size} and focusRedesignOptOut is false`, async ({ + mount, + page, + }) => { + await mount( + {}}> + Pill + + ); + + const elementLocator = pillCloseIcon(page); + await elementLocator.focus(); + await expect(elementLocator).toHaveCSS( + "box-shadow", + "rgb(255, 188, 25) 0px 0px 0px 3px, rgba(0, 0, 0, 0.9) 0px 0px 0px 6px" + ); + await expect(elementLocator).toHaveCSS( + "outline", + "rgba(0, 0, 0, 0) solid 3px" + ); + }); + } + ); + + ([small, medium, large, extraLarge] as PillProps["size"][]).forEach( + (size) => { + test(`should have the expected styling when size is ${size} and focusRedesignOptOut is true`, async ({ + mount, + page, + }) => { + await mount( + {}}> + Pill + , + { + hooksConfig: { focusRedesignOptOut: true }, + } + ); + + const elementLocator = pillCloseIcon(page); + await elementLocator.focus(); + await expect(elementLocator).toHaveCSS( + "box-shadow", + "rgb(255, 188, 25) 0px 0px 0px 3px" + ); + }); + } + ); + + ([small, medium, large, extraLarge] as PillProps["size"][]).forEach( + (size) => { + test(`should have the expected border radius styling when size is ${size}`, async ({ + mount, + page, + }) => { + await mount( + {}}> + Pill + + ); + + const pillPreviewLocator = pillPreview(page); + await expect(pillPreviewLocator).toHaveCSS("border-radius", "2px"); + + const elementLocator = pillCloseIcon(page); + await expect(elementLocator).toHaveCSS("border-radius", "0px"); + await elementLocator.focus(); + await expect(elementLocator).toHaveCSS( + "border-radius", + "0px 2px 2px 0px" + ); + }); + } + ); +}); + +test.describe("should check for action events", () => { + test(`should call the delete action after the CloseIcon is clicked`, async ({ + mount, + page, + }) => { + let callbackCount = 0; + await mount( + { + callbackCount += 1; + }} + /> + ); + + const cross = pillCloseIcon(page); + await cross.click(); + expect(callbackCount).toBe(1); + }); + + test(`should call the click action after the Pill is clicked`, async ({ + mount, + page, + }) => { + let callbackCount = 0; + await mount( + { + callbackCount += 1; + }} + /> + ); + + const cross = pillPreview(page); + await cross.click(); + expect(callbackCount).toBe(1); + }); +}); + +test.describe("should check for Accessibility tests", () => { + specialCharacters.forEach((label) => { + test(`should render label as ${label} for accessibility`, async ({ + mount, + page, + }) => { + await mount({label}); + + await checkAccessibility(page); + }); + }); + + (["warning", "neutral", "negative", "positive"] as const).forEach((color) => { + test(`should render colorVariant as ${color} for accessibility`, async ({ + mount, + page, + }) => { + await mount(); + + await checkAccessibility(page); + }); + }); + + (["tag", "status"] as const).forEach((role) => { + test(`should render pillRole prop set as ${role} for accessibility`, async ({ + mount, + page, + }) => { + await mount({role}); + + await checkAccessibility(page); + }); + }); + + (["warning", "neutral", "negative", "positive"] as const).forEach((color) => { + test(`should render colorVariant with fill color as ${color} for accessibility`, async ({ + mount, + page, + }) => { + await mount( + + ); + + await checkAccessibility(page); + }); + }); + + ["20px", "100px"].forEach((maxWidth) => { + test(`should render maxWidth prop set as ${maxWidth} for accessibility`, async ({ + mount, + page, + }) => { + await mount(Pill with a long label); + + await checkAccessibility(page); + }); + }); + + ([small, medium, large, extraLarge] as const).forEach((size) => { + test(`should render size prop set as ${size} for accessibility`, async ({ + mount, + page, + }) => { + await mount(Pill); + + await checkAccessibility(page); + }); + }); + + ([ + colorsSemanticCaution500, + blackOpacity65, + brilliantGreenShade20, + red, + hexBlue, + green, + ] as const).forEach((color) => { + test(`should render borderColor set as ${color} for accessibility`, async ({ + mount, + page, + }) => { + await mount( + + Pill + + ); + + await checkAccessibility(page); + }); + }); +});