Skip to content

Commit ee42b35

Browse files
author
Ace Nassri
authored
Update Twilio sample + add (unit) tests (#1268)
* Update Twilio sample + add tests * Remove linter
1 parent dc69ebf commit ee42b35

File tree

3 files changed

+118
-24
lines changed

3 files changed

+118
-24
lines changed

appengine/twilio/app.js

Lines changed: 25 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2016, Google, Inc.
2+
* Copyright 2019, Google LLC.
33
* Licensed under the Apache License, Version 2.0 (the "License");
44
* you may not use this file except in compliance with the License.
55
* You may obtain a copy of the License at
@@ -15,7 +15,6 @@
1515

1616
'use strict';
1717

18-
const format = require('util').format;
1918
const express = require('express');
2019
const bodyParser = require('body-parser').urlencoded({
2120
extended: false,
@@ -33,12 +32,14 @@ if (!TWILIO_NUMBER) {
3332
);
3433
}
3534

36-
const twilio = require('twilio')(
35+
const Twilio = require('twilio');
36+
37+
const twilioClient = Twilio(
3738
process.env.TWILIO_ACCOUNT_SID,
3839
process.env.TWILIO_AUTH_TOKEN
3940
);
4041

41-
const TwimlResponse = require('twilio').TwimlResponse;
42+
const TwimlResponse = Twilio.TwimlResponse;
4243

4344
// [START gae_flex_twilio_receive_call]
4445
app.post('/call/receive', (req, res) => {
@@ -53,7 +54,7 @@ app.post('/call/receive', (req, res) => {
5354
// [END gae_flex_twilio_receive_call]
5455

5556
// [START gae_flex_twilio_send_sms]
56-
app.get('/sms/send', (req, res, next) => {
57+
app.get('/sms/send', async (req, res, next) => {
5758
const to = req.query.to;
5859
if (!to) {
5960
res
@@ -62,20 +63,18 @@ app.get('/sms/send', (req, res, next) => {
6263
return;
6364
}
6465

65-
twilio.sendMessage(
66-
{
66+
try {
67+
await twilioClient.messages.create({
6768
to: to,
6869
from: TWILIO_NUMBER,
6970
body: 'Hello from Google App Engine',
70-
},
71-
err => {
72-
if (err) {
73-
next(err);
74-
return;
75-
}
76-
res.status(200).send('Message sent.');
77-
}
78-
);
71+
});
72+
console.log('BAZ!');
73+
res.status(200).send('Message sent.');
74+
} catch (err) {
75+
next(err);
76+
return;
77+
}
7978
});
8079
// [END gae_flex_twilio_send_sms]
8180

@@ -85,7 +84,7 @@ app.post('/sms/receive', bodyParser, (req, res) => {
8584
const body = req.body.Body;
8685

8786
const resp = new TwimlResponse();
88-
resp.message(format('Hello, %s, you said: %s', sender, body));
87+
resp.message(`Hello, ${sender}, you said: ${body}`);
8988

9089
res
9190
.status(200)
@@ -95,8 +94,12 @@ app.post('/sms/receive', bodyParser, (req, res) => {
9594
// [END gae_flex_twilio_receive_sms]
9695

9796
// Start the server
98-
const PORT = process.env.PORT;
99-
app.listen(PORT, () => {
100-
console.log(`App listening on port ${PORT}`);
101-
console.log('Press Ctrl+C to quit.');
102-
});
97+
if (module === require.main) {
98+
const PORT = process.env.PORT || 8080;
99+
app.listen(PORT, () => {
100+
console.log(`App listening on port ${PORT}`);
101+
console.log('Press Ctrl+C to quit.');
102+
});
103+
}
104+
105+
exports.app = app;

appengine/twilio/package.json

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,19 @@
99
"node": ">=8"
1010
},
1111
"scripts": {
12-
"start": "node app.js"
12+
"start": "node app.js",
13+
"test": "mocha test/*.test.js"
1314
},
1415
"dependencies": {
1516
"body-parser": "^1.18.3",
1617
"express": "^4.16.4",
17-
"twilio": "^3.28.0"
18+
"twilio": "^3.30.3"
19+
},
20+
"devDependencies": {
21+
"assert": "^1.4.1",
22+
"mocha": "^6.1.4",
23+
"proxyquire": "^2.1.0",
24+
"sinon": "^7.3.2",
25+
"supertest": "^4.0.2"
1826
}
1927
}

appengine/twilio/test/app.test.js

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
/**
2+
* Copyright 2019, Google LLC.
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
'use strict';
17+
18+
const assert = require('assert');
19+
const Supertest = require('supertest');
20+
const sinon = require('sinon');
21+
const proxyquire = require('proxyquire').noCallThru();
22+
23+
const getSample = () => {
24+
const twilioMock = {
25+
messages: {
26+
create: sinon.stub().resolves(),
27+
},
28+
message: sinon.stub(),
29+
say: sinon.stub(),
30+
toString: sinon.stub(),
31+
};
32+
33+
const twilioStub = sinon.stub().returns(twilioMock);
34+
twilioStub.TwimlResponse = sinon.stub().returns(twilioMock);
35+
36+
const {app} = proxyquire('../app', {twilio: twilioStub});
37+
38+
return {
39+
supertest: Supertest(app, {
40+
twilio: twilioStub,
41+
}),
42+
mocks: {
43+
twilio: twilioMock,
44+
},
45+
};
46+
};
47+
48+
it('should send an SMS message', async () => {
49+
const {supertest} = getSample();
50+
51+
return supertest
52+
.get('/sms/send')
53+
.query({to: 1234})
54+
.expect(200)
55+
.expect(response => {
56+
assert.strictEqual(response.text, 'Message sent.');
57+
});
58+
});
59+
60+
it('should receive an SMS message', async () => {
61+
const {supertest, mocks} = getSample();
62+
63+
return supertest
64+
.post('/sms/receive')
65+
.send({From: 'Bob', Body: 'hi'})
66+
.type('form')
67+
.expect(200)
68+
.expect(() => {
69+
assert(mocks.twilio.message.calledWith('Hello, Bob, you said: hi'));
70+
});
71+
});
72+
73+
it('should receive a call', async () => {
74+
const {supertest, mocks} = getSample();
75+
76+
return supertest
77+
.post('/call/receive')
78+
.send()
79+
.expect(200)
80+
.expect(() => {
81+
assert(mocks.twilio.say.calledWith('Hello from Google App Engine.'));
82+
});
83+
});

0 commit comments

Comments
 (0)