<!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-account-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-account-list.html">

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

<test-fixture id="basic">
  <template>
    <gr-account-list></gr-account-list>
  </template>
</test-fixture>

<script>
  class MockSuggestionsProvider {
    getSuggestions(input) {
      return Promise.resolve([]);
    }

    makeSuggestionItem(item) {
      return item;
    }
  }
  suite('gr-account-list tests', () => {
    let _nextAccountId = 0;
    const makeAccount = function() {
      const accountId = ++_nextAccountId;
      return {
        _account_id: accountId,
      };
    };
    const makeGroup = function() {
      const groupId = 'group' + (++_nextAccountId);
      return {
        id: groupId,
        _group: true,
      };
    };

    let existingAccount1;
    let existingAccount2;
    let sandbox;
    let element;
    let suggestionsProvider;

    function getChips() {
      return Polymer.dom(element.root).querySelectorAll('gr-account-chip');
    }

    setup(() => {
      sandbox = sinon.sandbox.create();
      existingAccount1 = makeAccount();
      existingAccount2 = makeAccount();

      stub('gr-rest-api-interface', {
        getConfig() { return Promise.resolve({}); },
      });
      element = fixture('basic');
      element.accounts = [existingAccount1, existingAccount2];
      suggestionsProvider = new MockSuggestionsProvider();
      element.suggestionsProvider = suggestionsProvider;
    });

    teardown(() => {
      sandbox.restore();
    });

    test('account entry only appears when editable', () => {
      element.readonly = false;
      assert.isFalse(element.$.entry.hasAttribute('hidden'));
      element.readonly = true;
      assert.isTrue(element.$.entry.hasAttribute('hidden'));
    });

    test('addition and removal of account/group chips', () => {
      flushAsynchronousOperations();
      sandbox.stub(element, '_computeRemovable').returns(true);
      // Existing accounts are listed.
      let chips = getChips();
      assert.equal(chips.length, 2);
      assert.isFalse(chips[0].classList.contains('pendingAdd'));
      assert.isFalse(chips[1].classList.contains('pendingAdd'));

      // New accounts are added to end with pendingAdd class.
      const newAccount = makeAccount();
      element._handleAdd({
        detail: {
          value: {
            account: newAccount,
          },
        },
      });
      flushAsynchronousOperations();
      chips = getChips();
      assert.equal(chips.length, 3);
      assert.isFalse(chips[0].classList.contains('pendingAdd'));
      assert.isFalse(chips[1].classList.contains('pendingAdd'));
      assert.isTrue(chips[2].classList.contains('pendingAdd'));

      // Removed accounts are taken out of the list.
      element.fire('remove', {account: existingAccount1});
      flushAsynchronousOperations();
      chips = getChips();
      assert.equal(chips.length, 2);
      assert.isFalse(chips[0].classList.contains('pendingAdd'));
      assert.isTrue(chips[1].classList.contains('pendingAdd'));

      // Invalid remove is ignored.
      element.fire('remove', {account: existingAccount1});
      element.fire('remove', {account: newAccount});
      flushAsynchronousOperations();
      chips = getChips();
      assert.equal(chips.length, 1);
      assert.isFalse(chips[0].classList.contains('pendingAdd'));

      // New groups are added to end with pendingAdd and group classes.
      const newGroup = makeGroup();
      element._handleAdd({
        detail: {
          value: {
            group: newGroup,
          },
        },
      });
      flushAsynchronousOperations();
      chips = getChips();
      assert.equal(chips.length, 2);
      assert.isTrue(chips[1].classList.contains('group'));
      assert.isTrue(chips[1].classList.contains('pendingAdd'));

      // Removed groups are taken out of the list.
      element.fire('remove', {account: newGroup});
      flushAsynchronousOperations();
      chips = getChips();
      assert.equal(chips.length, 1);
      assert.isFalse(chips[0].classList.contains('pendingAdd'));
    });

    test('_getSuggestions uses filter correctly', done => {
      const originalSuggestions = [
        {
          email: 'abc@example.com',
          text: 'abcd',
          _account_id: 3,
        },
        {
          email: 'qwe@example.com',
          text: 'qwer',
          _account_id: 1,
        },
        {
          email: 'xyz@example.com',
          text: 'aaaaa',
          _account_id: 25,
        },
      ];
      sandbox.stub(suggestionsProvider, 'getSuggestions')
          .returns(Promise.resolve(originalSuggestions));
      sandbox.stub(suggestionsProvider, 'makeSuggestionItem', suggestion => {
        return {
          name: suggestion.email,
          value: suggestion._account_id,
        };
      });


      element._getSuggestions().then(suggestions => {
        // Default is no filtering.
        assert.equal(suggestions.length, 3);

        // Set up filter that only accepts suggestion1.
        const accountId = originalSuggestions[0]._account_id;
        element.filter = function(suggestion) {
          return suggestion._account_id === accountId;
        };

        element._getSuggestions().then(suggestions => {
          assert.deepEqual(suggestions,
              [{name: originalSuggestions[0].email,
                value: originalSuggestions[0]._account_id}]);
        }).then(done);
      });
    });

    test('_computeChipClass', () => {
      const account = makeAccount();
      assert.equal(element._computeChipClass(account), '');
      account._pendingAdd = true;
      assert.equal(element._computeChipClass(account), 'pendingAdd');
      account._group = true;
      assert.equal(element._computeChipClass(account), 'group pendingAdd');
      account._pendingAdd = false;
      assert.equal(element._computeChipClass(account), 'group');
    });

    test('_computeRemovable', () => {
      const newAccount = makeAccount();
      newAccount._pendingAdd = true;
      element.readonly = false;
      element.removableValues = [];
      assert.isFalse(element._computeRemovable(existingAccount1, false));
      assert.isTrue(element._computeRemovable(newAccount, false));


      element.removableValues = [existingAccount1];
      assert.isTrue(element._computeRemovable(existingAccount1, false));
      assert.isTrue(element._computeRemovable(newAccount, false));
      assert.isFalse(element._computeRemovable(existingAccount2, false));

      element.readonly = true;
      assert.isFalse(element._computeRemovable(existingAccount1, true));
      assert.isFalse(element._computeRemovable(newAccount, true));
    });

    test('submitEntryText', () => {
      element.allowAnyInput = true;
      flushAsynchronousOperations();

      const getTextStub = sandbox.stub(element.$.entry, 'getText');
      getTextStub.onFirstCall().returns('');
      getTextStub.onSecondCall().returns('test');
      getTextStub.onThirdCall().returns('test@test');

      // When entry is empty, return true.
      const clearStub = sandbox.stub(element.$.entry, 'clear');
      assert.isTrue(element.submitEntryText());
      assert.isFalse(clearStub.called);

      // When entry is invalid, return false.
      assert.isFalse(element.submitEntryText());
      assert.isFalse(clearStub.called);

      // When entry is valid, return true and clear text.
      assert.isTrue(element.submitEntryText());
      assert.isTrue(clearStub.called);
      assert.equal(element.additions()[0].account.email, 'test@test');
    });

    test('additions returns sanitized new accounts and groups', () => {
      assert.equal(element.additions().length, 0);

      const newAccount = makeAccount();
      element._handleAdd({
        detail: {
          value: {
            account: newAccount,
          },
        },
      });
      const newGroup = makeGroup();
      element._handleAdd({
        detail: {
          value: {
            group: newGroup,
          },
        },
      });

      assert.deepEqual(element.additions(), [
        {
          account: {
            _account_id: newAccount._account_id,
            _pendingAdd: true,
          },
        },
        {
          group: {
            id: newGroup.id,
            _group: true,
            _pendingAdd: true,
          },
        },
      ]);
    });

    test('large group confirmations', () => {
      assert.isNull(element.pendingConfirmation);
      assert.deepEqual(element.additions(), []);

      const group = makeGroup();
      const reviewer = {
        group,
        count: 10,
        confirm: true,
      };
      element._handleAdd({
        detail: {
          value: reviewer,
        },
      });

      assert.deepEqual(element.pendingConfirmation, reviewer);
      assert.deepEqual(element.additions(), []);

      element.confirmGroup(group);
      assert.isNull(element.pendingConfirmation);
      assert.deepEqual(element.additions(), [
        {
          group: {
            id: group.id,
            _group: true,
            _pendingAdd: true,
            confirmed: true,
          },
        },
      ]);
    });

    test('removeAccount fails if account is not removable', () => {
      element.readonly = true;
      const acct = makeAccount();
      element.accounts = [acct];
      element._removeAccount(acct);
      assert.equal(element.accounts.length, 1);
    });

    test('max-count', () => {
      element.maxCount = 1;
      const acct = makeAccount();
      element._handleAdd({
        detail: {
          value: {
            account: acct,
          },
        },
      });
      flushAsynchronousOperations();
      assert.isTrue(element.$.entry.hasAttribute('hidden'));
    });

    test('enter text calls suggestions provider', done => {
      const suggestions = [
        {
          email: 'abc@example.com',
          text: 'abcd',
        },
        {
          email: 'qwe@example.com',
          text: 'qwer',
        },
      ];
      const getSuggestionsStub =
          sandbox.stub(suggestionsProvider, 'getSuggestions')
              .returns(Promise.resolve(suggestions));

      const makeSuggestionItemStub =
          sandbox.stub(suggestionsProvider, 'makeSuggestionItem', item => item);

      const input = element.$.entry.$.input;

      input.text = 'newTest';
      MockInteractions.focus(input.$.input);
      input.noDebounce = true;
      flushAsynchronousOperations();
      flush(() => {
        assert.isTrue(getSuggestionsStub.calledOnce);
        assert.equal(getSuggestionsStub.lastCall.args[0], 'newTest');
        assert.equal(makeSuggestionItemStub.getCalls().length, 2);
        done();
      });
    });

    suite('allowAnyInput', () => {
      setup(() => {
        element.allowAnyInput = true;
      });

      test('adds emails', () => {
        const accountLen = element.accounts.length;
        element._handleAdd({detail: {value: 'test@test'}});
        assert.equal(element.accounts.length, accountLen + 1);
        assert.equal(element.accounts[accountLen].email, 'test@test');
      });

      test('toasts on invalid email', () => {
        const toastHandler = sandbox.stub();
        element.addEventListener('show-alert', toastHandler);
        element._handleAdd({detail: {value: 'test'}});
        assert.isTrue(toastHandler.called);
      });
    });

    test('_accountMatches', () => {
      const acct = makeAccount();

      assert.isTrue(element._accountMatches(acct, acct));
      acct.email = 'test';
      assert.isTrue(element._accountMatches(acct, acct));
      assert.isTrue(element._accountMatches({email: 'test'}, acct));

      assert.isFalse(element._accountMatches({}, acct));
      assert.isFalse(element._accountMatches({email: 'test2'}, acct));
      assert.isFalse(element._accountMatches({_account_id: -1}, acct));
    });

    suite('keyboard interactions', () => {
      test('backspace at text input start removes last account', done => {
        const input = element.$.entry.$.input;
        sandbox.stub(input, '_updateSuggestions');
        sandbox.stub(element, '_computeRemovable').returns(true);
        flush(() => {
          // Next line is a workaround for Firefix not moving cursor
          // on input field update
          assert.equal(
              element._getNativeInput(input.$.input).selectionStart, 0);
          input.text = 'test';
          MockInteractions.focus(input.$.input);
          flushAsynchronousOperations();
          assert.equal(element.accounts.length, 2);
          MockInteractions.pressAndReleaseKeyOn(
              element._getNativeInput(input.$.input), 8); // Backspace
          assert.equal(element.accounts.length, 2);
          input.text = '';
          MockInteractions.pressAndReleaseKeyOn(
              element._getNativeInput(input.$.input), 8); // Backspace
          flushAsynchronousOperations();
          assert.equal(element.accounts.length, 1);
          done();
        });
      });

      test('arrow key navigation', done => {
        const input = element.$.entry.$.input;
        input.text = '';
        element.accounts = [makeAccount(), makeAccount()];
        flush(() => {
          MockInteractions.focus(input.$.input);
          flushAsynchronousOperations();
          const chips = element.accountChips;
          const chipsOneSpy = sandbox.spy(chips[1], 'focus');
          MockInteractions.pressAndReleaseKeyOn(input.$.input, 37); // Left
          assert.isTrue(chipsOneSpy.called);
          const chipsZeroSpy = sandbox.spy(chips[0], 'focus');
          MockInteractions.pressAndReleaseKeyOn(chips[1], 37); // Left
          assert.isTrue(chipsZeroSpy.called);
          MockInteractions.pressAndReleaseKeyOn(chips[0], 37); // Left
          assert.isTrue(chipsZeroSpy.calledOnce);
          MockInteractions.pressAndReleaseKeyOn(chips[0], 39); // Right
          assert.isTrue(chipsOneSpy.calledTwice);
          done();
        });
      });

      test('delete', done => {
        element.accounts = [makeAccount(), makeAccount()];
        flush(() => {
          const focusSpy = sandbox.spy(element.accountChips[1], 'focus');
          const removeSpy = sandbox.spy(element, '_removeAccount');
          MockInteractions.pressAndReleaseKeyOn(
              element.accountChips[0], 8); // Backspace
          assert.isTrue(focusSpy.called);
          assert.isTrue(removeSpy.calledOnce);

          MockInteractions.pressAndReleaseKeyOn(
              element.accountChips[1], 46); // Delete
          assert.isTrue(removeSpy.calledTwice);
          done();
        });
      });
    });
  });
</script>
