Skip to content

Commit 3465396

Browse files
authored
test: Include a cluster test for Request Validator (#178)
* test: Include a cluster test for Request Validator
1 parent 1d186f5 commit 3465396

File tree

5 files changed

+134
-2
lines changed

5 files changed

+134
-2
lines changed

.github/workflows/test-and-deploy.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ jobs:
5757
TWILIO_API_SECRET: ${{ secrets.TWILIO_CLUSTER_TEST_API_KEY_SECRET }}
5858
TWILIO_FROM_NUMBER: ${{ secrets.TWILIO_FROM_NUMBER }}
5959
TWILIO_TO_NUMBER: ${{ secrets.TWILIO_TO_NUMBER }}
60+
TWILIO_AUTH_TOKEN: ${{ secrets.TWILIO_AUTH_TOKEN }}
6061
run: make cluster-test
6162

6263
- name: Run Test Coverage

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,7 +285,7 @@ func main() {
285285
]
286286
}`
287287

288-
definition := make(map[string]interface{})
288+
var definition interface{}
289289
_ = json.Unmarshal([]byte(jsonStr), &definition)
290290

291291
client := twilio.NewRestClient()

cluster_test.go

Lines changed: 129 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,20 @@
44
package twilio
55

66
import (
7+
"encoding/json"
8+
"fmt"
9+
"net/http"
710
"os"
811
"testing"
12+
"time"
913

14+
"github.com/localtunnel/go-localtunnel"
1015
"github.com/stretchr/testify/assert"
16+
twilio "github.com/twilio/twilio-go/client"
1117
Api "github.com/twilio/twilio-go/rest/api/v2010"
1218
ChatV2 "github.com/twilio/twilio-go/rest/chat/v2"
1319
EventsV1 "github.com/twilio/twilio-go/rest/events/v1"
20+
StudioV2 "github.com/twilio/twilio-go/rest/studio/v2"
1421
)
1522

1623
var from string
@@ -120,6 +127,127 @@ func TestListParams(t *testing.T) {
120127
assert.Nil(t, err)
121128
}
122129

130+
func createValidationServer(channel chan bool) *http.Server {
131+
server := &http.Server{}
132+
server.Handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
133+
url := r.Header["X-Forwarded-Proto"][0] + "://" + r.Header["X-Forwarded-Host"][0] + r.URL.RequestURI()
134+
signatureHeader := r.Header["X-Twilio-Signature"]
135+
r.ParseForm()
136+
params := make(map[string]string)
137+
for k, v := range r.PostForm {
138+
params[k] = v[0]
139+
}
140+
requestValidator := twilio.NewRequestValidator(os.Getenv("TWILIO_AUTH_TOKEN"))
141+
if len(signatureHeader) != 0 {
142+
channel <- requestValidator.Validate(url, params, r.Header["X-Twilio-Signature"][0])
143+
} else {
144+
channel <- false
145+
}
146+
})
147+
return server
148+
}
149+
150+
func createStudioFlowParams(url string, method string) *StudioV2.CreateFlowParams {
151+
jsonStr := fmt.Sprintf(`{
152+
"description": "Studio Flow",
153+
"states": [
154+
{
155+
"name": "Trigger",
156+
"type": "trigger",
157+
"transitions": [
158+
{
159+
"next": "httpRequest",
160+
"event": "incomingRequest"
161+
}
162+
],
163+
"properties": {
164+
}
165+
},
166+
{
167+
"name": "httpRequest",
168+
"type": "make-http-request",
169+
"transitions": [],
170+
"properties": {
171+
"method": "%s",
172+
"content_type": "application/x-www-form-urlencoded;charset=utf-8",
173+
"url": "%s"
174+
}
175+
}
176+
],
177+
"initial_state": "Trigger",
178+
"flags": {
179+
"allow_concurrent_calls": true
180+
}
181+
}`, method, url)
182+
183+
var definition interface{}
184+
_ = json.Unmarshal([]byte(jsonStr), &definition)
185+
186+
params := &StudioV2.CreateFlowParams{
187+
Definition: &definition,
188+
}
189+
params.SetFriendlyName("Go Cluster Test Flow")
190+
params.SetStatus("published")
191+
return params
192+
}
193+
194+
func createStudioExecutionParams() *StudioV2.CreateExecutionParams {
195+
executionParams := &StudioV2.CreateExecutionParams{}
196+
executionParams.SetTo("To")
197+
executionParams.SetFrom("From")
198+
return executionParams
199+
}
200+
201+
func executeFlow(t *testing.T, flowSid string) {
202+
_, exeErr := testClient.StudioV2.CreateExecution(flowSid, createStudioExecutionParams())
203+
if exeErr != nil {
204+
t.Fatal("Error with Studio Execution Creation: ", exeErr)
205+
}
206+
}
207+
208+
func requestValidation(t *testing.T, method string) {
209+
//Invoke Localtunnel
210+
listener, ltErr := localtunnel.Listen(localtunnel.Options{})
211+
if ltErr != nil {
212+
t.Fatal("Error with Localtunnel: ", ltErr)
213+
}
214+
//Create Validation Server & Listen
215+
channel := make(chan bool)
216+
server := createValidationServer(channel)
217+
go server.Serve(listener)
218+
219+
//Extra time for server to set up
220+
time.Sleep(1 * time.Second)
221+
222+
//Create Studio Flow
223+
params := createStudioFlowParams(listener.URL(), method)
224+
resp, flowErr := testClient.StudioV2.CreateFlow(params)
225+
if flowErr != nil {
226+
t.Fatal("Error with Studio Flow Creation: ", flowErr)
227+
}
228+
flowSid := *resp.Sid
229+
executeFlow(t, flowSid)
230+
231+
//Await for Request Validation
232+
afterCh := time.After(5 * time.Second)
233+
select {
234+
case validate := <-channel:
235+
assert.True(t, validate)
236+
case <-afterCh:
237+
t.Fatal("No request was sent to validation server")
238+
}
239+
defer testClient.StudioV2.DeleteFlow(flowSid)
240+
defer server.Close()
241+
}
242+
243+
func TestRequestValidation_GETMethod(t *testing.T) {
244+
requestValidation(t, "GET")
245+
}
246+
247+
func TestRequestValidation_POSTMethod(t *testing.T) {
248+
requestValidation(t, "POST")
249+
}
250+
123251
func TestListingAvailableNumber(t *testing.T) {
124252
params := &Api.ListAvailablePhoneNumberTollFreeParams{}
125253
params.SetLimit(2)
@@ -128,4 +256,4 @@ func TestListingAvailableNumber(t *testing.T) {
128256
assert.Nil(t, err)
129257
assert.NotNil(t, resp)
130258
assert.Equal(t, 2, len(resp))
131-
}
259+
}

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ require (
77
github.com/golang-jwt/jwt v3.2.2+incompatible
88
github.com/golang/mock v1.6.0
99
github.com/kr/text v0.2.0 // indirect
10+
github.com/localtunnel/go-localtunnel v0.0.0-20170326223115-8a804488f275 // indirect
1011
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
1112
github.com/pkg/errors v0.9.1
1213
github.com/stretchr/testify v1.7.0

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
1010
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
1111
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
1212
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
13+
github.com/localtunnel/go-localtunnel v0.0.0-20170326223115-8a804488f275 h1:IZycmTpoUtQK3PD60UYBwjaCUHUP7cML494ao9/O8+Q=
14+
github.com/localtunnel/go-localtunnel v0.0.0-20170326223115-8a804488f275/go.mod h1:zt6UU74K6Z6oMOYJbJzYpYucqdcQwSMPBEdSvGiaUMw=
1315
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
1416
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
1517
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=

0 commit comments

Comments
 (0)