diff --git a/README.md b/README.md index 570e191..0e4f912 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,11 @@ Go-Rest-Assured keeps track of the Assured Calls you have stubbed out and the Ca - Method - Response - Headers +- Callbacks -Set these fields as a *Given* call through the client or a HTTP request to the service directly and they will be returned from the Go Rest Assured API when you hit the *When* endpoint. The Calls you stub out are uniquie mapped with an identity of their Method and Path. If you stub multiple calls to the same Method and Path, the responses will cycle through your stubs based on the order they were created. +Set these fields as a *Given* call through the client or a HTTP request to the service directly and they will be returned from the Go Rest Assured API when you hit the *When* endpoint. The Calls you stub out are uniquely mapped with an identity of their Method and Path. If you stub multiple calls to the same Method and Path, the responses will cycle through your stubs based on the order they were created. + +If loading callbacks from a JSON file, the call unmarshaller will attempt to read the resource field as a relative file, or else a quoted string, or else just a byte slice. ## Running diff --git a/assured/call.go b/assured/call.go index 86f1836..2269df8 100644 --- a/assured/call.go +++ b/assured/call.go @@ -1,7 +1,12 @@ package assured import ( + "encoding/json" "fmt" + "io/ioutil" + "os" + "path/filepath" + "strconv" ) // Call is a structure containing a request that is stubbed or made @@ -10,7 +15,7 @@ type Call struct { Method string `json:"method"` StatusCode int `json:"status_code"` Headers map[string]string `json:"headers"` - Response []byte `json:"response,omitempty"` + Response CallResponse `json:"response,omitempty"` Callbacks []Callback `json:"callbacks,omitempty"` } @@ -27,11 +32,43 @@ func (c Call) String() string { return rawString } +// CallResponse allows control over the Call's Response encoding +type CallResponse []byte + +// UnmarshalJSON is a custom implementation for JSON Unmarshalling for the CallResponse +// Unmarshalling will first check if the data is a local filepath that can be read +// Else it will check if the data is stringified JSON and un-stringify the data to use +// or Else it will just use the []byte +func (response *CallResponse) UnmarshalJSON(data []byte) error { + unmarshaled := []byte{} + if err := json.Unmarshal(data, &unmarshaled); err != nil { + // The data is a []byte, so use it + unmarshaled = data + } + + if s, err := strconv.Unquote(string(unmarshaled)); err == nil { + absPath, _ := filepath.Abs(s) + if _, err := os.Stat(absPath); err == nil { + // The data is a path that exists, therefore we will read the file + if file, err := ioutil.ReadFile(absPath); err == nil { + *response = file + return nil + } + } + // The data is stringified JSON, therefore we eill use the unquoted JSON + *response = []byte(s) + return nil + } + + *response = unmarshaled + return nil +} + // Callback is a structure containing a callback that is stubbed type Callback struct { Target string `json:"target"` Method string `json:"method"` Delay int `json:"delay,omitempty"` Headers map[string]string `json:"headers"` - Response []byte `json:"response,omitempty"` + Response CallResponse `json:"response,omitempty"` } diff --git a/assured/call_test.go b/assured/call_test.go index c466475..c05c021 100644 --- a/assured/call_test.go +++ b/assured/call_test.go @@ -1,6 +1,7 @@ package assured import ( + "encoding/json" "testing" "github.com/stretchr/testify/require" @@ -34,3 +35,108 @@ func TestCallStringNil(t *testing.T) { require.Equal(t, "", call.String()) } + +func TestCallUnmarshalNoResponse(t *testing.T) { + raw := `{ + "path": "teapot/assured", + "method": "POST", + "status_code": 418, + "headers": {"Content-Length": "0", "User-Agent": "Go-http-client/1.1", "Accept-Encoding": "gzip"} + }` + + call := Call{} + err := json.Unmarshal([]byte(raw), &call) + require.NoError(t, err) + require.Equal(t, *testCall3(), call) +} + +func TestCallUnmarshalString(t *testing.T) { + raw := `{ + "path": "test/assured", + "method": "GET", + "status_code": 409, + "headers": {"Content-Length": "5", "User-Agent": "Go-http-client/1.1", "Accept-Encoding": "gzip"}, + "response": "error" + }` + + call := Call{} + err := json.Unmarshal([]byte(raw), &call) + require.NoError(t, err) + require.Equal(t, *testCall2(), call) +} + +func TestCallUnmarshalJSON(t *testing.T) { + raw := `{ + "path": "test/assured", + "method": "GET", + "status_code": 200, + "headers": {"Content-Length": "17", "User-Agent": "Go-http-client/1.1", "Accept-Encoding": "gzip"}, + "response": "{\"assured\": true}" + }` + + call := Call{} + err := json.Unmarshal([]byte(raw), &call) + require.NoError(t, err) + require.Equal(t, *testCall1(), call) +} + +func TestCallUnmarshalBytes(t *testing.T) { + raw := `{ + "path": "test/assured", + "method": "GET", + "status_code": 200, + "headers": {"Content-Length": "17", "User-Agent": "Go-http-client/1.1", "Accept-Encoding": "gzip"}, + "response": "eyJhc3N1cmVkIjogdHJ1ZX0=" + }` + + call := Call{} + err := json.Unmarshal([]byte(raw), &call) + require.NoError(t, err) + require.Equal(t, *testCall1(), call) +} + +func TestCallUnmarshalFile(t *testing.T) { + raw := `{ + "path": "test/assured", + "method": "GET", + "status_code": 200, + "headers": {"Content-Length": "17", "User-Agent": "Go-http-client/1.1", "Accept-Encoding": "gzip"}, + "response": "../testdata/assured.json" + }` + + call := Call{} + err := json.Unmarshal([]byte(raw), &call) + require.NoError(t, err) + require.Equal(t, *testCall1(), call) +} + +func TestCallUnmarshalCallbacks(t *testing.T) { + raw := `{ + "path": "test/assured", + "method": "GET", + "status_code": 200, + "headers": {"Content-Length": "17", "User-Agent": "Go-http-client/1.1", "Accept-Encoding": "gzip"}, + "response": "../testdata/assured.json", + "callbacks": [ + { + "target": "http://faketarget.com/ + "method": "POST", + "response": "{\"done\": true}", + "headers": {"Assured-Callback-Key": "call-key", "Assured-Callback-Target": "http://faketarget.com/"}} + ] + }` + expected := *testCall1() + expected.Callbacks = []Callback{ + Callback{ + Target: "http://faketarget.com/", + Response: []byte(`{"done": true}`), + Method: "POST", + Headers: map[string]string{"Assured-Callback-Key": "call-key", "Assured-Callback-Target": "http://faketarget.com/"}, + }, + } + + call := Call{} + err := json.Unmarshal([]byte(raw), &call) + require.NoError(t, err) + require.Equal(t, expected, call) +} diff --git a/testdata/assured.json b/testdata/assured.json new file mode 100644 index 0000000..00bf62d --- /dev/null +++ b/testdata/assured.json @@ -0,0 +1 @@ +{"assured": true} \ No newline at end of file diff --git a/testdata/callbacks.json b/testdata/callbacks.json new file mode 100644 index 0000000..f3fd68f --- /dev/null +++ b/testdata/callbacks.json @@ -0,0 +1,42 @@ +[ + { + "path": "test/assured", + "method": "GET", + "status_code": 201, + "response": "testdata/assured.json", + "headers": { + "Content-Length": "17", + "User-Agent": "Go-http-client/1.1", + "Accept-Encoding": "gzip" + } + }, + { + "path": "test/assured", + "method": "GET", + "status_code": 200, + "response": "testdata/image.jpg", + "headers": { + "Content-Length": "56000", + "Content-Type": "image/jpeg", + "User-Agent": "Go-http-client/1.1" + } + }, + { + "path": "teapot/assured", + "method": "POST", + "status_code": 418, + "headers": { + "Content-Length": "0", + "User-Agent": "Go-http-client/1.1", + "Accept-Encoding": "gzip" + }, + "callbacks": [ + { + "target": "http://localhost:9000/when/capture", + "method": "PUT", + "delay": 5, + "response": "Therefore do not worry about tomorrow, for tomorrow will worry about itself. Each day has enough trouble of its own." + } + ] + } +] diff --git a/testdata/calls.json b/testdata/calls.json index d1e371e..2ec17ff 100644 --- a/testdata/calls.json +++ b/testdata/calls.json @@ -3,7 +3,7 @@ "path": "test/assured", "method": "GET", "status_code": 200, - "response": "eyJhc3N1cmVkIjogdHJ1ZX0=", + "response": "{\"assured\": true}", "headers": { "Content-Length": "17", "User-Agent": "Go-http-client/1.1", @@ -14,7 +14,7 @@ "path": "test/assured", "method": "GET", "status_code": 409, - "response": "ZXJyb3I=", + "response": "error", "headers": { "Content-Length": "5", "User-Agent": "Go-http-client/1.1", diff --git a/testdata/image.jpg b/testdata/image.jpg new file mode 100644 index 0000000..abf2643 Binary files /dev/null and b/testdata/image.jpg differ