summaryrefslogtreecommitdiffstats
path: root/browser/components/customizableui/test/browser_editcontrols_update.js
blob: 9f064e521a67a9895a6215ad2c5e05b94833881c (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
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
// This test checks that the edit command enabled state (cut/paste) is updated
// properly when the edit controls are on the toolbar, popup and not present.
// It also verifies that the performance optimiation implemented by
// updateEditUIVisibility in browser.js is applied.

let isMac = navigator.platform.indexOf("Mac") == 0;

function checkState(allowCut, desc, testWindow = window) {
  is(
    testWindow.document.getElementById("cmd_cut").getAttribute("disabled") ==
      "true",
    !allowCut,
    desc + " - cut"
  );
  is(
    testWindow.document.getElementById("cmd_paste").getAttribute("disabled") ==
      "true",
    false,
    desc + " - paste"
  );
}

// Add a special controller to the urlbar and browser to listen in on when
// commands are being updated. Return a promise that resolves when 'count'
// updates have occurred.
function expectCommandUpdate(count, testWindow = window) {
  return new Promise((resolve, reject) => {
    let overrideController = {
      supportsCommand(cmd) {
        return cmd == "cmd_delete";
      },
      isCommandEnabled(cmd) {
        if (!count) {
          ok(false, "unexpected update");
          reject();
        }

        if (!--count) {
          testWindow.gURLBar.inputField.controllers.removeControllerAt(
            0,
            overrideController
          );
          testWindow.gBrowser.selectedBrowser.controllers.removeControllerAt(
            0,
            overrideController
          );
          resolve(true);
        }
      },
    };

    if (!count) {
      SimpleTest.executeSoon(() => {
        testWindow.gURLBar.inputField.controllers.removeControllerAt(
          0,
          overrideController
        );
        testWindow.gBrowser.selectedBrowser.controllers.removeControllerAt(
          0,
          overrideController
        );
        resolve(false);
      });
    }

    testWindow.gURLBar.inputField.controllers.insertControllerAt(
      0,
      overrideController
    );
    testWindow.gBrowser.selectedBrowser.controllers.insertControllerAt(
      0,
      overrideController
    );
  });
}

// Call this between `.select()` to make sure the selection actually changes
// and thus TextInputListener::UpdateTextInputCommands() is called.
function deselectURLBarAndSpin() {
  gURLBar.inputField.setSelectionRange(0, 0);
  return new Promise(setTimeout);
}

add_task(async function test_init() {
  // Put something on the clipboard to verify that the paste button is properly enabled during the test.
  let clipboardHelper = Cc["@mozilla.org/widget/clipboardhelper;1"].getService(
    Ci.nsIClipboardHelper
  );
  await new Promise(resolve => {
    SimpleTest.waitForClipboard(
      "Sample",
      function () {
        clipboardHelper.copyString("Sample");
      },
      resolve
    );
  });

  // Open and close the panel first so that it is fully initialized.
  await gCUITestUtils.openMainMenu();
  await gCUITestUtils.hideMainMenu();
});

// Test updating when the panel is open with the edit-controls on the panel.
// Updates should occur.
add_task(async function test_panelui_opened() {
  document.commandDispatcher.unlock();
  gURLBar.focus();
  gURLBar.value = "test";

  await gCUITestUtils.openMainMenu();

  checkState(false, "Update when edit-controls is on panel and visible");

  let overridePromise = expectCommandUpdate(1);
  gURLBar.select();
  await overridePromise;

  checkState(
    true,
    "Update when edit-controls is on panel and selection changed"
  );

  overridePromise = expectCommandUpdate(0);
  await gCUITestUtils.hideMainMenu();
  await overridePromise;

  // Check that updates do not occur after the panel has been closed.
  checkState(true, "Update when edit-controls is on panel and hidden");

  // Mac will update the enabled state even when the panel is closed so that
  // main menubar shortcuts will work properly.
  await deselectURLBarAndSpin();
  overridePromise = expectCommandUpdate(isMac ? 1 : 0);
  gURLBar.select();
  await overridePromise;
  checkState(
    true,
    "Update when edit-controls is on panel, hidden and selection changed"
  );
});

// Test updating when the edit-controls are moved to the toolbar.
add_task(async function test_panelui_customize_to_toolbar() {
  await startCustomizing();
  let navbar = document.getElementById("nav-bar");
  simulateItemDrag(
    document.getElementById("edit-controls"),
    CustomizableUI.getCustomizationTarget(navbar),
    "end"
  );
  await endCustomizing();

  // updateEditUIVisibility should be called when customization ends but isn't. See bug 1359790.
  updateEditUIVisibility();

  // The URL bar may have been focused to begin with, which means
  // that subsequent calls to focus it won't result in command
  // updates, so we'll make sure to blur it.
  gURLBar.blur();

  let overridePromise = expectCommandUpdate(1);
  gURLBar.select();
  gURLBar.focus();
  gURLBar.value = "other";
  await overridePromise;
  checkState(false, "Update when edit-controls on toolbar and focused");

  await deselectURLBarAndSpin();
  overridePromise = expectCommandUpdate(1);
  gURLBar.select();
  await overridePromise;
  checkState(
    true,
    "Update when edit-controls on toolbar and selection changed"
  );

  const kOverflowPanel = document.getElementById("widget-overflow");

  let originalWidth = window.outerWidth;
  registerCleanupFunction(async function () {
    kOverflowPanel.removeAttribute("animate");
    window.resizeTo(originalWidth, window.outerHeight);
    await TestUtils.waitForCondition(() => !navbar.hasAttribute("overflowing"));
    CustomizableUI.reset();
  });

  window.resizeTo(kForceOverflowWidthPx, window.outerHeight);
  await TestUtils.waitForCondition(
    () =>
      navbar.hasAttribute("overflowing") &&
      !navbar.querySelector("edit-controls")
  );

  // Mac will update the enabled state even when the buttons are overflowing,
  // so main menubar shortcuts will work properly.
  await deselectURLBarAndSpin();
  overridePromise = expectCommandUpdate(isMac ? 1 : 0);
  gURLBar.select();
  await overridePromise;
  checkState(
    true,
    "Update when edit-controls is on overflow panel, hidden and selection changed"
  );

  // Check that we get an update if we select content while the panel is open.
  await deselectURLBarAndSpin();
  overridePromise = expectCommandUpdate(1);
  await navbar.overflowable.show();
  gURLBar.select();
  await overridePromise;

  // And that we don't (except on mac) when the panel is hidden.
  kOverflowPanel.hidePopup();
  await deselectURLBarAndSpin();
  overridePromise = expectCommandUpdate(isMac ? 1 : 0);
  gURLBar.select();
  await overridePromise;

  window.resizeTo(originalWidth, window.outerHeight);
  await TestUtils.waitForCondition(() => !navbar.hasAttribute("overflowing"));

  CustomizableUI.addWidgetToArea(
    "edit-controls",
    CustomizableUI.AREA_FIXED_OVERFLOW_PANEL
  );
  // updateEditUIVisibility should be called when customization happens but isn't. See bug 1359790.
  updateEditUIVisibility();

  await deselectURLBarAndSpin();
  overridePromise = expectCommandUpdate(isMac ? 1 : 0);
  gURLBar.select();
  await overridePromise;

  // Check that we get an update if we select content while the panel is open.
  await deselectURLBarAndSpin();
  overridePromise = expectCommandUpdate(1);
  await navbar.overflowable.show();
  gURLBar.select();
  await overridePromise;

  // And that we don't (except on mac) when the panel is hidden.
  kOverflowPanel.hidePopup();
  await deselectURLBarAndSpin();
  overridePromise = expectCommandUpdate(isMac ? 1 : 0);
  gURLBar.select();
  await overridePromise;
});

// Test updating when the edit-controls are moved to the palette.
add_task(async function test_panelui_customize_to_palette() {
  await startCustomizing();
  let palette = document.getElementById("customization-palette");
  simulateItemDrag(document.getElementById("edit-controls"), palette);
  await endCustomizing();

  // updateEditUIVisibility should be called when customization ends but isn't. See bug 1359790.
  updateEditUIVisibility();

  let overridePromise = expectCommandUpdate(isMac ? 1 : 0);
  gURLBar.focus();
  gURLBar.value = "other";
  gURLBar.select();
  await overridePromise;

  // If the UI isn't found, the command is set to be enabled.
  checkState(
    true,
    "Update when edit-controls is on palette, hidden and selection changed"
  );
});

add_task(async function finish() {
  await resetCustomization();
});

// Test updating in the initial state when the edit-controls are on the panel but
// have not yet been created. This needs to be done in a new window to ensure that
// other tests haven't opened the panel.
add_task(async function test_initial_state() {
  let testWindow = await BrowserTestUtils.openNewBrowserWindow();
  await SimpleTest.promiseFocus(testWindow);

  // For focusing the URL bar to have an effect, we need to ensure the URL bar isn't
  // initially focused:
  testWindow.gBrowser.selectedTab.focus();
  await TestUtils.waitForCondition(() => !testWindow.gURLBar.focused);

  let overridePromise = expectCommandUpdate(isMac, testWindow);

  testWindow.gURLBar.focus();
  testWindow.gURLBar.value = "test";

  await overridePromise;

  // Commands won't update when no edit UI is present. They default to being
  // enabled so that keyboard shortcuts will work. The real enabled state will
  // be checked when shortcut is pressed.
  checkState(
    !isMac,
    "No update when edit-controls is on panel and not visible",
    testWindow
  );

  await BrowserTestUtils.closeWindow(testWindow);
  await SimpleTest.promiseFocus(window);
});