summaryrefslogtreecommitdiffstats
path: root/browser/components/extensions/test/browser/head_browserAction.js
blob: 98bee897f480fdb6f20a8e2a5dc80fbf57ad5795 (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
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* vim: set sts=2 sw=2 et tw=80: */
"use strict";

/* exported testPopupSize */

// This file is imported into the same scope as head.js.

/* import-globals-from head.js */

// A test helper that retrives an old and new value after a given delay
// and then check that calls an `isCompleted` callback to check that
// the value has reached the expected value.
function waitUntilValue({
  getValue,
  isCompleted,
  message,
  delay: delayTime,
  times = 1,
} = {}) {
  let i = 0;
  return BrowserTestUtils.waitForCondition(async () => {
    const oldVal = await getValue();
    await delay(delayTime);
    const newVal = await getValue();

    const done = isCompleted(oldVal, newVal);

    // Reset the counter if the value wasn't the expected one.
    if (!done) {
      i = 0;
    }

    return done && times === ++i;
  }, message);
}

async function testPopupSize(
  standardsMode,
  browserWin = window,
  arrowSide = "top"
) {
  let docType = standardsMode ? "<!DOCTYPE html>" : "";

  let extension = ExtensionTestUtils.loadExtension({
    manifest: {
      browser_action: {
        default_popup: "popup.html",
        default_area: "navbar",
        browser_style: false,
      },
    },

    files: {
      "popup.html": `${docType}
        <html>
          <head>
            <meta charset="utf-8">
            <style type="text/css">
              body > span {
                display: inline-block;
                width: 10px;
                height: 150px;
                border: 2px solid black;
              }
              .big > span {
                width: 300px;
                height: 100px;
              }
              .bigger > span {
                width: 150px;
                height: 150px;
              }
              .huge > span {
                height: ${2 * screen.height}px;
              }
            </style>
          </head>
          <body>
            <span></span>
            <span></span>
            <span></span>
            <span></span>
          </body>
        </html>`,
    },
  });

  await extension.startup();

  if (arrowSide == "top") {
    // Test the standalone panel for a toolbar button.
    let browser = await openBrowserActionPanel(extension, browserWin, true);

    let dims = await promiseContentDimensions(browser);

    is(
      dims.isStandards,
      standardsMode,
      "Document has the expected compat mode"
    );

    let { innerWidth, innerHeight } = dims.window;

    dims = await alterContent(browser, () => {
      content.document.body.classList.add("bigger");
    });

    let win = dims.window;
    ok(
      Math.abs(win.innerHeight - innerHeight) <= 1,
      `Window height should not change (${win.innerHeight} ~= ${innerHeight})`
    );
    ok(
      win.innerWidth > innerWidth,
      `Window width should increase (${win.innerWidth} > ${innerWidth})`
    );

    dims = await alterContent(browser, () => {
      content.document.body.classList.remove("bigger");
    });

    win = dims.window;

    // The getContentSize calculation is not always reliable to single-pixel
    // precision.
    ok(
      Math.abs(win.innerHeight - innerHeight) <= 1,
      `Window height should return to approximately its original value (${win.innerHeight} ~= ${innerHeight})`
    );
    ok(
      Math.abs(win.innerWidth - innerWidth) <= 1,
      `Window width should return to approximately its original value (${win.innerWidth} ~= ${innerWidth})`
    );

    await closeBrowserAction(extension, browserWin);
  }

  // Test the PanelUI panel for a menu panel button.
  let widget = getBrowserActionWidget(extension);
  CustomizableUI.addWidgetToArea(widget.id, getCustomizableUIPanelID());

  let panel = browserWin.gUnifiedExtensions.panel;
  panel.setAttribute("animate", "false");

  let shownPromise = Promise.resolve();

  let browser = await openBrowserActionPanel(extension, browserWin);

  // Small changes if this is a fixed width window
  let isFixedWidth = !widget.disallowSubView;

  // Wait long enough to make sure the initial popup positioning has been completed (
  // by waiting until the value stays the same for 20 times in a row).
  await waitUntilValue({
    getValue: () => panel.getBoundingClientRect().top,
    isCompleted: (oldVal, newVal) => {
      return oldVal === newVal;
    },
    times: 20,
    message: "Wait the popup opening to be completed",
    delay: 500,
  });

  let origPanelRect = panel.getBoundingClientRect();

  // Check that the panel is still positioned as expected.
  let checkPanelPosition = () => {
    is(
      panel.getAttribute("side"),
      arrowSide,
      "Panel arrow is positioned as expected"
    );

    let panelRect = panel.getBoundingClientRect();
    if (arrowSide == "top") {
      is(panelRect.top, origPanelRect.top, "Panel has not moved downwards");
      ok(
        panelRect.bottom >= origPanelRect.bottom,
        `Panel has not shrunk from original size (${panelRect.bottom} >= ${origPanelRect.bottom})`
      );

      let screenBottom =
        browserWin.screen.availTop + browserWin.screen.availHeight;
      let panelBottom = browserWin.mozInnerScreenY + panelRect.bottom;
      ok(
        Math.round(panelBottom) <= screenBottom,
        `Bottom of popup should be on-screen. (${panelBottom} <= ${screenBottom})`
      );
    } else {
      is(panelRect.bottom, origPanelRect.bottom, "Panel has not moved upwards");
      ok(
        panelRect.top <= origPanelRect.top,
        `Panel has not shrunk from original size (${panelRect.top} <= ${origPanelRect.top})`
      );

      let panelTop = browserWin.mozInnerScreenY + panelRect.top;
      ok(
        panelTop >= browserWin.screen.availTop,
        `Top of popup should be on-screen. (${panelTop} >= ${browserWin.screen.availTop})`
      );
    }
  };

  await awaitBrowserLoaded(browser);
  await shownPromise;

  // Wait long enough to make sure the initial resize debouncing timer has
  // expired.
  await waitUntilValue({
    getValue: () => promiseContentDimensions(browser),
    isCompleted: (oldDims, newDims) => {
      return (
        oldDims.window.innerWidth === newDims.window.innerWidth &&
        oldDims.window.innerHeight === newDims.window.innerHeight
      );
    },
    message: "Wait the popup resize to be completed",
    delay: 500,
  });

  let dims = await promiseContentDimensions(browser);

  is(dims.isStandards, standardsMode, "Document has the expected compat mode");

  // If the browser's preferred height is smaller than the initial height of the
  // panel, then it will still take up the full available vertical space. Even
  // so, we need to check that we've gotten the preferred height calculation
  // correct, so check that explicitly.
  let getHeight = () => parseFloat(browser.style.height);

  let { innerWidth, innerHeight } = dims.window;
  let height = getHeight();

  let setClass = className => {
    content.document.body.className = className;
  };

  info(
    "Increase body children's width. " +
      "Expect them to wrap, and the frame to grow vertically rather than widen."
  );

  dims = await alterContent(browser, setClass, "big");
  let win = dims.window;

  ok(
    getHeight() > height,
    `Browser height should increase (${getHeight()} > ${height})`
  );

  if (isFixedWidth) {
    is(win.innerWidth, innerWidth, "Window width should not change");
  } else {
    ok(
      win.innerWidth >= innerWidth,
      `Window width should increase (${win.innerWidth} >= ${innerWidth})`
    );
  }
  ok(
    win.innerHeight >= innerHeight,
    `Window height should increase (${win.innerHeight} >= ${innerHeight})`
  );
  Assert.lessOrEqual(
    win.scrollMaxY,
    1,
    "Document should not be vertically scrollable"
  );

  checkPanelPosition();

  if (isFixedWidth) {
    // Test a fixed width window grows in height when elements wrap
    info(
      "Increase body children's width and height. " +
        "Expect them to wrap, and the frame to grow vertically rather than widen."
    );

    dims = await alterContent(browser, setClass, "bigger");
    win = dims.window;

    ok(
      getHeight() > height,
      `Browser height should increase (${getHeight()} > ${height})`
    );

    is(win.innerWidth, innerWidth, "Window width should not change");
    ok(
      win.innerHeight >= innerHeight,
      `Window height should increase (${win.innerHeight} >= ${innerHeight})`
    );
    Assert.lessOrEqual(
      win.scrollMaxY,
      1,
      "Document should not be vertically scrollable"
    );

    checkPanelPosition();
  }

  info(
    "Increase body height beyond the height of the screen. " +
      "Expect the panel to grow to accommodate, but not larger than the height of the screen."
  );

  dims = await alterContent(browser, setClass, "huge");
  win = dims.window;

  ok(
    getHeight() > height,
    `Browser height should increase (${getHeight()} > ${height})`
  );

  is(win.innerWidth, innerWidth, "Window width should not change");
  ok(
    win.innerHeight > innerHeight,
    `Window height should increase (${win.innerHeight} > ${innerHeight})`
  );
  // Commented out check for the window height here which mysteriously breaks
  // on infra but not locally. bug 1396843 covers re-enabling this.
  // ok(win.innerHeight < screen.height, `Window height be less than the screen height (${win.innerHeight} < ${screen.height})`);
  ok(
    win.scrollMaxY > 0,
    `Document should be vertically scrollable (${win.scrollMaxY} > 0)`
  );

  checkPanelPosition();

  info("Restore original styling. Expect original dimensions.");
  dims = await alterContent(browser, setClass, "");
  win = dims.window;

  is(getHeight(), height, "Browser height should return to its original value");

  is(win.innerWidth, innerWidth, "Window width should not change");
  is(
    win.innerHeight,
    innerHeight,
    "Window height should return to its original value"
  );
  Assert.lessOrEqual(
    win.scrollMaxY,
    1,
    "Document should not be vertically scrollable"
  );

  checkPanelPosition();

  await closeBrowserAction(extension, browserWin);

  await extension.unload();
}