@defra-fish/gafl-webapp-service
Version:
The websales frontend for the GAFL service
352 lines (305 loc) • 13.6 kB
JavaScript
import pageHandler from '../page-handler.js'
import journeyDefinition from '../../routes/journey-definition.js'
import { addLanguageCodeToUri } from '../../processors/uri-helper.js'
import { welshEnabledAndApplied } from '../../processors/page-language-helper.js'
import GetDataRedirect from '../get-data-redirect.js'
import { ANALYTICS } from '../../constants.js'
import { AGREED, IDENTIFY, LICENCE_DETAILS, LICENCE_FOR, ORDER_COMPLETE, PAYMENT_CANCELLED, PAYMENT_FAILED } from '../../uri.js'
import { trackGTM } from '../analytics-handler.js'
jest.mock('../../routes/journey-definition.js', () => [])
jest.mock('../../processors/uri-helper.js')
jest.mock('../../processors/page-language-helper.js')
jest.mock('../analytics-handler.js', () => ({
trackGTM: jest.fn()
}))
jest.mock('../../constants', () => ({
ANALYTICS: {
selected: 'chosen-one',
acceptTracking: 'you-may-watch-me',
seenMessage: 'seen-it',
omitPageFromAnalytics: 'no-tracky',
pageSkipped: 'ignored-page'
},
PAGE_STATE: { completed: true, error: false }
}))
jest.mock('../../uri.js', () => ({
AGREED: { uri: '/buy/agreed/page' },
LICENCE_DETAILS: { uri: '/buy/licence/details' },
ORDER_COMPLETE: { uri: '/buy/order/complete/page' },
PAYMENT_CANCELLED: { uri: '/buy/payment/cancelled/page' },
PAYMENT_FAILED: { uri: '/buy/payment/failed/page' },
PROCESS_ANALYTICS_PREFERENCES: { uri: '/buy/process/analytics/preferences/page' },
LICENCE_FOR: { uri: '/buy/licence-for' },
IDENTIFY: { uri: '/buy/renew/identify' }
}))
describe('The page handler function', () => {
beforeEach(() => {
jest.resetAllMocks()
journeyDefinition.length = 0
})
it('the get method re-throws any exceptions which are not transaction errors ', async () => {
const request = getMockRequest()
const getData = async () => {
throw new Error('Random exception')
}
try {
await pageHandler(null, null, null, getData).get(request)
} catch (err) {
expect(err.message).toBe('Random exception')
}
})
it('the error method re-throws any exceptions which are not transaction errors ', async () => {
const request = getMockRequest({
setCurrentPermission: () => {
throw new Error('Random exception')
}
})
try {
await pageHandler().error(request, null, { details: [] })
} catch (err) {
expect(err.message).toBe('Random exception')
}
})
it.each([['/previous/page'], ['/last/page']])('get calls addLanguageCodeToUri with request and backLink', async previousPage => {
const backLink = () => previousPage
journeyDefinition.push({ current: { page: 'view' }, backLink })
const { get } = pageHandler(null, 'view', '/next/page')
const request = getMockRequest(undefined, '/this/page')
const toolkit = getMockToolkit()
await get(request, toolkit)
expect(addLanguageCodeToUri).toHaveBeenCalledWith(request, backLink())
})
it.each([[() => '/last/page'], ['previous/page']])(
'pageData.backRef from get uses value generated by addLanguageCodeToUri',
async backLink => {
journeyDefinition.push({ current: { page: 'view' }, backLink })
const { get } = pageHandler(null, 'view', '/next/page')
const returnValue = Symbol('/previous/page')
addLanguageCodeToUri.mockReturnValueOnce(returnValue)
const toolkit = getMockToolkit()
await get(getMockRequest(), toolkit)
expect(toolkit.view).toHaveBeenCalledWith(
expect.any(String),
expect.objectContaining({
backRef: returnValue
})
)
}
)
it('pageData.backRef is null if backLink is null', async () => {
const backLink = () => {}
journeyDefinition.push({ current: { page: 'view' }, backLink })
const { get } = pageHandler(null, 'view', '/next/page')
const returnValue = Symbol('/previous/page')
addLanguageCodeToUri.mockReturnValueOnce(returnValue)
const toolkit = getMockToolkit()
await get(getMockRequest(), toolkit)
expect(toolkit.view).toHaveBeenCalledWith(
expect.any(String),
expect.objectContaining({
backRef: null
})
)
})
it('GetDataRedirect being thrown will redirectWithLanguageCode to the target', async () => {
journeyDefinition.push({ current: { page: 'view' }, backLink: '/previous/page' })
const url = Symbol('/go/somewhere/else')
const getData = () => {
throw new GetDataRedirect(url)
}
const { get } = pageHandler(null, 'view', '/next/page', getData)
const request = getMockRequest()
const toolkit = getMockToolkit()
await get(request, toolkit)
expect(toolkit.redirectWithLanguageCode).toHaveBeenCalledWith(url)
})
it.each([['/route/one'], ['/route/sixty-six']])('error redirects with language code', async url => {
const { error } = pageHandler('', 'view')
const request = getMockRequest(undefined, url)
const toolkit = getMockToolkit()
await error(request, toolkit, { details: [] })
expect(toolkit.redirectWithLanguageCode).toHaveBeenCalledWith()
})
it('sets the value of pageData with displayAnalytics true', async () => {
addLanguageCodeToUri.mockReturnValueOnce('/buy/process-analytics-preferences')
welshEnabledAndApplied.mockReturnValueOnce(false)
trackGTM.mockReturnValueOnce(false)
const { get } = pageHandler('', 'view', '/next/page')
const toolkit = getMockToolkit()
await get(getMockRequest(), toolkit)
expect(toolkit.view).toMatchSnapshot()
})
it('sets the value of pageData with displayAnalytics false', async () => {
addLanguageCodeToUri.mockReturnValueOnce('/buy/process-analytics-preferences')
welshEnabledAndApplied.mockReturnValueOnce(false)
trackGTM.mockReturnValueOnce(false)
const { get } = pageHandler('', 'view', '/next/page')
const toolkit = getMockToolkit()
await get(getMockRequest({ path: '/we/are/here' }), toolkit)
expect(toolkit.view).toMatchSnapshot()
})
it('sets the value of gtmContainerId to the GTM_CONTAINER_ID env var', async () => {
const expectedValue = 'expected'
process.env.GTM_CONTAINER_ID = expectedValue
const { get } = pageHandler('', 'view', '/next/page')
const toolkit = getMockToolkit()
await get(getMockRequest(), toolkit)
expect(toolkit.view).toHaveBeenCalledWith(
expect.any(String),
expect.objectContaining({
gtmContainerId: expectedValue
})
)
delete process.env.GTM_CONTAINER_ID
})
it.each([false, true])('sets the value of approvedGTM as %s when trackGTM returns same', async gtm => {
trackGTM.mockReturnValueOnce(gtm)
const { get } = pageHandler('', 'view', '/next/page')
const toolkit = getMockToolkit()
await get(getMockRequest(), toolkit)
expect(toolkit.view).toHaveBeenCalledWith(
expect.any(String),
expect.objectContaining({
approvedGTM: gtm
})
)
delete process.env.GTM_CONTAINER_ID
})
it.each([
['payment cancelled', PAYMENT_CANCELLED.uri],
['payment failed', PAYMENT_FAILED.uri],
['agreed', AGREED.uri],
['order complete', ORDER_COMPLETE.uri],
['licence details', LICENCE_DETAILS.uri]
])('hides the analytics banner for %s page', async (_pageLabel, path) => {
const { get } = pageHandler('', 'view', '/next/page')
const toolkit = getMockToolkit()
const mockRequest = getMockRequest({ path })
await get(mockRequest, toolkit)
const pageData = toolkit.view.mock.calls[0][1]
expect(pageData.displayAnalytics).toBeFalsy()
})
it('sets analytics values to default values if analytics key is not set', async () => {
const { get } = pageHandler('', 'view', '/next/page')
const toolkit = getMockToolkit()
const mockRequest = getMockRequest('/current/page', false)
await get(mockRequest, toolkit)
const pageData = toolkit.view.mock.calls[0][1]
expect(pageData).toEqual(
expect.objectContaining({
analyticsMessageDisplayed: false,
analyticsSelected: false,
acceptedTracking: false
})
)
})
it.each([[PAYMENT_CANCELLED.uri], [PAYMENT_FAILED.uri], [AGREED.uri], [ORDER_COMPLETE.uri], [LICENCE_DETAILS.uri]])(
'sets journeyBeginning is not set if not on licence_for or identify page',
async pageUri => {
const { get } = pageHandler('', 'view', '/next/page')
const toolkit = getMockToolkit()
const mockRequest = getMockRequest(pageUri)
await get(mockRequest, toolkit)
const pageData = toolkit.view.mock.calls[0][1]
expect(pageData).toEqual(
expect.not.objectContaining({
journeyBeginning: true
})
)
}
)
it.each([[IDENTIFY.uri], [LICENCE_FOR.uri]])('sets journeyBeginning to true if on licence_for or identify page', async path => {
const { get } = pageHandler('', 'view', '/next/page')
const toolkit = getMockToolkit()
const mockRequest = getMockRequest({ path })
await get(mockRequest, toolkit)
const pageData = toolkit.view.mock.calls[0][1]
expect(pageData).toEqual(
expect.objectContaining({
journeyBeginning: true
})
)
})
it.each([['/next/page'], ['/another/page']])(
'post method called redirectWithLanguageCode with completion value when completion is a string',
async pageUri => {
const { post } = pageHandler('', 'view', pageUri)
const toolkit = getMockToolkit()
const mockRequest = getMockRequest()
await post(mockRequest, toolkit)
expect(toolkit.redirectWithLanguageCode).toHaveBeenCalledWith(pageUri)
}
)
describe('omitPageFromAnalytics', () => {
it.each`
desc | values | result
${'undefined: omitPageFromAnalytics property is set to false'} | ${{}} | ${{ [ANALYTICS.omitPageFromAnalytics]: false }}
${'defined with pageSkip property not equal to true, seenMessage property equals true and omitPageFromAnalytics property not equal to true: omitPageFromAnalytics and pageSkipped property is set to true'} | ${{ [ANALYTICS.seenMessage]: 'seen-message' }} | ${{ [ANALYTICS.omitPageFromAnalytics]: true, [ANALYTICS.pageSkipped]: true }}
${'defined, pageSkip property equals true, seenMessage property equals true and omitPageFromAnalytics property not equal to true: omitPageFromAnalytics property is set to false'} | ${{ [ANALYTICS.omitPageFromAnalytics]: true, [ANALYTICS.seenMessage]: 'seen-message' }} | ${{ [ANALYTICS.omitPageFromAnalytics]: false }}
${'defined, pageSkip property not equal to true, seenMessage property not equal to true and omitPageFromAnalytics property not equal to true: omitPageFromAnalytics property is set to false'} | ${{ [ANALYTICS.seenMessage]: false }} | ${{ [ANALYTICS.omitPageFromAnalytics]: false }}
${'defined, pageSkip property not equal to true, seenMessage property equals true and omitPageFromAnalytics property equals true: omitPageFromAnalytics property is set to false'} | ${{ [ANALYTICS.seenMessage]: 'seen-message', [ANALYTICS.pageSkipped]: true }} | ${{ [ANALYTICS.omitPageFromAnalytics]: false }}
`('when analytics cache is $desc', async ({ values, result }) => {
const set = jest.fn()
const analytics = getAnalytics(values)
const { get } = pageHandler('', 'view', 'next-page')
const toolkit = getMockToolkit()
const mockRequest = getMockRequest({ analytics, set })
await get(mockRequest, toolkit)
expect(set).toBeCalledWith(result)
})
})
describe('pageLanguageSetToWelsh', () => {
it('returns the value of welshEnabledAndApplied', async () => {
const expectedValue = Symbol('expected')
welshEnabledAndApplied.mockReturnValueOnce(expectedValue)
const { get } = pageHandler('', 'view', '/next/page')
const toolkit = getMockToolkit()
await get(getMockRequest(), toolkit)
expect(toolkit.view).toHaveBeenCalledWith(
expect.any(String),
expect.objectContaining({
pageLanguageSetToWelsh: expectedValue
})
)
})
})
})
const getAnalytics = overides => ({
[ANALYTICS.acceptTracking]: 'accepted-tracking',
[ANALYTICS.selected]: 'selected',
...overides
})
const getMockRequest = ({ setCurrentPermission = () => {}, path = '/buy/we/are/here', analytics, set = () => {} } = {}) => ({
cache: () => ({
helpers: {
page: {
getCurrentPermission: () => ({}),
setCurrentPermission
},
status: {
getCurrentPermission: () => ({}),
setCurrentPermission: () => {}
},
transaction: {
getCurrentPermission: () => {}
},
analytics: {
get: async () => analytics,
set
}
}
}),
i18n: {
getCatalog: () => {},
getLocales: () => [],
getLocale: () => ''
},
path,
url: {
search: ''
}
})
const getMockToolkit = () => ({
redirectWithLanguageCode: jest.fn(() => ({ takeover: () => {} })),
view: jest.fn()
})