1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/addon-sdk/source/test/test-ui-toolbar.js Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,477 @@ 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 { Toolbar } = require("sdk/ui/toolbar"); 1.16 +const { Loader } = require("sdk/test/loader"); 1.17 +const { identify } = require("sdk/ui/id"); 1.18 +const { getMostRecentBrowserWindow, open, getOuterId } = require("sdk/window/utils"); 1.19 +const { ready, close } = require("sdk/window/helpers"); 1.20 +const { defer } = require("sdk/core/promise"); 1.21 +const { send, stop, Reactor } = require("sdk/event/utils"); 1.22 +const { object } = require("sdk/util/sequence"); 1.23 +const { CustomizationInput } = require("sdk/input/customizable-ui"); 1.24 +const { OutputPort } = require("sdk/output/system"); 1.25 +const output = new OutputPort({ id: "toolbar-change" }); 1.26 + 1.27 +const wait = (toolbar, event) => { 1.28 + let { promise, resolve } = defer(); 1.29 + toolbar.once(event, resolve); 1.30 + return promise; 1.31 +}; 1.32 + 1.33 +const show = ({id}) => send(output, object([id, {collapsed: false}])); 1.34 +const hide = ({id}) => send(output, object([id, {collapsed: true}])); 1.35 +const retitle = ({id}, title) => send(output, object([id, {title: title}])); 1.36 + 1.37 +const isAttached = ({id}, window=getMostRecentBrowserWindow()) => 1.38 + !!window.document.getElementById(id); 1.39 + 1.40 +const isCollapsed = ({id}, window=getMostRecentBrowserWindow()) => 1.41 + window.document.getElementById(id).getAttribute("collapsed") === "true"; 1.42 + 1.43 +const closeViaButton = ({id}, window=getMostRecentBrowserWindow()) => 1.44 + window.document.getElementById("close-" + id).click(); 1.45 + 1.46 +const readTitle = ({id}, window=getMostRecentBrowserWindow()) => 1.47 + window.document.getElementById(id).getAttribute("toolbarname"); 1.48 + 1.49 +exports["test toolbar API"] = function*(assert) { 1.50 + assert.throws(() => new Toolbar(), 1.51 + /The `option.title`/, 1.52 + "toolbar requires title"); 1.53 + 1.54 + assert.throws(() => new Toolbar({ hidden: false }), 1.55 + /The `option.title`/, 1.56 + "toolbar requires title"); 1.57 + 1.58 + const t1 = new Toolbar({ title: "foo" }); 1.59 + 1.60 + assert.throws(() => new Toolbar({ title: "foo" }), 1.61 + /already exists/, 1.62 + "can't create identical toolbars"); 1.63 + 1.64 + assert.ok(t1.id, "toolbar has an id"); 1.65 + assert.equal(t1.id, identify(t1), "identify returns toolbar id"); 1.66 + assert.deepEqual(t1.items, [], "toolbar items are empty"); 1.67 + assert.equal(t1.title, void(0), "title is void until attached"); 1.68 + assert.equal(t1.hidden, void(0), "hidden is void until attached"); 1.69 + 1.70 + yield wait(t1, "attach"); 1.71 + 1.72 + assert.equal(t1.title, "foo", "title is set after attach"); 1.73 + assert.equal(t1.hidden, false, "by default toolbar isn't hidden"); 1.74 + 1.75 + assert.throws(() => new Toolbar({ title: "foo" }), 1.76 + /already exists/, 1.77 + "still can't create identical toolbar"); 1.78 + 1.79 + 1.80 + const t2 = new Toolbar({ title: "bar", hidden: true }); 1.81 + assert.pass("can create different toolbar though"); 1.82 + 1.83 + assert.ok(t2.id, "toolbar has an id"); 1.84 + assert.equal(t2.id, identify(t2), "identify returns toolbar id"); 1.85 + assert.notEqual(t2.id, t1.id, "each toolbar has unique id"); 1.86 + 1.87 + yield wait(t2, "attach"); 1.88 + 1.89 + assert.equal(t2.title, "bar", "title is set after attach"); 1.90 + assert.equal(t2.hidden, true, "toolbar is hidden as specified"); 1.91 + 1.92 + t2.destroy(); 1.93 + t1.destroy(); 1.94 + 1.95 + yield wait(t1, "detach"); 1.96 + 1.97 + assert.equal(t1.title, void(0), "title is voided after detach"); 1.98 + assert.equal(t1.hidden, void(0), "hidden is void fater detach"); 1.99 + 1.100 + 1.101 + const t3 = new Toolbar({ title: "foo" }); 1.102 + assert.pass("Can create toolbar after identical was detached"); 1.103 + 1.104 + assert.equal(t3.id, t1.id, "toolbar has a same id"); 1.105 + assert.equal(t3.id, identify(t3), "identify returns toolbar.id"); 1.106 + assert.equal(t3.title, void(0), "title is void before attach"); 1.107 + assert.equal(t3.hidden, void(0), "hidden is void before attach"); 1.108 + 1.109 + yield wait(t3, "attach"); 1.110 + 1.111 + assert.equal(t3.title, "foo", "title is set"); 1.112 + assert.equal(t3.hidden, false, "toolbar is hidden"); 1.113 + 1.114 + t3.destroy(); 1.115 + 1.116 + yield wait(t3, "detach"); 1.117 +}; 1.118 + 1.119 +exports["test show / hide toolbar"] = function*(assert) { 1.120 + const t1 = new Toolbar({ title: "foo" }); 1.121 + 1.122 + yield wait(t1, "attach"); 1.123 + 1.124 + assert.equal(t1.title, "foo", "title is set after attach"); 1.125 + assert.equal(t1.hidden, false, "by default toolbar isn't hidden"); 1.126 + assert.ok(isAttached(t1), "toolbar was actually attarched"); 1.127 + assert.ok(!isCollapsed(t1), "toolbar isn't collapsed"); 1.128 + 1.129 + hide(t1); 1.130 + assert.equal(t1.hidden, false, "not hidden yet"); 1.131 + 1.132 + yield wait(t1, "hide"); 1.133 + assert.equal(t1.hidden, true, "toolbar got hidden"); 1.134 + assert.ok(isCollapsed(t1), "toolbar is collapsed"); 1.135 + 1.136 + show(t1); 1.137 + 1.138 + yield wait(t1, "show"); 1.139 + assert.equal(t1.hidden, false, "toolbar got shown"); 1.140 + assert.ok(!isCollapsed(t1), "toolbar isn't collapsed"); 1.141 + 1.142 + t1.destroy(); 1.143 + yield wait(t1, "detach"); 1.144 + assert.ok(!isAttached(t1), "toolbar is no longer attached"); 1.145 +}; 1.146 + 1.147 +exports["test multiple windows & toolbars"] = function*(assert) { 1.148 + const w1 = getMostRecentBrowserWindow(); 1.149 + const t1 = new Toolbar({ title: "multi window" }); 1.150 + 1.151 + yield wait(t1, "attach"); 1.152 + 1.153 + assert.equal(t1.title, "multi window", "title is set after attach"); 1.154 + assert.equal(t1.hidden, false, "by default toolbar isn't hidden"); 1.155 + assert.ok(isAttached(t1, w1), "toolbar was actually attarched"); 1.156 + assert.ok(!isCollapsed(t1, w1), "toolbar isn't collapsed"); 1.157 + 1.158 + const w2 = open(); 1.159 + yield ready(w2); 1.160 + 1.161 + assert.ok(isAttached(t1, w2), "toolbar was attached to second window"); 1.162 + assert.ok(!isCollapsed(t1, w2), "toolbar isn't collabsed"); 1.163 + 1.164 + hide(t1); 1.165 + yield wait(t1, "hide"); 1.166 + 1.167 + assert.ok(isCollapsed(t1, w1) && isCollapsed(t1, w2), 1.168 + "toolbar is collabsed"); 1.169 + 1.170 + 1.171 + const w3 = open(); 1.172 + yield ready(w3); 1.173 + 1.174 + assert.ok(isAttached(t1, w1) && isAttached(t1, w2) && isAttached(t1, w3), 1.175 + "toolbar is attached to all windows"); 1.176 + assert.ok(isCollapsed(t1, w3) && isCollapsed(t1, w3) && isCollapsed(t1, w3), 1.177 + "toolbar still collapsed in all windows"); 1.178 + 1.179 + 1.180 + const t2 = new Toolbar({ title: "multi hidden", hidden: true }); 1.181 + 1.182 + yield wait(t2, "attach"); 1.183 + 1.184 + assert.equal(t2.title, "multi hidden", "title is set after attach"); 1.185 + assert.equal(t2.hidden, true, "isn't hidden as specified"); 1.186 + 1.187 + assert.ok(isAttached(t1, w1) && isAttached(t1, w2) && isAttached(t1, w3), 1.188 + "toolbar#1 is still attached"); 1.189 + assert.ok(isAttached(t2, w1) && isAttached(t2, w2) && isAttached(t2, w3), 1.190 + "toolbar#2 was attached to all windows"); 1.191 + 1.192 + assert.ok(isCollapsed(t1, w1) && isCollapsed(t1, w2) && isCollapsed(t1, w3), 1.193 + "toolbar#1 is still collapsed"); 1.194 + 1.195 + assert.ok(isCollapsed(t2, w1) && isCollapsed(t2, w2) && isCollapsed(t2, w3), 1.196 + "toolbar#2 is collapsed"); 1.197 + 1.198 + t1.destroy(); 1.199 + yield wait(t1, "detach"); 1.200 + 1.201 + assert.ok(!isAttached(t1, w1) && !isAttached(t1, w2) && !isAttached(t1, w3), 1.202 + "toolbar#1 was detached from all windows"); 1.203 + assert.ok(isAttached(t2, w1) && isAttached(t2, w2) && isAttached(t2, w3), 1.204 + "toolbar#2 is still attached to all windows"); 1.205 + 1.206 + yield close(w2); 1.207 + 1.208 + assert.ok(isAttached(t2, w1) && isAttached(t2, w3), 1.209 + "toolbar#2 is still attached to remaining windows"); 1.210 + assert.ok(isCollapsed(t2, w1) && isCollapsed(t2, w3), 1.211 + "toolbar#2 is still collapsed"); 1.212 + 1.213 + show(t2); 1.214 + yield wait(t2, "show"); 1.215 + 1.216 + assert.ok(!isCollapsed(t2, w1) && !isCollapsed(t2, w3), 1.217 + "toolbar#2 is not collapsed"); 1.218 + 1.219 + yield close(w3); 1.220 + 1.221 + assert.ok(isAttached(t2, w1), "still attached to last window"); 1.222 + assert.ok(!isCollapsed(t2, w1), "still isn't collapsed"); 1.223 + 1.224 + t2.destroy(); 1.225 + yield wait(t2, "detach"); 1.226 + 1.227 + assert.ok(!isAttached(t2, w1), "toolbar was removed"); 1.228 +}; 1.229 + 1.230 +exports["test toolbar persistence"] = function*(assert) { 1.231 + const t1 = new Toolbar({ title: "per sist ence" }); 1.232 + 1.233 + yield wait(t1, "attach"); 1.234 + 1.235 + assert.equal(t1.hidden, false, "toolbar is visible"); 1.236 + 1.237 + hide(t1); 1.238 + yield wait(t1, "hide"); 1.239 + 1.240 + assert.equal(t1.hidden, true, "toolbar is hidden"); 1.241 + assert.ok(isCollapsed(t1), "toolbar is collapsed"); 1.242 + 1.243 + t1.destroy(); 1.244 + 1.245 + yield wait(t1, "detach"); 1.246 + 1.247 + const t2 = new Toolbar({ title: "per sist ence" }); 1.248 + 1.249 + yield wait(t2, "attach"); 1.250 + 1.251 + assert.equal(t2.hidden, true, "toolbar persisted state"); 1.252 + assert.ok(isCollapsed(t2), "toolbar is collapsed"); 1.253 + 1.254 + show(t2); 1.255 + t2.destroy(); 1.256 + 1.257 + yield wait(t2, "detach"); 1.258 + 1.259 + const t3 = new Toolbar({ title: "per sist ence", hidden: true }); 1.260 + 1.261 + yield wait(t3, "attach"); 1.262 + 1.263 + assert.equal(t3.hidden, false, "toolbar persisted state & ignored option"); 1.264 + assert.ok(!isCollapsed(t3), "toolbar isn1t collapsed"); 1.265 + 1.266 + t3.destroy(); 1.267 + 1.268 + yield wait(t3, "detach"); 1.269 +}; 1.270 + 1.271 + 1.272 +exports["test toolbar unload"] = function*(assert) { 1.273 + // We override add-on id, otherwise two instances of Toolbar host (view.js) 1.274 + // handling same updates, cause message port is bound to add-on id. 1.275 + const loader = Loader(module, null, null, {id: "toolbar-unload-addon"}); 1.276 + const { Toolbar } = loader.require("sdk/ui/toolbar"); 1.277 + 1.278 + const w1 = getMostRecentBrowserWindow(); 1.279 + const w2 = open(); 1.280 + 1.281 + yield ready(w2); 1.282 + 1.283 + const t1 = new Toolbar({ title: "unload" }); 1.284 + 1.285 + yield wait(t1, "attach"); 1.286 + 1.287 + assert.ok(isAttached(t1, w1) && isAttached(t1, w2), 1.288 + "attached to both windows"); 1.289 + 1.290 + 1.291 + loader.unload(); 1.292 + 1.293 + 1.294 + assert.ok(!isAttached(t1, w1) && !isAttached(t1, w2), 1.295 + "detached from both windows on unload"); 1.296 + 1.297 + yield close(w2); 1.298 +}; 1.299 + 1.300 +exports["test toolbar close button"] = function*(assert) { 1.301 + const t1 = new Toolbar({ title: "close with button" }); 1.302 + 1.303 + yield wait(t1, "attach"); 1.304 + const w1 = getMostRecentBrowserWindow(); 1.305 + const w2 = open(); 1.306 + 1.307 + yield ready(w2); 1.308 + 1.309 + assert.ok(!isCollapsed(t1, w1) && !isCollapsed(t1, w2), 1.310 + "toolbar isn't collapsed"); 1.311 + 1.312 + closeViaButton(t1); 1.313 + 1.314 + yield wait(t1, "hide"); 1.315 + 1.316 + assert.ok(isCollapsed(t1, w1) && isCollapsed(t1, w2), 1.317 + "toolbar was collapsed"); 1.318 + 1.319 + t1.destroy(); 1.320 + yield wait(t1, "detach"); 1.321 + yield close(w2); 1.322 +}; 1.323 + 1.324 +exports["test title change"] = function*(assert) { 1.325 + const w1 = getMostRecentBrowserWindow(); 1.326 + const w2 = open(); 1.327 + 1.328 + yield ready(w2); 1.329 + 1.330 + const t1 = new Toolbar({ title: "first title" }); 1.331 + const id = t1.id; 1.332 + 1.333 + yield wait(t1, "attach"); 1.334 + 1.335 + 1.336 + assert.equal(t1.title, "first title", 1.337 + "correct title is set"); 1.338 + assert.equal(readTitle(t1, w1), "first title", 1.339 + "title set in the view of first window"); 1.340 + assert.equal(readTitle(t1, w2), "first title", 1.341 + "title set in the view of second window"); 1.342 + 1.343 + retitle(t1, "second title"); 1.344 + 1.345 + // Hide & show so to make sure changes go through a round 1.346 + // loop. 1.347 + hide(t1); 1.348 + yield wait(t1, "hide"); 1.349 + show(t1); 1.350 + yield wait(t1, "show"); 1.351 + 1.352 + assert.equal(t1.id, id, "id remains same"); 1.353 + assert.equal(t1.title, "second title", "instance title was updated"); 1.354 + assert.equal(readTitle(t1, w1), "second title", 1.355 + "title updated in first window"); 1.356 + assert.equal(readTitle(t1, w2), "second title", 1.357 + "title updated in second window"); 1.358 + 1.359 + t1.destroy(); 1.360 + yield wait(t1, "detach"); 1.361 + yield close(w2); 1.362 +}; 1.363 + 1.364 +exports["test toolbar is not customizable"] = function*(assert, done) { 1.365 + const { window, document, gCustomizeMode } = getMostRecentBrowserWindow(); 1.366 + const outerId = getOuterId(window); 1.367 + const input = new CustomizationInput(); 1.368 + const customized = defer(); 1.369 + const customizedEnd = defer(); 1.370 + 1.371 + new Reactor({ onStep: value => { 1.372 + if (value[outerId] === true) 1.373 + customized.resolve(); 1.374 + if (value[outerId] === null) 1.375 + customizedEnd.resolve(); 1.376 + }}).run(input); 1.377 + 1.378 + const toolbar = new Toolbar({ title: "foo" }); 1.379 + 1.380 + yield wait(toolbar, "attach"); 1.381 + 1.382 + let view = document.getElementById(toolbar.id); 1.383 + let label = view.querySelector("label"); 1.384 + let inner = view.querySelector("toolbar"); 1.385 + 1.386 + assert.equal(view.getAttribute("customizable"), "false", 1.387 + "The outer toolbar is not customizable."); 1.388 + 1.389 + assert.ok(label.collapsed, 1.390 + "The label is not displayed.") 1.391 + 1.392 + assert.equal(inner.getAttribute("customizable"), "true", 1.393 + "The inner toolbar is customizable."); 1.394 + 1.395 + assert.equal(window.getComputedStyle(inner).visibility, "visible", 1.396 + "The inner toolbar is visible."); 1.397 + 1.398 + // Enter in customization mode 1.399 + gCustomizeMode.toggle(); 1.400 + 1.401 + yield customized.promise; 1.402 + 1.403 + assert.equal(view.getAttribute("customizable"), "false", 1.404 + "The outer toolbar is not customizable."); 1.405 + 1.406 + assert.equal(label.collapsed, false, 1.407 + "The label is displayed.") 1.408 + 1.409 + assert.equal(inner.getAttribute("customizable"), "true", 1.410 + "The inner toolbar is customizable."); 1.411 + 1.412 + assert.equal(window.getComputedStyle(inner).visibility, "hidden", 1.413 + "The inner toolbar is hidden."); 1.414 + 1.415 + // Exit from customization mode 1.416 + gCustomizeMode.toggle(); 1.417 + 1.418 + yield customizedEnd.promise; 1.419 + 1.420 + assert.equal(view.getAttribute("customizable"), "false", 1.421 + "The outer toolbar is not customizable."); 1.422 + 1.423 + assert.ok(label.collapsed, 1.424 + "The label is not displayed.") 1.425 + 1.426 + assert.equal(inner.getAttribute("customizable"), "true", 1.427 + "The inner toolbar is customizable."); 1.428 + 1.429 + assert.equal(window.getComputedStyle(inner).visibility, "visible", 1.430 + "The inner toolbar is visible."); 1.431 + 1.432 + toolbar.destroy(); 1.433 +}; 1.434 + 1.435 +exports["test button are attached to toolbar"] = function*(assert) { 1.436 + const { document } = getMostRecentBrowserWindow(); 1.437 + const { ActionButton, ToggleButton } = require("sdk/ui"); 1.438 + const { identify } = require("sdk/ui/id"); 1.439 + 1.440 + let action = ActionButton({ 1.441 + id: "btn-1", 1.442 + label: "action", 1.443 + icon: "./placeholder.png" 1.444 + }); 1.445 + 1.446 + let toggle = ToggleButton({ 1.447 + id: "btn-2", 1.448 + label: "toggle", 1.449 + icon: "./placeholder.png" 1.450 + }); 1.451 + 1.452 + const toolbar = new Toolbar({ 1.453 + title: "foo", 1.454 + items: [action, toggle] 1.455 + }); 1.456 + 1.457 + yield wait(toolbar, "attach"); 1.458 + 1.459 + let actionNode = document.getElementById(identify(action)); 1.460 + let toggleNode = document.getElementById(identify(toggle)); 1.461 + 1.462 + assert.notEqual(actionNode, null, 1.463 + "action button exists in the document"); 1.464 + 1.465 + assert.notEqual(actionNode, null, 1.466 + "action button exists in the document"); 1.467 + 1.468 + assert.notEqual(toggleNode, null, 1.469 + "toggle button exists in the document"); 1.470 + 1.471 + assert.equal(actionNode.nextElementSibling, toggleNode, 1.472 + "action button is placed before toggle button"); 1.473 + 1.474 + assert.equal(actionNode.parentNode.parentNode.id, toolbar.id, 1.475 + "buttons are placed in the correct toolbar"); 1.476 + 1.477 + toolbar.destroy(); 1.478 +}; 1.479 + 1.480 +require("sdk/test").run(exports);