Skip to content

Commit

Permalink
824: bugfix for level queryparam (#855)
Browse files Browse the repository at this point in the history
* Use query-types lib to parse request query params
* API tests for start endpoint
  • Loading branch information
chriswilty authored Mar 5, 2024
1 parent ee5bec5 commit a3cd818
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 11 deletions.
8 changes: 7 additions & 1 deletion backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
"memorystore": "^1.6.7",
"openai": "^4.19.0",
"openai-chat-tokens": "^0.2.8",
"pdf-parse": "^1.1.1"
"pdf-parse": "^1.1.1",
"query-types": "^0.1.4"
},
"devDependencies": {
"@jest/globals": "^29.7.0",
Expand Down
2 changes: 2 additions & 0 deletions backend/src/app.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import cors from 'cors';
import express from 'express';
import queryTypes from 'query-types';

import nonSessionRoutes from './nonSessionRoutes';
import sessionRoutes from './sessionRoutes';

export default express()
.use(express.json())
.use(queryTypes.middleware())
.use(
cors({
origin: process.env.CORS_ALLOW_ORIGIN,
Expand Down
7 changes: 5 additions & 2 deletions backend/src/controller/startController.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import { Response } from 'express';

import { StartGetRequest } from '@src/models/api/StartGetRequest';
import {
StartGetRequest,
StartResponse,
} from '@src/models/api/StartGetRequest';
import { LEVEL_NAMES, isValidLevel } from '@src/models/level';
import { getValidOpenAIModels } from '@src/openai';
import {
Expand Down Expand Up @@ -36,7 +39,7 @@ function handleStart(req: StartGetRequest, res: Response) {
defences: req.session.levelState[level].defences,
availableModels: getValidOpenAIModels(),
systemRoles,
});
} as StartResponse);
}

export { handleStart };
19 changes: 12 additions & 7 deletions backend/src/models/api/StartGetRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,20 @@ import { Defence } from '@src/models/defence';
import { EmailInfo } from '@src/models/email';
import { LEVEL_NAMES } from '@src/models/level';

export type StartResponse = {
emails: EmailInfo[];
chatHistory: ChatMessage[];
defences: Defence[];
availableModels: string[];
systemRoles: {
level: LEVEL_NAMES;
systemRole: string;
}[];
};

export type StartGetRequest = Request<
never,
{
emails: EmailInfo[];
chatHistory: ChatMessage[];
defences: Defence[];
availableModels: string[];
systemRoles: string[];
},
StartResponse,
never,
{
level?: LEVEL_NAMES;
Expand Down
54 changes: 54 additions & 0 deletions backend/test/api/start.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { beforeAll, describe, expect, it, jest } from '@jest/globals';
import { OpenAI } from 'openai';
import request from 'supertest';

import app from '@src/app';
import { StartResponse } from '@src/models/api/StartGetRequest';
import { LEVEL_NAMES } from '@src/models/level';

jest.mock('openai');

const PATH = '/start';

describe('/start endpoints', () => {
const mockListFn = jest.fn<OpenAI.Models['list']>();
jest.mocked(OpenAI).mockImplementation(
() =>
({
models: {
list: mockListFn,
},
} as unknown as jest.MockedObject<OpenAI>)
);

beforeAll(() => {
mockListFn.mockResolvedValue({
data: [{ id: 'gpt-3.5-turbo' }],
} as OpenAI.ModelsPage);
});

it.each(Object.values(LEVEL_NAMES))(
'WHEN given valid level [%s] THEN it responds with 200',
async (level) =>
request(app)
.get(`${PATH}?level=${level}`)
.expect(200)
.expect('Content-Type', /application\/json/)
.then((response) => {
const { chatHistory, emails } = response.body as StartResponse;
expect(chatHistory).toEqual([]);
expect(emails).toEqual([]);
})
);

it.each([-1, 4, 'SANDBOX'])(
'WHEN given invalid level [%s] THEN it responds with 400',
async (level) =>
request(app)
.get(`${PATH}?level=${level}`)
.expect(400)
.then((response) => {
expect(response.text).toEqual('Invalid level');
})
);
});
1 change: 1 addition & 0 deletions backend/test/setupEnvVars.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
// set the environment variables
process.env.OPENAI_API_KEY = 'sk-12345';
process.env.SESSION_SECRET = "shhh! Don't tell anyone...";
5 changes: 5 additions & 0 deletions backend/typings/query-types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
declare module 'query-types' {
import type { NextHandleFunction } from 'connect';

function middleware(): NextHandleFunction;
}

0 comments on commit a3cd818

Please sign in to comment.