diff --git a/server/@types/ActivityLog.type.ts b/server/@types/ActivityLog.type.ts index a2e343b0..f91967d4 100644 --- a/server/@types/ActivityLog.type.ts +++ b/server/@types/ActivityLog.type.ts @@ -30,10 +30,16 @@ export interface ActivityLogFiltersResponse extends ActivityLogFilters { queryStrPrefix: string queryStrSuffix: string maxDate: string + query?: ActivityLogFilters } -export interface ActivityLogCache extends ActivityLogFilters { +export interface ActivityLogCacheItem extends ActivityLogFilters { crn: string personActivity: PersonActivity tierCalculation: TierCalculation } + +export interface ActivityLogCache { + results: ActivityLogCacheItem[] + filters?: ActivityLogFilters +} diff --git a/server/@types/express/index.d.ts b/server/@types/express/index.d.ts index 3e0d8df7..2c5177ad 100644 --- a/server/@types/express/index.d.ts +++ b/server/@types/express/index.d.ts @@ -18,7 +18,7 @@ declare module 'express-session' { data?: Data errors?: Errors cache?: { - activityLog: ActivityLogCache[] + activityLog: ActivityLogCache } } diff --git a/server/middleware/getPersonActivity.test.ts b/server/middleware/getPersonActivity.test.ts new file mode 100644 index 00000000..62346eb8 --- /dev/null +++ b/server/middleware/getPersonActivity.test.ts @@ -0,0 +1,174 @@ +import { Request } from 'express' +import { getPersonActivity } from './getPersonActivity' +import { AppResponse } from '../@types' +import HmppsAuthClient from '../data/hmppsAuthClient' + +const crn = 'X756510' +const mockPersonActivityResponse = { + size: 10, + page: 1, + totalResults: 20, + totalPages: 2, + personSummary: { + crn, + name: { + forename: 'Eula', + surname: 'Schmeler', + }, + dateOfBirth: '', + }, + activities: [ + { + id: '11', + type: 'Phone call', + startDateTime: '2044-12-22T09:15:00.382936Z[Europe/London]', + endDateTime: '2044-12-22T09:30:00.382936Z[Europe/London]', + rarToolKit: 'Choices and Changes', + rarCategory: 'Stepping Stones', + isSensitive: false, + hasOutcome: false, + wasAbsent: true, + notes: '', + + isCommunication: true, + isPhoneCallFromPop: true, + officerName: { + forename: 'Terry', + surname: 'Jones', + }, + lastUpdated: '2023-03-20', + lastUpdatedBy: { + forename: 'Paul', + surname: 'Smith', + }, + }, + ], +} +const mockTierCalculationResponse = { + tierScore: '1', + calculationId: '1', + calculationDate: '', + data: { + protect: { + tier: '', + points: 1, + pointsBreakdown: { + NEEDS: 1, + NO_MANDATE_FOR_CHANGE: 1, + NO_VALID_ASSESSMENT: 1, + OGRS: 1, + IOM: 1, + RSR: 1, + ROSH: 1, + MAPPA: 1, + COMPLEXITY: 1, + ADDITIONAL_FACTORS_FOR_WOMEN: 1, + }, + }, + change: { + tier: '', + points: 1, + pointsBreakdown: { + NEEDS: 1, + NO_MANDATE_FOR_CHANGE: 1, + NO_VALID_ASSESSMENT: 1, + OGRS: 1, + IOM: 1, + RSR: 1, + ROSH: 1, + MAPPA: 1, + COMPLEXITY: 1, + ADDITIONAL_FACTORS_FOR_WOMEN: 1, + }, + }, + calculationVersion: '', + }, +} + +jest.mock('../data/hmppsAuthClient', () => { + return jest.fn().mockImplementation(() => { + return { + getSystemClientToken: jest.fn().mockImplementation(() => Promise.resolve('token-1')), + } + }) +}) +jest.mock('../data/masApiClient', () => { + return jest.fn().mockImplementation(() => { + return { + postPersonActivityLog: jest.fn().mockImplementation(() => Promise.resolve(mockPersonActivityResponse)), + } + }) +}) + +jest.mock('../data/tierApiClient', () => { + return jest.fn().mockImplementation(() => { + return { + getCalculationDetails: jest.fn().mockImplementation(() => Promise.resolve(mockTierCalculationResponse)), + } + }) +}) + +const hmppsAuthClient = new HmppsAuthClient(null) as jest.Mocked + +describe('/middleware/getPersonActivity', () => { + const req = { + body: {}, + params: {}, + query: {}, + session: {}, + method: 'GET', + } as Request + + const res = { + locals: { + filters: {}, + user: { + username: 'user-1', + }, + }, + redirect: jest.fn().mockReturnThis(), + } as unknown as AppResponse + + const filterVals = { + keywords: 'Some keywords', + dateFrom: '14/1/2025', + dateTo: '21/1/2025', + compliance: ['complied', 'not complied'], + } + + it('should request the filtered results from the api, if matching cache does not exist', async () => { + req.query = { page: '0' } + res.locals.filters = { + ...filterVals, + complianceOptions: [], + errors: null, + selectedFilterItems: [], + baseUrl: '', + query: { ...filterVals }, + queryStr: '', + queryStrPrefix: '', + queryStrSuffix: '', + maxDate: '21/1/2025', + } + + const [_tierCalculation, personActivity] = await getPersonActivity(req, res, hmppsAuthClient) + expect(personActivity).toEqual(mockPersonActivityResponse) + }) + it('should return the cached person activity data if matching cache exists', async () => { + req.session.cache = { + activityLog: { + ...(req?.session?.cache?.activityLog || {}), + results: [ + { + crn, + personActivity: mockPersonActivityResponse, + tierCalculation: mockTierCalculationResponse, + ...filterVals, + }, + ], + }, + } + const [_tierCalculation, personActivity] = await getPersonActivity(req, res, hmppsAuthClient) + expect(personActivity).toEqual(req.session.cache.activityLog.results[0].personActivity) + }) +}) diff --git a/server/middleware/getPersonActivity.ts b/server/middleware/getPersonActivity.ts index 1bfcdbd5..f05f4f21 100644 --- a/server/middleware/getPersonActivity.ts +++ b/server/middleware/getPersonActivity.ts @@ -1,7 +1,7 @@ import { Request } from 'express' import { HmppsAuthClient } from '../data' import MasApiClient from '../data/masApiClient' -import { ActivityLogCache, ActivityLogRequestBody, AppResponse } from '../@types' +import { ActivityLogCacheItem, ActivityLogRequestBody, AppResponse } from '../@types' import { PersonActivity } from '../data/model/activityLog' import { toISODate, toCamelCase } from '../utils/utils' import TierApiClient, { TierCalculation } from '../data/tierApiClient' @@ -23,7 +23,7 @@ export const getPersonActivity = async ( let personActivity: PersonActivity | null = null let tierCalculation: TierCalculation | null = null if (req?.session?.cache?.activityLog) { - const cache: ActivityLogCache | undefined = req.session.cache.activityLog.find( + const cache: ActivityLogCacheItem | undefined = req.session.cache.activityLog.results.find( cacheItem => crn === cacheItem.crn && keywords === cacheItem.keywords && @@ -49,8 +49,8 @@ export const getPersonActivity = async ( masClient.postPersonActivityLog(crn, body, page as string), tierClient.getCalculationDetails(crn), ]) - const newCache: ActivityLogCache[] = [ - ...(req?.session?.cache?.activityLog || []), + const newCache: ActivityLogCacheItem[] = [ + ...(req?.session?.cache?.activityLog?.results || []), { crn, keywords, @@ -63,7 +63,10 @@ export const getPersonActivity = async ( ] req.session.cache = { ...(req?.session?.cache || {}), - activityLog: newCache, + activityLog: { + ...(req?.session?.cache?.activityLog || {}), + results: newCache, + }, } } return [tierCalculation, personActivity]