test-window-utils.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  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 windowUtils = require("sdk/deprecated/window-utils");
  11. const timer = require("sdk/timers");
  12. const { Cc, Ci } = require("chrome");
  13. const { Loader } = require("sdk/test/loader");
  14. const { open, getFrames, getWindowTitle, onFocus, windows } = require('sdk/window/utils');
  15. const { close } = require('sdk/window/helpers');
  16. const { fromIterator: toArray } = require('sdk/util/array');
  17. const WM = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
  18. function makeEmptyWindow(options) {
  19. options = options || {};
  20. var xulNs = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
  21. var blankXul = ('<?xml version="1.0"?>' +
  22. '<?xml-stylesheet href="chrome://global/skin/" ' +
  23. ' type="text/css"?>' +
  24. '<window xmlns="' + xulNs + '" windowtype="test:window">' +
  25. '</window>');
  26. return open("data:application/vnd.mozilla.xul+xml;charset=utf-8," + escape(blankXul), {
  27. features: {
  28. chrome: true,
  29. width: 10,
  30. height: 10
  31. }
  32. });
  33. }
  34. exports['test close on unload'] = function(assert) {
  35. var timesClosed = 0;
  36. var fakeWindow = {
  37. _listeners: [],
  38. addEventListener: function(name, func, bool) {
  39. this._listeners.push(func);
  40. },
  41. removeEventListener: function(name, func, bool) {
  42. var index = this._listeners.indexOf(func);
  43. if (index == -1)
  44. throw new Error("event listener not found");
  45. this._listeners.splice(index, 1);
  46. },
  47. close: function() {
  48. timesClosed++;
  49. this._listeners.forEach(
  50. function(func) {
  51. func({target: fakeWindow.document});
  52. });
  53. },
  54. document: {
  55. get defaultView() { return fakeWindow; }
  56. }
  57. };
  58. let loader = Loader(module);
  59. loader.require("sdk/deprecated/window-utils").closeOnUnload(fakeWindow);
  60. assert.equal(fakeWindow._listeners.length, 1,
  61. "unload listener added on closeOnUnload()");
  62. assert.equal(timesClosed, 0,
  63. "window not closed when registered.");
  64. loader.unload();
  65. assert.equal(timesClosed, 1,
  66. "window closed on module unload.");
  67. assert.equal(fakeWindow._listeners.length, 0,
  68. "unload event listener removed on module unload");
  69. timesClosed = 0;
  70. loader = Loader(module);
  71. loader.require("sdk/deprecated/window-utils").closeOnUnload(fakeWindow);
  72. assert.equal(timesClosed, 0,
  73. "window not closed when registered.");
  74. fakeWindow.close();
  75. assert.equal(timesClosed, 1,
  76. "window closed when close() called.");
  77. assert.equal(fakeWindow._listeners.length, 0,
  78. "unload event listener removed on window close");
  79. loader.unload();
  80. assert.equal(timesClosed, 1,
  81. "window not closed again on module unload.");
  82. };
  83. exports.testWindowTracker = function(assert, done) {
  84. var myWindow;
  85. var finished = false;
  86. var delegate = {
  87. onTrack: function(window) {
  88. if (window == myWindow) {
  89. assert.pass("onTrack() called with our test window");
  90. timer.setTimeout(function() myWindow.close());
  91. }
  92. },
  93. onUntrack: function(window) {
  94. if (window == myWindow) {
  95. assert.pass("onUntrack() called with our test window");
  96. timer.setTimeout(function() {
  97. if (!finished) {
  98. finished = true;
  99. myWindow = null;
  100. wt.unload();
  101. done();
  102. }
  103. else {
  104. assert.fail("finishTest() called multiple times.");
  105. }
  106. });
  107. }
  108. }
  109. };
  110. // test bug 638007 (new is optional), using new
  111. var wt = new windowUtils.WindowTracker(delegate);
  112. myWindow = makeEmptyWindow();
  113. };
  114. exports['test window watcher untracker'] = function(assert, done) {
  115. var myWindow;
  116. var tracks = 0;
  117. var unloadCalled = false;
  118. var delegate = {
  119. onTrack: function(window) {
  120. tracks = tracks + 1;
  121. if (window == myWindow) {
  122. assert.pass("onTrack() called with our test window");
  123. timer.setTimeout(function() {
  124. myWindow.close();
  125. }, 1);
  126. }
  127. },
  128. onUntrack: function(window) {
  129. tracks = tracks - 1;
  130. if (window == myWindow && !unloadCalled) {
  131. unloadCalled = true;
  132. timer.setTimeout(function() {
  133. wt.unload();
  134. }, 1);
  135. }
  136. if (0 > tracks) {
  137. assert.fail("WindowTracker onUntrack was called more times than onTrack..");
  138. }
  139. else if (0 == tracks) {
  140. timer.setTimeout(function() {
  141. myWindow = null;
  142. done();
  143. }, 1);
  144. }
  145. }
  146. };
  147. // test bug 638007 (new is optional), not using new
  148. var wt = windowUtils.WindowTracker(delegate);
  149. myWindow = makeEmptyWindow();
  150. };
  151. // test that _unregWindow calls _unregLoadingWindow
  152. exports['test window watcher unregs 4 loading wins'] = function(assert, done) {
  153. var myWindow;
  154. var finished = false;
  155. let browserWindow = WM.getMostRecentWindow("navigator:browser");
  156. var counter = 0;
  157. var delegate = {
  158. onTrack: function(window) {
  159. var type = window.document.documentElement.getAttribute("windowtype");
  160. if (type == "test:window")
  161. assert.fail("onTrack shouldn't have been executed.");
  162. }
  163. };
  164. var wt = new windowUtils.WindowTracker(delegate);
  165. // make a new window
  166. myWindow = makeEmptyWindow();
  167. // make sure that the window hasn't loaded yet
  168. assert.notEqual(
  169. myWindow.document.readyState,
  170. "complete",
  171. "window hasn't loaded yet.");
  172. // unload WindowTracker
  173. wt.unload();
  174. // make sure that the window still hasn't loaded, which means that the onTrack
  175. // would have been removed successfully assuming that it doesn't execute.
  176. assert.notEqual(
  177. myWindow.document.readyState,
  178. "complete",
  179. "window still hasn't loaded yet.");
  180. // wait for the window to load and then close it. onTrack wouldn't be called
  181. // until the window loads, so we must let it load before closing it to be
  182. // certain that onTrack was removed.
  183. myWindow.addEventListener("load", function() {
  184. // allow all of the load handles to execute before closing
  185. myWindow.setTimeout(function() {
  186. myWindow.addEventListener("unload", function() {
  187. // once the window unloads test is done
  188. done();
  189. }, false);
  190. myWindow.close();
  191. }, 0);
  192. }, false);
  193. }
  194. exports['test window watcher without untracker'] = function(assert, done) {
  195. let myWindow;
  196. let wt = new windowUtils.WindowTracker({
  197. onTrack: function(window) {
  198. if (window == myWindow) {
  199. assert.pass("onTrack() called with our test window");
  200. close(myWindow).then(function() {
  201. wt.unload();
  202. done();
  203. }, assert.fail);
  204. }
  205. }
  206. });
  207. myWindow = makeEmptyWindow();
  208. };
  209. exports['test active window'] = function(assert, done) {
  210. let browserWindow = WM.getMostRecentWindow("navigator:browser");
  211. let continueAfterFocus = function(window) onFocus(window).then(nextTest);
  212. assert.equal(windowUtils.activeBrowserWindow, browserWindow,
  213. "Browser window is the active browser window.");
  214. let testSteps = [
  215. function() {
  216. continueAfterFocus(windowUtils.activeWindow = browserWindow);
  217. },
  218. function() {
  219. assert.equal(windowUtils.activeWindow, browserWindow,
  220. "Correct active window [1]");
  221. nextTest();
  222. },
  223. function() {
  224. assert.equal(windowUtils.activeBrowserWindow, browserWindow,
  225. "Correct active browser window [2]");
  226. continueAfterFocus(windowUtils.activeWindow = browserWindow);
  227. },
  228. function() {
  229. assert.equal(windowUtils.activeWindow, browserWindow,
  230. "Correct active window [3]");
  231. nextTest();
  232. },
  233. function() {
  234. assert.equal(windowUtils.activeBrowserWindow, browserWindow,
  235. "Correct active browser window [4]");
  236. done();
  237. }
  238. ];
  239. function nextTest() {
  240. if (testSteps.length)
  241. testSteps.shift()();
  242. }
  243. nextTest();
  244. };
  245. exports.testWindowIterator = function(assert, done) {
  246. // make a new window
  247. let window = makeEmptyWindow();
  248. // make sure that the window hasn't loaded yet
  249. assert.notEqual(
  250. window.document.readyState,
  251. "complete",
  252. "window hasn't loaded yet.");
  253. // this window should only appear in windowIterator() while its loading
  254. assert.ok(toArray(windowUtils.windowIterator()).indexOf(window) === -1,
  255. "window isn't in windowIterator()");
  256. // Then it should be in windowIterator()
  257. window.addEventListener("load", function onload() {
  258. window.addEventListener("load", onload, false);
  259. assert.ok(toArray(windowUtils.windowIterator()).indexOf(window) !== -1,
  260. "window is now in windowIterator()");
  261. // Wait for the window unload before ending test
  262. close(window).then(done);
  263. }, false);
  264. };
  265. exports.testIgnoreClosingWindow = function(assert, done) {
  266. assert.equal(windows().length, 1, "Only one window open");
  267. // make a new window
  268. let window = makeEmptyWindow();
  269. assert.equal(windows().length, 2, "Two windows open");
  270. window.addEventListener("load", function onload() {
  271. window.addEventListener("load", onload, false);
  272. assert.equal(windows().length, 2, "Two windows open");
  273. // Wait for the window unload before ending test
  274. let checked = false;
  275. close(window).then(function() {
  276. assert.ok(checked, 'the test is finished');
  277. }).then(done, assert.fail)
  278. assert.equal(windows().length, 1, "Only one window open");
  279. checked = true;
  280. }, false);
  281. };
  282. require("test").run(exports);