blob: 8186fde749036b5b303023c3d98000ad89bbf0f1 [file] [log] [blame]
<!DOCTYPE html>
<!--
Copyright (C) 2017 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=yes">
<title>gr-router</title>
<script src="../../../bower_components/webcomponentsjs/webcomponents-lite.min.js"></script>
<script src="../../../bower_components/web-component-tester/browser.js"></script>
<link rel="import" href="../../../test/common-test-setup.html"/>
<link rel="import" href="gr-router.html">
<script>void(0);</script>
<test-fixture id="basic">
<template>
<gr-router></gr-router>
</template>
</test-fixture>
<script>
suite('gr-router tests', () => {
let element;
let sandbox;
setup(() => {
sandbox = sinon.sandbox.create();
element = fixture('basic');
});
teardown(() => { sandbox.restore(); });
test('_getHashFromCanonicalPath', () => {
let url = '/foo/bar';
let hash = element._getHashFromCanonicalPath(url);
assert.equal(hash, '');
url = '';
hash = element._getHashFromCanonicalPath(url);
assert.equal(hash, '');
url = '/foo#bar';
hash = element._getHashFromCanonicalPath(url);
assert.equal(hash, 'bar');
url = '/foo#bar#baz';
hash = element._getHashFromCanonicalPath(url);
assert.equal(hash, 'bar#baz');
url = '#foo#bar#baz';
hash = element._getHashFromCanonicalPath(url);
assert.equal(hash, 'foo#bar#baz');
});
suite('_parseLineAddress', () => {
test('returns null for empty and invalid hashes', () => {
let actual = element._parseLineAddress('');
assert.isNull(actual);
actual = element._parseLineAddress('foobar');
assert.isNull(actual);
actual = element._parseLineAddress('foo123');
assert.isNull(actual);
actual = element._parseLineAddress('123bar');
assert.isNull(actual);
});
test('parses correctly', () => {
let actual = element._parseLineAddress('1234');
assert.isOk(actual);
assert.equal(actual.lineNum, 1234);
assert.isFalse(actual.leftSide);
actual = element._parseLineAddress('a4');
assert.isOk(actual);
assert.equal(actual.lineNum, 4);
assert.isTrue(actual.leftSide);
actual = element._parseLineAddress('b77');
assert.isOk(actual);
assert.equal(actual.lineNum, 77);
assert.isTrue(actual.leftSide);
});
});
test('_startRouter requires auth for the right handlers', () => {
// This test encodes the lists of route handler methods that gr-router
// automatically checks for authentication before triggering.
const requiresAuth = {};
const doesNotRequireAuth = {};
sandbox.stub(Gerrit.Nav, 'setup');
sandbox.stub(window.page, 'start');
sandbox.stub(window.page, 'base');
sandbox.stub(window, 'page');
sandbox.stub(element, '_mapRoute', (pattern, methodName, usesAuth) => {
if (usesAuth) {
requiresAuth[methodName] = true;
} else {
doesNotRequireAuth[methodName] = true;
}
});
element._startRouter();
const actualRequiresAuth = Object.keys(requiresAuth);
actualRequiresAuth.sort();
const actualDoesNotRequireAuth = Object.keys(doesNotRequireAuth);
actualDoesNotRequireAuth.sort();
const shouldRequireAutoAuth = [
'_handleAdminPlaceholderRoute',
'_handleAgreementsRoute',
'_handleCreateGroupRoute',
'_handleCreateProjectRoute',
'_handleDiffEditRoute',
'_handleGroupAuditLogRoute',
'_handleGroupInfoRoute',
'_handleGroupListFilterOffsetRoute',
'_handleGroupListFilterRoute',
'_handleGroupListOffsetRoute',
'_handleGroupMembersRoute',
'_handleGroupRoute',
'_handlePluginListFilterOffsetRoute',
'_handlePluginListFilterRoute',
'_handlePluginListOffsetRoute',
'_handlePluginListRoute',
'_handleProjectCommandsRoute',
'_handleSettingsLegacyRoute',
'_handleSettingsRoute',
];
assert.deepEqual(actualRequiresAuth, shouldRequireAutoAuth);
const unauthenticatedHandlers = [
'_handleBranchListFilterOffsetRoute',
'_handleBranchListFilterRoute',
'_handleBranchListOffsetRoute',
'_handleChangeNumberLegacyRoute',
'_handleChangeOrDiffRoute',
'_handleDefaultRoute',
'_handleChangeLegacyRoute',
'_handleDiffLegacyRoute',
'_handleLegacyLinenum',
'_handleImproperlyEncodedPlusRoute',
'_handlePassThroughRoute',
'_handleProjectAccessRoute',
'_handleProjectListFilterOffsetRoute',
'_handleProjectListFilterRoute',
'_handleProjectListOffsetRoute',
'_handleProjectRoute',
'_handleQueryLegacySuffixRoute',
'_handleQueryRoute',
'_handleRegisterRoute',
'_handleTagListFilterOffsetRoute',
'_handleTagListFilterRoute',
'_handleTagListOffsetRoute',
];
// Handler names that check authentication themselves, and thus don't need
// it performed for them.
const selfAuthenticatingHandlers = [
'_handleDashboardRoute',
'_handleRootRoute',
];
const shouldNotRequireAuth = unauthenticatedHandlers
.concat(selfAuthenticatingHandlers);
shouldNotRequireAuth.sort();
assert.deepEqual(actualDoesNotRequireAuth, shouldNotRequireAuth);
});
test('_redirectIfNotLoggedIn while logged in', () => {
sandbox.stub(element.$.restAPI, 'getLoggedIn')
.returns(Promise.resolve(true));
const data = {canonicalPath: ''};
const redirectStub = sandbox.stub(element, '_redirectToLogin');
return element._redirectIfNotLoggedIn(data).then(() => {
assert.isFalse(redirectStub.called);
});
});
test('_redirectIfNotLoggedIn while logged out', () => {
sandbox.stub(element.$.restAPI, 'getLoggedIn')
.returns(Promise.resolve(false));
const redirectStub = sandbox.stub(element, '_redirectToLogin');
const data = {canonicalPath: ''};
return new Promise(resolve => {
element._redirectIfNotLoggedIn(data)
.then(() => {
assert.isTrue(false, 'Should never execute');
})
.catch(() => {
assert.isTrue(redirectStub.calledOnce);
resolve();
});
});
});
suite('generateUrl', () => {
test('search', () => {
let params = {
view: Gerrit.Nav.View.SEARCH,
owner: 'a%b',
project: 'c%d',
branch: 'e%f',
topic: 'g%h',
statuses: ['op%en'],
};
assert.equal(element._generateUrl(params),
'/q/owner:a%2525b+project:c%2525d+branch:e%2525f+' +
'topic:"g%2525h"+status:op%2525en');
params = {
view: Gerrit.Nav.View.SEARCH,
statuses: ['a', 'b', 'c'],
};
assert.equal(element._generateUrl(params),
'/q/(status:a OR status:b OR status:c)');
});
test('change', () => {
const params = {
view: Gerrit.Nav.View.CHANGE,
changeNum: '1234',
project: 'test',
};
assert.equal(element._generateUrl(params), '/c/test/+/1234');
params.patchNum = 10;
assert.equal(element._generateUrl(params), '/c/test/+/1234/10');
params.basePatchNum = 5;
assert.equal(element._generateUrl(params), '/c/test/+/1234/5..10');
});
test('diff', () => {
const params = {
view: Gerrit.Nav.View.DIFF,
changeNum: '42',
path: 'x+y/path.cpp',
patchNum: 12,
};
assert.equal(element._generateUrl(params),
'/c/42/12/x%252By/path.cpp');
params.project = 'test';
assert.equal(element._generateUrl(params),
'/c/test/+/42/12/x%252By/path.cpp');
params.basePatchNum = 6;
assert.equal(element._generateUrl(params),
'/c/test/+/42/6..12/x%252By/path.cpp');
params.path = 'foo bar/my+file.txt%';
params.patchNum = 2;
delete params.basePatchNum;
assert.equal(element._generateUrl(params),
'/c/test/+/42/2/foo+bar/my%252Bfile.txt%2525');
params.path = 'file.cpp';
params.lineNum = 123;
assert.equal(element._generateUrl(params),
'/c/test/+/42/2/file.cpp#123');
params.leftSide = true;
assert.equal(element._generateUrl(params),
'/c/test/+/42/2/file.cpp#b123');
});
test('_getPatchRangeExpression', () => {
const params = {};
let actual = element._getPatchRangeExpression(params);
assert.equal(actual, '');
params.patchNum = 4;
actual = element._getPatchRangeExpression(params);
assert.equal(actual, '4');
params.basePatchNum = 2;
actual = element._getPatchRangeExpression(params);
assert.equal(actual, '2..4');
delete params.patchNum;
actual = element._getPatchRangeExpression(params);
assert.equal(actual, '2..');
});
});
suite('param normalization', () => {
let projectLookupStub;
setup(() => {
projectLookupStub = sandbox
.stub(element.$.restAPI, 'getFromProjectLookup');
sandbox.stub(element, '_generateUrl');
});
suite('_normalizeLegacyRouteParams', () => {
let rangeStub;
let redirectStub;
setup(() => {
rangeStub = sandbox.stub(element, '_normalizePatchRangeParams')
.returns(Promise.resolve());
redirectStub = sandbox.stub(element, '_redirect');
});
test('w/o changeNum', () => {
projectLookupStub.returns(Promise.resolve('foo/bar'));
const params = {};
return element._normalizeLegacyRouteParams(params).then(() => {
assert.isFalse(projectLookupStub.called);
assert.isFalse(rangeStub.called);
assert.isNotOk(params.project);
assert.isFalse(redirectStub.called);
});
});
test('w/ changeNum', () => {
projectLookupStub.returns(Promise.resolve('foo/bar'));
const params = {changeNum: 1234};
return element._normalizeLegacyRouteParams(params).then(() => {
assert.isTrue(projectLookupStub.called);
assert.isTrue(rangeStub.called);
assert.equal(params.project, 'foo/bar');
assert.isTrue(redirectStub.calledOnce);
});
});
test('halts on project lookup failure', () => {
projectLookupStub.returns(Promise.resolve(undefined));
const params = {changeNum: 1234};
return element._normalizeLegacyRouteParams(params).then(() => {
assert.isTrue(projectLookupStub.called);
assert.isFalse(rangeStub.called);
assert.isUndefined(params.project);
assert.isFalse(redirectStub.called);
});
});
});
suite('_normalizePatchRangeParams', () => {
test('range n..n normalizes to n', () => {
const params = {basePatchNum: 4, patchNum: 4};
const needsRedirect = element._normalizePatchRangeParams(params);
assert.isTrue(needsRedirect);
assert.isNotOk(params.basePatchNum);
assert.equal(params.patchNum, 4);
});
test('range n.. normalizes to n', () => {
const params = {basePatchNum: 4};
const needsRedirect = element._normalizePatchRangeParams(params);
assert.isFalse(needsRedirect);
assert.isNotOk(params.basePatchNum);
assert.equal(params.patchNum, 4);
});
test('range 0..n normalizes to edit..n', () => {
const params = {basePatchNum: 0, patchNum: 4};
const needsRedirect = element._normalizePatchRangeParams(params);
assert.isTrue(needsRedirect);
assert.equal(params.basePatchNum, 'edit');
assert.equal(params.patchNum, 4);
});
test('range n..0 normalizes to n..edit', () => {
const params = {basePatchNum: 4, patchNum: 0};
const needsRedirect = element._normalizePatchRangeParams(params);
assert.isTrue(needsRedirect);
assert.equal(params.basePatchNum, 4);
assert.equal(params.patchNum, 'edit');
});
test('range 0..0 normalizes to edit', () => {
const params = {basePatchNum: 0, patchNum: 0};
const needsRedirect = element._normalizePatchRangeParams(params);
assert.isTrue(needsRedirect);
assert.isNotOk(params.basePatchNum);
assert.equal(params.patchNum, 'edit');
});
// TODO(issue 4760): Remove when PG supports diffing against numbered
// parents of a merge.
test('range -n..m normalizes to m', () => {
const params = {basePatchNum: -2, patchNum: 4};
const needsRedirect = element._normalizePatchRangeParams(params);
assert.isTrue(needsRedirect);
assert.isNotOk(params.basePatchNum);
assert.equal(params.patchNum, 4);
});
});
});
suite('route handlers', () => {
let redirectStub;
let setParamsStub;
// Simple route handlers are direct mappings from parsed route data to a
// new set of app.params. This test helper asserts that passing `data`
// into `methodName` results in setting the params specified in `params`.
function assertDataToParams(data, methodName, params) {
element[methodName](data);
assert.deepEqual(setParamsStub.lastCall.args[0], params);
}
setup(() => {
redirectStub = sandbox.stub(element, '_redirect');
setParamsStub = sandbox.stub(element, '_setParams');
});
test('_handleAdminPlaceholderRoute', () => {
element._handleAdminPlaceholderRoute({params: {}});
assert.equal(setParamsStub.lastCall.args[0].view,
Gerrit.Nav.View.ADMIN);
assert.isTrue(setParamsStub.lastCall.args[0].placeholder);
});
test('_handleAgreementsRoute', () => {
element._handleAgreementsRoute({params: {}});
assert.isTrue(setParamsStub.calledOnce);
assert.equal(setParamsStub.lastCall.args[0].view,
Gerrit.Nav.View.AGREEMENTS);
});
test('_handleSettingsLegacyRoute', () => {
const data = {params: {0: 'my-token'}};
assertDataToParams(data, '_handleSettingsLegacyRoute', {
view: Gerrit.Nav.View.SETTINGS,
emailToken: 'my-token',
});
});
test('_handleSettingsRoute', () => {
const data = {};
assertDataToParams(data, '_handleSettingsRoute', {
view: Gerrit.Nav.View.SETTINGS,
});
});
test('_handleDefaultRoute', () => {
element._app = {dispatchEvent: sinon.stub()};
element._handleDefaultRoute();
assert.isTrue(element._app.dispatchEvent.calledOnce);
assert.equal(
element._app.dispatchEvent.lastCall.args[0].detail.response.status,
404);
});
test('_handleImproperlyEncodedPlusRoute', () => {
// Regression test for Issue 7100.
element._handleImproperlyEncodedPlusRoute(
{canonicalPath: '/c/test/%20/42', params: ['test', '42']});
assert.isTrue(redirectStub.calledOnce);
assert.equal(
redirectStub.lastCall.args[0],
'/c/test/+/42');
sandbox.stub(element, '_getHashFromCanonicalPath').returns('foo');
element._handleImproperlyEncodedPlusRoute(
{canonicalPath: '/c/test/%20/42', params: ['test', '42']});
assert.equal(
redirectStub.lastCall.args[0],
'/c/test/+/42#foo');
});
test('_handleQueryLegacySuffixRoute', () => {
element._handleQueryLegacySuffixRoute({path: '/q/foo+bar,n,z'});
assert.isTrue(redirectStub.calledOnce);
assert.equal(redirectStub.lastCall.args[0], '/q/foo+bar');
});
test('_handleQueryRoute', () => {
const data = {params: ['project:foo/bar/baz']};
assertDataToParams(data, '_handleQueryRoute', {
view: Gerrit.Nav.View.SEARCH,
query: 'project:foo/bar/baz',
offset: undefined,
});
data.params.push(',123', '123');
assertDataToParams(data, '_handleQueryRoute', {
view: Gerrit.Nav.View.SEARCH,
query: 'project:foo/bar/baz',
offset: '123',
});
});
suite('_handleRegisterRoute', () => {
test('happy path', () => {
const ctx = {params: ['/foo/bar']};
element._handleRegisterRoute(ctx);
assert.isTrue(redirectStub.calledWithExactly('/foo/bar'));
assert.isTrue(setParamsStub.calledOnce);
assert.isTrue(setParamsStub.lastCall.args[0].justRegistered);
});
test('no param', () => {
const ctx = {params: ['']};
element._handleRegisterRoute(ctx);
assert.isTrue(redirectStub.calledWithExactly('/'));
assert.isTrue(setParamsStub.calledOnce);
assert.isTrue(setParamsStub.lastCall.args[0].justRegistered);
});
test('prevent redirect', () => {
const ctx = {params: ['/register']};
element._handleRegisterRoute(ctx);
assert.isTrue(redirectStub.calledWithExactly('/'));
assert.isTrue(setParamsStub.calledOnce);
assert.isTrue(setParamsStub.lastCall.args[0].justRegistered);
});
});
suite('_handleRootRoute', () => {
test('closes for closeAfterLogin', () => {
const data = {querystring: 'closeAfterLogin', canonicalPath: ''};
const closeStub = sandbox.stub(window, 'close');
const result = element._handleRootRoute(data);
assert.isNotOk(result);
assert.isTrue(closeStub.called);
assert.isFalse(redirectStub.called);
});
test('redirects to dahsboard if logged in', () => {
sandbox.stub(element.$.restAPI, 'getLoggedIn')
.returns(Promise.resolve(true));
const data = {
canonicalPath: '/', path: '/', querystring: '', hash: '',
};
const result = element._handleRootRoute(data);
assert.isOk(result);
return result.then(() => {
assert.isTrue(redirectStub.calledWithExactly('/dashboard/self'));
});
});
test('redirects to open changes if not logged in', () => {
sandbox.stub(element.$.restAPI, 'getLoggedIn')
.returns(Promise.resolve(false));
const data = {
canonicalPath: '/', path: '/', querystring: '', hash: '',
};
const result = element._handleRootRoute(data);
assert.isOk(result);
return result.then(() => {
assert.isTrue(redirectStub.calledWithExactly('/q/status:open'));
});
});
suite('GWT hash-path URLs', () => {
test('redirects hash-path URLs', () => {
const data = {
canonicalPath: '/#/foo/bar/baz',
hash: '/foo/bar/baz',
querystring: '',
};
const result = element._handleRootRoute(data);
assert.isNotOk(result);
assert.isTrue(redirectStub.called);
assert.isTrue(redirectStub.calledWithExactly('/foo/bar/baz'));
});
test('redirects hash-path URLs w/o leading slash', () => {
const data = {
canonicalPath: '/#foo/bar/baz',
querystring: '',
hash: 'foo/bar/baz',
};
const result = element._handleRootRoute(data);
assert.isNotOk(result);
assert.isTrue(redirectStub.called);
assert.isTrue(redirectStub.calledWithExactly('/foo/bar/baz'));
});
test('normalizes "/ /" in hash to "/+/"', () => {
const data = {
canonicalPath: '/#/foo/bar/+/123/4',
querystring: '',
hash: '/foo/bar/ /123/4',
};
const result = element._handleRootRoute(data);
assert.isNotOk(result);
assert.isTrue(redirectStub.called);
assert.isTrue(redirectStub.calledWithExactly('/foo/bar/+/123/4'));
});
test('prepends baseurl to hash-path', () => {
const data = {
canonicalPath: '/#/foo/bar',
querystring: '',
hash: '/foo/bar',
};
sandbox.stub(element, 'getBaseUrl').returns('/baz');
const result = element._handleRootRoute(data);
assert.isNotOk(result);
assert.isTrue(redirectStub.called);
assert.isTrue(redirectStub.calledWithExactly('/baz/foo/bar'));
});
test('normalizes /VE/ settings hash-paths', () => {
const data = {
canonicalPath: '/#/VE/foo/bar',
querystring: '',
hash: '/VE/foo/bar',
};
const result = element._handleRootRoute(data);
assert.isNotOk(result);
assert.isTrue(redirectStub.called);
assert.isTrue(redirectStub.calledWithExactly(
'/settings/VE/foo/bar'));
});
test('does not drop "inner hashes"', () => {
const data = {
canonicalPath: '/#/foo/bar#baz',
querystring: '',
hash: '/foo/bar',
};
const result = element._handleRootRoute(data);
assert.isNotOk(result);
assert.isTrue(redirectStub.called);
assert.isTrue(redirectStub.calledWithExactly('/foo/bar#baz'));
});
});
});
suite('_handleDashboardRoute', () => {
let redirectToLoginStub;
setup(() => {
redirectToLoginStub = sandbox.stub(element, '_redirectToLogin');
});
test('no user specified', () => {
const data = {canonicalPath: '/dashboard', params: {}};
const result = element._handleDashboardRoute(data);
assert.isNotOk(result);
assert.isFalse(setParamsStub.called);
assert.isFalse(redirectToLoginStub.called);
assert.isTrue(redirectStub.called);
assert.equal(redirectStub.lastCall.args[0], '/dashboard/self');
});
test('own dahsboard but signed out redirects to login', () => {
sandbox.stub(element.$.restAPI, 'getLoggedIn')
.returns(Promise.resolve(false));
const data = {canonicalPath: '/dashboard', params: {0: 'seLF'}};
const result = element._handleDashboardRoute(data);
assert.isOk(result);
return result.then(() => {
assert.isTrue(redirectToLoginStub.calledOnce);
assert.isFalse(redirectStub.called);
assert.isFalse(setParamsStub.called);
});
});
test('non-self dahsboard but signed out does not redirect', () => {
sandbox.stub(element.$.restAPI, 'getLoggedIn')
.returns(Promise.resolve(false));
const data = {canonicalPath: '/dashboard', params: {0: 'foo'}};
const result = element._handleDashboardRoute(data);
assert.isOk(result);
return result.then(() => {
assert.isFalse(redirectToLoginStub.called);
assert.isFalse(setParamsStub.called);
assert.isTrue(redirectStub.calledOnce);
assert.equal(redirectStub.lastCall.args[0], '/q/owner:foo');
});
});
test('dahsboard while signed in sets params', () => {
sandbox.stub(element.$.restAPI, 'getLoggedIn')
.returns(Promise.resolve(true));
const data = {canonicalPath: '/dashboard', params: {0: 'foo'}};
const result = element._handleDashboardRoute(data);
assert.isOk(result);
return result.then(() => {
assert.isFalse(redirectToLoginStub.called);
assert.isFalse(redirectStub.called);
assert.isTrue(setParamsStub.calledOnce);
assert.deepEqual(setParamsStub.lastCall.args[0], {
view: Gerrit.Nav.View.DASHBOARD,
user: 'foo',
});
});
});
});
suite('group routes', () => {
test('_handleGroupInfoRoute', () => {
const data = {params: {0: 1234}};
element._handleGroupInfoRoute(data);
assert.isTrue(redirectStub.calledOnce);
assert.equal(redirectStub.lastCall.args[0], '/admin/groups/1234');
});
test('_handleGroupAuditLogRoute', () => {
const data = {params: {0: 1234}};
assertDataToParams(data, '_handleGroupAuditLogRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-group-audit-log',
detailType: 'audit-log',
groupId: 1234,
});
});
test('_handleGroupMembersRoute', () => {
const data = {params: {0: 1234}};
assertDataToParams(data, '_handleGroupMembersRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-group-members',
detailType: 'members',
groupId: 1234,
});
});
test('_handleGroupListOffsetRoute', () => {
const data = {params: {}};
assertDataToParams(data, '_handleGroupListOffsetRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-admin-group-list',
offset: 0,
filter: null,
openCreateModal: false,
});
data.params[1] = 42;
assertDataToParams(data, '_handleGroupListOffsetRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-admin-group-list',
offset: 42,
filter: null,
openCreateModal: false,
});
data.hash = 'create';
assertDataToParams(data, '_handleGroupListOffsetRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-admin-group-list',
offset: 42,
filter: null,
openCreateModal: true,
});
});
test('_handleGroupListFilterOffsetRoute', () => {
const data = {params: {filter: 'foo', offset: 42}};
assertDataToParams(data, '_handleGroupListFilterOffsetRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-admin-group-list',
offset: 42,
filter: 'foo',
});
});
test('_handleGroupListFilterRoute', () => {
const data = {params: {filter: 'foo'}};
assertDataToParams(data, '_handleGroupListFilterRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-admin-group-list',
filter: 'foo',
});
});
test('_handleGroupRoute', () => {
const data = {params: {0: 4321}};
assertDataToParams(data, '_handleGroupRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-group',
groupId: 4321,
});
});
});
suite('project routes', () => {
test('_handleProjectRoute', () => {
const data = {params: {0: 4321}};
assertDataToParams(data, '_handleProjectRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-project',
project: 4321,
});
});
test('_handleProjectCommandsRoute', () => {
const data = {params: {0: 4321}};
assertDataToParams(data, '_handleProjectCommandsRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-project-commands',
detailType: 'commands',
project: 4321,
});
});
test('_handleProjectAccessRoute', () => {
const data = {params: {0: 4321}};
assertDataToParams(data, '_handleProjectAccessRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-project-access',
detailType: 'access',
project: 4321,
});
});
suite('branch list routes', () => {
test('_handleBranchListOffsetRoute', () => {
const data = {params: {0: 4321}};
assertDataToParams(data, '_handleBranchListOffsetRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-project-detail-list',
detailType: 'branches',
project: 4321,
offset: 0,
filter: null,
});
data.params[2] = 42;
assertDataToParams(data, '_handleBranchListOffsetRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-project-detail-list',
detailType: 'branches',
project: 4321,
offset: 42,
filter: null,
});
});
test('_handleBranchListFilterOffsetRoute', () => {
const data = {params: {project: 4321, filter: 'foo', offset: 42}};
assertDataToParams(data, '_handleBranchListFilterOffsetRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-project-detail-list',
detailType: 'branches',
project: 4321,
offset: 42,
filter: 'foo',
});
});
test('_handleBranchListFilterRoute', () => {
const data = {params: {project: 4321, filter: 'foo'}};
assertDataToParams(data, '_handleBranchListFilterRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-project-detail-list',
detailType: 'branches',
project: 4321,
filter: 'foo',
});
});
});
suite('tag list routes', () => {
test('_handleTagListOffsetRoute', () => {
const data = {params: {0: 4321}};
assertDataToParams(data, '_handleTagListOffsetRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-project-detail-list',
detailType: 'tags',
project: 4321,
offset: 0,
filter: null,
});
});
test('_handleTagListFilterOffsetRoute', () => {
const data = {params: {project: 4321, filter: 'foo', offset: 42}};
assertDataToParams(data, '_handleTagListFilterOffsetRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-project-detail-list',
detailType: 'tags',
project: 4321,
offset: 42,
filter: 'foo',
});
});
test('_handleTagListFilterRoute', () => {
const data = {params: {project: 4321}};
assertDataToParams(data, '_handleTagListFilterRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-project-detail-list',
detailType: 'tags',
project: 4321,
filter: null,
});
data.params.filter = 'foo';
assertDataToParams(data, '_handleTagListFilterRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-project-detail-list',
detailType: 'tags',
project: 4321,
filter: 'foo',
});
});
});
suite('project list routes', () => {
test('_handleProjectListOffsetRoute', () => {
const data = {params: {}};
assertDataToParams(data, '_handleProjectListOffsetRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-project-list',
offset: 0,
filter: null,
openCreateModal: false,
});
data.params[1] = 42;
assertDataToParams(data, '_handleProjectListOffsetRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-project-list',
offset: 42,
filter: null,
openCreateModal: false,
});
data.hash = 'create';
assertDataToParams(data, '_handleProjectListOffsetRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-project-list',
offset: 42,
filter: null,
openCreateModal: true,
});
});
test('_handleProjectListFilterOffsetRoute', () => {
const data = {params: {filter: 'foo', offset: 42}};
assertDataToParams(data, '_handleProjectListFilterOffsetRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-project-list',
offset: 42,
filter: 'foo',
});
});
test('_handleProjectListFilterRoute', () => {
const data = {params: {}};
assertDataToParams(data, '_handleProjectListFilterRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-project-list',
filter: null,
});
data.params.filter = 'foo';
assertDataToParams(data, '_handleProjectListFilterRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-project-list',
filter: 'foo',
});
});
});
});
suite('plugin routes', () => {
test('_handlePluginListOffsetRoute', () => {
const data = {params: {}};
assertDataToParams(data, '_handlePluginListOffsetRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-plugin-list',
offset: 0,
filter: null,
});
data.params[1] = 42;
assertDataToParams(data, '_handlePluginListOffsetRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-plugin-list',
offset: 42,
filter: null,
});
});
test('_handlePluginListFilterOffsetRoute', () => {
const data = {params: {filter: 'foo', offset: 42}};
assertDataToParams(data, '_handlePluginListFilterOffsetRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-plugin-list',
offset: 42,
filter: 'foo',
});
});
test('_handlePluginListFilterRoute', () => {
const data = {params: {}};
assertDataToParams(data, '_handlePluginListFilterRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-plugin-list',
filter: null,
});
data.params.filter = 'foo';
assertDataToParams(data, '_handlePluginListFilterRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-plugin-list',
filter: 'foo',
});
});
test('_handlePluginListRoute', () => {
const data = {params: {}};
assertDataToParams(data, '_handlePluginListRoute', {
view: Gerrit.Nav.View.ADMIN,
adminView: 'gr-plugin-list',
});
});
});
suite('change/diff routes', () => {
test('_handleChangeNumberLegacyRoute', () => {
const data = {params: {0: 12345}};
element._handleChangeNumberLegacyRoute(data);
assert.isTrue(redirectStub.calledOnce);
assert.isTrue(redirectStub.calledWithExactly('/c/12345'));
});
test('_handleChangeLegacyRoute', () => {
const normalizeRouteStub = sandbox.stub(element,
'_normalizeLegacyRouteParams');
const ctx = {
params: [
1234, // 0 Change number
null, // 1 Unused
null, // 2 Unused
6, // 3 Base patch number
null, // 4 Unused
9, // 5 Patch number
],
};
element._handleChangeLegacyRoute(ctx);
assert.isTrue(normalizeRouteStub.calledOnce);
assert.deepEqual(normalizeRouteStub.lastCall.args[0], {
changeNum: 1234,
basePatchNum: 6,
patchNum: 9,
view: Gerrit.Nav.View.CHANGE,
});
});
test('_handleDiffLegacyRoute', () => {
const normalizeRouteStub = sandbox.stub(element,
'_normalizeLegacyRouteParams');
const ctx = {
params: [
1234, // 0 Change number
null, // 1 Unused
3, // 2 Base patch number
null, // 3 Unused
8, // 4 Patch number
'foo/bar', // 5 Diff path
],
path: '/c/1234/3..8/foo/bar',
hash: 'b123',
};
element._handleDiffLegacyRoute(ctx);
assert.isFalse(redirectStub.called);
assert.isTrue(normalizeRouteStub.calledOnce);
assert.deepEqual(normalizeRouteStub.lastCall.args[0], {
changeNum: 1234,
basePatchNum: 3,
patchNum: 8,
view: Gerrit.Nav.View.DIFF,
path: 'foo/bar',
lineNum: 123,
leftSide: true,
});
});
test('_handleLegacyLinenum w/ @321', () => {
const ctx = {path: '/c/1234/3..8/foo/bar@321'};
element._handleLegacyLinenum(ctx);
assert.isTrue(redirectStub.calledOnce);
assert.isTrue(redirectStub.calledWithExactly(
'/c/1234/3..8/foo/bar#321'));
});
test('_handleLegacyLinenum w/ @b123', () => {
const ctx = {path: '/c/1234/3..8/foo/bar@b123'};
element._handleLegacyLinenum(ctx);
assert.isTrue(redirectStub.calledOnce);
assert.isTrue(redirectStub.calledWithExactly(
'/c/1234/3..8/foo/bar#b123'));
});
suite('_handleChangeOrDiffRoute', () => {
let normalizeRangeStub;
function makeParams(path, hash) {
return {
params: [
'foo/bar', // 0 Project
1234, // 1 Change number
null, // 2 Unused
null, // 3 Unused
4, // 4 Base patch number
null, // 5 Unused
7, // 6 Patch number
null, // 7 Unused,
path, // 8 Diff path
],
hash,
};
}
setup(() => {
normalizeRangeStub = sandbox.stub(element,
'_normalizePatchRangeParams');
sandbox.stub(element.$.restAPI, 'setInProjectLookup');
});
test('needs redirect', () => {
normalizeRangeStub.returns(true);
sandbox.stub(element, '_generateUrl').returns('foo');
const ctx = makeParams(null, '');
element._handleChangeOrDiffRoute(ctx);
assert.isTrue(normalizeRangeStub.called);
assert.isFalse(setParamsStub.called);
assert.isTrue(redirectStub.calledOnce);
assert.isTrue(redirectStub.calledWithExactly('foo'));
});
test('change view', () => {
normalizeRangeStub.returns(false);
sandbox.stub(element, '_generateUrl').returns('foo');
const ctx = makeParams(null, '');
assertDataToParams(ctx, '_handleChangeOrDiffRoute', {
view: Gerrit.Nav.View.CHANGE,
project: 'foo/bar',
changeNum: 1234,
basePatchNum: 4,
patchNum: 7,
path: null,
});
assert.isFalse(redirectStub.called);
assert.isTrue(normalizeRangeStub.called);
});
test('diff view', () => {
normalizeRangeStub.returns(false);
sandbox.stub(element, '_generateUrl').returns('foo');
const ctx = makeParams('foo/bar/baz', 'b44');
assertDataToParams(ctx, '_handleChangeOrDiffRoute', {
view: Gerrit.Nav.View.DIFF,
project: 'foo/bar',
changeNum: 1234,
basePatchNum: 4,
patchNum: 7,
path: 'foo/bar/baz',
leftSide: true,
lineNum: 44,
});
assert.isFalse(redirectStub.called);
assert.isTrue(normalizeRangeStub.called);
});
});
test('_handleDiffEditRoute', () => {
const normalizeRangeSpy =
sandbox.spy(element, '_normalizePatchRangeParams');
sandbox.stub(element.$.restAPI, 'setInProjectLookup');
const ctx = {
params: [
'foo/bar', // 0 Project
1234, // 1 Change number
'foo/bar/baz', // 2 File path
],
};
const appParams = {
project: 'foo/bar',
changeNum: 1234,
view: Gerrit.Nav.View.EDIT,
path: 'foo/bar/baz',
};
element._handleDiffEditRoute(ctx);
assert.isFalse(redirectStub.called);
assert.isTrue(normalizeRangeSpy.calledOnce);
assert.deepEqual(normalizeRangeSpy.lastCall.args[0], appParams);
assert.isFalse(normalizeRangeSpy.lastCall.returnValue);
assert.deepEqual(setParamsStub.lastCall.args[0], appParams);
});
});
});
});
</script>