<!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-settings-view</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-settings-view.html">

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

<test-fixture id="basic">
  <template>
    <gr-settings-view></gr-settings-view>
  </template>
</test-fixture>

<test-fixture id="blank">
  <template>
    <div></div>
  </template>
</test-fixture>

<script>
  suite('gr-settings-view tests', () => {
    let element;
    let account;
    let preferences;
    let config;
    let sandbox;

    function valueOf(title, fieldsetid) {
      const sections = element.$[fieldsetid].querySelectorAll('section');
      let titleEl;
      for (let i = 0; i < sections.length; i++) {
        titleEl = sections[i].querySelector('.title');
        if (titleEl.textContent.trim() === title) {
          return sections[i].querySelector('.value');
        }
      }
    }

    // Because deepEqual isn't behaving in Safari.
    function assertMenusEqual(actual, expected) {
      assert.equal(actual.length, expected.length);
      for (let i = 0; i < actual.length; i++) {
        assert.equal(actual[i].name, expected[i].name);
        assert.equal(actual[i].url, expected[i].url);
      }
    }

    function stubAddAccountEmail(statusCode) {
      return sandbox.stub(element.$.restAPI, 'addAccountEmail',
          () => { return Promise.resolve({status: statusCode}); });
    }

    setup(done => {
      sandbox = sinon.sandbox.create();
      account = {
        _account_id: 123,
        name: 'user name',
        email: 'user@email',
        username: 'user username',
        registered: '2000-01-01 00:00:00.000000000',
      };
      preferences = {
        changes_per_page: 25,
        date_format: 'UK',
        time_format: 'HHMM_12',
        diff_view: 'UNIFIED_DIFF',
        email_strategy: 'ENABLED',
        email_format: 'HTML_PLAINTEXT',
        size_bar_in_change_table: true,

        my: [
          {url: '/first/url', name: 'first name', target: '_blank'},
          {url: '/second/url', name: 'second name', target: '_blank'},
        ],
        change_table: [],
      };
      config = {auth: {editable_account_fields: []}};

      stub('gr-rest-api-interface', {
        getLoggedIn() { return Promise.resolve(true); },
        getAccount() { return Promise.resolve(account); },
        getPreferences() { return Promise.resolve(preferences); },
        getWatchedProjects() {
          return Promise.resolve([]);
        },
        getAccountEmails() { return Promise.resolve(); },
        getConfig() { return Promise.resolve(config); },
        getAccountGroups() { return Promise.resolve([]); },
      });
      element = fixture('basic');

      // Allow the element to render.
      element._loadingPromise.then(done);
    });

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

    test('calls the title-change event', () => {
      const titleChangedStub = sandbox.stub();

      // Create a new view.
      const newElement = document.createElement('gr-settings-view');
      newElement.addEventListener('title-change', titleChangedStub);

      // Attach it to the fixture.
      const blank = fixture('blank');
      blank.appendChild(newElement);

      Polymer.dom.flush();

      assert.isTrue(titleChangedStub.called);
      assert.equal(titleChangedStub.getCall(0).args[0].detail.title,
          'Settings');
    });

    test('user preferences', done => {
      // Rendered with the expected preferences selected.
      assert.equal(valueOf('Changes per page', 'preferences')
          .firstElementChild.bindValue, preferences.changes_per_page);
      assert.equal(valueOf('Date/time format', 'preferences')
          .firstElementChild.bindValue, preferences.date_format);
      assert.equal(valueOf('Date/time format', 'preferences')
          .lastElementChild.bindValue, preferences.time_format);
      assert.equal(valueOf('Email notifications', 'preferences')
          .firstElementChild.bindValue, preferences.email_strategy);
      assert.equal(valueOf('Email format', 'preferences')
          .firstElementChild.bindValue, preferences.email_format);
      assert.equal(valueOf('Diff view', 'preferences')
          .firstElementChild.bindValue, preferences.diff_view);
      assert.equal(valueOf('Show size bars in file list', 'preferences')
          .firstElementChild.checked, true);
      assert.equal(valueOf('Publish comments on push', 'preferences')
          .firstElementChild.checked, false);
      assert.equal(valueOf(
          'Set new changes to "work in progress" by default', 'preferences')
          .firstElementChild.checked, false);
      assert.equal(valueOf(
          'Insert Signed-off-by Footer For Inline Edit Changes', 'preferences')
          .firstElementChild.checked, false);

      assert.isFalse(element._prefsChanged);
      assert.isFalse(element._menuChanged);

      // Change the diff view element.
      const diffSelect = valueOf('Diff view', 'preferences').firstElementChild;
      diffSelect.bindValue = 'SIDE_BY_SIDE';

      const publishOnPush =
          valueOf('Publish comments on push', 'preferences').firstElementChild;
      diffSelect.fire('change');

      MockInteractions.tap(publishOnPush);

      assert.isTrue(element._prefsChanged);
      assert.isFalse(element._menuChanged);

      stub('gr-rest-api-interface', {
        savePreferences(prefs) {
          assert.equal(prefs.diff_view, 'SIDE_BY_SIDE');
          assertMenusEqual(prefs.my, preferences.my);
          assert.equal(prefs.publish_comments_on_push, true);
          return Promise.resolve();
        },
      });

      // Save the change.
      element._handleSavePreferences().then(() => {
        assert.isFalse(element._prefsChanged);
        assert.isFalse(element._menuChanged);
        done();
      });
    });

    test('publish comments on push', done => {
      const publishCommentsOnPush =
        valueOf('Publish comments on push', 'preferences').firstElementChild;
      MockInteractions.tap(publishCommentsOnPush);

      assert.isFalse(element._menuChanged);
      assert.isTrue(element._prefsChanged);

      stub('gr-rest-api-interface', {
        savePreferences(prefs) {
          assert.equal(prefs.publish_comments_on_push, true);
          return Promise.resolve();
        },
      });

      // Save the change.
      element._handleSavePreferences().then(() => {
        assert.isFalse(element._prefsChanged);
        assert.isFalse(element._menuChanged);
        done();
      });
    });

    test('set new changes work-in-progress', done => {
      const newChangesWorkInProgress =
        valueOf('Set new changes to "work in progress" by default',
            'preferences').firstElementChild;
      MockInteractions.tap(newChangesWorkInProgress);

      assert.isFalse(element._menuChanged);
      assert.isTrue(element._prefsChanged);

      stub('gr-rest-api-interface', {
        savePreferences(prefs) {
          assert.equal(prefs.work_in_progress_by_default, true);
          return Promise.resolve();
        },
      });

      // Save the change.
      element._handleSavePreferences().then(() => {
        assert.isFalse(element._prefsChanged);
        assert.isFalse(element._menuChanged);
        done();
      });
    });

    test('menu', done => {
      assert.isFalse(element._menuChanged);
      assert.isFalse(element._prefsChanged);

      assertMenusEqual(element._localMenu, preferences.my);

      const menu = element.$.menu.firstElementChild;
      let tableRows = Polymer.dom(menu.root).querySelectorAll('tbody tr');
      assert.equal(tableRows.length, preferences.my.length);

      // Add a menu item:
      element.splice('_localMenu', 1, 0, {name: 'foo', url: 'bar', target: ''});
      Polymer.dom.flush();

      tableRows = Polymer.dom(menu.root).querySelectorAll('tbody tr');
      assert.equal(tableRows.length, preferences.my.length + 1);

      assert.isTrue(element._menuChanged);
      assert.isFalse(element._prefsChanged);

      stub('gr-rest-api-interface', {
        savePreferences(prefs) {
          assertMenusEqual(prefs.my, element._localMenu);
          return Promise.resolve();
        },
      });

      element._handleSaveMenu().then(() => {
        assert.isFalse(element._menuChanged);
        assert.isFalse(element._prefsChanged);
        assertMenusEqual(element.prefs.my, element._localMenu);
        done();
      });
    });

    test('add email validation', () => {
      assert.isFalse(element._isNewEmailValid('invalid email'));
      assert.isTrue(element._isNewEmailValid('vaguely@valid.email'));

      assert.isFalse(
          element._computeAddEmailButtonEnabled('invalid email'), true);
      assert.isFalse(
          element._computeAddEmailButtonEnabled('vaguely@valid.email', true));
      assert.isTrue(
          element._computeAddEmailButtonEnabled('vaguely@valid.email', false));
    });

    test('add email does not save invalid', () => {
      const addEmailStub = stubAddAccountEmail(201);

      assert.isFalse(element._addingEmail);
      assert.isNotOk(element._lastSentVerificationEmail);
      element._newEmail = 'invalid email';

      element._handleAddEmailButton();

      assert.isFalse(element._addingEmail);
      assert.isFalse(addEmailStub.called);
      assert.isNotOk(element._lastSentVerificationEmail);

      assert.isFalse(addEmailStub.called);
    });

    test('add email does save valid', done => {
      const addEmailStub = stubAddAccountEmail(201);

      assert.isFalse(element._addingEmail);
      assert.isNotOk(element._lastSentVerificationEmail);
      element._newEmail = 'valid@email.com';

      element._handleAddEmailButton();

      assert.isTrue(element._addingEmail);
      assert.isTrue(addEmailStub.called);

      assert.isTrue(addEmailStub.called);
      addEmailStub.lastCall.returnValue.then(() => {
        assert.isOk(element._lastSentVerificationEmail);
        done();
      });
    });

    test('add email does not set last-email if error', done => {
      const addEmailStub = stubAddAccountEmail(500);

      assert.isNotOk(element._lastSentVerificationEmail);
      element._newEmail = 'valid@email.com';

      element._handleAddEmailButton();

      assert.isTrue(addEmailStub.called);
      addEmailStub.lastCall.returnValue.then(() => {
        assert.isNotOk(element._lastSentVerificationEmail);
        done();
      });
    });

    test('emails are loaded without emailToken', () => {
      sandbox.stub(element.$.emailEditor, 'loadData');
      element.params = {};
      element.attached();
      assert.isTrue(element.$.emailEditor.loadData.calledOnce);
    });

    test('_handleSaveChangeTable', () => {
      let newColumns = ['Owner', 'Project', 'Branch'];
      element._localChangeTableColumns = newColumns.slice(0);
      element._showNumber = false;
      const cloneStub = sandbox.stub(element, '_cloneChangeTableColumns');
      element._handleSaveChangeTable();
      assert.isTrue(cloneStub.calledOnce);
      assert.deepEqual(element.prefs.change_table, newColumns);
      assert.isNotOk(element.prefs.legacycid_in_change_table);

      newColumns = ['Size'];
      element._localChangeTableColumns = newColumns;
      element._showNumber = true;
      element._handleSaveChangeTable();
      assert.isTrue(cloneStub.calledTwice);
      assert.deepEqual(element.prefs.change_table, newColumns);
      assert.isTrue(element.prefs.legacycid_in_change_table);
    });

    test('reset menu item back to default', done => {
      const originalMenu = {
        my: [
          {url: '/first/url', name: 'first name', target: '_blank'},
          {url: '/second/url', name: 'second name', target: '_blank'},
          {url: '/third/url', name: 'third name', target: '_blank'},
        ],
      };

      stub('gr-rest-api-interface', {
        getDefaultPreferences() { return Promise.resolve(originalMenu); },
      });

      const updatedMenu = [
        {url: '/first/url', name: 'first name', target: '_blank'},
        {url: '/second/url', name: 'second name', target: '_blank'},
        {url: '/third/url', name: 'third name', target: '_blank'},
        {url: '/fourth/url', name: 'fourth name', target: '_blank'},
      ];

      element.set('_localMenu', updatedMenu);

      element._handleResetMenuButton().then(() => {
        assertMenusEqual(element._localMenu, originalMenu.my);
        done();
      });
    });

    test('test that reset button is called', () => {
      const overlayOpen = sandbox.stub(element, '_handleResetMenuButton');

      MockInteractions.tap(element.$.resetMenu);

      assert.isTrue(overlayOpen.called);
    });

    suite('_getFilterDocsLink', () => {
      test('with http: docs base URL', () => {
        const base = 'http://example.com/';
        const result = element._getFilterDocsLink(base);
        assert.equal(result, 'http://example.com/user-notify.html');
      });

      test('with http: docs base URL without slash', () => {
        const base = 'http://example.com';
        const result = element._getFilterDocsLink(base);
        assert.equal(result, 'http://example.com/user-notify.html');
      });

      test('with https: docs base URL', () => {
        const base = 'https://example.com/';
        const result = element._getFilterDocsLink(base);
        assert.equal(result, 'https://example.com/user-notify.html');
      });

      test('without docs base URL', () => {
        const result = element._getFilterDocsLink(null);
        assert.equal(result, 'https://gerrit-review.googlesource.com/' +
            'Documentation/user-notify.html');
      });

      test('ignores non HTTP links', () => {
        const base = 'javascript://alert("evil");';
        const result = element._getFilterDocsLink(base);
        assert.equal(result, 'https://gerrit-review.googlesource.com/' +
            'Documentation/user-notify.html');
      });
    });

    suite('when email verification token is provided', () => {
      let resolveConfirm;

      setup(() => {
        sandbox.stub(element.$.emailEditor, 'loadData');
        sandbox.stub(element.$.restAPI, 'confirmEmail', () => {
          return new Promise(resolve => { resolveConfirm = resolve; });
        });
        element.params = {emailToken: 'foo'};
        element.attached();
      });

      test('it is used to confirm email via rest API', () => {
        assert.isTrue(element.$.restAPI.confirmEmail.calledOnce);
        assert.isTrue(element.$.restAPI.confirmEmail.calledWith('foo'));
      });

      test('emails are not loaded initially', () => {
        assert.isFalse(element.$.emailEditor.loadData.called);
      });

      test('user emails are loaded after email confirmed', done => {
        element._loadingPromise.then(() => {
          assert.isTrue(element.$.emailEditor.loadData.calledOnce);
          done();
        });
        resolveConfirm();
      });

      test('show-alert is fired when email is confirmed', done => {
        sandbox.spy(element, 'fire');
        element._loadingPromise.then(() => {
          assert.isTrue(
              element.fire.calledWith('show-alert', {message: 'bar'}));
          done();
        });
        resolveConfirm('bar');
      });
    });
  });
</script>
