addon-sdk/source/test/addons/private-browsing-supported/test-selection.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

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
michael@0 5 "use strict";
michael@0 6
michael@0 7 const HTML = "<html>\
michael@0 8 <body>\
michael@0 9 <div>foo</div>\
michael@0 10 <div>and</div>\
michael@0 11 <textarea>noodles</textarea>\
michael@0 12 </body>\
michael@0 13 </html>";
michael@0 14
michael@0 15 const URL = "data:text/html;charset=utf-8," + encodeURIComponent(HTML);
michael@0 16
michael@0 17 const FRAME_HTML = "<iframe src='" + URL + "'><iframe>";
michael@0 18 const FRAME_URL = "data:text/html;charset=utf-8," + encodeURIComponent(FRAME_HTML);
michael@0 19
michael@0 20 const { defer } = require("sdk/core/promise");
michael@0 21 const { browserWindows } = require("sdk/windows");
michael@0 22 const tabs = require("sdk/tabs");
michael@0 23 const { setTabURL, getActiveTab, getTabContentWindow, closeTab, getTabs,
michael@0 24 getTabTitle } = require("sdk/tabs/utils");
michael@0 25 const { getMostRecentBrowserWindow, isFocused } = require("sdk/window/utils");
michael@0 26 const { open: openNewWindow, close: closeWindow, focus } = require("sdk/window/helpers");
michael@0 27 const { Loader } = require("sdk/test/loader");
michael@0 28 const { merge } = require("sdk/util/object");
michael@0 29 const { isPrivate } = require("sdk/private-browsing");
michael@0 30
michael@0 31 // General purpose utility functions
michael@0 32
michael@0 33 /**
michael@0 34 * Opens the url given and return a promise, that will be resolved with the
michael@0 35 * content window when the document is ready.
michael@0 36 *
michael@0 37 * I believe this approach could be useful in most of our unit test, that
michael@0 38 * requires to open a tab and need to access to its content.
michael@0 39 */
michael@0 40 function open(url, options) {
michael@0 41 let { promise, resolve } = defer();
michael@0 42
michael@0 43 if (options && typeof(options) === "object") {
michael@0 44 openNewWindow("", {
michael@0 45 features: merge({ toolbar: true }, options)
michael@0 46 }).then(function(chromeWindow) {
michael@0 47 if (isPrivate(chromeWindow) !== !!options.private)
michael@0 48 throw new Error("Window should have Private set to " + !!options.private);
michael@0 49
michael@0 50 let tab = getActiveTab(chromeWindow);
michael@0 51
michael@0 52 tab.linkedBrowser.addEventListener("load", function ready(event) {
michael@0 53 let { document } = getTabContentWindow(tab);
michael@0 54
michael@0 55 if (document.readyState === "complete" && document.URL === url) {
michael@0 56 this.removeEventListener(event.type, ready);
michael@0 57
michael@0 58 if (options.title)
michael@0 59 document.title = options.title;
michael@0 60
michael@0 61 resolve(document.defaultView);
michael@0 62 }
michael@0 63 }, true);
michael@0 64
michael@0 65 setTabURL(tab, url);
michael@0 66 });
michael@0 67
michael@0 68 return promise;
michael@0 69 };
michael@0 70
michael@0 71 tabs.open({
michael@0 72 url: url,
michael@0 73 onReady: function(tab) {
michael@0 74 // Unfortunately there is no way to get a XUL Tab from SDK Tab on Firefox,
michael@0 75 // only on Fennec. We should implement `tabNS` also on Firefox in order
michael@0 76 // to have that.
michael@0 77
michael@0 78 // Here we assuming that the most recent browser window is the one we're
michael@0 79 // doing the test, and the active tab is the one we just opened.
michael@0 80 let window = getTabContentWindow(getActiveTab(getMostRecentBrowserWindow()));
michael@0 81
michael@0 82 resolve(window);
michael@0 83 }
michael@0 84 });
michael@0 85
michael@0 86 return promise;
michael@0 87 };
michael@0 88
michael@0 89 /**
michael@0 90 * Close the Active Tab
michael@0 91 */
michael@0 92 function close(window) {
michael@0 93 let { promise, resolve } = defer();
michael@0 94
michael@0 95 if (window && typeof(window.close) === "function") {
michael@0 96 closeWindow(window).then(function() resolve());
michael@0 97 }
michael@0 98 else {
michael@0 99 // Here we assuming that the most recent browser window is the one we're
michael@0 100 // doing the test, and the active tab is the one we just opened.
michael@0 101 closeTab(getActiveTab(getMostRecentBrowserWindow()));
michael@0 102 resolve();
michael@0 103 }
michael@0 104
michael@0 105 return promise;
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 * Select the first div in the page, adding the range to the selection.
michael@0 132 */
michael@0 133 function selectFirstDiv(window) {
michael@0 134 let div = window.document.querySelector("div");
michael@0 135 let selection = window.getSelection();
michael@0 136 let range = window.document.createRange();
michael@0 137
michael@0 138 if (selection.rangeCount > 0)
michael@0 139 selection.removeAllRanges();
michael@0 140
michael@0 141 range.selectNode(div);
michael@0 142 selection.addRange(range);
michael@0 143
michael@0 144 return window;
michael@0 145 }
michael@0 146
michael@0 147 /**
michael@0 148 * Select all divs in the page, adding the ranges to the selection.
michael@0 149 */
michael@0 150 function selectAllDivs(window) {
michael@0 151 let divs = window.document.getElementsByTagName("div");
michael@0 152 let selection = window.getSelection();
michael@0 153
michael@0 154 if (selection.rangeCount > 0)
michael@0 155 selection.removeAllRanges();
michael@0 156
michael@0 157 for (let i = 0; i < divs.length; i++) {
michael@0 158 let range = window.document.createRange();
michael@0 159
michael@0 160 range.selectNode(divs[i]);
michael@0 161 selection.addRange(range);
michael@0 162 }
michael@0 163
michael@0 164 return window;
michael@0 165 }
michael@0 166
michael@0 167 /**
michael@0 168 * Select the textarea content
michael@0 169 */
michael@0 170 function selectTextarea(window) {
michael@0 171 let selection = window.getSelection();
michael@0 172 let textarea = window.document.querySelector("textarea");
michael@0 173
michael@0 174 if (selection.rangeCount > 0)
michael@0 175 selection.removeAllRanges();
michael@0 176
michael@0 177 textarea.setSelectionRange(0, textarea.value.length);
michael@0 178 textarea.focus();
michael@0 179
michael@0 180 return window;
michael@0 181 }
michael@0 182
michael@0 183 /**
michael@0 184 * Select the content of the first div
michael@0 185 */
michael@0 186 function selectContentFirstDiv(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.selectNodeContents(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 * Dispatch the selection event for the selection listener added by
michael@0 202 * `nsISelectionPrivate.addSelectionListener`
michael@0 203 */
michael@0 204 function dispatchSelectionEvent(window) {
michael@0 205 // We modify the selection in order to dispatch the selection's event, by
michael@0 206 // contract the selection by one character. So if the text selected is "foo"
michael@0 207 // will be "fo".
michael@0 208 window.getSelection().modify("extend", "backward", "character");
michael@0 209
michael@0 210 return window;
michael@0 211 }
michael@0 212
michael@0 213 /**
michael@0 214 * Dispatch the selection event for the selection listener added by
michael@0 215 * `window.onselect` / `window.addEventListener`
michael@0 216 */
michael@0 217 function dispatchOnSelectEvent(window) {
michael@0 218 let { document } = window;
michael@0 219 let textarea = document.querySelector("textarea");
michael@0 220 let event = document.createEvent("UIEvents");
michael@0 221
michael@0 222 event.initUIEvent("select", true, true, window, 1);
michael@0 223
michael@0 224 textarea.dispatchEvent(event);
michael@0 225
michael@0 226 return window;
michael@0 227 }
michael@0 228
michael@0 229 // Test cases
michael@0 230
michael@0 231 exports["test PWPB Selection Listener"] = function(assert, done) {
michael@0 232 let loader = Loader(module);
michael@0 233 let selection = loader.require("sdk/selection");
michael@0 234
michael@0 235 open(URL, {private: true, title: "PWPB Selection Listener"}).
michael@0 236 then(function(window) {
michael@0 237 selection.once("select", function() {
michael@0 238 assert.equal(browserWindows.length, 2, "there should be only two windows open.");
michael@0 239 assert.equal(getTabs().length, 2, "there should be only two tabs open: '" +
michael@0 240 getTabs().map(function(tab) getTabTitle(tab)).join("', '") +
michael@0 241 "'."
michael@0 242 );
michael@0 243
michael@0 244 // window should be focused, but force the focus anyhow.. see bug 841823
michael@0 245 focus(window).then(function() {
michael@0 246 // check state of window
michael@0 247 assert.ok(isFocused(window), "the window is focused");
michael@0 248 assert.ok(isPrivate(window), "the window should be a private window");
michael@0 249
michael@0 250 assert.equal(selection.text, "fo");
michael@0 251
michael@0 252 close(window).
michael@0 253 then(loader.unload).
michael@0 254 then(done).
michael@0 255 then(null, assert.fail);
michael@0 256 });
michael@0 257 });
michael@0 258 return window;
michael@0 259 }).
michael@0 260 then(selectContentFirstDiv).
michael@0 261 then(dispatchSelectionEvent).
michael@0 262 then(null, assert.fail);
michael@0 263 };
michael@0 264
michael@0 265 exports["test PWPB Textarea OnSelect Listener"] = function(assert, done) {
michael@0 266 let loader = Loader(module);
michael@0 267 let selection = loader.require("sdk/selection");
michael@0 268
michael@0 269 open(URL, {private: true, title: "PWPB OnSelect Listener"}).
michael@0 270 then(function(window) {
michael@0 271 selection.once("select", function() {
michael@0 272 assert.equal(browserWindows.length, 2, "there should be only two windows open.");
michael@0 273 assert.equal(getTabs().length, 2, "there should be only two tabs open: '" +
michael@0 274 getTabs().map(function(tab) getTabTitle(tab)).join("', '") +
michael@0 275 "'."
michael@0 276 );
michael@0 277
michael@0 278 // window should be focused, but force the focus anyhow.. see bug 841823
michael@0 279 focus(window).then(function() {
michael@0 280 assert.equal(selection.text, "noodles");
michael@0 281
michael@0 282 close(window).
michael@0 283 then(loader.unload).
michael@0 284 then(done).
michael@0 285 then(null, assert.fail);
michael@0 286 });
michael@0 287 });
michael@0 288 return window;
michael@0 289 }).
michael@0 290 then(selectTextarea).
michael@0 291 then(dispatchOnSelectEvent).
michael@0 292 then(null, assert.fail);
michael@0 293 };
michael@0 294
michael@0 295 exports["test PWPB Single DOM Selection"] = function(assert, done) {
michael@0 296 let loader = Loader(module);
michael@0 297 let selection = loader.require("sdk/selection");
michael@0 298
michael@0 299 open(URL, {private: true, title: "PWPB Single DOM Selection"}).
michael@0 300 then(selectFirstDiv).
michael@0 301 then(focus).then(function() {
michael@0 302 assert.equal(selection.isContiguous, true,
michael@0 303 "selection.isContiguous with single DOM Selection works.");
michael@0 304
michael@0 305 assert.equal(selection.text, "foo",
michael@0 306 "selection.text with single DOM Selection works.");
michael@0 307
michael@0 308 assert.equal(selection.html, "<div>foo</div>",
michael@0 309 "selection.html with single DOM 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(sel.text, "foo",
michael@0 316 "iterable selection.text with single DOM Selection works.");
michael@0 317
michael@0 318 assert.equal(sel.html, "<div>foo</div>",
michael@0 319 "iterable selection.html with single DOM Selection works.");
michael@0 320 }
michael@0 321
michael@0 322 assert.equal(selectionCount, 1,
michael@0 323 "One iterable selection");
michael@0 324 }).then(close).then(loader.unload).then(done).then(null, assert.fail);
michael@0 325 }
michael@0 326
michael@0 327 exports["test PWPB Textarea Selection"] = function(assert, done) {
michael@0 328 let loader = Loader(module);
michael@0 329 let selection = loader.require("sdk/selection");
michael@0 330
michael@0 331 open(URL, {private: true, title: "PWPB Textarea Listener"}).
michael@0 332 then(selectTextarea).
michael@0 333 then(focus).
michael@0 334 then(function() {
michael@0 335
michael@0 336 assert.equal(selection.isContiguous, true,
michael@0 337 "selection.isContiguous with Textarea Selection works.");
michael@0 338
michael@0 339 assert.equal(selection.text, "noodles",
michael@0 340 "selection.text with Textarea Selection works.");
michael@0 341
michael@0 342 assert.strictEqual(selection.html, null,
michael@0 343 "selection.html with Textarea Selection works.");
michael@0 344
michael@0 345 let selectionCount = 0;
michael@0 346 for each (let sel in selection) {
michael@0 347 selectionCount++;
michael@0 348
michael@0 349 assert.equal(sel.text, "noodles",
michael@0 350 "iterable selection.text with Textarea Selection works.");
michael@0 351
michael@0 352 assert.strictEqual(sel.html, null,
michael@0 353 "iterable selection.html with Textarea Selection works.");
michael@0 354 }
michael@0 355
michael@0 356 assert.equal(selectionCount, 1,
michael@0 357 "One iterable selection");
michael@0 358 }).then(close).then(loader.unload).then(done).then(null, assert.fail);
michael@0 359 };
michael@0 360
michael@0 361 exports["test PWPB Set HTML in Multiple DOM Selection"] = function(assert, done) {
michael@0 362 let loader = Loader(module);
michael@0 363 let selection = loader.require("sdk/selection");
michael@0 364
michael@0 365 open(URL, {private: true, title: "PWPB Set HTML in Multiple DOM Selection"}).
michael@0 366 then(selectAllDivs).
michael@0 367 then(focus).
michael@0 368 then(function() {
michael@0 369 let html = "<span>b<b>a</b>r</span>";
michael@0 370
michael@0 371 let expectedText = ["bar", "and"];
michael@0 372 let expectedHTML = [html, "<div>and</div>"];
michael@0 373
michael@0 374 selection.html = html;
michael@0 375
michael@0 376 assert.equal(selection.text, expectedText[0],
michael@0 377 "set selection.text with DOM Selection works.");
michael@0 378
michael@0 379 assert.equal(selection.html, expectedHTML[0],
michael@0 380 "selection.html with DOM Selection works.");
michael@0 381
michael@0 382 let selectionCount = 0;
michael@0 383 for each (let sel in selection) {
michael@0 384
michael@0 385 assert.equal(sel.text, expectedText[selectionCount],
michael@0 386 "iterable selection.text with multiple DOM Selection works.");
michael@0 387
michael@0 388 assert.equal(sel.html, expectedHTML[selectionCount],
michael@0 389 "iterable selection.html with multiple DOM Selection works.");
michael@0 390
michael@0 391 selectionCount++;
michael@0 392 }
michael@0 393
michael@0 394 assert.equal(selectionCount, 2,
michael@0 395 "Two iterable selections");
michael@0 396 }).then(close).then(loader.unload).then(done).then(null, assert.fail);
michael@0 397 };
michael@0 398
michael@0 399 exports["test PWPB Set Text in Textarea Selection"] = function(assert, done) {
michael@0 400 let loader = Loader(module);
michael@0 401 let selection = loader.require("sdk/selection");
michael@0 402
michael@0 403 open(URL, {private: true, title: "test PWPB Set Text in Textarea Selection"}).
michael@0 404 then(selectTextarea).
michael@0 405 then(focus).
michael@0 406 then(function() {
michael@0 407
michael@0 408 let text = "bar";
michael@0 409
michael@0 410 selection.text = text;
michael@0 411
michael@0 412 assert.equal(selection.text, text,
michael@0 413 "set selection.text with Textarea Selection works.");
michael@0 414
michael@0 415 assert.strictEqual(selection.html, null,
michael@0 416 "selection.html with Textarea Selection works.");
michael@0 417
michael@0 418 let selectionCount = 0;
michael@0 419 for each (let sel in selection) {
michael@0 420 selectionCount++;
michael@0 421
michael@0 422 assert.equal(sel.text, text,
michael@0 423 "iterable selection.text with Textarea Selection works.");
michael@0 424
michael@0 425 assert.strictEqual(sel.html, null,
michael@0 426 "iterable selection.html with Textarea Selection works.");
michael@0 427 }
michael@0 428
michael@0 429 assert.equal(selectionCount, 1,
michael@0 430 "One iterable selection");
michael@0 431
michael@0 432 }).then(close).then(loader.unload).then(done).then(null, assert.fail);
michael@0 433 };
michael@0 434
michael@0 435 // If the platform doesn't support the PBPW, we're replacing PBPW tests
michael@0 436 if (!require("sdk/private-browsing/utils").isWindowPBSupported) {
michael@0 437 module.exports = {
michael@0 438 "test PBPW Unsupported": function Unsupported (assert) {
michael@0 439 assert.pass("Private Window Per Browsing is not supported on this platform.");
michael@0 440 }
michael@0 441 }
michael@0 442 }
michael@0 443
michael@0 444 // If the module doesn't support the app we're being run in, require() will
michael@0 445 // throw. In that case, remove all tests above from exports, and add one dummy
michael@0 446 // test that passes.
michael@0 447 try {
michael@0 448 require("sdk/selection");
michael@0 449 }
michael@0 450 catch (err) {
michael@0 451 if (!/^Unsupported Application/.test(err.message))
michael@0 452 throw err;
michael@0 453
michael@0 454 module.exports = {
michael@0 455 "test Unsupported Application": function Unsupported (assert) {
michael@0 456 assert.pass(err.message);
michael@0 457 }
michael@0 458 }
michael@0 459 }

mercurial