hovercard_test.js 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  1. // Copyright 2010 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.HoverCardTest');
  15. goog.setTestOnly('goog.ui.HoverCardTest');
  16. goog.require('goog.dom');
  17. goog.require('goog.events');
  18. goog.require('goog.math.Coordinate');
  19. goog.require('goog.style');
  20. goog.require('goog.testing.MockClock');
  21. goog.require('goog.testing.events');
  22. goog.require('goog.testing.events.Event');
  23. goog.require('goog.testing.jsunit');
  24. goog.require('goog.ui.HoverCard');
  25. var timer = new goog.testing.MockClock();
  26. var card;
  27. // Variables for mocks
  28. var triggeredElement;
  29. var cancelledElement;
  30. var showDelay;
  31. var shownCard;
  32. var hideDelay;
  33. // spans
  34. var john;
  35. var jane;
  36. var james;
  37. var bill;
  38. var child;
  39. // Inactive
  40. var elsewhere;
  41. var offAnchor;
  42. function setUpPage() {
  43. john = goog.dom.getElement('john');
  44. jane = goog.dom.getElement('jane');
  45. james = goog.dom.getElement('james');
  46. bill = goog.dom.getElement('bill');
  47. child = goog.dom.getElement('child');
  48. }
  49. function setUp() {
  50. timer.install();
  51. triggeredElement = null;
  52. cancelledElement = null;
  53. showDelay = null;
  54. shownCard = null;
  55. hideDelay = null;
  56. elsewhere = goog.dom.getElement('notpopup');
  57. offAnchor = new goog.math.Coordinate(1, 1);
  58. }
  59. function initCard(opt_isAnchor, opt_checkChildren, opt_maxSearchSteps) {
  60. var isAnchor = opt_isAnchor || {SPAN: 'email'};
  61. card = new goog.ui.HoverCard(isAnchor, opt_checkChildren);
  62. card.setText('Test hovercard');
  63. if (opt_maxSearchSteps != null) {
  64. card.setMaxSearchSteps(opt_maxSearchSteps);
  65. }
  66. goog.events.listen(card, goog.ui.HoverCard.EventType.TRIGGER, onTrigger);
  67. goog.events.listen(
  68. card, goog.ui.HoverCard.EventType.CANCEL_TRIGGER, onCancel);
  69. goog.events.listen(
  70. card, goog.ui.HoverCard.EventType.BEFORE_SHOW, onBeforeShow);
  71. // This gets around the problem where AdvancedToolTip thinks it's
  72. // receiving a ghost event because cursor position hasn't moved off of
  73. // (0, 0).
  74. card.cursorPosition = new goog.math.Coordinate(1, 1);
  75. }
  76. // Event handlers
  77. function onTrigger(event) {
  78. triggeredElement = event.anchor;
  79. if (showDelay) {
  80. card.setShowDelayMs(showDelay);
  81. }
  82. return true;
  83. }
  84. function onCancel(event) {
  85. cancelledElement = event.anchor;
  86. }
  87. function onBeforeShow() {
  88. shownCard = card.getAnchorElement();
  89. if (hideDelay) {
  90. card.setHideDelayMs(hideDelay);
  91. }
  92. return true;
  93. }
  94. function tearDown() {
  95. card.dispose();
  96. timer.uninstall();
  97. }
  98. /**
  99. * Verify that hovercard displays and goes away under normal circumstances.
  100. */
  101. function testTrigger() {
  102. initCard();
  103. // Mouse over correct element fires trigger
  104. showDelay = 500;
  105. goog.testing.events.fireMouseOverEvent(john, elsewhere);
  106. assertEquals('Hovercard should have triggered', john, triggeredElement);
  107. // Show card after delay
  108. timer.tick(showDelay - 1);
  109. assertNull('Card should not have shown', shownCard);
  110. assertFalse(card.isVisible());
  111. hideDelay = 5000;
  112. timer.tick(1);
  113. assertEquals('Card should have shown', john, shownCard);
  114. assertTrue(card.isVisible());
  115. // Mouse out leads to hide delay
  116. goog.testing.events.fireMouseOutEvent(john, elsewhere);
  117. goog.testing.events.fireMouseMoveEvent(document, offAnchor);
  118. timer.tick(hideDelay - 1);
  119. assertTrue('Card should still be visible', card.isVisible());
  120. timer.tick(10);
  121. assertFalse('Card should be hidden', card.isVisible());
  122. }
  123. /**
  124. * Verify that CANCEL_TRIGGER event occurs when mouse goes out of
  125. * triggering element before hovercard is shown.
  126. */
  127. function testOnCancel() {
  128. initCard();
  129. showDelay = 500;
  130. goog.testing.events.fireMouseOverEvent(john, elsewhere);
  131. timer.tick(showDelay - 1);
  132. goog.testing.events.fireMouseOutEvent(john, elsewhere);
  133. goog.testing.events.fireMouseMoveEvent(document, offAnchor);
  134. timer.tick(10);
  135. assertFalse('Card should be hidden', card.isVisible());
  136. assertEquals('Should have cancelled trigger', john, cancelledElement);
  137. }
  138. /**
  139. * Verify that mousing over non-triggering elements don't interfere.
  140. */
  141. function testMouseOverNonTrigger() {
  142. initCard();
  143. // Mouse over correct element fires trigger
  144. showDelay = 500;
  145. goog.testing.events.fireMouseOverEvent(john, elsewhere);
  146. timer.tick(showDelay);
  147. // Mouse over and out other element does nothing
  148. triggeredElement = null;
  149. goog.testing.events.fireMouseOverEvent(jane, elsewhere);
  150. timer.tick(showDelay + 1);
  151. assertNull(triggeredElement);
  152. }
  153. /**
  154. * Verify that a mouse over event with no target will not break
  155. * hover card.
  156. */
  157. function testMouseOverNoTarget() {
  158. initCard();
  159. card.handleTriggerMouseOver_(new goog.testing.events.Event());
  160. }
  161. /**
  162. * Verify that mousing over a second trigger before the first one shows
  163. * will correctly cancel the first and show the second.
  164. */
  165. function testMultipleTriggers() {
  166. initCard();
  167. // Test second trigger when first one still pending
  168. showDelay = 500;
  169. hideDelay = 1000;
  170. goog.testing.events.fireMouseOverEvent(john, elsewhere);
  171. timer.tick(250);
  172. goog.testing.events.fireMouseOutEvent(john, james);
  173. goog.testing.events.fireMouseOverEvent(james, john);
  174. // First trigger should cancel because it isn't showing yet
  175. assertEquals('Should cancel first trigger', john, cancelledElement);
  176. timer.tick(300);
  177. assertFalse(card.isVisible());
  178. timer.tick(250);
  179. assertEquals('Should show second card', james, shownCard);
  180. assertTrue(card.isVisible());
  181. goog.testing.events.fireMouseOutEvent(james, john);
  182. goog.testing.events.fireMouseOverEvent(john, james);
  183. assertEquals('Should still show second card', james, card.getAnchorElement());
  184. assertTrue(card.isVisible());
  185. shownCard = null;
  186. timer.tick(501);
  187. assertEquals('Should show first card again', john, shownCard);
  188. assertTrue(card.isVisible());
  189. // Test that cancelling while another is showing gives correct cancel
  190. // information
  191. cancelledElement = null;
  192. goog.testing.events.fireMouseOutEvent(john, james);
  193. goog.testing.events.fireMouseOverEvent(james, john);
  194. goog.testing.events.fireMouseOutEvent(james, elsewhere);
  195. assertEquals('Should cancel second card', james, cancelledElement);
  196. }
  197. /**
  198. * Verify manual triggering.
  199. */
  200. function testManualTrigger() {
  201. initCard();
  202. // Doesn't normally trigger for div tag
  203. showDelay = 500;
  204. goog.testing.events.fireMouseOverEvent(bill, elsewhere);
  205. timer.tick(showDelay);
  206. assertFalse(card.isVisible());
  207. // Manually trigger element
  208. card.triggerForElement(bill);
  209. hideDelay = 600;
  210. timer.tick(showDelay);
  211. assertTrue(card.isVisible());
  212. goog.testing.events.fireMouseOutEvent(bill, elsewhere);
  213. goog.testing.events.fireMouseMoveEvent(document, offAnchor);
  214. timer.tick(hideDelay);
  215. assertFalse(card.isVisible());
  216. }
  217. /**
  218. * Verify creating with isAnchor function.
  219. */
  220. function testIsAnchor() {
  221. // Initialize card so only bill triggers it.
  222. initCard(function(element) { return element == bill; });
  223. showDelay = 500;
  224. goog.testing.events.fireMouseOverEvent(bill, elsewhere);
  225. timer.tick(showDelay);
  226. assertTrue('Should trigger card', card.isVisible());
  227. hideDelay = 300;
  228. goog.testing.events.fireMouseOutEvent(bill, elsewhere);
  229. goog.testing.events.fireMouseMoveEvent(document, offAnchor);
  230. timer.tick(hideDelay);
  231. assertFalse(card.isVisible());
  232. goog.testing.events.fireMouseOverEvent(john, elsewhere);
  233. timer.tick(showDelay);
  234. assertFalse('Should not trigger card', card.isVisible());
  235. }
  236. /**
  237. * Verify mouse over child of anchor triggers hovercard.
  238. */
  239. function testAnchorWithChildren() {
  240. initCard();
  241. showDelay = 500;
  242. goog.testing.events.fireMouseOverEvent(james, elsewhere);
  243. timer.tick(250);
  244. // Moving from an anchor to a child of that anchor shouldn't cancel
  245. // or retrigger.
  246. var childBounds = goog.style.getBounds(child);
  247. var inChild =
  248. new goog.math.Coordinate(childBounds.left + 1, childBounds.top + 1);
  249. goog.testing.events.fireMouseOutEvent(james, child);
  250. goog.testing.events.fireMouseMoveEvent(child, inChild);
  251. assertNull("Shouldn't cancel trigger", cancelledElement);
  252. triggeredElement = null;
  253. goog.testing.events.fireMouseOverEvent(child, james);
  254. assertNull("Shouldn't retrigger card", triggeredElement);
  255. timer.tick(250);
  256. assertTrue('Card should show with original delay', card.isVisible());
  257. hideDelay = 300;
  258. goog.testing.events.fireMouseOutEvent(child, elsewhere);
  259. goog.testing.events.fireMouseMoveEvent(child, offAnchor);
  260. timer.tick(hideDelay);
  261. assertFalse(card.isVisible());
  262. goog.testing.events.fireMouseOverEvent(child, elsewhere);
  263. timer.tick(showDelay);
  264. assertTrue('Mouse over child should trigger card', card.isVisible());
  265. }
  266. function testNoTriggerWithMaxSearchSteps() {
  267. initCard(undefined, true, 0);
  268. showDelay = 500;
  269. goog.testing.events.fireMouseOverEvent(child, elsewhere);
  270. timer.tick(showDelay);
  271. assertFalse('Should not trigger card', card.isVisible());
  272. }
  273. function testTriggerWithMaxSearchSteps() {
  274. initCard(undefined, true, 2);
  275. showDelay = 500;
  276. goog.testing.events.fireMouseOverEvent(child, elsewhere);
  277. timer.tick(showDelay);
  278. assertTrue('Should trigger card', card.isVisible());
  279. }
  280. function testPositionAfterSecondTriggerWithMaxSearchSteps() {
  281. initCard(undefined, true, 2);
  282. showDelay = 500;
  283. goog.testing.events.fireMouseOverEvent(john, elsewhere);
  284. timer.tick(showDelay);
  285. assertTrue('Should trigger card', card.isVisible());
  286. assertEquals(
  287. 'Card cursor x coordinate should be 1', card.position_.coordinate.x, 1);
  288. card.cursorPosition = new goog.math.Coordinate(2, 2);
  289. goog.testing.events.fireMouseOverEvent(child, elsewhere);
  290. timer.tick(showDelay);
  291. assertTrue('Should trigger card', card.isVisible());
  292. assertEquals(
  293. 'Card cursor x coordinate should be 2', card.position_.coordinate.x, 2);
  294. }