UNPKG

sku-pg

Version:

Skulpt is a Javascript implementation of Python 2.x. Python that runs in your browser!

381 lines (336 loc) 16 kB
<!DOCTYPE html> <html> <!-- Copyright 2008 The Closure Library Authors. All Rights Reserved. Use of this source code is governed by the Apache License, Version 2.0. See the COPYING file for details. --> <!-- Author: attila@google.com (Attila Bodis) --> <head> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>Closure Unit Tests - goog.ui.Tooltip</title> <script src="../base.js"></script> <script> goog.require('goog.dom'); goog.require('goog.events'); goog.require('goog.events.Event'); goog.require('goog.events.EventHandler'); goog.require('goog.events.EventType'); goog.require('goog.positioning.AbsolutePosition'); goog.require('goog.style'); goog.require('goog.ui.Tooltip'); goog.require('goog.testing.MockClock'); goog.require('goog.testing.TestQueue'); goog.require('goog.testing.events'); goog.require('goog.testing.jsunit'); goog.require('goog.userAgent'); </script> </head> <body> <iframe id="testframe" style="width: 200px; height: 200px;" src="blank_test_helper.html"> </iframe> <script> /** * A subclass of Tooltip that overrides {@code getPositioningStrategy} * for testing purposes. */ function TestTooltip(el, text, dom) { goog.ui.Tooltip.call(this, el, text, dom); }; goog.inherits(TestTooltip, goog.ui.Tooltip); /** {@override} */ TestTooltip.prototype.getPositioningStrategy = function() { return new goog.positioning.AbsolutePosition(13, 17); }; var tt, clock, handler, eventQueue, dom; // Allow positions to be off by one in gecko as it reports scrolling // offsets in steps of 2. var ALLOWED_OFFSET = goog.userAgent.GECKO ? 1 : 0; function setUp() { // We get access denied error when accessing the iframe in IE on the farm // as IE doesn't have the same window size issues as firefox on the farm // we bypass the iframe and use the current document instead. if (goog.userAgent.IE) { dom = goog.dom.getDomHelper(document); } else { var frame = document.getElementById('testframe'); var doc = goog.dom.getFrameContentDocument(frame); dom = goog.dom.getDomHelper(doc); } // Host elements in fixed size iframe to avoid window size problems when // running under Selenium. dom.getDocument().body.innerHTML = '<p id="notpopup">Content</p>' + '<p id="hovertarget">Hover Here For Popup</p>' + '<p id="second">Secondary target</p>'; tt = new goog.ui.Tooltip(undefined, undefined, dom); tt.setElement(dom.createDom('div', {id: 'popup', style: 'visibility:hidden'}, 'Hello')); clock = new goog.testing.MockClock(true); eventQueue = new goog.testing.TestQueue(); handler = new goog.events.EventHandler(eventQueue); handler.listen(tt, goog.ui.PopupBase.EventType.SHOW, eventQueue.enqueue); handler.listen(tt, goog.ui.PopupBase.EventType.HIDE, eventQueue.enqueue); } function tearDown() { // tooltip needs to be hidden as well as disposed of so that it doesn't // leave global state hanging around to trip up other tests. tt.onHide_(); tt.dispose(); clock.uninstall(); handler.removeAll(); } function testConstructor() { var element = tt.getElement(); assertNotNull('Tooltip should have non-null element', element); assertEquals('Tooltip element should be the DIV we created', dom.getElement('popup'), element); assertEquals('Tooltip element should be a child of the document body', dom.getDocument().body, element.parentNode); } function testTooltipShowsAndHides() { var hoverTarget = dom.getElement('hovertarget'); var elsewhere = dom.getElement('notpopup'); var element = tt.getElement(); var position = new goog.math.Coordinate(5, 5); assertNotNull('Tooltip should have non-null element', element); assertEquals('Initial state should be inactive', goog.ui.Tooltip.State.INACTIVE, tt.getState()); tt.attach(hoverTarget); tt.setShowDelayMs(100); tt.setHideDelayMs(50); goog.testing.events.fireMouseOverEvent(hoverTarget, elsewhere, position); assertEquals(goog.ui.Tooltip.State.WAITING_TO_SHOW, tt.getState()); clock.tick(101); assertEquals('visible', tt.getElement().style.visibility); assertEquals('tooltip y position (10px margin below the cursor)', '15px', tt.getElement().style.top); assertEquals(goog.ui.Tooltip.State.SHOWING, tt.getState()); assertEquals(goog.ui.PopupBase.EventType.SHOW, eventQueue.dequeue().type); assertTrue(eventQueue.isEmpty()); goog.testing.events.fireMouseOutEvent(hoverTarget, elsewhere); assertEquals(goog.ui.Tooltip.State.WAITING_TO_HIDE, tt.getState()); clock.tick(51); assertEquals('hidden', tt.getElement().style.visibility); assertEquals(goog.ui.Tooltip.State.INACTIVE, tt.getState()); assertEquals(goog.ui.PopupBase.EventType.HIDE, eventQueue.dequeue().type); assertTrue(eventQueue.isEmpty()); } function testMultipleTargets() { var firstTarget = dom.getElement('hovertarget'); var secondTarget = dom.getElement('second'); var elsewhere = dom.getElement('notpopup'); var element = tt.getElement(); tt.attach(firstTarget); tt.attach(secondTarget); tt.setShowDelayMs(100); tt.setHideDelayMs(50); // Move over first target goog.testing.events.fireMouseOverEvent(firstTarget, elsewhere); clock.tick(101); assertEquals(goog.ui.PopupBase.EventType.SHOW, eventQueue.dequeue().type); assertTrue(eventQueue.isEmpty()); // Move from first to second goog.testing.events.fireMouseOutEvent(firstTarget, secondTarget); goog.testing.events.fireMouseOverEvent(secondTarget, firstTarget); assertEquals(goog.ui.Tooltip.State.UPDATING, tt.getState()); assertTrue(eventQueue.isEmpty()); // Move from second to element (before second shows) goog.testing.events.fireMouseOutEvent(secondTarget, element); goog.testing.events.fireMouseOverEvent(element, secondTarget); assertEquals(goog.ui.Tooltip.State.SHOWING, tt.getState()); assertTrue(eventQueue.isEmpty()); // Move from element to second, and let it show goog.testing.events.fireMouseOutEvent(element, secondTarget); goog.testing.events.fireMouseOverEvent(secondTarget, element); assertEquals(goog.ui.Tooltip.State.UPDATING, tt.getState()); clock.tick(101); assertEquals(goog.ui.Tooltip.State.SHOWING, tt.getState()); assertEquals('Anchor should be second target', secondTarget, tt.anchor); assertEquals(goog.ui.PopupBase.EventType.HIDE, eventQueue.dequeue().type); assertEquals(goog.ui.PopupBase.EventType.SHOW, eventQueue.dequeue().type); assertTrue(eventQueue.isEmpty()); // Move from second to first and then off without first showing goog.testing.events.fireMouseOutEvent(secondTarget, firstTarget); goog.testing.events.fireMouseOverEvent(firstTarget, secondTarget); assertEquals(goog.ui.Tooltip.State.UPDATING, tt.getState()); goog.testing.events.fireMouseOutEvent(firstTarget, elsewhere); assertEquals(goog.ui.Tooltip.State.WAITING_TO_HIDE, tt.getState()); clock.tick(51); assertEquals('hidden', tt.getElement().style.visibility); assertEquals(goog.ui.Tooltip.State.INACTIVE, tt.getState()); assertEquals(goog.ui.PopupBase.EventType.HIDE, eventQueue.dequeue().type); assertTrue(eventQueue.isEmpty()); clock.tick(200); // Move from element to second, but detach second before it shows. goog.testing.events.fireMouseOutEvent(element, secondTarget); goog.testing.events.fireMouseOverEvent(secondTarget, element); assertEquals(goog.ui.Tooltip.State.WAITING_TO_SHOW, tt.getState()); tt.detach(secondTarget); clock.tick(200); assertEquals(goog.ui.Tooltip.State.INACTIVE, tt.getState()); assertEquals('Anchor should be second target', secondTarget, tt.anchor); assertTrue(eventQueue.isEmpty()); } function testRequireInteraction() { var hoverTarget = dom.getElement('hovertarget'); var elsewhere = dom.getElement('notpopup'); tt.attach(hoverTarget); tt.setShowDelayMs(100); tt.setHideDelayMs(50); tt.setRequireInteraction(true); goog.testing.events.fireMouseOverEvent(hoverTarget, elsewhere); clock.tick(101); assertEquals( 'Tooltip should not show without mouse move event', 'hidden', tt.getElement().style.visibility); goog.testing.events.fireMouseMoveEvent(hoverTarget); goog.testing.events.fireMouseOverEvent(hoverTarget, elsewhere); clock.tick(101); assertEquals( 'Tooltip should show because we had mouse move event', 'visible', tt.getElement().style.visibility); goog.testing.events.fireMouseOutEvent(hoverTarget, elsewhere); clock.tick(51); assertEquals('hidden', tt.getElement().style.visibility); goog.testing.events.fireBrowserEvent(new goog.events.Event( goog.events.EventType.FOCUS, hoverTarget)); clock.tick(101); assertEquals( 'Tooltip should show because we had focus event', 'visible', tt.getElement().style.visibility); goog.testing.events.fireBrowserEvent(new goog.events.Event( goog.events.EventType.BLUR, hoverTarget)); clock.tick(51); assertEquals('hidden', tt.getElement().style.visibility); goog.testing.events.fireMouseMoveEvent(hoverTarget); goog.testing.events.fireMouseOverEvent(hoverTarget, elsewhere); goog.testing.events.fireMouseOutEvent(hoverTarget, elsewhere); goog.testing.events.fireMouseOverEvent(hoverTarget, elsewhere); clock.tick(101); assertEquals( 'A cancelled trigger should also cancel the seen interaction', 'hidden', tt.getElement().style.visibility); } function testDispose() { var element = tt.getElement(); tt.dispose(); assertTrue('Tooltip should have been disposed of', tt.isDisposed()); assertNull('Tooltip element reference should have been nulled out', tt.getElement()); assertNotEquals('Tooltip element should not be a child of the body', document.body, element.parentNode); } function testNested() { var ttNested; tt.getElement().appendChild(dom.createDom( 'span', {id: 'nested'}, 'Goodbye')); ttNested = new goog.ui.Tooltip(undefined, undefined, dom); ttNested.setElement(dom.createDom('div', {id: 'nestedPopup'}, 'hi')); tt.setShowDelayMs(100); tt.setHideDelayMs(50); ttNested.setShowDelayMs(75); ttNested.setHideDelayMs(25); var nestedAnchor = dom.getElement('nested'); var hoverTarget = dom.getElement('hovertarget'); var outerTooltip = dom.getElement('popup'); var innerTooltip = dom.getElement('nestedPopup'); var elsewhere = dom.getElement('notpopup'); ttNested.attach(nestedAnchor); tt.attach(hoverTarget); // Test mouse into, out of nested tooltip goog.testing.events.fireMouseOverEvent(hoverTarget, elsewhere); clock.tick(101); goog.testing.events.fireMouseOutEvent(hoverTarget, outerTooltip); goog.testing.events.fireMouseOverEvent(outerTooltip, hoverTarget); clock.tick(51); assertEquals('visible', tt.getElement().style.visibility); goog.testing.events.fireMouseOutEvent(outerTooltip, nestedAnchor); goog.testing.events.fireMouseOverEvent(nestedAnchor, outerTooltip); clock.tick(76); assertEquals('visible', tt.getElement().style.visibility); assertEquals('visible', ttNested.getElement().style.visibility); goog.testing.events.fireMouseOutEvent(nestedAnchor, outerTooltip); goog.testing.events.fireMouseOverEvent(outerTooltip, nestedAnchor); clock.tick(100); assertEquals('visible', tt.getElement().style.visibility); assertEquals('hidden', ttNested.getElement().style.visibility); // Go back in nested tooltip and then out through tooltip element. goog.testing.events.fireMouseOutEvent(outerTooltip, nestedAnchor); goog.testing.events.fireMouseOverEvent(nestedAnchor, outerTooltip); clock.tick(76); goog.testing.events.fireMouseOutEvent(nestedAnchor, innerTooltip); goog.testing.events.fireMouseOverEvent(innerTooltip, nestedAnchor); clock.tick(15); assertEquals('visible', tt.getElement().style.visibility); assertEquals('visible', ttNested.getElement().style.visibility); goog.testing.events.fireMouseOutEvent(innerTooltip, elsewhere); clock.tick(26); assertEquals('hidden', ttNested.getElement().style.visibility); clock.tick(51); assertEquals('hidden', tt.getElement().style.visibility); // Test with focus goog.testing.events.fireBrowserEvent(new goog.events.Event( goog.events.EventType.FOCUS, hoverTarget)); clock.tick(101); goog.testing.events.fireBrowserEvent(new goog.events.Event( goog.events.EventType.BLUR, hoverTarget)); goog.testing.events.fireBrowserEvent(new goog.events.Event( goog.events.EventType.FOCUS, nestedAnchor)); clock.tick(76); assertEquals('visible', tt.getElement().style.visibility); assertEquals('visible', ttNested.getElement().style.visibility); goog.testing.events.fireBrowserEvent(new goog.events.Event( goog.events.EventType.BLUR, nestedAnchor)); goog.testing.events.fireBrowserEvent(new goog.events.Event( goog.events.EventType.FOCUS, hoverTarget)); clock.tick(26); assertEquals('visible', tt.getElement().style.visibility); assertEquals('hidden', ttNested.getElement().style.visibility); ttNested.onHide_(); ttNested.dispose(); } function testMemoryLeak() { var listeners = goog.events.getTotalListenerCount(); var anchor = dom.createElement('div'); var tooltip = new goog.ui.Tooltip(anchor, ''); tooltip.setVisible(true); tooltip.dispose(); assertEquals('no event listeners leaked', listeners, goog.events.getTotalListenerCount()); } function testPosition() { dom.getDocument().body.style.paddingBottom = '150%'; // force scrollbar var scrollEl = dom.getDocumentScrollElement(); var anchor = dom.getElement('hovertarget'); var tooltip = new goog.ui.Tooltip(anchor, 'foo'); tooltip.getElement().style.position = 'absolute'; tooltip.cursorPosition.x = 100; tooltip.cursorPosition.y = 100; tooltip.showForElement(anchor); assertEquals('Tooltip should be at cursor position', '(110, 110)', // (100, 100) + padding (10, 10) goog.style.getPageOffset(tooltip.getElement()).toString()); scrollEl.scrollTop = 50; var offset = goog.style.getPageOffset(tooltip.getElement()); assertTrue('Tooltip should be at cursor position when scrolled', Math.abs(offset.x - 110) <= ALLOWED_OFFSET); // 100 + padding 10 assertTrue('Tooltip should be at cursor position when scrolled', Math.abs(offset.y - 110) <= ALLOWED_OFFSET); // 100 + padding 10 tooltip.dispose(); dom.getDocument().body.style.paddingTop = ''; scrollEl.scrollTop = 0; } function testPositionOverride() { var anchor = dom.getElement('hovertarget'); var tooltip = new TestTooltip(anchor, 'foo', dom); tooltip.showForElement(anchor); assertEquals('Tooltip should be at absolute position', '(13, 17)', goog.style.getPageOffset(tooltip.getElement()).toString()); tooltip.dispose(); } </script> </body> </html>