Skip to content

Commit

Permalink
Updating terminology, working parse tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Derek Dowling committed Nov 11, 2015
1 parent e8d4a65 commit 32a89e7
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 99 deletions.
27 changes: 17 additions & 10 deletions request.go → parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package japi

import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
)
Expand All @@ -21,16 +22,19 @@ func ParseObject(reader io.ReadCloser) (*Object, error) {
return nil, err
}

request := struct {
Object *Object `json:"data"`
data := struct {
Object Object `json:"data"`
}{}

err = json.Unmarshal(byteData, request)
err = json.Unmarshal(byteData, &data)
if err != nil {
return nil, err
return nil, fmt.Errorf("Unable to parse json: \n%s\nError:%s",
string(byteData),
err.Error(),
)
}

return request.Object, nil
return &data.Object, nil
}

// ParseList returns a JSON List for a given io.ReadCloser containing
Expand All @@ -43,14 +47,17 @@ func ParseList(reader io.ReadCloser) ([]*Object, error) {
return nil, err
}

request := struct {
data := struct {
List []*Object `json:"data"`
}{}
}{List: []*Object{}}

err = json.Unmarshal(byteData, request)
err = json.Unmarshal(byteData, &data)
if err != nil {
return nil, err
return nil, fmt.Errorf("Unable to parse json: \n%s\nError:%s",
string(byteData),
err.Error(),
)
}

return request.List, nil
return data.List, nil
}
53 changes: 53 additions & 0 deletions parse_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package japi

import (
"bytes"
"io"
"io/ioutil"
"testing"

. "github.com/smartystreets/goconvey/convey"
)

func TestRequest(t *testing.T) {

Convey("Request Tests", t, func() {

Convey("->ParseObject()", func() {
objectJSON := `{"data": {"type": "user", "id": "sweetID123", "attributes": {"ID":"123"}}}`

closer := createIOCloser([]byte(objectJSON))

object, err := ParseObject(closer)
So(err, ShouldBeNil)
So(object, ShouldNotBeEmpty)
So(object.Type, ShouldEqual, "user")
So(object.ID, ShouldEqual, "sweetID123")
So(object.Attributes, ShouldResemble, map[string]interface{}{"ID": "123"})
})

Convey("->ParseList()", func() {
listJSON :=
`{"data": [
{"type": "user", "id": "sweetID123", "attributes": {"ID": "123"}},
{"type": "user", "id": "sweetID456", "attributes": {"ID": "456"}}
]}`

closer := createIOCloser([]byte(listJSON))

list, err := ParseList(closer)
So(err, ShouldBeNil)
So(len(list), ShouldEqual, 2)

object := list[1]
So(object.Type, ShouldEqual, "user")
So(object.ID, ShouldEqual, "sweetID456")
So(object.Attributes, ShouldResemble, map[string]interface{}{"ID": "456"})
})
})
}

func createIOCloser(data []byte) io.ReadCloser {
reader := bytes.NewReader(data)
return ioutil.NopCloser(reader)
}
28 changes: 23 additions & 5 deletions request_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,41 @@ import (
. "github.com/smartystreets/goconvey/convey"
)

func TestRequest(t *testing.T) {
func TestParsing(t *testing.T) {

Convey("Request Tests", t, func() {
Convey("Parse Tests", t, func() {

Convey("->ParseObject()", func() {
jsonStr := `{"data": {"type": "user", "id": "sweetID123", "attributes": {"ID":"123"}}}`
objectJSON := `{"data": {"type": "user", "id": "sweetID123", "attributes": {"ID":"123"}}}`

closer := createIOCloser([]byte(jsonStr))
closer := createIOCloser([]byte(objectJSON))

object, err := ParseObject(closer)
So(err, ShouldBeNil)
So(object, ShouldNotBeEmpty)
So(err, ShouldBeNil)
So(object.Type, ShouldEqual, "user")
So(object.ID, ShouldEqual, "sweetID123")
So(object.Attributes, ShouldResemble, map[string]interface{}{"ID": "123"})
})

Convey("->ParseList()", func() {
listJSON :=
`{"data": [
{"type": "user", "id": "sweetID123", "attributes": {"ID": "123"}},
{"type": "user", "id": "sweetID456", "attributes": {"ID": "456"}}
]}`

closer := createIOCloser([]byte(listJSON))

list, err := ParseList(closer)
So(err, ShouldBeNil)
So(len(list), ShouldEqual, 2)

object := list[1]
So(object.Type, ShouldEqual, "user")
So(object.ID, ShouldEqual, "sweetID456")
So(object.Attributes, ShouldResemble, map[string]interface{}{"ID": "456"})
})
})
}

Expand Down
84 changes: 0 additions & 84 deletions response.go

This file was deleted.

81 changes: 81 additions & 0 deletions send.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package japi

import (
"encoding/json"
"fmt"
"net/http"
"strconv"
)

// Data represents the top level json format of incoming requests
// and outgoing responses
type Data struct {
Data interface{} `json:"data"`
}

// ErrorResponse for API requests
type ErrorResponse struct {
Errors []*Error `json:"errors"`
}

// SendObject sends a single data object as a JSON response
func SendObject(w http.ResponseWriter, status int, object *Object) error {
return Send(w, status, prepareObject(object))
}

// SendList sends a list of data objects as a JSON response
func SendList(w http.ResponseWriter, status int, list []*Object) error {
return Send(w, status, prepareList(list))
}

// SendError is a convenience function that puts an error into an array
// and then calls SendErrors which is the correct error response format
func SendError(w http.ResponseWriter, err *Error) error {
return SendErrors(w, prepareError(err))
}

// SendErrors sends the expected error response format for a
// request that cannot be fulfilled in someway. Allows the user
// to compile multiple errors that can be sent back to a user. Uses
// the first error status as the HTTP Status to return.
func SendErrors(w http.ResponseWriter, errors []*Error) error {

if len(errors) == 0 {
return fmt.Errorf("No errors provided for attempted error response.")
}

// use the first error to set the error status
status := errors[0].Status
return Send(w, status, prepareErrorList(errors))
}

// Send formats a JSON response with the appropriate headers.
func Send(w http.ResponseWriter, status int, payload interface{}) error {
content, err := json.MarshalIndent(payload, "", " ")
if err != nil {
return err
}

w.Header().Add("Content-Type", ContentType)
w.Header().Set("Content-Length", strconv.Itoa(len(content)))
w.WriteHeader(status)
w.Write(content)

return nil
}

func prepareError(err *Error) []*Error {
return []*Error{err}
}

func prepareErrorList(errors []*Error) *ErrorResponse {
return &ErrorResponse{Errors: errors}
}

func prepareObject(object *Object) *Data {
return &Data{Data: object}
}

func prepareList(list []*Object) *Data {
return &Data{Data: list}
}
24 changes: 24 additions & 0 deletions send_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package japi

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

. "github.com/smartystreets/goconvey/convey"
)

func TestSend(t *testing.T) {

Convey("Send Tests", t, func() {

response := httptest.NewRecorder()

Convey("->SendObject()", func() {

})

Convey("->SendList()", func() {

})
})
}

0 comments on commit 32a89e7

Please sign in to comment.