| // Copyright 2010 The Closure Library Authors. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS-IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| goog.provide('goog.ui.HoverCardTest'); |
| goog.setTestOnly('goog.ui.HoverCardTest'); |
| |
| goog.require('goog.dom'); |
| goog.require('goog.events'); |
| goog.require('goog.math.Coordinate'); |
| goog.require('goog.style'); |
| goog.require('goog.testing.MockClock'); |
| goog.require('goog.testing.events'); |
| goog.require('goog.testing.events.Event'); |
| goog.require('goog.testing.jsunit'); |
| goog.require('goog.ui.HoverCard'); |
| |
| var timer = new goog.testing.MockClock(); |
| var card; |
| |
| // Variables for mocks |
| var triggeredElement; |
| var cancelledElement; |
| var showDelay; |
| var shownCard; |
| var hideDelay; |
| |
| // spans |
| var john; |
| var jane; |
| var james; |
| var bill; |
| var child; |
| |
| // Inactive |
| var elsewhere; |
| var offAnchor; |
| |
| function setUpPage() { |
| john = goog.dom.getElement('john'); |
| jane = goog.dom.getElement('jane'); |
| james = goog.dom.getElement('james'); |
| bill = goog.dom.getElement('bill'); |
| child = goog.dom.getElement('child'); |
| } |
| |
| function setUp() { |
| timer.install(); |
| triggeredElement = null; |
| cancelledElement = null; |
| showDelay = null; |
| shownCard = null; |
| hideDelay = null; |
| elsewhere = goog.dom.getElement('notpopup'); |
| offAnchor = new goog.math.Coordinate(1, 1); |
| } |
| |
| function initCard(opt_isAnchor, opt_checkChildren, opt_maxSearchSteps) { |
| var isAnchor = opt_isAnchor || {SPAN: 'email'}; |
| card = new goog.ui.HoverCard(isAnchor, opt_checkChildren); |
| card.setText('Test hovercard'); |
| |
| if (opt_maxSearchSteps != null) { |
| card.setMaxSearchSteps(opt_maxSearchSteps); |
| } |
| |
| goog.events.listen(card, goog.ui.HoverCard.EventType.TRIGGER, onTrigger); |
| goog.events.listen(card, goog.ui.HoverCard.EventType.CANCEL_TRIGGER, |
| onCancel); |
| goog.events.listen(card, goog.ui.HoverCard.EventType.BEFORE_SHOW, |
| onBeforeShow); |
| |
| // This gets around the problem where AdvancedToolTip thinks it's |
| // receiving a ghost event because cursor position hasn't moved off of |
| // (0, 0). |
| card.cursorPosition = new goog.math.Coordinate(1, 1); |
| } |
| |
| // Event handlers |
| function onTrigger(event) { |
| triggeredElement = event.anchor; |
| if (showDelay) { |
| card.setShowDelayMs(showDelay); |
| } |
| return true; |
| } |
| |
| function onCancel(event) { |
| cancelledElement = event.anchor; |
| } |
| |
| function onBeforeShow() { |
| shownCard = card.getAnchorElement(); |
| if (hideDelay) { |
| card.setHideDelayMs(hideDelay); |
| } |
| return true; |
| } |
| |
| function tearDown() { |
| card.dispose(); |
| timer.uninstall(); |
| } |
| |
| |
| /** |
| * Verify that hovercard displays and goes away under normal circumstances. |
| */ |
| function testTrigger() { |
| initCard(); |
| |
| // Mouse over correct element fires trigger |
| showDelay = 500; |
| goog.testing.events.fireMouseOverEvent(john, elsewhere); |
| assertEquals('Hovercard should have triggered', john, |
| triggeredElement); |
| |
| // Show card after delay |
| timer.tick(showDelay - 1); |
| assertNull('Card should not have shown', shownCard); |
| assertFalse(card.isVisible()); |
| hideDelay = 5000; |
| timer.tick(1); |
| assertEquals('Card should have shown', john, shownCard); |
| assertTrue(card.isVisible()); |
| |
| // Mouse out leads to hide delay |
| goog.testing.events.fireMouseOutEvent(john, elsewhere); |
| goog.testing.events.fireMouseMoveEvent(document, offAnchor); |
| timer.tick(hideDelay - 1); |
| assertTrue('Card should still be visible', card.isVisible()); |
| timer.tick(10); |
| assertFalse('Card should be hidden', card.isVisible()); |
| } |
| |
| |
| /** |
| * Verify that CANCEL_TRIGGER event occurs when mouse goes out of |
| * triggering element before hovercard is shown. |
| */ |
| function testOnCancel() { |
| initCard(); |
| |
| showDelay = 500; |
| goog.testing.events.fireMouseOverEvent(john, elsewhere); |
| timer.tick(showDelay - 1); |
| goog.testing.events.fireMouseOutEvent(john, elsewhere); |
| goog.testing.events.fireMouseMoveEvent(document, offAnchor); |
| timer.tick(10); |
| assertFalse('Card should be hidden', card.isVisible()); |
| assertEquals('Should have cancelled trigger', john, cancelledElement); |
| } |
| |
| |
| /** |
| * Verify that mousing over non-triggering elements don't interfere. |
| */ |
| function testMouseOverNonTrigger() { |
| initCard(); |
| |
| // Mouse over correct element fires trigger |
| showDelay = 500; |
| goog.testing.events.fireMouseOverEvent(john, elsewhere); |
| timer.tick(showDelay); |
| |
| // Mouse over and out other element does nothing |
| triggeredElement = null; |
| goog.testing.events.fireMouseOverEvent(jane, elsewhere); |
| timer.tick(showDelay + 1); |
| assertNull(triggeredElement); |
| } |
| |
| |
| /** |
| * Verify that a mouse over event with no target will not break |
| * hover card. |
| */ |
| function testMouseOverNoTarget() { |
| initCard(); |
| card.handleTriggerMouseOver_(new goog.testing.events.Event()); |
| } |
| |
| |
| /** |
| * Verify that mousing over a second trigger before the first one shows |
| * will correctly cancel the first and show the second. |
| */ |
| function testMultipleTriggers() { |
| initCard(); |
| |
| // Test second trigger when first one still pending |
| showDelay = 500; |
| hideDelay = 1000; |
| goog.testing.events.fireMouseOverEvent(john, elsewhere); |
| timer.tick(250); |
| goog.testing.events.fireMouseOutEvent(john, james); |
| goog.testing.events.fireMouseOverEvent(james, john); |
| // First trigger should cancel because it isn't showing yet |
| assertEquals('Should cancel first trigger', john, cancelledElement); |
| timer.tick(300); |
| assertFalse(card.isVisible()); |
| timer.tick(250); |
| assertEquals('Should show second card', james, shownCard); |
| assertTrue(card.isVisible()); |
| |
| goog.testing.events.fireMouseOutEvent(james, john); |
| goog.testing.events.fireMouseOverEvent(john, james); |
| assertEquals('Should still show second card', james, |
| card.getAnchorElement()); |
| assertTrue(card.isVisible()); |
| |
| shownCard = null; |
| timer.tick(501); |
| assertEquals('Should show first card again', john, shownCard); |
| assertTrue(card.isVisible()); |
| |
| // Test that cancelling while another is showing gives correct cancel |
| // information |
| cancelledElement = null; |
| goog.testing.events.fireMouseOutEvent(john, james); |
| goog.testing.events.fireMouseOverEvent(james, john); |
| goog.testing.events.fireMouseOutEvent(james, elsewhere); |
| assertEquals('Should cancel second card', james, cancelledElement); |
| } |
| |
| |
| /** |
| * Verify manual triggering. |
| */ |
| function testManualTrigger() { |
| initCard(); |
| |
| // Doesn't normally trigger for div tag |
| showDelay = 500; |
| goog.testing.events.fireMouseOverEvent(bill, elsewhere); |
| timer.tick(showDelay); |
| assertFalse(card.isVisible()); |
| |
| // Manually trigger element |
| card.triggerForElement(bill); |
| hideDelay = 600; |
| timer.tick(showDelay); |
| assertTrue(card.isVisible()); |
| goog.testing.events.fireMouseOutEvent(bill, elsewhere); |
| goog.testing.events.fireMouseMoveEvent(document, offAnchor); |
| timer.tick(hideDelay); |
| assertFalse(card.isVisible()); |
| } |
| |
| |
| /** |
| * Verify creating with isAnchor function. |
| */ |
| function testIsAnchor() { |
| // Initialize card so only bill triggers it. |
| initCard(function(element) { |
| return element == bill; |
| }); |
| |
| showDelay = 500; |
| goog.testing.events.fireMouseOverEvent(bill, elsewhere); |
| timer.tick(showDelay); |
| assertTrue('Should trigger card', card.isVisible()); |
| |
| hideDelay = 300; |
| goog.testing.events.fireMouseOutEvent(bill, elsewhere); |
| goog.testing.events.fireMouseMoveEvent(document, offAnchor); |
| timer.tick(hideDelay); |
| assertFalse(card.isVisible()); |
| |
| goog.testing.events.fireMouseOverEvent(john, elsewhere); |
| timer.tick(showDelay); |
| assertFalse('Should not trigger card', card.isVisible()); |
| } |
| |
| |
| /** |
| * Verify mouse over child of anchor triggers hovercard. |
| */ |
| function testAnchorWithChildren() { |
| initCard(); |
| |
| showDelay = 500; |
| goog.testing.events.fireMouseOverEvent(james, elsewhere); |
| timer.tick(250); |
| |
| // Moving from an anchor to a child of that anchor shouldn't cancel |
| // or retrigger. |
| var childBounds = goog.style.getBounds(child); |
| var inChild = new goog.math.Coordinate(childBounds.left + 1, |
| childBounds.top + 1); |
| goog.testing.events.fireMouseOutEvent(james, child); |
| goog.testing.events.fireMouseMoveEvent(child, inChild); |
| assertNull("Shouldn't cancel trigger", cancelledElement); |
| triggeredElement = null; |
| goog.testing.events.fireMouseOverEvent(child, james); |
| assertNull("Shouldn't retrigger card", triggeredElement); |
| timer.tick(250); |
| assertTrue('Card should show with original delay', card.isVisible()); |
| |
| hideDelay = 300; |
| goog.testing.events.fireMouseOutEvent(child, elsewhere); |
| goog.testing.events.fireMouseMoveEvent(child, offAnchor); |
| timer.tick(hideDelay); |
| assertFalse(card.isVisible()); |
| |
| goog.testing.events.fireMouseOverEvent(child, elsewhere); |
| timer.tick(showDelay); |
| assertTrue('Mouse over child should trigger card', card.isVisible()); |
| } |
| |
| function testNoTriggerWithMaxSearchSteps() { |
| initCard(undefined, true, 0); |
| |
| showDelay = 500; |
| goog.testing.events.fireMouseOverEvent(child, elsewhere); |
| timer.tick(showDelay); |
| assertFalse('Should not trigger card', card.isVisible()); |
| } |
| |
| function testTriggerWithMaxSearchSteps() { |
| initCard(undefined, true, 2); |
| |
| showDelay = 500; |
| goog.testing.events.fireMouseOverEvent(child, elsewhere); |
| timer.tick(showDelay); |
| assertTrue('Should trigger card', card.isVisible()); |
| } |
| |
| function testPositionAfterSecondTriggerWithMaxSearchSteps() { |
| initCard(undefined, true, 2); |
| |
| showDelay = 500; |
| goog.testing.events.fireMouseOverEvent(john, elsewhere); |
| timer.tick(showDelay); |
| assertTrue('Should trigger card', card.isVisible()); |
| assertEquals('Card cursor x coordinate should be 1', |
| card.position_.coordinate.x, 1); |
| card.cursorPosition = new goog.math.Coordinate(2, 2); |
| goog.testing.events.fireMouseOverEvent(child, elsewhere); |
| timer.tick(showDelay); |
| assertTrue('Should trigger card', card.isVisible()); |
| assertEquals('Card cursor x coordinate should be 2', |
| card.position_.coordinate.x, 2); |
| } |