Rewrite router tests for GROUP_LIST in a more robust way A major issue with the existing tests is that they don't test the URL parsing and matching at all. They just test the handler methods. That creates a huge gap in testing and prevents safe refactorings. We want to refactor all route matching and handling in a similar way as change 356680 shows it for one route. So it makes sense to write the tests in a way that the input is a URL and the output is a view state. I will follow up with other tests once this change is approved and submitted. Release-Notes: skip Change-Id: I7ed36dd147fac2d500331da7aa0384c6aeee8c7b
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 168f334..00cb938 100644 --- a/polygerrit-ui/app/elements/core/gr-router/gr-router.ts +++ b/polygerrit-ui/app/elements/core/gr-router/gr-router.ts
@@ -1158,7 +1158,7 @@ const state: AdminViewState = { view: GerritView.ADMIN, adminView: AdminChildView.GROUPS, - offset: ctx.params[1] || 0, + offset: ctx.params[1] ?? '0', filter: null, openCreateModal: ctx.hash === 'create', }; @@ -1173,6 +1173,7 @@ adminView: AdminChildView.GROUPS, offset: ctx.params['offset'], filter: ctx.params['filter'], + openCreateModal: false, }; // Note that router model view must be updated before view models. this.setState(state); @@ -1183,7 +1184,9 @@ const state: AdminViewState = { view: GerritView.ADMIN, adminView: AdminChildView.GROUPS, + offset: ctx.params[1] ?? '0', filter: ctx.params['filter'] || null, + openCreateModal: false, }; // Note that router model view must be updated before view models. this.setState(state);
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 98272b4..af44739 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
@@ -11,6 +11,7 @@ stubRestApi, addListenerForTest, waitEventLoop, + waitUntilCalled, } from '../../../test/test-utils'; import {GrRouter, routerToken, _testOnly_RoutePattern} from './gr-router'; import {GerritView} from '../../../services/router/router-model'; @@ -25,7 +26,7 @@ } from '../../../types/common'; import {AppElementParams} from '../../gr-app-types'; import {assert} from '@open-wc/testing'; -import {AdminChildView} from '../../../models/views/admin'; +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'; @@ -38,6 +39,7 @@ createRevision, } from '../../../test/test-data-generators'; import {ParsedChangeInfo} from '../../../types/types'; +import {ViewState} from '../../../models/views/base'; suite('gr-router tests', () => { let router: GrRouter; @@ -291,6 +293,19 @@ 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.deepEqual(setStateStub.lastCall.firstArg, state); + } + + async function checkUrlNotMatched(url: string) { + handlePassThroughRoute.reset(); + router.page.show(url); + await waitUntilCalled(handlePassThroughRoute, 'handlePassThroughRoute'); + } + function createPageContext(): PageContext { return { canonicalPath: '', @@ -306,6 +321,7 @@ redirectStub = sinon.stub(router, 'redirect'); setStateStub = sinon.stub(router, 'setState'); handlePassThroughRoute = sinon.stub(router, 'handlePassThroughRoute'); + router.startRouter(); }); test('handleLegacyProjectDashboardRoute', () => { @@ -737,55 +753,55 @@ }); }); - test('handleGroupListOffsetRoute', () => { - const ctx = createPageContext(); - assertctxToParams(ctx, 'handleGroupListOffsetRoute', { + test('list of groups', async () => { + const defaultState: AdminViewState = { view: GerritView.ADMIN, adminView: AdminChildView.GROUPS, - offset: 0, - filter: null, + offset: '0', openCreateModal: false, - }); - - ctx.params[1] = '42'; - assertctxToParams(ctx, 'handleGroupListOffsetRoute', { - view: GerritView.ADMIN, - adminView: AdminChildView.GROUPS, - offset: '42', filter: null, - openCreateModal: false, - }); + }; - ctx.hash = 'create'; - assertctxToParams(ctx, 'handleGroupListOffsetRoute', { - view: GerritView.ADMIN, - adminView: AdminChildView.GROUPS, - offset: '42', - filter: null, + await checkUrlToState('/admin/groups', defaultState); + await checkUrlToState('/admin/groups/', defaultState); + await checkUrlToState('/admin/groups#create', { + ...defaultState, openCreateModal: true, }); - }); - - test('handleGroupListFilterOffsetRoute', () => { - const ctx = { - ...createPageContext(), - params: {filter: 'foo', offset: '42'}, - }; - assertctxToParams(ctx, 'handleGroupListFilterOffsetRoute', { - view: GerritView.ADMIN, - adminView: AdminChildView.GROUPS, - offset: '42', - filter: 'foo', + await checkUrlToState('/admin/groups,123', { + ...defaultState, + offset: '123', }); - }); - - test('handleGroupListFilterRoute', () => { - const ctx = {...createPageContext(), params: {filter: 'foo'}}; - assertctxToParams(ctx, 'handleGroupListFilterRoute', { - view: GerritView.ADMIN, - adminView: AdminChildView.GROUPS, - filter: 'foo', + await checkUrlToState('/admin/groups,123#create', { + ...defaultState, + offset: '123', + openCreateModal: true, }); + + await checkUrlToState('/admin/groups/q/filter:asdf', { + ...defaultState, + filter: 'asdf', + }); + await checkUrlToState('/admin/groups/q/filter:asdf,123', { + ...defaultState, + filter: 'asdf', + offset: '123', + }); + // #create is ignored when filtering + await checkUrlToState('/admin/groups/q/filter:asdf,123#create', { + ...defaultState, + filter: 'asdf', + offset: '123', + }); + // filter is decoded (twice) + await checkUrlToState( + '/admin/groups/q/filter:XX%20XX%2520XX%252FXX%3FXX', + {...defaultState, filter: 'XX XX XX/XX?XX'} + ); + + // Slash must be double encoded in `filter` param. + await checkUrlNotMatched('/admin/groups/q/filter:asdf/qwer,11'); + await checkUrlNotMatched('/admin/groups/q/filter:asdf%2Fqwer,11'); }); test('handleGroupRoute', () => {