summaryrefslogtreecommitdiffstats
path: root/toolkit/components/printing/tests/browser_modal_resize.js
blob: 058e5acf29674e5160f6c2d03c28e99e55e03056 (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
/* Any copyright is dedicated to the Public Domain.
 * http://creativecommons.org/publicdomain/zero/1.0/
 */

function waitForAnimationFrames() {
  // Wait for 2 animation frames in hopes it's actually done resizing.
  return new Promise(resolve =>
    window.requestAnimationFrame(() => window.requestAnimationFrame(resolve))
  );
}

async function mouseMoveAndWait(elem) {
  let mouseMovePromise = BrowserTestUtils.waitForEvent(elem, "mousemove");
  EventUtils.synthesizeMouseAtCenter(elem, { type: "mousemove" });
  await mouseMovePromise;
  await TestUtils.waitForTick();
}

function closeEnough(actual, expected) {
  return expected - 1 < actual && actual < expected + 1;
}

async function resizeWindow(x, y) {
  let resizePromise = BrowserTestUtils.waitForEvent(window, "resize");
  window.resizeTo(
    x + window.outerWidth - window.innerWidth,
    y + window.outerHeight - window.innerHeight
  );
  await resizePromise;

  await waitForAnimationFrames();

  ok(
    closeEnough(window.innerWidth, x),
    `Window innerWidth ${window.innerWidth} is close enough to ${x}`
  );
  ok(
    closeEnough(window.innerHeight, y),
    `Window innerHeight ${window.innerHeight} is close enough to ${y}`
  );
}

async function waitForExpectedSize(helper, x, y) {
  // Wait a few frames, this is generally enough for the resize to happen.
  await waitForAnimationFrames();

  let isExpectedSize = () => {
    let box = helper.dialog._box;
    info(`Dialog is ${box.clientWidth}x${box.clientHeight}`);
    if (closeEnough(box.clientWidth, x) && closeEnough(box.clientHeight, y)) {
      // Make sure there's an assertion so the test passes.
      ok(true, `${box.clientWidth} close enough to ${x}`);
      ok(true, `${box.clientHeight} close enough to ${y}`);
      return true;
    }
    return false;
  };

  if (isExpectedSize()) {
    // We can stop now if we hit the expected size.
    return;
  }

  // In verify and debug runs sometimes this takes longer than expected,
  // fallback to the slow method.
  await TestUtils.waitForCondition(isExpectedSize, `Wait for ${x}x${y}`);
}

async function checkPreviewNavigationVisibility(expected) {
  function isHidden(elem) {
    // BTU.isHidden can't handle shadow DOM elements
    return !elem.getBoundingClientRect().height;
  }

  let previewStack = document.querySelector(".previewStack");
  let paginationElem = document.querySelector(".printPreviewNavigation");
  // move the mouse to a known position, then back to the preview to show the paginator
  await mouseMoveAndWait(gURLBar.textbox);
  await mouseMoveAndWait(previewStack);

  ok(
    BrowserTestUtils.isVisible(paginationElem),
    "The preview pagination toolbar is visible"
  );
  for (let [id, visible] of Object.entries(expected)) {
    let elem = paginationElem.shadowRoot.querySelector(`#${id}`);
    if (visible) {
      ok(!isHidden(elem), `Navigation element ${id} is visible`);
    } else {
      ok(isHidden(elem), `Navigation element ${id} is hidden`);
    }
  }
}

add_task(async function testResizing() {
  if (window.windowState != window.STATE_NORMAL) {
    todo_is(
      window.windowState,
      window.STATE_NORMAL,
      "windowState should be STATE_NORMAL"
    );
    // On Windows the size of the window decoration depends on the size mode.
    // Trying to set the inner size of a maximized window changes the size mode
    // but calculates the new window size with the maximized window
    // decorations. On Linux a maximized window can also cause problems when
    // the window was maximized recently and the corresponding resize event is
    // still outstanding.
    window.restore();
    // On Linux we would have to wait for the resize event here, but the
    // restored and maximized size can also be equal. Brute forcing a resize
    // to a specific size works around that.
    await BrowserTestUtils.waitForCondition(async () => {
      let width = window.screen.availWidth * 0.75;
      let height = window.screen.availHeight * 0.75;
      window.resizeTo(width, height);
      return (
        closeEnough(window.outerWidth, width) &&
        closeEnough(window.outerHeight, height)
      );
    });
  }

  await PrintHelper.withTestPage(async helper => {
    let { innerWidth, innerHeight } = window;

    await resizeWindow(500, 400);

    await helper.startPrint();

    let chromeHeight = window.windowUtils.getBoundsWithoutFlushing(
      document.getElementById("browser")
    ).top;

    let initialWidth = 500 - 8;
    let initialHeight = 400 - 16 - chromeHeight + 5;

    await waitForExpectedSize(helper, initialWidth, initialHeight);

    // check the preview pagination state for this window size
    await checkPreviewNavigationVisibility({
      navigateHome: false,
      navigatePrevious: false,
      navigateNext: false,
      navigateEnd: false,
      sheetIndicator: true,
    });

    await resizeWindow(600, 500);

    await checkPreviewNavigationVisibility({
      navigateHome: true,
      navigatePrevious: true,
      navigateNext: true,
      navigateEnd: true,
      sheetIndicator: true,
    });

    // 100 wider for window, add back the old 4px padding, it's now 16px * 2.
    let updatedWidth = initialWidth + 100 + 8 - 32;
    await waitForExpectedSize(helper, updatedWidth, initialHeight + 100);

    await resizeWindow(1100, 900);

    await waitForExpectedSize(helper, 1000, 650);

    await checkPreviewNavigationVisibility({
      navigateHome: true,
      navigatePrevious: true,
      navigateNext: true,
      navigateEnd: true,
      sheetIndicator: true,
    });

    await helper.closeDialog();

    await resizeWindow(innerWidth, innerHeight);
  });
});