Skip to content

Commit

Permalink
Allow outgoing tests to check multiple requests
Browse files Browse the repository at this point in the history
  • Loading branch information
rowanseymour committed Sep 29, 2023
1 parent e4f20bf commit c38b30f
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 80 deletions.
29 changes: 20 additions & 9 deletions handlers/africastalking/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package africastalking

import (
"net/http/httptest"
"net/url"
"testing"
"time"

Expand Down Expand Up @@ -123,7 +124,9 @@ var outgoingTestCases = []OutgoingTestCase{
MockResponseBody: `{ "SMSMessageData": {"Recipients": [{"status": "Success", "messageId": "1002"}] } }`,
MockResponseStatus: 200,
ExpectedHeaders: map[string]string{"apikey": "KEY"},
ExpectedPostParams: map[string]string{"message": "Simple Message ☺", "username": "Username", "to": "+250788383383", "from": "2020"},
ExpectedRequests: []ExpectedRequest{
{Form: url.Values{"message": {"Simple Message ☺"}, "username": {"Username"}, "to": {"+250788383383"}, "from": {"2020"}}},
},
ExpectedMsgStatus: "W",
ExpectedExternalID: "1002",
SendPrep: setSendURL,
Expand All @@ -135,7 +138,9 @@ var outgoingTestCases = []OutgoingTestCase{
MsgAttachments: []string{"image/jpeg:https://foo.bar/image.jpg"},
MockResponseBody: `{ "SMSMessageData": {"Recipients": [{"status": "Success", "messageId": "1002"}] } }`,
MockResponseStatus: 200,
ExpectedPostParams: map[string]string{"message": "My pic!\nhttps://foo.bar/image.jpg"},
ExpectedRequests: []ExpectedRequest{
{Form: url.Values{"message": {"My pic!\nhttps://foo.bar/image.jpg"}, "username": {"Username"}, "to": {"+250788383383"}, "from": {"2020"}}},
},
ExpectedMsgStatus: "W",
ExpectedExternalID: "1002",
SendPrep: setSendURL,
Expand All @@ -146,19 +151,23 @@ var outgoingTestCases = []OutgoingTestCase{
MsgURN: "tel:+250788383383",
MockResponseBody: `{ "SMSMessageData": {"Recipients": [{"status": "Failed" }] } }`,
MockResponseStatus: 200,
ExpectedPostParams: map[string]string{"message": `No External ID`},
ExpectedMsgStatus: "E",
SendPrep: setSendURL,
ExpectedRequests: []ExpectedRequest{
{Form: url.Values{"message": {`No External ID`}, "username": {"Username"}, "to": {"+250788383383"}, "from": {"2020"}}},
},
ExpectedMsgStatus: "E",
SendPrep: setSendURL,
},
{
Label: "Error Sending",
MsgText: "Error Message",
MsgURN: "tel:+250788383383",
MockResponseBody: `{ "error": "failed" }`,
MockResponseStatus: 401,
ExpectedPostParams: map[string]string{"message": `Error Message`},
ExpectedMsgStatus: "E",
SendPrep: setSendURL,
ExpectedRequests: []ExpectedRequest{
{Form: url.Values{"message": {`Error Message`}, "username": {"Username"}, "to": {"+250788383383"}, "from": {"2020"}}},
},
ExpectedMsgStatus: "E",
SendPrep: setSendURL,
},
}

Expand All @@ -170,7 +179,9 @@ var sharedSendTestCases = []OutgoingTestCase{
MockResponseBody: `{ "SMSMessageData": {"Recipients": [{"status": "Success", "messageId": "1002"}] } }`,
MockResponseStatus: 200,
ExpectedHeaders: map[string]string{"apikey": "KEY"},
ExpectedPostParams: map[string]string{"message": "Simple Message ☺", "username": "Username", "to": "+250788383383", "from": ""},
ExpectedRequests: []ExpectedRequest{
{Form: url.Values{"message": {"Simple Message ☺"}, "username": {"Username"}, "to": {"+250788383383"}}},
},
ExpectedMsgStatus: "W",
ExpectedExternalID: "1002",
SendPrep: setSendURL,
Expand Down
21 changes: 13 additions & 8 deletions handlers/arabiacell/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package arabiacell

import (
"net/http/httptest"
"net/url"
"testing"

"github.com/nyaruka/courier"
Expand Down Expand Up @@ -60,14 +61,18 @@ var defaultSendTestCases = []OutgoingTestCase{
<message_id>external1</message_id>
</response>`,
MockResponseStatus: 200,
ExpectedPostParams: map[string]string{
"userName": "user1",
"password": "pass1",
"handlerType": "send_msg",
"serviceId": "service1",
"msisdn": "+250788383383",
"messageBody": "Simple Message ☺\nhttps://foo.bar/image.jpg",
"chargingLevel": "0",
ExpectedRequests: []ExpectedRequest{
{
Form: url.Values{
"userName": {"user1"},
"password": {"pass1"},
"handlerType": {"send_msg"},
"serviceId": {"service1"},
"msisdn": {"+250788383383"},
"messageBody": {"Simple Message ☺\nhttps://foo.bar/image.jpg"},
"chargingLevel": {"0"},
},
},
},
ExpectedMsgStatus: "W",
ExpectedExternalID: "external1",
Expand Down
13 changes: 9 additions & 4 deletions handlers/burstsms/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package burstsms

import (
"net/http/httptest"
"net/url"
"testing"

"github.com/nyaruka/courier"
Expand Down Expand Up @@ -69,10 +70,14 @@ var defaultSendTestCases = []OutgoingTestCase{
MsgAttachments: []string{"image/jpeg:https://foo.bar/image.jpg"},
MockResponseBody: `{ "message_id": 19835, "recipients": 3, "cost": 1.000 }`,
MockResponseStatus: 200,
ExpectedPostParams: map[string]string{
"to": "250788383383",
"message": "Simple Message ☺\nhttps://foo.bar/image.jpg",
"from": "2020",
ExpectedRequests: []ExpectedRequest{
{
Form: url.Values{
"to": {"250788383383"},
"message": {"Simple Message ☺\nhttps://foo.bar/image.jpg"},
"from": {"2020"},
},
},
},
ExpectedMsgStatus: "W",
ExpectedExternalID: "19835",
Expand Down
15 changes: 10 additions & 5 deletions handlers/i2sms/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package i2sms

import (
"net/http/httptest"
"net/url"
"testing"

"github.com/nyaruka/courier"
Expand Down Expand Up @@ -57,11 +58,15 @@ var defaultSendTestCases = []OutgoingTestCase{
MsgAttachments: []string{"image/jpeg:https://foo.bar/image.jpg"},
MockResponseBody: `{"result":{"session_id":"5b8fc97d58795484819426"}, "error_code": "00", "error_desc": "Success"}`,
MockResponseStatus: 200,
ExpectedPostParams: map[string]string{
"action": "send_single",
"mobile": "250788383383",
"message": "Simple Message ☺\nhttps://foo.bar/image.jpg",
"channel": "hash123",
ExpectedRequests: []ExpectedRequest{
{
Form: url.Values{
"action": {"send_single"},
"mobile": {"250788383383"},
"message": {"Simple Message ☺\nhttps://foo.bar/image.jpg"},
"channel": {"hash123"},
},
},
},
ExpectedMsgStatus: "W",
ExpectedExternalID: "5b8fc97d58795484819426",
Expand Down
125 changes: 83 additions & 42 deletions handlers/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,38 @@ func RunIncomingTestCases(t *testing.T, channels []courier.Channel, handler cour
// SendPrepFunc allows test cases to modify the channel, msg or server before a message is sent
type SendPrepFunc func(*httptest.Server, courier.ChannelHandler, courier.Channel, courier.MsgOut)

type ExpectedRequest struct {
Headers map[string]string
Path string
Params map[string]string
Form url.Values
Body string
}

func (e *ExpectedRequest) AssertMatches(t *testing.T, actual *http.Request, requestNum int) {
if e.Headers != nil {
for k, v := range e.Headers {
assert.Equal(t, v, actual.Header.Get(k), "header %s mismatch for request %d", k, requestNum)
}
}
if e.Path != "" {
assert.Equal(t, e.Path, actual.URL.Path, "patch mismatch for request %d", requestNum)
}
if e.Params != nil {
for k, v := range e.Params {
assert.Equal(t, v, actual.URL.Query().Get(k), "URL param %s mismatch for request %d", requestNum)
}
}
if e.Form != nil {
actual.ParseMultipartForm(32 << 20)
assert.Equal(t, e.Form, actual.PostForm, "form mismatch for request %d", requestNum)
}
if e.Body != "" {
value, _ := io.ReadAll(actual.Body)
assert.Equal(t, e.Body, strings.Trim(string(value), "\n"), "body mismatch for request %d", requestNum)
}
}

// OutgoingTestCase defines the test values for a particular test case
type OutgoingTestCase struct {
Label string
Expand All @@ -292,18 +324,20 @@ type OutgoingTestCase struct {
MockResponseBody string
MockResponses map[MockedRequest]*httpx.MockResponse

ExpectedRequestPath string
ExpectedURLParams map[string]string
ExpectedPostParams map[string]string // deprecated, use ExpectedPostForm
ExpectedPostForm url.Values
ExpectedRequestBody string
ExpectedHeaders map[string]string
ExpectedRequests []ExpectedRequest
ExpectedMsgStatus courier.MsgStatus
ExpectedExternalID string
ExpectedErrors []*courier.ChannelError
ExpectedStopEvent bool
ExpectedContactURNs map[string]bool
ExpectedNewURN string

// deprecated, use ExpectedRequests
ExpectedRequestPath string
ExpectedURLParams map[string]string
ExpectedPostParams map[string]string
ExpectedRequestBody string
ExpectedHeaders map[string]string
}

// RunOutgoingTestCases runs all the passed in test cases against the channel
Expand Down Expand Up @@ -347,11 +381,13 @@ func RunOutgoingTestCases(t *testing.T, channel courier.Channel, handler courier
msg.WithOptIn(tc.MsgOptIn)
}

var testRequest *http.Request
actualRequests := make([]*http.Request, 0, 1)
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// copy request and add to list
body, _ := io.ReadAll(r.Body)
testRequest = httptest.NewRequest(r.Method, r.URL.String(), bytes.NewBuffer(body))
testRequest.Header = r.Header
copy := httptest.NewRequest(r.Method, r.URL.String(), bytes.NewBuffer(body))
copy.Header = r.Header
actualRequests = append(actualRequests, copy)

if (len(tc.MockResponses)) == 0 {
w.WriteHeader(tc.MockResponseStatus)
Expand Down Expand Up @@ -387,49 +423,54 @@ func RunOutgoingTestCases(t *testing.T, channel courier.Channel, handler courier

assert.Equal(t, tc.ExpectedErrors, clog.Errors(), "unexpected errors logged")

if tc.ExpectedRequestPath != "" {
require.NotNil(testRequest, "path should not be nil")
require.Equal(tc.ExpectedRequestPath, testRequest.URL.Path)
}
if tc.ExpectedRequestPath != "" || tc.ExpectedURLParams != nil || tc.ExpectedPostParams != nil || tc.ExpectedRequestBody != "" || tc.ExpectedHeaders != nil {
testRequest := actualRequests[len(actualRequests)-1]

if tc.ExpectedURLParams != nil {
require.NotNil(testRequest)
for k, v := range tc.ExpectedURLParams {
value := testRequest.URL.Query().Get(k)
require.Equal(v, value, fmt.Sprintf("%s not equal", k))
if tc.ExpectedRequestPath != "" {
require.NotNil(testRequest, "path should not be nil")
require.Equal(tc.ExpectedRequestPath, testRequest.URL.Path)
}
}

if tc.ExpectedPostParams != nil {
require.NotNil(testRequest, "post body should not be nil")
for k, v := range tc.ExpectedPostParams {
value := testRequest.PostFormValue(k)
require.Equal(v, value)
if tc.ExpectedURLParams != nil {
require.NotNil(testRequest)
for k, v := range tc.ExpectedURLParams {
value := testRequest.URL.Query().Get(k)
require.Equal(v, value, fmt.Sprintf("%s not equal", k))
}
}
} else if tc.ExpectedPostForm != nil {
require.NotNil(testRequest, "post body should not be nil")
testRequest.ParseMultipartForm(32 << 20)
assert.Equal(t, tc.ExpectedPostForm, testRequest.PostForm)
}
if tc.ExpectedPostParams != nil {
require.NotNil(testRequest, "post body should not be nil")
for k, v := range tc.ExpectedPostParams {
value := testRequest.PostFormValue(k)
require.Equal(v, value)
}
}
if tc.ExpectedRequestBody != "" {
require.NotNil(testRequest, "request body should not be nil")
value, _ := io.ReadAll(testRequest.Body)
require.Equal(tc.ExpectedRequestBody, strings.Trim(string(value), "\n"))
}
if tc.ExpectedHeaders != nil {
require.NotNil(testRequest, "headers should not be nil")
for k, v := range tc.ExpectedHeaders {
value := testRequest.Header.Get(k)
require.Equal(v, value)
}
}
} else if len(tc.ExpectedRequests) > 0 {
assert.Len(t, actualRequests, len(tc.ExpectedRequests), "unexpected number of requests made")

if tc.ExpectedRequestBody != "" {
require.NotNil(testRequest, "request body should not be nil")
value, _ := io.ReadAll(testRequest.Body)
require.Equal(tc.ExpectedRequestBody, strings.Trim(string(value), "\n"))
for i, expectedRequest := range tc.ExpectedRequests {
if (len(actualRequests) - 1) < i {
break
}
expectedRequest.AssertMatches(t, actualRequests[i], i)
}
}

if (len(tc.MockResponses)) != 0 {
assert.Equal(t, len(tc.MockResponses), mockRRCount, "mocked request count mismatch")
}

if tc.ExpectedHeaders != nil {
require.NotNil(testRequest, "headers should not be nil")
for k, v := range tc.ExpectedHeaders {
value := testRequest.Header.Get(k)
require.Equal(v, value)
}
}

if tc.ExpectedExternalID != "" {
require.Equal(tc.ExpectedExternalID, status.ExternalID())
}
Expand Down
32 changes: 20 additions & 12 deletions handlers/twiml/handlers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -631,12 +631,16 @@ var defaultSendTestCases = []OutgoingTestCase{
MsgAttachments: []string{"image/jpeg:https://foo.bar/image.jpg"},
MockResponseBody: `{ "sid": "1002" }`,
MockResponseStatus: 200,
ExpectedPostForm: url.Values{
"Body": []string{"My pic!"},
"To": []string{"+250788383383"},
"MediaUrl": []string{"https://foo.bar/image.jpg"},
"From": []string{"2020"},
"StatusCallback": []string{"https://localhost/c/t/8eb23e93-5ecb-45ba-b726-3b064e0c56ab/status?id=10&action=callback"},
ExpectedRequests: []ExpectedRequest{
{
Form: url.Values{
"Body": []string{"My pic!"},
"To": []string{"+250788383383"},
"MediaUrl": []string{"https://foo.bar/image.jpg"},
"From": []string{"2020"},
"StatusCallback": []string{"https://localhost/c/t/8eb23e93-5ecb-45ba-b726-3b064e0c56ab/status?id=10&action=callback"},
},
},
},
ExpectedMsgStatus: "W",
SendPrep: setSendURL,
Expand All @@ -647,12 +651,16 @@ var defaultSendTestCases = []OutgoingTestCase{
MsgAttachments: []string{"image/jpeg:https://foo.bar/image.jpg", "audio/mp4:https://foo.bar/audio.m4a"},
MockResponseBody: `{ "sid": "1002" }`,
MockResponseStatus: 200,
ExpectedPostForm: url.Values{
"Body": []string{""},
"To": []string{"+250788383383"},
"MediaUrl": []string{"https://foo.bar/image.jpg", "https://foo.bar/audio.m4a"},
"From": []string{"2020"},
"StatusCallback": []string{"https://localhost/c/t/8eb23e93-5ecb-45ba-b726-3b064e0c56ab/status?id=10&action=callback"},
ExpectedRequests: []ExpectedRequest{
{
Form: url.Values{
"Body": []string{""},
"To": []string{"+250788383383"},
"MediaUrl": []string{"https://foo.bar/image.jpg", "https://foo.bar/audio.m4a"},
"From": []string{"2020"},
"StatusCallback": []string{"https://localhost/c/t/8eb23e93-5ecb-45ba-b726-3b064e0c56ab/status?id=10&action=callback"},
},
},
},
ExpectedMsgStatus: "W",
SendPrep: setSendURL,
Expand Down

0 comments on commit c38b30f

Please sign in to comment.