<!DOCTYPE html>
<!--
Copyright (C) 2015 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-reply-dialog</title>

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

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

<test-fixture id="basic">
  <template>
    <gr-reply-dialog></gr-reply-dialog>
  </template>
</test-fixture>

<script>
  suite('gr-reply-dialog tests', function() {
    var element;
    var changeNum;
    var patchNum;

    var sandbox;
    var getDraftCommentStub;
    var setDraftCommentStub;
    var eraseDraftCommentStub;

    setup(function() {
      sandbox = sinon.sandbox.create();

      changeNum = 42;
      patchNum = 1;

      stub('gr-rest-api-interface', {
        getAccount: function() { return Promise.resolve({}); },
      });

      element = fixture('basic');
      element.change = { _number: changeNum };
      element.patchNum = patchNum;
      element.labels = {
        Verified: {
          values: {
            '-1': 'Fails',
            ' 0': 'No score',
            '+1': 'Verified'
          },
          default_value: 0
        },
        'Code-Review': {
          values: {
            '-2': 'Do not submit',
            '-1': 'I would prefer that you didn\'t submit this',
            ' 0': 'No score',
            '+1': 'Looks good to me, but someone else must approve',
            '+2': 'Looks good to me, approved'
          },
          default_value: 0
        }
      };
      element.permittedLabels = {
        'Code-Review': [
          '-1',
          ' 0',
          '+1'
        ],
        Verified: [
          '-1',
          ' 0',
          '+1'
        ]
      };
      element.serverConfig = {};

      getDraftCommentStub = sandbox.stub(element.$.storage, 'getDraftComment');
      setDraftCommentStub = sandbox.stub(element.$.storage, 'setDraftComment');
      eraseDraftCommentStub = sandbox.stub(element.$.storage,
          'eraseDraftComment');

      // Allow the elements created by dom-repeat to be stamped.
      flushAsynchronousOperations();
    });

    teardown(function() {
      sandbox.restore();
    });

    test('cancel event', function(done) {
      element.addEventListener('cancel', function() { done(); });
      MockInteractions.tap(element.$$('.cancel'));
    });

    test('show/hide labels', function() {
      var revisions = {
        rev1: {_number: 1},
        rev2: {_number: 2},
      };
      assert.isFalse(element._computeShowLabels('1', revisions));
      assert.isTrue(element._computeShowLabels('2', revisions));
    });

    test('label picker', function(done) {
      var showLabelsStub = sinon.stub(element, '_computeShowLabels',
          function() { return true; });
      element.revisions = {};
      element.patchNum = '';

      // Async tick is needed because iron-selector content is distributed and
      // distributed content requires an observer to be set up.
      flush(function() {
        for (var label in element.permittedLabels) {
          assert.ok(element.$$('iron-selector[data-label="' + label + '"]'),
              label);
        }
        element.draft = 'I wholeheartedly disapprove';
        MockInteractions.tap(element.$$(
            'iron-selector[data-label="Code-Review"] > ' +
            'gr-button[data-value="-1"]'));
        MockInteractions.tap(element.$$(
            'iron-selector[data-label="Verified"] > ' +
            'gr-button[data-value="-1"]'));

        var saveReviewStub = sinon.stub(element, '_saveReview',
            function(review) {
          assert.deepEqual(review, {
            drafts: 'PUBLISH_ALL_REVISIONS',
            labels: {
              'Code-Review': -1,
              'Verified': -1
            },
            message: 'I wholeheartedly disapprove',
            reviewers: [],
          });
          return Promise.resolve({ok: true});
        });

        element.addEventListener('send', function() {
          assert.isFalse(element.disabled,
              'Element should be enabled when done sending reply.');
          assert.equal(element.draft.length, 0);
          saveReviewStub.restore();
          showLabelsStub.restore();
          done();
        });

        // This is needed on non-Blink engines most likely due to the ways in
        // which the dom-repeat elements are stamped.
        flush(function() {
          MockInteractions.tap(element.$$('.send'));
          assert.isTrue(element.disabled);
        });
      });
    });

    function getActiveElement() {
      return Polymer.IronOverlayManager.deepActiveElement;
    }

    function isVisible(el) {
      assert.ok(el);
      return getComputedStyle(el).getPropertyValue('display') != 'none';
    }

    function overlayObserver(mode) {
      return new Promise(function(resolve) {
        function listener() {
          element.removeEventListener('iron-overlay-' + mode, listener);
          resolve();
        }
        element.addEventListener('iron-overlay-' + mode, listener);
      });
    }

    test('reviewer confirmation', function(done) {
      var yesButton =
          element.$$('.reviewerConfirmationButtons gr-button:first-child');
      var noButton =
          element.$$('.reviewerConfirmationButtons gr-button:last-child');

      element._reviewerPendingConfirmation = null;
      flushAsynchronousOperations();
      assert.isFalse(isVisible(element.$.reviewerConfirmationOverlay));

      // Cause the confirmation dialog to display.
      var observer = overlayObserver('opened');
      var group = {
        id: 'id',
        name: 'name',
        count: 10,
      };
      element._reviewerPendingConfirmation = {
        group: group,
      };

      observer.then(function() {
        assert.isTrue(isVisible(element.$.reviewerConfirmationOverlay));
        observer = overlayObserver('closed');
        MockInteractions.tap(noButton); // close the overlay
        return observer;
      }).then(function() {
        assert.isFalse(isVisible(element.$.reviewerConfirmationOverlay));

        // We should be focused on account entry input.
        assert.equal(getActiveElement().id, 'input');

        // No reviewer should have been added.
        assert.deepEqual(element.$.reviewers.additions(), []);

        // Reopen confirmation dialog.
        observer = overlayObserver('opened');
        element._reviewerPendingConfirmation = {
          group: group,
        };
        return observer;
      }).then(function() {
        assert.isTrue(isVisible(element.$.reviewerConfirmationOverlay));
        observer = overlayObserver('closed');
        MockInteractions.tap(yesButton); // confirm the group
        return observer;
      }).then(function() {
        assert.isFalse(isVisible(element.$.reviewerConfirmationOverlay));
        assert.deepEqual(
            element.$.reviewers.additions(),
            [
              {
                group: {
                  id: 'id',
                  name: 'name',
                  count: 10,
                  confirmed: true,
                  _group: true,
                  _pendingAdd: true,
                },
              },
            ]);

        // We should be focused on account entry input.
        assert.equal(getActiveElement().id, 'input');
      }).then(done);
    });

    test('_getStorageLocation', function() {
      var actual = element._getStorageLocation();
      assert.equal(actual.changeNum, changeNum);
      assert.equal(actual.patchNum, patchNum);
      assert.equal(actual.path, '@change');
    });

    test('gets draft from storage on open', function() {
      var storedDraft = 'hello world';
      getDraftCommentStub.returns({message: storedDraft});
      element.open();
      assert.isTrue(getDraftCommentStub.called);
      assert.equal(element.draft, storedDraft);
    });

    test('blank if no stored draft', function() {
      getDraftCommentStub.returns(null);
      element.open();
      assert.isTrue(getDraftCommentStub.called);
      assert.equal(element.draft, '');
    });

    test('updates stored draft on edits', function() {
      var firstEdit = 'hello';
      var location = element._getStorageLocation();

      element.draft = firstEdit;
      element.flushDebouncer('store');

      assert.isTrue(setDraftCommentStub.calledWith(location, firstEdit));

      element.draft = '';
      element.flushDebouncer('store');

      assert.isTrue(eraseDraftCommentStub.calledWith(location));
    });

    test('400 converts to human-readable server-error', function(done) {
      sandbox.stub(window, 'fetch', function() {
        var text = '....{"reviewers":{"id1":{"error":"first error"}},' +
          '"ccs":{"id2":{"error":"second error"}}}';
        return Promise.resolve({
          ok: false,
          status: 400,
          text: function() { return Promise.resolve(text); },
        });
      });

      element.addEventListener('server-error', function(event) {
        if (event.target !== element) {
          return;
        }
        event.detail.response.text().then(function(body) {
          assert.equal(body, 'first error, second error');
        });
      });
      element.send().then(done);
    });

    test('ccs are displayed if NoteDb is enabled', function() {
      function hasCc() {
        flushAsynchronousOperations();
        return !!element.$$('#ccs');
      }

      element.serverConfig = {};
      assert.isFalse(hasCc());

      element.serverConfig = {note_db_enabled: true};
      assert.isTrue(hasCc());
    });

    test('filterReviewerSuggestion', function() {
      var counter = 0;
      function makeAccount() {
        return {_account_id: counter++};
      }
      function makeGroup() {
        return {id: counter++};
      }

      var owner = makeAccount();
      var reviewer1 = makeAccount();
      var reviewer2 = makeGroup();
      var cc1 = makeAccount();
      var cc2 = makeGroup();

      element._owner = owner;
      element._reviewers = [reviewer1, reviewer2];
      element._ccs = [cc1, cc2];

      assert.isTrue(
          element._filterReviewerSuggestion({account: makeAccount()}));
      assert.isTrue(element._filterReviewerSuggestion({group: makeGroup()}));

      // Owner should be excluded.
      assert.isFalse(element._filterReviewerSuggestion({account: owner}));

      // Existing and pending reviewers should be excluded.
      assert.isFalse(element._filterReviewerSuggestion({account: reviewer1}));
      assert.isFalse(element._filterReviewerSuggestion({group: reviewer2}));

      // Existing and pending CCs should be excluded.
      assert.isFalse(element._filterReviewerSuggestion({account: cc1}));
      assert.isFalse(element._filterReviewerSuggestion({group: cc2}));
    });

    test('_chooseFocusTarget', function() {
      element._account = null;
      assert.strictEqual(
          element._chooseFocusTarget(), element.FocusTarget.BODY);

      element._account = {_account_id: 1};
      assert.strictEqual(
          element._chooseFocusTarget(), element.FocusTarget.BODY);

      element.change.owner = {_account_id: 2};
      assert.strictEqual(
          element._chooseFocusTarget(), element.FocusTarget.BODY);

      element.change.owner._account_id = 1;
      element.change._reviewers = null;
      assert.strictEqual(
          element._chooseFocusTarget(), element.FocusTarget.REVIEWERS);

      element._reviewers = [];
      assert.strictEqual(
          element._chooseFocusTarget(), element.FocusTarget.REVIEWERS);

      element._reviewers.push({});
      assert.strictEqual(
          element._chooseFocusTarget(), element.FocusTarget.BODY);
    });
  });
</script>
