blob: 29cc37069fa6d193d79742c6c1f385f71a6aef82 [file] [log] [blame]
/**
* @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.
*/
import '../test/common-test-setup-karma.js';
import {
_testOnly_computeWipForPatchSets, computeAllPatchSets,
fetchChangeUpdates, findEditParentPatchNum, findEditParentRevision,
getParentIndex, getRevisionByPatchNum,
isMergeParent,
patchNumEquals, sortRevisions,
} from './patch-set-util.js';
suite('gr-patch-set-util tests', () => {
test('getRevisionByPatchNum', () => {
const revisions = [
{_number: 0},
{_number: 1},
{_number: 2},
];
assert.deepEqual(getRevisionByPatchNum(revisions, '1'), revisions[1]);
assert.deepEqual(getRevisionByPatchNum(revisions, 2), revisions[2]);
assert.equal(getRevisionByPatchNum(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);
},
};
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);
},
};
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);
},
};
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);
},
};
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 = _testOnly_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', () => {
assert.isFalse(patchNumEquals('edit', 'PARENT'));
assert.isFalse(patchNumEquals('edit', NaN));
assert.isFalse(patchNumEquals(1, '2'));
assert.isTrue(patchNumEquals(1, '1'));
assert.isTrue(patchNumEquals(1, 1));
assert.isTrue(patchNumEquals('edit', 'edit'));
assert.isTrue(patchNumEquals('PARENT', 'PARENT'));
});
test('isMergeParent', () => {
assert.isFalse(isMergeParent(1));
assert.isFalse(isMergeParent(4321));
assert.isFalse(isMergeParent('52'));
assert.isFalse(isMergeParent('edit'));
assert.isFalse(isMergeParent('PARENT'));
assert.isFalse(isMergeParent(0));
assert.isTrue(isMergeParent(-23));
assert.isTrue(isMergeParent(-1));
assert.isTrue(isMergeParent('-42'));
});
test('findEditParentRevision', () => {
let revisions = [
{_number: 0},
{_number: 1},
{_number: 2},
];
assert.strictEqual(findEditParentRevision(revisions), null);
revisions = [...revisions, {_number: 'edit', basePatchNum: 3}];
assert.strictEqual(findEditParentRevision(revisions), null);
revisions = [...revisions, {_number: 3}];
assert.deepEqual(findEditParentRevision(revisions), {_number: 3});
});
test('findEditParentPatchNum', () => {
let revisions = [
{_number: 0},
{_number: 1},
{_number: 2},
];
assert.equal(findEditParentPatchNum(revisions), -1);
revisions =
[...revisions, {_number: 'edit', basePatchNum: 3}, {_number: 3}];
assert.deepEqual(findEditParentPatchNum(revisions), 3);
});
test('sortRevisions', () => {
const revisions = [
{_number: 0},
{_number: 2},
{_number: 1},
];
const sorted = [
{_number: 2},
{_number: 1},
{_number: 0},
];
assert.deepEqual(sortRevisions(revisions), sorted);
// Edit patchset should follow directly after its basePatchNum.
revisions.push({_number: 'edit', basePatchNum: 2});
sorted.unshift({_number: 'edit', basePatchNum: 2});
assert.deepEqual(sortRevisions(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(sortRevisions(revisions), sorted);
});
test('getParentIndex', () => {
assert.equal(getParentIndex('-13'), 13);
assert.equal(getParentIndex(-4), 4);
});
test('computeAllPatchSets', () => {
const expected = [
{num: 4, desc: 'test', sha: 'rev4'},
{num: 3, desc: 'test', sha: 'rev3'},
{num: 2, desc: 'test', sha: 'rev2'},
{num: 1, desc: 'test', sha: 'rev1'},
];
const patchNums = computeAllPatchSets({
revisions: {
rev3: {_number: 3, description: 'test', date: 3},
rev1: {_number: 1, description: 'test', date: 1},
rev4: {_number: 4, description: 'test', date: 4},
rev2: {_number: 2, description: 'test', date: 2},
},
});
assert.equal(patchNums.length, expected.length);
for (let i = 0; i < expected.length; i++) {
assert.deepEqual(patchNums[i], expected[i]);
}
});
});