From 2525ecf20e302c8d1a6e0f36021c87d995caa7be Mon Sep 17 00:00:00 2001 From: anveshmekala Date: Fri, 21 Apr 2023 16:39:38 -0500 Subject: [PATCH 1/3] test(menu-item): add e2e tests for keyboard support for horizontal & vertical layout --- src/components/menu-item/menu-item.e2e.ts | 152 ++++++++++++++++++++++ src/components/menu/menu.tsx | 1 + 2 files changed, 153 insertions(+) diff --git a/src/components/menu-item/menu-item.e2e.ts b/src/components/menu-item/menu-item.e2e.ts index 522199b173b..e785d68e659 100644 --- a/src/components/menu-item/menu-item.e2e.ts +++ b/src/components/menu-item/menu-item.e2e.ts @@ -107,4 +107,156 @@ describe("calcite-menu-item", () => { expect(await page.evaluate(() => document.activeElement.id)).not.toBe("ArcGISOnline"); }); }); + + describe("keyboard support", () => { + it("should open and close horizontal calcite-menu", async () => { + const page = await newE2EPage(); + await page.setContent(html` + + + + + + + + + + `); + + const menuItemMenu = await page.find("calcite-menu-item[id='Nature'] >>> calcite-menu"); + const subMenuItemMenu = await page.find("calcite-menu-item[id='Mountains'] >>> calcite-menu"); + expect(await menuItemMenu.isVisible()).toBe(false); + + await page.keyboard.press("Tab"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Nature"); + + await page.keyboard.press("Enter"); + expect(await menuItemMenu.isVisible()).toBe(false); + + await page.keyboard.press("Tab"); + await page.keyboard.press("Enter"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Nature"); + await page.waitForChanges(); + expect(await menuItemMenu.isVisible()).toBe(true); + + await page.keyboard.press("ArrowDown"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Mountains"); + + await page.keyboard.press("ArrowDown"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Rivers"); + + await page.keyboard.press("ArrowDown"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Rivers"); + + await page.keyboard.press("ArrowUp"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Mountains"); + + expect(await subMenuItemMenu.isVisible()).toBe(false); + await page.keyboard.press("Enter"); + expect(await subMenuItemMenu.isVisible()).toBe(true); + + await page.keyboard.press("ArrowRight"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Rocky Mountains"); + + await page.keyboard.press("ArrowDown"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Smoky Mountains"); + + await page.keyboard.press("ArrowUp"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Rocky Mountains"); + + await page.keyboard.press("ArrowLeft"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Mountains"); + expect(await subMenuItemMenu.isVisible()).toBe(false); + expect(await menuItemMenu.isVisible()).toBe(true); + + await page.keyboard.press("ArrowLeft"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Nature"); + expect(await menuItemMenu.isVisible()).toBe(false); + + await page.keyboard.press("ArrowRight"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Planets"); + + await page.keyboard.press("ArrowLeft"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Nature"); + }); + + it("should open and close vertical calcite-menu", async () => { + const page = await newE2EPage(); + await page.setContent(html` + + + + + + + + + + `); + + const menuItemMenu = await page.find("calcite-menu-item[id='Nature'] >>> calcite-menu"); + const subMenuItemMenu = await page.find("calcite-menu-item[id='Mountains'] >>> calcite-menu"); + expect(await menuItemMenu.isVisible()).toBe(false); + + await page.keyboard.press("Tab"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Nature"); + + await page.keyboard.press("Enter"); + expect(await menuItemMenu.isVisible()).toBe(false); + + await page.keyboard.press("Tab"); + await page.keyboard.press("Enter"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Nature"); + await page.waitForChanges(); + expect(await menuItemMenu.isVisible()).toBe(true); + + await page.keyboard.press("ArrowRight"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Mountains"); + + await page.keyboard.press("ArrowDown"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Rivers"); + + await page.keyboard.press("ArrowDown"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Rivers"); + + await page.keyboard.press("ArrowUp"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Mountains"); + + expect(await subMenuItemMenu.isVisible()).toBe(false); + await page.keyboard.press("Enter"); + expect(await subMenuItemMenu.isVisible()).toBe(true); + + await page.keyboard.press("ArrowRight"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Rocky Mountains"); + + await page.keyboard.press("ArrowDown"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Smoky Mountains"); + + await page.keyboard.press("ArrowUp"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Rocky Mountains"); + + await page.keyboard.press("ArrowLeft"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Mountains"); + expect(await subMenuItemMenu.isVisible()).toBe(false); + expect(await menuItemMenu.isVisible()).toBe(true); + + await page.keyboard.press("ArrowLeft"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Nature"); + expect(await menuItemMenu.isVisible()).toBe(false); + + await page.keyboard.press("ArrowDown"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Planets"); + + await page.keyboard.press("ArrowUp"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Nature"); + }); + }); }); diff --git a/src/components/menu/menu.tsx b/src/components/menu/menu.tsx index 6f6da55ff72..a9b8c67fbab 100644 --- a/src/components/menu/menu.tsx +++ b/src/components/menu/menu.tsx @@ -115,6 +115,7 @@ export class CalciteMenu { const parentEl = el.parentElement as HTMLCalciteMenuItemElement; if (parentEl) { focusElement(parentEl); + parentEl.open = false; } }; From db2a6741f4605718e5bf56151e6e2ce28b776671 Mon Sep 17 00:00:00 2001 From: anveshmekala Date: Fri, 21 Apr 2023 16:41:54 -0500 Subject: [PATCH 2/3] move tests from menu-item to menu --- src/components/menu-item/menu-item.e2e.ts | 213 --------------------- src/components/menu/menu.e2e.ts | 215 ++++++++++++++++++++++ 2 files changed, 215 insertions(+), 213 deletions(-) diff --git a/src/components/menu-item/menu-item.e2e.ts b/src/components/menu-item/menu-item.e2e.ts index e785d68e659..753d087ba65 100644 --- a/src/components/menu-item/menu-item.e2e.ts +++ b/src/components/menu-item/menu-item.e2e.ts @@ -46,217 +46,4 @@ describe("calcite-menu-item", () => { }); it("is focusable", () => focusable("calcite-menu-item")); - - describe("mouse support", () => { - it("should open the submenu on click", async () => { - const page = await newE2EPage(); - await page.setContent(html` - - - - - - - - `); - - const menuItem = await page.find("calcite-menu-item[id='ArcGISOnline']"); - const menuItemMenu = await page.find("calcite-menu-item[id='ArcGISOnline'] >>> calcite-menu"); - - expect(await menuItemMenu.isVisible()).toBe(false); - - await menuItem.click(); - await page.waitForChanges(); - expect(await menuItemMenu.isVisible()).toBe(true); - expect(await page.evaluate(() => document.activeElement.id)).toBe("ArcGISOnline"); - - const subMenuItem = await page.find("calcite-menu-item[text='ArcGISJS']"); - const subMenuItemMenu = await page.find("calcite-menu-item[text='ArcGISJS'] >>> calcite-menu"); - expect(await subMenuItemMenu.isVisible()).toBe(false); - await subMenuItem.click(); - await page.waitForChanges(); - expect(await subMenuItemMenu.isVisible()).toBe(true); - expect(await page.evaluate(() => document.activeElement.id)).toBe("ArcGISJS"); - }); - - it("should close any opened submenu when clicked outside", async () => { - const page = await newE2EPage(); - await page.setContent(html` - - - - - `); - - const menuItem = await page.find("calcite-menu-item[id='ArcGISOnline']"); - const menuItemMenu = await page.find("calcite-menu-item[id='ArcGISOnline'] >>> calcite-menu"); - - expect(await menuItemMenu.isVisible()).toBe(false); - - await menuItem.click(); - await page.waitForChanges(); - expect(await menuItemMenu.isVisible()).toBe(true); - expect(await page.evaluate(() => document.activeElement.id)).toBe("ArcGISOnline"); - - const menuElement = await page.$("calcite-menu"); - const { x, y, width, height } = await menuElement.boundingBox(); - - await page.mouse.click(x + width + 50, y + height + 50); - await page.waitForChanges(); - expect(await menuItemMenu.isVisible()).toBe(false); - expect(await page.evaluate(() => document.activeElement.id)).not.toBe("ArcGISOnline"); - }); - }); - - describe("keyboard support", () => { - it("should open and close horizontal calcite-menu", async () => { - const page = await newE2EPage(); - await page.setContent(html` - - - - - - - - - - `); - - const menuItemMenu = await page.find("calcite-menu-item[id='Nature'] >>> calcite-menu"); - const subMenuItemMenu = await page.find("calcite-menu-item[id='Mountains'] >>> calcite-menu"); - expect(await menuItemMenu.isVisible()).toBe(false); - - await page.keyboard.press("Tab"); - expect(await page.evaluate(() => document.activeElement.id)).toBe("Nature"); - - await page.keyboard.press("Enter"); - expect(await menuItemMenu.isVisible()).toBe(false); - - await page.keyboard.press("Tab"); - await page.keyboard.press("Enter"); - expect(await page.evaluate(() => document.activeElement.id)).toBe("Nature"); - await page.waitForChanges(); - expect(await menuItemMenu.isVisible()).toBe(true); - - await page.keyboard.press("ArrowDown"); - expect(await page.evaluate(() => document.activeElement.id)).toBe("Mountains"); - - await page.keyboard.press("ArrowDown"); - expect(await page.evaluate(() => document.activeElement.id)).toBe("Rivers"); - - await page.keyboard.press("ArrowDown"); - expect(await page.evaluate(() => document.activeElement.id)).toBe("Rivers"); - - await page.keyboard.press("ArrowUp"); - expect(await page.evaluate(() => document.activeElement.id)).toBe("Mountains"); - - expect(await subMenuItemMenu.isVisible()).toBe(false); - await page.keyboard.press("Enter"); - expect(await subMenuItemMenu.isVisible()).toBe(true); - - await page.keyboard.press("ArrowRight"); - expect(await page.evaluate(() => document.activeElement.id)).toBe("Rocky Mountains"); - - await page.keyboard.press("ArrowDown"); - expect(await page.evaluate(() => document.activeElement.id)).toBe("Smoky Mountains"); - - await page.keyboard.press("ArrowUp"); - expect(await page.evaluate(() => document.activeElement.id)).toBe("Rocky Mountains"); - - await page.keyboard.press("ArrowLeft"); - expect(await page.evaluate(() => document.activeElement.id)).toBe("Mountains"); - expect(await subMenuItemMenu.isVisible()).toBe(false); - expect(await menuItemMenu.isVisible()).toBe(true); - - await page.keyboard.press("ArrowLeft"); - expect(await page.evaluate(() => document.activeElement.id)).toBe("Nature"); - expect(await menuItemMenu.isVisible()).toBe(false); - - await page.keyboard.press("ArrowRight"); - expect(await page.evaluate(() => document.activeElement.id)).toBe("Planets"); - - await page.keyboard.press("ArrowLeft"); - expect(await page.evaluate(() => document.activeElement.id)).toBe("Nature"); - }); - - it("should open and close vertical calcite-menu", async () => { - const page = await newE2EPage(); - await page.setContent(html` - - - - - - - - - - `); - - const menuItemMenu = await page.find("calcite-menu-item[id='Nature'] >>> calcite-menu"); - const subMenuItemMenu = await page.find("calcite-menu-item[id='Mountains'] >>> calcite-menu"); - expect(await menuItemMenu.isVisible()).toBe(false); - - await page.keyboard.press("Tab"); - expect(await page.evaluate(() => document.activeElement.id)).toBe("Nature"); - - await page.keyboard.press("Enter"); - expect(await menuItemMenu.isVisible()).toBe(false); - - await page.keyboard.press("Tab"); - await page.keyboard.press("Enter"); - expect(await page.evaluate(() => document.activeElement.id)).toBe("Nature"); - await page.waitForChanges(); - expect(await menuItemMenu.isVisible()).toBe(true); - - await page.keyboard.press("ArrowRight"); - expect(await page.evaluate(() => document.activeElement.id)).toBe("Mountains"); - - await page.keyboard.press("ArrowDown"); - expect(await page.evaluate(() => document.activeElement.id)).toBe("Rivers"); - - await page.keyboard.press("ArrowDown"); - expect(await page.evaluate(() => document.activeElement.id)).toBe("Rivers"); - - await page.keyboard.press("ArrowUp"); - expect(await page.evaluate(() => document.activeElement.id)).toBe("Mountains"); - - expect(await subMenuItemMenu.isVisible()).toBe(false); - await page.keyboard.press("Enter"); - expect(await subMenuItemMenu.isVisible()).toBe(true); - - await page.keyboard.press("ArrowRight"); - expect(await page.evaluate(() => document.activeElement.id)).toBe("Rocky Mountains"); - - await page.keyboard.press("ArrowDown"); - expect(await page.evaluate(() => document.activeElement.id)).toBe("Smoky Mountains"); - - await page.keyboard.press("ArrowUp"); - expect(await page.evaluate(() => document.activeElement.id)).toBe("Rocky Mountains"); - - await page.keyboard.press("ArrowLeft"); - expect(await page.evaluate(() => document.activeElement.id)).toBe("Mountains"); - expect(await subMenuItemMenu.isVisible()).toBe(false); - expect(await menuItemMenu.isVisible()).toBe(true); - - await page.keyboard.press("ArrowLeft"); - expect(await page.evaluate(() => document.activeElement.id)).toBe("Nature"); - expect(await menuItemMenu.isVisible()).toBe(false); - - await page.keyboard.press("ArrowDown"); - expect(await page.evaluate(() => document.activeElement.id)).toBe("Planets"); - - await page.keyboard.press("ArrowUp"); - expect(await page.evaluate(() => document.activeElement.id)).toBe("Nature"); - }); - }); }); diff --git a/src/components/menu/menu.e2e.ts b/src/components/menu/menu.e2e.ts index 11a480756cb..77ddd101f21 100755 --- a/src/components/menu/menu.e2e.ts +++ b/src/components/menu/menu.e2e.ts @@ -1,3 +1,5 @@ +import { newE2EPage } from "@stencil/core/testing"; +import { html } from "../../../support/formatting"; import { accessible, hidden, renders } from "../../tests/commonTests"; describe("calcite-menu", () => { @@ -6,4 +8,217 @@ describe("calcite-menu", () => { it("honors hidden attribute", async () => hidden("calcite-menu")); it("is accessible", () => accessible("calcite-menu")); + + describe("mouse support", () => { + it("should open the submenu on click", async () => { + const page = await newE2EPage(); + await page.setContent(html` + + + + + + + + `); + + const menuItem = await page.find("calcite-menu-item[id='ArcGISOnline']"); + const menuItemMenu = await page.find("calcite-menu-item[id='ArcGISOnline'] >>> calcite-menu"); + + expect(await menuItemMenu.isVisible()).toBe(false); + + await menuItem.click(); + await page.waitForChanges(); + expect(await menuItemMenu.isVisible()).toBe(true); + expect(await page.evaluate(() => document.activeElement.id)).toBe("ArcGISOnline"); + + const subMenuItem = await page.find("calcite-menu-item[text='ArcGISJS']"); + const subMenuItemMenu = await page.find("calcite-menu-item[text='ArcGISJS'] >>> calcite-menu"); + expect(await subMenuItemMenu.isVisible()).toBe(false); + await subMenuItem.click(); + await page.waitForChanges(); + expect(await subMenuItemMenu.isVisible()).toBe(true); + expect(await page.evaluate(() => document.activeElement.id)).toBe("ArcGISJS"); + }); + + it("should close any opened submenu when clicked outside", async () => { + const page = await newE2EPage(); + await page.setContent(html` + + + + + `); + + const menuItem = await page.find("calcite-menu-item[id='ArcGISOnline']"); + const menuItemMenu = await page.find("calcite-menu-item[id='ArcGISOnline'] >>> calcite-menu"); + + expect(await menuItemMenu.isVisible()).toBe(false); + + await menuItem.click(); + await page.waitForChanges(); + expect(await menuItemMenu.isVisible()).toBe(true); + expect(await page.evaluate(() => document.activeElement.id)).toBe("ArcGISOnline"); + + const menuElement = await page.$("calcite-menu"); + const { x, y, width, height } = await menuElement.boundingBox(); + + await page.mouse.click(x + width + 50, y + height + 50); + await page.waitForChanges(); + expect(await menuItemMenu.isVisible()).toBe(false); + expect(await page.evaluate(() => document.activeElement.id)).not.toBe("ArcGISOnline"); + }); + }); + + describe("keyboard support", () => { + it("should open and close horizontal calcite-menu", async () => { + const page = await newE2EPage(); + await page.setContent(html` + + + + + + + + + + `); + + const menuItemMenu = await page.find("calcite-menu-item[id='Nature'] >>> calcite-menu"); + const subMenuItemMenu = await page.find("calcite-menu-item[id='Mountains'] >>> calcite-menu"); + expect(await menuItemMenu.isVisible()).toBe(false); + + await page.keyboard.press("Tab"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Nature"); + + await page.keyboard.press("Enter"); + expect(await menuItemMenu.isVisible()).toBe(false); + + await page.keyboard.press("Tab"); + await page.keyboard.press("Enter"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Nature"); + await page.waitForChanges(); + expect(await menuItemMenu.isVisible()).toBe(true); + + await page.keyboard.press("ArrowDown"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Mountains"); + + await page.keyboard.press("ArrowDown"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Rivers"); + + await page.keyboard.press("ArrowDown"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Rivers"); + + await page.keyboard.press("ArrowUp"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Mountains"); + + expect(await subMenuItemMenu.isVisible()).toBe(false); + await page.keyboard.press("Enter"); + expect(await subMenuItemMenu.isVisible()).toBe(true); + + await page.keyboard.press("ArrowRight"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Rocky Mountains"); + + await page.keyboard.press("ArrowDown"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Smoky Mountains"); + + await page.keyboard.press("ArrowUp"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Rocky Mountains"); + + await page.keyboard.press("ArrowLeft"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Mountains"); + expect(await subMenuItemMenu.isVisible()).toBe(false); + expect(await menuItemMenu.isVisible()).toBe(true); + + await page.keyboard.press("ArrowLeft"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Nature"); + expect(await menuItemMenu.isVisible()).toBe(false); + + await page.keyboard.press("ArrowRight"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Planets"); + + await page.keyboard.press("ArrowLeft"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Nature"); + }); + + it("should open and close vertical calcite-menu", async () => { + const page = await newE2EPage(); + await page.setContent(html` + + + + + + + + + + `); + + const menuItemMenu = await page.find("calcite-menu-item[id='Nature'] >>> calcite-menu"); + const subMenuItemMenu = await page.find("calcite-menu-item[id='Mountains'] >>> calcite-menu"); + expect(await menuItemMenu.isVisible()).toBe(false); + + await page.keyboard.press("Tab"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Nature"); + + await page.keyboard.press("Enter"); + expect(await menuItemMenu.isVisible()).toBe(false); + + await page.keyboard.press("Tab"); + await page.keyboard.press("Enter"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Nature"); + await page.waitForChanges(); + expect(await menuItemMenu.isVisible()).toBe(true); + + await page.keyboard.press("ArrowRight"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Mountains"); + + await page.keyboard.press("ArrowDown"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Rivers"); + + await page.keyboard.press("ArrowDown"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Rivers"); + + await page.keyboard.press("ArrowUp"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Mountains"); + + expect(await subMenuItemMenu.isVisible()).toBe(false); + await page.keyboard.press("Enter"); + expect(await subMenuItemMenu.isVisible()).toBe(true); + + await page.keyboard.press("ArrowRight"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Rocky Mountains"); + + await page.keyboard.press("ArrowDown"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Smoky Mountains"); + + await page.keyboard.press("ArrowUp"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Rocky Mountains"); + + await page.keyboard.press("ArrowLeft"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Mountains"); + expect(await subMenuItemMenu.isVisible()).toBe(false); + expect(await menuItemMenu.isVisible()).toBe(true); + + await page.keyboard.press("ArrowLeft"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Nature"); + expect(await menuItemMenu.isVisible()).toBe(false); + + await page.keyboard.press("ArrowDown"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Planets"); + + await page.keyboard.press("ArrowUp"); + expect(await page.evaluate(() => document.activeElement.id)).toBe("Nature"); + }); + }); }); From 6e5b0776d6d8886055ef7be919f64f3e9c4bb66b Mon Sep 17 00:00:00 2001 From: anveshmekala Date: Fri, 21 Apr 2023 16:52:14 -0500 Subject: [PATCH 3/3] add screenshot tests --- src/components/menu/menu.stories.ts | 30 +++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/components/menu/menu.stories.ts b/src/components/menu/menu.stories.ts index 317133daf05..781176fb5b9 100644 --- a/src/components/menu/menu.stories.ts +++ b/src/components/menu/menu.stories.ts @@ -37,3 +37,33 @@ export const withNesting = (): string => html` `; + +export const WithSubMenuOpen_TestOnly = (): string => html` + + + + + `; + +export const WithSubMenuOpenInVerticalLayout_TestOnly = (): string => html` + + + + + `;