@defra-fish/gafl-webapp-service 1.76.0 → 1.77.0-rc.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defra-fish/gafl-webapp-service",
3
- "version": "1.76.0",
3
+ "version": "1.77.0-rc.10",
4
4
  "description": "The websales frontend for the GAFL service",
5
5
  "type": "module",
6
6
  "engines": {
@@ -36,8 +36,8 @@
36
36
  "prepare": "gulp --gulpfile build/gulpfile.cjs"
37
37
  },
38
38
  "dependencies": {
39
- "@defra-fish/business-rules-lib": "1.76.0",
40
- "@defra-fish/connectors-lib": "1.76.0",
39
+ "@defra-fish/business-rules-lib": "1.77.0-rc.10",
40
+ "@defra-fish/connectors-lib": "1.77.0-rc.10",
41
41
  "@defra/hapi-gapi": "2.0.0",
42
42
  "@hapi/boom": "9.1.2",
43
43
  "@hapi/catbox-redis": "6.0.2",
@@ -79,5 +79,5 @@
79
79
  "./gafl-jest-matchers.js"
80
80
  ]
81
81
  },
82
- "gitHead": "2287ca0defd4b61d66cbea6f0df84568265b036f"
82
+ "gitHead": "b41c703037390290c9403cafc2e0252ef63e149e"
83
83
  }
@@ -0,0 +1,77 @@
1
+ import updateTransaction from '../update-transaction.js'
2
+ import { licenceDetailsService } from '../../../../../services/licence-details/licence-details-service.js'
3
+
4
+ jest.mock('../../../../../services/licence-details/licence-details-service.js', () => ({ licenceDetailsService: jest.fn(() => []) }))
5
+ describe('update-transaction', () => {
6
+ const generateMockRequest = ({
7
+ licensee = {},
8
+ licenceLength = '12M',
9
+ premises = '',
10
+ postcode = '',
11
+ setExistingPermissions = () => {}
12
+ } = {}) => ({
13
+ cache: () => ({
14
+ helpers: {
15
+ page: { getCurrentPermission: () => ({ payload: { premises, postcode } }) },
16
+ transaction: { getCurrentPermission: () => ({ licensee, licenceLength }), setCurrentPermission: () => {} },
17
+ existingPermissions: { set: setExistingPermissions }
18
+ }
19
+ })
20
+ })
21
+
22
+ beforeEach(jest.clearAllMocks)
23
+
24
+ it('sends correct parameters to look up existing permissions', async () => {
25
+ const sampleLicensee = {
26
+ firstName: 'Brenin',
27
+ lastName: 'Pysgotwr',
28
+ birthDate: '1987-07-10'
29
+ }
30
+ const premises = '59'
31
+ const postcode = 'YO99 9AA'
32
+
33
+ await updateTransaction(generateMockRequest({ licensee: sampleLicensee, premises, postcode }))
34
+ expect(licenceDetailsService).toHaveBeenCalledWith(
35
+ expect.objectContaining({
36
+ firstName: sampleLicensee.firstName,
37
+ lastName: sampleLicensee.lastName,
38
+ birthDate: sampleLicensee.birthDate,
39
+ premises,
40
+ postcode
41
+ })
42
+ )
43
+ })
44
+
45
+ it('saves retrieved permissions in existingPermissions cache', async () => {
46
+ const setExistingPermissions = jest.fn()
47
+ const sampleRequest = generateMockRequest({ setExistingPermissions })
48
+ const existingPermissions = Symbol('existingPermissions')
49
+ licenceDetailsService.mockReturnValueOnce(existingPermissions)
50
+
51
+ await updateTransaction(sampleRequest)
52
+
53
+ expect(setExistingPermissions).toHaveBeenCalledWith({ permissions: existingPermissions })
54
+ })
55
+
56
+ describe.each([
57
+ ['one day', '1D'],
58
+ ['eight days', '8D']
59
+ ])('for licence duration %s', (_d, licenceLength) => {
60
+ it("doesn't look up existingPermissions", async () => {
61
+ const sampleRequest = generateMockRequest({ licenceLength })
62
+
63
+ await updateTransaction(sampleRequest)
64
+
65
+ expect(licenceDetailsService).not.toHaveBeenCalled()
66
+ })
67
+
68
+ it("doesn't set existingPermissions cache", async () => {
69
+ const setExistingPermissions = jest.fn()
70
+ const sampleRequest = generateMockRequest({ licenceLength, setExistingPermissions })
71
+
72
+ await updateTransaction(sampleRequest)
73
+
74
+ expect(setExistingPermissions).not.toHaveBeenCalled()
75
+ })
76
+ })
77
+ })
@@ -1,4 +1,5 @@
1
1
  import { ADDRESS_ENTRY } from '../../../../uri.js'
2
+ import { licenceDetailsService } from '../../../../services/licence-details/licence-details-service.js'
2
3
 
3
4
  /**
4
5
  * In this case the result of the address search is placed into the page data of the select address page
@@ -7,8 +8,14 @@ import { ADDRESS_ENTRY } from '../../../../uri.js'
7
8
  */
8
9
  export default async request => {
9
10
  const { payload } = await request.cache().helpers.page.getCurrentPermission(ADDRESS_ENTRY.page)
10
- const { licensee } = await request.cache().helpers.transaction.getCurrentPermission()
11
+ const { licensee, licenceLength } = await request.cache().helpers.transaction.getCurrentPermission()
12
+
11
13
  const { premises, street, locality, town, postcode, 'country-code': countryCode } = payload
12
14
  Object.assign(licensee, { premises, street, locality, town, postcode, countryCode, organisation: null })
13
15
  await request.cache().helpers.transaction.setCurrentPermission({ licensee })
16
+ if (licenceLength === '12M') {
17
+ const { firstName, lastName, birthDate } = licensee
18
+ const existingPermissions = await licenceDetailsService({ firstName, lastName, birthDate, premises, postcode })
19
+ await request.cache().helpers.existingPermissions.set({ permissions: existingPermissions })
20
+ }
14
21
  }
@@ -0,0 +1,79 @@
1
+ import updateTransaction from '../update-transaction.js'
2
+ import { licenceDetailsService } from '../../../../../services/licence-details/licence-details-service.js'
3
+
4
+ jest.mock('../../../../../services/licence-details/licence-details-service.js', () => ({ licenceDetailsService: jest.fn(() => []) }))
5
+
6
+ describe('update-transaction', () => {
7
+ const generateMockRequest = ({
8
+ licensee = {},
9
+ licenceLength = '12M',
10
+ premises,
11
+ postcode = '',
12
+ setExistingPermissions = () => {}
13
+ } = {}) => ({
14
+ cache: () => ({
15
+ helpers: {
16
+ page: { getCurrentPermission: () => ({ payload: { address: 'a1' } }) },
17
+ transaction: { getCurrentPermission: () => ({ licensee, licenceLength }), setCurrentPermission: () => {} },
18
+ addressLookup: { getCurrentPermission: () => ({ addresses: [{ id: 'a1', premises, postcode }] }) },
19
+ existingPermissions: { set: setExistingPermissions }
20
+ }
21
+ })
22
+ })
23
+
24
+ beforeEach(jest.clearAllMocks)
25
+
26
+ it('sends correct parameters to look up existing permissions', async () => {
27
+ const sampleLicensee = {
28
+ firstName: 'Brenin',
29
+ lastName: 'Pysgotwr',
30
+ birthDate: '1987-07-10'
31
+ }
32
+ const premises = '27'
33
+ const postcode = 'YO99 9AA'
34
+
35
+ await updateTransaction(generateMockRequest({ licensee: sampleLicensee, premises, postcode }))
36
+ expect(licenceDetailsService).toHaveBeenCalledWith(
37
+ expect.objectContaining({
38
+ firstName: sampleLicensee.firstName,
39
+ lastName: sampleLicensee.lastName,
40
+ birthDate: sampleLicensee.birthDate,
41
+ premises,
42
+ postcode
43
+ })
44
+ )
45
+ })
46
+
47
+ it('saves retrieved permissions in existingPermissions cache', async () => {
48
+ const setExistingPermissions = jest.fn()
49
+ const sampleRequest = generateMockRequest({ setExistingPermissions })
50
+ const existingPermissions = Symbol('existingPermissions')
51
+ licenceDetailsService.mockReturnValueOnce(existingPermissions)
52
+
53
+ await updateTransaction(sampleRequest)
54
+
55
+ expect(setExistingPermissions).toHaveBeenCalledWith({ permissions: existingPermissions })
56
+ })
57
+
58
+ describe.each([
59
+ ['one day', '1D'],
60
+ ['eight days', '8D']
61
+ ])('for licence duration %s', (_d, licenceLength) => {
62
+ it("doesn't look up existingPermissions", async () => {
63
+ const sampleRequest = generateMockRequest({ licenceLength })
64
+
65
+ await updateTransaction(sampleRequest)
66
+
67
+ expect(licenceDetailsService).not.toHaveBeenCalled()
68
+ })
69
+
70
+ it("doesn't set existingPermissions cache", async () => {
71
+ const setExistingPermissions = jest.fn()
72
+ const sampleRequest = generateMockRequest({ licenceLength, setExistingPermissions })
73
+
74
+ await updateTransaction(sampleRequest)
75
+
76
+ expect(setExistingPermissions).not.toHaveBeenCalled()
77
+ })
78
+ })
79
+ })
@@ -1,4 +1,5 @@
1
1
  import { ADDRESS_SELECT } from '../../../../uri.js'
2
+ import { licenceDetailsService } from '../../../../services/licence-details/licence-details-service.js'
2
3
 
3
4
  /**
4
5
  * In this case the result of the address search is placed into the page data of the select address page
@@ -7,7 +8,7 @@ import { ADDRESS_SELECT } from '../../../../uri.js'
7
8
  */
8
9
  export default async request => {
9
10
  const { payload } = await request.cache().helpers.page.getCurrentPermission(ADDRESS_SELECT.page)
10
- const { licensee } = await request.cache().helpers.transaction.getCurrentPermission()
11
+ const { licensee, licenceLength } = await request.cache().helpers.transaction.getCurrentPermission()
11
12
  const { addresses } = await request.cache().helpers.addressLookup.getCurrentPermission()
12
13
  const { premises, street, locality, town, postcode } = addresses.find(a => a.id === payload.address)
13
14
  // All UK addresses from lookup default to GB
@@ -27,4 +28,10 @@ export default async request => {
27
28
  }
28
29
 
29
30
  await request.cache().helpers.transaction.setCurrentPermission({ licensee })
31
+ if (licenceLength === '12M') {
32
+ const { firstName, lastName, birthDate } = licensee
33
+ const existingPermissions = await licenceDetailsService({ firstName, lastName, birthDate, premises, postcode })
34
+ console.log('existingPermissions', JSON.stringify(existingPermissions))
35
+ await request.cache().helpers.existingPermissions.set({ permissions: existingPermissions })
36
+ }
30
37
  }
@@ -125,7 +125,7 @@
125
125
  classes: "govuk-!-font-weight-bold govuk-label"
126
126
  }
127
127
  },
128
- errorMessage: dobErrorMessage,
128
+ errorMessage: data.dobErrorMessage,
129
129
  hint: {
130
130
  text: mssgs.enter_dob_example
131
131
  }
@@ -202,4 +202,4 @@
202
202
  })
203
203
  })()
204
204
  </script>
205
- {% endblock %}
205
+ {% endblock %}
@@ -0,0 +1,72 @@
1
+ import { salesApi } from '@defra-fish/connectors-lib'
2
+ import { licenceDetailsService } from '../licence-details-service'
3
+ jest.mock('@defra-fish/connectors-lib', () => ({
4
+ salesApi: {
5
+ getLicenceDetails: jest.fn(() => ({ licences: [] }))
6
+ }
7
+ }))
8
+
9
+ const getParams = () => ({
10
+ firstName: 'Fishy',
11
+ lastName: 'McFishface',
12
+ birthDate: '2000-01-01',
13
+ premises: '22',
14
+ postcode: 'TE1 1ST'
15
+ })
16
+
17
+ describe('licence-details-service', () => {
18
+ it('calls getLicenceDetails with the correct params', async () => {
19
+ const params = getParams()
20
+ await licenceDetailsService(params)
21
+
22
+ expect(salesApi.getLicenceDetails).toHaveBeenCalledWith(params)
23
+ })
24
+
25
+ it.each([
26
+ ['there are no matches', { licences: [] }],
27
+ ['there is one match', { licences: [{ referenceNumber: 'AAAAAA-1' }] }],
28
+ ['there are multiple matches', { licences: [{ referenceNumber: 'AAAAAA-1' }, { referenceNumber: 'AAAAAA-2' }] }]
29
+ ])('returns the correct result when %s', async (_description, responseBody) => {
30
+ salesApi.getLicenceDetails.mockResolvedValueOnce(responseBody)
31
+
32
+ const result = await licenceDetailsService(getParams())
33
+ expect(result).toBe(responseBody.licences)
34
+ })
35
+
36
+ it('returns an empty array when there is no licences object in the result', async () => {
37
+ salesApi.getLicenceDetails.mockResolvedValueOnce({})
38
+
39
+ const result = await licenceDetailsService(getParams())
40
+ expect(result).toEqual([])
41
+ })
42
+
43
+ describe('if getLicenceDetails throws an error', () => {
44
+ it('catches the error', async () => {
45
+ const error = new Error('Something went wrong')
46
+ salesApi.getLicenceDetails.mockRejectedValueOnce(error)
47
+
48
+ await expect(licenceDetailsService(getParams())).resolves.toBeDefined()
49
+ })
50
+
51
+ it('calls console.error with the details', async () => {
52
+ const error = new Error('Something went wrong')
53
+ const consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(jest.fn())
54
+ salesApi.getLicenceDetails.mockRejectedValueOnce(error)
55
+ const params = getParams()
56
+
57
+ await licenceDetailsService(params)
58
+
59
+ expect(consoleErrorSpy).toHaveBeenCalledWith(`Error retrieving licence details for ${JSON.stringify(params)}`, error)
60
+ consoleErrorSpy.mockRestore()
61
+ })
62
+
63
+ it('returns an empty array', async () => {
64
+ const error = new Error('Something went wrong')
65
+ salesApi.getLicenceDetails.mockRejectedValueOnce(error)
66
+
67
+ const results = await licenceDetailsService(getParams())
68
+
69
+ expect(results).toEqual([])
70
+ })
71
+ })
72
+ })
@@ -0,0 +1,15 @@
1
+ import { salesApi } from '@defra-fish/connectors-lib'
2
+
3
+ const matchingLicences = async contactInfo => {
4
+ try {
5
+ return await salesApi.getLicenceDetails(contactInfo)
6
+ } catch (err) {
7
+ console.error(`Error retrieving licence details for ${JSON.stringify(contactInfo)}`, err)
8
+ return {}
9
+ }
10
+ }
11
+
12
+ export const licenceDetailsService = async ({ firstName, lastName, birthDate, premises, postcode }) => {
13
+ const response = await matchingLicences({ firstName, lastName, birthDate, premises, postcode })
14
+ return response?.licences || []
15
+ }
@@ -0,0 +1,44 @@
1
+ // Jest Snapshot v1, https://goo.gl/fbAQLP
2
+
3
+ exports[`contexts has expected contexts 1`] = `
4
+ Object {
5
+ "addressLookup": Object {
6
+ "identifier": "address-lookup-context",
7
+ "initializer": Object {
8
+ "permissions": Array [],
9
+ },
10
+ },
11
+ "analytics": Object {
12
+ "identifier": "analytics-context",
13
+ "initializer": Object {
14
+ "permissions": Array [],
15
+ },
16
+ },
17
+ "existingPermissions": Object {
18
+ "identifier": "existing-permissions-context",
19
+ "initializer": Object {
20
+ "permissions": Array [],
21
+ },
22
+ },
23
+ "page": Object {
24
+ "identifier": "page-context",
25
+ "initializer": Object {
26
+ "permissions": Array [],
27
+ },
28
+ },
29
+ "status": Object {
30
+ "identifier": "status-context",
31
+ "initializer": Object {
32
+ "currentPermissionIdx": -1,
33
+ "permissions": Array [],
34
+ },
35
+ },
36
+ "transaction": Object {
37
+ "identifier": "transaction-context",
38
+ "initializer": Object {
39
+ "payment": Object {},
40
+ "permissions": Array [],
41
+ },
42
+ },
43
+ }
44
+ `;
@@ -1,6 +1,8 @@
1
- import { CacheError } from '../cache-manager.js'
1
+ import { CacheError, contextCache } from '../cache-manager.js'
2
2
  import { cacheDecorator } from '../cache-decorator.js'
3
3
 
4
+ jest.mock('../cache-manager.js')
5
+
4
6
  describe('Cache decorator', () => {
5
7
  it('gets id from state', () => {
6
8
  const sessionId = 'abc123'
@@ -31,14 +33,66 @@ describe('Cache decorator', () => {
31
33
  expect(error instanceof CacheError).toBeTruthy()
32
34
  })
33
35
 
34
- // it.each([
35
- // [{ state: {} }, false],
36
- // [{ state: { bourbon: { id: 'abc123' } } }, true]
37
- // ])('hasSession flags whether cache is available', (state, expectedHasSession) => {
38
- // const context = getCacheDecoratorContext(state)
36
+ describe('existingPermissions', () => {
37
+ beforeEach(jest.clearAllMocks)
38
+
39
+ const getSampleCache = (cookieName = 'crunch-cream') => {
40
+ const sampleCache = {
41
+ server: { app: {} },
42
+ state: { [cookieName]: { id: 'abc-123' } }
43
+ }
44
+ sampleCache.decorator = cacheDecorator(cookieName)
45
+ Object.assign(sampleCache, sampleCache.decorator())
46
+ return sampleCache
47
+ }
48
+
49
+ it('uses contextCache to get existingPermissions', async () => {
50
+ const sampleCache = getSampleCache()
51
+ const mockCacheStore = { get: jest.fn() }
52
+ contextCache.mockReturnValueOnce(mockCacheStore)
53
+
54
+ await sampleCache.helpers.existingPermissions.get()
55
+
56
+ expect(mockCacheStore.get).toHaveBeenCalled()
57
+ })
58
+
59
+ it('uses value returned by cache store to fulfill request', async () => {
60
+ const cacheValue = Symbol('cacheValue')
61
+ const sampleCache = getSampleCache()
62
+ const mockCacheStore = { get: jest.fn(() => cacheValue) }
63
+ contextCache.mockReturnValueOnce(mockCacheStore)
64
+
65
+ const fulfilledValue = await sampleCache.helpers.existingPermissions.get()
39
66
 
40
- // expect(generateCacheDecorator(context).hasSession()).toEqual(expectedHasSession)
41
- // })
67
+ expect(fulfilledValue).toBe(cacheValue)
68
+ })
69
+
70
+ it.each(['get', 'set'])('passes server cache, id and correct key to contextCache before calling %s', async method => {
71
+ const cookieName = 'fig-roll'
72
+ const sampleCache = getSampleCache(cookieName)
73
+ const id = Symbol('id')
74
+ const appCache = Symbol('appCache')
75
+ sampleCache.server.app.cache = appCache
76
+ sampleCache.state[cookieName].id = id
77
+ const mockCacheStore = { [method]: jest.fn() }
78
+ contextCache.mockReturnValueOnce(mockCacheStore)
79
+
80
+ await sampleCache.helpers.existingPermissions[method]()
81
+
82
+ expect(contextCache).toHaveBeenCalledWith(appCache, id, 'existingPermissions')
83
+ })
84
+
85
+ it('uses contextCache to set cache', async () => {
86
+ const cacheValue = Symbol('cacheValue')
87
+ const sampleCache = getSampleCache()
88
+ const mockCacheStore = { set: jest.fn() }
89
+ contextCache.mockReturnValueOnce(mockCacheStore)
90
+
91
+ await sampleCache.helpers.existingPermissions.set(cacheValue)
92
+
93
+ expect(mockCacheStore.set).toHaveBeenCalledWith(cacheValue)
94
+ })
95
+ })
42
96
  })
43
97
 
44
98
  const getCacheDecoratorContext = context => ({
@@ -1,5 +1,6 @@
1
1
  import { start, stop, initialize, injectWithCookies, mockSalesApi } from '../../__mocks__/test-utils-system.js'
2
2
  import { CONTROLLER, LICENCE_TYPE } from '../../uri.js'
3
+ import { contexts, base, contextCache } from '../cache-manager.js'
3
4
 
4
5
  beforeAll(() => new Promise(resolve => start(resolve)))
5
6
  beforeAll(() => new Promise(resolve => initialize(resolve)))
@@ -7,6 +8,12 @@ afterAll(d => stop(d))
7
8
 
8
9
  mockSalesApi()
9
10
 
11
+ const getMockAppCache = () => ({
12
+ set: jest.fn(),
13
+ get: jest.fn(),
14
+ drop: jest.fn()
15
+ })
16
+
10
17
  describe('The session cache removal', () => {
11
18
  it('will result in a redirect to the controller', async () => {
12
19
  await injectWithCookies('GET', '/buy/clear-cache')
@@ -27,3 +34,70 @@ describe('The session cache removal', () => {
27
34
  expect(response.headers.location).toHaveValidPathFor(CONTROLLER.uri)
28
35
  })
29
36
  })
37
+
38
+ describe('contexts', () => {
39
+ it('has expected contexts', () => {
40
+ expect(contexts).toMatchSnapshot()
41
+ })
42
+ })
43
+
44
+ describe('base', () => {
45
+ describe.each(['init', 'set'])('has %s function', fnName => {
46
+ it.each(['abc-123', 'def-456', 'db396bac-38df-48ea-9e1f-c4567274ef44'])('that sets app cache with id %s', sampleId => {
47
+ const sampleAppCache = getMockAppCache()
48
+ const sampleBase = base(sampleAppCache, sampleId)
49
+ const objParam = {}
50
+ sampleBase[fnName](objParam)
51
+ expect(sampleAppCache.set).toHaveBeenCalledWith(sampleId, objParam)
52
+ })
53
+ })
54
+
55
+ it.each(['abc-123', 'def-456', 'db396bac-38df-48ae-9e1f-c4567274ef44'])('has get function that gets app cache with id %s', sampleId => {
56
+ const sampleAppCache = getMockAppCache()
57
+ const sampleBase = base(sampleAppCache, sampleId)
58
+ sampleBase.get()
59
+ expect(sampleAppCache.get).toHaveBeenCalledWith(sampleId)
60
+ })
61
+
62
+ it.each(['abc-123', 'def-456', 'db396bac-38df-48ea-9ef1-c4567274ef44'])(
63
+ 'has clear function that drops app cache with id %s',
64
+ sampleId => {
65
+ const sampleAppCache = getMockAppCache()
66
+ const sampleBase = base(sampleAppCache, sampleId)
67
+ sampleBase.clear()
68
+ expect(sampleAppCache.drop).toHaveBeenCalledWith(sampleId)
69
+ }
70
+ )
71
+ })
72
+
73
+ describe('contextCache', () => {
74
+ it('get method returns context value if defined', async () => {
75
+ const sampleAppCache = getMockAppCache()
76
+ const sampleValue = Symbol('identifier')
77
+ sampleAppCache.get.mockResolvedValueOnce({ 'page-context': sampleValue })
78
+
79
+ const contextValue = await contextCache(sampleAppCache, 'abc-123', 'page').get()
80
+
81
+ expect(contextValue).toBe(sampleValue)
82
+ })
83
+
84
+ it('get method returns null if context value is not defined', async () => {
85
+ const sampleAppCache = getMockAppCache()
86
+
87
+ const contextValue = await contextCache(sampleAppCache, 'abc-123', 'page').get()
88
+
89
+ expect(contextValue).toBeNull()
90
+ })
91
+
92
+ it('set method is additive to existing context', async () => {
93
+ const sampleAppCache = getMockAppCache()
94
+ const originalCacheValue = { 'transaction-context': { a: 1, b: 'f57a955d-40d4-41e3-b1b1-fb7356e7c13b' } }
95
+ const additionalCacheValue = { c: 'cceab89a-d310-45fc-8d69-2003ded3c736' }
96
+ const expectedValue = { 'transaction-context': { ...originalCacheValue['transaction-context'], ...additionalCacheValue } }
97
+ sampleAppCache.get.mockResolvedValueOnce(originalCacheValue)
98
+
99
+ await contextCache(sampleAppCache, 'abc-123', 'transaction').set(additionalCacheValue)
100
+
101
+ expect(sampleAppCache.set).toHaveBeenCalledWith(expect.any(String), expect.objectContaining(expectedValue))
102
+ })
103
+ })
@@ -91,6 +91,10 @@ const cacheDecorator = sessionCookieName =>
91
91
  get: async () => contextCache(this.server.app.cache, id(), 'analytics').get(),
92
92
  set: async obj => contextCache(this.server.app.cache, id(), 'analytics').set(obj)
93
93
  },
94
+ existingPermissions: {
95
+ get: async () => contextCache(this.server.app.cache, id(), 'existingPermissions').get(),
96
+ set: async obj => contextCache(this.server.app.cache, id(), 'existingPermissions').set(obj)
97
+ },
94
98
 
95
99
  // This one differs in that it has an individual segment for each page
96
100
  page: {
@@ -11,7 +11,8 @@ const contexts = {
11
11
  transaction: { identifier: 'transaction-context', initializer: { payment: {}, permissions: [] } },
12
12
  status: { identifier: 'status-context', initializer: { permissions: [], currentPermissionIdx: -1 } },
13
13
  addressLookup: { identifier: 'address-lookup-context', initializer: { permissions: [] } },
14
- analytics: { identifier: 'analytics-context', initializer: { permissions: [] } }
14
+ analytics: { identifier: 'analytics-context', initializer: { permissions: [] } },
15
+ existingPermissions: { identifier: 'existing-permissions-context', initializer: { permissions: [] } }
15
16
  }
16
17
 
17
18
  class CacheError extends Error {}