summaryrefslogtreecommitdiffstats
path: root/devtools/client/framework/test/browser_toolbox_options_disable_buttons.js
blob: 417970bc07ec8b2695662229e5d1f4c870712fc0 (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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/ */

"use strict";

let TEST_URL =
  "data:text/html;charset=utf8,test for dynamically " +
  "registering and unregistering tools";

// The frames button is only shown if the page has at least one iframe so we
// need to add one to the test page.
TEST_URL += '<iframe src="data:text/plain,iframe"></iframe>';
// The error count button is only shown if there are errors on the page
TEST_URL += '<script>console.error("err")</script>';

var modifiedPrefs = [];
registerCleanupFunction(() => {
  for (const pref of modifiedPrefs) {
    Services.prefs.clearUserPref(pref);
  }
});

const TOGGLE_BUTTONS = [
  "command-button-measure",
  "command-button-rulers",
  "command-button-responsive",
  "command-button-pick",
];

add_task(async function test() {
  const tab = await addTab(TEST_URL);
  let toolbox = await gDevTools.showToolboxForTab(tab);
  const optionsPanelWin = await selectOptionsPanel(toolbox);
  await testToggleToolboxButtons(toolbox, optionsPanelWin);
  toolbox = await testPrefsAreRespectedWhenReopeningToolbox();
  await testButtonStateOnClick(toolbox);

  await toolbox.destroy();
});

async function selectOptionsPanel(toolbox) {
  info("Selecting the options panel");

  const onOptionsSelected = toolbox.once("options-selected");
  toolbox.selectTool("options");
  const optionsPanel = await onOptionsSelected;
  ok(true, "Options panel selected via selectTool method");
  return optionsPanel.panelWin;
}

async function testToggleToolboxButtons(toolbox, optionsPanelWin) {
  const checkNodes = [
    ...optionsPanelWin.document.querySelectorAll(
      "#enabled-toolbox-buttons-box input[type=checkbox]"
    ),
  ];

  // Filter out all the buttons which are not supported on the current target.
  // (DevTools Experimental Preferences etc...)
  const toolbarButtons = toolbox.toolbarButtons.filter(tool =>
    tool.isToolSupported(toolbox)
  );

  const visibleToolbarButtons = toolbarButtons.filter(tool => tool.isVisible);

  const toolbarButtonNodes = [
    ...toolbox.doc.querySelectorAll(".command-button"),
  ];

  is(
    checkNodes.length,
    toolbarButtons.length,
    "All of the buttons are toggleable."
  );
  is(
    visibleToolbarButtons.length,
    toolbarButtonNodes.length,
    "All of the DOM buttons are toggleable."
  );

  for (const tool of toolbarButtons) {
    const id = tool.id;
    const matchedCheckboxes = checkNodes.filter(node => node.id === id);
    const matchedButtons = toolbarButtonNodes.filter(
      button => button.id === id
    );
    if (tool.isVisible) {
      is(
        matchedCheckboxes.length,
        1,
        "There should be a single toggle checkbox for: " + id
      );
      is(
        matchedCheckboxes[0].nextSibling.textContent,
        tool.description,
        "The label for checkbox matches the tool definition."
      );
      is(
        matchedButtons.length,
        1,
        "There should be a DOM button for the visible: " + id
      );

      // The error count button title isn't its description
      if (id !== "command-button-errorcount") {
        is(
          matchedButtons[0].getAttribute("title"),
          tool.description,
          "The tooltip for button matches the tool definition."
        );
      }

      if (TOGGLE_BUTTONS.includes(id)) {
        is(
          matchedButtons[0].getAttribute("aria-pressed"),
          "false",
          `The aria-pressed attribute is set to false for ${id} button`
        );
      } else {
        is(
          matchedButtons[0].getAttribute("aria-pressed"),
          null,
          `The ${id} button does not have the aria-pressed attribute`
        );
      }
    } else {
      is(
        matchedButtons.length,
        0,
        "There should not be a DOM button for the invisible: " + id
      );
    }
  }

  // Store modified pref names so that they can be cleared on error.
  for (const tool of toolbarButtons) {
    const pref = tool.visibilityswitch;
    modifiedPrefs.push(pref);
  }

  // Try checking each checkbox, making sure that it changes the preference
  for (const node of checkNodes) {
    const tool = toolbarButtons.filter(
      commandButton => commandButton.id === node.id
    )[0];
    const isVisible = getBoolPref(tool.visibilityswitch);

    testPreferenceAndUIStateIsConsistent(toolbox, optionsPanelWin);
    node.click();
    testPreferenceAndUIStateIsConsistent(toolbox, optionsPanelWin);

    const isVisibleAfterClick = getBoolPref(tool.visibilityswitch);

    is(
      isVisible,
      !isVisibleAfterClick,
      "Clicking on the node should have toggled visibility preference for " +
        tool.visibilityswitch
    );

    if (isVisibleAfterClick) {
      const matchedButton = toolbox.doc.getElementById(tool.id);
      if (TOGGLE_BUTTONS.includes(tool.id)) {
        is(
          matchedButton.getAttribute("aria-pressed"),
          "false",
          `The aria-pressed attribute is set to false for ${tool.id} button`
        );
      } else {
        is(
          matchedButton.getAttribute("aria-pressed"),
          null,
          `The ${tool.id} button does not have the aria-pressed attribute`
        );
      }
    }
  }
}

async function testPrefsAreRespectedWhenReopeningToolbox() {
  info("Closing toolbox to test after reopening");
  await gDevTools.closeToolboxForTab(gBrowser.selectedTab);

  const toolbox = await gDevTools.showToolboxForTab(gBrowser.selectedTab);
  const optionsPanelWin = await selectOptionsPanel(toolbox);

  info("Toolbox has been reopened.  Checking UI state.");
  await testPreferenceAndUIStateIsConsistent(toolbox, optionsPanelWin);
  return toolbox;
}

function testPreferenceAndUIStateIsConsistent(toolbox, optionsPanelWin) {
  const checkNodes = [
    ...optionsPanelWin.document.querySelectorAll(
      "#enabled-toolbox-buttons-box input[type=checkbox]"
    ),
  ];
  const toolboxButtonNodes = [
    ...toolbox.doc.querySelectorAll(".command-button"),
  ];

  for (const tool of toolbox.toolbarButtons) {
    const isVisible = getBoolPref(tool.visibilityswitch);

    const button = toolboxButtonNodes.find(
      toolboxButton => toolboxButton.id === tool.id
    );
    is(!!button, isVisible, "Button visibility matches pref for " + tool.id);

    const check = checkNodes.filter(node => node.id === tool.id)[0];
    if (check) {
      is(
        check.checked,
        isVisible,
        "Checkbox should be selected based on current pref for " + tool.id
      );
    }
  }
}

async function testButtonStateOnClick(toolbox) {
  const toolboxButtons = ["#command-button-rulers", "#command-button-measure"];
  for (const toolboxButton of toolboxButtons) {
    const button = toolbox.doc.querySelector(toolboxButton);
    if (!button) {
      ok(false, `Couldn't find ${toolboxButton}`);
      continue;
    }

    const isChecked = waitUntil(() => button.classList.contains("checked"));
    is(
      button.getAttribute("aria-pressed"),
      "false",
      `${toolboxButton} has aria-pressed set to false when it's off`
    );

    button.click();
    await isChecked;
    ok(
      button.classList.contains("checked"),
      `Button for ${toolboxButton} can be toggled on`
    );
    is(
      button.getAttribute("aria-pressed"),
      "true",
      `${toolboxButton} has aria-pressed set to true when it's on`
    );

    const isUnchecked = waitUntil(() => !button.classList.contains("checked"));
    button.click();
    await isUnchecked;
    ok(
      !button.classList.contains("checked"),
      `Button for ${toolboxButton} can be toggled off`
    );
    is(
      button.getAttribute("aria-pressed"),
      "false",
      `aria-pressed is set back to false on ${toolboxButton} after it has been toggled off`
    );
  }
}

function getBoolPref(key) {
  try {
    return Services.prefs.getBoolPref(key);
  } catch (e) {
    return false;
  }
}