| // Copyright 2006 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.ac.AutoCompleteTest'); |
| goog.setTestOnly('goog.ui.ac.AutoCompleteTest'); |
| |
| goog.require('goog.a11y.aria'); |
| goog.require('goog.a11y.aria.Role'); |
| goog.require('goog.dom'); |
| goog.require('goog.events.EventHandler'); |
| goog.require('goog.events.EventTarget'); |
| goog.require('goog.string'); |
| goog.require('goog.testing.MockControl'); |
| goog.require('goog.testing.events'); |
| goog.require('goog.testing.jsunit'); |
| goog.require('goog.testing.mockmatchers'); |
| goog.require('goog.ui.ac.AutoComplete'); |
| goog.require('goog.ui.ac.InputHandler'); |
| goog.require('goog.ui.ac.RenderOptions'); |
| goog.require('goog.ui.ac.Renderer'); |
| |
| |
| |
| /** |
| * Mock DataStore |
| * @constructor |
| */ |
| function MockDS(opt_autoHilite) { |
| this.autoHilite_ = opt_autoHilite; |
| var disabledRow = { |
| match: function(str) {return this.text.match(str);}, |
| rowDisabled: true, |
| text: 'hello@u.edu' |
| }; |
| this.rows_ = [ |
| '"Slartibartfast Theadore" <fjordmaster@magrathea.com>', |
| '"Zaphod Beeblebrox" <theprez@universe.gov>', |
| '"Ford Prefect" <ford@theguide.com>', |
| '"Arthur Dent" <has.no.tea@gmail.com>', |
| '"Marvin The Paranoid Android" <marv@googlemail.com>', |
| 'the.mice@magrathea.com', |
| 'the.mice@myotherdomain.com', |
| 'hello@a.com', |
| disabledRow, |
| 'row@u.edu', |
| 'person@a.edu' |
| ]; |
| this.isRowDisabled = function(row) { |
| return !!row.rowDisabled; |
| }; |
| } |
| |
| MockDS.prototype.requestMatchingRows = function(token, maxMatches, |
| matchHandler) { |
| var escapedToken = goog.string.regExpEscape(token); |
| var matcher = new RegExp('(^|\\W+)' + escapedToken); |
| var matches = []; |
| for (var i = 0; i < this.rows_.length && matches.length < maxMatches; ++i) { |
| var row = this.rows_[i]; |
| if (row.match(matcher)) { |
| matches.push(row); |
| } |
| } |
| if (this.autoHilite_ === undefined) { |
| matchHandler(token, matches); |
| } else { |
| var options = new goog.ui.ac.RenderOptions(); |
| options.setAutoHilite(this.autoHilite_); |
| matchHandler(token, matches, options); |
| } |
| }; |
| |
| |
| /** |
| * Mock Selection Handler |
| */ |
| |
| function MockSelect() { |
| } |
| goog.inherits(MockSelect, goog.events.EventTarget); |
| |
| MockSelect.prototype.selectRow = function(row) { |
| this.selectedRow = row; |
| }; |
| |
| |
| |
| /** |
| * Renderer subclass that exposes additional private members for testing. |
| * @constructor |
| */ |
| function TestRend() { |
| goog.ui.ac.Renderer.call(this, goog.dom.getElement('test-area')); |
| } |
| goog.inherits(TestRend, goog.ui.ac.Renderer); |
| |
| TestRend.prototype.getRenderedRows = function() { |
| return this.rows_; |
| }; |
| |
| TestRend.prototype.getHilitedRowIndex = function() { |
| return this.hilitedRow_; |
| }; |
| |
| TestRend.prototype.getHilitedRowDiv = function() { |
| return this.rowDivs_[this.hilitedRow_]; |
| }; |
| |
| TestRend.prototype.getRowDiv = function(index) { |
| return this.rowDivs_[index]; |
| }; |
| |
| var handler; |
| var inputElement; |
| var mockControl; |
| |
| function setUp() { |
| inputElement = goog.dom.createDom('input', {type: 'text'}); |
| handler = new goog.events.EventHandler(); |
| mockControl = new goog.testing.MockControl(); |
| } |
| |
| function tearDown() { |
| handler.dispose(); |
| mockControl.$tearDown(); |
| goog.dom.removeChildren(goog.dom.getElement('test-area')); |
| } |
| |
| |
| /** |
| * Make sure results are truncated (or not) by setMaxMatches. |
| */ |
| function testMaxMatches() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| |
| ac.setMaxMatches(2); |
| ac.setToken('the'); |
| assertEquals(2, rend.getRenderedRows().length); |
| ac.setToken(''); |
| |
| ac.setMaxMatches(3); |
| ac.setToken('the'); |
| assertEquals(3, rend.getRenderedRows().length); |
| ac.setToken(''); |
| |
| ac.setMaxMatches(1000); |
| ac.setToken('the'); |
| assertEquals(4, rend.getRenderedRows().length); |
| ac.setToken(''); |
| } |
| |
| function testHiliteViaMouse() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var updates = 0; |
| var row = null; |
| var rowNode = null; |
| handler.listen(rend, |
| goog.ui.ac.AutoComplete.EventType.ROW_HILITE, |
| function(evt) { |
| updates++; |
| rowNode = evt.rowNode; |
| }); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setMaxMatches(4); |
| ac.setToken('the'); |
| // Need to set the startRenderingRows_ time to something long ago, otherwise |
| // the mouse event will not be fired. (The autocomplete logic waits for some |
| // time to pass after rendering before firing mouseover events.) |
| rend.startRenderingRows_ = -1; |
| var hilitedRowDiv = rend.getRowDiv(3); |
| goog.testing.events.fireMouseOverEvent(hilitedRowDiv); |
| assertEquals(2, updates); |
| assertTrue(goog.string.contains(rowNode.innerHTML, 'mice@myotherdomain.com')); |
| } |
| |
| function testMouseClickBeforeHilite() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setMaxMatches(4); |
| ac.setToken('the'); |
| // Need to set the startRenderingRows_ time to something long ago, otherwise |
| // the mouse event will not be fired. (The autocomplete logic waits for some |
| // time to pass after rendering before firing mouseover events.) |
| rend.startRenderingRows_ = -1; |
| |
| // hilite row 3... |
| var hilitedRowDiv = rend.getRowDiv(3); |
| goog.testing.events.fireMouseOverEvent(hilitedRowDiv); |
| |
| // but click row 2, to simulate mouse getting ahead of focus. |
| var targetRowDiv = rend.getRowDiv(2); |
| goog.testing.events.fireClickEvent(targetRowDiv); |
| |
| assertEquals('the.mice@magrathea.com', select.selectedRow); |
| } |
| |
| function testMouseClickOnFirstRowBeforeHilite() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setAutoHilite(false); |
| ac.setMaxMatches(4); |
| ac.setToken('the'); |
| |
| // Click the first row before highlighting it, to simulate mouse getting ahead |
| // of focus. |
| var targetRowDiv = rend.getRowDiv(0); |
| goog.testing.events.fireClickEvent(targetRowDiv); |
| |
| assertEquals( |
| '"Zaphod Beeblebrox" <theprez@universe.gov>', select.selectedRow); |
| } |
| |
| function testMouseClickOnRowAfterBlur() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var ih = new goog.ui.ac.InputHandler(); |
| ih.attachInput(inputElement); |
| |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, ih); |
| goog.testing.events.fireFocusEvent(inputElement); |
| ac.setToken('the'); |
| var targetRowDiv = rend.getRowDiv(0); |
| |
| // Simulate the user clicking on an autocomplete row in the short time between |
| // blur and autocomplete dismissal. |
| goog.testing.events.fireBlurEvent(inputElement); |
| assertNotThrows(function() { |
| goog.testing.events.fireClickEvent(targetRowDiv); |
| }); |
| } |
| |
| |
| /* |
| * Send AutoComplete a SELECT event with empty string for the row. We can't |
| * simulate with a simple mouse click, so we dispatch the event directly. |
| */ |
| function testSelectEventEmptyRow() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setMaxMatches(4); |
| ac.setToken('the'); |
| rend.startRenderingRows_ = -1; |
| |
| // hilight row 2 ('the.mice@...') |
| var hilitedRowDiv = rend.getRowDiv(2); |
| goog.testing.events.fireMouseOverEvent(hilitedRowDiv); |
| assertUndefined(select.selectedRow); |
| |
| // Dispatch an event that does not specify a row. |
| rend.dispatchEvent({ |
| type: goog.ui.ac.AutoComplete.EventType.SELECT, |
| row: '' |
| }); |
| |
| assertEquals('the.mice@magrathea.com', select.selectedRow); |
| } |
| |
| function testSuggestionsUpdateEvent() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| var updates = 0; |
| handler.listen(ac, |
| goog.ui.ac.AutoComplete.EventType.SUGGESTIONS_UPDATE, |
| function() { |
| updates++; |
| }); |
| |
| ac.setToken('the'); |
| assertEquals(1, updates); |
| |
| ac.setToken('beeb'); |
| assertEquals(2, updates); |
| |
| ac.setToken('ford'); |
| assertEquals(3, updates); |
| |
| ac.dismiss(); |
| assertEquals(4, updates); |
| |
| ac.setToken('dent'); |
| assertEquals(5, updates); |
| } |
| |
| function checkHilitedIndex(renderer, index) { |
| assertEquals(index, renderer.getHilitedRowIndex()); |
| } |
| |
| function testGetRowCount() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| assertEquals(0, ac.getRowCount()); |
| |
| ac.setToken('Zaphod'); |
| assertEquals(1, ac.getRowCount()); |
| |
| ac.setMaxMatches(2); |
| ac.setToken('the'); |
| assertEquals(2, ac.getRowCount()); |
| } |
| |
| |
| /** |
| * Try using next and prev to navigate past the ends with default behavior of |
| * allowFreeSelect_ and wrap_. |
| */ |
| function testHiliteNextPrev_default() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| |
| var updates = 0; |
| handler.listen(rend, |
| goog.ui.ac.AutoComplete.EventType.ROW_HILITE, |
| function() { |
| updates++; |
| }); |
| |
| // make sure 'next' and 'prev' don't explode before any token is set |
| ac.hiliteNext(); |
| ac.hilitePrev(); |
| ac.setMaxMatches(4); |
| assertEquals(0, rend.getRenderedRows().length); |
| |
| // check a few times |
| for (var i = 0; i < 3; ++i) { |
| ac.setToken(''); |
| ac.setToken('the'); |
| assertEquals(4, rend.getRenderedRows().length); |
| // check to see if we can select the last of the 4 items |
| checkHilitedIndex(rend, 0); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 1); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 2); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 3); |
| // try going over the edge |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 3); |
| |
| // go back down |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 2); |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 1); |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 0); |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 0); |
| } |
| // 21 changes in the loop above (3 * 7) |
| assertEquals(21, updates); |
| } |
| |
| |
| /** |
| * Try using next and prev to navigate past the ends with default behavior of |
| * allowFreeSelect_ and wrap_ and with a disabled first row. |
| */ |
| function testHiliteNextPrevWithDisabledFirstRow_default() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| |
| var updates = 0; |
| handler.listen(rend, |
| goog.ui.ac.AutoComplete.EventType.ROW_HILITE, |
| function() { |
| updates++; |
| }); |
| |
| // make sure 'next' and 'prev' don't explode before any token is set |
| ac.hiliteNext(); |
| ac.hilitePrev(); |
| ac.setMaxMatches(3); |
| assertEquals(0, rend.getRenderedRows().length); |
| |
| // check a few times with disabled first row |
| for (var i = 0; i < 3; ++i) { |
| ac.setToken(''); |
| ac.setToken('edu'); |
| assertEquals(3, rend.getRenderedRows().length); |
| // The first row is disabled, second should be highlighted. |
| checkHilitedIndex(rend, 1); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 2); |
| // try going over the edge |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 2); |
| |
| // go back down |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 1); |
| // First row is disabled, make sure we don't highlight it. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 1); |
| } |
| // 9 changes in the loop above (3 * 3) |
| assertEquals(9, updates); |
| } |
| |
| |
| /** |
| * Try using next and prev to navigate past the ends with default behavior of |
| * allowFreeSelect_ and wrap_ and with a disabled middle row. |
| */ |
| function testHiliteNextPrevWithDisabledMiddleRow_default() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| |
| var updates = 0; |
| handler.listen(rend, |
| goog.ui.ac.AutoComplete.EventType.ROW_HILITE, |
| function() { |
| updates++; |
| }); |
| |
| // make sure 'next' and 'prev' don't explode before any token is set |
| ac.hiliteNext(); |
| ac.hilitePrev(); |
| ac.setMaxMatches(3); |
| assertEquals(0, rend.getRenderedRows().length); |
| |
| // check a few times with disabled middle row |
| for (var i = 0; i < 3; ++i) { |
| ac.setToken(''); |
| ac.setToken('u'); |
| assertEquals(3, rend.getRenderedRows().length); |
| checkHilitedIndex(rend, 0); |
| ac.hiliteNext(); |
| // Second row is disabled and should be skipped. |
| checkHilitedIndex(rend, 2); |
| // try going over the edge |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 2); |
| |
| // go back down |
| ac.hilitePrev(); |
| // Second row is disabled, make sure we don't highlight it. |
| checkHilitedIndex(rend, 0); |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 0); |
| } |
| // 9 changes in the loop above (3 * 3) |
| assertEquals(9, updates); |
| } |
| |
| |
| /** |
| * Try using next and prev to navigate past the ends with default behavior of |
| * allowFreeSelect_ and wrap_ and with a disabled last row. |
| */ |
| function testHiliteNextPrevWithDisabledLastRow_default() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| |
| var updates = 0; |
| handler.listen(rend, |
| goog.ui.ac.AutoComplete.EventType.ROW_HILITE, |
| function() { |
| updates++; |
| }); |
| |
| // make sure 'next' and 'prev' don't explode before any token is set |
| ac.hiliteNext(); |
| ac.hilitePrev(); |
| ac.setMaxMatches(3); |
| assertEquals(0, rend.getRenderedRows().length); |
| |
| // check a few times with disabled last row |
| for (var i = 0; i < 3; ++i) { |
| ac.setToken(''); |
| ac.setToken('h'); |
| assertEquals(3, rend.getRenderedRows().length); |
| checkHilitedIndex(rend, 0); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 1); |
| // try going over the edge since last row is disabled |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 1); |
| |
| // go back down |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 0); |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 0); |
| } |
| // 9 changes in the loop above (3 * 3) |
| assertEquals(9, updates); |
| } |
| |
| |
| /** |
| * Try using next and prev to navigate past the ends with wrap_ off and |
| * allowFreeSelect_ on. |
| */ |
| function testHiliteNextPrev_allowFreeSelect() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setAllowFreeSelect(true); |
| |
| // make sure 'next' and 'prev' don't explode before any token is set |
| ac.hiliteNext(); |
| ac.hilitePrev(); |
| ac.setMaxMatches(4); |
| assertEquals(0, rend.getRenderedRows().length); |
| |
| // check a few times |
| for (var i = 0; i < 3; ++i) { |
| ac.setToken(''); |
| ac.setToken('the'); |
| assertEquals(4, rend.getRenderedRows().length); |
| // check to see if we can select the last of the 4 items |
| checkHilitedIndex(rend, 0); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 1); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 2); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 3); |
| // try going over the edge. Since allowFreeSelect is on, this will |
| // deselect the last row. |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, -1); |
| |
| // go back down the list |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 0); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 1); |
| |
| // go back up the list. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 0); |
| // go back above the first, deselects first. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, -1); |
| } |
| } |
| |
| |
| /** |
| * Try using next and prev to navigate past the ends with wrap_ off and |
| * allowFreeSelect_ on, and a disabled first row. |
| */ |
| function testHiliteNextPrevWithDisabledFirstRow_allowFreeSelect() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setAllowFreeSelect(true); |
| |
| // make sure 'next' and 'prev' don't explode before any token is set |
| ac.hiliteNext(); |
| ac.hilitePrev(); |
| ac.setMaxMatches(4); |
| assertEquals(0, rend.getRenderedRows().length); |
| |
| // check a few times with disabled first row |
| for (var i = 0; i < 3; ++i) { |
| ac.setToken(''); |
| ac.setToken('edu'); |
| assertEquals(3, rend.getRenderedRows().length); |
| // The first row is disabled, second should be highlighted. |
| checkHilitedIndex(rend, 1); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 2); |
| // Try going over the edge. Since allowFreeSelect is on, this will |
| // deselect the last row. |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, -1); |
| |
| // go back down the list, first row is disabled |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 1); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 2); |
| |
| // go back up the list. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 1); |
| // first is disabled, so deselect the second. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, -1); |
| } |
| } |
| |
| |
| /** |
| * Try using next and prev to navigate past the ends with wrap_ off and |
| * allowFreeSelect_ on, and a disabled middle row. |
| */ |
| function testHiliteNextPrevWithDisabledMiddleRow_allowFreeSelect() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setAllowFreeSelect(true); |
| |
| // make sure 'next' and 'prev' don't explode before any token is set |
| ac.hiliteNext(); |
| ac.hilitePrev(); |
| ac.setMaxMatches(4); |
| assertEquals(0, rend.getRenderedRows().length); |
| |
| // check a few times with disabled middle row |
| for (var i = 0; i < 3; ++i) { |
| ac.setToken(''); |
| ac.setToken('u'); |
| assertEquals(3, rend.getRenderedRows().length); |
| checkHilitedIndex(rend, 0); |
| ac.hiliteNext(); |
| // Second row is disabled and should be skipped. |
| checkHilitedIndex(rend, 2); |
| // try going over the edge. Since allowFreeSelect is on, this will |
| // deselect the last row. |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, -1); |
| |
| // go back down the list |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 0); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 2); |
| |
| // go back up the list. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 0); |
| // go back above the first, deselects first. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, -1); |
| } |
| } |
| |
| |
| /** |
| * Try using next and prev to navigate past the ends with wrap_ off and |
| * allowFreeSelect_ on, and a disabled last row. |
| */ |
| function testHiliteNextPrevWithDisabledLastRow_allowFreeSelect() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setAllowFreeSelect(true); |
| |
| // make sure 'next' and 'prev' don't explode before any token is set |
| ac.hiliteNext(); |
| ac.hilitePrev(); |
| ac.setMaxMatches(4); |
| assertEquals(0, rend.getRenderedRows().length); |
| |
| // check a few times with disabled last row |
| for (var i = 0; i < 3; ++i) { |
| ac.setToken(''); |
| ac.setToken('h'); |
| assertEquals(3, rend.getRenderedRows().length); |
| checkHilitedIndex(rend, 0); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 1); |
| // try going over the edge since last row is disabled. Since allowFreeSelect |
| // is on, this will deselect the last row. |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, -1); |
| |
| // go back down the list |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 0); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 1); |
| |
| // go back up the list. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 0); |
| // go back above the first, deselects first. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, -1); |
| } |
| } |
| |
| |
| /** |
| * Try using next and prev to navigate past the ends with wrap_ on |
| * allowFreeSelect_ off. |
| */ |
| function testHiliteNextPrev_wrap() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setWrap(true); |
| |
| // make sure 'next' and 'prev' don't explode before any token is set |
| ac.hiliteNext(); |
| ac.hilitePrev(); |
| ac.setMaxMatches(4); |
| assertEquals(0, rend.getRenderedRows().length); |
| |
| // check a few times |
| for (var i = 0; i < 3; ++i) { |
| ac.setToken(''); |
| ac.setToken('the'); |
| assertEquals(4, rend.getRenderedRows().length); |
| // check to see if we can select the last of the 4 items |
| checkHilitedIndex(rend, 0); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 1); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 2); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 3); |
| // try going over the edge. Since wrap is on, this will go back to 0. |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 0); |
| |
| // go back down the list |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 1); |
| |
| // go back up the list. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 0); |
| // go back above the first, selects last. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 3); |
| } |
| } |
| |
| |
| /** |
| * Try using next and prev to navigate past the ends with wrap_ on |
| * allowFreeSelect_ off and a disabled first row. |
| */ |
| function testHiliteNextPrevWithDisabledFirstRow_wrap() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setWrap(true); |
| |
| // make sure 'next' and 'prev' don't explode before any token is set |
| ac.hiliteNext(); |
| ac.hilitePrev(); |
| ac.setMaxMatches(4); |
| assertEquals(0, rend.getRenderedRows().length); |
| |
| // check a few times with disabled first row |
| for (var i = 0; i < 3; ++i) { |
| ac.setToken(''); |
| ac.setToken('edu'); |
| assertEquals(3, rend.getRenderedRows().length); |
| // The first row is disabled, second should be highlighted. |
| checkHilitedIndex(rend, 1); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 2); |
| // try going over the edge. Since wrap is on and first row is disabled, |
| // this will go back to 1. |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 1); |
| |
| // go back down the list |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 2); |
| |
| // go back up the list. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 1); |
| // first is disabled, so wrap and select the last. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 2); |
| } |
| } |
| |
| |
| /** |
| * Try using next and prev to navigate past the ends with wrap_ on |
| * allowFreeSelect_ off and a disabled middle row. |
| */ |
| function testHiliteNextPrevWithDisabledMiddleRow_wrap() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setWrap(true); |
| |
| // make sure 'next' and 'prev' don't explode before any token is set |
| ac.hiliteNext(); |
| ac.hilitePrev(); |
| ac.setMaxMatches(4); |
| assertEquals(0, rend.getRenderedRows().length); |
| |
| // check a few times with disabled middle row |
| for (var i = 0; i < 3; ++i) { |
| ac.setToken(''); |
| ac.setToken('u'); |
| assertEquals(3, rend.getRenderedRows().length); |
| checkHilitedIndex(rend, 0); |
| ac.hiliteNext(); |
| // Second row is disabled and should be skipped. |
| checkHilitedIndex(rend, 2); |
| // try going over the edge. Since wrap is on, this will go back to 0. |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 0); |
| |
| // go back down the list |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 2); |
| |
| // go back up the list. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 0); |
| // go back above the first, selects last. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 2); |
| } |
| } |
| |
| |
| /** |
| * Try using next and prev to navigate past the ends with wrap_ on |
| * allowFreeSelect_ off and a disabled last row. |
| */ |
| function testHiliteNextPrevWithDisabledLastRow_wrap() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setWrap(true); |
| |
| // make sure 'next' and 'prev' don't explode before any token is set |
| ac.hiliteNext(); |
| ac.hilitePrev(); |
| ac.setMaxMatches(4); |
| assertEquals(0, rend.getRenderedRows().length); |
| |
| // check a few times with disabled last row |
| for (var i = 0; i < 3; ++i) { |
| ac.setToken(''); |
| ac.setToken('h'); |
| assertEquals(3, rend.getRenderedRows().length); |
| checkHilitedIndex(rend, 0); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 1); |
| // try going over the edge since last row is disabled. Since wrap is on, |
| // this will go back to 0. |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 0); |
| |
| // go back down the list |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 1); |
| |
| // go back up the list. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 0); |
| // go back above the first, since wrap is on and last row is disabled, this |
| // will select the second last. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 1); |
| } |
| } |
| |
| |
| /** |
| * Try using next and prev to navigate past the ends with wrap_ on |
| * allowFreeSelect_ on. |
| */ |
| function testHiliteNextPrev_wrapAndAllowFreeSelect() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setWrap(true); |
| ac.setAllowFreeSelect(true); |
| |
| // make sure 'next' and 'prev' don't explode before any token is set |
| ac.hiliteNext(); |
| ac.hilitePrev(); |
| ac.setMaxMatches(4); |
| assertEquals(0, rend.getRenderedRows().length); |
| |
| // check a few times |
| for (var i = 0; i < 3; ++i) { |
| ac.setToken(''); |
| ac.setToken('the'); |
| assertEquals(4, rend.getRenderedRows().length); |
| // check to see if we can select the last of the 4 items |
| checkHilitedIndex(rend, 0); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 1); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 2); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 3); |
| // try going over the edge. Since free select is on, this should go |
| // to -1. |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, -1); |
| |
| // go back down the list |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 0); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 1); |
| |
| // go back up the list. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 0); |
| // go back above the first, free select. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, -1); |
| // wrap to last |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 3); |
| } |
| } |
| |
| |
| /** |
| * Try using next and prev to navigate past the ends with wrap_ on |
| * allowFreeSelect_ on and a disabled first row. |
| */ |
| function testHiliteNextPrevWithDisabledFirstRow_wrapAndAllowFreeSelect() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setWrap(true); |
| ac.setAllowFreeSelect(true); |
| |
| // make sure 'next' and 'prev' don't explode before any token is set |
| ac.hiliteNext(); |
| ac.hilitePrev(); |
| ac.setMaxMatches(4); |
| assertEquals(0, rend.getRenderedRows().length); |
| |
| // check a few times with disabled first row |
| for (var i = 0; i < 3; ++i) { |
| ac.setToken(''); |
| ac.setToken('edu'); |
| assertEquals(3, rend.getRenderedRows().length); |
| // The first row is disabled, second should be highlighted. |
| checkHilitedIndex(rend, 1); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 2); |
| // try going over the edge. Since free select is on, this should go to -1. |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, -1); |
| |
| // go back down the list, fist row is disabled |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 1); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 2); |
| |
| // go back up the list. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 1); |
| // go back above the first, free select. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, -1); |
| // wrap to last |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 2); |
| } |
| } |
| |
| |
| /** |
| * Try using next and prev to navigate past the ends with wrap_ on |
| * allowFreeSelect_ on and a disabled middle row. |
| */ |
| function testHiliteNextPrevWithDisabledMiddleRow_wrapAndAllowFreeSelect() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setWrap(true); |
| ac.setAllowFreeSelect(true); |
| |
| // make sure 'next' and 'prev' don't explode before any token is set |
| ac.hiliteNext(); |
| ac.hilitePrev(); |
| ac.setMaxMatches(4); |
| assertEquals(0, rend.getRenderedRows().length); |
| |
| // check a few times with disabled middle row |
| for (var i = 0; i < 3; ++i) { |
| ac.setToken(''); |
| ac.setToken('u'); |
| assertEquals(3, rend.getRenderedRows().length); |
| checkHilitedIndex(rend, 0); |
| ac.hiliteNext(); |
| // Second row is disabled and should be skipped. |
| checkHilitedIndex(rend, 2); |
| // try going over the edge. Since free select is on, this should go to -1 |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, -1); |
| |
| // go back down the list |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 0); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 2); |
| |
| // go back up the list. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 0); |
| // go back above the first, free select. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, -1); |
| // wrap to last |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 2); |
| } |
| } |
| |
| |
| /** |
| * Try using next and prev to navigate past the ends with wrap_ on |
| * allowFreeSelect_ on and a disabled last row. |
| */ |
| function testHiliteNextPrevWithDisabledLastRow_wrapAndAllowFreeSelect() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setWrap(true); |
| ac.setAllowFreeSelect(true); |
| |
| // make sure 'next' and 'prev' don't explode before any token is set |
| ac.hiliteNext(); |
| ac.hilitePrev(); |
| ac.setMaxMatches(4); |
| assertEquals(0, rend.getRenderedRows().length); |
| |
| // check a few times with disabled last row |
| for (var i = 0; i < 3; ++i) { |
| ac.setToken(''); |
| ac.setToken('h'); |
| assertEquals(3, rend.getRenderedRows().length); |
| checkHilitedIndex(rend, 0); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 1); |
| // try going over the edge since last row is disabled. Since free select is |
| // on, this should go to -1 |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, -1); |
| |
| // go back down the list |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 0); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 1); |
| |
| // go back up the list. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 0); |
| // go back above the first, free select. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, -1); |
| // wrap to the second last, since last is disabled. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 1); |
| } |
| } |
| |
| |
| /** |
| * Try using next and prev to navigate past the ends with wrap_ on |
| * allowFreeSelect_ on AND turn autoHilite_ off. |
| */ |
| function testHiliteNextPrev_wrapAndAllowFreeSelectNoAutoHilite() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setWrap(true); |
| ac.setAllowFreeSelect(true); |
| ac.setAutoHilite(false); |
| |
| // make sure 'next' and 'prev' don't explode before any token is set |
| ac.hiliteNext(); |
| ac.hilitePrev(); |
| ac.setMaxMatches(4); |
| assertEquals(0, rend.getRenderedRows().length); |
| |
| // check a few times |
| for (var i = 0; i < 3; ++i) { |
| ac.setToken(''); |
| ac.setToken('the'); |
| assertEquals(4, rend.getRenderedRows().length); |
| // check to see if we can select the last of the 4 items. |
| // Initially nothing should be selected since autoHilite_ is off. |
| checkHilitedIndex(rend, -1); |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 3); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, -1); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 0); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 1); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 2); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 3); |
| // try going over the edge. Since free select is on, this should go |
| // to -1. |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, -1); |
| |
| // go back down the list |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 0); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 1); |
| |
| // go back up the list. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 0); |
| // go back above the first, free select. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, -1); |
| // wrap to last |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 3); |
| } |
| } |
| |
| |
| /** |
| * Try using next and prev to navigate past the ends with wrap_ on |
| * allowFreeSelect_ on AND turn autoHilite_ off, and a disabled first row. |
| */ |
| function testHiliteNextPrevWithDisabledFirstRow_wrapAndAllowFreeSelectNoAutoHilite() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setWrap(true); |
| ac.setAllowFreeSelect(true); |
| ac.setAutoHilite(false); |
| |
| // make sure 'next' and 'prev' don't explode before any token is set |
| ac.hiliteNext(); |
| ac.hilitePrev(); |
| ac.setMaxMatches(4); |
| assertEquals(0, rend.getRenderedRows().length); |
| |
| // check a few times with disabled first row |
| for (var i = 0; i < 3; ++i) { |
| ac.setToken(''); |
| ac.setToken('edu'); |
| assertEquals(3, rend.getRenderedRows().length); |
| // Initially nothing should be selected since autoHilite_ is off. |
| checkHilitedIndex(rend, -1); |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 2); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, -1); |
| ac.hiliteNext(); |
| // First row is disabled. |
| checkHilitedIndex(rend, 1); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 2); |
| // try going over the edge. Since free select is on, this should go to -1 |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, -1); |
| |
| // go back down the list, first row is disabled |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 1); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 2); |
| |
| // go back up the list. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 1); |
| // go back above the first, free select. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, -1); |
| // wrap to last |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 2); |
| } |
| } |
| |
| |
| /** |
| * Try using next and prev to navigate past the ends with wrap_ on |
| * allowFreeSelect_ on AND turn autoHilite_ off, and a disabled middle row. |
| */ |
| function testHiliteNextPrevWithDisabledMiddleRow_wrapAndAllowFreeSelectNoAutoHilite() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setWrap(true); |
| ac.setAllowFreeSelect(true); |
| ac.setAutoHilite(false); |
| |
| // make sure 'next' and 'prev' don't explode before any token is set |
| ac.hiliteNext(); |
| ac.hilitePrev(); |
| ac.setMaxMatches(4); |
| assertEquals(0, rend.getRenderedRows().length); |
| |
| // check a few times with disabled middle row |
| for (var i = 0; i < 3; ++i) { |
| ac.setToken(''); |
| ac.setToken('u'); |
| assertEquals(3, rend.getRenderedRows().length); |
| // Initially nothing should be selected since autoHilite_ is off. |
| checkHilitedIndex(rend, -1); |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 2); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, -1); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 0); |
| ac.hiliteNext(); |
| // Second row is disabled |
| checkHilitedIndex(rend, 2); |
| // try going over the edge. Since free select is on, this should go to -1. |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, -1); |
| |
| // go back down the list |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 0); |
| ac.hiliteNext(); |
| // Second row is disabled. |
| checkHilitedIndex(rend, 2); |
| |
| // go back up the list. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 0); |
| // go back above the first, free select. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, -1); |
| // wrap to last |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 2); |
| } |
| } |
| |
| |
| /** |
| * Try using next and prev to navigate past the ends with wrap_ on |
| * allowFreeSelect_ on AND turn autoHilite_ off, and a disabled last row. |
| */ |
| function testHiliteNextPrevWithDisabledLastRow_wrapAndAllowFreeSelectNoAutoHilite() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setWrap(true); |
| ac.setAllowFreeSelect(true); |
| ac.setAutoHilite(false); |
| |
| // make sure 'next' and 'prev' don't explode before any token is set |
| ac.hiliteNext(); |
| ac.hilitePrev(); |
| ac.setMaxMatches(4); |
| assertEquals(0, rend.getRenderedRows().length); |
| |
| // check a few times with disabled last row |
| for (var i = 0; i < 3; ++i) { |
| ac.setToken(''); |
| ac.setToken('h'); |
| assertEquals(3, rend.getRenderedRows().length); |
| // Initially nothing should be selected since autoHilite_ is off. |
| checkHilitedIndex(rend, -1); |
| ac.hilitePrev(); |
| // Last row is disabled |
| checkHilitedIndex(rend, 1); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, -1); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 0); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 1); |
| // try going over the edge. Since free select is on, this should go to -1. |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, -1); |
| |
| // go back down the list |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 0); |
| ac.hiliteNext(); |
| checkHilitedIndex(rend, 1); |
| |
| // go back up the list. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 0); |
| // go back above the first, free select. |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, -1); |
| // wrap to last |
| ac.hilitePrev(); |
| checkHilitedIndex(rend, 1); |
| } |
| } |
| |
| function testHiliteWithChangingNumberOfRows() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setAutoHilite(true); |
| ac.setMaxMatches(4); |
| |
| ac.setToken('m'); |
| assertEquals(4, rend.getRenderedRows().length); |
| checkHilitedIndex(rend, 0); |
| |
| ac.setToken('ma'); |
| assertEquals(3, rend.getRenderedRows().length); |
| checkHilitedIndex(rend, 0); |
| |
| // Hilite the second element |
| var id = rend.getRenderedRows()[1].id; |
| ac.hiliteId(id); |
| |
| ac.setToken('mar'); |
| assertEquals(1, rend.getRenderedRows().length); |
| checkHilitedIndex(rend, 0); |
| |
| ac.setToken('ma'); |
| assertEquals(3, rend.getRenderedRows().length); |
| checkHilitedIndex(rend, 0); |
| |
| // Hilite the second element |
| var id = rend.getRenderedRows()[1].id; |
| ac.hiliteId(id); |
| |
| ac.setToken('m'); |
| assertEquals(4, rend.getRenderedRows().length); |
| checkHilitedIndex(rend, 0); |
| } |
| |
| |
| /** |
| * Checks that autohilite is disabled when there is no token; this allows the |
| * user to tab out of an empty autocomplete. |
| */ |
| function testNoAutoHiliteWhenTokenIsEmpty() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setWrap(true); |
| ac.setAllowFreeSelect(true); |
| ac.setAutoHilite(true); |
| ac.setMaxMatches(4); |
| |
| ac.setToken(''); |
| assertEquals(4, rend.getRenderedRows().length); |
| // No token; nothing should be hilited. |
| checkHilitedIndex(rend, -1); |
| |
| ac.setToken('the'); |
| assertEquals(4, rend.getRenderedRows().length); |
| // Now there is a token, so the first row should be highlighted. |
| checkHilitedIndex(rend, 0); |
| } |
| |
| |
| /** |
| * Checks that opt_preserveHilited works. |
| */ |
| function testPreserveHilitedWithoutAutoHilite() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setWrap(true); |
| ac.setAllowFreeSelect(true); |
| ac.setMaxMatches(4); |
| ac.setAutoHilite(false); |
| |
| ac.setToken('m'); |
| assertEquals(4, rend.getRenderedRows().length); |
| // No token; nothing should be hilited. |
| checkHilitedIndex(rend, -1); |
| |
| // Hilite the second element |
| var id = rend.getRenderedRows()[1].id; |
| ac.hiliteId(id); |
| |
| checkHilitedIndex(rend, 1); |
| |
| // Re-render and check if the second element is still hilited |
| ac.renderRows(rend.getRenderedRows(), true /* preserve hilite */); |
| |
| checkHilitedIndex(rend, 1); |
| |
| // Re-render without preservation |
| ac.renderRows(rend.getRenderedRows()); |
| |
| checkHilitedIndex(rend, -1); |
| } |
| |
| |
| /** |
| * Checks that the autohilite argument "true" of the matcher is used. |
| */ |
| function testAutoHiliteFromMatcherTrue() { |
| var ds = new MockDS(true); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setWrap(true); |
| ac.setAllowFreeSelect(true); |
| ac.setAutoHilite(false); // Will be overruled. |
| ac.setMaxMatches(4); |
| |
| ac.setToken('the'); |
| assertEquals(4, rend.getRenderedRows().length); |
| // The first row should be highlighted. |
| checkHilitedIndex(rend, 0); |
| } |
| |
| |
| /** |
| * Checks that the autohilite argument "false" of the matcher is used. |
| */ |
| function testAutoHiliteFromMatcherFalse() { |
| var ds = new MockDS(false); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setWrap(true); |
| ac.setAllowFreeSelect(true); |
| ac.setAutoHilite(true); // Will be overruled. |
| ac.setMaxMatches(4); |
| |
| ac.setToken('the'); |
| assertEquals(4, rend.getRenderedRows().length); |
| // The first row should not be highlighted. |
| checkHilitedIndex(rend, -1); |
| } |
| |
| |
| /** |
| * Hilite using ids, the way mouse-based hiliting would work. |
| */ |
| function testHiliteId() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| |
| // check a few times |
| for (var i = 0; i < 3; ++i) { |
| ac.setToken('m'); |
| assertEquals(4, rend.getRenderedRows().length); |
| // try hiliting all 3 |
| for (var x = 0; x < 4; ++x) { |
| var id = rend.getRenderedRows()[x].id; |
| ac.hiliteId(id); |
| assertEquals(ac.getIdOfIndex_(x), id); |
| } |
| } |
| } |
| |
| |
| /** |
| * Test selecting the hilited row |
| */ |
| function testSelection() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac; |
| |
| // try with default selection |
| ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setToken('m'); |
| ac.selectHilited(); |
| assertEquals('"Slartibartfast Theadore" <fjordmaster@magrathea.com>', |
| select.selectedRow); |
| |
| // try second item |
| ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setToken('the'); |
| ac.hiliteNext(); |
| ac.selectHilited(); |
| assertEquals('"Ford Prefect" <ford@theguide.com>', |
| select.selectedRow); |
| } |
| |
| |
| /** |
| * Dismiss when empty and non-empty |
| */ |
| function testDismiss() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| |
| // dismiss empty |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| var dismissed = 0; |
| handler.listen(ac, |
| goog.ui.ac.AutoComplete.EventType.DISMISS, |
| function() { |
| dismissed++; |
| }); |
| ac.dismiss(); |
| assertEquals(1, dismissed); |
| |
| ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setToken('sir not seen in this picture'); |
| ac.dismiss(); |
| |
| // dismiss with contents |
| ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setToken('t'); |
| ac.dismiss(); |
| } |
| |
| function testTriggerSuggestionsOnUpdate() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| |
| var dismissCalled = 0; |
| rend.dismiss = function() { |
| dismissCalled++; |
| }; |
| |
| var updateCalled = 0; |
| select.update = function(opt_force) { |
| updateCalled++; |
| }; |
| |
| // Normally, menu is dismissed after selecting row (without updating). |
| ac.setToken('the'); |
| ac.selectHilited(); |
| assertEquals(1, dismissCalled); |
| assertEquals(0, updateCalled); |
| |
| // But not if we re-trigger on update. |
| ac.setTriggerSuggestionsOnUpdate(true); |
| ac.setToken('the'); |
| ac.selectHilited(); |
| assertEquals(1, dismissCalled); |
| assertEquals(1, updateCalled); |
| } |
| |
| function testDispose() { |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setToken('the'); |
| ac.dispose(); |
| } |
| |
| |
| /** |
| * Ensure that activedescendant is updated properly. |
| */ |
| function testRolesAndStates() { |
| function checkActiveDescendant(activeDescendant) { |
| assertNotNull(inputElement); |
| assertEquals( |
| goog.a11y.aria.getActiveDescendant(inputElement), |
| activeDescendant); |
| } |
| function checkRole(el, role) { |
| assertNotNull(el); |
| assertEquals(goog.a11y.aria.getRole(el), role); |
| } |
| var ds = new MockDS(); |
| var rend = new TestRend(); |
| var select = new MockSelect(); |
| var ac = new goog.ui.ac.AutoComplete(ds, rend, select); |
| ac.setTarget(inputElement); |
| |
| // initially activedescendant is not set |
| checkActiveDescendant(null); |
| |
| // highlight the matching row and check that activedescendant updates |
| ac.setToken(''); |
| ac.setToken('the'); |
| ac.hiliteNext(); |
| checkActiveDescendant(rend.getHilitedRowDiv()); |
| |
| // highligted row should have a role of 'option' |
| checkRole(rend.getHilitedRowDiv(), goog.a11y.aria.Role.OPTION); |
| |
| // closing the autocomplete should clear activedescendant |
| ac.dismiss(); |
| checkActiveDescendant(null); |
| } |
| |
| function testAttachInputWithAnchor() { |
| var anchorElement = goog.dom.createDom('div', null, inputElement); |
| |
| var mockRenderer = mockControl.createLooseMock( |
| goog.ui.ac.Renderer, true); |
| mockRenderer.setAnchorElement(anchorElement); |
| var ignore = goog.testing.mockmatchers.ignoreArgument; |
| mockRenderer.renderRows(ignore, ignore, inputElement); |
| |
| var mockInputHandler = mockControl.createLooseMock( |
| goog.ui.ac.InputHandler, true); |
| mockInputHandler.attachInputs(inputElement); |
| |
| mockControl.$replayAll(); |
| var autoComplete = new goog.ui.ac.AutoComplete( |
| null, mockRenderer, mockInputHandler); |
| autoComplete.attachInputWithAnchor(inputElement, anchorElement); |
| autoComplete.setTarget(inputElement); |
| |
| autoComplete.renderRows(['abc', 'def']); |
| mockControl.$verifyAll(); |
| } |
| |
| function testDetachInputWithAnchor() { |
| var mockRenderer = mockControl.createLooseMock( |
| goog.ui.ac.Renderer, true); |
| var mockInputHandler = mockControl.createLooseMock( |
| goog.ui.ac.InputHandler, true); |
| var anchorElement = goog.dom.createDom('div', null, inputElement); |
| var inputElement2 = goog.dom.createDom('input', {type: 'text'}); |
| var anchorElement2 = goog.dom.createDom('div', null, inputElement2); |
| |
| mockControl.$replayAll(); |
| var autoComplete = new goog.ui.ac.AutoComplete( |
| null, mockRenderer, mockInputHandler); |
| |
| autoComplete.attachInputWithAnchor(inputElement, anchorElement); |
| autoComplete.attachInputWithAnchor(inputElement2, anchorElement2); |
| autoComplete.detachInputs(inputElement, inputElement2); |
| |
| assertFalse(goog.getUid(inputElement) in autoComplete.inputToAnchorMap_); |
| assertFalse(goog.getUid(inputElement2) in autoComplete.inputToAnchorMap_); |
| mockControl.$verifyAll(); |
| } |