|
1 /* Any copyright is dedicated to the Public Domain. |
|
2 * http://creativecommons.org/publicdomain/zero/1.0/ */ |
|
3 |
|
4 Cu.import("resource://gre/modules/Promise.jsm"); |
|
5 |
|
6 function waitForCondition(condition, nextTest, errorMsg) { |
|
7 var tries = 0; |
|
8 var interval = setInterval(function() { |
|
9 if (tries >= 30) { |
|
10 ok(false, errorMsg); |
|
11 moveOn(); |
|
12 } |
|
13 var conditionPassed; |
|
14 try { |
|
15 conditionPassed = condition(); |
|
16 } catch (e) { |
|
17 ok(false, e + "\n" + e.stack); |
|
18 conditionPassed = false; |
|
19 } |
|
20 if (conditionPassed) { |
|
21 moveOn(); |
|
22 } |
|
23 tries++; |
|
24 }, 100); |
|
25 var moveOn = function() { clearInterval(interval); nextTest(); }; |
|
26 } |
|
27 |
|
28 function is_hidden(element) { |
|
29 var style = element.ownerDocument.defaultView.getComputedStyle(element, ""); |
|
30 if (style.display == "none") |
|
31 return true; |
|
32 if (style.visibility != "visible") |
|
33 return true; |
|
34 if (style.display == "-moz-popup") |
|
35 return ["hiding","closed"].indexOf(element.state) != -1; |
|
36 |
|
37 // Hiding a parent element will hide all its children |
|
38 if (element.parentNode != element.ownerDocument) |
|
39 return is_hidden(element.parentNode); |
|
40 |
|
41 return false; |
|
42 } |
|
43 |
|
44 function is_element_visible(element, msg) { |
|
45 isnot(element, null, "Element should not be null, when checking visibility"); |
|
46 ok(!is_hidden(element), msg); |
|
47 } |
|
48 |
|
49 function waitForElementToBeVisible(element, nextTest, msg) { |
|
50 waitForCondition(() => !is_hidden(element), |
|
51 () => { |
|
52 ok(true, msg); |
|
53 nextTest(); |
|
54 }, |
|
55 "Timeout waiting for visibility: " + msg); |
|
56 } |
|
57 |
|
58 function waitForElementToBeHidden(element, nextTest, msg) { |
|
59 waitForCondition(() => is_hidden(element), |
|
60 () => { |
|
61 ok(true, msg); |
|
62 nextTest(); |
|
63 }, |
|
64 "Timeout waiting for invisibility: " + msg); |
|
65 } |
|
66 |
|
67 function waitForPopupAtAnchor(popup, anchorNode, nextTest, msg) { |
|
68 waitForCondition(() => popup.popupBoxObject.anchorNode == anchorNode, |
|
69 () => { |
|
70 ok(true, msg); |
|
71 is_element_visible(popup, "Popup should be visible"); |
|
72 nextTest(); |
|
73 }, |
|
74 "Timeout waiting for popup at anchor: " + msg); |
|
75 } |
|
76 |
|
77 function promisePanelShown(win) { |
|
78 let panelEl = win.PanelUI.panel; |
|
79 return promisePanelElementShown(win, panelEl); |
|
80 } |
|
81 |
|
82 function promisePanelElementShown(win, aPanel) { |
|
83 let deferred = Promise.defer(); |
|
84 let timeoutId = win.setTimeout(() => { |
|
85 deferred.reject("Panel did not show within 5 seconds."); |
|
86 }, 5000); |
|
87 aPanel.addEventListener("popupshown", function onPanelOpen(e) { |
|
88 aPanel.removeEventListener("popupshown", onPanelOpen); |
|
89 win.clearTimeout(timeoutId); |
|
90 deferred.resolve(); |
|
91 }); |
|
92 return deferred.promise; |
|
93 } |
|
94 |
|
95 function is_element_hidden(element, msg) { |
|
96 isnot(element, null, "Element should not be null, when checking visibility"); |
|
97 ok(is_hidden(element), msg); |
|
98 } |
|
99 |
|
100 function loadUITourTestPage(callback, host = "https://example.com/") { |
|
101 if (gTestTab) |
|
102 gBrowser.removeTab(gTestTab); |
|
103 |
|
104 let url = getRootDirectory(gTestPath) + "uitour.html"; |
|
105 url = url.replace("chrome://mochitests/content/", host); |
|
106 |
|
107 gTestTab = gBrowser.addTab(url); |
|
108 gBrowser.selectedTab = gTestTab; |
|
109 |
|
110 gTestTab.linkedBrowser.addEventListener("load", function onLoad() { |
|
111 gTestTab.linkedBrowser.removeEventListener("load", onLoad, true); |
|
112 |
|
113 gContentWindow = Components.utils.waiveXrays(gTestTab.linkedBrowser.contentDocument.defaultView); |
|
114 gContentAPI = gContentWindow.Mozilla.UITour; |
|
115 |
|
116 waitForFocus(callback, gContentWindow); |
|
117 }, true); |
|
118 } |
|
119 |
|
120 function UITourTest() { |
|
121 Services.prefs.setBoolPref("browser.uitour.enabled", true); |
|
122 let testUri = Services.io.newURI("http://example.com", null, null); |
|
123 Services.perms.add(testUri, "uitour", Services.perms.ALLOW_ACTION); |
|
124 |
|
125 waitForExplicitFinish(); |
|
126 |
|
127 registerCleanupFunction(function() { |
|
128 delete window.UITour; |
|
129 delete window.gContentWindow; |
|
130 delete window.gContentAPI; |
|
131 if (gTestTab) |
|
132 gBrowser.removeTab(gTestTab); |
|
133 delete window.gTestTab; |
|
134 Services.prefs.clearUserPref("browser.uitour.enabled", true); |
|
135 Services.perms.remove("example.com", "uitour"); |
|
136 }); |
|
137 |
|
138 function done() { |
|
139 executeSoon(() => { |
|
140 if (gTestTab) |
|
141 gBrowser.removeTab(gTestTab); |
|
142 gTestTab = null; |
|
143 |
|
144 let highlight = document.getElementById("UITourHighlightContainer"); |
|
145 is_element_hidden(highlight, "Highlight should be closed/hidden after UITour tab is closed"); |
|
146 |
|
147 let tooltip = document.getElementById("UITourTooltip"); |
|
148 is_element_hidden(tooltip, "Tooltip should be closed/hidden after UITour tab is closed"); |
|
149 |
|
150 ok(!PanelUI.panel.hasAttribute("noautohide"), "@noautohide on the menu panel should have been cleaned up"); |
|
151 ok(!PanelUI.panel.hasAttribute("panelopen"), "The panel shouldn't have @panelopen"); |
|
152 isnot(PanelUI.panel.state, "open", "The panel shouldn't be open"); |
|
153 is(document.getElementById("PanelUI-menu-button").hasAttribute("open"), false, "Menu button should know that the menu is closed"); |
|
154 |
|
155 is(UITour.pinnedTabs.get(window), null, "Any pinned tab should be closed after UITour tab is closed"); |
|
156 |
|
157 executeSoon(nextTest); |
|
158 }); |
|
159 } |
|
160 |
|
161 function nextTest() { |
|
162 if (tests.length == 0) { |
|
163 finish(); |
|
164 return; |
|
165 } |
|
166 let test = tests.shift(); |
|
167 info("Starting " + test.name); |
|
168 waitForFocus(function() { |
|
169 loadUITourTestPage(function() { |
|
170 test(done); |
|
171 }); |
|
172 }); |
|
173 } |
|
174 nextTest(); |
|
175 } |