<!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-group-members</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="../../../test/common-test-setup.html"/>
<link rel="import" href="gr-group-members.html">

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

<test-fixture id="basic">
  <template>
    <gr-group-members></gr-group-members>
  </template>
</test-fixture>

<script>
  suite('gr-group-members tests', () => {
    let element;
    let sandbox;
    let groups;
    let groupMembers;
    let includedGroups;

    setup(() => {
      sandbox = sinon.sandbox.create();
      groups = {
        name: 'Administrators',
        owner: 'Administrators',
        group_id: 1,
      };

      groupMembers = [
        {
          _account_id: 1000097,
          name: 'Jane Roe',
          email: 'jane.roe@example.com',
          username: 'jane',
        },
        {
          _account_id: 1000096,
          name: 'Test User',
          email: 'john.doe@example.com',
        },
        {
          _account_id: 1000095,
          name: 'Gerrit',
        },
        {
          _account_id: 1000098,
        },
      ];

      includedGroups = [{
        url: 'https://group/url',
        options: {},
        id: 'testId',
        name: 'testName',
      },
      {
        url: '/group/url',
        options: {},
        id: 'testId2',
        name: 'testName2',
      },
      {
        url: '#/group/url',
        options: {},
        id: 'testId3',
        name: 'testName3',
      },
      ];

      stub('gr-rest-api-interface', {
        getSuggestedAccounts(input) {
          if (input.startsWith('test')) {
            return Promise.resolve([
              {
                _account_id: 1000096,
                name: 'test-account',
                email: 'test.account@example.com',
                username: 'test123',
              },
              {
                _account_id: 1001439,
                name: 'test-admin',
                email: 'test.admin@example.com',
                username: 'test_admin',
              },
              {
                _account_id: 1001439,
                name: 'test-git',
                username: 'test_git',
              },
            ]);
          } else {
            return Promise.resolve({});
          }
        },
        getLoggedIn() { return Promise.resolve(true); },
        getConfig() {
          return Promise.resolve();
        },
        getGroupConfig() {
          return Promise.resolve(groups);
        },
        getGroupMembers() {
          return Promise.resolve(groupMembers);
        },
        getIsGroupOwner() {
          return Promise.resolve(true);
        },
        getIncludedGroup() {
          return Promise.resolve(includedGroups);
        },
        getAccountCapabilities() {
          return Promise.resolve();
        },
      });
      element = fixture('basic');
      sandbox.stub(element, 'getBaseUrl').returns('https://test/site');
      element.groupId = 1;
      return element._loadGroupDetails();
    });

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

    test('_includedGroups', () => {
      assert.equal(element._includedGroups.length, 3);
      assert.equal(Polymer.dom(element.root)
          .querySelectorAll('.nameColumn a')[0].href, includedGroups[0].url);
      assert.equal(Polymer.dom(element.root)
          .querySelectorAll('.nameColumn a')[1].href,
          'https://test/site/group/url');
      assert.equal(Polymer.dom(element.root)
          .querySelectorAll('.nameColumn a')[2].href,
          'https://test/site/group/url');
    });

    test('save correctly', () => {
      element._groupOwner = true;

      const memberName = 'test-admin';

      const saveStub = sandbox.stub(element.$.restAPI, 'saveGroupMembers',
          () => {
            return Promise.resolve({});
          });

      const button = Polymer.dom(element.root).querySelector('gr-button');

      assert.isTrue(button.hasAttribute('disabled'));

      element.$.groupMemberSearchInput.text = memberName;
      element.$.groupMemberSearchInput.value = 1234;

      assert.isFalse(button.hasAttribute('disabled'));

      return element._handleSavingGroupMember().then(() => {
        assert.isTrue(button.hasAttribute('disabled'));
        assert.isFalse(element.$.Title.classList.contains('edited'));
        assert.isTrue(saveStub.lastCall.calledWithExactly('Administrators',
            1234));
      });
    });

    test('add included group 404 shows helpful error text', () => {
      element._groupOwner = true;

      const memberName = 'bad-name';
      const alertStub = sandbox.stub();
      element.addEventListener('show-alert', alertStub);

      sandbox.stub(element.$.restAPI, 'saveGroupMembers',
          () => Promise.reject({status: 404}));

      element.$.groupMemberSearchInput.text = memberName;
      element.$.groupMemberSearchInput.value = 1234;

      return element._handleSavingIncludedGroups().then(() => {
        assert.isTrue(alertStub.called);
      });
    });

    test('_getAccountSuggestions empty', () => {
      return element._getAccountSuggestions('nonexistent').then(accounts => {
        assert.equal(accounts.length, 0);
      });
    });

    test('_getAccountSuggestions non-empty', () => {
      return element._getAccountSuggestions('test-').then(accounts => {
        assert.equal(accounts.length, 3);
        assert.equal(accounts[0].name,
            'test-account <test.account@example.com>');
        assert.equal(accounts[1].name, 'test-admin <test.admin@example.com>');
        assert.equal(accounts[2].name, 'test-git');
      });
    });

    test('_computeHideItemClass returns string for admin', () => {
      const admin = true;
      const owner = false;
      assert.equal(element._computeHideItemClass(owner, admin), '');
    });

    test('_computeHideItemClass returns hideItem for admin and owner', () => {
      const admin = false;
      const owner = false;
      assert.equal(element._computeHideItemClass(owner, admin), 'canModify');
    });

    test('_computeHideItemClass returns string for owner', () => {
      const admin = false;
      const owner = true;
      assert.equal(element._computeHideItemClass(owner, admin), '');
    });

    test('delete member', () => {
      const deletelBtns = Polymer.dom(element.root)
          .querySelectorAll('.deleteButton');
      MockInteractions.tap(deletelBtns[0]);
      assert.equal(element._itemId, '1000097');
      assert.equal(element._itemName, 'jane');
      MockInteractions.tap(deletelBtns[1]);
      assert.equal(element._itemId, '1000096');
      assert.equal(element._itemName, 'Test User');
      MockInteractions.tap(deletelBtns[2]);
      assert.equal(element._itemId, '1000095');
      assert.equal(element._itemName, 'Gerrit');
      MockInteractions.tap(deletelBtns[3]);
      assert.equal(element._itemId, '1000098');
      assert.equal(element._itemName, '1000098');
    });
  });
</script>
