<!--
@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.
-->
<!-- Polymer included for the html import polyfill. -->
<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"/>
<title>gr-patch-set-behavior</title>

<script src="/bower_components/webcomponentsjs/custom-elements-es5-adapter.js"></script>

<link rel="import" href="gr-patch-set-behavior.html">

<script>
  suite('gr-patch-set-behavior tests', () => {
    test('getRevisionByPatchNum', () => {
      const get = Gerrit.PatchSetBehavior.getRevisionByPatchNum;
      const revisions = [
        {_number: 0},
        {_number: 1},
        {_number: 2},
      ];
      assert.deepEqual(get(revisions, '1'), revisions[1]);
      assert.deepEqual(get(revisions, 2), revisions[2]);
      assert.equal(get(revisions, '3'), undefined);
    });

    test('fetchChangeUpdates on latest', done => {
      const knownChange = {
        revisions: {
          sha1: {description: 'patch 1', _number: 1},
          sha2: {description: 'patch 2', _number: 2},
        },
        status: 'NEW',
        messages: [],
      };
      const mockRestApi = {
        getChangeDetail() {
          return Promise.resolve(knownChange);
        },
      };
      Gerrit.PatchSetBehavior.fetchChangeUpdates(knownChange, mockRestApi)
          .then(result => {
            assert.isTrue(result.isLatest);
            assert.isNotOk(result.newStatus);
            assert.isFalse(result.newMessages);
            done();
          });
    });

    test('fetchChangeUpdates not on latest', done => {
      const knownChange = {
        revisions: {
          sha1: {description: 'patch 1', _number: 1},
          sha2: {description: 'patch 2', _number: 2},
        },
        status: 'NEW',
        messages: [],
      };
      const actualChange = {
        revisions: {
          sha1: {description: 'patch 1', _number: 1},
          sha2: {description: 'patch 2', _number: 2},
          sha3: {description: 'patch 3', _number: 3},
        },
        status: 'NEW',
        messages: [],
      };
      const mockRestApi = {
        getChangeDetail() {
          return Promise.resolve(actualChange);
        },
      };
      Gerrit.PatchSetBehavior.fetchChangeUpdates(knownChange, mockRestApi)
          .then(result => {
            assert.isFalse(result.isLatest);
            assert.isNotOk(result.newStatus);
            assert.isFalse(result.newMessages);
            done();
          });
    });

    test('fetchChangeUpdates new status', done => {
      const knownChange = {
        revisions: {
          sha1: {description: 'patch 1', _number: 1},
          sha2: {description: 'patch 2', _number: 2},
        },
        status: 'NEW',
        messages: [],
      };
      const actualChange = {
        revisions: {
          sha1: {description: 'patch 1', _number: 1},
          sha2: {description: 'patch 2', _number: 2},
        },
        status: 'MERGED',
        messages: [],
      };
      const mockRestApi = {
        getChangeDetail() {
          return Promise.resolve(actualChange);
        },
      };
      Gerrit.PatchSetBehavior.fetchChangeUpdates(knownChange, mockRestApi)
          .then(result => {
            assert.isTrue(result.isLatest);
            assert.equal(result.newStatus, 'MERGED');
            assert.isFalse(result.newMessages);
            done();
          });
    });

    test('fetchChangeUpdates new messages', done => {
      const knownChange = {
        revisions: {
          sha1: {description: 'patch 1', _number: 1},
          sha2: {description: 'patch 2', _number: 2},
        },
        status: 'NEW',
        messages: [],
      };
      const actualChange = {
        revisions: {
          sha1: {description: 'patch 1', _number: 1},
          sha2: {description: 'patch 2', _number: 2},
        },
        status: 'NEW',
        messages: [{message: 'blah blah'}],
      };
      const mockRestApi = {
        getChangeDetail() {
          return Promise.resolve(actualChange);
        },
      };
      Gerrit.PatchSetBehavior.fetchChangeUpdates(knownChange, mockRestApi)
          .then(result => {
            assert.isTrue(result.isLatest);
            assert.isNotOk(result.newStatus);
            assert.isTrue(result.newMessages);
            done();
          });
    });

    test('_computeWipForPatchSets', () => {
      // Compute patch sets for a given timeline on a change. The initial WIP
      // property of the change can be true or false. The map of tags by
      // revision is keyed by patch set number. Each value is a list of change
      // message tags in the order that they occurred in the timeline. These
      // indicate actions that modify the WIP property of the change and/or
      // create new patch sets.
      //
      // Returns the actual results with an assertWip method that can be used
      // to compare against an expected value for a particular patch set.
      const compute = (initialWip, tagsByRevision) => {
        const change = {
          messages: [],
          work_in_progress: initialWip,
        };
        const revs = Object.keys(tagsByRevision).sort((a, b) => a - b);
        for (const rev of revs) {
          for (const tag of tagsByRevision[rev]) {
            change.messages.push({
              tag,
              _revision_number: rev,
            });
          }
        }
        let patchNums = revs.map(rev => { return {num: rev}; });
        patchNums = Gerrit.PatchSetBehavior._computeWipForPatchSets(
            change, patchNums);
        const actualWipsByRevision = {};
        for (const patchNum of patchNums) {
          actualWipsByRevision[patchNum.num] = patchNum.wip;
        }
        const verifier = {
          assertWip(revision, expectedWip) {
            const patchNum = patchNums.find(patchNum => patchNum.num == revision);
            if (!patchNum) {
              assert.fail('revision ' + revision + ' not found');
            }
            assert.equal(patchNum.wip, expectedWip,
                'wip state for ' + revision + ' is ' +
              patchNum.wip + '; expected ' + expectedWip);
            return verifier;
          },
        };
        return verifier;
      };

      compute(false, {1: ['upload']}).assertWip(1, false);
      compute(true, {1: ['upload']}).assertWip(1, true);

      const setWip = 'autogenerated:gerrit:setWorkInProgress';
      const uploadInWip = 'autogenerated:gerrit:newWipPatchSet';
      const clearWip = 'autogenerated:gerrit:setReadyForReview';

      compute(false, {
        1: ['upload', setWip],
        2: ['upload'],
        3: ['upload', clearWip],
        4: ['upload', setWip],
      }).assertWip(1, false) // Change was created with PS1 ready for review
          .assertWip(2, true) // PS2 was uploaded during WIP
          .assertWip(3, false) // PS3 was marked ready for review after upload
          .assertWip(4, false); // PS4 was uploaded ready for review

      compute(false, {
        1: [uploadInWip, null, 'addReviewer'],
        2: ['upload'],
        3: ['upload', clearWip, setWip],
        4: ['upload'],
        5: ['upload', clearWip],
        6: [uploadInWip],
      }).assertWip(1, true) // Change was created in WIP
          .assertWip(2, true) // PS2 was uploaded during WIP
          .assertWip(3, false) // PS3 was marked ready for review
          .assertWip(4, true) // PS4 was uploaded during WIP
          .assertWip(5, false) // PS5 was marked ready for review
          .assertWip(6, true); // PS6 was uploaded with WIP option
    });

    test('patchNumEquals', () => {
      const equals = Gerrit.PatchSetBehavior.patchNumEquals;
      assert.isFalse(equals('edit', 'PARENT'));
      assert.isFalse(equals('edit', NaN));
      assert.isFalse(equals(1, '2'));

      assert.isTrue(equals(1, '1'));
      assert.isTrue(equals(1, 1));
      assert.isTrue(equals('edit', 'edit'));
      assert.isTrue(equals('PARENT', 'PARENT'));
    });

    test('isMergeParent', () => {
      const isParent = Gerrit.PatchSetBehavior.isMergeParent;
      assert.isFalse(isParent(1));
      assert.isFalse(isParent(4321));
      assert.isFalse(isParent('52'));
      assert.isFalse(isParent('edit'));
      assert.isFalse(isParent('PARENT'));
      assert.isFalse(isParent(0));

      assert.isTrue(isParent(-23));
      assert.isTrue(isParent(-1));
      assert.isTrue(isParent('-42'));
    });

    test('findEditParentRevision', () => {
      const findParent = Gerrit.PatchSetBehavior.findEditParentRevision;
      let revisions = [
        {_number: 0},
        {_number: 1},
        {_number: 2},
      ];
      assert.strictEqual(findParent(revisions), null);

      revisions = [...revisions, {_number: 'edit', basePatchNum: 3}];
      assert.strictEqual(findParent(revisions), null);

      revisions = [...revisions, {_number: 3}];
      assert.deepEqual(findParent(revisions), {_number: 3});
    });

    test('findEditParentPatchNum', () => {
      const findNum = Gerrit.PatchSetBehavior.findEditParentPatchNum;
      let revisions = [
        {_number: 0},
        {_number: 1},
        {_number: 2},
      ];
      assert.equal(findNum(revisions), -1);

      revisions =
          [...revisions, {_number: 'edit', basePatchNum: 3}, {_number: 3}];
      assert.deepEqual(findNum(revisions), 3);
    });

    test('sortRevisions', () => {
      const sort = Gerrit.PatchSetBehavior.sortRevisions;
      const revisions = [
        {_number: 0},
        {_number: 2},
        {_number: 1},
      ];
      const sorted = [
        {_number: 2},
        {_number: 1},
        {_number: 0},
      ];

      assert.deepEqual(sort(revisions), sorted);

      // Edit patchset should follow directly after its basePatchNum.
      revisions.push({_number: 'edit', basePatchNum: 2});
      sorted.unshift({_number: 'edit', basePatchNum: 2});
      assert.deepEqual(sort(revisions), sorted);

      revisions[0].basePatchNum = 0;
      const edit = sorted.shift();
      edit.basePatchNum = 0;
      // Edit patchset should be at index 2.
      sorted.splice(2, 0, edit);
      assert.deepEqual(sort(revisions), sorted);
    });

    test('getParentIndex', () => {
      assert.equal(Gerrit.PatchSetBehavior.getParentIndex('-13'), 13);
      assert.equal(Gerrit.PatchSetBehavior.getParentIndex(-4), 4);
    });
  });
</script>
