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 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | 'use strict'; |
michael@0 | 5 | |
michael@0 | 6 | let { Cc, Ci } = require("chrome"); |
michael@0 | 7 | |
michael@0 | 8 | require("sdk/context-menu"); |
michael@0 | 9 | |
michael@0 | 10 | const { Loader } = require('sdk/test/loader'); |
michael@0 | 11 | const timer = require("sdk/timers"); |
michael@0 | 12 | const { merge } = require("sdk/util/object"); |
michael@0 | 13 | |
michael@0 | 14 | // These should match the same constants in the module. |
michael@0 | 15 | const ITEM_CLASS = "addon-context-menu-item"; |
michael@0 | 16 | const SEPARATOR_CLASS = "addon-context-menu-separator"; |
michael@0 | 17 | const OVERFLOW_THRESH_DEFAULT = 10; |
michael@0 | 18 | const OVERFLOW_THRESH_PREF = |
michael@0 | 19 | "extensions.addon-sdk.context-menu.overflowThreshold"; |
michael@0 | 20 | const OVERFLOW_MENU_CLASS = "addon-content-menu-overflow-menu"; |
michael@0 | 21 | const OVERFLOW_POPUP_CLASS = "addon-content-menu-overflow-popup"; |
michael@0 | 22 | |
michael@0 | 23 | const TEST_DOC_URL = module.uri.replace(/\.js$/, ".html"); |
michael@0 | 24 | const data = require("./fixtures"); |
michael@0 | 25 | |
michael@0 | 26 | // Tests that when present the separator is placed before the separator from |
michael@0 | 27 | // the old context-menu module |
michael@0 | 28 | exports.testSeparatorPosition = function (assert, done) { |
michael@0 | 29 | let test = new TestHelper(assert, done); |
michael@0 | 30 | let loader = test.newLoader(); |
michael@0 | 31 | |
michael@0 | 32 | // Create the old separator |
michael@0 | 33 | let oldSeparator = test.contextMenuPopup.ownerDocument.createElement("menuseparator"); |
michael@0 | 34 | oldSeparator.id = "jetpack-context-menu-separator"; |
michael@0 | 35 | test.contextMenuPopup.appendChild(oldSeparator); |
michael@0 | 36 | |
michael@0 | 37 | // Create an item. |
michael@0 | 38 | let item = new loader.cm.Item({ label: "item" }); |
michael@0 | 39 | |
michael@0 | 40 | test.showMenu(null, function (popup) { |
michael@0 | 41 | assert.equal(test.contextMenuSeparator.nextSibling.nextSibling, oldSeparator, |
michael@0 | 42 | "New separator should appear before the old one"); |
michael@0 | 43 | test.contextMenuPopup.removeChild(oldSeparator); |
michael@0 | 44 | test.done(); |
michael@0 | 45 | }); |
michael@0 | 46 | }; |
michael@0 | 47 | |
michael@0 | 48 | // Destroying items that were previously created should cause them to be absent |
michael@0 | 49 | // from the menu. |
michael@0 | 50 | exports.testConstructDestroy = function (assert, done) { |
michael@0 | 51 | let test = new TestHelper(assert, done); |
michael@0 | 52 | let loader = test.newLoader(); |
michael@0 | 53 | |
michael@0 | 54 | // Create an item. |
michael@0 | 55 | let item = new loader.cm.Item({ label: "item" }); |
michael@0 | 56 | assert.equal(item.parentMenu, loader.cm.contentContextMenu, |
michael@0 | 57 | "item's parent menu should be correct"); |
michael@0 | 58 | |
michael@0 | 59 | test.showMenu(null, function (popup) { |
michael@0 | 60 | |
michael@0 | 61 | // It should be present when the menu is shown. |
michael@0 | 62 | test.checkMenu([item], [], []); |
michael@0 | 63 | popup.hidePopup(); |
michael@0 | 64 | |
michael@0 | 65 | // Destroy the item. Multiple destroys should be harmless. |
michael@0 | 66 | item.destroy(); |
michael@0 | 67 | item.destroy(); |
michael@0 | 68 | test.showMenu(null, function (popup) { |
michael@0 | 69 | |
michael@0 | 70 | // It should be removed from the menu. |
michael@0 | 71 | test.checkMenu([item], [], [item]); |
michael@0 | 72 | test.done(); |
michael@0 | 73 | }); |
michael@0 | 74 | }); |
michael@0 | 75 | }; |
michael@0 | 76 | |
michael@0 | 77 | |
michael@0 | 78 | // Destroying an item twice should not cause an error. |
michael@0 | 79 | exports.testDestroyTwice = function (assert, done) { |
michael@0 | 80 | let test = new TestHelper(assert, done); |
michael@0 | 81 | let loader = test.newLoader(); |
michael@0 | 82 | |
michael@0 | 83 | let item = new loader.cm.Item({ label: "item" }); |
michael@0 | 84 | item.destroy(); |
michael@0 | 85 | item.destroy(); |
michael@0 | 86 | |
michael@0 | 87 | test.pass("Destroying an item twice should not cause an error."); |
michael@0 | 88 | test.done(); |
michael@0 | 89 | }; |
michael@0 | 90 | |
michael@0 | 91 | |
michael@0 | 92 | // CSS selector contexts should cause their items to be present in the menu |
michael@0 | 93 | // when the menu is invoked on nodes that match the selectors. |
michael@0 | 94 | exports.testSelectorContextMatch = function (assert, done) { |
michael@0 | 95 | let test = new TestHelper(assert, done); |
michael@0 | 96 | let loader = test.newLoader(); |
michael@0 | 97 | |
michael@0 | 98 | let item = new loader.cm.Item({ |
michael@0 | 99 | label: "item", |
michael@0 | 100 | data: "item", |
michael@0 | 101 | context: loader.cm.SelectorContext("img") |
michael@0 | 102 | }); |
michael@0 | 103 | |
michael@0 | 104 | test.withTestDoc(function (window, doc) { |
michael@0 | 105 | test.showMenu(doc.getElementById("image"), function (popup) { |
michael@0 | 106 | test.checkMenu([item], [], []); |
michael@0 | 107 | test.done(); |
michael@0 | 108 | }); |
michael@0 | 109 | }); |
michael@0 | 110 | }; |
michael@0 | 111 | |
michael@0 | 112 | |
michael@0 | 113 | // CSS selector contexts should cause their items to be present in the menu |
michael@0 | 114 | // when the menu is invoked on nodes that have ancestors that match the |
michael@0 | 115 | // selectors. |
michael@0 | 116 | exports.testSelectorAncestorContextMatch = function (assert, done) { |
michael@0 | 117 | let test = new TestHelper(assert, done); |
michael@0 | 118 | let loader = test.newLoader(); |
michael@0 | 119 | |
michael@0 | 120 | let item = new loader.cm.Item({ |
michael@0 | 121 | label: "item", |
michael@0 | 122 | data: "item", |
michael@0 | 123 | context: loader.cm.SelectorContext("a[href]") |
michael@0 | 124 | }); |
michael@0 | 125 | |
michael@0 | 126 | test.withTestDoc(function (window, doc) { |
michael@0 | 127 | test.showMenu(doc.getElementById("span-link"), function (popup) { |
michael@0 | 128 | test.checkMenu([item], [], []); |
michael@0 | 129 | test.done(); |
michael@0 | 130 | }); |
michael@0 | 131 | }); |
michael@0 | 132 | }; |
michael@0 | 133 | |
michael@0 | 134 | |
michael@0 | 135 | // CSS selector contexts should cause their items to be absent from the menu |
michael@0 | 136 | // when the menu is not invoked on nodes that match or have ancestors that |
michael@0 | 137 | // match the selectors. |
michael@0 | 138 | exports.testSelectorContextNoMatch = function (assert, done) { |
michael@0 | 139 | let test = new TestHelper(assert, done); |
michael@0 | 140 | let loader = test.newLoader(); |
michael@0 | 141 | |
michael@0 | 142 | let item = new loader.cm.Item({ |
michael@0 | 143 | label: "item", |
michael@0 | 144 | data: "item", |
michael@0 | 145 | context: loader.cm.SelectorContext("img") |
michael@0 | 146 | }); |
michael@0 | 147 | |
michael@0 | 148 | test.showMenu(null, function (popup) { |
michael@0 | 149 | test.checkMenu([item], [item], []); |
michael@0 | 150 | test.done(); |
michael@0 | 151 | }); |
michael@0 | 152 | }; |
michael@0 | 153 | |
michael@0 | 154 | |
michael@0 | 155 | // Page contexts should cause their items to be present in the menu when the |
michael@0 | 156 | // menu is not invoked on an active element. |
michael@0 | 157 | exports.testPageContextMatch = function (assert, done) { |
michael@0 | 158 | let test = new TestHelper(assert, done); |
michael@0 | 159 | let loader = test.newLoader(); |
michael@0 | 160 | |
michael@0 | 161 | let items = [ |
michael@0 | 162 | new loader.cm.Item({ |
michael@0 | 163 | label: "item 0" |
michael@0 | 164 | }), |
michael@0 | 165 | new loader.cm.Item({ |
michael@0 | 166 | label: "item 1", |
michael@0 | 167 | context: undefined |
michael@0 | 168 | }), |
michael@0 | 169 | new loader.cm.Item({ |
michael@0 | 170 | label: "item 2", |
michael@0 | 171 | context: loader.cm.PageContext() |
michael@0 | 172 | }), |
michael@0 | 173 | new loader.cm.Item({ |
michael@0 | 174 | label: "item 3", |
michael@0 | 175 | context: [loader.cm.PageContext()] |
michael@0 | 176 | }) |
michael@0 | 177 | ]; |
michael@0 | 178 | |
michael@0 | 179 | test.showMenu(null, function (popup) { |
michael@0 | 180 | test.checkMenu(items, [], []); |
michael@0 | 181 | test.done(); |
michael@0 | 182 | }); |
michael@0 | 183 | }; |
michael@0 | 184 | |
michael@0 | 185 | |
michael@0 | 186 | // Page contexts should cause their items to be absent from the menu when the |
michael@0 | 187 | // menu is invoked on an active element. |
michael@0 | 188 | exports.testPageContextNoMatch = function (assert, done) { |
michael@0 | 189 | let test = new TestHelper(assert, done); |
michael@0 | 190 | let loader = test.newLoader(); |
michael@0 | 191 | |
michael@0 | 192 | let items = [ |
michael@0 | 193 | new loader.cm.Item({ |
michael@0 | 194 | label: "item 0" |
michael@0 | 195 | }), |
michael@0 | 196 | new loader.cm.Item({ |
michael@0 | 197 | label: "item 1", |
michael@0 | 198 | context: undefined |
michael@0 | 199 | }), |
michael@0 | 200 | new loader.cm.Item({ |
michael@0 | 201 | label: "item 2", |
michael@0 | 202 | context: loader.cm.PageContext() |
michael@0 | 203 | }), |
michael@0 | 204 | new loader.cm.Item({ |
michael@0 | 205 | label: "item 3", |
michael@0 | 206 | context: [loader.cm.PageContext()] |
michael@0 | 207 | }) |
michael@0 | 208 | ]; |
michael@0 | 209 | |
michael@0 | 210 | test.withTestDoc(function (window, doc) { |
michael@0 | 211 | test.showMenu(doc.getElementById("image"), function (popup) { |
michael@0 | 212 | test.checkMenu(items, items, []); |
michael@0 | 213 | test.done(); |
michael@0 | 214 | }); |
michael@0 | 215 | }); |
michael@0 | 216 | }; |
michael@0 | 217 | |
michael@0 | 218 | |
michael@0 | 219 | // Selection contexts should cause items to appear when a selection exists. |
michael@0 | 220 | exports.testSelectionContextMatch = function (assert, done) { |
michael@0 | 221 | let test = new TestHelper(assert, done); |
michael@0 | 222 | let loader = test.newLoader(); |
michael@0 | 223 | |
michael@0 | 224 | let item = loader.cm.Item({ |
michael@0 | 225 | label: "item", |
michael@0 | 226 | context: loader.cm.SelectionContext() |
michael@0 | 227 | }); |
michael@0 | 228 | |
michael@0 | 229 | test.withTestDoc(function (window, doc) { |
michael@0 | 230 | window.getSelection().selectAllChildren(doc.body); |
michael@0 | 231 | test.showMenu(null, function (popup) { |
michael@0 | 232 | test.checkMenu([item], [], []); |
michael@0 | 233 | test.done(); |
michael@0 | 234 | }); |
michael@0 | 235 | }); |
michael@0 | 236 | }; |
michael@0 | 237 | |
michael@0 | 238 | |
michael@0 | 239 | // Selection contexts should cause items to appear when a selection exists in |
michael@0 | 240 | // a text field. |
michael@0 | 241 | exports.testSelectionContextMatchInTextField = function (assert, done) { |
michael@0 | 242 | let test = new TestHelper(assert, done); |
michael@0 | 243 | let loader = test.newLoader(); |
michael@0 | 244 | |
michael@0 | 245 | let item = loader.cm.Item({ |
michael@0 | 246 | label: "item", |
michael@0 | 247 | context: loader.cm.SelectionContext() |
michael@0 | 248 | }); |
michael@0 | 249 | |
michael@0 | 250 | test.withTestDoc(function (window, doc) { |
michael@0 | 251 | let textfield = doc.getElementById("textfield"); |
michael@0 | 252 | textfield.setSelectionRange(0, textfield.value.length); |
michael@0 | 253 | test.showMenu(textfield, function (popup) { |
michael@0 | 254 | test.checkMenu([item], [], []); |
michael@0 | 255 | test.done(); |
michael@0 | 256 | }); |
michael@0 | 257 | }); |
michael@0 | 258 | }; |
michael@0 | 259 | |
michael@0 | 260 | |
michael@0 | 261 | // Selection contexts should not cause items to appear when a selection does |
michael@0 | 262 | // not exist in a text field. |
michael@0 | 263 | exports.testSelectionContextNoMatchInTextField = function (assert, done) { |
michael@0 | 264 | let test = new TestHelper(assert, done); |
michael@0 | 265 | let loader = test.newLoader(); |
michael@0 | 266 | |
michael@0 | 267 | let item = loader.cm.Item({ |
michael@0 | 268 | label: "item", |
michael@0 | 269 | context: loader.cm.SelectionContext() |
michael@0 | 270 | }); |
michael@0 | 271 | |
michael@0 | 272 | test.withTestDoc(function (window, doc) { |
michael@0 | 273 | let textfield = doc.getElementById("textfield"); |
michael@0 | 274 | textfield.setSelectionRange(0, 0); |
michael@0 | 275 | test.showMenu(textfield, function (popup) { |
michael@0 | 276 | test.checkMenu([item], [item], []); |
michael@0 | 277 | test.done(); |
michael@0 | 278 | }); |
michael@0 | 279 | }); |
michael@0 | 280 | }; |
michael@0 | 281 | |
michael@0 | 282 | |
michael@0 | 283 | // Selection contexts should not cause items to appear when a selection does |
michael@0 | 284 | // not exist. |
michael@0 | 285 | exports.testSelectionContextNoMatch = function (assert, done) { |
michael@0 | 286 | let test = new TestHelper(assert, done); |
michael@0 | 287 | let loader = test.newLoader(); |
michael@0 | 288 | |
michael@0 | 289 | let item = loader.cm.Item({ |
michael@0 | 290 | label: "item", |
michael@0 | 291 | context: loader.cm.SelectionContext() |
michael@0 | 292 | }); |
michael@0 | 293 | |
michael@0 | 294 | test.showMenu(null, function (popup) { |
michael@0 | 295 | test.checkMenu([item], [item], []); |
michael@0 | 296 | test.done(); |
michael@0 | 297 | }); |
michael@0 | 298 | }; |
michael@0 | 299 | |
michael@0 | 300 | |
michael@0 | 301 | // Selection contexts should cause items to appear when a selection exists even |
michael@0 | 302 | // for newly opened pages |
michael@0 | 303 | exports.testSelectionContextInNewTab = function (assert, done) { |
michael@0 | 304 | let test = new TestHelper(assert, done); |
michael@0 | 305 | let loader = test.newLoader(); |
michael@0 | 306 | |
michael@0 | 307 | let item = loader.cm.Item({ |
michael@0 | 308 | label: "item", |
michael@0 | 309 | context: loader.cm.SelectionContext() |
michael@0 | 310 | }); |
michael@0 | 311 | |
michael@0 | 312 | test.withTestDoc(function (window, doc) { |
michael@0 | 313 | let link = doc.getElementById("targetlink"); |
michael@0 | 314 | link.click(); |
michael@0 | 315 | |
michael@0 | 316 | test.delayedEventListener(this.tabBrowser, "load", function () { |
michael@0 | 317 | let browser = test.tabBrowser.selectedBrowser; |
michael@0 | 318 | let window = browser.contentWindow; |
michael@0 | 319 | let doc = browser.contentDocument; |
michael@0 | 320 | window.getSelection().selectAllChildren(doc.body); |
michael@0 | 321 | |
michael@0 | 322 | test.showMenu(null, function (popup) { |
michael@0 | 323 | test.checkMenu([item], [], []); |
michael@0 | 324 | popup.hidePopup(); |
michael@0 | 325 | |
michael@0 | 326 | test.tabBrowser.removeTab(test.tabBrowser.selectedTab); |
michael@0 | 327 | test.tabBrowser.selectedTab = test.tab; |
michael@0 | 328 | |
michael@0 | 329 | test.showMenu(null, function (popup) { |
michael@0 | 330 | test.checkMenu([item], [item], []); |
michael@0 | 331 | test.done(); |
michael@0 | 332 | }); |
michael@0 | 333 | }); |
michael@0 | 334 | }, true); |
michael@0 | 335 | }); |
michael@0 | 336 | }; |
michael@0 | 337 | |
michael@0 | 338 | |
michael@0 | 339 | // Selection contexts should work when right clicking a form button |
michael@0 | 340 | exports.testSelectionContextButtonMatch = function (assert, done) { |
michael@0 | 341 | let test = new TestHelper(assert, done); |
michael@0 | 342 | let loader = test.newLoader(); |
michael@0 | 343 | |
michael@0 | 344 | let item = loader.cm.Item({ |
michael@0 | 345 | label: "item", |
michael@0 | 346 | context: loader.cm.SelectionContext() |
michael@0 | 347 | }); |
michael@0 | 348 | |
michael@0 | 349 | test.withTestDoc(function (window, doc) { |
michael@0 | 350 | window.getSelection().selectAllChildren(doc.body); |
michael@0 | 351 | let button = doc.getElementById("button"); |
michael@0 | 352 | test.showMenu(button, function (popup) { |
michael@0 | 353 | test.checkMenu([item], [], []); |
michael@0 | 354 | test.done(); |
michael@0 | 355 | }); |
michael@0 | 356 | }); |
michael@0 | 357 | }; |
michael@0 | 358 | |
michael@0 | 359 | |
michael@0 | 360 | //Selection contexts should work when right clicking a form button |
michael@0 | 361 | exports.testSelectionContextButtonNoMatch = function (assert, done) { |
michael@0 | 362 | let test = new TestHelper(assert, done); |
michael@0 | 363 | let loader = test.newLoader(); |
michael@0 | 364 | |
michael@0 | 365 | let item = loader.cm.Item({ |
michael@0 | 366 | label: "item", |
michael@0 | 367 | context: loader.cm.SelectionContext() |
michael@0 | 368 | }); |
michael@0 | 369 | |
michael@0 | 370 | test.withTestDoc(function (window, doc) { |
michael@0 | 371 | let button = doc.getElementById("button"); |
michael@0 | 372 | test.showMenu(button, function (popup) { |
michael@0 | 373 | test.checkMenu([item], [item], []); |
michael@0 | 374 | test.done(); |
michael@0 | 375 | }); |
michael@0 | 376 | }); |
michael@0 | 377 | }; |
michael@0 | 378 | |
michael@0 | 379 | |
michael@0 | 380 | // URL contexts should cause items to appear on pages that match. |
michael@0 | 381 | exports.testURLContextMatch = function (assert, done) { |
michael@0 | 382 | let test = new TestHelper(assert, done); |
michael@0 | 383 | let loader = test.newLoader(); |
michael@0 | 384 | |
michael@0 | 385 | let items = [ |
michael@0 | 386 | loader.cm.Item({ |
michael@0 | 387 | label: "item 0", |
michael@0 | 388 | context: loader.cm.URLContext(TEST_DOC_URL) |
michael@0 | 389 | }), |
michael@0 | 390 | loader.cm.Item({ |
michael@0 | 391 | label: "item 1", |
michael@0 | 392 | context: loader.cm.URLContext([TEST_DOC_URL, "*.bogus.com"]) |
michael@0 | 393 | }), |
michael@0 | 394 | loader.cm.Item({ |
michael@0 | 395 | label: "item 2", |
michael@0 | 396 | context: loader.cm.URLContext([new RegExp(".*\\.html")]) |
michael@0 | 397 | }) |
michael@0 | 398 | ]; |
michael@0 | 399 | |
michael@0 | 400 | test.withTestDoc(function (window, doc) { |
michael@0 | 401 | test.showMenu(null, function (popup) { |
michael@0 | 402 | test.checkMenu(items, [], []); |
michael@0 | 403 | test.done(); |
michael@0 | 404 | }); |
michael@0 | 405 | }); |
michael@0 | 406 | }; |
michael@0 | 407 | |
michael@0 | 408 | |
michael@0 | 409 | // URL contexts should not cause items to appear on pages that do not match. |
michael@0 | 410 | exports.testURLContextNoMatch = function (assert, done) { |
michael@0 | 411 | let test = new TestHelper(assert, done); |
michael@0 | 412 | let loader = test.newLoader(); |
michael@0 | 413 | |
michael@0 | 414 | let items = [ |
michael@0 | 415 | loader.cm.Item({ |
michael@0 | 416 | label: "item 0", |
michael@0 | 417 | context: loader.cm.URLContext("*.bogus.com") |
michael@0 | 418 | }), |
michael@0 | 419 | loader.cm.Item({ |
michael@0 | 420 | label: "item 1", |
michael@0 | 421 | context: loader.cm.URLContext(["*.bogus.com", "*.gnarly.com"]) |
michael@0 | 422 | }), |
michael@0 | 423 | loader.cm.Item({ |
michael@0 | 424 | label: "item 2", |
michael@0 | 425 | context: loader.cm.URLContext([new RegExp(".*\\.js")]) |
michael@0 | 426 | }) |
michael@0 | 427 | ]; |
michael@0 | 428 | |
michael@0 | 429 | test.withTestDoc(function (window, doc) { |
michael@0 | 430 | test.showMenu(null, function (popup) { |
michael@0 | 431 | test.checkMenu(items, items, []); |
michael@0 | 432 | test.done(); |
michael@0 | 433 | }); |
michael@0 | 434 | }); |
michael@0 | 435 | }; |
michael@0 | 436 | |
michael@0 | 437 | |
michael@0 | 438 | // Removing a non-matching URL context after its item is created and the page is |
michael@0 | 439 | // loaded should cause the item's content script to be evaluated when the |
michael@0 | 440 | // context menu is next opened. |
michael@0 | 441 | exports.testURLContextRemove = function (assert, done) { |
michael@0 | 442 | let test = new TestHelper(assert, done); |
michael@0 | 443 | let loader = test.newLoader(); |
michael@0 | 444 | |
michael@0 | 445 | let shouldBeEvaled = false; |
michael@0 | 446 | let context = loader.cm.URLContext("*.bogus.com"); |
michael@0 | 447 | let item = loader.cm.Item({ |
michael@0 | 448 | label: "item", |
michael@0 | 449 | context: context, |
michael@0 | 450 | contentScript: 'self.postMessage("ok"); self.on("context", function () true);', |
michael@0 | 451 | onMessage: function (msg) { |
michael@0 | 452 | assert.ok(shouldBeEvaled, |
michael@0 | 453 | "content script should be evaluated when expected"); |
michael@0 | 454 | assert.equal(msg, "ok", "Should have received the right message"); |
michael@0 | 455 | shouldBeEvaled = false; |
michael@0 | 456 | } |
michael@0 | 457 | }); |
michael@0 | 458 | |
michael@0 | 459 | test.withTestDoc(function (window, doc) { |
michael@0 | 460 | test.showMenu(null, function (popup) { |
michael@0 | 461 | test.checkMenu([item], [item], []); |
michael@0 | 462 | |
michael@0 | 463 | item.context.remove(context); |
michael@0 | 464 | |
michael@0 | 465 | shouldBeEvaled = true; |
michael@0 | 466 | |
michael@0 | 467 | test.hideMenu(function () { |
michael@0 | 468 | test.showMenu(null, function (popup) { |
michael@0 | 469 | test.checkMenu([item], [], []); |
michael@0 | 470 | |
michael@0 | 471 | assert.ok(!shouldBeEvaled, |
michael@0 | 472 | "content script should have been evaluated"); |
michael@0 | 473 | |
michael@0 | 474 | test.hideMenu(function () { |
michael@0 | 475 | // Shouldn't get evaluated again |
michael@0 | 476 | test.showMenu(null, function (popup) { |
michael@0 | 477 | test.checkMenu([item], [], []); |
michael@0 | 478 | test.done(); |
michael@0 | 479 | }); |
michael@0 | 480 | }); |
michael@0 | 481 | }); |
michael@0 | 482 | }); |
michael@0 | 483 | }); |
michael@0 | 484 | }); |
michael@0 | 485 | }; |
michael@0 | 486 | |
michael@0 | 487 | // Loading a new page in the same tab should correctly start a new worker for |
michael@0 | 488 | // any content scripts |
michael@0 | 489 | exports.testPageReload = function (assert, done) { |
michael@0 | 490 | let test = new TestHelper(assert, done); |
michael@0 | 491 | let loader = test.newLoader(); |
michael@0 | 492 | |
michael@0 | 493 | let item = loader.cm.Item({ |
michael@0 | 494 | label: "Item", |
michael@0 | 495 | contentScript: "var doc = document; self.on('context', function(node) doc.body.getAttribute('showItem') == 'true');" |
michael@0 | 496 | }); |
michael@0 | 497 | |
michael@0 | 498 | test.withTestDoc(function (window, doc) { |
michael@0 | 499 | // Set a flag on the document that the item uses |
michael@0 | 500 | doc.body.setAttribute("showItem", "true"); |
michael@0 | 501 | |
michael@0 | 502 | test.showMenu(null, function (popup) { |
michael@0 | 503 | // With the attribute true the item should be visible in the menu |
michael@0 | 504 | test.checkMenu([item], [], []); |
michael@0 | 505 | test.hideMenu(function() { |
michael@0 | 506 | let browser = this.tabBrowser.getBrowserForTab(this.tab) |
michael@0 | 507 | test.delayedEventListener(browser, "load", function() { |
michael@0 | 508 | test.delayedEventListener(browser, "load", function() { |
michael@0 | 509 | window = browser.contentWindow; |
michael@0 | 510 | doc = window.document; |
michael@0 | 511 | |
michael@0 | 512 | // Set a flag on the document that the item uses |
michael@0 | 513 | doc.body.setAttribute("showItem", "false"); |
michael@0 | 514 | |
michael@0 | 515 | test.showMenu(null, function (popup) { |
michael@0 | 516 | // In the new document with the attribute false the item should be |
michael@0 | 517 | // hidden, but if the contentScript hasn't been reloaded it will |
michael@0 | 518 | // still see the old value |
michael@0 | 519 | test.checkMenu([item], [item], []); |
michael@0 | 520 | |
michael@0 | 521 | test.done(); |
michael@0 | 522 | }); |
michael@0 | 523 | }, true); |
michael@0 | 524 | browser.loadURI(TEST_DOC_URL, null, null); |
michael@0 | 525 | }, true); |
michael@0 | 526 | // Required to make sure we load a new page in history rather than |
michael@0 | 527 | // just reloading the current page which would unload it |
michael@0 | 528 | browser.loadURI("about:blank", null, null); |
michael@0 | 529 | }); |
michael@0 | 530 | }); |
michael@0 | 531 | }); |
michael@0 | 532 | }; |
michael@0 | 533 | |
michael@0 | 534 | // Closing a page after it's been used with a worker should cause the worker |
michael@0 | 535 | // to be destroyed |
michael@0 | 536 | /*exports.testWorkerDestroy = function (assert, done) { |
michael@0 | 537 | let test = new TestHelper(assert, done); |
michael@0 | 538 | let loader = test.newLoader(); |
michael@0 | 539 | |
michael@0 | 540 | let loadExpected = false; |
michael@0 | 541 | |
michael@0 | 542 | let item = loader.cm.Item({ |
michael@0 | 543 | label: "item", |
michael@0 | 544 | contentScript: 'self.postMessage("loaded"); self.on("detach", function () { console.log("saw detach"); self.postMessage("detach") });', |
michael@0 | 545 | onMessage: function (msg) { |
michael@0 | 546 | switch (msg) { |
michael@0 | 547 | case "loaded": |
michael@0 | 548 | assert.ok(loadExpected, "Should have seen the load event at the right time"); |
michael@0 | 549 | loadExpected = false; |
michael@0 | 550 | break; |
michael@0 | 551 | case "detach": |
michael@0 | 552 | test.done(); |
michael@0 | 553 | break; |
michael@0 | 554 | } |
michael@0 | 555 | } |
michael@0 | 556 | }); |
michael@0 | 557 | |
michael@0 | 558 | test.withTestDoc(function (window, doc) { |
michael@0 | 559 | loadExpected = true; |
michael@0 | 560 | test.showMenu(null, function (popup) { |
michael@0 | 561 | assert.ok(!loadExpected, "Should have seen a message"); |
michael@0 | 562 | |
michael@0 | 563 | test.checkMenu([item], [], []); |
michael@0 | 564 | |
michael@0 | 565 | test.closeTab(); |
michael@0 | 566 | }); |
michael@0 | 567 | }); |
michael@0 | 568 | };*/ |
michael@0 | 569 | |
michael@0 | 570 | |
michael@0 | 571 | // Content contexts that return true should cause their items to be present |
michael@0 | 572 | // in the menu. |
michael@0 | 573 | exports.testContentContextMatch = function (assert, done) { |
michael@0 | 574 | let test = new TestHelper(assert, done); |
michael@0 | 575 | let loader = test.newLoader(); |
michael@0 | 576 | |
michael@0 | 577 | let item = new loader.cm.Item({ |
michael@0 | 578 | label: "item", |
michael@0 | 579 | contentScript: 'self.on("context", function () true);' |
michael@0 | 580 | }); |
michael@0 | 581 | |
michael@0 | 582 | test.showMenu(null, function (popup) { |
michael@0 | 583 | test.checkMenu([item], [], []); |
michael@0 | 584 | test.done(); |
michael@0 | 585 | }); |
michael@0 | 586 | }; |
michael@0 | 587 | |
michael@0 | 588 | |
michael@0 | 589 | // Content contexts that return false should cause their items to be absent |
michael@0 | 590 | // from the menu. |
michael@0 | 591 | exports.testContentContextNoMatch = function (assert, done) { |
michael@0 | 592 | let test = new TestHelper(assert, done); |
michael@0 | 593 | let loader = test.newLoader(); |
michael@0 | 594 | |
michael@0 | 595 | let item = new loader.cm.Item({ |
michael@0 | 596 | label: "item", |
michael@0 | 597 | contentScript: 'self.on("context", function () false);' |
michael@0 | 598 | }); |
michael@0 | 599 | |
michael@0 | 600 | test.showMenu(null, function (popup) { |
michael@0 | 601 | test.checkMenu([item], [item], []); |
michael@0 | 602 | test.done(); |
michael@0 | 603 | }); |
michael@0 | 604 | }; |
michael@0 | 605 | |
michael@0 | 606 | |
michael@0 | 607 | // Content contexts that return undefined should cause their items to be absent |
michael@0 | 608 | // from the menu. |
michael@0 | 609 | exports.testContentContextUndefined = function (assert, done) { |
michael@0 | 610 | let test = new TestHelper(assert, done); |
michael@0 | 611 | let loader = test.newLoader(); |
michael@0 | 612 | |
michael@0 | 613 | let item = new loader.cm.Item({ |
michael@0 | 614 | label: "item", |
michael@0 | 615 | contentScript: 'self.on("context", function () {});' |
michael@0 | 616 | }); |
michael@0 | 617 | |
michael@0 | 618 | test.showMenu(null, function (popup) { |
michael@0 | 619 | test.checkMenu([item], [item], []); |
michael@0 | 620 | test.done(); |
michael@0 | 621 | }); |
michael@0 | 622 | }; |
michael@0 | 623 | |
michael@0 | 624 | |
michael@0 | 625 | // Content contexts that return an empty string should cause their items to be |
michael@0 | 626 | // absent from the menu and shouldn't wipe the label |
michael@0 | 627 | exports.testContentContextEmptyString = function (assert, done) { |
michael@0 | 628 | let test = new TestHelper(assert, done); |
michael@0 | 629 | let loader = test.newLoader(); |
michael@0 | 630 | |
michael@0 | 631 | let item = new loader.cm.Item({ |
michael@0 | 632 | label: "item", |
michael@0 | 633 | contentScript: 'self.on("context", function () "");' |
michael@0 | 634 | }); |
michael@0 | 635 | |
michael@0 | 636 | test.showMenu(null, function (popup) { |
michael@0 | 637 | test.checkMenu([item], [item], []); |
michael@0 | 638 | assert.equal(item.label, "item", "Label should still be correct"); |
michael@0 | 639 | test.done(); |
michael@0 | 640 | }); |
michael@0 | 641 | }; |
michael@0 | 642 | |
michael@0 | 643 | |
michael@0 | 644 | // If any content contexts returns true then their items should be present in |
michael@0 | 645 | // the menu. |
michael@0 | 646 | exports.testMultipleContentContextMatch1 = function (assert, done) { |
michael@0 | 647 | let test = new TestHelper(assert, done); |
michael@0 | 648 | let loader = test.newLoader(); |
michael@0 | 649 | |
michael@0 | 650 | let item = new loader.cm.Item({ |
michael@0 | 651 | label: "item", |
michael@0 | 652 | contentScript: 'self.on("context", function () true); ' + |
michael@0 | 653 | 'self.on("context", function () false);', |
michael@0 | 654 | onMessage: function() { |
michael@0 | 655 | test.fail("Should not have called the second context listener"); |
michael@0 | 656 | } |
michael@0 | 657 | }); |
michael@0 | 658 | |
michael@0 | 659 | test.showMenu(null, function (popup) { |
michael@0 | 660 | test.checkMenu([item], [], []); |
michael@0 | 661 | test.done(); |
michael@0 | 662 | }); |
michael@0 | 663 | }; |
michael@0 | 664 | |
michael@0 | 665 | |
michael@0 | 666 | // If any content contexts returns true then their items should be present in |
michael@0 | 667 | // the menu. |
michael@0 | 668 | exports.testMultipleContentContextMatch2 = function (assert, done) { |
michael@0 | 669 | let test = new TestHelper(assert, done); |
michael@0 | 670 | let loader = test.newLoader(); |
michael@0 | 671 | |
michael@0 | 672 | let item = new loader.cm.Item({ |
michael@0 | 673 | label: "item", |
michael@0 | 674 | contentScript: 'self.on("context", function () false); ' + |
michael@0 | 675 | 'self.on("context", function () true);' |
michael@0 | 676 | }); |
michael@0 | 677 | |
michael@0 | 678 | test.showMenu(null, function (popup) { |
michael@0 | 679 | test.checkMenu([item], [], []); |
michael@0 | 680 | test.done(); |
michael@0 | 681 | }); |
michael@0 | 682 | }; |
michael@0 | 683 | |
michael@0 | 684 | |
michael@0 | 685 | // If any content contexts returns a string then their items should be present |
michael@0 | 686 | // in the menu. |
michael@0 | 687 | exports.testMultipleContentContextString1 = function (assert, done) { |
michael@0 | 688 | let test = new TestHelper(assert, done); |
michael@0 | 689 | let loader = test.newLoader(); |
michael@0 | 690 | |
michael@0 | 691 | let item = new loader.cm.Item({ |
michael@0 | 692 | label: "item", |
michael@0 | 693 | contentScript: 'self.on("context", function () "new label"); ' + |
michael@0 | 694 | 'self.on("context", function () false);' |
michael@0 | 695 | }); |
michael@0 | 696 | |
michael@0 | 697 | test.showMenu(null, function (popup) { |
michael@0 | 698 | test.checkMenu([item], [], []); |
michael@0 | 699 | assert.equal(item.label, "new label", "Label should have changed"); |
michael@0 | 700 | test.done(); |
michael@0 | 701 | }); |
michael@0 | 702 | }; |
michael@0 | 703 | |
michael@0 | 704 | |
michael@0 | 705 | // If any content contexts returns a string then their items should be present |
michael@0 | 706 | // in the menu. |
michael@0 | 707 | exports.testMultipleContentContextString2 = function (assert, done) { |
michael@0 | 708 | let test = new TestHelper(assert, done); |
michael@0 | 709 | let loader = test.newLoader(); |
michael@0 | 710 | |
michael@0 | 711 | let item = new loader.cm.Item({ |
michael@0 | 712 | label: "item", |
michael@0 | 713 | contentScript: 'self.on("context", function () false); ' + |
michael@0 | 714 | 'self.on("context", function () "new label");' |
michael@0 | 715 | }); |
michael@0 | 716 | |
michael@0 | 717 | test.showMenu(null, function (popup) { |
michael@0 | 718 | test.checkMenu([item], [], []); |
michael@0 | 719 | assert.equal(item.label, "new label", "Label should have changed"); |
michael@0 | 720 | test.done(); |
michael@0 | 721 | }); |
michael@0 | 722 | }; |
michael@0 | 723 | |
michael@0 | 724 | |
michael@0 | 725 | // If many content contexts returns a string then the first should take effect |
michael@0 | 726 | exports.testMultipleContentContextString3 = function (assert, done) { |
michael@0 | 727 | let test = new TestHelper(assert, done); |
michael@0 | 728 | let loader = test.newLoader(); |
michael@0 | 729 | |
michael@0 | 730 | let item = new loader.cm.Item({ |
michael@0 | 731 | label: "item", |
michael@0 | 732 | contentScript: 'self.on("context", function () "new label 1"); ' + |
michael@0 | 733 | 'self.on("context", function () "new label 2");' |
michael@0 | 734 | }); |
michael@0 | 735 | |
michael@0 | 736 | test.showMenu(null, function (popup) { |
michael@0 | 737 | test.checkMenu([item], [], []); |
michael@0 | 738 | assert.equal(item.label, "new label 1", "Label should have changed"); |
michael@0 | 739 | test.done(); |
michael@0 | 740 | }); |
michael@0 | 741 | }; |
michael@0 | 742 | |
michael@0 | 743 | |
michael@0 | 744 | // Content contexts that return true should cause their items to be present |
michael@0 | 745 | // in the menu when context clicking an active element. |
michael@0 | 746 | exports.testContentContextMatchActiveElement = function (assert, done) { |
michael@0 | 747 | let test = new TestHelper(assert, done); |
michael@0 | 748 | let loader = test.newLoader(); |
michael@0 | 749 | |
michael@0 | 750 | let items = [ |
michael@0 | 751 | new loader.cm.Item({ |
michael@0 | 752 | label: "item 1", |
michael@0 | 753 | contentScript: 'self.on("context", function () true);' |
michael@0 | 754 | }), |
michael@0 | 755 | new loader.cm.Item({ |
michael@0 | 756 | label: "item 2", |
michael@0 | 757 | context: undefined, |
michael@0 | 758 | contentScript: 'self.on("context", function () true);' |
michael@0 | 759 | }), |
michael@0 | 760 | // These items will always be hidden by the declarative usage of PageContext |
michael@0 | 761 | new loader.cm.Item({ |
michael@0 | 762 | label: "item 3", |
michael@0 | 763 | context: loader.cm.PageContext(), |
michael@0 | 764 | contentScript: 'self.on("context", function () true);' |
michael@0 | 765 | }), |
michael@0 | 766 | new loader.cm.Item({ |
michael@0 | 767 | label: "item 4", |
michael@0 | 768 | context: [loader.cm.PageContext()], |
michael@0 | 769 | contentScript: 'self.on("context", function () true);' |
michael@0 | 770 | }) |
michael@0 | 771 | ]; |
michael@0 | 772 | |
michael@0 | 773 | test.withTestDoc(function (window, doc) { |
michael@0 | 774 | test.showMenu(doc.getElementById("image"), function (popup) { |
michael@0 | 775 | test.checkMenu(items, [items[2], items[3]], []); |
michael@0 | 776 | test.done(); |
michael@0 | 777 | }); |
michael@0 | 778 | }); |
michael@0 | 779 | }; |
michael@0 | 780 | |
michael@0 | 781 | |
michael@0 | 782 | // Content contexts that return false should cause their items to be absent |
michael@0 | 783 | // from the menu when context clicking an active element. |
michael@0 | 784 | exports.testContentContextNoMatchActiveElement = function (assert, done) { |
michael@0 | 785 | let test = new TestHelper(assert, done); |
michael@0 | 786 | let loader = test.newLoader(); |
michael@0 | 787 | |
michael@0 | 788 | let items = [ |
michael@0 | 789 | new loader.cm.Item({ |
michael@0 | 790 | label: "item 1", |
michael@0 | 791 | contentScript: 'self.on("context", function () false);' |
michael@0 | 792 | }), |
michael@0 | 793 | new loader.cm.Item({ |
michael@0 | 794 | label: "item 2", |
michael@0 | 795 | context: undefined, |
michael@0 | 796 | contentScript: 'self.on("context", function () false);' |
michael@0 | 797 | }), |
michael@0 | 798 | // These items will always be hidden by the declarative usage of PageContext |
michael@0 | 799 | new loader.cm.Item({ |
michael@0 | 800 | label: "item 3", |
michael@0 | 801 | context: loader.cm.PageContext(), |
michael@0 | 802 | contentScript: 'self.on("context", function () false);' |
michael@0 | 803 | }), |
michael@0 | 804 | new loader.cm.Item({ |
michael@0 | 805 | label: "item 4", |
michael@0 | 806 | context: [loader.cm.PageContext()], |
michael@0 | 807 | contentScript: 'self.on("context", function () false);' |
michael@0 | 808 | }) |
michael@0 | 809 | ]; |
michael@0 | 810 | |
michael@0 | 811 | test.withTestDoc(function (window, doc) { |
michael@0 | 812 | test.showMenu(doc.getElementById("image"), function (popup) { |
michael@0 | 813 | test.checkMenu(items, items, []); |
michael@0 | 814 | test.done(); |
michael@0 | 815 | }); |
michael@0 | 816 | }); |
michael@0 | 817 | }; |
michael@0 | 818 | |
michael@0 | 819 | |
michael@0 | 820 | // Content contexts that return undefined should cause their items to be absent |
michael@0 | 821 | // from the menu when context clicking an active element. |
michael@0 | 822 | exports.testContentContextNoMatchActiveElement = function (assert, done) { |
michael@0 | 823 | let test = new TestHelper(assert, done); |
michael@0 | 824 | let loader = test.newLoader(); |
michael@0 | 825 | |
michael@0 | 826 | let items = [ |
michael@0 | 827 | new loader.cm.Item({ |
michael@0 | 828 | label: "item 1", |
michael@0 | 829 | contentScript: 'self.on("context", function () {});' |
michael@0 | 830 | }), |
michael@0 | 831 | new loader.cm.Item({ |
michael@0 | 832 | label: "item 2", |
michael@0 | 833 | context: undefined, |
michael@0 | 834 | contentScript: 'self.on("context", function () {});' |
michael@0 | 835 | }), |
michael@0 | 836 | // These items will always be hidden by the declarative usage of PageContext |
michael@0 | 837 | new loader.cm.Item({ |
michael@0 | 838 | label: "item 3", |
michael@0 | 839 | context: loader.cm.PageContext(), |
michael@0 | 840 | contentScript: 'self.on("context", function () {});' |
michael@0 | 841 | }), |
michael@0 | 842 | new loader.cm.Item({ |
michael@0 | 843 | label: "item 4", |
michael@0 | 844 | context: [loader.cm.PageContext()], |
michael@0 | 845 | contentScript: 'self.on("context", function () {});' |
michael@0 | 846 | }) |
michael@0 | 847 | ]; |
michael@0 | 848 | |
michael@0 | 849 | test.withTestDoc(function (window, doc) { |
michael@0 | 850 | test.showMenu(doc.getElementById("image"), function (popup) { |
michael@0 | 851 | test.checkMenu(items, items, []); |
michael@0 | 852 | test.done(); |
michael@0 | 853 | }); |
michael@0 | 854 | }); |
michael@0 | 855 | }; |
michael@0 | 856 | |
michael@0 | 857 | |
michael@0 | 858 | // Content contexts that return a string should cause their items to be present |
michael@0 | 859 | // in the menu and the items' labels to be updated. |
michael@0 | 860 | exports.testContentContextMatchString = function (assert, done) { |
michael@0 | 861 | let test = new TestHelper(assert, done); |
michael@0 | 862 | let loader = test.newLoader(); |
michael@0 | 863 | |
michael@0 | 864 | let item = new loader.cm.Item({ |
michael@0 | 865 | label: "first label", |
michael@0 | 866 | contentScript: 'self.on("context", function () "second label");' |
michael@0 | 867 | }); |
michael@0 | 868 | |
michael@0 | 869 | test.showMenu(null, function (popup) { |
michael@0 | 870 | test.checkMenu([item], [], []); |
michael@0 | 871 | assert.equal(item.label, "second label", |
michael@0 | 872 | "item's label should be updated"); |
michael@0 | 873 | test.done(); |
michael@0 | 874 | }); |
michael@0 | 875 | }; |
michael@0 | 876 | |
michael@0 | 877 | |
michael@0 | 878 | // Ensure that contentScriptFile is working correctly |
michael@0 | 879 | exports.testContentScriptFile = function (assert, done) { |
michael@0 | 880 | let test = new TestHelper(assert, done); |
michael@0 | 881 | let loader = test.newLoader(); |
michael@0 | 882 | |
michael@0 | 883 | // Reject remote files |
michael@0 | 884 | assert.throws(function() { |
michael@0 | 885 | new loader.cm.Item({ |
michael@0 | 886 | label: "item", |
michael@0 | 887 | contentScriptFile: "http://mozilla.com/context-menu.js" |
michael@0 | 888 | }); |
michael@0 | 889 | }, |
michael@0 | 890 | new RegExp("The 'contentScriptFile' option must be a local file URL " + |
michael@0 | 891 | "or an array of local file URLs."), |
michael@0 | 892 | "Item throws when contentScriptFile is a remote URL"); |
michael@0 | 893 | |
michael@0 | 894 | // But accept files from data folder |
michael@0 | 895 | let item = new loader.cm.Item({ |
michael@0 | 896 | label: "item", |
michael@0 | 897 | contentScriptFile: data.url("test-context-menu.js") |
michael@0 | 898 | }); |
michael@0 | 899 | |
michael@0 | 900 | test.showMenu(null, function (popup) { |
michael@0 | 901 | test.checkMenu([item], [], []); |
michael@0 | 902 | test.done(); |
michael@0 | 903 | }); |
michael@0 | 904 | }; |
michael@0 | 905 | |
michael@0 | 906 | |
michael@0 | 907 | // The args passed to context listeners should be correct. |
michael@0 | 908 | exports.testContentContextArgs = function (assert, done) { |
michael@0 | 909 | let test = new TestHelper(assert, done); |
michael@0 | 910 | let loader = test.newLoader(); |
michael@0 | 911 | let callbacks = 0; |
michael@0 | 912 | |
michael@0 | 913 | let item = new loader.cm.Item({ |
michael@0 | 914 | label: "item", |
michael@0 | 915 | contentScript: 'self.on("context", function (node) {' + |
michael@0 | 916 | ' self.postMessage(node.tagName);' + |
michael@0 | 917 | ' return false;' + |
michael@0 | 918 | '});', |
michael@0 | 919 | onMessage: function (tagName) { |
michael@0 | 920 | assert.equal(tagName, "HTML", "node should be an HTML element"); |
michael@0 | 921 | if (++callbacks == 2) test.done(); |
michael@0 | 922 | } |
michael@0 | 923 | }); |
michael@0 | 924 | |
michael@0 | 925 | test.showMenu(null, function () { |
michael@0 | 926 | if (++callbacks == 2) test.done(); |
michael@0 | 927 | }); |
michael@0 | 928 | }; |
michael@0 | 929 | |
michael@0 | 930 | // Multiple contexts imply intersection, not union, and content context |
michael@0 | 931 | // listeners should not be called if all declarative contexts are not current. |
michael@0 | 932 | exports.testMultipleContexts = function (assert, done) { |
michael@0 | 933 | let test = new TestHelper(assert, done); |
michael@0 | 934 | let loader = test.newLoader(); |
michael@0 | 935 | |
michael@0 | 936 | let item = new loader.cm.Item({ |
michael@0 | 937 | label: "item", |
michael@0 | 938 | context: [loader.cm.SelectorContext("a[href]"), loader.cm.PageContext()], |
michael@0 | 939 | contentScript: 'self.on("context", function () self.postMessage());', |
michael@0 | 940 | onMessage: function () { |
michael@0 | 941 | test.fail("Context listener should not be called"); |
michael@0 | 942 | } |
michael@0 | 943 | }); |
michael@0 | 944 | |
michael@0 | 945 | test.withTestDoc(function (window, doc) { |
michael@0 | 946 | test.showMenu(doc.getElementById("span-link"), function (popup) { |
michael@0 | 947 | test.checkMenu([item], [item], []); |
michael@0 | 948 | test.done(); |
michael@0 | 949 | }); |
michael@0 | 950 | }); |
michael@0 | 951 | }; |
michael@0 | 952 | |
michael@0 | 953 | // Once a context is removed, it should no longer cause its item to appear. |
michael@0 | 954 | exports.testRemoveContext = function (assert, done) { |
michael@0 | 955 | let test = new TestHelper(assert, done); |
michael@0 | 956 | let loader = test.newLoader(); |
michael@0 | 957 | |
michael@0 | 958 | let ctxt = loader.cm.SelectorContext("img"); |
michael@0 | 959 | let item = new loader.cm.Item({ |
michael@0 | 960 | label: "item", |
michael@0 | 961 | context: ctxt |
michael@0 | 962 | }); |
michael@0 | 963 | |
michael@0 | 964 | test.withTestDoc(function (window, doc) { |
michael@0 | 965 | test.showMenu(doc.getElementById("image"), function (popup) { |
michael@0 | 966 | |
michael@0 | 967 | // The item should be present at first. |
michael@0 | 968 | test.checkMenu([item], [], []); |
michael@0 | 969 | popup.hidePopup(); |
michael@0 | 970 | |
michael@0 | 971 | // Remove the img context and check again. |
michael@0 | 972 | item.context.remove(ctxt); |
michael@0 | 973 | test.showMenu(doc.getElementById("image"), function (popup) { |
michael@0 | 974 | test.checkMenu([item], [item], []); |
michael@0 | 975 | test.done(); |
michael@0 | 976 | }); |
michael@0 | 977 | }); |
michael@0 | 978 | }); |
michael@0 | 979 | }; |
michael@0 | 980 | |
michael@0 | 981 | |
michael@0 | 982 | // Lots of items should overflow into the overflow submenu. |
michael@0 | 983 | exports.testOverflow = function (assert, done) { |
michael@0 | 984 | let test = new TestHelper(assert, done); |
michael@0 | 985 | let loader = test.newLoader(); |
michael@0 | 986 | |
michael@0 | 987 | let items = []; |
michael@0 | 988 | for (let i = 0; i < OVERFLOW_THRESH_DEFAULT + 1; i++) { |
michael@0 | 989 | let item = new loader.cm.Item({ label: "item " + i }); |
michael@0 | 990 | items.push(item); |
michael@0 | 991 | } |
michael@0 | 992 | |
michael@0 | 993 | test.showMenu(null, function (popup) { |
michael@0 | 994 | test.checkMenu(items, [], []); |
michael@0 | 995 | test.done(); |
michael@0 | 996 | }); |
michael@0 | 997 | }; |
michael@0 | 998 | |
michael@0 | 999 | |
michael@0 | 1000 | // Module unload should cause all items to be removed. |
michael@0 | 1001 | exports.testUnload = function (assert, done) { |
michael@0 | 1002 | let test = new TestHelper(assert, done); |
michael@0 | 1003 | let loader = test.newLoader(); |
michael@0 | 1004 | |
michael@0 | 1005 | let item = new loader.cm.Item({ label: "item" }); |
michael@0 | 1006 | |
michael@0 | 1007 | test.showMenu(null, function (popup) { |
michael@0 | 1008 | |
michael@0 | 1009 | // The menu should contain the item. |
michael@0 | 1010 | test.checkMenu([item], [], []); |
michael@0 | 1011 | popup.hidePopup(); |
michael@0 | 1012 | |
michael@0 | 1013 | // Unload the module. |
michael@0 | 1014 | loader.unload(); |
michael@0 | 1015 | test.showMenu(null, function (popup) { |
michael@0 | 1016 | |
michael@0 | 1017 | // The item should be removed from the menu. |
michael@0 | 1018 | test.checkMenu([item], [], [item]); |
michael@0 | 1019 | test.done(); |
michael@0 | 1020 | }); |
michael@0 | 1021 | }); |
michael@0 | 1022 | }; |
michael@0 | 1023 | |
michael@0 | 1024 | |
michael@0 | 1025 | // Using multiple module instances to add items without causing overflow should |
michael@0 | 1026 | // work OK. Assumes OVERFLOW_THRESH_DEFAULT >= 2. |
michael@0 | 1027 | exports.testMultipleModulesAdd = function (assert, done) { |
michael@0 | 1028 | let test = new TestHelper(assert, done); |
michael@0 | 1029 | let loader0 = test.newLoader(); |
michael@0 | 1030 | let loader1 = test.newLoader(); |
michael@0 | 1031 | |
michael@0 | 1032 | // Use each module to add an item, then unload each module in turn. |
michael@0 | 1033 | let item0 = new loader0.cm.Item({ label: "item 0" }); |
michael@0 | 1034 | let item1 = new loader1.cm.Item({ label: "item 1" }); |
michael@0 | 1035 | |
michael@0 | 1036 | test.showMenu(null, function (popup) { |
michael@0 | 1037 | |
michael@0 | 1038 | // The menu should contain both items. |
michael@0 | 1039 | test.checkMenu([item0, item1], [], []); |
michael@0 | 1040 | popup.hidePopup(); |
michael@0 | 1041 | |
michael@0 | 1042 | // Unload the first module. |
michael@0 | 1043 | loader0.unload(); |
michael@0 | 1044 | test.showMenu(null, function (popup) { |
michael@0 | 1045 | |
michael@0 | 1046 | // The first item should be removed from the menu. |
michael@0 | 1047 | test.checkMenu([item0, item1], [], [item0]); |
michael@0 | 1048 | popup.hidePopup(); |
michael@0 | 1049 | |
michael@0 | 1050 | // Unload the second module. |
michael@0 | 1051 | loader1.unload(); |
michael@0 | 1052 | test.showMenu(null, function (popup) { |
michael@0 | 1053 | |
michael@0 | 1054 | // Both items should be removed from the menu. |
michael@0 | 1055 | test.checkMenu([item0, item1], [], [item0, item1]); |
michael@0 | 1056 | test.done(); |
michael@0 | 1057 | }); |
michael@0 | 1058 | }); |
michael@0 | 1059 | }); |
michael@0 | 1060 | }; |
michael@0 | 1061 | |
michael@0 | 1062 | |
michael@0 | 1063 | // Using multiple module instances to add items causing overflow should work OK. |
michael@0 | 1064 | exports.testMultipleModulesAddOverflow = function (assert, done) { |
michael@0 | 1065 | let test = new TestHelper(assert, done); |
michael@0 | 1066 | let loader0 = test.newLoader(); |
michael@0 | 1067 | let loader1 = test.newLoader(); |
michael@0 | 1068 | |
michael@0 | 1069 | // Use module 0 to add OVERFLOW_THRESH_DEFAULT items. |
michael@0 | 1070 | let items0 = []; |
michael@0 | 1071 | for (let i = 0; i < OVERFLOW_THRESH_DEFAULT; i++) { |
michael@0 | 1072 | let item = new loader0.cm.Item({ label: "item 0 " + i }); |
michael@0 | 1073 | items0.push(item); |
michael@0 | 1074 | } |
michael@0 | 1075 | |
michael@0 | 1076 | // Use module 1 to add one item. |
michael@0 | 1077 | let item1 = new loader1.cm.Item({ label: "item 1" }); |
michael@0 | 1078 | |
michael@0 | 1079 | let allItems = items0.concat(item1); |
michael@0 | 1080 | |
michael@0 | 1081 | test.showMenu(null, function (popup) { |
michael@0 | 1082 | |
michael@0 | 1083 | // The menu should contain all items in overflow. |
michael@0 | 1084 | test.checkMenu(allItems, [], []); |
michael@0 | 1085 | popup.hidePopup(); |
michael@0 | 1086 | |
michael@0 | 1087 | // Unload the first module. |
michael@0 | 1088 | loader0.unload(); |
michael@0 | 1089 | test.showMenu(null, function (popup) { |
michael@0 | 1090 | |
michael@0 | 1091 | // The first items should be removed from the menu, which should not |
michael@0 | 1092 | // overflow. |
michael@0 | 1093 | test.checkMenu(allItems, [], items0); |
michael@0 | 1094 | popup.hidePopup(); |
michael@0 | 1095 | |
michael@0 | 1096 | // Unload the second module. |
michael@0 | 1097 | loader1.unload(); |
michael@0 | 1098 | test.showMenu(null, function (popup) { |
michael@0 | 1099 | |
michael@0 | 1100 | // All items should be removed from the menu. |
michael@0 | 1101 | test.checkMenu(allItems, [], allItems); |
michael@0 | 1102 | test.done(); |
michael@0 | 1103 | }); |
michael@0 | 1104 | }); |
michael@0 | 1105 | }); |
michael@0 | 1106 | }; |
michael@0 | 1107 | |
michael@0 | 1108 | |
michael@0 | 1109 | // Using multiple module instances to modify the menu without causing overflow |
michael@0 | 1110 | // should work OK. This test creates two loaders and: |
michael@0 | 1111 | // loader0 create item -> loader1 create item -> loader0.unload -> |
michael@0 | 1112 | // loader1.unload |
michael@0 | 1113 | exports.testMultipleModulesDiffContexts1 = function (assert, done) { |
michael@0 | 1114 | let test = new TestHelper(assert, done); |
michael@0 | 1115 | let loader0 = test.newLoader(); |
michael@0 | 1116 | let loader1 = test.newLoader(); |
michael@0 | 1117 | |
michael@0 | 1118 | let item0 = new loader0.cm.Item({ |
michael@0 | 1119 | label: "item 0", |
michael@0 | 1120 | context: loader0.cm.SelectorContext("img") |
michael@0 | 1121 | }); |
michael@0 | 1122 | |
michael@0 | 1123 | let item1 = new loader1.cm.Item({ label: "item 1" }); |
michael@0 | 1124 | |
michael@0 | 1125 | test.showMenu(null, function (popup) { |
michael@0 | 1126 | |
michael@0 | 1127 | // The menu should contain item1. |
michael@0 | 1128 | test.checkMenu([item0, item1], [item0], []); |
michael@0 | 1129 | popup.hidePopup(); |
michael@0 | 1130 | |
michael@0 | 1131 | // Unload module 0. |
michael@0 | 1132 | loader0.unload(); |
michael@0 | 1133 | test.showMenu(null, function (popup) { |
michael@0 | 1134 | |
michael@0 | 1135 | // item0 should be removed from the menu. |
michael@0 | 1136 | test.checkMenu([item0, item1], [], [item0]); |
michael@0 | 1137 | popup.hidePopup(); |
michael@0 | 1138 | |
michael@0 | 1139 | // Unload module 1. |
michael@0 | 1140 | loader1.unload(); |
michael@0 | 1141 | test.showMenu(null, function (popup) { |
michael@0 | 1142 | |
michael@0 | 1143 | // Both items should be removed from the menu. |
michael@0 | 1144 | test.checkMenu([item0, item1], [], [item0, item1]); |
michael@0 | 1145 | test.done(); |
michael@0 | 1146 | }); |
michael@0 | 1147 | }); |
michael@0 | 1148 | }); |
michael@0 | 1149 | }; |
michael@0 | 1150 | |
michael@0 | 1151 | |
michael@0 | 1152 | // Using multiple module instances to modify the menu without causing overflow |
michael@0 | 1153 | // should work OK. This test creates two loaders and: |
michael@0 | 1154 | // loader1 create item -> loader0 create item -> loader0.unload -> |
michael@0 | 1155 | // loader1.unload |
michael@0 | 1156 | exports.testMultipleModulesDiffContexts2 = function (assert, done) { |
michael@0 | 1157 | let test = new TestHelper(assert, done); |
michael@0 | 1158 | let loader0 = test.newLoader(); |
michael@0 | 1159 | let loader1 = test.newLoader(); |
michael@0 | 1160 | |
michael@0 | 1161 | let item1 = new loader1.cm.Item({ label: "item 1" }); |
michael@0 | 1162 | |
michael@0 | 1163 | let item0 = new loader0.cm.Item({ |
michael@0 | 1164 | label: "item 0", |
michael@0 | 1165 | context: loader0.cm.SelectorContext("img") |
michael@0 | 1166 | }); |
michael@0 | 1167 | |
michael@0 | 1168 | test.showMenu(null, function (popup) { |
michael@0 | 1169 | |
michael@0 | 1170 | // The menu should contain item1. |
michael@0 | 1171 | test.checkMenu([item0, item1], [item0], []); |
michael@0 | 1172 | popup.hidePopup(); |
michael@0 | 1173 | |
michael@0 | 1174 | // Unload module 0. |
michael@0 | 1175 | loader0.unload(); |
michael@0 | 1176 | test.showMenu(null, function (popup) { |
michael@0 | 1177 | |
michael@0 | 1178 | // item0 should be removed from the menu. |
michael@0 | 1179 | test.checkMenu([item0, item1], [], [item0]); |
michael@0 | 1180 | popup.hidePopup(); |
michael@0 | 1181 | |
michael@0 | 1182 | // Unload module 1. |
michael@0 | 1183 | loader1.unload(); |
michael@0 | 1184 | test.showMenu(null, function (popup) { |
michael@0 | 1185 | |
michael@0 | 1186 | // Both items should be removed from the menu. |
michael@0 | 1187 | test.checkMenu([item0, item1], [], [item0, item1]); |
michael@0 | 1188 | test.done(); |
michael@0 | 1189 | }); |
michael@0 | 1190 | }); |
michael@0 | 1191 | }); |
michael@0 | 1192 | }; |
michael@0 | 1193 | |
michael@0 | 1194 | |
michael@0 | 1195 | // Using multiple module instances to modify the menu without causing overflow |
michael@0 | 1196 | // should work OK. This test creates two loaders and: |
michael@0 | 1197 | // loader0 create item -> loader1 create item -> loader1.unload -> |
michael@0 | 1198 | // loader0.unload |
michael@0 | 1199 | exports.testMultipleModulesDiffContexts3 = function (assert, done) { |
michael@0 | 1200 | let test = new TestHelper(assert, done); |
michael@0 | 1201 | let loader0 = test.newLoader(); |
michael@0 | 1202 | let loader1 = test.newLoader(); |
michael@0 | 1203 | |
michael@0 | 1204 | let item0 = new loader0.cm.Item({ |
michael@0 | 1205 | label: "item 0", |
michael@0 | 1206 | context: loader0.cm.SelectorContext("img") |
michael@0 | 1207 | }); |
michael@0 | 1208 | |
michael@0 | 1209 | let item1 = new loader1.cm.Item({ label: "item 1" }); |
michael@0 | 1210 | |
michael@0 | 1211 | test.showMenu(null, function (popup) { |
michael@0 | 1212 | |
michael@0 | 1213 | // The menu should contain item1. |
michael@0 | 1214 | test.checkMenu([item0, item1], [item0], []); |
michael@0 | 1215 | popup.hidePopup(); |
michael@0 | 1216 | |
michael@0 | 1217 | // Unload module 1. |
michael@0 | 1218 | loader1.unload(); |
michael@0 | 1219 | test.showMenu(null, function (popup) { |
michael@0 | 1220 | |
michael@0 | 1221 | // item1 should be removed from the menu. |
michael@0 | 1222 | test.checkMenu([item0, item1], [item0], [item1]); |
michael@0 | 1223 | popup.hidePopup(); |
michael@0 | 1224 | |
michael@0 | 1225 | // Unload module 0. |
michael@0 | 1226 | loader0.unload(); |
michael@0 | 1227 | test.showMenu(null, function (popup) { |
michael@0 | 1228 | |
michael@0 | 1229 | // Both items should be removed from the menu. |
michael@0 | 1230 | test.checkMenu([item0, item1], [], [item0, item1]); |
michael@0 | 1231 | test.done(); |
michael@0 | 1232 | }); |
michael@0 | 1233 | }); |
michael@0 | 1234 | }); |
michael@0 | 1235 | }; |
michael@0 | 1236 | |
michael@0 | 1237 | |
michael@0 | 1238 | // Using multiple module instances to modify the menu without causing overflow |
michael@0 | 1239 | // should work OK. This test creates two loaders and: |
michael@0 | 1240 | // loader1 create item -> loader0 create item -> loader1.unload -> |
michael@0 | 1241 | // loader0.unload |
michael@0 | 1242 | exports.testMultipleModulesDiffContexts4 = function (assert, done) { |
michael@0 | 1243 | let test = new TestHelper(assert, done); |
michael@0 | 1244 | let loader0 = test.newLoader(); |
michael@0 | 1245 | let loader1 = test.newLoader(); |
michael@0 | 1246 | |
michael@0 | 1247 | let item1 = new loader1.cm.Item({ label: "item 1" }); |
michael@0 | 1248 | |
michael@0 | 1249 | let item0 = new loader0.cm.Item({ |
michael@0 | 1250 | label: "item 0", |
michael@0 | 1251 | context: loader0.cm.SelectorContext("img") |
michael@0 | 1252 | }); |
michael@0 | 1253 | |
michael@0 | 1254 | test.showMenu(null, function (popup) { |
michael@0 | 1255 | |
michael@0 | 1256 | // The menu should contain item1. |
michael@0 | 1257 | test.checkMenu([item0, item1], [item0], []); |
michael@0 | 1258 | popup.hidePopup(); |
michael@0 | 1259 | |
michael@0 | 1260 | // Unload module 1. |
michael@0 | 1261 | loader1.unload(); |
michael@0 | 1262 | test.showMenu(null, function (popup) { |
michael@0 | 1263 | |
michael@0 | 1264 | // item1 should be removed from the menu. |
michael@0 | 1265 | test.checkMenu([item0, item1], [item0], [item1]); |
michael@0 | 1266 | popup.hidePopup(); |
michael@0 | 1267 | |
michael@0 | 1268 | // Unload module 0. |
michael@0 | 1269 | loader0.unload(); |
michael@0 | 1270 | test.showMenu(null, function (popup) { |
michael@0 | 1271 | |
michael@0 | 1272 | // Both items should be removed from the menu. |
michael@0 | 1273 | test.checkMenu([item0, item1], [], [item0, item1]); |
michael@0 | 1274 | test.done(); |
michael@0 | 1275 | }); |
michael@0 | 1276 | }); |
michael@0 | 1277 | }); |
michael@0 | 1278 | }; |
michael@0 | 1279 | |
michael@0 | 1280 | |
michael@0 | 1281 | // Test interactions between a loaded module, unloading another module, and the |
michael@0 | 1282 | // menu separator and overflow submenu. |
michael@0 | 1283 | exports.testMultipleModulesAddRemove = function (assert, done) { |
michael@0 | 1284 | let test = new TestHelper(assert, done); |
michael@0 | 1285 | let loader0 = test.newLoader(); |
michael@0 | 1286 | let loader1 = test.newLoader(); |
michael@0 | 1287 | |
michael@0 | 1288 | let item = new loader0.cm.Item({ label: "item" }); |
michael@0 | 1289 | |
michael@0 | 1290 | test.showMenu(null, function (popup) { |
michael@0 | 1291 | |
michael@0 | 1292 | // The menu should contain the item. |
michael@0 | 1293 | test.checkMenu([item], [], []); |
michael@0 | 1294 | popup.hidePopup(); |
michael@0 | 1295 | |
michael@0 | 1296 | // Remove the item. |
michael@0 | 1297 | item.destroy(); |
michael@0 | 1298 | test.showMenu(null, function (popup) { |
michael@0 | 1299 | |
michael@0 | 1300 | // The item should be removed from the menu. |
michael@0 | 1301 | test.checkMenu([item], [], [item]); |
michael@0 | 1302 | popup.hidePopup(); |
michael@0 | 1303 | |
michael@0 | 1304 | // Unload module 1. |
michael@0 | 1305 | loader1.unload(); |
michael@0 | 1306 | test.showMenu(null, function (popup) { |
michael@0 | 1307 | |
michael@0 | 1308 | // There shouldn't be any errors involving the menu separator or |
michael@0 | 1309 | // overflow submenu. |
michael@0 | 1310 | test.checkMenu([item], [], [item]); |
michael@0 | 1311 | test.done(); |
michael@0 | 1312 | }); |
michael@0 | 1313 | }); |
michael@0 | 1314 | }); |
michael@0 | 1315 | }; |
michael@0 | 1316 | |
michael@0 | 1317 | |
michael@0 | 1318 | // Checks that the order of menu items is correct when adding/removing across |
michael@0 | 1319 | // multiple modules. All items from a single module should remain in a group |
michael@0 | 1320 | exports.testMultipleModulesOrder = function (assert, done) { |
michael@0 | 1321 | let test = new TestHelper(assert, done); |
michael@0 | 1322 | let loader0 = test.newLoader(); |
michael@0 | 1323 | let loader1 = test.newLoader(); |
michael@0 | 1324 | |
michael@0 | 1325 | // Use each module to add an item, then unload each module in turn. |
michael@0 | 1326 | let item0 = new loader0.cm.Item({ label: "item 0" }); |
michael@0 | 1327 | let item1 = new loader1.cm.Item({ label: "item 1" }); |
michael@0 | 1328 | |
michael@0 | 1329 | test.showMenu(null, function (popup) { |
michael@0 | 1330 | |
michael@0 | 1331 | // The menu should contain both items. |
michael@0 | 1332 | test.checkMenu([item0, item1], [], []); |
michael@0 | 1333 | popup.hidePopup(); |
michael@0 | 1334 | |
michael@0 | 1335 | let item2 = new loader0.cm.Item({ label: "item 2" }); |
michael@0 | 1336 | |
michael@0 | 1337 | test.showMenu(null, function (popup) { |
michael@0 | 1338 | |
michael@0 | 1339 | // The new item should be grouped with the same items from loader0. |
michael@0 | 1340 | test.checkMenu([item0, item2, item1], [], []); |
michael@0 | 1341 | popup.hidePopup(); |
michael@0 | 1342 | |
michael@0 | 1343 | let item3 = new loader1.cm.Item({ label: "item 3" }); |
michael@0 | 1344 | |
michael@0 | 1345 | test.showMenu(null, function (popup) { |
michael@0 | 1346 | |
michael@0 | 1347 | // Same again |
michael@0 | 1348 | test.checkMenu([item0, item2, item1, item3], [], []); |
michael@0 | 1349 | test.done(); |
michael@0 | 1350 | }); |
michael@0 | 1351 | }); |
michael@0 | 1352 | }); |
michael@0 | 1353 | }; |
michael@0 | 1354 | |
michael@0 | 1355 | |
michael@0 | 1356 | // Checks that the order of menu items is correct when adding/removing across |
michael@0 | 1357 | // multiple modules when overflowing. All items from a single module should |
michael@0 | 1358 | // remain in a group |
michael@0 | 1359 | exports.testMultipleModulesOrderOverflow = function (assert, done) { |
michael@0 | 1360 | let test = new TestHelper(assert, done); |
michael@0 | 1361 | let loader0 = test.newLoader(); |
michael@0 | 1362 | let loader1 = test.newLoader(); |
michael@0 | 1363 | |
michael@0 | 1364 | let prefs = loader0.loader.require("sdk/preferences/service"); |
michael@0 | 1365 | prefs.set(OVERFLOW_THRESH_PREF, 0); |
michael@0 | 1366 | |
michael@0 | 1367 | // Use each module to add an item, then unload each module in turn. |
michael@0 | 1368 | let item0 = new loader0.cm.Item({ label: "item 0" }); |
michael@0 | 1369 | let item1 = new loader1.cm.Item({ label: "item 1" }); |
michael@0 | 1370 | |
michael@0 | 1371 | test.showMenu(null, function (popup) { |
michael@0 | 1372 | |
michael@0 | 1373 | // The menu should contain both items. |
michael@0 | 1374 | test.checkMenu([item0, item1], [], []); |
michael@0 | 1375 | popup.hidePopup(); |
michael@0 | 1376 | |
michael@0 | 1377 | let item2 = new loader0.cm.Item({ label: "item 2" }); |
michael@0 | 1378 | |
michael@0 | 1379 | test.showMenu(null, function (popup) { |
michael@0 | 1380 | |
michael@0 | 1381 | // The new item should be grouped with the same items from loader0. |
michael@0 | 1382 | test.checkMenu([item0, item2, item1], [], []); |
michael@0 | 1383 | popup.hidePopup(); |
michael@0 | 1384 | |
michael@0 | 1385 | let item3 = new loader1.cm.Item({ label: "item 3" }); |
michael@0 | 1386 | |
michael@0 | 1387 | test.showMenu(null, function (popup) { |
michael@0 | 1388 | |
michael@0 | 1389 | // Same again |
michael@0 | 1390 | test.checkMenu([item0, item2, item1, item3], [], []); |
michael@0 | 1391 | test.done(); |
michael@0 | 1392 | }); |
michael@0 | 1393 | }); |
michael@0 | 1394 | }); |
michael@0 | 1395 | }; |
michael@0 | 1396 | |
michael@0 | 1397 | |
michael@0 | 1398 | // Checks that if a module's items are all hidden then the overflow menu doesn't |
michael@0 | 1399 | // get hidden |
michael@0 | 1400 | exports.testMultipleModulesOverflowHidden = function (assert, done) { |
michael@0 | 1401 | let test = new TestHelper(assert, done); |
michael@0 | 1402 | let loader0 = test.newLoader(); |
michael@0 | 1403 | let loader1 = test.newLoader(); |
michael@0 | 1404 | |
michael@0 | 1405 | let prefs = loader0.loader.require("sdk/preferences/service"); |
michael@0 | 1406 | prefs.set(OVERFLOW_THRESH_PREF, 0); |
michael@0 | 1407 | |
michael@0 | 1408 | // Use each module to add an item, then unload each module in turn. |
michael@0 | 1409 | let item0 = new loader0.cm.Item({ label: "item 0" }); |
michael@0 | 1410 | let item1 = new loader1.cm.Item({ |
michael@0 | 1411 | label: "item 1", |
michael@0 | 1412 | context: loader1.cm.SelectorContext("a") |
michael@0 | 1413 | }); |
michael@0 | 1414 | |
michael@0 | 1415 | test.showMenu(null, function (popup) { |
michael@0 | 1416 | // One should be hidden |
michael@0 | 1417 | test.checkMenu([item0, item1], [item1], []); |
michael@0 | 1418 | test.done(); |
michael@0 | 1419 | }); |
michael@0 | 1420 | }; |
michael@0 | 1421 | |
michael@0 | 1422 | |
michael@0 | 1423 | // Checks that if a module's items are all hidden then the overflow menu doesn't |
michael@0 | 1424 | // get hidden (reverse order to above) |
michael@0 | 1425 | exports.testMultipleModulesOverflowHidden2 = function (assert, done) { |
michael@0 | 1426 | let test = new TestHelper(assert, done); |
michael@0 | 1427 | let loader0 = test.newLoader(); |
michael@0 | 1428 | let loader1 = test.newLoader(); |
michael@0 | 1429 | |
michael@0 | 1430 | let prefs = loader0.loader.require("sdk/preferences/service"); |
michael@0 | 1431 | prefs.set(OVERFLOW_THRESH_PREF, 0); |
michael@0 | 1432 | |
michael@0 | 1433 | // Use each module to add an item, then unload each module in turn. |
michael@0 | 1434 | let item0 = new loader0.cm.Item({ |
michael@0 | 1435 | label: "item 0", |
michael@0 | 1436 | context: loader0.cm.SelectorContext("a") |
michael@0 | 1437 | }); |
michael@0 | 1438 | let item1 = new loader1.cm.Item({ label: "item 1" }); |
michael@0 | 1439 | |
michael@0 | 1440 | test.showMenu(null, function (popup) { |
michael@0 | 1441 | // One should be hidden |
michael@0 | 1442 | test.checkMenu([item0, item1], [item0], []); |
michael@0 | 1443 | test.done(); |
michael@0 | 1444 | }); |
michael@0 | 1445 | }; |
michael@0 | 1446 | |
michael@0 | 1447 | |
michael@0 | 1448 | // Checks that we don't overflow if there are more items than the overflow |
michael@0 | 1449 | // threshold but not all of them are visible |
michael@0 | 1450 | exports.testOverflowIgnoresHidden = function (assert, done) { |
michael@0 | 1451 | let test = new TestHelper(assert, done); |
michael@0 | 1452 | let loader = test.newLoader(); |
michael@0 | 1453 | |
michael@0 | 1454 | let prefs = loader.loader.require("sdk/preferences/service"); |
michael@0 | 1455 | prefs.set(OVERFLOW_THRESH_PREF, 2); |
michael@0 | 1456 | |
michael@0 | 1457 | let allItems = [ |
michael@0 | 1458 | new loader.cm.Item({ |
michael@0 | 1459 | label: "item 0" |
michael@0 | 1460 | }), |
michael@0 | 1461 | new loader.cm.Item({ |
michael@0 | 1462 | label: "item 1" |
michael@0 | 1463 | }), |
michael@0 | 1464 | new loader.cm.Item({ |
michael@0 | 1465 | label: "item 2", |
michael@0 | 1466 | context: loader.cm.SelectorContext("a") |
michael@0 | 1467 | }) |
michael@0 | 1468 | ]; |
michael@0 | 1469 | |
michael@0 | 1470 | test.showMenu(null, function (popup) { |
michael@0 | 1471 | // One should be hidden |
michael@0 | 1472 | test.checkMenu(allItems, [allItems[2]], []); |
michael@0 | 1473 | test.done(); |
michael@0 | 1474 | }); |
michael@0 | 1475 | }; |
michael@0 | 1476 | |
michael@0 | 1477 | |
michael@0 | 1478 | // Checks that we don't overflow if there are more items than the overflow |
michael@0 | 1479 | // threshold but not all of them are visible |
michael@0 | 1480 | exports.testOverflowIgnoresHiddenMultipleModules1 = function (assert, done) { |
michael@0 | 1481 | let test = new TestHelper(assert, done); |
michael@0 | 1482 | let loader0 = test.newLoader(); |
michael@0 | 1483 | let loader1 = test.newLoader(); |
michael@0 | 1484 | |
michael@0 | 1485 | let prefs = loader0.loader.require("sdk/preferences/service"); |
michael@0 | 1486 | prefs.set(OVERFLOW_THRESH_PREF, 2); |
michael@0 | 1487 | |
michael@0 | 1488 | let allItems = [ |
michael@0 | 1489 | new loader0.cm.Item({ |
michael@0 | 1490 | label: "item 0" |
michael@0 | 1491 | }), |
michael@0 | 1492 | new loader0.cm.Item({ |
michael@0 | 1493 | label: "item 1" |
michael@0 | 1494 | }), |
michael@0 | 1495 | new loader1.cm.Item({ |
michael@0 | 1496 | label: "item 2", |
michael@0 | 1497 | context: loader1.cm.SelectorContext("a") |
michael@0 | 1498 | }), |
michael@0 | 1499 | new loader1.cm.Item({ |
michael@0 | 1500 | label: "item 3", |
michael@0 | 1501 | context: loader1.cm.SelectorContext("a") |
michael@0 | 1502 | }) |
michael@0 | 1503 | ]; |
michael@0 | 1504 | |
michael@0 | 1505 | test.showMenu(null, function (popup) { |
michael@0 | 1506 | // One should be hidden |
michael@0 | 1507 | test.checkMenu(allItems, [allItems[2], allItems[3]], []); |
michael@0 | 1508 | test.done(); |
michael@0 | 1509 | }); |
michael@0 | 1510 | }; |
michael@0 | 1511 | |
michael@0 | 1512 | |
michael@0 | 1513 | // Checks that we don't overflow if there are more items than the overflow |
michael@0 | 1514 | // threshold but not all of them are visible |
michael@0 | 1515 | exports.testOverflowIgnoresHiddenMultipleModules2 = function (assert, done) { |
michael@0 | 1516 | let test = new TestHelper(assert, done); |
michael@0 | 1517 | let loader0 = test.newLoader(); |
michael@0 | 1518 | let loader1 = test.newLoader(); |
michael@0 | 1519 | |
michael@0 | 1520 | let prefs = loader0.loader.require("sdk/preferences/service"); |
michael@0 | 1521 | prefs.set(OVERFLOW_THRESH_PREF, 2); |
michael@0 | 1522 | |
michael@0 | 1523 | let allItems = [ |
michael@0 | 1524 | new loader0.cm.Item({ |
michael@0 | 1525 | label: "item 0" |
michael@0 | 1526 | }), |
michael@0 | 1527 | new loader0.cm.Item({ |
michael@0 | 1528 | label: "item 1", |
michael@0 | 1529 | context: loader0.cm.SelectorContext("a") |
michael@0 | 1530 | }), |
michael@0 | 1531 | new loader1.cm.Item({ |
michael@0 | 1532 | label: "item 2" |
michael@0 | 1533 | }), |
michael@0 | 1534 | new loader1.cm.Item({ |
michael@0 | 1535 | label: "item 3", |
michael@0 | 1536 | context: loader1.cm.SelectorContext("a") |
michael@0 | 1537 | }) |
michael@0 | 1538 | ]; |
michael@0 | 1539 | |
michael@0 | 1540 | test.showMenu(null, function (popup) { |
michael@0 | 1541 | // One should be hidden |
michael@0 | 1542 | test.checkMenu(allItems, [allItems[1], allItems[3]], []); |
michael@0 | 1543 | test.done(); |
michael@0 | 1544 | }); |
michael@0 | 1545 | }; |
michael@0 | 1546 | |
michael@0 | 1547 | |
michael@0 | 1548 | // Checks that we don't overflow if there are more items than the overflow |
michael@0 | 1549 | // threshold but not all of them are visible |
michael@0 | 1550 | exports.testOverflowIgnoresHiddenMultipleModules3 = function (assert, done) { |
michael@0 | 1551 | let test = new TestHelper(assert, done); |
michael@0 | 1552 | let loader0 = test.newLoader(); |
michael@0 | 1553 | let loader1 = test.newLoader(); |
michael@0 | 1554 | |
michael@0 | 1555 | let prefs = loader0.loader.require("sdk/preferences/service"); |
michael@0 | 1556 | prefs.set(OVERFLOW_THRESH_PREF, 2); |
michael@0 | 1557 | |
michael@0 | 1558 | let allItems = [ |
michael@0 | 1559 | new loader0.cm.Item({ |
michael@0 | 1560 | label: "item 0", |
michael@0 | 1561 | context: loader0.cm.SelectorContext("a") |
michael@0 | 1562 | }), |
michael@0 | 1563 | new loader0.cm.Item({ |
michael@0 | 1564 | label: "item 1", |
michael@0 | 1565 | context: loader0.cm.SelectorContext("a") |
michael@0 | 1566 | }), |
michael@0 | 1567 | new loader1.cm.Item({ |
michael@0 | 1568 | label: "item 2" |
michael@0 | 1569 | }), |
michael@0 | 1570 | new loader1.cm.Item({ |
michael@0 | 1571 | label: "item 3" |
michael@0 | 1572 | }) |
michael@0 | 1573 | ]; |
michael@0 | 1574 | |
michael@0 | 1575 | test.showMenu(null, function (popup) { |
michael@0 | 1576 | // One should be hidden |
michael@0 | 1577 | test.checkMenu(allItems, [allItems[0], allItems[1]], []); |
michael@0 | 1578 | test.done(); |
michael@0 | 1579 | }); |
michael@0 | 1580 | }; |
michael@0 | 1581 | |
michael@0 | 1582 | |
michael@0 | 1583 | // Tests that we transition between overflowing to non-overflowing to no items |
michael@0 | 1584 | // and back again |
michael@0 | 1585 | exports.testOverflowTransition = function (assert, done) { |
michael@0 | 1586 | let test = new TestHelper(assert, done); |
michael@0 | 1587 | let loader = test.newLoader(); |
michael@0 | 1588 | |
michael@0 | 1589 | let prefs = loader.loader.require("sdk/preferences/service"); |
michael@0 | 1590 | prefs.set(OVERFLOW_THRESH_PREF, 2); |
michael@0 | 1591 | |
michael@0 | 1592 | let pItems = [ |
michael@0 | 1593 | new loader.cm.Item({ |
michael@0 | 1594 | label: "item 0", |
michael@0 | 1595 | context: loader.cm.SelectorContext("p") |
michael@0 | 1596 | }), |
michael@0 | 1597 | new loader.cm.Item({ |
michael@0 | 1598 | label: "item 1", |
michael@0 | 1599 | context: loader.cm.SelectorContext("p") |
michael@0 | 1600 | }) |
michael@0 | 1601 | ]; |
michael@0 | 1602 | |
michael@0 | 1603 | let aItems = [ |
michael@0 | 1604 | new loader.cm.Item({ |
michael@0 | 1605 | label: "item 2", |
michael@0 | 1606 | context: loader.cm.SelectorContext("a") |
michael@0 | 1607 | }), |
michael@0 | 1608 | new loader.cm.Item({ |
michael@0 | 1609 | label: "item 3", |
michael@0 | 1610 | context: loader.cm.SelectorContext("a") |
michael@0 | 1611 | }) |
michael@0 | 1612 | ]; |
michael@0 | 1613 | |
michael@0 | 1614 | let allItems = pItems.concat(aItems); |
michael@0 | 1615 | |
michael@0 | 1616 | test.withTestDoc(function (window, doc) { |
michael@0 | 1617 | test.showMenu(doc.getElementById("link"), function (popup) { |
michael@0 | 1618 | // The menu should contain all items and will overflow |
michael@0 | 1619 | test.checkMenu(allItems, [], []); |
michael@0 | 1620 | popup.hidePopup(); |
michael@0 | 1621 | |
michael@0 | 1622 | test.showMenu(doc.getElementById("text"), function (popup) { |
michael@0 | 1623 | // Only contains hald the items and will not overflow |
michael@0 | 1624 | test.checkMenu(allItems, aItems, []); |
michael@0 | 1625 | popup.hidePopup(); |
michael@0 | 1626 | |
michael@0 | 1627 | test.showMenu(null, function (popup) { |
michael@0 | 1628 | // None of the items will be visible |
michael@0 | 1629 | test.checkMenu(allItems, allItems, []); |
michael@0 | 1630 | popup.hidePopup(); |
michael@0 | 1631 | |
michael@0 | 1632 | test.showMenu(doc.getElementById("text"), function (popup) { |
michael@0 | 1633 | // Only contains hald the items and will not overflow |
michael@0 | 1634 | test.checkMenu(allItems, aItems, []); |
michael@0 | 1635 | popup.hidePopup(); |
michael@0 | 1636 | |
michael@0 | 1637 | test.showMenu(doc.getElementById("link"), function (popup) { |
michael@0 | 1638 | // The menu should contain all items and will overflow |
michael@0 | 1639 | test.checkMenu(allItems, [], []); |
michael@0 | 1640 | popup.hidePopup(); |
michael@0 | 1641 | |
michael@0 | 1642 | test.showMenu(null, function (popup) { |
michael@0 | 1643 | // None of the items will be visible |
michael@0 | 1644 | test.checkMenu(allItems, allItems, []); |
michael@0 | 1645 | popup.hidePopup(); |
michael@0 | 1646 | |
michael@0 | 1647 | test.showMenu(doc.getElementById("link"), function (popup) { |
michael@0 | 1648 | // The menu should contain all items and will overflow |
michael@0 | 1649 | test.checkMenu(allItems, [], []); |
michael@0 | 1650 | test.done(); |
michael@0 | 1651 | }); |
michael@0 | 1652 | }); |
michael@0 | 1653 | }); |
michael@0 | 1654 | }); |
michael@0 | 1655 | }); |
michael@0 | 1656 | }); |
michael@0 | 1657 | }); |
michael@0 | 1658 | }); |
michael@0 | 1659 | }; |
michael@0 | 1660 | |
michael@0 | 1661 | |
michael@0 | 1662 | // An item's command listener should work. |
michael@0 | 1663 | exports.testItemCommand = function (assert, done) { |
michael@0 | 1664 | let test = new TestHelper(assert, done); |
michael@0 | 1665 | let loader = test.newLoader(); |
michael@0 | 1666 | |
michael@0 | 1667 | let item = new loader.cm.Item({ |
michael@0 | 1668 | label: "item", |
michael@0 | 1669 | data: "item data", |
michael@0 | 1670 | contentScript: 'self.on("click", function (node, data) {' + |
michael@0 | 1671 | ' self.postMessage({' + |
michael@0 | 1672 | ' tagName: node.tagName,' + |
michael@0 | 1673 | ' data: data' + |
michael@0 | 1674 | ' });' + |
michael@0 | 1675 | '});', |
michael@0 | 1676 | onMessage: function (data) { |
michael@0 | 1677 | assert.equal(this, item, "`this` inside onMessage should be item"); |
michael@0 | 1678 | assert.equal(data.tagName, "HTML", "node should be an HTML element"); |
michael@0 | 1679 | assert.equal(data.data, item.data, "data should be item data"); |
michael@0 | 1680 | test.done(); |
michael@0 | 1681 | } |
michael@0 | 1682 | }); |
michael@0 | 1683 | |
michael@0 | 1684 | test.showMenu(null, function (popup) { |
michael@0 | 1685 | test.checkMenu([item], [], []); |
michael@0 | 1686 | let elt = test.getItemElt(popup, item); |
michael@0 | 1687 | |
michael@0 | 1688 | // create a command event |
michael@0 | 1689 | let evt = elt.ownerDocument.createEvent('Event'); |
michael@0 | 1690 | evt.initEvent('command', true, true); |
michael@0 | 1691 | elt.dispatchEvent(evt); |
michael@0 | 1692 | }); |
michael@0 | 1693 | }; |
michael@0 | 1694 | |
michael@0 | 1695 | |
michael@0 | 1696 | // A menu's click listener should work and receive bubbling 'command' events from |
michael@0 | 1697 | // sub-items appropriately. This also tests menus and ensures that when a CSS |
michael@0 | 1698 | // selector context matches the clicked node's ancestor, the matching ancestor |
michael@0 | 1699 | // is passed to listeners as the clicked node. |
michael@0 | 1700 | exports.testMenuCommand = function (assert, done) { |
michael@0 | 1701 | // Create a top-level menu, submenu, and item, like this: |
michael@0 | 1702 | // topMenu -> submenu -> item |
michael@0 | 1703 | // Click the item and make sure the click bubbles. |
michael@0 | 1704 | let test = new TestHelper(assert, done); |
michael@0 | 1705 | let loader = test.newLoader(); |
michael@0 | 1706 | |
michael@0 | 1707 | let item = new loader.cm.Item({ |
michael@0 | 1708 | label: "submenu item", |
michael@0 | 1709 | data: "submenu item data", |
michael@0 | 1710 | context: loader.cm.SelectorContext("a"), |
michael@0 | 1711 | }); |
michael@0 | 1712 | |
michael@0 | 1713 | let submenu = new loader.cm.Menu({ |
michael@0 | 1714 | label: "submenu", |
michael@0 | 1715 | context: loader.cm.SelectorContext("a"), |
michael@0 | 1716 | items: [item] |
michael@0 | 1717 | }); |
michael@0 | 1718 | |
michael@0 | 1719 | let topMenu = new loader.cm.Menu({ |
michael@0 | 1720 | label: "top menu", |
michael@0 | 1721 | contentScript: 'self.on("click", function (node, data) {' + |
michael@0 | 1722 | ' self.postMessage({' + |
michael@0 | 1723 | ' tagName: node.tagName,' + |
michael@0 | 1724 | ' data: data' + |
michael@0 | 1725 | ' });' + |
michael@0 | 1726 | '});', |
michael@0 | 1727 | onMessage: function (data) { |
michael@0 | 1728 | assert.equal(this, topMenu, "`this` inside top menu should be menu"); |
michael@0 | 1729 | assert.equal(data.tagName, "A", "Clicked node should be anchor"); |
michael@0 | 1730 | assert.equal(data.data, item.data, |
michael@0 | 1731 | "Clicked item data should be correct"); |
michael@0 | 1732 | test.done(); |
michael@0 | 1733 | }, |
michael@0 | 1734 | items: [submenu], |
michael@0 | 1735 | context: loader.cm.SelectorContext("a") |
michael@0 | 1736 | }); |
michael@0 | 1737 | |
michael@0 | 1738 | test.withTestDoc(function (window, doc) { |
michael@0 | 1739 | test.showMenu(doc.getElementById("span-link"), function (popup) { |
michael@0 | 1740 | test.checkMenu([topMenu], [], []); |
michael@0 | 1741 | let topMenuElt = test.getItemElt(popup, topMenu); |
michael@0 | 1742 | let topMenuPopup = topMenuElt.firstChild; |
michael@0 | 1743 | let submenuElt = test.getItemElt(topMenuPopup, submenu); |
michael@0 | 1744 | let submenuPopup = submenuElt.firstChild; |
michael@0 | 1745 | let itemElt = test.getItemElt(submenuPopup, item); |
michael@0 | 1746 | |
michael@0 | 1747 | // create a command event |
michael@0 | 1748 | let evt = itemElt.ownerDocument.createEvent('Event'); |
michael@0 | 1749 | evt.initEvent('command', true, true); |
michael@0 | 1750 | itemElt.dispatchEvent(evt); |
michael@0 | 1751 | }); |
michael@0 | 1752 | }); |
michael@0 | 1753 | }; |
michael@0 | 1754 | |
michael@0 | 1755 | |
michael@0 | 1756 | // Click listeners should work when multiple modules are loaded. |
michael@0 | 1757 | exports.testItemCommandMultipleModules = function (assert, done) { |
michael@0 | 1758 | let test = new TestHelper(assert, done); |
michael@0 | 1759 | let loader0 = test.newLoader(); |
michael@0 | 1760 | let loader1 = test.newLoader(); |
michael@0 | 1761 | |
michael@0 | 1762 | let item0 = loader0.cm.Item({ |
michael@0 | 1763 | label: "loader 0 item", |
michael@0 | 1764 | contentScript: 'self.on("click", self.postMessage);', |
michael@0 | 1765 | onMessage: function () { |
michael@0 | 1766 | test.fail("loader 0 item should not emit click event"); |
michael@0 | 1767 | } |
michael@0 | 1768 | }); |
michael@0 | 1769 | let item1 = loader1.cm.Item({ |
michael@0 | 1770 | label: "loader 1 item", |
michael@0 | 1771 | contentScript: 'self.on("click", self.postMessage);', |
michael@0 | 1772 | onMessage: function () { |
michael@0 | 1773 | test.pass("loader 1 item clicked as expected"); |
michael@0 | 1774 | test.done(); |
michael@0 | 1775 | } |
michael@0 | 1776 | }); |
michael@0 | 1777 | |
michael@0 | 1778 | test.showMenu(null, function (popup) { |
michael@0 | 1779 | test.checkMenu([item0, item1], [], []); |
michael@0 | 1780 | let item1Elt = test.getItemElt(popup, item1); |
michael@0 | 1781 | |
michael@0 | 1782 | // create a command event |
michael@0 | 1783 | let evt = item1Elt.ownerDocument.createEvent('Event'); |
michael@0 | 1784 | evt.initEvent('command', true, true); |
michael@0 | 1785 | item1Elt.dispatchEvent(evt); |
michael@0 | 1786 | }); |
michael@0 | 1787 | }; |
michael@0 | 1788 | |
michael@0 | 1789 | |
michael@0 | 1790 | |
michael@0 | 1791 | |
michael@0 | 1792 | // An item's click listener should work. |
michael@0 | 1793 | exports.testItemClick = function (assert, done) { |
michael@0 | 1794 | let test = new TestHelper(assert, done); |
michael@0 | 1795 | let loader = test.newLoader(); |
michael@0 | 1796 | |
michael@0 | 1797 | let item = new loader.cm.Item({ |
michael@0 | 1798 | label: "item", |
michael@0 | 1799 | data: "item data", |
michael@0 | 1800 | contentScript: 'self.on("click", function (node, data) {' + |
michael@0 | 1801 | ' self.postMessage({' + |
michael@0 | 1802 | ' tagName: node.tagName,' + |
michael@0 | 1803 | ' data: data' + |
michael@0 | 1804 | ' });' + |
michael@0 | 1805 | '});', |
michael@0 | 1806 | onMessage: function (data) { |
michael@0 | 1807 | assert.equal(this, item, "`this` inside onMessage should be item"); |
michael@0 | 1808 | assert.equal(data.tagName, "HTML", "node should be an HTML element"); |
michael@0 | 1809 | assert.equal(data.data, item.data, "data should be item data"); |
michael@0 | 1810 | test.done(); |
michael@0 | 1811 | } |
michael@0 | 1812 | }); |
michael@0 | 1813 | |
michael@0 | 1814 | test.showMenu(null, function (popup) { |
michael@0 | 1815 | test.checkMenu([item], [], []); |
michael@0 | 1816 | let elt = test.getItemElt(popup, item); |
michael@0 | 1817 | elt.click(); |
michael@0 | 1818 | }); |
michael@0 | 1819 | }; |
michael@0 | 1820 | |
michael@0 | 1821 | |
michael@0 | 1822 | // A menu's click listener should work and receive bubbling clicks from |
michael@0 | 1823 | // sub-items appropriately. This also tests menus and ensures that when a CSS |
michael@0 | 1824 | // selector context matches the clicked node's ancestor, the matching ancestor |
michael@0 | 1825 | // is passed to listeners as the clicked node. |
michael@0 | 1826 | exports.testMenuClick = function (assert, done) { |
michael@0 | 1827 | // Create a top-level menu, submenu, and item, like this: |
michael@0 | 1828 | // topMenu -> submenu -> item |
michael@0 | 1829 | // Click the item and make sure the click bubbles. |
michael@0 | 1830 | let test = new TestHelper(assert, done); |
michael@0 | 1831 | let loader = test.newLoader(); |
michael@0 | 1832 | |
michael@0 | 1833 | let item = new loader.cm.Item({ |
michael@0 | 1834 | label: "submenu item", |
michael@0 | 1835 | data: "submenu item data", |
michael@0 | 1836 | context: loader.cm.SelectorContext("a"), |
michael@0 | 1837 | }); |
michael@0 | 1838 | |
michael@0 | 1839 | let submenu = new loader.cm.Menu({ |
michael@0 | 1840 | label: "submenu", |
michael@0 | 1841 | context: loader.cm.SelectorContext("a"), |
michael@0 | 1842 | items: [item] |
michael@0 | 1843 | }); |
michael@0 | 1844 | |
michael@0 | 1845 | let topMenu = new loader.cm.Menu({ |
michael@0 | 1846 | label: "top menu", |
michael@0 | 1847 | contentScript: 'self.on("click", function (node, data) {' + |
michael@0 | 1848 | ' self.postMessage({' + |
michael@0 | 1849 | ' tagName: node.tagName,' + |
michael@0 | 1850 | ' data: data' + |
michael@0 | 1851 | ' });' + |
michael@0 | 1852 | '});', |
michael@0 | 1853 | onMessage: function (data) { |
michael@0 | 1854 | assert.equal(this, topMenu, "`this` inside top menu should be menu"); |
michael@0 | 1855 | assert.equal(data.tagName, "A", "Clicked node should be anchor"); |
michael@0 | 1856 | assert.equal(data.data, item.data, |
michael@0 | 1857 | "Clicked item data should be correct"); |
michael@0 | 1858 | test.done(); |
michael@0 | 1859 | }, |
michael@0 | 1860 | items: [submenu], |
michael@0 | 1861 | context: loader.cm.SelectorContext("a") |
michael@0 | 1862 | }); |
michael@0 | 1863 | |
michael@0 | 1864 | test.withTestDoc(function (window, doc) { |
michael@0 | 1865 | test.showMenu(doc.getElementById("span-link"), function (popup) { |
michael@0 | 1866 | test.checkMenu([topMenu], [], []); |
michael@0 | 1867 | let topMenuElt = test.getItemElt(popup, topMenu); |
michael@0 | 1868 | let topMenuPopup = topMenuElt.firstChild; |
michael@0 | 1869 | let submenuElt = test.getItemElt(topMenuPopup, submenu); |
michael@0 | 1870 | let submenuPopup = submenuElt.firstChild; |
michael@0 | 1871 | let itemElt = test.getItemElt(submenuPopup, item); |
michael@0 | 1872 | itemElt.click(); |
michael@0 | 1873 | }); |
michael@0 | 1874 | }); |
michael@0 | 1875 | }; |
michael@0 | 1876 | |
michael@0 | 1877 | // Click listeners should work when multiple modules are loaded. |
michael@0 | 1878 | exports.testItemClickMultipleModules = function (assert, done) { |
michael@0 | 1879 | let test = new TestHelper(assert, done); |
michael@0 | 1880 | let loader0 = test.newLoader(); |
michael@0 | 1881 | let loader1 = test.newLoader(); |
michael@0 | 1882 | |
michael@0 | 1883 | let item0 = loader0.cm.Item({ |
michael@0 | 1884 | label: "loader 0 item", |
michael@0 | 1885 | contentScript: 'self.on("click", self.postMessage);', |
michael@0 | 1886 | onMessage: function () { |
michael@0 | 1887 | test.fail("loader 0 item should not emit click event"); |
michael@0 | 1888 | } |
michael@0 | 1889 | }); |
michael@0 | 1890 | let item1 = loader1.cm.Item({ |
michael@0 | 1891 | label: "loader 1 item", |
michael@0 | 1892 | contentScript: 'self.on("click", self.postMessage);', |
michael@0 | 1893 | onMessage: function () { |
michael@0 | 1894 | test.pass("loader 1 item clicked as expected"); |
michael@0 | 1895 | test.done(); |
michael@0 | 1896 | } |
michael@0 | 1897 | }); |
michael@0 | 1898 | |
michael@0 | 1899 | test.showMenu(null, function (popup) { |
michael@0 | 1900 | test.checkMenu([item0, item1], [], []); |
michael@0 | 1901 | let item1Elt = test.getItemElt(popup, item1); |
michael@0 | 1902 | item1Elt.click(); |
michael@0 | 1903 | }); |
michael@0 | 1904 | }; |
michael@0 | 1905 | |
michael@0 | 1906 | |
michael@0 | 1907 | // Adding a separator to a submenu should work OK. |
michael@0 | 1908 | exports.testSeparator = function (assert, done) { |
michael@0 | 1909 | let test = new TestHelper(assert, done); |
michael@0 | 1910 | let loader = test.newLoader(); |
michael@0 | 1911 | |
michael@0 | 1912 | let menu = new loader.cm.Menu({ |
michael@0 | 1913 | label: "submenu", |
michael@0 | 1914 | items: [new loader.cm.Separator()] |
michael@0 | 1915 | }); |
michael@0 | 1916 | |
michael@0 | 1917 | test.showMenu(null, function (popup) { |
michael@0 | 1918 | test.checkMenu([menu], [], []); |
michael@0 | 1919 | test.done(); |
michael@0 | 1920 | }); |
michael@0 | 1921 | }; |
michael@0 | 1922 | |
michael@0 | 1923 | |
michael@0 | 1924 | // The parentMenu option should work |
michael@0 | 1925 | exports.testParentMenu = function (assert, done) { |
michael@0 | 1926 | let test = new TestHelper(assert, done); |
michael@0 | 1927 | let loader = test.newLoader(); |
michael@0 | 1928 | |
michael@0 | 1929 | let menu = new loader.cm.Menu({ |
michael@0 | 1930 | label: "submenu", |
michael@0 | 1931 | items: [loader.cm.Item({ label: "item 1" })], |
michael@0 | 1932 | parentMenu: loader.cm.contentContextMenu |
michael@0 | 1933 | }); |
michael@0 | 1934 | |
michael@0 | 1935 | let item = loader.cm.Item({ |
michael@0 | 1936 | label: "item 2", |
michael@0 | 1937 | parentMenu: menu, |
michael@0 | 1938 | }); |
michael@0 | 1939 | |
michael@0 | 1940 | assert.equal(menu.items[1], item, "Item should be in the sub menu"); |
michael@0 | 1941 | |
michael@0 | 1942 | test.showMenu(null, function (popup) { |
michael@0 | 1943 | test.checkMenu([menu], [], []); |
michael@0 | 1944 | test.done(); |
michael@0 | 1945 | }); |
michael@0 | 1946 | }; |
michael@0 | 1947 | |
michael@0 | 1948 | |
michael@0 | 1949 | // Existing context menu modifications should apply to new windows. |
michael@0 | 1950 | exports.testNewWindow = function (assert, done) { |
michael@0 | 1951 | let test = new TestHelper(assert, done); |
michael@0 | 1952 | let loader = test.newLoader(); |
michael@0 | 1953 | |
michael@0 | 1954 | let item = new loader.cm.Item({ label: "item" }); |
michael@0 | 1955 | |
michael@0 | 1956 | test.withNewWindow(function () { |
michael@0 | 1957 | test.showMenu(null, function (popup) { |
michael@0 | 1958 | test.checkMenu([item], [], []); |
michael@0 | 1959 | test.done(); |
michael@0 | 1960 | }); |
michael@0 | 1961 | }); |
michael@0 | 1962 | }; |
michael@0 | 1963 | |
michael@0 | 1964 | |
michael@0 | 1965 | // When a new window is opened, items added by an unloaded module should not |
michael@0 | 1966 | // be present in the menu. |
michael@0 | 1967 | exports.testNewWindowMultipleModules = function (assert, done) { |
michael@0 | 1968 | let test = new TestHelper(assert, done); |
michael@0 | 1969 | let loader = test.newLoader(); |
michael@0 | 1970 | let item = new loader.cm.Item({ label: "item" }); |
michael@0 | 1971 | |
michael@0 | 1972 | test.showMenu(null, function (popup) { |
michael@0 | 1973 | test.checkMenu([item], [], []); |
michael@0 | 1974 | popup.hidePopup(); |
michael@0 | 1975 | loader.unload(); |
michael@0 | 1976 | test.withNewWindow(function () { |
michael@0 | 1977 | test.showMenu(null, function (popup) { |
michael@0 | 1978 | test.checkMenu([item], [], [item]); |
michael@0 | 1979 | test.done(); |
michael@0 | 1980 | }); |
michael@0 | 1981 | }); |
michael@0 | 1982 | }); |
michael@0 | 1983 | }; |
michael@0 | 1984 | |
michael@0 | 1985 | |
michael@0 | 1986 | // Existing context menu modifications should not apply to new private windows. |
michael@0 | 1987 | exports.testNewPrivateWindow = function (assert, done) { |
michael@0 | 1988 | let test = new TestHelper(assert, done); |
michael@0 | 1989 | let loader = test.newLoader(); |
michael@0 | 1990 | |
michael@0 | 1991 | let item = new loader.cm.Item({ label: "item" }); |
michael@0 | 1992 | |
michael@0 | 1993 | test.showMenu(null, function (popup) { |
michael@0 | 1994 | test.checkMenu([item], [], []); |
michael@0 | 1995 | popup.hidePopup(); |
michael@0 | 1996 | |
michael@0 | 1997 | test.withNewPrivateWindow(function () { |
michael@0 | 1998 | test.showMenu(null, function (popup) { |
michael@0 | 1999 | test.checkMenu([], [], []); |
michael@0 | 2000 | test.done(); |
michael@0 | 2001 | }); |
michael@0 | 2002 | }); |
michael@0 | 2003 | }); |
michael@0 | 2004 | }; |
michael@0 | 2005 | |
michael@0 | 2006 | |
michael@0 | 2007 | // Existing context menu modifications should apply to new private windows when |
michael@0 | 2008 | // private browsing support is enabled. |
michael@0 | 2009 | exports.testNewPrivateEnabledWindow = function (assert, done) { |
michael@0 | 2010 | let test = new TestHelper(assert, done); |
michael@0 | 2011 | let loader = test.newPrivateLoader(); |
michael@0 | 2012 | |
michael@0 | 2013 | let item = new loader.cm.Item({ label: "item" }); |
michael@0 | 2014 | |
michael@0 | 2015 | test.showMenu(null, function (popup) { |
michael@0 | 2016 | test.checkMenu([item], [], []); |
michael@0 | 2017 | popup.hidePopup(); |
michael@0 | 2018 | |
michael@0 | 2019 | test.withNewPrivateWindow(function () { |
michael@0 | 2020 | test.showMenu(null, function (popup) { |
michael@0 | 2021 | test.checkMenu([item], [], []); |
michael@0 | 2022 | test.done(); |
michael@0 | 2023 | }); |
michael@0 | 2024 | }); |
michael@0 | 2025 | }); |
michael@0 | 2026 | }; |
michael@0 | 2027 | |
michael@0 | 2028 | |
michael@0 | 2029 | // Existing context menu modifications should apply to new private windows when |
michael@0 | 2030 | // private browsing support is enabled unless unloaded. |
michael@0 | 2031 | exports.testNewPrivateEnabledWindowUnloaded = function (assert, done) { |
michael@0 | 2032 | let test = new TestHelper(assert, done); |
michael@0 | 2033 | let loader = test.newPrivateLoader(); |
michael@0 | 2034 | |
michael@0 | 2035 | let item = new loader.cm.Item({ label: "item" }); |
michael@0 | 2036 | |
michael@0 | 2037 | test.showMenu(null, function (popup) { |
michael@0 | 2038 | test.checkMenu([item], [], []); |
michael@0 | 2039 | popup.hidePopup(); |
michael@0 | 2040 | |
michael@0 | 2041 | loader.unload(); |
michael@0 | 2042 | |
michael@0 | 2043 | test.withNewPrivateWindow(function () { |
michael@0 | 2044 | test.showMenu(null, function (popup) { |
michael@0 | 2045 | test.checkMenu([], [], []); |
michael@0 | 2046 | test.done(); |
michael@0 | 2047 | }); |
michael@0 | 2048 | }); |
michael@0 | 2049 | }); |
michael@0 | 2050 | }; |
michael@0 | 2051 | |
michael@0 | 2052 | |
michael@0 | 2053 | // Items in the context menu should be sorted according to locale. |
michael@0 | 2054 | exports.testSorting = function (assert, done) { |
michael@0 | 2055 | let test = new TestHelper(assert, done); |
michael@0 | 2056 | let loader = test.newLoader(); |
michael@0 | 2057 | |
michael@0 | 2058 | // Make an unsorted items list. It'll look like this: |
michael@0 | 2059 | // item 1, item 0, item 3, item 2, item 5, item 4, ... |
michael@0 | 2060 | let items = []; |
michael@0 | 2061 | for (let i = 0; i < OVERFLOW_THRESH_DEFAULT; i += 2) { |
michael@0 | 2062 | items.push(new loader.cm.Item({ label: "item " + (i + 1) })); |
michael@0 | 2063 | items.push(new loader.cm.Item({ label: "item " + i })); |
michael@0 | 2064 | } |
michael@0 | 2065 | |
michael@0 | 2066 | test.showMenu(null, function (popup) { |
michael@0 | 2067 | test.checkMenu(items, [], []); |
michael@0 | 2068 | test.done(); |
michael@0 | 2069 | }); |
michael@0 | 2070 | }; |
michael@0 | 2071 | |
michael@0 | 2072 | |
michael@0 | 2073 | // Items in the overflow menu should be sorted according to locale. |
michael@0 | 2074 | exports.testSortingOverflow = function (assert, done) { |
michael@0 | 2075 | let test = new TestHelper(assert, done); |
michael@0 | 2076 | let loader = test.newLoader(); |
michael@0 | 2077 | |
michael@0 | 2078 | // Make an unsorted items list. It'll look like this: |
michael@0 | 2079 | // item 1, item 0, item 3, item 2, item 5, item 4, ... |
michael@0 | 2080 | let items = []; |
michael@0 | 2081 | for (let i = 0; i < OVERFLOW_THRESH_DEFAULT * 2; i += 2) { |
michael@0 | 2082 | items.push(new loader.cm.Item({ label: "item " + (i + 1) })); |
michael@0 | 2083 | items.push(new loader.cm.Item({ label: "item " + i })); |
michael@0 | 2084 | } |
michael@0 | 2085 | |
michael@0 | 2086 | test.showMenu(null, function (popup) { |
michael@0 | 2087 | test.checkMenu(items, [], []); |
michael@0 | 2088 | test.done(); |
michael@0 | 2089 | }); |
michael@0 | 2090 | }; |
michael@0 | 2091 | |
michael@0 | 2092 | |
michael@0 | 2093 | // Multiple modules shouldn't interfere with sorting. |
michael@0 | 2094 | exports.testSortingMultipleModules = function (assert, done) { |
michael@0 | 2095 | let test = new TestHelper(assert, done); |
michael@0 | 2096 | let loader0 = test.newLoader(); |
michael@0 | 2097 | let loader1 = test.newLoader(); |
michael@0 | 2098 | |
michael@0 | 2099 | let items0 = []; |
michael@0 | 2100 | let items1 = []; |
michael@0 | 2101 | for (let i = 0; i < OVERFLOW_THRESH_DEFAULT; i++) { |
michael@0 | 2102 | if (i % 2) { |
michael@0 | 2103 | let item = new loader0.cm.Item({ label: "item " + i }); |
michael@0 | 2104 | items0.push(item); |
michael@0 | 2105 | } |
michael@0 | 2106 | else { |
michael@0 | 2107 | let item = new loader1.cm.Item({ label: "item " + i }); |
michael@0 | 2108 | items1.push(item); |
michael@0 | 2109 | } |
michael@0 | 2110 | } |
michael@0 | 2111 | let allItems = items0.concat(items1); |
michael@0 | 2112 | |
michael@0 | 2113 | test.showMenu(null, function (popup) { |
michael@0 | 2114 | |
michael@0 | 2115 | // All items should be present and sorted. |
michael@0 | 2116 | test.checkMenu(allItems, [], []); |
michael@0 | 2117 | popup.hidePopup(); |
michael@0 | 2118 | loader0.unload(); |
michael@0 | 2119 | loader1.unload(); |
michael@0 | 2120 | test.showMenu(null, function (popup) { |
michael@0 | 2121 | |
michael@0 | 2122 | // All items should be removed. |
michael@0 | 2123 | test.checkMenu(allItems, [], allItems); |
michael@0 | 2124 | test.done(); |
michael@0 | 2125 | }); |
michael@0 | 2126 | }); |
michael@0 | 2127 | }; |
michael@0 | 2128 | |
michael@0 | 2129 | |
michael@0 | 2130 | // Content click handlers and context handlers should be able to communicate, |
michael@0 | 2131 | // i.e., they're eval'ed in the same worker and sandbox. |
michael@0 | 2132 | exports.testContentCommunication = function (assert, done) { |
michael@0 | 2133 | let test = new TestHelper(assert, done); |
michael@0 | 2134 | let loader = test.newLoader(); |
michael@0 | 2135 | |
michael@0 | 2136 | let item = new loader.cm.Item({ |
michael@0 | 2137 | label: "item", |
michael@0 | 2138 | contentScript: 'var potato;' + |
michael@0 | 2139 | 'self.on("context", function () {' + |
michael@0 | 2140 | ' potato = "potato";' + |
michael@0 | 2141 | ' return true;' + |
michael@0 | 2142 | '});' + |
michael@0 | 2143 | 'self.on("click", function () {' + |
michael@0 | 2144 | ' self.postMessage(potato);' + |
michael@0 | 2145 | '});', |
michael@0 | 2146 | }); |
michael@0 | 2147 | |
michael@0 | 2148 | item.on("message", function (data) { |
michael@0 | 2149 | assert.equal(data, "potato", "That's a lot of potatoes!"); |
michael@0 | 2150 | test.done(); |
michael@0 | 2151 | }); |
michael@0 | 2152 | |
michael@0 | 2153 | test.showMenu(null, function (popup) { |
michael@0 | 2154 | test.checkMenu([item], [], []); |
michael@0 | 2155 | let elt = test.getItemElt(popup, item); |
michael@0 | 2156 | elt.click(); |
michael@0 | 2157 | }); |
michael@0 | 2158 | }; |
michael@0 | 2159 | |
michael@0 | 2160 | |
michael@0 | 2161 | // When the context menu is invoked on a tab that was already open when the |
michael@0 | 2162 | // module was loaded, it should contain the expected items and content workers |
michael@0 | 2163 | // should function as expected. |
michael@0 | 2164 | exports.testLoadWithOpenTab = function (assert, done) { |
michael@0 | 2165 | let test = new TestHelper(assert, done); |
michael@0 | 2166 | test.withTestDoc(function (window, doc) { |
michael@0 | 2167 | let loader = test.newLoader(); |
michael@0 | 2168 | let item = new loader.cm.Item({ |
michael@0 | 2169 | label: "item", |
michael@0 | 2170 | contentScript: |
michael@0 | 2171 | 'self.on("click", function () self.postMessage("click"));', |
michael@0 | 2172 | onMessage: function (msg) { |
michael@0 | 2173 | if (msg === "click") |
michael@0 | 2174 | test.done(); |
michael@0 | 2175 | } |
michael@0 | 2176 | }); |
michael@0 | 2177 | test.showMenu(null, function (popup) { |
michael@0 | 2178 | test.checkMenu([item], [], []); |
michael@0 | 2179 | test.getItemElt(popup, item).click(); |
michael@0 | 2180 | }); |
michael@0 | 2181 | }); |
michael@0 | 2182 | }; |
michael@0 | 2183 | |
michael@0 | 2184 | // Bug 732716: Ensure that the node given in `click` event works fine |
michael@0 | 2185 | // (i.e. is correctly wrapped) |
michael@0 | 2186 | exports.testDrawImageOnClickNode = function (assert, done) { |
michael@0 | 2187 | let test = new TestHelper(assert, done); |
michael@0 | 2188 | test.withTestDoc(function (window, doc) { |
michael@0 | 2189 | let loader = test.newLoader(); |
michael@0 | 2190 | let item = new loader.cm.Item({ |
michael@0 | 2191 | label: "item", |
michael@0 | 2192 | context: loader.cm.SelectorContext("img"), |
michael@0 | 2193 | contentScript: "new " + function() { |
michael@0 | 2194 | self.on("click", function (img, data) { |
michael@0 | 2195 | let ctx = document.createElement("canvas").getContext("2d"); |
michael@0 | 2196 | ctx.drawImage(img, 1, 1, 1, 1); |
michael@0 | 2197 | self.postMessage("done"); |
michael@0 | 2198 | }); |
michael@0 | 2199 | }, |
michael@0 | 2200 | onMessage: function (msg) { |
michael@0 | 2201 | if (msg === "done") |
michael@0 | 2202 | test.done(); |
michael@0 | 2203 | } |
michael@0 | 2204 | }); |
michael@0 | 2205 | test.showMenu(doc.getElementById("image"), function (popup) { |
michael@0 | 2206 | test.checkMenu([item], [], []); |
michael@0 | 2207 | test.getItemElt(popup, item).click(); |
michael@0 | 2208 | }); |
michael@0 | 2209 | }); |
michael@0 | 2210 | }; |
michael@0 | 2211 | |
michael@0 | 2212 | |
michael@0 | 2213 | // Setting an item's label before the menu is ever shown should correctly change |
michael@0 | 2214 | // its label. |
michael@0 | 2215 | exports.testSetLabelBeforeShow = function (assert, done) { |
michael@0 | 2216 | let test = new TestHelper(assert, done); |
michael@0 | 2217 | let loader = test.newLoader(); |
michael@0 | 2218 | |
michael@0 | 2219 | let items = [ |
michael@0 | 2220 | new loader.cm.Item({ label: "a" }), |
michael@0 | 2221 | new loader.cm.Item({ label: "b" }) |
michael@0 | 2222 | ] |
michael@0 | 2223 | items[0].label = "z"; |
michael@0 | 2224 | assert.equal(items[0].label, "z"); |
michael@0 | 2225 | |
michael@0 | 2226 | test.showMenu(null, function (popup) { |
michael@0 | 2227 | test.checkMenu(items, [], []); |
michael@0 | 2228 | test.done(); |
michael@0 | 2229 | }); |
michael@0 | 2230 | }; |
michael@0 | 2231 | |
michael@0 | 2232 | |
michael@0 | 2233 | // Setting an item's label after the menu is shown should correctly change its |
michael@0 | 2234 | // label. |
michael@0 | 2235 | exports.testSetLabelAfterShow = function (assert, done) { |
michael@0 | 2236 | let test = new TestHelper(assert, done); |
michael@0 | 2237 | let loader = test.newLoader(); |
michael@0 | 2238 | |
michael@0 | 2239 | let items = [ |
michael@0 | 2240 | new loader.cm.Item({ label: "a" }), |
michael@0 | 2241 | new loader.cm.Item({ label: "b" }) |
michael@0 | 2242 | ]; |
michael@0 | 2243 | |
michael@0 | 2244 | test.showMenu(null, function (popup) { |
michael@0 | 2245 | test.checkMenu(items, [], []); |
michael@0 | 2246 | popup.hidePopup(); |
michael@0 | 2247 | |
michael@0 | 2248 | items[0].label = "z"; |
michael@0 | 2249 | assert.equal(items[0].label, "z"); |
michael@0 | 2250 | test.showMenu(null, function (popup) { |
michael@0 | 2251 | test.checkMenu(items, [], []); |
michael@0 | 2252 | test.done(); |
michael@0 | 2253 | }); |
michael@0 | 2254 | }); |
michael@0 | 2255 | }; |
michael@0 | 2256 | |
michael@0 | 2257 | |
michael@0 | 2258 | // Setting an item's label before the menu is ever shown should correctly change |
michael@0 | 2259 | // its label. |
michael@0 | 2260 | exports.testSetLabelBeforeShowOverflow = function (assert, done) { |
michael@0 | 2261 | let test = new TestHelper(assert, done); |
michael@0 | 2262 | let loader = test.newLoader(); |
michael@0 | 2263 | |
michael@0 | 2264 | let prefs = loader.loader.require("sdk/preferences/service"); |
michael@0 | 2265 | prefs.set(OVERFLOW_THRESH_PREF, 0); |
michael@0 | 2266 | |
michael@0 | 2267 | let items = [ |
michael@0 | 2268 | new loader.cm.Item({ label: "a" }), |
michael@0 | 2269 | new loader.cm.Item({ label: "b" }) |
michael@0 | 2270 | ] |
michael@0 | 2271 | items[0].label = "z"; |
michael@0 | 2272 | assert.equal(items[0].label, "z"); |
michael@0 | 2273 | |
michael@0 | 2274 | test.showMenu(null, function (popup) { |
michael@0 | 2275 | test.checkMenu(items, [], []); |
michael@0 | 2276 | test.done(); |
michael@0 | 2277 | }); |
michael@0 | 2278 | }; |
michael@0 | 2279 | |
michael@0 | 2280 | |
michael@0 | 2281 | // Setting an item's label after the menu is shown should correctly change its |
michael@0 | 2282 | // label. |
michael@0 | 2283 | exports.testSetLabelAfterShowOverflow = function (assert, done) { |
michael@0 | 2284 | let test = new TestHelper(assert, done); |
michael@0 | 2285 | let loader = test.newLoader(); |
michael@0 | 2286 | |
michael@0 | 2287 | let prefs = loader.loader.require("sdk/preferences/service"); |
michael@0 | 2288 | prefs.set(OVERFLOW_THRESH_PREF, 0); |
michael@0 | 2289 | |
michael@0 | 2290 | let items = [ |
michael@0 | 2291 | new loader.cm.Item({ label: "a" }), |
michael@0 | 2292 | new loader.cm.Item({ label: "b" }) |
michael@0 | 2293 | ]; |
michael@0 | 2294 | |
michael@0 | 2295 | test.showMenu(null, function (popup) { |
michael@0 | 2296 | test.checkMenu(items, [], []); |
michael@0 | 2297 | popup.hidePopup(); |
michael@0 | 2298 | |
michael@0 | 2299 | items[0].label = "z"; |
michael@0 | 2300 | assert.equal(items[0].label, "z"); |
michael@0 | 2301 | test.showMenu(null, function (popup) { |
michael@0 | 2302 | test.checkMenu(items, [], []); |
michael@0 | 2303 | test.done(); |
michael@0 | 2304 | }); |
michael@0 | 2305 | }); |
michael@0 | 2306 | }; |
michael@0 | 2307 | |
michael@0 | 2308 | |
michael@0 | 2309 | // Setting the label of an item in a Menu should work. |
michael@0 | 2310 | exports.testSetLabelMenuItem = function (assert, done) { |
michael@0 | 2311 | let test = new TestHelper(assert, done); |
michael@0 | 2312 | let loader = test.newLoader(); |
michael@0 | 2313 | |
michael@0 | 2314 | let menu = loader.cm.Menu({ |
michael@0 | 2315 | label: "menu", |
michael@0 | 2316 | items: [loader.cm.Item({ label: "a" })] |
michael@0 | 2317 | }); |
michael@0 | 2318 | menu.items[0].label = "z"; |
michael@0 | 2319 | |
michael@0 | 2320 | assert.equal(menu.items[0].label, "z"); |
michael@0 | 2321 | |
michael@0 | 2322 | test.showMenu(null, function (popup) { |
michael@0 | 2323 | test.checkMenu([menu], [], []); |
michael@0 | 2324 | test.done(); |
michael@0 | 2325 | }); |
michael@0 | 2326 | }; |
michael@0 | 2327 | |
michael@0 | 2328 | |
michael@0 | 2329 | // Menu.addItem() should work. |
michael@0 | 2330 | exports.testMenuAddItem = function (assert, done) { |
michael@0 | 2331 | let test = new TestHelper(assert, done); |
michael@0 | 2332 | let loader = test.newLoader(); |
michael@0 | 2333 | |
michael@0 | 2334 | let menu = loader.cm.Menu({ |
michael@0 | 2335 | label: "menu", |
michael@0 | 2336 | items: [ |
michael@0 | 2337 | loader.cm.Item({ label: "item 0" }) |
michael@0 | 2338 | ] |
michael@0 | 2339 | }); |
michael@0 | 2340 | menu.addItem(loader.cm.Item({ label: "item 1" })); |
michael@0 | 2341 | menu.addItem(loader.cm.Item({ label: "item 2" })); |
michael@0 | 2342 | |
michael@0 | 2343 | assert.equal(menu.items.length, 3, |
michael@0 | 2344 | "menu should have correct number of items"); |
michael@0 | 2345 | for (let i = 0; i < 3; i++) { |
michael@0 | 2346 | assert.equal(menu.items[i].label, "item " + i, |
michael@0 | 2347 | "item label should be correct"); |
michael@0 | 2348 | assert.equal(menu.items[i].parentMenu, menu, |
michael@0 | 2349 | "item's parent menu should be correct"); |
michael@0 | 2350 | } |
michael@0 | 2351 | |
michael@0 | 2352 | test.showMenu(null, function (popup) { |
michael@0 | 2353 | test.checkMenu([menu], [], []); |
michael@0 | 2354 | test.done(); |
michael@0 | 2355 | }); |
michael@0 | 2356 | }; |
michael@0 | 2357 | |
michael@0 | 2358 | |
michael@0 | 2359 | // Adding the same item twice to a menu should work as expected. |
michael@0 | 2360 | exports.testMenuAddItemTwice = function (assert, done) { |
michael@0 | 2361 | let test = new TestHelper(assert, done); |
michael@0 | 2362 | let loader = test.newLoader(); |
michael@0 | 2363 | |
michael@0 | 2364 | let menu = loader.cm.Menu({ |
michael@0 | 2365 | label: "menu", |
michael@0 | 2366 | items: [] |
michael@0 | 2367 | }); |
michael@0 | 2368 | let subitem = loader.cm.Item({ label: "item 1" }) |
michael@0 | 2369 | menu.addItem(subitem); |
michael@0 | 2370 | menu.addItem(loader.cm.Item({ label: "item 0" })); |
michael@0 | 2371 | menu.addItem(subitem); |
michael@0 | 2372 | |
michael@0 | 2373 | assert.equal(menu.items.length, 2, |
michael@0 | 2374 | "menu should have correct number of items"); |
michael@0 | 2375 | for (let i = 0; i < 2; i++) { |
michael@0 | 2376 | assert.equal(menu.items[i].label, "item " + i, |
michael@0 | 2377 | "item label should be correct"); |
michael@0 | 2378 | } |
michael@0 | 2379 | |
michael@0 | 2380 | test.showMenu(null, function (popup) { |
michael@0 | 2381 | test.checkMenu([menu], [], []); |
michael@0 | 2382 | test.done(); |
michael@0 | 2383 | }); |
michael@0 | 2384 | }; |
michael@0 | 2385 | |
michael@0 | 2386 | |
michael@0 | 2387 | // Menu.removeItem() should work. |
michael@0 | 2388 | exports.testMenuRemoveItem = function (assert, done) { |
michael@0 | 2389 | let test = new TestHelper(assert, done); |
michael@0 | 2390 | let loader = test.newLoader(); |
michael@0 | 2391 | |
michael@0 | 2392 | let subitem = loader.cm.Item({ label: "item 1" }); |
michael@0 | 2393 | let menu = loader.cm.Menu({ |
michael@0 | 2394 | label: "menu", |
michael@0 | 2395 | items: [ |
michael@0 | 2396 | loader.cm.Item({ label: "item 0" }), |
michael@0 | 2397 | subitem, |
michael@0 | 2398 | loader.cm.Item({ label: "item 2" }) |
michael@0 | 2399 | ] |
michael@0 | 2400 | }); |
michael@0 | 2401 | |
michael@0 | 2402 | // Removing twice should be harmless. |
michael@0 | 2403 | menu.removeItem(subitem); |
michael@0 | 2404 | menu.removeItem(subitem); |
michael@0 | 2405 | |
michael@0 | 2406 | assert.equal(subitem.parentMenu, null, |
michael@0 | 2407 | "item's parent menu should be correct"); |
michael@0 | 2408 | |
michael@0 | 2409 | assert.equal(menu.items.length, 2, |
michael@0 | 2410 | "menu should have correct number of items"); |
michael@0 | 2411 | assert.equal(menu.items[0].label, "item 0", |
michael@0 | 2412 | "item label should be correct"); |
michael@0 | 2413 | assert.equal(menu.items[1].label, "item 2", |
michael@0 | 2414 | "item label should be correct"); |
michael@0 | 2415 | |
michael@0 | 2416 | test.showMenu(null, function (popup) { |
michael@0 | 2417 | test.checkMenu([menu], [], []); |
michael@0 | 2418 | test.done(); |
michael@0 | 2419 | }); |
michael@0 | 2420 | }; |
michael@0 | 2421 | |
michael@0 | 2422 | |
michael@0 | 2423 | // Adding an item currently contained in one menu to another menu should work. |
michael@0 | 2424 | exports.testMenuItemSwap = function (assert, done) { |
michael@0 | 2425 | let test = new TestHelper(assert, done); |
michael@0 | 2426 | let loader = test.newLoader(); |
michael@0 | 2427 | |
michael@0 | 2428 | let subitem = loader.cm.Item({ label: "item" }); |
michael@0 | 2429 | let menu0 = loader.cm.Menu({ |
michael@0 | 2430 | label: "menu 0", |
michael@0 | 2431 | items: [subitem] |
michael@0 | 2432 | }); |
michael@0 | 2433 | let menu1 = loader.cm.Menu({ |
michael@0 | 2434 | label: "menu 1", |
michael@0 | 2435 | items: [] |
michael@0 | 2436 | }); |
michael@0 | 2437 | menu1.addItem(subitem); |
michael@0 | 2438 | |
michael@0 | 2439 | assert.equal(menu0.items.length, 0, |
michael@0 | 2440 | "menu should have correct number of items"); |
michael@0 | 2441 | |
michael@0 | 2442 | assert.equal(menu1.items.length, 1, |
michael@0 | 2443 | "menu should have correct number of items"); |
michael@0 | 2444 | assert.equal(menu1.items[0].label, "item", |
michael@0 | 2445 | "item label should be correct"); |
michael@0 | 2446 | |
michael@0 | 2447 | assert.equal(subitem.parentMenu, menu1, |
michael@0 | 2448 | "item's parent menu should be correct"); |
michael@0 | 2449 | |
michael@0 | 2450 | test.showMenu(null, function (popup) { |
michael@0 | 2451 | test.checkMenu([menu0, menu1], [menu0], []); |
michael@0 | 2452 | test.done(); |
michael@0 | 2453 | }); |
michael@0 | 2454 | }; |
michael@0 | 2455 | |
michael@0 | 2456 | |
michael@0 | 2457 | // Destroying an item should remove it from its parent menu. |
michael@0 | 2458 | exports.testMenuItemDestroy = function (assert, done) { |
michael@0 | 2459 | let test = new TestHelper(assert, done); |
michael@0 | 2460 | let loader = test.newLoader(); |
michael@0 | 2461 | |
michael@0 | 2462 | let subitem = loader.cm.Item({ label: "item" }); |
michael@0 | 2463 | let menu = loader.cm.Menu({ |
michael@0 | 2464 | label: "menu", |
michael@0 | 2465 | items: [subitem] |
michael@0 | 2466 | }); |
michael@0 | 2467 | subitem.destroy(); |
michael@0 | 2468 | |
michael@0 | 2469 | assert.equal(menu.items.length, 0, |
michael@0 | 2470 | "menu should have correct number of items"); |
michael@0 | 2471 | assert.equal(subitem.parentMenu, null, |
michael@0 | 2472 | "item's parent menu should be correct"); |
michael@0 | 2473 | |
michael@0 | 2474 | test.showMenu(null, function (popup) { |
michael@0 | 2475 | test.checkMenu([menu], [menu], []); |
michael@0 | 2476 | test.done(); |
michael@0 | 2477 | }); |
michael@0 | 2478 | }; |
michael@0 | 2479 | |
michael@0 | 2480 | |
michael@0 | 2481 | // Setting Menu.items should work. |
michael@0 | 2482 | exports.testMenuItemsSetter = function (assert, done) { |
michael@0 | 2483 | let test = new TestHelper(assert, done); |
michael@0 | 2484 | let loader = test.newLoader(); |
michael@0 | 2485 | |
michael@0 | 2486 | let menu = loader.cm.Menu({ |
michael@0 | 2487 | label: "menu", |
michael@0 | 2488 | items: [ |
michael@0 | 2489 | loader.cm.Item({ label: "old item 0" }), |
michael@0 | 2490 | loader.cm.Item({ label: "old item 1" }) |
michael@0 | 2491 | ] |
michael@0 | 2492 | }); |
michael@0 | 2493 | menu.items = [ |
michael@0 | 2494 | loader.cm.Item({ label: "new item 0" }), |
michael@0 | 2495 | loader.cm.Item({ label: "new item 1" }), |
michael@0 | 2496 | loader.cm.Item({ label: "new item 2" }) |
michael@0 | 2497 | ]; |
michael@0 | 2498 | |
michael@0 | 2499 | assert.equal(menu.items.length, 3, |
michael@0 | 2500 | "menu should have correct number of items"); |
michael@0 | 2501 | for (let i = 0; i < 3; i++) { |
michael@0 | 2502 | assert.equal(menu.items[i].label, "new item " + i, |
michael@0 | 2503 | "item label should be correct"); |
michael@0 | 2504 | assert.equal(menu.items[i].parentMenu, menu, |
michael@0 | 2505 | "item's parent menu should be correct"); |
michael@0 | 2506 | } |
michael@0 | 2507 | |
michael@0 | 2508 | test.showMenu(null, function (popup) { |
michael@0 | 2509 | test.checkMenu([menu], [], []); |
michael@0 | 2510 | test.done(); |
michael@0 | 2511 | }); |
michael@0 | 2512 | }; |
michael@0 | 2513 | |
michael@0 | 2514 | |
michael@0 | 2515 | // Setting Item.data should work. |
michael@0 | 2516 | exports.testItemDataSetter = function (assert, done) { |
michael@0 | 2517 | let test = new TestHelper(assert, done); |
michael@0 | 2518 | let loader = test.newLoader(); |
michael@0 | 2519 | |
michael@0 | 2520 | let item = loader.cm.Item({ label: "old item 0", data: "old" }); |
michael@0 | 2521 | item.data = "new"; |
michael@0 | 2522 | |
michael@0 | 2523 | assert.equal(item.data, "new", "item should have correct data"); |
michael@0 | 2524 | |
michael@0 | 2525 | test.showMenu(null, function (popup) { |
michael@0 | 2526 | test.checkMenu([item], [], []); |
michael@0 | 2527 | test.done(); |
michael@0 | 2528 | }); |
michael@0 | 2529 | }; |
michael@0 | 2530 | |
michael@0 | 2531 | |
michael@0 | 2532 | // Open the test doc, load the module, make sure items appear when context- |
michael@0 | 2533 | // clicking the iframe. |
michael@0 | 2534 | exports.testAlreadyOpenIframe = function (assert, done) { |
michael@0 | 2535 | let test = new TestHelper(assert, done); |
michael@0 | 2536 | test.withTestDoc(function (window, doc) { |
michael@0 | 2537 | let loader = test.newLoader(); |
michael@0 | 2538 | let item = new loader.cm.Item({ |
michael@0 | 2539 | label: "item" |
michael@0 | 2540 | }); |
michael@0 | 2541 | test.showMenu(doc.getElementById("iframe"), function (popup) { |
michael@0 | 2542 | test.checkMenu([item], [], []); |
michael@0 | 2543 | test.done(); |
michael@0 | 2544 | }); |
michael@0 | 2545 | }); |
michael@0 | 2546 | }; |
michael@0 | 2547 | |
michael@0 | 2548 | |
michael@0 | 2549 | // Tests that a missing label throws an exception |
michael@0 | 2550 | exports.testItemNoLabel = function (assert, done) { |
michael@0 | 2551 | let test = new TestHelper(assert, done); |
michael@0 | 2552 | let loader = test.newLoader(); |
michael@0 | 2553 | |
michael@0 | 2554 | try { |
michael@0 | 2555 | new loader.cm.Item({}); |
michael@0 | 2556 | assert.ok(false, "Should have seen exception"); |
michael@0 | 2557 | } |
michael@0 | 2558 | catch (e) { |
michael@0 | 2559 | assert.ok(true, "Should have seen exception"); |
michael@0 | 2560 | } |
michael@0 | 2561 | |
michael@0 | 2562 | try { |
michael@0 | 2563 | new loader.cm.Item({ label: null }); |
michael@0 | 2564 | assert.ok(false, "Should have seen exception"); |
michael@0 | 2565 | } |
michael@0 | 2566 | catch (e) { |
michael@0 | 2567 | assert.ok(true, "Should have seen exception"); |
michael@0 | 2568 | } |
michael@0 | 2569 | |
michael@0 | 2570 | try { |
michael@0 | 2571 | new loader.cm.Item({ label: undefined }); |
michael@0 | 2572 | assert.ok(false, "Should have seen exception"); |
michael@0 | 2573 | } |
michael@0 | 2574 | catch (e) { |
michael@0 | 2575 | assert.ok(true, "Should have seen exception"); |
michael@0 | 2576 | } |
michael@0 | 2577 | |
michael@0 | 2578 | try { |
michael@0 | 2579 | new loader.cm.Item({ label: "" }); |
michael@0 | 2580 | assert.ok(false, "Should have seen exception"); |
michael@0 | 2581 | } |
michael@0 | 2582 | catch (e) { |
michael@0 | 2583 | assert.ok(true, "Should have seen exception"); |
michael@0 | 2584 | } |
michael@0 | 2585 | |
michael@0 | 2586 | test.done(); |
michael@0 | 2587 | } |
michael@0 | 2588 | |
michael@0 | 2589 | |
michael@0 | 2590 | // Tests that items can have an empty data property |
michael@0 | 2591 | exports.testItemNoData = function (assert, done) { |
michael@0 | 2592 | let test = new TestHelper(assert, done); |
michael@0 | 2593 | let loader = test.newLoader(); |
michael@0 | 2594 | |
michael@0 | 2595 | function checkData(data) { |
michael@0 | 2596 | assert.equal(data, undefined, "Data should be undefined"); |
michael@0 | 2597 | } |
michael@0 | 2598 | |
michael@0 | 2599 | let item1 = new loader.cm.Item({ |
michael@0 | 2600 | label: "item 1", |
michael@0 | 2601 | contentScript: 'self.on("click", function(node, data) self.postMessage(data))', |
michael@0 | 2602 | onMessage: checkData |
michael@0 | 2603 | }); |
michael@0 | 2604 | let item2 = new loader.cm.Item({ |
michael@0 | 2605 | label: "item 2", |
michael@0 | 2606 | data: null, |
michael@0 | 2607 | contentScript: 'self.on("click", function(node, data) self.postMessage(data))', |
michael@0 | 2608 | onMessage: checkData |
michael@0 | 2609 | }); |
michael@0 | 2610 | let item3 = new loader.cm.Item({ |
michael@0 | 2611 | label: "item 3", |
michael@0 | 2612 | data: undefined, |
michael@0 | 2613 | contentScript: 'self.on("click", function(node, data) self.postMessage(data))', |
michael@0 | 2614 | onMessage: checkData |
michael@0 | 2615 | }); |
michael@0 | 2616 | |
michael@0 | 2617 | assert.equal(item1.data, undefined, "Should be no defined data"); |
michael@0 | 2618 | assert.equal(item2.data, null, "Should be no defined data"); |
michael@0 | 2619 | assert.equal(item3.data, undefined, "Should be no defined data"); |
michael@0 | 2620 | |
michael@0 | 2621 | test.showMenu(null, function (popup) { |
michael@0 | 2622 | test.checkMenu([item1, item2, item3], [], []); |
michael@0 | 2623 | |
michael@0 | 2624 | let itemElt = test.getItemElt(popup, item1); |
michael@0 | 2625 | itemElt.click(); |
michael@0 | 2626 | |
michael@0 | 2627 | test.hideMenu(function() { |
michael@0 | 2628 | test.showMenu(null, function (popup) { |
michael@0 | 2629 | let itemElt = test.getItemElt(popup, item2); |
michael@0 | 2630 | itemElt.click(); |
michael@0 | 2631 | |
michael@0 | 2632 | test.hideMenu(function() { |
michael@0 | 2633 | test.showMenu(null, function (popup) { |
michael@0 | 2634 | let itemElt = test.getItemElt(popup, item3); |
michael@0 | 2635 | itemElt.click(); |
michael@0 | 2636 | |
michael@0 | 2637 | test.done(); |
michael@0 | 2638 | }); |
michael@0 | 2639 | }); |
michael@0 | 2640 | }); |
michael@0 | 2641 | }); |
michael@0 | 2642 | }); |
michael@0 | 2643 | } |
michael@0 | 2644 | |
michael@0 | 2645 | |
michael@0 | 2646 | // Tests that items without an image don't attempt to show one |
michael@0 | 2647 | exports.testItemNoImage = function (assert, done) { |
michael@0 | 2648 | let test = new TestHelper(assert, done); |
michael@0 | 2649 | let loader = test.newLoader(); |
michael@0 | 2650 | |
michael@0 | 2651 | let item1 = new loader.cm.Item({ label: "item 1" }); |
michael@0 | 2652 | let item2 = new loader.cm.Item({ label: "item 2", image: null }); |
michael@0 | 2653 | let item3 = new loader.cm.Item({ label: "item 3", image: undefined }); |
michael@0 | 2654 | |
michael@0 | 2655 | assert.equal(item1.image, undefined, "Should be no defined image"); |
michael@0 | 2656 | assert.equal(item2.image, null, "Should be no defined image"); |
michael@0 | 2657 | assert.equal(item3.image, undefined, "Should be no defined image"); |
michael@0 | 2658 | |
michael@0 | 2659 | test.showMenu(null, function (popup) { |
michael@0 | 2660 | test.checkMenu([item1, item2, item3], [], []); |
michael@0 | 2661 | |
michael@0 | 2662 | test.done(); |
michael@0 | 2663 | }); |
michael@0 | 2664 | } |
michael@0 | 2665 | |
michael@0 | 2666 | |
michael@0 | 2667 | // Test image support. |
michael@0 | 2668 | exports.testItemImage = function (assert, done) { |
michael@0 | 2669 | let test = new TestHelper(assert, done); |
michael@0 | 2670 | let loader = test.newLoader(); |
michael@0 | 2671 | |
michael@0 | 2672 | let imageURL = data.url("moz_favicon.ico"); |
michael@0 | 2673 | let item = new loader.cm.Item({ label: "item", image: imageURL }); |
michael@0 | 2674 | let menu = new loader.cm.Menu({ label: "menu", image: imageURL, items: [ |
michael@0 | 2675 | loader.cm.Item({ label: "subitem" }) |
michael@0 | 2676 | ]}); |
michael@0 | 2677 | assert.equal(item.image, imageURL, "Should have set the image correctly"); |
michael@0 | 2678 | assert.equal(menu.image, imageURL, "Should have set the image correctly"); |
michael@0 | 2679 | |
michael@0 | 2680 | test.showMenu(null, function (popup) { |
michael@0 | 2681 | test.checkMenu([item, menu], [], []); |
michael@0 | 2682 | |
michael@0 | 2683 | let imageURL2 = data.url("dummy.ico"); |
michael@0 | 2684 | item.image = imageURL2; |
michael@0 | 2685 | menu.image = imageURL2; |
michael@0 | 2686 | assert.equal(item.image, imageURL2, "Should have set the image correctly"); |
michael@0 | 2687 | assert.equal(menu.image, imageURL2, "Should have set the image correctly"); |
michael@0 | 2688 | test.checkMenu([item, menu], [], []); |
michael@0 | 2689 | |
michael@0 | 2690 | item.image = null; |
michael@0 | 2691 | menu.image = null; |
michael@0 | 2692 | assert.equal(item.image, null, "Should have set the image correctly"); |
michael@0 | 2693 | assert.equal(menu.image, null, "Should have set the image correctly"); |
michael@0 | 2694 | test.checkMenu([item, menu], [], []); |
michael@0 | 2695 | |
michael@0 | 2696 | test.done(); |
michael@0 | 2697 | }); |
michael@0 | 2698 | }; |
michael@0 | 2699 | |
michael@0 | 2700 | // Test image URL validation. |
michael@0 | 2701 | exports.testItemImageValidURL = function (assert, done) { |
michael@0 | 2702 | let test = new TestHelper(assert, done); |
michael@0 | 2703 | let loader = test.newLoader(); |
michael@0 | 2704 | |
michael@0 | 2705 | assert.throws(function(){ |
michael@0 | 2706 | new loader.cm.Item({ |
michael@0 | 2707 | label: "item 1", |
michael@0 | 2708 | image: "foo" |
michael@0 | 2709 | }) |
michael@0 | 2710 | }, /Image URL validation failed/ |
michael@0 | 2711 | ); |
michael@0 | 2712 | |
michael@0 | 2713 | assert.throws(function(){ |
michael@0 | 2714 | new loader.cm.Item({ |
michael@0 | 2715 | label: "item 2", |
michael@0 | 2716 | image: false |
michael@0 | 2717 | }) |
michael@0 | 2718 | }, /Image URL validation failed/ |
michael@0 | 2719 | ); |
michael@0 | 2720 | |
michael@0 | 2721 | assert.throws(function(){ |
michael@0 | 2722 | new loader.cm.Item({ |
michael@0 | 2723 | label: "item 3", |
michael@0 | 2724 | image: 0 |
michael@0 | 2725 | }) |
michael@0 | 2726 | }, /Image URL validation failed/ |
michael@0 | 2727 | ); |
michael@0 | 2728 | |
michael@0 | 2729 | let imageURL = data.url("moz_favicon.ico"); |
michael@0 | 2730 | let item4 = new loader.cm.Item({ label: "item 4", image: imageURL }); |
michael@0 | 2731 | let item5 = new loader.cm.Item({ label: "item 5", image: null }); |
michael@0 | 2732 | let item6 = new loader.cm.Item({ label: "item 6", image: undefined }); |
michael@0 | 2733 | |
michael@0 | 2734 | assert.equal(item4.image, imageURL, "Should be proper image URL"); |
michael@0 | 2735 | assert.equal(item5.image, null, "Should be null image"); |
michael@0 | 2736 | assert.equal(item6.image, undefined, "Should be undefined image"); |
michael@0 | 2737 | |
michael@0 | 2738 | test.done(); |
michael@0 | 2739 | }; |
michael@0 | 2740 | |
michael@0 | 2741 | |
michael@0 | 2742 | // Menu.destroy should destroy the item tree rooted at that menu. |
michael@0 | 2743 | exports.testMenuDestroy = function (assert, done) { |
michael@0 | 2744 | let test = new TestHelper(assert, done); |
michael@0 | 2745 | let loader = test.newLoader(); |
michael@0 | 2746 | |
michael@0 | 2747 | let menu = loader.cm.Menu({ |
michael@0 | 2748 | label: "menu", |
michael@0 | 2749 | items: [ |
michael@0 | 2750 | loader.cm.Item({ label: "item 0" }), |
michael@0 | 2751 | loader.cm.Menu({ |
michael@0 | 2752 | label: "item 1", |
michael@0 | 2753 | items: [ |
michael@0 | 2754 | loader.cm.Item({ label: "subitem 0" }), |
michael@0 | 2755 | loader.cm.Item({ label: "subitem 1" }), |
michael@0 | 2756 | loader.cm.Item({ label: "subitem 2" }) |
michael@0 | 2757 | ] |
michael@0 | 2758 | }), |
michael@0 | 2759 | loader.cm.Item({ label: "item 2" }) |
michael@0 | 2760 | ] |
michael@0 | 2761 | }); |
michael@0 | 2762 | menu.destroy(); |
michael@0 | 2763 | |
michael@0 | 2764 | /*let numRegistryEntries = 0; |
michael@0 | 2765 | loader.globalScope.browserManager.browserWins.forEach(function (bwin) { |
michael@0 | 2766 | for (let itemID in bwin.items) |
michael@0 | 2767 | numRegistryEntries++; |
michael@0 | 2768 | }); |
michael@0 | 2769 | assert.equal(numRegistryEntries, 0, "All items should be unregistered.");*/ |
michael@0 | 2770 | |
michael@0 | 2771 | test.showMenu(null, function (popup) { |
michael@0 | 2772 | test.checkMenu([menu], [], [menu]); |
michael@0 | 2773 | test.done(); |
michael@0 | 2774 | }); |
michael@0 | 2775 | }; |
michael@0 | 2776 | |
michael@0 | 2777 | // Checks that if a menu contains sub items that are hidden then the menu is |
michael@0 | 2778 | // hidden too. Also checks that content scripts and contexts work for sub items. |
michael@0 | 2779 | exports.testSubItemContextNoMatchHideMenu = function (assert, done) { |
michael@0 | 2780 | let test = new TestHelper(assert, done); |
michael@0 | 2781 | let loader = test.newLoader(); |
michael@0 | 2782 | |
michael@0 | 2783 | let items = [ |
michael@0 | 2784 | loader.cm.Menu({ |
michael@0 | 2785 | label: "menu 1", |
michael@0 | 2786 | items: [ |
michael@0 | 2787 | loader.cm.Item({ |
michael@0 | 2788 | label: "subitem 1", |
michael@0 | 2789 | context: loader.cm.SelectorContext(".foo") |
michael@0 | 2790 | }) |
michael@0 | 2791 | ] |
michael@0 | 2792 | }), |
michael@0 | 2793 | loader.cm.Menu({ |
michael@0 | 2794 | label: "menu 2", |
michael@0 | 2795 | items: [ |
michael@0 | 2796 | loader.cm.Item({ |
michael@0 | 2797 | label: "subitem 2", |
michael@0 | 2798 | contentScript: 'self.on("context", function () false);' |
michael@0 | 2799 | }) |
michael@0 | 2800 | ] |
michael@0 | 2801 | }), |
michael@0 | 2802 | loader.cm.Menu({ |
michael@0 | 2803 | label: "menu 3", |
michael@0 | 2804 | items: [ |
michael@0 | 2805 | loader.cm.Item({ |
michael@0 | 2806 | label: "subitem 3", |
michael@0 | 2807 | context: loader.cm.SelectorContext(".foo") |
michael@0 | 2808 | }), |
michael@0 | 2809 | loader.cm.Item({ |
michael@0 | 2810 | label: "subitem 4", |
michael@0 | 2811 | contentScript: 'self.on("context", function () false);' |
michael@0 | 2812 | }) |
michael@0 | 2813 | ] |
michael@0 | 2814 | }) |
michael@0 | 2815 | ]; |
michael@0 | 2816 | |
michael@0 | 2817 | test.showMenu(null, function (popup) { |
michael@0 | 2818 | test.checkMenu(items, items, []); |
michael@0 | 2819 | test.done(); |
michael@0 | 2820 | }); |
michael@0 | 2821 | }; |
michael@0 | 2822 | |
michael@0 | 2823 | |
michael@0 | 2824 | // Checks that if a menu contains a combination of hidden and visible sub items |
michael@0 | 2825 | // then the menu is still visible too. |
michael@0 | 2826 | exports.testSubItemContextMatch = function (assert, done) { |
michael@0 | 2827 | let test = new TestHelper(assert, done); |
michael@0 | 2828 | let loader = test.newLoader(); |
michael@0 | 2829 | |
michael@0 | 2830 | let hiddenItems = [ |
michael@0 | 2831 | loader.cm.Item({ |
michael@0 | 2832 | label: "subitem 3", |
michael@0 | 2833 | context: loader.cm.SelectorContext(".foo") |
michael@0 | 2834 | }), |
michael@0 | 2835 | loader.cm.Item({ |
michael@0 | 2836 | label: "subitem 6", |
michael@0 | 2837 | contentScript: 'self.on("context", function () false);' |
michael@0 | 2838 | }) |
michael@0 | 2839 | ]; |
michael@0 | 2840 | |
michael@0 | 2841 | let items = [ |
michael@0 | 2842 | loader.cm.Menu({ |
michael@0 | 2843 | label: "menu 1", |
michael@0 | 2844 | items: [ |
michael@0 | 2845 | loader.cm.Item({ |
michael@0 | 2846 | label: "subitem 1", |
michael@0 | 2847 | context: loader.cm.URLContext(TEST_DOC_URL) |
michael@0 | 2848 | }) |
michael@0 | 2849 | ] |
michael@0 | 2850 | }), |
michael@0 | 2851 | loader.cm.Menu({ |
michael@0 | 2852 | label: "menu 2", |
michael@0 | 2853 | items: [ |
michael@0 | 2854 | loader.cm.Item({ |
michael@0 | 2855 | label: "subitem 2", |
michael@0 | 2856 | contentScript: 'self.on("context", function () true);' |
michael@0 | 2857 | }) |
michael@0 | 2858 | ] |
michael@0 | 2859 | }), |
michael@0 | 2860 | loader.cm.Menu({ |
michael@0 | 2861 | label: "menu 3", |
michael@0 | 2862 | items: [ |
michael@0 | 2863 | hiddenItems[0], |
michael@0 | 2864 | loader.cm.Item({ |
michael@0 | 2865 | label: "subitem 4", |
michael@0 | 2866 | contentScript: 'self.on("context", function () true);' |
michael@0 | 2867 | }) |
michael@0 | 2868 | ] |
michael@0 | 2869 | }), |
michael@0 | 2870 | loader.cm.Menu({ |
michael@0 | 2871 | label: "menu 4", |
michael@0 | 2872 | items: [ |
michael@0 | 2873 | loader.cm.Item({ |
michael@0 | 2874 | label: "subitem 5", |
michael@0 | 2875 | context: loader.cm.URLContext(TEST_DOC_URL) |
michael@0 | 2876 | }), |
michael@0 | 2877 | hiddenItems[1] |
michael@0 | 2878 | ] |
michael@0 | 2879 | }), |
michael@0 | 2880 | loader.cm.Menu({ |
michael@0 | 2881 | label: "menu 5", |
michael@0 | 2882 | items: [ |
michael@0 | 2883 | loader.cm.Item({ |
michael@0 | 2884 | label: "subitem 7", |
michael@0 | 2885 | context: loader.cm.URLContext(TEST_DOC_URL) |
michael@0 | 2886 | }), |
michael@0 | 2887 | loader.cm.Item({ |
michael@0 | 2888 | label: "subitem 8", |
michael@0 | 2889 | contentScript: 'self.on("context", function () true);' |
michael@0 | 2890 | }) |
michael@0 | 2891 | ] |
michael@0 | 2892 | }) |
michael@0 | 2893 | ]; |
michael@0 | 2894 | |
michael@0 | 2895 | test.withTestDoc(function (window, doc) { |
michael@0 | 2896 | test.showMenu(null, function (popup) { |
michael@0 | 2897 | test.checkMenu(items, hiddenItems, []); |
michael@0 | 2898 | test.done(); |
michael@0 | 2899 | }); |
michael@0 | 2900 | }); |
michael@0 | 2901 | }; |
michael@0 | 2902 | |
michael@0 | 2903 | |
michael@0 | 2904 | // Child items should default to visible, not to PageContext |
michael@0 | 2905 | exports.testSubItemDefaultVisible = function (assert, done) { |
michael@0 | 2906 | let test = new TestHelper(assert, done); |
michael@0 | 2907 | let loader = test.newLoader(); |
michael@0 | 2908 | |
michael@0 | 2909 | let items = [ |
michael@0 | 2910 | loader.cm.Menu({ |
michael@0 | 2911 | label: "menu 1", |
michael@0 | 2912 | context: loader.cm.SelectorContext("img"), |
michael@0 | 2913 | items: [ |
michael@0 | 2914 | loader.cm.Item({ |
michael@0 | 2915 | label: "subitem 1" |
michael@0 | 2916 | }), |
michael@0 | 2917 | loader.cm.Item({ |
michael@0 | 2918 | label: "subitem 2", |
michael@0 | 2919 | context: loader.cm.SelectorContext("img") |
michael@0 | 2920 | }), |
michael@0 | 2921 | loader.cm.Item({ |
michael@0 | 2922 | label: "subitem 3", |
michael@0 | 2923 | context: loader.cm.SelectorContext("a") |
michael@0 | 2924 | }) |
michael@0 | 2925 | ] |
michael@0 | 2926 | }) |
michael@0 | 2927 | ]; |
michael@0 | 2928 | |
michael@0 | 2929 | // subitem 3 will be hidden |
michael@0 | 2930 | let hiddenItems = [items[0].items[2]]; |
michael@0 | 2931 | |
michael@0 | 2932 | test.withTestDoc(function (window, doc) { |
michael@0 | 2933 | test.showMenu(doc.getElementById("image"), function (popup) { |
michael@0 | 2934 | test.checkMenu(items, hiddenItems, []); |
michael@0 | 2935 | test.done(); |
michael@0 | 2936 | }); |
michael@0 | 2937 | }); |
michael@0 | 2938 | }; |
michael@0 | 2939 | |
michael@0 | 2940 | // Tests that the click event on sub menuitem |
michael@0 | 2941 | // tiggers the click event for the sub menuitem and the parent menu |
michael@0 | 2942 | exports.testSubItemClick = function (assert, done) { |
michael@0 | 2943 | let test = new TestHelper(assert, done); |
michael@0 | 2944 | let loader = test.newLoader(); |
michael@0 | 2945 | |
michael@0 | 2946 | let state = 0; |
michael@0 | 2947 | |
michael@0 | 2948 | let items = [ |
michael@0 | 2949 | loader.cm.Menu({ |
michael@0 | 2950 | label: "menu 1", |
michael@0 | 2951 | items: [ |
michael@0 | 2952 | loader.cm.Item({ |
michael@0 | 2953 | label: "subitem 1", |
michael@0 | 2954 | data: "foobar", |
michael@0 | 2955 | contentScript: 'self.on("click", function (node, data) {' + |
michael@0 | 2956 | ' self.postMessage({' + |
michael@0 | 2957 | ' tagName: node.tagName,' + |
michael@0 | 2958 | ' data: data' + |
michael@0 | 2959 | ' });' + |
michael@0 | 2960 | '});', |
michael@0 | 2961 | onMessage: function(msg) { |
michael@0 | 2962 | assert.equal(msg.tagName, "HTML", "should have seen the right node"); |
michael@0 | 2963 | assert.equal(msg.data, "foobar", "should have seen the right data"); |
michael@0 | 2964 | assert.equal(state, 0, "should have seen the event at the right time"); |
michael@0 | 2965 | state++; |
michael@0 | 2966 | } |
michael@0 | 2967 | }) |
michael@0 | 2968 | ], |
michael@0 | 2969 | contentScript: 'self.on("click", function (node, data) {' + |
michael@0 | 2970 | ' self.postMessage({' + |
michael@0 | 2971 | ' tagName: node.tagName,' + |
michael@0 | 2972 | ' data: data' + |
michael@0 | 2973 | ' });' + |
michael@0 | 2974 | '});', |
michael@0 | 2975 | onMessage: function(msg) { |
michael@0 | 2976 | assert.equal(msg.tagName, "HTML", "should have seen the right node"); |
michael@0 | 2977 | assert.equal(msg.data, "foobar", "should have seen the right data"); |
michael@0 | 2978 | assert.equal(state, 1, "should have seen the event at the right time"); |
michael@0 | 2979 | |
michael@0 | 2980 | test.done(); |
michael@0 | 2981 | } |
michael@0 | 2982 | }) |
michael@0 | 2983 | ]; |
michael@0 | 2984 | |
michael@0 | 2985 | test.withTestDoc(function (window, doc) { |
michael@0 | 2986 | test.showMenu(null, function (popup) { |
michael@0 | 2987 | test.checkMenu(items, [], []); |
michael@0 | 2988 | |
michael@0 | 2989 | let topMenuElt = test.getItemElt(popup, items[0]); |
michael@0 | 2990 | let topMenuPopup = topMenuElt.firstChild; |
michael@0 | 2991 | let itemElt = test.getItemElt(topMenuPopup, items[0].items[0]); |
michael@0 | 2992 | itemElt.click(); |
michael@0 | 2993 | }); |
michael@0 | 2994 | }); |
michael@0 | 2995 | }; |
michael@0 | 2996 | |
michael@0 | 2997 | // Tests that the command event on sub menuitem |
michael@0 | 2998 | // tiggers the click event for the sub menuitem and the parent menu |
michael@0 | 2999 | exports.testSubItemCommand = function (assert, done) { |
michael@0 | 3000 | let test = new TestHelper(assert, done); |
michael@0 | 3001 | let loader = test.newLoader(); |
michael@0 | 3002 | |
michael@0 | 3003 | let state = 0; |
michael@0 | 3004 | |
michael@0 | 3005 | let items = [ |
michael@0 | 3006 | loader.cm.Menu({ |
michael@0 | 3007 | label: "menu 1", |
michael@0 | 3008 | items: [ |
michael@0 | 3009 | loader.cm.Item({ |
michael@0 | 3010 | label: "subitem 1", |
michael@0 | 3011 | data: "foobar", |
michael@0 | 3012 | contentScript: 'self.on("click", function (node, data) {' + |
michael@0 | 3013 | ' self.postMessage({' + |
michael@0 | 3014 | ' tagName: node.tagName,' + |
michael@0 | 3015 | ' data: data' + |
michael@0 | 3016 | ' });' + |
michael@0 | 3017 | '});', |
michael@0 | 3018 | onMessage: function(msg) { |
michael@0 | 3019 | assert.equal(msg.tagName, "HTML", "should have seen the right node"); |
michael@0 | 3020 | assert.equal(msg.data, "foobar", "should have seen the right data"); |
michael@0 | 3021 | assert.equal(state, 0, "should have seen the event at the right time"); |
michael@0 | 3022 | state++; |
michael@0 | 3023 | } |
michael@0 | 3024 | }) |
michael@0 | 3025 | ], |
michael@0 | 3026 | contentScript: 'self.on("click", function (node, data) {' + |
michael@0 | 3027 | ' self.postMessage({' + |
michael@0 | 3028 | ' tagName: node.tagName,' + |
michael@0 | 3029 | ' data: data' + |
michael@0 | 3030 | ' });' + |
michael@0 | 3031 | '});', |
michael@0 | 3032 | onMessage: function(msg) { |
michael@0 | 3033 | assert.equal(msg.tagName, "HTML", "should have seen the right node"); |
michael@0 | 3034 | assert.equal(msg.data, "foobar", "should have seen the right data"); |
michael@0 | 3035 | assert.equal(state, 1, "should have seen the event at the right time"); |
michael@0 | 3036 | state++ |
michael@0 | 3037 | |
michael@0 | 3038 | test.done(); |
michael@0 | 3039 | } |
michael@0 | 3040 | }) |
michael@0 | 3041 | ]; |
michael@0 | 3042 | |
michael@0 | 3043 | test.withTestDoc(function (window, doc) { |
michael@0 | 3044 | test.showMenu(null, function (popup) { |
michael@0 | 3045 | test.checkMenu(items, [], []); |
michael@0 | 3046 | |
michael@0 | 3047 | let topMenuElt = test.getItemElt(popup, items[0]); |
michael@0 | 3048 | let topMenuPopup = topMenuElt.firstChild; |
michael@0 | 3049 | let itemElt = test.getItemElt(topMenuPopup, items[0].items[0]); |
michael@0 | 3050 | |
michael@0 | 3051 | // create a command event |
michael@0 | 3052 | let evt = itemElt.ownerDocument.createEvent('Event'); |
michael@0 | 3053 | evt.initEvent('command', true, true); |
michael@0 | 3054 | itemElt.dispatchEvent(evt); |
michael@0 | 3055 | }); |
michael@0 | 3056 | }); |
michael@0 | 3057 | }; |
michael@0 | 3058 | |
michael@0 | 3059 | // Tests that opening a context menu for an outer frame when an inner frame |
michael@0 | 3060 | // has a selection doesn't activate the SelectionContext |
michael@0 | 3061 | exports.testSelectionInInnerFrameNoMatch = function (assert, done) { |
michael@0 | 3062 | let test = new TestHelper(assert, done); |
michael@0 | 3063 | let loader = test.newLoader(); |
michael@0 | 3064 | |
michael@0 | 3065 | let state = 0; |
michael@0 | 3066 | |
michael@0 | 3067 | let items = [ |
michael@0 | 3068 | loader.cm.Item({ |
michael@0 | 3069 | label: "test item", |
michael@0 | 3070 | context: loader.cm.SelectionContext() |
michael@0 | 3071 | }) |
michael@0 | 3072 | ]; |
michael@0 | 3073 | |
michael@0 | 3074 | test.withTestDoc(function (window, doc) { |
michael@0 | 3075 | let frame = doc.getElementById("iframe"); |
michael@0 | 3076 | frame.contentWindow.getSelection().selectAllChildren(frame.contentDocument.body); |
michael@0 | 3077 | |
michael@0 | 3078 | test.showMenu(null, function (popup) { |
michael@0 | 3079 | test.checkMenu(items, items, []); |
michael@0 | 3080 | test.done(); |
michael@0 | 3081 | }); |
michael@0 | 3082 | }); |
michael@0 | 3083 | }; |
michael@0 | 3084 | |
michael@0 | 3085 | // Tests that opening a context menu for an inner frame when the inner frame |
michael@0 | 3086 | // has a selection does activate the SelectionContext |
michael@0 | 3087 | exports.testSelectionInInnerFrameMatch = function (assert, done) { |
michael@0 | 3088 | let test = new TestHelper(assert, done); |
michael@0 | 3089 | let loader = test.newLoader(); |
michael@0 | 3090 | |
michael@0 | 3091 | let state = 0; |
michael@0 | 3092 | |
michael@0 | 3093 | let items = [ |
michael@0 | 3094 | loader.cm.Item({ |
michael@0 | 3095 | label: "test item", |
michael@0 | 3096 | context: loader.cm.SelectionContext() |
michael@0 | 3097 | }) |
michael@0 | 3098 | ]; |
michael@0 | 3099 | |
michael@0 | 3100 | test.withTestDoc(function (window, doc) { |
michael@0 | 3101 | let frame = doc.getElementById("iframe"); |
michael@0 | 3102 | frame.contentWindow.getSelection().selectAllChildren(frame.contentDocument.body); |
michael@0 | 3103 | |
michael@0 | 3104 | test.showMenu(frame.contentDocument.getElementById("text"), function (popup) { |
michael@0 | 3105 | test.checkMenu(items, [], []); |
michael@0 | 3106 | test.done(); |
michael@0 | 3107 | }); |
michael@0 | 3108 | }); |
michael@0 | 3109 | }; |
michael@0 | 3110 | |
michael@0 | 3111 | // Tests that opening a context menu for an inner frame when the outer frame |
michael@0 | 3112 | // has a selection doesn't activate the SelectionContext |
michael@0 | 3113 | exports.testSelectionInOuterFrameNoMatch = function (assert, done) { |
michael@0 | 3114 | let test = new TestHelper(assert, done); |
michael@0 | 3115 | let loader = test.newLoader(); |
michael@0 | 3116 | |
michael@0 | 3117 | let state = 0; |
michael@0 | 3118 | |
michael@0 | 3119 | let items = [ |
michael@0 | 3120 | loader.cm.Item({ |
michael@0 | 3121 | label: "test item", |
michael@0 | 3122 | context: loader.cm.SelectionContext() |
michael@0 | 3123 | }) |
michael@0 | 3124 | ]; |
michael@0 | 3125 | |
michael@0 | 3126 | test.withTestDoc(function (window, doc) { |
michael@0 | 3127 | let frame = doc.getElementById("iframe"); |
michael@0 | 3128 | window.getSelection().selectAllChildren(doc.body); |
michael@0 | 3129 | |
michael@0 | 3130 | test.showMenu(frame.contentDocument.getElementById("text"), function (popup) { |
michael@0 | 3131 | test.checkMenu(items, items, []); |
michael@0 | 3132 | test.done(); |
michael@0 | 3133 | }); |
michael@0 | 3134 | }); |
michael@0 | 3135 | }; |
michael@0 | 3136 | |
michael@0 | 3137 | |
michael@0 | 3138 | // Test that the return value of the predicate function determines if |
michael@0 | 3139 | // item is shown |
michael@0 | 3140 | exports.testPredicateContextControl = function (assert, done) { |
michael@0 | 3141 | let test = new TestHelper(assert, done); |
michael@0 | 3142 | let loader = test.newLoader(); |
michael@0 | 3143 | |
michael@0 | 3144 | let itemTrue = loader.cm.Item({ |
michael@0 | 3145 | label: "visible", |
michael@0 | 3146 | context: loader.cm.PredicateContext(function () { return true; }) |
michael@0 | 3147 | }); |
michael@0 | 3148 | |
michael@0 | 3149 | let itemFalse = loader.cm.Item({ |
michael@0 | 3150 | label: "hidden", |
michael@0 | 3151 | context: loader.cm.PredicateContext(function () { return false; }) |
michael@0 | 3152 | }); |
michael@0 | 3153 | |
michael@0 | 3154 | test.showMenu(null, function (popup) { |
michael@0 | 3155 | test.checkMenu([itemTrue, itemFalse], [itemFalse], []); |
michael@0 | 3156 | test.done(); |
michael@0 | 3157 | }); |
michael@0 | 3158 | }; |
michael@0 | 3159 | |
michael@0 | 3160 | // Test that the data object has the correct document type |
michael@0 | 3161 | exports.testPredicateContextDocumentType = function (assert, done) { |
michael@0 | 3162 | let test = new TestHelper(assert, done); |
michael@0 | 3163 | let loader = test.newLoader(); |
michael@0 | 3164 | |
michael@0 | 3165 | let items = [loader.cm.Item({ |
michael@0 | 3166 | label: "item", |
michael@0 | 3167 | context: loader.cm.PredicateContext(function (data) { |
michael@0 | 3168 | assert.equal(data.documentType, 'text/html'); |
michael@0 | 3169 | return true; |
michael@0 | 3170 | }) |
michael@0 | 3171 | })]; |
michael@0 | 3172 | |
michael@0 | 3173 | test.withTestDoc(function (window, doc) { |
michael@0 | 3174 | test.showMenu(null, function (popup) { |
michael@0 | 3175 | test.checkMenu(items, [], []); |
michael@0 | 3176 | test.done(); |
michael@0 | 3177 | }); |
michael@0 | 3178 | }); |
michael@0 | 3179 | }; |
michael@0 | 3180 | |
michael@0 | 3181 | // Test that the data object has the correct document URL |
michael@0 | 3182 | exports.testPredicateContextDocumentURL = function (assert, done) { |
michael@0 | 3183 | let test = new TestHelper(assert, done); |
michael@0 | 3184 | let loader = test.newLoader(); |
michael@0 | 3185 | |
michael@0 | 3186 | let items = [loader.cm.Item({ |
michael@0 | 3187 | label: "item", |
michael@0 | 3188 | context: loader.cm.PredicateContext(function (data) { |
michael@0 | 3189 | assert.equal(data.documentURL, TEST_DOC_URL); |
michael@0 | 3190 | return true; |
michael@0 | 3191 | }) |
michael@0 | 3192 | })]; |
michael@0 | 3193 | |
michael@0 | 3194 | test.withTestDoc(function (window, doc) { |
michael@0 | 3195 | test.showMenu(null, function (popup) { |
michael@0 | 3196 | test.checkMenu(items, [], []); |
michael@0 | 3197 | test.done(); |
michael@0 | 3198 | }); |
michael@0 | 3199 | }); |
michael@0 | 3200 | }; |
michael@0 | 3201 | |
michael@0 | 3202 | |
michael@0 | 3203 | // Test that the data object has the correct element name |
michael@0 | 3204 | exports.testPredicateContextTargetName = function (assert, done) { |
michael@0 | 3205 | let test = new TestHelper(assert, done); |
michael@0 | 3206 | let loader = test.newLoader(); |
michael@0 | 3207 | |
michael@0 | 3208 | let items = [loader.cm.Item({ |
michael@0 | 3209 | label: "item", |
michael@0 | 3210 | context: loader.cm.PredicateContext(function (data) { |
michael@0 | 3211 | assert.strictEqual(data.targetName, "input"); |
michael@0 | 3212 | return true; |
michael@0 | 3213 | }) |
michael@0 | 3214 | })]; |
michael@0 | 3215 | |
michael@0 | 3216 | test.withTestDoc(function (window, doc) { |
michael@0 | 3217 | test.showMenu(doc.getElementById("button"), function (popup) { |
michael@0 | 3218 | test.checkMenu(items, [], []); |
michael@0 | 3219 | test.done(); |
michael@0 | 3220 | }); |
michael@0 | 3221 | }); |
michael@0 | 3222 | }; |
michael@0 | 3223 | |
michael@0 | 3224 | |
michael@0 | 3225 | // Test that the data object has the correct ID |
michael@0 | 3226 | exports.testPredicateContextTargetIDSet = function (assert, done) { |
michael@0 | 3227 | let test = new TestHelper(assert, done); |
michael@0 | 3228 | let loader = test.newLoader(); |
michael@0 | 3229 | |
michael@0 | 3230 | let items = [loader.cm.Item({ |
michael@0 | 3231 | label: "item", |
michael@0 | 3232 | context: loader.cm.PredicateContext(function (data) { |
michael@0 | 3233 | assert.strictEqual(data.targetID, "button"); |
michael@0 | 3234 | return true; |
michael@0 | 3235 | }) |
michael@0 | 3236 | })]; |
michael@0 | 3237 | |
michael@0 | 3238 | test.withTestDoc(function (window, doc) { |
michael@0 | 3239 | test.showMenu(doc.getElementById("button"), function (popup) { |
michael@0 | 3240 | test.checkMenu(items, [], []); |
michael@0 | 3241 | test.done(); |
michael@0 | 3242 | }); |
michael@0 | 3243 | }); |
michael@0 | 3244 | }; |
michael@0 | 3245 | |
michael@0 | 3246 | // Test that the data object has the correct ID |
michael@0 | 3247 | exports.testPredicateContextTargetIDNotSet = function (assert, done) { |
michael@0 | 3248 | let test = new TestHelper(assert, done); |
michael@0 | 3249 | let loader = test.newLoader(); |
michael@0 | 3250 | |
michael@0 | 3251 | let items = [loader.cm.Item({ |
michael@0 | 3252 | label: "item", |
michael@0 | 3253 | context: loader.cm.PredicateContext(function (data) { |
michael@0 | 3254 | assert.strictEqual(data.targetID, null); |
michael@0 | 3255 | return true; |
michael@0 | 3256 | }) |
michael@0 | 3257 | })]; |
michael@0 | 3258 | |
michael@0 | 3259 | test.withTestDoc(function (window, doc) { |
michael@0 | 3260 | test.showMenu(doc.getElementsByClassName("predicate-test-a")[0], function (popup) { |
michael@0 | 3261 | test.checkMenu(items, [], []); |
michael@0 | 3262 | test.done(); |
michael@0 | 3263 | }); |
michael@0 | 3264 | }); |
michael@0 | 3265 | }; |
michael@0 | 3266 | |
michael@0 | 3267 | // Test that the data object is showing editable correctly for regular text inputs |
michael@0 | 3268 | exports.testPredicateContextTextBoxIsEditable = function (assert, done) { |
michael@0 | 3269 | let test = new TestHelper(assert, done); |
michael@0 | 3270 | let loader = test.newLoader(); |
michael@0 | 3271 | |
michael@0 | 3272 | let items = [loader.cm.Item({ |
michael@0 | 3273 | label: "item", |
michael@0 | 3274 | context: loader.cm.PredicateContext(function (data) { |
michael@0 | 3275 | assert.strictEqual(data.isEditable, true); |
michael@0 | 3276 | return true; |
michael@0 | 3277 | }) |
michael@0 | 3278 | })]; |
michael@0 | 3279 | |
michael@0 | 3280 | test.withTestDoc(function (window, doc) { |
michael@0 | 3281 | test.showMenu(doc.getElementById("textbox"), function (popup) { |
michael@0 | 3282 | test.checkMenu(items, [], []); |
michael@0 | 3283 | test.done(); |
michael@0 | 3284 | }); |
michael@0 | 3285 | }); |
michael@0 | 3286 | }; |
michael@0 | 3287 | |
michael@0 | 3288 | // Test that the data object is showing editable correctly for readonly text inputs |
michael@0 | 3289 | exports.testPredicateContextReadonlyTextBoxIsNotEditable = function (assert, done) { |
michael@0 | 3290 | let test = new TestHelper(assert, done); |
michael@0 | 3291 | let loader = test.newLoader(); |
michael@0 | 3292 | |
michael@0 | 3293 | let items = [loader.cm.Item({ |
michael@0 | 3294 | label: "item", |
michael@0 | 3295 | context: loader.cm.PredicateContext(function (data) { |
michael@0 | 3296 | assert.strictEqual(data.isEditable, false); |
michael@0 | 3297 | return true; |
michael@0 | 3298 | }) |
michael@0 | 3299 | })]; |
michael@0 | 3300 | |
michael@0 | 3301 | test.withTestDoc(function (window, doc) { |
michael@0 | 3302 | test.showMenu(doc.getElementById("readonly-textbox"), function (popup) { |
michael@0 | 3303 | test.checkMenu(items, [], []); |
michael@0 | 3304 | test.done(); |
michael@0 | 3305 | }); |
michael@0 | 3306 | }); |
michael@0 | 3307 | }; |
michael@0 | 3308 | |
michael@0 | 3309 | // Test that the data object is showing editable correctly for disabled text inputs |
michael@0 | 3310 | exports.testPredicateContextDisabledTextBoxIsNotEditable = function (assert, done) { |
michael@0 | 3311 | let test = new TestHelper(assert, done); |
michael@0 | 3312 | let loader = test.newLoader(); |
michael@0 | 3313 | |
michael@0 | 3314 | let items = [loader.cm.Item({ |
michael@0 | 3315 | label: "item", |
michael@0 | 3316 | context: loader.cm.PredicateContext(function (data) { |
michael@0 | 3317 | assert.strictEqual(data.isEditable, false); |
michael@0 | 3318 | return true; |
michael@0 | 3319 | }) |
michael@0 | 3320 | })]; |
michael@0 | 3321 | |
michael@0 | 3322 | test.withTestDoc(function (window, doc) { |
michael@0 | 3323 | test.showMenu(doc.getElementById("disabled-textbox"), function (popup) { |
michael@0 | 3324 | test.checkMenu(items, [], []); |
michael@0 | 3325 | test.done(); |
michael@0 | 3326 | }); |
michael@0 | 3327 | }); |
michael@0 | 3328 | }; |
michael@0 | 3329 | |
michael@0 | 3330 | // Test that the data object is showing editable correctly for text areas |
michael@0 | 3331 | exports.testPredicateContextTextAreaIsEditable = function (assert, done) { |
michael@0 | 3332 | let test = new TestHelper(assert, done); |
michael@0 | 3333 | let loader = test.newLoader(); |
michael@0 | 3334 | |
michael@0 | 3335 | let items = [loader.cm.Item({ |
michael@0 | 3336 | label: "item", |
michael@0 | 3337 | context: loader.cm.PredicateContext(function (data) { |
michael@0 | 3338 | assert.strictEqual(data.isEditable, true); |
michael@0 | 3339 | return true; |
michael@0 | 3340 | }) |
michael@0 | 3341 | })]; |
michael@0 | 3342 | |
michael@0 | 3343 | test.withTestDoc(function (window, doc) { |
michael@0 | 3344 | test.showMenu(doc.getElementById("textfield"), function (popup) { |
michael@0 | 3345 | test.checkMenu(items, [], []); |
michael@0 | 3346 | test.done(); |
michael@0 | 3347 | }); |
michael@0 | 3348 | }); |
michael@0 | 3349 | }; |
michael@0 | 3350 | |
michael@0 | 3351 | // Test that non-text inputs are not considered editable |
michael@0 | 3352 | exports.testPredicateContextButtonIsNotEditable = function (assert, done) { |
michael@0 | 3353 | let test = new TestHelper(assert, done); |
michael@0 | 3354 | let loader = test.newLoader(); |
michael@0 | 3355 | |
michael@0 | 3356 | let items = [loader.cm.Item({ |
michael@0 | 3357 | label: "item", |
michael@0 | 3358 | context: loader.cm.PredicateContext(function (data) { |
michael@0 | 3359 | assert.strictEqual(data.isEditable, false); |
michael@0 | 3360 | return true; |
michael@0 | 3361 | }) |
michael@0 | 3362 | })]; |
michael@0 | 3363 | |
michael@0 | 3364 | test.withTestDoc(function (window, doc) { |
michael@0 | 3365 | test.showMenu(doc.getElementById("button"), function (popup) { |
michael@0 | 3366 | test.checkMenu(items, [], []); |
michael@0 | 3367 | test.done(); |
michael@0 | 3368 | }); |
michael@0 | 3369 | }); |
michael@0 | 3370 | }; |
michael@0 | 3371 | |
michael@0 | 3372 | |
michael@0 | 3373 | // Test that the data object is showing editable correctly |
michael@0 | 3374 | exports.testPredicateContextNonInputIsNotEditable = function (assert, done) { |
michael@0 | 3375 | let test = new TestHelper(assert, done); |
michael@0 | 3376 | let loader = test.newLoader(); |
michael@0 | 3377 | |
michael@0 | 3378 | let items = [loader.cm.Item({ |
michael@0 | 3379 | label: "item", |
michael@0 | 3380 | context: loader.cm.PredicateContext(function (data) { |
michael@0 | 3381 | assert.strictEqual(data.isEditable, false); |
michael@0 | 3382 | return true; |
michael@0 | 3383 | }) |
michael@0 | 3384 | })]; |
michael@0 | 3385 | |
michael@0 | 3386 | test.withTestDoc(function (window, doc) { |
michael@0 | 3387 | test.showMenu(doc.getElementById("image"), function (popup) { |
michael@0 | 3388 | test.checkMenu(items, [], []); |
michael@0 | 3389 | test.done(); |
michael@0 | 3390 | }); |
michael@0 | 3391 | }); |
michael@0 | 3392 | }; |
michael@0 | 3393 | |
michael@0 | 3394 | |
michael@0 | 3395 | // Test that the data object is showing editable correctly for HTML contenteditable elements |
michael@0 | 3396 | exports.testPredicateContextEditableElement = function (assert, done) { |
michael@0 | 3397 | let test = new TestHelper(assert, done); |
michael@0 | 3398 | let loader = test.newLoader(); |
michael@0 | 3399 | |
michael@0 | 3400 | let items = [loader.cm.Item({ |
michael@0 | 3401 | label: "item", |
michael@0 | 3402 | context: loader.cm.PredicateContext(function (data) { |
michael@0 | 3403 | assert.strictEqual(data.isEditable, true); |
michael@0 | 3404 | return true; |
michael@0 | 3405 | }) |
michael@0 | 3406 | })]; |
michael@0 | 3407 | |
michael@0 | 3408 | test.withTestDoc(function (window, doc) { |
michael@0 | 3409 | test.showMenu(doc.getElementById("editable"), function (popup) { |
michael@0 | 3410 | test.checkMenu(items, [], []); |
michael@0 | 3411 | test.done(); |
michael@0 | 3412 | }); |
michael@0 | 3413 | }); |
michael@0 | 3414 | }; |
michael@0 | 3415 | |
michael@0 | 3416 | |
michael@0 | 3417 | // Test that the data object does not have a selection when there is none |
michael@0 | 3418 | exports.testPredicateContextNoSelectionInPage = function (assert, done) { |
michael@0 | 3419 | let test = new TestHelper(assert, done); |
michael@0 | 3420 | let loader = test.newLoader(); |
michael@0 | 3421 | |
michael@0 | 3422 | let items = [loader.cm.Item({ |
michael@0 | 3423 | label: "item", |
michael@0 | 3424 | context: loader.cm.PredicateContext(function (data) { |
michael@0 | 3425 | assert.strictEqual(data.selectionText, null); |
michael@0 | 3426 | return true; |
michael@0 | 3427 | }) |
michael@0 | 3428 | })]; |
michael@0 | 3429 | |
michael@0 | 3430 | test.withTestDoc(function (window, doc) { |
michael@0 | 3431 | test.showMenu(null, function (popup) { |
michael@0 | 3432 | test.checkMenu(items, [], []); |
michael@0 | 3433 | test.done(); |
michael@0 | 3434 | }); |
michael@0 | 3435 | }); |
michael@0 | 3436 | }; |
michael@0 | 3437 | |
michael@0 | 3438 | // Test that the data object includes the selected page text |
michael@0 | 3439 | exports.testPredicateContextSelectionInPage = function (assert, done) { |
michael@0 | 3440 | let test = new TestHelper(assert, done); |
michael@0 | 3441 | let loader = test.newLoader(); |
michael@0 | 3442 | |
michael@0 | 3443 | let items = [loader.cm.Item({ |
michael@0 | 3444 | label: "item", |
michael@0 | 3445 | context: loader.cm.PredicateContext(function (data) { |
michael@0 | 3446 | // since we might get whitespace |
michael@0 | 3447 | assert.ok(data.selectionText && data.selectionText.search(/^\s*Some text.\s*$/) != -1, |
michael@0 | 3448 | 'Expected "Some text.", got "' + data.selectionText + '"'); |
michael@0 | 3449 | return true; |
michael@0 | 3450 | }) |
michael@0 | 3451 | })]; |
michael@0 | 3452 | |
michael@0 | 3453 | test.withTestDoc(function (window, doc) { |
michael@0 | 3454 | window.getSelection().selectAllChildren(doc.getElementById("text")); |
michael@0 | 3455 | test.showMenu(null, function (popup) { |
michael@0 | 3456 | test.checkMenu(items, [], []); |
michael@0 | 3457 | test.done(); |
michael@0 | 3458 | }); |
michael@0 | 3459 | }); |
michael@0 | 3460 | }; |
michael@0 | 3461 | |
michael@0 | 3462 | // Test that the data object includes the selected input text |
michael@0 | 3463 | exports.testPredicateContextSelectionInTextBox = function (assert, done) { |
michael@0 | 3464 | let test = new TestHelper(assert, done); |
michael@0 | 3465 | let loader = test.newLoader(); |
michael@0 | 3466 | |
michael@0 | 3467 | let items = [loader.cm.Item({ |
michael@0 | 3468 | label: "item", |
michael@0 | 3469 | context: loader.cm.PredicateContext(function (data) { |
michael@0 | 3470 | // since we might get whitespace |
michael@0 | 3471 | assert.strictEqual(data.selectionText, "t v"); |
michael@0 | 3472 | return true; |
michael@0 | 3473 | }) |
michael@0 | 3474 | })]; |
michael@0 | 3475 | |
michael@0 | 3476 | test.withTestDoc(function (window, doc) { |
michael@0 | 3477 | let textbox = doc.getElementById("textbox"); |
michael@0 | 3478 | textbox.focus(); |
michael@0 | 3479 | textbox.setSelectionRange(3, 6); |
michael@0 | 3480 | test.showMenu(textbox, function (popup) { |
michael@0 | 3481 | test.checkMenu(items, [], []); |
michael@0 | 3482 | test.done(); |
michael@0 | 3483 | }); |
michael@0 | 3484 | }); |
michael@0 | 3485 | }; |
michael@0 | 3486 | |
michael@0 | 3487 | // Test that the data object has the correct src for an image |
michael@0 | 3488 | exports.testPredicateContextTargetSrcSet = function (assert, done) { |
michael@0 | 3489 | let test = new TestHelper(assert, done); |
michael@0 | 3490 | let loader = test.newLoader(); |
michael@0 | 3491 | let image; |
michael@0 | 3492 | |
michael@0 | 3493 | let items = [loader.cm.Item({ |
michael@0 | 3494 | label: "item", |
michael@0 | 3495 | context: loader.cm.PredicateContext(function (data) { |
michael@0 | 3496 | assert.strictEqual(data.srcURL, image.src); |
michael@0 | 3497 | return true; |
michael@0 | 3498 | }) |
michael@0 | 3499 | })]; |
michael@0 | 3500 | |
michael@0 | 3501 | test.withTestDoc(function (window, doc) { |
michael@0 | 3502 | image = doc.getElementById("image"); |
michael@0 | 3503 | test.showMenu(image, function (popup) { |
michael@0 | 3504 | test.checkMenu(items, [], []); |
michael@0 | 3505 | test.done(); |
michael@0 | 3506 | }); |
michael@0 | 3507 | }); |
michael@0 | 3508 | }; |
michael@0 | 3509 | |
michael@0 | 3510 | // Test that the data object has no src for a link |
michael@0 | 3511 | exports.testPredicateContextTargetSrcNotSet = function (assert, done) { |
michael@0 | 3512 | let test = new TestHelper(assert, done); |
michael@0 | 3513 | let loader = test.newLoader(); |
michael@0 | 3514 | |
michael@0 | 3515 | let items = [loader.cm.Item({ |
michael@0 | 3516 | label: "item", |
michael@0 | 3517 | context: loader.cm.PredicateContext(function (data) { |
michael@0 | 3518 | assert.strictEqual(data.srcURL, null); |
michael@0 | 3519 | return true; |
michael@0 | 3520 | }) |
michael@0 | 3521 | })]; |
michael@0 | 3522 | |
michael@0 | 3523 | test.withTestDoc(function (window, doc) { |
michael@0 | 3524 | test.showMenu(doc.getElementById("link"), function (popup) { |
michael@0 | 3525 | test.checkMenu(items, [], []); |
michael@0 | 3526 | test.done(); |
michael@0 | 3527 | }); |
michael@0 | 3528 | }); |
michael@0 | 3529 | }; |
michael@0 | 3530 | |
michael@0 | 3531 | |
michael@0 | 3532 | // Test that the data object has the correct link set |
michael@0 | 3533 | exports.testPredicateContextTargetLinkSet = function (assert, done) { |
michael@0 | 3534 | let test = new TestHelper(assert, done); |
michael@0 | 3535 | let loader = test.newLoader(); |
michael@0 | 3536 | let image; |
michael@0 | 3537 | |
michael@0 | 3538 | let items = [loader.cm.Item({ |
michael@0 | 3539 | label: "item", |
michael@0 | 3540 | context: loader.cm.PredicateContext(function (data) { |
michael@0 | 3541 | assert.strictEqual(data.linkURL, TEST_DOC_URL + "#test"); |
michael@0 | 3542 | return true; |
michael@0 | 3543 | }) |
michael@0 | 3544 | })]; |
michael@0 | 3545 | |
michael@0 | 3546 | test.withTestDoc(function (window, doc) { |
michael@0 | 3547 | test.showMenu(doc.getElementsByClassName("predicate-test-a")[0], function (popup) { |
michael@0 | 3548 | test.checkMenu(items, [], []); |
michael@0 | 3549 | test.done(); |
michael@0 | 3550 | }); |
michael@0 | 3551 | }); |
michael@0 | 3552 | }; |
michael@0 | 3553 | |
michael@0 | 3554 | // Test that the data object has no link for an image |
michael@0 | 3555 | exports.testPredicateContextTargetLinkNotSet = function (assert, done) { |
michael@0 | 3556 | let test = new TestHelper(assert, done); |
michael@0 | 3557 | let loader = test.newLoader(); |
michael@0 | 3558 | |
michael@0 | 3559 | let items = [loader.cm.Item({ |
michael@0 | 3560 | label: "item", |
michael@0 | 3561 | context: loader.cm.PredicateContext(function (data) { |
michael@0 | 3562 | assert.strictEqual(data.linkURL, null); |
michael@0 | 3563 | return true; |
michael@0 | 3564 | }) |
michael@0 | 3565 | })]; |
michael@0 | 3566 | |
michael@0 | 3567 | test.withTestDoc(function (window, doc) { |
michael@0 | 3568 | test.showMenu(doc.getElementById("image"), function (popup) { |
michael@0 | 3569 | test.checkMenu(items, [], []); |
michael@0 | 3570 | test.done(); |
michael@0 | 3571 | }); |
michael@0 | 3572 | }); |
michael@0 | 3573 | }; |
michael@0 | 3574 | |
michael@0 | 3575 | // Test that the data object has the value for an input textbox |
michael@0 | 3576 | exports.testPredicateContextTargetValueSet = function (assert, done) { |
michael@0 | 3577 | let test = new TestHelper(assert, done); |
michael@0 | 3578 | let loader = test.newLoader(); |
michael@0 | 3579 | let image; |
michael@0 | 3580 | |
michael@0 | 3581 | let items = [loader.cm.Item({ |
michael@0 | 3582 | label: "item", |
michael@0 | 3583 | context: loader.cm.PredicateContext(function (data) { |
michael@0 | 3584 | assert.strictEqual(data.value, "test value"); |
michael@0 | 3585 | return true; |
michael@0 | 3586 | }) |
michael@0 | 3587 | })]; |
michael@0 | 3588 | |
michael@0 | 3589 | test.withTestDoc(function (window, doc) { |
michael@0 | 3590 | test.showMenu(doc.getElementById("textbox"), function (popup) { |
michael@0 | 3591 | test.checkMenu(items, [], []); |
michael@0 | 3592 | test.done(); |
michael@0 | 3593 | }); |
michael@0 | 3594 | }); |
michael@0 | 3595 | }; |
michael@0 | 3596 | |
michael@0 | 3597 | // Test that the data object has no value for an image |
michael@0 | 3598 | exports.testPredicateContextTargetValueNotSet = function (assert, done) { |
michael@0 | 3599 | let test = new TestHelper(assert, done); |
michael@0 | 3600 | let loader = test.newLoader(); |
michael@0 | 3601 | |
michael@0 | 3602 | let items = [loader.cm.Item({ |
michael@0 | 3603 | label: "item", |
michael@0 | 3604 | context: loader.cm.PredicateContext(function (data) { |
michael@0 | 3605 | assert.strictEqual(data.value, null); |
michael@0 | 3606 | return true; |
michael@0 | 3607 | }) |
michael@0 | 3608 | })]; |
michael@0 | 3609 | |
michael@0 | 3610 | test.withTestDoc(function (window, doc) { |
michael@0 | 3611 | test.showMenu(doc.getElementById("image"), function (popup) { |
michael@0 | 3612 | test.checkMenu(items, [], []); |
michael@0 | 3613 | test.done(); |
michael@0 | 3614 | }); |
michael@0 | 3615 | }); |
michael@0 | 3616 | }; |
michael@0 | 3617 | |
michael@0 | 3618 | |
michael@0 | 3619 | // NO TESTS BELOW THIS LINE! /////////////////////////////////////////////////// |
michael@0 | 3620 | |
michael@0 | 3621 | // This makes it easier to run tests by handling things like opening the menu, |
michael@0 | 3622 | // opening new windows, making assertions, etc. Methods on |test| can be called |
michael@0 | 3623 | // on instances of this class. Don't forget to call done() to end the test! |
michael@0 | 3624 | // WARNING: This looks up items in popups by comparing labels, so don't give two |
michael@0 | 3625 | // items the same label. |
michael@0 | 3626 | function TestHelper(assert, done) { |
michael@0 | 3627 | this.assert = assert; |
michael@0 | 3628 | this.end = done; |
michael@0 | 3629 | this.loaders = []; |
michael@0 | 3630 | this.browserWindow = Cc["@mozilla.org/appshell/window-mediator;1"]. |
michael@0 | 3631 | getService(Ci.nsIWindowMediator). |
michael@0 | 3632 | getMostRecentWindow("navigator:browser"); |
michael@0 | 3633 | this.overflowThreshValue = require("sdk/preferences/service"). |
michael@0 | 3634 | get(OVERFLOW_THRESH_PREF, OVERFLOW_THRESH_DEFAULT); |
michael@0 | 3635 | } |
michael@0 | 3636 | |
michael@0 | 3637 | TestHelper.prototype = { |
michael@0 | 3638 | get contextMenuPopup() { |
michael@0 | 3639 | return this.browserWindow.document.getElementById("contentAreaContextMenu"); |
michael@0 | 3640 | }, |
michael@0 | 3641 | |
michael@0 | 3642 | get contextMenuSeparator() { |
michael@0 | 3643 | return this.browserWindow.document.querySelector("." + SEPARATOR_CLASS); |
michael@0 | 3644 | }, |
michael@0 | 3645 | |
michael@0 | 3646 | get overflowPopup() { |
michael@0 | 3647 | return this.browserWindow.document.querySelector("." + OVERFLOW_POPUP_CLASS); |
michael@0 | 3648 | }, |
michael@0 | 3649 | |
michael@0 | 3650 | get overflowSubmenu() { |
michael@0 | 3651 | return this.browserWindow.document.querySelector("." + OVERFLOW_MENU_CLASS); |
michael@0 | 3652 | }, |
michael@0 | 3653 | |
michael@0 | 3654 | get tabBrowser() { |
michael@0 | 3655 | return this.browserWindow.gBrowser; |
michael@0 | 3656 | }, |
michael@0 | 3657 | |
michael@0 | 3658 | // Methods on the wrapped test can be called on this object. |
michael@0 | 3659 | __noSuchMethod__: function (methodName, args) { |
michael@0 | 3660 | this.assert[methodName].apply(this.assert, args); |
michael@0 | 3661 | }, |
michael@0 | 3662 | |
michael@0 | 3663 | // Asserts that elt, a DOM element representing item, looks OK. |
michael@0 | 3664 | checkItemElt: function (elt, item) { |
michael@0 | 3665 | let itemType = this.getItemType(item); |
michael@0 | 3666 | |
michael@0 | 3667 | switch (itemType) { |
michael@0 | 3668 | case "Item": |
michael@0 | 3669 | this.assert.equal(elt.localName, "menuitem", |
michael@0 | 3670 | "Item DOM element should be a xul:menuitem"); |
michael@0 | 3671 | if (typeof(item.data) === "string") { |
michael@0 | 3672 | this.assert.equal(elt.getAttribute("value"), item.data, |
michael@0 | 3673 | "Item should have correct data"); |
michael@0 | 3674 | } |
michael@0 | 3675 | break |
michael@0 | 3676 | case "Menu": |
michael@0 | 3677 | this.assert.equal(elt.localName, "menu", |
michael@0 | 3678 | "Menu DOM element should be a xul:menu"); |
michael@0 | 3679 | let subPopup = elt.firstChild; |
michael@0 | 3680 | this.assert.ok(subPopup, "xul:menu should have a child"); |
michael@0 | 3681 | this.assert.equal(subPopup.localName, "menupopup", |
michael@0 | 3682 | "xul:menu's first child should be a menupopup"); |
michael@0 | 3683 | break; |
michael@0 | 3684 | case "Separator": |
michael@0 | 3685 | this.assert.equal(elt.localName, "menuseparator", |
michael@0 | 3686 | "Separator DOM element should be a xul:menuseparator"); |
michael@0 | 3687 | break; |
michael@0 | 3688 | } |
michael@0 | 3689 | |
michael@0 | 3690 | if (itemType === "Item" || itemType === "Menu") { |
michael@0 | 3691 | this.assert.equal(elt.getAttribute("label"), item.label, |
michael@0 | 3692 | "Item should have correct title"); |
michael@0 | 3693 | if (typeof(item.image) === "string") { |
michael@0 | 3694 | this.assert.equal(elt.getAttribute("image"), item.image, |
michael@0 | 3695 | "Item should have correct image"); |
michael@0 | 3696 | if (itemType === "Menu") |
michael@0 | 3697 | this.assert.ok(elt.classList.contains("menu-iconic"), |
michael@0 | 3698 | "Menus with images should have the correct class") |
michael@0 | 3699 | else |
michael@0 | 3700 | this.assert.ok(elt.classList.contains("menuitem-iconic"), |
michael@0 | 3701 | "Items with images should have the correct class") |
michael@0 | 3702 | } |
michael@0 | 3703 | else { |
michael@0 | 3704 | this.assert.ok(!elt.getAttribute("image"), |
michael@0 | 3705 | "Item should not have image"); |
michael@0 | 3706 | this.assert.ok(!elt.classList.contains("menu-iconic") && !elt.classList.contains("menuitem-iconic"), |
michael@0 | 3707 | "The iconic classes should not be present") |
michael@0 | 3708 | } |
michael@0 | 3709 | } |
michael@0 | 3710 | }, |
michael@0 | 3711 | |
michael@0 | 3712 | // Asserts that the context menu looks OK given the arguments. presentItems |
michael@0 | 3713 | // are items that have been added to the menu. absentItems are items that |
michael@0 | 3714 | // shouldn't match the current context. removedItems are items that have been |
michael@0 | 3715 | // removed from the menu. |
michael@0 | 3716 | checkMenu: function (presentItems, absentItems, removedItems) { |
michael@0 | 3717 | // Count up how many top-level items there are |
michael@0 | 3718 | let total = 0; |
michael@0 | 3719 | for (let item of presentItems) { |
michael@0 | 3720 | if (absentItems.indexOf(item) < 0 && removedItems.indexOf(item) < 0) |
michael@0 | 3721 | total++; |
michael@0 | 3722 | } |
michael@0 | 3723 | |
michael@0 | 3724 | let separator = this.contextMenuSeparator; |
michael@0 | 3725 | if (total == 0) { |
michael@0 | 3726 | this.assert.ok(!separator || separator.hidden, |
michael@0 | 3727 | "separator should not be present"); |
michael@0 | 3728 | } |
michael@0 | 3729 | else { |
michael@0 | 3730 | this.assert.ok(separator && !separator.hidden, |
michael@0 | 3731 | "separator should be present"); |
michael@0 | 3732 | } |
michael@0 | 3733 | |
michael@0 | 3734 | let mainNodes = this.browserWindow.document.querySelectorAll("#contentAreaContextMenu > ." + ITEM_CLASS); |
michael@0 | 3735 | let overflowNodes = this.browserWindow.document.querySelectorAll("." + OVERFLOW_POPUP_CLASS + " > ." + ITEM_CLASS); |
michael@0 | 3736 | |
michael@0 | 3737 | this.assert.ok(mainNodes.length == 0 || overflowNodes.length == 0, |
michael@0 | 3738 | "Should only see nodes at the top level or in overflow"); |
michael@0 | 3739 | |
michael@0 | 3740 | let overflow = this.overflowSubmenu; |
michael@0 | 3741 | if (this.shouldOverflow(total)) { |
michael@0 | 3742 | this.assert.ok(overflow && !overflow.hidden, |
michael@0 | 3743 | "overflow menu should be present"); |
michael@0 | 3744 | this.assert.equal(mainNodes.length, 0, |
michael@0 | 3745 | "should be no items in the main context menu"); |
michael@0 | 3746 | } |
michael@0 | 3747 | else { |
michael@0 | 3748 | this.assert.ok(!overflow || overflow.hidden, |
michael@0 | 3749 | "overflow menu should not be present"); |
michael@0 | 3750 | // When visible nodes == 0 they could be in overflow or top level |
michael@0 | 3751 | if (total > 0) { |
michael@0 | 3752 | this.assert.equal(overflowNodes.length, 0, |
michael@0 | 3753 | "should be no items in the overflow context menu"); |
michael@0 | 3754 | } |
michael@0 | 3755 | } |
michael@0 | 3756 | |
michael@0 | 3757 | // Iterate over wherever the nodes have ended up |
michael@0 | 3758 | let nodes = mainNodes.length ? mainNodes : overflowNodes; |
michael@0 | 3759 | this.checkNodes(nodes, presentItems, absentItems, removedItems) |
michael@0 | 3760 | let pos = 0; |
michael@0 | 3761 | }, |
michael@0 | 3762 | |
michael@0 | 3763 | // Recurses through the item hierarchy of presentItems comparing it to the |
michael@0 | 3764 | // node hierarchy of nodes. Any items in removedItems will be skipped (so |
michael@0 | 3765 | // should not exist in the XUL), any items in absentItems must exist and be |
michael@0 | 3766 | // hidden |
michael@0 | 3767 | checkNodes: function (nodes, presentItems, absentItems, removedItems) { |
michael@0 | 3768 | let pos = 0; |
michael@0 | 3769 | for (let item of presentItems) { |
michael@0 | 3770 | // Removed items shouldn't be in the list |
michael@0 | 3771 | if (removedItems.indexOf(item) >= 0) |
michael@0 | 3772 | continue; |
michael@0 | 3773 | |
michael@0 | 3774 | if (nodes.length <= pos) { |
michael@0 | 3775 | this.assert.ok(false, "Not enough nodes"); |
michael@0 | 3776 | return; |
michael@0 | 3777 | } |
michael@0 | 3778 | |
michael@0 | 3779 | let hidden = absentItems.indexOf(item) >= 0; |
michael@0 | 3780 | |
michael@0 | 3781 | this.checkItemElt(nodes[pos], item); |
michael@0 | 3782 | this.assert.equal(nodes[pos].hidden, hidden, |
michael@0 | 3783 | "hidden should be set correctly"); |
michael@0 | 3784 | |
michael@0 | 3785 | // The contents of hidden menus doesn't matter so much |
michael@0 | 3786 | if (!hidden && this.getItemType(item) == "Menu") { |
michael@0 | 3787 | this.assert.equal(nodes[pos].firstChild.localName, "menupopup", |
michael@0 | 3788 | "menu XUL should contain a menupopup"); |
michael@0 | 3789 | this.checkNodes(nodes[pos].firstChild.childNodes, item.items, absentItems, removedItems); |
michael@0 | 3790 | } |
michael@0 | 3791 | |
michael@0 | 3792 | if (pos > 0) |
michael@0 | 3793 | this.assert.equal(nodes[pos].previousSibling, nodes[pos - 1], |
michael@0 | 3794 | "nodes should all be in the same group"); |
michael@0 | 3795 | pos++; |
michael@0 | 3796 | } |
michael@0 | 3797 | |
michael@0 | 3798 | this.assert.equal(nodes.length, pos, |
michael@0 | 3799 | "should have checked all the XUL nodes"); |
michael@0 | 3800 | }, |
michael@0 | 3801 | |
michael@0 | 3802 | // Attaches an event listener to node. The listener is automatically removed |
michael@0 | 3803 | // when it's fired (so it's assumed it will fire), and callback is called |
michael@0 | 3804 | // after a short delay. Since the module we're testing relies on the same |
michael@0 | 3805 | // event listeners to do its work, this is to give them a little breathing |
michael@0 | 3806 | // room before callback runs. Inside callback |this| is this object. |
michael@0 | 3807 | // Optionally you can pass a function to test if the event is the event you |
michael@0 | 3808 | // want. |
michael@0 | 3809 | delayedEventListener: function (node, event, callback, useCapture, isValid) { |
michael@0 | 3810 | const self = this; |
michael@0 | 3811 | node.addEventListener(event, function handler(evt) { |
michael@0 | 3812 | if (isValid && !isValid(evt)) |
michael@0 | 3813 | return; |
michael@0 | 3814 | node.removeEventListener(event, handler, useCapture); |
michael@0 | 3815 | timer.setTimeout(function () { |
michael@0 | 3816 | try { |
michael@0 | 3817 | callback.call(self, evt); |
michael@0 | 3818 | } |
michael@0 | 3819 | catch (err) { |
michael@0 | 3820 | self.assert.fail(err); |
michael@0 | 3821 | self.end(); |
michael@0 | 3822 | } |
michael@0 | 3823 | }, 20); |
michael@0 | 3824 | }, useCapture); |
michael@0 | 3825 | }, |
michael@0 | 3826 | |
michael@0 | 3827 | // Call to finish the test. |
michael@0 | 3828 | done: function () { |
michael@0 | 3829 | const self = this; |
michael@0 | 3830 | function commonDone() { |
michael@0 | 3831 | this.closeTab(); |
michael@0 | 3832 | |
michael@0 | 3833 | while (this.loaders.length) { |
michael@0 | 3834 | this.loaders[0].unload(); |
michael@0 | 3835 | } |
michael@0 | 3836 | |
michael@0 | 3837 | require("sdk/preferences/service").set(OVERFLOW_THRESH_PREF, self.overflowThreshValue); |
michael@0 | 3838 | |
michael@0 | 3839 | this.end(); |
michael@0 | 3840 | } |
michael@0 | 3841 | |
michael@0 | 3842 | function closeBrowserWindow() { |
michael@0 | 3843 | if (this.oldBrowserWindow) { |
michael@0 | 3844 | this.delayedEventListener(this.browserWindow, "unload", commonDone, |
michael@0 | 3845 | false); |
michael@0 | 3846 | this.browserWindow.close(); |
michael@0 | 3847 | this.browserWindow = this.oldBrowserWindow; |
michael@0 | 3848 | delete this.oldBrowserWindow; |
michael@0 | 3849 | } |
michael@0 | 3850 | else { |
michael@0 | 3851 | commonDone.call(this); |
michael@0 | 3852 | } |
michael@0 | 3853 | }; |
michael@0 | 3854 | |
michael@0 | 3855 | if (this.contextMenuPopup.state == "closed") { |
michael@0 | 3856 | closeBrowserWindow.call(this); |
michael@0 | 3857 | } |
michael@0 | 3858 | else { |
michael@0 | 3859 | this.delayedEventListener(this.contextMenuPopup, "popuphidden", |
michael@0 | 3860 | function () closeBrowserWindow.call(this), |
michael@0 | 3861 | false); |
michael@0 | 3862 | this.contextMenuPopup.hidePopup(); |
michael@0 | 3863 | } |
michael@0 | 3864 | }, |
michael@0 | 3865 | |
michael@0 | 3866 | closeTab: function() { |
michael@0 | 3867 | if (this.tab) { |
michael@0 | 3868 | this.tabBrowser.removeTab(this.tab); |
michael@0 | 3869 | this.tabBrowser.selectedTab = this.oldSelectedTab; |
michael@0 | 3870 | this.tab = null; |
michael@0 | 3871 | } |
michael@0 | 3872 | }, |
michael@0 | 3873 | |
michael@0 | 3874 | // Returns the DOM element in popup corresponding to item. |
michael@0 | 3875 | // WARNING: The element is found by comparing labels, so don't give two items |
michael@0 | 3876 | // the same label. |
michael@0 | 3877 | getItemElt: function (popup, item) { |
michael@0 | 3878 | let nodes = popup.childNodes; |
michael@0 | 3879 | for (let i = nodes.length - 1; i >= 0; i--) { |
michael@0 | 3880 | if (this.getItemType(item) === "Separator") { |
michael@0 | 3881 | if (nodes[i].localName === "menuseparator") |
michael@0 | 3882 | return nodes[i]; |
michael@0 | 3883 | } |
michael@0 | 3884 | else if (nodes[i].getAttribute("label") === item.label) |
michael@0 | 3885 | return nodes[i]; |
michael@0 | 3886 | } |
michael@0 | 3887 | return null; |
michael@0 | 3888 | }, |
michael@0 | 3889 | |
michael@0 | 3890 | // Returns "Item", "Menu", or "Separator". |
michael@0 | 3891 | getItemType: function (item) { |
michael@0 | 3892 | // Could use instanceof here, but that would require accessing the loader |
michael@0 | 3893 | // that created the item, and I don't want to A) somehow search through the |
michael@0 | 3894 | // this.loaders list to find it, and B) assume there are any live loaders at |
michael@0 | 3895 | // all. |
michael@0 | 3896 | return /^\[object (Item|Menu|Separator)/.exec(item.toString())[1]; |
michael@0 | 3897 | }, |
michael@0 | 3898 | |
michael@0 | 3899 | // Returns a wrapper around a new loader: { loader, cm, unload, globalScope }. |
michael@0 | 3900 | // loader is a Cuddlefish sandboxed loader, cm is the context menu module, |
michael@0 | 3901 | // globalScope is the context menu module's global scope, and unload is a |
michael@0 | 3902 | // function that unloads the loader and associated resources. |
michael@0 | 3903 | newLoader: function () { |
michael@0 | 3904 | const self = this; |
michael@0 | 3905 | let loader = Loader(module); |
michael@0 | 3906 | let wrapper = { |
michael@0 | 3907 | loader: loader, |
michael@0 | 3908 | cm: loader.require("sdk/context-menu"), |
michael@0 | 3909 | globalScope: loader.sandbox("sdk/context-menu"), |
michael@0 | 3910 | unload: function () { |
michael@0 | 3911 | loader.unload(); |
michael@0 | 3912 | let idx = self.loaders.indexOf(wrapper); |
michael@0 | 3913 | if (idx < 0) |
michael@0 | 3914 | throw new Error("Test error: tried to unload nonexistent loader"); |
michael@0 | 3915 | self.loaders.splice(idx, 1); |
michael@0 | 3916 | } |
michael@0 | 3917 | }; |
michael@0 | 3918 | this.loaders.push(wrapper); |
michael@0 | 3919 | return wrapper; |
michael@0 | 3920 | }, |
michael@0 | 3921 | |
michael@0 | 3922 | // As above but the loader has private-browsing support enabled. |
michael@0 | 3923 | newPrivateLoader: function() { |
michael@0 | 3924 | let base = require("@loader/options"); |
michael@0 | 3925 | |
michael@0 | 3926 | // Clone current loader's options adding the private-browsing permission |
michael@0 | 3927 | let options = merge({}, base, { |
michael@0 | 3928 | metadata: merge({}, base.metadata || {}, { |
michael@0 | 3929 | permissions: merge({}, base.metadata.permissions || {}, { |
michael@0 | 3930 | 'private-browsing': true |
michael@0 | 3931 | }) |
michael@0 | 3932 | }) |
michael@0 | 3933 | }); |
michael@0 | 3934 | |
michael@0 | 3935 | const self = this; |
michael@0 | 3936 | let loader = Loader(module, null, options); |
michael@0 | 3937 | let wrapper = { |
michael@0 | 3938 | loader: loader, |
michael@0 | 3939 | cm: loader.require("sdk/context-menu"), |
michael@0 | 3940 | globalScope: loader.sandbox("sdk/context-menu"), |
michael@0 | 3941 | unload: function () { |
michael@0 | 3942 | loader.unload(); |
michael@0 | 3943 | let idx = self.loaders.indexOf(wrapper); |
michael@0 | 3944 | if (idx < 0) |
michael@0 | 3945 | throw new Error("Test error: tried to unload nonexistent loader"); |
michael@0 | 3946 | self.loaders.splice(idx, 1); |
michael@0 | 3947 | } |
michael@0 | 3948 | }; |
michael@0 | 3949 | this.loaders.push(wrapper); |
michael@0 | 3950 | return wrapper; |
michael@0 | 3951 | }, |
michael@0 | 3952 | |
michael@0 | 3953 | // Returns true if the count crosses the overflow threshold. |
michael@0 | 3954 | shouldOverflow: function (count) { |
michael@0 | 3955 | return count > |
michael@0 | 3956 | (this.loaders.length ? |
michael@0 | 3957 | this.loaders[0].loader.require("sdk/preferences/service"). |
michael@0 | 3958 | get(OVERFLOW_THRESH_PREF, OVERFLOW_THRESH_DEFAULT) : |
michael@0 | 3959 | OVERFLOW_THRESH_DEFAULT); |
michael@0 | 3960 | }, |
michael@0 | 3961 | |
michael@0 | 3962 | // Opens the context menu on the current page. If targetNode is null, the |
michael@0 | 3963 | // menu is opened in the top-left corner. onShowncallback is passed the |
michael@0 | 3964 | // popup. |
michael@0 | 3965 | showMenu: function(targetNode, onshownCallback) { |
michael@0 | 3966 | function sendEvent() { |
michael@0 | 3967 | this.delayedEventListener(this.browserWindow, "popupshowing", |
michael@0 | 3968 | function (e) { |
michael@0 | 3969 | let popup = e.target; |
michael@0 | 3970 | onshownCallback.call(this, popup); |
michael@0 | 3971 | }, false); |
michael@0 | 3972 | |
michael@0 | 3973 | let rect = targetNode ? |
michael@0 | 3974 | targetNode.getBoundingClientRect() : |
michael@0 | 3975 | { left: 0, top: 0, width: 0, height: 0 }; |
michael@0 | 3976 | let contentWin = targetNode ? targetNode.ownerDocument.defaultView |
michael@0 | 3977 | : this.browserWindow.content; |
michael@0 | 3978 | contentWin. |
michael@0 | 3979 | QueryInterface(Ci.nsIInterfaceRequestor). |
michael@0 | 3980 | getInterface(Ci.nsIDOMWindowUtils). |
michael@0 | 3981 | sendMouseEvent("contextmenu", |
michael@0 | 3982 | rect.left + (rect.width / 2), |
michael@0 | 3983 | rect.top + (rect.height / 2), |
michael@0 | 3984 | 2, 1, 0); |
michael@0 | 3985 | } |
michael@0 | 3986 | |
michael@0 | 3987 | // If a new tab or window has not yet been opened, open a new tab now. For |
michael@0 | 3988 | // some reason using the tab already opened when the test starts causes |
michael@0 | 3989 | // leaks. See bug 566351 for details. |
michael@0 | 3990 | if (!targetNode && !this.oldSelectedTab && !this.oldBrowserWindow) { |
michael@0 | 3991 | this.oldSelectedTab = this.tabBrowser.selectedTab; |
michael@0 | 3992 | this.tab = this.tabBrowser.addTab("about:blank"); |
michael@0 | 3993 | let browser = this.tabBrowser.getBrowserForTab(this.tab); |
michael@0 | 3994 | |
michael@0 | 3995 | this.delayedEventListener(browser, "load", function () { |
michael@0 | 3996 | this.tabBrowser.selectedTab = this.tab; |
michael@0 | 3997 | sendEvent.call(this); |
michael@0 | 3998 | }, true); |
michael@0 | 3999 | } |
michael@0 | 4000 | else |
michael@0 | 4001 | sendEvent.call(this); |
michael@0 | 4002 | }, |
michael@0 | 4003 | |
michael@0 | 4004 | hideMenu: function(onhiddenCallback) { |
michael@0 | 4005 | this.delayedEventListener(this.browserWindow, "popuphidden", onhiddenCallback); |
michael@0 | 4006 | |
michael@0 | 4007 | this.contextMenuPopup.hidePopup(); |
michael@0 | 4008 | }, |
michael@0 | 4009 | |
michael@0 | 4010 | // Opens a new browser window. The window will be closed automatically when |
michael@0 | 4011 | // done() is called. |
michael@0 | 4012 | withNewWindow: function (onloadCallback) { |
michael@0 | 4013 | let win = this.browserWindow.OpenBrowserWindow(); |
michael@0 | 4014 | this.delayedEventListener(win, "load", onloadCallback, true); |
michael@0 | 4015 | this.oldBrowserWindow = this.browserWindow; |
michael@0 | 4016 | this.browserWindow = win; |
michael@0 | 4017 | }, |
michael@0 | 4018 | |
michael@0 | 4019 | // Opens a new private browser window. The window will be closed |
michael@0 | 4020 | // automatically when done() is called. |
michael@0 | 4021 | withNewPrivateWindow: function (onloadCallback) { |
michael@0 | 4022 | let win = this.browserWindow.OpenBrowserWindow({private: true}); |
michael@0 | 4023 | this.delayedEventListener(win, "load", onloadCallback, true); |
michael@0 | 4024 | this.oldBrowserWindow = this.browserWindow; |
michael@0 | 4025 | this.browserWindow = win; |
michael@0 | 4026 | }, |
michael@0 | 4027 | |
michael@0 | 4028 | // Opens a new tab with our test page in the current window. The tab will |
michael@0 | 4029 | // be closed automatically when done() is called. |
michael@0 | 4030 | withTestDoc: function (onloadCallback) { |
michael@0 | 4031 | this.oldSelectedTab = this.tabBrowser.selectedTab; |
michael@0 | 4032 | this.tab = this.tabBrowser.addTab(TEST_DOC_URL); |
michael@0 | 4033 | let browser = this.tabBrowser.getBrowserForTab(this.tab); |
michael@0 | 4034 | |
michael@0 | 4035 | this.delayedEventListener(browser, "load", function () { |
michael@0 | 4036 | this.tabBrowser.selectedTab = this.tab; |
michael@0 | 4037 | onloadCallback.call(this, browser.contentWindow, browser.contentDocument); |
michael@0 | 4038 | }, true, function(evt) { |
michael@0 | 4039 | return evt.target.location == TEST_DOC_URL; |
michael@0 | 4040 | }); |
michael@0 | 4041 | } |
michael@0 | 4042 | }; |
michael@0 | 4043 | |
michael@0 | 4044 | require('sdk/test').run(exports); |