addon-sdk/source/test/test-ui-frame.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/addon-sdk/source/test/test-ui-frame.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,252 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +"use strict";
     1.8 +
     1.9 +module.metadata = {
    1.10 +  "engines": {
    1.11 +    "Firefox": "*"
    1.12 +  }
    1.13 +};
    1.14 +
    1.15 +const { Cu } = require("chrome");
    1.16 +const { Frame } = require("sdk/ui/frame");
    1.17 +const { Toolbar } = require("sdk/ui/toolbar");
    1.18 +const { Loader } = require("sdk/test/loader");
    1.19 +const { identify } = require("sdk/ui/id");
    1.20 +const { setTimeout } = require("sdk/timers");
    1.21 +const { getMostRecentBrowserWindow, open } = require("sdk/window/utils");
    1.22 +const { ready, loaded, close } = require("sdk/window/helpers");
    1.23 +const { defer, all } = require("sdk/core/promise");
    1.24 +const { send } = require("sdk/event/utils");
    1.25 +const { object } = require("sdk/util/sequence");
    1.26 +const { OutputPort } = require("sdk/output/system");
    1.27 +const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
    1.28 +const output = new OutputPort({ id: "toolbar-change" });
    1.29 +
    1.30 +const wait = (toolbar, event, times) => {
    1.31 +  let { promise, resolve } = defer();
    1.32 +  if (times) {
    1.33 +    let resolveArray = [];
    1.34 +    let counter = 0;
    1.35 +    toolbar.on(event, function onEvent (e) {
    1.36 +      resolveArray.push(e);
    1.37 +      if (++counter === times) {
    1.38 +        toolbar.off(event, onEvent);
    1.39 +        resolve(resolveArray);
    1.40 +      }
    1.41 +    });
    1.42 +  }
    1.43 +  else {
    1.44 +    toolbar.once(event, resolve);
    1.45 +  }
    1.46 +  return promise;
    1.47 +};
    1.48 +
    1.49 +const stateEventsFor = frame =>
    1.50 +  [wait(frame, "attach"), wait(frame, "ready"),
    1.51 +   wait(frame, "load"), wait(frame, "detach")];
    1.52 +
    1.53 +
    1.54 +const isAttached = ({id}, window=getMostRecentBrowserWindow()) =>
    1.55 +  !!window.document.getElementById(id);
    1.56 +
    1.57 +// Use `Task.spawn` instead of `Task.async` because the returned function does not contain
    1.58 +// a length for the test harness to determine whether the test should be executed
    1.59 +exports["test frame API"] = function* (assert) {
    1.60 +  const url = "data:text/html,frame-api";
    1.61 +  assert.throws(() => new Frame(),
    1.62 +                /The `options.url`/,
    1.63 +                "must provide url");
    1.64 +
    1.65 +  assert.throws(() => new Frame({ url: "http://mozilla.org/" }),
    1.66 +                /The `options.url`/,
    1.67 +                "options.url must be local url");
    1.68 +
    1.69 +  assert.throws(() => new Frame({url: url, name: "4you" }),
    1.70 +                /The `option.name` must be a valid/,
    1.71 +                "can only take valid names");
    1.72 +
    1.73 +  const f1 = new Frame({ url: url });
    1.74 +
    1.75 +  assert.ok(f1.id, "frame has an id");
    1.76 +  assert.equal(f1.url, void(0), "frame has no url until it's loaded");
    1.77 +  assert.equal(typeof(f1.postMessage), "function",
    1.78 +               "frames can postMessages");
    1.79 +
    1.80 +  const p1 = wait(f1, "register");
    1.81 +
    1.82 +  assert.throws(() => new Frame({ url: url }),
    1.83 +                /Frame with this id already exists/,
    1.84 +                "can't have two identical frames");
    1.85 +
    1.86 +
    1.87 +  const f2 = new Frame({ name: "frame-2", url: url });
    1.88 +  assert.pass("can create frame with same url but diff name");
    1.89 +  const p2 = wait(f2, "register");
    1.90 +
    1.91 +  yield p1;
    1.92 +  assert.pass("frame#1 was registered");
    1.93 +  assert.equal(f1.url, url, "once registered it get's url");
    1.94 +
    1.95 +  yield p2;
    1.96 +  assert.pass("frame#2 was registered");
    1.97 +  assert.equal(f2.url, url, "once registered it get's url");
    1.98 +
    1.99 +  f1.destroy();
   1.100 +  const f3 = new Frame({ url: url });
   1.101 +  assert.pass("frame identical to destroyed one can be created");
   1.102 +
   1.103 +  yield wait(f3, "register");
   1.104 +  assert.equal(f3.url, url, "url is set");
   1.105 +  f2.destroy();
   1.106 +  f3.destroy();
   1.107 +};
   1.108 +
   1.109 +exports["test frame in toolbar"] = function* (assert) {
   1.110 +  const assertEvent = (event, type) => {
   1.111 +    assert.ok(event, "`" + type + "` event was dispatched");
   1.112 +    assert.equal(event.type, type, "event.type is: " + type);
   1.113 +    assert.equal(typeof(event.source), "object",
   1.114 +                 "event.source is an object");
   1.115 +    assert.equal(typeof(event.source.postMessage), "function",
   1.116 +                 "messages can be posted to event.source");
   1.117 +  };
   1.118 +
   1.119 +
   1.120 +  const url = "data:text/html,toolbar-frame";
   1.121 +  const f1 = new Frame({ url: url });
   1.122 +  const t1 = new Toolbar({
   1.123 +    title: "frame toolbar",
   1.124 +    items: [f1]
   1.125 +  });
   1.126 +
   1.127 +  const w1 = getMostRecentBrowserWindow();
   1.128 +  const [a1, r1, l1] = stateEventsFor(f1);
   1.129 +
   1.130 +  assertEvent((yield a1), "attach");
   1.131 +  assert.ok(isAttached(f1, w1), "frame is in the window#1");
   1.132 +  assertEvent((yield r1), "ready");
   1.133 +  assertEvent((yield l1), "load");
   1.134 +
   1.135 +  const [a2, r2, l2] = stateEventsFor(f1);
   1.136 +  const w2 = open();
   1.137 +
   1.138 +  assertEvent((yield a2), "attach");
   1.139 +  assert.ok(isAttached(f1, w2), "frame is in the window#2");
   1.140 +  assertEvent((yield r2), "ready");
   1.141 +  assertEvent((yield l2), "load");
   1.142 +  assert.pass("frame attached to window#2");
   1.143 +
   1.144 +
   1.145 +  const d1 = wait(f1, "detach");
   1.146 +  yield close(w2);
   1.147 +  assertEvent((yield d1), "detach");
   1.148 +  assert.pass("frame detached when window is closed");
   1.149 +
   1.150 +  t1.destroy();
   1.151 +
   1.152 +  assertEvent((yield wait(f1, "detach")), "detach");
   1.153 +  assert.ok(!isAttached(f1, w1), "frame was removed from window#1");
   1.154 +  assert.pass("toolbar destroy detaches frame");
   1.155 +};
   1.156 +
   1.157 +
   1.158 +exports["test host to content messaging"] = function* (assert) {
   1.159 +  const url = "data:text/html,<script>new " + function() {
   1.160 +    window.addEventListener("message", (event) => {
   1.161 +      if (event.data === "ping!")
   1.162 +        event.source.postMessage("pong!", event.origin);
   1.163 +    });
   1.164 +  } + "</script>";
   1.165 +  const f1 = new Frame({ name: "mailbox", url: url });
   1.166 +  const t1 = new Toolbar({ title: "mailbox", items: [f1] });
   1.167 +
   1.168 +  const e1 = yield wait(f1, "ready");
   1.169 +  e1.source.postMessage("ping!", e1.origin);
   1.170 +
   1.171 +  const pong = yield wait(f1, "message");
   1.172 +  assert.equal(pong.data, "pong!", "received ping back");
   1.173 +  t1.destroy();
   1.174 +
   1.175 +  yield wait(t1, "detach");
   1.176 +};
   1.177 +
   1.178 +
   1.179 +exports["test content to host messaging"] = function* (assert) {
   1.180 +  const url = "data:text/html,<script>new " + function() {
   1.181 +    window.addEventListener("message", (event) => {
   1.182 +      if (event.data === "pong!")
   1.183 +        event.source.postMessage("end", event.origin);
   1.184 +    });
   1.185 +
   1.186 +    window.parent.postMessage("ping!", "*");
   1.187 +  } + "</script>";
   1.188 +
   1.189 +  const f1 = new Frame({ name: "inbox", url: url });
   1.190 +  const t1 = new Toolbar({ title: "inbox", items: [f1] });
   1.191 +
   1.192 +  const e1 = yield wait(f1, "message");
   1.193 +  assert.equal(e1.data, "ping!", "received ping from content");
   1.194 +
   1.195 +  e1.source.postMessage("pong!", e1.origin);
   1.196 +
   1.197 +  const e2 = yield wait(f1, "message");
   1.198 +  assert.equal(e2.data, "end", "received end message");
   1.199 +
   1.200 +  t1.destroy();
   1.201 +  yield wait(t1, "detach");
   1.202 +
   1.203 +};
   1.204 +
   1.205 +
   1.206 +exports["test direct messaging"] = function* (assert) {
   1.207 +  const url = "data:text/html,<script>new " + function() {
   1.208 +    var n = 0;
   1.209 +    window.addEventListener("message", (event) => {
   1.210 +      if (event.data === "inc")
   1.211 +        n = n + 1;
   1.212 +      if (event.data === "print")
   1.213 +        event.source.postMessage({ n: n }, event.origin);
   1.214 +    });
   1.215 +  } + "</script>";
   1.216 +
   1.217 +  const w1 = getMostRecentBrowserWindow();
   1.218 +  const f1 = new Frame({ url: url, name: "mail-cluster" });
   1.219 +  const t1 = new Toolbar({ title: "claster", items: [f1] });
   1.220 +
   1.221 +  yield wait(f1, "ready");
   1.222 +  assert.pass("document loaded in window#1");
   1.223 +
   1.224 +  const w2 = open();
   1.225 +
   1.226 +  yield wait(f1, "ready");
   1.227 +  assert.pass("document loaded in window#2");
   1.228 +
   1.229 +  let messages = wait(f1, "message", 2);
   1.230 +  f1.postMessage("inc", f1.origin);
   1.231 +  f1.postMessage("print", f1.origin);
   1.232 +
   1.233 +  const [e1, e2] = yield messages;
   1.234 +  assert.deepEqual(e1.data, {n: 1}, "received message from window#1");
   1.235 +  assert.deepEqual(e2.data, {n: 1}, "received message from window#2");
   1.236 +
   1.237 +  let message = wait(f1, "message");
   1.238 +  e1.source.postMessage("inc", e1.origin);
   1.239 +  e1.source.postMessage("print", e1.origin);
   1.240 +  const e3 = yield message;
   1.241 +  assert.deepEqual(e3.data, {n: 2}, "state changed in window#1");
   1.242 +
   1.243 +  let message = wait(f1, "message");
   1.244 +  e2.source.postMessage("print", e2.origin);
   1.245 +  yield message;
   1.246 +  assert.deepEqual(e2.data, {n:1}, "window#2 didn't received inc message");
   1.247 +
   1.248 +  yield close(w2);
   1.249 +  t1.destroy();
   1.250 +
   1.251 +  yield wait(t1, "detach");
   1.252 +
   1.253 +};
   1.254 +
   1.255 +require("sdk/test").run(exports);

mercurial