diff --git a/packages/dotcom-middleware-navigation/readme.md b/packages/dotcom-middleware-navigation/readme.md index c167f1eeb..a84f4b11c 100644 --- a/packages/dotcom-middleware-navigation/readme.md +++ b/packages/dotcom-middleware-navigation/readme.md @@ -45,6 +45,14 @@ The middleware accepts the following parameters. All options will be passed alon Enables fetching hierarchical navigation data for the current path including any parent and child pages. Defaults to `false`. +### `getCurrentPath` + +Enables overriding of the default current path logic. Defaults to: + +```js + (request) => normalizePath(request.get('ft-vanity-url') || request.path) +``` + ### `interval` See the [FT navigation documentation] for more details. diff --git a/packages/dotcom-middleware-navigation/src/__test__/navigation.spec.ts b/packages/dotcom-middleware-navigation/src/__test__/navigation.spec.ts index 4f20f2cb0..ebb394e58 100644 --- a/packages/dotcom-middleware-navigation/src/__test__/navigation.spec.ts +++ b/packages/dotcom-middleware-navigation/src/__test__/navigation.spec.ts @@ -136,6 +136,38 @@ describe('dotcom-middleware-navigation', () => { }) }) + describe('when handling a request with a custom getCurrentPath', () => { + + it('executes the provided getCurrentPath function', async () => { + request = httpMocks.createRequest({ + path: '/path/to/page/123', + headers: { + 'ft-vanity-url': '/vanity-url?page=2' + } + }) + const dummyPath = '/foo'; + const instance = subject.init({ getCurrentPath: () => dummyPath }) + await instance(request, response, next) + + expect(FakeNavigation.getSubNavigationFor).toHaveBeenCalledWith(dummyPath) + }); + + it('allows overriding of how to calculate current path logic', async () => { + request = httpMocks.createRequest({ + path: '/path/to/page/123', + headers: { + 'ft-blocked-url': '/ig-content-test' + } + }) + + const instance = subject.init({ getCurrentPath: (request) => request.get('ft-blocked-url') }) + await instance(request, response, next) + + expect(FakeNavigation.getSubNavigationFor).toHaveBeenCalledWith('/ig-content-test') + }) + + }); + describe('when something goes wrong', () => { beforeEach(() => { FakeNavigation.getMenusFor = jest.fn(() => { diff --git a/packages/dotcom-middleware-navigation/src/navigation.ts b/packages/dotcom-middleware-navigation/src/navigation.ts index ef0cb121a..101ab40dc 100644 --- a/packages/dotcom-middleware-navigation/src/navigation.ts +++ b/packages/dotcom-middleware-navigation/src/navigation.ts @@ -5,11 +5,13 @@ import handleEdition from './handleEdition' import normalizePath from './normalizePath' type MiddlewareOptions = TNavOptions & { - enableSubNavigation?: boolean + enableSubNavigation?: boolean, + getCurrentPath?: Function } const defaultOptions: MiddlewareOptions = { - enableSubNavigation: false + enableSubNavigation: false, + getCurrentPath: (request) => normalizePath(request.get('ft-vanity-url') || request.path) } export const init = (userOptions: MiddlewareOptions = {}) => { @@ -26,7 +28,7 @@ export const init = (userOptions: MiddlewareOptions = {}) => { // rather than the underlying path, so prefer that when available. // // NOTE: Next router sets the vanity header inc. any query string so it must be normalized. - const currentPath = normalizePath(request.get('ft-vanity-url') || request.path) + const currentPath = options.getCurrentPath(request); const currentEdition = handleEdition(request, response) const [menusData, subNavigationData] = await Promise.all([