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

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4 "use strict";
michael@0 5
michael@0 6 module.metadata = {
michael@0 7 "engines": {
michael@0 8 "Firefox": "*"
michael@0 9 }
michael@0 10 };
michael@0 11
michael@0 12 const { Cu } = require("chrome");
michael@0 13 const { Frame } = require("sdk/ui/frame");
michael@0 14 const { Toolbar } = require("sdk/ui/toolbar");
michael@0 15 const { Loader } = require("sdk/test/loader");
michael@0 16 const { identify } = require("sdk/ui/id");
michael@0 17 const { setTimeout } = require("sdk/timers");
michael@0 18 const { getMostRecentBrowserWindow, open } = require("sdk/window/utils");
michael@0 19 const { ready, loaded, close } = require("sdk/window/helpers");
michael@0 20 const { defer, all } = require("sdk/core/promise");
michael@0 21 const { send } = require("sdk/event/utils");
michael@0 22 const { object } = require("sdk/util/sequence");
michael@0 23 const { OutputPort } = require("sdk/output/system");
michael@0 24 const { Task } = Cu.import("resource://gre/modules/Task.jsm", {});
michael@0 25 const output = new OutputPort({ id: "toolbar-change" });
michael@0 26
michael@0 27 const wait = (toolbar, event, times) => {
michael@0 28 let { promise, resolve } = defer();
michael@0 29 if (times) {
michael@0 30 let resolveArray = [];
michael@0 31 let counter = 0;
michael@0 32 toolbar.on(event, function onEvent (e) {
michael@0 33 resolveArray.push(e);
michael@0 34 if (++counter === times) {
michael@0 35 toolbar.off(event, onEvent);
michael@0 36 resolve(resolveArray);
michael@0 37 }
michael@0 38 });
michael@0 39 }
michael@0 40 else {
michael@0 41 toolbar.once(event, resolve);
michael@0 42 }
michael@0 43 return promise;
michael@0 44 };
michael@0 45
michael@0 46 const stateEventsFor = frame =>
michael@0 47 [wait(frame, "attach"), wait(frame, "ready"),
michael@0 48 wait(frame, "load"), wait(frame, "detach")];
michael@0 49
michael@0 50
michael@0 51 const isAttached = ({id}, window=getMostRecentBrowserWindow()) =>
michael@0 52 !!window.document.getElementById(id);
michael@0 53
michael@0 54 // Use `Task.spawn` instead of `Task.async` because the returned function does not contain
michael@0 55 // a length for the test harness to determine whether the test should be executed
michael@0 56 exports["test frame API"] = function* (assert) {
michael@0 57 const url = "data:text/html,frame-api";
michael@0 58 assert.throws(() => new Frame(),
michael@0 59 /The `options.url`/,
michael@0 60 "must provide url");
michael@0 61
michael@0 62 assert.throws(() => new Frame({ url: "http://mozilla.org/" }),
michael@0 63 /The `options.url`/,
michael@0 64 "options.url must be local url");
michael@0 65
michael@0 66 assert.throws(() => new Frame({url: url, name: "4you" }),
michael@0 67 /The `option.name` must be a valid/,
michael@0 68 "can only take valid names");
michael@0 69
michael@0 70 const f1 = new Frame({ url: url });
michael@0 71
michael@0 72 assert.ok(f1.id, "frame has an id");
michael@0 73 assert.equal(f1.url, void(0), "frame has no url until it's loaded");
michael@0 74 assert.equal(typeof(f1.postMessage), "function",
michael@0 75 "frames can postMessages");
michael@0 76
michael@0 77 const p1 = wait(f1, "register");
michael@0 78
michael@0 79 assert.throws(() => new Frame({ url: url }),
michael@0 80 /Frame with this id already exists/,
michael@0 81 "can't have two identical frames");
michael@0 82
michael@0 83
michael@0 84 const f2 = new Frame({ name: "frame-2", url: url });
michael@0 85 assert.pass("can create frame with same url but diff name");
michael@0 86 const p2 = wait(f2, "register");
michael@0 87
michael@0 88 yield p1;
michael@0 89 assert.pass("frame#1 was registered");
michael@0 90 assert.equal(f1.url, url, "once registered it get's url");
michael@0 91
michael@0 92 yield p2;
michael@0 93 assert.pass("frame#2 was registered");
michael@0 94 assert.equal(f2.url, url, "once registered it get's url");
michael@0 95
michael@0 96 f1.destroy();
michael@0 97 const f3 = new Frame({ url: url });
michael@0 98 assert.pass("frame identical to destroyed one can be created");
michael@0 99
michael@0 100 yield wait(f3, "register");
michael@0 101 assert.equal(f3.url, url, "url is set");
michael@0 102 f2.destroy();
michael@0 103 f3.destroy();
michael@0 104 };
michael@0 105
michael@0 106 exports["test frame in toolbar"] = function* (assert) {
michael@0 107 const assertEvent = (event, type) => {
michael@0 108 assert.ok(event, "`" + type + "` event was dispatched");
michael@0 109 assert.equal(event.type, type, "event.type is: " + type);
michael@0 110 assert.equal(typeof(event.source), "object",
michael@0 111 "event.source is an object");
michael@0 112 assert.equal(typeof(event.source.postMessage), "function",
michael@0 113 "messages can be posted to event.source");
michael@0 114 };
michael@0 115
michael@0 116
michael@0 117 const url = "data:text/html,toolbar-frame";
michael@0 118 const f1 = new Frame({ url: url });
michael@0 119 const t1 = new Toolbar({
michael@0 120 title: "frame toolbar",
michael@0 121 items: [f1]
michael@0 122 });
michael@0 123
michael@0 124 const w1 = getMostRecentBrowserWindow();
michael@0 125 const [a1, r1, l1] = stateEventsFor(f1);
michael@0 126
michael@0 127 assertEvent((yield a1), "attach");
michael@0 128 assert.ok(isAttached(f1, w1), "frame is in the window#1");
michael@0 129 assertEvent((yield r1), "ready");
michael@0 130 assertEvent((yield l1), "load");
michael@0 131
michael@0 132 const [a2, r2, l2] = stateEventsFor(f1);
michael@0 133 const w2 = open();
michael@0 134
michael@0 135 assertEvent((yield a2), "attach");
michael@0 136 assert.ok(isAttached(f1, w2), "frame is in the window#2");
michael@0 137 assertEvent((yield r2), "ready");
michael@0 138 assertEvent((yield l2), "load");
michael@0 139 assert.pass("frame attached to window#2");
michael@0 140
michael@0 141
michael@0 142 const d1 = wait(f1, "detach");
michael@0 143 yield close(w2);
michael@0 144 assertEvent((yield d1), "detach");
michael@0 145 assert.pass("frame detached when window is closed");
michael@0 146
michael@0 147 t1.destroy();
michael@0 148
michael@0 149 assertEvent((yield wait(f1, "detach")), "detach");
michael@0 150 assert.ok(!isAttached(f1, w1), "frame was removed from window#1");
michael@0 151 assert.pass("toolbar destroy detaches frame");
michael@0 152 };
michael@0 153
michael@0 154
michael@0 155 exports["test host to content messaging"] = function* (assert) {
michael@0 156 const url = "data:text/html,<script>new " + function() {
michael@0 157 window.addEventListener("message", (event) => {
michael@0 158 if (event.data === "ping!")
michael@0 159 event.source.postMessage("pong!", event.origin);
michael@0 160 });
michael@0 161 } + "</script>";
michael@0 162 const f1 = new Frame({ name: "mailbox", url: url });
michael@0 163 const t1 = new Toolbar({ title: "mailbox", items: [f1] });
michael@0 164
michael@0 165 const e1 = yield wait(f1, "ready");
michael@0 166 e1.source.postMessage("ping!", e1.origin);
michael@0 167
michael@0 168 const pong = yield wait(f1, "message");
michael@0 169 assert.equal(pong.data, "pong!", "received ping back");
michael@0 170 t1.destroy();
michael@0 171
michael@0 172 yield wait(t1, "detach");
michael@0 173 };
michael@0 174
michael@0 175
michael@0 176 exports["test content to host messaging"] = function* (assert) {
michael@0 177 const url = "data:text/html,<script>new " + function() {
michael@0 178 window.addEventListener("message", (event) => {
michael@0 179 if (event.data === "pong!")
michael@0 180 event.source.postMessage("end", event.origin);
michael@0 181 });
michael@0 182
michael@0 183 window.parent.postMessage("ping!", "*");
michael@0 184 } + "</script>";
michael@0 185
michael@0 186 const f1 = new Frame({ name: "inbox", url: url });
michael@0 187 const t1 = new Toolbar({ title: "inbox", items: [f1] });
michael@0 188
michael@0 189 const e1 = yield wait(f1, "message");
michael@0 190 assert.equal(e1.data, "ping!", "received ping from content");
michael@0 191
michael@0 192 e1.source.postMessage("pong!", e1.origin);
michael@0 193
michael@0 194 const e2 = yield wait(f1, "message");
michael@0 195 assert.equal(e2.data, "end", "received end message");
michael@0 196
michael@0 197 t1.destroy();
michael@0 198 yield wait(t1, "detach");
michael@0 199
michael@0 200 };
michael@0 201
michael@0 202
michael@0 203 exports["test direct messaging"] = function* (assert) {
michael@0 204 const url = "data:text/html,<script>new " + function() {
michael@0 205 var n = 0;
michael@0 206 window.addEventListener("message", (event) => {
michael@0 207 if (event.data === "inc")
michael@0 208 n = n + 1;
michael@0 209 if (event.data === "print")
michael@0 210 event.source.postMessage({ n: n }, event.origin);
michael@0 211 });
michael@0 212 } + "</script>";
michael@0 213
michael@0 214 const w1 = getMostRecentBrowserWindow();
michael@0 215 const f1 = new Frame({ url: url, name: "mail-cluster" });
michael@0 216 const t1 = new Toolbar({ title: "claster", items: [f1] });
michael@0 217
michael@0 218 yield wait(f1, "ready");
michael@0 219 assert.pass("document loaded in window#1");
michael@0 220
michael@0 221 const w2 = open();
michael@0 222
michael@0 223 yield wait(f1, "ready");
michael@0 224 assert.pass("document loaded in window#2");
michael@0 225
michael@0 226 let messages = wait(f1, "message", 2);
michael@0 227 f1.postMessage("inc", f1.origin);
michael@0 228 f1.postMessage("print", f1.origin);
michael@0 229
michael@0 230 const [e1, e2] = yield messages;
michael@0 231 assert.deepEqual(e1.data, {n: 1}, "received message from window#1");
michael@0 232 assert.deepEqual(e2.data, {n: 1}, "received message from window#2");
michael@0 233
michael@0 234 let message = wait(f1, "message");
michael@0 235 e1.source.postMessage("inc", e1.origin);
michael@0 236 e1.source.postMessage("print", e1.origin);
michael@0 237 const e3 = yield message;
michael@0 238 assert.deepEqual(e3.data, {n: 2}, "state changed in window#1");
michael@0 239
michael@0 240 let message = wait(f1, "message");
michael@0 241 e2.source.postMessage("print", e2.origin);
michael@0 242 yield message;
michael@0 243 assert.deepEqual(e2.data, {n:1}, "window#2 didn't received inc message");
michael@0 244
michael@0 245 yield close(w2);
michael@0 246 t1.destroy();
michael@0 247
michael@0 248 yield wait(t1, "detach");
michael@0 249
michael@0 250 };
michael@0 251
michael@0 252 require("sdk/test").run(exports);

mercurial