diff --git a/cypress/components/tooltip/tooltip.cy.tsx b/cypress/components/tooltip/tooltip.cy.tsx
deleted file mode 100644
index b4c876db14..0000000000
--- a/cypress/components/tooltip/tooltip.cy.tsx
+++ /dev/null
@@ -1,274 +0,0 @@
-import React from "react";
-import CypressMountWithProviders from "../../support/component-helper/cypress-mount";
-import { TooltipProps } from "../../../src/components/tooltip";
-import * as testStories from "../../../src/components/tooltip/tooltip-test.stories";
-import * as stories from "../../../src/components/tooltip/tooltip.stories";
-import {
- tooltipPreview,
- tooltipTrigger,
- tooltipTriggerToggle,
-} from "../../locators/tooltip/index";
-import {
- SIZE,
- COLOR,
- CHARACTERS,
-} from "../../support/component-helper/constants";
-import { assertCssValueIsApproximately } from "../../support/component-helper/common-steps";
-import { getDataElementByValue } from "../../locators";
-import { TooltipPositions } from "../../../src/components/tooltip/tooltip.config";
-
-const testData = [CHARACTERS.DIACRITICS, CHARACTERS.SPECIALCHARACTERS];
-const backgroundColors = [COLOR.ORANGE, COLOR.RED, COLOR.BLACK, COLOR.BROWN];
-
-context("Tests for Tooltip component", () => {
- describe("should check Tooltip component properties", () => {
- it.each(testData)(
- "should check %s as message for Tooltip component",
- (message) => {
- CypressMountWithProviders(
-
- );
- tooltipPreview().should("have.text", message);
- }
- );
-
- it.each(testData)("should check %s as Id for Tooltip component", (id) => {
- CypressMountWithProviders();
- tooltipPreview().should("have.id", id);
- });
-
- it.each([
- [true, "be.visible"],
- [false, "not.exist"],
- ])(
- "should check when tooltip visibility is %s for Tooltip component",
- (bool, state) => {
- CypressMountWithProviders(
-
- );
- tooltipPreview().should(state);
- }
- );
-
- it.each(["bottom", "left", "right", "top"] as TooltipProps["position"][])(
- "should check %s position of tooltip for Tooltip component",
- (position) => {
- CypressMountWithProviders(
-
- <>{`This tooltip is positioned ${position}`}>
-
- );
- tooltipPreview().should("be.visible").and("have.css", position);
- }
- );
-
- it.each(["undefined", "error"])(
- "should check %s type for Tooltip component",
- (type) => {
- CypressMountWithProviders();
- tooltipPreview().should("have.attr", "type", type);
- }
- );
-
- it.each(backgroundColors)(
- "should check tooltip background-color as %s for Tooltip component",
- (color) => {
- CypressMountWithProviders(
-
- );
- tooltipPreview().should("have.css", "background-color", color);
- }
- );
-
- it.each(backgroundColors)(
- "should check tooltip font color as %s for Tooltip component",
- (color) => {
- CypressMountWithProviders(
-
- );
- tooltipPreview().should("have.css", "color", color);
- }
- );
-
- it.each([
- [SIZE.MEDIUM, 14],
- [SIZE.LARGE, 16],
- ] as [TooltipProps["size"], number][])(
- "should check %s size for Tooltip component",
- (size, fontSize) => {
- CypressMountWithProviders();
- tooltipPreview().should("have.css", "font-size", `${fontSize}px`);
- }
- );
-
- it.each([
- ["left", "bottom", "top"],
- ["top", "bottom", "top"],
- ["left", "top", "bottom"],
- ["bottom", "top", "bottom"],
- ["bottom", "left", "bottom"],
- ["bottom", "right", "bottom"],
- ["top", "left", "top"],
- ["top", "right", "top"],
- ["right", "bottom", "right"],
- ["right", "top", "right"],
- ] as [TooltipPositions, TooltipProps["position"], Cypress.PositionType][])(
- "should check flip position to the %s when tooltip position is %s and scrolling to the %s side for Tooltip component",
- (flipPosition, tooltipPosition, scrollPosition) => {
- CypressMountWithProviders(
-
-
-
- );
- cy.viewport(700, 120);
- cy.scrollTo(scrollPosition);
- tooltipPreview().should("have.attr", "data-placement", flipPosition);
- }
- );
-
- describe.each(["top", "bottom", "right", "left"] as NonNullable<
- TooltipProps["position"]
- >[])("when tooltip has %s position and", (position) => {
- it.each([
- [SIZE.SMALL, { top: 15, bottom: 631, left: 47, right: 1040 }],
- [SIZE.MEDIUM, { top: 14, bottom: 630, left: 44, right: 1037 }],
- [SIZE.LARGE, { top: 10, bottom: 626, left: 40, right: 1033 }],
- ] as [TooltipProps["inputSize"], { top: number; bottom: number; left: number; right: number }][])(
- "when inputSize is %s should have correct styles applied",
- (inputSize, offset) => {
- CypressMountWithProviders(
-
- );
- tooltipPreview().then(($el) => {
- assertCssValueIsApproximately($el, position, offset[position]);
- Cypress.dom.isVisible($el);
- });
- }
- );
- });
-
- it("should show tooltip when target is hovered", () => {
- CypressMountWithProviders();
- tooltipPreview().should("not.exist");
- tooltipTrigger().trigger("mouseenter");
- tooltipPreview().should("be.visible");
- });
-
- it("should hide tooltip when mouse leaves target", () => {
- CypressMountWithProviders();
- tooltipPreview().should("not.exist");
- tooltipTrigger().trigger("mouseenter");
- tooltipPreview().should("be.visible");
- tooltipTrigger().trigger("mouseleave");
- tooltipPreview().should("not.exist");
- });
-
- it("should show tooltip when target is focused", () => {
- CypressMountWithProviders();
- tooltipPreview().should("not.exist");
- tooltipTrigger().focus();
- tooltipPreview().should("be.visible");
- });
-
- it("should hide tooltip when target is blurred", () => {
- CypressMountWithProviders();
- tooltipPreview().should("not.exist");
- tooltipTrigger().focus();
- tooltipPreview().should("be.visible");
- tooltipTrigger().blur();
- tooltipPreview().should("not.exist");
- });
-
- it("new tooltip target should still trigger tooltip visibility", () => {
- CypressMountWithProviders(
-
- );
- tooltipTrigger().should("have.text", "Target");
-
- tooltipTrigger().trigger("mouseenter");
- tooltipPreview().should("be.visible");
- tooltipTrigger().trigger("mouseleave");
- tooltipPreview().should("not.exist");
-
- tooltipTriggerToggle().click();
- tooltipTrigger().should("have.text", "Secondary target");
-
- tooltipTrigger().trigger("mouseenter");
- tooltipPreview().should("be.visible");
- tooltipTrigger().trigger("mouseleave");
- tooltipPreview().should("not.exist");
- });
- });
-
- describe("Accessibility tests for Tooltip component", () => {
- it("should pass accessibility tests for Tooltip Default story", () => {
- CypressMountWithProviders();
-
- getDataElementByValue("main-text").click();
- cy.checkAccessibility();
- });
-
- it("should pass accessibility tests for Tooltip Controlled story", () => {
- CypressMountWithProviders();
-
- getDataElementByValue("main-text").eq(0).click();
- cy.checkAccessibility();
- });
-
- it.each([
- ["top", 0],
- ["bottom", 1],
- ["left", 2],
- ["right", 3],
- ])(
- "should pass accessibility tests for Tooltip Positioning story %s position",
- (position, button) => {
- CypressMountWithProviders();
-
- getDataElementByValue("main-text").eq(button).click();
- cy.checkAccessibility();
- }
- );
-
- it("should pass accessibility tests for Tooltip FlipBehaviourOverrides story", () => {
- CypressMountWithProviders();
-
- cy.checkAccessibility();
- });
-
- it("should pass accessibility tests for Tooltip LargeTooltip story", () => {
- CypressMountWithProviders();
-
- getDataElementByValue("main-text").click();
- cy.checkAccessibility();
- });
-
- it("should pass accessibility tests for Tooltip Types story", () => {
- CypressMountWithProviders();
-
- getDataElementByValue("main-text").eq(1).click();
-
- getDataElementByValue("main-text").eq(2).click();
- cy.checkAccessibility();
- });
-
- it("should pass accessibility tests for Tooltip ColorOverrides story", () => {
- CypressMountWithProviders();
-
- getDataElementByValue("main-text").click();
- cy.checkAccessibility();
- });
-
- it("should render the Tooltip with the expected border radius styling", () => {
- CypressMountWithProviders();
- tooltipPreview().should("have.css", "border-radius", "4px");
- });
- });
-});
diff --git a/playwright/components/tooltip/index.ts b/playwright/components/tooltip/index.ts
new file mode 100644
index 0000000000..8bf3f0df85
--- /dev/null
+++ b/playwright/components/tooltip/index.ts
@@ -0,0 +1,9 @@
+import type { Page } from "@playwright/test";
+import { TOOLTIP_PREVIEW } from "./locators";
+
+// component preview locators
+const tooltipPreview = (page: Page) => {
+ return page.locator(TOOLTIP_PREVIEW);
+};
+
+export default tooltipPreview;
diff --git a/playwright/components/tooltip/locators.ts b/playwright/components/tooltip/locators.ts
new file mode 100644
index 0000000000..fd44fb8309
--- /dev/null
+++ b/playwright/components/tooltip/locators.ts
@@ -0,0 +1,4 @@
+// component preview locators
+const TOOLTIP_PREVIEW = '[data-element="tooltip"]';
+
+export default TOOLTIP_PREVIEW;
diff --git a/src/components/tooltip/components.test-pw.tsx b/src/components/tooltip/components.test-pw.tsx
new file mode 100644
index 0000000000..0c4d983c01
--- /dev/null
+++ b/src/components/tooltip/components.test-pw.tsx
@@ -0,0 +1,213 @@
+import React, { forwardRef, useState } from "react";
+import Tooltip, { TooltipProps } from ".";
+import Button, { ButtonProps } from "../button";
+import { SecondaryButton } from "../button/button.stories";
+import Box from "../box";
+import { TooltipPositions } from "./tooltip.config";
+
+export const TooltipComponent = ({
+ message,
+ ...props
+}: Partial) => (
+
+
+
+
+
+);
+
+export const UncontrolledTooltipComponent = () => (
+
+
+
+
+
+);
+
+export const TooltipWithChangingTargetComponent = () => {
+ const [displayOther, setDisplayOther] = useState(false);
+
+ return (
+ <>
+
+
+ {displayOther ? (
+ Secondary target
+ ) : (
+
+ )}
+
+ >
+ );
+};
+
+export const Default = () => {
+ const Component = forwardRef(
+ ({ children }: ButtonProps, ref) => (
+
+ )
+ );
+ Component.displayName = "Example Button";
+ return (
+
+
+ target
+
+
+ );
+};
+
+export const Controlled = () => {
+ const [isVisible, setIsVisible] = useState(false);
+ const Component = forwardRef(
+ ({ children }: ButtonProps, ref) => (
+
+ )
+ );
+ Component.displayName = "Example Button";
+ return (
+ <>
+
+
+
+
+
+ target
+
+
+ >
+ );
+};
+
+export const Positioning = () => {
+ const [position, setPosition] = useState("top");
+ const Component = forwardRef(
+ ({ children }: ButtonProps, ref) => (
+
+ )
+ );
+ Component.displayName = "Example Button";
+ return (
+ <>
+
+
+
+
+
+
+
+
+ target
+
+
+ >
+ );
+};
+
+export const FlipBehaviourOverrides = () => {
+ const Component = forwardRef(
+ ({ children }: ButtonProps, ref) => (
+
+ )
+ );
+ Component.displayName = "Example Button";
+ return (
+
+
+ target
+
+
+ );
+};
+
+export const LargeTooltip = () => {
+ const Component = forwardRef(
+ ({ children }: ButtonProps, ref) => (
+
+ )
+ );
+ Component.displayName = "Example Button";
+ return (
+
+
+ target
+
+
+ );
+};
+
+export const Types = () => {
+ const [type, setType] = useState(undefined);
+ const Component = forwardRef(
+ ({ children }: ButtonProps, ref) => (
+
+ )
+ );
+ Component.displayName = "Example Button";
+ return (
+ <>
+
+
+
+
+
+
+ target
+
+
+ >
+ );
+};
+
+export const ColorOverrides = () => {
+ const Component = forwardRef(
+ ({ children }: ButtonProps, ref) => (
+
+ )
+ );
+ Component.displayName = "Example Button";
+ return (
+
+
+ target
+
+
+ );
+};
diff --git a/src/components/tooltip/tooltip-test.stories.tsx b/src/components/tooltip/tooltip-test.stories.tsx
index 75857beeec..a8897dd3b9 100644
--- a/src/components/tooltip/tooltip-test.stories.tsx
+++ b/src/components/tooltip/tooltip-test.stories.tsx
@@ -149,53 +149,3 @@ const SecondaryButton = forwardRef(
)
);
SecondaryButton.displayName = "Tooltip";
-
-export const TooltipComponent = ({
- message,
- ...props
-}: Partial) => (
-
-
-
-
-
-);
-
-export const UncontrolledTooltipComponent = () => (
-
-
-
-
-
-);
-
-export const TooltipWithChangingTargetComponent = () => {
- const [displayOther, setDisplayOther] = useState(false);
-
- return (
- <>
-
-
- {displayOther ? (
- Secondary target
- ) : (
-
- )}
-
- >
- );
-};
diff --git a/src/components/tooltip/tooltip.pw.tsx b/src/components/tooltip/tooltip.pw.tsx
new file mode 100644
index 0000000000..a81aa2cdfd
--- /dev/null
+++ b/src/components/tooltip/tooltip.pw.tsx
@@ -0,0 +1,365 @@
+import React from "react";
+import { test, expect } from "@playwright/experimental-ct-react17";
+import {
+ TooltipComponent,
+ UncontrolledTooltipComponent,
+ Default,
+ Controlled,
+ Positioning,
+ FlipBehaviourOverrides,
+ LargeTooltip,
+ Types,
+ ColorOverrides,
+} from "./components.test-pw";
+import Box from "../../../src/components/box";
+import { tooltipPreview } from "../../../playwright/components/tooltip";
+import { TooltipPositions } from "../../../src/components/tooltip/tooltip.config";
+import {
+ checkAccessibility,
+ assertCssValueIsApproximately,
+} from "../../../playwright/support/helper";
+import { SIZE, COLOR, CHARACTERS } from "../../../playwright/support/constants";
+import { TooltipProps } from "../../../src/components/tooltip/tooltip.component";
+import { getDataElementByValue } from "../../../playwright/components";
+
+const backgroundColors = [COLOR.ORANGE, COLOR.RED, COLOR.BLACK, COLOR.BROWN];
+const testData = [CHARACTERS.DIACRITICS, CHARACTERS.SPECIALCHARACTERS];
+
+test.describe("Tooltip component", () => {
+ testData.forEach((message) => {
+ test(`check when message prop is set as ${message}`, async ({
+ mount,
+ page,
+ }) => {
+ await mount();
+
+ await expect(tooltipPreview(page)).toHaveText(message);
+ });
+ });
+
+ testData.forEach((id) => {
+ test(`check when id prop is set as ${id}`, async ({ mount, page }) => {
+ await mount();
+
+ await expect(tooltipPreview(page)).toHaveId(id);
+ });
+ });
+
+ [true, false].forEach((boolVal) => {
+ test(`check when tooltip visibility is set as ${boolVal}`, async ({
+ mount,
+ page,
+ }) => {
+ await mount();
+
+ if (boolVal === true) {
+ await expect(tooltipPreview(page)).toBeVisible();
+ } else {
+ await expect(tooltipPreview(page)).not.toBeVisible();
+ }
+ });
+ });
+
+ (["bottom", "left", "right", "top"] as [
+ "bottom",
+ "left",
+ "right",
+ "top"
+ ]).forEach((position) => {
+ test(`check when tooltip position is set as ${position}`, async ({
+ mount,
+ page,
+ }) => {
+ await mount(
+
+ <>{`This tooltip is positioned ${position}`}>
+
+ );
+
+ await expect(tooltipPreview(page)).toBeVisible();
+ await expect(tooltipPreview(page)).toHaveAttribute(
+ "data-placement",
+ position
+ );
+ });
+ });
+
+ ["undefined", "error"].forEach((type) => {
+ test(`check when type prop is set as ${type}`, async ({ mount, page }) => {
+ await mount();
+
+ await expect(tooltipPreview(page)).toHaveAttribute("type", type);
+ });
+ });
+
+ backgroundColors.forEach((color) => {
+ test(`check when tooltip background color is set as ${color}`, async ({
+ mount,
+ page,
+ }) => {
+ await mount();
+
+ await expect(tooltipPreview(page)).toHaveCSS("background-color", color);
+ });
+ });
+
+ backgroundColors.forEach((color) => {
+ test(`check when tooltip font color is set as ${color}`, async ({
+ mount,
+ page,
+ }) => {
+ await mount();
+
+ await expect(tooltipPreview(page)).toHaveCSS("color", color);
+ });
+ });
+
+ ([
+ [SIZE.MEDIUM, 14],
+ [SIZE.LARGE, 16],
+ ] as [TooltipProps["size"], number][]).forEach(([size, fontSize]) => {
+ test(`check when size prop is set as ${size}`, async ({ mount, page }) => {
+ await mount();
+
+ await expect(tooltipPreview(page)).toHaveCSS(
+ "font-size",
+ `${fontSize}px`
+ );
+ });
+ });
+
+ ([
+ ["left", "bottom"],
+ ["top", "bottom"],
+ ["left", "top"],
+ ["bottom", "top"],
+ ["bottom", "left"],
+ ["bottom", "right"],
+ ["top", "left"],
+ ["top", "right"],
+ ["right", "bottom"],
+ ["right", "top"],
+ ] as [TooltipPositions, TooltipProps["position"]][]).forEach(
+ ([flipPosition, tooltipPosition]) => {
+ test(`check flip position to the ${flipPosition} when tooltip position is set as ${tooltipPosition}`, async ({
+ mount,
+ page,
+ }) => {
+ await page.setViewportSize({ width: 700, height: 120 });
+ await mount(
+
+
+
+ );
+
+ await expect(tooltipPreview(page)).toHaveAttribute(
+ "data-placement",
+ flipPosition
+ );
+ });
+ }
+ );
+
+ ([
+ [SIZE.SMALL, 15],
+ [SIZE.MEDIUM, 14],
+ [SIZE.LARGE, 10],
+ ] as [TooltipProps["inputSize"], number][]).forEach(([inputSize, offset]) => {
+ test(`should have correct styles applied when inputSize is ${inputSize} and tooltip position is set as top`, async ({
+ mount,
+ page,
+ }) => {
+ await mount(
+
+ );
+
+ const element = tooltipPreview(page);
+ await assertCssValueIsApproximately(element, "top", offset);
+ });
+ });
+
+ ([
+ [SIZE.SMALL, 5],
+ [SIZE.MEDIUM, 6],
+ [SIZE.LARGE, 10],
+ ] as [TooltipProps["inputSize"], number][]).forEach(([inputSize, offset]) => {
+ test(`should have correct styles applied when inputSize is ${inputSize} and tooltip position is set as bottom`, async ({
+ mount,
+ page,
+ }) => {
+ await mount(
+
+ );
+
+ const buttonRect = await page
+ .getByRole("button")
+ .evaluate((element) => element.getBoundingClientRect());
+ const element = tooltipPreview(page);
+
+ await assertCssValueIsApproximately(
+ element,
+ "top",
+ buttonRect.top + buttonRect.height + offset
+ );
+ });
+ });
+
+ ([
+ [SIZE.SMALL, 47],
+ [SIZE.MEDIUM, 44],
+ [SIZE.LARGE, 40],
+ ] as [TooltipProps["inputSize"], number][]).forEach(([inputSize, offset]) => {
+ test(`should have correct styles applied when inputSize is ${inputSize} and tooltip position is set as left`, async ({
+ mount,
+ page,
+ }) => {
+ await mount(
+
+ );
+
+ const element = tooltipPreview(page);
+
+ await assertCssValueIsApproximately(element, "left", offset);
+ });
+ });
+
+ ([
+ [SIZE.SMALL, 5],
+ [SIZE.MEDIUM, 8],
+ [SIZE.LARGE, 12],
+ ] as [TooltipProps["inputSize"], number][]).forEach(([inputSize, offset]) => {
+ test(`should have correct styles applied when inputSize is ${inputSize} and tooltip position is set as right`, async ({
+ mount,
+ page,
+ }) => {
+ await mount(
+
+ );
+
+ const buttonRect = await page
+ .getByRole("button")
+ .evaluate((element) => element.getBoundingClientRect());
+ const element = tooltipPreview(page);
+
+ await assertCssValueIsApproximately(
+ element,
+ "left",
+ buttonRect.left + buttonRect.width + offset
+ );
+ });
+ });
+
+ test(`should show tooltip when target is hovered`, async ({
+ mount,
+ page,
+ }) => {
+ await mount();
+
+ await expect(tooltipPreview(page)).not.toBeVisible();
+ const tooltipElement = page.getByRole("button");
+ await tooltipElement.hover();
+ await expect(tooltipPreview(page)).toBeVisible();
+ });
+
+ test(`should have the expected border radius styling`, async ({
+ mount,
+ page,
+ }) => {
+ await mount();
+
+ await expect(tooltipPreview(page)).toHaveCSS("border-radius", "4px");
+ });
+});
+
+test.describe("Accessibility tests for Tooltip component", () => {
+ test(`check accessibility tests for Default story`, async ({
+ mount,
+ page,
+ }) => {
+ await mount();
+
+ await checkAccessibility(page);
+ });
+
+ test(`check accessibility tests for Controlled story`, async ({
+ mount,
+ page,
+ }) => {
+ await mount();
+
+ expect(getDataElementByValue(page, "main-text").nth(0).click());
+ await checkAccessibility(page);
+ });
+
+ test(`check accessibility tests for FlipBehaviourOverrides story`, async ({
+ mount,
+ page,
+ }) => {
+ await mount();
+
+ await checkAccessibility(page);
+ });
+
+ ([
+ ["top", 0],
+ ["bottom", 1],
+ ["left", 2],
+ ["right", 3],
+ ] as [string, number][]).forEach(([position, button]) => {
+ test(`check accessibility tests for Positioning story when position is set as ${position}`, async ({
+ mount,
+ page,
+ }) => {
+ await mount();
+
+ expect(getDataElementByValue(page, "main-text").nth(button).click());
+ await checkAccessibility(page);
+ });
+ });
+
+ test(`check accessibility tests for LargeTooltip story`, async ({
+ mount,
+ page,
+ }) => {
+ await mount();
+
+ expect(getDataElementByValue(page, "main-text").click());
+ await checkAccessibility(page);
+ });
+
+ ([
+ ["undefined", 0],
+ ["error", 1],
+ ] as [string, number][]).forEach(([type, button]) => {
+ test(`check accessibility tests when type is set as ${type}`, async ({
+ mount,
+ page,
+ }) => {
+ await mount();
+
+ expect(getDataElementByValue(page, "main-text").nth(button).click());
+ await checkAccessibility(page);
+ });
+ });
+
+ test(`check accessibility tests for ColorOverrides story`, async ({
+ mount,
+ page,
+ }) => {
+ await mount();
+
+ expect(getDataElementByValue(page, "main-text").click());
+ await checkAccessibility(page);
+ });
+});