blob: 136ae2ef8bef6d838042973c2dddfaaaeb3c9285 [file] [log] [blame]
paladox68b968e2022-02-20 17:31:50 +00001/**
2 * @license
Ben Rohlfs94fcbbc2022-05-27 10:45:03 +02003 * Copyright 2017 Google LLC
4 * SPDX-License-Identifier: Apache-2.0
paladox68b968e2022-02-20 17:31:50 +00005 */
Frank Bordenbe9451a2022-09-12 15:44:29 +02006import '../../../test/common-test-setup';
paladox68b968e2022-02-20 17:31:50 +00007import './gr-router';
8import {page} from '../../../utils/page-wrapper-utils';
Milutin Kristofic84e818d2022-08-09 21:30:38 +02009import {GerritNav, WeblinkType} from '../gr-navigation/gr-navigation';
paladox68b968e2022-02-20 17:31:50 +000010import {
11 stubBaseUrl,
12 stubRestApi,
13 addListenerForTest,
Frank Borden7b24f732022-09-12 14:29:32 +020014 waitEventLoop,
paladox68b968e2022-02-20 17:31:50 +000015} from '../../../test/test-utils';
16import {
17 GrRouter,
18 PageContextWithQueryMap,
paladox68b968e2022-02-20 17:31:50 +000019 _testOnly_RoutePattern,
20} from './gr-router';
21import {GerritView} from '../../../services/router/router-model';
22import {
23 BasePatchSetNum,
paladox68b968e2022-02-20 17:31:50 +000024 CommitId,
paladox68b968e2022-02-20 17:31:50 +000025 GroupId,
26 NumericChangeId,
Ben Rohlfs58267b72022-05-27 15:59:18 +020027 PARENT,
paladox68b968e2022-02-20 17:31:50 +000028 RepoName,
29 RevisionPatchSetNum,
paladox68b968e2022-02-20 17:31:50 +000030 UrlEncodedCommentId,
31 WebLinkInfo,
32} from '../../../types/common';
33import {
34 createGerritInfo,
35 createServerInfo,
36} from '../../../test/test-data-generators';
37import {AppElementParams} from '../../gr-app-types';
Ben Rohlfs804e7242022-09-15 16:16:12 +020038import {GenerateUrlParameters} from '../../../utils/router-util';
Frank Bordene1ba8212022-08-29 15:20:01 +020039import {assert} from '@open-wc/testing';
Ben Rohlfsdcb88ac2022-09-12 11:50:26 +020040import {AdminChildView} from '../../../models/views/admin';
Ben Rohlfsade94cb2022-09-14 19:59:42 +020041import {RepoDetailView} from '../../../models/views/repo';
42import {GroupDetailView} from '../../../models/views/group';
Ben Rohlfs6a0033a2022-09-15 11:32:55 +020043import {EditViewState} from '../../../models/views/edit';
Ben Rohlfs804e7242022-09-15 16:16:12 +020044import {ChangeViewState} from '../../../models/views/change';
Ben Rohlfsbd8dbcf2022-09-16 09:01:14 +020045import {PatchRangeParams} from '../../../utils/url-util';
paladox68b968e2022-02-20 17:31:50 +000046
paladox68b968e2022-02-20 17:31:50 +000047suite('gr-router tests', () => {
Frank Borden79448112022-04-12 16:59:32 +020048 let router: GrRouter;
paladox68b968e2022-02-20 17:31:50 +000049
50 setup(() => {
Frank Borden79448112022-04-12 16:59:32 +020051 router = new GrRouter();
paladox68b968e2022-02-20 17:31:50 +000052 });
53
Frank Borden79448112022-04-12 16:59:32 +020054 test('firstCodeBrowserWeblink', () => {
paladox68b968e2022-02-20 17:31:50 +000055 assert.deepEqual(
Frank Borden79448112022-04-12 16:59:32 +020056 router.firstCodeBrowserWeblink([
paladox68b968e2022-02-20 17:31:50 +000057 {name: 'gitweb'},
58 {name: 'gitiles'},
59 {name: 'browse'},
60 {name: 'test'},
61 ]),
62 {name: 'gitiles'}
63 );
64
65 assert.deepEqual(
Frank Borden79448112022-04-12 16:59:32 +020066 router.firstCodeBrowserWeblink([{name: 'gitweb'}, {name: 'test'}]),
paladox68b968e2022-02-20 17:31:50 +000067 {name: 'gitweb'}
68 );
69 });
70
Frank Borden79448112022-04-12 16:59:32 +020071 test('getBrowseCommitWeblink', () => {
paladox68b968e2022-02-20 17:31:50 +000072 const browserLink = {name: 'browser', url: 'browser/url'};
73 const link = {name: 'test', url: 'test/url'};
74 const weblinks = [browserLink, link];
75 const config = {
76 ...createServerInfo(),
77 gerrit: {...createGerritInfo(), primary_weblink_name: browserLink.name},
78 };
Frank Borden79448112022-04-12 16:59:32 +020079 sinon.stub(router, 'firstCodeBrowserWeblink').returns(link);
paladox68b968e2022-02-20 17:31:50 +000080
81 assert.deepEqual(
Frank Borden79448112022-04-12 16:59:32 +020082 router.getBrowseCommitWeblink(weblinks, config),
paladox68b968e2022-02-20 17:31:50 +000083 browserLink
84 );
85
Frank Borden79448112022-04-12 16:59:32 +020086 assert.deepEqual(router.getBrowseCommitWeblink(weblinks), link);
paladox68b968e2022-02-20 17:31:50 +000087 });
88
Frank Borden79448112022-04-12 16:59:32 +020089 test('getChangeWeblinks', () => {
paladox68b968e2022-02-20 17:31:50 +000090 const link = {name: 'test', url: 'test/url'};
91 const browserLink = {name: 'browser', url: 'browser/url'};
92 const mapLinksToConfig = (weblinks: WebLinkInfo[]) => {
93 return {
94 type: 'change' as WeblinkType.CHANGE,
95 repo: 'test' as RepoName,
96 commit: '111' as CommitId,
97 options: {weblinks},
98 };
99 };
Frank Borden79448112022-04-12 16:59:32 +0200100 sinon.stub(router, 'getBrowseCommitWeblink').returns(browserLink);
paladox68b968e2022-02-20 17:31:50 +0000101
102 assert.deepEqual(
Frank Borden79448112022-04-12 16:59:32 +0200103 router.getChangeWeblinks(mapLinksToConfig([link, browserLink]))[0],
paladox68b968e2022-02-20 17:31:50 +0000104 {name: 'test', url: 'test/url'}
105 );
106
Frank Borden79448112022-04-12 16:59:32 +0200107 assert.deepEqual(router.getChangeWeblinks(mapLinksToConfig([link]))[0], {
paladox68b968e2022-02-20 17:31:50 +0000108 name: 'test',
109 url: 'test/url',
110 });
111
112 link.url = `https://${link.url}`;
Frank Borden79448112022-04-12 16:59:32 +0200113 assert.deepEqual(router.getChangeWeblinks(mapLinksToConfig([link]))[0], {
paladox68b968e2022-02-20 17:31:50 +0000114 name: 'test',
115 url: 'https://test/url',
116 });
117 });
118
Frank Borden79448112022-04-12 16:59:32 +0200119 test('getHashFromCanonicalPath', () => {
paladox68b968e2022-02-20 17:31:50 +0000120 let url = '/foo/bar';
Frank Borden79448112022-04-12 16:59:32 +0200121 let hash = router.getHashFromCanonicalPath(url);
paladox68b968e2022-02-20 17:31:50 +0000122 assert.equal(hash, '');
123
124 url = '';
Frank Borden79448112022-04-12 16:59:32 +0200125 hash = router.getHashFromCanonicalPath(url);
paladox68b968e2022-02-20 17:31:50 +0000126 assert.equal(hash, '');
127
128 url = '/foo#bar';
Frank Borden79448112022-04-12 16:59:32 +0200129 hash = router.getHashFromCanonicalPath(url);
paladox68b968e2022-02-20 17:31:50 +0000130 assert.equal(hash, 'bar');
131
132 url = '/foo#bar#baz';
Frank Borden79448112022-04-12 16:59:32 +0200133 hash = router.getHashFromCanonicalPath(url);
paladox68b968e2022-02-20 17:31:50 +0000134 assert.equal(hash, 'bar#baz');
135
136 url = '#foo#bar#baz';
Frank Borden79448112022-04-12 16:59:32 +0200137 hash = router.getHashFromCanonicalPath(url);
paladox68b968e2022-02-20 17:31:50 +0000138 assert.equal(hash, 'foo#bar#baz');
139 });
140
Frank Borden79448112022-04-12 16:59:32 +0200141 suite('parseLineAddress', () => {
paladox68b968e2022-02-20 17:31:50 +0000142 test('returns null for empty and invalid hashes', () => {
Frank Borden79448112022-04-12 16:59:32 +0200143 let actual = router.parseLineAddress('');
paladox68b968e2022-02-20 17:31:50 +0000144 assert.isNull(actual);
145
Frank Borden79448112022-04-12 16:59:32 +0200146 actual = router.parseLineAddress('foobar');
paladox68b968e2022-02-20 17:31:50 +0000147 assert.isNull(actual);
148
Frank Borden79448112022-04-12 16:59:32 +0200149 actual = router.parseLineAddress('foo123');
paladox68b968e2022-02-20 17:31:50 +0000150 assert.isNull(actual);
151
Frank Borden79448112022-04-12 16:59:32 +0200152 actual = router.parseLineAddress('123bar');
paladox68b968e2022-02-20 17:31:50 +0000153 assert.isNull(actual);
154 });
155
156 test('parses correctly', () => {
Frank Borden79448112022-04-12 16:59:32 +0200157 let actual = router.parseLineAddress('1234');
paladox68b968e2022-02-20 17:31:50 +0000158 assert.isOk(actual);
159 assert.equal(actual!.lineNum, 1234);
160 assert.isFalse(actual!.leftSide);
161
Frank Borden79448112022-04-12 16:59:32 +0200162 actual = router.parseLineAddress('a4');
paladox68b968e2022-02-20 17:31:50 +0000163 assert.isOk(actual);
164 assert.equal(actual!.lineNum, 4);
165 assert.isTrue(actual!.leftSide);
166
Frank Borden79448112022-04-12 16:59:32 +0200167 actual = router.parseLineAddress('b77');
paladox68b968e2022-02-20 17:31:50 +0000168 assert.isOk(actual);
169 assert.equal(actual!.lineNum, 77);
170 assert.isTrue(actual!.leftSide);
171 });
172 });
173
Frank Borden79448112022-04-12 16:59:32 +0200174 test('startRouter requires auth for the right handlers', () => {
paladox68b968e2022-02-20 17:31:50 +0000175 // This test encodes the lists of route handler methods that gr-router
176 // automatically checks for authentication before triggering.
177
178 const requiresAuth: any = {};
179 const doesNotRequireAuth: any = {};
180 sinon.stub(GerritNav, 'setup');
181 sinon.stub(page, 'start');
182 sinon.stub(page, 'base');
183 sinon
Frank Borden79448112022-04-12 16:59:32 +0200184 .stub(router, 'mapRoute')
185 .callsFake((_pattern, methodName, _method, usesAuth) => {
paladox68b968e2022-02-20 17:31:50 +0000186 if (usesAuth) {
187 requiresAuth[methodName] = true;
188 } else {
189 doesNotRequireAuth[methodName] = true;
190 }
191 });
Frank Borden79448112022-04-12 16:59:32 +0200192 router.startRouter();
paladox68b968e2022-02-20 17:31:50 +0000193
194 const actualRequiresAuth = Object.keys(requiresAuth);
195 actualRequiresAuth.sort();
196 const actualDoesNotRequireAuth = Object.keys(doesNotRequireAuth);
197 actualDoesNotRequireAuth.sort();
198
199 const shouldRequireAutoAuth = [
Frank Borden79448112022-04-12 16:59:32 +0200200 'handleAgreementsRoute',
201 'handleChangeEditRoute',
202 'handleCreateGroupRoute',
203 'handleCreateProjectRoute',
204 'handleDiffEditRoute',
205 'handleGroupAuditLogRoute',
206 'handleGroupInfoRoute',
207 'handleGroupListFilterOffsetRoute',
208 'handleGroupListFilterRoute',
209 'handleGroupListOffsetRoute',
210 'handleGroupMembersRoute',
211 'handleGroupRoute',
212 'handleGroupSelfRedirectRoute',
213 'handleNewAgreementsRoute',
214 'handlePluginListFilterOffsetRoute',
215 'handlePluginListFilterRoute',
216 'handlePluginListOffsetRoute',
217 'handlePluginListRoute',
218 'handleRepoCommandsRoute',
219 'handleSettingsLegacyRoute',
220 'handleSettingsRoute',
paladox68b968e2022-02-20 17:31:50 +0000221 ];
222 assert.deepEqual(actualRequiresAuth, shouldRequireAutoAuth);
223
224 const unauthenticatedHandlers = [
Frank Borden79448112022-04-12 16:59:32 +0200225 'handleBranchListFilterOffsetRoute',
226 'handleBranchListFilterRoute',
227 'handleBranchListOffsetRoute',
228 'handleChangeIdQueryRoute',
229 'handleChangeNumberLegacyRoute',
230 'handleChangeRoute',
231 'handleCommentRoute',
232 'handleCommentsRoute',
233 'handleDiffRoute',
234 'handleDefaultRoute',
235 'handleChangeLegacyRoute',
236 'handleDocumentationRedirectRoute',
237 'handleDocumentationSearchRoute',
238 'handleDocumentationSearchRedirectRoute',
239 'handleLegacyLinenum',
240 'handleImproperlyEncodedPlusRoute',
241 'handlePassThroughRoute',
242 'handleProjectDashboardRoute',
243 'handleLegacyProjectDashboardRoute',
244 'handleProjectsOldRoute',
245 'handleRepoAccessRoute',
246 'handleRepoDashboardsRoute',
247 'handleRepoGeneralRoute',
248 'handleRepoListFilterOffsetRoute',
249 'handleRepoListFilterRoute',
250 'handleRepoListOffsetRoute',
251 'handleRepoRoute',
252 'handleQueryLegacySuffixRoute',
253 'handleQueryRoute',
254 'handleRegisterRoute',
255 'handleTagListFilterOffsetRoute',
256 'handleTagListFilterRoute',
257 'handleTagListOffsetRoute',
258 'handlePluginScreen',
paladox68b968e2022-02-20 17:31:50 +0000259 ];
260
261 // Handler names that check authentication themselves, and thus don't need
262 // it performed for them.
263 const selfAuthenticatingHandlers = [
Frank Borden79448112022-04-12 16:59:32 +0200264 'handleDashboardRoute',
265 'handleCustomDashboardRoute',
266 'handleRootRoute',
paladox68b968e2022-02-20 17:31:50 +0000267 ];
268
269 const shouldNotRequireAuth = unauthenticatedHandlers.concat(
270 selfAuthenticatingHandlers
271 );
272 shouldNotRequireAuth.sort();
273 assert.deepEqual(actualDoesNotRequireAuth, shouldNotRequireAuth);
274 });
275
Frank Borden79448112022-04-12 16:59:32 +0200276 test('redirectIfNotLoggedIn while logged in', () => {
paladox68b968e2022-02-20 17:31:50 +0000277 stubRestApi('getLoggedIn').returns(Promise.resolve(true));
278 const data = {
279 save() {},
280 handled: true,
281 canonicalPath: '',
282 path: '',
283 querystring: '',
284 pathname: '',
285 state: '',
286 title: '',
287 hash: '',
288 params: {test: 'test'},
289 };
Frank Borden79448112022-04-12 16:59:32 +0200290 const redirectStub = sinon.stub(router, 'redirectToLogin');
291 return router.redirectIfNotLoggedIn(data).then(() => {
paladox68b968e2022-02-20 17:31:50 +0000292 assert.isFalse(redirectStub.called);
293 });
294 });
295
Frank Borden79448112022-04-12 16:59:32 +0200296 test('redirectIfNotLoggedIn while logged out', () => {
paladox68b968e2022-02-20 17:31:50 +0000297 stubRestApi('getLoggedIn').returns(Promise.resolve(false));
Frank Borden79448112022-04-12 16:59:32 +0200298 const redirectStub = sinon.stub(router, 'redirectToLogin');
paladox68b968e2022-02-20 17:31:50 +0000299 const data = {
300 save() {},
301 handled: true,
302 canonicalPath: '',
303 path: '',
304 querystring: '',
305 pathname: '',
306 state: '',
307 title: '',
308 hash: '',
309 params: {test: 'test'},
310 };
311 return new Promise(resolve => {
Frank Borden79448112022-04-12 16:59:32 +0200312 router
313 .redirectIfNotLoggedIn(data)
paladox68b968e2022-02-20 17:31:50 +0000314 .then(() => {
315 assert.isTrue(false, 'Should never execute');
316 })
317 .catch(() => {
318 assert.isTrue(redirectStub.calledOnce);
319 resolve(Promise.resolve());
320 });
321 });
322 });
323
paladox68b968e2022-02-20 17:31:50 +0000324 suite('param normalization', () => {
Frank Borden79448112022-04-12 16:59:32 +0200325 suite('normalizePatchRangeParams', () => {
paladox68b968e2022-02-20 17:31:50 +0000326 test('range n..n normalizes to n', () => {
327 const params: PatchRangeParams = {
328 basePatchNum: 4 as BasePatchSetNum,
Ben Rohlfsabaeacf2022-05-27 15:24:22 +0200329 patchNum: 4 as RevisionPatchSetNum,
paladox68b968e2022-02-20 17:31:50 +0000330 };
Frank Borden79448112022-04-12 16:59:32 +0200331 const needsRedirect = router.normalizePatchRangeParams(params);
paladox68b968e2022-02-20 17:31:50 +0000332 assert.isTrue(needsRedirect);
Ben Rohlfs58267b72022-05-27 15:59:18 +0200333 assert.equal(params.basePatchNum, PARENT);
Ben Rohlfsabaeacf2022-05-27 15:24:22 +0200334 assert.equal(params.patchNum, 4 as RevisionPatchSetNum);
paladox68b968e2022-02-20 17:31:50 +0000335 });
336
337 test('range n.. normalizes to n', () => {
338 const params: PatchRangeParams = {basePatchNum: 4 as BasePatchSetNum};
Frank Borden79448112022-04-12 16:59:32 +0200339 const needsRedirect = router.normalizePatchRangeParams(params);
paladox68b968e2022-02-20 17:31:50 +0000340 assert.isFalse(needsRedirect);
Ben Rohlfs58267b72022-05-27 15:59:18 +0200341 assert.equal(params.basePatchNum, PARENT);
Ben Rohlfsabaeacf2022-05-27 15:24:22 +0200342 assert.equal(params.patchNum, 4 as RevisionPatchSetNum);
paladox68b968e2022-02-20 17:31:50 +0000343 });
344 });
345 });
346
347 suite('route handlers', () => {
348 let redirectStub: sinon.SinonStub;
349 let setParamsStub: sinon.SinonStub;
350 let handlePassThroughRoute: sinon.SinonStub;
351
352 // Simple route handlers are direct mappings from parsed route data to a
353 // new set of app.params. This test helper asserts that passing `data`
354 // into `methodName` results in setting the params specified in `params`.
355 function assertDataToParams(
356 data: PageContextWithQueryMap,
357 methodName: string,
358 params: AppElementParams | GenerateUrlParameters
359 ) {
Frank Borden79448112022-04-12 16:59:32 +0200360 (router as any)[methodName](data);
paladox68b968e2022-02-20 17:31:50 +0000361 assert.deepEqual(setParamsStub.lastCall.args[0], params);
362 }
363
364 function createPageContext(): PageContextWithQueryMap {
365 return {
366 queryMap: new Map(),
367 save() {},
368 handled: true,
369 canonicalPath: '',
370 path: '',
371 querystring: '',
372 pathname: '',
373 state: '',
374 title: '',
375 hash: '',
376 params: {},
377 };
378 }
379
380 setup(() => {
Frank Borden79448112022-04-12 16:59:32 +0200381 redirectStub = sinon.stub(router, 'redirect');
382 setParamsStub = sinon.stub(router, 'setParams');
383 handlePassThroughRoute = sinon.stub(router, 'handlePassThroughRoute');
paladox68b968e2022-02-20 17:31:50 +0000384 });
385
Frank Borden79448112022-04-12 16:59:32 +0200386 test('handleLegacyProjectDashboardRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000387 const params = {
388 ...createPageContext(),
389 params: {0: 'gerrit/project', 1: 'dashboard:main'},
390 };
Frank Borden79448112022-04-12 16:59:32 +0200391 router.handleLegacyProjectDashboardRoute(params);
paladox68b968e2022-02-20 17:31:50 +0000392 assert.isTrue(redirectStub.calledOnce);
393 assert.equal(
394 redirectStub.lastCall.args[0],
395 '/p/gerrit/project/+/dashboard/dashboard:main'
396 );
397 });
398
Frank Borden79448112022-04-12 16:59:32 +0200399 test('handleAgreementsRoute', () => {
400 router.handleAgreementsRoute();
paladox68b968e2022-02-20 17:31:50 +0000401 assert.isTrue(redirectStub.calledOnce);
402 assert.equal(redirectStub.lastCall.args[0], '/settings/#Agreements');
403 });
404
Frank Borden79448112022-04-12 16:59:32 +0200405 test('handleNewAgreementsRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000406 const params = createPageContext();
Frank Borden79448112022-04-12 16:59:32 +0200407 router.handleNewAgreementsRoute(params);
paladox68b968e2022-02-20 17:31:50 +0000408 assert.isTrue(setParamsStub.calledOnce);
Ben Rohlfs8163cd42022-08-18 16:04:36 +0200409 assert.equal(setParamsStub.lastCall.args[0].view, GerritView.AGREEMENTS);
paladox68b968e2022-02-20 17:31:50 +0000410 });
411
Frank Borden79448112022-04-12 16:59:32 +0200412 test('handleSettingsLegacyRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000413 const data = {...createPageContext(), params: {0: 'my-token'}};
Frank Borden79448112022-04-12 16:59:32 +0200414 assertDataToParams(data, 'handleSettingsLegacyRoute', {
Ben Rohlfs8163cd42022-08-18 16:04:36 +0200415 view: GerritView.SETTINGS,
paladox68b968e2022-02-20 17:31:50 +0000416 emailToken: 'my-token',
417 });
418 });
419
Frank Borden79448112022-04-12 16:59:32 +0200420 test('handleSettingsLegacyRoute with +', () => {
paladox68b968e2022-02-20 17:31:50 +0000421 const data = {...createPageContext(), params: {0: 'my-token test'}};
Frank Borden79448112022-04-12 16:59:32 +0200422 assertDataToParams(data, 'handleSettingsLegacyRoute', {
Ben Rohlfs8163cd42022-08-18 16:04:36 +0200423 view: GerritView.SETTINGS,
paladox68b968e2022-02-20 17:31:50 +0000424 emailToken: 'my-token+test',
425 });
426 });
427
Frank Borden79448112022-04-12 16:59:32 +0200428 test('handleSettingsRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000429 const data = createPageContext();
Frank Borden79448112022-04-12 16:59:32 +0200430 assertDataToParams(data, 'handleSettingsRoute', {
Ben Rohlfs8163cd42022-08-18 16:04:36 +0200431 view: GerritView.SETTINGS,
paladox68b968e2022-02-20 17:31:50 +0000432 });
433 });
434
Frank Borden79448112022-04-12 16:59:32 +0200435 test('handleDefaultRoute on first load', () => {
paladox68b968e2022-02-20 17:31:50 +0000436 const spy = sinon.spy();
437 addListenerForTest(document, 'page-error', spy);
Frank Borden79448112022-04-12 16:59:32 +0200438 router.handleDefaultRoute();
paladox68b968e2022-02-20 17:31:50 +0000439 assert.isTrue(spy.calledOnce);
440 assert.equal(spy.lastCall.args[0].detail.response.status, 404);
441 });
442
Frank Borden79448112022-04-12 16:59:32 +0200443 test('handleDefaultRoute after internal navigation', () => {
paladox68b968e2022-02-20 17:31:50 +0000444 let onExit: Function | null = null;
445 const onRegisteringExit = (
446 _match: string | RegExp,
447 _onExit: Function
448 ) => {
449 onExit = _onExit;
450 };
451 sinon.stub(page, 'exit').callsFake(onRegisteringExit);
452 sinon.stub(GerritNav, 'setup');
453 sinon.stub(page, 'start');
454 sinon.stub(page, 'base');
Frank Borden79448112022-04-12 16:59:32 +0200455 router.startRouter();
paladox68b968e2022-02-20 17:31:50 +0000456
Frank Borden79448112022-04-12 16:59:32 +0200457 router.handleDefaultRoute();
paladox68b968e2022-02-20 17:31:50 +0000458
459 onExit!('', () => {}); // we left page;
460
Frank Borden79448112022-04-12 16:59:32 +0200461 router.handleDefaultRoute();
paladox68b968e2022-02-20 17:31:50 +0000462 assert.isTrue(handlePassThroughRoute.calledOnce);
463 });
464
Frank Borden79448112022-04-12 16:59:32 +0200465 test('handleImproperlyEncodedPlusRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000466 const params = {
467 ...createPageContext(),
468 canonicalPath: '/c/test/%20/42',
469 params: {0: 'test', 1: '42'},
470 };
471 // Regression test for Issue 7100.
Frank Borden79448112022-04-12 16:59:32 +0200472 router.handleImproperlyEncodedPlusRoute(params);
paladox68b968e2022-02-20 17:31:50 +0000473 assert.isTrue(redirectStub.calledOnce);
474 assert.equal(redirectStub.lastCall.args[0], '/c/test/+/42');
475
Frank Borden79448112022-04-12 16:59:32 +0200476 sinon.stub(router, 'getHashFromCanonicalPath').returns('foo');
477 router.handleImproperlyEncodedPlusRoute(params);
paladox68b968e2022-02-20 17:31:50 +0000478 assert.equal(redirectStub.lastCall.args[0], '/c/test/+/42#foo');
479 });
480
Frank Borden79448112022-04-12 16:59:32 +0200481 test('handleQueryRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000482 const data: PageContextWithQueryMap = {
483 ...createPageContext(),
484 params: {0: 'project:foo/bar/baz'},
485 };
Frank Borden79448112022-04-12 16:59:32 +0200486 assertDataToParams(data, 'handleQueryRoute', {
Ben Rohlfs8163cd42022-08-18 16:04:36 +0200487 view: GerritView.SEARCH,
paladox68b968e2022-02-20 17:31:50 +0000488 query: 'project:foo/bar/baz',
489 offset: undefined,
490 });
491
492 data.params[1] = '123';
493 data.params[2] = '123';
Frank Borden79448112022-04-12 16:59:32 +0200494 assertDataToParams(data, 'handleQueryRoute', {
Ben Rohlfs8163cd42022-08-18 16:04:36 +0200495 view: GerritView.SEARCH,
paladox68b968e2022-02-20 17:31:50 +0000496 query: 'project:foo/bar/baz',
497 offset: '123',
498 });
499 });
500
Frank Borden79448112022-04-12 16:59:32 +0200501 test('handleQueryLegacySuffixRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000502 const params = {...createPageContext(), path: '/q/foo+bar,n,z'};
Frank Borden79448112022-04-12 16:59:32 +0200503 router.handleQueryLegacySuffixRoute(params);
paladox68b968e2022-02-20 17:31:50 +0000504 assert.isTrue(redirectStub.calledOnce);
505 assert.equal(redirectStub.lastCall.args[0], '/q/foo+bar');
506 });
507
Frank Borden79448112022-04-12 16:59:32 +0200508 test('handleChangeIdQueryRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000509 const data = {
510 ...createPageContext(),
511 params: {0: 'I0123456789abcdef0123456789abcdef01234567'},
512 };
Frank Borden79448112022-04-12 16:59:32 +0200513 assertDataToParams(data, 'handleChangeIdQueryRoute', {
Ben Rohlfs8163cd42022-08-18 16:04:36 +0200514 view: GerritView.SEARCH,
paladox68b968e2022-02-20 17:31:50 +0000515 query: 'I0123456789abcdef0123456789abcdef01234567',
516 });
517 });
518
Frank Borden79448112022-04-12 16:59:32 +0200519 suite('handleRegisterRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000520 test('happy path', () => {
521 const ctx = {...createPageContext(), params: {0: '/foo/bar'}};
Frank Borden79448112022-04-12 16:59:32 +0200522 router.handleRegisterRoute(ctx);
paladox68b968e2022-02-20 17:31:50 +0000523 assert.isTrue(redirectStub.calledWithExactly('/foo/bar'));
524 assert.isTrue(setParamsStub.calledOnce);
525 assert.isTrue(setParamsStub.lastCall.args[0].justRegistered);
526 });
527
528 test('no param', () => {
529 const ctx = createPageContext();
Frank Borden79448112022-04-12 16:59:32 +0200530 router.handleRegisterRoute(ctx);
paladox68b968e2022-02-20 17:31:50 +0000531 assert.isTrue(redirectStub.calledWithExactly('/'));
532 assert.isTrue(setParamsStub.calledOnce);
533 assert.isTrue(setParamsStub.lastCall.args[0].justRegistered);
534 });
535
536 test('prevent redirect', () => {
537 const ctx = {...createPageContext(), params: {0: '/register'}};
Frank Borden79448112022-04-12 16:59:32 +0200538 router.handleRegisterRoute(ctx);
paladox68b968e2022-02-20 17:31:50 +0000539 assert.isTrue(redirectStub.calledWithExactly('/'));
540 assert.isTrue(setParamsStub.calledOnce);
541 assert.isTrue(setParamsStub.lastCall.args[0].justRegistered);
542 });
543 });
544
Frank Borden79448112022-04-12 16:59:32 +0200545 suite('handleRootRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000546 test('closes for closeAfterLogin', () => {
547 const data = {...createPageContext(), querystring: 'closeAfterLogin'};
548 const closeStub = sinon.stub(window, 'close');
Frank Borden79448112022-04-12 16:59:32 +0200549 const result = router.handleRootRoute(data);
paladox68b968e2022-02-20 17:31:50 +0000550 assert.isNotOk(result);
551 assert.isTrue(closeStub.called);
552 assert.isFalse(redirectStub.called);
553 });
554
555 test('redirects to dashboard if logged in', () => {
556 const data = {...createPageContext(), canonicalPath: '/', path: '/'};
Frank Borden79448112022-04-12 16:59:32 +0200557 const result = router.handleRootRoute(data);
paladox68b968e2022-02-20 17:31:50 +0000558 assert.isOk(result);
559 return result!.then(() => {
560 assert.isTrue(redirectStub.calledWithExactly('/dashboard/self'));
561 });
562 });
563
564 test('redirects to open changes if not logged in', () => {
565 stubRestApi('getLoggedIn').returns(Promise.resolve(false));
566 const data = {...createPageContext(), canonicalPath: '/', path: '/'};
Frank Borden79448112022-04-12 16:59:32 +0200567 const result = router.handleRootRoute(data);
paladox68b968e2022-02-20 17:31:50 +0000568 assert.isOk(result);
569 return result!.then(() => {
570 assert.isTrue(
571 redirectStub.calledWithExactly('/q/status:open+-is:wip')
572 );
573 });
574 });
575
576 suite('GWT hash-path URLs', () => {
577 test('redirects hash-path URLs', () => {
578 const data = {
579 ...createPageContext(),
580 canonicalPath: '/#/foo/bar/baz',
581 hash: '/foo/bar/baz',
582 };
Frank Borden79448112022-04-12 16:59:32 +0200583 const result = router.handleRootRoute(data);
paladox68b968e2022-02-20 17:31:50 +0000584 assert.isNotOk(result);
585 assert.isTrue(redirectStub.called);
586 assert.isTrue(redirectStub.calledWithExactly('/foo/bar/baz'));
587 });
588
589 test('redirects hash-path URLs w/o leading slash', () => {
590 const data = {
591 ...createPageContext(),
592 canonicalPath: '/#foo/bar/baz',
593 hash: 'foo/bar/baz',
594 };
Frank Borden79448112022-04-12 16:59:32 +0200595 const result = router.handleRootRoute(data);
paladox68b968e2022-02-20 17:31:50 +0000596 assert.isNotOk(result);
597 assert.isTrue(redirectStub.called);
598 assert.isTrue(redirectStub.calledWithExactly('/foo/bar/baz'));
599 });
600
601 test('normalizes "/ /" in hash to "/+/"', () => {
602 const data = {
603 ...createPageContext(),
604 canonicalPath: '/#/foo/bar/+/123/4',
605 hash: '/foo/bar/ /123/4',
606 };
Frank Borden79448112022-04-12 16:59:32 +0200607 const result = router.handleRootRoute(data);
paladox68b968e2022-02-20 17:31:50 +0000608 assert.isNotOk(result);
609 assert.isTrue(redirectStub.called);
610 assert.isTrue(redirectStub.calledWithExactly('/foo/bar/+/123/4'));
611 });
612
613 test('prepends baseurl to hash-path', () => {
614 const data = {
615 ...createPageContext(),
616 canonicalPath: '/#/foo/bar',
617 hash: '/foo/bar',
618 };
619 stubBaseUrl('/baz');
Frank Borden79448112022-04-12 16:59:32 +0200620 const result = router.handleRootRoute(data);
paladox68b968e2022-02-20 17:31:50 +0000621 assert.isNotOk(result);
622 assert.isTrue(redirectStub.called);
623 assert.isTrue(redirectStub.calledWithExactly('/baz/foo/bar'));
624 });
625
626 test('normalizes /VE/ settings hash-paths', () => {
627 const data = {
628 ...createPageContext(),
629 canonicalPath: '/#/VE/foo/bar',
630 hash: '/VE/foo/bar',
631 };
Frank Borden79448112022-04-12 16:59:32 +0200632 const result = router.handleRootRoute(data);
paladox68b968e2022-02-20 17:31:50 +0000633 assert.isNotOk(result);
634 assert.isTrue(redirectStub.called);
635 assert.isTrue(redirectStub.calledWithExactly('/settings/VE/foo/bar'));
636 });
637
638 test('does not drop "inner hashes"', () => {
639 const data = {
640 ...createPageContext(),
641 canonicalPath: '/#/foo/bar#baz',
642 hash: '/foo/bar',
643 };
Frank Borden79448112022-04-12 16:59:32 +0200644 const result = router.handleRootRoute(data);
paladox68b968e2022-02-20 17:31:50 +0000645 assert.isNotOk(result);
646 assert.isTrue(redirectStub.called);
647 assert.isTrue(redirectStub.calledWithExactly('/foo/bar#baz'));
648 });
649 });
650 });
651
Frank Borden79448112022-04-12 16:59:32 +0200652 suite('handleDashboardRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000653 let redirectToLoginStub: sinon.SinonStub;
654
655 setup(() => {
Frank Borden79448112022-04-12 16:59:32 +0200656 redirectToLoginStub = sinon.stub(router, 'redirectToLogin');
paladox68b968e2022-02-20 17:31:50 +0000657 });
658
659 test('own dashboard but signed out redirects to login', () => {
660 stubRestApi('getLoggedIn').returns(Promise.resolve(false));
661 const data = {
662 ...createPageContext(),
663 canonicalPath: '/dashboard/',
664 params: {0: 'seLF'},
665 };
Frank Borden79448112022-04-12 16:59:32 +0200666 return router.handleDashboardRoute(data).then(() => {
paladox68b968e2022-02-20 17:31:50 +0000667 assert.isTrue(redirectToLoginStub.calledOnce);
668 assert.isFalse(redirectStub.called);
669 assert.isFalse(setParamsStub.called);
670 });
671 });
672
673 test('non-self dashboard but signed out does not redirect', () => {
674 stubRestApi('getLoggedIn').returns(Promise.resolve(false));
675 const data = {
676 ...createPageContext(),
677 canonicalPath: '/dashboard/',
678 params: {0: 'foo'},
679 };
Frank Borden79448112022-04-12 16:59:32 +0200680 return router.handleDashboardRoute(data).then(() => {
paladox68b968e2022-02-20 17:31:50 +0000681 assert.isFalse(redirectToLoginStub.called);
682 assert.isFalse(setParamsStub.called);
683 assert.isTrue(redirectStub.calledOnce);
684 assert.equal(redirectStub.lastCall.args[0], '/q/owner:foo');
685 });
686 });
687
688 test('dashboard while signed in sets params', () => {
689 const data = {
690 ...createPageContext(),
691 canonicalPath: '/dashboard/',
692 params: {0: 'foo'},
693 };
Frank Borden79448112022-04-12 16:59:32 +0200694 return router.handleDashboardRoute(data).then(() => {
paladox68b968e2022-02-20 17:31:50 +0000695 assert.isFalse(redirectToLoginStub.called);
696 assert.isFalse(redirectStub.called);
697 assert.isTrue(setParamsStub.calledOnce);
698 assert.deepEqual(setParamsStub.lastCall.args[0], {
Ben Rohlfs8163cd42022-08-18 16:04:36 +0200699 view: GerritView.DASHBOARD,
paladox68b968e2022-02-20 17:31:50 +0000700 user: 'foo',
701 });
702 });
703 });
704 });
705
Frank Borden79448112022-04-12 16:59:32 +0200706 suite('handleCustomDashboardRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000707 let redirectToLoginStub: sinon.SinonStub;
708
709 setup(() => {
Frank Borden79448112022-04-12 16:59:32 +0200710 redirectToLoginStub = sinon.stub(router, 'redirectToLogin');
paladox68b968e2022-02-20 17:31:50 +0000711 });
712
713 test('no user specified', () => {
714 const data = {
715 ...createPageContext(),
716 canonicalPath: '/dashboard/',
717 params: {0: ''},
718 };
Frank Borden79448112022-04-12 16:59:32 +0200719 return router.handleCustomDashboardRoute(data, '').then(() => {
paladox68b968e2022-02-20 17:31:50 +0000720 assert.isFalse(setParamsStub.called);
721 assert.isTrue(redirectStub.called);
722 assert.equal(redirectStub.lastCall.args[0], '/dashboard/self');
723 });
724 });
725
726 test('custom dashboard without title', () => {
727 const data = {
728 ...createPageContext(),
729 canonicalPath: '/dashboard/',
730 params: {0: ''},
731 };
Frank Borden79448112022-04-12 16:59:32 +0200732 return router
733 .handleCustomDashboardRoute(data, '?a=b&c&d=e')
paladox68b968e2022-02-20 17:31:50 +0000734 .then(() => {
735 assert.isFalse(redirectStub.called);
736 assert.isTrue(setParamsStub.calledOnce);
737 assert.deepEqual(setParamsStub.lastCall.args[0], {
Ben Rohlfs8163cd42022-08-18 16:04:36 +0200738 view: GerritView.DASHBOARD,
paladox68b968e2022-02-20 17:31:50 +0000739 user: 'self',
740 sections: [
741 {name: 'a', query: 'b'},
742 {name: 'd', query: 'e'},
743 ],
744 title: 'Custom Dashboard',
745 });
746 });
747 });
748
749 test('custom dashboard with title', () => {
750 const data = {
751 ...createPageContext(),
752 canonicalPath: '/dashboard/',
753 params: {0: ''},
754 };
Frank Borden79448112022-04-12 16:59:32 +0200755 return router
756 .handleCustomDashboardRoute(data, '?a=b&c&d=&=e&title=t')
paladox68b968e2022-02-20 17:31:50 +0000757 .then(() => {
758 assert.isFalse(redirectToLoginStub.called);
759 assert.isFalse(redirectStub.called);
760 assert.isTrue(setParamsStub.calledOnce);
761 assert.deepEqual(setParamsStub.lastCall.args[0], {
Ben Rohlfs8163cd42022-08-18 16:04:36 +0200762 view: GerritView.DASHBOARD,
paladox68b968e2022-02-20 17:31:50 +0000763 user: 'self',
764 sections: [{name: 'a', query: 'b'}],
765 title: 't',
766 });
767 });
768 });
769
770 test('custom dashboard with foreach', () => {
771 const data = {
772 ...createPageContext(),
773 canonicalPath: '/dashboard/',
774 params: {0: ''},
775 };
Frank Borden79448112022-04-12 16:59:32 +0200776 return router
777 .handleCustomDashboardRoute(data, '?a=b&c&d=&=e&foreach=is:open')
paladox68b968e2022-02-20 17:31:50 +0000778 .then(() => {
779 assert.isFalse(redirectToLoginStub.called);
780 assert.isFalse(redirectStub.called);
781 assert.isTrue(setParamsStub.calledOnce);
782 assert.deepEqual(setParamsStub.lastCall.args[0], {
Ben Rohlfs8163cd42022-08-18 16:04:36 +0200783 view: GerritView.DASHBOARD,
paladox68b968e2022-02-20 17:31:50 +0000784 user: 'self',
785 sections: [{name: 'a', query: 'is:open b'}],
786 title: 'Custom Dashboard',
787 });
788 });
789 });
790 });
791
792 suite('group routes', () => {
Frank Borden79448112022-04-12 16:59:32 +0200793 test('handleGroupInfoRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000794 const data = {...createPageContext(), params: {0: '1234'}};
Frank Borden79448112022-04-12 16:59:32 +0200795 router.handleGroupInfoRoute(data);
paladox68b968e2022-02-20 17:31:50 +0000796 assert.isTrue(redirectStub.calledOnce);
797 assert.equal(redirectStub.lastCall.args[0], '/admin/groups/1234');
798 });
799
Frank Borden79448112022-04-12 16:59:32 +0200800 test('handleGroupAuditLogRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000801 const data = {...createPageContext(), params: {0: '1234'}};
Frank Borden79448112022-04-12 16:59:32 +0200802 assertDataToParams(data, 'handleGroupAuditLogRoute', {
paladox68b968e2022-02-20 17:31:50 +0000803 view: GerritView.GROUP,
804 detail: GroupDetailView.LOG,
805 groupId: '1234' as GroupId,
806 });
807 });
808
Frank Borden79448112022-04-12 16:59:32 +0200809 test('handleGroupMembersRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000810 const data = {...createPageContext(), params: {0: '1234'}};
Frank Borden79448112022-04-12 16:59:32 +0200811 assertDataToParams(data, 'handleGroupMembersRoute', {
paladox68b968e2022-02-20 17:31:50 +0000812 view: GerritView.GROUP,
813 detail: GroupDetailView.MEMBERS,
814 groupId: '1234' as GroupId,
815 });
816 });
817
Frank Borden79448112022-04-12 16:59:32 +0200818 test('handleGroupListOffsetRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000819 const data = createPageContext();
Frank Borden79448112022-04-12 16:59:32 +0200820 assertDataToParams(data, 'handleGroupListOffsetRoute', {
paladox68b968e2022-02-20 17:31:50 +0000821 view: GerritView.ADMIN,
Ben Rohlfsdcb88ac2022-09-12 11:50:26 +0200822 adminView: AdminChildView.GROUPS,
paladox68b968e2022-02-20 17:31:50 +0000823 offset: 0,
824 filter: null,
825 openCreateModal: false,
826 });
827
828 data.params[1] = '42';
Frank Borden79448112022-04-12 16:59:32 +0200829 assertDataToParams(data, 'handleGroupListOffsetRoute', {
paladox68b968e2022-02-20 17:31:50 +0000830 view: GerritView.ADMIN,
Ben Rohlfsdcb88ac2022-09-12 11:50:26 +0200831 adminView: AdminChildView.GROUPS,
paladox68b968e2022-02-20 17:31:50 +0000832 offset: '42',
833 filter: null,
834 openCreateModal: false,
835 });
836
837 data.hash = 'create';
Frank Borden79448112022-04-12 16:59:32 +0200838 assertDataToParams(data, 'handleGroupListOffsetRoute', {
Ben Rohlfs8163cd42022-08-18 16:04:36 +0200839 view: GerritView.ADMIN,
Ben Rohlfsdcb88ac2022-09-12 11:50:26 +0200840 adminView: AdminChildView.GROUPS,
paladox68b968e2022-02-20 17:31:50 +0000841 offset: '42',
842 filter: null,
843 openCreateModal: true,
844 });
845 });
846
Frank Borden79448112022-04-12 16:59:32 +0200847 test('handleGroupListFilterOffsetRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000848 const data = {
849 ...createPageContext(),
850 params: {filter: 'foo', offset: '42'},
851 };
Frank Borden79448112022-04-12 16:59:32 +0200852 assertDataToParams(data, 'handleGroupListFilterOffsetRoute', {
paladox68b968e2022-02-20 17:31:50 +0000853 view: GerritView.ADMIN,
Ben Rohlfsdcb88ac2022-09-12 11:50:26 +0200854 adminView: AdminChildView.GROUPS,
paladox68b968e2022-02-20 17:31:50 +0000855 offset: '42',
856 filter: 'foo',
857 });
858 });
859
Frank Borden79448112022-04-12 16:59:32 +0200860 test('handleGroupListFilterRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000861 const data = {...createPageContext(), params: {filter: 'foo'}};
Frank Borden79448112022-04-12 16:59:32 +0200862 assertDataToParams(data, 'handleGroupListFilterRoute', {
paladox68b968e2022-02-20 17:31:50 +0000863 view: GerritView.ADMIN,
Ben Rohlfsdcb88ac2022-09-12 11:50:26 +0200864 adminView: AdminChildView.GROUPS,
paladox68b968e2022-02-20 17:31:50 +0000865 filter: 'foo',
866 });
867 });
868
Frank Borden79448112022-04-12 16:59:32 +0200869 test('handleGroupRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000870 const data = {...createPageContext(), params: {0: '4321'}};
Frank Borden79448112022-04-12 16:59:32 +0200871 assertDataToParams(data, 'handleGroupRoute', {
paladox68b968e2022-02-20 17:31:50 +0000872 view: GerritView.GROUP,
873 groupId: '4321' as GroupId,
874 });
875 });
876 });
877
878 suite('repo routes', () => {
Frank Borden79448112022-04-12 16:59:32 +0200879 test('handleProjectsOldRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000880 const data = {...createPageContext(), params: {}};
Frank Borden79448112022-04-12 16:59:32 +0200881 router.handleProjectsOldRoute(data);
paladox68b968e2022-02-20 17:31:50 +0000882 assert.isTrue(redirectStub.calledOnce);
883 assert.equal(redirectStub.lastCall.args[0], '/admin/repos/');
884 });
885
Frank Borden79448112022-04-12 16:59:32 +0200886 test('handleProjectsOldRoute test', () => {
paladox68b968e2022-02-20 17:31:50 +0000887 const data = {...createPageContext(), params: {1: 'test'}};
Frank Borden79448112022-04-12 16:59:32 +0200888 router.handleProjectsOldRoute(data);
paladox68b968e2022-02-20 17:31:50 +0000889 assert.isTrue(redirectStub.calledOnce);
890 assert.equal(redirectStub.lastCall.args[0], '/admin/repos/test');
891 });
892
Frank Borden79448112022-04-12 16:59:32 +0200893 test('handleProjectsOldRoute test,branches', () => {
paladox68b968e2022-02-20 17:31:50 +0000894 const data = {...createPageContext(), params: {1: 'test,branches'}};
Frank Borden79448112022-04-12 16:59:32 +0200895 router.handleProjectsOldRoute(data);
paladox68b968e2022-02-20 17:31:50 +0000896 assert.isTrue(redirectStub.calledOnce);
897 assert.equal(
898 redirectStub.lastCall.args[0],
899 '/admin/repos/test,branches'
900 );
901 });
902
Frank Borden79448112022-04-12 16:59:32 +0200903 test('handleRepoRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000904 const data = {...createPageContext(), path: '/admin/repos/test'};
Frank Borden79448112022-04-12 16:59:32 +0200905 router.handleRepoRoute(data);
paladox68b968e2022-02-20 17:31:50 +0000906 assert.isTrue(redirectStub.calledOnce);
907 assert.equal(
908 redirectStub.lastCall.args[0],
909 '/admin/repos/test,general'
910 );
911 });
912
Frank Borden79448112022-04-12 16:59:32 +0200913 test('handleRepoGeneralRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000914 const data = {...createPageContext(), params: {0: '4321'}};
Frank Borden79448112022-04-12 16:59:32 +0200915 assertDataToParams(data, 'handleRepoGeneralRoute', {
paladox68b968e2022-02-20 17:31:50 +0000916 view: GerritView.REPO,
Ben Rohlfs8163cd42022-08-18 16:04:36 +0200917 detail: RepoDetailView.GENERAL,
paladox68b968e2022-02-20 17:31:50 +0000918 repo: '4321' as RepoName,
919 });
920 });
921
Frank Borden79448112022-04-12 16:59:32 +0200922 test('handleRepoCommandsRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000923 const data = {...createPageContext(), params: {0: '4321'}};
Frank Borden79448112022-04-12 16:59:32 +0200924 assertDataToParams(data, 'handleRepoCommandsRoute', {
paladox68b968e2022-02-20 17:31:50 +0000925 view: GerritView.REPO,
Ben Rohlfs8163cd42022-08-18 16:04:36 +0200926 detail: RepoDetailView.COMMANDS,
paladox68b968e2022-02-20 17:31:50 +0000927 repo: '4321' as RepoName,
928 });
929 });
930
Frank Borden79448112022-04-12 16:59:32 +0200931 test('handleRepoAccessRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000932 const data = {...createPageContext(), params: {0: '4321'}};
Frank Borden79448112022-04-12 16:59:32 +0200933 assertDataToParams(data, 'handleRepoAccessRoute', {
paladox68b968e2022-02-20 17:31:50 +0000934 view: GerritView.REPO,
Ben Rohlfs8163cd42022-08-18 16:04:36 +0200935 detail: RepoDetailView.ACCESS,
paladox68b968e2022-02-20 17:31:50 +0000936 repo: '4321' as RepoName,
937 });
938 });
939
940 suite('branch list routes', () => {
Frank Borden79448112022-04-12 16:59:32 +0200941 test('handleBranchListOffsetRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000942 const data: PageContextWithQueryMap = {
943 ...createPageContext(),
944 params: {0: '4321'},
945 };
Frank Borden79448112022-04-12 16:59:32 +0200946 assertDataToParams(data, 'handleBranchListOffsetRoute', {
paladox68b968e2022-02-20 17:31:50 +0000947 view: GerritView.REPO,
Ben Rohlfs8163cd42022-08-18 16:04:36 +0200948 detail: RepoDetailView.BRANCHES,
paladox68b968e2022-02-20 17:31:50 +0000949 repo: '4321' as RepoName,
950 offset: 0,
951 filter: null,
952 });
953
954 data.params[2] = '42';
Frank Borden79448112022-04-12 16:59:32 +0200955 assertDataToParams(data, 'handleBranchListOffsetRoute', {
paladox68b968e2022-02-20 17:31:50 +0000956 view: GerritView.REPO,
Ben Rohlfs8163cd42022-08-18 16:04:36 +0200957 detail: RepoDetailView.BRANCHES,
paladox68b968e2022-02-20 17:31:50 +0000958 repo: '4321' as RepoName,
959 offset: '42',
960 filter: null,
961 });
962 });
963
Frank Borden79448112022-04-12 16:59:32 +0200964 test('handleBranchListFilterOffsetRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000965 const data = {
966 ...createPageContext(),
967 params: {repo: '4321', filter: 'foo', offset: '42'},
968 };
Frank Borden79448112022-04-12 16:59:32 +0200969 assertDataToParams(data, 'handleBranchListFilterOffsetRoute', {
paladox68b968e2022-02-20 17:31:50 +0000970 view: GerritView.REPO,
Ben Rohlfs8163cd42022-08-18 16:04:36 +0200971 detail: RepoDetailView.BRANCHES,
paladox68b968e2022-02-20 17:31:50 +0000972 repo: '4321' as RepoName,
973 offset: '42',
974 filter: 'foo',
975 });
976 });
977
Frank Borden79448112022-04-12 16:59:32 +0200978 test('handleBranchListFilterRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000979 const data = {
980 ...createPageContext(),
981 params: {repo: '4321', filter: 'foo'},
982 };
Frank Borden79448112022-04-12 16:59:32 +0200983 assertDataToParams(data, 'handleBranchListFilterRoute', {
paladox68b968e2022-02-20 17:31:50 +0000984 view: GerritView.REPO,
Ben Rohlfs8163cd42022-08-18 16:04:36 +0200985 detail: RepoDetailView.BRANCHES,
paladox68b968e2022-02-20 17:31:50 +0000986 repo: '4321' as RepoName,
987 filter: 'foo',
988 });
989 });
990 });
991
992 suite('tag list routes', () => {
Frank Borden79448112022-04-12 16:59:32 +0200993 test('handleTagListOffsetRoute', () => {
paladox68b968e2022-02-20 17:31:50 +0000994 const data = {...createPageContext(), params: {0: '4321'}};
Frank Borden79448112022-04-12 16:59:32 +0200995 assertDataToParams(data, 'handleTagListOffsetRoute', {
paladox68b968e2022-02-20 17:31:50 +0000996 view: GerritView.REPO,
Ben Rohlfs8163cd42022-08-18 16:04:36 +0200997 detail: RepoDetailView.TAGS,
paladox68b968e2022-02-20 17:31:50 +0000998 repo: '4321' as RepoName,
999 offset: 0,
1000 filter: null,
1001 });
1002 });
1003
Frank Borden79448112022-04-12 16:59:32 +02001004 test('handleTagListFilterOffsetRoute', () => {
paladox68b968e2022-02-20 17:31:50 +00001005 const data = {
1006 ...createPageContext(),
1007 params: {repo: '4321', filter: 'foo', offset: '42'},
1008 };
Frank Borden79448112022-04-12 16:59:32 +02001009 assertDataToParams(data, 'handleTagListFilterOffsetRoute', {
paladox68b968e2022-02-20 17:31:50 +00001010 view: GerritView.REPO,
Ben Rohlfs8163cd42022-08-18 16:04:36 +02001011 detail: RepoDetailView.TAGS,
paladox68b968e2022-02-20 17:31:50 +00001012 repo: '4321' as RepoName,
1013 offset: '42',
1014 filter: 'foo',
1015 });
1016 });
1017
Frank Borden79448112022-04-12 16:59:32 +02001018 test('handleTagListFilterRoute', () => {
paladox68b968e2022-02-20 17:31:50 +00001019 const data: PageContextWithQueryMap = {
1020 ...createPageContext(),
1021 params: {repo: '4321'},
1022 };
Frank Borden79448112022-04-12 16:59:32 +02001023 assertDataToParams(data, 'handleTagListFilterRoute', {
paladox68b968e2022-02-20 17:31:50 +00001024 view: GerritView.REPO,
Ben Rohlfs8163cd42022-08-18 16:04:36 +02001025 detail: RepoDetailView.TAGS,
paladox68b968e2022-02-20 17:31:50 +00001026 repo: '4321' as RepoName,
1027 filter: null,
1028 });
1029
1030 data.params.filter = 'foo';
Frank Borden79448112022-04-12 16:59:32 +02001031 assertDataToParams(data, 'handleTagListFilterRoute', {
paladox68b968e2022-02-20 17:31:50 +00001032 view: GerritView.REPO,
Ben Rohlfs8163cd42022-08-18 16:04:36 +02001033 detail: RepoDetailView.TAGS,
paladox68b968e2022-02-20 17:31:50 +00001034 repo: '4321' as RepoName,
1035 filter: 'foo',
1036 });
1037 });
1038 });
1039
1040 suite('repo list routes', () => {
Frank Borden79448112022-04-12 16:59:32 +02001041 test('handleRepoListOffsetRoute', () => {
paladox68b968e2022-02-20 17:31:50 +00001042 const data = createPageContext();
Frank Borden79448112022-04-12 16:59:32 +02001043 assertDataToParams(data, 'handleRepoListOffsetRoute', {
paladox68b968e2022-02-20 17:31:50 +00001044 view: GerritView.ADMIN,
Ben Rohlfsdcb88ac2022-09-12 11:50:26 +02001045 adminView: AdminChildView.REPOS,
paladox68b968e2022-02-20 17:31:50 +00001046 offset: 0,
1047 filter: null,
1048 openCreateModal: false,
1049 });
1050
1051 data.params[1] = '42';
Frank Borden79448112022-04-12 16:59:32 +02001052 assertDataToParams(data, 'handleRepoListOffsetRoute', {
paladox68b968e2022-02-20 17:31:50 +00001053 view: GerritView.ADMIN,
Ben Rohlfsdcb88ac2022-09-12 11:50:26 +02001054 adminView: AdminChildView.REPOS,
paladox68b968e2022-02-20 17:31:50 +00001055 offset: '42',
1056 filter: null,
1057 openCreateModal: false,
1058 });
1059
1060 data.hash = 'create';
Frank Borden79448112022-04-12 16:59:32 +02001061 assertDataToParams(data, 'handleRepoListOffsetRoute', {
paladox68b968e2022-02-20 17:31:50 +00001062 view: GerritView.ADMIN,
Ben Rohlfsdcb88ac2022-09-12 11:50:26 +02001063 adminView: AdminChildView.REPOS,
paladox68b968e2022-02-20 17:31:50 +00001064 offset: '42',
1065 filter: null,
1066 openCreateModal: true,
1067 });
1068 });
1069
Frank Borden79448112022-04-12 16:59:32 +02001070 test('handleRepoListFilterOffsetRoute', () => {
paladox68b968e2022-02-20 17:31:50 +00001071 const data = {
1072 ...createPageContext(),
1073 params: {filter: 'foo', offset: '42'},
1074 };
Frank Borden79448112022-04-12 16:59:32 +02001075 assertDataToParams(data, 'handleRepoListFilterOffsetRoute', {
paladox68b968e2022-02-20 17:31:50 +00001076 view: GerritView.ADMIN,
Ben Rohlfsdcb88ac2022-09-12 11:50:26 +02001077 adminView: AdminChildView.REPOS,
paladox68b968e2022-02-20 17:31:50 +00001078 offset: '42',
1079 filter: 'foo',
1080 });
1081 });
1082
Frank Borden79448112022-04-12 16:59:32 +02001083 test('handleRepoListFilterRoute', () => {
paladox68b968e2022-02-20 17:31:50 +00001084 const data = createPageContext();
Frank Borden79448112022-04-12 16:59:32 +02001085 assertDataToParams(data, 'handleRepoListFilterRoute', {
paladox68b968e2022-02-20 17:31:50 +00001086 view: GerritView.ADMIN,
Ben Rohlfsdcb88ac2022-09-12 11:50:26 +02001087 adminView: AdminChildView.REPOS,
paladox68b968e2022-02-20 17:31:50 +00001088 filter: null,
1089 });
1090
1091 data.params.filter = 'foo';
Frank Borden79448112022-04-12 16:59:32 +02001092 assertDataToParams(data, 'handleRepoListFilterRoute', {
paladox68b968e2022-02-20 17:31:50 +00001093 view: GerritView.ADMIN,
Ben Rohlfsdcb88ac2022-09-12 11:50:26 +02001094 adminView: AdminChildView.REPOS,
paladox68b968e2022-02-20 17:31:50 +00001095 filter: 'foo',
1096 });
1097 });
1098 });
1099 });
1100
1101 suite('plugin routes', () => {
Frank Borden79448112022-04-12 16:59:32 +02001102 test('handlePluginListOffsetRoute', () => {
paladox68b968e2022-02-20 17:31:50 +00001103 const data = createPageContext();
Frank Borden79448112022-04-12 16:59:32 +02001104 assertDataToParams(data, 'handlePluginListOffsetRoute', {
paladox68b968e2022-02-20 17:31:50 +00001105 view: GerritView.ADMIN,
Ben Rohlfsdcb88ac2022-09-12 11:50:26 +02001106 adminView: AdminChildView.PLUGINS,
paladox68b968e2022-02-20 17:31:50 +00001107 offset: 0,
1108 filter: null,
1109 });
1110
1111 data.params[1] = '42';
Frank Borden79448112022-04-12 16:59:32 +02001112 assertDataToParams(data, 'handlePluginListOffsetRoute', {
paladox68b968e2022-02-20 17:31:50 +00001113 view: GerritView.ADMIN,
Ben Rohlfsdcb88ac2022-09-12 11:50:26 +02001114 adminView: AdminChildView.PLUGINS,
paladox68b968e2022-02-20 17:31:50 +00001115 offset: '42',
1116 filter: null,
1117 });
1118 });
1119
Frank Borden79448112022-04-12 16:59:32 +02001120 test('handlePluginListFilterOffsetRoute', () => {
paladox68b968e2022-02-20 17:31:50 +00001121 const data = {
1122 ...createPageContext(),
1123 params: {filter: 'foo', offset: '42'},
1124 };
Frank Borden79448112022-04-12 16:59:32 +02001125 assertDataToParams(data, 'handlePluginListFilterOffsetRoute', {
paladox68b968e2022-02-20 17:31:50 +00001126 view: GerritView.ADMIN,
Ben Rohlfsdcb88ac2022-09-12 11:50:26 +02001127 adminView: AdminChildView.PLUGINS,
paladox68b968e2022-02-20 17:31:50 +00001128 offset: '42',
1129 filter: 'foo',
1130 });
1131 });
1132
Frank Borden79448112022-04-12 16:59:32 +02001133 test('handlePluginListFilterRoute', () => {
paladox68b968e2022-02-20 17:31:50 +00001134 const data = createPageContext();
Frank Borden79448112022-04-12 16:59:32 +02001135 assertDataToParams(data, 'handlePluginListFilterRoute', {
paladox68b968e2022-02-20 17:31:50 +00001136 view: GerritView.ADMIN,
Ben Rohlfsdcb88ac2022-09-12 11:50:26 +02001137 adminView: AdminChildView.PLUGINS,
paladox68b968e2022-02-20 17:31:50 +00001138 filter: null,
1139 });
1140
1141 data.params.filter = 'foo';
Frank Borden79448112022-04-12 16:59:32 +02001142 assertDataToParams(data, 'handlePluginListFilterRoute', {
paladox68b968e2022-02-20 17:31:50 +00001143 view: GerritView.ADMIN,
Ben Rohlfsdcb88ac2022-09-12 11:50:26 +02001144 adminView: AdminChildView.PLUGINS,
paladox68b968e2022-02-20 17:31:50 +00001145 filter: 'foo',
1146 });
1147 });
1148
Frank Borden79448112022-04-12 16:59:32 +02001149 test('handlePluginListRoute', () => {
paladox68b968e2022-02-20 17:31:50 +00001150 const data = createPageContext();
Frank Borden79448112022-04-12 16:59:32 +02001151 assertDataToParams(data, 'handlePluginListRoute', {
paladox68b968e2022-02-20 17:31:50 +00001152 view: GerritView.ADMIN,
Ben Rohlfsdcb88ac2022-09-12 11:50:26 +02001153 adminView: AdminChildView.PLUGINS,
paladox68b968e2022-02-20 17:31:50 +00001154 });
1155 });
1156 });
1157
1158 suite('change/diff routes', () => {
Frank Borden79448112022-04-12 16:59:32 +02001159 test('handleChangeNumberLegacyRoute', () => {
paladox68b968e2022-02-20 17:31:50 +00001160 const data = {...createPageContext(), params: {0: '12345'}};
Frank Borden79448112022-04-12 16:59:32 +02001161 router.handleChangeNumberLegacyRoute(data);
paladox68b968e2022-02-20 17:31:50 +00001162 assert.isTrue(redirectStub.calledOnce);
1163 assert.isTrue(redirectStub.calledWithExactly('/c/12345'));
1164 });
1165
Frank Borden79448112022-04-12 16:59:32 +02001166 test('handleChangeLegacyRoute', async () => {
paladox68b968e2022-02-20 17:31:50 +00001167 stubRestApi('getFromProjectLookup').returns(
1168 Promise.resolve('project' as RepoName)
1169 );
1170 const ctx = {
1171 ...createPageContext(),
1172 params: {0: '1234', 1: 'comment/6789'},
1173 };
Frank Borden79448112022-04-12 16:59:32 +02001174 router.handleChangeLegacyRoute(ctx);
Frank Borden7b24f732022-09-12 14:29:32 +02001175 await waitEventLoop();
paladox68b968e2022-02-20 17:31:50 +00001176 assert.isTrue(
1177 redirectStub.calledWithExactly('/c/project/+/1234' + '/comment/6789')
1178 );
1179 });
1180
Frank Borden79448112022-04-12 16:59:32 +02001181 test('handleLegacyLinenum w/ @321', () => {
paladox68b968e2022-02-20 17:31:50 +00001182 const ctx = {...createPageContext(), path: '/c/1234/3..8/foo/bar@321'};
Frank Borden79448112022-04-12 16:59:32 +02001183 router.handleLegacyLinenum(ctx);
paladox68b968e2022-02-20 17:31:50 +00001184 assert.isTrue(redirectStub.calledOnce);
1185 assert.isTrue(
1186 redirectStub.calledWithExactly('/c/1234/3..8/foo/bar#321')
1187 );
1188 });
1189
Frank Borden79448112022-04-12 16:59:32 +02001190 test('handleLegacyLinenum w/ @b123', () => {
paladox68b968e2022-02-20 17:31:50 +00001191 const ctx = {...createPageContext(), path: '/c/1234/3..8/foo/bar@b123'};
Frank Borden79448112022-04-12 16:59:32 +02001192 router.handleLegacyLinenum(ctx);
paladox68b968e2022-02-20 17:31:50 +00001193 assert.isTrue(redirectStub.calledOnce);
1194 assert.isTrue(
1195 redirectStub.calledWithExactly('/c/1234/3..8/foo/bar#b123')
1196 );
1197 });
1198
Frank Borden79448112022-04-12 16:59:32 +02001199 suite('handleChangeRoute', () => {
paladox68b968e2022-02-20 17:31:50 +00001200 let normalizeRangeStub: sinon.SinonStub;
1201
1202 function makeParams(
1203 _path: string,
1204 _hash: string
1205 ): PageContextWithQueryMap {
1206 return {
1207 ...createPageContext(),
1208 params: {
1209 0: 'foo/bar', // 0 Project
1210 1: '1234', // 1 Change number
1211 2: '', // 2 Unused
1212 3: '', // 3 Unused
1213 4: '4', // 4 Base patch number
1214 5: '', // 5 Unused
1215 6: '7', // 6 Patch number
1216 },
1217 };
1218 }
1219
1220 setup(() => {
Frank Borden79448112022-04-12 16:59:32 +02001221 normalizeRangeStub = sinon.stub(router, 'normalizePatchRangeParams');
paladox68b968e2022-02-20 17:31:50 +00001222 stubRestApi('setInProjectLookup');
1223 });
1224
1225 test('needs redirect', () => {
1226 normalizeRangeStub.returns(true);
Frank Borden79448112022-04-12 16:59:32 +02001227 sinon.stub(router, 'generateUrl').returns('foo');
paladox68b968e2022-02-20 17:31:50 +00001228 const ctx = makeParams('', '');
Frank Borden79448112022-04-12 16:59:32 +02001229 router.handleChangeRoute(ctx);
paladox68b968e2022-02-20 17:31:50 +00001230 assert.isTrue(normalizeRangeStub.called);
1231 assert.isFalse(setParamsStub.called);
1232 assert.isTrue(redirectStub.calledOnce);
1233 assert.isTrue(redirectStub.calledWithExactly('foo'));
1234 });
1235
1236 test('change view', () => {
1237 normalizeRangeStub.returns(false);
Frank Borden79448112022-04-12 16:59:32 +02001238 sinon.stub(router, 'generateUrl').returns('foo');
paladox68b968e2022-02-20 17:31:50 +00001239 const ctx = makeParams('', '');
Frank Borden79448112022-04-12 16:59:32 +02001240 assertDataToParams(ctx, 'handleChangeRoute', {
paladox68b968e2022-02-20 17:31:50 +00001241 view: GerritView.CHANGE,
1242 project: 'foo/bar' as RepoName,
1243 changeNum: 1234 as NumericChangeId,
1244 basePatchNum: 4 as BasePatchSetNum,
1245 patchNum: 7 as RevisionPatchSetNum,
1246 });
1247 assert.isFalse(redirectStub.called);
1248 assert.isTrue(normalizeRangeStub.called);
1249 });
1250
1251 test('params', () => {
1252 normalizeRangeStub.returns(false);
Frank Borden79448112022-04-12 16:59:32 +02001253 sinon.stub(router, 'generateUrl').returns('foo');
paladox68b968e2022-02-20 17:31:50 +00001254 const ctx = makeParams('', '');
1255 ctx.queryMap.set('tab', 'checks');
1256 ctx.queryMap.set('filter', 'fff');
1257 ctx.queryMap.set('select', 'sss');
1258 ctx.queryMap.set('attempt', '1');
Frank Borden79448112022-04-12 16:59:32 +02001259 assertDataToParams(ctx, 'handleChangeRoute', {
paladox68b968e2022-02-20 17:31:50 +00001260 view: GerritView.CHANGE,
1261 project: 'foo/bar' as RepoName,
1262 changeNum: 1234 as NumericChangeId,
1263 basePatchNum: 4 as BasePatchSetNum,
1264 patchNum: 7 as RevisionPatchSetNum,
1265 attempt: 1,
1266 filter: 'fff',
paladox68b968e2022-02-20 17:31:50 +00001267 tab: 'checks',
1268 });
1269 });
1270 });
1271
Frank Borden79448112022-04-12 16:59:32 +02001272 suite('handleDiffRoute', () => {
paladox68b968e2022-02-20 17:31:50 +00001273 let normalizeRangeStub: sinon.SinonStub;
1274
1275 function makeParams(
1276 path: string,
1277 hash: string
1278 ): PageContextWithQueryMap {
1279 return {
1280 ...createPageContext(),
1281 hash,
1282 params: {
1283 0: 'foo/bar', // 0 Project
1284 1: '1234', // 1 Change number
1285 2: '', // 2 Unused
1286 3: '', // 3 Unused
1287 4: '4', // 4 Base patch number
1288 5: '', // 5 Unused
1289 6: '7', // 6 Patch number
1290 7: '', // 7 Unused,
1291 8: path, // 8 Diff path
1292 },
1293 };
1294 }
1295
1296 setup(() => {
Frank Borden79448112022-04-12 16:59:32 +02001297 normalizeRangeStub = sinon.stub(router, 'normalizePatchRangeParams');
paladox68b968e2022-02-20 17:31:50 +00001298 stubRestApi('setInProjectLookup');
1299 });
1300
1301 test('needs redirect', () => {
1302 normalizeRangeStub.returns(true);
Frank Borden79448112022-04-12 16:59:32 +02001303 sinon.stub(router, 'generateUrl').returns('foo');
paladox68b968e2022-02-20 17:31:50 +00001304 const ctx = makeParams('', '');
Frank Borden79448112022-04-12 16:59:32 +02001305 router.handleDiffRoute(ctx);
paladox68b968e2022-02-20 17:31:50 +00001306 assert.isTrue(normalizeRangeStub.called);
1307 assert.isFalse(setParamsStub.called);
1308 assert.isTrue(redirectStub.calledOnce);
1309 assert.isTrue(redirectStub.calledWithExactly('foo'));
1310 });
1311
1312 test('diff view', () => {
1313 normalizeRangeStub.returns(false);
Frank Borden79448112022-04-12 16:59:32 +02001314 sinon.stub(router, 'generateUrl').returns('foo');
paladox68b968e2022-02-20 17:31:50 +00001315 const ctx = makeParams('foo/bar/baz', 'b44');
Frank Borden79448112022-04-12 16:59:32 +02001316 assertDataToParams(ctx, 'handleDiffRoute', {
paladox68b968e2022-02-20 17:31:50 +00001317 view: GerritView.DIFF,
1318 project: 'foo/bar' as RepoName,
1319 changeNum: 1234 as NumericChangeId,
1320 basePatchNum: 4 as BasePatchSetNum,
1321 patchNum: 7 as RevisionPatchSetNum,
1322 path: 'foo/bar/baz',
1323 leftSide: true,
1324 lineNum: 44,
1325 });
1326 assert.isFalse(redirectStub.called);
1327 assert.isTrue(normalizeRangeStub.called);
1328 });
1329
1330 test('comment route', () => {
1331 const url = '/c/gerrit/+/264833/comment/00049681_f34fd6a9/';
1332 const groups = url.match(_testOnly_RoutePattern.COMMENT);
1333 assert.deepEqual(groups!.slice(1), [
1334 'gerrit', // project
1335 '264833', // changeNum
1336 '00049681_f34fd6a9', // commentId
1337 ]);
1338 assertDataToParams(
1339 {params: groups!.slice(1)} as any,
Frank Borden79448112022-04-12 16:59:32 +02001340 'handleCommentRoute',
paladox68b968e2022-02-20 17:31:50 +00001341 {
1342 project: 'gerrit' as RepoName,
1343 changeNum: 264833 as NumericChangeId,
1344 commentId: '00049681_f34fd6a9' as UrlEncodedCommentId,
1345 commentLink: true,
1346 view: GerritView.DIFF,
1347 }
1348 );
1349 });
1350
1351 test('comments route', () => {
1352 const url = '/c/gerrit/+/264833/comments/00049681_f34fd6a9/';
1353 const groups = url.match(_testOnly_RoutePattern.COMMENTS_TAB);
1354 assert.deepEqual(groups!.slice(1), [
1355 'gerrit', // project
1356 '264833', // changeNum
1357 '00049681_f34fd6a9', // commentId
1358 ]);
1359 assertDataToParams(
1360 {params: groups!.slice(1)} as any,
Frank Borden79448112022-04-12 16:59:32 +02001361 'handleCommentsRoute',
paladox68b968e2022-02-20 17:31:50 +00001362 {
1363 project: 'gerrit' as RepoName,
1364 changeNum: 264833 as NumericChangeId,
1365 commentId: '00049681_f34fd6a9' as UrlEncodedCommentId,
1366 view: GerritView.CHANGE,
1367 }
1368 );
1369 });
1370 });
1371
Frank Borden79448112022-04-12 16:59:32 +02001372 test('handleDiffEditRoute', () => {
paladox68b968e2022-02-20 17:31:50 +00001373 const normalizeRangeSpy = sinon.spy(
Frank Borden79448112022-04-12 16:59:32 +02001374 router,
1375 'normalizePatchRangeParams'
paladox68b968e2022-02-20 17:31:50 +00001376 );
1377 stubRestApi('setInProjectLookup');
1378 const ctx = {
1379 ...createPageContext(),
1380 hash: '',
1381 params: {
1382 0: 'foo/bar', // 0 Project
1383 1: '1234', // 1 Change number
1384 2: '3', // 2 Patch num
1385 3: 'foo/bar/baz', // 3 File path
1386 },
1387 };
Ben Rohlfs6a0033a2022-09-15 11:32:55 +02001388 const appParams: EditViewState = {
paladox68b968e2022-02-20 17:31:50 +00001389 project: 'foo/bar' as RepoName,
1390 changeNum: 1234 as NumericChangeId,
Ben Rohlfs8163cd42022-08-18 16:04:36 +02001391 view: GerritView.EDIT,
paladox68b968e2022-02-20 17:31:50 +00001392 path: 'foo/bar/baz',
Ben Rohlfsabaeacf2022-05-27 15:24:22 +02001393 patchNum: 3 as RevisionPatchSetNum,
Ben Rohlfs6a0033a2022-09-15 11:32:55 +02001394 lineNum: 0,
paladox68b968e2022-02-20 17:31:50 +00001395 };
1396
Frank Borden79448112022-04-12 16:59:32 +02001397 router.handleDiffEditRoute(ctx);
paladox68b968e2022-02-20 17:31:50 +00001398 assert.isFalse(redirectStub.called);
1399 assert.isTrue(normalizeRangeSpy.calledOnce);
1400 assert.deepEqual(normalizeRangeSpy.lastCall.args[0], appParams);
1401 assert.isFalse(normalizeRangeSpy.lastCall.returnValue);
1402 assert.deepEqual(setParamsStub.lastCall.args[0], appParams);
1403 });
1404
Frank Borden79448112022-04-12 16:59:32 +02001405 test('handleDiffEditRoute with lineNum', () => {
paladox68b968e2022-02-20 17:31:50 +00001406 const normalizeRangeSpy = sinon.spy(
Frank Borden79448112022-04-12 16:59:32 +02001407 router,
1408 'normalizePatchRangeParams'
paladox68b968e2022-02-20 17:31:50 +00001409 );
1410 stubRestApi('setInProjectLookup');
1411 const ctx = {
1412 ...createPageContext(),
1413 hash: '4',
1414 params: {
1415 0: 'foo/bar', // 0 Project
1416 1: '1234', // 1 Change number
1417 2: '3', // 2 Patch num
1418 3: 'foo/bar/baz', // 3 File path
1419 },
1420 };
Ben Rohlfs6a0033a2022-09-15 11:32:55 +02001421 const appParams: EditViewState = {
paladox68b968e2022-02-20 17:31:50 +00001422 project: 'foo/bar' as RepoName,
1423 changeNum: 1234 as NumericChangeId,
Ben Rohlfs8163cd42022-08-18 16:04:36 +02001424 view: GerritView.EDIT,
paladox68b968e2022-02-20 17:31:50 +00001425 path: 'foo/bar/baz',
Ben Rohlfsabaeacf2022-05-27 15:24:22 +02001426 patchNum: 3 as RevisionPatchSetNum,
Ben Rohlfs6a0033a2022-09-15 11:32:55 +02001427 lineNum: 4,
paladox68b968e2022-02-20 17:31:50 +00001428 };
1429
Frank Borden79448112022-04-12 16:59:32 +02001430 router.handleDiffEditRoute(ctx);
paladox68b968e2022-02-20 17:31:50 +00001431 assert.isFalse(redirectStub.called);
1432 assert.isTrue(normalizeRangeSpy.calledOnce);
1433 assert.deepEqual(normalizeRangeSpy.lastCall.args[0], appParams);
1434 assert.isFalse(normalizeRangeSpy.lastCall.returnValue);
1435 assert.deepEqual(setParamsStub.lastCall.args[0], appParams);
1436 });
1437
Frank Borden79448112022-04-12 16:59:32 +02001438 test('handleChangeEditRoute', () => {
paladox68b968e2022-02-20 17:31:50 +00001439 const normalizeRangeSpy = sinon.spy(
Frank Borden79448112022-04-12 16:59:32 +02001440 router,
1441 'normalizePatchRangeParams'
paladox68b968e2022-02-20 17:31:50 +00001442 );
1443 stubRestApi('setInProjectLookup');
1444 const ctx = {
1445 ...createPageContext(),
1446 params: {
1447 0: 'foo/bar', // 0 Project
1448 1: '1234', // 1 Change number
1449 2: '',
1450 3: '3', // 3 Patch num
1451 },
1452 };
Ben Rohlfs804e7242022-09-15 16:16:12 +02001453 const appParams: ChangeViewState = {
paladox68b968e2022-02-20 17:31:50 +00001454 project: 'foo/bar' as RepoName,
1455 changeNum: 1234 as NumericChangeId,
1456 view: GerritView.CHANGE,
Ben Rohlfsabaeacf2022-05-27 15:24:22 +02001457 patchNum: 3 as RevisionPatchSetNum,
paladox68b968e2022-02-20 17:31:50 +00001458 edit: true,
1459 tab: '',
1460 };
1461
Frank Borden79448112022-04-12 16:59:32 +02001462 router.handleChangeEditRoute(ctx);
paladox68b968e2022-02-20 17:31:50 +00001463 assert.isFalse(redirectStub.called);
1464 assert.isTrue(normalizeRangeSpy.calledOnce);
1465 assert.deepEqual(normalizeRangeSpy.lastCall.args[0], appParams);
1466 assert.isFalse(normalizeRangeSpy.lastCall.returnValue);
1467 assert.deepEqual(setParamsStub.lastCall.args[0], appParams);
1468 });
1469 });
1470
Frank Borden79448112022-04-12 16:59:32 +02001471 test('handlePluginScreen', () => {
paladox68b968e2022-02-20 17:31:50 +00001472 const ctx = {...createPageContext(), params: {0: 'foo', 1: 'bar'}};
Frank Borden79448112022-04-12 16:59:32 +02001473 assertDataToParams(ctx, 'handlePluginScreen', {
Ben Rohlfs8163cd42022-08-18 16:04:36 +02001474 view: GerritView.PLUGIN_SCREEN,
paladox68b968e2022-02-20 17:31:50 +00001475 plugin: 'foo',
1476 screen: 'bar',
1477 });
1478 assert.isFalse(redirectStub.called);
1479 });
1480 });
1481
Frank Borden79448112022-04-12 16:59:32 +02001482 suite('parseQueryString', () => {
paladox68b968e2022-02-20 17:31:50 +00001483 test('empty queries', () => {
Frank Borden79448112022-04-12 16:59:32 +02001484 assert.deepEqual(router.parseQueryString(''), []);
1485 assert.deepEqual(router.parseQueryString('?'), []);
1486 assert.deepEqual(router.parseQueryString('??'), []);
1487 assert.deepEqual(router.parseQueryString('&&&'), []);
paladox68b968e2022-02-20 17:31:50 +00001488 });
1489
1490 test('url decoding', () => {
Frank Borden79448112022-04-12 16:59:32 +02001491 assert.deepEqual(router.parseQueryString('+'), [[' ', '']]);
1492 assert.deepEqual(router.parseQueryString('???+%3d+'), [[' = ', '']]);
paladox68b968e2022-02-20 17:31:50 +00001493 assert.deepEqual(
Frank Borden79448112022-04-12 16:59:32 +02001494 router.parseQueryString('%6e%61%6d%65=%76%61%6c%75%65'),
paladox68b968e2022-02-20 17:31:50 +00001495 [['name', 'value']]
1496 );
1497 });
1498
1499 test('multiple parameters', () => {
Frank Borden79448112022-04-12 16:59:32 +02001500 assert.deepEqual(router.parseQueryString('a=b&c=d&e=f'), [
paladox68b968e2022-02-20 17:31:50 +00001501 ['a', 'b'],
1502 ['c', 'd'],
1503 ['e', 'f'],
1504 ]);
Frank Borden79448112022-04-12 16:59:32 +02001505 assert.deepEqual(router.parseQueryString('&a=b&&&e=f&c'), [
paladox68b968e2022-02-20 17:31:50 +00001506 ['a', 'b'],
1507 ['e', 'f'],
1508 ['c', ''],
1509 ]);
1510 });
1511 });
1512});