summaryrefslogtreecommitdiffstats
path: root/browser/base/content/test/favicons/browser_title_flicker.js
blob: 71fadce908f43278b80e671dfd9885fed8cda125 (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
const TEST_PATH =
  // eslint-disable-next-line @microsoft/sdl/no-insecure-url
  "http://example.com/browser/browser/base/content/test/favicons/";

function waitForAttributeChange(tab, attr) {
  info(`Waiting for attribute ${attr}`);
  return new Promise(resolve => {
    let listener = event => {
      if (event.detail.changed.includes(attr)) {
        tab.removeEventListener("TabAttrModified", listener);
        resolve();
      }
    };

    tab.addEventListener("TabAttrModified", listener);
  });
}

function waitForPendingIcon() {
  return new Promise(resolve => {
    let listener = () => {
      LinkHandlerParent.removeListenerForTests(listener);
      resolve();
    };

    LinkHandlerParent.addListenerForTests(listener);
  });
}

// Verify that the title doesn't flicker if the icon takes too long to load.
// We expect to see events in the following order:
// "label" added to tab
// "busy" removed from tab
// icon available
// In all those cases the title should be in the same position.
add_task(async () => {
  await BrowserTestUtils.withNewTab(
    { gBrowser, url: "about:blank" },
    async browser => {
      let tab = gBrowser.getTabForBrowser(browser);
      BrowserTestUtils.loadURIString(
        browser,
        TEST_PATH + "file_with_slow_favicon.html"
      );

      await waitForAttributeChange(tab, "label");
      ok(tab.hasAttribute("busy"), "Should have seen the busy attribute");
      let label = tab.textLabel;
      let bounds = label.getBoundingClientRect();

      await waitForAttributeChange(tab, "busy");
      ok(
        !tab.hasAttribute("busy"),
        "Should have seen the busy attribute removed"
      );
      let newBounds = label.getBoundingClientRect();
      is(
        bounds.x,
        newBounds.left,
        "Should have seen the title in the same place."
      );

      await waitForFaviconMessage(true);
      newBounds = label.getBoundingClientRect();
      is(
        bounds.x,
        newBounds.left,
        "Should have seen the title in the same place."
      );
    }
  );
});

// Verify that the title doesn't flicker if a new icon is detected after load.
add_task(async () => {
  let iconAvailable = waitForFaviconMessage(true);
  await BrowserTestUtils.withNewTab(
    { gBrowser, url: TEST_PATH + "blank.html" },
    async browser => {
      let icon = await iconAvailable;
      // eslint-disable-next-line @microsoft/sdl/no-insecure-url
      is(icon.iconURL, "http://example.com/favicon.ico");

      let tab = gBrowser.getTabForBrowser(browser);
      let label = tab.textLabel;
      let bounds = label.getBoundingClientRect();

      await SpecialPowers.spawn(browser, [], () => {
        let link = content.document.createElement("link");
        link.setAttribute("href", "file_favicon.png");
        link.setAttribute("rel", "icon");
        link.setAttribute("type", "image/png");
        content.document.head.appendChild(link);
      });

      ok(
        !tab.hasAttribute("pendingicon"),
        "Should not have marked a pending icon"
      );
      let newBounds = label.getBoundingClientRect();
      is(
        bounds.x,
        newBounds.left,
        "Should have seen the title in the same place."
      );

      await waitForPendingIcon();

      ok(
        !tab.hasAttribute("pendingicon"),
        "Should not have marked a pending icon"
      );
      newBounds = label.getBoundingClientRect();
      is(
        bounds.x,
        newBounds.left,
        "Should have seen the title in the same place."
      );

      icon = await waitForFaviconMessage(true);
      is(
        icon.iconURL,
        TEST_PATH + "file_favicon.png",
        "Should have loaded the new icon."
      );

      ok(
        !tab.hasAttribute("pendingicon"),
        "Should not have marked a pending icon"
      );
      newBounds = label.getBoundingClientRect();
      is(
        bounds.x,
        newBounds.left,
        "Should have seen the title in the same place."
      );
    }
  );
});

// Verify that pinned tabs don't change size when an icon is pending.
add_task(async () => {
  await BrowserTestUtils.withNewTab(
    { gBrowser, url: "about:blank" },
    async browser => {
      let tab = gBrowser.getTabForBrowser(browser);
      gBrowser.pinTab(tab);

      let bounds = tab.getBoundingClientRect();
      BrowserTestUtils.loadURIString(
        browser,
        TEST_PATH + "file_with_slow_favicon.html"
      );

      await waitForAttributeChange(tab, "label");
      ok(tab.hasAttribute("busy"), "Should have seen the busy attribute");
      let newBounds = tab.getBoundingClientRect();
      is(
        bounds.width,
        newBounds.width,
        "Should have seen tab remain the same size."
      );

      await waitForAttributeChange(tab, "busy");
      ok(
        !tab.hasAttribute("busy"),
        "Should have seen the busy attribute removed"
      );
      newBounds = tab.getBoundingClientRect();
      is(
        bounds.width,
        newBounds.width,
        "Should have seen tab remain the same size."
      );

      await waitForFaviconMessage(true);
      newBounds = tab.getBoundingClientRect();
      is(
        bounds.width,
        newBounds.width,
        "Should have seen tab remain the same size."
      );
    }
  );
});