controlrenderer_test.js 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273
  1. // Copyright 2008 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.ControlRendererTest');
  15. goog.setTestOnly('goog.ui.ControlRendererTest');
  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.NodeType');
  21. goog.require('goog.dom.TagName');
  22. goog.require('goog.dom.classlist');
  23. goog.require('goog.object');
  24. goog.require('goog.style');
  25. goog.require('goog.testing.ExpectedFailures');
  26. goog.require('goog.testing.PropertyReplacer');
  27. goog.require('goog.testing.jsunit');
  28. goog.require('goog.ui.Component');
  29. goog.require('goog.ui.Control');
  30. goog.require('goog.ui.ControlRenderer');
  31. goog.require('goog.userAgent');
  32. var control, controlRenderer, testRenderer, propertyReplacer;
  33. var sandbox;
  34. var expectedFailures;
  35. function setUpPage() {
  36. sandbox = goog.dom.getElement('sandbox');
  37. expectedFailures = new goog.testing.ExpectedFailures();
  38. }
  39. /**
  40. * A subclass of ControlRenderer that overrides {@code getAriaRole} and
  41. * {@code getStructuralCssClass} for testing purposes.
  42. * @constructor
  43. * @extends {goog.ui.ControlRenderer}
  44. */
  45. function TestRenderer() {
  46. goog.ui.ControlRenderer.call(this);
  47. }
  48. goog.inherits(TestRenderer, goog.ui.ControlRenderer);
  49. goog.addSingletonGetter(TestRenderer);
  50. TestRenderer.CSS_CLASS = 'goog-button';
  51. TestRenderer.IE6_CLASS_COMBINATIONS = [
  52. ['combined', 'goog-base-hover', 'goog-button'],
  53. ['combined', 'goog-base-disabled', 'goog-button'],
  54. ['combined', 'combined2', 'goog-base-hover', 'goog-base-rtl', 'goog-button']
  55. ];
  56. /** @override */
  57. TestRenderer.prototype.getAriaRole = function() {
  58. return goog.a11y.aria.Role.BUTTON;
  59. };
  60. /** @override */
  61. TestRenderer.prototype.getCssClass = function() {
  62. return TestRenderer.CSS_CLASS;
  63. };
  64. /** @override */
  65. TestRenderer.prototype.getStructuralCssClass = function() {
  66. return 'goog-base';
  67. };
  68. /** @override */
  69. TestRenderer.prototype.getIe6ClassCombinations = function() {
  70. return TestRenderer.IE6_CLASS_COMBINATIONS;
  71. };
  72. /**
  73. * @return {boolean} Whether we're on Mac Safari 3.x.
  74. */
  75. function isMacSafari3() {
  76. return goog.userAgent.WEBKIT && goog.userAgent.MAC &&
  77. !goog.userAgent.isVersionOrHigher('527');
  78. }
  79. /**
  80. * @return {boolean} Whether we're on IE6 or lower.
  81. */
  82. function isIe6() {
  83. return goog.userAgent.IE && !goog.userAgent.isVersionOrHigher('7');
  84. }
  85. function setUp() {
  86. control = new goog.ui.Control('Hello');
  87. controlRenderer = goog.ui.ControlRenderer.getInstance();
  88. testRenderer = TestRenderer.getInstance();
  89. propertyReplacer = new goog.testing.PropertyReplacer();
  90. }
  91. function tearDown() {
  92. propertyReplacer.reset();
  93. control.dispose();
  94. expectedFailures.handleTearDown();
  95. control = null;
  96. controlRenderer = null;
  97. testRenderer = null;
  98. goog.dom.removeChildren(sandbox);
  99. }
  100. function testConstructor() {
  101. assertNotNull(
  102. 'ControlRenderer singleton instance must not be null', controlRenderer);
  103. assertNotNull(
  104. 'TestRenderer singleton instance must not be null', testRenderer);
  105. }
  106. function testGetCustomRenderer() {
  107. var cssClass = 'special-css-class';
  108. var renderer = goog.ui.ControlRenderer.getCustomRenderer(
  109. goog.ui.ControlRenderer, cssClass);
  110. assertEquals(
  111. 'Renderer should have returned the custom CSS class.', cssClass,
  112. renderer.getCssClass());
  113. }
  114. function testGetAriaRole() {
  115. assertUndefined(
  116. 'ControlRenderer\'s ARIA role must be undefined',
  117. controlRenderer.getAriaRole());
  118. assertEquals(
  119. 'TestRenderer\'s ARIA role must have expected value',
  120. goog.a11y.aria.Role.BUTTON, testRenderer.getAriaRole());
  121. }
  122. function testCreateDom() {
  123. assertHTMLEquals(
  124. 'ControlRenderer must create correct DOM',
  125. '<div class="goog-control">Hello</div>',
  126. goog.dom.getOuterHtml(controlRenderer.createDom(control)));
  127. assertHTMLEquals(
  128. 'TestRenderer must create correct DOM',
  129. '<div class="goog-button goog-base">Hello</div>',
  130. goog.dom.getOuterHtml(testRenderer.createDom(control)));
  131. }
  132. function testGetContentElement() {
  133. assertEquals(
  134. 'getContentElement() must return its argument', sandbox,
  135. controlRenderer.getContentElement(sandbox));
  136. }
  137. function testEnableExtraClassName() {
  138. // enableExtraClassName() must be a no-op if control has no DOM.
  139. controlRenderer.enableExtraClassName(control, 'foo', true);
  140. control.createDom();
  141. var element = control.getElement();
  142. controlRenderer.enableExtraClassName(control, 'foo', true);
  143. assertSameElements(
  144. 'Extra class name must have been added', ['goog-control', 'foo'],
  145. goog.dom.classlist.get(element));
  146. controlRenderer.enableExtraClassName(control, 'foo', true);
  147. assertSameElements(
  148. 'Enabling existing extra class name must be a no-op',
  149. ['goog-control', 'foo'], goog.dom.classlist.get(element));
  150. controlRenderer.enableExtraClassName(control, 'bar', false);
  151. assertSameElements(
  152. 'Disabling nonexistent class name must be a no-op',
  153. ['goog-control', 'foo'], goog.dom.classlist.get(element));
  154. controlRenderer.enableExtraClassName(control, 'foo', false);
  155. assertSameElements(
  156. 'Extra class name must have been removed', ['goog-control'],
  157. goog.dom.classlist.get(element));
  158. }
  159. function testCanDecorate() {
  160. assertTrue('canDecorate() must return true', controlRenderer.canDecorate());
  161. }
  162. function testDecorate() {
  163. sandbox.innerHTML = '<div id="foo">Hello, world!</div>';
  164. var foo = goog.dom.getElement('foo');
  165. var element = controlRenderer.decorate(control, foo);
  166. assertEquals('decorate() must return its argument', foo, element);
  167. assertEquals('Decorated control\'s ID must be set', 'foo', control.getId());
  168. assertTrue(
  169. 'Decorated control\'s content must be a text node',
  170. control.getContent().nodeType == goog.dom.NodeType.TEXT);
  171. assertEquals(
  172. 'Decorated control\'s content must have expected value', 'Hello, world!',
  173. control.getContent().nodeValue);
  174. assertEquals(
  175. 'Decorated control\'s state must be as expected', 0x00,
  176. control.getState());
  177. assertSameElements(
  178. 'Decorated element\'s classes must be as expected', ['goog-control'],
  179. goog.dom.classlist.get(element));
  180. }
  181. function testDecorateComplexDom() {
  182. sandbox.innerHTML = '<div id="foo"><i>Hello</i>,<b>world</b>!</div>';
  183. var foo = goog.dom.getElement('foo');
  184. var element = controlRenderer.decorate(control, foo);
  185. assertEquals('decorate() must return its argument', foo, element);
  186. assertEquals('Decorated control\'s ID must be set', 'foo', control.getId());
  187. assertTrue(
  188. 'Decorated control\'s content must be an array',
  189. goog.isArray(control.getContent()));
  190. assertEquals(
  191. 'Decorated control\'s content must have expected length', 4,
  192. control.getContent().length);
  193. assertEquals(
  194. 'Decorated control\'s state must be as expected', 0x00,
  195. control.getState());
  196. assertSameElements(
  197. 'Decorated element\'s classes must be as expected', ['goog-control'],
  198. goog.dom.classlist.get(element));
  199. }
  200. function testDecorateWithClasses() {
  201. sandbox.innerHTML =
  202. '<div id="foo" class="app goog-base-disabled goog-base-hover"></div>';
  203. var foo = goog.dom.getElement('foo');
  204. control.addClassName('extra');
  205. var element = testRenderer.decorate(control, foo);
  206. assertEquals('decorate() must return its argument', foo, element);
  207. assertEquals('Decorated control\'s ID must be set', 'foo', control.getId());
  208. assertNull('Decorated control\'s content must be null', control.getContent());
  209. assertEquals(
  210. 'Decorated control\'s state must be as expected',
  211. goog.ui.Component.State.DISABLED | goog.ui.Component.State.HOVER,
  212. control.getState());
  213. assertSameElements(
  214. 'Decorated element\'s classes must be as expected',
  215. [
  216. 'app', 'extra', 'goog-base', 'goog-base-disabled', 'goog-base-hover',
  217. 'goog-button'
  218. ],
  219. goog.dom.classlist.get(element));
  220. }
  221. function testDecorateOptimization() {
  222. // Temporarily replace goog.dom.classlist.set().
  223. propertyReplacer.set(goog.dom.classlist, 'set', function() {
  224. fail('goog.dom.classlist.set() must not be called');
  225. });
  226. // Since foo has all required classes, goog.dom.classlist.set() must not be
  227. // called at all.
  228. sandbox.innerHTML = '<div id="foo" class="goog-control">Foo</div>';
  229. controlRenderer.decorate(control, goog.dom.getElement('foo'));
  230. // Since bar has all required classes, goog.dom.classlist.set() must not be
  231. // called at all.
  232. sandbox.innerHTML = '<div id="bar" class="goog-base goog-button">Bar' +
  233. '</div>';
  234. testRenderer.decorate(control, goog.dom.getElement('bar'));
  235. // Since baz has all required classes, goog.dom.classlist.set() must not be
  236. // called at all.
  237. sandbox.innerHTML = '<div id="baz" class="goog-base goog-button ' +
  238. 'goog-button-disabled">Baz</div>';
  239. testRenderer.decorate(control, goog.dom.getElement('baz'));
  240. }
  241. function testInitializeDom() {
  242. var renderer = new goog.ui.ControlRenderer();
  243. // Replace setRightToLeft().
  244. renderer.setRightToLeft = function() {
  245. fail('setRightToLeft() must not be called');
  246. };
  247. // When a control with default render direction enters the document,
  248. // setRightToLeft() must not be called.
  249. control.setRenderer(renderer);
  250. control.render(sandbox);
  251. // When a control in the default state (enabled, visible, focusable)
  252. // enters the document, it must get a tab index.
  253. // Expected to fail on Mac Safari 3, because it doesn't support tab index.
  254. expectedFailures.expectFailureFor(isMacSafari3());
  255. try {
  256. assertTrue(
  257. 'Enabled, visible, focusable control must have tab index',
  258. goog.dom.isFocusableTabIndex(control.getElement()));
  259. } catch (e) {
  260. expectedFailures.handleException(e);
  261. }
  262. }
  263. function testInitializeDomDecorated() {
  264. var renderer = new goog.ui.ControlRenderer();
  265. // Replace setRightToLeft().
  266. renderer.setRightToLeft = function() {
  267. fail('setRightToLeft() must not be called');
  268. };
  269. sandbox.innerHTML = '<div id="foo" class="goog-control">Foo</div>';
  270. // When a control with default render direction enters the document,
  271. // setRightToLeft() must not be called.
  272. control.setRenderer(renderer);
  273. control.decorate(goog.dom.getElement('foo'));
  274. // When a control in the default state (enabled, visible, focusable)
  275. // enters the document, it must get a tab index.
  276. // Expected to fail on Mac Safari 3, because it doesn't support tab index.
  277. expectedFailures.expectFailureFor(isMacSafari3());
  278. try {
  279. assertTrue(
  280. 'Enabled, visible, focusable control must have tab index',
  281. goog.dom.isFocusableTabIndex(control.getElement()));
  282. } catch (e) {
  283. expectedFailures.handleException(e);
  284. }
  285. }
  286. function testInitializeDomDisabledBiDi() {
  287. var renderer = new goog.ui.ControlRenderer();
  288. // Replace setFocusable().
  289. renderer.setFocusable = function() {
  290. fail('setFocusable() must not be called');
  291. };
  292. // When a disabled control enters the document, setFocusable() must not
  293. // be called.
  294. control.setEnabled(false);
  295. control.setRightToLeft(true);
  296. control.setRenderer(renderer);
  297. control.render(sandbox);
  298. // When a right-to-left control enters the document, special stying must
  299. // be applied.
  300. assertSameElements(
  301. 'BiDi control must have right-to-left class',
  302. ['goog-control', 'goog-control-disabled', 'goog-control-rtl'],
  303. goog.dom.classlist.get(control.getElement()));
  304. }
  305. function testInitializeDomDisabledBiDiDecorated() {
  306. var renderer = new goog.ui.ControlRenderer();
  307. // Replace setFocusable().
  308. renderer.setFocusable = function() {
  309. fail('setFocusable() must not be called');
  310. };
  311. sandbox.innerHTML = '<div dir="rtl">\n' +
  312. ' <div id="foo" class="goog-control-disabled">Foo</div>\n' +
  313. '</div>\n';
  314. // When a disabled control enters the document, setFocusable() must not
  315. // be called.
  316. control.setRenderer(renderer);
  317. control.decorate(goog.dom.getElement('foo'));
  318. // When a right-to-left control enters the document, special stying must
  319. // be applied.
  320. assertSameElements(
  321. 'BiDi control must have right-to-left class',
  322. ['goog-control', 'goog-control-disabled', 'goog-control-rtl'],
  323. goog.dom.classlist.get(control.getElement()));
  324. }
  325. function testSetAriaRole() {
  326. sandbox.innerHTML = '<div id="foo">Foo</div><div id="bar">Bar</div>';
  327. var foo = goog.dom.getElement('foo');
  328. assertNotNull(foo);
  329. controlRenderer.setAriaRole(foo);
  330. assertEvaluatesToFalse(
  331. 'The role should be empty.', goog.a11y.aria.getRole(foo));
  332. var bar = goog.dom.getElement('bar');
  333. assertNotNull(bar);
  334. testRenderer.setAriaRole(bar);
  335. assertEquals(
  336. 'Element must have expected ARIA role', goog.a11y.aria.Role.BUTTON,
  337. goog.a11y.aria.getRole(bar));
  338. }
  339. function testSetAriaStatesHidden() {
  340. sandbox.innerHTML = '<div id="foo">Foo</div><div id="bar">Bar</div>';
  341. var foo = goog.dom.getElement('foo');
  342. control.setVisible(true);
  343. controlRenderer.setAriaStates(control, foo);
  344. assertEquals(
  345. 'ControlRenderer did not set aria-hidden.', '',
  346. goog.a11y.aria.getState(foo, goog.a11y.aria.State.HIDDEN));
  347. control.setVisible(false);
  348. controlRenderer.setAriaStates(control, foo);
  349. assertEquals(
  350. 'ControlRenderer did not set aria-hidden.', 'true',
  351. goog.a11y.aria.getState(foo, goog.a11y.aria.State.HIDDEN));
  352. }
  353. function testSetAriaStatesDisabled() {
  354. sandbox.innerHTML = '<div id="foo">Foo</div><div id="bar">Bar</div>';
  355. var foo = goog.dom.getElement('foo');
  356. control.setEnabled(true);
  357. controlRenderer.setAriaStates(control, foo);
  358. assertEquals(
  359. 'ControlRenderer did not set aria-disabled.', '',
  360. goog.a11y.aria.getState(foo, goog.a11y.aria.State.DISABLED));
  361. control.setEnabled(false);
  362. controlRenderer.setAriaStates(control, foo);
  363. assertEquals(
  364. 'ControlRenderer did not set aria-disabled.', 'true',
  365. goog.a11y.aria.getState(foo, goog.a11y.aria.State.DISABLED));
  366. }
  367. function testSetAriaStatesSelected() {
  368. sandbox.innerHTML = '<div id="foo">Foo</div><div id="bar">Bar</div>';
  369. var foo = goog.dom.getElement('foo');
  370. control.setSupportedState(goog.ui.Component.State.SELECTED, true);
  371. control.setSelected(true);
  372. controlRenderer.setAriaStates(control, foo);
  373. assertEquals(
  374. 'ControlRenderer did not set aria-selected.', 'true',
  375. goog.a11y.aria.getState(foo, goog.a11y.aria.State.SELECTED));
  376. control.setSelected(false);
  377. controlRenderer.setAriaStates(control, foo);
  378. assertEquals(
  379. 'ControlRenderer did not set aria-selected.', 'false',
  380. goog.a11y.aria.getState(foo, goog.a11y.aria.State.SELECTED));
  381. }
  382. function testSetAriaStatesChecked() {
  383. sandbox.innerHTML = '<div id="foo">Foo</div><div id="bar">Bar</div>';
  384. var foo = goog.dom.getElement('foo');
  385. control.setSupportedState(goog.ui.Component.State.CHECKED, true);
  386. control.setChecked(true);
  387. controlRenderer.setAriaStates(control, foo);
  388. assertEquals(
  389. 'ControlRenderer did not set aria-checked.', 'true',
  390. goog.a11y.aria.getState(foo, goog.a11y.aria.State.CHECKED));
  391. control.setChecked(false);
  392. controlRenderer.setAriaStates(control, foo);
  393. assertEquals(
  394. 'ControlRenderer did not set aria-checked.', 'false',
  395. goog.a11y.aria.getState(foo, goog.a11y.aria.State.CHECKED));
  396. }
  397. function testSetAriaStatesExpanded() {
  398. sandbox.innerHTML = '<div id="foo">Foo</div><div id="bar">Bar</div>';
  399. var foo = goog.dom.getElement('foo');
  400. control.setSupportedState(goog.ui.Component.State.OPENED, true);
  401. control.setOpen(true);
  402. controlRenderer.setAriaStates(control, foo);
  403. assertEquals(
  404. 'ControlRenderer did not set aria-expanded.', 'true',
  405. goog.a11y.aria.getState(foo, goog.a11y.aria.State.EXPANDED));
  406. control.setOpen(false);
  407. controlRenderer.setAriaStates(control, foo);
  408. assertEquals(
  409. 'ControlRenderer did not set aria-expanded.', 'false',
  410. goog.a11y.aria.getState(foo, goog.a11y.aria.State.EXPANDED));
  411. }
  412. function testSetAllowTextSelection() {
  413. sandbox.innerHTML = '<div id="foo"><span>Foo</span></div>';
  414. var foo = goog.dom.getElement('foo');
  415. controlRenderer.setAllowTextSelection(foo, false);
  416. assertTrue(
  417. 'Parent element must be unselectable on all browsers',
  418. goog.style.isUnselectable(foo));
  419. if (goog.userAgent.IE || goog.userAgent.OPERA) {
  420. assertTrue(
  421. 'On IE and Opera, child element must also be unselectable',
  422. goog.style.isUnselectable(foo.firstChild));
  423. } else {
  424. assertFalse(
  425. 'On browsers other than IE and Opera, the child element ' +
  426. 'must not be unselectable',
  427. goog.style.isUnselectable(foo.firstChild));
  428. }
  429. controlRenderer.setAllowTextSelection(foo, true);
  430. assertFalse(
  431. 'Parent element must be selectable', goog.style.isUnselectable(foo));
  432. assertFalse(
  433. 'Child element must be unselectable',
  434. goog.style.isUnselectable(foo.firstChild));
  435. }
  436. function testSetRightToLeft() {
  437. sandbox.innerHTML = '<div id="foo">Foo</div><div id="bar">Bar</div>';
  438. var foo = goog.dom.getElement('foo');
  439. controlRenderer.setRightToLeft(foo, true);
  440. assertSameElements(
  441. 'Element must have right-to-left class applied', ['goog-control-rtl'],
  442. goog.dom.classlist.get(foo));
  443. controlRenderer.setRightToLeft(foo, false);
  444. assertSameElements(
  445. 'Element must not have right-to-left class applied', [],
  446. goog.dom.classlist.get(foo));
  447. var bar = goog.dom.getElement('bar');
  448. testRenderer.setRightToLeft(bar, true);
  449. assertSameElements(
  450. 'Element must have right-to-left class applied', ['goog-base-rtl'],
  451. goog.dom.classlist.get(bar));
  452. testRenderer.setRightToLeft(bar, false);
  453. assertSameElements(
  454. 'Element must not have right-to-left class applied', [],
  455. goog.dom.classlist.get(bar));
  456. }
  457. function testIsFocusable() {
  458. control.render(sandbox);
  459. // Expected to fail on Mac Safari 3, because it doesn't support tab index.
  460. expectedFailures.expectFailureFor(isMacSafari3());
  461. try {
  462. assertTrue(
  463. 'Control\'s key event target must be focusable',
  464. controlRenderer.isFocusable(control));
  465. } catch (e) {
  466. expectedFailures.handleException(e);
  467. }
  468. }
  469. function testIsFocusableForNonFocusableControl() {
  470. control.setSupportedState(goog.ui.Component.State.FOCUSED, false);
  471. control.render(sandbox);
  472. assertFalse(
  473. 'Non-focusable control\'s key event target must not be ' +
  474. 'focusable',
  475. controlRenderer.isFocusable(control));
  476. }
  477. function testIsFocusableForControlWithoutKeyEventTarget() {
  478. // Unrendered control has no key event target.
  479. assertNull(
  480. 'Unrendered control must not have key event target',
  481. control.getKeyEventTarget());
  482. assertFalse(
  483. 'isFocusable() must return null if no key event target',
  484. controlRenderer.isFocusable(control));
  485. }
  486. function testSetFocusable() {
  487. control.render(sandbox);
  488. controlRenderer.setFocusable(control, false);
  489. assertFalse(
  490. 'Control\'s key event target must not have tab index',
  491. goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
  492. controlRenderer.setFocusable(control, true);
  493. // Expected to fail on Mac Safari 3, because it doesn't support tab index.
  494. expectedFailures.expectFailureFor(isMacSafari3());
  495. try {
  496. assertTrue(
  497. 'Control\'s key event target must have focusable tab index',
  498. goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
  499. } catch (e) {
  500. expectedFailures.handleException(e);
  501. }
  502. }
  503. function testSetFocusableForNonFocusableControl() {
  504. control.setSupportedState(goog.ui.Component.State.FOCUSED, false);
  505. control.render(sandbox);
  506. assertFalse(
  507. 'Non-focusable control\'s key event target must not be ' +
  508. 'focusable',
  509. goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
  510. controlRenderer.setFocusable(control, true);
  511. assertFalse(
  512. 'Non-focusable control\'s key event target must not be ' +
  513. 'focusable, even after calling setFocusable(true)',
  514. goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
  515. }
  516. function testSetVisible() {
  517. sandbox.innerHTML = '<div id="foo">Foo</div>';
  518. var foo = goog.dom.getElement('foo');
  519. assertTrue('Element must be visible', foo.style.display != 'none');
  520. controlRenderer.setVisible(foo, true);
  521. assertEquals(
  522. 'ControlRenderer did not set aria-hidden.', 'false',
  523. goog.a11y.aria.getState(foo, goog.a11y.aria.State.HIDDEN));
  524. assertTrue('Element must still be visible', foo.style.display != 'none');
  525. controlRenderer.setVisible(foo, false);
  526. assertEquals(
  527. 'ControlRenderer did not set aria-hidden.', 'true',
  528. goog.a11y.aria.getState(foo, goog.a11y.aria.State.HIDDEN));
  529. assertTrue('Element must be hidden', foo.style.display == 'none');
  530. }
  531. function testSetState() {
  532. control.setRenderer(testRenderer);
  533. control.createDom();
  534. var element = control.getElement();
  535. assertNotNull(element);
  536. assertSameElements(
  537. 'Control must have expected class names', ['goog-button', 'goog-base'],
  538. goog.dom.classlist.get(element));
  539. assertEquals(
  540. 'Control must not have disabled ARIA state', '',
  541. goog.a11y.aria.getState(element, goog.a11y.aria.State.DISABLED));
  542. testRenderer.setState(control, goog.ui.Component.State.DISABLED, true);
  543. assertSameElements(
  544. 'Control must have disabled class name',
  545. ['goog-button', 'goog-base', 'goog-base-disabled'],
  546. goog.dom.classlist.get(element));
  547. assertEquals(
  548. 'Control must have disabled ARIA state', 'true',
  549. goog.a11y.aria.getState(element, goog.a11y.aria.State.DISABLED));
  550. testRenderer.setState(control, goog.ui.Component.State.DISABLED, false);
  551. assertSameElements(
  552. 'Control must no longer have disabled class name',
  553. ['goog-button', 'goog-base'], goog.dom.classlist.get(element));
  554. assertEquals(
  555. 'Control must not have disabled ARIA state', 'false',
  556. goog.a11y.aria.getState(element, goog.a11y.aria.State.DISABLED));
  557. testRenderer.setState(control, 0xFFFFFF, true);
  558. assertSameElements(
  559. 'Class names must be unchanged for invalid state',
  560. ['goog-button', 'goog-base'], goog.dom.classlist.get(element));
  561. }
  562. function testUpdateAriaStateDisabled() {
  563. control.createDom();
  564. var element = control.getElement();
  565. assertNotNull(element);
  566. controlRenderer.updateAriaState(
  567. element, goog.ui.Component.State.DISABLED, true);
  568. assertEquals(
  569. 'Control must have disabled ARIA state', 'true',
  570. goog.a11y.aria.getState(element, goog.a11y.aria.State.DISABLED));
  571. controlRenderer.updateAriaState(
  572. element, goog.ui.Component.State.DISABLED, false);
  573. assertEquals(
  574. 'Control must no longer have disabled ARIA state', 'false',
  575. goog.a11y.aria.getState(element, goog.a11y.aria.State.DISABLED));
  576. }
  577. function testSetAriaStatesRender_ariaStateDisabled() {
  578. control.setEnabled(false);
  579. var renderer = new goog.ui.ControlRenderer();
  580. control.setRenderer(renderer);
  581. control.render(sandbox);
  582. var element = control.getElement();
  583. assertNotNull(element);
  584. assertFalse('Control must be disabled', control.isEnabled());
  585. assertEquals(
  586. 'Control must have disabled ARIA state', 'true',
  587. goog.a11y.aria.getState(element, goog.a11y.aria.State.DISABLED));
  588. }
  589. function testSetAriaStatesDecorate_ariaStateDisabled() {
  590. sandbox.innerHTML = '<div id="foo" class="app goog-base-disabled"></div>';
  591. var element = goog.dom.getElement('foo');
  592. control.setRenderer(testRenderer);
  593. control.decorate(element);
  594. assertNotNull(element);
  595. assertFalse('Control must be disabled', control.isEnabled());
  596. assertEquals(
  597. 'Control must have disabled ARIA state', 'true',
  598. goog.a11y.aria.getState(element, goog.a11y.aria.State.DISABLED));
  599. }
  600. function testUpdateAriaStateSelected() {
  601. control.createDom();
  602. var element = control.getElement();
  603. assertNotNull(element);
  604. controlRenderer.updateAriaState(
  605. element, goog.ui.Component.State.SELECTED, true);
  606. assertEquals(
  607. 'Control must have selected ARIA state', 'true',
  608. goog.a11y.aria.getState(element, goog.a11y.aria.State.SELECTED));
  609. controlRenderer.updateAriaState(
  610. element, goog.ui.Component.State.SELECTED, false);
  611. assertEquals(
  612. 'Control must no longer have selected ARIA state', 'false',
  613. goog.a11y.aria.getState(element, goog.a11y.aria.State.SELECTED));
  614. }
  615. function testSetAriaStatesRender_ariaStateSelected() {
  616. control.setSupportedState(goog.ui.Component.State.SELECTED, true);
  617. control.setSelected(true);
  618. var renderer = new goog.ui.ControlRenderer();
  619. control.setRenderer(renderer);
  620. control.render(sandbox);
  621. var element = control.getElement();
  622. assertNotNull(element);
  623. assertTrue('Control must be selected', control.isSelected());
  624. assertEquals(
  625. 'Control must have selected ARIA state', 'true',
  626. goog.a11y.aria.getState(element, goog.a11y.aria.State.SELECTED));
  627. }
  628. function testSetAriaStatesRender_ariaStateNotSelected() {
  629. control.setSupportedState(goog.ui.Component.State.SELECTED, true);
  630. var renderer = new goog.ui.ControlRenderer();
  631. control.setRenderer(renderer);
  632. control.render(sandbox);
  633. var element = control.getElement();
  634. assertNotNull(element);
  635. assertFalse('Control must not be selected', control.isSelected());
  636. assertEquals(
  637. 'Control must have not-selected ARIA state', 'false',
  638. goog.a11y.aria.getState(element, goog.a11y.aria.State.SELECTED));
  639. }
  640. function testSetAriaStatesDecorate_ariaStateSelected() {
  641. control.setSupportedState(goog.ui.Component.State.SELECTED, true);
  642. sandbox.innerHTML = '<div id="foo" class="app goog-control-selected"></div>';
  643. var element = goog.dom.getElement('foo');
  644. control.setRenderer(controlRenderer);
  645. control.decorate(element);
  646. assertNotNull(element);
  647. assertTrue('Control must be selected', control.isSelected());
  648. assertEquals(
  649. 'Control must have selected ARIA state', 'true',
  650. goog.a11y.aria.getState(element, goog.a11y.aria.State.SELECTED));
  651. }
  652. function testUpdateAriaStateChecked() {
  653. control.createDom();
  654. var element = control.getElement();
  655. assertNotNull(element);
  656. controlRenderer.updateAriaState(
  657. element, goog.ui.Component.State.CHECKED, true);
  658. assertEquals(
  659. 'Control must have checked ARIA state', 'true',
  660. goog.a11y.aria.getState(element, goog.a11y.aria.State.CHECKED));
  661. controlRenderer.updateAriaState(
  662. element, goog.ui.Component.State.CHECKED, false);
  663. assertEquals(
  664. 'Control must no longer have checked ARIA state', 'false',
  665. goog.a11y.aria.getState(element, goog.a11y.aria.State.CHECKED));
  666. }
  667. function testSetAriaStatesRender_ariaStateChecked() {
  668. control.setSupportedState(goog.ui.Component.State.CHECKED, true);
  669. control.setChecked(true);
  670. var renderer = new goog.ui.ControlRenderer();
  671. control.setRenderer(renderer);
  672. control.render(sandbox);
  673. var element = control.getElement();
  674. assertNotNull(element);
  675. assertTrue('Control must be checked', control.isChecked());
  676. assertEquals(
  677. 'Control must have checked ARIA state', 'true',
  678. goog.a11y.aria.getState(element, goog.a11y.aria.State.CHECKED));
  679. }
  680. function testSetAriaStatesDecorate_ariaStateChecked() {
  681. sandbox.innerHTML = '<div id="foo" class="app goog-control-checked"></div>';
  682. var element = goog.dom.getElement('foo');
  683. control.setSupportedState(goog.ui.Component.State.CHECKED, true);
  684. control.decorate(element);
  685. assertNotNull(element);
  686. assertTrue('Control must be checked', control.isChecked());
  687. assertEquals(
  688. 'Control must have checked ARIA state', 'true',
  689. goog.a11y.aria.getState(element, goog.a11y.aria.State.CHECKED));
  690. }
  691. function testUpdateAriaStateOpened() {
  692. control.createDom();
  693. var element = control.getElement();
  694. assertNotNull(element);
  695. controlRenderer.updateAriaState(
  696. element, goog.ui.Component.State.OPENED, true);
  697. assertEquals(
  698. 'Control must have expanded ARIA state', 'true',
  699. goog.a11y.aria.getState(element, goog.a11y.aria.State.EXPANDED));
  700. controlRenderer.updateAriaState(
  701. element, goog.ui.Component.State.OPENED, false);
  702. assertEquals(
  703. 'Control must no longer have expanded ARIA state', 'false',
  704. goog.a11y.aria.getState(element, goog.a11y.aria.State.EXPANDED));
  705. }
  706. function testSetAriaStatesRender_ariaStateOpened() {
  707. control.setSupportedState(goog.ui.Component.State.OPENED, true);
  708. control.setOpen(true);
  709. var renderer = new goog.ui.ControlRenderer();
  710. control.setRenderer(renderer);
  711. control.render(sandbox);
  712. var element = control.getElement();
  713. assertNotNull(element);
  714. assertTrue('Control must be opened', control.isOpen());
  715. assertEquals(
  716. 'Control must have expanded ARIA state', 'true',
  717. goog.a11y.aria.getState(element, goog.a11y.aria.State.EXPANDED));
  718. }
  719. function testSetAriaStatesDecorate_ariaStateOpened() {
  720. sandbox.innerHTML = '<div id="foo" class="app goog-base-open"></div>';
  721. var element = goog.dom.getElement('foo');
  722. control.setSupportedState(goog.ui.Component.State.OPENED, true);
  723. control.setRenderer(testRenderer);
  724. control.decorate(element);
  725. assertNotNull(element);
  726. assertTrue('Control must be opened', control.isOpen());
  727. assertEquals(
  728. 'Control must have expanded ARIA state', 'true',
  729. goog.a11y.aria.getState(element, goog.a11y.aria.State.EXPANDED));
  730. }
  731. function testSetAriaStateRoleNotInMap() {
  732. sandbox.innerHTML = '<div id="foo" role="option">Hello, world!</div>';
  733. control.setRenderer(controlRenderer);
  734. control.setSupportedState(goog.ui.Component.State.CHECKED, true);
  735. var element = goog.dom.getElement('foo');
  736. control.decorate(element);
  737. assertEquals(
  738. 'Element should have ARIA role option.', goog.a11y.aria.Role.OPTION,
  739. goog.a11y.aria.getRole(element));
  740. control.setStateInternal(goog.ui.Component.State.DISABLED, true);
  741. controlRenderer.setAriaStates(control, element);
  742. assertEquals(
  743. 'Element should have aria-disabled true', 'true',
  744. goog.a11y.aria.getState(element, goog.a11y.aria.State.DISABLED));
  745. control.setStateInternal(goog.ui.Component.State.CHECKED, true);
  746. controlRenderer.setAriaStates(control, element);
  747. assertEquals(
  748. 'Element should have aria-checked true', 'true',
  749. goog.a11y.aria.getState(element, goog.a11y.aria.State.CHECKED));
  750. }
  751. function testSetAriaStateRoleInMapMatches() {
  752. sandbox.innerHTML = '<div id="foo" role="checkbox">Hello, world!</div>';
  753. control.setRenderer(controlRenderer);
  754. control.setSupportedState(goog.ui.Component.State.CHECKED, true);
  755. var element = goog.dom.getElement('foo');
  756. control.decorate(element);
  757. assertEquals(
  758. 'Element should have ARIA role checkbox.', goog.a11y.aria.Role.CHECKBOX,
  759. goog.a11y.aria.getRole(element));
  760. control.setStateInternal(goog.ui.Component.State.DISABLED, true);
  761. controlRenderer.setAriaStates(control, element);
  762. assertEquals(
  763. 'Element should have aria-disabled true', 'true',
  764. goog.a11y.aria.getState(element, goog.a11y.aria.State.DISABLED));
  765. control.setStateInternal(goog.ui.Component.State.CHECKED, true);
  766. controlRenderer.setAriaStates(control, element);
  767. assertEquals(
  768. 'Element should have aria-checked true', 'true',
  769. goog.a11y.aria.getState(element, goog.a11y.aria.State.CHECKED));
  770. }
  771. function testSetAriaStateRoleInMapNotMatches() {
  772. sandbox.innerHTML = '<div id="foo" role="button">Hello, world!</div>';
  773. control.setRenderer(controlRenderer);
  774. control.setSupportedState(goog.ui.Component.State.CHECKED, true);
  775. var element = goog.dom.getElement('foo');
  776. control.decorate(element);
  777. assertEquals(
  778. 'Element should have ARIA role button.', goog.a11y.aria.Role.BUTTON,
  779. goog.a11y.aria.getRole(element));
  780. control.setStateInternal(goog.ui.Component.State.DISABLED, true);
  781. controlRenderer.setAriaStates(control, element);
  782. assertEquals(
  783. 'Element should have aria-disabled true', 'true',
  784. goog.a11y.aria.getState(element, goog.a11y.aria.State.DISABLED));
  785. control.setStateInternal(goog.ui.Component.State.CHECKED, true);
  786. controlRenderer.setAriaStates(control, element);
  787. assertEquals(
  788. 'Element should have aria-pressed true', 'true',
  789. goog.a11y.aria.getState(element, goog.a11y.aria.State.PRESSED));
  790. assertEquals(
  791. 'Element should not have aria-checked', '',
  792. goog.a11y.aria.getState(element, goog.a11y.aria.State.CHECKED));
  793. }
  794. function testToggleAriaStateMap() {
  795. var map = goog.object.create(
  796. goog.a11y.aria.Role.BUTTON, goog.a11y.aria.State.PRESSED,
  797. goog.a11y.aria.Role.CHECKBOX, goog.a11y.aria.State.CHECKED,
  798. goog.a11y.aria.Role.MENU_ITEM, goog.a11y.aria.State.SELECTED,
  799. goog.a11y.aria.Role.MENU_ITEM_CHECKBOX, goog.a11y.aria.State.CHECKED,
  800. goog.a11y.aria.Role.MENU_ITEM_RADIO, goog.a11y.aria.State.CHECKED,
  801. goog.a11y.aria.Role.RADIO, goog.a11y.aria.State.CHECKED,
  802. goog.a11y.aria.Role.TAB, goog.a11y.aria.State.SELECTED,
  803. goog.a11y.aria.Role.TREEITEM, goog.a11y.aria.State.SELECTED);
  804. for (var key in map) {
  805. assertTrue(
  806. 'Toggle ARIA state map incorrect.',
  807. key in goog.ui.ControlRenderer.TOGGLE_ARIA_STATE_MAP_);
  808. assertEquals(
  809. 'Toggle ARIA state map incorrect.', map[key],
  810. goog.ui.ControlRenderer.TOGGLE_ARIA_STATE_MAP_[key]);
  811. }
  812. }
  813. function testSetContent() {
  814. goog.dom.setTextContent(sandbox, 'Hello, world!');
  815. controlRenderer.setContent(sandbox, 'Not so fast!');
  816. assertEquals(
  817. 'Element must contain expected text value', 'Not so fast!',
  818. goog.dom.getTextContent(sandbox));
  819. }
  820. function testSetContentNull() {
  821. goog.dom.setTextContent(sandbox, 'Hello, world!');
  822. controlRenderer.setContent(sandbox, null);
  823. assertEquals(
  824. 'Element must have no child nodes', 0, sandbox.childNodes.length);
  825. assertEquals(
  826. 'Element must contain expected text value', '',
  827. goog.dom.getTextContent(sandbox));
  828. }
  829. function testSetContentEmpty() {
  830. goog.dom.setTextContent(sandbox, 'Hello, world!');
  831. controlRenderer.setContent(sandbox, '');
  832. assertEquals('Element must not have children', 0, sandbox.childNodes.length);
  833. assertEquals(
  834. 'Element must contain expected text value', '',
  835. goog.dom.getTextContent(sandbox));
  836. }
  837. function testSetContentWhitespace() {
  838. goog.dom.setTextContent(sandbox, 'Hello, world!');
  839. controlRenderer.setContent(sandbox, ' ');
  840. assertEquals('Element must have one child', 1, sandbox.childNodes.length);
  841. assertEquals(
  842. 'Child must be a text node', goog.dom.NodeType.TEXT,
  843. sandbox.firstChild.nodeType);
  844. assertEquals(
  845. 'Element must contain expected text value', ' ',
  846. goog.dom.getTextContent(sandbox));
  847. }
  848. function testSetContentTextNode() {
  849. goog.dom.setTextContent(sandbox, 'Hello, world!');
  850. controlRenderer.setContent(sandbox, document.createTextNode('Text'));
  851. assertEquals('Element must have one child', 1, sandbox.childNodes.length);
  852. assertEquals(
  853. 'Child must be a text node', goog.dom.NodeType.TEXT,
  854. sandbox.firstChild.nodeType);
  855. assertEquals(
  856. 'Element must contain expected text value', 'Text',
  857. goog.dom.getTextContent(sandbox));
  858. }
  859. function testSetContentElementNode() {
  860. goog.dom.setTextContent(sandbox, 'Hello, world!');
  861. controlRenderer.setContent(
  862. sandbox, goog.dom.createDom(goog.dom.TagName.DIV, {id: 'foo'}, 'Foo'));
  863. assertEquals('Element must have one child', 1, sandbox.childNodes.length);
  864. assertEquals(
  865. 'Child must be an element node', goog.dom.NodeType.ELEMENT,
  866. sandbox.firstChild.nodeType);
  867. assertHTMLEquals(
  868. 'Element must contain expected HTML', '<div id="foo">Foo</div>',
  869. sandbox.innerHTML);
  870. }
  871. function testSetContentArray() {
  872. goog.dom.setTextContent(sandbox, 'Hello, world!');
  873. controlRenderer.setContent(
  874. sandbox,
  875. ['Hello, ', goog.dom.createDom(goog.dom.TagName.B, null, 'world'), '!']);
  876. assertEquals(
  877. 'Element must have three children', 3, sandbox.childNodes.length);
  878. assertEquals(
  879. '1st child must be a text node', goog.dom.NodeType.TEXT,
  880. sandbox.childNodes[0].nodeType);
  881. assertEquals(
  882. '2nd child must be an element', goog.dom.NodeType.ELEMENT,
  883. sandbox.childNodes[1].nodeType);
  884. assertEquals(
  885. '3rd child must be a text node', goog.dom.NodeType.TEXT,
  886. sandbox.childNodes[2].nodeType);
  887. assertHTMLEquals(
  888. 'Element must contain expected HTML', 'Hello, <b>world</b>!',
  889. sandbox.innerHTML);
  890. }
  891. function testSetContentNodeList() {
  892. goog.dom.setTextContent(sandbox, 'Hello, world!');
  893. var div = goog.dom.createDom(
  894. goog.dom.TagName.DIV, null, 'Hello, ',
  895. goog.dom.createDom(goog.dom.TagName.B, null, 'world'), '!');
  896. controlRenderer.setContent(sandbox, div.childNodes);
  897. assertEquals(
  898. 'Element must have three children', 3, sandbox.childNodes.length);
  899. assertEquals(
  900. '1st child must be a text node', goog.dom.NodeType.TEXT,
  901. sandbox.childNodes[0].nodeType);
  902. assertEquals(
  903. '2nd child must be an element', goog.dom.NodeType.ELEMENT,
  904. sandbox.childNodes[1].nodeType);
  905. assertEquals(
  906. '3rd child must be a text node', goog.dom.NodeType.TEXT,
  907. sandbox.childNodes[2].nodeType);
  908. assertHTMLEquals(
  909. 'Element must contain expected HTML', 'Hello, <b>world</b>!',
  910. sandbox.innerHTML);
  911. }
  912. function testGetKeyEventTarget() {
  913. assertNull(
  914. 'Key event target for unrendered control must be null',
  915. controlRenderer.getKeyEventTarget(control));
  916. control.createDom();
  917. assertEquals(
  918. 'Key event target for rendered control must be its element',
  919. control.getElement(), controlRenderer.getKeyEventTarget(control));
  920. }
  921. function testGetCssClass() {
  922. assertEquals(
  923. 'ControlRenderer\'s CSS class must have expected value',
  924. goog.ui.ControlRenderer.CSS_CLASS, controlRenderer.getCssClass());
  925. assertEquals(
  926. 'TestRenderer\'s CSS class must have expected value',
  927. TestRenderer.CSS_CLASS, testRenderer.getCssClass());
  928. }
  929. function testGetStructuralCssClass() {
  930. assertEquals(
  931. 'ControlRenderer\'s structural class must be its CSS class',
  932. controlRenderer.getCssClass(), controlRenderer.getStructuralCssClass());
  933. assertEquals(
  934. 'TestRenderer\'s structural class must have expected value', 'goog-base',
  935. testRenderer.getStructuralCssClass());
  936. }
  937. function testGetClassNames() {
  938. // These tests use assertArrayEquals, because the order is significant.
  939. assertArrayEquals(
  940. 'ControlRenderer must return expected class names ' +
  941. 'in the expected order',
  942. ['goog-control'], controlRenderer.getClassNames(control));
  943. assertArrayEquals(
  944. 'TestRenderer must return expected class names ' +
  945. 'in the expected order',
  946. ['goog-button', 'goog-base'], testRenderer.getClassNames(control));
  947. }
  948. function testGetClassNamesForControlWithState() {
  949. control.setStateInternal(
  950. goog.ui.Component.State.HOVER | goog.ui.Component.State.ACTIVE);
  951. // These tests use assertArrayEquals, because the order is significant.
  952. assertArrayEquals(
  953. 'ControlRenderer must return expected class names ' +
  954. 'in the expected order',
  955. ['goog-control', 'goog-control-hover', 'goog-control-active'],
  956. controlRenderer.getClassNames(control));
  957. assertArrayEquals(
  958. 'TestRenderer must return expected class names ' +
  959. 'in the expected order',
  960. ['goog-button', 'goog-base', 'goog-base-hover', 'goog-base-active'],
  961. testRenderer.getClassNames(control));
  962. }
  963. function testGetClassNamesForControlWithExtraClassNames() {
  964. control.addClassName('foo');
  965. control.addClassName('bar');
  966. // These tests use assertArrayEquals, because the order is significant.
  967. assertArrayEquals(
  968. 'ControlRenderer must return expected class names ' +
  969. 'in the expected order',
  970. ['goog-control', 'foo', 'bar'], controlRenderer.getClassNames(control));
  971. assertArrayEquals(
  972. 'TestRenderer must return expected class names ' +
  973. 'in the expected order',
  974. ['goog-button', 'goog-base', 'foo', 'bar'],
  975. testRenderer.getClassNames(control));
  976. }
  977. function testGetClassNamesForControlWithStateAndExtraClassNames() {
  978. control.setStateInternal(
  979. goog.ui.Component.State.HOVER | goog.ui.Component.State.ACTIVE);
  980. control.addClassName('foo');
  981. control.addClassName('bar');
  982. // These tests use assertArrayEquals, because the order is significant.
  983. assertArrayEquals(
  984. 'ControlRenderer must return expected class names ' +
  985. 'in the expected order',
  986. [
  987. 'goog-control', 'goog-control-hover', 'goog-control-active', 'foo',
  988. 'bar'
  989. ],
  990. controlRenderer.getClassNames(control));
  991. assertArrayEquals(
  992. 'TestRenderer must return expected class names ' +
  993. 'in the expected order',
  994. [
  995. 'goog-button', 'goog-base', 'goog-base-hover', 'goog-base-active',
  996. 'foo', 'bar'
  997. ],
  998. testRenderer.getClassNames(control));
  999. }
  1000. function testGetClassNamesForState() {
  1001. // These tests use assertArrayEquals, because the order is significant.
  1002. assertArrayEquals(
  1003. 'ControlRenderer must return expected class names ' +
  1004. 'in the expected order',
  1005. ['goog-control-hover', 'goog-control-checked'],
  1006. controlRenderer.getClassNamesForState(
  1007. goog.ui.Component.State.HOVER | goog.ui.Component.State.CHECKED));
  1008. assertArrayEquals(
  1009. 'TestRenderer must return expected class names ' +
  1010. 'in the expected order',
  1011. ['goog-base-hover', 'goog-base-checked'],
  1012. testRenderer.getClassNamesForState(
  1013. goog.ui.Component.State.HOVER | goog.ui.Component.State.CHECKED));
  1014. }
  1015. function testGetClassForState() {
  1016. var renderer = new goog.ui.ControlRenderer();
  1017. assertUndefined(
  1018. 'State-to-class map must not exist until first use',
  1019. renderer.classByState_);
  1020. assertEquals(
  1021. 'Renderer must return expected class name for SELECTED',
  1022. 'goog-control-selected',
  1023. renderer.getClassForState(goog.ui.Component.State.SELECTED));
  1024. assertUndefined(
  1025. 'Renderer must return undefined for invalid state',
  1026. renderer.getClassForState('foo'));
  1027. }
  1028. function testGetStateFromClass() {
  1029. var renderer = new goog.ui.ControlRenderer();
  1030. assertUndefined(
  1031. 'Class-to-state map must not exist until first use',
  1032. renderer.stateByClass_);
  1033. assertEquals(
  1034. 'Renderer must return expected state', goog.ui.Component.State.SELECTED,
  1035. renderer.getStateFromClass('goog-control-selected'));
  1036. assertEquals(
  1037. 'Renderer must return 0x00 for unknown class', 0x00,
  1038. renderer.getStateFromClass('goog-control-annoyed'));
  1039. }
  1040. function testIe6ClassCombinationsCreateDom() {
  1041. control.setRenderer(testRenderer);
  1042. control.enableClassName('combined', true);
  1043. control.createDom();
  1044. var element = control.getElement();
  1045. testRenderer.setState(control, goog.ui.Component.State.DISABLED, true);
  1046. var expectedClasses =
  1047. ['combined', 'goog-base', 'goog-base-disabled', 'goog-button'];
  1048. if (isIe6()) {
  1049. assertSameElements(
  1050. 'IE6 and lower should have one combined class',
  1051. expectedClasses.concat(['combined_goog-base-disabled_goog-button']),
  1052. goog.dom.classlist.get(element));
  1053. } else {
  1054. assertSameElements(
  1055. 'Non IE6 browsers should not have a combined class', expectedClasses,
  1056. goog.dom.classlist.get(element));
  1057. }
  1058. testRenderer.setState(control, goog.ui.Component.State.DISABLED, false);
  1059. testRenderer.setState(control, goog.ui.Component.State.HOVER, true);
  1060. var expectedClasses =
  1061. ['combined', 'goog-base', 'goog-base-hover', 'goog-button'];
  1062. if (isIe6()) {
  1063. assertSameElements(
  1064. 'IE6 and lower should have one combined class',
  1065. expectedClasses.concat(['combined_goog-base-hover_goog-button']),
  1066. goog.dom.classlist.get(element));
  1067. } else {
  1068. assertSameElements(
  1069. 'Non IE6 browsers should not have a combined class', expectedClasses,
  1070. goog.dom.classlist.get(element));
  1071. }
  1072. testRenderer.setRightToLeft(element, true);
  1073. testRenderer.enableExtraClassName(control, 'combined2', true);
  1074. var expectedClasses = [
  1075. 'combined', 'combined2', 'goog-base', 'goog-base-hover', 'goog-base-rtl',
  1076. 'goog-button'
  1077. ];
  1078. if (isIe6()) {
  1079. assertSameElements(
  1080. 'IE6 and lower should have two combined class', expectedClasses.concat([
  1081. 'combined_goog-base-hover_goog-button',
  1082. 'combined_combined2_goog-base-hover_goog-base-rtl_goog-button'
  1083. ]),
  1084. goog.dom.classlist.get(element));
  1085. } else {
  1086. assertSameElements(
  1087. 'Non IE6 browsers should not have a combined class', expectedClasses,
  1088. goog.dom.classlist.get(element));
  1089. }
  1090. }
  1091. function testIe6ClassCombinationsDecorate() {
  1092. sandbox.innerHTML = '<div id="foo" class="combined goog-base-hover"></div>';
  1093. var foo = goog.dom.getElement('foo');
  1094. var element = testRenderer.decorate(control, foo);
  1095. var expectedClasses =
  1096. ['combined', 'goog-base', 'goog-base-hover', 'goog-button'];
  1097. if (isIe6()) {
  1098. assertSameElements(
  1099. 'IE6 and lower should have one combined class',
  1100. expectedClasses.concat(['combined_goog-base-hover_goog-button']),
  1101. goog.dom.classlist.get(element));
  1102. } else {
  1103. assertSameElements(
  1104. 'Non IE6 browsers should not have a combined class', expectedClasses,
  1105. goog.dom.classlist.get(element));
  1106. }
  1107. }