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

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

mercurial