test-ui-toolbar.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  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. module.metadata = {
  6. "engines": {
  7. "Firefox": "*"
  8. }
  9. };
  10. const { Toolbar } = require("sdk/ui/toolbar");
  11. const { Loader } = require("sdk/test/loader");
  12. const { identify } = require("sdk/ui/id");
  13. const { getMostRecentBrowserWindow, open, getOuterId } = require("sdk/window/utils");
  14. const { ready, close } = require("sdk/window/helpers");
  15. const { defer } = require("sdk/core/promise");
  16. const { send, stop, Reactor } = require("sdk/event/utils");
  17. const { object } = require("sdk/util/sequence");
  18. const { CustomizationInput } = require("sdk/input/customizable-ui");
  19. const { OutputPort } = require("sdk/output/system");
  20. const output = new OutputPort({ id: "toolbar-change" });
  21. const wait = (toolbar, event) => {
  22. let { promise, resolve } = defer();
  23. toolbar.once(event, resolve);
  24. return promise;
  25. };
  26. const show = ({id}) => send(output, object([id, {collapsed: false}]));
  27. const hide = ({id}) => send(output, object([id, {collapsed: true}]));
  28. const retitle = ({id}, title) => send(output, object([id, {title: title}]));
  29. const isAttached = ({id}, window=getMostRecentBrowserWindow()) =>
  30. !!window.document.getElementById(id);
  31. const isCollapsed = ({id}, window=getMostRecentBrowserWindow()) =>
  32. window.document.getElementById(id).getAttribute("collapsed") === "true";
  33. const closeViaButton = ({id}, window=getMostRecentBrowserWindow()) =>
  34. window.document.getElementById("close-" + id).click();
  35. const readTitle = ({id}, window=getMostRecentBrowserWindow()) =>
  36. window.document.getElementById(id).getAttribute("toolbarname");
  37. exports["test toolbar API"] = function*(assert) {
  38. assert.throws(() => new Toolbar(),
  39. /The `option.title`/,
  40. "toolbar requires title");
  41. assert.throws(() => new Toolbar({ hidden: false }),
  42. /The `option.title`/,
  43. "toolbar requires title");
  44. const t1 = new Toolbar({ title: "foo" });
  45. assert.throws(() => new Toolbar({ title: "foo" }),
  46. /already exists/,
  47. "can't create identical toolbars");
  48. assert.ok(t1.id, "toolbar has an id");
  49. assert.equal(t1.id, identify(t1), "identify returns toolbar id");
  50. assert.deepEqual(t1.items, [], "toolbar items are empty");
  51. assert.equal(t1.title, void(0), "title is void until attached");
  52. assert.equal(t1.hidden, void(0), "hidden is void until attached");
  53. yield wait(t1, "attach");
  54. assert.equal(t1.title, "foo", "title is set after attach");
  55. assert.equal(t1.hidden, false, "by default toolbar isn't hidden");
  56. assert.throws(() => new Toolbar({ title: "foo" }),
  57. /already exists/,
  58. "still can't create identical toolbar");
  59. const t2 = new Toolbar({ title: "bar", hidden: true });
  60. assert.pass("can create different toolbar though");
  61. assert.ok(t2.id, "toolbar has an id");
  62. assert.equal(t2.id, identify(t2), "identify returns toolbar id");
  63. assert.notEqual(t2.id, t1.id, "each toolbar has unique id");
  64. yield wait(t2, "attach");
  65. assert.equal(t2.title, "bar", "title is set after attach");
  66. assert.equal(t2.hidden, true, "toolbar is hidden as specified");
  67. t2.destroy();
  68. t1.destroy();
  69. yield wait(t1, "detach");
  70. assert.equal(t1.title, void(0), "title is voided after detach");
  71. assert.equal(t1.hidden, void(0), "hidden is void fater detach");
  72. const t3 = new Toolbar({ title: "foo" });
  73. assert.pass("Can create toolbar after identical was detached");
  74. assert.equal(t3.id, t1.id, "toolbar has a same id");
  75. assert.equal(t3.id, identify(t3), "identify returns toolbar.id");
  76. assert.equal(t3.title, void(0), "title is void before attach");
  77. assert.equal(t3.hidden, void(0), "hidden is void before attach");
  78. yield wait(t3, "attach");
  79. assert.equal(t3.title, "foo", "title is set");
  80. assert.equal(t3.hidden, false, "toolbar is hidden");
  81. t3.destroy();
  82. yield wait(t3, "detach");
  83. };
  84. exports["test show / hide toolbar"] = function*(assert) {
  85. const t1 = new Toolbar({ title: "foo" });
  86. yield wait(t1, "attach");
  87. assert.equal(t1.title, "foo", "title is set after attach");
  88. assert.equal(t1.hidden, false, "by default toolbar isn't hidden");
  89. assert.ok(isAttached(t1), "toolbar was actually attarched");
  90. assert.ok(!isCollapsed(t1), "toolbar isn't collapsed");
  91. hide(t1);
  92. assert.equal(t1.hidden, false, "not hidden yet");
  93. yield wait(t1, "hide");
  94. assert.equal(t1.hidden, true, "toolbar got hidden");
  95. assert.ok(isCollapsed(t1), "toolbar is collapsed");
  96. show(t1);
  97. yield wait(t1, "show");
  98. assert.equal(t1.hidden, false, "toolbar got shown");
  99. assert.ok(!isCollapsed(t1), "toolbar isn't collapsed");
  100. t1.destroy();
  101. yield wait(t1, "detach");
  102. assert.ok(!isAttached(t1), "toolbar is no longer attached");
  103. };
  104. exports["test multiple windows & toolbars"] = function*(assert) {
  105. const w1 = getMostRecentBrowserWindow();
  106. const t1 = new Toolbar({ title: "multi window" });
  107. yield wait(t1, "attach");
  108. assert.equal(t1.title, "multi window", "title is set after attach");
  109. assert.equal(t1.hidden, false, "by default toolbar isn't hidden");
  110. assert.ok(isAttached(t1, w1), "toolbar was actually attarched");
  111. assert.ok(!isCollapsed(t1, w1), "toolbar isn't collapsed");
  112. const w2 = open();
  113. yield ready(w2);
  114. assert.ok(isAttached(t1, w2), "toolbar was attached to second window");
  115. assert.ok(!isCollapsed(t1, w2), "toolbar isn't collabsed");
  116. hide(t1);
  117. yield wait(t1, "hide");
  118. assert.ok(isCollapsed(t1, w1) && isCollapsed(t1, w2),
  119. "toolbar is collabsed");
  120. const w3 = open();
  121. yield ready(w3);
  122. assert.ok(isAttached(t1, w1) && isAttached(t1, w2) && isAttached(t1, w3),
  123. "toolbar is attached to all windows");
  124. assert.ok(isCollapsed(t1, w3) && isCollapsed(t1, w3) && isCollapsed(t1, w3),
  125. "toolbar still collapsed in all windows");
  126. const t2 = new Toolbar({ title: "multi hidden", hidden: true });
  127. yield wait(t2, "attach");
  128. assert.equal(t2.title, "multi hidden", "title is set after attach");
  129. assert.equal(t2.hidden, true, "isn't hidden as specified");
  130. assert.ok(isAttached(t1, w1) && isAttached(t1, w2) && isAttached(t1, w3),
  131. "toolbar#1 is still attached");
  132. assert.ok(isAttached(t2, w1) && isAttached(t2, w2) && isAttached(t2, w3),
  133. "toolbar#2 was attached to all windows");
  134. assert.ok(isCollapsed(t1, w1) && isCollapsed(t1, w2) && isCollapsed(t1, w3),
  135. "toolbar#1 is still collapsed");
  136. assert.ok(isCollapsed(t2, w1) && isCollapsed(t2, w2) && isCollapsed(t2, w3),
  137. "toolbar#2 is collapsed");
  138. t1.destroy();
  139. yield wait(t1, "detach");
  140. assert.ok(!isAttached(t1, w1) && !isAttached(t1, w2) && !isAttached(t1, w3),
  141. "toolbar#1 was detached from all windows");
  142. assert.ok(isAttached(t2, w1) && isAttached(t2, w2) && isAttached(t2, w3),
  143. "toolbar#2 is still attached to all windows");
  144. yield close(w2);
  145. assert.ok(isAttached(t2, w1) && isAttached(t2, w3),
  146. "toolbar#2 is still attached to remaining windows");
  147. assert.ok(isCollapsed(t2, w1) && isCollapsed(t2, w3),
  148. "toolbar#2 is still collapsed");
  149. show(t2);
  150. yield wait(t2, "show");
  151. assert.ok(!isCollapsed(t2, w1) && !isCollapsed(t2, w3),
  152. "toolbar#2 is not collapsed");
  153. yield close(w3);
  154. assert.ok(isAttached(t2, w1), "still attached to last window");
  155. assert.ok(!isCollapsed(t2, w1), "still isn't collapsed");
  156. t2.destroy();
  157. yield wait(t2, "detach");
  158. assert.ok(!isAttached(t2, w1), "toolbar was removed");
  159. };
  160. exports["test toolbar persistence"] = function*(assert) {
  161. const t1 = new Toolbar({ title: "per sist ence" });
  162. yield wait(t1, "attach");
  163. assert.equal(t1.hidden, false, "toolbar is visible");
  164. hide(t1);
  165. yield wait(t1, "hide");
  166. assert.equal(t1.hidden, true, "toolbar is hidden");
  167. assert.ok(isCollapsed(t1), "toolbar is collapsed");
  168. t1.destroy();
  169. yield wait(t1, "detach");
  170. const t2 = new Toolbar({ title: "per sist ence" });
  171. yield wait(t2, "attach");
  172. assert.equal(t2.hidden, true, "toolbar persisted state");
  173. assert.ok(isCollapsed(t2), "toolbar is collapsed");
  174. show(t2);
  175. t2.destroy();
  176. yield wait(t2, "detach");
  177. const t3 = new Toolbar({ title: "per sist ence", hidden: true });
  178. yield wait(t3, "attach");
  179. assert.equal(t3.hidden, false, "toolbar persisted state & ignored option");
  180. assert.ok(!isCollapsed(t3), "toolbar isn1t collapsed");
  181. t3.destroy();
  182. yield wait(t3, "detach");
  183. };
  184. exports["test toolbar unload"] = function*(assert) {
  185. // We override add-on id, otherwise two instances of Toolbar host (view.js)
  186. // handling same updates, cause message port is bound to add-on id.
  187. const loader = Loader(module, null, null, {id: "toolbar-unload-addon"});
  188. const { Toolbar } = loader.require("sdk/ui/toolbar");
  189. const w1 = getMostRecentBrowserWindow();
  190. const w2 = open();
  191. yield ready(w2);
  192. const t1 = new Toolbar({ title: "unload" });
  193. yield wait(t1, "attach");
  194. assert.ok(isAttached(t1, w1) && isAttached(t1, w2),
  195. "attached to both windows");
  196. loader.unload();
  197. assert.ok(!isAttached(t1, w1) && !isAttached(t1, w2),
  198. "detached from both windows on unload");
  199. yield close(w2);
  200. };
  201. exports["test toolbar close button"] = function*(assert) {
  202. const t1 = new Toolbar({ title: "close with button" });
  203. yield wait(t1, "attach");
  204. const w1 = getMostRecentBrowserWindow();
  205. const w2 = open();
  206. yield ready(w2);
  207. assert.ok(!isCollapsed(t1, w1) && !isCollapsed(t1, w2),
  208. "toolbar isn't collapsed");
  209. closeViaButton(t1);
  210. yield wait(t1, "hide");
  211. assert.ok(isCollapsed(t1, w1) && isCollapsed(t1, w2),
  212. "toolbar was collapsed");
  213. t1.destroy();
  214. yield wait(t1, "detach");
  215. yield close(w2);
  216. };
  217. exports["test title change"] = function*(assert) {
  218. const w1 = getMostRecentBrowserWindow();
  219. const w2 = open();
  220. yield ready(w2);
  221. const t1 = new Toolbar({ title: "first title" });
  222. const id = t1.id;
  223. yield wait(t1, "attach");
  224. assert.equal(t1.title, "first title",
  225. "correct title is set");
  226. assert.equal(readTitle(t1, w1), "first title",
  227. "title set in the view of first window");
  228. assert.equal(readTitle(t1, w2), "first title",
  229. "title set in the view of second window");
  230. retitle(t1, "second title");
  231. // Hide & show so to make sure changes go through a round
  232. // loop.
  233. hide(t1);
  234. yield wait(t1, "hide");
  235. show(t1);
  236. yield wait(t1, "show");
  237. assert.equal(t1.id, id, "id remains same");
  238. assert.equal(t1.title, "second title", "instance title was updated");
  239. assert.equal(readTitle(t1, w1), "second title",
  240. "title updated in first window");
  241. assert.equal(readTitle(t1, w2), "second title",
  242. "title updated in second window");
  243. t1.destroy();
  244. yield wait(t1, "detach");
  245. yield close(w2);
  246. };
  247. exports["test toolbar is not customizable"] = function*(assert, done) {
  248. const { window, document, gCustomizeMode } = getMostRecentBrowserWindow();
  249. const outerId = getOuterId(window);
  250. const input = new CustomizationInput();
  251. const customized = defer();
  252. const customizedEnd = defer();
  253. new Reactor({ onStep: value => {
  254. if (value[outerId] === true)
  255. customized.resolve();
  256. if (value[outerId] === null)
  257. customizedEnd.resolve();
  258. }}).run(input);
  259. const toolbar = new Toolbar({ title: "foo" });
  260. yield wait(toolbar, "attach");
  261. let view = document.getElementById(toolbar.id);
  262. let label = view.querySelector("label");
  263. let inner = view.querySelector("toolbar");
  264. assert.equal(view.getAttribute("customizable"), "false",
  265. "The outer toolbar is not customizable.");
  266. assert.ok(label.collapsed,
  267. "The label is not displayed.")
  268. assert.equal(inner.getAttribute("customizable"), "true",
  269. "The inner toolbar is customizable.");
  270. assert.equal(window.getComputedStyle(inner).visibility, "visible",
  271. "The inner toolbar is visible.");
  272. // Enter in customization mode
  273. gCustomizeMode.toggle();
  274. yield customized.promise;
  275. assert.equal(view.getAttribute("customizable"), "false",
  276. "The outer toolbar is not customizable.");
  277. assert.equal(label.collapsed, false,
  278. "The label is displayed.")
  279. assert.equal(inner.getAttribute("customizable"), "true",
  280. "The inner toolbar is customizable.");
  281. assert.equal(window.getComputedStyle(inner).visibility, "hidden",
  282. "The inner toolbar is hidden.");
  283. // Exit from customization mode
  284. gCustomizeMode.toggle();
  285. yield customizedEnd.promise;
  286. assert.equal(view.getAttribute("customizable"), "false",
  287. "The outer toolbar is not customizable.");
  288. assert.ok(label.collapsed,
  289. "The label is not displayed.")
  290. assert.equal(inner.getAttribute("customizable"), "true",
  291. "The inner toolbar is customizable.");
  292. assert.equal(window.getComputedStyle(inner).visibility, "visible",
  293. "The inner toolbar is visible.");
  294. toolbar.destroy();
  295. };
  296. require("sdk/test").run(exports);