github.com/twilio/twilio-go@v1.20.1/client/client_test.go (about) 1 package client_test 2 3 import ( 4 "encoding/json" 5 "io" 6 "net/http" 7 "net/http/httptest" 8 "net/url" 9 "os" 10 "regexp" 11 "strings" 12 "testing" 13 "time" 14 15 "github.com/stretchr/testify/assert" 16 twilio "github.com/twilio/twilio-go/client" 17 ) 18 19 var mockServer *httptest.Server 20 var testClient *twilio.Client 21 22 func NewClient(accountSid string, authToken string) *twilio.Client { 23 c := &twilio.Client{ 24 Credentials: twilio.NewCredentials(accountSid, authToken), 25 HTTPClient: http.DefaultClient, 26 } 27 28 return c 29 } 30 31 func TestMain(m *testing.M) { 32 mockServer = httptest.NewServer(http.HandlerFunc( 33 func(writer http.ResponseWriter, request *http.Request) { 34 d := map[string]interface{}{ 35 "response": "ok", 36 } 37 encoder := json.NewEncoder(writer) 38 _ = encoder.Encode(&d) 39 })) 40 defer mockServer.Close() 41 42 testClient = NewClient("user", "pass") 43 os.Exit(m.Run()) 44 } 45 46 func TestClient_SendRequestError(t *testing.T) { 47 errorResponse := `{ 48 "status": 400, 49 "code":20001, 50 "message":"Bad request", 51 "more_info":"https://www.twilio.com/docs/errors/20001" 52 }` 53 errorServer := httptest.NewServer(http.HandlerFunc( 54 func(resp http.ResponseWriter, req *http.Request) { 55 resp.WriteHeader(400) 56 _, _ = resp.Write([]byte(errorResponse)) 57 })) 58 defer errorServer.Close() 59 60 resp, err := testClient.SendRequest("GET", errorServer.URL, nil, nil) //nolint:bodyclose 61 twilioError := err.(*twilio.TwilioRestError) 62 assert.Nil(t, resp) 63 assert.Equal(t, 400, twilioError.Status) 64 assert.Equal(t, 20001, twilioError.Code) 65 assert.Equal(t, "https://www.twilio.com/docs/errors/20001", twilioError.MoreInfo) 66 assert.Equal(t, "Bad request", twilioError.Message) 67 assert.Nil(t, twilioError.Details) 68 } 69 70 func TestClient_SendRequestDecodeError(t *testing.T) { 71 errorResponse := `{ 72 "status": 400, 73 "code":20001, 74 "message":"Bad request", 75 "more_info":"https://www.twilio.com/docs/errors/20001", 76 }` 77 errorServer := httptest.NewServer(http.HandlerFunc( 78 func(resp http.ResponseWriter, req *http.Request) { 79 resp.WriteHeader(400) 80 _, _ = resp.Write([]byte(errorResponse)) 81 })) 82 defer errorServer.Close() 83 84 resp, err := testClient.SendRequest("GET", errorServer.URL, nil, nil) //nolint:bodyclose 85 assert.Error(t, err) 86 assert.Contains(t, err.Error(), "error decoding the response for an HTTP error code: 400") 87 assert.Nil(t, resp) 88 } 89 90 func TestClient_SendRequestErrorWithDetails(t *testing.T) { 91 errorResponse := []byte(`{ 92 "status": 400, 93 "message": "Bad request", 94 "code": 20001, 95 "more_info": "https://www.twilio.com/docs/errors/20001", 96 "details": { 97 "foo": "bar" 98 } 99 }`) 100 errorServer := httptest.NewServer(http.HandlerFunc( 101 func(resp http.ResponseWriter, req *http.Request) { 102 resp.WriteHeader(400) 103 _, _ = resp.Write(errorResponse) 104 })) 105 defer errorServer.Close() 106 107 resp, err := testClient.SendRequest("GET", errorServer.URL, nil, nil) //nolint:bodyclose 108 twilioError := err.(*twilio.TwilioRestError) 109 details := make(map[string]interface{}) 110 details["foo"] = "bar" 111 assert.Nil(t, resp) 112 assert.Equal(t, 400, twilioError.Status) 113 assert.Equal(t, 20001, twilioError.Code) 114 assert.Equal(t, "https://www.twilio.com/docs/errors/20001", twilioError.MoreInfo) 115 assert.Equal(t, "Bad request", twilioError.Message) 116 assert.Equal(t, details, twilioError.Details) 117 } 118 119 func TestClient_SendRequestUsernameError(t *testing.T) { 120 newTestClient := NewClient("user1\nuser2", "pass") 121 resp, err := newTestClient.SendRequest("GET", "http://example.org", nil, nil) //nolint:bodyclose 122 twilioError := err.(*twilio.TwilioRestError) 123 assert.Nil(t, resp) 124 assert.Equal(t, 400, twilioError.Status) 125 assert.Equal(t, 21222, twilioError.Code) 126 assert.Equal(t, "https://www.twilio.com/docs/errors/21222", twilioError.MoreInfo) 127 assert.Equal(t, "Invalid Username. Illegal chars", twilioError.Message) 128 } 129 130 func TestClient_SendRequestPasswordError(t *testing.T) { 131 newTestClient := NewClient("user1", "pass1\npass2") 132 resp, err := newTestClient.SendRequest("GET", "http://example.org", nil, nil) //nolint:bodyclose 133 twilioError := err.(*twilio.TwilioRestError) 134 assert.Nil(t, resp) 135 assert.Equal(t, 400, twilioError.Status) 136 assert.Equal(t, 21224, twilioError.Code) 137 assert.Equal(t, "https://www.twilio.com/docs/errors/21224", twilioError.MoreInfo) 138 assert.Equal(t, "Invalid Password. Illegal chars", twilioError.Message) 139 } 140 141 func TestClient_SendRequestWithRedirect(t *testing.T) { 142 redirectServer := httptest.NewServer(http.HandlerFunc( 143 func(writer http.ResponseWriter, request *http.Request) { 144 writer.WriteHeader(307) 145 _, _ = writer.Write([]byte(`{"redirect_to": "some_place"}`)) 146 })) 147 defer redirectServer.Close() 148 149 resp, _ := testClient.SendRequest("GET", redirectServer.URL, nil, nil) //nolint:bodyclose 150 assert.Equal(t, 307, resp.StatusCode) 151 } 152 153 func TestClient_SendRequestCreatesClient(t *testing.T) { 154 c := &twilio.Client{ 155 Credentials: twilio.NewCredentials("user", "pass"), 156 } 157 resp, err := c.SendRequest("GET", mockServer.URL, nil, nil) //nolint:bodyclose 158 assert.NoError(t, err) 159 assert.Equal(t, 200, resp.StatusCode) 160 } 161 162 func TestClient_SendRequestWithData(t *testing.T) { 163 dataServer := httptest.NewServer(http.HandlerFunc( 164 func(writer http.ResponseWriter, request *http.Request) { 165 _ = request.ParseForm() 166 assert.Equal(t, "bar", request.FormValue("foo")) 167 d := map[string]interface{}{ 168 "response": "ok", 169 } 170 encoder := json.NewEncoder(writer) 171 err := encoder.Encode(&d) 172 if err != nil { 173 t.Error(err) 174 } 175 })) 176 defer dataServer.Close() 177 178 tests := []string{http.MethodGet, http.MethodPost} 179 for _, tc := range tests { 180 t.Run(tc, func(t *testing.T) { 181 data := url.Values{} 182 data.Set("foo", "bar") 183 resp, err := testClient.SendRequest(tc, dataServer.URL, data, nil) //nolint:bodyclose 184 assert.NoError(t, err) 185 assert.Equal(t, 200, resp.StatusCode) 186 }) 187 } 188 } 189 190 func TestClient_SendRequestWithHeaders(t *testing.T) { 191 headerServer := httptest.NewServer(http.HandlerFunc( 192 func(writer http.ResponseWriter, request *http.Request) { 193 assert.Equal(t, "bar", request.Header.Get("foo")) 194 d := map[string]interface{}{ 195 "response": "ok", 196 } 197 encoder := json.NewEncoder(writer) 198 err := encoder.Encode(&d) 199 if err != nil { 200 t.Error(err) 201 } 202 })) 203 defer headerServer.Close() 204 205 headers := map[string]interface{}{ 206 "foo": "bar", 207 } 208 resp, err := testClient.SendRequest("GET", headerServer.URL, nil, headers) //nolint:bodyclose 209 assert.NoError(t, err) 210 assert.Equal(t, 200, resp.StatusCode) 211 } 212 213 func TestClient_SetTimeoutTimesOut(t *testing.T) { 214 timeoutServer := httptest.NewServer(http.HandlerFunc( 215 func(writer http.ResponseWriter, request *http.Request) { 216 d := map[string]interface{}{ 217 "response": "ok", 218 } 219 time.Sleep(100 * time.Microsecond) 220 encoder := json.NewEncoder(writer) 221 err := encoder.Encode(&d) 222 if err != nil { 223 t.Error(err) 224 } 225 writer.WriteHeader(http.StatusOK) 226 })) 227 defer timeoutServer.Close() 228 229 c := NewClient("user", "pass") 230 c.SetTimeout(10 * time.Microsecond) 231 _, err := c.SendRequest("GET", timeoutServer.URL, nil, nil) //nolint:bodyclose 232 assert.Error(t, err) 233 } 234 235 func TestClient_SetTimeoutSucceeds(t *testing.T) { 236 timeoutServer := httptest.NewServer(http.HandlerFunc( 237 func(writer http.ResponseWriter, request *http.Request) { 238 d := map[string]interface{}{ 239 "response": "ok", 240 } 241 time.Sleep(100 * time.Microsecond) 242 encoder := json.NewEncoder(writer) 243 err := encoder.Encode(&d) 244 if err != nil { 245 t.Error(err) 246 } 247 })) 248 defer timeoutServer.Close() 249 250 c := NewClient("user", "pass") 251 c.SetTimeout(10 * time.Second) 252 resp, err := c.SendRequest("GET", timeoutServer.URL, nil, nil) //nolint:bodyclose 253 assert.NoError(t, err) 254 assert.Equal(t, 200, resp.StatusCode) 255 } 256 257 func TestClient_SetTimeoutCreatesClient(t *testing.T) { 258 c := &twilio.Client{ 259 Credentials: twilio.NewCredentials("user", "pass"), 260 } 261 c.SetTimeout(20 * time.Second) 262 resp, err := c.SendRequest("GET", mockServer.URL, nil, nil) //nolint:bodyclose 263 assert.NoError(t, err) 264 assert.Equal(t, 200, resp.StatusCode) 265 } 266 267 func TestClient_UnicodeResponse(t *testing.T) { 268 unicodeServer := httptest.NewServer(http.HandlerFunc( 269 func(writer http.ResponseWriter, request *http.Request) { 270 d := map[string]interface{}{ 271 "testing-unicode": "Ω≈ç√, 💩", 272 } 273 encoder := json.NewEncoder(writer) 274 err := encoder.Encode(&d) 275 if err != nil { 276 t.Error(err) 277 } 278 })) 279 defer unicodeServer.Close() 280 281 c := NewClient("user", "pass") 282 resp, _ := c.SendRequest("GET", unicodeServer.URL, nil, nil) //nolint:bodyclose 283 assert.Equal(t, 200, resp.StatusCode) 284 body, _ := io.ReadAll(resp.Body) 285 assert.Equal(t, "{\"testing-unicode\":\"Ω≈ç√, 💩\"}\n", string(body)) 286 } 287 288 func TestClient_SetAccountSid(t *testing.T) { 289 client := NewClient("user", "pass") 290 client.SetAccountSid("account_sid") 291 assert.Equal(t, "account_sid", client.AccountSid()) 292 } 293 294 func TestClient_DefaultUserAgentHeaders(t *testing.T) { 295 headerServer := httptest.NewServer(http.HandlerFunc( 296 func(writer http.ResponseWriter, request *http.Request) { 297 assert.Regexp(t, regexp.MustCompile(`^twilio-go/[0-9.]+(-rc.[0-9])*\s\(\w+\s\w+\)\sgo/\S+$`), request.Header.Get("User-Agent")) 298 })) 299 300 resp, _ := testClient.SendRequest("GET", headerServer.URL, nil, nil) 301 assert.Equal(t, 200, resp.StatusCode) 302 } 303 304 func TestClient_UserAgentExtensionsHeaders(t *testing.T) { 305 var expectedExtensions = []string{"twilio-run/2.0.0-test", "flex-plugin/3.4.0"} 306 testClient.UserAgentExtensions = expectedExtensions 307 headerServer := httptest.NewServer(http.HandlerFunc( 308 func(writer http.ResponseWriter, request *http.Request) { 309 var headersList = strings.Split(request.Header.Get("User-Agent"), " ") 310 assert.Equal(t, headersList[len(headersList)-len(expectedExtensions):], expectedExtensions) 311 })) 312 resp, _ := testClient.SendRequest("GET", headerServer.URL, nil, nil) 313 assert.Equal(t, 200, resp.StatusCode) 314 }