Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* Any copyright is dedicated to the Public Domain. |
michael@0 | 2 | http://creativecommons.org/publicdomain/zero/1.0/ */ |
michael@0 | 3 | "use strict"; |
michael@0 | 4 | |
michael@0 | 5 | const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components; |
michael@0 | 6 | |
michael@0 | 7 | let { Services } = Cu.import("resource://gre/modules/Services.jsm", {}); |
michael@0 | 8 | let { Task } = Cu.import("resource://gre/modules/Task.jsm", {}); |
michael@0 | 9 | let { Promise: promise } = Cu.import("resource://gre/modules/Promise.jsm", {}); |
michael@0 | 10 | let { gDevTools } = Cu.import("resource:///modules/devtools/gDevTools.jsm", {}); |
michael@0 | 11 | let { devtools } = Cu.import("resource://gre/modules/devtools/Loader.jsm", {}); |
michael@0 | 12 | let { CurlUtils } = Cu.import("resource:///modules/devtools/Curl.jsm", {}); |
michael@0 | 13 | let TargetFactory = devtools.TargetFactory; |
michael@0 | 14 | let Toolbox = devtools.Toolbox; |
michael@0 | 15 | |
michael@0 | 16 | const EXAMPLE_URL = "http://example.com/browser/browser/devtools/netmonitor/test/"; |
michael@0 | 17 | |
michael@0 | 18 | const SIMPLE_URL = EXAMPLE_URL + "html_simple-test-page.html"; |
michael@0 | 19 | const NAVIGATE_URL = EXAMPLE_URL + "html_navigate-test-page.html"; |
michael@0 | 20 | const CONTENT_TYPE_URL = EXAMPLE_URL + "html_content-type-test-page.html"; |
michael@0 | 21 | const CONTENT_TYPE_WITHOUT_CACHE_URL = EXAMPLE_URL + "html_content-type-without-cache-test-page.html"; |
michael@0 | 22 | const CYRILLIC_URL = EXAMPLE_URL + "html_cyrillic-test-page.html"; |
michael@0 | 23 | const STATUS_CODES_URL = EXAMPLE_URL + "html_status-codes-test-page.html"; |
michael@0 | 24 | const POST_DATA_URL = EXAMPLE_URL + "html_post-data-test-page.html"; |
michael@0 | 25 | const POST_RAW_URL = EXAMPLE_URL + "html_post-raw-test-page.html"; |
michael@0 | 26 | const POST_RAW_WITH_HEADERS_URL = EXAMPLE_URL + "html_post-raw-with-headers-test-page.html"; |
michael@0 | 27 | const PARAMS_URL = EXAMPLE_URL + "html_params-test-page.html"; |
michael@0 | 28 | const JSONP_URL = EXAMPLE_URL + "html_jsonp-test-page.html"; |
michael@0 | 29 | const JSON_LONG_URL = EXAMPLE_URL + "html_json-long-test-page.html"; |
michael@0 | 30 | const JSON_MALFORMED_URL = EXAMPLE_URL + "html_json-malformed-test-page.html"; |
michael@0 | 31 | const JSON_CUSTOM_MIME_URL = EXAMPLE_URL + "html_json-custom-mime-test-page.html"; |
michael@0 | 32 | const JSON_TEXT_MIME_URL = EXAMPLE_URL + "html_json-text-mime-test-page.html"; |
michael@0 | 33 | const SORTING_URL = EXAMPLE_URL + "html_sorting-test-page.html"; |
michael@0 | 34 | const FILTERING_URL = EXAMPLE_URL + "html_filter-test-page.html"; |
michael@0 | 35 | const INFINITE_GET_URL = EXAMPLE_URL + "html_infinite-get-page.html"; |
michael@0 | 36 | const CUSTOM_GET_URL = EXAMPLE_URL + "html_custom-get-page.html"; |
michael@0 | 37 | const SINGLE_GET_URL = EXAMPLE_URL + "html_single-get-page.html"; |
michael@0 | 38 | const STATISTICS_URL = EXAMPLE_URL + "html_statistics-test-page.html"; |
michael@0 | 39 | const CURL_URL = EXAMPLE_URL + "html_copy-as-curl.html"; |
michael@0 | 40 | const CURL_UTILS_URL = EXAMPLE_URL + "html_curl-utils.html"; |
michael@0 | 41 | |
michael@0 | 42 | const SIMPLE_SJS = EXAMPLE_URL + "sjs_simple-test-server.sjs"; |
michael@0 | 43 | const CONTENT_TYPE_SJS = EXAMPLE_URL + "sjs_content-type-test-server.sjs"; |
michael@0 | 44 | const STATUS_CODES_SJS = EXAMPLE_URL + "sjs_status-codes-test-server.sjs"; |
michael@0 | 45 | const SORTING_SJS = EXAMPLE_URL + "sjs_sorting-test-server.sjs"; |
michael@0 | 46 | |
michael@0 | 47 | const TEST_IMAGE = EXAMPLE_URL + "test-image.png"; |
michael@0 | 48 | const TEST_IMAGE_DATA_URI = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHWSURBVHjaYvz//z8DJQAggJiQOe/fv2fv7Oz8rays/N+VkfG/iYnJfyD/1+rVq7ffu3dPFpsBAAHEAHIBCJ85c8bN2Nj4vwsDw/8zQLwKiO8CcRoQu0DxqlWrdsHUwzBAAIGJmTNnPgYa9j8UqhFElwPxf2MIDeIrKSn9FwSJoRkAEEAM0DD4DzMAyPi/G+QKY4hh5WAXGf8PDQ0FGwJ22d27CjADAAIIrLmjo+MXA9R2kAHvGBA2wwx6B8W7od6CeQcggKCmCEL8bgwxYCbUIGTDVkHDBia+CuotgACCueD3TDQN75D4xmAvCoK9ARMHBzAw0AECiBHkAlC0Mdy7x9ABNA3obAZXIAa6iKEcGlMVQHwWyjYuL2d4v2cPg8vZswx7gHyAAAK7AOif7SAbOqCmn4Ha3AHFsIDtgPq/vLz8P4MSkJ2W9h8ggBjevXvHDo4FQUQg/kdypqCg4H8lUIACnQ/SOBMYI8bAsAJFPcj1AAEEjwVQqLpAbXmH5BJjqI0gi9DTAAgDBBCcAVLkgmQ7yKCZxpCQxqUZhAECCJ4XgMl493ug21ZD+aDAXH0WLM4A9MZPXJkJIIAwTAR5pQMalaCABQUULttBGCCAGCnNzgABBgAMJ5THwGvJLAAAAABJRU5ErkJggg=="; |
michael@0 | 49 | |
michael@0 | 50 | gDevTools.testing = true; |
michael@0 | 51 | SimpleTest.registerCleanupFunction(() => { |
michael@0 | 52 | gDevTools.testing = false; |
michael@0 | 53 | }); |
michael@0 | 54 | |
michael@0 | 55 | // All tests are asynchronous. |
michael@0 | 56 | waitForExplicitFinish(); |
michael@0 | 57 | |
michael@0 | 58 | const gEnableLogging = Services.prefs.getBoolPref("devtools.debugger.log"); |
michael@0 | 59 | // To enable logging for try runs, just set the pref to true. |
michael@0 | 60 | Services.prefs.setBoolPref("devtools.debugger.log", false); |
michael@0 | 61 | |
michael@0 | 62 | // Always reset some prefs to their original values after the test finishes. |
michael@0 | 63 | const gDefaultFilters = Services.prefs.getCharPref("devtools.netmonitor.filters"); |
michael@0 | 64 | |
michael@0 | 65 | registerCleanupFunction(() => { |
michael@0 | 66 | info("finish() was called, cleaning up..."); |
michael@0 | 67 | |
michael@0 | 68 | Services.prefs.setBoolPref("devtools.debugger.log", gEnableLogging); |
michael@0 | 69 | Services.prefs.setCharPref("devtools.netmonitor.filters", gDefaultFilters); |
michael@0 | 70 | }); |
michael@0 | 71 | |
michael@0 | 72 | function addTab(aUrl, aWindow) { |
michael@0 | 73 | info("Adding tab: " + aUrl); |
michael@0 | 74 | |
michael@0 | 75 | let deferred = promise.defer(); |
michael@0 | 76 | let targetWindow = aWindow || window; |
michael@0 | 77 | let targetBrowser = targetWindow.gBrowser; |
michael@0 | 78 | |
michael@0 | 79 | targetWindow.focus(); |
michael@0 | 80 | let tab = targetBrowser.selectedTab = targetBrowser.addTab(aUrl); |
michael@0 | 81 | let browser = tab.linkedBrowser; |
michael@0 | 82 | |
michael@0 | 83 | browser.addEventListener("load", function onLoad() { |
michael@0 | 84 | browser.removeEventListener("load", onLoad, true); |
michael@0 | 85 | deferred.resolve(tab); |
michael@0 | 86 | }, true); |
michael@0 | 87 | |
michael@0 | 88 | return deferred.promise; |
michael@0 | 89 | } |
michael@0 | 90 | |
michael@0 | 91 | function removeTab(aTab, aWindow) { |
michael@0 | 92 | info("Removing tab."); |
michael@0 | 93 | |
michael@0 | 94 | let targetWindow = aWindow || window; |
michael@0 | 95 | let targetBrowser = targetWindow.gBrowser; |
michael@0 | 96 | |
michael@0 | 97 | targetBrowser.removeTab(aTab); |
michael@0 | 98 | } |
michael@0 | 99 | |
michael@0 | 100 | function initNetMonitor(aUrl, aWindow) { |
michael@0 | 101 | info("Initializing a network monitor pane."); |
michael@0 | 102 | |
michael@0 | 103 | return addTab(aUrl).then((aTab) => { |
michael@0 | 104 | info("Net tab added successfully: " + aUrl); |
michael@0 | 105 | |
michael@0 | 106 | let deferred = promise.defer(); |
michael@0 | 107 | let debuggee = aTab.linkedBrowser.contentWindow.wrappedJSObject; |
michael@0 | 108 | let target = TargetFactory.forTab(aTab); |
michael@0 | 109 | |
michael@0 | 110 | gDevTools.showToolbox(target, "netmonitor").then((aToolbox) => { |
michael@0 | 111 | info("Netork monitor pane shown successfully."); |
michael@0 | 112 | |
michael@0 | 113 | let monitor = aToolbox.getCurrentPanel(); |
michael@0 | 114 | deferred.resolve([aTab, debuggee, monitor]); |
michael@0 | 115 | }); |
michael@0 | 116 | |
michael@0 | 117 | return deferred.promise; |
michael@0 | 118 | }); |
michael@0 | 119 | } |
michael@0 | 120 | |
michael@0 | 121 | function restartNetMonitor(aMonitor, aNewUrl) { |
michael@0 | 122 | info("Restarting the specified network monitor."); |
michael@0 | 123 | |
michael@0 | 124 | let deferred = promise.defer(); |
michael@0 | 125 | let tab = aMonitor.target.tab; |
michael@0 | 126 | let url = aNewUrl || tab.linkedBrowser.contentWindow.wrappedJSObject.location.href; |
michael@0 | 127 | |
michael@0 | 128 | aMonitor.once("destroyed", () => initNetMonitor(url).then(deferred.resolve)); |
michael@0 | 129 | removeTab(tab); |
michael@0 | 130 | |
michael@0 | 131 | return deferred.promise; |
michael@0 | 132 | } |
michael@0 | 133 | |
michael@0 | 134 | function teardown(aMonitor) { |
michael@0 | 135 | info("Destroying the specified network monitor."); |
michael@0 | 136 | |
michael@0 | 137 | let deferred = promise.defer(); |
michael@0 | 138 | let tab = aMonitor.target.tab; |
michael@0 | 139 | |
michael@0 | 140 | aMonitor.once("destroyed", () => executeSoon(deferred.resolve)); |
michael@0 | 141 | removeTab(tab); |
michael@0 | 142 | |
michael@0 | 143 | return deferred.promise; |
michael@0 | 144 | } |
michael@0 | 145 | |
michael@0 | 146 | function waitForNetworkEvents(aMonitor, aGetRequests, aPostRequests = 0) { |
michael@0 | 147 | let deferred = promise.defer(); |
michael@0 | 148 | |
michael@0 | 149 | let panel = aMonitor.panelWin; |
michael@0 | 150 | let genericEvents = 0; |
michael@0 | 151 | let postEvents = 0; |
michael@0 | 152 | |
michael@0 | 153 | function onGenericEvent() { |
michael@0 | 154 | genericEvents++; |
michael@0 | 155 | maybeResolve(); |
michael@0 | 156 | } |
michael@0 | 157 | |
michael@0 | 158 | function onPostEvent() { |
michael@0 | 159 | postEvents++; |
michael@0 | 160 | maybeResolve(); |
michael@0 | 161 | } |
michael@0 | 162 | |
michael@0 | 163 | function maybeResolve() { |
michael@0 | 164 | info("> Network events progress: " + |
michael@0 | 165 | genericEvents + "/" + ((aGetRequests + aPostRequests) * 13) + ", " + |
michael@0 | 166 | postEvents + "/" + (aPostRequests * 2)); |
michael@0 | 167 | |
michael@0 | 168 | // There are 15 updates which need to be fired for a request to be |
michael@0 | 169 | // considered finished. RequestPostData isn't fired for non-POST requests. |
michael@0 | 170 | if (genericEvents == (aGetRequests + aPostRequests) * 13 && |
michael@0 | 171 | postEvents == aPostRequests * 2) { |
michael@0 | 172 | |
michael@0 | 173 | panel.off(panel.EVENTS.UPDATING_REQUEST_HEADERS, onGenericEvent); |
michael@0 | 174 | panel.off(panel.EVENTS.RECEIVED_REQUEST_HEADERS, onGenericEvent); |
michael@0 | 175 | panel.off(panel.EVENTS.UPDATING_REQUEST_COOKIES, onGenericEvent); |
michael@0 | 176 | panel.off(panel.EVENTS.RECEIVED_REQUEST_COOKIES, onGenericEvent); |
michael@0 | 177 | panel.off(panel.EVENTS.UPDATING_REQUEST_POST_DATA, onPostEvent); |
michael@0 | 178 | panel.off(panel.EVENTS.RECEIVED_REQUEST_POST_DATA, onPostEvent); |
michael@0 | 179 | panel.off(panel.EVENTS.UPDATING_RESPONSE_HEADERS, onGenericEvent); |
michael@0 | 180 | panel.off(panel.EVENTS.RECEIVED_RESPONSE_HEADERS, onGenericEvent); |
michael@0 | 181 | panel.off(panel.EVENTS.UPDATING_RESPONSE_COOKIES, onGenericEvent); |
michael@0 | 182 | panel.off(panel.EVENTS.RECEIVED_RESPONSE_COOKIES, onGenericEvent); |
michael@0 | 183 | panel.off(panel.EVENTS.STARTED_RECEIVING_RESPONSE, onGenericEvent); |
michael@0 | 184 | panel.off(panel.EVENTS.UPDATING_RESPONSE_CONTENT, onGenericEvent); |
michael@0 | 185 | panel.off(panel.EVENTS.RECEIVED_RESPONSE_CONTENT, onGenericEvent); |
michael@0 | 186 | panel.off(panel.EVENTS.UPDATING_EVENT_TIMINGS, onGenericEvent); |
michael@0 | 187 | panel.off(panel.EVENTS.RECEIVED_EVENT_TIMINGS, onGenericEvent); |
michael@0 | 188 | |
michael@0 | 189 | executeSoon(deferred.resolve); |
michael@0 | 190 | } |
michael@0 | 191 | } |
michael@0 | 192 | |
michael@0 | 193 | panel.on(panel.EVENTS.UPDATING_REQUEST_HEADERS, onGenericEvent); |
michael@0 | 194 | panel.on(panel.EVENTS.RECEIVED_REQUEST_HEADERS, onGenericEvent); |
michael@0 | 195 | panel.on(panel.EVENTS.UPDATING_REQUEST_COOKIES, onGenericEvent); |
michael@0 | 196 | panel.on(panel.EVENTS.RECEIVED_REQUEST_COOKIES, onGenericEvent); |
michael@0 | 197 | panel.on(panel.EVENTS.UPDATING_REQUEST_POST_DATA, onPostEvent); |
michael@0 | 198 | panel.on(panel.EVENTS.RECEIVED_REQUEST_POST_DATA, onPostEvent); |
michael@0 | 199 | panel.on(panel.EVENTS.UPDATING_RESPONSE_HEADERS, onGenericEvent); |
michael@0 | 200 | panel.on(panel.EVENTS.RECEIVED_RESPONSE_HEADERS, onGenericEvent); |
michael@0 | 201 | panel.on(panel.EVENTS.UPDATING_RESPONSE_COOKIES, onGenericEvent); |
michael@0 | 202 | panel.on(panel.EVENTS.RECEIVED_RESPONSE_COOKIES, onGenericEvent); |
michael@0 | 203 | panel.on(panel.EVENTS.STARTED_RECEIVING_RESPONSE, onGenericEvent); |
michael@0 | 204 | panel.on(panel.EVENTS.UPDATING_RESPONSE_CONTENT, onGenericEvent); |
michael@0 | 205 | panel.on(panel.EVENTS.RECEIVED_RESPONSE_CONTENT, onGenericEvent); |
michael@0 | 206 | panel.on(panel.EVENTS.UPDATING_EVENT_TIMINGS, onGenericEvent); |
michael@0 | 207 | panel.on(panel.EVENTS.RECEIVED_EVENT_TIMINGS, onGenericEvent); |
michael@0 | 208 | |
michael@0 | 209 | return deferred.promise; |
michael@0 | 210 | } |
michael@0 | 211 | |
michael@0 | 212 | function verifyRequestItemTarget(aRequestItem, aMethod, aUrl, aData = {}) { |
michael@0 | 213 | info("> Verifying: " + aMethod + " " + aUrl + " " + aData.toSource()); |
michael@0 | 214 | // This bloats log sizes significantly in automation (bug 992485) |
michael@0 | 215 | //info("> Request: " + aRequestItem.attachment.toSource()); |
michael@0 | 216 | |
michael@0 | 217 | let requestsMenu = aRequestItem.ownerView; |
michael@0 | 218 | let widgetIndex = requestsMenu.indexOfItem(aRequestItem); |
michael@0 | 219 | let visibleIndex = requestsMenu.visibleItems.indexOf(aRequestItem); |
michael@0 | 220 | |
michael@0 | 221 | info("Widget index of item: " + widgetIndex); |
michael@0 | 222 | info("Visible index of item: " + visibleIndex); |
michael@0 | 223 | |
michael@0 | 224 | let { fuzzyUrl, status, statusText, type, fullMimeType, size, time } = aData; |
michael@0 | 225 | let { attachment, target } = aRequestItem |
michael@0 | 226 | |
michael@0 | 227 | let uri = Services.io.newURI(aUrl, null, null).QueryInterface(Ci.nsIURL); |
michael@0 | 228 | let name = uri.fileName || "/"; |
michael@0 | 229 | let query = uri.query; |
michael@0 | 230 | let hostPort = uri.hostPort; |
michael@0 | 231 | |
michael@0 | 232 | if (fuzzyUrl) { |
michael@0 | 233 | ok(attachment.method.startsWith(aMethod), "The attached method is incorrect."); |
michael@0 | 234 | ok(attachment.url.startsWith(aUrl), "The attached url is incorrect."); |
michael@0 | 235 | } else { |
michael@0 | 236 | is(attachment.method, aMethod, "The attached method is incorrect."); |
michael@0 | 237 | is(attachment.url, aUrl, "The attached url is incorrect."); |
michael@0 | 238 | } |
michael@0 | 239 | |
michael@0 | 240 | is(target.querySelector(".requests-menu-method").getAttribute("value"), |
michael@0 | 241 | aMethod, "The displayed method is incorrect."); |
michael@0 | 242 | |
michael@0 | 243 | if (fuzzyUrl) { |
michael@0 | 244 | ok(target.querySelector(".requests-menu-file").getAttribute("value").startsWith( |
michael@0 | 245 | name + (query ? "?" + query : "")), "The displayed file is incorrect."); |
michael@0 | 246 | ok(target.querySelector(".requests-menu-file").getAttribute("tooltiptext").startsWith( |
michael@0 | 247 | name + (query ? "?" + query : "")), "The tooltip file is incorrect."); |
michael@0 | 248 | } else { |
michael@0 | 249 | is(target.querySelector(".requests-menu-file").getAttribute("value"), |
michael@0 | 250 | name + (query ? "?" + query : ""), "The displayed file is incorrect."); |
michael@0 | 251 | is(target.querySelector(".requests-menu-file").getAttribute("tooltiptext"), |
michael@0 | 252 | name + (query ? "?" + query : ""), "The tooltip file is incorrect."); |
michael@0 | 253 | } |
michael@0 | 254 | |
michael@0 | 255 | is(target.querySelector(".requests-menu-domain").getAttribute("value"), |
michael@0 | 256 | hostPort, "The displayed domain is incorrect."); |
michael@0 | 257 | is(target.querySelector(".requests-menu-domain").getAttribute("tooltiptext"), |
michael@0 | 258 | hostPort, "The tooltip domain is incorrect."); |
michael@0 | 259 | |
michael@0 | 260 | if (status !== undefined) { |
michael@0 | 261 | let value = target.querySelector(".requests-menu-status").getAttribute("code"); |
michael@0 | 262 | let codeValue = target.querySelector(".requests-menu-status-code").getAttribute("value"); |
michael@0 | 263 | let tooltip = target.querySelector(".requests-menu-status-and-method").getAttribute("tooltiptext"); |
michael@0 | 264 | info("Displayed status: " + value); |
michael@0 | 265 | info("Displayed code: " + codeValue); |
michael@0 | 266 | info("Tooltip status: " + tooltip); |
michael@0 | 267 | is(value, status, "The displayed status is incorrect."); |
michael@0 | 268 | is(codeValue, status, "The displayed status code is incorrect."); |
michael@0 | 269 | is(tooltip, status + " " + statusText, "The tooltip status is incorrect."); |
michael@0 | 270 | } |
michael@0 | 271 | if (type !== undefined) { |
michael@0 | 272 | let value = target.querySelector(".requests-menu-type").getAttribute("value"); |
michael@0 | 273 | let tooltip = target.querySelector(".requests-menu-type").getAttribute("tooltiptext"); |
michael@0 | 274 | info("Displayed type: " + value); |
michael@0 | 275 | info("Tooltip type: " + tooltip); |
michael@0 | 276 | is(value, type, "The displayed type is incorrect."); |
michael@0 | 277 | is(tooltip, fullMimeType, "The tooltip type is incorrect."); |
michael@0 | 278 | } |
michael@0 | 279 | if (size !== undefined) { |
michael@0 | 280 | let value = target.querySelector(".requests-menu-size").getAttribute("value"); |
michael@0 | 281 | let tooltip = target.querySelector(".requests-menu-size").getAttribute("tooltiptext"); |
michael@0 | 282 | info("Displayed size: " + value); |
michael@0 | 283 | info("Tooltip size: " + tooltip); |
michael@0 | 284 | is(value, size, "The displayed size is incorrect."); |
michael@0 | 285 | is(tooltip, size, "The tooltip size is incorrect."); |
michael@0 | 286 | } |
michael@0 | 287 | if (time !== undefined) { |
michael@0 | 288 | let value = target.querySelector(".requests-menu-timings-total").getAttribute("value"); |
michael@0 | 289 | let tooltip = target.querySelector(".requests-menu-timings-total").getAttribute("tooltiptext"); |
michael@0 | 290 | info("Displayed time: " + value); |
michael@0 | 291 | info("Tooltip time: " + tooltip); |
michael@0 | 292 | ok(~~(value.match(/[0-9]+/)) >= 0, "The displayed time is incorrect."); |
michael@0 | 293 | ok(~~(tooltip.match(/[0-9]+/)) >= 0, "The tooltip time is incorrect."); |
michael@0 | 294 | } |
michael@0 | 295 | |
michael@0 | 296 | if (visibleIndex != -1) { |
michael@0 | 297 | if (visibleIndex % 2 == 0) { |
michael@0 | 298 | ok(aRequestItem.target.hasAttribute("even"), |
michael@0 | 299 | "Unexpected 'even' attribute for " + aRequestItem.value); |
michael@0 | 300 | ok(!aRequestItem.target.hasAttribute("odd"), |
michael@0 | 301 | "Unexpected 'odd' attribute for " + aRequestItem.value); |
michael@0 | 302 | } else { |
michael@0 | 303 | ok(!aRequestItem.target.hasAttribute("even"), |
michael@0 | 304 | "Unexpected 'even' attribute for " + aRequestItem.value); |
michael@0 | 305 | ok(aRequestItem.target.hasAttribute("odd"), |
michael@0 | 306 | "Unexpected 'odd' attribute for " + aRequestItem.value); |
michael@0 | 307 | } |
michael@0 | 308 | } |
michael@0 | 309 | } |
michael@0 | 310 | |
michael@0 | 311 | /** |
michael@0 | 312 | * Helper function for waiting for an event to fire before resolving a promise. |
michael@0 | 313 | * Example: waitFor(aMonitor.panelWin, aMonitor.panelWin.EVENTS.TAB_UPDATED); |
michael@0 | 314 | * |
michael@0 | 315 | * @param object subject |
michael@0 | 316 | * The event emitter object that is being listened to. |
michael@0 | 317 | * @param string eventName |
michael@0 | 318 | * The name of the event to listen to. |
michael@0 | 319 | * @return object |
michael@0 | 320 | * Returns a promise that resolves upon firing of the event. |
michael@0 | 321 | */ |
michael@0 | 322 | function waitFor (subject, eventName) { |
michael@0 | 323 | let deferred = promise.defer(); |
michael@0 | 324 | subject.once(eventName, deferred.resolve); |
michael@0 | 325 | return deferred.promise; |
michael@0 | 326 | } |
michael@0 | 327 | |
michael@0 | 328 | /** |
michael@0 | 329 | * Tests if a button for a filter of given type is the only one checked. |
michael@0 | 330 | * |
michael@0 | 331 | * @param string aFilterType |
michael@0 | 332 | * The type of the filter that should be the only one checked. |
michael@0 | 333 | */ |
michael@0 | 334 | function testFilterButtons(aMonitor, aFilterType) { |
michael@0 | 335 | let doc = aMonitor.panelWin.document; |
michael@0 | 336 | let target = doc.querySelector("#requests-menu-filter-" + aFilterType + "-button"); |
michael@0 | 337 | let buttons = doc.querySelectorAll(".requests-menu-footer-button"); |
michael@0 | 338 | |
michael@0 | 339 | // Only target should be checked. |
michael@0 | 340 | let checkStatus = [(button == target) ? 1 : 0 for (button of buttons)] |
michael@0 | 341 | testFilterButtonsCustom(aMonitor, checkStatus); |
michael@0 | 342 | } |
michael@0 | 343 | |
michael@0 | 344 | /** |
michael@0 | 345 | * Tests if filter buttons have 'checked' attributes set correctly. |
michael@0 | 346 | * |
michael@0 | 347 | * @param array aIsChecked |
michael@0 | 348 | * An array specifying if a button at given index should have a |
michael@0 | 349 | * 'checked' attribute. For example, if the third item of the array |
michael@0 | 350 | * evaluates to true, the third button should be checked. |
michael@0 | 351 | */ |
michael@0 | 352 | function testFilterButtonsCustom(aMonitor, aIsChecked) { |
michael@0 | 353 | let doc = aMonitor.panelWin.document; |
michael@0 | 354 | let buttons = doc.querySelectorAll(".requests-menu-footer-button"); |
michael@0 | 355 | for (let i = 0; i < aIsChecked.length; i++) { |
michael@0 | 356 | let button = buttons[i]; |
michael@0 | 357 | if (aIsChecked[i]) { |
michael@0 | 358 | is(button.hasAttribute("checked"), true, |
michael@0 | 359 | "The " + button.id + " button should have a 'checked' attribute."); |
michael@0 | 360 | } else { |
michael@0 | 361 | is(button.hasAttribute("checked"), false, |
michael@0 | 362 | "The " + button.id + " button should not have a 'checked' attribute."); |
michael@0 | 363 | } |
michael@0 | 364 | } |
michael@0 | 365 | } |