blob: 676e0667b4a1b1f505fc2cca0eb634804ddf3c3c [file] [log] [blame]
Dmitrii Filippovacd39a22020-04-02 10:31:43 +02001/**
2 * @license
3 * Copyright (C) 2015 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
Andrew Bonventre547b8ab2015-12-01 01:02:00 -050017
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010018import '../../../test/common-test-setup-karma';
19import '../../edit/gr-edit-constants';
20import './gr-change-view';
Dmitrii Filippov0695d402020-10-22 16:57:57 +020021import {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010022 ChangeStatus,
23 CommentSide,
24 DefaultBase,
25 DiffViewMode,
26 HttpMethod,
Dhruv Srivastava69a51732021-04-14 18:23:00 +020027 MessageTag,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010028 PrimaryTab,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010029} from '../../../constants/constants';
30import {GrEditConstants} from '../../edit/gr-edit-constants';
31import {_testOnly_resetEndpoints} from '../../shared/gr-js-api-interface/gr-plugin-endpoints';
Ben Rohlfsebe4acc2020-12-11 21:16:10 +010032import {GerritNav} from '../../core/gr-navigation/gr-navigation';
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010033import {getPluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader';
34import {_testOnly_initGerritPluginApi} from '../../shared/gr-js-api-interface/gr-gerrit';
Ben Rohlfsa7ab9502021-02-15 17:45:45 +010035import {EventType, PluginApi} from '../../../api/plugin';
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010036
37import 'lodash/lodash';
Ben Rohlfs3a6ff7e2021-01-18 14:08:39 +010038import {
Chris Pouceta2e173e2021-08-31 01:04:04 +000039 mockPromise,
Ben Rohlfs3a6ff7e2021-01-18 14:08:39 +010040 stubRestApi,
41 TestKeyboardShortcutBinder,
42} from '../../../test/test-utils';
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010043import {Shortcut} from '../../../mixins/keyboard-shortcut-mixin/keyboard-shortcut-mixin';
44import {
45 createAppElementChangeViewParams,
46 createApproval,
Dmitrii Filippov0695d402020-10-22 16:57:57 +020047 createChange,
48 createChangeMessages,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010049 createCommit,
50 createMergeable,
51 createPreferences,
52 createRevision,
Dmitrii Filippov0695d402020-10-22 16:57:57 +020053 createRevisions,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010054 createServerInfo,
55 createUserConfig,
56 TEST_NUMERIC_CHANGE_ID,
57 TEST_PROJECT_NAME,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010058 createEditRevision,
59 createAccountWithIdNameAndEmail,
Dhruv Srivastavada276592021-04-07 14:51:51 +020060 createChangeViewChange,
Milutin Kristofice9ddfa42021-04-20 23:34:45 +020061 createRelatedChangeAndCommitInfo,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010062} from '../../../test/test-data-generators';
63import {ChangeViewPatchRange, GrChangeView} from './gr-change-view';
64import {
65 AccountId,
66 ApprovalInfo,
Dhruv Srivastava591b4902021-03-10 11:48:12 +010067 BasePatchSetNum,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010068 ChangeId,
69 ChangeInfo,
70 CommitId,
71 CommitInfo,
72 EditInfo,
73 EditPatchSetNum,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010074 GitRef,
75 NumericChangeId,
76 ParentPatchSetNum,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010077 PatchRange,
78 PatchSetNum,
Milutin Kristofice9ddfa42021-04-20 23:34:45 +020079 RelatedChangeAndCommitInfo,
Dhruv Srivastava69a51732021-04-14 18:23:00 +020080 ReviewInputTag,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010081 RevisionInfo,
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +010082 RevisionPatchSetNum,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010083 RobotId,
84 Timestamp,
85 UrlEncodedCommentId,
86} from '../../../types/common';
87import {
88 pressAndReleaseKeyOn,
89 tap,
90} from '@polymer/iron-test-helpers/mock-interactions';
91import {GrEditControls} from '../../edit/gr-edit-controls/gr-edit-controls';
92import {AppElementChangeViewParams} from '../../gr-app-types';
Ben Rohlfs8e28ad82021-09-20 14:48:33 +020093import {SinonFakeTimers, SinonStubbedMember} from 'sinon';
Ben Rohlfsa9d2cff2021-01-22 21:33:58 +010094import {RestApiService} from '../../../services/gr-rest-api/gr-rest-api';
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010095import {CustomKeyboardEvent} from '../../../types/events';
Dhruv Srivastavadb2ab602021-06-24 15:20:29 +020096import {CommentThread, UIRobot} from '../../../utils/comment-util';
Ben Rohlfsebe4acc2020-12-11 21:16:10 +010097import {GerritView} from '../../../services/router/router-model';
Ben Rohlfsa00ef282021-01-22 21:45:53 +010098import {ParsedChangeInfo} from '../../../types/types';
Milutin Kristofic8803ea02020-12-09 23:34:39 +010099import {GrRelatedChangesList} from '../gr-related-changes-list/gr-related-changes-list';
Ben Rohlfsc4c5fdb2021-02-25 12:09:54 +0100100import {appContext} from '../../../services/app-context';
Dhruv Srivastava69a51732021-04-14 18:23:00 +0200101import {ChangeStates} from '../../shared/gr-change-status/gr-change-status';
Dmitrii Filippovacd39a22020-04-02 10:31:43 +0200102
Dmitrii Filippov5f25dc02020-04-07 18:49:00 +0200103const pluginApi = _testOnly_initGerritPluginApi();
Dmitrii Filippovacd39a22020-04-02 10:31:43 +0200104const fixture = fixtureFromElement('gr-change-view');
Dmitrii Filippov0028b582020-03-24 11:58:55 +0100105
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100106suite('gr-change-view tests', () => {
107 let element: GrChangeView;
108
Frank Borden6988bdf2021-04-07 14:42:00 +0200109 let navigateToChangeStub: SinonStubbedMember<
110 typeof GerritNav.navigateToChange
111 >;
Dmitrii Filippov06117e82020-06-25 13:26:55 +0200112
113 suiteSetup(() => {
114 const kb = TestKeyboardShortcutBinder.push();
Dmitrii Filippov2dd0a442020-07-11 16:37:25 +0200115 kb.bindShortcut(Shortcut.SEND_REPLY, 'ctrl+enter');
116 kb.bindShortcut(Shortcut.REFRESH_CHANGE, 'shift+r');
117 kb.bindShortcut(Shortcut.OPEN_REPLY_DIALOG, 'a');
118 kb.bindShortcut(Shortcut.OPEN_DOWNLOAD_DIALOG, 'd');
119 kb.bindShortcut(Shortcut.TOGGLE_DIFF_MODE, 'm');
120 kb.bindShortcut(Shortcut.TOGGLE_CHANGE_STAR, 's');
121 kb.bindShortcut(Shortcut.UP_TO_DASHBOARD, 'u');
122 kb.bindShortcut(Shortcut.EXPAND_ALL_MESSAGES, 'x');
123 kb.bindShortcut(Shortcut.COLLAPSE_ALL_MESSAGES, 'z');
124 kb.bindShortcut(Shortcut.OPEN_DIFF_PREFS, ',');
125 kb.bindShortcut(Shortcut.EDIT_TOPIC, 't');
Dmitrii Filippov06117e82020-06-25 13:26:55 +0200126 });
127
128 suiteTeardown(() => {
129 TestKeyboardShortcutBinder.pop();
130 });
131
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100132 const ROBOT_COMMENTS_LIMIT = 10;
133
Tao Zhou18738b92020-05-04 19:44:51 +0200134 // TODO: should have a mock service to generate VALID fake data
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100135 const THREADS: CommentThread[] = [
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100136 {
137 comments: [
138 {
Dhruv Srivastava3dfaf362020-12-01 21:53:59 +0100139 path: '/COMMIT_MSG',
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100140 author: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100141 _account_id: 1000000 as AccountId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100142 name: 'user',
143 username: 'user',
144 },
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100145 patch_set: 2 as PatchSetNum,
146 robot_id: 'rb1' as RobotId,
147 id: 'ecf0b9fa_fe1a5f62' as UrlEncodedCommentId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100148 line: 5,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100149 updated: '2018-02-08 18:49:18.000000000' as Timestamp,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100150 message: 'test',
151 unresolved: true,
152 },
153 {
Dhruv Srivastava3dfaf362020-12-01 21:53:59 +0100154 path: '/COMMIT_MSG',
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100155 author: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100156 _account_id: 1000000 as AccountId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100157 name: 'user',
158 username: 'user',
159 },
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100160 patch_set: 4 as PatchSetNum,
161 id: 'ecf0b9fa_fe1a5f62_1' as UrlEncodedCommentId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100162 line: 5,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100163 updated: '2018-02-08 18:49:18.000000000' as Timestamp,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100164 message: 'test',
165 unresolved: true,
166 },
167 {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100168 id: '503008e2_0ab203ee' as UrlEncodedCommentId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100169 path: '/COMMIT_MSG',
170 line: 5,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100171 in_reply_to: 'ecf0b9fa_fe1a5f62' as UrlEncodedCommentId,
172 updated: '2018-02-13 22:48:48.018000000' as Timestamp,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100173 message: 'draft',
174 unresolved: false,
175 __draft: true,
176 __draftID: '0.m683trwff68',
177 __editing: false,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100178 patch_set: 2 as PatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100179 },
180 ],
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +0100181 patchNum: 4 as RevisionPatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100182 path: '/COMMIT_MSG',
183 line: 5,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100184 rootId: 'ecf0b9fa_fe1a5f62' as UrlEncodedCommentId,
Dhruv Srivastava794db3a2020-11-11 11:28:08 +0100185 commentSide: CommentSide.REVISION,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100186 },
187 {
188 comments: [
189 {
Dhruv Srivastava3dfaf362020-12-01 21:53:59 +0100190 path: '/COMMIT_MSG',
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100191 author: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100192 _account_id: 1000000 as AccountId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100193 name: 'user',
194 username: 'user',
195 },
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100196 patch_set: 3 as PatchSetNum,
197 id: 'ecf0b9fa_fe5f62' as UrlEncodedCommentId,
198 robot_id: 'rb2' as RobotId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100199 line: 5,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100200 updated: '2018-02-08 18:49:18.000000000' as Timestamp,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100201 message: 'test',
202 unresolved: true,
203 },
204 {
Dhruv Srivastava3dfaf362020-12-01 21:53:59 +0100205 path: 'test.txt',
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100206 author: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100207 _account_id: 1000000 as AccountId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100208 name: 'user',
209 username: 'user',
210 },
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100211 patch_set: 3 as PatchSetNum,
212 id: '09a9fb0a_1484e6cf' as UrlEncodedCommentId,
213 side: CommentSide.PARENT,
214 updated: '2018-02-13 22:47:19.000000000' as Timestamp,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100215 message: 'Some comment on another patchset.',
216 unresolved: false,
217 },
218 ],
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100219 patchNum: 3 as PatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100220 path: 'test.txt',
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100221 rootId: '09a9fb0a_1484e6cf' as UrlEncodedCommentId,
222 commentSide: CommentSide.PARENT,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100223 },
224 {
225 comments: [
226 {
Dhruv Srivastava3dfaf362020-12-01 21:53:59 +0100227 path: '/COMMIT_MSG',
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100228 author: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100229 _account_id: 1000000 as AccountId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100230 name: 'user',
231 username: 'user',
232 },
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100233 patch_set: 2 as PatchSetNum,
234 id: '8caddf38_44770ec1' as UrlEncodedCommentId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100235 line: 4,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100236 updated: '2018-02-13 22:48:40.000000000' as Timestamp,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100237 message: 'Another unresolved comment',
238 unresolved: true,
239 },
240 ],
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +0100241 patchNum: 2 as RevisionPatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100242 path: '/COMMIT_MSG',
243 line: 4,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100244 rootId: '8caddf38_44770ec1' as UrlEncodedCommentId,
Dhruv Srivastava794db3a2020-11-11 11:28:08 +0100245 commentSide: CommentSide.REVISION,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100246 },
247 {
248 comments: [
249 {
Dhruv Srivastava3dfaf362020-12-01 21:53:59 +0100250 path: '/COMMIT_MSG',
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100251 author: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100252 _account_id: 1000000 as AccountId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100253 name: 'user',
254 username: 'user',
255 },
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100256 patch_set: 2 as PatchSetNum,
257 id: 'scaddf38_44770ec1' as UrlEncodedCommentId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100258 line: 4,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100259 updated: '2018-02-14 22:48:40.000000000' as Timestamp,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100260 message: 'Yet another unresolved comment',
261 unresolved: true,
262 },
263 ],
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +0100264 patchNum: 2 as RevisionPatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100265 path: '/COMMIT_MSG',
266 line: 4,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100267 rootId: 'scaddf38_44770ec1' as UrlEncodedCommentId,
Dhruv Srivastava794db3a2020-11-11 11:28:08 +0100268 commentSide: CommentSide.REVISION,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100269 },
270 {
271 comments: [
272 {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100273 id: 'zcf0b9fa_fe1a5f62' as UrlEncodedCommentId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100274 path: '/COMMIT_MSG',
275 line: 6,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100276 updated: '2018-02-15 22:48:48.018000000' as Timestamp,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100277 message: 'resolved draft',
278 unresolved: false,
279 __draft: true,
280 __draftID: '0.m683trwff68',
281 __editing: false,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100282 patch_set: 2 as PatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100283 },
284 ],
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +0100285 patchNum: 4 as RevisionPatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100286 path: '/COMMIT_MSG',
287 line: 6,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100288 rootId: 'zcf0b9fa_fe1a5f62' as UrlEncodedCommentId,
Dhruv Srivastava794db3a2020-11-11 11:28:08 +0100289 commentSide: CommentSide.REVISION,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100290 },
291 {
292 comments: [
293 {
Dhruv Srivastava3dfaf362020-12-01 21:53:59 +0100294 path: '/COMMIT_MSG',
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100295 author: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100296 _account_id: 1000000 as AccountId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100297 name: 'user',
298 username: 'user',
299 },
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100300 patch_set: 4 as PatchSetNum,
301 id: 'rc1' as UrlEncodedCommentId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100302 line: 5,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100303 updated: '2019-02-08 18:49:18.000000000' as Timestamp,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100304 message: 'test',
305 unresolved: true,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100306 robot_id: 'rc1' as RobotId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100307 },
308 ],
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +0100309 patchNum: 4 as RevisionPatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100310 path: '/COMMIT_MSG',
311 line: 5,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100312 rootId: 'rc1' as UrlEncodedCommentId,
Dhruv Srivastava794db3a2020-11-11 11:28:08 +0100313 commentSide: CommentSide.REVISION,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100314 },
315 {
316 comments: [
317 {
Dhruv Srivastava3dfaf362020-12-01 21:53:59 +0100318 path: '/COMMIT_MSG',
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100319 author: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100320 _account_id: 1000000 as AccountId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100321 name: 'user',
322 username: 'user',
323 },
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100324 patch_set: 4 as PatchSetNum,
325 id: 'rc2' as UrlEncodedCommentId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100326 line: 5,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100327 updated: '2019-03-08 18:49:18.000000000' as Timestamp,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100328 message: 'test',
329 unresolved: true,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100330 robot_id: 'rc2' as RobotId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100331 },
332 {
Dhruv Srivastava3dfaf362020-12-01 21:53:59 +0100333 path: '/COMMIT_MSG',
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100334 author: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100335 _account_id: 1000000 as AccountId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100336 name: 'user',
337 username: 'user',
338 },
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100339 patch_set: 4 as PatchSetNum,
340 id: 'c2_1' as UrlEncodedCommentId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100341 line: 5,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100342 updated: '2019-03-08 18:49:18.000000000' as Timestamp,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100343 message: 'test',
344 unresolved: true,
345 },
346 ],
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +0100347 patchNum: 4 as RevisionPatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100348 path: '/COMMIT_MSG',
349 line: 5,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100350 rootId: 'rc2' as UrlEncodedCommentId,
Dhruv Srivastava794db3a2020-11-11 11:28:08 +0100351 commentSide: CommentSide.REVISION,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100352 },
353 ];
354
355 setup(() => {
Dmitrii Filippovf97fc6e2020-04-07 09:59:22 +0200356 // Since pluginEndpoints are global, must reset state.
357 _testOnly_resetEndpoints();
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200358 navigateToChangeStub = sinon.stub(GerritNav, 'navigateToChange');
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100359
Ben Rohlfs3a6ff7e2021-01-18 14:08:39 +0100360 stubRestApi('getConfig').returns(
361 Promise.resolve({
362 ...createServerInfo(),
363 user: {
364 ...createUserConfig(),
365 anonymous_coward_name: 'test coward name',
366 },
367 })
368 );
369 stubRestApi('getAccount').returns(Promise.resolve(undefined));
370 stubRestApi('getDiffComments').returns(Promise.resolve({}));
371 stubRestApi('getDiffRobotComments').returns(Promise.resolve({}));
372 stubRestApi('getDiffDrafts').returns(Promise.resolve({}));
Dmitrii Filippovacd39a22020-04-02 10:31:43 +0200373 element = fixture.instantiate();
Ben Rohlfsa5356e92021-05-07 11:06:17 +0200374 element._changeNum = TEST_NUMERIC_CHANGE_ID;
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200375 sinon.stub(element.$.actions, 'reload').returns(Promise.resolve());
Dhruv Srivastava12e2c992020-09-01 16:40:21 +0200376 getPluginLoader().loadPlugins([]);
Dmitrii Filippov5f25dc02020-04-07 18:49:00 +0200377 pluginApi.install(
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100378 plugin => {
379 plugin.registerDynamicCustomComponent(
380 'change-view-tab-header',
381 'gr-checks-change-view-tab-header-view'
382 );
383 plugin.registerDynamicCustomComponent(
384 'change-view-tab-content',
385 'gr-checks-view'
386 );
387 },
388 '0.1',
Ben Rohlfsef1dd592021-03-09 10:58:29 +0100389 'http://some/plugins/url.js'
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100390 );
391 });
392
Chris Pouceta2e173e2021-08-31 01:04:04 +0000393 teardown(async () => {
394 await flush();
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100395 });
396
Dhruv Srivastava163de6f2020-06-04 09:40:28 +0000397 test('_handleMessageAnchorTap', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100398 element._changeNum = 1 as NumericChangeId;
Dhruv Srivastava163de6f2020-06-04 09:40:28 +0000399 element._patchRange = {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100400 basePatchNum: ParentPatchSetNum,
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +0100401 patchNum: 1 as RevisionPatchSetNum,
Dhruv Srivastava163de6f2020-06-04 09:40:28 +0000402 };
Dhruv Srivastavada276592021-04-07 14:51:51 +0200403 element._change = createChangeViewChange();
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200404 const getUrlStub = sinon.stub(GerritNav, 'getUrlForChange');
405 const replaceStateStub = sinon.stub(history, 'replaceState');
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100406 element._handleMessageAnchorTap(
407 new CustomEvent('message-anchor-tap', {detail: {id: 'a12345'}})
408 );
Dhruv Srivastava163de6f2020-06-04 09:40:28 +0000409
410 assert.equal(getUrlStub.lastCall.args[4], '#message-a12345');
411 assert.isTrue(replaceStateStub.called);
412 });
413
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200414 test('_handleDiffAgainstBase', () => {
Dmitrii Filippov0695d402020-10-22 16:57:57 +0200415 element._change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +0200416 ...createChangeViewChange(),
Dmitrii Filippov0695d402020-10-22 16:57:57 +0200417 revisions: createRevisions(10),
418 };
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200419 element._patchRange = {
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +0100420 patchNum: 3 as RevisionPatchSetNum,
Dhruv Srivastava591b4902021-03-10 11:48:12 +0100421 basePatchNum: 1 as BasePatchSetNum,
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200422 };
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200423 sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100424 element._handleDiffAgainstBase(new CustomEvent('') as CustomKeyboardEvent);
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200425 assert(navigateToChangeStub.called);
426 const args = navigateToChangeStub.getCall(0).args;
Dmitrii Filippov77e5f7f2020-07-10 18:39:45 +0200427 assert.equal(args[0], element._change);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100428 assert.equal(args[1], 3 as PatchSetNum);
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200429 });
430
431 test('_handleDiffAgainstLatest', () => {
Dmitrii Filippov0695d402020-10-22 16:57:57 +0200432 element._change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +0200433 ...createChangeViewChange(),
Dmitrii Filippov0695d402020-10-22 16:57:57 +0200434 revisions: createRevisions(10),
435 };
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200436 element._patchRange = {
Dhruv Srivastava591b4902021-03-10 11:48:12 +0100437 basePatchNum: 1 as BasePatchSetNum,
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +0100438 patchNum: 3 as RevisionPatchSetNum,
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200439 };
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200440 sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100441 element._handleDiffAgainstLatest(
442 new CustomEvent('') as CustomKeyboardEvent
443 );
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200444 assert(navigateToChangeStub.called);
445 const args = navigateToChangeStub.getCall(0).args;
Dmitrii Filippov77e5f7f2020-07-10 18:39:45 +0200446 assert.equal(args[0], element._change);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100447 assert.equal(args[1], 10 as PatchSetNum);
Ben Rohlfs8e28ad82021-09-20 14:48:33 +0200448 assert.equal(args[2], 1 as BasePatchSetNum);
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200449 });
450
451 test('_handleDiffBaseAgainstLeft', () => {
Dmitrii Filippov0695d402020-10-22 16:57:57 +0200452 element._change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +0200453 ...createChangeViewChange(),
Dmitrii Filippov0695d402020-10-22 16:57:57 +0200454 revisions: createRevisions(10),
455 };
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200456 element._patchRange = {
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +0100457 patchNum: 3 as RevisionPatchSetNum,
Dhruv Srivastava591b4902021-03-10 11:48:12 +0100458 basePatchNum: 1 as BasePatchSetNum,
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200459 };
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200460 sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100461 element._handleDiffBaseAgainstLeft(
462 new CustomEvent('') as CustomKeyboardEvent
463 );
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200464 assert(navigateToChangeStub.called);
465 const args = navigateToChangeStub.getCall(0).args;
Dmitrii Filippov77e5f7f2020-07-10 18:39:45 +0200466 assert.equal(args[0], element._change);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100467 assert.equal(args[1], 1 as PatchSetNum);
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200468 });
469
470 test('_handleDiffRightAgainstLatest', () => {
Dmitrii Filippov0695d402020-10-22 16:57:57 +0200471 element._change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +0200472 ...createChangeViewChange(),
Dmitrii Filippov0695d402020-10-22 16:57:57 +0200473 revisions: createRevisions(10),
474 };
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200475 element._patchRange = {
Dhruv Srivastava591b4902021-03-10 11:48:12 +0100476 basePatchNum: 1 as BasePatchSetNum,
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +0100477 patchNum: 3 as RevisionPatchSetNum,
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200478 };
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200479 sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100480 element._handleDiffRightAgainstLatest(
481 new CustomEvent('') as CustomKeyboardEvent
482 );
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200483 assert(navigateToChangeStub.called);
484 const args = navigateToChangeStub.getCall(0).args;
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100485 assert.equal(args[1], 10 as PatchSetNum);
Ben Rohlfs8e28ad82021-09-20 14:48:33 +0200486 assert.equal(args[2], 3 as BasePatchSetNum);
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200487 });
488
489 test('_handleDiffBaseAgainstLatest', () => {
Dmitrii Filippov0695d402020-10-22 16:57:57 +0200490 element._change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +0200491 ...createChangeViewChange(),
Dmitrii Filippov0695d402020-10-22 16:57:57 +0200492 revisions: createRevisions(10),
493 };
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200494 element._patchRange = {
Dhruv Srivastava591b4902021-03-10 11:48:12 +0100495 basePatchNum: 1 as BasePatchSetNum,
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +0100496 patchNum: 3 as RevisionPatchSetNum,
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200497 };
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200498 sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100499 element._handleDiffBaseAgainstLatest(
500 new CustomEvent('') as CustomKeyboardEvent
501 );
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200502 assert(navigateToChangeStub.called);
503 const args = navigateToChangeStub.getCall(0).args;
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100504 assert.equal(args[1], 10 as PatchSetNum);
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200505 assert.isNotOk(args[2]);
506 });
507
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100508 suite('plugins adding to file tab', () => {
Chris Pouceta2e173e2021-08-31 01:04:04 +0000509 setup(async () => {
Ben Rohlfsa5356e92021-05-07 11:06:17 +0200510 element._changeNum = TEST_NUMERIC_CHANGE_ID;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100511 // Resolving it here instead of during setup() as other tests depend
512 // on flush() not being called during setup.
Chris Pouceta2e173e2021-08-31 01:04:04 +0000513 await flush();
Andrew Bonventre547b8ab2015-12-01 01:02:00 -0500514 });
515
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100516 test('plugin added tab shows up as a dynamic endpoint', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100517 assert(
518 element._dynamicTabHeaderEndpoints.includes(
519 'change-view-tab-header-url'
520 )
521 );
522 const primaryTabs = element.shadowRoot!.querySelector('#primaryTabs')!;
523 const paperTabs = primaryTabs.querySelectorAll<HTMLElement>('paper-tab');
Dhruv Srivastava929af7f2020-05-13 19:10:05 +0200524 // 4 Tabs are : Files, Comment Threads, Plugin, Findings
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100525 assert.equal(primaryTabs.querySelectorAll('paper-tab').length, 4);
526 assert.equal(paperTabs[2].dataset.name, 'change-view-tab-header-url');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100527 });
528
Chris Pouceta2e173e2021-08-31 01:04:04 +0000529 test('_setActivePrimaryTab switched tab correctly', async () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100530 element._setActivePrimaryTab(
531 new CustomEvent('', {
532 detail: {tab: 'change-view-tab-header-url'},
533 })
534 );
Chris Pouceta2e173e2021-08-31 01:04:04 +0000535 await flush();
536 assert.equal(element._activeTabs[0], 'change-view-tab-header-url');
Tao Zhou4fd32d52020-04-06 17:23:10 +0200537 });
538
Chris Pouceta2e173e2021-08-31 01:04:04 +0000539 test('show-primary-tab switched primary tab correctly', async () => {
Paladox none6b055dc2020-06-28 14:53:18 +0000540 element.dispatchEvent(
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100541 new CustomEvent('show-primary-tab', {
542 composed: true,
543 bubbles: true,
544 detail: {
545 tab: 'change-view-tab-header-url',
546 },
547 })
548 );
Chris Pouceta2e173e2021-08-31 01:04:04 +0000549 await flush();
550 assert.equal(element._activeTabs[0], 'change-view-tab-header-url');
Tao Zhou4fd32d52020-04-06 17:23:10 +0200551 });
552
Chris Pouceta2e173e2021-08-31 01:04:04 +0000553 test('param change should switch primary tab correctly', async () => {
Dmitrii Filippove903bbf2020-05-06 12:57:39 +0200554 assert.equal(element._activeTabs[0], PrimaryTab.FILES);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100555 const queryMap = new Map<string, string>();
Dmitrii Filippove903bbf2020-05-06 12:57:39 +0200556 queryMap.set('tab', PrimaryTab.FINDINGS);
Tao Zhou4fd32d52020-04-06 17:23:10 +0200557 // view is required
Tao Zhou4cd35cb2020-07-22 11:28:22 +0200558 element.params = {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100559 ...createAppElementChangeViewParams(),
560 ...element.params,
561 queryMap,
562 };
Chris Pouceta2e173e2021-08-31 01:04:04 +0000563 await flush();
564 assert.equal(element._activeTabs[0], PrimaryTab.FINDINGS);
Tao Zhou4fd32d52020-04-06 17:23:10 +0200565 });
566
Chris Pouceta2e173e2021-08-31 01:04:04 +0000567 test('invalid param change should not switch primary tab', async () => {
Dmitrii Filippove903bbf2020-05-06 12:57:39 +0200568 assert.equal(element._activeTabs[0], PrimaryTab.FILES);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100569 const queryMap = new Map<string, string>();
Tao Zhou4fd32d52020-04-06 17:23:10 +0200570 queryMap.set('tab', 'random');
571 // view is required
Tao Zhou4cd35cb2020-07-22 11:28:22 +0200572 element.params = {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100573 ...createAppElementChangeViewParams(),
574 ...element.params,
575 queryMap,
576 };
Chris Pouceta2e173e2021-08-31 01:04:04 +0000577 await flush();
578 assert.equal(element._activeTabs[0], PrimaryTab.FILES);
Kasper Nilssonf0743732016-10-18 13:01:10 -0700579 });
580
Chris Pouceta2e173e2021-08-31 01:04:04 +0000581 test('switching tab sets _selectedTabPluginEndpoint', async () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100582 const paperTabs = element.shadowRoot!.querySelector('#primaryTabs')!;
583 tap(paperTabs.querySelectorAll('paper-tab')[2]);
Chris Pouceta2e173e2021-08-31 01:04:04 +0000584 await flush();
585 assert.equal(
586 element._selectedTabPluginEndpoint,
587 'change-view-tab-content-url'
588 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100589 });
590 });
Paladox none7acb7ac2017-11-09 18:06:18 +0000591
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100592 suite('keyboard shortcuts', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100593 let clock: SinonFakeTimers;
Dhruv Srivastava4caf0842020-09-18 11:50:33 +0200594 setup(() => {
595 clock = sinon.useFakeTimers();
596 });
597
598 teardown(() => {
599 clock.restore();
600 sinon.restore();
601 });
602
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100603 test('t to add topic', () => {
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200604 const editStub = sinon.stub(element.$.metadata, 'editTopic');
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100605 pressAndReleaseKeyOn(element, 83, null, 't');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100606 assert(editStub.called);
607 });
608
609 test('S should toggle the CL star', () => {
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200610 const starStub = sinon.stub(element.$.changeStar, 'toggleStar');
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100611 pressAndReleaseKeyOn(element, 83, null, 's');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100612 assert(starStub.called);
613 });
614
Dhruv Srivastava4caf0842020-09-18 11:50:33 +0200615 test('toggle star is throttled', () => {
616 const starStub = sinon.stub(element.$.changeStar, 'toggleStar');
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100617 pressAndReleaseKeyOn(element, 83, null, 's');
Dhruv Srivastava4caf0842020-09-18 11:50:33 +0200618 assert(starStub.called);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100619 pressAndReleaseKeyOn(element, 83, null, 's');
Dhruv Srivastava4caf0842020-09-18 11:50:33 +0200620 assert.equal(starStub.callCount, 1);
621 clock.tick(1000);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100622 pressAndReleaseKeyOn(element, 83, null, 's');
Dhruv Srivastava4caf0842020-09-18 11:50:33 +0200623 assert.equal(starStub.callCount, 2);
624 });
625
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100626 test('U should navigate to root if no backPage set', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100627 const relativeNavStub = sinon.stub(GerritNav, 'navigateToRelativeUrl');
628 pressAndReleaseKeyOn(element, 85, null, 'u');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100629 assert.isTrue(relativeNavStub.called);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100630 assert.isTrue(
631 relativeNavStub.lastCall.calledWithExactly(GerritNav.getUrlForRoot())
632 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100633 });
634
635 test('U should navigate to backPage if set', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100636 const relativeNavStub = sinon.stub(GerritNav, 'navigateToRelativeUrl');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100637 element.backPage = '/dashboard/self';
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100638 pressAndReleaseKeyOn(element, 85, null, 'u');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100639 assert.isTrue(relativeNavStub.called);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100640 assert.isTrue(
641 relativeNavStub.lastCall.calledWithExactly('/dashboard/self')
642 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100643 });
644
Chris Pouceta2e173e2021-08-31 01:04:04 +0000645 test('A fires an error event when not logged in', async () => {
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200646 sinon.stub(element, '_getLoggedIn').returns(Promise.resolve(false));
647 const loggedInErrorSpy = sinon.spy();
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100648 element.addEventListener('show-auth-required', loggedInErrorSpy);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100649 pressAndReleaseKeyOn(element, 65, null, 'a');
Chris Pouceta2e173e2021-08-31 01:04:04 +0000650 await flush();
651 assert.isFalse(element.$.replyOverlay.opened);
652 assert.isTrue(loggedInErrorSpy.called);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100653 });
654
Chris Pouceta2e173e2021-08-31 01:04:04 +0000655 test('shift A does not open reply overlay', async () => {
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200656 sinon.stub(element, '_getLoggedIn').returns(Promise.resolve(true));
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100657 pressAndReleaseKeyOn(element, 65, 'shift', 'a');
Chris Pouceta2e173e2021-08-31 01:04:04 +0000658 await flush();
659 assert.isFalse(element.$.replyOverlay.opened);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100660 });
661
Chris Pouceta2e173e2021-08-31 01:04:04 +0000662 test('A toggles overlay when logged in', async () => {
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200663 sinon.stub(element, '_getLoggedIn').returns(Promise.resolve(true));
Dmitrii Filippov0695d402020-10-22 16:57:57 +0200664 element._change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +0200665 ...createChangeViewChange(),
Dmitrii Filippov0695d402020-10-22 16:57:57 +0200666 revisions: createRevisions(1),
667 messages: createChangeMessages(1),
668 };
Dmitrii Filippov77e5f7f2020-07-10 18:39:45 +0200669 element._change.labels = {};
Ben Rohlfs3a6ff7e2021-01-18 14:08:39 +0100670 stubRestApi('getChangeDetail').callsFake(() =>
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100671 Promise.resolve({
Dhruv Srivastavada276592021-04-07 14:51:51 +0200672 ...createChangeViewChange(),
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100673 // element has latest info
674 revisions: createRevisions(1),
675 messages: createChangeMessages(1),
676 current_revision: 'rev1' as CommitId,
677 })
678 );
Dmitrii Filippov77e5f7f2020-07-10 18:39:45 +0200679
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200680 const openSpy = sinon.spy(element, '_openReplyDialog');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100681
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100682 pressAndReleaseKeyOn(element, 65, null, 'a');
Chris Pouceta2e173e2021-08-31 01:04:04 +0000683 await flush();
684 assert.isTrue(element.$.replyOverlay.opened);
685 element.$.replyOverlay.close();
686 assert.isFalse(element.$.replyOverlay.opened);
687 assert(
688 openSpy.lastCall.calledWithExactly(
689 element.$.replyDialog.FocusTarget.ANY
690 ),
691 '_openReplyDialog should have been passed ANY'
692 );
693 assert.equal(openSpy.callCount, 1);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100694 });
695
696 test('fullscreen-overlay-opened hides content', () => {
697 element._loggedIn = true;
698 element._loading = false;
699 element._change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +0200700 ...createChangeViewChange(),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100701 labels: {},
702 actions: {
703 abandon: {
704 enabled: true,
705 label: 'Abandon',
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100706 method: HttpMethod.POST,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100707 title: 'Abandon',
708 },
709 },
710 };
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100711 const handlerSpy = sinon.spy(element, '_handleHideBackgroundContent');
Tao Zhou0a3c9862020-04-08 14:45:37 +0200712 element.$.replyDialog.dispatchEvent(
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100713 new CustomEvent('fullscreen-overlay-opened', {
714 composed: true,
715 bubbles: true,
716 })
717 );
718 assert.isTrue(handlerSpy.called);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100719 assert.isTrue(element.$.mainContent.classList.contains('overlayOpen'));
720 assert.equal(getComputedStyle(element.$.actions).display, 'flex');
721 });
722
723 test('fullscreen-overlay-closed shows content', () => {
724 element._loggedIn = true;
725 element._loading = false;
726 element._change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +0200727 ...createChangeViewChange(),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100728 labels: {},
729 actions: {
730 abandon: {
731 enabled: true,
732 label: 'Abandon',
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100733 method: HttpMethod.POST,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100734 title: 'Abandon',
735 },
736 },
737 };
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100738 const handlerSpy = sinon.spy(element, '_handleShowBackgroundContent');
Tao Zhou0a3c9862020-04-08 14:45:37 +0200739 element.$.replyDialog.dispatchEvent(
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100740 new CustomEvent('fullscreen-overlay-closed', {
741 composed: true,
742 bubbles: true,
743 })
744 );
745 assert.isTrue(handlerSpy.called);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100746 assert.isFalse(element.$.mainContent.classList.contains('overlayOpen'));
747 });
748
749 test('expand all messages when expand-diffs fired', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100750 const handleExpand = sinon.stub(element.$.fileList, 'expandAllDiffs');
Tao Zhou0a3c9862020-04-08 14:45:37 +0200751 element.$.fileListHeader.dispatchEvent(
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100752 new CustomEvent('expand-diffs', {
753 composed: true,
754 bubbles: true,
755 })
756 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100757 assert.isTrue(handleExpand.called);
758 });
759
760 test('collapse all messages when collapse-diffs fired', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100761 const handleCollapse = sinon.stub(element.$.fileList, 'collapseAllDiffs');
Tao Zhou0a3c9862020-04-08 14:45:37 +0200762 element.$.fileListHeader.dispatchEvent(
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100763 new CustomEvent('collapse-diffs', {
764 composed: true,
765 bubbles: true,
766 })
767 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100768 assert.isTrue(handleCollapse.called);
769 });
770
Chris Pouceta2e173e2021-08-31 01:04:04 +0000771 test('X should expand all messages', async () => {
772 await flush();
773 const handleExpand = sinon.stub(
774 element.messagesList!,
775 'handleExpandCollapse'
776 );
777 pressAndReleaseKeyOn(element, 88, null, 'x');
778 assert(handleExpand.calledWith(true));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100779 });
780
Chris Pouceta2e173e2021-08-31 01:04:04 +0000781 test('Z should collapse all messages', async () => {
782 await flush();
783 const handleExpand = sinon.stub(
784 element.messagesList!,
785 'handleExpandCollapse'
786 );
787 pressAndReleaseKeyOn(element, 90, null, 'z');
788 assert(handleExpand.calledWith(false));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100789 });
790
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100791 test('d should open download overlay', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100792 const stub = sinon
793 .stub(element.$.downloadOverlay, 'open')
794 .returns(Promise.resolve());
795 pressAndReleaseKeyOn(element, 68, null, 'd');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100796 assert.isTrue(stub.called);
797 });
798
799 test(', should open diff preferences', () => {
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200800 const stub = sinon.stub(
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100801 element.$.fileList.$.diffPreferencesDialog,
802 'open'
803 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100804 element._loggedIn = false;
805 element.disableDiffPrefs = true;
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100806 pressAndReleaseKeyOn(element, 188, null, ',');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100807 assert.isFalse(stub.called);
808
809 element._loggedIn = true;
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100810 pressAndReleaseKeyOn(element, 188, null, ',');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100811 assert.isFalse(stub.called);
812
813 element.disableDiffPrefs = false;
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100814 pressAndReleaseKeyOn(element, 188, null, ',');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100815 assert.isTrue(stub.called);
816 });
817
818 test('m should toggle diff mode', () => {
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200819 sinon.stub(element, 'shouldSuppressKeyboardShortcut').returns(false);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100820 const setModeStub = sinon.stub(
821 element.$.fileListHeader,
822 'setDiffViewMode'
823 );
824 const e = {preventDefault: () => {}} as CustomKeyboardEvent;
Ben Rohlfsd47eeb92020-09-25 10:29:48 +0200825 flush();
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100826
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100827 element.viewState.diffMode = DiffViewMode.SIDE_BY_SIDE;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100828 element._handleToggleDiffMode(e);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100829 assert.isTrue(setModeStub.calledWith(DiffViewMode.UNIFIED));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100830
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100831 element.viewState.diffMode = DiffViewMode.UNIFIED;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100832 element._handleToggleDiffMode(e);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100833 assert.isTrue(setModeStub.calledWith(DiffViewMode.SIDE_BY_SIDE));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100834 });
835 });
836
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100837 suite('thread list and change log tabs', () => {
838 setup(() => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100839 element._changeNum = TEST_NUMERIC_CHANGE_ID;
Kasper Nilsson9c1a3db2018-10-19 15:11:07 -0700840 element._patchRange = {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100841 basePatchNum: ParentPatchSetNum,
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +0100842 patchNum: 1 as RevisionPatchSetNum,
Kasper Nilsson9c1a3db2018-10-19 15:11:07 -0700843 };
Becky Siegel9b03dd22017-10-26 14:57:32 -0700844 element._change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +0200845 ...createChangeViewChange(),
Becky Siegel9b03dd22017-10-26 14:57:32 -0700846 revisions: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100847 rev2: createRevision(2),
848 rev1: createRevision(1),
849 rev13: createRevision(13),
850 rev3: createRevision(3),
Kasper Nilssonf0743732016-10-18 13:01:10 -0700851 },
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100852 current_revision: 'rev3' as CommitId,
853 status: ChangeStatus.NEW,
Kasper Nilssonf0743732016-10-18 13:01:10 -0700854 labels: {
855 test: {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100856 all: [],
Kasper Nilssonf0743732016-10-18 13:01:10 -0700857 default_value: 0,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100858 values: {},
Kasper Nilssonf0743732016-10-18 13:01:10 -0700859 approved: {},
860 },
861 },
862 };
Milutin Kristofic8803ea02020-12-09 23:34:39 +0100863 const relatedChanges = element.shadowRoot!.querySelector(
864 '#relatedChanges'
865 ) as GrRelatedChangesList;
866 sinon.stub(relatedChanges, 'reload');
Han-Wen Nienhuys577ce0a2021-08-11 12:11:17 +0200867 sinon.stub(element, 'loadData').returns(Promise.resolve());
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200868 sinon.spy(element, '_paramsChanged');
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100869 element.params = createAppElementChangeViewParams();
Kasper Nilsson34a5d892018-04-11 11:10:53 -0700870 });
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100871 });
872
873 suite('Findings comment tab', () => {
Frank Borden0a05fa12021-08-09 13:50:52 +0200874 setup(async () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100875 element._changeNum = TEST_NUMERIC_CHANGE_ID;
Kasper Nilssonbbd28672018-08-01 10:23:23 -0700876 element._change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +0200877 ...createChangeViewChange(),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100878 revisions: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100879 rev2: createRevision(2),
880 rev1: createRevision(1),
881 rev13: createRevision(13),
882 rev3: createRevision(3),
883 rev4: createRevision(4),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100884 },
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100885 current_revision: 'rev4' as CommitId,
Kasper Nilssonbbd28672018-08-01 10:23:23 -0700886 };
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100887 element._commentThreads = THREADS;
Frank Borden0a05fa12021-08-09 13:50:52 +0200888 await flush();
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100889 const paperTabs = element.shadowRoot!.querySelector('#primaryTabs')!;
890 tap(paperTabs.querySelectorAll('paper-tab')[3]);
Frank Borden0a05fa12021-08-09 13:50:52 +0200891 await flush();
Kasper Nilssonbbd28672018-08-01 10:23:23 -0700892 });
Milutin Kristofic7a86db12019-08-07 15:26:13 +0200893
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100894 test('robot comments count per patchset', () => {
895 const count = element._robotCommentCountPerPatchSet(THREADS);
896 const expectedCount = {
897 2: 1,
898 3: 1,
899 4: 2,
900 };
901 assert.deepEqual(count, expectedCount);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100902 assert.equal(
903 element._computeText(createRevision(2), THREADS),
904 'Patchset 2 (1 finding)'
905 );
906 assert.equal(
907 element._computeText(createRevision(4), THREADS),
908 'Patchset 4 (2 findings)'
909 );
910 assert.equal(
911 element._computeText(createRevision(5), THREADS),
912 'Patchset 5'
913 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100914 });
Milutin Kristofic7a86db12019-08-07 15:26:13 +0200915
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100916 test('only robot comments are rendered', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100917 assert.equal(element._robotCommentThreads!.length, 2);
918 assert.equal(
919 (element._robotCommentThreads![0].comments[0] as UIRobot).robot_id,
920 'rc1'
921 );
922 assert.equal(
923 (element._robotCommentThreads![1].comments[0] as UIRobot).robot_id,
924 'rc2'
925 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100926 });
927
Chris Pouceta2e173e2021-08-31 01:04:04 +0000928 test('changing patchsets resets robot comments', async () => {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100929 element.set('_change.current_revision', 'rev3');
Chris Pouceta2e173e2021-08-31 01:04:04 +0000930 await flush();
931 assert.equal(element._robotCommentThreads!.length, 1);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100932 });
933
934 test('Show more button is hidden', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100935 assert.isNull(element.shadowRoot!.querySelector('.show-robot-comments'));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100936 });
937
938 suite('robot comments show more button', () => {
Chris Pouceta2e173e2021-08-31 01:04:04 +0000939 setup(async () => {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100940 const arr = [];
941 for (let i = 0; i <= 30; i++) {
942 arr.push(...THREADS);
943 }
944 element._commentThreads = arr;
Chris Pouceta2e173e2021-08-31 01:04:04 +0000945 await flush();
Milutin Kristofic7a86db12019-08-07 15:26:13 +0200946 });
947
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100948 test('Show more button is rendered', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100949 assert.isOk(element.shadowRoot!.querySelector('.show-robot-comments'));
950 assert.equal(
951 element._robotCommentThreads!.length,
952 ROBOT_COMMENTS_LIMIT
953 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100954 });
955
Chris Pouceta2e173e2021-08-31 01:04:04 +0000956 test('Clicking show more button renders all comments', async () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100957 tap(element.shadowRoot!.querySelector('.show-robot-comments')!);
Chris Pouceta2e173e2021-08-31 01:04:04 +0000958 await flush();
959 assert.equal(element._robotCommentThreads!.length, 62);
Milutin Kristofic7a86db12019-08-07 15:26:13 +0200960 });
961 });
Andrew Bonventre547b8ab2015-12-01 01:02:00 -0500962 });
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100963
964 test('reply button is not visible when logged out', () => {
965 assert.equal(getComputedStyle(element.$.replyBtn).display, 'none');
966 element._loggedIn = true;
967 assert.notEqual(getComputedStyle(element.$.replyBtn).display, 'none');
968 });
969
970 test('download tap calls _handleOpenDownloadDialog', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100971 const openDialogStub = sinon.stub(element, '_handleOpenDownloadDialog');
Tao Zhou0a3c9862020-04-08 14:45:37 +0200972 element.$.actions.dispatchEvent(
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100973 new CustomEvent('download-tap', {
974 composed: true,
975 bubbles: true,
976 })
977 );
978 assert.isTrue(openDialogStub.called);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100979 });
980
Chris Pouceta2e173e2021-08-31 01:04:04 +0000981 test('fetches the server config on attached', async () => {
982 await flush();
983 assert.equal(
984 element._serverConfig!.user.anonymous_coward_name,
985 'test coward name'
986 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100987 });
988
989 test('_changeStatuses', () => {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100990 element._loading = false;
991 element._change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +0200992 ...createChangeViewChange(),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100993 revisions: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100994 rev2: createRevision(2),
995 rev1: createRevision(1),
996 rev13: createRevision(13),
997 rev3: createRevision(3),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100998 },
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100999 current_revision: 'rev3' as CommitId,
Dmitrii Filippov3bf68892020-07-12 00:19:10 +02001000 status: ChangeStatus.MERGED,
1001 work_in_progress: true,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001002 labels: {
1003 test: {
1004 all: [],
1005 default_value: 0,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001006 values: {},
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001007 approved: {},
1008 },
1009 },
1010 };
1011 element._mergeable = true;
Frank Borden88603372021-06-02 16:50:51 +02001012 const expectedStatuses = [ChangeStates.MERGED, ChangeStates.WIP];
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001013 assert.deepEqual(element._changeStatuses, expectedStatuses);
Ben Rohlfsd47eeb92020-09-25 10:29:48 +02001014 flush();
Chris Poucetcaeea1b2021-08-19 22:12:56 +00001015 const statusChips =
1016 element.shadowRoot!.querySelectorAll('gr-change-status');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001017 assert.equal(statusChips.length, 2);
1018 });
1019
Dhruv Srivastava69a51732021-04-14 18:23:00 +02001020 suite('ChangeStatus revert', () => {
Chris Pouceta2e173e2021-08-31 01:04:04 +00001021 test('do not show any chip if no revert created', async () => {
Dhruv Srivastava4b634ac2021-04-19 12:18:53 +02001022 const change = {
1023 ...createChange(),
1024 messages: createChangeMessages(2),
1025 };
1026 const getChangeStub = stubRestApi('getChange');
1027 getChangeStub.onFirstCall().returns(
1028 Promise.resolve({
1029 ...createChange(),
1030 })
1031 );
1032 getChangeStub.onSecondCall().returns(
1033 Promise.resolve({
1034 ...createChange(),
1035 })
1036 );
1037 element._change = change;
1038 element._mergeable = true;
1039 element._submitEnabled = true;
Chris Pouceta2e173e2021-08-31 01:04:04 +00001040 await flush();
Dhruv Srivastava4b634ac2021-04-19 12:18:53 +02001041 element.computeRevertSubmitted(element._change);
Chris Pouceta2e173e2021-08-31 01:04:04 +00001042 await flush();
1043 assert.isFalse(
1044 element._changeStatuses?.includes(ChangeStates.REVERT_SUBMITTED)
1045 );
1046 assert.isFalse(
1047 element._changeStatuses?.includes(ChangeStates.REVERT_CREATED)
1048 );
Dhruv Srivastava4b634ac2021-04-19 12:18:53 +02001049 });
1050
Chris Pouceta2e173e2021-08-31 01:04:04 +00001051 test('do not show any chip if all reverts are abandoned', async () => {
Dhruv Srivastava4a557f22021-04-21 14:10:09 +02001052 const change = {
1053 ...createChange(),
1054 messages: createChangeMessages(2),
1055 };
1056 change.messages[0].message = 'Created a revert of this change as 12345';
1057 change.messages[0].tag = MessageTag.TAG_REVERT as ReviewInputTag;
1058
1059 change.messages[1].message = 'Created a revert of this change as 23456';
1060 change.messages[1].tag = MessageTag.TAG_REVERT as ReviewInputTag;
1061
1062 const getChangeStub = stubRestApi('getChange');
1063 getChangeStub.onFirstCall().returns(
1064 Promise.resolve({
1065 ...createChange(),
1066 status: ChangeStatus.ABANDONED,
1067 })
1068 );
1069 getChangeStub.onSecondCall().returns(
1070 Promise.resolve({
1071 ...createChange(),
1072 status: ChangeStatus.ABANDONED,
1073 })
1074 );
1075 element._change = change;
1076 element._mergeable = true;
1077 element._submitEnabled = true;
Chris Pouceta2e173e2021-08-31 01:04:04 +00001078 await flush();
Dhruv Srivastava4a557f22021-04-21 14:10:09 +02001079 element.computeRevertSubmitted(element._change);
Chris Pouceta2e173e2021-08-31 01:04:04 +00001080 await flush();
1081 assert.isFalse(
1082 element._changeStatuses?.includes(ChangeStates.REVERT_SUBMITTED)
1083 );
1084 assert.isFalse(
1085 element._changeStatuses?.includes(ChangeStates.REVERT_CREATED)
1086 );
Dhruv Srivastava4a557f22021-04-21 14:10:09 +02001087 });
1088
Chris Pouceta2e173e2021-08-31 01:04:04 +00001089 test('show revert created if no revert is merged', async () => {
Dhruv Srivastava69a51732021-04-14 18:23:00 +02001090 const change = {
1091 ...createChange(),
1092 messages: createChangeMessages(2),
1093 };
1094 change.messages[0].message = 'Created a revert of this change as 12345';
1095 change.messages[0].tag = MessageTag.TAG_REVERT as ReviewInputTag;
Dhruv Srivastava4a557f22021-04-21 14:10:09 +02001096
1097 change.messages[1].message = 'Created a revert of this change as 23456';
1098 change.messages[1].tag = MessageTag.TAG_REVERT as ReviewInputTag;
1099
Dhruv Srivastava69a51732021-04-14 18:23:00 +02001100 const getChangeStub = stubRestApi('getChange');
1101 getChangeStub.onFirstCall().returns(
1102 Promise.resolve({
1103 ...createChange(),
1104 })
1105 );
1106 getChangeStub.onSecondCall().returns(
1107 Promise.resolve({
1108 ...createChange(),
1109 })
1110 );
1111 element._change = change;
1112 element._mergeable = true;
1113 element._submitEnabled = true;
Chris Pouceta2e173e2021-08-31 01:04:04 +00001114 await flush();
Dhruv Srivastava69a51732021-04-14 18:23:00 +02001115 element.computeRevertSubmitted(element._change);
Chris Pouceta2e173e2021-08-31 01:04:04 +00001116 await flush();
1117 assert.isFalse(
1118 element._changeStatuses?.includes(ChangeStates.REVERT_SUBMITTED)
1119 );
1120 assert.isTrue(
1121 element._changeStatuses?.includes(ChangeStates.REVERT_CREATED)
1122 );
Dhruv Srivastava69a51732021-04-14 18:23:00 +02001123 });
1124
Chris Pouceta2e173e2021-08-31 01:04:04 +00001125 test('show revert submitted if revert is merged', async () => {
Dhruv Srivastava69a51732021-04-14 18:23:00 +02001126 const change = {
1127 ...createChange(),
1128 messages: createChangeMessages(2),
1129 };
1130 change.messages[0].message = 'Created a revert of this change as 12345';
1131 change.messages[0].tag = MessageTag.TAG_REVERT as ReviewInputTag;
1132 const getChangeStub = stubRestApi('getChange');
1133 getChangeStub.onFirstCall().returns(
1134 Promise.resolve({
1135 ...createChange(),
1136 status: ChangeStatus.MERGED,
1137 })
1138 );
1139 getChangeStub.onSecondCall().returns(
1140 Promise.resolve({
1141 ...createChange(),
1142 })
1143 );
1144 element._change = change;
1145 element._mergeable = true;
1146 element._submitEnabled = true;
Chris Pouceta2e173e2021-08-31 01:04:04 +00001147 await flush();
Dhruv Srivastava69a51732021-04-14 18:23:00 +02001148 element.computeRevertSubmitted(element._change);
Chris Pouceta2e173e2021-08-31 01:04:04 +00001149 await flush();
1150 assert.isFalse(
1151 element._changeStatuses?.includes(ChangeStates.REVERT_CREATED)
1152 );
1153 assert.isTrue(
1154 element._changeStatuses?.includes(ChangeStates.REVERT_SUBMITTED)
1155 );
Dhruv Srivastava69a51732021-04-14 18:23:00 +02001156 });
1157 });
1158
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001159 test('diff preferences open when open-diff-prefs is fired', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001160 const overlayOpenStub = sinon.stub(element.$.fileList, 'openDiffPrefs');
Tao Zhou0a3c9862020-04-08 14:45:37 +02001161 element.$.fileListHeader.dispatchEvent(
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001162 new CustomEvent('open-diff-prefs', {
1163 composed: true,
1164 bubbles: true,
1165 })
1166 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001167 assert.isTrue(overlayOpenStub.called);
1168 });
1169
1170 test('_prepareCommitMsgForLinkify', () => {
1171 let commitMessage = 'R=test@google.com';
1172 let result = element._prepareCommitMsgForLinkify(commitMessage);
1173 assert.equal(result, 'R=\u200Btest@google.com');
1174
1175 commitMessage = 'R=test@google.com\nR=test@google.com';
1176 result = element._prepareCommitMsgForLinkify(commitMessage);
1177 assert.equal(result, 'R=\u200Btest@google.com\nR=\u200Btest@google.com');
1178
1179 commitMessage = 'CC=test@google.com';
1180 result = element._prepareCommitMsgForLinkify(commitMessage);
1181 assert.equal(result, 'CC=\u200Btest@google.com');
David Ostrovskya2401c12020-05-03 19:29:26 +02001182 });
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001183
1184 test('_isSubmitEnabled', () => {
1185 assert.isFalse(element._isSubmitEnabled({}));
1186 assert.isFalse(element._isSubmitEnabled({submit: {}}));
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001187 assert.isTrue(element._isSubmitEnabled({submit: {enabled: true}}));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001188 });
1189
1190 test('_reload is called when an approved label is removed', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001191 const vote: ApprovalInfo = {
1192 ...createApproval(),
1193 _account_id: 1 as AccountId,
1194 name: 'bojack',
1195 value: 1,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001196 };
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001197 element._changeNum = TEST_NUMERIC_CHANGE_ID;
1198 element._patchRange = {
1199 basePatchNum: ParentPatchSetNum,
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01001200 patchNum: 1 as RevisionPatchSetNum,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001201 };
1202 const change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +02001203 ...createChangeViewChange(),
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001204 owner: createAccountWithIdNameAndEmail(),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001205 revisions: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001206 rev2: createRevision(2),
1207 rev1: createRevision(1),
1208 rev13: createRevision(13),
1209 rev3: createRevision(3),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001210 },
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001211 current_revision: 'rev3' as CommitId,
1212 status: ChangeStatus.NEW,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001213 labels: {
1214 test: {
1215 all: [vote],
1216 default_value: 0,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001217 values: {},
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001218 approved: {},
1219 },
1220 },
1221 };
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001222 element._change = change;
Ben Rohlfsd47eeb92020-09-25 10:29:48 +02001223 flush();
Ben Rohlfs66367b62021-04-30 10:06:32 +02001224 const reloadStub = sinon.stub(element, 'loadData');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001225 element.splice('_change.labels.test.all', 0, 1);
1226 assert.isFalse(reloadStub.called);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001227 change.labels.test.all.push(vote);
1228 change.labels.test.all.push(vote);
1229 change.labels.test.approved = vote;
Ben Rohlfsd47eeb92020-09-25 10:29:48 +02001230 flush();
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001231 element.splice('_change.labels.test.all', 0, 2);
1232 assert.isTrue(reloadStub.called);
1233 assert.isTrue(reloadStub.calledOnce);
1234 });
1235
1236 test('reply button has updated count when there are drafts', () => {
1237 const getLabel = element._computeReplyButtonLabel;
1238
Dhruv Srivastavadb2ab602021-06-24 15:20:29 +02001239 assert.equal(getLabel(undefined, false), 'Reply');
1240 assert.equal(getLabel(undefined, true), 'Reply');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001241
Dhruv Srivastavadb2ab602021-06-24 15:20:29 +02001242 let drafts = {};
1243 assert.equal(getLabel(drafts, false), 'Reply');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001244
Dhruv Srivastavadb2ab602021-06-24 15:20:29 +02001245 drafts = {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001246 'file1.txt': [{}],
1247 'file2.txt': [{}, {}],
1248 };
Dhruv Srivastavadb2ab602021-06-24 15:20:29 +02001249 assert.equal(getLabel(drafts, false), 'Reply (3)');
1250 assert.equal(getLabel(drafts, true), 'Start Review (3)');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001251 });
1252
1253 test('change num change', () => {
Ben Rohlfs3a6ff7e2021-01-18 14:08:39 +01001254 const change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +02001255 ...createChangeViewChange(),
Ben Rohlfs3a6ff7e2021-01-18 14:08:39 +01001256 labels: {},
1257 } as ParsedChangeInfo;
1258 stubRestApi('getChangeDetail').returns(Promise.resolve(change));
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001259 element._changeNum = undefined;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001260 element._patchRange = {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001261 basePatchNum: ParentPatchSetNum,
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01001262 patchNum: 2 as RevisionPatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001263 };
Ben Rohlfs3a6ff7e2021-01-18 14:08:39 +01001264 element._change = change;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001265 element.viewState.changeNum = null;
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001266 element.viewState.diffMode = DiffViewMode.UNIFIED;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001267 assert.equal(element.viewState.numFilesShown, 200);
1268 assert.equal(element._numFilesShown, 200);
1269 element._numFilesShown = 150;
Ben Rohlfsd47eeb92020-09-25 10:29:48 +02001270 flush();
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001271 assert.equal(element.viewState.diffMode, DiffViewMode.UNIFIED);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001272 assert.equal(element.viewState.numFilesShown, 150);
1273
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001274 element._changeNum = 1 as NumericChangeId;
1275 element.params = {
1276 ...createAppElementChangeViewParams(),
1277 changeNum: 1 as NumericChangeId,
1278 };
Ben Rohlfsd47eeb92020-09-25 10:29:48 +02001279 flush();
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001280 assert.equal(element.viewState.diffMode, DiffViewMode.UNIFIED);
1281 assert.equal(element.viewState.changeNum, 1);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001282
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001283 element._changeNum = 2 as NumericChangeId;
1284 element.params = {
1285 ...createAppElementChangeViewParams(),
1286 changeNum: 2 as NumericChangeId,
1287 };
Ben Rohlfsd47eeb92020-09-25 10:29:48 +02001288 flush();
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001289 assert.equal(element.viewState.diffMode, DiffViewMode.UNIFIED);
1290 assert.equal(element.viewState.changeNum, 2);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001291 assert.equal(element.viewState.numFilesShown, 200);
1292 assert.equal(element._numFilesShown, 200);
1293 });
1294
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001295 test('_setDiffViewMode is called with reset when new change is loaded', () => {
1296 const setDiffViewModeStub = sinon.stub(element, '_setDiffViewMode');
1297 element.viewState = {changeNum: 1 as NumericChangeId};
1298 element._changeNum = 2 as NumericChangeId;
1299 element._resetFileListViewState();
1300 assert.isTrue(setDiffViewModeStub.calledWithExactly(true));
1301 });
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001302
1303 test('diffViewMode is propagated from file list header', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001304 element.viewState = {diffMode: DiffViewMode.UNIFIED};
1305 element.$.fileListHeader.diffViewMode = DiffViewMode.SIDE_BY_SIDE;
1306 assert.equal(element.viewState.diffMode, DiffViewMode.SIDE_BY_SIDE);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001307 });
1308
Chris Pouceta2e173e2021-08-31 01:04:04 +00001309 test('diffMode defaults to side by side without preferences', async () => {
Ben Rohlfs3a6ff7e2021-01-18 14:08:39 +01001310 stubRestApi('getPreferences').returns(Promise.resolve(createPreferences()));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001311 // No user prefs or diff view mode set.
1312
Chris Pouceta2e173e2021-08-31 01:04:04 +00001313 await element._setDiffViewMode()!;
1314 assert.equal(element.viewState.diffMode, DiffViewMode.SIDE_BY_SIDE);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001315 });
1316
Chris Pouceta2e173e2021-08-31 01:04:04 +00001317 test('diffMode defaults to preference when not already set', async () => {
Ben Rohlfs3a6ff7e2021-01-18 14:08:39 +01001318 stubRestApi('getPreferences').returns(
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001319 Promise.resolve({
1320 ...createPreferences(),
1321 default_diff_view: DiffViewMode.UNIFIED,
1322 })
1323 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001324
Chris Pouceta2e173e2021-08-31 01:04:04 +00001325 await element._setDiffViewMode()!;
1326 assert.equal(element.viewState.diffMode, DiffViewMode.UNIFIED);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001327 });
1328
Chris Pouceta2e173e2021-08-31 01:04:04 +00001329 test('existing diffMode overrides preference', async () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001330 element.viewState.diffMode = DiffViewMode.SIDE_BY_SIDE;
Ben Rohlfs3a6ff7e2021-01-18 14:08:39 +01001331 stubRestApi('getPreferences').returns(
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001332 Promise.resolve({
1333 ...createPreferences(),
1334 default_diff_view: DiffViewMode.UNIFIED,
1335 })
1336 );
Chris Pouceta2e173e2021-08-31 01:04:04 +00001337 await element._setDiffViewMode()!;
1338 assert.equal(element.viewState.diffMode, DiffViewMode.SIDE_BY_SIDE);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001339 });
1340
Ben Rohlfs71a8dee2021-06-22 10:06:15 +02001341 test('don’t reload entire page when patchRange changes', async () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001342 const reloadStub = sinon
Ben Rohlfs66367b62021-04-30 10:06:32 +02001343 .stub(element, 'loadData')
Han-Wen Nienhuys577ce0a2021-08-11 12:11:17 +02001344 .callsFake(() => Promise.resolve());
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001345 const reloadPatchDependentStub = sinon
1346 .stub(element, '_reloadPatchNumDependentResources')
Dhruv Srivastava09a1b5a2021-01-20 09:28:15 +01001347 .callsFake(() => Promise.resolve([undefined, undefined, undefined]));
Dhruv Srivastava105fa212021-09-03 12:16:30 +00001348 flush();
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +02001349 const collapseStub = sinon.stub(element.$.fileList, 'collapseAllDiffs');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001350
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001351 const value: AppElementChangeViewParams = {
1352 ...createAppElementChangeViewParams(),
1353 view: GerritView.CHANGE,
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01001354 patchNum: 1 as RevisionPatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001355 };
Ben Rohlfs71a8dee2021-06-22 10:06:15 +02001356 element.params = value;
1357 await flush();
Dhruv Srivastava105fa212021-09-03 12:16:30 +00001358 assert.isTrue(reloadStub.calledOnce);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001359
1360 element._initialLoadComplete = true;
Ben Rohlfsd03b9b12021-05-12 12:04:50 +02001361 element._change = {
1362 ...createChangeViewChange(),
1363 revisions: {
1364 rev1: createRevision(1),
1365 rev2: createRevision(2),
1366 },
1367 };
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001368
Dhruv Srivastava591b4902021-03-10 11:48:12 +01001369 value.basePatchNum = 1 as BasePatchSetNum;
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01001370 value.patchNum = 2 as RevisionPatchSetNum;
Ben Rohlfs71a8dee2021-06-22 10:06:15 +02001371 element.params = {...value};
1372 await flush();
Dhruv Srivastava105fa212021-09-03 12:16:30 +00001373 assert.isFalse(reloadStub.calledTwice);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001374 assert.isTrue(reloadPatchDependentStub.calledOnce);
Dhruv Srivastava105fa212021-09-03 12:16:30 +00001375 assert.isTrue(collapseStub.calledTwice);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001376 });
1377
Ben Rohlfs71a8dee2021-06-22 10:06:15 +02001378 test('reload ported comments when patchNum changes', async () => {
Han-Wen Nienhuys577ce0a2021-08-11 12:11:17 +02001379 sinon.stub(element, 'loadData').callsFake(() => Promise.resolve());
Dhruv Srivastava09a1b5a2021-01-20 09:28:15 +01001380 sinon.stub(element, '_getCommitInfo');
1381 sinon.stub(element.$.fileList, 'reload');
Milutin Kristofic8803ea02020-12-09 23:34:39 +01001382 flush();
Dhruv Srivastava09a1b5a2021-01-20 09:28:15 +01001383 const reloadPortedCommentsStub = sinon.stub(
1384 element.$.commentAPI,
1385 'reloadPortedComments'
1386 );
Dhruv Srivastava09a1b5a2021-01-20 09:28:15 +01001387 sinon.stub(element.$.fileList, 'collapseAllDiffs');
1388
1389 const value: AppElementChangeViewParams = {
1390 ...createAppElementChangeViewParams(),
1391 view: GerritView.CHANGE,
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01001392 patchNum: 1 as RevisionPatchSetNum,
Dhruv Srivastava09a1b5a2021-01-20 09:28:15 +01001393 };
Ben Rohlfs71a8dee2021-06-22 10:06:15 +02001394 element.params = value;
1395 await flush();
Dhruv Srivastava09a1b5a2021-01-20 09:28:15 +01001396
1397 element._initialLoadComplete = true;
Ben Rohlfsd03b9b12021-05-12 12:04:50 +02001398 element._change = {
1399 ...createChangeViewChange(),
1400 revisions: {
1401 rev1: createRevision(1),
1402 rev2: createRevision(2),
1403 },
1404 };
Dhruv Srivastava09a1b5a2021-01-20 09:28:15 +01001405
Dhruv Srivastava591b4902021-03-10 11:48:12 +01001406 value.basePatchNum = 1 as BasePatchSetNum;
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01001407 value.patchNum = 2 as RevisionPatchSetNum;
Ben Rohlfs71a8dee2021-06-22 10:06:15 +02001408 element.params = {...value};
1409 await flush();
Dhruv Srivastava09a1b5a2021-01-20 09:28:15 +01001410 assert.isTrue(reloadPortedCommentsStub.calledOnce);
1411 });
1412
Dhruv Srivastava105fa212021-09-03 12:16:30 +00001413 test('reload entire page when patchRange doesnt change', async () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001414 const reloadStub = sinon
Ben Rohlfs66367b62021-04-30 10:06:32 +02001415 .stub(element, 'loadData')
Han-Wen Nienhuys577ce0a2021-08-11 12:11:17 +02001416 .callsFake(() => Promise.resolve());
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +02001417 const collapseStub = sinon.stub(element.$.fileList, 'collapseAllDiffs');
Chris Poucetcaeea1b2021-08-19 22:12:56 +00001418 const value: AppElementChangeViewParams =
1419 createAppElementChangeViewParams();
Ben Rohlfs71a8dee2021-06-22 10:06:15 +02001420 element.params = value;
1421 await flush();
Dhruv Srivastava105fa212021-09-03 12:16:30 +00001422 assert.isTrue(reloadStub.calledOnce);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001423 element._initialLoadComplete = true;
Ben Rohlfs71a8dee2021-06-22 10:06:15 +02001424 element.params = {...value};
1425 await flush();
Dhruv Srivastava105fa212021-09-03 12:16:30 +00001426 assert.isTrue(reloadStub.calledTwice);
1427 assert.isTrue(collapseStub.calledTwice);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001428 });
1429
Ben Rohlfs71a8dee2021-06-22 10:06:15 +02001430 test('do not handle new change numbers', async () => {
1431 const recreateSpy = sinon.spy();
1432 element.addEventListener('recreate-change-view', recreateSpy);
1433
Chris Poucetcaeea1b2021-08-19 22:12:56 +00001434 const value: AppElementChangeViewParams =
1435 createAppElementChangeViewParams();
Ben Rohlfs71a8dee2021-06-22 10:06:15 +02001436 element.params = value;
1437 await flush();
1438 assert.isFalse(recreateSpy.calledOnce);
1439
1440 value.changeNum = 555111333 as NumericChangeId;
1441 element.params = {...value};
1442 await flush();
1443 assert.isTrue(recreateSpy.calledOnce);
1444 });
1445
Chris Pouceta2e173e2021-08-31 01:04:04 +00001446 test('related changes are not updated after other action', async () => {
Han-Wen Nienhuys577ce0a2021-08-11 12:11:17 +02001447 sinon.stub(element, 'loadData').callsFake(() => Promise.resolve());
Chris Pouceta2e173e2021-08-31 01:04:04 +00001448 await flush();
Milutin Kristofic8803ea02020-12-09 23:34:39 +01001449 const relatedChanges = element.shadowRoot!.querySelector(
1450 '#relatedChanges'
1451 ) as GrRelatedChangesList;
1452 sinon.stub(relatedChanges, 'reload');
Chris Pouceta2e173e2021-08-31 01:04:04 +00001453 await element.loadData(true);
1454 assert.isFalse(navigateToChangeStub.called);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001455 });
1456
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001457 test('_computeCopyTextForTitle', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001458 const change: ChangeInfo = {
Dhruv Srivastavada276592021-04-07 14:51:51 +02001459 ...createChangeViewChange(),
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001460 _number: 123 as NumericChangeId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001461 subject: 'test subject',
1462 revisions: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001463 rev1: createRevision(1),
1464 rev3: createRevision(3),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001465 },
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001466 current_revision: 'rev3' as CommitId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001467 };
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001468 sinon.stub(GerritNav, 'getUrlForChange').returns('/change/123');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001469 assert.equal(
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001470 element._computeCopyTextForTitle(change),
1471 `123: test subject | http://${location.host}/change/123`
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001472 );
1473 });
1474
1475 test('get latest revision', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001476 let change: ChangeInfo = {
1477 ...createChange(),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001478 revisions: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001479 rev1: createRevision(1),
1480 rev3: createRevision(3),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001481 },
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001482 current_revision: 'rev3' as CommitId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001483 };
1484 assert.equal(element._getLatestRevisionSHA(change), 'rev3');
1485 change = {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001486 ...createChange(),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001487 revisions: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001488 rev1: createRevision(1),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001489 },
Dhruv Srivastavada276592021-04-07 14:51:51 +02001490 current_revision: undefined,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001491 };
1492 assert.equal(element._getLatestRevisionSHA(change), 'rev1');
1493 });
1494
1495 test('show commit message edit button', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001496 const change = createChange();
1497 const mergedChanged: ChangeInfo = {
Dhruv Srivastavada276592021-04-07 14:51:51 +02001498 ...createChangeViewChange(),
Dmitrii Filippov4e4522e2020-05-06 12:50:49 +02001499 status: ChangeStatus.MERGED,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001500 };
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001501 assert.isTrue(element._computeHideEditCommitMessage(false, false, change));
1502 assert.isTrue(element._computeHideEditCommitMessage(true, true, change));
1503 assert.isTrue(element._computeHideEditCommitMessage(false, true, change));
1504 assert.isFalse(element._computeHideEditCommitMessage(true, false, change));
1505 assert.isTrue(
1506 element._computeHideEditCommitMessage(true, false, mergedChanged)
1507 );
1508 assert.isTrue(
1509 element._computeHideEditCommitMessage(true, false, change, true)
1510 );
1511 assert.isFalse(
1512 element._computeHideEditCommitMessage(true, false, change, false)
1513 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001514 });
1515
1516 test('_handleCommitMessageSave trims trailing whitespace', () => {
Dhruv Srivastavada276592021-04-07 14:51:51 +02001517 element._change = createChangeViewChange();
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001518 // Response code is 500, because we want to avoid window reloading
Ben Rohlfs3a6ff7e2021-01-18 14:08:39 +01001519 const putStub = stubRestApi('putChangeCommitMessage').returns(
1520 Promise.resolve(new Response(null, {status: 500}))
1521 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001522
Frank Borden6988bdf2021-04-07 14:42:00 +02001523 const mockEvent = (content: string) =>
1524 new CustomEvent('', {detail: {content}});
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001525
1526 element._handleCommitMessageSave(mockEvent('test \n test '));
1527 assert.equal(putStub.lastCall.args[1], 'test\n test');
1528
1529 element._handleCommitMessageSave(mockEvent(' test\ntest'));
1530 assert.equal(putStub.lastCall.args[1], ' test\ntest');
1531
1532 element._handleCommitMessageSave(mockEvent('\n\n\n\n\n\n\n\n'));
1533 assert.equal(putStub.lastCall.args[1], '\n\n\n\n\n\n\n\n');
1534 });
1535
Chris Pouceta2e173e2021-08-31 01:04:04 +00001536 test('topic is coalesced to null', async () => {
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +02001537 sinon.stub(element, '_changeChanged');
Ben Rohlfs3a6ff7e2021-01-18 14:08:39 +01001538 stubRestApi('getChangeDetail').returns(
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001539 Promise.resolve({
Dhruv Srivastavada276592021-04-07 14:51:51 +02001540 ...createChangeViewChange(),
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001541 labels: {},
1542 current_revision: 'foo' as CommitId,
1543 revisions: {foo: createRevision()},
1544 })
1545 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001546
Chris Pouceta2e173e2021-08-31 01:04:04 +00001547 await element._getChangeDetail();
1548 assert.isNull(element._change!.topic);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001549 });
1550
Chris Pouceta2e173e2021-08-31 01:04:04 +00001551 test('commit sha is populated from getChangeDetail', async () => {
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +02001552 sinon.stub(element, '_changeChanged');
Ben Rohlfs3a6ff7e2021-01-18 14:08:39 +01001553 stubRestApi('getChangeDetail').callsFake(() =>
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001554 Promise.resolve({
Dhruv Srivastavada276592021-04-07 14:51:51 +02001555 ...createChangeViewChange(),
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001556 labels: {},
1557 current_revision: 'foo' as CommitId,
1558 revisions: {foo: createRevision()},
1559 })
1560 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001561
Chris Pouceta2e173e2021-08-31 01:04:04 +00001562 await element._getChangeDetail();
1563 assert.equal('foo', element._commitInfo!.commit);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001564 });
1565
1566 test('edit is added to change', () => {
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +02001567 sinon.stub(element, '_changeChanged');
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001568 const changeRevision = createRevision();
Ben Rohlfs3a6ff7e2021-01-18 14:08:39 +01001569 stubRestApi('getChangeDetail').callsFake(() =>
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001570 Promise.resolve({
Dhruv Srivastavada276592021-04-07 14:51:51 +02001571 ...createChangeViewChange(),
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001572 labels: {},
1573 current_revision: 'foo' as CommitId,
1574 revisions: {foo: {...changeRevision}},
1575 })
1576 );
1577 const editCommit: CommitInfo = {
1578 ...createCommit(),
1579 commit: 'bar' as CommitId,
1580 };
1581 sinon.stub(element, '_getEdit').callsFake(() =>
1582 Promise.resolve({
Dhruv Srivastava591b4902021-03-10 11:48:12 +01001583 base_patch_set_number: 1 as BasePatchSetNum,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001584 commit: {...editCommit},
1585 base_revision: 'abc',
1586 ref: 'some/ref' as GitRef,
1587 })
1588 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001589 element._patchRange = {};
1590
1591 return element._getChangeDetail().then(() => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001592 const revs = element._change!.revisions!;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001593 assert.equal(Object.keys(revs).length, 2);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001594 assert.deepEqual(revs['foo'], changeRevision);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001595 assert.deepEqual(revs['bar'], {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001596 ...createEditRevision(),
1597 commit: editCommit,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001598 fetch: undefined,
1599 });
1600 });
1601 });
1602
1603 test('_getBasePatchNum', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001604 const _change: ChangeInfo = {
Dhruv Srivastavada276592021-04-07 14:51:51 +02001605 ...createChangeViewChange(),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001606 revisions: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001607 '98da160735fb81604b4c40e93c368f380539dd0e': createRevision(),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001608 },
1609 };
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001610 const _patchRange: ChangeViewPatchRange = {
1611 basePatchNum: ParentPatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001612 };
1613 assert.equal(element._getBasePatchNum(_change, _patchRange), 'PARENT');
1614
1615 element._prefs = {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001616 ...createPreferences(),
1617 default_base_for_merges: DefaultBase.FIRST_PARENT,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001618 };
1619
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001620 const _change2: ChangeInfo = {
Dhruv Srivastavada276592021-04-07 14:51:51 +02001621 ...createChangeViewChange(),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001622 revisions: {
1623 '98da160735fb81604b4c40e93c368f380539dd0e': {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001624 ...createRevision(1),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001625 commit: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001626 ...createCommit(),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001627 parents: [
1628 {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001629 commit: '6e12bdf1176eb4ab24d8491ba3b6d0704409cde8' as CommitId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001630 subject: 'test',
1631 },
1632 {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001633 commit: '22f7db4754b5d9816fc581f3d9a6c0ef8429c841' as CommitId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001634 subject: 'test3',
1635 },
1636 ],
1637 },
1638 },
1639 },
1640 };
1641 assert.equal(element._getBasePatchNum(_change2, _patchRange), -1);
1642
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01001643 _patchRange.patchNum = 1 as RevisionPatchSetNum;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001644 assert.equal(element._getBasePatchNum(_change2, _patchRange), 'PARENT');
1645 });
1646
Chris Pouceta2e173e2021-08-31 01:04:04 +00001647 test('_openReplyDialog called with `ANY` when coming from tap event', async () => {
1648 await flush();
1649 const openStub = sinon.stub(element, '_openReplyDialog');
1650 tap(element.$.replyBtn);
1651 assert(
1652 openStub.lastCall.calledWithExactly(
1653 element.$.replyDialog.FocusTarget.ANY
1654 ),
1655 '_openReplyDialog should have been passed ANY'
1656 );
1657 assert.equal(openStub.callCount, 1);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001658 });
1659
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001660 test(
1661 '_openReplyDialog called with `BODY` when coming from message reply' +
1662 'event',
Chris Pouceta2e173e2021-08-31 01:04:04 +00001663 async () => {
1664 await flush();
1665 const openStub = sinon.stub(element, '_openReplyDialog');
1666 element.messagesList!.dispatchEvent(
1667 new CustomEvent('reply', {
1668 detail: {message: {message: 'text'}},
1669 composed: true,
1670 bubbles: true,
1671 })
1672 );
1673 assert(
1674 openStub.lastCall.calledWithExactly(
1675 element.$.replyDialog.FocusTarget.BODY
1676 ),
1677 '_openReplyDialog should have been passed BODY'
1678 );
1679 assert.equal(openStub.callCount, 1);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001680 }
1681 );
1682
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001683 test('reply dialog focus can be controlled', () => {
1684 const FocusTarget = element.$.replyDialog.FocusTarget;
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +02001685 const openStub = sinon.stub(element, '_openReplyDialog');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001686
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001687 const e = new CustomEvent('show-reply-dialog', {
1688 detail: {value: {ccsOnly: false}},
1689 });
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001690 element._handleShowReplyDialog(e);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001691 assert(
1692 openStub.lastCall.calledWithExactly(FocusTarget.REVIEWERS),
1693 '_openReplyDialog should have been passed REVIEWERS'
1694 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001695 assert.equal(openStub.callCount, 1);
1696
1697 e.detail.value = {ccsOnly: true};
1698 element._handleShowReplyDialog(e);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001699 assert(
1700 openStub.lastCall.calledWithExactly(FocusTarget.CCS),
1701 '_openReplyDialog should have been passed CCS'
1702 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001703 assert.equal(openStub.callCount, 2);
1704 });
1705
1706 test('getUrlParameter functionality', () => {
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +02001707 const locationStub = sinon.stub(element, '_getLocationSearch');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001708
1709 locationStub.returns('?test');
1710 assert.equal(element._getUrlParameter('test'), 'test');
1711 locationStub.returns('?test2=12&test=3');
1712 assert.equal(element._getUrlParameter('test'), 'test');
1713 locationStub.returns('');
1714 assert.isNull(element._getUrlParameter('test'));
1715 locationStub.returns('?');
1716 assert.isNull(element._getUrlParameter('test'));
1717 locationStub.returns('?test2');
1718 assert.isNull(element._getUrlParameter('test'));
1719 });
1720
Chris Pouceta2e173e2021-08-31 01:04:04 +00001721 test('revert dialog opened with revert param', async () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001722 const awaitPluginsLoadedStub = sinon
1723 .stub(getPluginLoader(), 'awaitPluginsLoaded')
1724 .callsFake(() => Promise.resolve());
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001725
1726 element._patchRange = {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001727 basePatchNum: ParentPatchSetNum,
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01001728 patchNum: 2 as RevisionPatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001729 };
1730 element._change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +02001731 ...createChangeViewChange(),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001732 revisions: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001733 rev1: createRevision(1),
1734 rev2: createRevision(2),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001735 },
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001736 current_revision: 'rev1' as CommitId,
Dmitrii Filippov4e4522e2020-05-06 12:50:49 +02001737 status: ChangeStatus.MERGED,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001738 labels: {},
1739 actions: {},
1740 };
1741
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001742 sinon.stub(element, '_getUrlParameter').callsFake(param => {
1743 assert.equal(param, 'revert');
1744 return param;
1745 });
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001746
Chris Pouceta2e173e2021-08-31 01:04:04 +00001747 const promise = mockPromise();
1748
1749 sinon
1750 .stub(element.$.actions, 'showRevertDialog')
1751 .callsFake(() => promise.resolve());
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001752
1753 element._maybeShowRevertDialog();
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001754 assert.isTrue(awaitPluginsLoadedStub.called);
Chris Pouceta2e173e2021-08-31 01:04:04 +00001755 await promise;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001756 });
1757
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001758 suite('reply dialog tests', () => {
1759 setup(() => {
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +02001760 sinon.stub(element.$.replyDialog, '_draftChanged');
Dmitrii Filippov0695d402020-10-22 16:57:57 +02001761 element._change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +02001762 ...createChangeViewChange(),
Dmitrii Filippov0695d402020-10-22 16:57:57 +02001763 revisions: createRevisions(1),
1764 messages: createChangeMessages(1),
1765 };
Dmitrii Filippov77e5f7f2020-07-10 18:39:45 +02001766 element._change.labels = {};
Ben Rohlfs3a6ff7e2021-01-18 14:08:39 +01001767 stubRestApi('getChangeDetail').callsFake(() =>
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001768 Promise.resolve({
Dhruv Srivastavada276592021-04-07 14:51:51 +02001769 ...createChangeViewChange(),
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001770 // element has latest info
1771 revisions: {rev1: createRevision()},
1772 messages: createChangeMessages(1),
1773 current_revision: 'rev1' as CommitId,
1774 })
1775 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001776 });
1777
Chris Pouceta2e173e2021-08-31 01:04:04 +00001778 test('show reply dialog on open-reply-dialog event', async () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001779 const openReplyDialogStub = sinon.stub(element, '_openReplyDialog');
Tao Zhouda7463c2020-07-14 11:17:20 +02001780 element.dispatchEvent(
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001781 new CustomEvent('open-reply-dialog', {
1782 composed: true,
1783 bubbles: true,
1784 detail: {},
1785 })
1786 );
Chris Pouceta2e173e2021-08-31 01:04:04 +00001787 await flush();
1788 assert.isTrue(openReplyDialogStub.calledOnce);
Tao Zhouda7463c2020-07-14 11:17:20 +02001789 });
1790
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001791 test('reply from comment adds quote text', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001792 const e = new CustomEvent('', {
1793 detail: {message: {message: 'quote text'}},
1794 });
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001795 element._handleMessageReply(e);
1796 assert.equal(element.$.replyDialog.quote, '> quote text\n\n');
1797 });
1798
1799 test('reply from comment replaces quote text', () => {
1800 element.$.replyDialog.draft = '> old quote text\n\n some draft text';
1801 element.$.replyDialog.quote = '> old quote text\n\n';
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001802 const e = new CustomEvent('', {
1803 detail: {message: {message: 'quote text'}},
1804 });
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001805 element._handleMessageReply(e);
1806 assert.equal(element.$.replyDialog.quote, '> quote text\n\n');
1807 });
1808
1809 test('reply from same comment preserves quote text', () => {
1810 element.$.replyDialog.draft = '> quote text\n\n some draft text';
1811 element.$.replyDialog.quote = '> quote text\n\n';
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001812 const e = new CustomEvent('', {
1813 detail: {message: {message: 'quote text'}},
1814 });
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001815 element._handleMessageReply(e);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001816 assert.equal(
1817 element.$.replyDialog.draft,
1818 '> quote text\n\n some draft text'
1819 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001820 assert.equal(element.$.replyDialog.quote, '> quote text\n\n');
1821 });
1822
1823 test('reply from top of page contains previous draft', () => {
1824 const div = document.createElement('div');
1825 element.$.replyDialog.draft = '> quote text\n\n some draft text';
1826 element.$.replyDialog.quote = '> quote text\n\n';
Chris Poucetcaeea1b2021-08-19 22:12:56 +00001827 const e = {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001828 target: div,
1829 preventDefault: sinon.spy(),
Chris Poucetcaeea1b2021-08-19 22:12:56 +00001830 } as unknown as MouseEvent;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001831 element._handleReplyTap(e);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001832 assert.equal(
1833 element.$.replyDialog.draft,
1834 '> quote text\n\n some draft text'
1835 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001836 assert.equal(element.$.replyDialog.quote, '> quote text\n\n');
1837 });
1838 });
1839
Chris Pouceta2e173e2021-08-31 01:04:04 +00001840 test('reply button is disabled until server config is loaded', async () => {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001841 assert.isTrue(element._replyDisabled);
Milutin Kristoficbec88f12020-10-13 16:53:28 +02001842 // fetches the server config on attached
Chris Pouceta2e173e2021-08-31 01:04:04 +00001843 await flush();
1844 assert.isFalse(element._replyDisabled);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001845 });
1846
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001847 test('header class computation', () => {
1848 assert.equal(element._computeHeaderClass(), 'header');
1849 assert.equal(element._computeHeaderClass(true), 'header editMode');
1850 });
1851
Chris Pouceta2e173e2021-08-31 01:04:04 +00001852 test('_maybeScrollToMessage', async () => {
1853 await flush();
1854 const scrollStub = sinon.stub(element.messagesList!, 'scrollToMessage');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001855
Chris Pouceta2e173e2021-08-31 01:04:04 +00001856 element._maybeScrollToMessage('');
1857 assert.isFalse(scrollStub.called);
1858 element._maybeScrollToMessage('message');
1859 assert.isFalse(scrollStub.called);
1860 element._maybeScrollToMessage('#message-TEST');
1861 assert.isTrue(scrollStub.called);
1862 assert.equal(scrollStub.lastCall.args[0], 'TEST');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001863 });
1864
1865 test('topic update reloads related changes', () => {
Milutin Kristofic8803ea02020-12-09 23:34:39 +01001866 flush();
1867 const relatedChanges = element.shadowRoot!.querySelector(
1868 '#relatedChanges'
1869 ) as GrRelatedChangesList;
1870 const reloadStub = sinon.stub(relatedChanges, 'reload');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001871 element.dispatchEvent(new CustomEvent('topic-changed'));
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001872 assert.isTrue(reloadStub.calledOnce);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001873 });
1874
1875 test('_computeEditMode', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001876 const callCompute = (
1877 range: PatchRange,
1878 params: AppElementChangeViewParams
1879 ) =>
1880 element._computeEditMode(
1881 {base: range, path: '', value: range},
1882 {base: params, path: '', value: params}
1883 );
1884 assert.isTrue(
1885 callCompute(
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01001886 {basePatchNum: ParentPatchSetNum, patchNum: 1 as RevisionPatchSetNum},
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001887 {...createAppElementChangeViewParams(), edit: true}
1888 )
1889 );
1890 assert.isFalse(
1891 callCompute(
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01001892 {basePatchNum: ParentPatchSetNum, patchNum: 1 as RevisionPatchSetNum},
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001893 createAppElementChangeViewParams()
1894 )
1895 );
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001896 assert.isTrue(
1897 callCompute(
Dhruv Srivastava591b4902021-03-10 11:48:12 +01001898 {basePatchNum: 1 as BasePatchSetNum, patchNum: EditPatchSetNum},
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001899 createAppElementChangeViewParams()
1900 )
1901 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001902 });
1903
1904 test('_processEdit', () => {
1905 element._patchRange = {};
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001906 const change: ParsedChangeInfo = {
Dhruv Srivastavada276592021-04-07 14:51:51 +02001907 ...createChangeViewChange(),
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001908 current_revision: 'foo' as CommitId,
1909 revisions: {
1910 foo: {...createRevision(), actions: {cherrypick: {enabled: true}}},
1911 },
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001912 };
1913 let mockChange;
1914
1915 // With no edit, mockChange should be unmodified.
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001916 element._processEdit((mockChange = _.cloneDeep(change)), false);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001917 assert.deepEqual(mockChange, change);
1918
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001919 const editCommit: CommitInfo = {
1920 ...createCommit(),
1921 commit: 'bar' as CommitId,
1922 };
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001923 // When edit is not based on the latest PS, current_revision should be
1924 // unmodified.
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001925 const edit: EditInfo = {
1926 ref: 'ref/test/abc' as GitRef,
1927 base_revision: 'abc',
Dhruv Srivastava591b4902021-03-10 11:48:12 +01001928 base_patch_set_number: 1 as BasePatchSetNum,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001929 commit: {...editCommit},
1930 fetch: {},
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001931 };
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001932 element._processEdit((mockChange = _.cloneDeep(change)), edit);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001933 assert.notDeepEqual(mockChange, change);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001934 assert.equal(mockChange.revisions.bar._number, EditPatchSetNum);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001935 assert.equal(mockChange.current_revision, change.current_revision);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001936 assert.deepEqual(mockChange.revisions.bar.commit, editCommit);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001937 assert.notOk(mockChange.revisions.bar.actions);
1938
1939 edit.base_revision = 'foo';
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001940 element._processEdit((mockChange = _.cloneDeep(change)), edit);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001941 assert.notDeepEqual(mockChange, change);
1942 assert.equal(mockChange.current_revision, 'bar');
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001943 assert.deepEqual(
1944 mockChange.revisions.bar.actions,
1945 mockChange.revisions.foo.actions
1946 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001947
1948 // If _patchRange.patchNum is defined, do not load edit.
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01001949 element._patchRange.patchNum = 5 as RevisionPatchSetNum;
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001950 change.current_revision = 'baz' as CommitId;
1951 element._processEdit((mockChange = _.cloneDeep(change)), edit);
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01001952 assert.equal(element._patchRange.patchNum, 5 as RevisionPatchSetNum);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001953 assert.notOk(mockChange.revisions.bar.actions);
1954 });
1955
1956 test('file-action-tap handling', () => {
1957 element._patchRange = {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001958 basePatchNum: ParentPatchSetNum,
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01001959 patchNum: 1 as RevisionPatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001960 };
Milutin Kristoficbec88f12020-10-13 16:53:28 +02001961 element._change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +02001962 ...createChangeViewChange(),
Milutin Kristoficbec88f12020-10-13 16:53:28 +02001963 };
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001964 const fileList = element.$.fileList;
1965 const Actions = GrEditConstants.Actions;
Milutin Kristofic21b0dc92020-05-18 22:44:11 +02001966 element.$.fileListHeader.editMode = true;
Ben Rohlfsd47eeb92020-09-25 10:29:48 +02001967 flush();
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001968 const controls = element.$.fileListHeader.shadowRoot!.querySelector(
1969 '#editControls'
1970 ) as GrEditControls;
1971 const openDeleteDialogStub = sinon.stub(controls, 'openDeleteDialog');
1972 const openRenameDialogStub = sinon.stub(controls, 'openRenameDialog');
1973 const openRestoreDialogStub = sinon.stub(controls, 'openRestoreDialog');
1974 const getEditUrlForDiffStub = sinon.stub(GerritNav, 'getEditUrlForDiff');
1975 const navigateToRelativeUrlStub = sinon.stub(
1976 GerritNav,
1977 'navigateToRelativeUrl'
1978 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001979
1980 // Delete
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001981 fileList.dispatchEvent(
1982 new CustomEvent('file-action-tap', {
1983 detail: {action: Actions.DELETE.id, path: 'foo'},
1984 bubbles: true,
1985 composed: true,
1986 })
1987 );
Ben Rohlfsd47eeb92020-09-25 10:29:48 +02001988 flush();
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001989
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001990 assert.isTrue(openDeleteDialogStub.called);
1991 assert.equal(openDeleteDialogStub.lastCall.args[0], 'foo');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001992
1993 // Restore
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001994 fileList.dispatchEvent(
1995 new CustomEvent('file-action-tap', {
1996 detail: {action: Actions.RESTORE.id, path: 'foo'},
1997 bubbles: true,
1998 composed: true,
1999 })
2000 );
Ben Rohlfsd47eeb92020-09-25 10:29:48 +02002001 flush();
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002002
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002003 assert.isTrue(openRestoreDialogStub.called);
2004 assert.equal(openRestoreDialogStub.lastCall.args[0], 'foo');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002005
2006 // Rename
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002007 fileList.dispatchEvent(
2008 new CustomEvent('file-action-tap', {
2009 detail: {action: Actions.RENAME.id, path: 'foo'},
2010 bubbles: true,
2011 composed: true,
2012 })
2013 );
Ben Rohlfsd47eeb92020-09-25 10:29:48 +02002014 flush();
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002015
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002016 assert.isTrue(openRenameDialogStub.called);
2017 assert.equal(openRenameDialogStub.lastCall.args[0], 'foo');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002018
2019 // Open
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002020 fileList.dispatchEvent(
2021 new CustomEvent('file-action-tap', {
2022 detail: {action: Actions.OPEN.id, path: 'foo'},
2023 bubbles: true,
2024 composed: true,
2025 })
2026 );
Ben Rohlfsd47eeb92020-09-25 10:29:48 +02002027 flush();
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002028
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002029 assert.isTrue(getEditUrlForDiffStub.called);
2030 assert.equal(getEditUrlForDiffStub.lastCall.args[1], 'foo');
2031 assert.equal(getEditUrlForDiffStub.lastCall.args[2], 1 as PatchSetNum);
2032 assert.isTrue(navigateToRelativeUrlStub.called);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002033 });
2034
2035 test('_selectedRevision updates when patchNum is changed', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002036 const revision1: RevisionInfo = createRevision(1);
2037 const revision2: RevisionInfo = createRevision(2);
Ben Rohlfs3a6ff7e2021-01-18 14:08:39 +01002038 stubRestApi('getChangeDetail').returns(
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002039 Promise.resolve({
Dhruv Srivastavada276592021-04-07 14:51:51 +02002040 ...createChangeViewChange(),
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002041 revisions: {
2042 aaa: revision1,
2043 bbb: revision2,
2044 },
2045 labels: {},
2046 actions: {},
2047 current_revision: 'bbb' as CommitId,
2048 })
2049 );
2050 sinon.stub(element, '_getEdit').returns(Promise.resolve(false));
2051 sinon
2052 .stub(element, '_getPreferences')
2053 .returns(Promise.resolve(createPreferences()));
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01002054 element._patchRange = {patchNum: 2 as RevisionPatchSetNum};
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002055 return element._getChangeDetail().then(() => {
2056 assert.strictEqual(element._selectedRevision, revision2);
2057
2058 element.set('_patchRange.patchNum', '1');
2059 assert.strictEqual(element._selectedRevision, revision1);
2060 });
2061 });
2062
2063 test('_selectedRevision is assigned when patchNum is edit', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002064 const revision1 = createRevision(1);
2065 const revision2 = createRevision(2);
2066 const revision3 = createEditRevision();
Ben Rohlfs3a6ff7e2021-01-18 14:08:39 +01002067 stubRestApi('getChangeDetail').returns(
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002068 Promise.resolve({
Dhruv Srivastavada276592021-04-07 14:51:51 +02002069 ...createChangeViewChange(),
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002070 revisions: {
2071 aaa: revision1,
2072 bbb: revision2,
2073 ccc: revision3,
2074 },
2075 labels: {},
2076 actions: {},
2077 current_revision: 'ccc' as CommitId,
2078 })
2079 );
2080 sinon.stub(element, '_getEdit').returns(Promise.resolve(undefined));
2081 sinon
2082 .stub(element, '_getPreferences')
2083 .returns(Promise.resolve(createPreferences()));
2084 element._patchRange = {patchNum: EditPatchSetNum};
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002085 return element._getChangeDetail().then(() => {
2086 assert.strictEqual(element._selectedRevision, revision3);
2087 });
2088 });
2089
2090 test('_sendShowChangeEvent', () => {
Dhruv Srivastavada276592021-04-07 14:51:51 +02002091 const change = {...createChangeViewChange(), labels: {}};
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002092 element._change = {...change};
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01002093 element._patchRange = {patchNum: 4 as RevisionPatchSetNum};
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002094 element._mergeable = true;
Ben Rohlfsc4c5fdb2021-02-25 12:09:54 +01002095 const showStub = sinon.stub(appContext.jsApiService, 'handleEvent');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002096 element._sendShowChangeEvent();
2097 assert.isTrue(showStub.calledOnce);
Ben Rohlfsa47355d2020-08-30 15:56:13 +02002098 assert.equal(showStub.lastCall.args[0], EventType.SHOW_CHANGE);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002099 assert.deepEqual(showStub.lastCall.args[1], {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002100 change,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002101 patchNum: 4,
2102 info: {mergeable: true},
2103 });
2104 });
2105
2106 suite('_handleEditTap', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002107 let fireEdit: () => void;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002108
2109 setup(() => {
2110 fireEdit = () => {
2111 element.$.actions.dispatchEvent(new CustomEvent('edit-tap'));
2112 };
2113 navigateToChangeStub.restore();
2114
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002115 element._change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +02002116 ...createChangeViewChange(),
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002117 revisions: {rev1: createRevision()},
2118 };
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002119 });
2120
Chris Pouceta2e173e2021-08-31 01:04:04 +00002121 test('edit exists in revisions', async () => {
2122 const promise = mockPromise();
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +02002123 sinon.stub(GerritNav, 'navigateToChange').callsFake((...args) => {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002124 assert.equal(args.length, 2);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002125 assert.equal(args[1], EditPatchSetNum); // patchNum
Chris Pouceta2e173e2021-08-31 01:04:04 +00002126 promise.resolve();
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002127 });
2128
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002129 element.set('_change.revisions.rev2', {
Ben Rohlfs41039d12021-02-03 17:58:39 +01002130 _number: EditPatchSetNum,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002131 });
Chris Pouceta2e173e2021-08-31 01:04:04 +00002132 await flush();
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002133
2134 fireEdit();
Chris Pouceta2e173e2021-08-31 01:04:04 +00002135 await promise;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002136 });
2137
Chris Pouceta2e173e2021-08-31 01:04:04 +00002138 test('no edit exists in revisions, non-latest patchset', async () => {
2139 const promise = mockPromise();
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +02002140 sinon.stub(GerritNav, 'navigateToChange').callsFake((...args) => {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002141 assert.equal(args.length, 4);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002142 assert.equal(args[1], 1 as PatchSetNum); // patchNum
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002143 assert.equal(args[3], true); // opt_isEdit
Chris Pouceta2e173e2021-08-31 01:04:04 +00002144 promise.resolve();
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002145 });
2146
2147 element.set('_change.revisions.rev2', {_number: 2});
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01002148 element._patchRange = {patchNum: 1 as RevisionPatchSetNum};
Chris Pouceta2e173e2021-08-31 01:04:04 +00002149 await flush();
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002150
2151 fireEdit();
Chris Pouceta2e173e2021-08-31 01:04:04 +00002152 await promise;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002153 });
2154
Chris Pouceta2e173e2021-08-31 01:04:04 +00002155 test('no edit exists in revisions, latest patchset', async () => {
2156 const promise = mockPromise();
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +02002157 sinon.stub(GerritNav, 'navigateToChange').callsFake((...args) => {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002158 assert.equal(args.length, 4);
2159 // No patch should be specified when patchNum == latest.
2160 assert.isNotOk(args[1]); // patchNum
2161 assert.equal(args[3], true); // opt_isEdit
Chris Pouceta2e173e2021-08-31 01:04:04 +00002162 promise.resolve();
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002163 });
2164
2165 element.set('_change.revisions.rev2', {_number: 2});
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01002166 element._patchRange = {patchNum: 2 as RevisionPatchSetNum};
Chris Pouceta2e173e2021-08-31 01:04:04 +00002167 await flush();
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002168
2169 fireEdit();
Chris Pouceta2e173e2021-08-31 01:04:04 +00002170 await promise;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002171 });
2172 });
2173
Chris Pouceta2e173e2021-08-31 01:04:04 +00002174 test('_handleStopEditTap', async () => {
Milutin Kristoficbec88f12020-10-13 16:53:28 +02002175 element._change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +02002176 ...createChangeViewChange(),
Milutin Kristoficbec88f12020-10-13 16:53:28 +02002177 };
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +02002178 sinon.stub(element.$.metadata, '_computeLabelNames');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002179 navigateToChangeStub.restore();
Chris Pouceta2e173e2021-08-31 01:04:04 +00002180 const promise = mockPromise();
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +02002181 sinon.stub(GerritNav, 'navigateToChange').callsFake((...args) => {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002182 assert.equal(args.length, 2);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002183 assert.equal(args[1], 1 as PatchSetNum); // patchNum
Chris Pouceta2e173e2021-08-31 01:04:04 +00002184 promise.resolve();
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002185 });
2186
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01002187 element._patchRange = {patchNum: 1 as RevisionPatchSetNum};
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002188 element.$.actions.dispatchEvent(
2189 new CustomEvent('stop-edit-tap', {bubbles: false})
2190 );
Chris Pouceta2e173e2021-08-31 01:04:04 +00002191 await promise;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002192 });
2193
2194 suite('plugin endpoints', () => {
Chris Pouceta2e173e2021-08-31 01:04:04 +00002195 test('endpoint params', async () => {
Dhruv Srivastavada276592021-04-07 14:51:51 +02002196 element._change = {...createChangeViewChange(), labels: {}};
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002197 element._selectedRevision = createRevision();
Chris Pouceta2e173e2021-08-31 01:04:04 +00002198 const promise = mockPromise();
2199 pluginApi.install(promise.resolve, '0.1', 'http://some/plugins/url.js');
2200 await flush();
2201 const plugin: PluginApi = (await promise) as PluginApi;
2202 const hookEl = await plugin
2203 .hook('change-view-integration')
2204 .getLastAttached();
2205 assert.strictEqual((hookEl as any).plugin, plugin);
2206 assert.strictEqual((hookEl as any).change, element._change);
2207 assert.strictEqual((hookEl as any).revision, element._selectedRevision);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002208 });
2209 });
2210
2211 suite('_getMergeability', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002212 let getMergeableStub: SinonStubbedMember<RestApiService['getMergeable']>;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002213 setup(() => {
Dhruv Srivastavada276592021-04-07 14:51:51 +02002214 element._change = {...createChangeViewChange(), labels: {}};
Ben Rohlfs3a6ff7e2021-01-18 14:08:39 +01002215 getMergeableStub = stubRestApi('getMergeable').returns(
2216 Promise.resolve({...createMergeable(), mergeable: true})
2217 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002218 });
2219
2220 test('merged change', () => {
2221 element._mergeable = null;
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002222 element._change!.status = ChangeStatus.MERGED;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002223 return element._getMergeability().then(() => {
2224 assert.isFalse(element._mergeable);
2225 assert.isFalse(getMergeableStub.called);
2226 });
2227 });
2228
2229 test('abandoned change', () => {
2230 element._mergeable = null;
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002231 element._change!.status = ChangeStatus.ABANDONED;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002232 return element._getMergeability().then(() => {
2233 assert.isFalse(element._mergeable);
2234 assert.isFalse(getMergeableStub.called);
2235 });
2236 });
2237
2238 test('open change', () => {
2239 element._mergeable = null;
2240 return element._getMergeability().then(() => {
2241 assert.isTrue(element._mergeable);
2242 assert.isTrue(getMergeableStub.called);
2243 });
2244 });
2245 });
2246
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002247 test('_handleToggleStar called when star is tapped', () => {
2248 element._change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +02002249 ...createChangeViewChange(),
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002250 owner: {_account_id: 1 as AccountId},
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002251 starred: false,
2252 };
2253 element._loggedIn = true;
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +02002254 const stub = sinon.stub(element, '_handleToggleStar');
Ben Rohlfsd47eeb92020-09-25 10:29:48 +02002255 flush();
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002256
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002257 tap(element.$.changeStar.shadowRoot!.querySelector('button')!);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002258 assert.isTrue(stub.called);
2259 });
2260
2261 suite('gr-reporting tests', () => {
2262 setup(() => {
2263 element._patchRange = {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002264 basePatchNum: ParentPatchSetNum,
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01002265 patchNum: 1 as RevisionPatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002266 };
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002267 sinon.stub(element, '_getChangeDetail').returns(Promise.resolve(false));
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +02002268 sinon.stub(element, '_getProjectConfig').returns(Promise.resolve());
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +02002269 sinon.stub(element, '_getMergeability').returns(Promise.resolve());
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002270 sinon.stub(element, '_getLatestCommitMessage').returns(Promise.resolve());
Ben Rohlfs3a6ff7e2021-01-18 14:08:39 +01002271 sinon
2272 .stub(element, '_reloadPatchNumDependentResources')
Dhruv Srivastava09a1b5a2021-01-20 09:28:15 +01002273 .returns(Promise.resolve([undefined, undefined, undefined]));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002274 });
2275
Chris Pouceta2e173e2021-08-31 01:04:04 +00002276 test("don't report changeDisplayed on reply", async () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002277 const changeDisplayStub = sinon.stub(
Ben Rohlfsc4c5fdb2021-02-25 12:09:54 +01002278 appContext.reportingService,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002279 'changeDisplayed'
2280 );
2281 const changeFullyLoadedStub = sinon.stub(
Ben Rohlfsc4c5fdb2021-02-25 12:09:54 +01002282 appContext.reportingService,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002283 'changeFullyLoaded'
2284 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002285 element._handleReplySent();
Chris Pouceta2e173e2021-08-31 01:04:04 +00002286 await flush();
2287 assert.isFalse(changeDisplayStub.called);
2288 assert.isFalse(changeFullyLoadedStub.called);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002289 });
2290
Ben Rohlfs71a8dee2021-06-22 10:06:15 +02002291 test('report changeDisplayed on _paramsChanged', async () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002292 const changeDisplayStub = sinon.stub(
Ben Rohlfsc4c5fdb2021-02-25 12:09:54 +01002293 appContext.reportingService,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002294 'changeDisplayed'
2295 );
2296 const changeFullyLoadedStub = sinon.stub(
Ben Rohlfsc4c5fdb2021-02-25 12:09:54 +01002297 appContext.reportingService,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002298 'changeFullyLoaded'
2299 );
Ben Rohlfs71a8dee2021-06-22 10:06:15 +02002300 element.params = {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002301 ...createAppElementChangeViewParams(),
Ben Rohlfsa5356e92021-05-07 11:06:17 +02002302 changeNum: TEST_NUMERIC_CHANGE_ID,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002303 project: TEST_PROJECT_NAME,
Ben Rohlfs71a8dee2021-06-22 10:06:15 +02002304 };
2305 await flush();
2306 assert.isTrue(changeDisplayStub.called);
2307 assert.isTrue(changeFullyLoadedStub.called);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002308 });
2309 });
Milutin Kristofice9ddfa42021-04-20 23:34:45 +02002310
2311 test('_calculateHasParent', () => {
2312 const changeId = '123' as ChangeId;
2313 const relatedChanges: RelatedChangeAndCommitInfo[] = [];
2314
2315 assert.equal(element._calculateHasParent(changeId, relatedChanges), false);
2316
2317 relatedChanges.push({
2318 ...createRelatedChangeAndCommitInfo(),
2319 change_id: '123' as ChangeId,
2320 });
2321 assert.equal(element._calculateHasParent(changeId, relatedChanges), false);
2322
2323 relatedChanges.push({
2324 ...createRelatedChangeAndCommitInfo(),
2325 change_id: '234' as ChangeId,
2326 });
2327 assert.equal(element._calculateHasParent(changeId, relatedChanges), true);
2328 });
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002329});