control_test.js 91 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777
  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.ControlTest');
  15. goog.setTestOnly('goog.ui.ControlTest');
  16. goog.require('goog.a11y.aria');
  17. goog.require('goog.a11y.aria.State');
  18. goog.require('goog.array');
  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.BrowserEvent');
  24. goog.require('goog.events.KeyCodes');
  25. goog.require('goog.html.testing');
  26. goog.require('goog.object');
  27. goog.require('goog.string');
  28. goog.require('goog.style');
  29. goog.require('goog.testing.ExpectedFailures');
  30. goog.require('goog.testing.events');
  31. goog.require('goog.testing.events.Event');
  32. goog.require('goog.testing.jsunit');
  33. goog.require('goog.ui.Component');
  34. goog.require('goog.ui.Control');
  35. goog.require('goog.ui.ControlRenderer');
  36. goog.require('goog.ui.registry');
  37. goog.require('goog.userAgent');
  38. // Disabled due to problems on farm.
  39. var testFocus = false;
  40. var control;
  41. var ALL_EVENTS = goog.object.getValues(goog.ui.Component.EventType);
  42. var events = {};
  43. var expectedFailures;
  44. var sandbox;
  45. var aria = goog.a11y.aria;
  46. var State = goog.a11y.aria.State;
  47. function setUpPage() {
  48. expectedFailures = new goog.testing.ExpectedFailures();
  49. sandbox = document.getElementById('sandbox');
  50. }
  51. /**
  52. * A dummy renderer, for testing purposes.
  53. * @constructor
  54. * @extends {goog.ui.ControlRenderer}
  55. */
  56. function TestRenderer() {
  57. goog.ui.ControlRenderer.call(this);
  58. }
  59. goog.inherits(TestRenderer, goog.ui.ControlRenderer);
  60. /**
  61. * Initializes the testcase prior to execution.
  62. */
  63. function setUp() {
  64. control = new goog.ui.Control('Hello');
  65. control.setDispatchTransitionEvents(goog.ui.Component.State.ALL, true);
  66. goog.events.listen(control, ALL_EVENTS, countEvent);
  67. }
  68. /**
  69. * Cleans up after executing the testcase.
  70. */
  71. function tearDown() {
  72. control.dispose();
  73. expectedFailures.handleTearDown();
  74. goog.dom.removeChildren(sandbox);
  75. resetEventCount();
  76. }
  77. /**
  78. * Resets the global counter for events dispatched by test objects.
  79. */
  80. function resetEventCount() {
  81. goog.object.clear(events);
  82. }
  83. /**
  84. * Increments the global counter for events of this type.
  85. * @param {goog.events.Event} e Event to count.
  86. */
  87. function countEvent(e) {
  88. var type = e.type;
  89. var target = e.target;
  90. if (!events[target]) {
  91. events[target] = {};
  92. }
  93. if (events[target][type]) {
  94. events[target][type]++;
  95. } else {
  96. events[target][type] = 1;
  97. }
  98. }
  99. /**
  100. * Returns the number of times test objects dispatched events of the given
  101. * type since the global counter was last reset.
  102. * @param {goog.ui.Control} target Event target.
  103. * @param {string} type Event type.
  104. * @return {number} Number of events of this type.
  105. */
  106. function getEventCount(target, type) {
  107. return events[target] && events[target][type] || 0;
  108. }
  109. /**
  110. * Returns true if no events were dispatched since the last reset.
  111. * @return {boolean} Whether no events have been dispatched since the last
  112. * reset.
  113. */
  114. function noEventsDispatched() {
  115. return !events || goog.object.isEmpty(events);
  116. }
  117. /**
  118. * Returns the number of event listeners created by the control.
  119. * @param {goog.ui.Control} control Control whose event listers are to be
  120. * counted.
  121. * @return {number} Number of event listeners.
  122. */
  123. function getListenerCount(control) {
  124. return control.googUiComponentHandler_ ?
  125. goog.object.getCount(control.getHandler().keys_) :
  126. 0;
  127. }
  128. /**
  129. * Simulates a mousedown event on the given element, including focusing it.
  130. * @param {Element} element Element on which to simulate mousedown.
  131. * @param {goog.events.BrowserEvent.MouseButton=} opt_button Mouse button;
  132. * defaults to {@code goog.events.BrowserEvent.MouseButton.LEFT}.
  133. * @return {boolean} Whether the event was allowed to proceed.
  134. */
  135. function fireMouseDownAndFocus(element, opt_button) {
  136. var result = goog.testing.events.fireMouseDownEvent(element, opt_button);
  137. if (result) {
  138. // Browsers move focus for all buttons, not just the left button.
  139. element.focus();
  140. }
  141. return result;
  142. }
  143. /**
  144. * @return {boolean} Whether we're on Mac Safari 3.x.
  145. */
  146. function isMacSafari3() {
  147. return goog.userAgent.WEBKIT && goog.userAgent.MAC &&
  148. !goog.userAgent.isVersionOrHigher('527');
  149. }
  150. /**
  151. * Tests the {@link goog.ui.Control} constructor.
  152. */
  153. function testConstructor() {
  154. assertNotNull('Constructed control must not be null', control);
  155. assertEquals(
  156. 'Content must have expected value', 'Hello', control.getContent());
  157. assertEquals(
  158. 'Renderer must default to the registered renderer',
  159. goog.ui.registry.getDefaultRenderer(goog.ui.Control),
  160. control.getRenderer());
  161. var content = goog.dom.createDom(
  162. goog.dom.TagName.DIV, null, 'Hello',
  163. goog.dom.createDom(goog.dom.TagName.B, null, 'World'));
  164. var testRenderer = new TestRenderer();
  165. var fakeDomHelper = {};
  166. var foo = new goog.ui.Control(content, testRenderer, fakeDomHelper);
  167. assertNotNull('Constructed object must not be null', foo);
  168. assertEquals('Content must have expected value', content, foo.getContent());
  169. assertEquals(
  170. 'Renderer must have expected value', testRenderer, foo.getRenderer());
  171. assertEquals(
  172. 'DOM helper must have expected value', fakeDomHelper, foo.getDomHelper());
  173. foo.dispose();
  174. }
  175. /**
  176. * Tests {@link goog.ui.Control#getHandler}.
  177. */
  178. function testGetHandler() {
  179. assertUndefined(
  180. 'Event handler must be undefined before getHandler() ' +
  181. 'is called',
  182. control.googUiComponentHandler_);
  183. var handler = control.getHandler();
  184. assertNotNull('Event handler must not be null', handler);
  185. assertEquals(
  186. 'getHandler() must return the same instance if called again', handler,
  187. control.getHandler());
  188. }
  189. /**
  190. * Tests {@link goog.ui.Control#isHandleMouseEvents}.
  191. */
  192. function testIsHandleMouseEvents() {
  193. assertTrue(
  194. 'Controls must handle their own mouse events by default',
  195. control.isHandleMouseEvents());
  196. }
  197. /**
  198. * Tests {@link goog.ui.Control#setHandleMouseEvents}.
  199. */
  200. function testSetHandleMouseEvents() {
  201. assertTrue(
  202. 'Control must handle its own mouse events by default',
  203. control.isHandleMouseEvents());
  204. control.setHandleMouseEvents(false);
  205. assertFalse(
  206. 'Control must no longer handle its own mouse events',
  207. control.isHandleMouseEvents());
  208. control.setHandleMouseEvents(true);
  209. assertTrue(
  210. 'Control must once again handle its own mouse events',
  211. control.isHandleMouseEvents());
  212. control.render(sandbox);
  213. assertTrue(
  214. 'Rendered control must handle its own mouse events',
  215. control.isHandleMouseEvents());
  216. control.setHandleMouseEvents(false);
  217. assertFalse(
  218. 'Rendered control must no longer handle its own mouse events',
  219. control.isHandleMouseEvents());
  220. control.setHandleMouseEvents(true);
  221. assertTrue(
  222. 'Rendered control must once again handle its own mouse events',
  223. control.isHandleMouseEvents());
  224. }
  225. /**
  226. * Tests {@link goog.ui.Control#getKeyEventTarget}.
  227. */
  228. function testGetKeyEventTarget() {
  229. assertNull(
  230. 'Key event target of control without DOM must be null',
  231. control.getKeyEventTarget());
  232. control.createDom();
  233. assertEquals(
  234. 'Key event target of control with DOM must be its element',
  235. control.getElement(), control.getKeyEventTarget());
  236. }
  237. /**
  238. * Tests {@link goog.ui.Control#getKeyHandler}.
  239. */
  240. function testGetKeyHandler() {
  241. assertUndefined(
  242. 'Key handler must be undefined before getKeyHandler() ' +
  243. 'is called',
  244. control.keyHandler_);
  245. var keyHandler = control.getKeyHandler();
  246. assertNotNull('Key handler must not be null', keyHandler);
  247. assertEquals(
  248. 'getKeyHandler() must return the same instance if called ' +
  249. 'again',
  250. keyHandler, control.getKeyHandler());
  251. }
  252. /**
  253. * Tests {@link goog.ui.Control#getRenderer}.
  254. */
  255. function testGetRenderer() {
  256. assertEquals(
  257. 'Renderer must be the default registered renderer',
  258. goog.ui.registry.getDefaultRenderer(goog.ui.Control),
  259. control.getRenderer());
  260. }
  261. /**
  262. * Tests {@link goog.ui.Control#setRenderer}.
  263. */
  264. function testSetRenderer() {
  265. control.createDom();
  266. assertNotNull('Control must have a DOM', control.getElement());
  267. assertFalse('Control must not be in the document', control.isInDocument());
  268. assertEquals(
  269. 'Renderer must be the default registered renderer',
  270. goog.ui.registry.getDefaultRenderer(goog.ui.Control),
  271. control.getRenderer());
  272. var testRenderer = new TestRenderer();
  273. control.setRenderer(testRenderer);
  274. assertNull(
  275. 'Control must not have a DOM after its renderer is reset',
  276. control.getElement());
  277. assertFalse(
  278. 'Control still must not be in the document', control.isInDocument());
  279. assertEquals(
  280. 'Renderer must have expected value', testRenderer, control.getRenderer());
  281. control.render(sandbox);
  282. assertTrue('Control must be in the document', control.isInDocument());
  283. assertThrows(
  284. 'Resetting the renderer after the control has entered ' +
  285. 'the document must throw error',
  286. function() { control.setRenderer({}); });
  287. }
  288. /**
  289. * Tests {@link goog.ui.Control#getExtraClassNames}.
  290. */
  291. function testGetExtraClassNames() {
  292. assertNull(
  293. 'Control must not have any extra class names by default',
  294. control.getExtraClassNames());
  295. }
  296. /**
  297. * Tests {@link goog.ui.Control#addExtraClassName} and
  298. * {@link goog.ui.Control#removeExtraClassName}.
  299. */
  300. function testAddRemoveClassName() {
  301. assertNull(
  302. 'Control must not have any extra class names by default',
  303. control.getExtraClassNames());
  304. control.addClassName('foo');
  305. assertArrayEquals(
  306. 'Control must have expected extra class names', ['foo'],
  307. control.getExtraClassNames());
  308. assertNull('Control must not have a DOM', control.getElement());
  309. control.createDom();
  310. assertSameElements(
  311. 'Control\'s element must have expected class names',
  312. ['goog-control', 'foo'], goog.dom.classlist.get(control.getElement()));
  313. control.addClassName('bar');
  314. assertArrayEquals(
  315. 'Control must have expected extra class names', ['foo', 'bar'],
  316. control.getExtraClassNames());
  317. assertSameElements(
  318. 'Control\'s element must have expected class names',
  319. ['goog-control', 'foo', 'bar'],
  320. goog.dom.classlist.get(control.getElement()));
  321. control.addClassName('bar');
  322. assertArrayEquals(
  323. 'Adding the same class name again must be a no-op', ['foo', 'bar'],
  324. control.getExtraClassNames());
  325. assertSameElements(
  326. 'Adding the same class name again must be a no-op',
  327. ['goog-control', 'foo', 'bar'],
  328. goog.dom.classlist.get(control.getElement()));
  329. control.addClassName(null);
  330. assertArrayEquals(
  331. 'Adding null class name must be a no-op', ['foo', 'bar'],
  332. control.getExtraClassNames());
  333. assertSameElements(
  334. 'Adding null class name must be a no-op', ['goog-control', 'foo', 'bar'],
  335. goog.dom.classlist.get(control.getElement()));
  336. control.removeClassName(null);
  337. assertArrayEquals(
  338. 'Removing null class name must be a no-op', ['foo', 'bar'],
  339. control.getExtraClassNames());
  340. assertSameElements(
  341. 'Removing null class name must be a no-op',
  342. ['goog-control', 'foo', 'bar'],
  343. goog.dom.classlist.get(control.getElement()));
  344. control.removeClassName('foo');
  345. assertArrayEquals(
  346. 'Control must have expected extra class names', ['bar'],
  347. control.getExtraClassNames());
  348. assertSameElements(
  349. 'Control\'s element must have expected class names',
  350. ['goog-control', 'bar'], goog.dom.classlist.get(control.getElement()));
  351. control.removeClassName('bar');
  352. assertNull(
  353. 'Control must not have any extra class names',
  354. control.getExtraClassNames());
  355. assertSameElements(
  356. 'Control\'s element must have expected class names', ['goog-control'],
  357. goog.dom.classlist.get(control.getElement()));
  358. }
  359. /**
  360. * Tests {@link goog.ui.Control#enableClassName}.
  361. */
  362. function testEnableClassName() {
  363. assertNull(
  364. 'Control must not have any extra class names by default',
  365. control.getExtraClassNames());
  366. control.enableClassName('foo', true);
  367. assertArrayEquals(
  368. 'Control must have expected extra class names', ['foo'],
  369. control.getExtraClassNames());
  370. control.enableClassName('bar', true);
  371. assertArrayEquals(
  372. 'Control must have expected extra class names', ['foo', 'bar'],
  373. control.getExtraClassNames());
  374. control.enableClassName('bar', true);
  375. assertArrayEquals(
  376. 'Enabling the same class name again must be a no-op', ['foo', 'bar'],
  377. control.getExtraClassNames());
  378. control.enableClassName(null);
  379. assertArrayEquals(
  380. 'Enabling null class name must be a no-op', ['foo', 'bar'],
  381. control.getExtraClassNames());
  382. control.enableClassName('foo', false);
  383. assertArrayEquals(
  384. 'Control must have expected extra class names', ['bar'],
  385. control.getExtraClassNames());
  386. control.enableClassName('bar', false);
  387. assertNull(
  388. 'Control must not have any extra class names',
  389. control.getExtraClassNames());
  390. }
  391. /**
  392. * Tests {@link goog.ui.Control#createDom}.
  393. */
  394. function testCreateDom() {
  395. assertNull('Control must not have a DOM by default', control.getElement());
  396. assertFalse(
  397. 'Control must not allow text selection by default',
  398. control.isAllowTextSelection());
  399. assertTrue('Control must be visible by default', control.isVisible());
  400. control.createDom();
  401. assertNotNull('Control must have a DOM', control.getElement());
  402. assertTrue(
  403. 'Control\'s element must be unselectable',
  404. goog.style.isUnselectable(control.getElement()));
  405. assertTrue(
  406. 'Control\'s element must be visible',
  407. control.getElement().style.display != 'none');
  408. control.setAllowTextSelection(true);
  409. control.createDom();
  410. assertFalse(
  411. 'Control\'s element must be selectable',
  412. goog.style.isUnselectable(control.getElement()));
  413. control.setVisible(false);
  414. control.createDom();
  415. assertTrue(
  416. 'Control\'s element must be hidden',
  417. control.getElement().style.display == 'none');
  418. }
  419. /**
  420. * Tests {@link goog.ui.Control#getContentElement}.
  421. */
  422. function testGetContentElement() {
  423. assertNull(
  424. 'Unrendered control must not have a content element',
  425. control.getContentElement());
  426. control.createDom();
  427. assertEquals(
  428. 'Control\'s content element must equal its root element',
  429. control.getElement(), control.getContentElement());
  430. }
  431. /**
  432. * Tests {@link goog.ui.Control#canDecorate}.
  433. */
  434. function testCanDecorate() {
  435. assertTrue(control.canDecorate(goog.dom.createElement(goog.dom.TagName.DIV)));
  436. }
  437. /**
  438. * Tests {@link goog.ui.Control#decorateInternal}.
  439. */
  440. function testDecorateInternal() {
  441. sandbox.innerHTML = '<div id="foo">Hello, <b>World</b>!</div>';
  442. var foo = goog.dom.getElement('foo');
  443. control.decorate(foo);
  444. assertEquals(
  445. 'Decorated control\'s element must have expected value', foo,
  446. control.getElement());
  447. assertTrue(
  448. 'Element must be unselectable',
  449. goog.style.isUnselectable(control.getElement()));
  450. assertTrue(
  451. 'Element must be visible', control.getElement().style.display != 'none');
  452. }
  453. /**
  454. * Tests {@link goog.ui.Control#decorateInternal} with a control that
  455. * allows text selection.
  456. */
  457. function testDecorateInternalForSelectableControl() {
  458. sandbox.innerHTML = '<div id="foo">Hello, <b>World</b>!</div>';
  459. var foo = goog.dom.getElement('foo');
  460. control.setAllowTextSelection(true);
  461. control.decorate(foo);
  462. assertEquals(
  463. 'Decorated control\'s element must have expected value', foo,
  464. control.getElement());
  465. assertFalse(
  466. 'Element must be selectable',
  467. goog.style.isUnselectable(control.getElement()));
  468. assertTrue('Control must be visible', control.isVisible());
  469. }
  470. /**
  471. * Tests {@link goog.ui.Control#decorateInternal} with a hidden element.
  472. */
  473. function testDecorateInternalForHiddenElement() {
  474. sandbox.innerHTML = '<div id="foo" style="display:none">Hello!</div>';
  475. var foo = goog.dom.getElement('foo');
  476. control.decorate(foo);
  477. assertEquals(
  478. 'Decorated control\'s element must have expected value', foo,
  479. control.getElement());
  480. assertTrue(
  481. 'Element must be unselectable',
  482. goog.style.isUnselectable(control.getElement()));
  483. assertFalse('Control must be hidden', control.isVisible());
  484. }
  485. /**
  486. * Tests {@link goog.ui.Control#enterDocument}.
  487. */
  488. function testEnterDocument() {
  489. control.render(sandbox);
  490. assertTrue('Control must be in the document', control.isInDocument());
  491. if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher(9)) {
  492. assertEquals(
  493. 'Control must have 5 mouse & 3 key event listeners on IE8', 8,
  494. getListenerCount(control));
  495. } else {
  496. assertEquals(
  497. 'Control must have 4 mouse and 3 key event listeners', 7,
  498. getListenerCount(control));
  499. }
  500. assertEquals(
  501. 'Control\'s key event handler must be attached to its ' +
  502. 'key event target',
  503. control.getKeyEventTarget(), control.getKeyHandler().element_);
  504. }
  505. /**
  506. * Tests {@link goog.ui.Control#enterDocument} for a control that doesn't
  507. * handle mouse events.
  508. */
  509. function testEnterDocumentForControlWithoutMouseHandling() {
  510. control.setHandleMouseEvents(false);
  511. control.render(sandbox);
  512. assertTrue('Control must be in the document', control.isInDocument());
  513. assertEquals(
  514. 'Control must have 3 key event listeners', 3, getListenerCount(control));
  515. assertEquals(
  516. 'Control\'s key event handler must be attached to its ' +
  517. 'key event target',
  518. control.getKeyEventTarget(), control.getKeyHandler().element_);
  519. }
  520. /**
  521. * Tests {@link goog.ui.Control#enterDocument} for a control that isn't
  522. * focusable.
  523. */
  524. function testEnterDocumentForNonFocusableControl() {
  525. control.setSupportedState(goog.ui.Component.State.FOCUSED, false);
  526. control.render(sandbox);
  527. assertTrue('Control must be in the document', control.isInDocument());
  528. if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher(9)) {
  529. assertEquals(
  530. 'Control must have 5 mouse event listeners on IE8', 5,
  531. getListenerCount(control));
  532. } else {
  533. assertEquals(
  534. 'Control must have 4 mouse event listeners', 4,
  535. getListenerCount(control));
  536. }
  537. assertUndefined(
  538. 'Control must not have a key event handler', control.keyHandler_);
  539. }
  540. /**
  541. * Tests {@link goog.ui.Control#enterDocument} for a control that doesn't
  542. * need to do any event handling.
  543. */
  544. function testEnterDocumentForControlWithoutEventHandlers() {
  545. control.setHandleMouseEvents(false);
  546. control.setSupportedState(goog.ui.Component.State.FOCUSED, false);
  547. control.render(sandbox);
  548. assertTrue('Control must be in the document', control.isInDocument());
  549. assertEquals(
  550. 'Control must have 0 event listeners', 0, getListenerCount(control));
  551. assertUndefined(
  552. 'Control must not have an event handler',
  553. control.googUiComponentHandler_);
  554. assertUndefined(
  555. 'Control must not have a key event handler', control.keyHandler_);
  556. }
  557. /**
  558. * Tests {@link goog.ui.Control#exitDocument}.
  559. */
  560. function testExitDocument() {
  561. control.render(sandbox);
  562. assertTrue('Control must be in the document', control.isInDocument());
  563. if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher(9)) {
  564. assertEquals(
  565. 'Control must have 5 mouse & 3 key event listeners on IE8', 8,
  566. getListenerCount(control));
  567. } else {
  568. assertEquals(
  569. 'Control must have 4 mouse and 3 key event listeners', 7,
  570. getListenerCount(control));
  571. }
  572. assertEquals(
  573. 'Control\'s key event handler must be attached to its ' +
  574. 'key event target',
  575. control.getKeyEventTarget(), control.getKeyHandler().element_);
  576. // Expected to fail on Mac Safari prior to version 527.
  577. expectedFailures.expectFailureFor(isMacSafari3());
  578. try {
  579. assertTrue(
  580. 'Control\'s element must support keyboard focus',
  581. goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
  582. } catch (e) {
  583. expectedFailures.handleException(e);
  584. }
  585. control.exitDocument();
  586. assertFalse(
  587. 'Control must no longer be in the document', control.isInDocument());
  588. assertEquals(
  589. 'Control must have no event listeners', 0, getListenerCount(control));
  590. assertNull(
  591. 'Control\'s key event handler must be unattached',
  592. control.getKeyHandler().element_);
  593. assertFalse(
  594. 'Control\'s element must no longer support keyboard focus',
  595. goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
  596. }
  597. /**
  598. * Tests {@link goog.ui.Control#dispose}.
  599. */
  600. function testDispose() {
  601. control.render(sandbox);
  602. var handler = control.getHandler();
  603. var keyHandler = control.getKeyHandler();
  604. control.dispose();
  605. assertFalse(
  606. 'Control must no longer be in the document', control.isInDocument());
  607. assertTrue('Control must have been disposed of', control.isDisposed());
  608. assertUndefined('Renderer must have been deleted', control.getRenderer());
  609. assertNull('Content must be nulled out', control.getContent());
  610. assertTrue('Event handler must have been disposed of', handler.isDisposed());
  611. assertUndefined(
  612. 'Event handler must have been deleted', control.googUiComponentHandler_);
  613. assertTrue('Key handler must have been disposed of', keyHandler.isDisposed());
  614. assertUndefined('Key handler must have been deleted', control.keyHandler_);
  615. assertNull(
  616. 'Extra class names must have been nulled out',
  617. control.getExtraClassNames());
  618. }
  619. /**
  620. * Tests {@link goog.ui.Control#getContent}.
  621. */
  622. function testGetContent() {
  623. assertNull(
  624. 'Empty control must have null content',
  625. (new goog.ui.Control(null)).getContent());
  626. assertEquals(
  627. 'Control must have expected content', 'Hello', control.getContent());
  628. control.render(sandbox);
  629. assertEquals(
  630. 'Control must have expected content after rendering', 'Hello',
  631. control.getContent());
  632. }
  633. /**
  634. * Tests {@link goog.ui.Control#getContent}.
  635. */
  636. function testGetContentForDecoratedControl() {
  637. sandbox.innerHTML = '<div id="empty"></div>\n' +
  638. '<div id="text">Hello, world!</div>\n' +
  639. '<div id="element"><span>Foo</span></div>\n' +
  640. '<div id="nodelist">Hello, <b>world</b>!</div>\n';
  641. var empty = new goog.ui.Control(null);
  642. empty.decorate(goog.dom.getElement('empty'));
  643. assertNull(
  644. 'Content of control decorating empty DIV must be null',
  645. empty.getContent());
  646. empty.dispose();
  647. var text = new goog.ui.Control(null);
  648. text.decorate(goog.dom.getElement('text'));
  649. assertEquals(
  650. 'Content of control decorating DIV with text contents ' +
  651. 'must be as expected',
  652. 'Hello, world!', text.getContent().nodeValue);
  653. text.dispose();
  654. var element = new goog.ui.Control(null);
  655. element.decorate(goog.dom.getElement('element'));
  656. assertEquals(
  657. 'Content of control decorating DIV with element child ' +
  658. 'must be as expected',
  659. goog.dom.getElement('element').firstChild, element.getContent());
  660. element.dispose();
  661. var nodelist = new goog.ui.Control(null);
  662. nodelist.decorate(goog.dom.getElement('nodelist'));
  663. assertSameElements(
  664. 'Content of control decorating DIV with mixed ' +
  665. 'contents must be as expected',
  666. goog.dom.getElement('nodelist').childNodes, nodelist.getContent());
  667. nodelist.dispose();
  668. }
  669. /**
  670. * Tests {@link goog.ui.Control#setAriaLabel}.
  671. */
  672. function testSetAriaLabel_render() {
  673. assertNull(
  674. 'Controls must not have any aria label by default',
  675. control.getAriaLabel());
  676. control.setAriaLabel('label');
  677. assertEquals('Control must have aria label', 'label', control.getAriaLabel());
  678. control.render(sandbox);
  679. var elem = control.getElementStrict();
  680. assertEquals(
  681. 'Element must have control\'s aria label after rendering', 'label',
  682. goog.a11y.aria.getLabel(elem));
  683. control.setAriaLabel('new label');
  684. assertEquals(
  685. 'Element must have the new aria label', 'new label',
  686. goog.a11y.aria.getLabel(elem));
  687. }
  688. /**
  689. * Tests {@link goog.ui.Control#setAriaLabel}.
  690. */
  691. function testSetAriaLabel_decorate() {
  692. assertNull(
  693. 'Controls must not have any aria label by default',
  694. control.getAriaLabel());
  695. control.setAriaLabel('label');
  696. assertEquals('Control must have aria label', 'label', control.getAriaLabel());
  697. sandbox.innerHTML = '<div id="nodelist" role="button">' +
  698. 'Hello, <b>world</b>!</div>';
  699. control.decorate(goog.dom.getElement('nodelist'));
  700. var elem = control.getElementStrict();
  701. assertEquals(
  702. 'Element must have control\'s aria label after rendering', 'label',
  703. goog.a11y.aria.getLabel(elem));
  704. assertEquals(
  705. 'Element must have the correct role', 'button',
  706. elem.getAttribute('role'));
  707. control.setAriaLabel('new label');
  708. assertEquals(
  709. 'Element must have the new aria label', 'new label',
  710. goog.a11y.aria.getLabel(elem));
  711. }
  712. /**
  713. * Tests {@link goog.ui.Control#setContent}.
  714. */
  715. function testSetContent() {
  716. control.setContent('Bye');
  717. assertEquals(
  718. 'Unrendered control control must have expected contents', 'Bye',
  719. control.getContent());
  720. assertNull('No DOM must be created by setContent', control.getElement());
  721. control.createDom();
  722. assertEquals(
  723. 'Rendered control\'s DOM must have expected contents', 'Bye',
  724. control.getElement().innerHTML);
  725. control.setContent(null);
  726. assertNull(
  727. 'Rendered control must have expected contents', control.getContent());
  728. assertEquals(
  729. 'Rendered control\'s DOM must have expected contents', '',
  730. control.getElement().innerHTML);
  731. control.setContent([
  732. goog.dom.createDom(
  733. goog.dom.TagName.DIV, null,
  734. goog.dom.createDom(goog.dom.TagName.SPAN, null, 'Hello')),
  735. 'World'
  736. ]);
  737. assertHTMLEquals(
  738. 'Control\'s DOM must be updated', '<div><span>Hello</span></div>World',
  739. control.getElement().innerHTML);
  740. }
  741. /**
  742. * Tests {@link goog.ui.Control#setContentInternal}.
  743. */
  744. function testSetContentInternal() {
  745. control.render(sandbox);
  746. assertEquals(
  747. 'Control must have expected content after rendering', 'Hello',
  748. control.getContent());
  749. control.setContentInternal('Bye');
  750. assertEquals(
  751. 'Control must have expected contents', 'Bye', control.getContent());
  752. assertEquals(
  753. 'Control\'s DOM must be unchanged', 'Hello',
  754. control.getElement().innerHTML);
  755. }
  756. /**
  757. * Tests {@link goog.ui.Control#getCaption}.
  758. */
  759. function testGetCaption() {
  760. assertEquals(
  761. 'Empty control\'s caption must be empty string', '',
  762. (new goog.ui.Control(null)).getCaption());
  763. assertEquals(
  764. 'Caption must have expected value', 'Hello', control.getCaption());
  765. sandbox.innerHTML = '<div id="nodelist">Hello, <b>world</b>!</div>';
  766. control.decorate(goog.dom.getElement('nodelist'));
  767. assertEquals(
  768. 'Caption must have expected value', 'Hello, world!',
  769. control.getCaption());
  770. var arrayContent = goog.array.clone(
  771. goog.dom.safeHtmlToNode(
  772. goog.html.testing.newSafeHtmlForTest(
  773. ' <b> foo</b><i> bar</i> ')).childNodes);
  774. control.setContent(arrayContent);
  775. assertEquals(
  776. 'whitespaces must be normalized in the caption', 'foo bar',
  777. control.getCaption());
  778. control.setContent('\xa0foo');
  779. assertEquals(
  780. 'indenting spaces must be kept', '\xa0foo', control.getCaption());
  781. }
  782. /**
  783. * Tests {@link goog.ui.Control#setCaption}.
  784. */
  785. function testSetCaption() {
  786. control.setCaption('Hello, world!');
  787. assertEquals(
  788. 'Control must have a string caption "Hello, world!"', 'Hello, world!',
  789. control.getCaption());
  790. }
  791. /**
  792. * Tests {@link goog.ui.Control#setRightToLeft}.
  793. */
  794. function testSetRightToLeft() {
  795. control.createDom();
  796. assertFalse(
  797. 'Control\'s element must not have right-to-left class',
  798. goog.dom.classlist.contains(control.getElement(), 'goog-control-rtl'));
  799. control.setRightToLeft(true);
  800. assertTrue(
  801. 'Control\'s element must have right-to-left class',
  802. goog.dom.classlist.contains(control.getElement(), 'goog-control-rtl'));
  803. control.render(sandbox);
  804. assertThrows(
  805. 'Changing the render direction of a control already in ' +
  806. 'the document is an error',
  807. function() { control.setRightToLeft(false); });
  808. }
  809. /**
  810. * Tests {@link goog.ui.Control#isAllowTextSelection}.
  811. */
  812. function testIsAllowTextSelection() {
  813. assertFalse(
  814. 'Controls must not allow text selection by default',
  815. control.isAllowTextSelection());
  816. }
  817. /**
  818. * Tests {@link goog.ui.Control#setAllowTextSelection}.
  819. */
  820. function testSetAllowTextSelection() {
  821. assertFalse(
  822. 'Controls must not allow text selection by default',
  823. control.isAllowTextSelection());
  824. control.setAllowTextSelection(true);
  825. assertTrue(
  826. 'Control must allow text selection', control.isAllowTextSelection());
  827. control.setAllowTextSelection(false);
  828. assertFalse(
  829. 'Control must no longer allow text selection',
  830. control.isAllowTextSelection());
  831. control.render(sandbox);
  832. assertFalse(
  833. 'Control must not allow text selection even after rendered',
  834. control.isAllowTextSelection());
  835. control.setAllowTextSelection(true);
  836. assertTrue(
  837. 'Control must once again allow text selection',
  838. control.isAllowTextSelection());
  839. }
  840. /**
  841. * Tests {@link goog.ui.Control#isVisible}.
  842. */
  843. function testIsVisible() {
  844. assertTrue('Controls must be visible by default', control.isVisible());
  845. }
  846. /**
  847. * Tests {@link goog.ui.Control#setVisible} before it is rendered.
  848. */
  849. function testSetVisible() {
  850. assertFalse(
  851. 'setVisible(true) must return false if already visible',
  852. control.setVisible(true));
  853. assertTrue('No events must have been dispatched', noEventsDispatched());
  854. assertTrue(
  855. 'setVisible(false) must return true if previously visible',
  856. control.setVisible(false));
  857. assertEquals(
  858. 'One HIDE event must have been dispatched', 1,
  859. getEventCount(control, goog.ui.Component.EventType.HIDE));
  860. assertFalse('Control must no longer be visible', control.isVisible());
  861. assertTrue(
  862. 'setVisible(true) must return true if previously hidden',
  863. control.setVisible(true));
  864. assertEquals(
  865. 'One SHOW event must have been dispatched', 1,
  866. getEventCount(control, goog.ui.Component.EventType.SHOW));
  867. assertTrue('Control must be visible', control.isVisible());
  868. }
  869. /**
  870. * Tests {@link goog.ui.Control#setVisible} after it is rendered.
  871. */
  872. function testSetVisibleForRenderedControl() {
  873. control.render(sandbox);
  874. assertTrue(
  875. 'No events must have been dispatched during rendering',
  876. noEventsDispatched());
  877. assertFalse(
  878. 'setVisible(true) must return false if already visible',
  879. control.setVisible(true));
  880. assertTrue('No events must have been dispatched', noEventsDispatched());
  881. assertTrue(
  882. 'Control\'s element must be visible',
  883. control.getElement().style.display != 'none');
  884. assertTrue(
  885. 'setVisible(false) must return true if previously visible',
  886. control.setVisible(false));
  887. assertEquals(
  888. 'One HIDE event must have been dispatched', 1,
  889. getEventCount(control, goog.ui.Component.EventType.HIDE));
  890. assertFalse('Control must no longer be visible', control.isVisible());
  891. assertTrue(
  892. 'Control\'s element must be hidden',
  893. control.getElement().style.display == 'none');
  894. assertTrue(
  895. 'setVisible(true) must return true if previously hidden',
  896. control.setVisible(true));
  897. assertEquals(
  898. 'One SHOW event must have been dispatched', 1,
  899. getEventCount(control, goog.ui.Component.EventType.SHOW));
  900. assertTrue('Control must be visible', control.isVisible());
  901. assertTrue(
  902. 'Control\'s element must be visible',
  903. control.getElement().style.display != 'none');
  904. }
  905. /**
  906. * Tests {@link goog.ui.Control#setVisible} for disabled non-focusable
  907. * controls.
  908. */
  909. function testSetVisibleForDisabledNonFocusableControl() {
  910. // Hidden, disabled, non-focusable control becoming visible.
  911. control.setEnabled(false);
  912. control.setSupportedState(goog.ui.Component.State.FOCUSED, false);
  913. control.render(sandbox);
  914. assertTrue('Control must be visible', control.isVisible());
  915. assertFalse(
  916. 'Control must not have a tab index',
  917. goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
  918. // Visible, disabled, non-focusable control becoming hidden.
  919. control.getKeyEventTarget().focus();
  920. assertEquals(
  921. 'Control must not have dispatched FOCUS', 0,
  922. getEventCount(control, goog.ui.Component.EventType.FOCUS));
  923. assertFalse('Control must not have keyboard focus', control.isFocused());
  924. control.setVisible(false);
  925. assertFalse('Control must be hidden', control.isVisible());
  926. assertFalse(
  927. 'Control must not have a tab index',
  928. goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
  929. assertEquals(
  930. 'Control must have dispatched HIDE', 1,
  931. getEventCount(control, goog.ui.Component.EventType.HIDE));
  932. assertEquals(
  933. 'Control must not have dispatched BLUR', 0,
  934. getEventCount(control, goog.ui.Component.EventType.BLUR));
  935. }
  936. /**
  937. * Tests {@link goog.ui.Control#setVisible} for disabled focusable controls.
  938. */
  939. function testSetVisibleForDisabledFocusableControl() {
  940. // Hidden, disabled, focusable control becoming visible.
  941. control.setEnabled(false);
  942. control.setSupportedState(goog.ui.Component.State.FOCUSED, true);
  943. control.render(sandbox);
  944. assertTrue('Control must be visible', control.isVisible());
  945. assertFalse(
  946. 'Control must not have a tab index',
  947. goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
  948. // Visible, disabled, focusable control becoming hidden.
  949. control.getKeyEventTarget().focus();
  950. assertEquals(
  951. 'Control must not have dispatched FOCUS', 0,
  952. getEventCount(control, goog.ui.Component.EventType.FOCUS));
  953. assertFalse('Control must not have keyboard focus', control.isFocused());
  954. control.setVisible(false);
  955. assertFalse('Control must be hidden', control.isVisible());
  956. assertFalse(
  957. 'Control must not have a tab index',
  958. goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
  959. assertEquals(
  960. 'Control must have dispatched HIDE', 1,
  961. getEventCount(control, goog.ui.Component.EventType.HIDE));
  962. assertEquals(
  963. 'Control must not have dispatched BLUR', 0,
  964. getEventCount(control, goog.ui.Component.EventType.BLUR));
  965. }
  966. /**
  967. * Tests {@link goog.ui.Control#setVisible} for enabled non-focusable
  968. * controls.
  969. */
  970. function testSetVisibleForEnabledNonFocusableControl() {
  971. // Hidden, enabled, non-focusable control becoming visible.
  972. control.setEnabled(true);
  973. control.setSupportedState(goog.ui.Component.State.FOCUSED, false);
  974. control.render(sandbox);
  975. assertTrue('Control must be visible', control.isVisible());
  976. assertFalse(
  977. 'Control must not have a tab index',
  978. goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
  979. if (testFocus) {
  980. // Visible, enabled, non-focusable control becoming hidden.
  981. control.getKeyEventTarget().focus();
  982. assertEquals(
  983. 'Control must not have dispatched FOCUS', 0,
  984. getEventCount(control, goog.ui.Component.EventType.FOCUS));
  985. assertFalse('Control must not have keyboard focus', control.isFocused());
  986. control.setVisible(false);
  987. assertFalse('Control must be hidden', control.isVisible());
  988. assertFalse(
  989. 'Control must not have a tab index',
  990. goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
  991. assertEquals(
  992. 'Control must have dispatched HIDE', 1,
  993. getEventCount(control, goog.ui.Component.EventType.HIDE));
  994. assertEquals(
  995. 'Control must not have dispatched BLUR', 0,
  996. getEventCount(control, goog.ui.Component.EventType.BLUR));
  997. }
  998. }
  999. /**
  1000. * Tests {@link goog.ui.Control#setVisible} for enabled focusable controls.
  1001. */
  1002. function testSetVisibleForEnabledFocusableControl() {
  1003. // Hidden, enabled, focusable control becoming visible.
  1004. control.setEnabled(true);
  1005. control.setSupportedState(goog.ui.Component.State.FOCUSED, true);
  1006. control.render(sandbox);
  1007. assertTrue('Control must be visible', control.isVisible());
  1008. if (testFocus) {
  1009. // Expected to fail on Mac Safari prior to version 527.
  1010. expectedFailures.expectFailureFor(isMacSafari3());
  1011. try {
  1012. // Mac Safari currently doesn't support tabIndex on arbitrary
  1013. // elements.
  1014. assertTrue(
  1015. 'Control must have a tab index',
  1016. goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
  1017. } catch (e) {
  1018. expectedFailures.handleException(e);
  1019. }
  1020. // Visible, enabled, focusable control becoming hidden.
  1021. control.getKeyEventTarget().focus();
  1022. // Expected to fail on IE.
  1023. expectedFailures.expectFailureFor(goog.userAgent.IE);
  1024. try {
  1025. // IE dispatches focus and blur events asynchronously!
  1026. assertEquals(
  1027. 'Control must have dispatched FOCUS', 1,
  1028. getEventCount(control, goog.ui.Component.EventType.FOCUS));
  1029. assertTrue('Control must have keyboard focus', control.isFocused());
  1030. } catch (e) {
  1031. expectedFailures.handleException(e);
  1032. }
  1033. control.setVisible(false);
  1034. assertFalse('Control must be hidden', control.isVisible());
  1035. assertFalse(
  1036. 'Control must not have a tab index',
  1037. goog.dom.isFocusableTabIndex(control.getKeyEventTarget()));
  1038. assertEquals(
  1039. 'Control must have dispatched HIDE', 1,
  1040. getEventCount(control, goog.ui.Component.EventType.HIDE));
  1041. // Expected to fail on IE.
  1042. expectedFailures.expectFailureFor(goog.userAgent.IE);
  1043. try {
  1044. // IE dispatches focus and blur events asynchronously!
  1045. assertEquals(
  1046. 'Control must have dispatched BLUR', 1,
  1047. getEventCount(control, goog.ui.Component.EventType.BLUR));
  1048. assertFalse(
  1049. 'Control must no longer have keyboard focus', control.isFocused());
  1050. } catch (e) {
  1051. expectedFailures.handleException(e);
  1052. }
  1053. }
  1054. }
  1055. /**
  1056. * Tests {@link goog.ui.Control#isEnabled}.
  1057. */
  1058. function testIsEnabled() {
  1059. assertTrue('Controls must be enabled by default', control.isEnabled());
  1060. }
  1061. /**
  1062. * Tests {@link goog.ui.Control#setEnabled}.
  1063. */
  1064. function testSetEnabled() {
  1065. control.render(sandbox);
  1066. control.setHighlighted(true);
  1067. control.setActive(true);
  1068. control.getKeyEventTarget().focus();
  1069. resetEventCount();
  1070. control.setEnabled(true);
  1071. assertTrue('No events must have been dispatched', noEventsDispatched());
  1072. assertTrue('Control must be enabled', control.isEnabled());
  1073. assertTrue('Control must be highlighted', control.isHighlighted());
  1074. assertTrue('Control must be active', control.isActive());
  1075. var elem = control.getElementStrict();
  1076. assertTrue(
  1077. 'Control element must not have aria-disabled',
  1078. goog.string.isEmptyOrWhitespace(aria.getState(elem, State.DISABLED)));
  1079. assertEquals(
  1080. 'Control element must have a tabIndex of 0', 0,
  1081. goog.string.toNumber(elem.getAttribute('tabIndex') || ''));
  1082. if (testFocus) {
  1083. // Expected to fail on IE and Mac Safari 3. IE calls focus handlers
  1084. // asynchronously, and Mac Safari 3 doesn't support keyboard focus.
  1085. expectedFailures.expectFailureFor(goog.userAgent.IE);
  1086. expectedFailures.expectFailureFor(isMacSafari3());
  1087. try {
  1088. assertTrue('Control must be focused', control.isFocused());
  1089. } catch (e) {
  1090. expectedFailures.handleException(e);
  1091. }
  1092. }
  1093. resetEventCount();
  1094. control.setEnabled(false);
  1095. assertEquals(
  1096. 'One DISABLE event must have been dispatched', 1,
  1097. getEventCount(control, goog.ui.Component.EventType.DISABLE));
  1098. assertFalse('Control must be disabled', control.isEnabled());
  1099. assertFalse('Control must not be highlighted', control.isHighlighted());
  1100. assertFalse('Control must not be active', control.isActive());
  1101. assertFalse('Control must not be focused', control.isFocused());
  1102. assertEquals(
  1103. 'Control element must have aria-disabled true', 'true',
  1104. aria.getState(control.getElementStrict(), State.DISABLED));
  1105. assertNull(
  1106. 'Control element must not have a tabIndex',
  1107. control.getElement().getAttribute('tabIndex'));
  1108. control.setEnabled(true);
  1109. control.exitDocument();
  1110. var cssClass = goog.getCssName(goog.ui.ControlRenderer.CSS_CLASS, 'disabled');
  1111. var element = goog.dom.createDom(goog.dom.TagName.DIV, {tabIndex: 0});
  1112. element.className = cssClass;
  1113. goog.dom.appendChild(sandbox, element);
  1114. control.decorate(element);
  1115. assertEquals(
  1116. 'Control element must have aria-disabled true', 'true',
  1117. aria.getState(control.getElementStrict(), State.DISABLED));
  1118. assertNull(
  1119. 'Control element must not have a tabIndex',
  1120. control.getElement().getAttribute('tabIndex'));
  1121. control.setEnabled(true);
  1122. elem = control.getElementStrict();
  1123. assertEquals(
  1124. 'Control element must have aria-disabled false', 'false',
  1125. aria.getState(elem, State.DISABLED));
  1126. assertEquals(
  1127. 'Control element must have tabIndex 0', 0,
  1128. goog.string.toNumber(elem.getAttribute('tabIndex') || ''));
  1129. }
  1130. /**
  1131. * Tests {@link goog.ui.Control#setState} when using
  1132. * goog.ui.Component.State.DISABLED.
  1133. */
  1134. function testSetStateWithDisabled() {
  1135. control.render(sandbox);
  1136. control.setHighlighted(true);
  1137. control.setActive(true);
  1138. control.getKeyEventTarget().focus();
  1139. resetEventCount();
  1140. control.setState(goog.ui.Component.State.DISABLED, false);
  1141. assertTrue('No events must have been dispatched', noEventsDispatched());
  1142. assertTrue('Control must be enabled', control.isEnabled());
  1143. assertTrue('Control must be highlighted', control.isHighlighted());
  1144. assertTrue('Control must be active', control.isActive());
  1145. assertTrue(
  1146. 'Control element must not have aria-disabled',
  1147. goog.string.isEmptyOrWhitespace(
  1148. aria.getState(control.getElementStrict(), State.DISABLED)));
  1149. assertEquals(
  1150. 'Control element must have a tabIndex of 0', 0,
  1151. goog.string.toNumber(
  1152. control.getElement().getAttribute('tabIndex') || ''));
  1153. if (testFocus) {
  1154. // Expected to fail on IE and Mac Safari 3. IE calls focus handlers
  1155. // asynchronously, and Mac Safari 3 doesn't support keyboard focus.
  1156. expectedFailures.expectFailureFor(goog.userAgent.IE);
  1157. expectedFailures.expectFailureFor(isMacSafari3());
  1158. try {
  1159. assertTrue('Control must be focused', control.isFocused());
  1160. } catch (e) {
  1161. expectedFailures.handleException(e);
  1162. }
  1163. }
  1164. resetEventCount();
  1165. control.setState(goog.ui.Component.State.DISABLED, true);
  1166. assertEquals(
  1167. 'One DISABLE event must have been dispatched', 1,
  1168. getEventCount(control, goog.ui.Component.EventType.DISABLE));
  1169. assertFalse('Control must be disabled', control.isEnabled());
  1170. assertFalse('Control must not be highlighted', control.isHighlighted());
  1171. assertFalse('Control must not be active', control.isActive());
  1172. assertFalse('Control must not be focused', control.isFocused());
  1173. assertEquals(
  1174. 'Control element must have aria-disabled true', 'true',
  1175. aria.getState(control.getElementStrict(), State.DISABLED));
  1176. assertNull(
  1177. 'Control element must not have a tabIndex',
  1178. control.getElement().getAttribute('tabIndex'));
  1179. control.setState(goog.ui.Component.State.DISABLED, false);
  1180. control.exitDocument();
  1181. var cssClass = goog.getCssName(goog.ui.ControlRenderer.CSS_CLASS, 'disabled');
  1182. var element = goog.dom.createDom(goog.dom.TagName.DIV, {tabIndex: 0});
  1183. element.className = cssClass;
  1184. goog.dom.appendChild(sandbox, element);
  1185. control.decorate(element);
  1186. assertEquals(
  1187. 'Control element must have aria-disabled true', 'true',
  1188. aria.getState(control.getElementStrict(), State.DISABLED));
  1189. assertNull(
  1190. 'Control element must not have a tabIndex',
  1191. control.getElement().getAttribute('tabIndex'));
  1192. control.setState(goog.ui.Component.State.DISABLED, false);
  1193. elem = control.getElementStrict();
  1194. assertEquals(
  1195. 'Control element must have aria-disabled false', 'false',
  1196. aria.getState(elem, State.DISABLED));
  1197. assertEquals(
  1198. 'Control element must have tabIndex 0', 0,
  1199. goog.string.toNumber(elem.getAttribute('tabIndex') || ''));
  1200. }
  1201. /**
  1202. * Tests {@link goog.ui.Control#setEnabled} when the control has a parent.
  1203. */
  1204. function testSetEnabledWithParent() {
  1205. var child = new goog.ui.Control(null);
  1206. child.setDispatchTransitionEvents(goog.ui.Component.State.ALL, true);
  1207. control.addChild(child, true /* opt_render */);
  1208. control.setEnabled(false);
  1209. resetEventCount();
  1210. assertFalse('Parent must be disabled', control.isEnabled());
  1211. assertTrue('Child must be enabled', child.isEnabled());
  1212. child.setEnabled(false);
  1213. assertTrue(
  1214. 'No events must have been dispatched when child is disabled',
  1215. noEventsDispatched());
  1216. assertTrue('Child must still be enabled', child.isEnabled());
  1217. resetEventCount();
  1218. control.setEnabled(true);
  1219. assertEquals(
  1220. 'One ENABLE event must have been dispatched by the parent', 1,
  1221. getEventCount(control, goog.ui.Component.EventType.ENABLE));
  1222. assertTrue('Parent must be enabled', control.isEnabled());
  1223. assertTrue('Child must still be enabled', child.isEnabled());
  1224. resetEventCount();
  1225. child.setEnabled(false);
  1226. assertEquals(
  1227. 'One DISABLE event must have been dispatched by the child', 1,
  1228. getEventCount(child, goog.ui.Component.EventType.DISABLE));
  1229. assertTrue('Parent must still be enabled', control.isEnabled());
  1230. assertFalse('Child must now be disabled', child.isEnabled());
  1231. resetEventCount();
  1232. control.setEnabled(false);
  1233. assertEquals(
  1234. 'One DISABLE event must have been dispatched by the parent', 1,
  1235. getEventCount(control, goog.ui.Component.EventType.DISABLE));
  1236. assertFalse('Parent must now be disabled', control.isEnabled());
  1237. assertFalse('Child must still be disabled', child.isEnabled());
  1238. child.dispose();
  1239. }
  1240. /**
  1241. * Tests {@link goog.ui.Control#isHighlighted}.
  1242. */
  1243. function testIsHighlighted() {
  1244. assertFalse(
  1245. 'Controls must not be highlighted by default', control.isHighlighted());
  1246. }
  1247. /**
  1248. * Tests {@link goog.ui.Control#setHighlighted}.
  1249. */
  1250. function testSetHighlighted() {
  1251. control.setSupportedState(goog.ui.Component.State.HOVER, false);
  1252. control.setHighlighted(true);
  1253. assertFalse(
  1254. 'Control must not be highlighted, because it isn\'t ' +
  1255. 'highlightable',
  1256. control.isHighlighted());
  1257. assertTrue(
  1258. 'Control must not have dispatched any events', noEventsDispatched());
  1259. control.setSupportedState(goog.ui.Component.State.HOVER, true);
  1260. control.setHighlighted(true);
  1261. assertTrue('Control must be highlighted', control.isHighlighted());
  1262. assertEquals(
  1263. 'Control must have dispatched a HIGHLIGHT event', 1,
  1264. getEventCount(control, goog.ui.Component.EventType.HIGHLIGHT));
  1265. control.setHighlighted(true);
  1266. assertTrue('Control must still be highlighted', control.isHighlighted());
  1267. assertEquals(
  1268. 'Control must not dispatch more HIGHLIGHT events', 1,
  1269. getEventCount(control, goog.ui.Component.EventType.HIGHLIGHT));
  1270. control.setHighlighted(false);
  1271. assertFalse('Control must not be highlighted', control.isHighlighted());
  1272. assertEquals(
  1273. 'Control must have dispatched an UNHIGHLIGHT event', 1,
  1274. getEventCount(control, goog.ui.Component.EventType.UNHIGHLIGHT));
  1275. control.setEnabled(false);
  1276. assertFalse('Control must be disabled', control.isEnabled());
  1277. control.setHighlighted(true);
  1278. assertTrue(
  1279. 'Control must be highlighted, even when disabled',
  1280. control.isHighlighted());
  1281. assertEquals(
  1282. 'Control must have dispatched another HIGHLIGHT event', 2,
  1283. getEventCount(control, goog.ui.Component.EventType.HIGHLIGHT));
  1284. }
  1285. /**
  1286. * Tests {@link goog.ui.Control#isActive}.
  1287. */
  1288. function testIsActive() {
  1289. assertFalse('Controls must not be active by default', control.isActive());
  1290. }
  1291. /**
  1292. * Tests {@link goog.ui.Control#setActive}.
  1293. */
  1294. function testSetActive() {
  1295. control.setSupportedState(goog.ui.Component.State.ACTIVE, false);
  1296. control.setActive(true);
  1297. assertFalse(
  1298. 'Control must not be active, because it isn\'t activateable',
  1299. control.isActive());
  1300. assertTrue(
  1301. 'Control must not have dispatched any events', noEventsDispatched());
  1302. control.setSupportedState(goog.ui.Component.State.ACTIVE, true);
  1303. control.setActive(true);
  1304. assertTrue('Control must be active', control.isActive());
  1305. assertEquals(
  1306. 'Control must have dispatched an ACTIVATE event', 1,
  1307. getEventCount(control, goog.ui.Component.EventType.ACTIVATE));
  1308. control.setActive(true);
  1309. assertTrue('Control must still be active', control.isActive());
  1310. assertEquals(
  1311. 'Control must not dispatch more ACTIVATE events', 1,
  1312. getEventCount(control, goog.ui.Component.EventType.ACTIVATE));
  1313. control.setEnabled(false);
  1314. assertFalse('Control must be disabled', control.isEnabled());
  1315. assertFalse('Control must not be active', control.isActive());
  1316. assertEquals(
  1317. 'Control must have dispatched a DEACTIVATE event', 1,
  1318. getEventCount(control, goog.ui.Component.EventType.DEACTIVATE));
  1319. }
  1320. /**
  1321. * Tests disposing the control from an action event handler.
  1322. */
  1323. function testDisposeOnAction() {
  1324. goog.events.listen(control, goog.ui.Component.EventType.ACTION, function(e) {
  1325. control.dispose();
  1326. });
  1327. // Control must not throw an exception if disposed of in an ACTION event
  1328. // handler.
  1329. control.performActionInternal();
  1330. control.setActive(true);
  1331. assertTrue('Control should have been disposed of', control.isDisposed());
  1332. }
  1333. /**
  1334. * Tests {@link goog.ui.Control#isSelected}.
  1335. */
  1336. function testIsSelected() {
  1337. assertFalse('Controls must not be selected by default', control.isSelected());
  1338. }
  1339. /**
  1340. * Tests {@link goog.ui.Control#setSelected}.
  1341. */
  1342. function testSetSelected() {
  1343. control.setSupportedState(goog.ui.Component.State.SELECTED, false);
  1344. control.setSelected(true);
  1345. assertFalse(
  1346. 'Control must not be selected, because it isn\'t selectable',
  1347. control.isSelected());
  1348. assertTrue(
  1349. 'Control must not have dispatched any events', noEventsDispatched());
  1350. control.setSupportedState(goog.ui.Component.State.SELECTED, true);
  1351. control.setSelected(true);
  1352. assertTrue('Control must be selected', control.isSelected());
  1353. assertEquals(
  1354. 'Control must have dispatched a SELECT event', 1,
  1355. getEventCount(control, goog.ui.Component.EventType.SELECT));
  1356. control.setSelected(true);
  1357. assertTrue('Control must still be selected', control.isSelected());
  1358. assertEquals(
  1359. 'Control must not dispatch more SELECT events', 1,
  1360. getEventCount(control, goog.ui.Component.EventType.SELECT));
  1361. control.setSelected(false);
  1362. assertFalse('Control must not be selected', control.isSelected());
  1363. assertEquals(
  1364. 'Control must have dispatched an UNSELECT event', 1,
  1365. getEventCount(control, goog.ui.Component.EventType.UNSELECT));
  1366. control.setEnabled(false);
  1367. assertFalse('Control must be disabled', control.isEnabled());
  1368. control.setSelected(true);
  1369. assertTrue(
  1370. 'Control must be selected, even when disabled', control.isSelected());
  1371. assertEquals(
  1372. 'Control must have dispatched another SELECT event', 2,
  1373. getEventCount(control, goog.ui.Component.EventType.SELECT));
  1374. }
  1375. /**
  1376. * Tests {@link goog.ui.Control#isChecked}.
  1377. */
  1378. function testIsChecked() {
  1379. assertFalse('Controls must not be checked by default', control.isChecked());
  1380. }
  1381. /**
  1382. * Tests {@link goog.ui.Control#setChecked}.
  1383. */
  1384. function testSetChecked() {
  1385. control.setSupportedState(goog.ui.Component.State.CHECKED, false);
  1386. control.setChecked(true);
  1387. assertFalse(
  1388. 'Control must not be checked, because it isn\'t checkable',
  1389. control.isChecked());
  1390. assertTrue(
  1391. 'Control must not have dispatched any events', noEventsDispatched());
  1392. control.setSupportedState(goog.ui.Component.State.CHECKED, true);
  1393. control.setChecked(true);
  1394. assertTrue('Control must be checked', control.isChecked());
  1395. assertEquals(
  1396. 'Control must have dispatched a CHECK event', 1,
  1397. getEventCount(control, goog.ui.Component.EventType.CHECK));
  1398. control.setChecked(true);
  1399. assertTrue('Control must still be checked', control.isChecked());
  1400. assertEquals(
  1401. 'Control must not dispatch more CHECK events', 1,
  1402. getEventCount(control, goog.ui.Component.EventType.CHECK));
  1403. control.setChecked(false);
  1404. assertFalse('Control must not be checked', control.isChecked());
  1405. assertEquals(
  1406. 'Control must have dispatched an UNCHECK event', 1,
  1407. getEventCount(control, goog.ui.Component.EventType.UNCHECK));
  1408. control.setEnabled(false);
  1409. assertFalse('Control must be disabled', control.isEnabled());
  1410. control.setChecked(true);
  1411. assertTrue(
  1412. 'Control must be checked, even when disabled', control.isChecked());
  1413. assertEquals(
  1414. 'Control must have dispatched another CHECK event', 2,
  1415. getEventCount(control, goog.ui.Component.EventType.CHECK));
  1416. }
  1417. /**
  1418. * Tests {@link goog.ui.Control#isFocused}.
  1419. */
  1420. function testIsFocused() {
  1421. assertFalse('Controls must not be focused by default', control.isFocused());
  1422. }
  1423. /**
  1424. * Tests {@link goog.ui.Control#setFocused}.
  1425. */
  1426. function testSetFocused() {
  1427. control.setSupportedState(goog.ui.Component.State.FOCUSED, false);
  1428. control.setFocused(true);
  1429. assertFalse(
  1430. 'Control must not be focused, because it isn\'t focusable',
  1431. control.isFocused());
  1432. assertTrue(
  1433. 'Control must not have dispatched any events', noEventsDispatched());
  1434. control.setSupportedState(goog.ui.Component.State.FOCUSED, true);
  1435. control.setFocused(true);
  1436. assertTrue('Control must be focused', control.isFocused());
  1437. assertEquals(
  1438. 'Control must have dispatched a FOCUS event', 1,
  1439. getEventCount(control, goog.ui.Component.EventType.FOCUS));
  1440. control.setFocused(true);
  1441. assertTrue('Control must still be focused', control.isFocused());
  1442. assertEquals(
  1443. 'Control must not dispatch more FOCUS events', 1,
  1444. getEventCount(control, goog.ui.Component.EventType.FOCUS));
  1445. control.setFocused(false);
  1446. assertFalse('Control must not be focused', control.isFocused());
  1447. assertEquals(
  1448. 'Control must have dispatched an BLUR event', 1,
  1449. getEventCount(control, goog.ui.Component.EventType.BLUR));
  1450. control.setEnabled(false);
  1451. assertFalse('Control must be disabled', control.isEnabled());
  1452. control.setFocused(true);
  1453. assertTrue(
  1454. 'Control must be focused, even when disabled', control.isFocused());
  1455. assertEquals(
  1456. 'Control must have dispatched another FOCUS event', 2,
  1457. getEventCount(control, goog.ui.Component.EventType.FOCUS));
  1458. }
  1459. /**
  1460. * Tests {@link goog.ui.Control#isOpen}.
  1461. */
  1462. function testIsOpen() {
  1463. assertFalse('Controls must not be open by default', control.isOpen());
  1464. }
  1465. /**
  1466. * Tests {@link goog.ui.Control#setOpen}.
  1467. */
  1468. function testSetOpen() {
  1469. control.setSupportedState(goog.ui.Component.State.OPENED, false);
  1470. control.setOpen(true);
  1471. assertFalse(
  1472. 'Control must not be opened, because it isn\'t openable',
  1473. control.isOpen());
  1474. assertTrue(
  1475. 'Control must not have dispatched any events', noEventsDispatched());
  1476. control.setSupportedState(goog.ui.Component.State.OPENED, true);
  1477. control.setOpen(true);
  1478. assertTrue('Control must be opened', control.isOpen());
  1479. assertEquals(
  1480. 'Control must have dispatched a OPEN event', 1,
  1481. getEventCount(control, goog.ui.Component.EventType.OPEN));
  1482. control.setOpen(true);
  1483. assertTrue('Control must still be opened', control.isOpen());
  1484. assertEquals(
  1485. 'Control must not dispatch more OPEN events', 1,
  1486. getEventCount(control, goog.ui.Component.EventType.OPEN));
  1487. control.setOpen(false);
  1488. assertFalse('Control must not be opened', control.isOpen());
  1489. assertEquals(
  1490. 'Control must have dispatched an CLOSE event', 1,
  1491. getEventCount(control, goog.ui.Component.EventType.CLOSE));
  1492. control.setEnabled(false);
  1493. assertFalse('Control must be disabled', control.isEnabled());
  1494. control.setOpen(true);
  1495. assertTrue('Control must be opened, even when disabled', control.isOpen());
  1496. assertEquals(
  1497. 'Control must have dispatched another OPEN event', 2,
  1498. getEventCount(control, goog.ui.Component.EventType.OPEN));
  1499. }
  1500. /**
  1501. * Tests {@link goog.ui.Control#getState}.
  1502. */
  1503. function testGetState() {
  1504. assertEquals(
  1505. 'Controls must be in the default state', 0x00, control.getState());
  1506. }
  1507. /**
  1508. * Tests {@link goog.ui.Control#hasState}.
  1509. */
  1510. function testHasState() {
  1511. assertFalse(
  1512. 'Control must not be disabled',
  1513. control.hasState(goog.ui.Component.State.DISABLED));
  1514. assertFalse(
  1515. 'Control must not be in the HOVER state',
  1516. control.hasState(goog.ui.Component.State.HOVER));
  1517. assertFalse(
  1518. 'Control must not be active',
  1519. control.hasState(goog.ui.Component.State.ACTIVE));
  1520. assertFalse(
  1521. 'Control must not be selected',
  1522. control.hasState(goog.ui.Component.State.SELECTED));
  1523. assertFalse(
  1524. 'Control must not be checked',
  1525. control.hasState(goog.ui.Component.State.CHECKED));
  1526. assertFalse(
  1527. 'Control must not be focused',
  1528. control.hasState(goog.ui.Component.State.FOCUSED));
  1529. assertFalse(
  1530. 'Control must not be open',
  1531. control.hasState(goog.ui.Component.State.OPEN));
  1532. }
  1533. /**
  1534. * Tests {@link goog.ui.Control#setState}.
  1535. */
  1536. function testSetState() {
  1537. control.createDom();
  1538. control.setSupportedState(goog.ui.Component.State.ACTIVE, false);
  1539. assertFalse(
  1540. 'Control must not be active',
  1541. control.hasState(goog.ui.Component.State.ACTIVE));
  1542. control.setState(goog.ui.Component.State.ACTIVE, true);
  1543. assertFalse(
  1544. 'Control must still be inactive (because it doesn\'t ' +
  1545. 'support the ACTIVE state)',
  1546. control.hasState(goog.ui.Component.State.ACTIVE));
  1547. control.setSupportedState(goog.ui.Component.State.ACTIVE, true);
  1548. control.setState(goog.ui.Component.State.ACTIVE, true);
  1549. assertTrue(
  1550. 'Control must be active',
  1551. control.hasState(goog.ui.Component.State.ACTIVE));
  1552. assertTrue(
  1553. 'Control must have the active CSS style',
  1554. goog.dom.classlist.contains(control.getElement(), 'goog-control-active'));
  1555. control.setState(goog.ui.Component.State.ACTIVE, true);
  1556. assertTrue(
  1557. 'Control must still be active',
  1558. control.hasState(goog.ui.Component.State.ACTIVE));
  1559. assertTrue(
  1560. 'Control must still have the active CSS style',
  1561. goog.dom.classlist.contains(control.getElement(), 'goog-control-active'));
  1562. assertTrue('No events must have been dispatched', noEventsDispatched());
  1563. }
  1564. /**
  1565. * Tests {@link goog.ui.Control#setStateInternal}.
  1566. */
  1567. function testSetStateInternal() {
  1568. control.setStateInternal(0x00);
  1569. assertEquals('State should be 0x00', 0x00, control.getState());
  1570. control.setStateInternal(0x17);
  1571. assertEquals('State should be 0x17', 0x17, control.getState());
  1572. }
  1573. /**
  1574. * Tests {@link goog.ui.Control#isSupportedState}.
  1575. */
  1576. function testIsSupportedState() {
  1577. assertTrue(
  1578. 'Control must support DISABLED',
  1579. control.isSupportedState(goog.ui.Component.State.DISABLED));
  1580. assertTrue(
  1581. 'Control must support HOVER',
  1582. control.isSupportedState(goog.ui.Component.State.HOVER));
  1583. assertTrue(
  1584. 'Control must support ACTIVE',
  1585. control.isSupportedState(goog.ui.Component.State.ACTIVE));
  1586. assertTrue(
  1587. 'Control must support FOCUSED',
  1588. control.isSupportedState(goog.ui.Component.State.FOCUSED));
  1589. assertFalse(
  1590. 'Control must no support SELECTED',
  1591. control.isSupportedState(goog.ui.Component.State.SELECTED));
  1592. assertFalse(
  1593. 'Control must no support CHECKED',
  1594. control.isSupportedState(goog.ui.Component.State.CHECKED));
  1595. assertFalse(
  1596. 'Control must no support OPENED',
  1597. control.isSupportedState(goog.ui.Component.State.OPENED));
  1598. }
  1599. /**
  1600. * Tests {@link goog.ui.Control#setSupportedState}.
  1601. */
  1602. function testSetSupportedState() {
  1603. control.setSupportedState(goog.ui.Component.State.HOVER, true);
  1604. assertTrue(
  1605. 'Control must still support HOVER',
  1606. control.isSupportedState(goog.ui.Component.State.HOVER));
  1607. control.setSupportedState(goog.ui.Component.State.HOVER, false);
  1608. assertFalse(
  1609. 'Control must no longer support HOVER',
  1610. control.isSupportedState(goog.ui.Component.State.HOVER));
  1611. control.setState(goog.ui.Component.State.ACTIVE, true);
  1612. control.setSupportedState(goog.ui.Component.State.ACTIVE, false);
  1613. assertFalse(
  1614. 'Control must no longer support ACTIVE',
  1615. control.isSupportedState(goog.ui.Component.State.ACTIVE));
  1616. assertFalse(
  1617. 'Control must no longer be in the ACTIVE state',
  1618. control.hasState(goog.ui.Component.State.ACTIVE));
  1619. control.render(sandbox);
  1620. control.setSupportedState(goog.ui.Component.State.FOCUSED, true);
  1621. control.setState(goog.ui.Component.State.FOCUSED, true);
  1622. assertThrows(
  1623. 'Must not be able to disable support for the FOCUSED ' +
  1624. "state for a control that's already in the document and focused",
  1625. function() {
  1626. control.setSupportedState(goog.ui.Component.State.FOCUSED, false);
  1627. });
  1628. assertTrue('No events must have been dispatched', noEventsDispatched());
  1629. }
  1630. /**
  1631. * Tests {@link goog.ui.Control#isAutoState}.
  1632. */
  1633. function testIsAutoState() {
  1634. assertTrue(
  1635. 'Control must have DISABLED as an auto-state',
  1636. control.isAutoState(goog.ui.Component.State.DISABLED));
  1637. assertTrue(
  1638. 'Control must have HOVER as an auto-state',
  1639. control.isAutoState(goog.ui.Component.State.HOVER));
  1640. assertTrue(
  1641. 'Control must have ACTIVE as an auto-state',
  1642. control.isAutoState(goog.ui.Component.State.ACTIVE));
  1643. assertTrue(
  1644. 'Control must have FOCUSED as an auto-state',
  1645. control.isAutoState(goog.ui.Component.State.FOCUSED));
  1646. assertFalse(
  1647. 'Control must not have SELECTED as an auto-state',
  1648. control.isAutoState(goog.ui.Component.State.SELECTED));
  1649. assertFalse(
  1650. 'Control must not have CHECKED as an auto-state',
  1651. control.isAutoState(goog.ui.Component.State.CHECKED));
  1652. assertFalse(
  1653. 'Control must not have OPENED as an auto-state',
  1654. control.isAutoState(goog.ui.Component.State.OPENED));
  1655. assertTrue('No events must have been dispatched', noEventsDispatched());
  1656. }
  1657. /**
  1658. * Tests {@link goog.ui.Control#setAutoStates}.
  1659. */
  1660. function testSetAutoStates() {
  1661. control.setAutoStates(goog.ui.Component.State.HOVER, false);
  1662. assertFalse(
  1663. 'Control must not have HOVER as an auto-state',
  1664. control.isAutoState(goog.ui.Component.State.HOVER));
  1665. control.setAutoStates(
  1666. goog.ui.Component.State.ACTIVE | goog.ui.Component.State.FOCUSED, false);
  1667. assertFalse(
  1668. 'Control must not have ACTIVE as an auto-state',
  1669. control.isAutoState(goog.ui.Component.State.ACTIVE));
  1670. assertFalse(
  1671. 'Control must not have FOCUSED as an auto-state',
  1672. control.isAutoState(goog.ui.Component.State.FOCUSED));
  1673. control.setSupportedState(goog.ui.Component.State.FOCUSED, false);
  1674. control.setAutoStates(goog.ui.Component.State.FOCUSED, true);
  1675. assertFalse(
  1676. 'Control must not have FOCUSED as an auto-state if it no ' +
  1677. 'longer supports FOCUSED',
  1678. control.isAutoState(goog.ui.Component.State.FOCUSED));
  1679. assertTrue('No events must have been dispatched', noEventsDispatched());
  1680. }
  1681. /**
  1682. * Tests {@link goog.ui.Control#isDispatchTransitionEvents}.
  1683. */
  1684. function testIsDispatchTransitionEvents() {
  1685. assertTrue(
  1686. 'Control must dispatch DISABLED transition events',
  1687. control.isDispatchTransitionEvents(goog.ui.Component.State.DISABLED));
  1688. assertTrue(
  1689. 'Control must dispatch HOVER transition events',
  1690. control.isDispatchTransitionEvents(goog.ui.Component.State.HOVER));
  1691. assertTrue(
  1692. 'Control must dispatch ACTIVE transition events',
  1693. control.isDispatchTransitionEvents(goog.ui.Component.State.ACTIVE));
  1694. assertTrue(
  1695. 'Control must dispatch FOCUSED transition events',
  1696. control.isDispatchTransitionEvents(goog.ui.Component.State.FOCUSED));
  1697. assertFalse(
  1698. 'Control must not dispatch SELECTED transition events',
  1699. control.isDispatchTransitionEvents(goog.ui.Component.State.SELECTED));
  1700. assertFalse(
  1701. 'Control must not dispatch CHECKED transition events',
  1702. control.isDispatchTransitionEvents(goog.ui.Component.State.CHECKED));
  1703. assertFalse(
  1704. 'Control must not dispatch OPENED transition events',
  1705. control.isDispatchTransitionEvents(goog.ui.Component.State.OPENED));
  1706. assertTrue('No events must have been dispatched', noEventsDispatched());
  1707. }
  1708. /**
  1709. * Tests {@link goog.ui.Control#setDispatchTransitionEvents}.
  1710. */
  1711. function testSetDispatchTransitionEvents() {
  1712. control.setDispatchTransitionEvents(goog.ui.Component.State.HOVER, false);
  1713. assertFalse(
  1714. 'Control must not dispatch HOVER transition events',
  1715. control.isDispatchTransitionEvents(goog.ui.Component.State.HOVER));
  1716. control.setSupportedState(goog.ui.Component.State.SELECTED, true);
  1717. control.setDispatchTransitionEvents(goog.ui.Component.State.SELECTED, true);
  1718. assertTrue(
  1719. 'Control must dispatch SELECTED transition events',
  1720. control.isDispatchTransitionEvents(goog.ui.Component.State.SELECTED));
  1721. assertTrue('No events must have been dispatched', noEventsDispatched());
  1722. }
  1723. /**
  1724. * Tests {@link goog.ui.Control#isTransitionAllowed}.
  1725. */
  1726. function testIsTransitionAllowed() {
  1727. assertTrue(
  1728. 'Control must support the HOVER state',
  1729. control.isSupportedState(goog.ui.Component.State.HOVER));
  1730. assertFalse(
  1731. 'Control must not be in the HOVER state',
  1732. control.hasState(goog.ui.Component.State.HOVER));
  1733. assertTrue(
  1734. 'Control must dispatch HOVER transition events',
  1735. control.isDispatchTransitionEvents(goog.ui.Component.State.HOVER));
  1736. assertTrue(
  1737. 'Control must be allowed to transition to the HOVER state',
  1738. control.isTransitionAllowed(goog.ui.Component.State.HOVER, true));
  1739. assertEquals(
  1740. 'Control must have dispatched one HIGHLIGHT event', 1,
  1741. getEventCount(control, goog.ui.Component.EventType.HIGHLIGHT));
  1742. assertFalse(
  1743. 'Control must not be highlighted',
  1744. control.hasState(goog.ui.Component.State.HOVER));
  1745. control.setState(goog.ui.Component.State.HOVER, true);
  1746. control.setDispatchTransitionEvents(goog.ui.Component.State.HOVER, false);
  1747. assertTrue(
  1748. 'Control must be allowed to transition from the HOVER state',
  1749. control.isTransitionAllowed(goog.ui.Component.State.HOVER, false));
  1750. assertEquals(
  1751. 'Control must not have dispatched any UNHIGHLIGHT events', 0,
  1752. getEventCount(control, goog.ui.Component.EventType.UNHIGHLIGHT));
  1753. assertTrue(
  1754. 'Control must still be highlighted',
  1755. control.hasState(goog.ui.Component.State.HOVER));
  1756. control.setSupportedState(goog.ui.Component.State.FOCUSED, false);
  1757. resetEventCount();
  1758. assertFalse(
  1759. 'Control doesn\'t support the FOCUSED state',
  1760. control.isSupportedState(goog.ui.Component.State.FOCUSED));
  1761. assertFalse(
  1762. 'Control must not be FOCUSED',
  1763. control.hasState(goog.ui.Component.State.FOCUSED));
  1764. assertFalse(
  1765. 'Control must not be allowed to transition to the FOCUSED ' +
  1766. 'state',
  1767. control.isTransitionAllowed(goog.ui.Component.State.FOCUSED, true));
  1768. assertEquals(
  1769. 'Control must not have dispatched any FOCUS events', 0,
  1770. getEventCount(control, goog.ui.Component.EventType.FOCUS));
  1771. control.setEnabled(false);
  1772. resetEventCount();
  1773. assertTrue(
  1774. 'Control must support the DISABLED state',
  1775. control.isSupportedState(goog.ui.Component.State.DISABLED));
  1776. assertTrue(
  1777. 'Control must be DISABLED',
  1778. control.hasState(goog.ui.Component.State.DISABLED));
  1779. assertFalse(
  1780. 'Control must not be allowed to transition to the DISABLED ' +
  1781. 'state, because it is already there',
  1782. control.isTransitionAllowed(goog.ui.Component.State.DISABLED, true));
  1783. assertEquals(
  1784. 'Control must not have dispatched any ENABLE events', 0,
  1785. getEventCount(control, goog.ui.Component.EventType.ENABLE));
  1786. }
  1787. /**
  1788. * Tests {@link goog.ui.Control#handleKeyEvent}.
  1789. */
  1790. function testHandleKeyEvent() {
  1791. control.render();
  1792. control.isVisible = control.isEnabled = function() { return true; };
  1793. goog.testing.events.fireKeySequence(
  1794. control.getKeyEventTarget(), goog.events.KeyCodes.A);
  1795. assertEquals(
  1796. 'Control must not have dispatched an ACTION event', 0,
  1797. getEventCount(control, goog.ui.Component.EventType.ACTION));
  1798. goog.testing.events.fireKeySequence(
  1799. control.getKeyEventTarget(), goog.events.KeyCodes.ENTER);
  1800. assertEquals(
  1801. 'Control must have dispatched an ACTION event', 1,
  1802. getEventCount(control, goog.ui.Component.EventType.ACTION));
  1803. }
  1804. /**
  1805. * Tests {@link goog.ui.Control#performActionInternal}.
  1806. */
  1807. function testPerformActionInternal() {
  1808. assertFalse('Control must not be checked', control.isChecked());
  1809. assertFalse('Control must not be selected', control.isSelected());
  1810. assertFalse('Control must not be open', control.isOpen());
  1811. control.performActionInternal();
  1812. assertFalse('Control must not be checked', control.isChecked());
  1813. assertFalse('Control must not be selected', control.isSelected());
  1814. assertFalse('Control must not be open', control.isOpen());
  1815. assertEquals(
  1816. 'Control must have dispatched an ACTION event', 1,
  1817. getEventCount(control, goog.ui.Component.EventType.ACTION));
  1818. control.setSupportedState(goog.ui.Component.State.CHECKED, true);
  1819. control.setSupportedState(goog.ui.Component.State.SELECTED, true);
  1820. control.setSupportedState(goog.ui.Component.State.OPENED, true);
  1821. control.performActionInternal();
  1822. assertTrue('Control must be checked', control.isChecked());
  1823. assertTrue('Control must be selected', control.isSelected());
  1824. assertTrue('Control must be open', control.isOpen());
  1825. assertEquals(
  1826. 'Control must have dispatched a CHECK event', 1,
  1827. getEventCount(control, goog.ui.Component.EventType.CHECK));
  1828. assertEquals(
  1829. 'Control must have dispatched a SELECT event', 1,
  1830. getEventCount(control, goog.ui.Component.EventType.SELECT));
  1831. assertEquals(
  1832. 'Control must have dispatched a OPEN event', 1,
  1833. getEventCount(control, goog.ui.Component.EventType.OPEN));
  1834. assertEquals(
  1835. 'Control must have dispatched another ACTION event', 2,
  1836. getEventCount(control, goog.ui.Component.EventType.ACTION));
  1837. control.performActionInternal();
  1838. assertFalse('Control must not be checked', control.isChecked());
  1839. assertTrue('Control must be selected', control.isSelected());
  1840. assertFalse('Control must not be open', control.isOpen());
  1841. assertEquals(
  1842. 'Control must have dispatched an UNCHECK event', 1,
  1843. getEventCount(control, goog.ui.Component.EventType.UNCHECK));
  1844. assertEquals(
  1845. 'Control must not have dispatched an UNSELECT event', 0,
  1846. getEventCount(control, goog.ui.Component.EventType.UNSELECT));
  1847. assertEquals(
  1848. 'Control must have dispatched a CLOSE event', 1,
  1849. getEventCount(control, goog.ui.Component.EventType.CLOSE));
  1850. assertEquals(
  1851. 'Control must have dispatched another ACTION event', 3,
  1852. getEventCount(control, goog.ui.Component.EventType.ACTION));
  1853. }
  1854. /**
  1855. * Tests {@link goog.ui.Control#handleMouseOver}.
  1856. */
  1857. function testHandleMouseOver() {
  1858. control.setContent(
  1859. goog.dom.createDom(goog.dom.TagName.SPAN, {id: 'caption'}, 'Hello'));
  1860. control.render(sandbox);
  1861. var element = control.getElement();
  1862. var caption = goog.dom.getElement('caption');
  1863. // Verify baseline assumptions.
  1864. assertTrue(
  1865. 'Caption must be contained within the control',
  1866. goog.dom.contains(element, caption));
  1867. assertTrue('Control must be enabled', control.isEnabled());
  1868. assertTrue(
  1869. 'HOVER must be an auto-state',
  1870. control.isAutoState(goog.ui.Component.State.HOVER));
  1871. assertFalse(
  1872. 'Control must not start out highlighted', control.isHighlighted());
  1873. // Scenario 1: relatedTarget is contained within the control's DOM.
  1874. goog.testing.events.fireMouseOverEvent(element, caption);
  1875. assertTrue(
  1876. 'No events must have been dispatched for internal mouse move',
  1877. noEventsDispatched());
  1878. assertFalse(
  1879. 'Control must not be highlighted for internal mouse move',
  1880. control.isHighlighted());
  1881. resetEventCount();
  1882. // Scenario 2: preventDefault() is called on the ENTER event.
  1883. var key = goog.events.listen(
  1884. control, goog.ui.Component.EventType.ENTER,
  1885. function(e) { e.preventDefault(); });
  1886. goog.testing.events.fireMouseOverEvent(element, sandbox);
  1887. assertEquals(
  1888. 'Control must have dispatched 1 ENTER event', 1,
  1889. getEventCount(control, goog.ui.Component.EventType.ENTER));
  1890. assertFalse(
  1891. 'Control must not be highlighted if ENTER is canceled',
  1892. control.isHighlighted());
  1893. goog.events.unlistenByKey(key);
  1894. resetEventCount();
  1895. // Scenario 3: Control is disabled.
  1896. control.setEnabled(false);
  1897. goog.testing.events.fireMouseOverEvent(element, sandbox);
  1898. assertEquals(
  1899. 'Control must dispatch ENTER event on mouseover even if ' +
  1900. 'disabled',
  1901. 1, getEventCount(control, goog.ui.Component.EventType.ENTER));
  1902. assertFalse(
  1903. 'Control must not be highlighted if it is disabled',
  1904. control.isHighlighted());
  1905. control.setEnabled(true);
  1906. resetEventCount();
  1907. // Scenario 4: HOVER is not an auto-state.
  1908. control.setAutoStates(goog.ui.Component.State.HOVER, false);
  1909. goog.testing.events.fireMouseOverEvent(element, sandbox);
  1910. assertEquals(
  1911. 'Control must dispatch ENTER event on mouseover even if ' +
  1912. 'HOVER is not an auto-state',
  1913. 1, getEventCount(control, goog.ui.Component.EventType.ENTER));
  1914. assertFalse(
  1915. 'Control must not be highlighted if HOVER isn\'t an auto-' +
  1916. 'state',
  1917. control.isHighlighted());
  1918. control.setAutoStates(goog.ui.Component.State.HOVER, true);
  1919. resetEventCount();
  1920. // Scenario 5: All is well.
  1921. goog.testing.events.fireMouseOverEvent(element, sandbox);
  1922. assertEquals(
  1923. 'Control must dispatch ENTER event on mouseover', 1,
  1924. getEventCount(control, goog.ui.Component.EventType.ENTER));
  1925. assertEquals(
  1926. 'Control must dispatch HIGHLIGHT event on mouseover', 1,
  1927. getEventCount(control, goog.ui.Component.EventType.HIGHLIGHT));
  1928. assertTrue('Control must be highlighted', control.isHighlighted());
  1929. resetEventCount();
  1930. // Scenario 6: relatedTarget is null
  1931. control.setHighlighted(false);
  1932. goog.testing.events.fireMouseOverEvent(element, null);
  1933. assertEquals(
  1934. 'Control must dispatch ENTER event on mouseover', 1,
  1935. getEventCount(control, goog.ui.Component.EventType.ENTER));
  1936. assertEquals(
  1937. 'Control must dispatch HIGHLIGHT event on mouseover', 1,
  1938. getEventCount(control, goog.ui.Component.EventType.HIGHLIGHT));
  1939. assertTrue('Control must be highlighted', control.isHighlighted());
  1940. resetEventCount();
  1941. }
  1942. /**
  1943. * Tests {@link goog.ui.Control#handleMouseOut}.
  1944. */
  1945. function testHandleMouseOut() {
  1946. control.setContent(
  1947. goog.dom.createDom(goog.dom.TagName.SPAN, {id: 'caption'}, 'Hello'));
  1948. control.setHighlighted(true);
  1949. control.setActive(true);
  1950. resetEventCount();
  1951. control.render(sandbox);
  1952. var element = control.getElement();
  1953. var caption = goog.dom.getElement('caption');
  1954. // Verify baseline assumptions.
  1955. assertTrue(
  1956. 'Caption must be contained within the control',
  1957. goog.dom.contains(element, caption));
  1958. assertTrue('Control must be enabled', control.isEnabled());
  1959. assertTrue(
  1960. 'HOVER must be an auto-state',
  1961. control.isAutoState(goog.ui.Component.State.HOVER));
  1962. assertTrue(
  1963. 'ACTIVE must be an auto-state',
  1964. control.isAutoState(goog.ui.Component.State.ACTIVE));
  1965. assertTrue('Control must start out highlighted', control.isHighlighted());
  1966. assertTrue('Control must start out active', control.isActive());
  1967. // Scenario 1: relatedTarget is contained within the control's DOM.
  1968. goog.testing.events.fireMouseOutEvent(element, caption);
  1969. assertTrue(
  1970. 'No events must have been dispatched for internal mouse move',
  1971. noEventsDispatched());
  1972. assertTrue(
  1973. 'Control must not be un-highlighted for internal mouse move',
  1974. control.isHighlighted());
  1975. assertTrue(
  1976. 'Control must not be deactivated for internal mouse move',
  1977. control.isActive());
  1978. resetEventCount();
  1979. // Scenario 2: preventDefault() is called on the LEAVE event.
  1980. var key = goog.events.listen(
  1981. control, goog.ui.Component.EventType.LEAVE,
  1982. function(e) { e.preventDefault(); });
  1983. goog.testing.events.fireMouseOutEvent(element, sandbox);
  1984. assertEquals(
  1985. 'Control must have dispatched 1 LEAVE event', 1,
  1986. getEventCount(control, goog.ui.Component.EventType.LEAVE));
  1987. assertTrue(
  1988. 'Control must not be un-highlighted if LEAVE is canceled',
  1989. control.isHighlighted());
  1990. assertTrue(
  1991. 'Control must not be deactivated if LEAVE is canceled',
  1992. control.isActive());
  1993. goog.events.unlistenByKey(key);
  1994. resetEventCount();
  1995. // Scenario 3: ACTIVE is not an auto-state.
  1996. control.setAutoStates(goog.ui.Component.State.ACTIVE, false);
  1997. goog.testing.events.fireMouseOutEvent(element, sandbox);
  1998. assertEquals(
  1999. 'Control must dispatch LEAVE event on mouseout even if ' +
  2000. 'ACTIVE is not an auto-state',
  2001. 1, getEventCount(control, goog.ui.Component.EventType.LEAVE));
  2002. assertTrue(
  2003. 'Control must not be deactivated if ACTIVE isn\'t an auto-' +
  2004. 'state',
  2005. control.isActive());
  2006. assertFalse(
  2007. 'Control must be un-highlighted even if ACTIVE isn\'t an ' +
  2008. 'auto-state',
  2009. control.isHighlighted());
  2010. control.setAutoStates(goog.ui.Component.State.ACTIVE, true);
  2011. control.setHighlighted(true);
  2012. resetEventCount();
  2013. // Scenario 4: HOVER is not an auto-state.
  2014. control.setAutoStates(goog.ui.Component.State.HOVER, false);
  2015. goog.testing.events.fireMouseOutEvent(element, sandbox);
  2016. assertEquals(
  2017. 'Control must dispatch LEAVE event on mouseout even if ' +
  2018. 'HOVER is not an auto-state',
  2019. 1, getEventCount(control, goog.ui.Component.EventType.LEAVE));
  2020. assertFalse(
  2021. 'Control must be deactivated even if HOVER isn\'t an auto-' +
  2022. 'state',
  2023. control.isActive());
  2024. assertTrue(
  2025. 'Control must not be un-highlighted if HOVER isn\'t an auto-' +
  2026. 'state',
  2027. control.isHighlighted());
  2028. control.setAutoStates(goog.ui.Component.State.HOVER, true);
  2029. control.setActive(true);
  2030. resetEventCount();
  2031. // Scenario 5: All is well.
  2032. goog.testing.events.fireMouseOutEvent(element, sandbox);
  2033. assertEquals(
  2034. 'Control must dispatch LEAVE event on mouseout', 1,
  2035. getEventCount(control, goog.ui.Component.EventType.LEAVE));
  2036. assertEquals(
  2037. 'Control must dispatch DEACTIVATE event on mouseout', 1,
  2038. getEventCount(control, goog.ui.Component.EventType.DEACTIVATE));
  2039. assertEquals(
  2040. 'Control must dispatch UNHIGHLIGHT event on mouseout', 1,
  2041. getEventCount(control, goog.ui.Component.EventType.UNHIGHLIGHT));
  2042. assertFalse('Control must be deactivated', control.isActive());
  2043. assertFalse('Control must be unhighlighted', control.isHighlighted());
  2044. resetEventCount();
  2045. // Scenario 6: relatedTarget is null
  2046. control.setActive(true);
  2047. control.setHighlighted(true);
  2048. goog.testing.events.fireMouseOutEvent(element, null);
  2049. assertEquals(
  2050. 'Control must dispatch LEAVE event on mouseout', 1,
  2051. getEventCount(control, goog.ui.Component.EventType.LEAVE));
  2052. assertEquals(
  2053. 'Control must dispatch DEACTIVATE event on mouseout', 1,
  2054. getEventCount(control, goog.ui.Component.EventType.DEACTIVATE));
  2055. assertEquals(
  2056. 'Control must dispatch UNHIGHLIGHT event on mouseout', 1,
  2057. getEventCount(control, goog.ui.Component.EventType.UNHIGHLIGHT));
  2058. assertFalse('Control must be deactivated', control.isActive());
  2059. assertFalse('Control must be unhighlighted', control.isHighlighted());
  2060. resetEventCount();
  2061. }
  2062. function testIsMouseEventWithinElement() {
  2063. var child = goog.dom.createElement(goog.dom.TagName.DIV);
  2064. var parent = goog.dom.createDom(goog.dom.TagName.DIV, null, child);
  2065. var notChild = goog.dom.createElement(goog.dom.TagName.DIV);
  2066. var event = new goog.testing.events.Event('mouseout');
  2067. event.relatedTarget = child;
  2068. assertTrue(
  2069. 'Event is within element',
  2070. goog.ui.Control.isMouseEventWithinElement_(event, parent));
  2071. var event = new goog.testing.events.Event('mouseout');
  2072. event.relatedTarget = notChild;
  2073. assertFalse(
  2074. 'Event is not within element',
  2075. goog.ui.Control.isMouseEventWithinElement_(event, parent));
  2076. }
  2077. function testHandleMouseDown() {
  2078. control.render(sandbox);
  2079. assertFalse(
  2080. 'preventDefault() must have been called for control that ' +
  2081. 'doesn\'t support text selection',
  2082. fireMouseDownAndFocus(control.getElement()));
  2083. assertTrue('Control must be highlighted', control.isHighlighted());
  2084. assertTrue('Control must be active', control.isActive());
  2085. if (testFocus) {
  2086. // Expected to fail on IE and Mac Safari 3. IE calls focus handlers
  2087. // asynchronously, and Mac Safari 3 doesn't support keyboard focus.
  2088. expectedFailures.expectFailureFor(goog.userAgent.IE);
  2089. expectedFailures.expectFailureFor(isMacSafari3());
  2090. try {
  2091. assertTrue('Control must be focused', control.isFocused());
  2092. } catch (e) {
  2093. expectedFailures.handleException(e);
  2094. }
  2095. }
  2096. }
  2097. function testHandleMouseDownForDisabledControl() {
  2098. control.setEnabled(false);
  2099. control.render(sandbox);
  2100. assertFalse(
  2101. 'preventDefault() must have been called for control that ' +
  2102. 'doesn\'t support text selection',
  2103. fireMouseDownAndFocus(control.getElement()));
  2104. assertFalse('Control must not be highlighted', control.isHighlighted());
  2105. assertFalse('Control must not be active', control.isActive());
  2106. if (testFocus) {
  2107. assertFalse('Control must not be focused', control.isFocused());
  2108. }
  2109. }
  2110. function testHandleMouseDownForNoHoverAutoState() {
  2111. control.setAutoStates(goog.ui.Component.State.HOVER, false);
  2112. control.render(sandbox);
  2113. assertFalse(
  2114. 'preventDefault() must have been called for control that ' +
  2115. 'doesn\'t support text selection',
  2116. fireMouseDownAndFocus(control.getElement()));
  2117. assertFalse('Control must not be highlighted', control.isHighlighted());
  2118. assertTrue('Control must be active', control.isActive());
  2119. if (testFocus) {
  2120. // Expected to fail on IE and Mac Safari 3. IE calls focus handlers
  2121. // asynchronously, and Mac Safari 3 doesn't support keyboard focus.
  2122. expectedFailures.expectFailureFor(goog.userAgent.IE);
  2123. expectedFailures.expectFailureFor(isMacSafari3());
  2124. try {
  2125. assertTrue('Control must be focused', control.isFocused());
  2126. } catch (e) {
  2127. expectedFailures.handleException(e);
  2128. }
  2129. }
  2130. }
  2131. function testHandleMouseDownForRightMouseButton() {
  2132. control.render(sandbox);
  2133. assertTrue(
  2134. 'preventDefault() must not have been called for right ' +
  2135. 'mouse button',
  2136. fireMouseDownAndFocus(
  2137. control.getElement(), goog.events.BrowserEvent.MouseButton.RIGHT));
  2138. assertTrue('Control must be highlighted', control.isHighlighted());
  2139. assertFalse('Control must not be active', control.isActive());
  2140. if (testFocus) {
  2141. // Expected to fail on IE and Mac Safari 3. IE calls focus handlers
  2142. // asynchronously, and Mac Safari 3 doesn't support keyboard focus.
  2143. expectedFailures.expectFailureFor(goog.userAgent.IE);
  2144. expectedFailures.expectFailureFor(isMacSafari3());
  2145. try {
  2146. assertTrue('Control must be focused', control.isFocused());
  2147. } catch (e) {
  2148. expectedFailures.handleException(e);
  2149. }
  2150. }
  2151. }
  2152. function testHandleMouseDownForNoActiveAutoState() {
  2153. control.setAutoStates(goog.ui.Component.State.ACTIVE, false);
  2154. control.render(sandbox);
  2155. assertFalse(
  2156. 'preventDefault() must have been called for control that ' +
  2157. 'doesn\'t support text selection',
  2158. fireMouseDownAndFocus(control.getElement()));
  2159. assertTrue('Control must be highlighted', control.isHighlighted());
  2160. assertFalse('Control must not be active', control.isActive());
  2161. if (testFocus) {
  2162. // Expected to fail on IE and Mac Safari 3. IE calls focus handlers
  2163. // asynchronously, and Mac Safari 3 doesn't support keyboard focus.
  2164. expectedFailures.expectFailureFor(goog.userAgent.IE);
  2165. expectedFailures.expectFailureFor(isMacSafari3());
  2166. try {
  2167. assertTrue('Control must be focused', control.isFocused());
  2168. } catch (e) {
  2169. expectedFailures.handleException(e);
  2170. }
  2171. }
  2172. }
  2173. function testHandleMouseDownForNonFocusableControl() {
  2174. control.setSupportedState(goog.ui.Component.State.FOCUSED, false);
  2175. control.render(sandbox);
  2176. assertFalse(
  2177. 'preventDefault() must have been called for control that ' +
  2178. 'doesn\'t support text selection',
  2179. fireMouseDownAndFocus(control.getElement()));
  2180. assertTrue('Control must be highlighted', control.isHighlighted());
  2181. assertTrue('Control must be active', control.isActive());
  2182. assertFalse('Control must not be focused', control.isFocused());
  2183. }
  2184. // TODO(attila): Find out why this is flaky on FF2/Linux and FF1.5/Win.
  2185. // function testHandleMouseDownForSelectableControl() {
  2186. // control.setAllowTextSelection(true);
  2187. // control.render(sandbox);
  2188. // assertTrue('preventDefault() must not have been called for control ' +
  2189. // 'that supports text selection',
  2190. // fireMouseDownAndFocus(control.getElement()));
  2191. // assertTrue('Control must be highlighted', control.isHighlighted());
  2192. // assertTrue('Control must be active', control.isActive());
  2193. // // Expected to fail on IE and Mac Safari 3. IE calls focus handlers
  2194. // // asynchronously, and Mac Safari 3 doesn't support keyboard focus.
  2195. // expectedFailures.expectFailureFor(goog.userAgent.IE);
  2196. // expectedFailures.expectFailureFor(isMacSafari3());
  2197. // try {
  2198. // assertTrue('Control must be focused', control.isFocused());
  2199. // } catch (e) {
  2200. // expectedFailures.handleException(e);
  2201. // }
  2202. //}
  2203. /**
  2204. * Tests {@link goog.ui.Control#handleMouseUp}.
  2205. */
  2206. function testHandleMouseUp() {
  2207. control.setActive(true);
  2208. // Override performActionInternal() for testing purposes.
  2209. var actionPerformed = false;
  2210. control.performActionInternal = function() {
  2211. actionPerformed = true;
  2212. return true;
  2213. };
  2214. resetEventCount();
  2215. control.render(sandbox);
  2216. var element = control.getElement();
  2217. // Verify baseline assumptions.
  2218. assertTrue('Control must be enabled', control.isEnabled());
  2219. assertTrue(
  2220. 'HOVER must be an auto-state',
  2221. control.isAutoState(goog.ui.Component.State.HOVER));
  2222. assertTrue(
  2223. 'ACTIVE must be an auto-state',
  2224. control.isAutoState(goog.ui.Component.State.ACTIVE));
  2225. assertFalse(
  2226. 'Control must not start out highlighted', control.isHighlighted());
  2227. assertTrue('Control must start out active', control.isActive());
  2228. // Scenario 1: Control is disabled.
  2229. control.setEnabled(false);
  2230. goog.testing.events.fireMouseUpEvent(element);
  2231. assertFalse(
  2232. 'Disabled control must not highlight on mouseup',
  2233. control.isHighlighted());
  2234. assertFalse('No action must have been performed', actionPerformed);
  2235. control.setActive(true);
  2236. control.setEnabled(true);
  2237. // Scenario 2: HOVER is not an auto-state.
  2238. control.setAutoStates(goog.ui.Component.State.HOVER, false);
  2239. goog.testing.events.fireMouseUpEvent(element);
  2240. assertFalse(
  2241. 'Control must not highlight on mouseup if HOVER isn\'t an ' +
  2242. 'auto-state',
  2243. control.isHighlighted());
  2244. assertTrue(
  2245. 'Action must have been performed even if HOVER isn\'t an ' +
  2246. 'auto-state',
  2247. actionPerformed);
  2248. assertFalse(
  2249. 'Control must have been deactivated on mouseup even if ' +
  2250. 'HOVER isn\'t an auto-state',
  2251. control.isActive());
  2252. actionPerformed = false;
  2253. control.setActive(true);
  2254. control.setAutoStates(goog.ui.Component.State.HOVER, true);
  2255. // Scenario 3: Control is not active.
  2256. control.setActive(false);
  2257. goog.testing.events.fireMouseUpEvent(element);
  2258. assertTrue(
  2259. 'Control must highlight on mouseup, even if inactive',
  2260. control.isHighlighted());
  2261. assertFalse(
  2262. 'No action must have been performed if control is inactive',
  2263. actionPerformed);
  2264. assertFalse(
  2265. 'Inactive control must remain inactive after mouseup',
  2266. control.isActive());
  2267. control.setHighlighted(false);
  2268. control.setActive(true);
  2269. // Scenario 4: performActionInternal() returns false.
  2270. control.performActionInternal = function() {
  2271. actionPerformed = true;
  2272. return false;
  2273. };
  2274. goog.testing.events.fireMouseUpEvent(element);
  2275. assertTrue(
  2276. 'Control must highlight on mouseup, even if no action is ' +
  2277. 'performed',
  2278. control.isHighlighted());
  2279. assertTrue('performActionInternal must have been called', actionPerformed);
  2280. assertTrue(
  2281. 'Control must not deactivate if performActionInternal ' +
  2282. 'returns false',
  2283. control.isActive());
  2284. control.setHighlighted(false);
  2285. actionPerformed = false;
  2286. control.performActionInternal = function() {
  2287. actionPerformed = true;
  2288. return true;
  2289. };
  2290. // Scenario 5: ACTIVE is not an auto-state.
  2291. control.setAutoStates(goog.ui.Component.State.ACTIVE, false);
  2292. goog.testing.events.fireMouseUpEvent(element);
  2293. assertTrue(
  2294. 'Control must highlight on mouseup even if ACTIVE isn\'t an ' +
  2295. 'auto-state',
  2296. control.isHighlighted());
  2297. assertTrue(
  2298. 'Action must have been performed even if ACTIVE isn\'t an ' +
  2299. 'auto-state',
  2300. actionPerformed);
  2301. assertTrue(
  2302. 'Control must not have been deactivated on mouseup if ' +
  2303. 'ACTIVE isn\'t an auto-state',
  2304. control.isActive());
  2305. actionPerformed = false;
  2306. control.setHighlighted(false);
  2307. control.setAutoStates(goog.ui.Component.State.ACTIVE, true);
  2308. // Scenario 6: All is well.
  2309. goog.testing.events.fireMouseUpEvent(element);
  2310. assertTrue('Control must highlight on mouseup', control.isHighlighted());
  2311. assertTrue('Action must have been performed', actionPerformed);
  2312. assertFalse('Control must have been deactivated', control.isActive());
  2313. }
  2314. function testDefaultConstructor() {
  2315. var control = new goog.ui.Control();
  2316. assertNull(control.getContent());
  2317. }
  2318. function assertClickSequenceFires(msg) {
  2319. var actionCount = getEventCount(control, goog.ui.Component.EventType.ACTION);
  2320. goog.testing.events.fireClickSequence(control.getKeyEventTarget());
  2321. assertEquals(
  2322. msg, actionCount + 1,
  2323. getEventCount(control, goog.ui.Component.EventType.ACTION));
  2324. }
  2325. function assertIsolatedClickFires(msg) {
  2326. var actionCount = getEventCount(control, goog.ui.Component.EventType.ACTION);
  2327. goog.testing.events.fireClickEvent(control.getKeyEventTarget());
  2328. assertEquals(
  2329. msg, actionCount + 1,
  2330. getEventCount(control, goog.ui.Component.EventType.ACTION));
  2331. }
  2332. function assertIsolatedClickDoesNotFire(msg) {
  2333. var actionCount = getEventCount(control, goog.ui.Component.EventType.ACTION);
  2334. goog.testing.events.fireClickEvent(control.getKeyEventTarget());
  2335. assertEquals(
  2336. msg, actionCount,
  2337. getEventCount(control, goog.ui.Component.EventType.ACTION));
  2338. }
  2339. function testIeMouseEventSequenceSimulator() {
  2340. control.render(sandbox);
  2341. // Click sequences and isolated clicks must be handled correctly in any order.
  2342. assertClickSequenceFires('ACTION event expected after a click sequence');
  2343. assertClickSequenceFires(
  2344. 'ACTION event expected after a second consecutive click sequence');
  2345. if (goog.userAgent.IE) {
  2346. // For some reason in IE8 and perhaps earlier, isolated clicks do not result
  2347. // a detectable dispatch of an ACTION event, so we'll only assert the
  2348. // desired handling of isolated clicks in IE9 and higher.
  2349. if (goog.userAgent.isVersionOrHigher(9)) {
  2350. assertIsolatedClickFires(
  2351. 'ACTION event expected after an isolated click immediately ' +
  2352. 'following a click sequence');
  2353. assertIsolatedClickFires(
  2354. 'ACTION event expected after second consecutive isolated click');
  2355. } else {
  2356. // For IE8-and-lower, fire an isolated click event in preparation for our
  2357. // final assertion.
  2358. goog.testing.events.fireClickEvent(control.getKeyEventTarget());
  2359. }
  2360. } else {
  2361. assertIsolatedClickDoesNotFire(
  2362. 'No ACTION event expected after an isolated click immediately ' +
  2363. 'following a click sequence');
  2364. assertIsolatedClickDoesNotFire(
  2365. 'No ACTION event expected after second consecutive isolated click');
  2366. }
  2367. assertClickSequenceFires(
  2368. 'ACTION event expected after click sequence immediately following ' +
  2369. 'an isolated click ');
  2370. }
  2371. function testIeMouseEventSequenceSimulatorStrictMode() {
  2372. if (!document.createEvent) {
  2373. return;
  2374. }
  2375. control.render(sandbox);
  2376. var actionCount = getEventCount(control, goog.ui.Component.EventType.ACTION);
  2377. var e = document.createEvent('MouseEvents');
  2378. e.initMouseEvent(
  2379. 'click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0,
  2380. null);
  2381. control.getElementStrict().dispatchEvent(e);
  2382. if (goog.userAgent.IE) {
  2383. assertEquals(
  2384. 'ACTION event expected after an isolated click', actionCount + 1,
  2385. getEventCount(control, goog.ui.Component.EventType.ACTION));
  2386. } else {
  2387. assertEquals(
  2388. 'No ACTION event expected after an isolated click', actionCount,
  2389. getEventCount(control, goog.ui.Component.EventType.ACTION));
  2390. }
  2391. }