<!DOCTYPE html>
<!--
Copyright (C) 2017 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-autocomplete-dropdown</title>

<script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
<script src="../../../bower_components/web-component-tester/browser.js"></script>

<link rel="import" href="gr-autocomplete-dropdown.html">
<link rel="import" href="../../../bower_components/iron-test-helpers/iron-test-helpers.html">

<script>void(0);</script>

<test-fixture id="basic">
  <template>
    <gr-autocomplete-dropdown id="dropdown"></gr-autocomplete-dropdown>
  </template>
</test-fixture>

<test-fixture id="move">
  <template>
    <gr-autocomplete-dropdown id="dropdown" move-to-root></gr-autocomplete-dropdown>
  </template>
</test-fixture>

<script>
  suite('gr-autocomplete-dropdown', () => {
    let element;
    let sandbox;

    setup(() => {
      sandbox = sinon.sandbox.create();
      element = fixture('basic');
      element.open();
      element.suggestions = [
        {dataValue: 'test value 1', name: 'test name 1', text: 1},
        {dataValue: 'test value 2', name: 'test name 2', text: 2}];
    });

    teardown(() => {
      sandbox.restore();
      if (element.isOpen) element.close();
    });

    test('dropdown has not been moved from text fixture to the body', () => {
      assert.equal(Polymer.dom(document.root)
          .querySelectorAll('gr-autocomplete-dropdown').length, 1);
      const dropdown = Polymer.dom(document.root)
          .querySelector('gr-autocomplete-dropdown');
      assert.isOk(dropdown);
      assert.notDeepEqual(dropdown.parentElement,
          Polymer.dom(document.root).querySelector('body'));
    });

    test('escape key', () => {
      const listener = sandbox.spy();
      element.hidden = false;
      element.addEventListener('dropdown-closed', listener);
      const closeSpy = sandbox.spy(element, 'close');
      MockInteractions.pressAndReleaseKeyOn(element, 27);
      flushAsynchronousOperations();
      assert.isTrue(listener.called);
      assert.isTrue(closeSpy.called);
      assert.isTrue(element.hidden);
    });

    test('tab key', () => {
      const handleTabSpy = sandbox.spy(element, '_handleTab');
      const itemSelectedStub = sandbox.stub();
      element.addEventListener('item-selected', itemSelectedStub);
      MockInteractions.pressAndReleaseKeyOn(element, 9);
      assert.isTrue(handleTabSpy.called);
      assert.equal(element.$.cursor.index, 0);
      assert.isTrue(itemSelectedStub.called);
      assert.deepEqual(itemSelectedStub.lastCall.args[0].detail, {
        trigger: 'tab',
        selected: element.getCursorTarget(),
      });
    });

    test('enter key', () => {
      const handleEnterSpy = sandbox.spy(element, '_handleEnter');
      const itemSelectedStub = sandbox.stub();
      element.addEventListener('item-selected', itemSelectedStub);
      MockInteractions.pressAndReleaseKeyOn(element, 13);
      assert.isTrue(handleEnterSpy.called);
      assert.equal(element.$.cursor.index, 0);
      assert.deepEqual(itemSelectedStub.lastCall.args[0].detail, {
        trigger: 'enter',
        selected: element.getCursorTarget(),
      });
    });

    test('down key', () => {
      element.hidden = true;
      const nextSpy = sandbox.spy(element.$.cursor, 'next');
      MockInteractions.pressAndReleaseKeyOn(element, 40);
      assert.isFalse(nextSpy.called);
      assert.equal(element.$.cursor.index, 0);
      element.hidden = false;
      MockInteractions.pressAndReleaseKeyOn(element, 40);
      assert.isTrue(nextSpy.called);
      assert.equal(element.$.cursor.index, 1);
    });

    test('up key', () => {
      element.hidden = true;
      const prevSpy = sandbox.spy(element.$.cursor, 'previous');
      MockInteractions.pressAndReleaseKeyOn(element, 38);
      assert.isFalse(prevSpy.called);
      assert.equal(element.$.cursor.index, 0);
      element.hidden = false;
      element.$.cursor.setCursorAtIndex(1);
      assert.equal(element.$.cursor.index, 1);
      MockInteractions.pressAndReleaseKeyOn(element, 38);
      assert.isTrue(prevSpy.called);
      assert.equal(element.$.cursor.index, 0);
    });

    test('tapping selects item', () => {
      const itemSelectedStub = sandbox.stub();
      element.addEventListener('item-selected', itemSelectedStub);

      MockInteractions.tap(element.$.suggestions.querySelectorAll('li')[1]);
      flushAsynchronousOperations();
      assert.deepEqual(itemSelectedStub.lastCall.args[0].detail, {
        trigger: 'tap',
        selected: element.$.suggestions.querySelectorAll('li')[1],
      });
    });

    test('updated suggestions resets cursor stops', () => {
      resetStopsSpy = sandbox.spy(element, '_resetCursorStops');
      element.suggestions = [];
      assert.isTrue(resetStopsSpy.called);
    });
  });

  suite('gr-autocomplete-dropdown to root', () => {
    let element;
    let sandbox;

    setup(() => {
      sandbox = sinon.sandbox.create();
      fixture('move').open();
      // The element was moved to the body, so look for it there.
      element = Polymer.dom(document.root)
        .querySelector('gr-autocomplete-dropdown');
      element.suggestions = [
        {dataValue: 'test value 1', name: 'test name 1', text: 1},
        {dataValue: 'test value 2', name: 'test name 2', text: 2}];
    });

    teardown(() => {
      sandbox.restore();
      if (!element.hidden) element.close();
    });

    test('dropdown has been moved from the text fixture to the body', () => {
      assert.equal(Polymer.dom(document.root)
          .querySelectorAll('gr-autocomplete-dropdown').length, 1);
      const dropdown = Polymer.dom(document.root)
        .querySelector('gr-autocomplete-dropdown');
      assert.isOk(dropdown);
      assert.deepEqual(dropdown.parentElement, Polymer.dom(document.root)
          .querySelector('body'));
    });

    test('closing removes from body and adding adds to body', () => {
      element.close();
      assert.equal(Polymer.dom(document.root)
          .querySelectorAll('gr-autocomplete-dropdown').length, 0);
      element.open();
      assert.equal(Polymer.dom(document.root)
          .querySelectorAll('gr-autocomplete-dropdown').length, 1);
    });

    test('setPosition', () => {
      const top = '10px';
      const left = '20px';
      element.setPosition(top, left);
      assert.equal(getComputedStyle(element).top, top);
      assert.equal(getComputedStyle(element).left, left);
    });

    test('getCurrentText', () => {
      assert.equal(element.getCurrentText(), 'test value 1');
    });
  });
</script>
