Skip to content

Commit d1b3ff3

Browse files
authored
Merge pull request #24 from aymenn/controllers-tests-session
Controllers tests: session controller
2 parents 22715e1 + 8356d62 commit d1b3ff3

File tree

8 files changed

+494
-229
lines changed

8 files changed

+494
-229
lines changed

index.ts

Lines changed: 6 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,11 @@
1-
import cors from "cors";
2-
import express from "express";
3-
import createError from "http-errors";
4-
import logger from "morgan";
5-
import router from "./src/routes";
6-
import bodyParser from 'body-parser';
1+
import {app} from './src/app/app'
72

8-
const PORT = process.env.PORT || 3000;
9-
10-
const app = express();
11-
12-
/****************************************************
13-
Apply Middleware
14-
****************************************************/
15-
if (app.get("env") === "development") {
16-
app.use(cors({ origin: "*" }));
17-
app.use(logger("dev"));
18-
}
19-
20-
app.use(bodyParser.json())
21-
app.use(express.json());
22-
app.use(express.urlencoded({ extended: true }));
23-
24-
app.use(router);
25-
26-
/****************************************************
27-
Apply Routes
28-
****************************************************/
29-
app.use((req, res, next) => next(createError(404))); // throw 404 if route not found
3+
const PORT = process.env.PORT || 3000
304

315
/****************************************************
326
Start Server
33-
****************************************************/
7+
****************************************************/
8+
349
app.listen(PORT, () => {
35-
console.log(`Server running on port:${PORT}`);
36-
});
10+
console.log(`Server running on port:${PORT}`)
11+
})

jest.config.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
22
module.exports = {
33
preset: 'ts-jest',
4-
testEnvironment: 'node'
4+
testEnvironment: 'node',
5+
setupFiles: ['<rootDir>/tests/.jest/setEnvVars.js']
56
};

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"express": "^4.18.1",
88
"express-basic-auth": "^1.2.1",
99
"http-errors": "^2.0.0",
10+
"moq.ts": "^9.0.2",
1011
"morgan": "^1.10.0",
1112
"twilio": "^3.78.0"
1213
},
@@ -18,9 +19,11 @@
1819
"@types/jest": "^28.1.5",
1920
"@types/morgan": "^1.9.3",
2021
"@types/node": "^18.0.1",
22+
"@types/supertest": "^2.0.12",
2123
"jest": "^28.1.3",
2224
"node-fetch": "2",
2325
"nodemon": "^2.0.19",
26+
"supertest": "^6.2.4",
2427
"ts-jest": "^28.0.6",
2528
"ts-node": "^10.8.2",
2629
"typescript": "^4.7.4"

src/app/app.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import cors from 'cors'
2+
import express from 'express'
3+
import createError from 'http-errors'
4+
import logger from 'morgan'
5+
import bodyParser from 'body-parser'
6+
import router from '../routes'
7+
8+
9+
export const app = express()
10+
11+
/****************************************************
12+
Apply Middleware
13+
****************************************************/
14+
if (app.get('env') === 'development') {
15+
app.use(cors({origin: '*'}))
16+
app.use(logger('dev'))
17+
}
18+
19+
app.use(bodyParser.json())
20+
app.use(express.json())
21+
app.use(express.urlencoded({extended: true}))
22+
23+
app.use(router)
24+
25+
/****************************************************
26+
Apply Routes
27+
****************************************************/
28+
app.use((req, res, next) => next(createError(404))) // throw 404 if route not found

src/controllers/session.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export const post = async (
2222
try {
2323
await addParticipantsToConversation(conversation.sid, proxyAddresses)
2424
res.setHeader('content-type', 'application/json');
25-
return res.status(200).send(`${JSON.stringify(conversation)}`);
25+
return res.status(200).send({'conversationSid': conversation.sid});
2626
} catch(err) {
2727
await deleteConversation(conversation.sid);
2828
return res.status(500).send(`${conversation.sid} failed to create session: ${err}`)

tests/.jest/setEnvVars.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
process.env.NUMBER_POOL = '["+3334445555", "+4445556666", "+5556667777", "+6667778888"]'
2+
process.env.TWILIO_ACCOUNT_SID = 'ACXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
3+
process.env.TWILIO_AUTH_TOKEN = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
4+
process.env.AUTH_USERNAME = 'testUser'
5+
process.env.AUTH_PASSWORD = 'testPassword'
6+
process.env.AUTH_HEADER = 'Basic dGVzdFVzZXI6dGVzdFBhc3N3b3Jk'

tests/controllers/session.test.ts

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import request from 'supertest'
2+
import * as SessionService from '../../src/services/session.service'
3+
import {addParticipantsToConversation, matchAvailableProxyAddresses} from '../../src/services/session.service'
4+
import * as CreateConversation from '../../src/utils/createConversation.util'
5+
import * as DeleteConversation from '../../src/utils/deleteConversation.util'
6+
import {ConversationInstance} from 'twilio/lib/rest/conversations/v1/conversation'
7+
import {Mock} from 'moq.ts'
8+
import {app} from '../../src/app/app'
9+
10+
describe('sessions controller', () => {
11+
12+
jest.setTimeout(3600000)
13+
14+
15+
// Test parameters
16+
const requestedPhoneNumbers = ['+1001', '+1002']
17+
const activeProxyAddresses = {
18+
'+1001': ['+2001', '+2002'],
19+
'+1002': [],
20+
}
21+
const availableProxyAddresses = {
22+
'+1001': ['+2003', '+2004'],
23+
'+1002': ['+2001', '+2002', '+2003', '+2004'],
24+
}
25+
const conversationsSid = 'CHXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
26+
27+
// Mocks
28+
const getActiveProxyAddressesSpy = jest
29+
.spyOn(SessionService, 'getActiveProxyAddresses')
30+
.mockResolvedValue(activeProxyAddresses)
31+
32+
const matchAvailableProxyAddressesSpy = jest
33+
.spyOn(SessionService, 'matchAvailableProxyAddresses')
34+
.mockResolvedValue(availableProxyAddresses)
35+
36+
// Apparently with jest following is not possible, at least I couldn't find anything like this
37+
const mockedConversationInstance = new Mock<ConversationInstance>()
38+
.setup(instance => instance.sid)
39+
.returns(conversationsSid)
40+
.object()
41+
42+
const createConversationSpy = jest
43+
.spyOn(CreateConversation, 'createConversation')
44+
.mockResolvedValue(mockedConversationInstance)
45+
46+
createConversationSpy.mockResolvedValue(mockedConversationInstance)
47+
48+
// Tests
49+
it('should create a session', async () => {
50+
51+
const addParticipantsToConversationSpy = jest
52+
.spyOn(SessionService, 'addParticipantsToConversation')
53+
.mockResolvedValue([])
54+
55+
const res = await request(app)
56+
.post('/sessions')
57+
.set('Content-Type', 'application/json')
58+
.set('Authorization', process.env.AUTH_HEADER)
59+
.send({
60+
addresses: requestedPhoneNumbers,
61+
})
62+
63+
expect(res.status).toEqual(200)
64+
expect(getActiveProxyAddressesSpy).toBeCalledWith(requestedPhoneNumbers)
65+
expect(matchAvailableProxyAddressesSpy).toBeCalledWith(activeProxyAddresses)
66+
expect(createConversationSpy).toBeCalledWith({addresses: requestedPhoneNumbers})
67+
expect(addParticipantsToConversationSpy).toBeCalledWith(conversationsSid, availableProxyAddresses)
68+
})
69+
70+
it('should delete conversation on failure and return 500', async () => {
71+
72+
const addParticipantsToConversationSpy = jest
73+
.spyOn(SessionService, 'addParticipantsToConversation')
74+
.mockRejectedValue([])
75+
76+
const deleteConversationSpy = jest
77+
.spyOn(DeleteConversation, 'deleteConversation')
78+
.mockResolvedValue(true)
79+
80+
const res = await request(app)
81+
.post('/sessions')
82+
.set('content-type', 'application/json')
83+
.set('Authorization', process.env.AUTH_HEADER)
84+
.send({
85+
addresses: requestedPhoneNumbers,
86+
})
87+
88+
expect(res.status).toEqual(500)
89+
expect(getActiveProxyAddressesSpy).toBeCalledWith(requestedPhoneNumbers)
90+
expect(matchAvailableProxyAddressesSpy).toBeCalledWith(activeProxyAddresses)
91+
expect(createConversationSpy).toBeCalledWith({addresses: requestedPhoneNumbers})
92+
expect(addParticipantsToConversationSpy).toBeCalledWith(conversationsSid, availableProxyAddresses)
93+
expect(deleteConversationSpy).toBeCalledWith(conversationsSid)
94+
})
95+
})

0 commit comments

Comments
 (0)