Skip to content

Commit edc44ad

Browse files
committed
replace PopupMenu cypress tests with playwright tests
1 parent dc8284d commit edc44ad

4 files changed

Lines changed: 158 additions & 115 deletions

File tree

vuu-ui/packages/vuu-popups/src/__tests__/__component__/PopupMenu.cy.tsx

Lines changed: 0 additions & 115 deletions
This file was deleted.
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
import { test } from "@playwright/experimental-ct-react";
2+
import { expect } from "../../../../../playwright/customAssertions";
3+
import { DefaultPopupMenu } from "../../../../../showcase/src/examples/Popups/PopupMenu.examples";
4+
5+
test.describe("Given a PopupMenu", () => {
6+
test("should apply correct aria attribues", async ({ mount, page }) => {
7+
await mount(<DefaultPopupMenu />);
8+
const button = page.getByRole("button", { name: "Popup menu" });
9+
await expect(button).toHaveAttribute("aria-haspopup", "menu");
10+
await expect(button).toHaveAttribute("aria-expanded", "false");
11+
await expect(page.getByRole("menu")).not.toBeAttached();
12+
});
13+
test.describe("WHEN clicked", () => {
14+
test("THEN popup is displayed and aria attributes updated", async ({
15+
mount,
16+
page,
17+
}) => {
18+
await mount(<DefaultPopupMenu />);
19+
const button = page.getByRole("button", { name: "Popup menu" });
20+
await button.click();
21+
await expect(button).toHaveAttribute("aria-expanded", "true");
22+
await expect(page.getByRole("menu")).toBeInViewport();
23+
});
24+
});
25+
26+
test.describe("WHEN keyboard navigation used", () => {
27+
test.describe("AND user tabs to PopupMenu", () => {
28+
test("THEN PopupMenu receives focus", async ({ mount, page }) => {
29+
await mount(<DefaultPopupMenu />);
30+
const button = page.getByRole("button", { name: "Popup menu" });
31+
const input = page.getByTestId("input");
32+
await input.click();
33+
await input.press("Tab");
34+
await expect(button).toBeFocused();
35+
});
36+
});
37+
test.describe("AND WHEN ENTER is pressed", () => {
38+
test("THEN Menu is displayed", async ({ mount, page }) => {
39+
await mount(<DefaultPopupMenu />);
40+
const input = page.getByTestId("input");
41+
await input.click();
42+
await input.press("Tab");
43+
const button = page.getByRole("button", { name: "Popup menu" });
44+
await expect(button).toBeFocused();
45+
await button.press("Enter");
46+
47+
await expect(button).toHaveAttribute("aria-expanded", "true");
48+
await expect(page.getByRole("menu")).toBeInViewport();
49+
// when we use keyboard to activate trigger, first menuitem is focused
50+
await expect(
51+
page.getByRole("menuitem", { name: "Menu Item 1" }),
52+
).toBeFocused();
53+
});
54+
});
55+
test.describe("OR WHEN Space is pressed", () => {
56+
test("THEN Menu is displayed", async ({ mount, page }) => {
57+
await mount(<DefaultPopupMenu />);
58+
const input = page.getByTestId("input");
59+
await input.click();
60+
await input.press("Tab");
61+
const button = page.getByRole("button", { name: "Popup menu" });
62+
await expect(button).toBeFocused();
63+
button.press("Space");
64+
65+
await expect(button).toHaveAttribute("aria-expanded", "true");
66+
await expect(page.getByRole("menu")).toBeInViewport();
67+
});
68+
});
69+
test.describe("AND if Escape is then pressed", () => {
70+
test("THEN Menu is hidden", async ({ mount, page }) => {
71+
await mount(<DefaultPopupMenu />);
72+
const button = page.getByRole("button", { name: "Popup menu" });
73+
const input = page.getByTestId("input");
74+
await input.click();
75+
await input.press("Tab");
76+
await expect(button).toBeFocused();
77+
await button.press("Enter");
78+
79+
const menuItem = page.getByRole("menuitem", { name: "Menu Item 1" });
80+
await expect(menuItem).toBeFocused();
81+
menuItem.press("Escape");
82+
83+
await expect(button).toHaveAttribute("aria-expanded", "false");
84+
await expect(page.getByRole("menu")).not.toBeAttached();
85+
await expect(button).toBeFocused();
86+
});
87+
});
88+
89+
test.describe("OR if user clicks outside the PopupMenu", () => {
90+
test("THEN Menu is hidden", async ({ mount, page }) => {
91+
await mount(<DefaultPopupMenu />);
92+
const button = page.getByRole("button", { name: "Popup menu" });
93+
await button.click();
94+
await expect(page.getByRole("menu")).toBeInViewport();
95+
// CLicking the button again should close menu but currently doesn't
96+
await page.getByTestId("input").click();
97+
await expect(page.getByRole("menu")).not.toBeAttached();
98+
});
99+
});
100+
101+
test.describe("OR if user tabs away", () => {
102+
test("THEN Menu is hidden", async ({ mount, page }) => {
103+
await mount(<DefaultPopupMenu />);
104+
const input = page.getByTestId("input");
105+
await input.click();
106+
await input.press("Tab");
107+
const button = page.getByRole("button", { name: "Popup menu" });
108+
await expect(button).toBeFocused();
109+
button.press("Enter");
110+
await expect(page.getByRole("menu")).toBeInViewport();
111+
112+
const menuItem = page.getByRole("menuitem", { name: "Menu Item 1" });
113+
await expect(menuItem).toBeFocused();
114+
menuItem.press("Tab");
115+
116+
await expect(button).toHaveAttribute("aria-expanded", "false");
117+
await expect(page.getByRole("menu")).not.toBeAttached();
118+
await expect(button).not.toBeFocused();
119+
});
120+
});
121+
});
122+
123+
test.describe("WHEN Enter is pressed, with first menu item highlighted", () => {
124+
test("THEN arrow key can be used for navigation, on Enter menuActionHandler is invoked", async ({
125+
mount,
126+
page,
127+
}) => {
128+
const callbacks: unknown[] = [];
129+
const handler: any = (...args: unknown[]) => callbacks.push(args);
130+
await mount(<DefaultPopupMenu menuActionHandler={handler} />);
131+
132+
await page.getByRole("button").click();
133+
134+
const menu = page.getByRole("menu");
135+
const menuItem1 = page.getByRole("menuitem", { name: "Menu Item 1" });
136+
const menuItem2 = page.getByRole("menuitem", { name: "Menu Item 2" });
137+
138+
await expect(menuItem1).toBeVisible();
139+
await expect(menuItem1).toBeFocused();
140+
141+
await menuItem1.press("ArrowDown");
142+
await expect(menuItem2).toBeFocused();
143+
144+
await menuItem2.press("Enter");
145+
146+
expect(callbacks).toHaveLength(1);
147+
expect(callbacks[0]).toEqual(["action-2"]);
148+
});
149+
});
150+
});

vuu-ui/packages/vuu-popups/src/popup-menu/PopupMenu.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ export interface PopupMenuProps
6565

6666
export const PopupMenu = ({
6767
anchorElement,
68+
"aria-label": ariaLabel,
6869
appearance = "transparent",
6970
className,
7071
disabled = false,
@@ -94,6 +95,7 @@ export const PopupMenu = ({
9495

9596
const { ariaAttributes, buttonProps, menuOpen, rootRef } = usePopupMenu({
9697
anchorElement,
98+
"aria-label": ariaLabel,
9799
id,
98100
menuActionHandler,
99101
menuBuilder,

vuu-ui/packages/vuu-popups/src/popup-menu/usePopupMenu.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export interface PopupMenuHookProps
1414
extends Pick<
1515
PopupMenuProps,
1616
| "anchorElement"
17+
| "aria-label"
1718
| "menuActionHandler"
1819
| "menuBuilder"
1920
| "menuClassName"
@@ -29,6 +30,7 @@ export interface PopupMenuHookProps
2930

3031
export const usePopupMenu = ({
3132
anchorElement,
33+
"aria-label": ariaLabel = "Popup menu",
3234
id,
3335
menuActionHandler,
3436
menuBuilder,
@@ -54,6 +56,8 @@ export const usePopupMenu = ({
5456
) as HTMLElement;
5557
firstOption?.focus();
5658
}, 40);
59+
} else {
60+
suppressShowMenuRef.current = false;
5761
}
5862
},
5963
[onMenuOpen],
@@ -76,6 +80,7 @@ export const usePopupMenu = ({
7680
if (suppressShowMenuRef.current) {
7781
suppressShowMenuRef.current = false;
7882
} else {
83+
suppressShowMenuRef.current = true;
7984
const anchorEl = anchorElement?.current ?? rootRef.current;
8085
if (anchorEl) {
8186
const {
@@ -109,6 +114,7 @@ export const usePopupMenu = ({
109114

110115
const ariaAttributes: AriaAttributes = {
111116
"aria-controls": menuOpen ? `${id}-menu` : undefined,
117+
"aria-label": ariaLabel,
112118
"aria-expanded": menuOpen,
113119
"aria-haspopup": "menu",
114120
};

0 commit comments

Comments
 (0)