summaryrefslogtreecommitdiffstats
path: root/browser/base/content/test/tabs/browser_lazy_tab_browser_events.js
blob: 665bdb7f69f62eb4913ede6a51c7daafc0005049 (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
"use strict";

// Helper that watches events that may be triggered when tab browsers are
// swapped during the test.
//
// The primary purpose of this helper is to access tab browser properties
// during tab events, to verify that there are no undesired side effects, as a
// regression test for https://bugzilla.mozilla.org/show_bug.cgi?id=1695346
class TabEventTracker {
  constructor(tab) {
    this.tab = tab;

    tab.addEventListener("TabAttrModified", this);
    tab.addEventListener("TabShow", this);
    tab.addEventListener("TabHide", this);
  }

  handleEvent(event) {
    let description = `${this._expectations.description} at ${event.type}`;
    if (event.type === "TabAttrModified") {
      description += `, changed=${event.detail.changed}`;
    }

    const browser = this.tab.linkedBrowser;
    is(
      browser.currentURI.spec,
      this._expectations.tabUrl,
      `${description} - expected currentURI`
    );
    ok(browser._cachedCurrentURI, `${description} - currentURI was cached`);

    if (event.type === "TabAttrModified") {
      if (event.detail.changed.includes("muted")) {
        if (browser.audioMuted) {
          this._counts.muted++;
        } else {
          this._counts.unmuted++;
        }
      }
    } else if (event.type === "TabShow") {
      this._counts.shown++;
    } else if (event.type === "TabHide") {
      this._counts.hidden++;
    } else {
      ok(false, `Unexpected event: ${event.type}`);
    }
  }

  setExpectations(expectations) {
    this._expectations = expectations;

    this._counts = {
      muted: 0,
      unmuted: 0,
      shown: 0,
      hidden: 0,
    };
  }

  checkExpectations() {
    const { description, counters, tabUrl } = this._expectations;
    Assert.deepEqual(
      this._counts,
      counters,
      `${description} - events observed while swapping tab`
    );
    let browser = this.tab.linkedBrowser;
    is(browser.currentURI.spec, tabUrl, `${description} - tab's currentURI`);

    // Tabs without titles default to URLs without scheme, according to the
    // logic of tabbrowser.js's setTabTitle/_setTabLabel.
    // TODO bug 1695512: lazy tabs deviate from that expectation, so the title
    // is the full URL instead of the URL with the scheme stripped.
    let tabTitle = tabUrl;
    is(browser.contentTitle, tabTitle, `${description} - tab's contentTitle`);
  }
}

add_task(async function test_hidden_muted_lazy_tabs_and_swapping() {
  const params = { createLazyBrowser: true };
  // eslint-disable-next-line @microsoft/sdl/no-insecure-url
  const URL_HIDDEN = "http://example.com/hide";
  // eslint-disable-next-line @microsoft/sdl/no-insecure-url
  const URL_MUTED = "http://example.com/mute";
  // eslint-disable-next-line @microsoft/sdl/no-insecure-url
  const URL_NORMAL = "http://example.com/back";

  const lazyTab = BrowserTestUtils.addTab(gBrowser, "", params);
  const mutedTab = BrowserTestUtils.addTab(gBrowser, URL_MUTED, params);
  const hiddenTab = BrowserTestUtils.addTab(gBrowser, URL_HIDDEN, params);
  const normalTab = BrowserTestUtils.addTab(gBrowser, URL_NORMAL, params);

  mutedTab.toggleMuteAudio();
  gBrowser.hideTab(hiddenTab);

  is(lazyTab.linkedPanel, "", "lazyTab is lazy");
  is(hiddenTab.linkedPanel, "", "hiddenTab is lazy");
  is(mutedTab.linkedPanel, "", "mutedTab is lazy");
  is(normalTab.linkedPanel, "", "normalTab is lazy");

  ok(mutedTab.linkedBrowser.audioMuted, "mutedTab is muted");
  ok(hiddenTab.hidden, "hiddenTab is hidden");
  ok(!lazyTab.linkedBrowser.audioMuted, "lazyTab was not muted");
  ok(!lazyTab.hidden, "lazyTab was not hidden");

  const tabEventTracker = new TabEventTracker(lazyTab);

  tabEventTracker.setExpectations({
    description: "mutedTab replaced lazyTab (initial)",
    counters: {
      muted: 1,
      unmuted: 0,
      shown: 0,
      hidden: 0,
    },
    tabUrl: URL_MUTED,
  });
  gBrowser.swapBrowsersAndCloseOther(lazyTab, mutedTab);
  tabEventTracker.checkExpectations();
  is(lazyTab.linkedPanel, "", "muted lazyTab is still lazy");
  ok(lazyTab.linkedBrowser.audioMuted, "muted lazyTab is now muted");
  ok(!lazyTab.hidden, "muted lazyTab is not hidden");

  tabEventTracker.setExpectations({
    description: "hiddenTab replaced lazyTab/mutedTab",
    counters: {
      muted: 0,
      unmuted: 1,
      shown: 0,
      hidden: 1,
    },
    tabUrl: URL_HIDDEN,
  });
  gBrowser.swapBrowsersAndCloseOther(lazyTab, hiddenTab);
  tabEventTracker.checkExpectations();
  is(lazyTab.linkedPanel, "", "hidden lazyTab is still lazy");
  ok(!lazyTab.linkedBrowser.audioMuted, "hidden lazyTab is not muted any more");
  ok(lazyTab.hidden, "hidden lazyTab has been hidden");

  tabEventTracker.setExpectations({
    description: "normalTab replaced lazyTab/hiddenTab",
    counters: {
      muted: 0,
      unmuted: 0,
      shown: 1,
      hidden: 0,
    },
    tabUrl: URL_NORMAL,
  });
  gBrowser.swapBrowsersAndCloseOther(lazyTab, normalTab);
  tabEventTracker.checkExpectations();
  is(lazyTab.linkedPanel, "", "normal lazyTab is still lazy");
  ok(!lazyTab.linkedBrowser.audioMuted, "normal lazyTab is not muted any more");
  ok(!lazyTab.hidden, "normal lazyTab is not hidden any more");

  BrowserTestUtils.removeTab(lazyTab);
});