summaryrefslogtreecommitdiffstats
path: root/browser/base/content/test/tabs/browser_tabSuccessors.js
blob: 9f577b62004c722386a72186c5944cf698a58ba4 (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
add_task(async function test() {
  const tabs = [gBrowser.selectedTab];
  for (let i = 0; i < 6; ++i) {
    tabs.push(BrowserTestUtils.addTab(gBrowser));
  }

  // Check that setSuccessor works.
  gBrowser.setSuccessor(tabs[0], tabs[2]);
  is(tabs[0].successor, tabs[2], "setSuccessor sets successor");
  ok(tabs[2].predecessors.has(tabs[0]), "setSuccessor adds predecessor");

  BrowserTestUtils.removeTab(tabs[0]);
  is(
    gBrowser.selectedTab,
    tabs[2],
    "When closing a selected tab, select its successor"
  );

  // Check that the successor of a hidden tab becomes the successor of the
  // tab's predecessors.
  gBrowser.setSuccessor(tabs[1], tabs[2]);
  gBrowser.setSuccessor(tabs[3], tabs[1]);
  ok(!tabs[2].predecessors.has(tabs[3]));

  gBrowser.hideTab(tabs[1]);
  is(
    tabs[3].successor,
    tabs[2],
    "A predecessor of a hidden tab should take as its successor the hidden tab's successor"
  );
  ok(tabs[2].predecessors.has(tabs[3]));

  gBrowser.showTab(tabs[1]);

  // Check that the successor of a closed tab also becomes the successor of the
  // tab's predecessors.
  gBrowser.setSuccessor(tabs[1], tabs[2]);
  gBrowser.setSuccessor(tabs[3], tabs[1]);
  ok(!tabs[2].predecessors.has(tabs[3]));

  BrowserTestUtils.removeTab(tabs[1]);
  is(
    tabs[3].successor,
    tabs[2],
    "A predecessor of a closed tab should take as its successor the closed tab's successor"
  );
  ok(tabs[2].predecessors.has(tabs[3]));

  // Check that clearing a successor makes the browser fall back to selecting
  // the owner or next tab.
  await BrowserTestUtils.switchTab(gBrowser, tabs[3]);
  gBrowser.setSuccessor(tabs[3], null);
  is(tabs[3].successor, null, "setSuccessor(..., null) should clear successor");
  ok(
    !tabs[2].predecessors.has(tabs[3]),
    "setSuccessor(..., null) should remove the old successor from predecessors"
  );

  BrowserTestUtils.removeTab(tabs[3]);
  is(
    gBrowser.selectedTab,
    tabs[4],
    "When the active tab is closed and its successor has been cleared, select the next tab"
  );

  // Like closing or hiding a tab, moving a tab to another window should also
  // result in its successor becoming the successor of the moved tab's
  // predecessors.
  gBrowser.setSuccessor(tabs[4], tabs[2]);
  gBrowser.setSuccessor(tabs[2], tabs[5]);
  const secondWin = gBrowser.replaceTabsWithWindow(tabs[2]);
  await TestUtils.waitForCondition(
    () => tabs[2].closing,
    "Wait for tab to be transferred"
  );
  is(
    tabs[4].successor,
    tabs[5],
    "A predecessor of a tab moved to another window should take as its successor the moved tab's successor"
  );

  // Trying to set a successor across windows should fail.
  let threw = false;
  try {
    gBrowser.setSuccessor(tabs[4], secondWin.gBrowser.selectedTab);
  } catch (ex) {
    threw = true;
  }
  ok(threw, "No cross window successors");
  is(tabs[4].successor, tabs[5], "Successor should remain unchanged");

  threw = false;
  try {
    secondWin.gBrowser.setSuccessor(tabs[4], null);
  } catch (ex) {
    threw = true;
  }
  ok(threw, "No setting successors for another window's tab");
  is(tabs[4].successor, tabs[5], "Successor should remain unchanged");

  BrowserTestUtils.closeWindow(secondWin);

  // A tab can't be its own successor
  gBrowser.setSuccessor(tabs[4], tabs[4]);
  is(
    tabs[4].successor,
    null,
    "Successor should be cleared instead of pointing to itself"
  );

  gBrowser.setSuccessor(tabs[4], tabs[5]);
  gBrowser.setSuccessor(tabs[5], tabs[4]);
  is(
    tabs[4].successor,
    tabs[5],
    "Successors can form cycles of length > 1 [a]"
  );
  is(
    tabs[5].successor,
    tabs[4],
    "Successors can form cycles of length > 1 [b]"
  );
  BrowserTestUtils.removeTab(tabs[5]);
  is(
    tabs[4].successor,
    null,
    "Successor should be cleared instead of pointing to itself"
  );

  gBrowser.removeTab(tabs[4]);
});