blob: f3017f8da2f66f62f8d20f3bb0f9c4aac83d4694 [file] [log] [blame]
Dmitrii Filippovacd39a22020-04-02 10:31:43 +02001/**
2 * @license
Ben Rohlfs94fcbbc2022-05-27 10:45:03 +02003 * Copyright 2015 Google LLC
4 * SPDX-License-Identifier: Apache-2.0
Dmitrii Filippovacd39a22020-04-02 10:31:43 +02005 */
Frank Bordenbe9451a2022-09-12 15:44:29 +02006import '../../../test/common-test-setup';
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01007import '../../edit/gr-edit-constants';
Dhruv Srivastavab213a1f2021-11-19 14:45:40 +01008import '../gr-thread-list/gr-thread-list';
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01009import './gr-change-view';
Dmitrii Filippov0695d402020-10-22 16:57:57 +020010import {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010011 ChangeStatus,
12 CommentSide,
13 DefaultBase,
14 DiffViewMode,
15 HttpMethod,
Dhruv Srivastava69a51732021-04-14 18:23:00 +020016 MessageTag,
Dhruv Srivastava80d34f42021-10-18 16:45:02 +020017 createDefaultPreferences,
Ben Rohlfs132bf282022-08-15 19:29:22 +020018 Tab,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010019} from '../../../constants/constants';
20import {GrEditConstants} from '../../edit/gr-edit-constants';
21import {_testOnly_resetEndpoints} from '../../shared/gr-js-api-interface/gr-plugin-endpoints';
Ben Rohlfs54934de2022-09-22 12:44:33 +020022import {navigationToken} from '../../core/gr-navigation/gr-navigation';
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010023import {getPluginLoader} from '../../shared/gr-js-api-interface/gr-plugin-loader';
Ben Rohlfsa7ab9502021-02-15 17:45:45 +010024import {EventType, PluginApi} from '../../../api/plugin';
Ben Rohlfs00049652021-10-25 16:40:38 +020025import {
26 mockPromise,
Frank Borden6919f442022-08-29 16:35:24 +020027 pressKey,
Ben Rohlfs00049652021-10-25 16:40:38 +020028 queryAndAssert,
Milutin Kristoficc3dfb232022-09-06 14:37:07 +020029 stubFlags,
Ben Rohlfs00049652021-10-25 16:40:38 +020030 stubRestApi,
31 stubUsers,
Frank Borden7b24f732022-09-12 14:29:32 +020032 waitEventLoop,
Ben Rohlfs00049652021-10-25 16:40:38 +020033 waitQueryAndAssert,
34 waitUntil,
35} from '../../../test/test-utils';
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010036import {
Ben Rohlfs65c2f2b2022-09-12 22:35:26 +020037 createChangeViewState,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010038 createApproval,
Dmitrii Filippov0695d402020-10-22 16:57:57 +020039 createChange,
40 createChangeMessages,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010041 createCommit,
42 createMergeable,
43 createPreferences,
44 createRevision,
Dmitrii Filippov0695d402020-10-22 16:57:57 +020045 createRevisions,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010046 createServerInfo,
47 createUserConfig,
48 TEST_NUMERIC_CHANGE_ID,
49 TEST_PROJECT_NAME,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010050 createEditRevision,
51 createAccountWithIdNameAndEmail,
Dhruv Srivastavada276592021-04-07 14:51:51 +020052 createChangeViewChange,
Milutin Kristofice9ddfa42021-04-20 23:34:45 +020053 createRelatedChangeAndCommitInfo,
Dhruv Srivastava8e1e2b22021-09-30 12:17:55 +010054 createAccountDetailWithId,
Ben Rohlfsa16c51a2021-11-22 12:50:55 +010055 createParsedChange,
Chris Poucet973ecc92022-06-13 10:44:07 +020056 createDraft,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010057} from '../../../test/test-data-generators';
Chris Poucet973ecc92022-06-13 10:44:07 +020058import {GrChangeView} from './gr-change-view';
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010059import {
60 AccountId,
61 ApprovalInfo,
Dhruv Srivastava591b4902021-03-10 11:48:12 +010062 BasePatchSetNum,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010063 ChangeId,
64 ChangeInfo,
65 CommitId,
Ben Rohlfsef043172022-05-27 16:07:27 +020066 EDIT,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010067 NumericChangeId,
Ben Rohlfs58267b72022-05-27 15:59:18 +020068 PARENT,
Milutin Kristofice9ddfa42021-04-20 23:34:45 +020069 RelatedChangeAndCommitInfo,
Dhruv Srivastava69a51732021-04-14 18:23:00 +020070 ReviewInputTag,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010071 RevisionInfo,
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +010072 RevisionPatchSetNum,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010073 RobotId,
Ben Rohlfs05750b92021-10-29 08:23:08 +020074 RobotCommentInfo,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010075 Timestamp,
76 UrlEncodedCommentId,
Chris Poucet973ecc92022-06-13 10:44:07 +020077 DetailedLabelInfo,
78 RepoName,
79 QuickLabelInfo,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010080} from '../../../types/common';
Dmitrii Filippov78448cd2020-10-26 17:39:11 +010081import {GrEditControls} from '../../edit/gr-edit-controls/gr-edit-controls';
Ben Rohlfs8e28ad82021-09-20 14:48:33 +020082import {SinonFakeTimers, SinonStubbedMember} from 'sinon';
Ben Rohlfsa9d2cff2021-01-22 21:33:58 +010083import {RestApiService} from '../../../services/gr-rest-api/gr-rest-api';
Ben Rohlfs05750b92021-10-29 08:23:08 +020084import {CommentThread} from '../../../utils/comment-util';
Ben Rohlfsebe4acc2020-12-11 21:16:10 +010085import {GerritView} from '../../../services/router/router-model';
Ben Rohlfsa00ef282021-01-22 21:45:53 +010086import {ParsedChangeInfo} from '../../../types/types';
Milutin Kristofic8803ea02020-12-09 23:34:39 +010087import {GrRelatedChangesList} from '../gr-related-changes-list/gr-related-changes-list';
Dhruv Srivastava69a51732021-04-14 18:23:00 +020088import {ChangeStates} from '../../shared/gr-change-status/gr-change-status';
Chris Poucetbf65b8f2022-01-18 21:18:12 +000089import {LoadingStatus} from '../../../models/change/change-model';
Ben Rohlfs00049652021-10-25 16:40:38 +020090import {FocusTarget, GrReplyDialog} from '../gr-reply-dialog/gr-reply-dialog';
91import {GrOverlay} from '../../shared/gr-overlay/gr-overlay';
Paladox none70efbef2021-08-12 05:21:59 +000092import {GrChangeStar} from '../../shared/gr-change-star/gr-change-star';
Dhruv Srivastavab213a1f2021-11-19 14:45:40 +010093import {GrThreadList} from '../gr-thread-list/gr-thread-list';
Chris Poucetdd2d0102022-05-13 14:09:39 +020094import {assertIsDefined} from '../../../utils/common-util';
Dhruv47c21d12022-06-07 16:37:52 +020095import {DEFAULT_NUM_FILES_SHOWN} from '../gr-file-list/gr-file-list';
Frank Bordene1ba8212022-08-29 15:20:01 +020096import {fixture, html, assert} from '@open-wc/testing';
Chris Poucet973ecc92022-06-13 10:44:07 +020097import {deepClone} from '../../../utils/deep-util';
Frank Borden6919f442022-08-29 16:35:24 +020098import {Modifier} from '../../../utils/dom-util';
99import {GrButton} from '../../shared/gr-button/gr-button';
Milutin Kristoficc3dfb232022-09-06 14:37:07 +0200100import {GrCopyLinks} from '../gr-copy-links/gr-copy-links';
Ben Rohlfs65c2f2b2022-09-12 22:35:26 +0200101import {ChangeViewState} from '../../../models/views/change';
Ben Rohlfse9051fe2022-09-16 11:08:40 +0200102import {rootUrl} from '../../../utils/url-util';
Ben Rohlfsaa533902022-09-22 09:07:12 +0200103import {testResolver} from '../../../test/common-test-setup';
Dmitrii Filippov0028b582020-03-24 11:58:55 +0100104
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100105suite('gr-change-view tests', () => {
106 let element: GrChangeView;
Ben Rohlfsaa533902022-09-22 09:07:12 +0200107 let setUrlStub: sinon.SinonStub;
Dmitrii Filippov06117e82020-06-25 13:26:55 +0200108
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100109 const ROBOT_COMMENTS_LIMIT = 10;
110
Tao Zhou18738b92020-05-04 19:44:51 +0200111 // TODO: should have a mock service to generate VALID fake data
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100112 const THREADS: CommentThread[] = [
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100113 {
114 comments: [
115 {
Dhruv Srivastava3dfaf362020-12-01 21:53:59 +0100116 path: '/COMMIT_MSG',
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100117 author: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100118 _account_id: 1000000 as AccountId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100119 name: 'user',
120 username: 'user',
121 },
Ben Rohlfsabaeacf2022-05-27 15:24:22 +0200122 patch_set: 2 as RevisionPatchSetNum,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100123 robot_id: 'rb1' as RobotId,
124 id: 'ecf0b9fa_fe1a5f62' as UrlEncodedCommentId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100125 line: 5,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100126 updated: '2018-02-08 18:49:18.000000000' as Timestamp,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100127 message: 'test',
128 unresolved: true,
129 },
130 {
Dhruv Srivastava3dfaf362020-12-01 21:53:59 +0100131 path: '/COMMIT_MSG',
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100132 author: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100133 _account_id: 1000000 as AccountId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100134 name: 'user',
135 username: 'user',
136 },
Ben Rohlfsabaeacf2022-05-27 15:24:22 +0200137 patch_set: 4 as RevisionPatchSetNum,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100138 id: 'ecf0b9fa_fe1a5f62_1' as UrlEncodedCommentId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100139 line: 5,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100140 updated: '2018-02-08 18:49:18.000000000' as Timestamp,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100141 message: 'test',
142 unresolved: true,
143 },
144 {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100145 id: '503008e2_0ab203ee' as UrlEncodedCommentId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100146 path: '/COMMIT_MSG',
147 line: 5,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100148 in_reply_to: 'ecf0b9fa_fe1a5f62' as UrlEncodedCommentId,
149 updated: '2018-02-13 22:48:48.018000000' as Timestamp,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100150 message: 'draft',
151 unresolved: false,
152 __draft: true,
Ben Rohlfsabaeacf2022-05-27 15:24:22 +0200153 patch_set: 2 as RevisionPatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100154 },
155 ],
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +0100156 patchNum: 4 as RevisionPatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100157 path: '/COMMIT_MSG',
158 line: 5,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100159 rootId: 'ecf0b9fa_fe1a5f62' as UrlEncodedCommentId,
Dhruv Srivastava794db3a2020-11-11 11:28:08 +0100160 commentSide: CommentSide.REVISION,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100161 },
162 {
163 comments: [
164 {
Dhruv Srivastava3dfaf362020-12-01 21:53:59 +0100165 path: '/COMMIT_MSG',
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100166 author: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100167 _account_id: 1000000 as AccountId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100168 name: 'user',
169 username: 'user',
170 },
Ben Rohlfsabaeacf2022-05-27 15:24:22 +0200171 patch_set: 3 as RevisionPatchSetNum,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100172 id: 'ecf0b9fa_fe5f62' as UrlEncodedCommentId,
173 robot_id: 'rb2' as RobotId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100174 line: 5,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100175 updated: '2018-02-08 18:49:18.000000000' as Timestamp,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100176 message: 'test',
177 unresolved: true,
178 },
179 {
Dhruv Srivastava3dfaf362020-12-01 21:53:59 +0100180 path: 'test.txt',
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100181 author: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100182 _account_id: 1000000 as AccountId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100183 name: 'user',
184 username: 'user',
185 },
Ben Rohlfsabaeacf2022-05-27 15:24:22 +0200186 patch_set: 3 as RevisionPatchSetNum,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100187 id: '09a9fb0a_1484e6cf' as UrlEncodedCommentId,
188 side: CommentSide.PARENT,
189 updated: '2018-02-13 22:47:19.000000000' as Timestamp,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100190 message: 'Some comment on another patchset.',
191 unresolved: false,
192 },
193 ],
Ben Rohlfsabaeacf2022-05-27 15:24:22 +0200194 patchNum: 3 as RevisionPatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100195 path: 'test.txt',
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100196 rootId: '09a9fb0a_1484e6cf' as UrlEncodedCommentId,
197 commentSide: CommentSide.PARENT,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100198 },
199 {
200 comments: [
201 {
Dhruv Srivastava3dfaf362020-12-01 21:53:59 +0100202 path: '/COMMIT_MSG',
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100203 author: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100204 _account_id: 1000000 as AccountId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100205 name: 'user',
206 username: 'user',
207 },
Ben Rohlfsabaeacf2022-05-27 15:24:22 +0200208 patch_set: 2 as RevisionPatchSetNum,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100209 id: '8caddf38_44770ec1' as UrlEncodedCommentId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100210 line: 4,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100211 updated: '2018-02-13 22:48:40.000000000' as Timestamp,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100212 message: 'Another unresolved comment',
213 unresolved: true,
214 },
215 ],
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +0100216 patchNum: 2 as RevisionPatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100217 path: '/COMMIT_MSG',
218 line: 4,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100219 rootId: '8caddf38_44770ec1' as UrlEncodedCommentId,
Dhruv Srivastava794db3a2020-11-11 11:28:08 +0100220 commentSide: CommentSide.REVISION,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100221 },
222 {
223 comments: [
224 {
Dhruv Srivastava3dfaf362020-12-01 21:53:59 +0100225 path: '/COMMIT_MSG',
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100226 author: {
Ben Rohlfs3f279682022-02-25 12:07:27 +0100227 // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100228 _account_id: 1000000 as AccountId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100229 name: 'user',
230 username: 'user',
231 },
Ben Rohlfsabaeacf2022-05-27 15:24:22 +0200232 patch_set: 2 as RevisionPatchSetNum,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100233 id: 'scaddf38_44770ec1' as UrlEncodedCommentId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100234 line: 4,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100235 updated: '2018-02-14 22:48:40.000000000' as Timestamp,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100236 message: 'Yet another unresolved comment',
237 unresolved: true,
238 },
239 ],
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +0100240 patchNum: 2 as RevisionPatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100241 path: '/COMMIT_MSG',
242 line: 4,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100243 rootId: 'scaddf38_44770ec1' as UrlEncodedCommentId,
Dhruv Srivastava794db3a2020-11-11 11:28:08 +0100244 commentSide: CommentSide.REVISION,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100245 },
246 {
247 comments: [
248 {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100249 id: 'zcf0b9fa_fe1a5f62' as UrlEncodedCommentId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100250 path: '/COMMIT_MSG',
251 line: 6,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100252 updated: '2018-02-15 22:48:48.018000000' as Timestamp,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100253 message: 'resolved draft',
254 unresolved: false,
255 __draft: true,
Ben Rohlfsabaeacf2022-05-27 15:24:22 +0200256 patch_set: 2 as RevisionPatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100257 },
258 ],
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +0100259 patchNum: 4 as RevisionPatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100260 path: '/COMMIT_MSG',
261 line: 6,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100262 rootId: 'zcf0b9fa_fe1a5f62' as UrlEncodedCommentId,
Dhruv Srivastava794db3a2020-11-11 11:28:08 +0100263 commentSide: CommentSide.REVISION,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100264 },
265 {
266 comments: [
267 {
Dhruv Srivastava3dfaf362020-12-01 21:53:59 +0100268 path: '/COMMIT_MSG',
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100269 author: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100270 _account_id: 1000000 as AccountId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100271 name: 'user',
272 username: 'user',
273 },
Ben Rohlfsabaeacf2022-05-27 15:24:22 +0200274 patch_set: 4 as RevisionPatchSetNum,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100275 id: 'rc1' as UrlEncodedCommentId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100276 line: 5,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100277 updated: '2019-02-08 18:49:18.000000000' as Timestamp,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100278 message: 'test',
279 unresolved: true,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100280 robot_id: 'rc1' as RobotId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100281 },
282 ],
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +0100283 patchNum: 4 as RevisionPatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100284 path: '/COMMIT_MSG',
285 line: 5,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100286 rootId: 'rc1' as UrlEncodedCommentId,
Dhruv Srivastava794db3a2020-11-11 11:28:08 +0100287 commentSide: CommentSide.REVISION,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100288 },
289 {
290 comments: [
291 {
Dhruv Srivastava3dfaf362020-12-01 21:53:59 +0100292 path: '/COMMIT_MSG',
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100293 author: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100294 _account_id: 1000000 as AccountId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100295 name: 'user',
296 username: 'user',
297 },
Ben Rohlfsabaeacf2022-05-27 15:24:22 +0200298 patch_set: 4 as RevisionPatchSetNum,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100299 id: 'rc2' as UrlEncodedCommentId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100300 line: 5,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100301 updated: '2019-03-08 18:49:18.000000000' as Timestamp,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100302 message: 'test',
303 unresolved: true,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100304 robot_id: 'rc2' as RobotId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100305 },
306 {
Dhruv Srivastava3dfaf362020-12-01 21:53:59 +0100307 path: '/COMMIT_MSG',
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100308 author: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100309 _account_id: 1000000 as AccountId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100310 name: 'user',
311 username: 'user',
312 },
Ben Rohlfsabaeacf2022-05-27 15:24:22 +0200313 patch_set: 4 as RevisionPatchSetNum,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100314 id: 'c2_1' as UrlEncodedCommentId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100315 line: 5,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100316 updated: '2019-03-08 18:49:18.000000000' as Timestamp,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100317 message: 'test',
318 unresolved: true,
319 },
320 ],
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +0100321 patchNum: 4 as RevisionPatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100322 path: '/COMMIT_MSG',
323 line: 5,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100324 rootId: 'rc2' as UrlEncodedCommentId,
Dhruv Srivastava794db3a2020-11-11 11:28:08 +0100325 commentSide: CommentSide.REVISION,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100326 },
327 ];
328
Chris Poucet973ecc92022-06-13 10:44:07 +0200329 setup(async () => {
Dmitrii Filippovf97fc6e2020-04-07 09:59:22 +0200330 // Since pluginEndpoints are global, must reset state.
331 _testOnly_resetEndpoints();
Ben Rohlfsaa533902022-09-22 09:07:12 +0200332 setUrlStub = sinon.stub(testResolver(navigationToken), 'setUrl');
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100333
Ben Rohlfs3a6ff7e2021-01-18 14:08:39 +0100334 stubRestApi('getConfig').returns(
335 Promise.resolve({
336 ...createServerInfo(),
337 user: {
338 ...createUserConfig(),
339 anonymous_coward_name: 'test coward name',
340 },
341 })
342 );
Dhruv Srivastava8e1e2b22021-09-30 12:17:55 +0100343 stubRestApi('getAccount').returns(
344 Promise.resolve(createAccountDetailWithId(5))
345 );
Ben Rohlfs3a6ff7e2021-01-18 14:08:39 +0100346 stubRestApi('getDiffComments').returns(Promise.resolve({}));
347 stubRestApi('getDiffRobotComments').returns(Promise.resolve({}));
348 stubRestApi('getDiffDrafts').returns(Promise.resolve({}));
Chris Poucet973ecc92022-06-13 10:44:07 +0200349
Dhruv Srivastava12e2c992020-09-01 16:40:21 +0200350 getPluginLoader().loadPlugins([]);
Chris Poucetd3f52fd2021-11-29 23:16:39 +0100351 window.Gerrit.install(
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100352 plugin => {
353 plugin.registerDynamicCustomComponent(
354 'change-view-tab-header',
355 'gr-checks-change-view-tab-header-view'
356 );
357 plugin.registerDynamicCustomComponent(
358 'change-view-tab-content',
359 'gr-checks-view'
360 );
361 },
362 '0.1',
Ben Rohlfsef1dd592021-03-09 10:58:29 +0100363 'http://some/plugins/url.js'
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100364 );
Chris Poucet973ecc92022-06-13 10:44:07 +0200365 element = await fixture<GrChangeView>(
366 html`<gr-change-view></gr-change-view>`
367 );
Ben Rohlfs10dfa932022-09-19 13:43:32 +0200368 element.viewState = {
Chris Poucet973ecc92022-06-13 10:44:07 +0200369 view: GerritView.CHANGE,
370 changeNum: TEST_NUMERIC_CHANGE_ID,
371 project: 'gerrit' as RepoName,
372 };
Ben Rohlfs132bf282022-08-15 19:29:22 +0200373 await element.updateComplete.then(() => {
Chris Poucet973ecc92022-06-13 10:44:07 +0200374 assertIsDefined(element.actions);
375 sinon.stub(element.actions, 'reload').returns(Promise.resolve());
376 });
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100377 });
378
Chris Pouceta2e173e2021-08-31 01:04:04 +0000379 teardown(async () => {
Chris Poucet973ecc92022-06-13 10:44:07 +0200380 await element.updateComplete;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100381 });
382
Frank Borden610556a2022-07-15 15:34:10 +0200383 test('render', () => {
Frank Borden37c7e422022-08-19 14:55:52 +0200384 assert.shadowDom.equal(
385 element,
386 /* HTML */ `
387 <div class="container loading">Loading...</div>
388 <div aria-hidden="false" class="container" hidden="" id="mainContent">
389 <section class="changeInfoSection">
390 <div class="header">
391 <h1 class="assistive-tech-only">Change :</h1>
392 <div class="headerTitle">
393 <div class="changeStatuses"></div>
394 <gr-change-star id="changeStar"> </gr-change-star>
395 <a aria-label="Change undefined" class="changeNumber"> </a>
396 <span class="changeNumberColon"> : </span>
397 <span class="headerSubject"> </span>
398 <gr-copy-clipboard
399 class="changeCopyClipboard"
400 hideinput=""
401 text="undefined: undefined | http://localhost:9876undefined"
402 >
403 </gr-copy-clipboard>
404 </div>
405 <div class="commitActions">
406 <gr-change-actions hidden="" id="actions"> </gr-change-actions>
Frank Borden610556a2022-07-15 15:34:10 +0200407 </div>
408 </div>
Frank Borden37c7e422022-08-19 14:55:52 +0200409 <h2 class="assistive-tech-only">Change metadata</h2>
410 <div class="changeInfo">
411 <div class="changeInfo-column changeMetadata hideOnMobileOverlay">
412 <gr-change-metadata id="metadata"> </gr-change-metadata>
413 </div>
414 <div class="changeInfo-column mainChangeInfo" id="mainChangeInfo">
415 <div class="hideOnMobileOverlay" id="commitAndRelated">
416 <div class="commitContainer">
417 <h3 class="assistive-tech-only">Commit Message</h3>
418 <div>
419 <gr-button
420 aria-disabled="false"
421 class="reply"
422 id="replyBtn"
423 primary=""
424 role="button"
425 tabindex="0"
426 title="Open reply dialog to publish comments and add reviewers (shortcut: a)"
427 >
428 Reply
429 </gr-button>
430 </div>
431 <div class="commitMessage" id="commitMessage">
432 <gr-editable-content
433 id="commitMessageEditor"
434 remove-zero-width-space=""
435 >
Frank Borden535abe52022-10-04 12:02:39 +0200436 <gr-formatted-text></gr-formatted-text>
Frank Borden37c7e422022-08-19 14:55:52 +0200437 </gr-editable-content>
438 </div>
439 <h3 class="assistive-tech-only">
440 Comments and Checks Summary
441 </h3>
442 <gr-change-summary> </gr-change-summary>
443 <gr-endpoint-decorator name="commit-container">
444 <gr-endpoint-param name="change"> </gr-endpoint-param>
445 <gr-endpoint-param name="revision"> </gr-endpoint-param>
446 </gr-endpoint-decorator>
447 </div>
448 <div class="relatedChanges">
449 <gr-related-changes-list id="relatedChanges">
450 </gr-related-changes-list>
451 </div>
452 <div class="emptySpace"></div>
453 </div>
454 </div>
455 </div>
456 </section>
457 <h2 class="assistive-tech-only">Files and Comments tabs</h2>
458 <paper-tabs dir="null" id="tabs" role="tablist" tabindex="0">
459 <paper-tab
460 aria-disabled="false"
461 aria-selected="true"
462 class="iron-selected"
463 data-name="files"
464 role="tab"
465 tabindex="0"
466 >
467 <span> Files </span>
468 </paper-tab>
469 <paper-tab
470 aria-disabled="false"
471 aria-selected="false"
472 class="commentThreads"
473 data-name="comments"
474 role="tab"
475 tabindex="-1"
476 >
477 <gr-tooltip-content has-tooltip="" title="">
478 <span> Comments </span>
479 </gr-tooltip-content>
480 </paper-tab>
481 <paper-tab
482 aria-disabled="false"
483 aria-selected="false"
484 data-name="change-view-tab-header-url"
485 role="tab"
486 tabindex="-1"
487 >
488 <gr-endpoint-decorator name="change-view-tab-header-url">
489 <gr-endpoint-param name="change"> </gr-endpoint-param>
490 <gr-endpoint-param name="revision"> </gr-endpoint-param>
491 </gr-endpoint-decorator>
492 </paper-tab>
493 </paper-tabs>
494 <section class="tabContent">
495 <div>
496 <gr-file-list-header id="fileListHeader"> </gr-file-list-header>
497 <gr-file-list class="hideOnMobileOverlay" id="fileList">
498 </gr-file-list>
499 </div>
500 </section>
501 <gr-endpoint-decorator name="change-view-integration">
502 <gr-endpoint-param name="change"> </gr-endpoint-param>
503 <gr-endpoint-param name="revision"> </gr-endpoint-param>
504 </gr-endpoint-decorator>
505 <paper-tabs dir="null" role="tablist" tabindex="0">
506 <paper-tab
507 aria-disabled="false"
508 aria-selected="false"
509 class="changeLog"
510 data-name="_changeLog"
511 role="tab"
512 tabindex="-1"
513 >
514 Change Log
515 </paper-tab>
516 </paper-tabs>
517 <section class="changeLog">
518 <h2 class="assistive-tech-only">Change Log</h2>
519 <gr-messages-list class="hideOnMobileOverlay"> </gr-messages-list>
520 </section>
521 </div>
522 <gr-apply-fix-dialog id="applyFixDialog"> </gr-apply-fix-dialog>
523 <gr-overlay
524 aria-hidden="true"
525 id="downloadOverlay"
526 style="outline: none; display: none;"
527 tabindex="-1"
528 with-backdrop=""
529 >
530 <gr-download-dialog id="downloadDialog" role="dialog">
531 </gr-download-dialog>
532 </gr-overlay>
533 <gr-overlay
534 aria-hidden="true"
535 id="includedInOverlay"
536 style="outline: none; display: none;"
537 tabindex="-1"
538 with-backdrop=""
539 >
540 <gr-included-in-dialog id="includedInDialog"> </gr-included-in-dialog>
541 </gr-overlay>
542 <gr-overlay
543 aria-hidden="true"
544 class="scrollable"
545 id="replyOverlay"
546 no-cancel-on-esc-key=""
547 no-cancel-on-outside-click=""
548 scroll-action="lock"
549 style="outline: none; display: none;"
550 tabindex="-1"
551 with-backdrop=""
552 >
553 </gr-overlay>
554 `
555 );
Frank Borden610556a2022-07-15 15:34:10 +0200556 });
557
Chris Poucet973ecc92022-06-13 10:44:07 +0200558 test('handleMessageAnchorTap', async () => {
559 element.changeNum = 1 as NumericChangeId;
560 element.patchRange = {
Ben Rohlfs58267b72022-05-27 15:59:18 +0200561 basePatchNum: PARENT,
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +0100562 patchNum: 1 as RevisionPatchSetNum,
Dhruv Srivastava163de6f2020-06-04 09:40:28 +0000563 };
Chris Poucet973ecc92022-06-13 10:44:07 +0200564 element.change = createChangeViewChange();
565 await element.updateComplete;
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200566 const replaceStateStub = sinon.stub(history, 'replaceState');
Chris Poucet973ecc92022-06-13 10:44:07 +0200567 element.handleMessageAnchorTap(
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100568 new CustomEvent('message-anchor-tap', {detail: {id: 'a12345'}})
569 );
Dhruv Srivastava163de6f2020-06-04 09:40:28 +0000570
Dhruv Srivastava163de6f2020-06-04 09:40:28 +0000571 assert.isTrue(replaceStateStub.called);
572 });
573
Chris Poucet973ecc92022-06-13 10:44:07 +0200574 test('handleDiffAgainstBase', () => {
575 element.change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +0200576 ...createChangeViewChange(),
Dmitrii Filippov0695d402020-10-22 16:57:57 +0200577 revisions: createRevisions(10),
578 };
Chris Poucet973ecc92022-06-13 10:44:07 +0200579 element.patchRange = {
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +0100580 patchNum: 3 as RevisionPatchSetNum,
Dhruv Srivastava591b4902021-03-10 11:48:12 +0100581 basePatchNum: 1 as BasePatchSetNum,
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200582 };
Chris Poucet973ecc92022-06-13 10:44:07 +0200583 element.handleDiffAgainstBase();
Ben Rohlfsaa533902022-09-22 09:07:12 +0200584 assert.isTrue(setUrlStub.called);
585 assert.equal(setUrlStub.lastCall.firstArg, '/c/test-project/+/42/3');
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200586 });
587
Chris Poucet973ecc92022-06-13 10:44:07 +0200588 test('handleDiffAgainstLatest', () => {
589 element.change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +0200590 ...createChangeViewChange(),
Dmitrii Filippov0695d402020-10-22 16:57:57 +0200591 revisions: createRevisions(10),
592 };
Chris Poucet973ecc92022-06-13 10:44:07 +0200593 element.patchRange = {
Dhruv Srivastava591b4902021-03-10 11:48:12 +0100594 basePatchNum: 1 as BasePatchSetNum,
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +0100595 patchNum: 3 as RevisionPatchSetNum,
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200596 };
Chris Poucet973ecc92022-06-13 10:44:07 +0200597 element.handleDiffAgainstLatest();
Ben Rohlfsaa533902022-09-22 09:07:12 +0200598 assert.isTrue(setUrlStub.called);
599 assert.equal(setUrlStub.lastCall.firstArg, '/c/test-project/+/42/1..10');
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200600 });
601
Chris Poucet973ecc92022-06-13 10:44:07 +0200602 test('handleDiffBaseAgainstLeft', () => {
603 element.change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +0200604 ...createChangeViewChange(),
Dmitrii Filippov0695d402020-10-22 16:57:57 +0200605 revisions: createRevisions(10),
606 };
Chris Poucet973ecc92022-06-13 10:44:07 +0200607 element.patchRange = {
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +0100608 patchNum: 3 as RevisionPatchSetNum,
Dhruv Srivastava591b4902021-03-10 11:48:12 +0100609 basePatchNum: 1 as BasePatchSetNum,
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200610 };
Chris Poucet973ecc92022-06-13 10:44:07 +0200611 element.handleDiffBaseAgainstLeft();
Ben Rohlfsaa533902022-09-22 09:07:12 +0200612 assert.isTrue(setUrlStub.called);
613 assert.equal(setUrlStub.lastCall.firstArg, '/c/test-project/+/42/1');
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200614 });
615
Chris Poucet973ecc92022-06-13 10:44:07 +0200616 test('handleDiffRightAgainstLatest', () => {
617 element.change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +0200618 ...createChangeViewChange(),
Dmitrii Filippov0695d402020-10-22 16:57:57 +0200619 revisions: createRevisions(10),
620 };
Chris Poucet973ecc92022-06-13 10:44:07 +0200621 element.patchRange = {
Dhruv Srivastava591b4902021-03-10 11:48:12 +0100622 basePatchNum: 1 as BasePatchSetNum,
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +0100623 patchNum: 3 as RevisionPatchSetNum,
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200624 };
Chris Poucet973ecc92022-06-13 10:44:07 +0200625 element.handleDiffRightAgainstLatest();
Ben Rohlfsaa533902022-09-22 09:07:12 +0200626 assert.isTrue(setUrlStub.called);
627 assert.equal(setUrlStub.lastCall.firstArg, '/c/test-project/+/42/3..10');
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200628 });
629
Chris Poucet973ecc92022-06-13 10:44:07 +0200630 test('handleDiffBaseAgainstLatest', () => {
631 element.change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +0200632 ...createChangeViewChange(),
Dmitrii Filippov0695d402020-10-22 16:57:57 +0200633 revisions: createRevisions(10),
634 };
Chris Poucet973ecc92022-06-13 10:44:07 +0200635 element.patchRange = {
Dhruv Srivastava591b4902021-03-10 11:48:12 +0100636 basePatchNum: 1 as BasePatchSetNum,
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +0100637 patchNum: 3 as RevisionPatchSetNum,
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200638 };
Chris Poucet973ecc92022-06-13 10:44:07 +0200639 element.handleDiffBaseAgainstLatest();
Ben Rohlfsaa533902022-09-22 09:07:12 +0200640 assert.isTrue(setUrlStub.called);
641 assert.equal(setUrlStub.lastCall.firstArg, '/c/test-project/+/42/10');
Dhruv Srivastava4757b352020-06-12 15:41:42 +0200642 });
643
Dhruv Srivastava8e1e2b22021-09-30 12:17:55 +0100644 test('toggle attention set status', async () => {
Chris Poucet973ecc92022-06-13 10:44:07 +0200645 element.change = {
Dhruv Srivastava8e1e2b22021-09-30 12:17:55 +0100646 ...createChangeViewChange(),
647 revisions: createRevisions(10),
648 };
649 const addToAttentionSetStub = stubRestApi('addToAttentionSet').returns(
650 Promise.resolve(new Response())
651 );
652
653 const removeFromAttentionSetStub = stubRestApi(
654 'removeFromAttentionSet'
655 ).returns(Promise.resolve(new Response()));
Chris Poucet973ecc92022-06-13 10:44:07 +0200656 element.patchRange = {
Dhruv Srivastava8e1e2b22021-09-30 12:17:55 +0100657 basePatchNum: 1 as BasePatchSetNum,
658 patchNum: 3 as RevisionPatchSetNum,
659 };
Chris Poucet973ecc92022-06-13 10:44:07 +0200660 await element.updateComplete;
661 assert.isNotOk(element.change.attention_set);
662 element.handleToggleAttentionSet();
Dhruv Srivastava8e1e2b22021-09-30 12:17:55 +0100663 assert.isTrue(addToAttentionSetStub.called);
664 assert.isFalse(removeFromAttentionSetStub.called);
665
Chris Poucet973ecc92022-06-13 10:44:07 +0200666 element.handleToggleAttentionSet();
Dhruv Srivastava8e1e2b22021-09-30 12:17:55 +0100667 assert.isTrue(removeFromAttentionSetStub.called);
668 });
669
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100670 suite('plugins adding to file tab', () => {
Chris Pouceta2e173e2021-08-31 01:04:04 +0000671 setup(async () => {
Chris Poucet973ecc92022-06-13 10:44:07 +0200672 element.changeNum = TEST_NUMERIC_CHANGE_ID;
673 await element.updateComplete;
Ben Rohlfs132bf282022-08-15 19:29:22 +0200674 await waitUntil(() => element.pluginTabsHeaderEndpoints.length > 0);
Andrew Bonventre547b8ab2015-12-01 01:02:00 -0500675 });
676
Chris Poucet973ecc92022-06-13 10:44:07 +0200677 test('plugin added tab shows up as a dynamic endpoint', async () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100678 assert(
Ben Rohlfs132bf282022-08-15 19:29:22 +0200679 element.pluginTabsHeaderEndpoints.includes('change-view-tab-header-url')
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100680 );
Ben Rohlfs132bf282022-08-15 19:29:22 +0200681 const tabs = element.shadowRoot!.querySelector('#tabs')!;
682 const paperTabs = tabs.querySelectorAll<HTMLElement>('paper-tab');
Ben Rohlfs36be36d2022-06-24 18:10:45 +0200683 // 4 Tabs are : Files, Comment Threads, Plugin
Ben Rohlfs132bf282022-08-15 19:29:22 +0200684 assert.equal(tabs.querySelectorAll('paper-tab').length, 3);
Ben Rohlfs36be36d2022-06-24 18:10:45 +0200685 assert.equal(paperTabs[0].dataset.name, 'files');
686 assert.equal(paperTabs[1].dataset.name, 'comments');
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100687 assert.equal(paperTabs[2].dataset.name, 'change-view-tab-header-url');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100688 });
689
Ben Rohlfs132bf282022-08-15 19:29:22 +0200690 test('setActiveTab switched tab correctly', async () => {
691 element.setActiveTab(
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100692 new CustomEvent('', {
693 detail: {tab: 'change-view-tab-header-url'},
694 })
695 );
Chris Poucet973ecc92022-06-13 10:44:07 +0200696 await element.updateComplete;
Ben Rohlfs132bf282022-08-15 19:29:22 +0200697 assert.equal(element.activeTab, 'change-view-tab-header-url');
Tao Zhou4fd32d52020-04-06 17:23:10 +0200698 });
699
Ben Rohlfs132bf282022-08-15 19:29:22 +0200700 test('show-tab switched primary tab correctly', async () => {
Paladox none6b055dc2020-06-28 14:53:18 +0000701 element.dispatchEvent(
Ben Rohlfs132bf282022-08-15 19:29:22 +0200702 new CustomEvent('show-tab', {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100703 composed: true,
704 bubbles: true,
705 detail: {
706 tab: 'change-view-tab-header-url',
707 },
708 })
709 );
Chris Poucet973ecc92022-06-13 10:44:07 +0200710 await element.updateComplete;
Ben Rohlfs132bf282022-08-15 19:29:22 +0200711 assert.equal(element.activeTab, 'change-view-tab-header-url');
Tao Zhou4fd32d52020-04-06 17:23:10 +0200712 });
713
Chris Pouceta2e173e2021-08-31 01:04:04 +0000714 test('param change should switch primary tab correctly', async () => {
Ben Rohlfs132bf282022-08-15 19:29:22 +0200715 assert.equal(element.activeTab, Tab.FILES);
Tao Zhou4fd32d52020-04-06 17:23:10 +0200716 // view is required
Chris Poucet973ecc92022-06-13 10:44:07 +0200717 element.changeNum = undefined;
Ben Rohlfs10dfa932022-09-19 13:43:32 +0200718 element.viewState = {
Ben Rohlfs65c2f2b2022-09-12 22:35:26 +0200719 ...createChangeViewState(),
Ben Rohlfs10dfa932022-09-19 13:43:32 +0200720 ...element.viewState,
Ben Rohlfs132bf282022-08-15 19:29:22 +0200721 tab: Tab.COMMENT_THREADS,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100722 };
Chris Poucet973ecc92022-06-13 10:44:07 +0200723 await element.updateComplete;
Ben Rohlfs132bf282022-08-15 19:29:22 +0200724 assert.equal(element.activeTab, Tab.COMMENT_THREADS);
Tao Zhou4fd32d52020-04-06 17:23:10 +0200725 });
726
Chris Pouceta2e173e2021-08-31 01:04:04 +0000727 test('invalid param change should not switch primary tab', async () => {
Ben Rohlfs132bf282022-08-15 19:29:22 +0200728 assert.equal(element.activeTab, Tab.FILES);
Tao Zhou4fd32d52020-04-06 17:23:10 +0200729 // view is required
Ben Rohlfs10dfa932022-09-19 13:43:32 +0200730 element.viewState = {
Ben Rohlfs65c2f2b2022-09-12 22:35:26 +0200731 ...createChangeViewState(),
Ben Rohlfs10dfa932022-09-19 13:43:32 +0200732 ...element.viewState,
Dhruv Srivastava49f0a7a2021-10-06 12:03:01 +0100733 tab: 'random',
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100734 };
Chris Poucet973ecc92022-06-13 10:44:07 +0200735 await element.updateComplete;
Ben Rohlfs132bf282022-08-15 19:29:22 +0200736 assert.equal(element.activeTab, Tab.FILES);
Kasper Nilssonf0743732016-10-18 13:01:10 -0700737 });
738
Ben Rohlfs132bf282022-08-15 19:29:22 +0200739 test('switching to plugin tab renders the plugin tab content', async () => {
740 const paperTabs = element.shadowRoot!.querySelector('#tabs')!;
Frank Borden6919f442022-08-29 16:35:24 +0200741 paperTabs.querySelectorAll('paper-tab')[2].click();
Chris Poucet973ecc92022-06-13 10:44:07 +0200742 await element.updateComplete;
Ben Rohlfs132bf282022-08-15 19:29:22 +0200743 const tabContent = queryAndAssert(element, '.tabContent');
744 const endpoint = queryAndAssert(tabContent, 'gr-endpoint-decorator');
Frank Borden37c7e422022-08-19 14:55:52 +0200745 assert.dom.equal(
746 endpoint,
747 /* HTML */ `
748 <gr-endpoint-decorator>
749 <gr-endpoint-param name="change"></gr-endpoint-param>
750 <gr-endpoint-param name="revision"></gr-endpoint-param>
751 </gr-endpoint-decorator>
752 `
753 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100754 });
755 });
Paladox none7acb7ac2017-11-09 18:06:18 +0000756
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100757 suite('keyboard shortcuts', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100758 let clock: SinonFakeTimers;
Dhruv Srivastava4caf0842020-09-18 11:50:33 +0200759 setup(() => {
760 clock = sinon.useFakeTimers();
761 });
762
763 teardown(() => {
764 clock.restore();
765 sinon.restore();
766 });
767
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100768 test('t to add topic', () => {
Chris Poucet973ecc92022-06-13 10:44:07 +0200769 assertIsDefined(element.metadata);
770 const editStub = sinon.stub(element.metadata, 'editTopic');
Frank Borden6919f442022-08-29 16:35:24 +0200771 pressKey(element, 't');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100772 assert(editStub.called);
773 });
774
775 test('S should toggle the CL star', () => {
Chris Poucet973ecc92022-06-13 10:44:07 +0200776 assertIsDefined(element.changeStar);
777 const starStub = sinon.stub(element.changeStar, 'toggleStar');
Frank Borden6919f442022-08-29 16:35:24 +0200778 pressKey(element, 's');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100779 assert(starStub.called);
780 });
781
Dhruv Srivastava4caf0842020-09-18 11:50:33 +0200782 test('toggle star is throttled', () => {
Chris Poucet973ecc92022-06-13 10:44:07 +0200783 assertIsDefined(element.changeStar);
784 const starStub = sinon.stub(element.changeStar, 'toggleStar');
Frank Borden6919f442022-08-29 16:35:24 +0200785 pressKey(element, 's');
Dhruv Srivastava4caf0842020-09-18 11:50:33 +0200786 assert(starStub.called);
Frank Borden6919f442022-08-29 16:35:24 +0200787 pressKey(element, 's');
Dhruv Srivastava4caf0842020-09-18 11:50:33 +0200788 assert.equal(starStub.callCount, 1);
789 clock.tick(1000);
Frank Borden6919f442022-08-29 16:35:24 +0200790 pressKey(element, 's');
Dhruv Srivastava4caf0842020-09-18 11:50:33 +0200791 assert.equal(starStub.callCount, 2);
792 });
793
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100794 test('U should navigate to root if no backPage set', () => {
Frank Borden6919f442022-08-29 16:35:24 +0200795 pressKey(element, 'u');
Ben Rohlfs54934de2022-09-22 12:44:33 +0200796 assert.isTrue(setUrlStub.called);
797 assert.isTrue(setUrlStub.lastCall.calledWithExactly(rootUrl()));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100798 });
799
800 test('U should navigate to backPage if set', () => {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100801 element.backPage = '/dashboard/self';
Frank Borden6919f442022-08-29 16:35:24 +0200802 pressKey(element, 'u');
Ben Rohlfs54934de2022-09-22 12:44:33 +0200803 assert.isTrue(setUrlStub.called);
804 assert.isTrue(setUrlStub.lastCall.calledWithExactly('/dashboard/self'));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100805 });
806
Chris Pouceta2e173e2021-08-31 01:04:04 +0000807 test('A fires an error event when not logged in', async () => {
Chris Poucet973ecc92022-06-13 10:44:07 +0200808 element.userModel.setAccount(undefined);
Dmitrii Filippov7d4f2f32020-06-28 23:14:26 +0200809 const loggedInErrorSpy = sinon.spy();
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100810 element.addEventListener('show-auth-required', loggedInErrorSpy);
Frank Borden6919f442022-08-29 16:35:24 +0200811 pressKey(element, 'a');
Chris Poucet973ecc92022-06-13 10:44:07 +0200812 await element.updateComplete;
813 assertIsDefined(element.replyOverlay);
814 assert.isFalse(element.replyOverlay.opened);
Chris Pouceta2e173e2021-08-31 01:04:04 +0000815 assert.isTrue(loggedInErrorSpy.called);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100816 });
817
Chris Pouceta2e173e2021-08-31 01:04:04 +0000818 test('shift A does not open reply overlay', async () => {
Frank Borden6919f442022-08-29 16:35:24 +0200819 pressKey(element, 'a', Modifier.SHIFT_KEY);
Chris Poucet973ecc92022-06-13 10:44:07 +0200820 await element.updateComplete;
821 assertIsDefined(element.replyOverlay);
822 assert.isFalse(element.replyOverlay.opened);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100823 });
824
Chris Pouceta2e173e2021-08-31 01:04:04 +0000825 test('A toggles overlay when logged in', async () => {
Chris Poucet973ecc92022-06-13 10:44:07 +0200826 element.change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +0200827 ...createChangeViewChange(),
Dmitrii Filippov0695d402020-10-22 16:57:57 +0200828 revisions: createRevisions(1),
829 messages: createChangeMessages(1),
830 };
Chris Poucet973ecc92022-06-13 10:44:07 +0200831 element.change.labels = {};
832 await element.updateComplete;
Dmitrii Filippov77e5f7f2020-07-10 18:39:45 +0200833
Chris Poucet973ecc92022-06-13 10:44:07 +0200834 const openSpy = sinon.spy(element, 'openReplyDialog');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100835
Frank Borden6919f442022-08-29 16:35:24 +0200836 pressKey(element, 'a');
Chris Poucet973ecc92022-06-13 10:44:07 +0200837 await element.updateComplete;
838 assertIsDefined(element.replyOverlay);
839 assert.isTrue(element.replyOverlay.opened);
840 element.replyOverlay.close();
841 assert.isFalse(element.replyOverlay.opened);
Chris Pouceta2e173e2021-08-31 01:04:04 +0000842 assert(
Ben Rohlfs00049652021-10-25 16:40:38 +0200843 openSpy.lastCall.calledWithExactly(FocusTarget.ANY),
Chris Poucet973ecc92022-06-13 10:44:07 +0200844 'openReplyDialog should have been passed ANY'
Chris Pouceta2e173e2021-08-31 01:04:04 +0000845 );
846 assert.equal(openSpy.callCount, 1);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100847 });
848
Chris Poucet973ecc92022-06-13 10:44:07 +0200849 test('fullscreen-overlay-opened hides content', async () => {
850 element.loggedIn = true;
851 element.loading = false;
852 element.change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +0200853 ...createChangeViewChange(),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100854 labels: {},
855 actions: {
856 abandon: {
857 enabled: true,
858 label: 'Abandon',
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100859 method: HttpMethod.POST,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100860 title: 'Abandon',
861 },
862 },
863 };
Chris Poucet973ecc92022-06-13 10:44:07 +0200864 await element.updateComplete;
865 const handlerSpy = sinon.spy(element, 'handleHideBackgroundContent');
Ben Rohlfs00049652021-10-25 16:40:38 +0200866 const overlay = queryAndAssert<GrOverlay>(element, '#replyOverlay');
867 overlay.dispatchEvent(
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100868 new CustomEvent('fullscreen-overlay-opened', {
869 composed: true,
870 bubbles: true,
871 })
872 );
Chris Poucet973ecc92022-06-13 10:44:07 +0200873 await element.updateComplete;
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100874 assert.isTrue(handlerSpy.called);
Chris Poucet973ecc92022-06-13 10:44:07 +0200875 assertIsDefined(element.mainContent);
876 assertIsDefined(element.actions);
877 assert.isTrue(element.mainContent.classList.contains('overlayOpen'));
878 assert.equal(getComputedStyle(element.actions).display, 'flex');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100879 });
880
Chris Poucet973ecc92022-06-13 10:44:07 +0200881 test('fullscreen-overlay-closed shows content', async () => {
882 element.loggedIn = true;
883 element.loading = false;
884 element.change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +0200885 ...createChangeViewChange(),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100886 labels: {},
887 actions: {
888 abandon: {
889 enabled: true,
890 label: 'Abandon',
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100891 method: HttpMethod.POST,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100892 title: 'Abandon',
893 },
894 },
895 };
Chris Poucet973ecc92022-06-13 10:44:07 +0200896 await element.updateComplete;
897 const handlerSpy = sinon.spy(element, 'handleShowBackgroundContent');
Ben Rohlfs00049652021-10-25 16:40:38 +0200898 const overlay = queryAndAssert<GrOverlay>(element, '#replyOverlay');
899 overlay.dispatchEvent(
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100900 new CustomEvent('fullscreen-overlay-closed', {
901 composed: true,
902 bubbles: true,
903 })
904 );
Chris Poucet973ecc92022-06-13 10:44:07 +0200905 await element.updateComplete;
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100906 assert.isTrue(handlerSpy.called);
Chris Poucet973ecc92022-06-13 10:44:07 +0200907 assertIsDefined(element.mainContent);
908 assert.isFalse(element.mainContent.classList.contains('overlayOpen'));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100909 });
910
911 test('expand all messages when expand-diffs fired', () => {
Chris Poucet973ecc92022-06-13 10:44:07 +0200912 assertIsDefined(element.fileList);
913 assertIsDefined(element.fileListHeader);
914 const handleExpand = sinon.stub(element.fileList, 'expandAllDiffs');
915 element.fileListHeader.dispatchEvent(
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100916 new CustomEvent('expand-diffs', {
917 composed: true,
918 bubbles: true,
919 })
920 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100921 assert.isTrue(handleExpand.called);
922 });
923
924 test('collapse all messages when collapse-diffs fired', () => {
Chris Poucet973ecc92022-06-13 10:44:07 +0200925 assertIsDefined(element.fileList);
926 assertIsDefined(element.fileListHeader);
927 const handleCollapse = sinon.stub(element.fileList, 'collapseAllDiffs');
928 element.fileListHeader.dispatchEvent(
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100929 new CustomEvent('collapse-diffs', {
930 composed: true,
931 bubbles: true,
932 })
933 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100934 assert.isTrue(handleCollapse.called);
935 });
936
Chris Pouceta2e173e2021-08-31 01:04:04 +0000937 test('X should expand all messages', async () => {
Chris Poucet973ecc92022-06-13 10:44:07 +0200938 await element.updateComplete;
Chris Pouceta2e173e2021-08-31 01:04:04 +0000939 const handleExpand = sinon.stub(
940 element.messagesList!,
941 'handleExpandCollapse'
942 );
Frank Borden6919f442022-08-29 16:35:24 +0200943 pressKey(element, 'x');
Chris Pouceta2e173e2021-08-31 01:04:04 +0000944 assert(handleExpand.calledWith(true));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100945 });
946
Chris Pouceta2e173e2021-08-31 01:04:04 +0000947 test('Z should collapse all messages', async () => {
Chris Poucet973ecc92022-06-13 10:44:07 +0200948 await element.updateComplete;
Chris Pouceta2e173e2021-08-31 01:04:04 +0000949 const handleExpand = sinon.stub(
950 element.messagesList!,
951 'handleExpandCollapse'
952 );
Frank Borden6919f442022-08-29 16:35:24 +0200953 pressKey(element, 'z');
Chris Pouceta2e173e2021-08-31 01:04:04 +0000954 assert(handleExpand.calledWith(false));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100955 });
956
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100957 test('d should open download overlay', () => {
Chris Poucet973ecc92022-06-13 10:44:07 +0200958 assertIsDefined(element.downloadOverlay);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100959 const stub = sinon
Chris Poucet973ecc92022-06-13 10:44:07 +0200960 .stub(element.downloadOverlay, 'open')
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100961 .returns(Promise.resolve());
Frank Borden6919f442022-08-29 16:35:24 +0200962 pressKey(element, 'd');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100963 assert.isTrue(stub.called);
964 });
965
Chris Poucetdd2d0102022-05-13 14:09:39 +0200966 test(', should open diff preferences', async () => {
Chris Poucet973ecc92022-06-13 10:44:07 +0200967 assertIsDefined(element.fileList);
968 await element.fileList.updateComplete;
969 assertIsDefined(element.fileList.diffPreferencesDialog);
970 const stub = sinon.stub(element.fileList.diffPreferencesDialog, 'open');
971 element.loggedIn = false;
Frank Borden6919f442022-08-29 16:35:24 +0200972 pressKey(element, ',');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100973 assert.isFalse(stub.called);
974
Chris Poucet973ecc92022-06-13 10:44:07 +0200975 element.loggedIn = true;
Frank Borden6919f442022-08-29 16:35:24 +0200976 pressKey(element, ',');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100977 assert.isTrue(stub.called);
978 });
979
Dhruv Srivastava80d34f42021-10-18 16:45:02 +0200980 test('m should toggle diff mode', async () => {
981 const updatePreferencesStub = stubUsers('updatePreferences');
Chris Poucet973ecc92022-06-13 10:44:07 +0200982 await element.updateComplete;
Dhruv Srivastava80d34f42021-10-18 16:45:02 +0200983
984 const prefs = {
985 ...createDefaultPreferences(),
986 diff_view: DiffViewMode.SIDE_BY_SIDE,
987 };
Chris Poucetefcdb202021-11-22 23:54:26 +0100988 element.userModel.setPreferences(prefs);
Chris Poucet973ecc92022-06-13 10:44:07 +0200989 element.handleToggleDiffMode();
Dhruv Srivastava80d34f42021-10-18 16:45:02 +0200990 assert.isTrue(
991 updatePreferencesStub.calledWith({diff_view: DiffViewMode.UNIFIED})
Dmitrii Filippov78448cd2020-10-26 17:39:11 +0100992 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +0100993
Dhruv Srivastava80d34f42021-10-18 16:45:02 +0200994 const newPrefs = {
995 ...createDefaultPreferences(),
996 diff_view: DiffViewMode.UNIFIED,
997 };
Chris Poucetefcdb202021-11-22 23:54:26 +0100998 element.userModel.setPreferences(newPrefs);
Chris Poucet973ecc92022-06-13 10:44:07 +0200999 await element.updateComplete;
1000 element.handleToggleDiffMode();
Dhruv Srivastava80d34f42021-10-18 16:45:02 +02001001 assert.isTrue(
1002 updatePreferencesStub.calledWith({diff_view: DiffViewMode.SIDE_BY_SIDE})
1003 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001004 });
1005 });
1006
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001007 suite('thread list and change log tabs', () => {
1008 setup(() => {
Chris Poucet973ecc92022-06-13 10:44:07 +02001009 element.changeNum = TEST_NUMERIC_CHANGE_ID;
1010 element.patchRange = {
Ben Rohlfs58267b72022-05-27 15:59:18 +02001011 basePatchNum: PARENT,
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01001012 patchNum: 1 as RevisionPatchSetNum,
Kasper Nilsson9c1a3db2018-10-19 15:11:07 -07001013 };
Chris Poucet973ecc92022-06-13 10:44:07 +02001014 element.change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +02001015 ...createChangeViewChange(),
Becky Siegel9b03dd22017-10-26 14:57:32 -07001016 revisions: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001017 rev2: createRevision(2),
1018 rev1: createRevision(1),
1019 rev13: createRevision(13),
1020 rev3: createRevision(3),
Kasper Nilssonf0743732016-10-18 13:01:10 -07001021 },
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001022 current_revision: 'rev3' as CommitId,
1023 status: ChangeStatus.NEW,
Kasper Nilssonf0743732016-10-18 13:01:10 -07001024 labels: {
1025 test: {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001026 all: [],
Kasper Nilssonf0743732016-10-18 13:01:10 -07001027 default_value: 0,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001028 values: {},
Kasper Nilssonf0743732016-10-18 13:01:10 -07001029 approved: {},
1030 },
1031 },
1032 };
Milutin Kristofic8803ea02020-12-09 23:34:39 +01001033 const relatedChanges = element.shadowRoot!.querySelector(
1034 '#relatedChanges'
1035 ) as GrRelatedChangesList;
1036 sinon.stub(relatedChanges, 'reload');
Han-Wen Nienhuys577ce0a2021-08-11 12:11:17 +02001037 sinon.stub(element, 'loadData').returns(Promise.resolve());
Ben Rohlfs10dfa932022-09-19 13:43:32 +02001038 sinon.spy(element, 'viewStateChanged');
1039 element.viewState = createChangeViewState();
Kasper Nilsson34a5d892018-04-11 11:10:53 -07001040 });
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001041 });
1042
Dhruv Srivastavab213a1f2021-11-19 14:45:40 +01001043 suite('Comments tab', () => {
1044 setup(async () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02001045 element.changeNum = TEST_NUMERIC_CHANGE_ID;
1046 element.change = {
Dhruv Srivastavab213a1f2021-11-19 14:45:40 +01001047 ...createChangeViewChange(),
1048 revisions: {
1049 rev2: createRevision(2),
1050 rev1: createRevision(1),
1051 rev13: createRevision(13),
1052 rev3: createRevision(3),
1053 rev4: createRevision(4),
1054 },
1055 current_revision: 'rev4' as CommitId,
1056 };
Chris Poucet973ecc92022-06-13 10:44:07 +02001057 element.commentThreads = THREADS;
1058 await element.updateComplete;
Ben Rohlfs132bf282022-08-15 19:29:22 +02001059 const paperTabs = element.shadowRoot!.querySelector('#tabs')!;
Ben Rohlfs36be36d2022-06-24 18:10:45 +02001060 const tabs = paperTabs.querySelectorAll('paper-tab');
1061 assert.isTrue(tabs.length > 1);
1062 assert.equal(tabs[1].dataset.name, 'comments');
Frank Borden6919f442022-08-29 16:35:24 +02001063 tabs[1].click();
Chris Poucet973ecc92022-06-13 10:44:07 +02001064 await element.updateComplete;
Dhruv Srivastavab213a1f2021-11-19 14:45:40 +01001065 });
1066
1067 test('commentId overrides unresolveOnly default', async () => {
1068 const threadList = queryAndAssert<GrThreadList>(
1069 element,
1070 'gr-thread-list'
1071 );
1072 assert.isTrue(element.unresolvedOnly);
1073 assert.isNotOk(element.scrollCommentId);
1074 assert.isTrue(threadList.unresolvedOnly);
1075
1076 element.scrollCommentId = 'abcd' as UrlEncodedCommentId;
Chris Poucet973ecc92022-06-13 10:44:07 +02001077 await element.updateComplete;
Dhruv Srivastavab213a1f2021-11-19 14:45:40 +01001078 assert.isFalse(threadList.unresolvedOnly);
1079 });
1080 });
1081
1082 suite('Findings robot-comment tab', () => {
Frank Borden0a05fa12021-08-09 13:50:52 +02001083 setup(async () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02001084 element.changeNum = TEST_NUMERIC_CHANGE_ID;
1085 element.change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +02001086 ...createChangeViewChange(),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001087 revisions: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001088 rev2: createRevision(2),
1089 rev1: createRevision(1),
1090 rev13: createRevision(13),
1091 rev3: createRevision(3),
1092 rev4: createRevision(4),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001093 },
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001094 current_revision: 'rev4' as CommitId,
Kasper Nilssonbbd28672018-08-01 10:23:23 -07001095 };
Chris Poucet973ecc92022-06-13 10:44:07 +02001096 element.commentThreads = THREADS;
Ben Rohlfs36be36d2022-06-24 18:10:45 +02001097 element.showFindingsTab = true;
Chris Poucet973ecc92022-06-13 10:44:07 +02001098 await element.updateComplete;
Ben Rohlfs132bf282022-08-15 19:29:22 +02001099 const paperTabs = element.shadowRoot!.querySelector('#tabs')!;
Ben Rohlfs36be36d2022-06-24 18:10:45 +02001100 const tabs = paperTabs.querySelectorAll('paper-tab');
1101 assert.isTrue(tabs.length > 3);
1102 assert.equal(tabs[3].dataset.name, 'findings');
Frank Borden6919f442022-08-29 16:35:24 +02001103 tabs[3].click();
Chris Poucet973ecc92022-06-13 10:44:07 +02001104 await element.updateComplete;
Kasper Nilssonbbd28672018-08-01 10:23:23 -07001105 });
Milutin Kristofic7a86db12019-08-07 15:26:13 +02001106
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001107 test('robot comments count per patchset', () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02001108 const count = element.robotCommentCountPerPatchSet(THREADS);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001109 const expectedCount = {
1110 2: 1,
1111 3: 1,
1112 4: 2,
1113 };
1114 assert.deepEqual(count, expectedCount);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001115 assert.equal(
Chris Poucet973ecc92022-06-13 10:44:07 +02001116 element.computeText(createRevision(2), THREADS),
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001117 'Patchset 2 (1 finding)'
1118 );
1119 assert.equal(
Chris Poucet973ecc92022-06-13 10:44:07 +02001120 element.computeText(createRevision(4), THREADS),
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001121 'Patchset 4 (2 findings)'
1122 );
1123 assert.equal(
Chris Poucet973ecc92022-06-13 10:44:07 +02001124 element.computeText(createRevision(5), THREADS),
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001125 'Patchset 5'
1126 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001127 });
Milutin Kristofic7a86db12019-08-07 15:26:13 +02001128
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001129 test('only robot comments are rendered', () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02001130 assert.equal(element.computeRobotCommentThreads().length, 2);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001131 assert.equal(
Chris Poucet973ecc92022-06-13 10:44:07 +02001132 (
1133 element.computeRobotCommentThreads()[0]
1134 .comments[0] as RobotCommentInfo
1135 ).robot_id,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001136 'rc1'
1137 );
1138 assert.equal(
Chris Poucet973ecc92022-06-13 10:44:07 +02001139 (
1140 element.computeRobotCommentThreads()[1]
1141 .comments[0] as RobotCommentInfo
1142 ).robot_id,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001143 'rc2'
1144 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001145 });
1146
Chris Pouceta2e173e2021-08-31 01:04:04 +00001147 test('changing patchsets resets robot comments', async () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02001148 assertIsDefined(element.change);
1149 const newChange = {...element.change};
1150 newChange.current_revision = 'rev3' as CommitId;
1151 element.change = newChange;
1152 await element.updateComplete;
1153 assert.equal(element.computeRobotCommentThreads().length, 1);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001154 });
1155
1156 test('Show more button is hidden', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001157 assert.isNull(element.shadowRoot!.querySelector('.show-robot-comments'));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001158 });
1159
1160 suite('robot comments show more button', () => {
Chris Pouceta2e173e2021-08-31 01:04:04 +00001161 setup(async () => {
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001162 const arr = [];
1163 for (let i = 0; i <= 30; i++) {
1164 arr.push(...THREADS);
1165 }
Chris Poucet973ecc92022-06-13 10:44:07 +02001166 element.commentThreads = arr;
1167 await element.updateComplete;
Milutin Kristofic7a86db12019-08-07 15:26:13 +02001168 });
1169
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001170 test('Show more button is rendered', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001171 assert.isOk(element.shadowRoot!.querySelector('.show-robot-comments'));
1172 assert.equal(
Chris Poucet973ecc92022-06-13 10:44:07 +02001173 element.computeRobotCommentThreads().length,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001174 ROBOT_COMMENTS_LIMIT
1175 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001176 });
1177
Chris Pouceta2e173e2021-08-31 01:04:04 +00001178 test('Clicking show more button renders all comments', async () => {
Frank Borden6919f442022-08-29 16:35:24 +02001179 element
1180 .shadowRoot!.querySelector<GrButton>('.show-robot-comments')!
1181 .click();
Chris Poucet973ecc92022-06-13 10:44:07 +02001182 await element.updateComplete;
1183 assert.equal(element.computeRobotCommentThreads().length, 62);
Milutin Kristofic7a86db12019-08-07 15:26:13 +02001184 });
1185 });
Andrew Bonventre547b8ab2015-12-01 01:02:00 -05001186 });
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001187
Chris Poucet973ecc92022-06-13 10:44:07 +02001188 test('reply button is not visible when logged out', async () => {
1189 assertIsDefined(element.replyBtn);
1190 element.loggedIn = false;
1191 await element.updateComplete;
1192 assert.equal(getComputedStyle(element.replyBtn).display, 'none');
1193 element.loggedIn = true;
1194 await element.updateComplete;
1195 assert.notEqual(getComputedStyle(element.replyBtn).display, 'none');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001196 });
1197
Chris Poucet973ecc92022-06-13 10:44:07 +02001198 test('download tap calls handleOpenDownloadDialog', () => {
1199 assertIsDefined(element.actions);
1200 const openDialogStub = sinon.stub(element, 'handleOpenDownloadDialog');
1201 element.actions.dispatchEvent(
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001202 new CustomEvent('download-tap', {
1203 composed: true,
1204 bubbles: true,
1205 })
1206 );
1207 assert.isTrue(openDialogStub.called);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001208 });
1209
Chris Pouceta2e173e2021-08-31 01:04:04 +00001210 test('fetches the server config on attached', async () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02001211 await element.updateComplete;
Chris Pouceta2e173e2021-08-31 01:04:04 +00001212 assert.equal(
Chris Poucet973ecc92022-06-13 10:44:07 +02001213 element.serverConfig!.user.anonymous_coward_name,
Chris Pouceta2e173e2021-08-31 01:04:04 +00001214 'test coward name'
1215 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001216 });
1217
Chris Poucet973ecc92022-06-13 10:44:07 +02001218 test('changeStatuses', async () => {
1219 element.loading = false;
1220 element.change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +02001221 ...createChangeViewChange(),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001222 revisions: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001223 rev2: createRevision(2),
1224 rev1: createRevision(1),
1225 rev13: createRevision(13),
1226 rev3: createRevision(3),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001227 },
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001228 current_revision: 'rev3' as CommitId,
Dmitrii Filippov3bf68892020-07-12 00:19:10 +02001229 status: ChangeStatus.MERGED,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001230 labels: {
1231 test: {
1232 all: [],
1233 default_value: 0,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001234 values: {},
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001235 approved: {},
1236 },
1237 },
1238 };
Chris Poucet973ecc92022-06-13 10:44:07 +02001239 element.mergeable = true;
1240 await element.updateComplete;
Ben Rohlfs3e323b62022-09-07 11:57:14 +02001241 const expectedStatuses = [ChangeStates.MERGED];
Chris Poucet973ecc92022-06-13 10:44:07 +02001242 assert.deepEqual(element.changeStatuses, expectedStatuses);
Chris Poucetcaeea1b2021-08-19 22:12:56 +00001243 const statusChips =
1244 element.shadowRoot!.querySelectorAll('gr-change-status');
Ben Rohlfs3e323b62022-09-07 11:57:14 +02001245 assert.equal(statusChips.length, 1);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001246 });
1247
Dhruv Srivastava69a51732021-04-14 18:23:00 +02001248 suite('ChangeStatus revert', () => {
Chris Pouceta2e173e2021-08-31 01:04:04 +00001249 test('do not show any chip if no revert created', async () => {
Dhruv Srivastava4b634ac2021-04-19 12:18:53 +02001250 const change = {
Ben Rohlfsa16c51a2021-11-22 12:50:55 +01001251 ...createParsedChange(),
Dhruv Srivastava4b634ac2021-04-19 12:18:53 +02001252 messages: createChangeMessages(2),
1253 };
1254 const getChangeStub = stubRestApi('getChange');
1255 getChangeStub.onFirstCall().returns(
1256 Promise.resolve({
1257 ...createChange(),
1258 })
1259 );
1260 getChangeStub.onSecondCall().returns(
1261 Promise.resolve({
1262 ...createChange(),
1263 })
1264 );
Chris Poucet973ecc92022-06-13 10:44:07 +02001265 element.change = change;
1266 element.mergeable = true;
1267 element.currentRevisionActions = {submit: {enabled: true}};
1268 assert.isTrue(element.isSubmitEnabled());
1269 await element.updateComplete;
1270 element.computeRevertSubmitted(element.change);
1271 await element.updateComplete;
Chris Pouceta2e173e2021-08-31 01:04:04 +00001272 assert.isFalse(
Chris Poucet973ecc92022-06-13 10:44:07 +02001273 element.changeStatuses?.includes(ChangeStates.REVERT_SUBMITTED)
Chris Pouceta2e173e2021-08-31 01:04:04 +00001274 );
1275 assert.isFalse(
Chris Poucet973ecc92022-06-13 10:44:07 +02001276 element.changeStatuses?.includes(ChangeStates.REVERT_CREATED)
Chris Pouceta2e173e2021-08-31 01:04:04 +00001277 );
Dhruv Srivastava4b634ac2021-04-19 12:18:53 +02001278 });
1279
Chris Pouceta2e173e2021-08-31 01:04:04 +00001280 test('do not show any chip if all reverts are abandoned', async () => {
Dhruv Srivastava4a557f22021-04-21 14:10:09 +02001281 const change = {
Ben Rohlfsa16c51a2021-11-22 12:50:55 +01001282 ...createParsedChange(),
Dhruv Srivastava4a557f22021-04-21 14:10:09 +02001283 messages: createChangeMessages(2),
1284 };
1285 change.messages[0].message = 'Created a revert of this change as 12345';
1286 change.messages[0].tag = MessageTag.TAG_REVERT as ReviewInputTag;
1287
1288 change.messages[1].message = 'Created a revert of this change as 23456';
1289 change.messages[1].tag = MessageTag.TAG_REVERT as ReviewInputTag;
1290
1291 const getChangeStub = stubRestApi('getChange');
1292 getChangeStub.onFirstCall().returns(
1293 Promise.resolve({
1294 ...createChange(),
1295 status: ChangeStatus.ABANDONED,
1296 })
1297 );
1298 getChangeStub.onSecondCall().returns(
1299 Promise.resolve({
1300 ...createChange(),
1301 status: ChangeStatus.ABANDONED,
1302 })
1303 );
Chris Poucet973ecc92022-06-13 10:44:07 +02001304 element.change = change;
1305 element.mergeable = true;
1306 element.currentRevisionActions = {submit: {enabled: true}};
1307 assert.isTrue(element.isSubmitEnabled());
1308 await element.updateComplete;
1309 element.computeRevertSubmitted(element.change);
1310 await element.updateComplete;
Chris Pouceta2e173e2021-08-31 01:04:04 +00001311 assert.isFalse(
Chris Poucet973ecc92022-06-13 10:44:07 +02001312 element.changeStatuses?.includes(ChangeStates.REVERT_SUBMITTED)
Chris Pouceta2e173e2021-08-31 01:04:04 +00001313 );
1314 assert.isFalse(
Chris Poucet973ecc92022-06-13 10:44:07 +02001315 element.changeStatuses?.includes(ChangeStates.REVERT_CREATED)
Chris Pouceta2e173e2021-08-31 01:04:04 +00001316 );
Dhruv Srivastava4a557f22021-04-21 14:10:09 +02001317 });
1318
Chris Pouceta2e173e2021-08-31 01:04:04 +00001319 test('show revert created if no revert is merged', async () => {
Dhruv Srivastava69a51732021-04-14 18:23:00 +02001320 const change = {
Ben Rohlfsa16c51a2021-11-22 12:50:55 +01001321 ...createParsedChange(),
Dhruv Srivastava69a51732021-04-14 18:23:00 +02001322 messages: createChangeMessages(2),
1323 };
1324 change.messages[0].message = 'Created a revert of this change as 12345';
1325 change.messages[0].tag = MessageTag.TAG_REVERT as ReviewInputTag;
Dhruv Srivastava4a557f22021-04-21 14:10:09 +02001326
1327 change.messages[1].message = 'Created a revert of this change as 23456';
1328 change.messages[1].tag = MessageTag.TAG_REVERT as ReviewInputTag;
1329
Dhruv Srivastava69a51732021-04-14 18:23:00 +02001330 const getChangeStub = stubRestApi('getChange');
1331 getChangeStub.onFirstCall().returns(
1332 Promise.resolve({
1333 ...createChange(),
1334 })
1335 );
1336 getChangeStub.onSecondCall().returns(
1337 Promise.resolve({
1338 ...createChange(),
1339 })
1340 );
Chris Poucet973ecc92022-06-13 10:44:07 +02001341 element.change = change;
1342 element.mergeable = true;
1343 element.currentRevisionActions = {submit: {enabled: true}};
1344 assert.isTrue(element.isSubmitEnabled());
1345 await element.updateComplete;
1346 element.computeRevertSubmitted(element.change);
1347 // Wait for promises to settle.
Frank Borden7b24f732022-09-12 14:29:32 +02001348 await waitEventLoop();
Chris Poucet973ecc92022-06-13 10:44:07 +02001349 await element.updateComplete;
Chris Pouceta2e173e2021-08-31 01:04:04 +00001350 assert.isFalse(
Chris Poucet973ecc92022-06-13 10:44:07 +02001351 element.changeStatuses?.includes(ChangeStates.REVERT_SUBMITTED)
Chris Pouceta2e173e2021-08-31 01:04:04 +00001352 );
1353 assert.isTrue(
Chris Poucet973ecc92022-06-13 10:44:07 +02001354 element.changeStatuses?.includes(ChangeStates.REVERT_CREATED)
Chris Pouceta2e173e2021-08-31 01:04:04 +00001355 );
Dhruv Srivastava69a51732021-04-14 18:23:00 +02001356 });
1357
Chris Pouceta2e173e2021-08-31 01:04:04 +00001358 test('show revert submitted if revert is merged', async () => {
Dhruv Srivastava69a51732021-04-14 18:23:00 +02001359 const change = {
Ben Rohlfsa16c51a2021-11-22 12:50:55 +01001360 ...createParsedChange(),
Dhruv Srivastava69a51732021-04-14 18:23:00 +02001361 messages: createChangeMessages(2),
1362 };
1363 change.messages[0].message = 'Created a revert of this change as 12345';
1364 change.messages[0].tag = MessageTag.TAG_REVERT as ReviewInputTag;
1365 const getChangeStub = stubRestApi('getChange');
1366 getChangeStub.onFirstCall().returns(
1367 Promise.resolve({
1368 ...createChange(),
1369 status: ChangeStatus.MERGED,
1370 })
1371 );
1372 getChangeStub.onSecondCall().returns(
1373 Promise.resolve({
1374 ...createChange(),
1375 })
1376 );
Chris Poucet973ecc92022-06-13 10:44:07 +02001377 element.change = change;
1378 element.mergeable = true;
1379 element.currentRevisionActions = {submit: {enabled: true}};
1380 assert.isTrue(element.isSubmitEnabled());
1381 await element.updateComplete;
1382 element.computeRevertSubmitted(element.change);
1383 // Wait for promises to settle.
Frank Borden7b24f732022-09-12 14:29:32 +02001384 await waitEventLoop();
Chris Poucet973ecc92022-06-13 10:44:07 +02001385 await element.updateComplete;
Chris Pouceta2e173e2021-08-31 01:04:04 +00001386 assert.isFalse(
Chris Poucet973ecc92022-06-13 10:44:07 +02001387 element.changeStatuses?.includes(ChangeStates.REVERT_CREATED)
Chris Pouceta2e173e2021-08-31 01:04:04 +00001388 );
1389 assert.isTrue(
Chris Poucet973ecc92022-06-13 10:44:07 +02001390 element.changeStatuses?.includes(ChangeStates.REVERT_SUBMITTED)
Chris Pouceta2e173e2021-08-31 01:04:04 +00001391 );
Dhruv Srivastava69a51732021-04-14 18:23:00 +02001392 });
1393 });
1394
Chris Poucetdd2d0102022-05-13 14:09:39 +02001395 test('diff preferences open when open-diff-prefs is fired', async () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02001396 await element.updateComplete;
1397 assertIsDefined(element.fileList);
1398 assertIsDefined(element.fileListHeader);
1399 await element.fileList.updateComplete;
1400 const overlayOpenStub = sinon.stub(element.fileList, 'openDiffPrefs');
1401 element.fileListHeader.dispatchEvent(
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001402 new CustomEvent('open-diff-prefs', {
1403 composed: true,
1404 bubbles: true,
1405 })
1406 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001407 assert.isTrue(overlayOpenStub.called);
1408 });
1409
Frank Bordenc2d5c1b2022-09-29 14:22:04 +02001410 test('prepareCommitMsgForLinkify', () => {
1411 let commitMessage = 'R=test@google.com';
1412 let result = element.prepareCommitMsgForLinkify(commitMessage);
1413 assert.equal(result, 'R=\u200Btest@google.com');
1414
1415 commitMessage = 'R=test@google.com\nR=test@google.com';
1416 result = element.prepareCommitMsgForLinkify(commitMessage);
1417 assert.equal(result, 'R=\u200Btest@google.com\nR=\u200Btest@google.com');
1418
1419 commitMessage = 'CC=test@google.com';
1420 result = element.prepareCommitMsgForLinkify(commitMessage);
1421 assert.equal(result, 'CC=\u200Btest@google.com');
1422 });
1423
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001424 test('_isSubmitEnabled', () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02001425 assert.isFalse(element.isSubmitEnabled());
1426 element.currentRevisionActions = {submit: {}};
1427 assert.isFalse(element.isSubmitEnabled());
1428 element.currentRevisionActions = {submit: {enabled: true}};
1429 assert.isTrue(element.isSubmitEnabled());
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001430 });
1431
Chris Poucet973ecc92022-06-13 10:44:07 +02001432 test('reload is called when an approved label is removed', async () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001433 const vote: ApprovalInfo = {
1434 ...createApproval(),
1435 _account_id: 1 as AccountId,
1436 name: 'bojack',
1437 value: 1,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001438 };
Chris Poucet973ecc92022-06-13 10:44:07 +02001439 element.changeNum = TEST_NUMERIC_CHANGE_ID;
1440 element.patchRange = {
Ben Rohlfs58267b72022-05-27 15:59:18 +02001441 basePatchNum: PARENT,
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01001442 patchNum: 1 as RevisionPatchSetNum,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001443 };
1444 const change = {
Chris Poucet973ecc92022-06-13 10:44:07 +02001445 ...createParsedChange(),
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001446 owner: createAccountWithIdNameAndEmail(),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001447 revisions: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001448 rev2: createRevision(2),
1449 rev1: createRevision(1),
1450 rev13: createRevision(13),
1451 rev3: createRevision(3),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001452 },
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001453 current_revision: 'rev3' as CommitId,
1454 status: ChangeStatus.NEW,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001455 labels: {
1456 test: {
1457 all: [vote],
1458 default_value: 0,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001459 values: {},
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001460 approved: {},
1461 },
1462 },
1463 };
Chris Poucet973ecc92022-06-13 10:44:07 +02001464 element.change = change;
1465 await element.updateComplete;
Ben Rohlfs66367b62021-04-30 10:06:32 +02001466 const reloadStub = sinon.stub(element, 'loadData');
Chris Poucet973ecc92022-06-13 10:44:07 +02001467 const newChange = {...element.change};
1468 (newChange.labels!.test! as DetailedLabelInfo).all = [];
1469 element.change = deepClone(newChange);
1470 await element.updateComplete;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001471 assert.isFalse(reloadStub.called);
Chris Poucet973ecc92022-06-13 10:44:07 +02001472
1473 assert.isDefined(element.change);
1474 const testLabels: DetailedLabelInfo & QuickLabelInfo =
1475 newChange.labels!.test;
1476 assertIsDefined(testLabels);
1477 testLabels.all!.push(vote);
1478 testLabels.all!.push(vote);
1479 testLabels.approved = vote;
1480 element.change = deepClone(newChange);
1481 await element.updateComplete;
1482 assert.isFalse(reloadStub.called);
1483
1484 assert.isDefined(element.change);
1485 (newChange.labels!.test! as DetailedLabelInfo).all = [];
1486 element.change = deepClone(newChange);
1487 await element.updateComplete;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001488 assert.isTrue(reloadStub.called);
1489 assert.isTrue(reloadStub.calledOnce);
1490 });
1491
1492 test('reply button has updated count when there are drafts', () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02001493 const getLabel = (canReview: boolean) => {
1494 element.change!.actions!.ready = {enabled: canReview};
1495 return element.computeReplyButtonLabel();
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001496 };
Chris Poucet973ecc92022-06-13 10:44:07 +02001497 element.change = createParsedChange();
1498 element.change.actions = {};
1499 element.diffDrafts = undefined;
1500 assert.equal(getLabel(false), 'Reply');
1501 assert.equal(getLabel(true), 'Reply');
1502
1503 element.diffDrafts = {};
1504 assert.equal(getLabel(false), 'Reply');
1505 assert.equal(getLabel(true), 'Start Review');
1506
1507 element.diffDrafts = {
1508 'file1.txt': [createDraft()],
1509 'file2.txt': [createDraft(), createDraft()],
1510 };
1511 assert.equal(getLabel(false), 'Reply (3)');
1512 assert.equal(getLabel(true), 'Start Review (3)');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001513 });
1514
Chris Poucet973ecc92022-06-13 10:44:07 +02001515 test('change num change', async () => {
Ben Rohlfs3a6ff7e2021-01-18 14:08:39 +01001516 const change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +02001517 ...createChangeViewChange(),
Ben Rohlfs3a6ff7e2021-01-18 14:08:39 +01001518 labels: {},
1519 } as ParsedChangeInfo;
Chris Poucet973ecc92022-06-13 10:44:07 +02001520 element.changeNum = undefined;
1521 element.patchRange = {
Ben Rohlfs58267b72022-05-27 15:59:18 +02001522 basePatchNum: PARENT,
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01001523 patchNum: 2 as RevisionPatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001524 };
Chris Poucet973ecc92022-06-13 10:44:07 +02001525 element.change = change;
1526 assertIsDefined(element.fileList);
1527 assert.equal(element.fileList.numFilesShown, DEFAULT_NUM_FILES_SHOWN);
1528 element.fileList.numFilesShown = 150;
Dhruv65b97262022-06-13 15:05:05 +02001529 element.fileList.selectedIndex = 15;
Chris Poucet973ecc92022-06-13 10:44:07 +02001530 await element.updateComplete;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001531
Chris Poucet973ecc92022-06-13 10:44:07 +02001532 element.changeNum = 2 as NumericChangeId;
Ben Rohlfs10dfa932022-09-19 13:43:32 +02001533 element.viewState = {
Ben Rohlfs65c2f2b2022-09-12 22:35:26 +02001534 ...createChangeViewState(),
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001535 changeNum: 2 as NumericChangeId,
1536 };
Chris Poucet973ecc92022-06-13 10:44:07 +02001537 await element.updateComplete;
1538 assert.equal(element.fileList.numFilesShown, DEFAULT_NUM_FILES_SHOWN);
Dhruv65b97262022-06-13 15:05:05 +02001539 assert.equal(element.fileList.selectedIndex, 0);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001540 });
1541
Ben Rohlfs71a8dee2021-06-22 10:06:15 +02001542 test('don’t reload entire page when patchRange changes', async () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001543 const reloadStub = sinon
Ben Rohlfs66367b62021-04-30 10:06:32 +02001544 .stub(element, 'loadData')
Han-Wen Nienhuys577ce0a2021-08-11 12:11:17 +02001545 .callsFake(() => Promise.resolve());
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001546 const reloadPatchDependentStub = sinon
Chris Poucet973ecc92022-06-13 10:44:07 +02001547 .stub(element, 'reloadPatchNumDependentResources')
Dhruv Srivastava09a1b5a2021-01-20 09:28:15 +01001548 .callsFake(() => Promise.resolve([undefined, undefined, undefined]));
Chris Poucet973ecc92022-06-13 10:44:07 +02001549 assertIsDefined(element.fileList);
1550 await element.fileList.updateComplete;
1551 const collapseStub = sinon.stub(element.fileList, 'collapseAllDiffs');
Ben Rohlfs65c2f2b2022-09-12 22:35:26 +02001552 const value: ChangeViewState = {
1553 ...createChangeViewState(),
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001554 view: GerritView.CHANGE,
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01001555 patchNum: 1 as RevisionPatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001556 };
Chris Poucet973ecc92022-06-13 10:44:07 +02001557 element.changeNum = undefined;
Ben Rohlfs10dfa932022-09-19 13:43:32 +02001558 element.viewState = value;
Chris Poucet973ecc92022-06-13 10:44:07 +02001559 await element.updateComplete;
Dhruv Srivastava105fa212021-09-03 12:16:30 +00001560 assert.isTrue(reloadStub.calledOnce);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001561
Chris Poucet973ecc92022-06-13 10:44:07 +02001562 element.initialLoadComplete = true;
Dhruv65b97262022-06-13 15:05:05 +02001563 element.fileList.selectedIndex = 15;
Chris Poucet973ecc92022-06-13 10:44:07 +02001564 element.change = {
Ben Rohlfsd03b9b12021-05-12 12:04:50 +02001565 ...createChangeViewChange(),
1566 revisions: {
1567 rev1: createRevision(1),
1568 rev2: createRevision(2),
1569 },
1570 };
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001571
Dhruv Srivastava591b4902021-03-10 11:48:12 +01001572 value.basePatchNum = 1 as BasePatchSetNum;
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01001573 value.patchNum = 2 as RevisionPatchSetNum;
Ben Rohlfs10dfa932022-09-19 13:43:32 +02001574 element.viewState = {...value};
Chris Poucet973ecc92022-06-13 10:44:07 +02001575 await element.updateComplete;
Frank Borden7b24f732022-09-12 14:29:32 +02001576 await waitEventLoop();
Dhruv65b97262022-06-13 15:05:05 +02001577 assert.equal(element.fileList.selectedIndex, 0);
Dhruv Srivastava105fa212021-09-03 12:16:30 +00001578 assert.isFalse(reloadStub.calledTwice);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001579 assert.isTrue(reloadPatchDependentStub.calledOnce);
Dhruv Srivastava105fa212021-09-03 12:16:30 +00001580 assert.isTrue(collapseStub.calledTwice);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001581 });
1582
Ben Rohlfs71a8dee2021-06-22 10:06:15 +02001583 test('reload ported comments when patchNum changes', async () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02001584 assertIsDefined(element.fileList);
Han-Wen Nienhuys577ce0a2021-08-11 12:11:17 +02001585 sinon.stub(element, 'loadData').callsFake(() => Promise.resolve());
Ben Rohlfs1fe7f4d2021-12-06 11:21:49 +01001586 sinon.stub(element, 'loadAndSetCommitInfo');
Chris Poucet973ecc92022-06-13 10:44:07 +02001587 await element.updateComplete;
Chris Poucet6c6b54f2021-12-09 02:53:13 +01001588 const reloadPortedCommentsStub = sinon.stub(
1589 element.getCommentsModel(),
1590 'reloadPortedComments'
1591 );
1592 const reloadPortedDraftsStub = sinon.stub(
1593 element.getCommentsModel(),
1594 'reloadPortedDrafts'
1595 );
Chris Poucet973ecc92022-06-13 10:44:07 +02001596 sinon.stub(element.fileList, 'collapseAllDiffs');
Dhruv Srivastava09a1b5a2021-01-20 09:28:15 +01001597
Ben Rohlfs65c2f2b2022-09-12 22:35:26 +02001598 const value: ChangeViewState = {
1599 ...createChangeViewState(),
Dhruv Srivastava09a1b5a2021-01-20 09:28:15 +01001600 view: GerritView.CHANGE,
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01001601 patchNum: 1 as RevisionPatchSetNum,
Dhruv Srivastava09a1b5a2021-01-20 09:28:15 +01001602 };
Ben Rohlfs10dfa932022-09-19 13:43:32 +02001603 element.viewState = value;
Chris Poucet973ecc92022-06-13 10:44:07 +02001604 await element.updateComplete;
Dhruv Srivastava09a1b5a2021-01-20 09:28:15 +01001605
Chris Poucet973ecc92022-06-13 10:44:07 +02001606 element.initialLoadComplete = true;
1607 element.change = {
Ben Rohlfsd03b9b12021-05-12 12:04:50 +02001608 ...createChangeViewChange(),
1609 revisions: {
1610 rev1: createRevision(1),
1611 rev2: createRevision(2),
1612 },
1613 };
Dhruv Srivastava09a1b5a2021-01-20 09:28:15 +01001614
Dhruv Srivastava591b4902021-03-10 11:48:12 +01001615 value.basePatchNum = 1 as BasePatchSetNum;
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01001616 value.patchNum = 2 as RevisionPatchSetNum;
Ben Rohlfs10dfa932022-09-19 13:43:32 +02001617 element.viewState = {...value};
Chris Poucet973ecc92022-06-13 10:44:07 +02001618 await element.updateComplete;
Dhruv Srivastava09a1b5a2021-01-20 09:28:15 +01001619 assert.isTrue(reloadPortedCommentsStub.calledOnce);
Ben Rohlfs718cec02021-11-03 09:04:15 +01001620 assert.isTrue(reloadPortedDraftsStub.calledOnce);
Dhruv Srivastava09a1b5a2021-01-20 09:28:15 +01001621 });
1622
Dhruv Srivastava49f0a7a2021-10-06 12:03:01 +01001623 test('do not reload entire page when patchRange doesnt change', async () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02001624 assertIsDefined(element.fileList);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001625 const reloadStub = sinon
Ben Rohlfs66367b62021-04-30 10:06:32 +02001626 .stub(element, 'loadData')
Han-Wen Nienhuys577ce0a2021-08-11 12:11:17 +02001627 .callsFake(() => Promise.resolve());
Chris Poucet973ecc92022-06-13 10:44:07 +02001628 const collapseStub = sinon.stub(element.fileList, 'collapseAllDiffs');
Ben Rohlfs65c2f2b2022-09-12 22:35:26 +02001629 const value: ChangeViewState = createChangeViewState();
Ben Rohlfs10dfa932022-09-19 13:43:32 +02001630 element.viewState = value;
Dhruv Srivastava49f0a7a2021-10-06 12:03:01 +01001631 // change already loaded
Chris Poucet973ecc92022-06-13 10:44:07 +02001632 assert.isOk(element.changeNum);
1633 await element.updateComplete;
Dhruv Srivastava49f0a7a2021-10-06 12:03:01 +01001634 assert.isFalse(reloadStub.calledOnce);
Chris Poucet973ecc92022-06-13 10:44:07 +02001635 element.initialLoadComplete = true;
Ben Rohlfs10dfa932022-09-19 13:43:32 +02001636 element.viewState = {...value};
Chris Poucet973ecc92022-06-13 10:44:07 +02001637 await element.updateComplete;
Dhruv Srivastava49f0a7a2021-10-06 12:03:01 +01001638 assert.isFalse(reloadStub.calledTwice);
1639 assert.isFalse(collapseStub.calledTwice);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001640 });
1641
Ben Rohlfsc04f61a2021-12-02 14:36:54 +01001642 test('forceReload updates the change', async () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02001643 assertIsDefined(element.fileList);
Ben Rohlfsc04f61a2021-12-02 14:36:54 +01001644 const getChangeStub = stubRestApi('getChangeDetail').returns(
1645 Promise.resolve(createParsedChange())
1646 );
1647 const loadDataStub = sinon
1648 .stub(element, 'loadData')
1649 .callsFake(() => Promise.resolve());
Chris Poucet973ecc92022-06-13 10:44:07 +02001650 const collapseStub = sinon.stub(element.fileList, 'collapseAllDiffs');
Ben Rohlfs10dfa932022-09-19 13:43:32 +02001651 element.viewState = {...createChangeViewState(), forceReload: true};
Chris Poucet973ecc92022-06-13 10:44:07 +02001652 await element.updateComplete;
Ben Rohlfsc04f61a2021-12-02 14:36:54 +01001653 assert.isTrue(getChangeStub.called);
1654 assert.isTrue(loadDataStub.called);
1655 assert.isTrue(collapseStub.called);
Chris Poucet973ecc92022-06-13 10:44:07 +02001656 // patchNum is set by changeChanged, so this verifies that change was set.
1657 assert.isOk(element.patchRange?.patchNum);
Ben Rohlfsc04f61a2021-12-02 14:36:54 +01001658 });
1659
Ben Rohlfs71a8dee2021-06-22 10:06:15 +02001660 test('do not handle new change numbers', async () => {
1661 const recreateSpy = sinon.spy();
1662 element.addEventListener('recreate-change-view', recreateSpy);
1663
Ben Rohlfs65c2f2b2022-09-12 22:35:26 +02001664 const value: ChangeViewState = createChangeViewState();
Ben Rohlfs10dfa932022-09-19 13:43:32 +02001665 element.viewState = value;
Chris Poucet973ecc92022-06-13 10:44:07 +02001666 await element.updateComplete;
Ben Rohlfs71a8dee2021-06-22 10:06:15 +02001667 assert.isFalse(recreateSpy.calledOnce);
1668
1669 value.changeNum = 555111333 as NumericChangeId;
Ben Rohlfs10dfa932022-09-19 13:43:32 +02001670 element.viewState = {...value};
Chris Poucet973ecc92022-06-13 10:44:07 +02001671 await element.updateComplete;
Ben Rohlfs71a8dee2021-06-22 10:06:15 +02001672 assert.isTrue(recreateSpy.calledOnce);
1673 });
1674
Ben Rohlfsbdf135d2021-12-20 15:09:02 +01001675 test('related changes are updated when loadData is called', async () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02001676 await element.updateComplete;
Milutin Kristofic8803ea02020-12-09 23:34:39 +01001677 const relatedChanges = element.shadowRoot!.querySelector(
1678 '#relatedChanges'
1679 ) as GrRelatedChangesList;
Ben Rohlfsbdf135d2021-12-20 15:09:02 +01001680 const reloadStub = sinon.stub(relatedChanges, 'reload');
1681 stubRestApi('getMergeable').returns(
1682 Promise.resolve({...createMergeable(), mergeable: true})
1683 );
1684
Ben Rohlfs10dfa932022-09-19 13:43:32 +02001685 element.viewState = createChangeViewState();
Chris Poucetbf65b8f2022-01-18 21:18:12 +00001686 element.getChangeModel().setState({
Ben Rohlfsbdf135d2021-12-20 15:09:02 +01001687 loadingStatus: LoadingStatus.LOADED,
1688 change: {
1689 ...createChangeViewChange(),
1690 },
1691 });
1692
Chris Pouceta2e173e2021-08-31 01:04:04 +00001693 await element.loadData(true);
Ben Rohlfsaa533902022-09-22 09:07:12 +02001694 assert.isFalse(setUrlStub.called);
Ben Rohlfsbdf135d2021-12-20 15:09:02 +01001695 assert.isTrue(reloadStub.called);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001696 });
1697
Chris Poucet973ecc92022-06-13 10:44:07 +02001698 test('computeCopyTextForTitle', () => {
1699 element.change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +02001700 ...createChangeViewChange(),
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001701 _number: 123 as NumericChangeId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001702 subject: 'test subject',
1703 revisions: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001704 rev1: createRevision(1),
1705 rev3: createRevision(3),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001706 },
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001707 current_revision: 'rev3' as CommitId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001708 };
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001709 assert.equal(
Chris Poucet973ecc92022-06-13 10:44:07 +02001710 element.computeCopyTextForTitle(),
Ben Rohlfs804e7242022-09-15 16:16:12 +02001711 `123: test subject | http://${location.host}/c/test-project/+/123`
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001712 );
1713 });
1714
1715 test('get latest revision', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001716 let change: ChangeInfo = {
1717 ...createChange(),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001718 revisions: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001719 rev1: createRevision(1),
1720 rev3: createRevision(3),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001721 },
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001722 current_revision: 'rev3' as CommitId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001723 };
Chris Poucet973ecc92022-06-13 10:44:07 +02001724 assert.equal(element.getLatestRevisionSHA(change), 'rev3');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001725 change = {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001726 ...createChange(),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001727 revisions: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001728 rev1: createRevision(1),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001729 },
Dhruv Srivastavada276592021-04-07 14:51:51 +02001730 current_revision: undefined,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001731 };
Chris Poucet973ecc92022-06-13 10:44:07 +02001732 assert.equal(element.getLatestRevisionSHA(change), 'rev1');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001733 });
1734
1735 test('show commit message edit button', () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02001736 const change = createParsedChange();
1737 const mergedChanged: ParsedChangeInfo = {
1738 ...createParsedChange(),
Dmitrii Filippov4e4522e2020-05-06 12:50:49 +02001739 status: ChangeStatus.MERGED,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001740 };
Chris Poucet973ecc92022-06-13 10:44:07 +02001741 assert.isTrue(element.computeHideEditCommitMessage(false, false, change));
1742 assert.isTrue(element.computeHideEditCommitMessage(true, true, change));
1743 assert.isTrue(element.computeHideEditCommitMessage(false, true, change));
1744 assert.isFalse(element.computeHideEditCommitMessage(true, false, change));
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001745 assert.isTrue(
Chris Poucet973ecc92022-06-13 10:44:07 +02001746 element.computeHideEditCommitMessage(true, false, mergedChanged)
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001747 );
1748 assert.isTrue(
Chris Poucet973ecc92022-06-13 10:44:07 +02001749 element.computeHideEditCommitMessage(true, false, change, true)
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001750 );
1751 assert.isFalse(
Chris Poucet973ecc92022-06-13 10:44:07 +02001752 element.computeHideEditCommitMessage(true, false, change, false)
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001753 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001754 });
1755
Chris Poucet973ecc92022-06-13 10:44:07 +02001756 test('handleCommitMessageSave trims trailing whitespace', async () => {
1757 element.change = createChangeViewChange();
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001758 // Response code is 500, because we want to avoid window reloading
Ben Rohlfs3a6ff7e2021-01-18 14:08:39 +01001759 const putStub = stubRestApi('putChangeCommitMessage').returns(
1760 Promise.resolve(new Response(null, {status: 500}))
1761 );
Chris Poucet973ecc92022-06-13 10:44:07 +02001762 await element.updateComplete;
Frank Borden6988bdf2021-04-07 14:42:00 +02001763 const mockEvent = (content: string) =>
1764 new CustomEvent('', {detail: {content}});
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001765
Chris Poucet973ecc92022-06-13 10:44:07 +02001766 assertIsDefined(element.commitMessageEditor);
1767 element.handleCommitMessageSave(mockEvent('test \n test '));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001768 assert.equal(putStub.lastCall.args[1], 'test\n test');
Chris Poucet973ecc92022-06-13 10:44:07 +02001769 element.commitMessageEditor.disabled = false;
1770 element.handleCommitMessageSave(mockEvent(' test\ntest'));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001771 assert.equal(putStub.lastCall.args[1], ' test\ntest');
Chris Poucet973ecc92022-06-13 10:44:07 +02001772 element.commitMessageEditor.disabled = false;
1773 element.handleCommitMessageSave(mockEvent('\n\n\n\n\n\n\n\n'));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001774 assert.equal(putStub.lastCall.args[1], '\n\n\n\n\n\n\n\n');
1775 });
1776
Chris Pouceta2e173e2021-08-31 01:04:04 +00001777 test('topic is coalesced to null', async () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02001778 sinon.stub(element, 'changeChanged');
Chris Poucetbf65b8f2022-01-18 21:18:12 +00001779 element.getChangeModel().setState({
Ben Rohlfs61bafc22021-11-29 10:40:08 +01001780 loadingStatus: LoadingStatus.LOADED,
Ben Rohlfsa16c51a2021-11-22 12:50:55 +01001781 change: {
Dhruv Srivastavada276592021-04-07 14:51:51 +02001782 ...createChangeViewChange(),
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001783 labels: {},
1784 current_revision: 'foo' as CommitId,
1785 revisions: {foo: createRevision()},
Ben Rohlfsa16c51a2021-11-22 12:50:55 +01001786 },
1787 });
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001788
Dhruv Srivastava21129812021-12-02 15:48:03 +01001789 await element.performPostChangeLoadTasks();
Chris Poucet973ecc92022-06-13 10:44:07 +02001790 assert.isNull(element.change!.topic);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001791 });
1792
Chris Pouceta2e173e2021-08-31 01:04:04 +00001793 test('commit sha is populated from getChangeDetail', async () => {
Chris Poucetbf65b8f2022-01-18 21:18:12 +00001794 element.getChangeModel().setState({
Ben Rohlfs61bafc22021-11-29 10:40:08 +01001795 loadingStatus: LoadingStatus.LOADED,
Ben Rohlfsa16c51a2021-11-22 12:50:55 +01001796 change: {
Dhruv Srivastavada276592021-04-07 14:51:51 +02001797 ...createChangeViewChange(),
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001798 labels: {},
1799 current_revision: 'foo' as CommitId,
1800 revisions: {foo: createRevision()},
Ben Rohlfsa16c51a2021-11-22 12:50:55 +01001801 },
1802 });
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001803
Dhruv Srivastava21129812021-12-02 15:48:03 +01001804 await element.performPostChangeLoadTasks();
Chris Poucet973ecc92022-06-13 10:44:07 +02001805 assert.equal('foo', element.commitInfo!.commit);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001806 });
1807
Chris Poucet973ecc92022-06-13 10:44:07 +02001808 test('getBasePatchNum', async () => {
1809 element.change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +02001810 ...createChangeViewChange(),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001811 revisions: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001812 '98da160735fb81604b4c40e93c368f380539dd0e': createRevision(),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001813 },
1814 };
Chris Poucet973ecc92022-06-13 10:44:07 +02001815 element.patchRange = {
Ben Rohlfs58267b72022-05-27 15:59:18 +02001816 basePatchNum: PARENT,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001817 };
Chris Poucet973ecc92022-06-13 10:44:07 +02001818 await element.updateComplete;
1819 assert.equal(element.getBasePatchNum(), PARENT);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001820
Chris Poucet973ecc92022-06-13 10:44:07 +02001821 element.prefs = {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001822 ...createPreferences(),
1823 default_base_for_merges: DefaultBase.FIRST_PARENT,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001824 };
1825
Chris Poucet973ecc92022-06-13 10:44:07 +02001826 element.change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +02001827 ...createChangeViewChange(),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001828 revisions: {
1829 '98da160735fb81604b4c40e93c368f380539dd0e': {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001830 ...createRevision(1),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001831 commit: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001832 ...createCommit(),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001833 parents: [
1834 {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001835 commit: '6e12bdf1176eb4ab24d8491ba3b6d0704409cde8' as CommitId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001836 subject: 'test',
1837 },
1838 {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001839 commit: '22f7db4754b5d9816fc581f3d9a6c0ef8429c841' as CommitId,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001840 subject: 'test3',
1841 },
1842 ],
1843 },
1844 },
1845 },
1846 };
Chris Poucet973ecc92022-06-13 10:44:07 +02001847 await element.updateComplete;
1848 assert.equal(element.getBasePatchNum(), -1 as BasePatchSetNum);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001849
Chris Poucet973ecc92022-06-13 10:44:07 +02001850 element.patchRange.basePatchNum = PARENT;
1851 element.patchRange.patchNum = 1 as RevisionPatchSetNum;
1852 await element.updateComplete;
1853 assert.equal(element.getBasePatchNum(), PARENT);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001854 });
1855
Chris Poucet973ecc92022-06-13 10:44:07 +02001856 test('openReplyDialog called with `ANY` when coming from tap event', async () => {
1857 await element.updateComplete;
1858 assertIsDefined(element.replyBtn);
1859 const openStub = sinon.stub(element, 'openReplyDialog');
Frank Borden6919f442022-08-29 16:35:24 +02001860 element.replyBtn.click();
Chris Pouceta2e173e2021-08-31 01:04:04 +00001861 assert(
Ben Rohlfs00049652021-10-25 16:40:38 +02001862 openStub.lastCall.calledWithExactly(FocusTarget.ANY),
Chris Poucet973ecc92022-06-13 10:44:07 +02001863 'openReplyDialog should have been passed ANY'
Chris Pouceta2e173e2021-08-31 01:04:04 +00001864 );
1865 assert.equal(openStub.callCount, 1);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001866 });
1867
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001868 test(
Chris Poucet973ecc92022-06-13 10:44:07 +02001869 'openReplyDialog called with `BODY` when coming from message reply' +
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001870 'event',
Chris Pouceta2e173e2021-08-31 01:04:04 +00001871 async () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02001872 await element.updateComplete;
1873 const openStub = sinon.stub(element, 'openReplyDialog');
Chris Pouceta2e173e2021-08-31 01:04:04 +00001874 element.messagesList!.dispatchEvent(
1875 new CustomEvent('reply', {
1876 detail: {message: {message: 'text'}},
1877 composed: true,
1878 bubbles: true,
1879 })
1880 );
Ben Rohlfs00049652021-10-25 16:40:38 +02001881 assert.isTrue(openStub.calledOnce);
1882 assert.equal(openStub.lastCall.args[0], FocusTarget.BODY);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001883 }
1884 );
1885
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001886 test('reply dialog focus can be controlled', () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02001887 const openStub = sinon.stub(element, 'openReplyDialog');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001888
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001889 const e = new CustomEvent('show-reply-dialog', {
1890 detail: {value: {ccsOnly: false}},
1891 });
Chris Poucet973ecc92022-06-13 10:44:07 +02001892 element.handleShowReplyDialog(e);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001893 assert(
1894 openStub.lastCall.calledWithExactly(FocusTarget.REVIEWERS),
Chris Poucet973ecc92022-06-13 10:44:07 +02001895 'openReplyDialog should have been passed REVIEWERS'
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001896 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001897 assert.equal(openStub.callCount, 1);
1898
1899 e.detail.value = {ccsOnly: true};
Chris Poucet973ecc92022-06-13 10:44:07 +02001900 element.handleShowReplyDialog(e);
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001901 assert(
1902 openStub.lastCall.calledWithExactly(FocusTarget.CCS),
Chris Poucet973ecc92022-06-13 10:44:07 +02001903 'openReplyDialog should have been passed CCS'
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001904 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001905 assert.equal(openStub.callCount, 2);
1906 });
1907
1908 test('getUrlParameter functionality', () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02001909 const locationStub = sinon.stub(element, 'getLocationSearch');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001910 locationStub.returns('?test');
1911 assert.equal(element._getUrlParameter('test'), 'test');
1912 locationStub.returns('?test2=12&test=3');
1913 assert.equal(element._getUrlParameter('test'), 'test');
1914 locationStub.returns('');
1915 assert.isNull(element._getUrlParameter('test'));
1916 locationStub.returns('?');
1917 assert.isNull(element._getUrlParameter('test'));
1918 locationStub.returns('?test2');
1919 assert.isNull(element._getUrlParameter('test'));
1920 });
1921
Chris Pouceta2e173e2021-08-31 01:04:04 +00001922 test('revert dialog opened with revert param', async () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001923 const awaitPluginsLoadedStub = sinon
1924 .stub(getPluginLoader(), 'awaitPluginsLoaded')
1925 .callsFake(() => Promise.resolve());
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001926
Chris Poucet973ecc92022-06-13 10:44:07 +02001927 element.patchRange = {
Ben Rohlfs58267b72022-05-27 15:59:18 +02001928 basePatchNum: PARENT,
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01001929 patchNum: 2 as RevisionPatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001930 };
Chris Poucet973ecc92022-06-13 10:44:07 +02001931 element.change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +02001932 ...createChangeViewChange(),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001933 revisions: {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001934 rev1: createRevision(1),
1935 rev2: createRevision(2),
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001936 },
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001937 current_revision: 'rev1' as CommitId,
Dmitrii Filippov4e4522e2020-05-06 12:50:49 +02001938 status: ChangeStatus.MERGED,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001939 labels: {},
1940 actions: {},
1941 };
1942
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001943 sinon.stub(element, '_getUrlParameter').callsFake(param => {
1944 assert.equal(param, 'revert');
1945 return param;
1946 });
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001947
Chris Pouceta2e173e2021-08-31 01:04:04 +00001948 const promise = mockPromise();
Chris Poucet973ecc92022-06-13 10:44:07 +02001949 assertIsDefined(element.actions);
Chris Pouceta2e173e2021-08-31 01:04:04 +00001950 sinon
Chris Poucet973ecc92022-06-13 10:44:07 +02001951 .stub(element.actions, 'showRevertDialog')
Chris Pouceta2e173e2021-08-31 01:04:04 +00001952 .callsFake(() => promise.resolve());
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001953
Chris Poucet973ecc92022-06-13 10:44:07 +02001954 element.maybeShowRevertDialog();
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001955 assert.isTrue(awaitPluginsLoadedStub.called);
Chris Pouceta2e173e2021-08-31 01:04:04 +00001956 await promise;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001957 });
1958
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001959 suite('reply dialog tests', () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02001960 setup(async () => {
1961 element.change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +02001962 ...createChangeViewChange(),
Ben Rohlfsa16c51a2021-11-22 12:50:55 +01001963 // element has latest info
1964 revisions: {rev1: createRevision()},
Dmitrii Filippov0695d402020-10-22 16:57:57 +02001965 messages: createChangeMessages(1),
Ben Rohlfsa16c51a2021-11-22 12:50:55 +01001966 current_revision: 'rev1' as CommitId,
1967 labels: {},
Dmitrii Filippov0695d402020-10-22 16:57:57 +02001968 };
Chris Poucet973ecc92022-06-13 10:44:07 +02001969 await element.updateComplete;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001970 });
1971
Chris Pouceta2e173e2021-08-31 01:04:04 +00001972 test('show reply dialog on open-reply-dialog event', async () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02001973 const openReplyDialogStub = sinon.stub(element, 'openReplyDialog');
Tao Zhouda7463c2020-07-14 11:17:20 +02001974 element.dispatchEvent(
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001975 new CustomEvent('open-reply-dialog', {
1976 composed: true,
1977 bubbles: true,
1978 detail: {},
1979 })
1980 );
Chris Poucet973ecc92022-06-13 10:44:07 +02001981 await element.updateComplete;
Chris Pouceta2e173e2021-08-31 01:04:04 +00001982 assert.isTrue(openReplyDialogStub.calledOnce);
Tao Zhouda7463c2020-07-14 11:17:20 +02001983 });
1984
Ben Rohlfs00049652021-10-25 16:40:38 +02001985 test('reply from comment adds quote text', async () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001986 const e = new CustomEvent('', {
1987 detail: {message: {message: 'quote text'}},
1988 });
Chris Poucet973ecc92022-06-13 10:44:07 +02001989 element.handleMessageReply(e);
Ben Rohlfs00049652021-10-25 16:40:38 +02001990 const dialog = await waitQueryAndAssert<GrReplyDialog>(
1991 element,
1992 '#replyDialog'
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01001993 );
Ben Rohlfs00049652021-10-25 16:40:38 +02001994 const openSpy = sinon.spy(dialog, 'open');
Chris Poucet973ecc92022-06-13 10:44:07 +02001995 await element.updateComplete;
Ben Rohlfs00049652021-10-25 16:40:38 +02001996 await waitUntil(() => openSpy.called && !!openSpy.lastCall.args[1]);
1997 assert.equal(openSpy.lastCall.args[1], '> quote text\n\n');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01001998 });
1999 });
2000
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002001 test('header class computation', () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02002002 assert.equal(element.computeHeaderClass(), 'header');
Ben Rohlfs10dfa932022-09-19 13:43:32 +02002003 assertIsDefined(element.viewState);
2004 element.viewState.edit = true;
Chris Poucet973ecc92022-06-13 10:44:07 +02002005 assert.equal(element.computeHeaderClass(), 'header editMode');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002006 });
2007
Chris Poucet973ecc92022-06-13 10:44:07 +02002008 test('maybeScrollToMessage', async () => {
2009 await element.updateComplete;
Chris Pouceta2e173e2021-08-31 01:04:04 +00002010 const scrollStub = sinon.stub(element.messagesList!, 'scrollToMessage');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002011
Chris Poucet973ecc92022-06-13 10:44:07 +02002012 element.maybeScrollToMessage('');
Chris Pouceta2e173e2021-08-31 01:04:04 +00002013 assert.isFalse(scrollStub.called);
Chris Poucet973ecc92022-06-13 10:44:07 +02002014 element.maybeScrollToMessage('message');
Chris Pouceta2e173e2021-08-31 01:04:04 +00002015 assert.isFalse(scrollStub.called);
Chris Poucet973ecc92022-06-13 10:44:07 +02002016 element.maybeScrollToMessage('#message-TEST');
Chris Pouceta2e173e2021-08-31 01:04:04 +00002017 assert.isTrue(scrollStub.called);
2018 assert.equal(scrollStub.lastCall.args[0], 'TEST');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002019 });
2020
Chris Poucet973ecc92022-06-13 10:44:07 +02002021 test('computeEditMode', async () => {
Ben Rohlfs10dfa932022-09-19 13:43:32 +02002022 const callCompute = async (viewState: ChangeViewState) => {
2023 element.viewState = viewState;
Chris Poucet973ecc92022-06-13 10:44:07 +02002024 await element.updateComplete;
2025 return element.getEditMode();
2026 };
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002027 assert.isTrue(
Chris Poucet973ecc92022-06-13 10:44:07 +02002028 await callCompute({
Ben Rohlfs65c2f2b2022-09-12 22:35:26 +02002029 ...createChangeViewState(),
Chris Poucet973ecc92022-06-13 10:44:07 +02002030 edit: true,
2031 basePatchNum: PARENT,
2032 patchNum: 1 as RevisionPatchSetNum,
2033 })
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002034 );
2035 assert.isFalse(
Chris Poucet973ecc92022-06-13 10:44:07 +02002036 await callCompute({
Ben Rohlfs65c2f2b2022-09-12 22:35:26 +02002037 ...createChangeViewState(),
Chris Poucet973ecc92022-06-13 10:44:07 +02002038 basePatchNum: PARENT,
2039 patchNum: 1 as RevisionPatchSetNum,
2040 })
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002041 );
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002042 assert.isTrue(
Chris Poucet973ecc92022-06-13 10:44:07 +02002043 await callCompute({
Ben Rohlfs65c2f2b2022-09-12 22:35:26 +02002044 ...createChangeViewState(),
Chris Poucet973ecc92022-06-13 10:44:07 +02002045 basePatchNum: 1 as BasePatchSetNum,
2046 patchNum: EDIT,
2047 })
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002048 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002049 });
2050
Chris Poucet973ecc92022-06-13 10:44:07 +02002051 test('processEdit', () => {
2052 element.patchRange = {};
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002053 const change: ParsedChangeInfo = {
Dhruv Srivastavada276592021-04-07 14:51:51 +02002054 ...createChangeViewChange(),
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002055 current_revision: 'foo' as CommitId,
2056 revisions: {
Ben Rohlfs5e167022021-12-06 11:48:22 +01002057 foo: {...createRevision()},
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002058 },
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002059 };
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002060
Ben Rohlfs1fe7f4d2021-12-06 11:21:49 +01002061 // With no edit, nothing happens.
Chris Poucet973ecc92022-06-13 10:44:07 +02002062 element.processEdit(change);
2063 assert.equal(element.patchRange.patchNum, undefined);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002064
Ben Rohlfs1fe7f4d2021-12-06 11:21:49 +01002065 change.revisions['bar'] = {
Ben Rohlfsef043172022-05-27 16:07:27 +02002066 _number: EDIT,
Ben Rohlfs1fe7f4d2021-12-06 11:21:49 +01002067 basePatchNum: 1 as BasePatchSetNum,
2068 commit: {
2069 ...createCommit(),
2070 commit: 'bar' as CommitId,
2071 },
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002072 fetch: {},
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002073 };
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002074
Ben Rohlfs1fe7f4d2021-12-06 11:21:49 +01002075 // When edit is set, but not patchNum, then switch to edit ps.
Chris Poucet973ecc92022-06-13 10:44:07 +02002076 element.processEdit(change);
2077 assert.equal(element.patchRange.patchNum, EDIT);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002078
Ben Rohlfs1fe7f4d2021-12-06 11:21:49 +01002079 // When edit is set, but patchNum as well, then keep patchNum.
Chris Poucet973ecc92022-06-13 10:44:07 +02002080 element.patchRange.patchNum = 5 as RevisionPatchSetNum;
Ben Rohlfs8ccb2d42021-12-08 11:22:20 +01002081 element.routerPatchNum = 5 as RevisionPatchSetNum;
Chris Poucet973ecc92022-06-13 10:44:07 +02002082 element.processEdit(change);
2083 assert.equal(element.patchRange.patchNum, 5 as RevisionPatchSetNum);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002084 });
2085
Frank Borden8198a832022-04-11 17:31:15 +02002086 test('file-action-tap handling', async () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02002087 element.patchRange = {
Ben Rohlfs58267b72022-05-27 15:59:18 +02002088 basePatchNum: PARENT,
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01002089 patchNum: 1 as RevisionPatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002090 };
Chris Poucet973ecc92022-06-13 10:44:07 +02002091 element.change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +02002092 ...createChangeViewChange(),
Milutin Kristoficbec88f12020-10-13 16:53:28 +02002093 };
Chris Poucet973ecc92022-06-13 10:44:07 +02002094 assertIsDefined(element.fileList);
2095 assertIsDefined(element.fileListHeader);
2096 const fileList = element.fileList;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002097 const Actions = GrEditConstants.Actions;
Chris Poucet973ecc92022-06-13 10:44:07 +02002098 element.fileListHeader.editMode = true;
2099 await element.fileListHeader.updateComplete;
2100 await element.updateComplete;
Frank Borden8198a832022-04-11 17:31:15 +02002101 const controls = queryAndAssert<GrEditControls>(
Chris Poucet973ecc92022-06-13 10:44:07 +02002102 element.fileListHeader,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002103 '#editControls'
Frank Borden8198a832022-04-11 17:31:15 +02002104 );
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002105 const openDeleteDialogStub = sinon.stub(controls, 'openDeleteDialog');
2106 const openRenameDialogStub = sinon.stub(controls, 'openRenameDialog');
2107 const openRestoreDialogStub = sinon.stub(controls, 'openRestoreDialog');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002108
2109 // Delete
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002110 fileList.dispatchEvent(
2111 new CustomEvent('file-action-tap', {
2112 detail: {action: Actions.DELETE.id, path: 'foo'},
2113 bubbles: true,
2114 composed: true,
2115 })
2116 );
Chris Poucet973ecc92022-06-13 10:44:07 +02002117 await element.updateComplete;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002118
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002119 assert.isTrue(openDeleteDialogStub.called);
2120 assert.equal(openDeleteDialogStub.lastCall.args[0], 'foo');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002121
2122 // Restore
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002123 fileList.dispatchEvent(
2124 new CustomEvent('file-action-tap', {
2125 detail: {action: Actions.RESTORE.id, path: 'foo'},
2126 bubbles: true,
2127 composed: true,
2128 })
2129 );
Chris Poucet973ecc92022-06-13 10:44:07 +02002130 await element.updateComplete;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002131
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002132 assert.isTrue(openRestoreDialogStub.called);
2133 assert.equal(openRestoreDialogStub.lastCall.args[0], 'foo');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002134
2135 // Rename
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002136 fileList.dispatchEvent(
2137 new CustomEvent('file-action-tap', {
2138 detail: {action: Actions.RENAME.id, path: 'foo'},
2139 bubbles: true,
2140 composed: true,
2141 })
2142 );
Chris Poucet973ecc92022-06-13 10:44:07 +02002143 await element.updateComplete;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002144
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002145 assert.isTrue(openRenameDialogStub.called);
2146 assert.equal(openRenameDialogStub.lastCall.args[0], 'foo');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002147
2148 // Open
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002149 fileList.dispatchEvent(
2150 new CustomEvent('file-action-tap', {
2151 detail: {action: Actions.OPEN.id, path: 'foo'},
2152 bubbles: true,
2153 composed: true,
2154 })
2155 );
Chris Poucet973ecc92022-06-13 10:44:07 +02002156 await element.updateComplete;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002157
Ben Rohlfs54934de2022-09-22 12:44:33 +02002158 assert.isTrue(setUrlStub.called);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002159 });
2160
Chris Poucet973ecc92022-06-13 10:44:07 +02002161 test('selectedRevision updates when patchNum is changed', async () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002162 const revision1: RevisionInfo = createRevision(1);
2163 const revision2: RevisionInfo = createRevision(2);
Chris Poucetbf65b8f2022-01-18 21:18:12 +00002164 element.getChangeModel().setState({
Ben Rohlfs61bafc22021-11-29 10:40:08 +01002165 loadingStatus: LoadingStatus.LOADED,
Ben Rohlfsa16c51a2021-11-22 12:50:55 +01002166 change: {
Dhruv Srivastavada276592021-04-07 14:51:51 +02002167 ...createChangeViewChange(),
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002168 revisions: {
2169 aaa: revision1,
2170 bbb: revision2,
2171 },
2172 labels: {},
2173 actions: {},
2174 current_revision: 'bbb' as CommitId,
Ben Rohlfsa16c51a2021-11-22 12:50:55 +01002175 },
2176 });
Chris Poucet973ecc92022-06-13 10:44:07 +02002177 element.userModel.setPreferences(createPreferences());
Ben Rohlfsa16c51a2021-11-22 12:50:55 +01002178
Chris Poucet973ecc92022-06-13 10:44:07 +02002179 element.patchRange = {patchNum: 2 as RevisionPatchSetNum};
2180 await element.performPostChangeLoadTasks();
2181 assert.strictEqual(element.selectedRevision, revision2);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002182
Chris Poucet973ecc92022-06-13 10:44:07 +02002183 element.patchRange = {patchNum: 1 as RevisionPatchSetNum};
2184 await element.updateComplete;
2185 assert.strictEqual(element.selectedRevision, revision1);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002186 });
2187
Chris Poucet973ecc92022-06-13 10:44:07 +02002188 test('selectedRevision is assigned when patchNum is edit', async () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002189 const revision1 = createRevision(1);
2190 const revision2 = createRevision(2);
2191 const revision3 = createEditRevision();
Chris Poucetbf65b8f2022-01-18 21:18:12 +00002192 element.getChangeModel().setState({
Ben Rohlfs61bafc22021-11-29 10:40:08 +01002193 loadingStatus: LoadingStatus.LOADED,
Ben Rohlfsa16c51a2021-11-22 12:50:55 +01002194 change: {
Dhruv Srivastavada276592021-04-07 14:51:51 +02002195 ...createChangeViewChange(),
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002196 revisions: {
2197 aaa: revision1,
2198 bbb: revision2,
2199 ccc: revision3,
2200 },
2201 labels: {},
2202 actions: {},
2203 current_revision: 'ccc' as CommitId,
Ben Rohlfsa16c51a2021-11-22 12:50:55 +01002204 },
2205 });
Chris Poucet973ecc92022-06-13 10:44:07 +02002206 stubRestApi('getPreferences').returns(Promise.resolve(createPreferences()));
2207
2208 element.patchRange = {patchNum: EDIT};
Ben Rohlfs1fe7f4d2021-12-06 11:21:49 +01002209 await element.performPostChangeLoadTasks();
Chris Poucet973ecc92022-06-13 10:44:07 +02002210 assert.strictEqual(element.selectedRevision, revision3);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002211 });
2212
Chris Poucet973ecc92022-06-13 10:44:07 +02002213 test('sendShowChangeEvent', () => {
Dhruv Srivastavada276592021-04-07 14:51:51 +02002214 const change = {...createChangeViewChange(), labels: {}};
Chris Poucet973ecc92022-06-13 10:44:07 +02002215 element.change = {...change};
2216 element.patchRange = {patchNum: 4 as RevisionPatchSetNum};
2217 element.mergeable = true;
Chris Poucetc6e880b2021-11-15 19:57:06 +01002218 const showStub = sinon.stub(element.jsAPI, 'handleEvent');
Chris Poucet973ecc92022-06-13 10:44:07 +02002219 element.sendShowChangeEvent();
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002220 assert.isTrue(showStub.calledOnce);
Ben Rohlfsa47355d2020-08-30 15:56:13 +02002221 assert.equal(showStub.lastCall.args[0], EventType.SHOW_CHANGE);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002222 assert.deepEqual(showStub.lastCall.args[1], {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002223 change,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002224 patchNum: 4,
2225 info: {mergeable: true},
2226 });
2227 });
2228
Dhruv Srivastava254b1da2021-10-27 12:32:44 +02002229 test('patch range changed', () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02002230 element.patchRange = undefined;
2231 element.change = createChangeViewChange();
2232 element.change.revisions = createRevisions(4);
2233 element.change.current_revision = '1' as CommitId;
2234 element.change = {...element.change};
Dhruv Srivastava254b1da2021-10-27 12:32:44 +02002235
Ben Rohlfs10dfa932022-09-19 13:43:32 +02002236 const viewState = createChangeViewState();
Dhruv Srivastava254b1da2021-10-27 12:32:44 +02002237
Ben Rohlfs10dfa932022-09-19 13:43:32 +02002238 assert.isFalse(element.hasPatchRangeChanged(viewState));
2239 assert.isFalse(element.hasPatchNumChanged(viewState));
Dhruv Srivastava254b1da2021-10-27 12:32:44 +02002240
Ben Rohlfs10dfa932022-09-19 13:43:32 +02002241 viewState.basePatchNum = PARENT;
Dhruv Srivastava254b1da2021-10-27 12:32:44 +02002242 // undefined means navigate to latest patchset
Ben Rohlfs10dfa932022-09-19 13:43:32 +02002243 viewState.patchNum = undefined;
Dhruv Srivastava254b1da2021-10-27 12:32:44 +02002244
Chris Poucet973ecc92022-06-13 10:44:07 +02002245 element.patchRange = {
Dhruv Srivastava254b1da2021-10-27 12:32:44 +02002246 patchNum: 2 as RevisionPatchSetNum,
Ben Rohlfs58267b72022-05-27 15:59:18 +02002247 basePatchNum: PARENT,
Dhruv Srivastava254b1da2021-10-27 12:32:44 +02002248 };
2249
Ben Rohlfs10dfa932022-09-19 13:43:32 +02002250 assert.isTrue(element.hasPatchRangeChanged(viewState));
2251 assert.isTrue(element.hasPatchNumChanged(viewState));
Dhruv Srivastava254b1da2021-10-27 12:32:44 +02002252
Chris Poucet973ecc92022-06-13 10:44:07 +02002253 element.patchRange = {
Dhruv Srivastava254b1da2021-10-27 12:32:44 +02002254 patchNum: 4 as RevisionPatchSetNum,
Ben Rohlfs58267b72022-05-27 15:59:18 +02002255 basePatchNum: PARENT,
Dhruv Srivastava254b1da2021-10-27 12:32:44 +02002256 };
2257
Ben Rohlfs10dfa932022-09-19 13:43:32 +02002258 assert.isFalse(element.hasPatchRangeChanged(viewState));
2259 assert.isFalse(element.hasPatchNumChanged(viewState));
Dhruv Srivastava254b1da2021-10-27 12:32:44 +02002260 });
2261
Chris Poucet973ecc92022-06-13 10:44:07 +02002262 suite('handleEditTap', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002263 let fireEdit: () => void;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002264
2265 setup(() => {
2266 fireEdit = () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02002267 assertIsDefined(element.actions);
2268 element.actions.dispatchEvent(new CustomEvent('edit-tap'));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002269 };
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002270
Chris Poucet973ecc92022-06-13 10:44:07 +02002271 element.change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +02002272 ...createChangeViewChange(),
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002273 revisions: {rev1: createRevision()},
2274 };
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002275 });
2276
Chris Pouceta2e173e2021-08-31 01:04:04 +00002277 test('edit exists in revisions', async () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02002278 assertIsDefined(element.change);
2279 const newChange = {...element.change};
2280 newChange.revisions.rev2 = createRevision(EDIT);
2281 element.change = newChange;
2282 await element.updateComplete;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002283
2284 fireEdit();
Ben Rohlfsaa533902022-09-22 09:07:12 +02002285 assert.isTrue(setUrlStub.called);
2286 assert.equal(setUrlStub.lastCall.firstArg, '/c/test-project/+/42/edit');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002287 });
2288
Chris Pouceta2e173e2021-08-31 01:04:04 +00002289 test('no edit exists in revisions, non-latest patchset', async () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02002290 assertIsDefined(element.change);
2291 const newChange = {...element.change};
2292 newChange.revisions.rev2 = createRevision(2);
2293 element.change = newChange;
2294 element.patchRange = {patchNum: 1 as RevisionPatchSetNum};
2295 await element.updateComplete;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002296
2297 fireEdit();
Ben Rohlfsaa533902022-09-22 09:07:12 +02002298 assert.isTrue(setUrlStub.called);
2299 assert.equal(
2300 setUrlStub.lastCall.firstArg,
2301 '/c/test-project/+/42/1,edit?forceReload=true'
2302 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002303 });
2304
Chris Pouceta2e173e2021-08-31 01:04:04 +00002305 test('no edit exists in revisions, latest patchset', async () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02002306 assertIsDefined(element.change);
2307 const newChange = {...element.change};
2308 newChange.revisions.rev2 = createRevision(2);
2309 element.change = newChange;
2310 element.patchRange = {patchNum: 2 as RevisionPatchSetNum};
2311 await element.updateComplete;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002312
2313 fireEdit();
Ben Rohlfsaa533902022-09-22 09:07:12 +02002314 assert.isTrue(setUrlStub.called);
2315 assert.equal(
2316 setUrlStub.lastCall.firstArg,
2317 '/c/test-project/+/42,edit?forceReload=true'
2318 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002319 });
2320 });
2321
Chris Poucet973ecc92022-06-13 10:44:07 +02002322 test('handleStopEditTap', async () => {
2323 element.change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +02002324 ...createChangeViewChange(),
Milutin Kristoficbec88f12020-10-13 16:53:28 +02002325 };
Chris Poucet973ecc92022-06-13 10:44:07 +02002326 await element.updateComplete;
2327 assertIsDefined(element.metadata);
2328 assertIsDefined(element.actions);
2329 sinon.stub(element.metadata, 'computeLabelNames');
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002330
Chris Poucet973ecc92022-06-13 10:44:07 +02002331 element.patchRange = {patchNum: 1 as RevisionPatchSetNum};
2332 element.actions.dispatchEvent(
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002333 new CustomEvent('stop-edit-tap', {bubbles: false})
2334 );
Ben Rohlfsaa533902022-09-22 09:07:12 +02002335
2336 assert.isTrue(setUrlStub.called);
2337 assert.equal(
2338 setUrlStub.lastCall.firstArg,
2339 '/c/test-project/+/42/1?forceReload=true'
2340 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002341 });
2342
2343 suite('plugin endpoints', () => {
Chris Pouceta2e173e2021-08-31 01:04:04 +00002344 test('endpoint params', async () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02002345 element.change = {...createChangeViewChange(), labels: {}};
2346 element.selectedRevision = createRevision();
Chris Pouceta2e173e2021-08-31 01:04:04 +00002347 const promise = mockPromise();
Chris Poucetd3f52fd2021-11-29 23:16:39 +01002348 window.Gerrit.install(
2349 promise.resolve,
2350 '0.1',
2351 'http://some/plugins/url.js'
2352 );
Chris Poucet973ecc92022-06-13 10:44:07 +02002353 await element.updateComplete;
Chris Pouceta2e173e2021-08-31 01:04:04 +00002354 const plugin: PluginApi = (await promise) as PluginApi;
2355 const hookEl = await plugin
2356 .hook('change-view-integration')
2357 .getLastAttached();
2358 assert.strictEqual((hookEl as any).plugin, plugin);
Chris Poucet973ecc92022-06-13 10:44:07 +02002359 assert.strictEqual((hookEl as any).change, element.change);
2360 assert.strictEqual((hookEl as any).revision, element.selectedRevision);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002361 });
2362 });
2363
Chris Poucet973ecc92022-06-13 10:44:07 +02002364 suite('getMergeability', () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002365 let getMergeableStub: SinonStubbedMember<RestApiService['getMergeable']>;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002366 setup(() => {
Chris Poucet973ecc92022-06-13 10:44:07 +02002367 element.change = {...createChangeViewChange(), labels: {}};
Ben Rohlfs3a6ff7e2021-01-18 14:08:39 +01002368 getMergeableStub = stubRestApi('getMergeable').returns(
2369 Promise.resolve({...createMergeable(), mergeable: true})
2370 );
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002371 });
2372
2373 test('merged change', () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02002374 element.mergeable = null;
2375 element.change!.status = ChangeStatus.MERGED;
2376 return element.getMergeability().then(() => {
2377 assert.isFalse(element.mergeable);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002378 assert.isFalse(getMergeableStub.called);
2379 });
2380 });
2381
2382 test('abandoned change', () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02002383 element.mergeable = null;
2384 element.change!.status = ChangeStatus.ABANDONED;
2385 return element.getMergeability().then(() => {
2386 assert.isFalse(element.mergeable);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002387 assert.isFalse(getMergeableStub.called);
2388 });
2389 });
2390
2391 test('open change', () => {
Chris Poucet973ecc92022-06-13 10:44:07 +02002392 element.mergeable = null;
2393 return element.getMergeability().then(() => {
2394 assert.isTrue(element.mergeable);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002395 assert.isTrue(getMergeableStub.called);
2396 });
2397 });
2398 });
2399
Chris Poucet973ecc92022-06-13 10:44:07 +02002400 test('handleToggleStar called when star is tapped', async () => {
2401 element.change = {
Dhruv Srivastavada276592021-04-07 14:51:51 +02002402 ...createChangeViewChange(),
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002403 owner: {_account_id: 1 as AccountId},
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002404 starred: false,
2405 };
Chris Poucet973ecc92022-06-13 10:44:07 +02002406 element.loggedIn = true;
2407 await element.updateComplete;
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002408
Chris Poucet973ecc92022-06-13 10:44:07 +02002409 const stub = sinon.stub(element, 'handleToggleStar');
Paladox none70efbef2021-08-12 05:21:59 +00002410
2411 const changeStar = queryAndAssert<GrChangeStar>(element, '#changeStar');
Frank Borden6919f442022-08-29 16:35:24 +02002412 queryAndAssert<HTMLButtonElement>(changeStar, 'button')!.click();
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002413 assert.isTrue(stub.called);
2414 });
2415
2416 suite('gr-reporting tests', () => {
2417 setup(() => {
Chris Poucet973ecc92022-06-13 10:44:07 +02002418 element.patchRange = {
Ben Rohlfs58267b72022-05-27 15:59:18 +02002419 basePatchNum: PARENT,
Dhruv Srivastava1c41a1b72021-03-11 16:24:53 +01002420 patchNum: 1 as RevisionPatchSetNum,
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002421 };
Dhruv Srivastava21129812021-12-02 15:48:03 +01002422 sinon
2423 .stub(element, 'performPostChangeLoadTasks')
2424 .returns(Promise.resolve(false));
Chris Poucet973ecc92022-06-13 10:44:07 +02002425 sinon.stub(element, 'getMergeability').returns(Promise.resolve());
2426 sinon.stub(element, 'getLatestCommitMessage').returns(Promise.resolve());
Ben Rohlfs3a6ff7e2021-01-18 14:08:39 +01002427 sinon
Chris Poucet973ecc92022-06-13 10:44:07 +02002428 .stub(element, 'reloadPatchNumDependentResources')
Dhruv Srivastava09a1b5a2021-01-20 09:28:15 +01002429 .returns(Promise.resolve([undefined, undefined, undefined]));
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002430 });
2431
Chris Pouceta2e173e2021-08-31 01:04:04 +00002432 test("don't report changeDisplayed on reply", async () => {
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002433 const changeDisplayStub = sinon.stub(
Chris Poucetc6e880b2021-11-15 19:57:06 +01002434 element.reporting,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002435 'changeDisplayed'
2436 );
2437 const changeFullyLoadedStub = sinon.stub(
Chris Poucetc6e880b2021-11-15 19:57:06 +01002438 element.reporting,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002439 'changeFullyLoaded'
2440 );
Chris Poucet973ecc92022-06-13 10:44:07 +02002441 element.handleReplySent();
2442 await element.updateComplete;
Chris Pouceta2e173e2021-08-31 01:04:04 +00002443 assert.isFalse(changeDisplayStub.called);
2444 assert.isFalse(changeFullyLoadedStub.called);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002445 });
2446
Ben Rohlfs10dfa932022-09-19 13:43:32 +02002447 test('report changeDisplayed on viewStateChanged', async () => {
Ben Rohlfsb7ef7f72022-06-10 12:17:28 +02002448 stubRestApi('getChangeOrEditFiles').resolves({
2449 'a-file.js': {},
2450 });
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002451 const changeDisplayStub = sinon.stub(
Chris Poucetc6e880b2021-11-15 19:57:06 +01002452 element.reporting,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002453 'changeDisplayed'
2454 );
2455 const changeFullyLoadedStub = sinon.stub(
Chris Poucetc6e880b2021-11-15 19:57:06 +01002456 element.reporting,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002457 'changeFullyLoaded'
2458 );
Dhruv Srivastava49f0a7a2021-10-06 12:03:01 +01002459 // reset so reload is triggered
Chris Poucet973ecc92022-06-13 10:44:07 +02002460 element.changeNum = undefined;
Ben Rohlfs10dfa932022-09-19 13:43:32 +02002461 element.viewState = {
Ben Rohlfs65c2f2b2022-09-12 22:35:26 +02002462 ...createChangeViewState(),
Ben Rohlfsa5356e92021-05-07 11:06:17 +02002463 changeNum: TEST_NUMERIC_CHANGE_ID,
Dmitrii Filippov78448cd2020-10-26 17:39:11 +01002464 project: TEST_PROJECT_NAME,
Ben Rohlfs71a8dee2021-06-22 10:06:15 +02002465 };
Chris Poucetbf65b8f2022-01-18 21:18:12 +00002466 element.getChangeModel().setState({
Dhruv Srivastava21129812021-12-02 15:48:03 +01002467 loadingStatus: LoadingStatus.LOADED,
2468 change: {
2469 ...createChangeViewChange(),
2470 labels: {},
2471 current_revision: 'foo' as CommitId,
2472 revisions: {foo: createRevision()},
2473 },
2474 });
Chris Poucet973ecc92022-06-13 10:44:07 +02002475 await element.updateComplete;
Frank Borden7b24f732022-09-12 14:29:32 +02002476 await waitEventLoop();
Ben Rohlfs71a8dee2021-06-22 10:06:15 +02002477 assert.isTrue(changeDisplayStub.called);
2478 assert.isTrue(changeFullyLoadedStub.called);
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002479 });
2480 });
Milutin Kristofice9ddfa42021-04-20 23:34:45 +02002481
Chris Poucet973ecc92022-06-13 10:44:07 +02002482 test('calculateHasParent', () => {
Milutin Kristofice9ddfa42021-04-20 23:34:45 +02002483 const changeId = '123' as ChangeId;
2484 const relatedChanges: RelatedChangeAndCommitInfo[] = [];
2485
Chris Poucet973ecc92022-06-13 10:44:07 +02002486 assert.equal(element.calculateHasParent(changeId, relatedChanges), false);
Milutin Kristofice9ddfa42021-04-20 23:34:45 +02002487
2488 relatedChanges.push({
2489 ...createRelatedChangeAndCommitInfo(),
2490 change_id: '123' as ChangeId,
2491 });
Chris Poucet973ecc92022-06-13 10:44:07 +02002492 assert.equal(element.calculateHasParent(changeId, relatedChanges), false);
Milutin Kristofice9ddfa42021-04-20 23:34:45 +02002493
2494 relatedChanges.push({
2495 ...createRelatedChangeAndCommitInfo(),
2496 change_id: '234' as ChangeId,
2497 });
Chris Poucet973ecc92022-06-13 10:44:07 +02002498 assert.equal(element.calculateHasParent(changeId, relatedChanges), true);
Milutin Kristofice9ddfa42021-04-20 23:34:45 +02002499 });
Milutin Kristoficc3dfb232022-09-06 14:37:07 +02002500
2501 test('renders sha in copy links', async () => {
2502 stubFlags('isEnabled').returns(true);
Milutin Kristoficc3dfb232022-09-06 14:37:07 +02002503 const sha = '123' as CommitId;
2504 element.change = {
2505 ...createChangeViewChange(),
2506 status: ChangeStatus.MERGED,
2507 current_revision: sha,
2508 };
2509 await element.updateComplete;
2510
2511 const copyLinksDialog = queryAndAssert<GrCopyLinks>(
2512 element,
2513 'gr-copy-links'
2514 );
2515 assert.isTrue(
2516 copyLinksDialog.copyLinks.some(copyLink => copyLink.value === sha)
2517 );
2518 });
Dmitrii Filippovdaf0ec92020-03-17 11:27:28 +01002519});