From fe97049d1a666ca5832cec67427883dabd43ae60 Mon Sep 17 00:00:00 2001 From: Chris Wilton-Magras Date: Thu, 25 Jan 2024 17:32:59 +0000 Subject: [PATCH] Prevent mutating state reset template (#798) --- backend/src/app.ts | 4 ++-- backend/src/controller/resetController.ts | 4 ++-- backend/src/models/level.ts | 23 +++++++++++-------- .../unit/controller/resetController.test.ts | 12 ++++++---- 4 files changed, 26 insertions(+), 17 deletions(-) diff --git a/backend/src/app.ts b/backend/src/app.ts index 22bfea7a3..642eeef05 100644 --- a/backend/src/app.ts +++ b/backend/src/app.ts @@ -7,7 +7,7 @@ import { fileURLToPath } from 'node:url'; import { importMetaUrl } from './importMetaUtils'; import { ChatModel, defaultChatModel } from './models/chat'; -import { LevelState, levelsInitialState } from './models/level'; +import { LevelState, getInitialLevelStates } from './models/level'; import { router } from './router'; dotenv.config(); @@ -55,7 +55,7 @@ app.use((req, _res, next) => { // initialise session variables first time if (!req.session.initialised) { req.session.chatModel = defaultChatModel; - req.session.levelState = levelsInitialState; + req.session.levelState = getInitialLevelStates(); req.session.initialised = true; } next(); diff --git a/backend/src/controller/resetController.ts b/backend/src/controller/resetController.ts index 0e697e9e2..b6d974921 100644 --- a/backend/src/controller/resetController.ts +++ b/backend/src/controller/resetController.ts @@ -1,10 +1,10 @@ import { Request, Response } from 'express'; -import { levelsInitialState } from '@src/models/level'; +import { getInitialLevelStates } from '@src/models/level'; function handleResetProgress(req: Request, res: Response) { console.debug('Resetting progress for all levels', req.session.levelState); - req.session.levelState = levelsInitialState; + req.session.levelState = getInitialLevelStates(); res.send(req.session.levelState); } diff --git a/backend/src/models/level.ts b/backend/src/models/level.ts index 0b862ac06..6659e4932 100644 --- a/backend/src/models/level.ts +++ b/backend/src/models/level.ts @@ -18,14 +18,19 @@ interface LevelState { sentEmails: EmailInfo[]; } -const levelsInitialState = Object.values(LEVEL_NAMES) - .filter((value) => Number.isNaN(Number(value))) - .map((value) => ({ - level: value as LEVEL_NAMES, - chatHistory: [], - defences: defaultDefences, - sentEmails: [], - })); +function getInitialLevelStates() { + return Object.values(LEVEL_NAMES) + .filter((value) => Number.isNaN(Number(value))) + .map( + (value) => + ({ + level: value as LEVEL_NAMES, + chatHistory: [], + defences: defaultDefences, + sentEmails: [], + } as LevelState) + ); +} -export { LEVEL_NAMES, levelsInitialState }; +export { LEVEL_NAMES, getInitialLevelStates }; export type { LevelState }; diff --git a/backend/test/unit/controller/resetController.test.ts b/backend/test/unit/controller/resetController.test.ts index fd280fc5d..cb5a98f6c 100644 --- a/backend/test/unit/controller/resetController.test.ts +++ b/backend/test/unit/controller/resetController.test.ts @@ -10,7 +10,11 @@ import { } from '@src/models/chat'; import { DEFENCE_ID, Defence, DefenceConfigItem } from '@src/models/defence'; import { EmailInfo } from '@src/models/email'; -import { LEVEL_NAMES, LevelState, levelsInitialState } from '@src/models/level'; +import { + LEVEL_NAMES, + LevelState, + getInitialLevelStates, +} from '@src/models/level'; declare module 'express-session' { interface Session { @@ -69,7 +73,7 @@ describe('handleResetProgress unit tests', () => { const res = responseMock(); handleResetProgress(reqWithChatHistory, res); - expect(res.send).toHaveBeenCalledWith(levelsInitialState); + expect(res.send).toHaveBeenCalledWith(getInitialLevelStates()); }); test('GIVEN sent emails THEN should reset emails for all levels', () => { @@ -84,7 +88,7 @@ describe('handleResetProgress unit tests', () => { const res = responseMock(); handleResetProgress(reqWithSentEmails, res); - expect(res.send).toHaveBeenCalledWith(levelsInitialState); + expect(res.send).toHaveBeenCalledWith(getInitialLevelStates()); }); test('GIVEN defences THEN should reset defences for levels', () => { @@ -116,6 +120,6 @@ describe('handleResetProgress unit tests', () => { const res = responseMock(); handleResetProgress(reqWithDefences, res); - expect(res.send).toHaveBeenCalledWith(levelsInitialState); + expect(res.send).toHaveBeenCalledWith(getInitialLevelStates()); }); });