Skip to content

Commit 513c984

Browse files
authored
Merge pull request #15 from aymenn/tests
Implement Unit Testing Framework
2 parents ec1f9f0 + 5723ef9 commit 513c984

File tree

7 files changed

+290
-186
lines changed

7 files changed

+290
-186
lines changed

src/config/retry.config.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export const retryConfig = {
2+
retries: 5,
3+
factor: 2,
4+
minTimeout: 1000,
5+
maxTimeout: 360000
6+
}

src/twilioClient.ts

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,26 @@
11
import twilio from "twilio";
22

3-
const { TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN } = process.env;
3+
let TWILIO_ACCOUNT_SID
4+
let TWILIO_AUTH_TOKEN
45

5-
if (!TWILIO_ACCOUNT_SID || !TWILIO_AUTH_TOKEN)
6+
if (process.env.NODE_ENV === "test") {
7+
TWILIO_ACCOUNT_SID = "ACabc"
8+
TWILIO_AUTH_TOKEN = "123"
9+
} else {
10+
TWILIO_ACCOUNT_SID = process.env.TWILIO_ACCOUNT_SID
11+
TWILIO_AUTH_TOKEN = process.env. TWILIO_AUTH_TOKEN
12+
}
13+
14+
15+
if (!TWILIO_ACCOUNT_SID || !TWILIO_AUTH_TOKEN) {
616
throw Error(
717
"TWILIO_ACCOUNT_SID &/or TWILIO_AUTH_TOKEN are missing from environment variables."
818
);
19+
}
920

1021
const client = twilio(
11-
process.env.TWILIO_ACCOUNT_SID,
12-
process.env.TWILIO_AUTH_TOKEN
22+
TWILIO_ACCOUNT_SID,
23+
TWILIO_AUTH_TOKEN
1324
);
1425

1526
export default client;

src/utils/createConversation.util.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,23 @@ import { SessionPostBody } from "../@types/types";
33
import client from "../twilioClient";
44

55
import retry from 'async-retry';
6+
import { retryConfig } from "../config/retry.config";
67

7-
export const createConversation = async (options: SessionPostBody) : Promise<ConversationInstance> => {
8+
9+
export const createConversation = async (options: SessionPostBody, retryOptions = retryConfig) : Promise<ConversationInstance> => {
810
return retry(async (quit) => {
911
try {
10-
const conversation = await client.conversations.conversations.create(options);
11-
return conversation;
12+
return client.conversations.conversations.create(options);
1213
} catch (err) {
1314
if (err.status !== 429) {
14-
quit(new Error(err));
15+
console.log('Quit without retry')
16+
console.log(err)
17+
quit(new Error('Quit without retry'));
1518
return;
1619
}
1720

1821
console.log('Re-trying on 429 error');
1922
throw new Error(err);
2023
}
21-
})
24+
}, retryOptions)
2225
}

tests/index.test.js

Lines changed: 0 additions & 3 deletions
This file was deleted.

tests/loadtest.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ const client = twilio(
99
process.env.TWILIO_AUTH_TOKEN
1010
);
1111

12+
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
13+
1214
async function makeRequest(contacts) {
1315
const body = { addresses: contacts }
1416

@@ -43,13 +45,17 @@ async function runTest() {
4345

4446
const promise = makeRequest(contacts)
4547
requests.push(promise);
48+
await sleep(2)
4649
}
4750

4851
results = await Promise.allSettled(requests);
4952
console.timeEnd('testCreate');
5053
} catch(e) {
5154
console.error(`failed ${JSON.stringify(e)}`);
5255
} finally {
56+
57+
const deletePromises = []
58+
5359
for (let i = 0; i < results.length; ++i) {
5460
const response = results[i];
5561

@@ -63,13 +69,23 @@ async function runTest() {
6369
if (response.value.sid) {
6470
console.log(`Removing conversation ${response.value.sid}`);
6571
}
66-
await client.conversations.conversations(response.value.sid).remove()
67-
72+
const deletePromise = client.conversations.conversations(response.value.sid).remove()
73+
deletePromises.push(deletePromise)
6874
}
6975
} catch(e){
7076
console.error(`Couldnt delete convo ${results[i]}: ${JSON.stringify(e)}`)
7177
}
78+
await sleep(50)
7279
}
80+
81+
try {
82+
await Promise.all(deletePromises)
83+
} catch (err) {
84+
console.log(err);
85+
}
86+
87+
console.log('Done cleaning up conversations')
88+
7389
}
7490
}
7591

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { createConversation } from "../../src/utils";
2+
import client from '../../src/twilioClient'
3+
4+
jest.mock('../../src/twilioClient')
5+
let mockedClient = jest.mocked(client, true)
6+
7+
describe('createConversation util', () => {
8+
beforeEach(() => {
9+
jest.resetAllMocks()
10+
})
11+
12+
it('it creates conversation with options passed', async () => {
13+
const createSpy = jest.fn((options) => { return options })
14+
mockedClient['conversations'] = {
15+
conversations: {
16+
create: (options) => createSpy(options)
17+
}
18+
} as any
19+
20+
const result = await createConversation({ friendlyName: "my conversation", addresses: ['1', '2'] })
21+
22+
expect(createSpy).toBeCalledWith({ friendlyName: "my conversation", addresses: ['1', '2'] })
23+
expect(result).toEqual({ friendlyName: "my conversation", addresses: ['1', '2'] })
24+
})
25+
26+
it('calls quit if error is not a 429 retry', async () => {
27+
mockedClient['conversations'] = {
28+
conversations: {
29+
create: (options) => {
30+
throw new Error('Twilio Problem')
31+
}
32+
}
33+
} as any
34+
35+
const consoleSpy = jest.spyOn(console, 'log');
36+
37+
try {
38+
await createConversation({ friendlyName: "my conversation", addresses: ['1', '2'] });
39+
} catch (e) {
40+
expect(consoleSpy).toHaveBeenCalledWith('Quit without retry');
41+
}
42+
})
43+
44+
it('throws error to retry on 429 status code', async () => {
45+
46+
interface TwilioError extends Error {
47+
status: number
48+
}
49+
50+
class TwilioError extends Error {
51+
constructor(message) {
52+
super(message);
53+
this.name = "ConcurrencyLimit";
54+
this.status = 429
55+
}
56+
}
57+
58+
mockedClient['conversations'] = {
59+
conversations: {
60+
create: (options) => {
61+
throw new TwilioError('Too many requests')
62+
}
63+
}
64+
} as any
65+
66+
const consoleSpy = jest.spyOn(console, 'log');
67+
68+
try {
69+
await createConversation(
70+
{ friendlyName: "my conversation", addresses: ['1', '2']},
71+
{ retries: 0, factor: 1, maxTimeout: 0, minTimeout: 0 });
72+
} catch (e) {
73+
expect(consoleSpy).toHaveBeenCalledWith('Re-trying on 429 error');
74+
}
75+
})
76+
})

0 commit comments

Comments
 (0)