summaryrefslogtreecommitdiffstats
path: root/devtools/client/framework/test/browser_toolbox_meatball.js
blob: 0cd0b33ebf5d6d4006393cf41a10f85db0d4b063 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/ */

"use strict";

// Sanity test for meatball menu.
//
// We also use this to test the common Menu* components since we don't currently
// have a means of testing React components in isolation.

const {
  focusableSelector,
} = require("resource://devtools/client/shared/focus.js");
const { Toolbox } = require("resource://devtools/client/framework/toolbox.js");

add_task(async function () {
  const tab = await addTab("about:blank");
  const toolbox = await openToolboxForTab(
    tab,
    "inspector",
    Toolbox.HostType.BOTTOM
  );

  info("Check opening meatball menu by clicking the menu button");
  await openMeatballMenuWithClick(toolbox);
  const menuDockToBottom = toolbox.doc.getElementById(
    "toolbox-meatball-menu-dock-bottom"
  );
  ok(
    menuDockToBottom.getAttribute("aria-checked") === "true",
    "menuDockToBottom has checked"
  );

  info("Check closing meatball menu by clicking outside the popup area");
  await closeMeatballMenuWithClick(toolbox);

  info("Check moving the focus element with key event");
  await openMeatballMenuWithClick(toolbox);
  checkKeyHandling(toolbox);

  info("Check closing meatball menu with escape key");
  EventUtils.synthesizeKey("VK_ESCAPE", {}, toolbox.win);
  await waitForMeatballMenuToClose(toolbox);

  // F1 should trigger the settings panel and close the menu at the same time.
  info("Check closing meatball menu with F1 key");
  await openMeatballMenuWithClick(toolbox);
  EventUtils.synthesizeKey("VK_F1", {}, toolbox.win);
  await waitForMeatballMenuToClose(toolbox);

  await toolbox.destroy();
});

async function openMeatballMenuWithClick(toolbox) {
  const meatballButton = toolbox.doc.getElementById(
    "toolbox-meatball-menu-button"
  );
  await waitUntil(() => meatballButton.style.pointerEvents !== "none");
  EventUtils.synthesizeMouseAtCenter(meatballButton, {}, toolbox.win);

  const panel = toolbox.doc.querySelectorAll(".tooltip-xul-wrapper");
  const shownListener = new Promise(res => {
    panel[0].addEventListener("popupshown", res, { once: true });
  });

  const menuPanel = toolbox.doc.getElementById(
    "toolbox-meatball-menu-button-panel"
  );
  ok(menuPanel, "meatball panel is available");

  info("Waiting for the menu panel to be displayed");

  await shownListener;
  await waitUntil(() => menuPanel.classList.contains("tooltip-visible"));
}

async function closeMeatballMenuWithClick(toolbox) {
  const meatballButton = toolbox.doc.getElementById(
    "toolbox-meatball-menu-button"
  );
  await waitUntil(
    () => toolbox.win.getComputedStyle(meatballButton).pointerEvents === "none"
  );
  meatballButton.click();

  const menuPanel = toolbox.doc.getElementById(
    "toolbox-meatball-menu-button-panel"
  );
  ok(menuPanel, "meatball panel is available");

  info("Waiting for the menu panel to be hidden");
  await waitUntil(() => !menuPanel.classList.contains("tooltip-visible"));
}

async function waitForMeatballMenuToClose(toolbox) {
  const menuPanel = toolbox.doc.getElementById(
    "toolbox-meatball-menu-button-panel"
  );
  ok(menuPanel, "meatball panel is available");

  info("Waiting for the menu panel to be hidden");
  await waitUntil(() => !menuPanel.classList.contains("tooltip-visible"));
}

function checkKeyHandling(toolbox) {
  const selectable = toolbox.doc
    .getElementById("toolbox-meatball-menu")
    .querySelectorAll(focusableSelector);

  EventUtils.synthesizeKey("VK_DOWN", {}, toolbox.win);
  is(
    toolbox.doc.activeElement,
    selectable[0],
    "First item selected with down key."
  );
  EventUtils.synthesizeKey("VK_UP", {}, toolbox.win);
  is(
    toolbox.doc.activeElement,
    selectable[selectable.length - 1],
    "End item selected with up key."
  );
  EventUtils.synthesizeKey("VK_HOME", {}, toolbox.win);
  is(
    toolbox.doc.activeElement,
    selectable[0],
    "First item selected with home key."
  );
  EventUtils.synthesizeKey("VK_END", {}, toolbox.win);
  is(
    toolbox.doc.activeElement,
    selectable[selectable.length - 1],
    "End item selected with down key."
  );
}