dialog_test.js 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835
  1. // Copyright 2007 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.DialogTest');
  15. goog.setTestOnly('goog.ui.DialogTest');
  16. goog.require('goog.a11y.aria');
  17. goog.require('goog.a11y.aria.Role');
  18. goog.require('goog.a11y.aria.State');
  19. goog.require('goog.dom');
  20. goog.require('goog.dom.TagName');
  21. goog.require('goog.dom.classlist');
  22. goog.require('goog.events');
  23. goog.require('goog.events.EventType');
  24. goog.require('goog.events.KeyCodes');
  25. goog.require('goog.fx.css3');
  26. goog.require('goog.html.SafeHtml');
  27. goog.require('goog.html.testing');
  28. goog.require('goog.style');
  29. goog.require('goog.testing.MockClock');
  30. goog.require('goog.testing.events');
  31. goog.require('goog.testing.jsunit');
  32. goog.require('goog.testing.recordFunction');
  33. goog.require('goog.ui.Dialog');
  34. goog.require('goog.userAgent');
  35. var bodyChildElement;
  36. var decorateTarget;
  37. var dialog;
  38. var mockClock;
  39. function setUp() {
  40. mockClock = new goog.testing.MockClock(true);
  41. bodyChildElement = goog.dom.createElement(goog.dom.TagName.DIV);
  42. document.body.appendChild(bodyChildElement);
  43. dialog = new goog.ui.Dialog();
  44. var buttons = new goog.ui.Dialog.ButtonSet();
  45. buttons.set(goog.ui.Dialog.DefaultButtonKeys.CANCEL, 'Foo!', false, true);
  46. buttons.set(goog.ui.Dialog.DefaultButtonKeys.OK, 'OK', true);
  47. dialog.setButtonSet(buttons);
  48. dialog.setVisible(true);
  49. decorateTarget = goog.dom.createDom(goog.dom.TagName.DIV);
  50. document.body.appendChild(decorateTarget);
  51. }
  52. function tearDown() {
  53. dialog.dispose();
  54. goog.dom.removeNode(bodyChildElement);
  55. goog.dom.removeNode(decorateTarget);
  56. mockClock.dispose();
  57. }
  58. function testCrossFrameFocus() {
  59. // Firefox (3.6, maybe future versions) fails this test when there are too
  60. // many other test files being run concurrently.
  61. if (goog.userAgent.IE || goog.userAgent.GECKO) {
  62. return;
  63. }
  64. dialog.setVisible(false);
  65. var iframeWindow = goog.dom.getElement('f').contentWindow;
  66. var iframeInput = goog.dom.getElementsByTagName(
  67. goog.dom.TagName.INPUT, iframeWindow.document)[0];
  68. dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK);
  69. var dialogElement = dialog.getElement();
  70. var focusCounter = 0;
  71. goog.events.listen(dialogElement, 'focus', function() { focusCounter++; });
  72. iframeInput.focus();
  73. dialog.setVisible(true);
  74. dialog.setVisible(false);
  75. iframeInput.focus();
  76. dialog.setVisible(true);
  77. assertEquals(2, focusCounter);
  78. }
  79. function testNoDisabledButtonFocus() {
  80. dialog.setVisible(false);
  81. var buttonEl =
  82. dialog.getButtonSet().getButton(goog.ui.Dialog.DefaultButtonKeys.OK);
  83. buttonEl.disabled = true;
  84. var focused = false;
  85. buttonEl.focus = function() { focused = true; };
  86. dialog.setVisible(true);
  87. assertFalse('Should not have called focus on disabled button', focused);
  88. }
  89. function testNoTitleClose() {
  90. assertTrue(goog.style.isElementShown(dialog.getTitleCloseElement()));
  91. dialog.setHasTitleCloseButton(false);
  92. assertFalse(goog.style.isElementShown(dialog.getTitleCloseElement()));
  93. }
  94. /**
  95. * Helper that clicks the first button in the dialog and checks if that
  96. * results in a goog.ui.Dialog.EventType.SELECT being dispatched.
  97. * @param {boolean} disableButton Whether to disable the button being
  98. * tested.
  99. * @return {boolean} Whether a goog.ui.Dialog.EventType.SELECT was dispatched.
  100. */
  101. function checkSelectDispatchedOnButtonClick(disableButton) {
  102. var aButton = goog.dom.getElementsByTagName(
  103. goog.dom.TagName.BUTTON, dialog.getButtonElement())[0];
  104. assertNotEquals(aButton, null);
  105. aButton.disabled = disableButton;
  106. var wasCalled = false;
  107. var callRecorder = function() { wasCalled = true; };
  108. goog.events.listen(dialog, goog.ui.Dialog.EventType.SELECT, callRecorder);
  109. goog.testing.events.fireClickSequence(aButton);
  110. return wasCalled;
  111. }
  112. function testButtonClicksDispatchSelectEvents() {
  113. assertTrue(
  114. 'Select event should be dispatched' +
  115. ' when clicking on an enabled button',
  116. checkSelectDispatchedOnButtonClick(false));
  117. }
  118. function testDisabledButtonClicksDontDispatchSelectEvents() {
  119. assertFalse(
  120. 'Select event should not be dispatched' +
  121. ' when clicking on a disabled button',
  122. checkSelectDispatchedOnButtonClick(true));
  123. }
  124. function testEnterKeyDispatchesDefaultSelectEvents() {
  125. var okButton = goog.dom.getElementsByTagName(
  126. goog.dom.TagName.BUTTON, dialog.getButtonElement())[1];
  127. assertNotEquals(okButton, null);
  128. var wasCalled = false;
  129. var callRecorder = function() { wasCalled = true; };
  130. goog.events.listen(dialog, goog.ui.Dialog.EventType.SELECT, callRecorder);
  131. // Test that event is not dispatched when default button is disabled.
  132. okButton.disabled = true;
  133. goog.testing.events.fireKeySequence(
  134. dialog.getElement(), goog.events.KeyCodes.ENTER);
  135. assertFalse(wasCalled);
  136. // Test that event is dispatched when default button is enabled.
  137. okButton.disabled = false;
  138. goog.testing.events.fireKeySequence(
  139. dialog.getElement(), goog.events.KeyCodes.ENTER);
  140. assertTrue(wasCalled);
  141. }
  142. function testEnterKeyOnDisabledDefaultButtonDoesNotDispatchSelectEvents() {
  143. var okButton = goog.dom.getElementsByTagName(
  144. goog.dom.TagName.BUTTON, dialog.getButtonElement())[1];
  145. okButton.focus();
  146. var callRecorder = goog.testing.recordFunction();
  147. goog.events.listen(dialog, goog.ui.Dialog.EventType.SELECT, callRecorder);
  148. okButton.disabled = true;
  149. goog.testing.events.fireKeySequence(okButton, goog.events.KeyCodes.ENTER);
  150. assertEquals(0, callRecorder.getCallCount());
  151. okButton.disabled = false;
  152. goog.testing.events.fireKeySequence(okButton, goog.events.KeyCodes.ENTER);
  153. assertEquals(1, callRecorder.getCallCount());
  154. }
  155. function testEnterKeyDoesNothingOnSpecialFormElements() {
  156. checkEnterKeyDoesNothingOnSpecialFormElement(
  157. goog.html.SafeHtml.create('textarea', {}, 'Hello dialog'),
  158. 'TEXTAREA');
  159. checkEnterKeyDoesNothingOnSpecialFormElement(
  160. goog.html.SafeHtml.create('select', {}, 'Selection'),
  161. 'SELECT');
  162. checkEnterKeyDoesNothingOnSpecialFormElement(
  163. goog.html.SafeHtml.create('a', {'href': 'http://google.com'},
  164. 'Hello dialog'),
  165. 'A');
  166. }
  167. function checkEnterKeyDoesNothingOnSpecialFormElement(content, tagName) {
  168. dialog.setSafeHtmlContent(content);
  169. var formElement = dialog.getContentElement().getElementsByTagName(tagName)[0];
  170. var wasCalled = false;
  171. var callRecorder = function() { wasCalled = true; };
  172. goog.events.listen(dialog, goog.ui.Dialog.EventType.SELECT, callRecorder);
  173. // Enter does not fire on the enabled form element.
  174. goog.testing.events.fireKeySequence(formElement, goog.events.KeyCodes.ENTER);
  175. assertFalse(wasCalled);
  176. // Enter fires on the disabled form element.
  177. formElement.disabled = true;
  178. goog.testing.events.fireKeySequence(formElement, goog.events.KeyCodes.ENTER);
  179. assertTrue(wasCalled);
  180. }
  181. function testEscapeKeyDoesNothingOnSpecialFormElements() {
  182. dialog.setSafeHtmlContent(goog.html.SafeHtml.create('select', {}, [
  183. goog.html.SafeHtml.create('option', {}, 'Hello'),
  184. goog.html.SafeHtml.create('option', {}, 'dialog')
  185. ]));
  186. var select = dialog.getContentElement().getElementsByTagName('SELECT')[0];
  187. var wasCalled = false;
  188. var callRecorder = function() { wasCalled = true; };
  189. goog.events.listen(dialog, goog.ui.Dialog.EventType.SELECT, callRecorder);
  190. // Escape does not fire on the enabled select box.
  191. goog.testing.events.fireKeySequence(select, goog.events.KeyCodes.ESC);
  192. assertFalse(wasCalled);
  193. // Escape fires on the disabled select.
  194. select.disabled = true;
  195. goog.testing.events.fireKeySequence(select, goog.events.KeyCodes.ESC);
  196. assertTrue(wasCalled);
  197. }
  198. function testEscapeCloses() {
  199. // If escapeCloses is set to false, the dialog should ignore the escape key
  200. assertTrue(dialog.isEscapeToCancel());
  201. dialog.setEscapeToCancel(false);
  202. assertFalse(dialog.isEscapeToCancel());
  203. var buttons = new goog.ui.Dialog.ButtonSet();
  204. buttons.set(goog.ui.Dialog.DefaultButtonKeys.OK, 'OK', true);
  205. dialog.setButtonSet(buttons);
  206. goog.testing.events.fireKeySequence(
  207. dialog.getContentElement(), goog.events.KeyCodes.ESC);
  208. assertTrue(dialog.isVisible());
  209. // Having a cancel button should make no difference, escape should still not
  210. // work.
  211. buttons.set(goog.ui.Dialog.DefaultButtonKeys.CANCEL, 'Foo!', false, true);
  212. dialog.setButtonSet(buttons);
  213. goog.testing.events.fireKeySequence(
  214. dialog.getContentElement(), goog.events.KeyCodes.ESC);
  215. assertTrue(dialog.isVisible());
  216. }
  217. function testKeydownClosesWithoutButtonSet() {
  218. // Clear button set
  219. dialog.setButtonSet(null);
  220. // Create a custom button.
  221. dialog.setSafeHtmlContent(goog.html.SafeHtml.create('button',
  222. {'id': 'button', 'name': 'ok'},
  223. 'OK'));
  224. var wasCalled = false;
  225. function called() { wasCalled = true; }
  226. var element = goog.dom.getElement('button');
  227. goog.events.listen(element, goog.events.EventType.KEYPRESS, called);
  228. // Listen for 'Enter' on the button.
  229. // This tests using a dialog with no ButtonSet that has been set. Uses
  230. // a custom button. The callback should be called with no exception thrown.
  231. goog.testing.events.fireKeySequence(element, goog.events.KeyCodes.ENTER);
  232. assertTrue('Should have gotten event on the button.', wasCalled);
  233. }
  234. function testEnterKeyWithoutDefaultDoesNotPreventPropagation() {
  235. var buttons = new goog.ui.Dialog.ButtonSet();
  236. buttons.set(goog.ui.Dialog.DefaultButtonKeys.CANCEL, 'Foo!', false);
  237. // Set a button set without a default selected button
  238. dialog.setButtonSet(buttons);
  239. dialog.setSafeHtmlContent(goog.html.SafeHtml.create('span',
  240. {'id': 'linkel', 'tabindex': '0'},
  241. 'Link Span'));
  242. var call = false;
  243. function called() { call = true; }
  244. var element = document.getElementById('linkel');
  245. goog.events.listen(element, goog.events.EventType.KEYDOWN, called);
  246. goog.testing.events.fireKeySequence(element, goog.events.KeyCodes.ENTER);
  247. assertTrue('Should have gotten event on the link', call);
  248. }
  249. function testPreventDefaultedSelectCausesStopPropagation() {
  250. dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK_CANCEL);
  251. var callCount = 0;
  252. var keypressCount = 0;
  253. var keydownCount = 0;
  254. var preventDefaulter = function(e) { e.preventDefault(); };
  255. goog.events.listen(dialog, goog.ui.Dialog.EventType.SELECT, preventDefaulter);
  256. goog.events.listen(document.body, goog.events.EventType.KEYPRESS, function() {
  257. keypressCount++;
  258. });
  259. goog.events.listen(document.body, goog.events.EventType.KEYDOWN, function() {
  260. keydownCount++;
  261. });
  262. // Ensure that if the SELECT event is prevented, all key events
  263. // are still stopped from propagating.
  264. goog.testing.events.fireKeySequence(
  265. dialog.getElement(), goog.events.KeyCodes.ENTER);
  266. assertEquals('The KEYPRESS should be stopped', 0, keypressCount);
  267. assertEquals('The KEYDOWN should not be stopped', 1, keydownCount);
  268. keypressCount = 0;
  269. keydownCount = 0;
  270. goog.testing.events.fireKeySequence(
  271. dialog.getElement(), goog.events.KeyCodes.ESC);
  272. assertEquals('The KEYDOWN should be stopped', 0, keydownCount);
  273. // Note: Some browsers don't yield keypresses on escape, so don't check.
  274. goog.events.unlisten(
  275. dialog, goog.ui.Dialog.EventType.SELECT, preventDefaulter);
  276. keypressCount = 0;
  277. keydownCount = 0;
  278. goog.testing.events.fireKeySequence(
  279. dialog.getElement(), goog.events.KeyCodes.ENTER);
  280. assertEquals('The KEYPRESS should be stopped', 0, keypressCount);
  281. assertEquals('The KEYDOWN should not be stopped', 1, keydownCount);
  282. }
  283. function testEnterKeyHandledInKeypress() {
  284. var inKeyPress = false;
  285. goog.events.listen(document.body, goog.events.EventType.KEYPRESS, function() {
  286. inKeyPress = true;
  287. }, true /* capture */);
  288. goog.events.listen(document.body, goog.events.EventType.KEYPRESS, function() {
  289. inKeyPress = false;
  290. }, false /* !capture */);
  291. var selectCalled = false;
  292. goog.events.listen(dialog, goog.ui.Dialog.EventType.SELECT, function() {
  293. selectCalled = true;
  294. assertTrue(
  295. 'Select must be dispatched during keypress to allow popups',
  296. inKeyPress);
  297. });
  298. goog.testing.events.fireKeySequence(
  299. dialog.getElement(), goog.events.KeyCodes.ENTER);
  300. assertTrue(selectCalled);
  301. }
  302. function testShiftTabAtTopSetsUpWrapAndDoesNotPreventPropagation() {
  303. dialog.setupBackwardTabWrap = goog.testing.recordFunction();
  304. shiftTabRecorder = goog.testing.recordFunction();
  305. goog.events.listen(
  306. dialog.getElement(), goog.events.EventType.KEYDOWN, shiftTabRecorder);
  307. var shiftProperties = {shiftKey: true};
  308. goog.testing.events.fireKeySequence(
  309. dialog.getElement(), goog.events.KeyCodes.TAB, shiftProperties);
  310. assertNotNull(
  311. 'Should have gotten event on Shift+TAB', shiftTabRecorder.getLastCall());
  312. assertNotNull(
  313. 'Backward tab wrap should have been set up',
  314. dialog.setupBackwardTabWrap.getLastCall());
  315. }
  316. function testButtonsWithContentsDispatchSelectEvents() {
  317. var aButton = goog.dom.getElementsByTagName(
  318. goog.dom.TagName.BUTTON, dialog.getButtonElement())[0];
  319. var aSpan = goog.dom.createElement(goog.dom.TagName.SPAN);
  320. aButton.appendChild(aSpan);
  321. var wasCalled = false;
  322. var callRecorder = function() { wasCalled = true; };
  323. goog.events.listen(dialog, goog.ui.Dialog.EventType.SELECT, callRecorder);
  324. goog.testing.events.fireClickSequence(aSpan);
  325. assertTrue(wasCalled);
  326. }
  327. function testAfterHideEvent() {
  328. var wasCalled = false;
  329. var callRecorder = function() { wasCalled = true; };
  330. goog.events.listen(dialog, goog.ui.Dialog.EventType.AFTER_HIDE, callRecorder);
  331. dialog.setVisible(false);
  332. assertTrue(wasCalled);
  333. }
  334. function testAfterShowEvent() {
  335. dialog.setVisible(false);
  336. var wasCalled = false;
  337. var callRecorder = function() { wasCalled = true; };
  338. goog.events.listen(dialog, goog.ui.Dialog.EventType.AFTER_SHOW, callRecorder);
  339. dialog.setVisible(true);
  340. assertTrue(wasCalled);
  341. }
  342. function testCannedButtonSets() {
  343. dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK);
  344. assertButtons([goog.ui.Dialog.DefaultButtonKeys.OK]);
  345. dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK_CANCEL);
  346. assertButtons([
  347. goog.ui.Dialog.DefaultButtonKeys.OK, goog.ui.Dialog.DefaultButtonKeys.CANCEL
  348. ]);
  349. dialog.setButtonSet(goog.ui.Dialog.ButtonSet.YES_NO);
  350. assertButtons([
  351. goog.ui.Dialog.DefaultButtonKeys.YES, goog.ui.Dialog.DefaultButtonKeys.NO
  352. ]);
  353. dialog.setButtonSet(goog.ui.Dialog.ButtonSet.YES_NO_CANCEL);
  354. assertButtons([
  355. goog.ui.Dialog.DefaultButtonKeys.YES, goog.ui.Dialog.DefaultButtonKeys.NO,
  356. goog.ui.Dialog.DefaultButtonKeys.CANCEL
  357. ]);
  358. dialog.setButtonSet(goog.ui.Dialog.ButtonSet.CONTINUE_SAVE_CANCEL);
  359. assertButtons([
  360. goog.ui.Dialog.DefaultButtonKeys.CONTINUE,
  361. goog.ui.Dialog.DefaultButtonKeys.SAVE,
  362. goog.ui.Dialog.DefaultButtonKeys.CANCEL
  363. ]);
  364. }
  365. function testFactoryButtonSets() {
  366. dialog.setButtonSet(goog.ui.Dialog.ButtonSet.createOk());
  367. assertButtons([goog.ui.Dialog.DefaultButtonKeys.OK]);
  368. dialog.setButtonSet(goog.ui.Dialog.ButtonSet.createOkCancel());
  369. assertButtons([
  370. goog.ui.Dialog.DefaultButtonKeys.OK, goog.ui.Dialog.DefaultButtonKeys.CANCEL
  371. ]);
  372. dialog.setButtonSet(goog.ui.Dialog.ButtonSet.createYesNo());
  373. assertButtons([
  374. goog.ui.Dialog.DefaultButtonKeys.YES, goog.ui.Dialog.DefaultButtonKeys.NO
  375. ]);
  376. dialog.setButtonSet(goog.ui.Dialog.ButtonSet.createYesNoCancel());
  377. assertButtons([
  378. goog.ui.Dialog.DefaultButtonKeys.YES, goog.ui.Dialog.DefaultButtonKeys.NO,
  379. goog.ui.Dialog.DefaultButtonKeys.CANCEL
  380. ]);
  381. dialog.setButtonSet(goog.ui.Dialog.ButtonSet.createContinueSaveCancel());
  382. assertButtons([
  383. goog.ui.Dialog.DefaultButtonKeys.CONTINUE,
  384. goog.ui.Dialog.DefaultButtonKeys.SAVE,
  385. goog.ui.Dialog.DefaultButtonKeys.CANCEL
  386. ]);
  387. }
  388. function testDefaultButtonClassName() {
  389. var key = 'someKey';
  390. var msg = 'someMessage';
  391. var isDefault = false;
  392. var buttonSetOne = new goog.ui.Dialog.ButtonSet().set(key, msg, isDefault);
  393. dialog.setButtonSet(buttonSetOne);
  394. var defaultClassName = goog.getCssName(buttonSetOne.class_, 'default');
  395. var buttonOne = buttonSetOne.getButton(key);
  396. assertNotEquals(defaultClassName, buttonOne.className);
  397. var isDefault = true;
  398. var buttonSetTwo = new goog.ui.Dialog.ButtonSet().set(key, msg, isDefault);
  399. dialog.setButtonSet(buttonSetTwo);
  400. var buttonTwo = buttonSetTwo.getButton(key);
  401. assertEquals(defaultClassName, buttonTwo.className);
  402. }
  403. function testGetButton() {
  404. dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK);
  405. var buttons = document.getElementsByName(goog.ui.Dialog.DefaultButtonKeys.OK);
  406. assertEquals(
  407. buttons[0],
  408. dialog.getButtonSet().getButton(goog.ui.Dialog.DefaultButtonKeys.OK));
  409. }
  410. function testGetAllButtons() {
  411. dialog.setButtonSet(goog.ui.Dialog.ButtonSet.YES_NO_CANCEL);
  412. var buttons = goog.dom.getElementsByTagName(
  413. goog.dom.TagName.BUTTON, dialog.getElement());
  414. for (var i = 0; i < buttons.length; i++) {
  415. assertEquals(buttons[i], dialog.getButtonSet().getAllButtons()[i]);
  416. }
  417. }
  418. function testSetButtonEnabled() {
  419. var buttonSet = goog.ui.Dialog.ButtonSet.createYesNoCancel();
  420. dialog.setButtonSet(buttonSet);
  421. assertFalse(
  422. buttonSet.getButton(goog.ui.Dialog.DefaultButtonKeys.NO).disabled);
  423. buttonSet.setButtonEnabled(goog.ui.Dialog.DefaultButtonKeys.NO, false);
  424. assertTrue(buttonSet.getButton(goog.ui.Dialog.DefaultButtonKeys.NO).disabled);
  425. buttonSet.setButtonEnabled(goog.ui.Dialog.DefaultButtonKeys.NO, true);
  426. assertFalse(
  427. buttonSet.getButton(goog.ui.Dialog.DefaultButtonKeys.NO).disabled);
  428. }
  429. function testSetAllButtonsEnabled() {
  430. var buttonSet = goog.ui.Dialog.ButtonSet.createContinueSaveCancel();
  431. dialog.setButtonSet(buttonSet);
  432. var buttons = buttonSet.getAllButtons();
  433. for (var i = 0; i < buttons.length; i++) {
  434. assertFalse(buttons[i].disabled);
  435. }
  436. buttonSet.setAllButtonsEnabled(false);
  437. for (var i = 0; i < buttons.length; i++) {
  438. assertTrue(buttons[i].disabled);
  439. }
  440. buttonSet.setAllButtonsEnabled(true);
  441. for (var i = 0; i < buttons.length; i++) {
  442. assertFalse(buttons[i].disabled);
  443. }
  444. }
  445. function testIframeMask() {
  446. var prevNumFrames =
  447. goog.dom.getElementsByTagNameAndClass(goog.dom.TagName.IFRAME).length;
  448. // generate a new dialog
  449. dialog.dispose();
  450. dialog = new goog.ui.Dialog(null, true /* iframe mask */);
  451. dialog.setVisible(true);
  452. // Test that the dialog added one iframe to the document.
  453. // The absolute number of iframes should not be tested because,
  454. // in certain cases, the test runner itself can can add an iframe
  455. // to the document as part of a strategy not to block the UI for too long.
  456. // See goog.async.nextTick.getSetImmediateEmulator_.
  457. var curNumFrames =
  458. goog.dom.getElementsByTagNameAndClass(goog.dom.TagName.IFRAME).length;
  459. assertEquals('No iframe mask created', prevNumFrames + 1, curNumFrames);
  460. }
  461. function testNonModalDialog() {
  462. var prevNumFrames =
  463. goog.dom.getElementsByTagNameAndClass(goog.dom.TagName.IFRAME).length;
  464. // generate a new dialog
  465. dialog.dispose();
  466. dialog = new goog.ui.Dialog(null, true /* iframe mask */);
  467. dialog.setModal(false);
  468. assertAriaHidden(false);
  469. dialog.setVisible(true);
  470. assertAriaHidden(true);
  471. // Test that the dialog did not change the number of iframes in the document.
  472. // The absolute number of iframes should not be tested because,
  473. // in certain cases, the test runner itself can can add an iframe
  474. // to the document as part of a strategy not to block the UI for too long.
  475. // See goog.async.nextTick.getSetImmediateEmulator_.
  476. var curNumFrames =
  477. goog.dom.getElementsByTagNameAndClass(goog.dom.TagName.IFRAME).length;
  478. assertEquals(
  479. 'Iframe mask created for modal dialog', prevNumFrames, curNumFrames);
  480. }
  481. function testSwapModalForOpenDialog() {
  482. dialog.dispose();
  483. dialog = new goog.ui.Dialog(null, true /* iframe mask */);
  484. assertAriaHidden(false);
  485. dialog.setVisible(true);
  486. assertAriaHidden(true);
  487. dialog.setModal(false);
  488. assertAriaHidden(false);
  489. assertFalse(
  490. 'IFrame bg element should not be in dom',
  491. goog.dom.contains(document.body, dialog.getBackgroundIframe()));
  492. assertFalse(
  493. 'bg element should not be in dom',
  494. goog.dom.contains(document.body, dialog.getBackgroundElement()));
  495. dialog.setModal(true);
  496. assertAriaHidden(true);
  497. assertTrue(
  498. 'IFrame bg element should be in dom',
  499. goog.dom.contains(document.body, dialog.getBackgroundIframe()));
  500. assertTrue(
  501. 'bg element should be in dom',
  502. goog.dom.contains(document.body, dialog.getBackgroundElement()));
  503. assertEquals(
  504. 'IFrame bg element is a child of body', document.body,
  505. dialog.getBackgroundIframe().parentNode);
  506. assertEquals(
  507. 'bg element is a child of body', document.body,
  508. dialog.getBackgroundElement().parentNode);
  509. assertTrue(
  510. 'IFrame bg element should visible',
  511. goog.style.isElementShown(dialog.getBackgroundIframe()));
  512. assertTrue(
  513. 'bg element should be visible',
  514. goog.style.isElementShown(dialog.getBackgroundElement()));
  515. }
  516. /**
  517. * Assert that the dialog has buttons with the given keys in the correct
  518. * order.
  519. * @param {Array<string>} keys An array of button keys.
  520. */
  521. function assertButtons(keys) {
  522. var buttons = goog.dom.getElementsByTagName(
  523. goog.dom.TagName.BUTTON, dialog.getElement());
  524. var actualKeys = [];
  525. for (var i = 0; i < buttons.length; i++) {
  526. actualKeys[i] = buttons[i].name;
  527. }
  528. assertArrayEquals(keys, actualKeys);
  529. }
  530. function testButtonSetOkFiresDialogEventOnEscape() {
  531. dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK);
  532. var wasCalled = false;
  533. var callRecorder = function() { wasCalled = true; };
  534. goog.events.listen(dialog, goog.ui.Dialog.EventType.SELECT, callRecorder);
  535. goog.testing.events.fireKeySequence(
  536. dialog.getElement(), goog.events.KeyCodes.ESC);
  537. assertTrue(wasCalled);
  538. }
  539. function testHideButtons_afterRender() {
  540. dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK);
  541. assertTrue(goog.style.isElementShown(dialog.buttonEl_));
  542. dialog.setButtonSet(null);
  543. assertFalse(goog.style.isElementShown(dialog.buttonEl_));
  544. dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK);
  545. assertTrue(goog.style.isElementShown(dialog.buttonEl_));
  546. }
  547. function testHideButtons_beforeRender() {
  548. dialog.dispose();
  549. dialog = new goog.ui.Dialog();
  550. dialog.setButtonSet(null);
  551. dialog.setVisible(true);
  552. assertFalse(goog.style.isElementShown(dialog.buttonEl_));
  553. dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK);
  554. assertTrue(goog.style.isElementShown(dialog.buttonEl_));
  555. }
  556. function testHideButtons_beforeDecorate() {
  557. dialog.dispose();
  558. dialog = new goog.ui.Dialog();
  559. dialog.setButtonSet(null);
  560. dialog.decorate(decorateTarget);
  561. dialog.setVisible(true);
  562. assertFalse(goog.style.isElementShown(dialog.buttonEl_));
  563. dialog.setButtonSet(goog.ui.Dialog.ButtonSet.OK);
  564. assertTrue(goog.style.isElementShown(dialog.buttonEl_));
  565. }
  566. function testAriaLabelledBy_render() {
  567. dialog.dispose();
  568. dialog = new goog.ui.Dialog();
  569. dialog.render();
  570. assertTrue(!!dialog.getTitleTextElement().id);
  571. assertNotNull(dialog.getElement());
  572. assertEquals(
  573. dialog.getTitleTextElement().id,
  574. goog.a11y.aria.getState(dialog.getElement(), 'labelledby'));
  575. }
  576. function testAriaLabelledBy_decorate() {
  577. dialog.dispose();
  578. dialog = new goog.ui.Dialog();
  579. dialog.decorate(decorateTarget);
  580. dialog.setVisible(true);
  581. assertTrue(!!dialog.getTitleTextElement().id);
  582. assertNotNull(dialog.getElement());
  583. assertEquals(
  584. dialog.getTitleTextElement().id,
  585. goog.a11y.aria.getState(dialog.getElement(), 'labelledby'));
  586. }
  587. function testPreferredAriaRole_renderDefault() {
  588. dialog.dispose();
  589. dialog = new goog.ui.Dialog();
  590. dialog.render();
  591. assertNotNull(dialog.getElement());
  592. assertEquals(
  593. dialog.getPreferredAriaRole(),
  594. goog.a11y.aria.getRole(dialog.getElement()));
  595. }
  596. function testPreferredAriaRole_decorateDefault() {
  597. dialog.dispose();
  598. dialog = new goog.ui.Dialog();
  599. dialog.decorate(decorateTarget);
  600. assertNotNull(dialog.getElement());
  601. assertEquals(
  602. dialog.getPreferredAriaRole(),
  603. goog.a11y.aria.getRole(dialog.getElement()));
  604. }
  605. function testPreferredAriaRole_renderOverride() {
  606. dialog.dispose();
  607. dialog = new goog.ui.Dialog();
  608. dialog.setPreferredAriaRole(goog.a11y.aria.Role.ALERTDIALOG);
  609. dialog.render();
  610. assertNotNull(dialog.getElement());
  611. assertEquals(
  612. goog.a11y.aria.Role.ALERTDIALOG,
  613. goog.a11y.aria.getRole(dialog.getElement()));
  614. }
  615. function testPreferredAriaRole_decorateOverride() {
  616. dialog.dispose();
  617. dialog = new goog.ui.Dialog();
  618. dialog.setPreferredAriaRole(goog.a11y.aria.Role.ALERTDIALOG);
  619. dialog.decorate(decorateTarget);
  620. assertNotNull(dialog.getElement());
  621. assertEquals(
  622. goog.a11y.aria.Role.ALERTDIALOG,
  623. goog.a11y.aria.getRole(dialog.getElement()));
  624. }
  625. function testDefaultOpacityIsAppliedOnRender() {
  626. dialog.dispose();
  627. dialog = new goog.ui.Dialog();
  628. dialog.render();
  629. assertEquals(0.5, goog.style.getOpacity(dialog.getBackgroundElement()));
  630. }
  631. function testDefaultOpacityIsAppliedOnDecorate() {
  632. dialog.dispose();
  633. dialog = new goog.ui.Dialog();
  634. dialog.decorate(decorateTarget);
  635. assertEquals(0.5, goog.style.getOpacity(dialog.getBackgroundElement()));
  636. }
  637. function testDraggableStyle() {
  638. assertTrue(
  639. 'draggable CSS class is set',
  640. goog.dom.classlist.contains(
  641. dialog.titleEl_, 'modal-dialog-title-draggable'));
  642. dialog.setDraggable(false);
  643. assertFalse(
  644. 'draggable CSS class is removed',
  645. goog.dom.classlist.contains(
  646. dialog.titleEl_, 'modal-dialog-title-draggable'));
  647. }
  648. function testDraggingLifecycle() {
  649. dialog.dispose();
  650. dialog = new goog.ui.Dialog();
  651. dialog.setDraggerLimits_ = goog.testing.recordFunction();
  652. dialog.createDom();
  653. assertNull('dragger is not created in createDom', dialog.dragger_);
  654. dialog.setVisible(true);
  655. assertNotNull(
  656. 'dragger is created when the dialog is rendered', dialog.dragger_);
  657. assertNull(
  658. 'dragging limits are not set just before dragging',
  659. dialog.setDraggerLimits_.getLastCall());
  660. goog.testing.events.fireMouseDownEvent(dialog.titleEl_);
  661. assertNotNull(
  662. 'dragging limits are set', dialog.setDraggerLimits_.getLastCall());
  663. dialog.exitDocument();
  664. assertNull('dragger is cleaned up in exitDocument', dialog.dragger_);
  665. }
  666. function testDisposingVisibleDialogWithTransitionsDoesNotThrowException() {
  667. var transition = goog.fx.css3.fadeIn(dialog.getElement(), 0.1 /* duration */);
  668. dialog.setTransition(transition, transition, transition, transition);
  669. dialog.setVisible(true);
  670. dialog.dispose();
  671. // Nothing to assert. We only want to ensure that there is no error.
  672. }
  673. function testEventsDuringAnimation() {
  674. dialog.dispose();
  675. dialog = new goog.ui.Dialog();
  676. dialog.render();
  677. dialog.setTransition(
  678. goog.fx.css3.fadeIn(dialog.getElement(), 1),
  679. goog.fx.css3.fadeIn(dialog.getBackgroundElement(), 1),
  680. goog.fx.css3.fadeOut(dialog.getElement(), 1),
  681. goog.fx.css3.fadeOut(dialog.getBackgroundElement(), 1));
  682. dialog.setVisible(true);
  683. assertTrue(dialog.isVisible());
  684. var buttonSet = dialog.getButtonSet();
  685. var button = buttonSet.getButton(buttonSet.getDefault());
  686. // The button event fires while the animation is still going.
  687. goog.testing.events.fireClickSequence(button);
  688. mockClock.tick(2000);
  689. assertFalse(dialog.isVisible());
  690. }
  691. function testHtmlContent() {
  692. dialog.setSafeHtmlContent(
  693. goog.html.testing.newSafeHtmlForTest(
  694. '<span class="theSpan">Hello</span>'));
  695. var spanEl =
  696. goog.dom.getElementByClass('theSpan', dialog.getContentElement());
  697. assertEquals('Hello', goog.dom.getTextContent(spanEl));
  698. assertEquals('<span class="theSpan">Hello</span>', dialog.getContent());
  699. assertEquals(
  700. '<span class="theSpan">Hello</span>',
  701. goog.html.SafeHtml.unwrap(dialog.getSafeHtmlContent()));
  702. }
  703. function testSetTextContent() {
  704. dialog.setTextContent('Dinner <3\nTogether');
  705. assertEquals('Dinner &lt;3<br>Together', dialog.getContent());
  706. }
  707. function testFocus() {
  708. // Focus should go to the dialog element.
  709. document.body.focus();
  710. dialog.focus();
  711. assertEquals(dialog.getElement(), document.activeElement);
  712. }
  713. // Asserts that a test element which is a child of the document body has the
  714. // aria property 'hidden' set on it, or not.
  715. function assertAriaHidden(expectedHidden) {
  716. var expectedString = expectedHidden ? 'true' : '';
  717. assertEquals(
  718. expectedString,
  719. goog.a11y.aria.getState(bodyChildElement, goog.a11y.aria.State.HIDDEN));
  720. }