// Copyright 2007 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.acTest'); goog.setTestOnly('goog.ui.acTest'); goog.require('goog.array'); goog.require('goog.asserts'); goog.require('goog.dom'); goog.require('goog.dom.NodeType'); goog.require('goog.dom.classlist'); goog.require('goog.dom.selection'); goog.require('goog.events'); goog.require('goog.events.BrowserEvent'); goog.require('goog.events.Event'); goog.require('goog.events.EventType'); goog.require('goog.events.KeyCodes'); goog.require('goog.style'); goog.require('goog.testing.MockClock'); goog.require('goog.testing.jsunit'); goog.require('goog.ui.ac'); goog.require('goog.userAgent'); var autocomplete; var data = ['ab', 'aab', 'aaab']; var input; var mockClock; function setUpPage() { goog.ui.ac.createSimpleAutoComplete( data, goog.dom.getElement('user'), true, false); } function setUp() { mockClock = new goog.testing.MockClock(true); input = goog.dom.getElement('input'); input.value = ''; autocomplete = goog.ui.ac.createSimpleAutoComplete(data, input, true, false); } function tearDown() { autocomplete.dispose(); mockClock.dispose(); } //========================================================================= // Utility methods /** * Fire listeners of a given type that are listening to the event's * currentTarget. * * @param {goog.events.BrowserEvent} event */ function simulateEvent(event) { goog.events.fireListeners(event.currentTarget, event.type, true, event); goog.events.fireListeners(event.currentTarget, event.type, false, event); } /** * Fire all key event listeners that are listening to the input element. * * @param {number} keyCode The key code. */ function simulateAllKeyEventsOnInput(keyCode) { var eventTypes = [ goog.events.EventType.KEYDOWN, goog.events.EventType.KEYPRESS, goog.events.EventType.KEYUP ]; goog.array.forEach(eventTypes, function(type) { var event = new goog.events.Event(type, input); event.keyCode = keyCode; simulateEvent(new goog.events.BrowserEvent(event, input)); }); } /** * @param {string} text * @return {Node} Node whose inner text maches the given text. */ function findNodeByInnerText(text) { return goog.dom.findNode(document.body, function(node) { try { var display = goog.userAgent.IE ? goog.style.getCascadedStyle(node, 'display') : goog.style.getComputedStyle(node, 'display'); return goog.dom.getRawTextContent(node) == text && 'none' != display && node.nodeType == goog.dom.NodeType.ELEMENT; } catch (e) { return false; } }); } //========================================================================= // Tests /** * Ensure that the display of the autocompleter works. */ function testBasicDisplay() { simulateAllKeyEventsOnInput(goog.events.KeyCodes.DOWN); input.value = 'a'; simulateAllKeyEventsOnInput(goog.events.KeyCodes.A); mockClock.tick(500); var nodes = [ findNodeByInnerText(data[0]), findNodeByInnerText(data[1]), findNodeByInnerText(data[2]) ]; assert(!!nodes[0]); assert(!!nodes[1]); assert(!!nodes[2]); assert(goog.style.isUnselectable(nodes[0])); assert(goog.style.isUnselectable(nodes[1])); assert(goog.style.isUnselectable(nodes[2])); input.value = 'aa'; simulateAllKeyEventsOnInput(goog.events.KeyCodes.A); mockClock.tick(500); assertFalse(!!findNodeByInnerText(data[0])); assert(!!findNodeByInnerText(data[1])); assert(!!findNodeByInnerText(data[2])); } /** * Ensure that key navigation with multiple inputs work */ function testKeyNavigation() { simulateAllKeyEventsOnInput(goog.events.KeyCodes.DOWN); input.value = 'c, a'; goog.dom.selection.setCursorPosition(input, 'c, a'.length); simulateAllKeyEventsOnInput(goog.events.KeyCodes.A); mockClock.tick(500); assert(document.body.innerHTML, !!findNodeByInnerText(data[1])); assert(!!findNodeByInnerText(data[2])); var selected = goog.asserts.assertElement(findNodeByInnerText(data[0])); assertTrue( 'Should have new standard active class', goog.dom.classlist.contains(selected, 'ac-active')); assertTrue( 'Should have legacy active class', goog.dom.classlist.contains(selected, 'active')); simulateAllKeyEventsOnInput(goog.events.KeyCodes.DOWN); assertFalse( goog.dom.classlist.contains( goog.asserts.assertElement(findNodeByInnerText(data[0])), 'ac-active')); assert( goog.dom.classlist.contains( goog.asserts.assertElement(findNodeByInnerText(data[1])), 'ac-active')); simulateAllKeyEventsOnInput(goog.events.KeyCodes.ENTER); assertEquals('c, aab, ', input.value); } /** * Ensure that mouse navigation with multiple inputs works. */ function testMouseNavigation() { simulateAllKeyEventsOnInput(goog.events.KeyCodes.DOWN); input.value = 'c, a'; goog.dom.selection.setCursorPosition(input, 'c, a'.length); simulateAllKeyEventsOnInput(goog.events.KeyCodes.A); mockClock.tick(500); var secondOption = goog.asserts.assertElement(findNodeByInnerText(data[1])); var parent = secondOption.parentNode; assertFalse(goog.dom.classlist.contains(secondOption, 'ac-active')); var mouseOver = new goog.events.Event(goog.events.EventType.MOUSEOVER, secondOption); simulateEvent(new goog.events.BrowserEvent(mouseOver, parent)); assert(goog.dom.classlist.contains(secondOption, 'ac-active')); var mouseDown = new goog.events.Event(goog.events.EventType.MOUSEDOWN, secondOption); simulateEvent(new goog.events.BrowserEvent(mouseDown, parent)); var mouseClick = new goog.events.Event(goog.events.EventType.CLICK, secondOption); simulateEvent(new goog.events.BrowserEvent(mouseClick, parent)); assertEquals('c, aab, ', input.value); }