Source code

Revision control

Other Tools

1
/* Any copyright is dedicated to the Public Domain.
3
4
"use strict";
5
6
/**
7
* Shared functions generally available for tests involving PanelMultiView and
8
* the CustomizableUI elements in the browser window.
9
*/
10
11
var EXPORTED_SYMBOLS = ["CustomizableUITestUtils"];
12
13
const { Assert } = ChromeUtils.import("resource://testing-common/Assert.jsm");
14
const { BrowserTestUtils } = ChromeUtils.import(
16
);
17
const { TestUtils } = ChromeUtils.import(
19
);
20
21
ChromeUtils.defineModuleGetter(
22
this,
23
"CustomizableUI",
25
);
26
27
class CustomizableUITestUtils {
28
/**
29
* Constructs an instance that operates with the specified browser window.
30
*/
31
constructor(window) {
32
this.window = window;
33
this.document = window.document;
34
this.PanelUI = window.PanelUI;
35
}
36
37
/**
38
* Opens a closed PanelMultiView via the specified function while waiting for
39
* the main view with the specified ID to become fully interactive.
40
*/
41
async openPanelMultiView(panel, mainView, openFn) {
42
if (panel.state == "open") {
43
// Some tests may intermittently leave the panel open. We report this, but
44
// don't fail so we don't introduce new intermittent test failures.
45
Assert.ok(
46
true,
47
"A previous test left the panel open. This should be" +
48
" fixed, but we can still do a best-effort recovery and" +
49
" assume that the requested view will be made visible."
50
);
51
await openFn();
52
return;
53
}
54
55
if (panel.state == "hiding") {
56
// There may still be tests that don't wait after invoking a command that
57
// causes the main menu panel to close. Depending on timing, the panel may
58
// or may not be fully closed when the following test runs. We handle this
59
// case gracefully so we don't risk introducing new intermittent test
60
// failures that may show up at a later time.
61
Assert.ok(
62
true,
63
"A previous test requested the panel to close but" +
64
" didn't wait for the operation to complete. While" +
65
" the test should be fixed, we can still continue."
66
);
67
} else {
68
Assert.equal(panel.state, "closed", "The panel is closed to begin with.");
69
}
70
71
let promiseShown = BrowserTestUtils.waitForEvent(mainView, "ViewShown");
72
await openFn();
73
await promiseShown;
74
}
75
76
/**
77
* Closes an open PanelMultiView via the specified function while waiting for
78
* the operation to complete.
79
*/
80
async hidePanelMultiView(panel, closeFn) {
81
Assert.ok(panel.state == "open", "The panel is open to begin with.");
82
83
let promiseHidden = BrowserTestUtils.waitForEvent(panel, "popuphidden");
84
await closeFn();
85
await promiseHidden;
86
}
87
88
/**
89
* Opens the main menu and waits for it to become fully interactive.
90
*/
91
async openMainMenu() {
92
await this.openPanelMultiView(
93
this.PanelUI.panel,
94
this.PanelUI.mainView,
95
() => this.PanelUI.show()
96
);
97
}
98
99
/**
100
* Closes the main menu and waits for the operation to complete.
101
*/
102
async hideMainMenu() {
103
await this.hidePanelMultiView(this.PanelUI.panel, () =>
104
this.PanelUI.hide()
105
);
106
}
107
108
/**
109
* Add the search bar into the nav bar and verify it does not overflow.
110
*
111
* @returns {Promise}
112
* @resolves The search bar element.
113
* @rejects If search bar is not found, or overflows.
114
*/
115
async addSearchBar() {
116
CustomizableUI.addWidgetToArea(
117
"search-container",
118
CustomizableUI.AREA_NAVBAR,
119
CustomizableUI.getPlacementOfWidget("urlbar-container").position + 1
120
);
121
122
// addWidgetToArea adds the search bar into the nav bar first. If the
123
// search bar overflows, OverflowableToolbar for the nav bar moves the
124
// search bar into the overflow panel in its overflow event handler
125
// asynchronously.
126
//
127
// We should first wait for the layout flush to make sure either the search
128
// bar fits into the nav bar, or overflow event gets dispatched and the
129
// overflow event handler is called.
130
await this.window.promiseDocumentFlushed(() => {});
131
132
// Check if the OverflowableToolbar is handling the overflow event.
133
let navbar = this.window.document.getElementById(
134
CustomizableUI.AREA_NAVBAR
135
);
136
await TestUtils.waitForCondition(() => {
137
return !navbar.overflowable.isHandlingOverflow();
138
});
139
140
let searchbar = this.window.document.getElementById("searchbar");
141
if (!searchbar) {
142
throw new Error("The search bar should exist.");
143
}
144
145
// If the search bar overflows, it's placed inside the overflow panel.
146
//
147
// We cannot use navbar's property to check if overflow happens, since it
148
// can be different widget than the search bar that overflows.
149
if (searchbar.closest("#widget-overflow")) {
150
throw new Error(
151
"The search bar should not overflow from the nav bar. " +
152
"This test fails if the screen resolution is small and " +
153
"the search bar overflows from the nav bar."
154
);
155
}
156
157
return searchbar;
158
}
159
160
removeSearchBar() {
161
CustomizableUI.removeWidgetFromArea("search-container");
162
}
163
}