content/base/test/browser_state_notifications.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/content/base/test/browser_state_notifications.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,189 @@
     1.4 +/* globals Components: true, Promise: true, gBrowser: true, Test: true,
     1.5 +           info: true, is: true, window: true, waitForExplicitFinish: true,
     1.6 +           finish: true, ok: true*/
     1.7 +
     1.8 +"use strict";
     1.9 +
    1.10 +const { interfaces: Ci, classes: Cc, utils: Cu } = Components;
    1.11 +const { addObserver, removeObserver } = Cc["@mozilla.org/observer-service;1"].
    1.12 +                                          getService(Ci.nsIObserverService);
    1.13 +const { openWindow } = Cc["@mozilla.org/embedcomp/window-watcher;1"].
    1.14 +                         getService(Ci.nsIWindowWatcher);
    1.15 +
    1.16 +const Test = routine => () => {
    1.17 +  waitForExplicitFinish();
    1.18 +  Task.spawn(routine)
    1.19 +      .then(finish, error => {
    1.20 +        ok(false, error);
    1.21 +        finish();
    1.22 +      });
    1.23 +};
    1.24 +
    1.25 +// Returns promise for the observer notification subject for
    1.26 +// the given topic. If `receive("foo")` is called `n` times
    1.27 +// nth promise is resolved on an `nth` "foo" notification.
    1.28 +const receive = (topic, p, syncCallback) => {
    1.29 +  const { promise, resolve, reject } = Promise.defer();
    1.30 +  const { queue } = receive;
    1.31 +  const timeout = () => {
    1.32 +    queue.splice(queue.indexOf(resolve) - 1, 2);
    1.33 +    reject(new Error("Timeout"));
    1.34 +  };
    1.35 +
    1.36 +  const observer = {
    1.37 +    observe: subject => {
    1.38 +      // Browser loads bunch of other documents that we don't care
    1.39 +      // about so we let allow filtering notifications via `p` function.
    1.40 +      if (p && !p(subject)) return;
    1.41 +      // If observer is a first one with a given `topic`
    1.42 +      // in a queue resolve promise and take it off the queue
    1.43 +      // otherwise keep waiting.
    1.44 +      const index = queue.indexOf(topic);
    1.45 +      if (queue.indexOf(resolve) === index + 1) {
    1.46 +        removeObserver(observer, topic);
    1.47 +        clearTimeout(id, reject);
    1.48 +        queue.splice(index, 2);
    1.49 +        // Some tests need to be executed synchronously when the event is fired.
    1.50 +        if (syncCallback) {
    1.51 +          syncCallback(subject);
    1.52 +        }
    1.53 +        resolve(subject);
    1.54 +      }
    1.55 +    }
    1.56 +  };
    1.57 +  const id = setTimeout(timeout, 90000);
    1.58 +  addObserver(observer, topic, false);
    1.59 +  queue.push(topic, resolve);
    1.60 +
    1.61 +  return promise;
    1.62 +};
    1.63 +receive.queue = [];
    1.64 +
    1.65 +const openTab = uri => gBrowser.selectedTab = gBrowser.addTab(uri);
    1.66 +
    1.67 +const sleep = ms => {
    1.68 +  const { promise, resolve } = Promise.defer();
    1.69 +  setTimeout(resolve, ms);
    1.70 +  return promise;
    1.71 +};
    1.72 +
    1.73 +const isData = document => document.URL.startsWith("data:");
    1.74 +
    1.75 +const uri1 = "data:text/html;charset=utf-8,<h1>1</h1>";
    1.76 +// For whatever reason going back on load event doesn't work so timeout it is :(
    1.77 +const uri2 = "data:text/html;charset=utf-8,<h1>2</h1><script>setTimeout(back,100)</script>";
    1.78 +const uri3 = "data:text/html;charset=utf-8,<h1>3</h1>";
    1.79 +
    1.80 +const uri4 = "chrome://browser/content/license.html";
    1.81 +
    1.82 +const test = Test(function*() {
    1.83 +  let documentInteractive = receive("content-document-interactive", isData, d => {
    1.84 +    // This test is executed synchronously when the event is received.
    1.85 +    is(d.readyState, "interactive", "document is interactive");
    1.86 +    is(d.URL, uri1, "document.URL matches tab url");
    1.87 +  });
    1.88 +  let documentLoaded = receive("content-document-loaded", isData);
    1.89 +  let pageShown = receive("content-page-shown", isData);
    1.90 +
    1.91 +  info("open: uri#1");
    1.92 +  const tab1 = openTab(uri1);
    1.93 +  const browser1 = gBrowser.getBrowserForTab(tab1);
    1.94 +
    1.95 +  let interactiveDocument1 = yield documentInteractive;
    1.96 +
    1.97 +  let loadedDocument1 = yield documentLoaded;
    1.98 +  is(loadedDocument1.readyState, "complete", "document is loaded");
    1.99 +  is(interactiveDocument1, loadedDocument1, "interactive document is loaded");
   1.100 +
   1.101 +  let shownPage = yield pageShown;
   1.102 +  is(interactiveDocument1, shownPage, "loaded document is shown");
   1.103 +
   1.104 +  // Wait until history entry is created before loading new uri.
   1.105 +  yield receive("sessionstore-state-write-complete");
   1.106 +
   1.107 +  info("load uri#2");
   1.108 +
   1.109 +  documentInteractive = receive("content-document-interactive", isData, d => {
   1.110 +    // This test is executed synchronously when the event is received.
   1.111 +    is(d.readyState, "interactive", "document is interactive");
   1.112 +    is(d.URL, uri2, "document.URL matches URL loaded");
   1.113 +  });
   1.114 +  documentLoaded = receive("content-document-loaded", isData);
   1.115 +  pageShown = receive("content-page-shown", isData);
   1.116 +  let pageHidden = receive("content-page-hidden", isData);
   1.117 +
   1.118 +  browser1.loadURI(uri2);
   1.119 +
   1.120 +  let hiddenPage = yield pageHidden;
   1.121 +  is(interactiveDocument1, hiddenPage, "loaded document is hidden");
   1.122 +
   1.123 +  let interactiveDocument2 = yield documentInteractive;
   1.124 +
   1.125 +  let loadedDocument2 = yield documentLoaded;
   1.126 +  is(loadedDocument2.readyState, "complete", "document is loaded");
   1.127 +  is(interactiveDocument2, loadedDocument2, "interactive document is loaded");
   1.128 +
   1.129 +  shownPage = yield pageShown;
   1.130 +  is(interactiveDocument2, shownPage, "loaded document is shown");
   1.131 +
   1.132 +  info("go back to uri#1");
   1.133 +
   1.134 +
   1.135 +  documentInteractive = receive("content-document-interactive", isData, d => {
   1.136 +    // This test is executed synchronously when the event is received.
   1.137 +    is(d.readyState, "interactive", "document is interactive");
   1.138 +    is(d.URL, uri3, "document.URL matches URL loaded");
   1.139 +  });
   1.140 +  documentLoaded = receive("content-document-loaded", isData);
   1.141 +  pageShown = receive("content-page-shown", isData);
   1.142 +  pageHidden = receive("content-page-hidden", isData);
   1.143 +
   1.144 +  hiddenPage = yield pageHidden;
   1.145 +  is(interactiveDocument2, hiddenPage, "new document is hidden");
   1.146 +
   1.147 +  shownPage = yield pageShown;
   1.148 +  is(interactiveDocument1, shownPage, "previous document is shown");
   1.149 +
   1.150 +  info("load uri#3");
   1.151 +
   1.152 +  browser1.loadURI(uri3);
   1.153 +
   1.154 +  pageShown = receive("content-page-shown", isData);
   1.155 +
   1.156 +  let interactiveDocument3 = yield documentInteractive;
   1.157 +
   1.158 +  let loadedDocument3 = yield documentLoaded;
   1.159 +  is(loadedDocument3.readyState, "complete", "document is loaded");
   1.160 +  is(interactiveDocument3, loadedDocument3, "interactive document is loaded");
   1.161 +
   1.162 +  shownPage = yield pageShown;
   1.163 +  is(interactiveDocument3, shownPage, "previous document is shown");
   1.164 +
   1.165 +  gBrowser.removeTab(tab1);
   1.166 +
   1.167 +  info("load chrome uri");
   1.168 +
   1.169 +  const tab2 = openTab(uri4);
   1.170 +  documentInteractive = receive("chrome-document-interactive", null, d => {
   1.171 +    // This test is executed synchronously when the event is received.
   1.172 +    is(d.readyState, "interactive", "document is interactive");
   1.173 +    is(d.URL, uri4, "document.URL matches URL loaded");
   1.174 +  });
   1.175 +  documentLoaded = receive("chrome-document-loaded");
   1.176 +  pageShown = receive("chrome-page-shown");
   1.177 +
   1.178 +  const interactiveDocument4 = yield documentInteractive;
   1.179 +
   1.180 +  let loadedDocument4 = yield documentLoaded;
   1.181 +  is(loadedDocument4.readyState, "complete", "document is loaded");
   1.182 +  is(interactiveDocument4, loadedDocument4, "interactive document is loaded");
   1.183 +
   1.184 +  shownPage = yield pageShown;
   1.185 +  is(interactiveDocument4, shownPage, "loaded chrome document is shown");
   1.186 +
   1.187 +  pageHidden = receive("chrome-page-hidden");
   1.188 +  gBrowser.removeTab(tab2);
   1.189 +
   1.190 +  hiddenPage = yield pageHidden;
   1.191 +  is(interactiveDocument4, hiddenPage, "chrome document hidden");
   1.192 +});

mercurial