addon-sdk/source/test/test-selection.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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
michael@0 5 'use strict';
michael@0 6
michael@0 7 module.metadata = {
michael@0 8 'engines': {
michael@0 9 'Firefox': '*'
michael@0 10 }
michael@0 11 };
michael@0 12
michael@0 13 const HTML = "<html>\
michael@0 14 <body>\
michael@0 15 <div>foo</div>\
michael@0 16 <div>and</div>\
michael@0 17 <textarea>noodles</textarea>\
michael@0 18 </body>\
michael@0 19 </html>";
michael@0 20
michael@0 21 const URL = "data:text/html;charset=utf-8," + encodeURIComponent(HTML);
michael@0 22
michael@0 23 const FRAME_HTML = "<iframe src='" + URL + "'><iframe>";
michael@0 24 const FRAME_URL = "data:text/html;charset=utf-8," + encodeURIComponent(FRAME_HTML);
michael@0 25
michael@0 26 const { defer } = require("sdk/core/promise");
michael@0 27 const tabs = require("sdk/tabs");
michael@0 28 const { setTabURL } = require("sdk/tabs/utils");
michael@0 29 const { getActiveTab, getTabContentWindow, closeTab } = require("sdk/tabs/utils")
michael@0 30 const { getMostRecentBrowserWindow } = require("sdk/window/utils");
michael@0 31 const { open: openNewWindow } = require("sdk/window/helpers");
michael@0 32 const { Loader } = require("sdk/test/loader");
michael@0 33 const { setTimeout } = require("sdk/timers");
michael@0 34 const { Cu } = require("chrome");
michael@0 35 const { merge } = require("sdk/util/object");
michael@0 36 const { isPrivate } = require("sdk/private-browsing");
michael@0 37 const events = require("sdk/system/events");
michael@0 38 // General purpose utility functions
michael@0 39
michael@0 40 /**
michael@0 41 * Opens the url given and return a promise, that will be resolved with the
michael@0 42 * content window when the document is ready.
michael@0 43 *
michael@0 44 * I believe this approach could be useful in most of our unit test, that
michael@0 45 * requires to open a tab and need to access to its content.
michael@0 46 */
michael@0 47 function open(url, options) {
michael@0 48 let { promise, resolve } = defer();
michael@0 49
michael@0 50 if (options && typeof(options) === "object") {
michael@0 51 openNewWindow("", {
michael@0 52 features: merge({ toolbar: true }, options)
michael@0 53 }).then(function(chromeWindow) {
michael@0 54 if (isPrivate(chromeWindow) !== !!options.private)
michael@0 55 throw new Error("Window should have Private set to " + !!options.private);
michael@0 56
michael@0 57 let tab = getActiveTab(chromeWindow);
michael@0 58
michael@0 59 tab.linkedBrowser.addEventListener("load", function ready(event) {
michael@0 60 let { document } = getTabContentWindow(tab);
michael@0 61
michael@0 62 if (document.readyState === "complete" && document.URL === url) {
michael@0 63 this.removeEventListener(event.type, ready);
michael@0 64
michael@0 65 resolve(document.defaultView);
michael@0 66 }
michael@0 67 }, true);
michael@0 68
michael@0 69 setTabURL(tab, url);
michael@0 70 });
michael@0 71
michael@0 72 return promise;
michael@0 73 };
michael@0 74
michael@0 75 tabs.open({
michael@0 76 url: url,
michael@0 77 onReady: function(tab) {
michael@0 78 // Unfortunately there is no way to get a XUL Tab from SDK Tab on Firefox,
michael@0 79 // only on Fennec. We should implement `tabNS` also on Firefox in order
michael@0 80 // to have that.
michael@0 81
michael@0 82 // Here we assuming that the most recent browser window is the one we're
michael@0 83 // doing the test, and the active tab is the one we just opened.
michael@0 84 let window = getTabContentWindow(getActiveTab(getMostRecentBrowserWindow()));
michael@0 85
michael@0 86 resolve(window);
michael@0 87 }
michael@0 88 });
michael@0 89
michael@0 90 return promise;
michael@0 91 };
michael@0 92
michael@0 93 /**
michael@0 94 * Close the Active Tab
michael@0 95 */
michael@0 96 function close(window) {
michael@0 97 if (window && window.top && typeof(window.top).close === "function") {
michael@0 98 window.top.close();
michael@0 99 } else {
michael@0 100 // Here we assuming that the most recent browser window is the one we're
michael@0 101 // doing the test, and the active tab is the one we just opened.
michael@0 102 let tab = getActiveTab(getMostRecentBrowserWindow());
michael@0 103
michael@0 104 closeTab(tab);
michael@0 105 }
michael@0 106 }
michael@0 107
michael@0 108 /**
michael@0 109 * Reload the window given and return a promise, that will be resolved with the
michael@0 110 * content window after a small delay.
michael@0 111 */
michael@0 112 function reload(window) {
michael@0 113 let { promise, resolve } = defer();
michael@0 114
michael@0 115 // Here we assuming that the most recent browser window is the one we're
michael@0 116 // doing the test, and the active tab is the one we just opened.
michael@0 117 let tab = tabs.activeTab;
michael@0 118
michael@0 119 tab.once("ready", function () {
michael@0 120 resolve(window);
michael@0 121 });
michael@0 122
michael@0 123 window.location.reload(true);
michael@0 124
michael@0 125 return promise;
michael@0 126 }
michael@0 127
michael@0 128 // Selection's unit test utility function
michael@0 129
michael@0 130 /**
michael@0 131 * Returns the frame's window once the document is loaded
michael@0 132 */
michael@0 133 function getFrameWindow(window) {
michael@0 134 let { promise, resolve } = defer();
michael@0 135
michael@0 136 let frame = window.frames[0];
michael@0 137 let { document } = frame;
michael@0 138
michael@0 139 frame.focus();
michael@0 140
michael@0 141 if (document.readyState === "complete")
michael@0 142 return frame;
michael@0 143
michael@0 144 document.addEventListener("readystatechange", function readystate() {
michael@0 145 if (this.readyState === "complete") {
michael@0 146 this.removeEventListener("readystatechange", readystate);
michael@0 147 frame.focus();
michael@0 148 resolve(frame);
michael@0 149 }
michael@0 150 });
michael@0 151
michael@0 152 return promise;
michael@0 153 }
michael@0 154
michael@0 155 /**
michael@0 156 * Hide the frame in order to destroy the selection object, and show it again
michael@0 157 * after ~500 msec, to give time to attach the code on `document-shown`
michael@0 158 * notification.
michael@0 159 * In the process, call `Cu.forgeGC` to ensure that the `document-shown` code
michael@0 160 * is not garbaged.
michael@0 161 */
michael@0 162 function hideAndShowFrame(window) {
michael@0 163 let { promise, resolve } = defer();
michael@0 164 let iframe = window.document.querySelector("iframe");
michael@0 165
michael@0 166 iframe.style.display = "none";
michael@0 167
michael@0 168 Cu.schedulePreciseGC(function() {
michael@0 169 events.on("document-shown", function shown(event) {
michael@0 170 if (iframe.contentWindow !== event.subject.defaultView)
michael@0 171 return;
michael@0 172
michael@0 173 events.off("document-shown", shown);
michael@0 174 setTimeout(resolve, 0, window);
michael@0 175 }, true);
michael@0 176
michael@0 177 iframe.style.display = "";
michael@0 178 });
michael@0 179
michael@0 180 return promise;
michael@0 181 }
michael@0 182
michael@0 183 /**
michael@0 184 * Select the first div in the page, adding the range to the selection.
michael@0 185 */
michael@0 186 function selectFirstDiv(window) {
michael@0 187 let div = window.document.querySelector("div");
michael@0 188 let selection = window.getSelection();
michael@0 189 let range = window.document.createRange();
michael@0 190
michael@0 191 if (selection.rangeCount > 0)
michael@0 192 selection.removeAllRanges();
michael@0 193
michael@0 194 range.selectNode(div);
michael@0 195 selection.addRange(range);
michael@0 196
michael@0 197 return window;
michael@0 198 }
michael@0 199
michael@0 200 /**
michael@0 201 * Select all divs in the page, adding the ranges to the selection.
michael@0 202 */
michael@0 203 function selectAllDivs(window) {
michael@0 204 let divs = window.document.getElementsByTagName("div");
michael@0 205 let selection = window.getSelection();
michael@0 206
michael@0 207 if (selection.rangeCount > 0)
michael@0 208 selection.removeAllRanges();
michael@0 209
michael@0 210 for (let i = 0; i < divs.length; i++) {
michael@0 211 let range = window.document.createRange();
michael@0 212
michael@0 213 range.selectNode(divs[i]);
michael@0 214 selection.addRange(range);
michael@0 215 }
michael@0 216
michael@0 217 return window;
michael@0 218 }
michael@0 219
michael@0 220 /**
michael@0 221 * Select the textarea content
michael@0 222 */
michael@0 223 function selectTextarea(window) {
michael@0 224 let selection = window.getSelection();
michael@0 225 let textarea = window.document.querySelector("textarea");
michael@0 226
michael@0 227 if (selection.rangeCount > 0)
michael@0 228 selection.removeAllRanges();
michael@0 229
michael@0 230 textarea.setSelectionRange(0, textarea.value.length);
michael@0 231 textarea.focus();
michael@0 232
michael@0 233 return window;
michael@0 234 }
michael@0 235
michael@0 236 /**
michael@0 237 * Select the content of the first div
michael@0 238 */
michael@0 239 function selectContentFirstDiv(window) {
michael@0 240 let div = window.document.querySelector("div");
michael@0 241 let selection = window.getSelection();
michael@0 242 let range = window.document.createRange();
michael@0 243
michael@0 244 if (selection.rangeCount > 0)
michael@0 245 selection.removeAllRanges();
michael@0 246
michael@0 247 range.selectNodeContents(div);
michael@0 248 selection.addRange(range);
michael@0 249
michael@0 250 return window;
michael@0 251 }
michael@0 252
michael@0 253 /**
michael@0 254 * Dispatch the selection event for the selection listener added by
michael@0 255 * `nsISelectionPrivate.addSelectionListener`
michael@0 256 */
michael@0 257 function dispatchSelectionEvent(window) {
michael@0 258 // We modify the selection in order to dispatch the selection's event, by
michael@0 259 // contract the selection by one character. So if the text selected is "foo"
michael@0 260 // will be "fo".
michael@0 261 window.getSelection().modify("extend", "backward", "character");
michael@0 262
michael@0 263 return window;
michael@0 264 }
michael@0 265
michael@0 266 /**
michael@0 267 * Dispatch the selection event for the selection listener added by
michael@0 268 * `window.onselect` / `window.addEventListener`
michael@0 269 */
michael@0 270 function dispatchOnSelectEvent(window) {
michael@0 271 let { document } = window;
michael@0 272 let textarea = document.querySelector("textarea");
michael@0 273 let event = document.createEvent("UIEvents");
michael@0 274
michael@0 275 event.initUIEvent("select", true, true, window, 1);
michael@0 276
michael@0 277 textarea.dispatchEvent(event);
michael@0 278
michael@0 279 return window;
michael@0 280 }
michael@0 281
michael@0 282 /**
michael@0 283 * Creates empty ranges and add them to selections
michael@0 284 */
michael@0 285 function createEmptySelections(window) {
michael@0 286 selectAllDivs(window);
michael@0 287
michael@0 288 let selection = window.getSelection();
michael@0 289
michael@0 290 for (let i = 0; i < selection.rangeCount; i++)
michael@0 291 selection.getRangeAt(i).collapse(true);
michael@0 292 }
michael@0 293
michael@0 294 // Test cases
michael@0 295
michael@0 296 exports["test No Selection"] = function(assert, done) {
michael@0 297 let loader = Loader(module);
michael@0 298 let selection = loader.require("sdk/selection");
michael@0 299
michael@0 300 open(URL).then(function() {
michael@0 301
michael@0 302 assert.equal(selection.isContiguous, false,
michael@0 303 "selection.isContiguous without selection works.");
michael@0 304
michael@0 305 assert.strictEqual(selection.text, null,
michael@0 306 "selection.text without selection works.");
michael@0 307
michael@0 308 assert.strictEqual(selection.html, null,
michael@0 309 "selection.html without selection works.");
michael@0 310
michael@0 311 let selectionCount = 0;
michael@0 312 for each (let sel in selection)
michael@0 313 selectionCount++;
michael@0 314
michael@0 315 assert.equal(selectionCount, 0,
michael@0 316 "No iterable selections");
michael@0 317
michael@0 318 }).then(close).then(loader.unload).then(done, assert.fail);
michael@0 319 };
michael@0 320
michael@0 321 exports["test Single DOM Selection"] = function(assert, done) {
michael@0 322 let loader = Loader(module);
michael@0 323 let selection = loader.require("sdk/selection");
michael@0 324
michael@0 325 open(URL).then(selectFirstDiv).then(function() {
michael@0 326
michael@0 327 assert.equal(selection.isContiguous, true,
michael@0 328 "selection.isContiguous with single DOM Selection works.");
michael@0 329
michael@0 330 assert.equal(selection.text, "foo",
michael@0 331 "selection.text with single DOM Selection works.");
michael@0 332
michael@0 333 assert.equal(selection.html, "<div>foo</div>",
michael@0 334 "selection.html with single DOM Selection works.");
michael@0 335
michael@0 336 let selectionCount = 0;
michael@0 337 for each (let sel in selection) {
michael@0 338 selectionCount++;
michael@0 339
michael@0 340 assert.equal(sel.text, "foo",
michael@0 341 "iterable selection.text with single DOM Selection works.");
michael@0 342
michael@0 343 assert.equal(sel.html, "<div>foo</div>",
michael@0 344 "iterable selection.html with single DOM Selection works.");
michael@0 345 }
michael@0 346
michael@0 347 assert.equal(selectionCount, 1,
michael@0 348 "One iterable selection");
michael@0 349
michael@0 350 }).then(close).then(loader.unload).then(done, assert.fail);
michael@0 351 };
michael@0 352
michael@0 353 exports["test Multiple DOM Selection"] = function(assert, done) {
michael@0 354 let loader = Loader(module);
michael@0 355 let selection = loader.require("sdk/selection");
michael@0 356
michael@0 357 open(URL).then(selectAllDivs).then(function() {
michael@0 358 let expectedText = ["foo", "and"];
michael@0 359 let expectedHTML = ["<div>foo</div>", "<div>and</div>"];
michael@0 360
michael@0 361 assert.equal(selection.isContiguous, false,
michael@0 362 "selection.isContiguous with multiple DOM Selection works.");
michael@0 363
michael@0 364 assert.equal(selection.text, expectedText[0],
michael@0 365 "selection.text with multiple DOM Selection works.");
michael@0 366
michael@0 367 assert.equal(selection.html, expectedHTML[0],
michael@0 368 "selection.html with multiple DOM Selection works.");
michael@0 369
michael@0 370 let selectionCount = 0;
michael@0 371 for each (let sel in selection) {
michael@0 372 assert.equal(sel.text, expectedText[selectionCount],
michael@0 373 "iterable selection.text with multiple DOM Selection works.");
michael@0 374
michael@0 375 assert.equal(sel.html, expectedHTML[selectionCount],
michael@0 376 "iterable selection.text with multiple DOM Selection works.");
michael@0 377
michael@0 378 selectionCount++;
michael@0 379 }
michael@0 380
michael@0 381 assert.equal(selectionCount, 2,
michael@0 382 "Two iterable selections");
michael@0 383
michael@0 384 }).then(close).then(loader.unload).then(done, assert.fail);
michael@0 385 };
michael@0 386
michael@0 387 exports["test Textarea Selection"] = function(assert, done) {
michael@0 388 let loader = Loader(module);
michael@0 389 let selection = loader.require("sdk/selection");
michael@0 390
michael@0 391 open(URL).then(selectTextarea).then(function() {
michael@0 392
michael@0 393 assert.equal(selection.isContiguous, true,
michael@0 394 "selection.isContiguous with Textarea Selection works.");
michael@0 395
michael@0 396 assert.equal(selection.text, "noodles",
michael@0 397 "selection.text with Textarea Selection works.");
michael@0 398
michael@0 399 assert.strictEqual(selection.html, null,
michael@0 400 "selection.html with Textarea Selection works.");
michael@0 401
michael@0 402 let selectionCount = 0;
michael@0 403 for each (let sel in selection) {
michael@0 404 selectionCount++;
michael@0 405
michael@0 406 assert.equal(sel.text, "noodles",
michael@0 407 "iterable selection.text with Textarea Selection works.");
michael@0 408
michael@0 409 assert.strictEqual(sel.html, null,
michael@0 410 "iterable selection.html with Textarea Selection works.");
michael@0 411 }
michael@0 412
michael@0 413 assert.equal(selectionCount, 1,
michael@0 414 "One iterable selection");
michael@0 415
michael@0 416 }).then(close).then(loader.unload).then(done, assert.fail);
michael@0 417 };
michael@0 418
michael@0 419 exports["test Set Text in Multiple DOM Selection"] = function(assert, done) {
michael@0 420 let loader = Loader(module);
michael@0 421 let selection = loader.require("sdk/selection");
michael@0 422
michael@0 423 open(URL).then(selectAllDivs).then(function() {
michael@0 424 let expectedText = ["bar", "and"];
michael@0 425 let expectedHTML = ["bar", "<div>and</div>"];
michael@0 426
michael@0 427 selection.text = "bar";
michael@0 428
michael@0 429 assert.equal(selection.text, expectedText[0],
michael@0 430 "set selection.text with single DOM Selection works.");
michael@0 431
michael@0 432 assert.equal(selection.html, expectedHTML[0],
michael@0 433 "selection.html with single DOM Selection works.");
michael@0 434
michael@0 435 let selectionCount = 0;
michael@0 436 for each (let sel in selection) {
michael@0 437
michael@0 438 assert.equal(sel.text, expectedText[selectionCount],
michael@0 439 "iterable selection.text with multiple DOM Selection works.");
michael@0 440
michael@0 441 assert.equal(sel.html, expectedHTML[selectionCount],
michael@0 442 "iterable selection.html with multiple DOM Selection works.");
michael@0 443
michael@0 444 selectionCount++;
michael@0 445 }
michael@0 446
michael@0 447 assert.equal(selectionCount, 2,
michael@0 448 "Two iterable selections");
michael@0 449
michael@0 450 }).then(close).then(loader.unload).then(done, assert.fail);
michael@0 451 };
michael@0 452
michael@0 453 exports["test Set HTML in Multiple DOM Selection"] = function(assert, done) {
michael@0 454 let loader = Loader(module);
michael@0 455 let selection = loader.require("sdk/selection");
michael@0 456
michael@0 457 open(URL).then(selectAllDivs).then(function() {
michael@0 458 let html = "<span>b<b>a</b>r</span>";
michael@0 459
michael@0 460 let expectedText = ["bar", "and"];
michael@0 461 let expectedHTML = [html, "<div>and</div>"];
michael@0 462
michael@0 463 selection.html = html;
michael@0 464
michael@0 465 assert.equal(selection.text, expectedText[0],
michael@0 466 "set selection.text with DOM Selection works.");
michael@0 467
michael@0 468 assert.equal(selection.html, expectedHTML[0],
michael@0 469 "selection.html with DOM Selection works.");
michael@0 470
michael@0 471 let selectionCount = 0;
michael@0 472 for each (let sel in selection) {
michael@0 473
michael@0 474 assert.equal(sel.text, expectedText[selectionCount],
michael@0 475 "iterable selection.text with multiple DOM Selection works.");
michael@0 476
michael@0 477 assert.equal(sel.html, expectedHTML[selectionCount],
michael@0 478 "iterable selection.html with multiple DOM Selection works.");
michael@0 479
michael@0 480 selectionCount++;
michael@0 481 }
michael@0 482
michael@0 483 assert.equal(selectionCount, 2,
michael@0 484 "Two iterable selections");
michael@0 485
michael@0 486 }).then(close).then(loader.unload).then(done, assert.fail);
michael@0 487 };
michael@0 488
michael@0 489 exports["test Set HTML as text in Multiple DOM Selection"] = function(assert, done) {
michael@0 490 let loader = Loader(module);
michael@0 491 let selection = loader.require("sdk/selection");
michael@0 492
michael@0 493 open(URL).then(selectAllDivs).then(function() {
michael@0 494 let text = "<span>b<b>a</b>r</span>";
michael@0 495 let html = "&lt;span&gt;b&lt;b&gt;a&lt;/b&gt;r&lt;/span&gt;";
michael@0 496
michael@0 497 let expectedText = [text, "and"];
michael@0 498 let expectedHTML = [html, "<div>and</div>"];
michael@0 499
michael@0 500 selection.text = text;
michael@0 501
michael@0 502 assert.equal(selection.text, expectedText[0],
michael@0 503 "set selection.text with DOM Selection works.");
michael@0 504
michael@0 505 assert.equal(selection.html, expectedHTML[0],
michael@0 506 "selection.html with DOM Selection works.");
michael@0 507
michael@0 508 let selectionCount = 0;
michael@0 509 for each (let sel in selection) {
michael@0 510
michael@0 511 assert.equal(sel.text, expectedText[selectionCount],
michael@0 512 "iterable selection.text with multiple DOM Selection works.");
michael@0 513
michael@0 514 assert.equal(sel.html, expectedHTML[selectionCount],
michael@0 515 "iterable selection.html with multiple DOM Selection works.");
michael@0 516
michael@0 517 selectionCount++;
michael@0 518 }
michael@0 519
michael@0 520 assert.equal(selectionCount, 2,
michael@0 521 "Two iterable selections");
michael@0 522
michael@0 523 }).then(close).then(loader.unload).then(done, assert.fail);
michael@0 524 };
michael@0 525
michael@0 526 exports["test Set Text in Textarea Selection"] = function(assert, done) {
michael@0 527 let loader = Loader(module);
michael@0 528 let selection = loader.require("sdk/selection");
michael@0 529
michael@0 530 open(URL).then(selectTextarea).then(function() {
michael@0 531
michael@0 532 let text = "bar";
michael@0 533
michael@0 534 selection.text = text;
michael@0 535
michael@0 536 assert.equal(selection.text, text,
michael@0 537 "set selection.text with Textarea Selection works.");
michael@0 538
michael@0 539 assert.strictEqual(selection.html, null,
michael@0 540 "selection.html with Textarea Selection works.");
michael@0 541
michael@0 542 let selectionCount = 0;
michael@0 543 for each (let sel in selection) {
michael@0 544 selectionCount++;
michael@0 545
michael@0 546 assert.equal(sel.text, text,
michael@0 547 "iterable selection.text with Textarea Selection works.");
michael@0 548
michael@0 549 assert.strictEqual(sel.html, null,
michael@0 550 "iterable selection.html with Textarea Selection works.");
michael@0 551 }
michael@0 552
michael@0 553 assert.equal(selectionCount, 1,
michael@0 554 "One iterable selection");
michael@0 555
michael@0 556 }).then(close).then(loader.unload).then(done, assert.fail);
michael@0 557 };
michael@0 558
michael@0 559 exports["test Set HTML in Textarea Selection"] = function(assert, done) {
michael@0 560 let loader = Loader(module);
michael@0 561 let selection = loader.require("sdk/selection");
michael@0 562
michael@0 563 open(URL).then(selectTextarea).then(function() {
michael@0 564
michael@0 565 let html = "<span>b<b>a</b>r</span>";
michael@0 566
michael@0 567 // Textarea can't have HTML so set `html` property is equals to set `text`
michael@0 568 // property
michael@0 569 selection.html = html;
michael@0 570
michael@0 571 assert.equal(selection.text, html,
michael@0 572 "set selection.text with Textarea Selection works.");
michael@0 573
michael@0 574 assert.strictEqual(selection.html, null,
michael@0 575 "selection.html with Textarea Selection works.");
michael@0 576
michael@0 577 let selectionCount = 0;
michael@0 578 for each (let sel in selection) {
michael@0 579 selectionCount++;
michael@0 580
michael@0 581 assert.equal(sel.text, html,
michael@0 582 "iterable selection.text with Textarea Selection works.");
michael@0 583
michael@0 584 assert.strictEqual(sel.html, null,
michael@0 585 "iterable selection.html with Textarea Selection works.");
michael@0 586 }
michael@0 587
michael@0 588 assert.equal(selectionCount, 1,
michael@0 589 "One iterable selection");
michael@0 590
michael@0 591 }).then(close).then(loader.unload).then(done, assert.fail);
michael@0 592 };
michael@0 593
michael@0 594 exports["test Empty Selections"] = function(assert, done) {
michael@0 595 let loader = Loader(module);
michael@0 596 let selection = loader.require("sdk/selection");
michael@0 597
michael@0 598 open(URL).then(createEmptySelections).then(function(){
michael@0 599 assert.equal(selection.isContiguous, false,
michael@0 600 "selection.isContiguous with empty selections works.");
michael@0 601
michael@0 602 assert.strictEqual(selection.text, null,
michael@0 603 "selection.text with empty selections works.");
michael@0 604
michael@0 605 assert.strictEqual(selection.html, null,
michael@0 606 "selection.html with empty selections works.");
michael@0 607
michael@0 608 let selectionCount = 0;
michael@0 609 for each (let sel in selection)
michael@0 610 selectionCount++;
michael@0 611
michael@0 612 assert.equal(selectionCount, 0,
michael@0 613 "No iterable selections");
michael@0 614
michael@0 615 }).then(close).then(loader.unload).then(done, assert.fail);
michael@0 616 }
michael@0 617
michael@0 618
michael@0 619 exports["test No Selection Exception"] = function(assert, done) {
michael@0 620 const NO_SELECTION = /It isn't possible to change the selection/;
michael@0 621
michael@0 622 let loader = Loader(module);
michael@0 623 let selection = loader.require("sdk/selection");
michael@0 624
michael@0 625 open(URL).then(function() {
michael@0 626
michael@0 627 // We're trying to change a selection when there is no selection
michael@0 628 assert.throws(function() {
michael@0 629 selection.text = "bar";
michael@0 630 }, NO_SELECTION);
michael@0 631
michael@0 632 assert.throws(function() {
michael@0 633 selection.html = "bar";
michael@0 634 }, NO_SELECTION);
michael@0 635
michael@0 636 }).then(close).then(loader.unload).then(done, assert.fail);
michael@0 637 };
michael@0 638
michael@0 639 exports["test for...of without selections"] = function(assert, done) {
michael@0 640 let loader = Loader(module);
michael@0 641 let selection = loader.require("sdk/selection");
michael@0 642
michael@0 643 open(URL).then(function() {
michael@0 644 let selectionCount = 0;
michael@0 645
michael@0 646 for (let sel of selection)
michael@0 647 selectionCount++;
michael@0 648
michael@0 649 assert.equal(selectionCount, 0,
michael@0 650 "No iterable selections");
michael@0 651
michael@0 652 }).then(close).then(loader.unload).then(null, function(error) {
michael@0 653 // iterable are not supported yet in Firefox 16, for example, but
michael@0 654 // they are in Firefox 17.
michael@0 655 if (error.message.indexOf("is not iterable") > -1)
michael@0 656 assert.pass("`iterable` method not supported in this application");
michael@0 657 else
michael@0 658 assert.fail(error);
michael@0 659 }).then(done, assert.fail);
michael@0 660 }
michael@0 661
michael@0 662 exports["test for...of with selections"] = function(assert, done) {
michael@0 663 let loader = Loader(module);
michael@0 664 let selection = loader.require("sdk/selection");
michael@0 665
michael@0 666 open(URL).then(selectAllDivs).then(function(){
michael@0 667 let expectedText = ["foo", "and"];
michael@0 668 let expectedHTML = ["<div>foo</div>", "<div>and</div>"];
michael@0 669
michael@0 670 let selectionCount = 0;
michael@0 671
michael@0 672 for (let sel of selection) {
michael@0 673 assert.equal(sel.text, expectedText[selectionCount],
michael@0 674 "iterable selection.text with for...of works.");
michael@0 675
michael@0 676 assert.equal(sel.html, expectedHTML[selectionCount],
michael@0 677 "iterable selection.text with for...of works.");
michael@0 678
michael@0 679 selectionCount++;
michael@0 680 }
michael@0 681
michael@0 682 assert.equal(selectionCount, 2,
michael@0 683 "Two iterable selections");
michael@0 684
michael@0 685 }).then(close).then(loader.unload).then(null, function(error) {
michael@0 686 // iterable are not supported yet in Firefox 16, for example, but
michael@0 687 // they are in Firefox 17.
michael@0 688 if (error.message.indexOf("is not iterable") > -1)
michael@0 689 assert.pass("`iterable` method not supported in this application");
michael@0 690 else
michael@0 691 assert.fail(error);
michael@0 692 }).then(done, assert.fail)
michael@0 693 }
michael@0 694
michael@0 695 exports["test Selection Listener"] = function(assert, done) {
michael@0 696 let loader = Loader(module);
michael@0 697 let selection = loader.require("sdk/selection");
michael@0 698
michael@0 699 selection.once("select", function() {
michael@0 700 assert.equal(selection.text, "fo");
michael@0 701 done();
michael@0 702 });
michael@0 703
michael@0 704 open(URL).then(selectContentFirstDiv).
michael@0 705 then(dispatchSelectionEvent).
michael@0 706 then(close).
michael@0 707 then(loader.unload, assert.fail);
michael@0 708 };
michael@0 709
michael@0 710 exports["test Textarea OnSelect Listener"] = function(assert, done) {
michael@0 711 let loader = Loader(module);
michael@0 712 let selection = loader.require("sdk/selection");
michael@0 713
michael@0 714 selection.once("select", function() {
michael@0 715 assert.equal(selection.text, "noodles");
michael@0 716 done();
michael@0 717 });
michael@0 718
michael@0 719 open(URL).then(selectTextarea).
michael@0 720 then(dispatchOnSelectEvent).
michael@0 721 then(close).
michael@0 722 then(loader.unload, assert.fail);
michael@0 723 };
michael@0 724
michael@0 725 exports["test Selection listener removed on unload"] = function(assert, done) {
michael@0 726 let loader = Loader(module);
michael@0 727 let selection = loader.require("sdk/selection");
michael@0 728
michael@0 729 selection.once("select", function() {
michael@0 730 assert.fail("Shouldn't be never called");
michael@0 731 });
michael@0 732
michael@0 733 loader.unload();
michael@0 734
michael@0 735 assert.pass();
michael@0 736
michael@0 737 open(URL).
michael@0 738 then(selectContentFirstDiv).
michael@0 739 then(dispatchSelectionEvent).
michael@0 740 then(close).
michael@0 741 then(done, assert.fail);
michael@0 742 };
michael@0 743
michael@0 744 exports["test Textarea onSelect Listener removed on unload"] = function(assert, done) {
michael@0 745 let loader = Loader(module);
michael@0 746 let selection = loader.require("sdk/selection");
michael@0 747
michael@0 748 selection.once("select", function() {
michael@0 749 assert.fail("Shouldn't be never called");
michael@0 750 });
michael@0 751
michael@0 752 loader.unload();
michael@0 753
michael@0 754 assert.pass();
michael@0 755
michael@0 756 open(URL).
michael@0 757 then(selectTextarea).
michael@0 758 then(dispatchOnSelectEvent).
michael@0 759 then(close).
michael@0 760 then(done, assert.fail);
michael@0 761 };
michael@0 762
michael@0 763
michael@0 764 exports["test Selection Listener on existing document"] = function(assert, done) {
michael@0 765 let loader = Loader(module);
michael@0 766
michael@0 767 open(URL).then(function(window){
michael@0 768 let selection = loader.require("sdk/selection");
michael@0 769
michael@0 770 selection.once("select", function() {
michael@0 771 assert.equal(selection.text, "fo");
michael@0 772 done();
michael@0 773 });
michael@0 774
michael@0 775 return window;
michael@0 776 }).then(selectContentFirstDiv).
michael@0 777 then(dispatchSelectionEvent).
michael@0 778 then(close).
michael@0 779 then(loader.unload, assert.fail);
michael@0 780 };
michael@0 781
michael@0 782
michael@0 783 exports["test Textarea OnSelect Listener on existing document"] = function(assert, done) {
michael@0 784 let loader = Loader(module);
michael@0 785
michael@0 786 open(URL).then(function(window){
michael@0 787 let selection = loader.require("sdk/selection");
michael@0 788
michael@0 789 selection.once("select", function() {
michael@0 790 assert.equal(selection.text, "noodles");
michael@0 791 done();
michael@0 792 });
michael@0 793
michael@0 794 return window;
michael@0 795 }).then(selectTextarea).
michael@0 796 then(dispatchOnSelectEvent).
michael@0 797 then(close).
michael@0 798 then(loader.unload, assert.fail);
michael@0 799 };
michael@0 800
michael@0 801 exports["test Selection Listener on document reload"] = function(assert, done) {
michael@0 802 let loader = Loader(module);
michael@0 803 let selection = loader.require("sdk/selection");
michael@0 804
michael@0 805 selection.once("select", function() {
michael@0 806 assert.equal(selection.text, "fo");
michael@0 807 done();
michael@0 808 });
michael@0 809
michael@0 810 open(URL).
michael@0 811 then(reload).
michael@0 812 then(selectContentFirstDiv).
michael@0 813 then(dispatchSelectionEvent).
michael@0 814 then(close).
michael@0 815 then(loader.unload, assert.fail);
michael@0 816 };
michael@0 817
michael@0 818 exports["test Textarea OnSelect Listener on document reload"] = function(assert, done) {
michael@0 819 let loader = Loader(module);
michael@0 820 let selection = loader.require("sdk/selection");
michael@0 821
michael@0 822 selection.once("select", function() {
michael@0 823 assert.equal(selection.text, "noodles");
michael@0 824 done();
michael@0 825 });
michael@0 826
michael@0 827 open(URL).
michael@0 828 then(reload).
michael@0 829 then(selectTextarea).
michael@0 830 then(dispatchOnSelectEvent).
michael@0 831 then(close).
michael@0 832 then(loader.unload, assert.fail);
michael@0 833 };
michael@0 834
michael@0 835 exports["test Selection Listener on frame"] = function(assert, done) {
michael@0 836 let loader = Loader(module);
michael@0 837 let selection = loader.require("sdk/selection");
michael@0 838
michael@0 839 selection.once("select", function() {
michael@0 840 assert.equal(selection.text, "fo");
michael@0 841 close();
michael@0 842 loader.unload();
michael@0 843 done();
michael@0 844 });
michael@0 845
michael@0 846 open(FRAME_URL).
michael@0 847 then(hideAndShowFrame).
michael@0 848 then(getFrameWindow).
michael@0 849 then(selectContentFirstDiv).
michael@0 850 then(dispatchSelectionEvent).
michael@0 851 then(null, assert.fail);
michael@0 852 };
michael@0 853
michael@0 854 exports["test Textarea onSelect Listener on frame"] = function(assert, done) {
michael@0 855 let loader = Loader(module);
michael@0 856 let selection = loader.require("sdk/selection");
michael@0 857
michael@0 858 selection.once("select", function() {
michael@0 859 assert.equal(selection.text, "noodles");
michael@0 860 close();
michael@0 861 loader.unload();
michael@0 862 done();
michael@0 863 });
michael@0 864
michael@0 865 open(FRAME_URL).
michael@0 866 then(hideAndShowFrame).
michael@0 867 then(getFrameWindow).
michael@0 868 then(selectTextarea).
michael@0 869 then(dispatchOnSelectEvent).
michael@0 870 then(null, assert.fail);
michael@0 871 };
michael@0 872
michael@0 873
michael@0 874 exports["test PBPW Selection Listener"] = function(assert, done) {
michael@0 875 let loader = Loader(module);
michael@0 876 let selection = loader.require("sdk/selection");
michael@0 877
michael@0 878 selection.once("select", function() {
michael@0 879 assert.fail("Shouldn't be never called");
michael@0 880 });
michael@0 881
michael@0 882 assert.pass();
michael@0 883
michael@0 884 open(URL, {private: true}).
michael@0 885 then(selectContentFirstDiv).
michael@0 886 then(dispatchSelectionEvent).
michael@0 887 then(close).
michael@0 888 then(loader.unload).
michael@0 889 then(done, assert.fail);
michael@0 890 };
michael@0 891
michael@0 892 exports["test PBPW Textarea OnSelect Listener"] = function(assert, done) {
michael@0 893 let loader = Loader(module);
michael@0 894 let selection = loader.require("sdk/selection");
michael@0 895
michael@0 896 selection.once("select", function() {
michael@0 897 assert.fail("Shouldn't be never called");
michael@0 898 });
michael@0 899
michael@0 900 assert.pass();
michael@0 901
michael@0 902 open(URL, {private: true}).
michael@0 903 then(selectTextarea).
michael@0 904 then(dispatchOnSelectEvent).
michael@0 905 then(close).
michael@0 906 then(loader.unload).
michael@0 907 then(done, assert.fail);
michael@0 908 };
michael@0 909
michael@0 910
michael@0 911 exports["test PBPW Single DOM Selection"] = function(assert, done) {
michael@0 912 let loader = Loader(module);
michael@0 913 let selection = loader.require("sdk/selection");
michael@0 914
michael@0 915 open(URL, {private: true}).then(selectFirstDiv).then(function(window) {
michael@0 916
michael@0 917 assert.equal(selection.isContiguous, false,
michael@0 918 "selection.isContiguous with single DOM Selection in PBPW works.");
michael@0 919
michael@0 920 assert.equal(selection.text, null,
michael@0 921 "selection.text with single DOM Selection in PBPW works.");
michael@0 922
michael@0 923 assert.equal(selection.html, null,
michael@0 924 "selection.html with single DOM Selection in PBPW works.");
michael@0 925
michael@0 926 let selectionCount = 0;
michael@0 927 for each (let sel in selection)
michael@0 928 selectionCount++;
michael@0 929
michael@0 930 assert.equal(selectionCount, 0,
michael@0 931 "No iterable selection in PBPW");
michael@0 932
michael@0 933 return window;
michael@0 934 }).then(close).then(loader.unload).then(done, assert.fail);
michael@0 935 };
michael@0 936
michael@0 937 exports["test PBPW Textarea Selection"] = function(assert, done) {
michael@0 938 let loader = Loader(module);
michael@0 939 let selection = loader.require("sdk/selection");
michael@0 940
michael@0 941 open(URL, {private: true}).then(selectTextarea).then(function(window) {
michael@0 942
michael@0 943 assert.equal(selection.isContiguous, false,
michael@0 944 "selection.isContiguous with Textarea Selection in PBPW works.");
michael@0 945
michael@0 946 assert.equal(selection.text, null,
michael@0 947 "selection.text with Textarea Selection in PBPW works.");
michael@0 948
michael@0 949 assert.strictEqual(selection.html, null,
michael@0 950 "selection.html with Textarea Selection in PBPW works.");
michael@0 951
michael@0 952 let selectionCount = 0;
michael@0 953 for each (let sel in selection) {
michael@0 954 selectionCount++;
michael@0 955
michael@0 956 assert.equal(sel.text, null,
michael@0 957 "iterable selection.text with Textarea Selection in PBPW works.");
michael@0 958
michael@0 959 assert.strictEqual(sel.html, null,
michael@0 960 "iterable selection.html with Textarea Selection in PBPW works.");
michael@0 961 }
michael@0 962
michael@0 963 assert.equal(selectionCount, 0,
michael@0 964 "No iterable selection in PBPW");
michael@0 965
michael@0 966 return window;
michael@0 967 }).then(close).then(loader.unload).then(done, assert.fail);
michael@0 968 };
michael@0 969
michael@0 970 // TODO: test Selection Listener on long-held connection (Bug 661884)
michael@0 971 //
michael@0 972 // I didn't find a way to do so with httpd, using `processAsync` I'm able to
michael@0 973 // Keep the connection but not to flush the buffer to the client in two steps,
michael@0 974 // that is what I need for this test (e.g. flush "Hello" to the client, makes
michael@0 975 // selection when the connection is still hold, and check that the listener
michael@0 976 // is executed before the server send "World" and close the connection).
michael@0 977 //
michael@0 978 // Because this test is needed to the refactoring of context-menu as well, I
michael@0 979 // believe we will find a proper solution quickly.
michael@0 980 /*
michael@0 981 exports["test Selection Listener on long-held connection"] = function(assert, done) {
michael@0 982
michael@0 983 };
michael@0 984 */
michael@0 985
michael@0 986 // If the platform doesn't support the PBPW, we're replacing PBPW tests
michael@0 987 if (!require("sdk/private-browsing/utils").isWindowPBSupported) {
michael@0 988 Object.keys(module.exports).forEach(function(key) {
michael@0 989 if (key.indexOf("test PBPW") === 0) {
michael@0 990 module.exports[key] = function Unsupported (assert) {
michael@0 991 assert.pass("Private Window Per Browsing is not supported on this platform.");
michael@0 992 }
michael@0 993 }
michael@0 994 });
michael@0 995 }
michael@0 996
michael@0 997 require("test").run(exports)

mercurial