modalpopup_test.js 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. // Copyright 2011 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. goog.provide('goog.ui.ModalPopupTest');
  15. goog.setTestOnly('goog.ui.ModalPopupTest');
  16. goog.require('goog.a11y.aria');
  17. goog.require('goog.a11y.aria.State');
  18. goog.require('goog.dispose');
  19. goog.require('goog.dom');
  20. goog.require('goog.dom.TagName');
  21. goog.require('goog.events');
  22. goog.require('goog.events.EventTarget');
  23. goog.require('goog.events.EventType');
  24. goog.require('goog.fx.Transition');
  25. goog.require('goog.fx.css3');
  26. goog.require('goog.string');
  27. goog.require('goog.style');
  28. goog.require('goog.testing.MockClock');
  29. goog.require('goog.testing.events');
  30. goog.require('goog.testing.jsunit');
  31. goog.require('goog.ui.ModalPopup');
  32. goog.require('goog.ui.PopupBase');
  33. var popup;
  34. var main;
  35. var mockClock;
  36. function setUp() {
  37. main = /** @type {!Element}*/ (goog.dom.getElement('main'));
  38. mockClock = new goog.testing.MockClock(true);
  39. }
  40. function tearDown() {
  41. goog.dispose(popup);
  42. mockClock.dispose();
  43. goog.a11y.aria.removeState(main, goog.a11y.aria.State.HIDDEN);
  44. }
  45. function testOrientationChange() {
  46. var i = 0;
  47. popup = new goog.ui.ModalPopup();
  48. popup.resizeBackgroundTask_ = function() { i++; };
  49. popup.render();
  50. popup.setVisible(true);
  51. var event = new goog.events.Event(
  52. goog.events.EventType.ORIENTATIONCHANGE,
  53. popup.getDomHelper().getWindow());
  54. goog.testing.events.fireBrowserEvent(event);
  55. assertEquals(1, i);
  56. goog.testing.events.fireBrowserEvent(event);
  57. assertEquals(2, i);
  58. popup.setVisible(false);
  59. goog.testing.events.fireBrowserEvent(event);
  60. assertEquals(2, i);
  61. }
  62. function testDispose() {
  63. popup = new goog.ui.ModalPopup();
  64. popup.render();
  65. goog.dispose(popup);
  66. assertNull(goog.dom.getElementByClass('goog-modalpopup-bg'));
  67. assertNull(goog.dom.getElementByClass('goog-modalpopup'));
  68. assertEquals(
  69. 0, goog.dom.getElementsByTagNameAndClass(goog.dom.TagName.SPAN).length);
  70. }
  71. function testRenderWithoutIframeMask() {
  72. popup = new goog.ui.ModalPopup();
  73. popup.render();
  74. assertEquals(
  75. 0, goog.dom
  76. .getElementsByTagNameAndClass(
  77. goog.dom.TagName.IFRAME, 'goog-modalpopup-bg')
  78. .length);
  79. var bg = goog.dom.getElementsByTagNameAndClass(
  80. goog.dom.TagName.DIV, 'goog-modalpopup-bg');
  81. assertEquals(1, bg.length);
  82. var content = goog.dom.getElementByClass('goog-modalpopup');
  83. assertNotNull(content);
  84. var tabCatcher = goog.dom.getElementsByTagNameAndClass(goog.dom.TagName.SPAN);
  85. assertEquals(1, tabCatcher.length);
  86. assertTrue(goog.dom.compareNodeOrder(bg[0], content) < 0);
  87. assertTrue(goog.dom.compareNodeOrder(content, tabCatcher[0]) < 0);
  88. assertTrue(
  89. goog.string.isEmptyOrWhitespace(
  90. goog.string.makeSafe(
  91. goog.a11y.aria.getState(main, goog.a11y.aria.State.HIDDEN))));
  92. popup.setVisible(true);
  93. assertTrue(
  94. goog.string.isEmptyOrWhitespace(
  95. goog.string.makeSafe(
  96. goog.a11y.aria.getState(
  97. popup.getElementStrict(), goog.a11y.aria.State.HIDDEN))));
  98. assertEquals(
  99. 'true', goog.a11y.aria.getState(main, goog.a11y.aria.State.HIDDEN));
  100. popup.setVisible(false);
  101. assertTrue(
  102. goog.string.isEmptyOrWhitespace(
  103. goog.string.makeSafe(
  104. goog.a11y.aria.getState(main, goog.a11y.aria.State.HIDDEN))));
  105. }
  106. function testRenderWithIframeMask() {
  107. popup = new goog.ui.ModalPopup(true);
  108. popup.render();
  109. var iframe = goog.dom.getElementsByTagNameAndClass(
  110. goog.dom.TagName.IFRAME, 'goog-modalpopup-bg');
  111. assertEquals(1, iframe.length);
  112. var bg = goog.dom.getElementsByTagNameAndClass(
  113. goog.dom.TagName.DIV, 'goog-modalpopup-bg');
  114. assertEquals(1, bg.length);
  115. var content = goog.dom.getElementByClass('goog-modalpopup');
  116. assertNotNull(content);
  117. var tabCatcher = goog.dom.getElementsByTagNameAndClass(goog.dom.TagName.SPAN);
  118. assertEquals(1, tabCatcher.length);
  119. assertTrue(goog.dom.compareNodeOrder(iframe[0], bg[0]) < 0);
  120. assertTrue(goog.dom.compareNodeOrder(bg[0], content) < 0);
  121. assertTrue(goog.dom.compareNodeOrder(content, tabCatcher[0]) < 0);
  122. assertTrue(
  123. goog.string.isEmptyOrWhitespace(
  124. goog.string.makeSafe(
  125. goog.a11y.aria.getState(main, goog.a11y.aria.State.HIDDEN))));
  126. popup.setVisible(true);
  127. assertTrue(
  128. goog.string.isEmptyOrWhitespace(
  129. goog.string.makeSafe(
  130. goog.a11y.aria.getState(
  131. popup.getElementStrict(), goog.a11y.aria.State.HIDDEN))));
  132. assertEquals(
  133. 'true', goog.a11y.aria.getState(main, goog.a11y.aria.State.HIDDEN));
  134. popup.setVisible(false);
  135. assertTrue(
  136. goog.string.isEmptyOrWhitespace(
  137. goog.string.makeSafe(
  138. goog.a11y.aria.getState(main, goog.a11y.aria.State.HIDDEN))));
  139. }
  140. function testRenderWithAriaState() {
  141. popup = new goog.ui.ModalPopup();
  142. popup.render();
  143. goog.a11y.aria.setState(main, goog.a11y.aria.State.HIDDEN, true);
  144. popup.setVisible(true);
  145. assertEquals(
  146. 'true', goog.a11y.aria.getState(main, goog.a11y.aria.State.HIDDEN));
  147. popup.setVisible(false);
  148. assertEquals(
  149. 'true', goog.a11y.aria.getState(main, goog.a11y.aria.State.HIDDEN));
  150. goog.a11y.aria.setState(main, goog.a11y.aria.State.HIDDEN, false);
  151. popup.setVisible(true);
  152. assertEquals(
  153. 'false', goog.a11y.aria.getState(main, goog.a11y.aria.State.HIDDEN));
  154. popup.setVisible(false);
  155. assertEquals(
  156. 'false', goog.a11y.aria.getState(main, goog.a11y.aria.State.HIDDEN));
  157. }
  158. function testRenderDoesNotShowAnyElement() {
  159. popup = new goog.ui.ModalPopup(true);
  160. popup.render();
  161. var iframe = goog.dom.getElementsByTagNameAndClass(
  162. goog.dom.TagName.IFRAME, 'goog-modalpopup-bg');
  163. assertFalse(goog.style.isElementShown(iframe[0]));
  164. var bg = goog.dom.getElementsByTagNameAndClass(
  165. goog.dom.TagName.DIV, 'goog-modalpopup-bg');
  166. assertFalse(goog.style.isElementShown(bg[0]));
  167. assertFalse(
  168. goog.style.isElementShown(goog.dom.getElementByClass('goog-modalpopup')));
  169. var tabCatcher = goog.dom.getElementsByTagNameAndClass(goog.dom.TagName.SPAN);
  170. assertFalse(goog.style.isElementShown(tabCatcher[0]));
  171. }
  172. function testIframeOpacityIsSetToZero() {
  173. popup = new goog.ui.ModalPopup(true);
  174. popup.render();
  175. var iframe = goog.dom.getElementsByTagNameAndClass(
  176. goog.dom.TagName.IFRAME, 'goog-modalpopup-bg')[0];
  177. assertEquals(0, goog.style.getOpacity(iframe));
  178. }
  179. function testEventFiredOnShow() {
  180. popup = new goog.ui.ModalPopup(true);
  181. popup.render();
  182. var beforeShowCallCount = 0;
  183. var beforeShowHandler = function() { beforeShowCallCount++; };
  184. var showCallCount = false;
  185. var showHandler = function() {
  186. assertEquals(
  187. 'BEFORE_SHOW is not dispatched before SHOW', 1, beforeShowCallCount);
  188. showCallCount++;
  189. };
  190. goog.events.listen(
  191. popup, goog.ui.PopupBase.EventType.BEFORE_SHOW, beforeShowHandler);
  192. goog.events.listen(popup, goog.ui.PopupBase.EventType.SHOW, showHandler);
  193. popup.setVisible(true);
  194. assertEquals(1, beforeShowCallCount);
  195. assertEquals(1, showCallCount);
  196. }
  197. function testEventFiredOnHide() {
  198. popup = new goog.ui.ModalPopup(true);
  199. popup.render();
  200. popup.setVisible(true);
  201. var beforeHideCallCount = 0;
  202. var beforeHideHandler = function() { beforeHideCallCount++; };
  203. var hideCallCount = false;
  204. var hideHandler = function() {
  205. assertEquals(
  206. 'BEFORE_HIDE is not dispatched before HIDE', 1, beforeHideCallCount);
  207. hideCallCount++;
  208. };
  209. goog.events.listen(
  210. popup, goog.ui.PopupBase.EventType.BEFORE_HIDE, beforeHideHandler);
  211. goog.events.listen(popup, goog.ui.PopupBase.EventType.HIDE, hideHandler);
  212. popup.setVisible(false);
  213. assertEquals(1, beforeHideCallCount);
  214. assertEquals(1, hideCallCount);
  215. }
  216. function testShowEventFiredWithNoTransition() {
  217. popup = new goog.ui.ModalPopup();
  218. popup.render();
  219. var showHandlerCalled = false;
  220. goog.events.listen(popup, goog.ui.PopupBase.EventType.SHOW, function() {
  221. showHandlerCalled = true;
  222. });
  223. popup.setVisible(true);
  224. assertTrue(showHandlerCalled);
  225. }
  226. function testHideEventFiredWithNoTransition() {
  227. popup = new goog.ui.ModalPopup();
  228. popup.render();
  229. var hideHandlerCalled = false;
  230. goog.events.listen(popup, goog.ui.PopupBase.EventType.HIDE, function() {
  231. hideHandlerCalled = true;
  232. });
  233. popup.setVisible(true);
  234. popup.setVisible(false);
  235. assertTrue(hideHandlerCalled);
  236. }
  237. function testTransitionsPlayedOnShow() {
  238. popup = new goog.ui.ModalPopup();
  239. popup.render();
  240. var mockPopupShowTransition = new MockTransition();
  241. var mockPopupHideTransition = new MockTransition();
  242. var mockBgShowTransition = new MockTransition();
  243. var mockBgHideTransition = new MockTransition();
  244. var showHandlerCalled = false;
  245. goog.events.listen(popup, goog.ui.PopupBase.EventType.SHOW, function() {
  246. showHandlerCalled = true;
  247. });
  248. popup.setTransition(
  249. mockPopupShowTransition, mockPopupHideTransition, mockBgShowTransition,
  250. mockBgHideTransition);
  251. assertFalse(mockPopupShowTransition.wasPlayed);
  252. assertFalse(mockBgShowTransition.wasPlayed);
  253. popup.setVisible(true);
  254. assertTrue(mockPopupShowTransition.wasPlayed);
  255. assertTrue(mockBgShowTransition.wasPlayed);
  256. assertFalse(showHandlerCalled);
  257. mockPopupShowTransition.dispatchEvent(goog.fx.Transition.EventType.END);
  258. assertTrue(showHandlerCalled);
  259. }
  260. function testTransitionsPlayedOnHide() {
  261. popup = new goog.ui.ModalPopup();
  262. popup.render();
  263. var mockPopupShowTransition = new MockTransition();
  264. var mockPopupHideTransition = new MockTransition();
  265. var mockBgShowTransition = new MockTransition();
  266. var mockBgHideTransition = new MockTransition();
  267. var hideHandlerCalled = false;
  268. goog.events.listen(popup, goog.ui.PopupBase.EventType.HIDE, function() {
  269. hideHandlerCalled = true;
  270. });
  271. popup.setTransition(
  272. mockPopupShowTransition, mockPopupHideTransition, mockBgShowTransition,
  273. mockBgHideTransition);
  274. popup.setVisible(true);
  275. assertFalse(mockPopupHideTransition.wasPlayed);
  276. assertFalse(mockBgHideTransition.wasPlayed);
  277. popup.setVisible(false);
  278. assertTrue(mockPopupHideTransition.wasPlayed);
  279. assertTrue(mockBgHideTransition.wasPlayed);
  280. assertFalse(hideHandlerCalled);
  281. mockPopupHideTransition.dispatchEvent(goog.fx.Transition.EventType.END);
  282. assertTrue(hideHandlerCalled);
  283. }
  284. function testTransitionsAndDisposingOnHideWorks() {
  285. popup = new goog.ui.ModalPopup();
  286. popup.render();
  287. goog.events.listen(
  288. popup, goog.ui.PopupBase.EventType.HIDE, function() { popup.dispose(); });
  289. var popupShowTransition =
  290. goog.fx.css3.fadeIn(popup.getElement(), 0.1 /* duration */);
  291. var popupHideTransition =
  292. goog.fx.css3.fadeOut(popup.getElement(), 0.1 /* duration */);
  293. var bgShowTransition =
  294. goog.fx.css3.fadeIn(popup.getElement(), 0.1 /* duration */);
  295. var bgHideTransition =
  296. goog.fx.css3.fadeOut(popup.getElement(), 0.1 /* duration */);
  297. popup.setTransition(
  298. popupShowTransition, popupHideTransition, bgShowTransition,
  299. bgHideTransition);
  300. popup.setVisible(true);
  301. popup.setVisible(false);
  302. // Nothing to assert. We only want to ensure that there is no error.
  303. }
  304. function testSetVisibleWorksCorrectlyWithTransitions() {
  305. popup = new goog.ui.ModalPopup();
  306. popup.render();
  307. popup.setTransition(
  308. goog.fx.css3.fadeIn(popup.getElement(), 1),
  309. goog.fx.css3.fadeIn(popup.getBackgroundElement(), 1),
  310. goog.fx.css3.fadeOut(popup.getElement(), 1),
  311. goog.fx.css3.fadeOut(popup.getBackgroundElement(), 1));
  312. // Consecutive calls to setVisible works without needing to wait for
  313. // transition to finish.
  314. popup.setVisible(true);
  315. assertTrue(popup.isVisible());
  316. popup.setVisible(false);
  317. assertFalse(popup.isVisible());
  318. mockClock.tick(1100);
  319. // Calling setVisible(true) immediately changed the state to visible.
  320. popup.setVisible(true);
  321. assertTrue(popup.isVisible());
  322. mockClock.tick(1100);
  323. // Consecutive calls to setVisible, in opposite order.
  324. popup.setVisible(false);
  325. popup.setVisible(true);
  326. assertTrue(popup.isVisible());
  327. mockClock.tick(1100);
  328. // Calling setVisible(false) immediately changed the state to not visible.
  329. popup.setVisible(false);
  330. assertFalse(popup.isVisible());
  331. mockClock.tick(1100);
  332. }
  333. function testTransitionsDisposed() {
  334. popup = new goog.ui.ModalPopup();
  335. popup.render();
  336. var transition = goog.fx.css3.fadeIn(popup.getElement(), 0.1 /* duration */);
  337. var hideHandlerCalled = false;
  338. goog.events.listen(popup, goog.ui.PopupBase.EventType.HIDE, function() {
  339. hideHandlerCalled = true;
  340. });
  341. popup.setTransition(transition, transition, transition, transition);
  342. popup.dispose();
  343. transition.dispatchEvent(goog.fx.Transition.EventType.END);
  344. assertFalse(hideHandlerCalled);
  345. }
  346. function testBackgroundHeight() {
  347. // Insert an absolutely-positioned element larger than the viewport.
  348. var viewportSize = goog.dom.getViewportSize();
  349. var w = viewportSize.width * 2;
  350. var h = viewportSize.height * 2;
  351. var dummy = goog.dom.createElement(goog.dom.TagName.DIV);
  352. dummy.style.position = 'absolute';
  353. goog.style.setSize(dummy, w, h);
  354. document.body.appendChild(dummy);
  355. try {
  356. popup = new goog.ui.ModalPopup();
  357. popup.render();
  358. popup.setVisible(true);
  359. var size = goog.style.getSize(popup.getBackgroundElement());
  360. assertTrue(
  361. 'Background element must cover the size of the content',
  362. size.width >= w && size.height >= h);
  363. } finally {
  364. goog.dom.removeNode(dummy);
  365. }
  366. }
  367. function testSetupBackwardTabWrapResetsFlagAfterTimeout() {
  368. popup.setupBackwardTabWrap();
  369. assertTrue(
  370. 'Backward tab wrap should be in progress',
  371. popup.backwardTabWrapInProgress_);
  372. mockClock.tick(1);
  373. assertFalse(
  374. 'Backward tab wrap flag should be reset after delay',
  375. popup.backwardTabWrapInProgress_);
  376. }
  377. function testPopupGetsFocus() {
  378. popup = new goog.ui.ModalPopup();
  379. popup.render();
  380. popup.setVisible(true);
  381. assertTrue(
  382. 'Dialog must receive initial focus',
  383. goog.dom.getActiveElement(document) == popup.getElement());
  384. }
  385. function testDecoratedPopupGetsFocus() {
  386. var dialogElem = goog.dom.createElement(goog.dom.TagName.DIV);
  387. document.body.appendChild(dialogElem);
  388. popup = new goog.ui.ModalPopup();
  389. popup.decorate(dialogElem);
  390. popup.setVisible(true);
  391. assertTrue(
  392. 'Dialog must receive initial focus',
  393. goog.dom.getActiveElement(document) == popup.getElement());
  394. goog.dom.removeNode(dialogElem);
  395. }
  396. /**
  397. * @implements {goog.fx.Transition}
  398. * @extends {goog.events.EventTarget}
  399. * @constructor
  400. */
  401. var MockTransition = function() {
  402. MockTransition.base(this, 'constructor');
  403. this.wasPlayed = false;
  404. };
  405. goog.inherits(MockTransition, goog.events.EventTarget);
  406. MockTransition.prototype.play = function() {
  407. this.wasPlayed = true;
  408. };
  409. MockTransition.prototype.stop = goog.nullFunction;