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.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 "use strict";
     7 const HTML = "<html>\
     8   <body>\
     9     <div>foo</div>\
    10     <div>and</div>\
    11     <textarea>noodles</textarea>\
    12   </body>\
    13 </html>";
    15 const URL = "data:text/html;charset=utf-8," + encodeURIComponent(HTML);
    17 const FRAME_HTML = "<iframe src='" + URL + "'><iframe>";
    18 const FRAME_URL = "data:text/html;charset=utf-8," + encodeURIComponent(FRAME_HTML);
    20 const { defer } = require("sdk/core/promise");
    21 const { browserWindows } = require("sdk/windows");
    22 const tabs = require("sdk/tabs");
    23 const { setTabURL, getActiveTab, getTabContentWindow, closeTab, getTabs,
    24   getTabTitle } = require("sdk/tabs/utils");
    25 const { getMostRecentBrowserWindow, isFocused } = require("sdk/window/utils");
    26 const { open: openNewWindow, close: closeWindow, focus } = require("sdk/window/helpers");
    27 const { Loader } = require("sdk/test/loader");
    28 const { merge } = require("sdk/util/object");
    29 const { isPrivate } = require("sdk/private-browsing");
    31 // General purpose utility functions
    33 /**
    34  * Opens the url given and return a promise, that will be resolved with the
    35  * content window when the document is ready.
    36  *
    37  * I believe this approach could be useful in most of our unit test, that
    38  * requires to open a tab and need to access to its content.
    39  */
    40 function open(url, options) {
    41   let { promise, resolve } = defer();
    43   if (options && typeof(options) === "object") {
    44     openNewWindow("", {
    45       features: merge({ toolbar: true }, options)
    46     }).then(function(chromeWindow) {
    47       if (isPrivate(chromeWindow) !== !!options.private)
    48         throw new Error("Window should have Private set to " + !!options.private);
    50       let tab = getActiveTab(chromeWindow);
    52       tab.linkedBrowser.addEventListener("load", function ready(event) {
    53         let { document } = getTabContentWindow(tab);
    55         if (document.readyState === "complete" && document.URL === url) {
    56           this.removeEventListener(event.type, ready);
    58           if (options.title)
    59             document.title = options.title;
    61           resolve(document.defaultView);
    62         }
    63       }, true);
    65       setTabURL(tab, url);
    66     });
    68     return promise;
    69   };
    71   tabs.open({
    72     url: url,
    73     onReady: function(tab) {
    74       // Unfortunately there is no way to get a XUL Tab from SDK Tab on Firefox,
    75       // only on Fennec. We should implement `tabNS` also on Firefox in order
    76       // to have that.
    78       // Here we assuming that the most recent browser window is the one we're
    79       // doing the test, and the active tab is the one we just opened.
    80       let window = getTabContentWindow(getActiveTab(getMostRecentBrowserWindow()));
    82       resolve(window);
    83     }
    84   });
    86   return promise;
    87 };
    89 /**
    90  * Close the Active Tab
    91  */
    92 function close(window) {
    93   let { promise, resolve } = defer();
    95   if (window && typeof(window.close) === "function") {
    96     closeWindow(window).then(function() resolve());
    97   }
    98   else {
    99     // Here we assuming that the most recent browser window is the one we're
   100     // doing the test, and the active tab is the one we just opened.
   101     closeTab(getActiveTab(getMostRecentBrowserWindow()));
   102     resolve();
   103   }
   105   return promise;
   106 }
   108 /**
   109  * Reload the window given and return a promise, that will be resolved with the
   110  * content window after a small delay.
   111  */
   112 function reload(window) {
   113   let { promise, resolve } = defer();
   115   // Here we assuming that the most recent browser window is the one we're
   116   // doing the test, and the active tab is the one we just opened.
   117   let tab = tabs.activeTab;
   119   tab.once("ready", function () {
   120     resolve(window);
   121   });
   123   window.location.reload(true);
   125   return promise;
   126 }
   128 // Selection's unit test utility function
   130 /**
   131  * Select the first div in the page, adding the range to the selection.
   132  */
   133 function selectFirstDiv(window) {
   134   let div = window.document.querySelector("div");
   135   let selection = window.getSelection();
   136   let range = window.document.createRange();
   138   if (selection.rangeCount > 0)
   139     selection.removeAllRanges();
   141   range.selectNode(div);
   142   selection.addRange(range);
   144   return window;
   145 }
   147 /**
   148  * Select all divs in the page, adding the ranges to the selection.
   149  */
   150 function selectAllDivs(window) {
   151   let divs = window.document.getElementsByTagName("div");
   152   let selection = window.getSelection();
   154   if (selection.rangeCount > 0)
   155     selection.removeAllRanges();
   157   for (let i = 0; i < divs.length; i++) {
   158     let range = window.document.createRange();
   160     range.selectNode(divs[i]);
   161     selection.addRange(range);
   162   }
   164   return window;
   165 }
   167 /**
   168  * Select the textarea content
   169  */
   170 function selectTextarea(window) {
   171   let selection = window.getSelection();
   172   let textarea = window.document.querySelector("textarea");
   174   if (selection.rangeCount > 0)
   175     selection.removeAllRanges();
   177   textarea.setSelectionRange(0, textarea.value.length);
   178   textarea.focus();
   180   return window;
   181 }
   183 /**
   184  * Select the content of the first div
   185  */
   186 function selectContentFirstDiv(window) {
   187   let div = window.document.querySelector("div");
   188   let selection = window.getSelection();
   189   let range = window.document.createRange();
   191   if (selection.rangeCount > 0)
   192     selection.removeAllRanges();
   194   range.selectNodeContents(div);
   195   selection.addRange(range);
   197   return window;
   198 }
   200 /**
   201  * Dispatch the selection event for the selection listener added by
   202  * `nsISelectionPrivate.addSelectionListener`
   203  */
   204 function dispatchSelectionEvent(window) {
   205   // We modify the selection in order to dispatch the selection's event, by
   206   // contract the selection by one character. So if the text selected is "foo"
   207   // will be "fo".
   208   window.getSelection().modify("extend", "backward", "character");
   210   return window;
   211 }
   213 /**
   214  * Dispatch the selection event for the selection listener added by
   215  * `window.onselect` / `window.addEventListener`
   216  */
   217 function dispatchOnSelectEvent(window) {
   218   let { document } = window;
   219   let textarea = document.querySelector("textarea");
   220   let event = document.createEvent("UIEvents");
   222   event.initUIEvent("select", true, true, window, 1);
   224   textarea.dispatchEvent(event);
   226   return window;
   227 }
   229 // Test cases
   231 exports["test PWPB Selection Listener"] = function(assert, done) {
   232   let loader = Loader(module);
   233   let selection = loader.require("sdk/selection");
   235   open(URL, {private: true, title: "PWPB Selection Listener"}).
   236     then(function(window) {
   237       selection.once("select", function() {
   238         assert.equal(browserWindows.length, 2, "there should be only two windows open.");
   239         assert.equal(getTabs().length, 2, "there should be only two tabs open: '" +
   240                      getTabs().map(function(tab) getTabTitle(tab)).join("', '") +
   241                      "'."
   242         );
   244         // window should be focused, but force the focus anyhow.. see bug 841823
   245         focus(window).then(function() {
   246           // check state of window
   247           assert.ok(isFocused(window), "the window is focused");
   248           assert.ok(isPrivate(window), "the window should be a private window");
   250           assert.equal(selection.text, "fo");
   252           close(window).
   253             then(loader.unload).
   254             then(done).
   255             then(null, assert.fail);
   256         });
   257       });
   258       return window;
   259     }).
   260     then(selectContentFirstDiv).
   261     then(dispatchSelectionEvent).
   262     then(null, assert.fail);
   263 };
   265 exports["test PWPB Textarea OnSelect Listener"] = function(assert, done) {
   266   let loader = Loader(module);
   267   let selection = loader.require("sdk/selection");
   269   open(URL, {private: true, title: "PWPB OnSelect Listener"}).
   270     then(function(window) {
   271       selection.once("select", function() {
   272         assert.equal(browserWindows.length, 2, "there should be only two windows open.");
   273         assert.equal(getTabs().length, 2, "there should be only two tabs open: '" +
   274                      getTabs().map(function(tab) getTabTitle(tab)).join("', '") +
   275                      "'."
   276         );
   278         // window should be focused, but force the focus anyhow.. see bug 841823
   279         focus(window).then(function() {
   280           assert.equal(selection.text, "noodles");
   282           close(window).
   283             then(loader.unload).
   284             then(done).
   285             then(null, assert.fail);
   286         });
   287       });
   288       return window;
   289     }).
   290     then(selectTextarea).
   291     then(dispatchOnSelectEvent).
   292     then(null, assert.fail);
   293 };
   295 exports["test PWPB Single DOM Selection"] = function(assert, done) {
   296   let loader = Loader(module);
   297   let selection = loader.require("sdk/selection");
   299   open(URL, {private: true, title: "PWPB Single DOM Selection"}).
   300     then(selectFirstDiv).
   301     then(focus).then(function() {
   302       assert.equal(selection.isContiguous, true,
   303         "selection.isContiguous with single DOM Selection works.");
   305       assert.equal(selection.text, "foo",
   306         "selection.text with single DOM Selection works.");
   308       assert.equal(selection.html, "<div>foo</div>",
   309         "selection.html with single DOM Selection works.");
   311       let selectionCount = 0;
   312       for each (let sel in selection) {
   313         selectionCount++;
   315         assert.equal(sel.text, "foo",
   316           "iterable selection.text with single DOM Selection works.");
   318         assert.equal(sel.html, "<div>foo</div>",
   319           "iterable selection.html with single DOM Selection works.");
   320       }
   322       assert.equal(selectionCount, 1,
   323         "One iterable selection");
   324     }).then(close).then(loader.unload).then(done).then(null, assert.fail);
   325 }
   327 exports["test PWPB Textarea Selection"] = function(assert, done) {
   328   let loader = Loader(module);
   329   let selection = loader.require("sdk/selection");
   331   open(URL, {private: true, title: "PWPB Textarea Listener"}).
   332     then(selectTextarea).
   333     then(focus).
   334     then(function() {
   336       assert.equal(selection.isContiguous, true,
   337         "selection.isContiguous with Textarea Selection works.");
   339       assert.equal(selection.text, "noodles",
   340         "selection.text with Textarea Selection works.");
   342       assert.strictEqual(selection.html, null,
   343         "selection.html with Textarea Selection works.");
   345       let selectionCount = 0;
   346       for each (let sel in selection) {
   347         selectionCount++;
   349         assert.equal(sel.text, "noodles",
   350           "iterable selection.text with Textarea Selection works.");
   352         assert.strictEqual(sel.html, null,
   353           "iterable selection.html with Textarea Selection works.");
   354       }
   356       assert.equal(selectionCount, 1,
   357         "One iterable selection");
   358     }).then(close).then(loader.unload).then(done).then(null, assert.fail);
   359 };
   361 exports["test PWPB Set HTML in Multiple DOM Selection"] = function(assert, done) {
   362   let loader = Loader(module);
   363   let selection = loader.require("sdk/selection");
   365   open(URL, {private: true, title: "PWPB Set HTML in Multiple DOM Selection"}).
   366     then(selectAllDivs).
   367     then(focus).
   368     then(function() {
   369       let html = "<span>b<b>a</b>r</span>";
   371       let expectedText = ["bar", "and"];
   372       let expectedHTML = [html, "<div>and</div>"];
   374       selection.html = html;
   376       assert.equal(selection.text, expectedText[0],
   377         "set selection.text with DOM Selection works.");
   379       assert.equal(selection.html, expectedHTML[0],
   380         "selection.html with DOM Selection works.");
   382       let selectionCount = 0;
   383       for each (let sel in selection) {
   385         assert.equal(sel.text, expectedText[selectionCount],
   386           "iterable selection.text with multiple DOM Selection works.");
   388         assert.equal(sel.html, expectedHTML[selectionCount],
   389           "iterable selection.html with multiple DOM Selection works.");
   391         selectionCount++;
   392       }
   394       assert.equal(selectionCount, 2,
   395         "Two iterable selections");
   396     }).then(close).then(loader.unload).then(done).then(null, assert.fail);
   397 };
   399 exports["test PWPB Set Text in Textarea Selection"] = function(assert, done) {
   400   let loader = Loader(module);
   401   let selection = loader.require("sdk/selection");
   403   open(URL, {private: true, title: "test PWPB Set Text in Textarea Selection"}).
   404     then(selectTextarea).
   405     then(focus).
   406     then(function() {
   408       let text = "bar";
   410       selection.text = text;
   412       assert.equal(selection.text, text,
   413         "set selection.text with Textarea Selection works.");
   415       assert.strictEqual(selection.html, null,
   416         "selection.html with Textarea Selection works.");
   418       let selectionCount = 0;
   419       for each (let sel in selection) {
   420         selectionCount++;
   422         assert.equal(sel.text, text,
   423           "iterable selection.text with Textarea Selection works.");
   425         assert.strictEqual(sel.html, null,
   426           "iterable selection.html with Textarea Selection works.");
   427       }
   429       assert.equal(selectionCount, 1,
   430         "One iterable selection");
   432     }).then(close).then(loader.unload).then(done).then(null, assert.fail);
   433 };
   435 // If the platform doesn't support the PBPW, we're replacing PBPW tests
   436 if (!require("sdk/private-browsing/utils").isWindowPBSupported) {
   437   module.exports = {
   438     "test PBPW Unsupported": function Unsupported (assert) {
   439       assert.pass("Private Window Per Browsing is not supported on this platform.");
   440     }
   441   }
   442 }
   444 // If the module doesn't support the app we're being run in, require() will
   445 // throw.  In that case, remove all tests above from exports, and add one dummy
   446 // test that passes.
   447 try {
   448   require("sdk/selection");
   449 }
   450 catch (err) {
   451   if (!/^Unsupported Application/.test(err.message))
   452     throw err;
   454   module.exports = {
   455     "test Unsupported Application": function Unsupported (assert) {
   456       assert.pass(err.message);
   457     }
   458   }
   459 }

mercurial