test-selection.js 27 KB

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