/** * @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 {GrReviewerUpdatesParser} from './gr-reviewer-updates-parser.js'; import {parseDate} from '../../../utils/date-util.js'; suite('gr-reviewer-updates-parser tests', () => { let instance; test('ignores changes without messages', () => { const change = {}; sinon.stub( GrReviewerUpdatesParser.prototype, '_filterRemovedMessages'); sinon.stub( GrReviewerUpdatesParser.prototype, '_groupUpdates'); sinon.stub( GrReviewerUpdatesParser.prototype, '_formatUpdates'); assert.strictEqual(GrReviewerUpdatesParser.parse(change), change); assert.isFalse( GrReviewerUpdatesParser.prototype._filterRemovedMessages.called); assert.isFalse( GrReviewerUpdatesParser.prototype._groupUpdates.called); assert.isFalse( GrReviewerUpdatesParser.prototype._formatUpdates.called); }); test('ignores changes without reviewer updates', () => { const change = { messages: [], }; sinon.stub( GrReviewerUpdatesParser.prototype, '_filterRemovedMessages'); sinon.stub( GrReviewerUpdatesParser.prototype, '_groupUpdates'); sinon.stub( GrReviewerUpdatesParser.prototype, '_formatUpdates'); assert.strictEqual(GrReviewerUpdatesParser.parse(change), change); assert.isFalse( GrReviewerUpdatesParser.prototype._filterRemovedMessages.called); assert.isFalse( GrReviewerUpdatesParser.prototype._groupUpdates.called); assert.isFalse( GrReviewerUpdatesParser.prototype._formatUpdates.called); }); test('ignores changes with empty reviewer updates', () => { const change = { messages: [], reviewer_updates: [], }; sinon.stub( GrReviewerUpdatesParser.prototype, '_filterRemovedMessages'); sinon.stub( GrReviewerUpdatesParser.prototype, '_groupUpdates'); sinon.stub( GrReviewerUpdatesParser.prototype, '_formatUpdates'); assert.strictEqual(GrReviewerUpdatesParser.parse(change), change); assert.isFalse( GrReviewerUpdatesParser.prototype._filterRemovedMessages.called); assert.isFalse( GrReviewerUpdatesParser.prototype._groupUpdates.called); assert.isFalse( GrReviewerUpdatesParser.prototype._formatUpdates.called); }); test('filter removed messages', () => { const change = { messages: [ { message: 'msg1', tag: 'autogenerated:gerrit:deleteReviewer', }, { message: 'msg2', tag: 'foo', }, ], }; instance = new GrReviewerUpdatesParser(change); instance._filterRemovedMessages(); assert.deepEqual(instance.result, { messages: [{ message: 'msg2', tag: 'foo', }], }); }); test('group reviewer updates', () => { const reviewer1 = {_account_id: 1}; const reviewer2 = {_account_id: 2}; const date1 = '2017-01-26 12:11:50.000000000'; const date2 = '2017-01-26 12:11:55.000000000'; // Within threshold. const date3 = '2017-01-26 12:33:50.000000000'; const date4 = '2017-01-26 12:44:50.000000000'; const makeItem = function(state, reviewer, opt_date, opt_author) { return { reviewer, updated: opt_date || date1, updated_by: opt_author || reviewer1, state, }; }; let change = { reviewer_updates: [ makeItem('REVIEWER', reviewer1), // New group. makeItem('CC', reviewer2), // Appended. makeItem('REVIEWER', reviewer2, date2), // Overrides previous one. makeItem('CC', reviewer1, date2, reviewer2), // New group. makeItem('REMOVED', reviewer2, date3), // Group has no state change. makeItem('REVIEWER', reviewer2, date3), makeItem('CC', reviewer1, date4), // No change, removed. makeItem('REVIEWER', reviewer1, date4), // Forms new group makeItem('REMOVED', reviewer2, date4), // Should be grouped. ], }; instance = new GrReviewerUpdatesParser(change); instance._groupUpdates(); change = instance.result; assert.equal(change.reviewer_updates.length, 3); assert.equal(change.reviewer_updates[0].updates.length, 2); assert.equal(change.reviewer_updates[1].updates.length, 1); assert.equal(change.reviewer_updates[2].updates.length, 2); assert.equal(change.reviewer_updates[0].date, date1); assert.deepEqual(change.reviewer_updates[0].author, reviewer1); assert.deepEqual(change.reviewer_updates[0].updates, [ { reviewer: reviewer1, state: 'REVIEWER', }, { reviewer: reviewer2, state: 'REVIEWER', }, ]); assert.equal(change.reviewer_updates[1].date, date2); assert.deepEqual(change.reviewer_updates[1].author, reviewer2); assert.deepEqual(change.reviewer_updates[1].updates, [ { reviewer: reviewer1, state: 'CC', prev_state: 'REVIEWER', }, ]); assert.equal(change.reviewer_updates[2].date, date4); assert.deepEqual(change.reviewer_updates[2].author, reviewer1); assert.deepEqual(change.reviewer_updates[2].updates, [ { reviewer: reviewer1, prev_state: 'CC', state: 'REVIEWER', }, { reviewer: reviewer2, prev_state: 'REVIEWER', state: 'REMOVED', }, ]); }); test('format reviewer updates', () => { const reviewer1 = {_account_id: 1}; const reviewer2 = {_account_id: 2}; const makeItem = function(prev, state, opt_reviewer) { return { reviewer: opt_reviewer || reviewer1, prev_state: prev, state, }; }; const makeUpdate = function(items) { return { author: reviewer1, updated: '', updates: items, }; }; const change = { reviewer_updates: [ makeUpdate([ makeItem(undefined, 'CC'), makeItem(undefined, 'CC', reviewer2), ]), makeUpdate([ makeItem('CC', 'REVIEWER'), makeItem('REVIEWER', 'REMOVED'), makeItem('REMOVED', 'REVIEWER'), makeItem(undefined, 'REVIEWER', reviewer2), ]), ], }; instance = new GrReviewerUpdatesParser(change); instance._formatUpdates(); assert.equal(change.reviewer_updates.length, 2); assert.equal(change.reviewer_updates[0].updates.length, 1); assert.equal(change.reviewer_updates[1].updates.length, 3); let items = change.reviewer_updates[0].updates; assert.equal(items[0].message, 'Added to cc: '); assert.deepEqual(items[0].reviewers, [reviewer1, reviewer2]); items = change.reviewer_updates[1].updates; assert.equal(items[0].message, 'Moved from cc to reviewer: '); assert.deepEqual(items[0].reviewers, [reviewer1]); assert.equal(items[1].message, 'Removed from reviewer: '); assert.deepEqual(items[1].reviewers, [reviewer1]); assert.equal(items[2].message, 'Added to reviewer: '); assert.deepEqual(items[2].reviewers, [reviewer1, reviewer2]); }); test('_advanceUpdates', () => { const T0 = parseDate('2017-02-17 19:04:18.000000000').getTime(); const tplus = delta => new Date(T0 + delta) .toISOString() .replace('T', ' ') .replace('Z', '000000'); const change = { reviewer_updates: [{ date: tplus(0), type: 'REVIEWER_UPDATE', updates: [{ message: 'same time update', }], }, { date: tplus(200), type: 'REVIEWER_UPDATE', updates: [{ message: 'update within threshold', }], }, { date: tplus(600), type: 'REVIEWER_UPDATE', updates: [{ message: 'update between messages', }], }, { date: tplus(1000), type: 'REVIEWER_UPDATE', updates: [{ message: 'late update', }], }], messages: [{ id: '6734489eb9d642de28dbf2bcf9bda875923800d8', date: tplus(0), message: 'Uploaded patch set 1.', }, { id: '6734489eb9d642de28dbf2bcf9bda875923800d8', date: tplus(800), message: 'Uploaded patch set 2.', }], }; instance = new GrReviewerUpdatesParser(change); instance._advanceUpdates(); const updates = instance.result.reviewer_updates; assert.isBelow(parseDate(updates[0].date).getTime(), T0); assert.isBelow(parseDate(updates[1].date).getTime(), T0); assert.equal(updates[2].date, tplus(100)); assert.equal(updates[3].date, tplus(500)); }); });