diff --git a/src/components/menu-item/menu-item.e2e.ts b/src/components/menu-item/menu-item.e2e.ts
index 522199b173b..753d087ba65 100644
--- a/src/components/menu-item/menu-item.e2e.ts
+++ b/src/components/menu-item/menu-item.e2e.ts
@@ -46,65 +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");
- });
- });
});
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");
+ });
+ });
});
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`
+
+
+
+
+ `;
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;
}
};