Merge "Refactor gr-router_test"
diff --git a/polygerrit-ui/app/elements/core/gr-router/gr-router.ts b/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
index 00cb938..88bacdf 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
@@ -4,6 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
import {
+ Options,
page,
PageContext,
PageNextCallback,
@@ -257,8 +258,6 @@
DOCUMENTATION: /^\/Documentation(\/)?(.+)?/,
};
-export const _testOnly_RoutePattern = RoutePattern;
-
/**
* Pattern to recognize and parse the diff line locations as they appear in
* the hash of diff URLs. In this format, a number on its own indicates that
@@ -587,7 +586,11 @@
);
}
- startRouter() {
+ _testOnly_startRouter() {
+ this.startRouter({dispatch: false, popstate: false});
+ }
+
+ startRouter(opts: Options = {}) {
const base = getBaseUrl();
if (base) {
this.page.base(base);
@@ -991,7 +994,7 @@
this.handleDefaultRoute()
);
- this.page.start();
+ this.page.start(opts);
}
/**
@@ -1280,7 +1283,7 @@
view: GerritView.REPO,
detail: RepoDetailView.BRANCHES,
repo: ctx.params[0] as RepoName,
- offset: ctx.params[2] || 0,
+ offset: ctx.params[2] ?? '0',
filter: null,
};
// Note that router model view must be updated before view models.
@@ -1293,8 +1296,8 @@
view: GerritView.REPO,
detail: RepoDetailView.BRANCHES,
repo: ctx.params['repo'] as RepoName,
- offset: ctx.params['offset'],
- filter: ctx.params['filter'],
+ offset: ctx.params['offset'] ?? '0',
+ filter: ctx.params['filter'] ?? null,
};
// Note that router model view must be updated before view models.
this.setState(state);
@@ -1306,7 +1309,8 @@
view: GerritView.REPO,
detail: RepoDetailView.BRANCHES,
repo: ctx.params['repo'] as RepoName,
- filter: ctx.params['filter'] || null,
+ filter: ctx.params['filter'] ?? null,
+ offset: '0',
};
// Note that router model view must be updated before view models.
this.setState(state);
@@ -1318,7 +1322,7 @@
view: GerritView.REPO,
detail: RepoDetailView.TAGS,
repo: ctx.params[0] as RepoName,
- offset: ctx.params[2] || 0,
+ offset: ctx.params[2] ?? '0',
filter: null,
};
// Note that router model view must be updated before view models.
@@ -1331,7 +1335,7 @@
view: GerritView.REPO,
detail: RepoDetailView.TAGS,
repo: ctx.params['repo'] as RepoName,
- offset: ctx.params['offset'],
+ offset: ctx.params['offset'] ?? '0',
filter: ctx.params['filter'],
};
// Note that router model view must be updated before view models.
@@ -1344,7 +1348,8 @@
view: GerritView.REPO,
detail: RepoDetailView.TAGS,
repo: ctx.params['repo'] as RepoName,
- filter: ctx.params['filter'] || null,
+ offset: '0',
+ filter: ctx.params['filter'] ?? null,
};
// Note that router model view must be updated before view models.
this.setState(state);
@@ -1355,7 +1360,7 @@
const state: AdminViewState = {
view: GerritView.ADMIN,
adminView: AdminChildView.REPOS,
- offset: ctx.params[1] || 0,
+ offset: ctx.params[1] ?? '0',
filter: null,
openCreateModal: ctx.hash === 'create',
};
@@ -1368,8 +1373,9 @@
const state: AdminViewState = {
view: GerritView.ADMIN,
adminView: AdminChildView.REPOS,
- offset: ctx.params['offset'],
+ offset: ctx.params['offset'] ?? '0',
filter: ctx.params['filter'],
+ openCreateModal: false,
};
// Note that router model view must be updated before view models.
this.setState(state);
@@ -1380,7 +1386,9 @@
const state: AdminViewState = {
view: GerritView.ADMIN,
adminView: AdminChildView.REPOS,
- filter: ctx.params['filter'] || null,
+ offset: '0',
+ filter: ctx.params['filter'] ?? null,
+ openCreateModal: false,
};
// Note that router model view must be updated before view models.
this.setState(state);
@@ -1407,7 +1415,7 @@
const state: AdminViewState = {
view: GerritView.ADMIN,
adminView: AdminChildView.PLUGINS,
- offset: ctx.params[1] || 0,
+ offset: ctx.params[1] ?? '0',
filter: null,
};
// Note that router model view must be updated before view models.
@@ -1419,7 +1427,7 @@
const state: AdminViewState = {
view: GerritView.ADMIN,
adminView: AdminChildView.PLUGINS,
- offset: ctx.params['offset'],
+ offset: ctx.params['offset'] ?? '0',
filter: ctx.params['filter'],
};
// Note that router model view must be updated before view models.
@@ -1431,7 +1439,8 @@
const state: AdminViewState = {
view: GerritView.ADMIN,
adminView: AdminChildView.PLUGINS,
- filter: ctx.params['filter'] || null,
+ offset: '0',
+ filter: ctx.params['filter'] ?? null,
};
// Note that router model view must be updated before view models.
this.setState(state);
@@ -1439,10 +1448,12 @@
}
handleQueryRoute(ctx: PageContext) {
- const state: Partial<SearchViewState> = {
+ const state: SearchViewState = {
view: GerritView.SEARCH,
query: ctx.params[0],
offset: ctx.params[2],
+ loading: false,
+ changes: [],
};
// Note that router model view must be updated before view models.
this.setState(state as AppElementParams);
@@ -1453,10 +1464,12 @@
// TODO(pcc): This will need to indicate that this was a change ID query if
// standard queries gain the ability to search places like commit messages
// for change IDs.
- const state: Partial<SearchViewState> = {
+ const state: SearchViewState = {
view: GerritView.SEARCH,
query: ctx.params[0],
offset: undefined,
+ loading: false,
+ changes: [],
};
// Note that router model view must be updated before view models.
this.setState(state as AppElementParams);
diff --git a/polygerrit-ui/app/elements/core/gr-router/gr-router_test.ts b/polygerrit-ui/app/elements/core/gr-router/gr-router_test.ts
index af44739..e1ba42c 100644
--- a/polygerrit-ui/app/elements/core/gr-router/gr-router_test.ts
+++ b/polygerrit-ui/app/elements/core/gr-router/gr-router_test.ts
@@ -10,33 +10,42 @@
stubBaseUrl,
stubRestApi,
addListenerForTest,
- waitEventLoop,
waitUntilCalled,
} from '../../../test/test-utils';
-import {GrRouter, routerToken, _testOnly_RoutePattern} from './gr-router';
+import {GrRouter, routerToken} from './gr-router';
import {GerritView} from '../../../services/router/router-model';
import {
BasePatchSetNum,
- GroupId,
NumericChangeId,
PARENT,
RepoName,
RevisionPatchSetNum,
UrlEncodedCommentId,
} from '../../../types/common';
-import {AppElementParams} from '../../gr-app-types';
+import {AppElementJustRegisteredParams} from '../../gr-app-types';
import {assert} from '@open-wc/testing';
import {AdminChildView, AdminViewState} from '../../../models/views/admin';
import {RepoDetailView} from '../../../models/views/repo';
import {GroupDetailView} from '../../../models/views/group';
-import {ChangeChildView, ChangeViewState} from '../../../models/views/change';
+import {ChangeChildView} from '../../../models/views/change';
import {PatchRangeParams} from '../../../utils/url-util';
import {testResolver} from '../../../test/common-test-setup';
import {
+ createAdminPluginsViewState,
+ createAdminReposViewState,
+ createChangeViewState,
createComment,
+ createDashboardViewState,
createDiff,
+ createDiffViewState,
+ createEditViewState,
+ createGroupViewState,
createParsedChange,
+ createRepoBranchesViewState,
+ createRepoTagsViewState,
+ createRepoViewState,
createRevision,
+ createSearchViewState,
} from '../../../test/test-data-generators';
import {ParsedChangeInfo} from '../../../types/types';
import {ViewState} from '../../../models/views/base';
@@ -50,6 +59,10 @@
page = router.page;
});
+ teardown(async () => {
+ router.finalize();
+ });
+
test('getHashFromCanonicalPath', () => {
let url = '/foo/bar';
let hash = router.getHashFromCanonicalPath(url);
@@ -105,7 +118,7 @@
});
});
- test('startRouter requires auth for the right handlers', () => {
+ test('startRouterForTesting requires auth for the right handlers', () => {
// This test encodes the lists of route handler methods that gr-router
// automatically checks for authentication before triggering.
@@ -122,7 +135,7 @@
doesNotRequireAuth[methodName] = true;
}
});
- router.startRouter();
+ router._testOnly_startRouter();
const actualRequiresAuth = Object.keys(requiresAuth);
actualRequiresAuth.sort();
@@ -280,26 +293,38 @@
let redirectStub: sinon.SinonStub;
let setStateStub: sinon.SinonStub;
let handlePassThroughRoute: sinon.SinonStub;
+ let redirectToLoginStub: sinon.SinonStub;
- // Simple route handlers are direct mappings from parsed route ctx to a
- // new set of app.params. This test helper asserts that passing `ctx`
- // into `methodName` results in setting the params specified in `params`.
- function assertctxToParams(
- ctx: PageContext,
- methodName: string,
- params: AppElementParams
+ async function checkUrlToState<T extends ViewState>(
+ url: string,
+ state: T | AppElementJustRegisteredParams
) {
- (router as any)[methodName](ctx);
- assert.deepEqual(setStateStub.lastCall.args[0], params);
- }
-
- async function checkUrlToState<T extends ViewState>(url: string, state: T) {
setStateStub.reset();
router.page.show(url);
await waitUntilCalled(setStateStub, 'setState');
+ assert.isTrue(setStateStub.calledOnce);
assert.deepEqual(setStateStub.lastCall.firstArg, state);
}
+ async function checkRedirect(fromUrl: string, toUrl: string) {
+ redirectStub.reset();
+ router.page.show(fromUrl);
+ await waitUntilCalled(redirectStub, 'redirect');
+ assert.isTrue(redirectStub.calledOnce);
+ assert.isFalse(setStateStub.called);
+ assert.equal(redirectStub.lastCall.firstArg, toUrl);
+ }
+
+ async function checkRedirectToLogin(fromUrl: string, toUrl: string) {
+ redirectToLoginStub.reset();
+ router.page.show(fromUrl);
+ await waitUntilCalled(redirectToLoginStub, 'redirectToLogin');
+ assert.isTrue(redirectToLoginStub.calledOnce);
+ assert.isFalse(redirectStub.called);
+ assert.isFalse(setStateStub.called);
+ assert.equal(redirectToLoginStub.lastCall.firstArg, toUrl);
+ }
+
async function checkUrlNotMatched(url: string) {
handlePassThroughRoute.reset();
router.page.show(url);
@@ -318,57 +343,49 @@
}
setup(() => {
+ stubRestApi('setInProjectLookup');
redirectStub = sinon.stub(router, 'redirect');
+ redirectToLoginStub = sinon.stub(router, 'redirectToLogin');
setStateStub = sinon.stub(router, 'setState');
handlePassThroughRoute = sinon.stub(router, 'handlePassThroughRoute');
- router.startRouter();
+ router._testOnly_startRouter();
});
- test('handleLegacyProjectDashboardRoute', () => {
- const params = {
- ...createPageContext(),
- params: {0: 'gerrit/project', 1: 'dashboard:main'},
- };
- router.handleLegacyProjectDashboardRoute(params);
- assert.isTrue(redirectStub.calledOnce);
- assert.equal(
- redirectStub.lastCall.args[0],
+ test('LEGACY_PROJECT_DASHBOARD', async () => {
+ // LEGACY_PROJECT_DASHBOARD: /^\/projects\/(.+),dashboards\/(.+)/,
+ await checkRedirect(
+ '/projects/gerrit/project,dashboards/dashboard:main',
'/p/gerrit/project/+/dashboard/dashboard:main'
);
});
- test('handleAgreementsRoute', () => {
- router.handleAgreementsRoute();
- assert.isTrue(redirectStub.calledOnce);
- assert.equal(redirectStub.lastCall.args[0], '/settings/#Agreements');
+ test('AGREEMENTS', async () => {
+ // AGREEMENTS: /^\/settings\/agreements\/?/,
+ await checkRedirect('/settings/agreements', '/settings/#Agreements');
});
- test('handleNewAgreementsRoute', () => {
- router.handleNewAgreementsRoute();
- assert.isTrue(setStateStub.calledOnce);
- assert.equal(setStateStub.lastCall.args[0].view, GerritView.AGREEMENTS);
- });
-
- test('handleSettingsLegacyRoute', () => {
- const ctx = {...createPageContext(), params: {0: 'my-token'}};
- assertctxToParams(ctx, 'handleSettingsLegacyRoute', {
- view: GerritView.SETTINGS,
- emailToken: 'my-token',
+ test('NEW_AGREEMENTS', async () => {
+ // NEW_AGREEMENTS: /^\/settings\/new-agreement\/?/,
+ await checkUrlToState('/settings/new-agreement', {
+ view: GerritView.AGREEMENTS,
+ });
+ await checkUrlToState('/settings/new-agreement/', {
+ view: GerritView.AGREEMENTS,
});
});
- test('handleSettingsLegacyRoute with +', () => {
- const ctx = {...createPageContext(), params: {0: 'my-token test'}};
- assertctxToParams(ctx, 'handleSettingsLegacyRoute', {
+ test('SETTINGS', async () => {
+ // SETTINGS: /^\/settings\/?/,
+ // SETTINGS_LEGACY: /^\/settings\/VE\/(\S+)/,
+ await checkUrlToState('/settings', {view: GerritView.SETTINGS});
+ await checkUrlToState('/settings/', {view: GerritView.SETTINGS});
+ await checkUrlToState('/settings/VE/asdf', {
view: GerritView.SETTINGS,
- emailToken: 'my-token+test',
+ emailToken: 'asdf',
});
- });
-
- test('handleSettingsRoute', () => {
- const ctx = createPageContext();
- assertctxToParams(ctx, 'handleSettingsRoute', {
+ await checkUrlToState('/settings/VE/asdf%2520qwer', {
view: GerritView.SETTINGS,
+ emailToken: 'asdf+qwer',
});
});
@@ -391,7 +408,7 @@
sinon.stub(page, 'exit').callsFake(onRegisteringExit);
sinon.stub(page, 'start');
sinon.stub(page, 'base');
- router.startRouter();
+ router._testOnly_startRouter();
router.handleDefaultRoute();
@@ -401,88 +418,62 @@
assert.isTrue(handlePassThroughRoute.calledOnce);
});
- test('handleImproperlyEncodedPlusRoute', () => {
- const params = {
- ...createPageContext(),
- canonicalPath: '/c/test/%20/42',
- params: {0: 'test', 1: '42'},
- };
- // Regression test for Issue 7100.
- router.handleImproperlyEncodedPlusRoute(params);
- assert.isTrue(redirectStub.calledOnce);
- assert.equal(redirectStub.lastCall.args[0], '/c/test/+/42');
-
- sinon.stub(router, 'getHashFromCanonicalPath').returns('foo');
- router.handleImproperlyEncodedPlusRoute(params);
- assert.equal(redirectStub.lastCall.args[0], '/c/test/+/42#foo');
+ test('IMPROPERLY_ENCODED_PLUS', async () => {
+ // IMPROPERLY_ENCODED_PLUS: /^\/c\/(.+)\/ \/(.+)$/,
+ await checkRedirect('/c/repo/ /42', '/c/repo/+/42');
+ await checkRedirect('/c/repo/%20/42', '/c/repo/+/42');
+ await checkRedirect('/c/repo/ /42#foo', '/c/repo/+/42#foo');
});
- test('handleQueryRoute', () => {
- const ctx: PageContext = {
- ...createPageContext(),
- params: {0: 'project:foo/bar/baz'},
- };
- assertctxToParams(ctx, 'handleQueryRoute', {
- view: GerritView.SEARCH,
+ test('QUERY', async () => {
+ // QUERY: /^\/q\/([^,]+)(,(\d+))?$/,
+ await checkUrlToState('/q/asdf', {
+ ...createSearchViewState(),
+ query: 'asdf',
+ });
+ await checkUrlToState('/q/project:foo/bar/baz', {
+ ...createSearchViewState(),
query: 'project:foo/bar/baz',
- offset: undefined,
- } as AppElementParams);
-
- ctx.params[1] = '123';
- ctx.params[2] = '123';
- assertctxToParams(ctx, 'handleQueryRoute', {
- view: GerritView.SEARCH,
- query: 'project:foo/bar/baz',
+ });
+ await checkUrlToState('/q/asdf,123', {
+ ...createSearchViewState(),
+ query: 'asdf',
offset: '123',
- } as AppElementParams);
+ });
});
- test('handleQueryLegacySuffixRoute', () => {
- const params = {...createPageContext(), path: '/q/foo+bar,n,z'};
- router.handleQueryLegacySuffixRoute(params);
- assert.isTrue(redirectStub.calledOnce);
- assert.equal(redirectStub.lastCall.args[0], '/q/foo+bar');
+ test('QUERY_LEGACY_SUFFIX', async () => {
+ // QUERY_LEGACY_SUFFIX: /^\/q\/.+,n,z$/,
+ await checkRedirect('/q/foo+bar,n,z', '/q/foo+bar');
});
- test('handleChangeIdQueryRoute', () => {
- const ctx = {
- ...createPageContext(),
- params: {0: 'I0123456789abcdef0123456789abcdef01234567'},
- };
- assertctxToParams(ctx, 'handleChangeIdQueryRoute', {
- view: GerritView.SEARCH,
+ test('CHANGE_ID_QUERY', async () => {
+ // CHANGE_ID_QUERY: /^\/id\/(I[0-9a-f]{40})$/,
+ await checkUrlToState('/id/I0123456789abcdef0123456789abcdef01234567', {
+ ...createSearchViewState(),
query: 'I0123456789abcdef0123456789abcdef01234567',
- offset: undefined,
- } as AppElementParams);
- });
-
- suite('handleRegisterRoute', () => {
- test('happy path', () => {
- const ctx = {...createPageContext(), params: {0: '/foo/bar'}};
- router.handleRegisterRoute(ctx);
- assert.isTrue(redirectStub.calledWithExactly('/foo/bar'));
- assert.isTrue(setStateStub.calledOnce);
- assert.isTrue(setStateStub.lastCall.args[0].justRegistered);
- });
-
- test('no param', () => {
- const ctx = createPageContext();
- router.handleRegisterRoute(ctx);
- assert.isTrue(redirectStub.calledWithExactly('/'));
- assert.isTrue(setStateStub.calledOnce);
- assert.isTrue(setStateStub.lastCall.args[0].justRegistered);
- });
-
- test('prevent redirect', () => {
- const ctx = {...createPageContext(), params: {0: '/register'}};
- router.handleRegisterRoute(ctx);
- assert.isTrue(redirectStub.calledWithExactly('/'));
- assert.isTrue(setStateStub.calledOnce);
- assert.isTrue(setStateStub.lastCall.args[0].justRegistered);
});
});
- suite('handleRootRoute', () => {
+ test('REGISTER', async () => {
+ // REGISTER: /^\/register(\/.*)?$/,
+ await checkUrlToState('/register/foo/bar', {
+ justRegistered: true,
+ });
+ assert.isTrue(redirectStub.calledWithExactly('/foo/bar'));
+
+ await checkUrlToState('/register', {
+ justRegistered: true,
+ });
+ assert.isTrue(redirectStub.calledWithExactly('/'));
+
+ await checkUrlToState('/register/register', {
+ justRegistered: true,
+ });
+ assert.isTrue(redirectStub.calledWithExactly('/'));
+ });
+
+ suite('ROOT', () => {
test('closes for closeAfterLogin', () => {
const ctx = {...createPageContext(), querystring: 'closeAfterLogin'};
const closeStub = sinon.stub(window, 'close');
@@ -492,268 +483,116 @@
assert.isFalse(redirectStub.called);
});
- test('redirects to dashboard if logged in', () => {
- const ctx = {...createPageContext(), canonicalPath: '/', path: '/'};
- const result = router.handleRootRoute(ctx);
- assert.isOk(result);
- return result!.then(() => {
- assert.isTrue(redirectStub.calledWithExactly('/dashboard/self'));
- });
+ test('ROOT logged in', async () => {
+ stubRestApi('getLoggedIn').resolves(true);
+ await checkRedirect('/', '/dashboard/self');
});
- test('redirects to open changes if not logged in', () => {
- stubRestApi('getLoggedIn').returns(Promise.resolve(false));
- const ctx = {...createPageContext(), canonicalPath: '/', path: '/'};
- const result = router.handleRootRoute(ctx);
- assert.isOk(result);
- return result!.then(() => {
- assert.isTrue(
- redirectStub.calledWithExactly('/q/status:open+-is:wip')
- );
- });
+ test('ROOT not logged in', async () => {
+ stubRestApi('getLoggedIn').resolves(false);
+ await checkRedirect('/', '/q/status:open+-is:wip');
});
- suite('GWT hash-path URLs', () => {
- test('redirects hash-path URLs', () => {
- const ctx = {
- ...createPageContext(),
- canonicalPath: '/#/foo/bar/baz',
- hash: '/foo/bar/baz',
- };
- const result = router.handleRootRoute(ctx);
- assert.isNotOk(result);
- assert.isTrue(redirectStub.called);
- assert.isTrue(redirectStub.calledWithExactly('/foo/bar/baz'));
+ suite('ROOT GWT hash-path URLs', () => {
+ test('ROOT hash-path URLs', async () => {
+ await checkRedirect('/#/foo/bar/baz', '/foo/bar/baz');
});
- test('redirects hash-path URLs w/o leading slash', () => {
- const ctx = {
- ...createPageContext(),
- canonicalPath: '/#foo/bar/baz',
- hash: 'foo/bar/baz',
- };
- const result = router.handleRootRoute(ctx);
- assert.isNotOk(result);
- assert.isTrue(redirectStub.called);
- assert.isTrue(redirectStub.calledWithExactly('/foo/bar/baz'));
+ test('ROOT hash-path URLs w/o leading slash', async () => {
+ await checkRedirect('/#foo/bar/baz', '/foo/bar/baz');
});
- test('normalizes "/ /" in hash to "/+/"', () => {
- const ctx = {
- ...createPageContext(),
- canonicalPath: '/#/foo/bar/+/123/4',
- hash: '/foo/bar/ /123/4',
- };
- const result = router.handleRootRoute(ctx);
- assert.isNotOk(result);
- assert.isTrue(redirectStub.called);
- assert.isTrue(redirectStub.calledWithExactly('/foo/bar/+/123/4'));
+ test('ROOT normalizes "/ /" in hash to "/+/"', async () => {
+ await checkRedirect('/#/foo/bar/+/123/4', '/foo/bar/+/123/4');
});
- test('prepends baseurl to hash-path', () => {
- const ctx = {
- ...createPageContext(),
- canonicalPath: '/#/foo/bar',
- hash: '/foo/bar',
- };
+ test('ROOT prepends baseurl to hash-path', async () => {
stubBaseUrl('/baz');
- const result = router.handleRootRoute(ctx);
- assert.isNotOk(result);
- assert.isTrue(redirectStub.called);
- assert.isTrue(redirectStub.calledWithExactly('/baz/foo/bar'));
+ await checkRedirect('/#/foo/bar', '/baz/foo/bar');
});
- test('normalizes /VE/ settings hash-paths', () => {
- const ctx = {
- ...createPageContext(),
- canonicalPath: '/#/VE/foo/bar',
- hash: '/VE/foo/bar',
- };
- const result = router.handleRootRoute(ctx);
- assert.isNotOk(result);
- assert.isTrue(redirectStub.called);
- assert.isTrue(redirectStub.calledWithExactly('/settings/VE/foo/bar'));
+ test('ROOT normalizes /VE/ settings hash-paths', async () => {
+ await checkRedirect('/#/VE/foo/bar', '/settings/VE/foo/bar');
});
- test('does not drop "inner hashes"', () => {
- const ctx = {
- ...createPageContext(),
- canonicalPath: '/#/foo/bar#baz',
- hash: '/foo/bar',
- };
- const result = router.handleRootRoute(ctx);
- assert.isNotOk(result);
- assert.isTrue(redirectStub.called);
- assert.isTrue(redirectStub.calledWithExactly('/foo/bar#baz'));
+ test('ROOT does not drop "inner hashes"', async () => {
+ await checkRedirect('/#/foo/bar#baz', '/foo/bar#baz');
});
});
});
- suite('handleDashboardRoute', () => {
- let redirectToLoginStub: sinon.SinonStub;
-
- setup(() => {
- redirectToLoginStub = sinon.stub(router, 'redirectToLogin');
+ suite('DASHBOARD', () => {
+ test('DASHBOARD own dashboard but signed out redirects to login', async () => {
+ stubRestApi('getLoggedIn').resolves(false);
+ await checkRedirectToLogin('/dashboard/seLF', '/dashboard/seLF');
});
- test('own dashboard but signed out redirects to login', () => {
- stubRestApi('getLoggedIn').returns(Promise.resolve(false));
- const ctx = {
- ...createPageContext(),
- canonicalPath: '/dashboard/',
- params: {0: 'seLF'},
- };
- return router.handleDashboardRoute(ctx).then(() => {
- assert.isTrue(redirectToLoginStub.calledOnce);
- assert.isFalse(redirectStub.called);
- assert.isFalse(setStateStub.called);
- });
+ test('DASHBOARD non-self dashboard but signed out redirects', async () => {
+ stubRestApi('getLoggedIn').resolves(false);
+ await checkRedirect('/dashboard/foo', '/q/owner:foo');
});
- test('non-self dashboard but signed out does not redirect', () => {
- stubRestApi('getLoggedIn').returns(Promise.resolve(false));
- const ctx = {
- ...createPageContext(),
- canonicalPath: '/dashboard/',
- params: {0: 'foo'},
- };
- return router.handleDashboardRoute(ctx).then(() => {
- assert.isFalse(redirectToLoginStub.called);
- assert.isFalse(setStateStub.called);
- assert.isTrue(redirectStub.calledOnce);
- assert.equal(redirectStub.lastCall.args[0], '/q/owner:foo');
- });
- });
-
- test('dashboard while signed in sets params', () => {
- const ctx = {
- ...createPageContext(),
- canonicalPath: '/dashboard/',
- params: {0: 'foo'},
- };
- return router.handleDashboardRoute(ctx).then(() => {
- assert.isFalse(redirectToLoginStub.called);
- assert.isFalse(redirectStub.called);
- assert.isTrue(setStateStub.calledOnce);
- assert.deepEqual(setStateStub.lastCall.args[0], {
- view: GerritView.DASHBOARD,
- user: 'foo',
- });
+ test('DASHBOARD', async () => {
+ // DASHBOARD: /^\/dashboard\/(.+)$/,
+ await checkUrlToState('/dashboard/foo', {
+ ...createDashboardViewState(),
+ user: 'foo',
});
});
});
- suite('handleCustomDashboardRoute', () => {
- let redirectToLoginStub: sinon.SinonStub;
-
- setup(() => {
- redirectToLoginStub = sinon.stub(router, 'redirectToLogin');
+ suite('CUSTOM_DASHBOARD', () => {
+ test('CUSTOM_DASHBOARD no user specified', async () => {
+ await checkRedirect('/dashboard/', '/dashboard/self');
});
- test('no user specified', () => {
- const ctx: PageContext = {
- ...createPageContext(),
- canonicalPath: '/dashboard/',
- params: {0: ''},
- querystring: '',
- };
- return router.handleCustomDashboardRoute(ctx).then(() => {
- assert.isFalse(setStateStub.called);
- assert.isTrue(redirectStub.called);
- assert.equal(redirectStub.lastCall.args[0], '/dashboard/self');
+ test('CUSTOM_DASHBOARD', async () => {
+ // CUSTOM_DASHBOARD: /^\/dashboard\/?$/,
+ await checkUrlToState('/dashboard?title=Custom Dashboard&a=b&d=e', {
+ ...createDashboardViewState(),
+ sections: [
+ {name: 'a', query: 'b'},
+ {name: 'd', query: 'e'},
+ ],
+ title: 'Custom Dashboard',
});
- });
-
- test('custom dashboard without title', () => {
- const ctx: PageContext = {
- ...createPageContext(),
- canonicalPath: '/dashboard/',
- params: {0: ''},
- querystring: '?a=b&c&d=e',
- };
- return router.handleCustomDashboardRoute(ctx).then(() => {
- assert.isFalse(redirectStub.called);
- assert.isTrue(setStateStub.calledOnce);
- assert.deepEqual(setStateStub.lastCall.args[0], {
- view: GerritView.DASHBOARD,
- user: 'self',
- sections: [
- {name: 'a', query: 'b'},
- {name: 'd', query: 'e'},
- ],
- title: 'Custom Dashboard',
- });
- });
- });
-
- test('custom dashboard with title', () => {
- const ctx: PageContext = {
- ...createPageContext(),
- canonicalPath: '/dashboard/',
- params: {0: ''},
- querystring: '?a=b&c&d=&=e&title=t',
- };
- return router.handleCustomDashboardRoute(ctx).then(() => {
- assert.isFalse(redirectToLoginStub.called);
- assert.isFalse(redirectStub.called);
- assert.isTrue(setStateStub.calledOnce);
- assert.deepEqual(setStateStub.lastCall.args[0], {
- view: GerritView.DASHBOARD,
- user: 'self',
- sections: [{name: 'a', query: 'b'}],
- title: 't',
- });
- });
- });
-
- test('custom dashboard with foreach', () => {
- const ctx: PageContext = {
- ...createPageContext(),
- canonicalPath: '/dashboard/',
- params: {0: ''},
- querystring: '?a=b&c&d=&=e&foreach=is:open',
- };
- return router.handleCustomDashboardRoute(ctx).then(() => {
- assert.isFalse(redirectToLoginStub.called);
- assert.isFalse(redirectStub.called);
- assert.isTrue(setStateStub.calledOnce);
- assert.deepEqual(setStateStub.lastCall.args[0], {
- view: GerritView.DASHBOARD,
- user: 'self',
- sections: [{name: 'a', query: 'is:open b'}],
- title: 'Custom Dashboard',
- });
+ await checkUrlToState('/dashboard?a=b&c&d=&=e&foreach=is:open', {
+ ...createDashboardViewState(),
+ sections: [{name: 'a', query: 'is:open b'}],
+ title: 'Custom Dashboard',
});
});
});
suite('group routes', () => {
- test('handleGroupInfoRoute', () => {
- const ctx = {...createPageContext(), params: {0: '1234'}};
- router.handleGroupInfoRoute(ctx);
- assert.isTrue(redirectStub.calledOnce);
- assert.equal(redirectStub.lastCall.args[0], '/admin/groups/1234');
+ test('GROUP_INFO', async () => {
+ // GROUP_INFO: /^\/admin\/groups\/(?:uuid-)?(.+),info$/,
+ await checkRedirect('/admin/groups/1234,info', '/admin/groups/1234');
});
- test('handleGroupAuditLogRoute', () => {
- const ctx = {...createPageContext(), params: {0: '1234'}};
- assertctxToParams(ctx, 'handleGroupAuditLogRoute', {
- view: GerritView.GROUP,
+ test('GROUP_AUDIT_LOG', async () => {
+ // GROUP_AUDIT_LOG: /^\/admin\/groups\/(?:uuid-)?(.+),audit-log$/,
+ await checkUrlToState('/admin/groups/1234,audit-log', {
+ ...createGroupViewState(),
detail: GroupDetailView.LOG,
- groupId: '1234' as GroupId,
+ groupId: '1234',
});
});
- test('handleGroupMembersRoute', () => {
- const ctx = {...createPageContext(), params: {0: '1234'}};
- assertctxToParams(ctx, 'handleGroupMembersRoute', {
- view: GerritView.GROUP,
+ test('GROUP_MEMBERS', async () => {
+ // GROUP_MEMBERS: /^\/admin\/groups\/(?:uuid-)?(.+),members$/,
+ await checkUrlToState('/admin/groups/1234,members', {
+ ...createGroupViewState(),
detail: GroupDetailView.MEMBERS,
- groupId: '1234' as GroupId,
+ groupId: '1234',
});
});
- test('list of groups', async () => {
+ test('GROUP_LIST_*', async () => {
+ // GROUP_LIST_OFFSET: /^\/admin\/groups(,(\d+))?(\/)?$/,
+ // GROUP_LIST_FILTER: '/admin/groups/q/filter::filter',
+ // GROUP_LIST_FILTER_OFFSET: '/admin/groups/q/filter::filter,:offset',
+
const defaultState: AdminViewState = {
view: GerritView.ADMIN,
adminView: AdminChildView.GROUPS,
@@ -804,417 +643,274 @@
await checkUrlNotMatched('/admin/groups/q/filter:asdf%2Fqwer,11');
});
- test('handleGroupRoute', () => {
- const ctx = {...createPageContext(), params: {0: '4321'}};
- assertctxToParams(ctx, 'handleGroupRoute', {
- view: GerritView.GROUP,
- groupId: '4321' as GroupId,
+ test('GROUP', async () => {
+ // GROUP: /^\/admin\/groups\/(?:uuid-)?([^,]+)$/,
+ await checkUrlToState('/admin/groups/4321', {
+ ...createGroupViewState(),
+ groupId: '4321',
});
});
});
- suite('repo routes', () => {
- test('handleProjectsOldRoute', () => {
- const ctx = {...createPageContext(), params: {}};
- router.handleProjectsOldRoute(ctx);
- assert.isTrue(redirectStub.calledOnce);
- assert.equal(redirectStub.lastCall.args[0], '/admin/repos/');
- });
-
- test('handleProjectsOldRoute test', () => {
- const ctx = {...createPageContext(), params: {1: 'test'}};
- router.handleProjectsOldRoute(ctx);
- assert.isTrue(redirectStub.calledOnce);
- assert.equal(redirectStub.lastCall.args[0], '/admin/repos/test');
- });
-
- test('handleProjectsOldRoute test,branches', () => {
- const ctx = {...createPageContext(), params: {1: 'test,branches'}};
- router.handleProjectsOldRoute(ctx);
- assert.isTrue(redirectStub.calledOnce);
- assert.equal(
- redirectStub.lastCall.args[0],
+ suite('REPO*', () => {
+ test('PROJECT_OLD', async () => {
+ // PROJECT_OLD: /^\/admin\/(projects)\/?(.+)?$/,
+ await checkRedirect('/admin/projects/', '/admin/repos/');
+ await checkRedirect('/admin/projects/test', '/admin/repos/test');
+ await checkRedirect(
+ '/admin/projects/test,branches',
'/admin/repos/test,branches'
);
});
- test('handleRepoRoute', () => {
- const ctx = {...createPageContext(), path: '/admin/repos/test'};
- router.handleRepoRoute(ctx);
- assert.isTrue(redirectStub.calledOnce);
- assert.equal(
- redirectStub.lastCall.args[0],
- '/admin/repos/test,general'
- );
+ test('REPO', async () => {
+ // REPO: /^\/admin\/repos\/([^,]+)$/,
+ await checkRedirect('/admin/repos/test', '/admin/repos/test,general');
});
- test('handleRepoGeneralRoute', () => {
- const ctx = {...createPageContext(), params: {0: '4321'}};
- assertctxToParams(ctx, 'handleRepoGeneralRoute', {
- view: GerritView.REPO,
+ test('REPO_GENERAL', async () => {
+ // REPO_GENERAL: /^\/admin\/repos\/(.+),general$/,
+ await checkUrlToState('/admin/repos/4321,general', {
+ ...createRepoViewState(),
detail: RepoDetailView.GENERAL,
repo: '4321' as RepoName,
});
});
- test('handleRepoCommandsRoute', () => {
- const ctx = {...createPageContext(), params: {0: '4321'}};
- assertctxToParams(ctx, 'handleRepoCommandsRoute', {
- view: GerritView.REPO,
+ test('REPO_COMMANDS', async () => {
+ // REPO_COMMANDS: /^\/admin\/repos\/(.+),commands$/,
+ await checkUrlToState('/admin/repos/4321,commands', {
+ ...createRepoViewState(),
detail: RepoDetailView.COMMANDS,
repo: '4321' as RepoName,
});
});
- test('handleRepoAccessRoute', () => {
- const ctx = {...createPageContext(), params: {0: '4321'}};
- assertctxToParams(ctx, 'handleRepoAccessRoute', {
- view: GerritView.REPO,
+ test('REPO_ACCESS', async () => {
+ // REPO_ACCESS: /^\/admin\/repos\/(.+),access$/,
+ await checkUrlToState('/admin/repos/4321,access', {
+ ...createRepoViewState(),
detail: RepoDetailView.ACCESS,
repo: '4321' as RepoName,
});
});
- suite('branch list routes', () => {
- test('handleBranchListOffsetRoute', () => {
- const ctx: PageContext = {
- ...createPageContext(),
- params: {0: '4321'},
- };
- assertctxToParams(ctx, 'handleBranchListOffsetRoute', {
- view: GerritView.REPO,
- detail: RepoDetailView.BRANCHES,
+ suite('BRANCH_LIST_*', () => {
+ test('BRANCH_LIST_OFFSET', async () => {
+ // BRANCH_LIST_OFFSET: /^\/admin\/repos\/(.+),branches(,(.+))?$/,
+ await checkUrlToState('/admin/repos/4321,branches', {
+ ...createRepoBranchesViewState(),
repo: '4321' as RepoName,
- offset: 0,
- filter: null,
});
-
- ctx.params[2] = '42';
- assertctxToParams(ctx, 'handleBranchListOffsetRoute', {
- view: GerritView.REPO,
- detail: RepoDetailView.BRANCHES,
+ await checkUrlToState('/admin/repos/4321,branches,42', {
+ ...createRepoBranchesViewState(),
repo: '4321' as RepoName,
offset: '42',
- filter: null,
});
});
- test('handleBranchListFilterOffsetRoute', () => {
- const ctx = {
- ...createPageContext(),
- params: {repo: '4321', filter: 'foo', offset: '42'},
- };
- assertctxToParams(ctx, 'handleBranchListFilterOffsetRoute', {
- view: GerritView.REPO,
- detail: RepoDetailView.BRANCHES,
+ test('BRANCH_LIST_FILTER_OFFSET', async () => {
+ // BRANCH_LIST_FILTER_OFFSET: '/admin/repos/:repo,branches/q/filter::filter,:offset',
+ await checkUrlToState('/admin/repos/4321,branches/q/filter:foo,42', {
+ ...createRepoBranchesViewState(),
repo: '4321' as RepoName,
offset: '42',
filter: 'foo',
});
});
- test('handleBranchListFilterRoute', () => {
- const ctx = {
- ...createPageContext(),
- params: {repo: '4321', filter: 'foo'},
- };
- assertctxToParams(ctx, 'handleBranchListFilterRoute', {
- view: GerritView.REPO,
- detail: RepoDetailView.BRANCHES,
+ test('BRANCH_LIST_FILTER', async () => {
+ // BRANCH_LIST_FILTER: '/admin/repos/:repo,branches/q/filter::filter',
+ await checkUrlToState('/admin/repos/4321,branches/q/filter:foo', {
+ ...createRepoBranchesViewState(),
repo: '4321' as RepoName,
filter: 'foo',
});
});
});
- suite('tag list routes', () => {
- test('handleTagListOffsetRoute', () => {
- const ctx = {...createPageContext(), params: {0: '4321'}};
- assertctxToParams(ctx, 'handleTagListOffsetRoute', {
- view: GerritView.REPO,
- detail: RepoDetailView.TAGS,
+ suite('TAG_LIST_*', () => {
+ test('TAG_LIST_OFFSET', async () => {
+ // TAG_LIST_OFFSET: /^\/admin\/repos\/(.+),tags(,(.+))?$/,
+ await checkUrlToState('/admin/repos/4321,tags', {
+ ...createRepoTagsViewState(),
repo: '4321' as RepoName,
- offset: 0,
- filter: null,
+ });
+ await checkUrlToState('/admin/repos/4321,tags,42', {
+ ...createRepoTagsViewState(),
+ repo: '4321' as RepoName,
+ offset: '42',
});
});
- test('handleTagListFilterOffsetRoute', () => {
- const ctx = {
- ...createPageContext(),
- params: {repo: '4321', filter: 'foo', offset: '42'},
- };
- assertctxToParams(ctx, 'handleTagListFilterOffsetRoute', {
- view: GerritView.REPO,
- detail: RepoDetailView.TAGS,
+ test('TAG_LIST_FILTER_OFFSET', async () => {
+ // TAG_LIST_FILTER_OFFSET: '/admin/repos/:repo,tags/q/filter::filter,:offset',
+ await checkUrlToState('/admin/repos/4321,tags/q/filter:foo,42', {
+ ...createRepoTagsViewState(),
repo: '4321' as RepoName,
offset: '42',
filter: 'foo',
});
});
- test('handleTagListFilterRoute', () => {
- const ctx: PageContext = {
- ...createPageContext(),
- params: {repo: '4321'},
- };
- assertctxToParams(ctx, 'handleTagListFilterRoute', {
- view: GerritView.REPO,
- detail: RepoDetailView.TAGS,
- repo: '4321' as RepoName,
- filter: null,
- });
-
- ctx.params.filter = 'foo';
- assertctxToParams(ctx, 'handleTagListFilterRoute', {
- view: GerritView.REPO,
- detail: RepoDetailView.TAGS,
+ test('TAG_LIST_FILTER', async () => {
+ // TAG_LIST_FILTER: '/admin/repos/:repo,tags/q/filter::filter',
+ await checkUrlToState('/admin/repos/4321,tags/q/filter:foo', {
+ ...createRepoTagsViewState(),
repo: '4321' as RepoName,
filter: 'foo',
});
});
});
- suite('repo list routes', () => {
- test('handleRepoListOffsetRoute', () => {
- const ctx = createPageContext();
- assertctxToParams(ctx, 'handleRepoListOffsetRoute', {
- view: GerritView.ADMIN,
- adminView: AdminChildView.REPOS,
- offset: 0,
- filter: null,
- openCreateModal: false,
+ suite('REPO_LIST_*', () => {
+ test('REPO_LIST_OFFSET', async () => {
+ // REPO_LIST_OFFSET: /^\/admin\/repos(,(\d+))?(\/)?$/,
+ await checkUrlToState('/admin/repos', {
+ ...createAdminReposViewState(),
});
-
- ctx.params[1] = '42';
- assertctxToParams(ctx, 'handleRepoListOffsetRoute', {
- view: GerritView.ADMIN,
- adminView: AdminChildView.REPOS,
+ await checkUrlToState('/admin/repos,42', {
+ ...createAdminReposViewState(),
offset: '42',
- filter: null,
- openCreateModal: false,
});
-
- ctx.hash = 'create';
- assertctxToParams(ctx, 'handleRepoListOffsetRoute', {
- view: GerritView.ADMIN,
- adminView: AdminChildView.REPOS,
+ await checkUrlToState('/admin/repos,42#create', {
+ ...createAdminReposViewState(),
offset: '42',
- filter: null,
openCreateModal: true,
});
});
- test('handleRepoListFilterOffsetRoute', () => {
- const ctx = {
- ...createPageContext(),
- params: {filter: 'foo', offset: '42'},
- };
- assertctxToParams(ctx, 'handleRepoListFilterOffsetRoute', {
- view: GerritView.ADMIN,
- adminView: AdminChildView.REPOS,
+ test('REPO_LIST_FILTER_OFFSET', async () => {
+ // REPO_LIST_FILTER_OFFSET: '/admin/repos/q/filter::filter,:offset',
+ await checkUrlToState('/admin/repos/q/filter:foo,42', {
+ ...createAdminReposViewState(),
offset: '42',
filter: 'foo',
});
});
- test('handleRepoListFilterRoute', () => {
- const ctx = createPageContext();
- assertctxToParams(ctx, 'handleRepoListFilterRoute', {
- view: GerritView.ADMIN,
- adminView: AdminChildView.REPOS,
- filter: null,
- });
-
- ctx.params.filter = 'foo';
- assertctxToParams(ctx, 'handleRepoListFilterRoute', {
- view: GerritView.ADMIN,
- adminView: AdminChildView.REPOS,
+ test('REPO_LIST_FILTER', async () => {
+ // REPO_LIST_FILTER: '/admin/repos/q/filter::filter',
+ await checkUrlToState('/admin/repos/q/filter:foo', {
+ ...createAdminReposViewState(),
filter: 'foo',
});
});
});
});
- suite('plugin routes', () => {
- test('handlePluginListOffsetRoute', () => {
- const ctx = createPageContext();
- assertctxToParams(ctx, 'handlePluginListOffsetRoute', {
- view: GerritView.ADMIN,
- adminView: AdminChildView.PLUGINS,
- offset: 0,
- filter: null,
+ suite('PLUGIN_LIST_*', () => {
+ test('PLUGIN_LIST_OFFSET', async () => {
+ // PLUGIN_LIST_OFFSET: /^\/admin\/plugins(,(\d+))?(\/)?$/,
+ await checkUrlToState('/admin/plugins', {
+ ...createAdminPluginsViewState(),
});
-
- ctx.params[1] = '42';
- assertctxToParams(ctx, 'handlePluginListOffsetRoute', {
- view: GerritView.ADMIN,
- adminView: AdminChildView.PLUGINS,
+ await checkUrlToState('/admin/plugins/', {
+ ...createAdminPluginsViewState(),
+ });
+ await checkUrlToState('/admin/plugins,42', {
+ ...createAdminPluginsViewState(),
offset: '42',
- filter: null,
});
});
- test('handlePluginListFilterOffsetRoute', () => {
- const ctx = {
- ...createPageContext(),
- params: {filter: 'foo', offset: '42'},
- };
- assertctxToParams(ctx, 'handlePluginListFilterOffsetRoute', {
- view: GerritView.ADMIN,
- adminView: AdminChildView.PLUGINS,
+ test('PLUGIN_LIST_FILTER_OFFSET', async () => {
+ // PLUGIN_LIST_FILTER_OFFSET: '/admin/plugins/q/filter::filter,:offset',
+ await checkUrlToState('/admin/plugins/q/filter:foo,42', {
+ ...createAdminPluginsViewState(),
offset: '42',
filter: 'foo',
});
});
- test('handlePluginListFilterRoute', () => {
- const ctx = createPageContext();
- assertctxToParams(ctx, 'handlePluginListFilterRoute', {
- view: GerritView.ADMIN,
- adminView: AdminChildView.PLUGINS,
- filter: null,
- });
-
- ctx.params.filter = 'foo';
- assertctxToParams(ctx, 'handlePluginListFilterRoute', {
- view: GerritView.ADMIN,
- adminView: AdminChildView.PLUGINS,
+ test('PLUGIN_LIST_FILTER', async () => {
+ // PLUGIN_LIST_FILTER: '/admin/plugins/q/filter::filter',
+ await checkUrlToState('/admin/plugins/q/filter:foo', {
+ ...createAdminPluginsViewState(),
filter: 'foo',
});
});
});
- suite('change/diff routes', () => {
- test('handleChangeNumberLegacyRoute', () => {
- const ctx = {...createPageContext(), params: {0: '12345'}};
- router.handleChangeNumberLegacyRoute(ctx);
- assert.isTrue(redirectStub.calledOnce);
- assert.isTrue(redirectStub.calledWithExactly('/c/12345'));
+ suite('CHANGE* / DIFF*', () => {
+ test('CHANGE_NUMBER_LEGACY', async () => {
+ // CHANGE_NUMBER_LEGACY: /^\/(\d+)\/?/,
+ await checkRedirect('/12345', '/c/12345');
});
- test('handleChangeLegacyRoute', async () => {
- stubRestApi('getFromProjectLookup').returns(
- Promise.resolve('project' as RepoName)
- );
- const ctx = {
- ...createPageContext(),
- params: {0: '1234', 1: 'comment/6789'},
- };
- router.handleChangeLegacyRoute(ctx);
- await waitEventLoop();
- assert.isTrue(
- redirectStub.calledWithExactly('/c/project/+/1234' + '/comment/6789')
+ test('CHANGE_LEGACY', async () => {
+ // CHANGE_LEGACY: /^\/c\/(\d+)\/?(.*)$/,
+ stubRestApi('getFromProjectLookup').resolves('project' as RepoName);
+ await checkRedirect('/c/1234', '/c/project/+/1234/');
+ await checkRedirect(
+ '/c/1234/comment/6789',
+ '/c/project/+/1234/comment/6789'
);
});
- test('handleLegacyLinenum w/ @321', () => {
- const ctx = {...createPageContext(), path: '/c/1234/3..8/foo/bar@321'};
- router.handleLegacyLinenum(ctx);
- assert.isTrue(redirectStub.calledOnce);
- assert.isTrue(
- redirectStub.calledWithExactly('/c/1234/3..8/foo/bar#321')
+ test('DIFF_LEGACY_LINENUM', async () => {
+ await checkRedirect(
+ '/c/1234/3..8/foo/bar@321',
+ '/c/1234/3..8/foo/bar#321'
+ );
+ await checkRedirect(
+ '/c/1234/3..8/foo/bar@b321',
+ '/c/1234/3..8/foo/bar#b321'
);
});
- test('handleLegacyLinenum w/ @b123', () => {
- const ctx = {...createPageContext(), path: '/c/1234/3..8/foo/bar@b123'};
- router.handleLegacyLinenum(ctx);
- assert.isTrue(redirectStub.calledOnce);
- assert.isTrue(
- redirectStub.calledWithExactly('/c/1234/3..8/foo/bar#b123')
- );
- });
-
- suite('handleChangeRoute', () => {
- function makeParams(_path: string, _hash: string): PageContext {
- return {
- ...createPageContext(),
- params: {
- 0: 'foo/bar', // 0 Project
- 1: '1234', // 1 Change number
- 2: '', // 2 Unused
- 3: '', // 3 Unused
- 4: '4', // 4 Base patch number
- 5: '', // 5 Unused
- 6: '7', // 6 Patch number
- },
- };
- }
-
- setup(() => {
- stubRestApi('setInProjectLookup');
+ test('CHANGE', async () => {
+ // CHANGE: /^\/c\/(.+)\/\+\/(\d+)(\/?((-?\d+|edit)(\.\.(\d+|edit))?))?\/?$/,
+ await checkUrlToState('/c/test-project/+/42', {
+ ...createChangeViewState(),
+ basePatchNum: undefined,
+ patchNum: undefined,
});
-
- test('change view', () => {
- const ctx = makeParams('', '');
- assertctxToParams(ctx, 'handleChangeRoute', {
- view: GerritView.CHANGE,
- childView: ChangeChildView.OVERVIEW,
- repo: 'foo/bar' as RepoName,
- changeNum: 1234 as NumericChangeId,
- basePatchNum: 4 as BasePatchSetNum,
- patchNum: 7 as RevisionPatchSetNum,
- });
- assert.isFalse(redirectStub.called);
+ await checkUrlToState('/c/test-project/+/42/7', {
+ ...createChangeViewState(),
+ basePatchNum: PARENT,
+ patchNum: 7,
});
-
- test('params', () => {
- const ctx = makeParams('', '');
- const queryMap = new URLSearchParams();
- queryMap.set('tab', 'checks');
- queryMap.set('filter', 'fff');
- queryMap.set('select', 'sss');
- queryMap.set('attempt', '1');
- queryMap.set('checksRunsSelected', 'asdf,qwer');
- queryMap.set('checksResultsFilter', 'asdf.*qwer');
- ctx.querystring = queryMap.toString();
- assertctxToParams(ctx, 'handleChangeRoute', {
- view: GerritView.CHANGE,
- childView: ChangeChildView.OVERVIEW,
- repo: 'foo/bar' as RepoName,
- changeNum: 1234 as NumericChangeId,
- basePatchNum: 4 as BasePatchSetNum,
- patchNum: 7 as RevisionPatchSetNum,
+ await checkUrlToState('/c/test-project/+/42/4..7', {
+ ...createChangeViewState(),
+ basePatchNum: 4,
+ patchNum: 7,
+ });
+ await checkUrlToState(
+ '/c/test-project/+/42/4..7?tab=checks&filter=fff&attempt=1&checksRunsSelected=asdf,qwer&checksResultsFilter=asdf.*qwer',
+ {
+ ...createChangeViewState(),
+ basePatchNum: 4,
+ patchNum: 7,
attempt: 1,
filter: 'fff',
tab: 'checks',
checksRunsSelected: new Set(['asdf', 'qwer']),
checksResultsFilter: 'asdf.*qwer',
- });
- });
+ }
+ );
+ });
+
+ test('COMMENTS_TAB', async () => {
+ // COMMENTS_TAB: /^\/c\/(.+)\/\+\/(\d+)\/comments(?:\/)?(\w+)?\/?$/,
+ await checkUrlToState(
+ '/c/gerrit/+/264833/comments/00049681_f34fd6a9/',
+ {
+ ...createChangeViewState(),
+ repo: 'gerrit' as RepoName,
+ changeNum: 264833 as NumericChangeId,
+ commentId: '00049681_f34fd6a9' as UrlEncodedCommentId,
+ view: GerritView.CHANGE,
+ childView: ChangeChildView.OVERVIEW,
+ }
+ );
});
suite('handleDiffRoute', () => {
- function makeParams(path: string, hash: string): PageContext {
- return {
- ...createPageContext(),
- hash,
- params: {
- 0: 'foo/bar', // 0 Project
- 1: '1234', // 1 Change number
- 2: '', // 2 Unused
- 3: '', // 3 Unused
- 4: '4', // 4 Base patch number
- 5: '', // 5 Unused
- 6: '7', // 6 Patch number
- 7: '', // 7 Unused,
- 8: path, // 8 Diff path
- },
- };
- }
-
- setup(() => {
- stubRestApi('setInProjectLookup');
- });
-
- test('diff view', () => {
- const ctx = makeParams('foo/bar/baz', 'b44');
- assertctxToParams(ctx, 'handleDiffRoute', {
- view: GerritView.CHANGE,
- childView: ChangeChildView.DIFF,
- repo: 'foo/bar' as RepoName,
- changeNum: 1234 as NumericChangeId,
+ test('DIFF', async () => {
+ // DIFF: /^\/c\/(.+)\/\+\/(\d+)(\/((-?\d+|edit)(\.\.(\d+|edit))?(\/(.+))))\/?$/,
+ await checkUrlToState('/c/test-project/+/42/4..7/foo/bar/baz#b44', {
+ ...createDiffViewState(),
basePatchNum: 4 as BasePatchSetNum,
patchNum: 7 as RevisionPatchSetNum,
diffView: {
@@ -1223,10 +919,9 @@
leftSide: true,
},
});
- assert.isFalse(redirectStub.called);
});
- test('comment route base..1', async () => {
+ test('COMMENT base..1', async () => {
const change: ParsedChangeInfo = createParsedChange();
const repo = change.project;
const changeNum = change._number;
@@ -1238,19 +933,13 @@
filepath: [{...createComment(), id, patch_set: ps, line}],
});
- const url = `/c/${repo}/+/${changeNum}/comment/${id}/`;
- const groups = url.match(_testOnly_RoutePattern.COMMENT);
- assert.deepEqual(groups!.slice(1), [repo, `${changeNum}`, id]);
-
- await router.handleCommentRoute({params: groups!.slice(1)} as any);
- assert.isTrue(redirectStub.calledOnce);
- assert.equal(
- redirectStub.lastCall.args[0],
+ await checkRedirect(
+ `/c/${repo}/+/${changeNum}/comment/${id}/`,
`/c/${repo}/+/${changeNum}/${ps}/filepath#${line}`
);
});
- test('comment route 1..2', async () => {
+ test('COMMENT 1..2', async () => {
const change: ParsedChangeInfo = {
...createParsedChange(),
revisions: {
@@ -1270,16 +959,11 @@
});
const diffStub = stubRestApi('getDiff');
- const url = `/c/${repo}/+/${changeNum}/comment/${id}/`;
- const groups = url.match(_testOnly_RoutePattern.COMMENT);
-
// If getDiff() returns a diff with changes, then we will compare
// the patchset of the comment (1) against latest (2).
diffStub.onFirstCall().resolves(createDiff());
- await router.handleCommentRoute({params: groups!.slice(1)} as any);
- assert.isTrue(redirectStub.calledOnce);
- assert.equal(
- redirectStub.lastCall.args[0],
+ await checkRedirect(
+ `/c/${repo}/+/${changeNum}/comment/${id}/`,
`/c/${repo}/+/${changeNum}/${ps}..2/filepath#b${line}`
);
@@ -1289,122 +973,56 @@
...createDiff(),
content: [],
});
- await router.handleCommentRoute({params: groups!.slice(1)} as any);
- assert.isTrue(redirectStub.calledTwice);
- assert.equal(
- redirectStub.lastCall.args[0],
+ await checkRedirect(
+ `/c/${repo}/+/${changeNum}/comment/${id}/`,
`/c/${repo}/+/${changeNum}/${ps}/filepath#${line}`
);
});
-
- test('comments route', () => {
- const url = '/c/gerrit/+/264833/comments/00049681_f34fd6a9/';
- const groups = url.match(_testOnly_RoutePattern.COMMENTS_TAB);
- assert.deepEqual(groups!.slice(1), [
- 'gerrit', // project
- '264833', // changeNum
- '00049681_f34fd6a9', // commentId
- ]);
- assertctxToParams(
- {params: groups!.slice(1)} as any,
- 'handleCommentsRoute',
- {
- repo: 'gerrit' as RepoName,
- changeNum: 264833 as NumericChangeId,
- commentId: '00049681_f34fd6a9' as UrlEncodedCommentId,
- view: GerritView.CHANGE,
- childView: ChangeChildView.OVERVIEW,
- }
- );
- });
});
- test('handleDiffEditRoute', () => {
- stubRestApi('setInProjectLookup');
- const ctx = {
- ...createPageContext(),
- hash: '',
- params: {
- 0: 'foo/bar', // 0 Project
- 1: '1234', // 1 Change number
- 2: '3', // 2 Patch num
- 3: 'foo/bar/baz', // 3 File path
- },
- };
- const appParams: ChangeViewState = {
+ test('DIFF_EDIT', async () => {
+ // DIFF_EDIT: /^\/c\/(.+)\/\+\/(\d+)\/(\d+|edit)\/(.+),edit(#\d+)?$/,
+ await checkUrlToState('/c/foo/bar/+/1234/3/foo/bar/baz,edit', {
+ ...createEditViewState(),
repo: 'foo/bar' as RepoName,
changeNum: 1234 as NumericChangeId,
view: GerritView.CHANGE,
childView: ChangeChildView.EDIT,
patchNum: 3 as RevisionPatchSetNum,
editView: {path: 'foo/bar/baz', lineNum: 0},
- };
-
- router.handleDiffEditRoute(ctx);
- assert.isFalse(redirectStub.called);
- assert.deepEqual(setStateStub.lastCall.args[0], appParams);
- });
-
- test('handleDiffEditRoute with lineNum', () => {
- stubRestApi('setInProjectLookup');
- const ctx = {
- ...createPageContext(),
- hash: '4',
- params: {
- 0: 'foo/bar', // 0 Project
- 1: '1234', // 1 Change number
- 2: '3', // 2 Patch num
- 3: 'foo/bar/baz', // 3 File path
- },
- };
- const appParams: ChangeViewState = {
+ });
+ await checkUrlToState('/c/foo/bar/+/1234/3/foo/bar/baz,edit#4', {
+ ...createEditViewState(),
repo: 'foo/bar' as RepoName,
changeNum: 1234 as NumericChangeId,
view: GerritView.CHANGE,
childView: ChangeChildView.EDIT,
patchNum: 3 as RevisionPatchSetNum,
editView: {path: 'foo/bar/baz', lineNum: 4},
- };
-
- router.handleDiffEditRoute(ctx);
- assert.isFalse(redirectStub.called);
- assert.deepEqual(setStateStub.lastCall.args[0], appParams);
+ });
});
- test('handleChangeEditRoute', () => {
- stubRestApi('setInProjectLookup');
- const ctx = {
- ...createPageContext(),
- params: {
- 0: 'foo/bar', // 0 Project
- 1: '1234', // 1 Change number
- 2: '',
- 3: '3', // 3 Patch num
- },
- };
- const appParams: ChangeViewState = {
+ test('CHANGE_EDIT', async () => {
+ // CHANGE_EDIT: /^\/c\/(.+)\/\+\/(\d+)(\/(\d+))?,edit\/?$/,
+ await checkUrlToState('/c/foo/bar/+/1234/3,edit', {
+ ...createChangeViewState(),
repo: 'foo/bar' as RepoName,
changeNum: 1234 as NumericChangeId,
view: GerritView.CHANGE,
childView: ChangeChildView.OVERVIEW,
patchNum: 3 as RevisionPatchSetNum,
edit: true,
- };
-
- router.handleChangeEditRoute(ctx);
- assert.isFalse(redirectStub.called);
- assert.deepEqual(setStateStub.lastCall.args[0], appParams);
+ });
});
});
- test('handlePluginScreen', () => {
- const ctx = {...createPageContext(), params: {0: 'foo', 1: 'bar'}};
- assertctxToParams(ctx, 'handlePluginScreen', {
+ test('PLUGIN_SCREEN', async () => {
+ // PLUGIN_SCREEN: /^\/x\/([\w-]+)\/([\w-]+)\/?/,
+ await checkUrlToState('/x/foo/bar', {
view: GerritView.PLUGIN_SCREEN,
plugin: 'foo',
screen: 'bar',
});
- assert.isFalse(redirectStub.called);
});
});
});
diff --git a/polygerrit-ui/app/test/test-data-generators.ts b/polygerrit-ui/app/test/test-data-generators.ts
index f0a4cbe..b480bfe 100644
--- a/polygerrit-ui/app/test/test-data-generators.ts
+++ b/polygerrit-ui/app/test/test-data-generators.ts
@@ -116,6 +116,10 @@
import {SearchViewState} from '../models/views/search';
import {ChangeChildView, ChangeViewState} from '../models/views/change';
import {NormalizedFileInfo} from '../models/change/files-model';
+import {GroupViewState} from '../models/views/group';
+import {RepoDetailView, RepoViewState} from '../models/views/repo';
+import {AdminChildView, AdminViewState} from '../models/views/admin';
+import {DashboardViewState} from '../models/views/dashboard';
const TEST_DEFAULT_EXPRESSION = 'label:Verified=MAX -label:Verified=MIN';
export const TEST_PROJECT_NAME: RepoName = 'test-project' as RepoName;
@@ -741,6 +745,73 @@
};
}
+export function createSearchViewState(): SearchViewState {
+ return {
+ view: GerritView.SEARCH,
+ query: '',
+ offset: undefined,
+ loading: false,
+ changes: [],
+ };
+}
+
+export function createDashboardViewState(): DashboardViewState {
+ return {
+ view: GerritView.DASHBOARD,
+ user: 'self',
+ };
+}
+
+export function createAdminReposViewState(): AdminViewState {
+ return {
+ view: GerritView.ADMIN,
+ adminView: AdminChildView.REPOS,
+ offset: '0',
+ filter: null,
+ openCreateModal: false,
+ };
+}
+
+export function createAdminPluginsViewState(): AdminViewState {
+ return {
+ view: GerritView.ADMIN,
+ adminView: AdminChildView.PLUGINS,
+ offset: '0',
+ filter: null,
+ };
+}
+
+export function createGroupViewState(): GroupViewState {
+ return {
+ view: GerritView.GROUP,
+ groupId: 'test-group-id' as GroupId,
+ };
+}
+
+export function createRepoViewState(): RepoViewState {
+ return {
+ view: GerritView.REPO,
+ };
+}
+
+export function createRepoBranchesViewState(): RepoViewState {
+ return {
+ view: GerritView.REPO,
+ detail: RepoDetailView.BRANCHES,
+ offset: '0',
+ filter: null,
+ };
+}
+
+export function createRepoTagsViewState(): RepoViewState {
+ return {
+ view: GerritView.REPO,
+ detail: RepoDetailView.TAGS,
+ offset: '0',
+ filter: null,
+ };
+}
+
export function createRequirement(): Requirement {
return {
status: RequirementStatus.OK,
diff --git a/polygerrit-ui/app/utils/page-wrapper-utils.ts b/polygerrit-ui/app/utils/page-wrapper-utils.ts
index 2e5c7b42..58bb024 100644
--- a/polygerrit-ui/app/utils/page-wrapper-utils.ts
+++ b/polygerrit-ui/app/utils/page-wrapper-utils.ts
@@ -16,11 +16,16 @@
redirect(url: string): void;
replace(path: string, state: null, init: boolean, dispatch: boolean): void;
base(url: string): void;
- start(): void;
+ start(opts: Options): void;
stop(): void;
exit(pattern: string | RegExp, ...pageCallback: PageCallback[]): void;
}
+export interface Options {
+ popstate?: boolean;
+ dispatch?: boolean;
+}
+
// See https://visionmedia.github.io/page.js/ for details
export interface PageContext {
canonicalPath: string;