Skip to content

Commit

Permalink
Merge branch 'master' into ah-assertable-helpers
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex Hornbake committed Dec 13, 2018
2 parents a2c9c2f + 122a1e1 commit 8112163
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 10 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,14 @@ In some cases, attributes in a JSON response can by dynamic (e.g unique id's, da
```json
{
"defaults": {
"Etag": "default-etag-value",
"updated_at": 0,
"foo": "foobar"
}
}
```

When used with `AssertHTTPResponse`, for any response with `Content-Type: application/json`, the key-value pairs in `defaults` will be used to override the JSON response, allowing for consistent snapshot testing.
When used with `AssertHTTPResponse`, for any response with `Content-Type: application/json`, the key-value pairs in `defaults` will be used to override the JSON response, allowing for consistent snapshot testing. Any HTTP headers will also be override for key matches in `defaults`.


## Using custom `__snapshot__` directory
Expand Down
2 changes: 1 addition & 1 deletion abide.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ func (s snapshots) save() error {
return err
}

err = ioutil.WriteFile(path, data, os.ModePerm)
err = ioutil.WriteFile(path, data, 0666)
if err != nil {
return err
}
Expand Down
52 changes: 46 additions & 6 deletions assert.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,63 @@ func Assert(t *testing.T, id string, a Assertable) {

// AssertHTTPResponse asserts the value of an http.Response.
func AssertHTTPResponse(t *testing.T, id string, w *http.Response) {
config, err := getConfig()
body, err := httputil.DumpResponse(w, true)
if err != nil {
t.Fatal(err)
}

body, err := httputil.DumpResponse(w, true)
assertHTTP(t, id, body, contentTypeIsJSON(w.Header.Get("Content-Type")))
}

// AssertHTTPRequestOut asserts the value of an http.Request.
// Intended for use when testing outgoing client requests
// See https://golang.org/pkg/net/http/httputil/#DumpRequestOut for more
func AssertHTTPRequestOut(t *testing.T, id string, r *http.Request) {
body, err := httputil.DumpRequestOut(r, true)
if err != nil {
t.Fatal(err)
}

assertHTTP(t, id, body, contentTypeIsJSON(r.Header.Get("Content-Type")))
}

// AssertHTTPRequest asserts the value of an http.Request.
// Intended for use when testing incoming client requests
// See https://golang.org/pkg/net/http/httputil/#DumpRequest for more
func AssertHTTPRequest(t *testing.T, id string, r *http.Request) {
body, err := httputil.DumpRequest(r, true)
if err != nil {
t.Fatal(err)
}

assertHTTP(t, id, body, contentTypeIsJSON(r.Header.Get("Content-Type")))
}

func assertHTTP(t *testing.T, id string, body []byte, isJSON bool) {
config, err := getConfig()
if err != nil {
t.Fatal(err)
}

data := string(body)
lines := strings.Split(strings.TrimSpace(data), "\n")

contentType := w.Header.Get("Content-Type")
if config != nil {
// empty line identifies the end of the HTTP header
for i, line := range lines {
if line == "" {
break
}

headerItem := strings.Split(line, ":")
if def, ok := config.Defaults[headerItem[0]]; ok {
lines[i] = fmt.Sprintf("%s: %s", headerItem[0], def)
}
}
}

// If the response body is JSON, indent.
if contentTypeIsJSON(contentType) {
lines := strings.Split(strings.TrimSpace(data), "\n")
if isJSON {
jsonStr := lines[len(lines)-1]

var jsonIface map[string]interface{}
Expand All @@ -64,9 +104,9 @@ func AssertHTTPResponse(t *testing.T, id string, w *http.Response) {
t.Fatal(err)
}
lines[len(lines)-1] = string(out)
data = strings.Join(lines, "\n")
}

data = strings.Join(lines, "\n")
createOrUpdateSnapshot(t, id, data)
}

Expand Down
26 changes: 26 additions & 0 deletions example/__snapshots__/example.snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,44 @@ string to be asserted
HTTP/1.1 200 OK
Connection: close
Content-Type: application/json
Etag: default-etag-value

{
"foo": "foobar"
}

/* snapshot: http client request */
GET / HTTP/1.1
Host: example.com
User-Agent: Go-http-client/1.1
Content-Length: 31
Content-Type: application/json
X-Expected-Header: expected header value
Accept-Encoding: gzip

{
"message": "expected message"
}

/* snapshot: http server request */
POST / HTTP/1.1
Accept-Encoding: gzip
Content-Length: 31
Content-Type: application/json
User-Agent: Go-http-client/1.1

{
"message": "expected message"
}

/* snapshot: reader */
Hello World.

/* snapshot: second route */
HTTP/1.1 200 OK
Connection: close
Content-Type: application/json
Etag: default-etag-value

{
"post": {
Expand Down
1 change: 1 addition & 0 deletions example/abide.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"defaults": {
"Etag": "default-etag-value",
"updated_at": 0,
"foo": "foobar"
}
Expand Down
3 changes: 3 additions & 0 deletions example/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"encoding/json"
"net/http"
"strconv"
"time"

"github.com/beme/abide/example/models"
Expand All @@ -20,6 +21,7 @@ func firstHandler(w http.ResponseWriter, r *http.Request) {
}

w.Header().Set("Content-Type", "application/json")
w.Header().Set("Etag", strconv.FormatInt(time.Now().UnixNano(), 10))
w.Write(body)
}

Expand Down Expand Up @@ -47,6 +49,7 @@ func secondHandler(w http.ResponseWriter, r *http.Request) {
}

w.Header().Set("Content-Type", "application/json")
w.Header().Set("Etag", strconv.FormatInt(time.Now().UnixNano(), 10))
w.Write(body)
}

Expand Down
22 changes: 20 additions & 2 deletions example/main_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package main

import (
"net/http"
"net/http/httptest"
"os"
"strings"
"testing"

"github.com/beme/abide"
Expand Down Expand Up @@ -42,6 +44,23 @@ func TestReader(t *testing.T) {
abide.AssertReader(t, "reader", res.Body)
}

func TestAssertHTTPRequestOut(t *testing.T) {
req := httptest.NewRequest(http.MethodGet, "http://example.com", strings.NewReader(`{"message": "expected message"}`))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Expected-Header", "expected header value")

abide.AssertHTTPRequestOut(t, "http client request", req)
}

func TestAssertHTTPRequest(t *testing.T) {
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
r.Host = "" // httptest servers are spawned on random ports, prevent that from being in the snapshot.
abide.AssertHTTPRequest(t, "http server request", r)
}))

http.Post(server.URL, "application/json", strings.NewReader(`{"message": "expected message"}`))
}

func TestAssertableString(t *testing.T) {
abide.Assert(t, "assertable string", abide.String("string to be asserted"))
}
Expand All @@ -59,5 +78,4 @@ func TestAssertableInterface(t *testing.T) {
true,
"string4",
}
abide.Assert(t, "assertable interface", abide.Interface(myStruct))
}
abide.Assert(t, "assertable interface", abide.Interface(myStruct))

0 comments on commit 8112163

Please sign in to comment.