| <!-- |
| @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="/node_modules/@webcomponents/webcomponentsjs/webcomponents-lite.js"></script> |
| <script src="/components/wct-browser-legacy/browser.js"></script> |
| <title>gr-patch-set-behavior</title> |
| |
| <script src="/node_modules/@webcomponents/webcomponentsjs/custom-elements-es5-adapter.js"></script> |
| |
| <script type="module"> |
| import '../../test/common-test-setup.js'; |
| import {PatchSetBehavior} from './gr-patch-set-behavior.js'; |
| suite('gr-patch-set-behavior tests', () => { |
| test('getRevisionByPatchNum', () => { |
| const get = 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); |
| }, |
| }; |
| 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); |
| }, |
| }; |
| 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); |
| }, |
| }; |
| 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); |
| }, |
| }; |
| 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 = 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 = 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 = 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 = 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 = 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 = 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(PatchSetBehavior.getParentIndex('-13'), 13); |
| assert.equal(PatchSetBehavior.getParentIndex(-4), 4); |
| }); |
| }); |
| </script> |