bubble_test.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  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.editor.BubbleTest');
  15. goog.setTestOnly('goog.ui.editor.BubbleTest');
  16. goog.require('goog.dom');
  17. goog.require('goog.dom.TagName');
  18. goog.require('goog.events');
  19. goog.require('goog.events.EventType');
  20. goog.require('goog.positioning.Corner');
  21. goog.require('goog.positioning.OverflowStatus');
  22. goog.require('goog.string');
  23. goog.require('goog.style');
  24. goog.require('goog.testing.editor.TestHelper');
  25. goog.require('goog.testing.events');
  26. goog.require('goog.testing.jsunit');
  27. goog.require('goog.ui.Component');
  28. goog.require('goog.ui.editor.Bubble');
  29. goog.require('goog.userAgent.product');
  30. var testHelper;
  31. var fieldDiv;
  32. var bubble;
  33. var link;
  34. var link2;
  35. var panelId;
  36. function setUpPage() {
  37. fieldDiv = goog.dom.getElement('field');
  38. var viewportSize = goog.dom.getViewportSize();
  39. // Some tests depends on enough size of viewport.
  40. if (viewportSize.width < 600 || viewportSize.height < 440) {
  41. window.moveTo(0, 0);
  42. window.resizeTo(640, 480);
  43. }
  44. }
  45. function setUp() {
  46. testHelper = new goog.testing.editor.TestHelper(fieldDiv);
  47. testHelper.setUpEditableElement();
  48. bubble = new goog.ui.editor.Bubble(document.body, 999);
  49. fieldDiv.innerHTML = '<a href="http://www.google.com">Google</a>' +
  50. '<a href="http://www.google.com">Google2</a>';
  51. link = fieldDiv.firstChild;
  52. link2 = fieldDiv.lastChild;
  53. window.scrollTo(0, 0);
  54. goog.style.setStyle(document.body, 'direction', 'ltr');
  55. goog.style.setStyle(document.getElementById('field'), 'position', 'static');
  56. }
  57. function tearDown() {
  58. if (panelId) {
  59. bubble.removePanel(panelId);
  60. panelId = null;
  61. }
  62. testHelper.tearDownEditableElement();
  63. }
  64. /**
  65. * This is a helper function for setting up the target element with a
  66. * given direction.
  67. *
  68. * @param {string} dir The direction of the target element, 'ltr' or 'rtl'.
  69. * @param {boolean=} opt_preferTopPosition Whether to prefer placing the bubble
  70. * above the element instead of below it. Defaults to preferring below.
  71. */
  72. function prepareTargetWithGivenDirection(dir, opt_preferTopPosition) {
  73. goog.style.setStyle(document.body, 'direction', dir);
  74. fieldDiv.style.direction = dir;
  75. fieldDiv.innerHTML = '<a href="http://www.google.com">Google</a>';
  76. link = fieldDiv.firstChild;
  77. panelId = bubble.addPanel('A', 'Link', link, function(el) {
  78. el.innerHTML = '<div style="border:1px solid blue;">B</div>';
  79. }, opt_preferTopPosition);
  80. }
  81. /**
  82. * This is a helper function for getting the expected position of the bubble.
  83. * (align to the right or the left of the target element). Align left by
  84. * default and align right if opt_alignRight is true. The expected Y is
  85. * unaffected by alignment.
  86. *
  87. * @param {boolean=} opt_alignRight Sets the expected alignment to be right.
  88. */
  89. function getExpectedBubblePositionWithGivenAlignment(opt_alignRight) {
  90. var targetPosition = goog.style.getFramedPageOffset(link, window);
  91. var targetWidth = link.offsetWidth;
  92. var bubbleSize = goog.style.getSize(bubble.bubbleContainer_);
  93. var expectedBubbleX = opt_alignRight ?
  94. targetPosition.x + targetWidth - bubbleSize.width :
  95. targetPosition.x;
  96. var expectedBubbleY = link.offsetHeight + targetPosition.y +
  97. goog.ui.editor.Bubble.VERTICAL_CLEARANCE_;
  98. return {x: expectedBubbleX, y: expectedBubbleY};
  99. }
  100. function testCreateBubbleWithLinkPanel() {
  101. var id = goog.string.createUniqueString();
  102. panelId = bubble.addPanel('A', 'Link', link, function(container) {
  103. container.innerHTML = '<span id="' + id + '">Test</span>';
  104. });
  105. assertNotNull('Bubble should be created', bubble.bubbleContents_);
  106. assertNotNull('Added element should be present', goog.dom.getElement(id));
  107. assertTrue('Bubble should be visible', bubble.isVisible());
  108. }
  109. function testCloseBubble() {
  110. testCreateBubbleWithLinkPanel();
  111. var count = 0;
  112. goog.events.listen(
  113. bubble, goog.ui.Component.EventType.HIDE, function() { count++; });
  114. bubble.removePanel(panelId);
  115. panelId = null;
  116. assertFalse('Bubble should not be visible', bubble.isVisible());
  117. assertEquals('Hide event should be dispatched', 1, count);
  118. }
  119. function testCloseBox() {
  120. testCreateBubbleWithLinkPanel();
  121. var count = 0;
  122. goog.events.listen(
  123. bubble, goog.ui.Component.EventType.HIDE, function() { count++; });
  124. var closeBox = goog.dom.getElementsByTagNameAndClass(
  125. goog.dom.TagName.DIV, 'tr_bubble_closebox', bubble.bubbleContainer_)[0];
  126. goog.testing.events.fireClickSequence(closeBox);
  127. panelId = null;
  128. assertFalse('Bubble should not be visible', bubble.isVisible());
  129. assertEquals('Hide event should be dispatched', 1, count);
  130. }
  131. function testViewPortSizeMonitorEvent() {
  132. testCreateBubbleWithLinkPanel();
  133. var numCalled = 0;
  134. bubble.reposition = function() { numCalled++; };
  135. assertNotUndefined(
  136. 'viewPortSizeMonitor_ should not be undefined',
  137. bubble.viewPortSizeMonitor_);
  138. bubble.viewPortSizeMonitor_.dispatchEvent(goog.events.EventType.RESIZE);
  139. assertEquals('reposition not called', 1, numCalled);
  140. }
  141. function testBubblePositionPreferTop() {
  142. called = false;
  143. bubble.positionAtAnchor_ = function(targetCorner, bubbleCorner, overflow) {
  144. called = true;
  145. // Assert that the bubble is positioned below the target.
  146. assertEquals(goog.positioning.Corner.TOP_START, targetCorner);
  147. assertEquals(goog.positioning.Corner.BOTTOM_START, bubbleCorner);
  148. return goog.positioning.OverflowStatus.NONE;
  149. };
  150. prepareTargetWithGivenDirection('ltr', true);
  151. assertTrue(called);
  152. }
  153. function testBubblePosition() {
  154. panelId = bubble.addPanel('A', 'Link', link, goog.nullFunction);
  155. var CLEARANCE = goog.ui.editor.Bubble.VERTICAL_CLEARANCE_;
  156. var bubbleContainer = bubble.bubbleContainer_;
  157. // The field is at a normal place, alomost the top of the viewport, and
  158. // there is enough space at the bottom of the field.
  159. var targetPos = goog.style.getFramedPageOffset(link, window);
  160. var targetSize = goog.style.getSize(link);
  161. var pos = goog.style.getFramedPageOffset(bubbleContainer);
  162. assertEquals(targetPos.y + targetSize.height + CLEARANCE, pos.y);
  163. assertEquals(targetPos.x, pos.x);
  164. // Move the target to the bottom of the viewport.
  165. var field = document.getElementById('field');
  166. var fieldPos = goog.style.getFramedPageOffset(field, window);
  167. fieldPos.y +=
  168. bubble.dom_.getViewportSize().height - (targetPos.y + targetSize.height);
  169. goog.style.setStyle(field, 'position', 'absolute');
  170. goog.style.setPosition(field, fieldPos);
  171. bubble.reposition();
  172. var bubbleSize = goog.style.getSize(bubbleContainer);
  173. targetPosition = goog.style.getFramedPageOffset(link, window);
  174. pos = goog.style.getFramedPageOffset(bubbleContainer);
  175. assertEquals(targetPosition.y - CLEARANCE - bubbleSize.height, pos.y);
  176. }
  177. function testBubblePositionRightAligned() {
  178. if (goog.userAgent.product.SAFARI) {
  179. // TODO(b/20733468): Disabled so we can get the rest of the Closure test
  180. // suite running in a continuous build. Will investigate later.
  181. return;
  182. }
  183. prepareTargetWithGivenDirection('rtl');
  184. var expectedPos = getExpectedBubblePositionWithGivenAlignment(true);
  185. var pos = goog.style.getFramedPageOffset(bubble.bubbleContainer_);
  186. assertRoughlyEquals(expectedPos.x, pos.x, 0.1);
  187. assertRoughlyEquals(expectedPos.y, pos.y, 0.1);
  188. }
  189. /**
  190. * Test for bug 1955511, the bubble should align to the right side
  191. * of the target element when the bubble is RTL, regardless of the
  192. * target element's directionality.
  193. */
  194. function testBubblePositionLeftToRight() {
  195. if (goog.userAgent.product.SAFARI) {
  196. // TODO(b/20733468): Disabled so we can get the rest of the Closure test
  197. // suite running in a continuous build. Will investigate later.
  198. return;
  199. }
  200. goog.style.setStyle(bubble.bubbleContainer_, 'direction', 'ltr');
  201. prepareTargetWithGivenDirection('rtl');
  202. var expectedPos = getExpectedBubblePositionWithGivenAlignment();
  203. var pos = goog.style.getFramedPageOffset(bubble.bubbleContainer_);
  204. assertRoughlyEquals(expectedPos.x, pos.x, 0.1);
  205. assertRoughlyEquals(expectedPos.y, pos.y, 0.1);
  206. }
  207. /**
  208. * Test for bug 1955511, the bubble should align to the left side
  209. * of the target element when the bubble is LTR, regardless of the
  210. * target element's directionality.
  211. */
  212. function testBubblePositionRightToLeft() {
  213. goog.style.setStyle(bubble.bubbleContainer_, 'direction', 'rtl');
  214. prepareTargetWithGivenDirection('ltr');
  215. var expectedPos = getExpectedBubblePositionWithGivenAlignment(true);
  216. var pos = goog.style.getFramedPageOffset(bubble.bubbleContainer_);
  217. assertEquals(expectedPos.x, pos.x);
  218. assertEquals(expectedPos.y, pos.y);
  219. }