| <!DOCTYPE html> | 
 | <!-- | 
 | @license | 
 | Copyright (C) 2016 The Android Open Source Project | 
 |  | 
 | 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. | 
 | --> | 
 |  | 
 | <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes"> | 
 | <title>gr-reviewer-list</title> | 
 | <script src="/test/common-test-setup.js"></script> | 
 | <script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script> | 
 |  | 
 | <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script> | 
 | <script src="/bower_components/web-component-tester/browser.js"></script> | 
 | <link rel="import" href="../../../test/common-test-setup.html"/> | 
 | <link rel="import" href="gr-autocomplete.html"> | 
 |  | 
 | <script>void(0);</script> | 
 |  | 
 | <test-fixture id="basic"> | 
 |   <template> | 
 |     <gr-autocomplete no-debounce></gr-autocomplete> | 
 |   </template> | 
 | </test-fixture> | 
 |  | 
 | <script> | 
 |   suite('gr-autocomplete tests', () => { | 
 |     let element; | 
 |     let sandbox; | 
 |  | 
 |     setup(() => { | 
 |       element = fixture('basic'); | 
 |       sandbox = sinon.sandbox.create(); | 
 |     }); | 
 |  | 
 |     teardown(() => { | 
 |       sandbox.restore(); | 
 |     }); | 
 |  | 
 |     test('renders', () => { | 
 |       let promise; | 
 |       const queryStub = sandbox.spy(input => { | 
 |         return promise = Promise.resolve([ | 
 |           {name: input + ' 0', value: 0}, | 
 |           {name: input + ' 1', value: 1}, | 
 |           {name: input + ' 2', value: 2}, | 
 |           {name: input + ' 3', value: 3}, | 
 |           {name: input + ' 4', value: 4}, | 
 |         ]); | 
 |       }); | 
 |       element.query = queryStub; | 
 |       assert.isTrue(element.$.suggestions.isHidden); | 
 |       assert.equal(element.$.suggestions.$.cursor.index, -1); | 
 |  | 
 |       element.text = 'blah'; | 
 |  | 
 |       assert.isTrue(queryStub.called); | 
 |       element._focused = true; | 
 |  | 
 |       return promise.then(() => { | 
 |         assert.isFalse(element.$.suggestions.isHidden); | 
 |         const suggestions = | 
 |             Polymer.dom(element.$.suggestions.root).querySelectorAll('li'); | 
 |         assert.equal(suggestions.length, 5); | 
 |  | 
 |         for (let i = 0; i < 5; i++) { | 
 |           assert.equal(suggestions[i].innerText.trim(), 'blah ' + i); | 
 |         } | 
 |  | 
 |         assert.notEqual(element.$.suggestions.$.cursor.index, -1); | 
 |       }); | 
 |     }); | 
 |  | 
 |     test('selectAll', done => { | 
 |       flush(() => { | 
 |         const nativeInput = element._nativeInput; | 
 |         const selectionStub = sandbox.stub(nativeInput, 'setSelectionRange'); | 
 |  | 
 |         element.selectAll(); | 
 |         assert.isFalse(selectionStub.called); | 
 |  | 
 |         element.$.input.value = 'test'; | 
 |         element.selectAll(); | 
 |         assert.isTrue(selectionStub.called); | 
 |         done(); | 
 |       }); | 
 |     }); | 
 |  | 
 |     test('esc key behavior', done => { | 
 |       let promise; | 
 |       const queryStub = sandbox.spy(() => { | 
 |         return promise = Promise.resolve([ | 
 |           {name: 'blah', value: 123}, | 
 |         ]); | 
 |       }); | 
 |       element.query = queryStub; | 
 |  | 
 |       assert.isTrue(element.$.suggestions.isHidden); | 
 |  | 
 |       element._focused = true; | 
 |       element.text = 'blah'; | 
 |  | 
 |       promise.then(() => { | 
 |         assert.isFalse(element.$.suggestions.isHidden); | 
 |  | 
 |         const cancelHandler = sandbox.spy(); | 
 |         element.addEventListener('cancel', cancelHandler); | 
 |  | 
 |         MockInteractions.pressAndReleaseKeyOn(element.$.input, 27, null, 'esc'); | 
 |         assert.isFalse(cancelHandler.called); | 
 |         assert.isTrue(element.$.suggestions.isHidden); | 
 |         assert.equal(element._suggestions.length, 0); | 
 |  | 
 |         MockInteractions.pressAndReleaseKeyOn(element.$.input, 27, null, 'esc'); | 
 |         assert.isTrue(cancelHandler.called); | 
 |         done(); | 
 |       }); | 
 |     }); | 
 |  | 
 |     test('emits commit and handles cursor movement', done => { | 
 |       let promise; | 
 |       const queryStub = sandbox.spy(input => { | 
 |         return promise = Promise.resolve([ | 
 |           {name: input + ' 0', value: 0}, | 
 |           {name: input + ' 1', value: 1}, | 
 |           {name: input + ' 2', value: 2}, | 
 |           {name: input + ' 3', value: 3}, | 
 |           {name: input + ' 4', value: 4}, | 
 |         ]); | 
 |       }); | 
 |       element.query = queryStub; | 
 |  | 
 |       assert.isTrue(element.$.suggestions.isHidden); | 
 |       assert.equal(element.$.suggestions.$.cursor.index, -1); | 
 |       element._focused = true; | 
 |       element.text = 'blah'; | 
 |  | 
 |       promise.then(() => { | 
 |         assert.isFalse(element.$.suggestions.isHidden); | 
 |  | 
 |         const commitHandler = sandbox.spy(); | 
 |         element.addEventListener('commit', commitHandler); | 
 |  | 
 |         assert.equal(element.$.suggestions.$.cursor.index, 0); | 
 |  | 
 |         MockInteractions.pressAndReleaseKeyOn(element.$.input, 40, null, | 
 |             'down'); | 
 |  | 
 |         assert.equal(element.$.suggestions.$.cursor.index, 1); | 
 |  | 
 |         MockInteractions.pressAndReleaseKeyOn(element.$.input, 40, null, | 
 |             'down'); | 
 |  | 
 |         assert.equal(element.$.suggestions.$.cursor.index, 2); | 
 |  | 
 |         MockInteractions.pressAndReleaseKeyOn(element.$.input, 38, null, 'up'); | 
 |  | 
 |         assert.equal(element.$.suggestions.$.cursor.index, 1); | 
 |  | 
 |         MockInteractions.pressAndReleaseKeyOn(element.$.input, 13, null, | 
 |             'enter'); | 
 |  | 
 |         assert.equal(element.value, 1); | 
 |         assert.isTrue(commitHandler.called); | 
 |         assert.equal(commitHandler.getCall(0).args[0].detail.value, 1); | 
 |         assert.isTrue(element.$.suggestions.isHidden); | 
 |         assert.isTrue(element._focused); | 
 |         done(); | 
 |       }); | 
 |     }); | 
 |  | 
 |     test('clear-on-commit behavior (off)', done => { | 
 |       let promise; | 
 |       const queryStub = sandbox.spy(() => { | 
 |         return promise = Promise.resolve([{name: 'suggestion', value: 0}]); | 
 |       }); | 
 |       element.query = queryStub; | 
 |       element.text = 'blah'; | 
 |  | 
 |       promise.then(() => { | 
 |         const commitHandler = sandbox.spy(); | 
 |         element.addEventListener('commit', commitHandler); | 
 |  | 
 |         MockInteractions.pressAndReleaseKeyOn(element.$.input, 13, null, | 
 |             'enter'); | 
 |  | 
 |         assert.isTrue(commitHandler.called); | 
 |         assert.equal(element.text, 'suggestion'); | 
 |         done(); | 
 |       }); | 
 |     }); | 
 |  | 
 |     test('clear-on-commit behavior (on)', done => { | 
 |       let promise; | 
 |       const queryStub = sandbox.spy(() => { | 
 |         return promise = Promise.resolve([{name: 'suggestion', value: 0}]); | 
 |       }); | 
 |       element.query = queryStub; | 
 |       element.text = 'blah'; | 
 |       element.clearOnCommit = true; | 
 |  | 
 |       promise.then(() => { | 
 |         const commitHandler = sandbox.spy(); | 
 |         element.addEventListener('commit', commitHandler); | 
 |  | 
 |         MockInteractions.pressAndReleaseKeyOn(element.$.input, 13, null, | 
 |             'enter'); | 
 |  | 
 |         assert.isTrue(commitHandler.called); | 
 |         assert.equal(element.text, ''); | 
 |         done(); | 
 |       }); | 
 |     }); | 
 |  | 
 |     test('threshold guards the query', () => { | 
 |       const queryStub = sandbox.spy(() => { | 
 |         return Promise.resolve([]); | 
 |       }); | 
 |       element.query = queryStub; | 
 |  | 
 |       element.threshold = 2; | 
 |  | 
 |       element.text = 'a'; | 
 |  | 
 |       assert.isFalse(queryStub.called); | 
 |  | 
 |       element.text = 'ab'; | 
 |  | 
 |       assert.isTrue(queryStub.called); | 
 |     }); | 
 |  | 
 |     test('noDebounce=false debounces the query', () => { | 
 |       const queryStub = sandbox.spy(() => { | 
 |         return Promise.resolve([]); | 
 |       }); | 
 |       let callback; | 
 |       const debounceStub = sandbox.stub(element, 'debounce', | 
 |           (name, cb) => { callback = cb; }); | 
 |       element.query = queryStub; | 
 |       element.noDebounce = false; | 
 |       element.text = 'a'; | 
 |       assert.isFalse(queryStub.called); | 
 |       assert.isTrue(debounceStub.called); | 
 |       assert.equal(debounceStub.lastCall.args[2], 200); | 
 |       assert.isFunction(callback); | 
 |       callback(); | 
 |       assert.isTrue(queryStub.called); | 
 |     }); | 
 |  | 
 |     test('_computeClass respects border property', () => { | 
 |       assert.equal(element._computeClass(), ''); | 
 |       assert.equal(element._computeClass(false), ''); | 
 |       assert.equal(element._computeClass(true), 'borderless'); | 
 |     }); | 
 |  | 
 |     test('undefined or empty text results in no suggestions', () => { | 
 |       element._updateSuggestions(undefined, 0, null); | 
 |       assert.equal(element._suggestions.length, 0); | 
 |     }); | 
 |  | 
 |     test('multi completes only the last part of the query', done => { | 
 |       let promise; | 
 |       const queryStub = sandbox.stub() | 
 |           .returns(promise = Promise.resolve([{name: 'suggestion', value: 0}])); | 
 |       element.query = queryStub; | 
 |       element.text = 'blah blah'; | 
 |       element.multi = true; | 
 |  | 
 |       promise.then(() => { | 
 |         const commitHandler = sandbox.spy(); | 
 |         element.addEventListener('commit', commitHandler); | 
 |  | 
 |         MockInteractions.pressAndReleaseKeyOn(element.$.input, 13, null, | 
 |             'enter'); | 
 |  | 
 |         assert.isTrue(commitHandler.called); | 
 |         assert.equal(element.text, 'blah 0'); | 
 |         done(); | 
 |       }); | 
 |     }); | 
 |  | 
 |     test('tabComplete flag functions', () => { | 
 |       // commitHandler checks for the commit event, whereas commitSpy checks for | 
 |       // the _commit function of the element. | 
 |       const commitHandler = sandbox.spy(); | 
 |       element.addEventListener('commit', commitHandler); | 
 |       const commitSpy = sandbox.spy(element, '_commit'); | 
 |       element._focused = true; | 
 |  | 
 |       element._suggestions = ['tunnel snakes rule!']; | 
 |       element.tabComplete = false; | 
 |       MockInteractions.pressAndReleaseKeyOn(element.$.input, 9, null, 'tab'); | 
 |       assert.isFalse(commitHandler.called); | 
 |       assert.isFalse(commitSpy.called); | 
 |       assert.isFalse(element._focused); | 
 |  | 
 |       element.tabComplete = true; | 
 |       element._focused = true; | 
 |       MockInteractions.pressAndReleaseKeyOn(element.$.input, 9, null, 'tab'); | 
 |       assert.isFalse(commitHandler.called); | 
 |       assert.isTrue(commitSpy.called); | 
 |       assert.isTrue(element._focused); | 
 |     }); | 
 |  | 
 |     test('_focused flag properly triggered', done => { | 
 |       flush(() => { | 
 |         assert.isFalse(element._focused); | 
 |         const input = element.$$('paper-input').inputElement; | 
 |         MockInteractions.focus(input); | 
 |         assert.isTrue(element._focused); | 
 |         done(); | 
 |       }); | 
 |     }); | 
 |  | 
 |     test('search icon shows with showSearchIcon property', done => { | 
 |       flush(() => { | 
 |         assert.equal(getComputedStyle(element.$$('iron-icon')).display, | 
 |             'none'); | 
 |         element.showSearchIcon = true; | 
 |         assert.notEqual(getComputedStyle(element.$$('iron-icon')).display, | 
 |             'none'); | 
 |         done(); | 
 |       }); | 
 |     }); | 
 |  | 
 |     test('vertical offset overridden by param if it exists', () => { | 
 |       assert.equal(element.$.suggestions.verticalOffset, 20); | 
 |       element.verticalOffset = 30; | 
 |       assert.equal(element.$.suggestions.verticalOffset, 30); | 
 |     }); | 
 |  | 
 |     test('_focused flag shows/hides the suggestions', () => { | 
 |       const openStub = sandbox.stub(element.$.suggestions, 'open'); | 
 |       const closedStub = sandbox.stub(element.$.suggestions, 'close'); | 
 |       element._suggestions = ['hello', 'its me']; | 
 |       assert.isFalse(openStub.called); | 
 |       assert.isTrue(closedStub.calledOnce); | 
 |       element._focused = true; | 
 |       assert.isTrue(openStub.calledOnce); | 
 |       element._suggestions = []; | 
 |       assert.isTrue(closedStub.calledTwice); | 
 |       assert.isTrue(openStub.calledOnce); | 
 |     }); | 
 |  | 
 |     test('_handleInputCommit with autocomplete hidden does nothing without' + | 
 |           'without allowNonSuggestedValues', () => { | 
 |       const commitStub = sandbox.stub(element, '_commit'); | 
 |       element.$.suggestions.isHidden = true; | 
 |       element._handleInputCommit(); | 
 |       assert.isFalse(commitStub.called); | 
 |     }); | 
 |  | 
 |     test('_handleInputCommit with autocomplete hidden with' + | 
 |           'allowNonSuggestedValues', () => { | 
 |       const commitStub = sandbox.stub(element, '_commit'); | 
 |       element.allowNonSuggestedValues = true; | 
 |       element.$.suggestions.isHidden = true; | 
 |       element._handleInputCommit(); | 
 |       assert.isTrue(commitStub.called); | 
 |     }); | 
 |  | 
 |     test('_handleInputCommit with autocomplete open calls commit', () => { | 
 |       const commitStub = sandbox.stub(element, '_commit'); | 
 |       element.$.suggestions.isHidden = false; | 
 |       element._handleInputCommit(); | 
 |       assert.isTrue(commitStub.calledOnce); | 
 |     }); | 
 |  | 
 |     test('_handleInputCommit with autocomplete open calls commit' + | 
 |           'with allowNonSuggestedValues', () => { | 
 |       const commitStub = sandbox.stub(element, '_commit'); | 
 |       element.allowNonSuggestedValues = true; | 
 |       element.$.suggestions.isHidden = false; | 
 |       element._handleInputCommit(); | 
 |       assert.isTrue(commitStub.calledOnce); | 
 |     }); | 
 |  | 
 |     test('issue 8655', () => { | 
 |       function makeSuggestion(s) { return {name: s, text: s, value: s}; } | 
 |       const keydownSpy = sandbox.spy(element, '_handleKeydown'); | 
 |       element.setText('file:'); | 
 |       element._suggestions = | 
 |           [makeSuggestion('file:'), makeSuggestion('-file:')]; | 
 |       MockInteractions.pressAndReleaseKeyOn(element.$.input, 88, null, 'x'); | 
 |       // Must set the value, because the MockInteraction does not. | 
 |       element.$.input.value = 'file:x'; | 
 |       assert.isTrue(keydownSpy.calledOnce); | 
 |       MockInteractions.pressAndReleaseKeyOn(element.$.input, 13, null, 'enter'); | 
 |       assert.isTrue(keydownSpy.calledTwice); | 
 |       assert.equal(element.text, 'file:x'); | 
 |     }); | 
 |  | 
 |     suite('focus', () => { | 
 |       let commitSpy; | 
 |       let focusSpy; | 
 |  | 
 |       setup(() => { | 
 |         commitSpy = sandbox.spy(element, '_commit'); | 
 |       }); | 
 |  | 
 |       test('enter does not call focus', () => { | 
 |         element._suggestions = ['sugar bombs']; | 
 |         focusSpy = sandbox.spy(element, 'focus'); | 
 |         MockInteractions.pressAndReleaseKeyOn(element.$.input, 13, null, | 
 |             'enter'); | 
 |         flushAsynchronousOperations(); | 
 |  | 
 |         assert.isTrue(commitSpy.called); | 
 |         assert.isFalse(focusSpy.called); | 
 |         assert.equal(element._suggestions.length, 0); | 
 |       }); | 
 |  | 
 |       test('tab in input, tabComplete = true', () => { | 
 |         focusSpy = sandbox.spy(element, 'focus'); | 
 |         const commitHandler = sandbox.stub(); | 
 |         element.addEventListener('commit', commitHandler); | 
 |         element.tabComplete = true; | 
 |         element._suggestions = ['tunnel snakes drool']; | 
 |         MockInteractions.pressAndReleaseKeyOn(element.$.input, 9, null, 'tab'); | 
 |         flushAsynchronousOperations(); | 
 |  | 
 |         assert.isTrue(commitSpy.called); | 
 |         assert.isTrue(focusSpy.called); | 
 |         assert.isFalse(commitHandler.called); | 
 |         assert.equal(element._suggestions.length, 0); | 
 |       }); | 
 |  | 
 |       test('tab in input, tabComplete = false', () => { | 
 |         element._suggestions = ['sugar bombs']; | 
 |         focusSpy = sandbox.spy(element, 'focus'); | 
 |         MockInteractions.pressAndReleaseKeyOn(element.$.input, 9, null, 'tab'); | 
 |         flushAsynchronousOperations(); | 
 |  | 
 |         assert.isFalse(commitSpy.called); | 
 |         assert.isFalse(focusSpy.called); | 
 |         assert.equal(element._suggestions.length, 1); | 
 |       }); | 
 |  | 
 |       test('tab on suggestion, tabComplete = false', () => { | 
 |         element._suggestions = [{name: 'sugar bombs'}]; | 
 |         element._focused = true; | 
 |         // When tabComplete is false, do not focus. | 
 |         element.tabComplete = false; | 
 |         focusSpy = sandbox.spy(element, 'focus'); | 
 |         Polymer.dom.flush(); | 
 |         assert.isFalse(element.$.suggestions.isHidden); | 
 |  | 
 |         MockInteractions.pressAndReleaseKeyOn( | 
 |             element.$.suggestions.$$('li:first-child'), 9, null, 'tab'); | 
 |         flushAsynchronousOperations(); | 
 |         assert.isFalse(commitSpy.called); | 
 |         assert.isFalse(element._focused); | 
 |       }); | 
 |  | 
 |       test('tab on suggestion, tabComplete = true', () => { | 
 |         element._suggestions = [{name: 'sugar bombs'}]; | 
 |         element._focused = true; | 
 |         // When tabComplete is true, focus. | 
 |         element.tabComplete = true; | 
 |         focusSpy = sandbox.spy(element, 'focus'); | 
 |         Polymer.dom.flush(); | 
 |         assert.isFalse(element.$.suggestions.isHidden); | 
 |  | 
 |         MockInteractions.pressAndReleaseKeyOn( | 
 |             element.$.suggestions.$$('li:first-child'), 9, null, 'tab'); | 
 |         flushAsynchronousOperations(); | 
 |  | 
 |         assert.isTrue(commitSpy.called); | 
 |         assert.isTrue(element._focused); | 
 |       }); | 
 |  | 
 |       test('tap on suggestion commits, does not call focus', () => { | 
 |         focusSpy = sandbox.spy(element, 'focus'); | 
 |         element._focused = true; | 
 |         element._suggestions = [{name: 'first suggestion'}]; | 
 |         Polymer.dom.flush(); | 
 |         assert.isFalse(element.$.suggestions.isHidden); | 
 |         MockInteractions.tap(element.$.suggestions.$$('li:first-child')); | 
 |         flushAsynchronousOperations(); | 
 |  | 
 |         assert.isFalse(focusSpy.called); | 
 |         assert.isTrue(commitSpy.called); | 
 |         assert.isTrue(element.$.suggestions.isHidden); | 
 |       }); | 
 |     }); | 
 |  | 
 |     test('input-keydown event fired', () => { | 
 |       const listener = sandbox.spy(); | 
 |       element.addEventListener('input-keydown', listener); | 
 |       MockInteractions.pressAndReleaseKeyOn(element.$.input, 9, null, 'tab'); | 
 |       flushAsynchronousOperations(); | 
 |       assert.isTrue(listener.called); | 
 |     }); | 
 |  | 
 |     test('enter with modifier does not complete', () => { | 
 |       const handleSpy = sandbox.spy(element, '_handleKeydown'); | 
 |       const commitStub = sandbox.stub(element, '_handleInputCommit'); | 
 |       MockInteractions.pressAndReleaseKeyOn( | 
 |           element.$.input, 13, 'ctrl', 'enter'); | 
 |       assert.isTrue(handleSpy.called); | 
 |       assert.isFalse(commitStub.called); | 
 |       MockInteractions.pressAndReleaseKeyOn( | 
 |           element.$.input, 13, null, 'enter'); | 
 |       assert.isTrue(commitStub.called); | 
 |     }); | 
 |  | 
 |     suite('warnUncommitted', () => { | 
 |       let inputClassList; | 
 |       setup(() => { | 
 |         inputClassList = element.$.input.classList; | 
 |       }); | 
 |  | 
 |       test('enabled', () => { | 
 |         element.warnUncommitted = true; | 
 |         element.text = 'blah blah blah'; | 
 |         MockInteractions.blur(element.$.input); | 
 |         assert.isTrue(inputClassList.contains('warnUncommitted')); | 
 |         MockInteractions.focus(element.$.input); | 
 |         assert.isFalse(inputClassList.contains('warnUncommitted')); | 
 |       }); | 
 |  | 
 |       test('disabled', () => { | 
 |         element.warnUncommitted = false; | 
 |         element.text = 'blah blah blah'; | 
 |         MockInteractions.blur(element.$.input); | 
 |         assert.isFalse(inputClassList.contains('warnUncommitted')); | 
 |       }); | 
 |  | 
 |       test('no text', () => { | 
 |         element.warnUncommitted = true; | 
 |         element.text = ''; | 
 |         MockInteractions.blur(element.$.input); | 
 |         assert.isFalse(inputClassList.contains('warnUncommitted')); | 
 |       }); | 
 |     }); | 
 |   }); | 
 | </script> |