blob: be6f646a5d611a7c846f26375bc01c564eafd4d5 [file] [log] [blame]
/**
* @license
* Copyright (C) 2017 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 './gr-comment-api.js';
import {ChangeComments} from './gr-comment-api.js';
const basicFixture = fixtureFromElement('gr-comment-api');
suite('gr-comment-api tests', () => {
const PARENT = 'PARENT';
let element;
setup(() => {
element = basicFixture.instantiate();
});
test('loads logged-out', () => {
const changeNum = 1234;
sinon.stub(element.$.restAPI, 'getLoggedIn')
.returns(Promise.resolve(false));
sinon.stub(element.$.restAPI, 'getDiffComments')
.returns(Promise.resolve({
'foo.c': [{id: '123', message: 'foo bar', in_reply_to: '321'}],
}));
sinon.stub(element.$.restAPI, 'getDiffRobotComments')
.returns(Promise.resolve({'foo.c': [{id: '321', message: 'done'}]}));
sinon.stub(element.$.restAPI, 'getDiffDrafts')
.returns(Promise.resolve({}));
return element.loadAll(changeNum).then(() => {
assert.isTrue(element.$.restAPI.getDiffComments.calledWithExactly(
changeNum));
assert.isTrue(element.$.restAPI.getDiffRobotComments.calledWithExactly(
changeNum));
assert.isTrue(element.$.restAPI.getDiffDrafts.calledWithExactly(
changeNum));
assert.isOk(element._changeComments._comments);
assert.isOk(element._changeComments._robotComments);
assert.deepEqual(element._changeComments._drafts, {});
});
});
test('loads logged-in', () => {
const changeNum = 1234;
sinon.stub(element.$.restAPI, 'getLoggedIn')
.returns(Promise.resolve(true));
sinon.stub(element.$.restAPI, 'getDiffComments')
.returns(Promise.resolve({
'foo.c': [{id: '123', message: 'foo bar', in_reply_to: '321'}],
}));
sinon.stub(element.$.restAPI, 'getDiffRobotComments')
.returns(Promise.resolve({'foo.c': [{id: '321', message: 'done'}]}));
sinon.stub(element.$.restAPI, 'getDiffDrafts')
.returns(Promise.resolve({'foo.c': [{id: '555', message: 'ack'}]}));
return element.loadAll(changeNum).then(() => {
assert.isTrue(element.$.restAPI.getDiffComments.calledWithExactly(
changeNum));
assert.isTrue(element.$.restAPI.getDiffRobotComments.calledWithExactly(
changeNum));
assert.isTrue(element.$.restAPI.getDiffDrafts.calledWithExactly(
changeNum));
assert.isOk(element._changeComments._comments);
assert.isOk(element._changeComments._robotComments);
assert.notDeepEqual(element._changeComments._drafts, {});
});
});
suite('reloadDrafts', () => {
let commentStub;
let robotCommentStub;
let draftStub;
setup(() => {
commentStub = sinon.stub(element.$.restAPI, 'getDiffComments')
.returns(Promise.resolve({}));
robotCommentStub = sinon.stub(element.$.restAPI,
'getDiffRobotComments').returns(Promise.resolve({}));
draftStub = sinon.stub(element.$.restAPI, 'getDiffDrafts')
.returns(Promise.resolve({}));
});
test('without loadAll first', done => {
assert.isNotOk(element._changeComments);
sinon.spy(element, 'loadAll');
element.reloadDrafts().then(() => {
assert.isTrue(element.loadAll.called);
assert.isOk(element._changeComments);
assert.equal(commentStub.callCount, 1);
assert.equal(robotCommentStub.callCount, 1);
assert.equal(draftStub.callCount, 1);
done();
});
});
test('with loadAll first', done => {
assert.isNotOk(element._changeComments);
element.loadAll()
.then(() => {
assert.isOk(element._changeComments);
assert.equal(commentStub.callCount, 1);
assert.equal(robotCommentStub.callCount, 1);
assert.equal(draftStub.callCount, 1);
return element.reloadDrafts();
})
.then(() => {
assert.isOk(element._changeComments);
assert.equal(commentStub.callCount, 1);
assert.equal(robotCommentStub.callCount, 1);
assert.equal(draftStub.callCount, 2);
done();
});
});
});
suite('_changeComment methods', () => {
setup(done => {
const changeNum = 1234;
stub('gr-rest-api-interface', {
getDiffComments() { return Promise.resolve({}); },
getDiffRobotComments() { return Promise.resolve({}); },
getDiffDrafts() { return Promise.resolve({}); },
});
element.loadAll(changeNum).then(() => {
done();
});
});
test('_isInBaseOfPatchRange', () => {
const comment = {patch_set: 1};
const patchRange = {basePatchNum: 1, patchNum: 2};
assert.isTrue(element._changeComments._isInBaseOfPatchRange(comment,
patchRange));
patchRange.basePatchNum = PARENT;
assert.isFalse(element._changeComments._isInBaseOfPatchRange(comment,
patchRange));
comment.side = PARENT;
assert.isFalse(element._changeComments._isInBaseOfPatchRange(comment,
patchRange));
comment.patch_set = 2;
assert.isTrue(element._changeComments._isInBaseOfPatchRange(comment,
patchRange));
patchRange.basePatchNum = -2;
comment.side = PARENT;
comment.parent = 1;
assert.isFalse(element._changeComments._isInBaseOfPatchRange(comment,
patchRange));
comment.parent = 2;
assert.isTrue(element._changeComments._isInBaseOfPatchRange(comment,
patchRange));
});
test('_isInRevisionOfPatchRange', () => {
const comment = {patch_set: 123};
const patchRange = {basePatchNum: 122, patchNum: 124};
assert.isFalse(element._changeComments._isInRevisionOfPatchRange(
comment, patchRange));
patchRange.patchNum = 123;
assert.isTrue(element._changeComments._isInRevisionOfPatchRange(
comment, patchRange));
comment.side = PARENT;
assert.isFalse(element._changeComments._isInRevisionOfPatchRange(
comment, patchRange));
});
test('_isInPatchRange', () => {
const patchRange1 = {basePatchNum: 122, patchNum: 124};
const patchRange2 = {basePatchNum: 123, patchNum: 125};
const patchRange3 = {basePatchNum: 124, patchNum: 125};
const isInBasePatchStub = sinon.stub(element._changeComments,
'_isInBaseOfPatchRange');
const isInRevisionPatchStub = sinon.stub(element._changeComments,
'_isInRevisionOfPatchRange');
isInBasePatchStub.withArgs({}, patchRange1).returns(true);
isInBasePatchStub.withArgs({}, patchRange2).returns(false);
isInBasePatchStub.withArgs({}, patchRange3).returns(false);
isInRevisionPatchStub.withArgs({}, patchRange1).returns(false);
isInRevisionPatchStub.withArgs({}, patchRange2).returns(true);
isInRevisionPatchStub.withArgs({}, patchRange3).returns(false);
assert.isTrue(element._changeComments._isInPatchRange({}, patchRange1));
assert.isTrue(element._changeComments._isInPatchRange({}, patchRange2));
assert.isFalse(element._changeComments._isInPatchRange({},
patchRange3));
});
suite('comment ranges and paths', () => {
function makeTime(mins) {
return `2013-02-26 15:0${mins}:43.986000000`;
}
setup(() => {
const drafts = {
'file/one': [
{
id: '12',
patch_set: 2,
side: PARENT,
line: 1,
updated: makeTime(3),
},
{
id: '13',
in_reply_to: '04',
patch_set: 2,
line: 1,
// Draft gets lower timestamp than published comment, because we
// want to test that the draft still gets sorted to the end.
updated: makeTime(2),
},
],
'file/two': [
{
id: '05',
patch_set: 3,
line: 1,
updated: makeTime(3),
},
],
};
const robotComments = {
'file/one': [
{
id: '01',
patch_set: 2,
side: PARENT,
line: 1,
updated: makeTime(1),
range: {
start_line: 1,
start_character: 2,
end_line: 2,
end_character: 2,
},
}, {
id: '02',
in_reply_to: '04',
patch_set: 2,
unresolved: true,
line: 1,
updated: makeTime(3),
},
],
};
const comments = {
'file/one': [
{
id: '03',
patch_set: 2,
side: PARENT,
line: 2,
updated: makeTime(1),
},
{id: '04', patch_set: 2, line: 1, updated: makeTime(1)},
],
'file/two': [
{id: '05', patch_set: 2, line: 2, updated: makeTime(1)},
{id: '06', patch_set: 3, line: 2, updated: makeTime(1)},
],
'file/three': [
{
id: '07',
patch_set: 2,
side: PARENT,
unresolved: false,
line: 1,
updated: makeTime(1),
},
{
id: '08',
patch_set: 2,
side: PARENT,
unresolved: true,
in_reply_to: '07',
line: 1,
updated: makeTime(1),
},
{id: '09', patch_set: 3, line: 1, updated: makeTime(1)},
],
'file/four': [
{
id: '10',
patch_set: 5,
side: PARENT,
line: 1,
updated: makeTime(1),
},
{id: '11', patch_set: 5, line: 1, updated: makeTime(1)},
],
};
element._changeComments =
new ChangeComments(comments, robotComments, drafts, 1234);
});
test('getPaths', () => {
const patchRange = {basePatchNum: 1, patchNum: 4};
let paths = element._changeComments.getPaths(patchRange);
assert.equal(Object.keys(paths).length, 0);
patchRange.basePatchNum = PARENT;
patchRange.patchNum = 3;
paths = element._changeComments.getPaths(patchRange);
assert.notProperty(paths, 'file/one');
assert.property(paths, 'file/two');
assert.property(paths, 'file/three');
assert.notProperty(paths, 'file/four');
patchRange.patchNum = 2;
paths = element._changeComments.getPaths(patchRange);
assert.property(paths, 'file/one');
assert.property(paths, 'file/two');
assert.property(paths, 'file/three');
assert.notProperty(paths, 'file/four');
paths = element._changeComments.getPaths();
assert.property(paths, 'file/one');
assert.property(paths, 'file/two');
assert.property(paths, 'file/three');
assert.property(paths, 'file/four');
});
test('getCommentsBySideForPath', () => {
const patchRange = {basePatchNum: 1, patchNum: 3};
let path = 'file/one';
let comments = element._changeComments.getCommentsBySideForPath(path,
patchRange);
assert.equal(comments.meta.changeNum, 1234);
assert.equal(comments.left.length, 0);
assert.equal(comments.right.length, 0);
path = 'file/two';
comments = element._changeComments.getCommentsBySideForPath(path,
patchRange);
assert.equal(comments.left.length, 0);
assert.equal(comments.right.length, 2);
patchRange.basePatchNum = 2;
comments = element._changeComments.getCommentsBySideForPath(path,
patchRange);
assert.equal(comments.left.length, 1);
assert.equal(comments.right.length, 2);
patchRange.basePatchNum = PARENT;
path = 'file/three';
comments = element._changeComments.getCommentsBySideForPath(path,
patchRange);
assert.equal(comments.left.length, 0);
assert.equal(comments.right.length, 1);
});
test('getAllCommentsForPath', () => {
let path = 'file/one';
let comments = element._changeComments.getAllCommentsForPath(path);
assert.equal(comments.length, 4);
path = 'file/two';
comments = element._changeComments.getAllCommentsForPath(path, 2);
assert.equal(comments.length, 1);
const aCopyOfComments = element._changeComments
.getAllCommentsForPath(path, 2);
assert.deepEqual(comments, aCopyOfComments);
assert.notEqual(comments[0], aCopyOfComments[0]);
});
test('getAllDraftsForPath', () => {
const path = 'file/one';
const drafts = element._changeComments.getAllDraftsForPath(path);
assert.equal(drafts.length, 2);
const aCopyOfDrafts = element._changeComments
.getAllDraftsForPath(path);
assert.deepEqual(drafts, aCopyOfDrafts);
assert.notEqual(drafts[0], aCopyOfDrafts[0]);
});
test('computeUnresolvedNum', () => {
assert.equal(element._changeComments
.computeUnresolvedNum({
patchNum: 2,
path: 'file/one',
}), 0);
assert.equal(element._changeComments
.computeUnresolvedNum({
patchNum: 1,
path: 'file/one',
}), 0);
assert.equal(element._changeComments
.computeUnresolvedNum({
patchNum: 2,
path: 'file/three',
}), 1);
});
test('computeUnresolvedNum w/ non-linear thread', () => {
const comments = {
path: [{
id: '9c6ba3c6_28b7d467',
patch_set: 1,
updated: '2018-02-28 14:41:13.000000000',
unresolved: true,
}, {
id: '3df7b331_0bead405',
patch_set: 1,
in_reply_to: '1c346623_ab85d14a',
updated: '2018-02-28 23:07:55.000000000',
unresolved: false,
}, {
id: '6153dce6_69958d1e',
patch_set: 1,
in_reply_to: '9c6ba3c6_28b7d467',
updated: '2018-02-28 17:11:31.000000000',
unresolved: true,
}, {
id: '1c346623_ab85d14a',
patch_set: 1,
in_reply_to: '9c6ba3c6_28b7d467',
updated: '2018-02-28 23:01:39.000000000',
unresolved: false,
}],
};
element._changeComments = new ChangeComments(comments, {}, {}, 1234);
assert.equal(
element._changeComments.computeUnresolvedNum(1, 'path'), 0);
});
test('computeCommentThreadCount', () => {
assert.equal(element._changeComments
.computeCommentThreadCount({
patchNum: 2,
path: 'file/one',
}), 3);
assert.equal(element._changeComments
.computeCommentThreadCount({
patchNum: 1,
path: 'file/one',
}), 0);
assert.equal(element._changeComments
.computeCommentThreadCount({
patchNum: 2,
path: 'file/three',
}), 1);
});
test('computeDraftCount', () => {
assert.equal(element._changeComments
.computeDraftCount({
patchNum: 2,
path: 'file/one',
}), 2);
assert.equal(element._changeComments
.computeDraftCount({
patchNum: 1,
path: 'file/one',
}), 0);
assert.equal(element._changeComments
.computeDraftCount({
patchNum: 2,
path: 'file/three',
}), 0);
assert.equal(element._changeComments
.computeDraftCount(), 3);
});
test('getAllPublishedComments', () => {
let publishedComments = element._changeComments
.getAllPublishedComments();
assert.equal(Object.keys(publishedComments).length, 4);
assert.equal(Object.keys(publishedComments[['file/one']]).length, 4);
assert.equal(Object.keys(publishedComments[['file/two']]).length, 2);
publishedComments = element._changeComments
.getAllPublishedComments(2);
assert.equal(Object.keys(publishedComments[['file/one']]).length, 4);
assert.equal(Object.keys(publishedComments[['file/two']]).length, 1);
});
test('getAllComments', () => {
let comments = element._changeComments.getAllComments();
assert.equal(Object.keys(comments).length, 4);
assert.equal(Object.keys(comments[['file/one']]).length, 4);
assert.equal(Object.keys(comments[['file/two']]).length, 2);
comments = element._changeComments.getAllComments(false, 2);
assert.equal(Object.keys(comments).length, 4);
assert.equal(Object.keys(comments[['file/one']]).length, 4);
assert.equal(Object.keys(comments[['file/two']]).length, 1);
// Include drafts
comments = element._changeComments.getAllComments(true);
assert.equal(Object.keys(comments).length, 4);
assert.equal(Object.keys(comments[['file/one']]).length, 6);
assert.equal(Object.keys(comments[['file/two']]).length, 3);
comments = element._changeComments.getAllComments(true, 2);
assert.equal(Object.keys(comments).length, 4);
assert.equal(Object.keys(comments[['file/one']]).length, 6);
assert.equal(Object.keys(comments[['file/two']]).length, 1);
});
test('computeAllThreads', () => {
const expectedThreads = [
{
comments: [
{
id: '01',
patch_set: 2,
side: 'PARENT',
line: 1,
updated: '2013-02-26 15:01:43.986000000',
range: {
start_line: 1,
start_character: 2,
end_line: 2,
end_character: 2,
},
path: 'file/one',
__path: 'file/one',
},
],
commentSide: 'PARENT',
patchNum: 2,
path: 'file/one',
line: 1,
rootId: '01',
}, {
comments: [
{
id: '03',
patch_set: 2,
side: 'PARENT',
line: 2,
path: 'file/one',
__path: 'file/one',
updated: '2013-02-26 15:01:43.986000000',
},
],
commentSide: 'PARENT',
patchNum: 2,
path: 'file/one',
line: 2,
rootId: '03',
}, {
comments: [
{
id: '04',
patch_set: 2,
line: 1,
path: 'file/one',
__path: 'file/one',
updated: '2013-02-26 15:01:43.986000000',
},
{
id: '02',
in_reply_to: '04',
patch_set: 2,
unresolved: true,
line: 1,
path: 'file/one',
__path: 'file/one',
updated: '2013-02-26 15:03:43.986000000',
},
{
id: '13',
in_reply_to: '04',
patch_set: 2,
line: 1,
path: 'file/one',
__path: 'file/one',
__draft: true,
updated: '2013-02-26 15:02:43.986000000',
},
],
patchNum: 2,
path: 'file/one',
line: 1,
rootId: '04',
}, {
comments: [
{
id: '05',
patch_set: 2,
line: 2,
path: 'file/two',
__path: 'file/two',
updated: '2013-02-26 15:01:43.986000000',
},
],
patchNum: 2,
path: 'file/two',
line: 2,
rootId: '05',
}, {
comments: [
{
id: '06',
patch_set: 3,
line: 2,
path: 'file/two',
__path: 'file/two',
updated: '2013-02-26 15:01:43.986000000',
},
],
patchNum: 3,
path: 'file/two',
line: 2,
rootId: '06',
}, {
comments: [
{
id: '07',
patch_set: 2,
side: 'PARENT',
unresolved: false,
line: 1,
path: 'file/three',
__path: 'file/three',
updated: '2013-02-26 15:01:43.986000000',
},
{
id: '08',
in_reply_to: '07',
patch_set: 2,
side: 'PARENT',
unresolved: true,
line: 1,
path: 'file/three',
__path: 'file/three',
updated: '2013-02-26 15:01:43.986000000',
},
],
commentSide: 'PARENT',
patchNum: 2,
path: 'file/three',
line: 1,
rootId: '07',
}, {
comments: [
{
id: '09',
patch_set: 3,
line: 1,
path: 'file/three',
__path: 'file/three',
updated: '2013-02-26 15:01:43.986000000',
},
],
patchNum: 3,
path: 'file/three',
line: 1,
rootId: '09',
}, {
comments: [
{
id: '10',
patch_set: 5,
side: 'PARENT',
line: 1,
path: 'file/four',
__path: 'file/four',
updated: '2013-02-26 15:01:43.986000000',
},
],
commentSide: 'PARENT',
patchNum: 5,
path: 'file/four',
line: 1,
rootId: '10',
}, {
comments: [
{
id: '11',
patch_set: 5,
line: 1,
path: 'file/four',
__path: 'file/four',
updated: '2013-02-26 15:01:43.986000000',
},
],
rootId: '11',
patchNum: 5,
path: 'file/four',
line: 1,
}, {
comments: [
{
id: '05',
patch_set: 3,
line: 1,
path: 'file/two',
__path: 'file/two',
__draft: true,
updated: '2013-02-26 15:03:43.986000000',
},
],
rootId: '05',
patchNum: 3,
path: 'file/two',
line: 1,
}, {
comments: [
{
id: '12',
patch_set: 2,
side: 'PARENT',
line: 1,
path: 'file/one',
__path: 'file/one',
__draft: true,
updated: '2013-02-26 15:03:43.986000000',
},
],
rootId: '12',
commentSide: 'PARENT',
patchNum: 2,
path: 'file/one',
line: 1,
},
];
const threads = element._changeComments.getAllThreadsForChange();
assert.deepEqual(threads, expectedThreads);
});
test('getCommentsForThreadGroup', () => {
let expectedComments = [
{
__path: 'file/one',
path: 'file/one',
id: '04',
patch_set: 2,
line: 1,
updated: '2013-02-26 15:01:43.986000000',
},
{
__path: 'file/one',
path: 'file/one',
id: '02',
in_reply_to: '04',
patch_set: 2,
unresolved: true,
line: 1,
updated: '2013-02-26 15:03:43.986000000',
},
{
__path: 'file/one',
path: 'file/one',
__draft: true,
id: '13',
in_reply_to: '04',
patch_set: 2,
line: 1,
updated: '2013-02-26 15:02:43.986000000',
},
];
assert.deepEqual(element._changeComments.getCommentsForThread('04'),
expectedComments);
expectedComments = [{
id: '12',
patch_set: 2,
side: 'PARENT',
line: 1,
path: 'file/one',
__path: 'file/one',
__draft: true,
updated: '2013-02-26 15:03:43.986000000',
}];
assert.deepEqual(element._changeComments.getCommentsForThread('12'),
expectedComments);
assert.deepEqual(element._changeComments.getCommentsForThread('1000'),
null);
});
});
});
});