2015-07-06 16:40:43 -04:00
|
|
|
package jsonapi
|
|
|
|
|
2015-07-07 18:46:20 -04:00
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/json"
|
2015-07-08 12:34:37 -04:00
|
|
|
"io"
|
2015-08-29 13:29:58 -04:00
|
|
|
"strings"
|
2015-07-07 18:46:20 -04:00
|
|
|
"testing"
|
2015-07-10 14:41:54 -04:00
|
|
|
"time"
|
2015-07-07 18:46:20 -04:00
|
|
|
)
|
2015-07-06 16:40:43 -04:00
|
|
|
|
2015-07-08 14:49:36 -04:00
|
|
|
type BadModel struct {
|
2016-07-05 21:32:15 -04:00
|
|
|
ID int `jsonapi:"primary"`
|
2015-07-08 14:49:36 -04:00
|
|
|
}
|
|
|
|
|
2016-07-22 21:34:38 -04:00
|
|
|
type WithPointer struct {
|
Added support for string, int(8,16,32,64), uint(8,16,32,64) and each … (#51)
* Added support for string, int(8,16,32,64), uint(8,16,32,64) and each of their ptr types as acceptable to use for the ID field.
* No longer declaring a new idErr var; also eliminate the switch within a switch - if the ID field was a string or *string it will continue. Added a couple extra tests.
2016-09-22 18:02:30 -04:00
|
|
|
ID *uint64 `jsonapi:"primary,with-pointers"`
|
2016-07-22 21:34:38 -04:00
|
|
|
Name *string `jsonapi:"attr,name"`
|
|
|
|
IsActive *bool `jsonapi:"attr,is-active"`
|
|
|
|
IntVal *int `jsonapi:"attr,int-val"`
|
|
|
|
FloatVal *float32 `jsonapi:"attr,float-val"`
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestUnmarshalToStructWithPointerAttr(t *testing.T) {
|
|
|
|
out := new(WithPointer)
|
|
|
|
in := map[string]interface{}{
|
|
|
|
"name": "The name",
|
|
|
|
"is-active": true,
|
|
|
|
"int-val": 8,
|
|
|
|
"float-val": 1.1,
|
|
|
|
}
|
|
|
|
if err := UnmarshalPayload(sampleWithPointerPayload(in), out); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
if *out.Name != "The name" {
|
|
|
|
t.Fatalf("Error unmarshalling to string ptr")
|
|
|
|
}
|
|
|
|
if *out.IsActive != true {
|
|
|
|
t.Fatalf("Error unmarshalling to bool ptr")
|
|
|
|
}
|
|
|
|
if *out.IntVal != 8 {
|
|
|
|
t.Fatalf("Error unmarshalling to int ptr")
|
|
|
|
}
|
|
|
|
if *out.FloatVal != 1.1 {
|
|
|
|
t.Fatalf("Error unmarshalling to float ptr")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Added support for string, int(8,16,32,64), uint(8,16,32,64) and each … (#51)
* Added support for string, int(8,16,32,64), uint(8,16,32,64) and each of their ptr types as acceptable to use for the ID field.
* No longer declaring a new idErr var; also eliminate the switch within a switch - if the ID field was a string or *string it will continue. Added a couple extra tests.
2016-09-22 18:02:30 -04:00
|
|
|
func TestUnmarshalPayload_ptrsAllNil(t *testing.T) {
|
|
|
|
out := new(WithPointer)
|
|
|
|
if err := UnmarshalPayload(
|
|
|
|
strings.NewReader(`{"data": {}}`), out); err != nil {
|
|
|
|
t.Fatalf("Error unmarshalling to Foo")
|
|
|
|
}
|
|
|
|
|
|
|
|
if out.ID != nil {
|
|
|
|
t.Fatalf("Error unmarshalling; expected ID ptr to be nil")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestUnmarshalPayloadWithPointerID(t *testing.T) {
|
|
|
|
out := new(WithPointer)
|
|
|
|
attrs := map[string]interface{}{}
|
|
|
|
|
|
|
|
if err := UnmarshalPayload(sampleWithPointerPayload(attrs), out); err != nil {
|
|
|
|
t.Fatalf("Error unmarshalling to Foo")
|
|
|
|
}
|
|
|
|
|
|
|
|
// these were present in the payload -- expect val to be not nil
|
|
|
|
if out.ID == nil {
|
|
|
|
t.Fatalf("Error unmarshalling; expected ID ptr to be not nil")
|
|
|
|
}
|
|
|
|
if e, a := uint64(2), *out.ID; e != a {
|
|
|
|
t.Fatalf("Was expecting the ID to have a value of %d, got %d", e, a)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestUnmarshalPayloadWithPointerAttr_AbsentVal(t *testing.T) {
|
2016-07-22 21:34:38 -04:00
|
|
|
out := new(WithPointer)
|
|
|
|
in := map[string]interface{}{
|
|
|
|
"name": "The name",
|
|
|
|
"is-active": true,
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := UnmarshalPayload(sampleWithPointerPayload(in), out); err != nil {
|
|
|
|
t.Fatalf("Error unmarshalling to Foo")
|
|
|
|
}
|
|
|
|
|
|
|
|
// these were present in the payload -- expect val to be not nil
|
|
|
|
if out.Name == nil || out.IsActive == nil {
|
|
|
|
t.Fatalf("Error unmarshalling; expected ptr to be not nil")
|
|
|
|
}
|
|
|
|
|
|
|
|
// these were absent in the payload -- expect val to be nil
|
|
|
|
if out.IntVal != nil || out.FloatVal != nil {
|
|
|
|
t.Fatalf("Error unmarshalling; expected ptr to be nil")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestStringPointerField(t *testing.T) {
|
|
|
|
// Build Book payload
|
|
|
|
description := "Hello World!"
|
|
|
|
data := map[string]interface{}{
|
|
|
|
"data": map[string]interface{}{
|
|
|
|
"type": "books",
|
|
|
|
"id": "5",
|
|
|
|
"attributes": map[string]interface{}{
|
|
|
|
"author": "aren55555",
|
|
|
|
"description": description,
|
|
|
|
"isbn": "",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
payload, err := json.Marshal(data)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse JSON API payload
|
|
|
|
book := new(Book)
|
|
|
|
if err := UnmarshalPayload(bytes.NewReader(payload), book); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if book.Description == nil {
|
|
|
|
t.Fatal("Was not expecting a nil pointer for book.Description")
|
|
|
|
}
|
|
|
|
if expected, actual := description, *book.Description; expected != actual {
|
|
|
|
t.Fatalf("Was expecting descript to be `%s`, got `%s`", expected, actual)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-08 14:49:36 -04:00
|
|
|
func TestMalformedTag(t *testing.T) {
|
|
|
|
out := new(BadModel)
|
2015-07-10 12:07:12 -04:00
|
|
|
err := UnmarshalPayload(samplePayload(), out)
|
2016-01-05 16:13:24 -05:00
|
|
|
if err == nil || err != ErrBadJSONAPIStructTag {
|
2015-07-08 14:49:36 -04:00
|
|
|
t.Fatalf("Did not error out with wrong number of arguments in tag")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-08-29 13:29:58 -04:00
|
|
|
func TestUnmarshalInvalidJSON(t *testing.T) {
|
|
|
|
in := strings.NewReader("{}")
|
|
|
|
out := new(Blog)
|
|
|
|
|
|
|
|
err := UnmarshalPayload(in, out)
|
|
|
|
|
|
|
|
if err == nil {
|
|
|
|
t.Fatalf("Did not error out the invalid JSON.")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-05 21:32:15 -04:00
|
|
|
func TestUnmarshalSetsID(t *testing.T) {
|
|
|
|
in := samplePayloadWithID()
|
2015-07-08 16:11:03 -04:00
|
|
|
out := new(Blog)
|
2015-07-06 16:40:43 -04:00
|
|
|
|
2015-07-10 12:07:12 -04:00
|
|
|
if err := UnmarshalPayload(in, out); err != nil {
|
2015-07-08 16:11:03 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-07-06 16:40:43 -04:00
|
|
|
|
2016-07-05 21:32:15 -04:00
|
|
|
if out.ID != 2 {
|
|
|
|
t.Fatalf("Did not set ID on dst interface")
|
2015-07-08 16:11:03 -04:00
|
|
|
}
|
|
|
|
}
|
2015-07-06 17:41:53 -04:00
|
|
|
|
Added support for string, int(8,16,32,64), uint(8,16,32,64) and each … (#51)
* Added support for string, int(8,16,32,64), uint(8,16,32,64) and each of their ptr types as acceptable to use for the ID field.
* No longer declaring a new idErr var; also eliminate the switch within a switch - if the ID field was a string or *string it will continue. Added a couple extra tests.
2016-09-22 18:02:30 -04:00
|
|
|
func TestUnmarshal_nonNumericID(t *testing.T) {
|
|
|
|
data := samplePayloadWithoutIncluded()
|
|
|
|
data["data"].(map[string]interface{})["id"] = "non-numeric-id"
|
|
|
|
payload, _ := payload(data)
|
|
|
|
in := bytes.NewReader(payload)
|
|
|
|
out := new(Post)
|
|
|
|
|
|
|
|
if err := UnmarshalPayload(in, out); err != ErrBadJSONAPIID {
|
|
|
|
t.Fatalf(
|
|
|
|
"Was expecting a `%s` error, got `%s`",
|
|
|
|
ErrBadJSONAPIID,
|
|
|
|
err,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-06 17:41:53 -04:00
|
|
|
func TestUnmarshalSetsAttrs(t *testing.T) {
|
2015-07-08 14:49:36 -04:00
|
|
|
out, err := unmarshalSamplePayload()
|
|
|
|
if err != nil {
|
2015-07-06 17:41:53 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-07-06 16:40:43 -04:00
|
|
|
|
|
|
|
if out.CreatedAt.IsZero() {
|
|
|
|
t.Fatalf("Did not parse time")
|
|
|
|
}
|
|
|
|
|
|
|
|
if out.ViewCount != 1000 {
|
|
|
|
t.Fatalf("View count not properly serialized")
|
|
|
|
}
|
|
|
|
}
|
2015-07-06 17:41:53 -04:00
|
|
|
|
2016-09-22 16:58:07 -04:00
|
|
|
func TestUnmarshalParsesISO8601(t *testing.T) {
|
|
|
|
payload := &OnePayload{
|
|
|
|
Data: &Node{
|
|
|
|
Type: "timestamps",
|
|
|
|
Attributes: map[string]interface{}{
|
|
|
|
"timestamp": "2016-08-17T08:27:12Z",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
in := bytes.NewBuffer(nil)
|
|
|
|
json.NewEncoder(in).Encode(payload)
|
|
|
|
|
|
|
|
out := new(Timestamp)
|
|
|
|
|
|
|
|
if err := UnmarshalPayload(in, out); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
expected := time.Date(2016, 8, 17, 8, 27, 12, 0, time.UTC)
|
|
|
|
|
|
|
|
if !out.Time.Equal(expected) {
|
|
|
|
t.Fatal("Parsing the ISO8601 timestamp failed")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestUnmarshalParsesISO8601TimePointer(t *testing.T) {
|
|
|
|
payload := &OnePayload{
|
|
|
|
Data: &Node{
|
|
|
|
Type: "timestamps",
|
|
|
|
Attributes: map[string]interface{}{
|
|
|
|
"next": "2016-08-17T08:27:12Z",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
in := bytes.NewBuffer(nil)
|
|
|
|
json.NewEncoder(in).Encode(payload)
|
|
|
|
|
|
|
|
out := new(Timestamp)
|
|
|
|
|
|
|
|
if err := UnmarshalPayload(in, out); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
expected := time.Date(2016, 8, 17, 8, 27, 12, 0, time.UTC)
|
|
|
|
|
|
|
|
if !out.Next.Equal(expected) {
|
|
|
|
t.Fatal("Parsing the ISO8601 timestamp failed")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestUnmarshalInvalidISO8601(t *testing.T) {
|
|
|
|
payload := &OnePayload{
|
|
|
|
Data: &Node{
|
|
|
|
Type: "timestamps",
|
|
|
|
Attributes: map[string]interface{}{
|
|
|
|
"timestamp": "17 Aug 16 08:027 MST",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
in := bytes.NewBuffer(nil)
|
|
|
|
json.NewEncoder(in).Encode(payload)
|
|
|
|
|
|
|
|
out := new(Timestamp)
|
|
|
|
|
|
|
|
if err := UnmarshalPayload(in, out); err != ErrInvalidISO8601 {
|
|
|
|
t.Fatalf("Expected ErrInvalidISO8601, got %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-13 21:32:04 -04:00
|
|
|
func TestUnmarshalRelationshipsWithoutIncluded(t *testing.T) {
|
Added support for string, int(8,16,32,64), uint(8,16,32,64) and each … (#51)
* Added support for string, int(8,16,32,64), uint(8,16,32,64) and each of their ptr types as acceptable to use for the ID field.
* No longer declaring a new idErr var; also eliminate the switch within a switch - if the ID field was a string or *string it will continue. Added a couple extra tests.
2016-09-22 18:02:30 -04:00
|
|
|
data, _ := payload(samplePayloadWithoutIncluded())
|
2016-07-13 21:32:04 -04:00
|
|
|
in := bytes.NewReader(data)
|
|
|
|
out := new(Post)
|
|
|
|
|
|
|
|
if err := UnmarshalPayload(in, out); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify each comment has at least an ID
|
|
|
|
for _, comment := range out.Comments {
|
2016-07-15 16:40:23 -04:00
|
|
|
if comment.ID == 0 {
|
2016-07-13 21:32:04 -04:00
|
|
|
t.Fatalf("The comment did not have an ID")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-08 12:34:37 -04:00
|
|
|
func TestUnmarshalRelationships(t *testing.T) {
|
2015-07-08 14:49:36 -04:00
|
|
|
out, err := unmarshalSamplePayload()
|
|
|
|
if err != nil {
|
2015-07-08 12:34:37 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if out.CurrentPost == nil {
|
|
|
|
t.Fatalf("Current post was not materialized")
|
|
|
|
}
|
|
|
|
|
|
|
|
if out.CurrentPost.Title != "Bas" || out.CurrentPost.Body != "Fuubar" {
|
2015-07-10 14:41:54 -04:00
|
|
|
t.Fatalf("Attributes were not set")
|
2015-07-08 12:34:37 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
if len(out.Posts) != 2 {
|
|
|
|
t.Fatalf("There should have been 2 posts")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-20 19:13:04 -05:00
|
|
|
func TestUnmarshalNullRelationship(t *testing.T) {
|
|
|
|
sample := map[string]interface{}{
|
|
|
|
"data": map[string]interface{}{
|
|
|
|
"type": "posts",
|
|
|
|
"id": "1",
|
|
|
|
"attributes": map[string]interface{}{
|
|
|
|
"body": "Hello",
|
|
|
|
"title": "World",
|
|
|
|
},
|
|
|
|
"relationships": map[string]interface{}{
|
|
|
|
"latest_comment": map[string]interface{}{
|
|
|
|
"data": nil, // empty to-one relationship
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
data, err := json.Marshal(sample)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
in := bytes.NewReader(data)
|
|
|
|
out := new(Post)
|
|
|
|
|
|
|
|
if err := UnmarshalPayload(in, out); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if out.LatestComment != nil {
|
|
|
|
t.Fatalf("Latest Comment was not set to nil")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestUnmarshalNullRelationshipInSlice(t *testing.T) {
|
|
|
|
sample := map[string]interface{}{
|
|
|
|
"data": map[string]interface{}{
|
|
|
|
"type": "posts",
|
|
|
|
"id": "1",
|
|
|
|
"attributes": map[string]interface{}{
|
|
|
|
"body": "Hello",
|
|
|
|
"title": "World",
|
|
|
|
},
|
|
|
|
"relationships": map[string]interface{}{
|
|
|
|
"comments": map[string]interface{}{
|
|
|
|
"data": []interface{}{}, // empty to-many relationships
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
data, err := json.Marshal(sample)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
in := bytes.NewReader(data)
|
|
|
|
out := new(Post)
|
|
|
|
|
|
|
|
if err := UnmarshalPayload(in, out); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(out.Comments) != 0 {
|
|
|
|
t.Fatalf("Wrong number of comments; Comments should be empty")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-08 12:34:37 -04:00
|
|
|
func TestUnmarshalNestedRelationships(t *testing.T) {
|
2015-07-08 14:49:36 -04:00
|
|
|
out, err := unmarshalSamplePayload()
|
|
|
|
if err != nil {
|
2015-07-08 12:34:37 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if out.CurrentPost == nil {
|
|
|
|
t.Fatalf("Current post was not materialized")
|
|
|
|
}
|
|
|
|
|
|
|
|
if out.CurrentPost.Comments == nil {
|
|
|
|
t.Fatalf("Did not materialize nested records, comments")
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(out.CurrentPost.Comments) != 2 {
|
|
|
|
t.Fatalf("Wrong number of comments")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-12 10:42:52 -04:00
|
|
|
func TestUnmarshalRelationshipsSerializedEmbedded(t *testing.T) {
|
|
|
|
out := sampleSerializedEmbeddedTestModel()
|
|
|
|
|
|
|
|
if out.CurrentPost == nil {
|
|
|
|
t.Fatalf("Current post was not materialized")
|
|
|
|
}
|
|
|
|
|
|
|
|
if out.CurrentPost.Title != "Foo" || out.CurrentPost.Body != "Bar" {
|
|
|
|
t.Fatalf("Attributes were not set")
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(out.Posts) != 2 {
|
|
|
|
t.Fatalf("There should have been 2 posts")
|
|
|
|
}
|
|
|
|
|
|
|
|
if out.Posts[0].LatestComment.Body != "foo" {
|
|
|
|
t.Fatalf("The comment body was not set")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-10 20:34:04 -04:00
|
|
|
func TestUnmarshalNestedRelationshipsEmbedded(t *testing.T) {
|
|
|
|
out := bytes.NewBuffer(nil)
|
|
|
|
if err := MarshalOnePayloadEmbedded(out, testModel()); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
model := new(Blog)
|
|
|
|
|
|
|
|
if err := UnmarshalPayload(out, model); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if model.CurrentPost == nil {
|
|
|
|
t.Fatalf("Current post was not materialized")
|
|
|
|
}
|
|
|
|
|
|
|
|
if model.CurrentPost.Comments == nil {
|
|
|
|
t.Fatalf("Did not materialize nested records, comments")
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(model.CurrentPost.Comments) != 2 {
|
|
|
|
t.Fatalf("Wrong number of comments")
|
|
|
|
}
|
|
|
|
|
|
|
|
if model.CurrentPost.Comments[0].Body != "foo" {
|
|
|
|
t.Fatalf("Comment body not set")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-10 14:41:54 -04:00
|
|
|
func TestUnmarshalRelationshipsSideloaded(t *testing.T) {
|
|
|
|
payload := samplePayloadWithSideloaded()
|
|
|
|
out := new(Blog)
|
|
|
|
|
|
|
|
if err := UnmarshalPayload(payload, out); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if out.CurrentPost == nil {
|
|
|
|
t.Fatalf("Current post was not materialized")
|
|
|
|
}
|
|
|
|
|
|
|
|
if out.CurrentPost.Title != "Foo" || out.CurrentPost.Body != "Bar" {
|
|
|
|
t.Fatalf("Attributes were not set")
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(out.Posts) != 2 {
|
|
|
|
t.Fatalf("There should have been 2 posts")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestUnmarshalNestedRelationshipsSideloaded(t *testing.T) {
|
|
|
|
payload := samplePayloadWithSideloaded()
|
|
|
|
out := new(Blog)
|
|
|
|
|
|
|
|
if err := UnmarshalPayload(payload, out); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if out.CurrentPost == nil {
|
|
|
|
t.Fatalf("Current post was not materialized")
|
|
|
|
}
|
|
|
|
|
|
|
|
if out.CurrentPost.Comments == nil {
|
|
|
|
t.Fatalf("Did not materialize nested records, comments")
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(out.CurrentPost.Comments) != 2 {
|
|
|
|
t.Fatalf("Wrong number of comments")
|
|
|
|
}
|
2015-07-10 17:31:26 -04:00
|
|
|
|
|
|
|
if out.CurrentPost.Comments[0].Body != "foo" {
|
|
|
|
t.Fatalf("Comment body not set")
|
|
|
|
}
|
2015-07-10 14:41:54 -04:00
|
|
|
}
|
|
|
|
|
2015-09-10 18:55:51 -04:00
|
|
|
func TestUnmarshalNestedRelationshipsEmbedded_withClientIDs(t *testing.T) {
|
|
|
|
model := new(Blog)
|
|
|
|
|
2015-09-17 18:55:53 -04:00
|
|
|
if err := UnmarshalPayload(samplePayload(), model); err != nil {
|
2015-09-10 18:55:51 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2016-07-05 21:32:15 -04:00
|
|
|
if model.Posts[0].ClientID == "" {
|
|
|
|
t.Fatalf("ClientID not set from request on related record")
|
2015-09-10 18:55:51 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-08 14:49:36 -04:00
|
|
|
func unmarshalSamplePayload() (*Blog, error) {
|
|
|
|
in := samplePayload()
|
|
|
|
out := new(Blog)
|
|
|
|
|
2015-07-10 12:07:12 -04:00
|
|
|
if err := UnmarshalPayload(in, out); err != nil {
|
2015-07-08 14:49:36 -04:00
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return out, nil
|
|
|
|
}
|
|
|
|
|
Added support for string, int(8,16,32,64), uint(8,16,32,64) and each … (#51)
* Added support for string, int(8,16,32,64), uint(8,16,32,64) and each of their ptr types as acceptable to use for the ID field.
* No longer declaring a new idErr var; also eliminate the switch within a switch - if the ID field was a string or *string it will continue. Added a couple extra tests.
2016-09-22 18:02:30 -04:00
|
|
|
func samplePayloadWithoutIncluded() map[string]interface{} {
|
|
|
|
return map[string]interface{}{
|
2016-07-13 21:32:04 -04:00
|
|
|
"data": map[string]interface{}{
|
|
|
|
"type": "posts",
|
|
|
|
"id": "1",
|
|
|
|
"attributes": map[string]interface{}{
|
|
|
|
"body": "Hello",
|
|
|
|
"title": "World",
|
|
|
|
},
|
|
|
|
"relationships": map[string]interface{}{
|
|
|
|
"comments": map[string]interface{}{
|
|
|
|
"data": []interface{}{
|
|
|
|
map[string]interface{}{
|
|
|
|
"type": "comments",
|
|
|
|
"id": "123",
|
|
|
|
},
|
|
|
|
map[string]interface{}{
|
|
|
|
"type": "comments",
|
|
|
|
"id": "456",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"latest_comment": map[string]interface{}{
|
|
|
|
"data": map[string]interface{}{
|
|
|
|
"type": "comments",
|
|
|
|
"id": "55555",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
Added support for string, int(8,16,32,64), uint(8,16,32,64) and each … (#51)
* Added support for string, int(8,16,32,64), uint(8,16,32,64) and each of their ptr types as acceptable to use for the ID field.
* No longer declaring a new idErr var; also eliminate the switch within a switch - if the ID field was a string or *string it will continue. Added a couple extra tests.
2016-09-22 18:02:30 -04:00
|
|
|
}
|
2016-07-22 21:34:38 -04:00
|
|
|
|
Added support for string, int(8,16,32,64), uint(8,16,32,64) and each … (#51)
* Added support for string, int(8,16,32,64), uint(8,16,32,64) and each of their ptr types as acceptable to use for the ID field.
* No longer declaring a new idErr var; also eliminate the switch within a switch - if the ID field was a string or *string it will continue. Added a couple extra tests.
2016-09-22 18:02:30 -04:00
|
|
|
func payload(data map[string]interface{}) (result []byte, err error) {
|
2016-07-13 21:32:04 -04:00
|
|
|
result, err = json.Marshal(data)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2015-07-08 12:34:37 -04:00
|
|
|
func samplePayload() io.Reader {
|
2015-07-10 12:07:12 -04:00
|
|
|
payload := &OnePayload{
|
|
|
|
Data: &Node{
|
2015-07-06 17:41:53 -04:00
|
|
|
Type: "blogs",
|
|
|
|
Attributes: map[string]interface{}{
|
|
|
|
"title": "New blog",
|
|
|
|
"created_at": 1436216820,
|
|
|
|
"view_count": 1000,
|
|
|
|
},
|
2015-07-07 18:46:20 -04:00
|
|
|
Relationships: map[string]interface{}{
|
2015-07-10 12:07:12 -04:00
|
|
|
"posts": &RelationshipManyNode{
|
|
|
|
Data: []*Node{
|
|
|
|
&Node{
|
2015-07-07 18:46:20 -04:00
|
|
|
Type: "posts",
|
|
|
|
Attributes: map[string]interface{}{
|
|
|
|
"title": "Foo",
|
|
|
|
"body": "Bar",
|
|
|
|
},
|
2016-07-05 21:32:15 -04:00
|
|
|
ClientID: "1",
|
2015-07-07 18:46:20 -04:00
|
|
|
},
|
2015-07-10 12:07:12 -04:00
|
|
|
&Node{
|
2015-07-08 12:34:37 -04:00
|
|
|
Type: "posts",
|
|
|
|
Attributes: map[string]interface{}{
|
|
|
|
"title": "X",
|
|
|
|
"body": "Y",
|
|
|
|
},
|
2016-07-05 21:32:15 -04:00
|
|
|
ClientID: "2",
|
2015-07-08 12:34:37 -04:00
|
|
|
},
|
2015-07-07 18:46:20 -04:00
|
|
|
},
|
|
|
|
},
|
2015-07-10 12:07:12 -04:00
|
|
|
"current_post": &RelationshipOneNode{
|
|
|
|
Data: &Node{
|
2015-07-07 18:46:20 -04:00
|
|
|
Type: "posts",
|
|
|
|
Attributes: map[string]interface{}{
|
|
|
|
"title": "Bas",
|
|
|
|
"body": "Fuubar",
|
|
|
|
},
|
2016-07-05 21:32:15 -04:00
|
|
|
ClientID: "3",
|
2015-07-08 12:34:37 -04:00
|
|
|
Relationships: map[string]interface{}{
|
2015-07-10 12:07:12 -04:00
|
|
|
"comments": &RelationshipManyNode{
|
|
|
|
Data: []*Node{
|
|
|
|
&Node{
|
2015-07-08 12:34:37 -04:00
|
|
|
Type: "comments",
|
|
|
|
Attributes: map[string]interface{}{
|
|
|
|
"body": "Great post!",
|
|
|
|
},
|
2016-07-05 21:32:15 -04:00
|
|
|
ClientID: "4",
|
2015-07-08 12:34:37 -04:00
|
|
|
},
|
2015-07-10 12:07:12 -04:00
|
|
|
&Node{
|
2015-07-08 12:34:37 -04:00
|
|
|
Type: "comments",
|
|
|
|
Attributes: map[string]interface{}{
|
|
|
|
"body": "Needs some work!",
|
|
|
|
},
|
2016-07-05 21:32:15 -04:00
|
|
|
ClientID: "5",
|
2015-07-08 12:34:37 -04:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2015-07-07 18:46:20 -04:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2015-07-06 17:41:53 -04:00
|
|
|
},
|
|
|
|
}
|
2015-07-07 18:46:20 -04:00
|
|
|
|
|
|
|
out := bytes.NewBuffer(nil)
|
|
|
|
json.NewEncoder(out).Encode(payload)
|
|
|
|
|
2015-07-08 12:34:37 -04:00
|
|
|
return out
|
2015-07-06 17:41:53 -04:00
|
|
|
}
|
2015-07-08 16:11:03 -04:00
|
|
|
|
2016-07-05 21:32:15 -04:00
|
|
|
func samplePayloadWithID() io.Reader {
|
2015-07-10 12:07:12 -04:00
|
|
|
payload := &OnePayload{
|
|
|
|
Data: &Node{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: "2",
|
2015-07-08 16:11:03 -04:00
|
|
|
Type: "blogs",
|
|
|
|
Attributes: map[string]interface{}{
|
|
|
|
"title": "New blog",
|
|
|
|
"view_count": 1000,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
out := bytes.NewBuffer(nil)
|
2016-07-22 21:34:38 -04:00
|
|
|
json.NewEncoder(out).Encode(payload)
|
|
|
|
|
|
|
|
return out
|
|
|
|
}
|
|
|
|
|
|
|
|
func sampleWithPointerPayload(m map[string]interface{}) io.Reader {
|
|
|
|
payload := &OnePayload{
|
|
|
|
Data: &Node{
|
|
|
|
ID: "2",
|
|
|
|
Type: "with-pointers",
|
|
|
|
Attributes: m,
|
|
|
|
},
|
|
|
|
}
|
2015-07-08 16:11:03 -04:00
|
|
|
|
2016-07-22 21:34:38 -04:00
|
|
|
out := bytes.NewBuffer(nil)
|
2015-07-08 16:11:03 -04:00
|
|
|
json.NewEncoder(out).Encode(payload)
|
|
|
|
|
|
|
|
return out
|
|
|
|
}
|
2015-07-10 14:41:54 -04:00
|
|
|
|
2015-07-10 20:34:04 -04:00
|
|
|
func testModel() *Blog {
|
|
|
|
return &Blog{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 5,
|
|
|
|
ClientID: "1",
|
2015-07-10 14:41:54 -04:00
|
|
|
Title: "Title 1",
|
|
|
|
CreatedAt: time.Now(),
|
|
|
|
Posts: []*Post{
|
|
|
|
&Post{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 1,
|
2015-07-10 14:41:54 -04:00
|
|
|
Title: "Foo",
|
|
|
|
Body: "Bar",
|
|
|
|
Comments: []*Comment{
|
|
|
|
&Comment{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 1,
|
2015-07-10 14:41:54 -04:00
|
|
|
Body: "foo",
|
|
|
|
},
|
|
|
|
&Comment{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 2,
|
2015-07-10 14:41:54 -04:00
|
|
|
Body: "bar",
|
|
|
|
},
|
|
|
|
},
|
2015-07-12 10:42:52 -04:00
|
|
|
LatestComment: &Comment{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 1,
|
2015-07-12 10:42:52 -04:00
|
|
|
Body: "foo",
|
|
|
|
},
|
2015-07-10 14:41:54 -04:00
|
|
|
},
|
|
|
|
&Post{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 2,
|
2015-07-10 14:41:54 -04:00
|
|
|
Title: "Fuubar",
|
|
|
|
Body: "Bas",
|
|
|
|
Comments: []*Comment{
|
|
|
|
&Comment{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 1,
|
2015-07-10 14:41:54 -04:00
|
|
|
Body: "foo",
|
|
|
|
},
|
|
|
|
&Comment{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 3,
|
2015-07-10 14:41:54 -04:00
|
|
|
Body: "bas",
|
|
|
|
},
|
|
|
|
},
|
2015-07-12 10:42:52 -04:00
|
|
|
LatestComment: &Comment{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 1,
|
2015-07-12 10:42:52 -04:00
|
|
|
Body: "foo",
|
|
|
|
},
|
2015-07-10 14:41:54 -04:00
|
|
|
},
|
|
|
|
},
|
|
|
|
CurrentPost: &Post{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 1,
|
2015-07-10 14:41:54 -04:00
|
|
|
Title: "Foo",
|
|
|
|
Body: "Bar",
|
|
|
|
Comments: []*Comment{
|
|
|
|
&Comment{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 1,
|
2015-07-10 14:41:54 -04:00
|
|
|
Body: "foo",
|
|
|
|
},
|
|
|
|
&Comment{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 2,
|
2015-07-10 14:41:54 -04:00
|
|
|
Body: "bar",
|
|
|
|
},
|
|
|
|
},
|
2015-07-12 10:42:52 -04:00
|
|
|
LatestComment: &Comment{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 1,
|
2015-07-12 10:42:52 -04:00
|
|
|
Body: "foo",
|
|
|
|
},
|
2015-07-10 14:41:54 -04:00
|
|
|
},
|
|
|
|
}
|
2015-07-10 20:34:04 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func samplePayloadWithSideloaded() io.Reader {
|
|
|
|
testModel := testModel()
|
2015-07-10 14:41:54 -04:00
|
|
|
|
|
|
|
out := bytes.NewBuffer(nil)
|
|
|
|
MarshalOnePayload(out, testModel)
|
|
|
|
|
|
|
|
return out
|
|
|
|
}
|
2015-07-12 10:42:52 -04:00
|
|
|
|
|
|
|
func sampleSerializedEmbeddedTestModel() *Blog {
|
|
|
|
out := bytes.NewBuffer(nil)
|
|
|
|
MarshalOnePayloadEmbedded(out, testModel())
|
|
|
|
|
|
|
|
blog := new(Blog)
|
|
|
|
UnmarshalPayload(out, blog)
|
|
|
|
|
|
|
|
return blog
|
|
|
|
}
|