UNPKG

jsaction

Version:

Google's event delegation library

683 lines (568 loc) 20.2 kB
// Copyright 2011 Google Inc. All rights reserved. /** */ /** @suppress {extraProvide} */ goog.provide('jsaction.eventTest'); goog.setTestOnly('jsaction.eventTest'); goog.require('goog.dom'); goog.require('goog.dom.TagName'); goog.require('goog.functions'); goog.require('goog.testing.PropertyReplacer'); goog.require('goog.testing.events.Event'); goog.require('goog.testing.jsunit'); goog.require('jsaction.EventType'); goog.require('jsaction.KeyCodes'); goog.require('jsaction.event'); var stubs = new goog.testing.PropertyReplacer(); function DivMock() { this.listeners = []; } DivMock.prototype.addEventListener = function(event, handler, capture) { this.listeners.push([0, event, handler, capture]); }; DivMock.prototype.attachEvent = function(event, handler) { this.listeners.push([1, event, handler]); }; var div_ = null; var validTarget = goog.dom.createDom(goog.dom.TagName.DIV, {tabIndex: 0, role: 'button'}); var invalidTarget = document.createElement('div'); var roleTarget = goog.dom.createDom(goog.dom.TagName.DIV, {tabIndex: 0, role: 'textbox'}); function setUp() { div_ = new DivMock; } function tearDown() { stubs.reset(); } function testAddEventListenerW3C() { var eventInfo = jsaction.event.addEventListener( div_, 'click', goog.nullFunction); assertEquals('click', eventInfo.eventType); assertFalse(eventInfo.capture); } function testAddEventListenerIE() { div_.addEventListener = null; var handlerThis = null; var handler = function() { handlerThis = this; }; var eventInfo = jsaction.event.addEventListener(div_, 'click', handler); assertEquals('click', eventInfo.eventType); assertFalse(handler == eventInfo.handler); eventInfo.handler(); assertEquals(div_, handlerThis); } function testAddEventListenerFocusW3C() { var eventInfo = jsaction.event.addEventListener( div_, 'focus', goog.nullFunction); assertEquals('focus', eventInfo.eventType); assertTrue(eventInfo.capture); } function testAddEventListenerBlurW3C() { var eventInfo = jsaction.event.addEventListener( div_, 'blur', goog.nullFunction); assertEquals('blur', eventInfo.eventType); assertTrue(eventInfo.capture); } function testAddEventListenerErrorW3C() { var eventInfo = jsaction.event.addEventListener( div_, 'error', goog.nullFunction); assertEquals('error', eventInfo.eventType); assertTrue(eventInfo.capture); } function testAddEventListenerLoadW3C() { var eventInfo = jsaction.event.addEventListener( div_, 'load', goog.nullFunction); assertEquals('load', eventInfo.eventType); assertTrue(eventInfo.capture); } function testAddEventListenerFocusIE() { div_.addEventListener = null; var eventInfo = jsaction.event.addEventListener( div_, 'focus', goog.nullFunction); assertEquals('focusin', eventInfo.eventType); } function testAddEventListenerBlurIE() { div_.addEventListener = null; var eventInfo = jsaction.event.addEventListener( div_, 'blur', goog.nullFunction); assertEquals('focusout', eventInfo.eventType); } function testIsModifiedClickEventMacMetaKey() { var event = {metaKey: true}; jsaction.event.isMac_ = true; assertTrue(jsaction.event.isModifiedClickEvent(event)); } function testIsModifiedClickEventNonMacCtrlKey() { var event = {ctrlKey: true}; jsaction.event.isMac_ = false; assertTrue(jsaction.event.isModifiedClickEvent(event)); } function testIsModifiedClickEventMiddleClick() { var event = {which: 2}; assertTrue(jsaction.event.isModifiedClickEvent(event)); } function testIsModifiedClickEventMiddleClickIE() { var event = {button: 4}; assertTrue(jsaction.event.isModifiedClickEvent(event)); } function testIsModifiedClickEventShiftKey() { var event = {shiftKey: true}; assertTrue(jsaction.event.isModifiedClickEvent(event)); } function testIsValidActionKeyTarget() { var div = document.createElement('div'); div.setAttribute('role', 'checkbox'); var textarea = document.createElement('textarea'); var input = document.createElement('input'); input.type = 'password'; assertTrue(jsaction.event.isValidActionKeyTarget_(div)); assertFalse(jsaction.event.isValidActionKeyTarget_(textarea)); assertFalse(jsaction.event.isValidActionKeyTarget_(input)); input.setAttribute('role', 'combobox'); assertEquals('combobox', input.getAttribute('role')); assertFalse(jsaction.event.isValidActionKeyTarget_(input)); var search = document.createElement('search'); search.type = 'search'; assertEquals('search', search.type); assertFalse(jsaction.event.isValidActionKeyTarget_(search)); var holder = document.createElement('div'); holder.innerHTML = '<input type=\"number\"/>'; var num = holder.firstChild; assertEquals('number', num.getAttribute('type')); assertFalse(jsaction.event.isValidActionKeyTarget_(num)); var div2 = document.createElement('div'); // contentEditable only works on non-orphaned elements. document.body.appendChild(div2); div2.contentEditable = 'true'; div2.setAttribute('role', 'combobox'); assertFalse(jsaction.event.isValidActionKeyTarget_(div2)); div2.removeAttribute('role'); assertFalse(jsaction.event.isValidActionKeyTarget_(div2)); div.removeAttribute('role'); assertTrue(jsaction.event.isValidActionKeyTarget_(div)); document.body.removeChild(div2); } function testIsActionKeyEventFailsOnClick() { var event = { type: 'click', target: validTarget }; assertFalse(jsaction.event.isActionKeyEvent(event)); } function baseIsActionKeyEvent(keyCode, opt_target, opt_originalTarget) { var event = { type: jsaction.EventType.KEYDOWN, which: keyCode, target: opt_target || validTarget, originalTarget: opt_originalTarget || opt_target || validTarget }; stubs.set(jsaction.event, 'isValidActionKeyTarget_', goog.functions.TRUE); try { // isFocusable() in IE calls getBoundingClientRect(), which fails on orphans document.body.appendChild(event.target); event.target.style.height = '4px'; // Make sure we don't report as hidden. event.target.style.width = '4px'; return jsaction.event.isActionKeyEvent(event); } finally { document.body.removeChild(event.target); } } function testIsActionKeyEventFailsOnInvalidKey() { assertFalse(baseIsActionKeyEvent(64)); } function testIsActionKeyEventEnter() { assertTrue(baseIsActionKeyEvent(jsaction.KeyCodes.ENTER)); } function testIsActionKeyEventSpace() { assertTrue(baseIsActionKeyEvent(jsaction.KeyCodes.SPACE)); } function testIsActionKeyRealCheckBox() { var checkbox = document.createElement('input'); checkbox.type = 'checkbox'; assertFalse(baseIsActionKeyEvent(jsaction.KeyCodes.SPACE, checkbox)); assertFalse(baseIsActionKeyEvent(jsaction.KeyCodes.ENTER, checkbox)); } function testIsActionKeyFakeCheckBox() { var checkbox = goog.dom.createDom(goog.dom.TagName.DIV, {tabIndex: 0, role: 'checkbox'}); assertTrue(baseIsActionKeyEvent(jsaction.KeyCodes.SPACE, checkbox)); assertFalse(baseIsActionKeyEvent(jsaction.KeyCodes.ENTER, checkbox)); } function testIsActionKeyEventMacEnter() { if (!jsaction.event.isWebKit_) { return; } assertTrue(baseIsActionKeyEvent(jsaction.KeyCodes.MAC_ENTER)); } function testIsActionKeyNonControl() { var control = goog.dom.createDom(goog.dom.TagName.DIV); assertFalse(baseIsActionKeyEvent(jsaction.KeyCodes.ENTER, control)); } function testIsActionKeyDisabledControl() { var control = goog.dom.createDom(goog.dom.TagName.BUTTON, {disabled: true}); assertFalse(baseIsActionKeyEvent(jsaction.KeyCodes.ENTER, control)); } function testIsActionKeyNormalControl() { var control = goog.dom.createDom(goog.dom.TagName.BUTTON); assertTrue(baseIsActionKeyEvent(jsaction.KeyCodes.ENTER, control)); } function testIsActionKeyNonTabbableControl() { var control = goog.dom.createDom(goog.dom.TagName.BUTTON, {tabIndex: '-1'}); assertTrue(baseIsActionKeyEvent(jsaction.KeyCodes.ENTER, control)); control = goog.dom.createDom(goog.dom.TagName.DIV); control.setAttribute('role', 'button'); control.removeAttribute('tabindex'); assertFalse(baseIsActionKeyEvent(jsaction.KeyCodes.ENTER, control)); } function testIsActionKeyEventNotInMap() { var control = goog.dom.createDom(goog.dom.TagName.DIV, {tabIndex: 0}); assertTrue(baseIsActionKeyEvent(jsaction.KeyCodes.ENTER, control)); assertFalse(baseIsActionKeyEvent(jsaction.KeyCodes.SPACE, control)); } function testIsMouseSpecialEventMouseenter() { var root = document.createElement('div'); var child = document.createElement('div'); root.appendChild(child); var event = { relatedTarget: root, type: jsaction.EventType.MOUSEOVER, target: child }; assertTrue(jsaction.event.isMouseSpecialEvent(event, jsaction.EventType.MOUSEENTER, child)); } function testIsMouseSpecialEventNotMouseenter() { var root = document.createElement('div'); var child = document.createElement('div'); root.appendChild(child); var event = { relatedTarget: child, type: jsaction.EventType.MOUSEOVER, target: root }; assertFalse(jsaction.event.isMouseSpecialEvent(event, jsaction.EventType.MOUSEENTER, root)); assertFalse(jsaction.event.isMouseSpecialEvent(event, jsaction.EventType.MOUSEENTER, child)); } function testIsMouseSpecialEventMouseover() { var root = document.createElement('div'); var child = document.createElement('div'); root.appendChild(child); var subchild = document.createElement('div'); child.appendChild(subchild); var event = { relatedTarget: child, type: jsaction.EventType.MOUSEOVER, target: subchild }; assertFalse(jsaction.event.isMouseSpecialEvent(event, jsaction.EventType.MOUSEENTER, root)); assertFalse(jsaction.event.isMouseSpecialEvent(event, jsaction.EventType.MOUSEENTER, child)); assertTrue(jsaction.event.isMouseSpecialEvent(event, jsaction.EventType.MOUSEENTER, subchild)); } function testIsMouseSpecialEventMouseleave() { var root = document.createElement('div'); var child = document.createElement('div'); root.appendChild(child); var event = { relatedTarget: root, type: jsaction.EventType.MOUSEOUT, target: child }; assertTrue(jsaction.event.isMouseSpecialEvent(event, jsaction.EventType.MOUSELEAVE, child)); } function testIsMouseSpecialEventNotMouseleave() { var root = document.createElement('div'); var child = document.createElement('div'); root.appendChild(child); var event = { relatedTarget: child, type: jsaction.EventType.MOUSEOUT, target: root }; assertFalse(jsaction.event.isMouseSpecialEvent(event, jsaction.EventType.MOUSELEAVE, root)); assertFalse(jsaction.event.isMouseSpecialEvent(event, jsaction.EventType.MOUSELEAVE, child)); } function testIsMouseSpecialEventMouseout() { var root = document.createElement('div'); var child = document.createElement('div'); root.appendChild(child); var subchild = document.createElement('div'); child.appendChild(subchild); var event = { relatedTarget: child, type: jsaction.EventType.MOUSEOUT, target: subchild }; assertFalse(jsaction.event.isMouseSpecialEvent(event, jsaction.EventType.MOUSELEAVE, root)); assertFalse(jsaction.event.isMouseSpecialEvent(event, jsaction.EventType.MOUSELEAVE, child)); assertTrue(jsaction.event.isMouseSpecialEvent(event, jsaction.EventType.MOUSELEAVE, subchild)); } function testIsMouseSpecialEventNotMouse() { var root = document.createElement('div'); var child = document.createElement('div'); root.appendChild(child); var event = { relatedTarget: root, type: jsaction.EventType.CLICK, target: child }; assertFalse(jsaction.event.isMouseSpecialEvent(event, jsaction.EventType.MOUSELEAVE, child)); assertFalse(jsaction.event.isMouseSpecialEvent(event, jsaction.EventType.MOUSELEAVE, child)); } function testCreateMouseSpecialEventMouseenter() { var div = document.createElement('div'); var event = new goog.testing.events.Event(jsaction.EventType.MOUSEOVER, div); var copiedEvent = jsaction.event.createMouseSpecialEvent(event, div); assertEquals(jsaction.EventType.MOUSEENTER, copiedEvent['type']); assertEquals(div, copiedEvent['target']); assertEquals(false, copiedEvent['bubbles']); } function testCreateMouseSpecialEventMouseleave() { var div = document.createElement('div'); var event = new goog.testing.events.Event(jsaction.EventType.MOUSEOUT, div); var copiedEvent = jsaction.event.createMouseSpecialEvent(event, div); assertEquals(jsaction.EventType.MOUSELEAVE, copiedEvent['type']); assertEquals(div, copiedEvent['target']); assertEquals(false, copiedEvent['bubbles']); } function testRecreateTouchEventAsClick() { var div = document.createElement('div'); var origEvent = new goog.testing.events.Event('touchend', div); origEvent.touches = [{ clientX: 1, clientY: 2, screenX: 3, screenY: 4, pageX: 5, pageY: 6 }, {}]; var event = jsaction.event.recreateTouchEventAsClick(origEvent); assertEquals('click', event.type); assertEquals(1, event.clientX); assertEquals(2, event.clientY); assertEquals(3, event.screenX); assertEquals(4, event.screenY); origEvent = new goog.testing.events.Event('touchend', div); origEvent.changedTouches = [{ clientX: 'other', clientY: 2, screenX: 3, screenY: 4, pageX: 5, pageY: 6 }]; assertEquals('touchend', origEvent.type); event = jsaction.event.recreateTouchEventAsClick(origEvent); assertEquals('click', event.type); assertEquals('other', event.clientX); assertEquals(2, event.clientY); assertEquals(3, event.screenX); assertEquals(4, event.screenY); assertEquals('touchend', event.originalEventType); origEvent = new goog.testing.events.Event('touchend', div); origEvent.changedTouches = []; origEvent.touches = [{ clientX: 1 }, {}]; event = jsaction.event.recreateTouchEventAsClick(origEvent); assertEquals('click', event.type); assertEquals(1, event.clientX); } function testRecreateTouchEventAsClick_hasTouchData() { var div = document.createElement('div'); var event = new goog.testing.events.Event(jsaction.EventType.TOUCHEND, div); event['touches'] = [{ 'clientX': 101, 'clientY': 102, 'screenX': 201, 'screenY': 202 }]; var copiedEvent = jsaction.event.recreateTouchEventAsClick(event); assertEquals(jsaction.EventType.CLICK, copiedEvent['type']); assertEquals(jsaction.EventType.TOUCHEND, copiedEvent['originalEventType']); assertEquals(div, copiedEvent['target']); assertEquals(101, copiedEvent['clientX']); assertEquals(102, copiedEvent['clientY']); assertEquals(201, copiedEvent['screenX']); assertEquals(202, copiedEvent['screenY']); } function testRecreateTouchEventAsClick_noTouchData() { var div = document.createElement('div'); var event = new goog.testing.events.Event(jsaction.EventType.TOUCHEND, div); var copiedEvent = jsaction.event.recreateTouchEventAsClick(event); assertEquals(jsaction.EventType.CLICK, copiedEvent['type']); assertEquals(jsaction.EventType.TOUCHEND, copiedEvent['originalEventType']); assertEquals(div, copiedEvent['target']); assertUndefined(copiedEvent['clientX']); assertUndefined(copiedEvent['clientY']); assertUndefined(copiedEvent['screenX']); assertUndefined(copiedEvent['screenY']); } function testRecreateTouchEventAsClick_behavior() { var div = document.createElement('div'); var origEvent = new goog.testing.events.Event('touchend', div); origEvent.touches = [{ clientX: 1, clientY: 2, screenX: 3, screenY: 4, pageX: 5, pageY: 6 }, {}]; var event = jsaction.event.recreateTouchEventAsClick(origEvent); assertEquals('click', event.type); assertFalse(event.defaultPrevented); event.preventDefault(); assertTrue(event.defaultPrevented); assertFalse(event['_propagationStopped']); event.stopPropagation(); assertTrue(event['_propagationStopped']); } function testRecreateTouchEventAsClick_timeStamp() { var div = document.createElement('div'); var origEvent = new goog.testing.events.Event('touchend', div); origEvent.touches = [{ clientX: 1, clientY: 2, screenX: 3, screenY: 4, pageX: 5, pageY: 6 }, {}]; var event = jsaction.event.recreateTouchEventAsClick(origEvent); assertEquals('click', event.type); assertTrue(event.timeStamp >= goog.now() - 500); } function testPreventMouseEvents() { var div = document.createElement('div'); var event = new goog.testing.events.Event('touchend', div); assertFalse(jsaction.event.isMouseEventsPrevented(event)); jsaction.event.preventMouseEvents(event); assertTrue(jsaction.event.isMouseEventsPrevented(event)); } function testAddPreventMouseEventsSupport() { var div = document.createElement('div'); var event = new goog.testing.events.Event('touchend', div); jsaction.event.addPreventMouseEventsSupport(event); assertFalse(jsaction.event.isMouseEventsPrevented(event)); event['_preventMouseEvents'](); assertTrue(jsaction.event.isMouseEventsPrevented(event)); } function testMaybeCopyEvent() { var div = document.createElement('div'); document.body.appendChild(div); var event; var maybeCopy; div.onclick = function(e) { event = e || window.event; maybeCopy = jsaction.event.maybeCopyEvent(event); }; if (document.createEvent) { // All browsers except older IEs. var toDispatch = document.createEvent('HTMLEvents'); toDispatch.initEvent('click', true, true); div.dispatchEvent(toDispatch); } else { div.click(); } assertNotNullNorUndefined(event); if (document.createEvent) { assertEquals(event, maybeCopy); } else { assertNotEquals(event, maybeCopy); } if (maybeCopy.target) { assertEquals(div, maybeCopy.target); } else { assertEquals(div, maybeCopy.srcElement); } } function testMaybeCopyEventDoesNotCopyNonBrowserEvent() { var event = {}; var maybeCopy = jsaction.event.maybeCopyEvent(event); assertEquals(event, maybeCopy); // More browser like: var node = document.createElement('div'); event = { type: 'click', target: node, srcElement: node }; maybeCopy = jsaction.event.maybeCopyEvent(event); assertEquals(event, maybeCopy); } function testIsSpaceKeyEvent() { var ev = { target: validTarget, keyCode: jsaction.KeyCodes.SPACE }; assertTrue(jsaction.event.isSpaceKeyEvent(ev)); var input = goog.dom.createDom(goog.dom.TagName.INPUT); input.type = 'checkbox'; ev = { target: input, keyCode: jsaction.KeyCodes.SPACE }; assertFalse(jsaction.event.isSpaceKeyEvent(ev)); } function testShouldCallPreventDefaultOnNativeHtmlControl() { var ev = { target: validTarget }; assertTrue(jsaction.event.shouldCallPreventDefaultOnNativeHtmlControl(ev)); ev = { target: invalidTarget }; assertFalse(jsaction.event.shouldCallPreventDefaultOnNativeHtmlControl(ev)); ev = { target: roleTarget }; assertFalse(jsaction.event.shouldCallPreventDefaultOnNativeHtmlControl(ev)); var button = document.createElement('button'); ev = { target: button }; assertTrue(jsaction.event.shouldCallPreventDefaultOnNativeHtmlControl(ev)); var input = document.createElement('input'); input.type = 'button'; ev = { target: input }; assertTrue(jsaction.event.shouldCallPreventDefaultOnNativeHtmlControl(ev)); var checkbox = document.createElement('input'); checkbox.type = 'checkbox'; ev = { target: checkbox }; assertFalse(jsaction.event.shouldCallPreventDefaultOnNativeHtmlControl(ev)); var radio = document.createElement('input'); radio.type = 'radio'; ev = { target: radio }; assertFalse(jsaction.event.shouldCallPreventDefaultOnNativeHtmlControl(ev)); var option = document.createElement('option'); ev = { target: option }; assertFalse(jsaction.event.shouldCallPreventDefaultOnNativeHtmlControl(ev)); var link = document.createElement('a'); link.setAttribute('href', 'http://www.google.com'); ev = { target: link }; assertFalse(jsaction.event.shouldCallPreventDefaultOnNativeHtmlControl(ev)); }