2015-07-05 11:59:30 -04:00
|
|
|
package jsonapi
|
|
|
|
|
2015-07-05 13:59:35 -04:00
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"encoding/json"
|
|
|
|
"testing"
|
2015-07-06 16:40:43 -04:00
|
|
|
"time"
|
2015-07-05 13:59:35 -04:00
|
|
|
)
|
|
|
|
|
2015-07-10 16:50:51 -04:00
|
|
|
type Blog struct {
|
2016-07-05 21:32:15 -04:00
|
|
|
ID int `jsonapi:"primary,blogs"`
|
|
|
|
ClientID string `jsonapi:"client-id"`
|
2015-07-10 16:50:51 -04:00
|
|
|
Title string `jsonapi:"attr,title"`
|
|
|
|
Posts []*Post `jsonapi:"relation,posts"`
|
|
|
|
CurrentPost *Post `jsonapi:"relation,current_post"`
|
2016-07-05 21:32:15 -04:00
|
|
|
CurrentPostID int `jsonapi:"attr,current_post_id"`
|
2015-07-10 16:50:51 -04:00
|
|
|
CreatedAt time.Time `jsonapi:"attr,created_at"`
|
|
|
|
ViewCount int `jsonapi:"attr,view_count"`
|
2015-07-08 12:34:37 -04:00
|
|
|
}
|
|
|
|
|
2015-07-05 13:59:35 -04:00
|
|
|
type Post struct {
|
2015-07-20 19:10:52 -04:00
|
|
|
Blog
|
2016-07-05 21:32:15 -04:00
|
|
|
ID int `jsonapi:"primary,posts"`
|
|
|
|
BlogID int `jsonapi:"attr,blog_id"`
|
|
|
|
ClientID string `jsonapi:"client-id"`
|
2015-07-12 10:42:52 -04:00
|
|
|
Title string `jsonapi:"attr,title"`
|
|
|
|
Body string `jsonapi:"attr,body"`
|
|
|
|
Comments []*Comment `jsonapi:"relation,comments"`
|
|
|
|
LatestComment *Comment `jsonapi:"relation,latest_comment"`
|
2015-07-05 13:59:35 -04:00
|
|
|
}
|
2015-07-05 11:59:30 -04:00
|
|
|
|
2015-07-10 16:50:51 -04:00
|
|
|
type Comment struct {
|
2016-07-05 21:32:15 -04:00
|
|
|
ID int `jsonapi:"primary,comments"`
|
|
|
|
ClientID string `jsonapi:"client-id"`
|
|
|
|
PostID int `jsonapi:"attr,post_id"`
|
2015-09-17 18:55:53 -04:00
|
|
|
Body string `jsonapi:"attr,body"`
|
2015-07-05 11:59:30 -04:00
|
|
|
}
|
|
|
|
|
2016-07-16 11:24:21 -04:00
|
|
|
type Book struct {
|
|
|
|
ID int `jsonapi:"primary,books"`
|
|
|
|
Author string `jsonapi:"attr,author"`
|
|
|
|
ISBN string `jsonapi:"attr,isbn"`
|
|
|
|
Title string `jsonapi:"attr,title,omitempty"`
|
|
|
|
Pages *uint `jsonapi:"attr,pages,omitempty"`
|
|
|
|
PublishedAt time.Time
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestOmitsEmptyAnnotation(t *testing.T) {
|
|
|
|
book := &Book{
|
|
|
|
Author: "aren55555",
|
|
|
|
PublishedAt: time.Now().AddDate(0, -1, 0),
|
|
|
|
}
|
|
|
|
|
|
|
|
out := bytes.NewBuffer(nil)
|
|
|
|
if err := MarshalOnePayload(out, book); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
var jsonData map[string]interface{}
|
|
|
|
if err := json.Unmarshal(out.Bytes(), &jsonData); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
attributes := jsonData["data"].(map[string]interface{})["attributes"].(map[string]interface{})
|
|
|
|
|
|
|
|
// Verify that the specifically omitted field were omitted
|
|
|
|
if val, exists := attributes["title"]; exists {
|
|
|
|
t.Fatalf("Was expecting the data.attributes.title key/value to have been omitted - it was not and had a value of %v", val)
|
|
|
|
}
|
|
|
|
if val, exists := attributes["pages"]; exists {
|
|
|
|
t.Fatalf("Was expecting the data.attributes.pages key/value to have been omitted - it was not and had a value of %v", val)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify the implicity omitted fields were omitted
|
|
|
|
if val, exists := attributes["PublishedAt"]; exists {
|
|
|
|
t.Fatalf("Was expecting the data.attributes.PublishedAt key/value to have been implicity omitted - it was not and had a value of %v", val)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Verify the unset fields were not omitted
|
|
|
|
if _, exists := attributes["isbn"]; !exists {
|
|
|
|
t.Fatal("Was expecting the data.attributes.isbn key/value to have NOT been omitted")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-05 11:59:30 -04:00
|
|
|
func TestHasPrimaryAnnotation(t *testing.T) {
|
2015-07-06 13:38:42 -04:00
|
|
|
testModel := &Blog{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 5,
|
2015-07-06 17:35:17 -04:00
|
|
|
Title: "Title 1",
|
|
|
|
CreatedAt: time.Now(),
|
2015-07-05 11:59:30 -04:00
|
|
|
}
|
|
|
|
|
2015-07-10 11:57:27 -04:00
|
|
|
out := bytes.NewBuffer(nil)
|
2015-07-10 12:07:12 -04:00
|
|
|
if err := MarshalOnePayload(out, testModel); err != nil {
|
2015-07-10 11:57:27 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2015-07-10 12:07:12 -04:00
|
|
|
resp := new(OnePayload)
|
2015-07-10 11:57:27 -04:00
|
|
|
|
|
|
|
if err := json.NewDecoder(out).Decode(resp); err != nil {
|
2015-07-05 11:59:30 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2015-07-10 11:57:27 -04:00
|
|
|
data := resp.Data
|
2015-07-05 13:59:35 -04:00
|
|
|
|
2015-07-10 11:57:27 -04:00
|
|
|
if data.Type != "blogs" {
|
|
|
|
t.Fatalf("type should have been blogs, got %s", data.Type)
|
2015-07-05 11:59:30 -04:00
|
|
|
}
|
|
|
|
|
2016-07-05 21:32:15 -04:00
|
|
|
if data.ID != "5" {
|
|
|
|
t.Fatalf("ID not transfered")
|
2015-07-05 11:59:30 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSupportsAttributes(t *testing.T) {
|
2015-07-06 13:38:42 -04:00
|
|
|
testModel := &Blog{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 5,
|
2015-07-06 17:35:17 -04:00
|
|
|
Title: "Title 1",
|
|
|
|
CreatedAt: time.Now(),
|
2015-07-05 11:59:30 -04:00
|
|
|
}
|
|
|
|
|
2015-07-10 11:57:27 -04:00
|
|
|
out := bytes.NewBuffer(nil)
|
2015-07-10 12:07:12 -04:00
|
|
|
if err := MarshalOnePayload(out, testModel); err != nil {
|
2015-07-10 11:57:27 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2015-07-10 12:07:12 -04:00
|
|
|
resp := new(OnePayload)
|
2015-07-10 11:57:27 -04:00
|
|
|
if err := json.NewDecoder(out).Decode(resp); err != nil {
|
2015-07-05 11:59:30 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2015-07-10 11:57:27 -04:00
|
|
|
data := resp.Data
|
2015-07-05 13:59:35 -04:00
|
|
|
|
2015-07-10 11:57:27 -04:00
|
|
|
if data.Attributes == nil {
|
2015-07-06 16:40:43 -04:00
|
|
|
t.Fatalf("Expected attributes")
|
2015-07-05 11:59:30 -04:00
|
|
|
}
|
|
|
|
|
2015-07-10 11:57:27 -04:00
|
|
|
if data.Attributes["title"] != "Title 1" {
|
2015-07-05 11:59:30 -04:00
|
|
|
t.Fatalf("Attributes hash not populated using tags correctly")
|
|
|
|
}
|
|
|
|
}
|
2015-07-06 14:57:20 -04:00
|
|
|
|
2015-07-09 15:07:33 -04:00
|
|
|
func TestOmitsZeroTimes(t *testing.T) {
|
|
|
|
testModel := &Blog{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 5,
|
2015-07-09 15:07:33 -04:00
|
|
|
Title: "Title 1",
|
|
|
|
CreatedAt: time.Time{},
|
|
|
|
}
|
|
|
|
|
2015-07-10 11:57:27 -04:00
|
|
|
out := bytes.NewBuffer(nil)
|
2015-07-10 12:07:12 -04:00
|
|
|
if err := MarshalOnePayload(out, testModel); err != nil {
|
2015-07-10 11:57:27 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2015-07-10 12:07:12 -04:00
|
|
|
resp := new(OnePayload)
|
2015-07-10 11:57:27 -04:00
|
|
|
if err := json.NewDecoder(out).Decode(resp); err != nil {
|
2015-07-09 15:07:33 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2015-07-10 11:57:27 -04:00
|
|
|
data := resp.Data
|
2015-07-09 15:07:33 -04:00
|
|
|
|
2015-07-10 11:57:27 -04:00
|
|
|
if data.Attributes == nil {
|
2015-07-09 15:07:33 -04:00
|
|
|
t.Fatalf("Expected attributes")
|
|
|
|
}
|
|
|
|
|
2015-07-10 11:57:27 -04:00
|
|
|
if data.Attributes["created_at"] != nil {
|
2015-07-09 15:07:33 -04:00
|
|
|
t.Fatalf("Created at was serialized even though it was a zero Time")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-06 14:57:20 -04:00
|
|
|
func TestRelations(t *testing.T) {
|
2015-07-12 11:46:30 -04:00
|
|
|
testModel := testBlog()
|
2015-07-06 14:57:20 -04:00
|
|
|
|
2015-07-10 11:57:27 -04:00
|
|
|
out := bytes.NewBuffer(nil)
|
2015-07-10 12:07:12 -04:00
|
|
|
if err := MarshalOnePayload(out, testModel); err != nil {
|
2015-07-06 14:57:20 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2015-07-10 12:07:12 -04:00
|
|
|
resp := new(OnePayload)
|
2015-07-10 11:57:27 -04:00
|
|
|
if err := json.NewDecoder(out).Decode(resp); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-07-06 14:57:20 -04:00
|
|
|
|
|
|
|
relations := resp.Data.Relationships
|
|
|
|
|
|
|
|
if relations == nil {
|
|
|
|
t.Fatalf("Relationships were not materialized")
|
|
|
|
}
|
|
|
|
|
|
|
|
if relations["posts"] == nil {
|
|
|
|
t.Fatalf("Posts relationship was not materialized")
|
|
|
|
}
|
|
|
|
|
|
|
|
if relations["current_post"] == nil {
|
|
|
|
t.Fatalf("Current post relationship was not materialized")
|
|
|
|
}
|
2015-07-06 15:00:17 -04:00
|
|
|
|
2015-07-10 11:57:27 -04:00
|
|
|
if len(relations["posts"].(map[string]interface{})["data"].([]interface{})) != 2 {
|
2015-07-06 15:00:17 -04:00
|
|
|
t.Fatalf("Did not materialize two posts")
|
|
|
|
}
|
2015-07-06 14:57:20 -04:00
|
|
|
}
|
|
|
|
|
2015-07-06 13:38:42 -04:00
|
|
|
func TestNoRelations(t *testing.T) {
|
2016-07-05 21:32:15 -04:00
|
|
|
testModel := &Blog{ID: 1, Title: "Title 1", CreatedAt: time.Now()}
|
2015-07-06 13:38:42 -04:00
|
|
|
|
2015-07-10 11:57:27 -04:00
|
|
|
out := bytes.NewBuffer(nil)
|
2015-07-10 12:07:12 -04:00
|
|
|
if err := MarshalOnePayload(out, testModel); err != nil {
|
2015-07-06 13:38:42 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2015-07-10 12:07:12 -04:00
|
|
|
resp := new(OnePayload)
|
2015-07-10 11:57:27 -04:00
|
|
|
if err := json.NewDecoder(out).Decode(resp); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-07-06 13:38:42 -04:00
|
|
|
|
2016-07-13 21:32:04 -04:00
|
|
|
if resp.Included != nil {
|
|
|
|
t.Fatalf("Encoding json response did not omit included")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMarshalOnePayloadWithoutIncluded(t *testing.T) {
|
|
|
|
data := &Post{
|
2016-07-15 16:40:23 -04:00
|
|
|
ID: 1,
|
|
|
|
BlogID: 2,
|
|
|
|
ClientID: "123e4567-e89b-12d3-a456-426655440000",
|
2016-07-13 21:32:04 -04:00
|
|
|
Title: "Foo",
|
|
|
|
Body: "Bar",
|
|
|
|
Comments: []*Comment{
|
|
|
|
&Comment{
|
2016-07-15 16:40:23 -04:00
|
|
|
ID: 20,
|
2016-07-13 21:32:04 -04:00
|
|
|
Body: "First",
|
|
|
|
},
|
|
|
|
&Comment{
|
2016-07-15 16:40:23 -04:00
|
|
|
ID: 21,
|
2016-07-13 21:32:04 -04:00
|
|
|
Body: "Hello World",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
LatestComment: &Comment{
|
2016-07-15 16:40:23 -04:00
|
|
|
ID: 22,
|
2016-07-13 21:32:04 -04:00
|
|
|
Body: "Cool!",
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
out := bytes.NewBuffer(nil)
|
|
|
|
if err := MarshalOnePayloadWithoutIncluded(out, data); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
resp := new(OnePayload)
|
|
|
|
if err := json.NewDecoder(out).Decode(resp); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2015-07-10 11:57:27 -04:00
|
|
|
if resp.Included != nil {
|
2015-07-06 13:38:42 -04:00
|
|
|
t.Fatalf("Encoding json response did not omit included")
|
|
|
|
}
|
|
|
|
}
|
2015-07-07 12:52:38 -04:00
|
|
|
|
|
|
|
func TestMarshalMany(t *testing.T) {
|
2015-07-12 14:37:31 -04:00
|
|
|
data := []interface{}{
|
2015-07-07 12:52:38 -04:00
|
|
|
&Blog{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 5,
|
2015-07-07 12:52:38 -04:00
|
|
|
Title: "Title 1",
|
|
|
|
CreatedAt: time.Now(),
|
|
|
|
Posts: []*Post{
|
|
|
|
&Post{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 1,
|
2015-07-07 12:52:38 -04:00
|
|
|
Title: "Foo",
|
|
|
|
Body: "Bar",
|
|
|
|
},
|
|
|
|
&Post{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 2,
|
2015-07-07 12:52:38 -04:00
|
|
|
Title: "Fuubar",
|
|
|
|
Body: "Bas",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
CurrentPost: &Post{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 1,
|
2015-07-07 12:52:38 -04:00
|
|
|
Title: "Foo",
|
|
|
|
Body: "Bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&Blog{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 6,
|
2015-07-07 12:52:38 -04:00
|
|
|
Title: "Title 2",
|
|
|
|
CreatedAt: time.Now(),
|
|
|
|
Posts: []*Post{
|
|
|
|
&Post{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 3,
|
2015-07-07 12:52:38 -04:00
|
|
|
Title: "Foo",
|
|
|
|
Body: "Bar",
|
|
|
|
},
|
|
|
|
&Post{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 4,
|
2015-07-07 12:52:38 -04:00
|
|
|
Title: "Fuubar",
|
|
|
|
Body: "Bas",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
CurrentPost: &Post{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 4,
|
2015-07-07 12:52:38 -04:00
|
|
|
Title: "Foo",
|
|
|
|
Body: "Bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2015-07-10 11:57:27 -04:00
|
|
|
out := bytes.NewBuffer(nil)
|
2015-07-12 14:45:03 -04:00
|
|
|
if err := MarshalManyPayload(out, data); err != nil {
|
2015-07-07 12:52:38 -04:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2015-07-10 12:07:12 -04:00
|
|
|
resp := new(ManyPayload)
|
2015-07-10 11:57:27 -04:00
|
|
|
if err := json.NewDecoder(out).Decode(resp); err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2015-07-07 12:52:38 -04:00
|
|
|
|
|
|
|
d := resp.Data
|
|
|
|
|
|
|
|
if len(d) != 2 {
|
|
|
|
t.Fatalf("data should have two elements")
|
|
|
|
}
|
|
|
|
}
|
2015-07-12 11:46:30 -04:00
|
|
|
|
|
|
|
func testBlog() *Blog {
|
|
|
|
return &Blog{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 5,
|
2015-07-12 11:46:30 -04:00
|
|
|
Title: "Title 1",
|
|
|
|
CreatedAt: time.Now(),
|
|
|
|
Posts: []*Post{
|
|
|
|
&Post{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 1,
|
2015-07-12 11:46:30 -04:00
|
|
|
Title: "Foo",
|
|
|
|
Body: "Bar",
|
|
|
|
Comments: []*Comment{
|
|
|
|
&Comment{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 1,
|
2015-07-12 11:46:30 -04:00
|
|
|
Body: "foo",
|
|
|
|
},
|
|
|
|
&Comment{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 2,
|
2015-07-12 11:46:30 -04:00
|
|
|
Body: "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
LatestComment: &Comment{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 1,
|
2015-07-12 11:46:30 -04:00
|
|
|
Body: "foo",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
&Post{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 2,
|
2015-07-12 11:46:30 -04:00
|
|
|
Title: "Fuubar",
|
|
|
|
Body: "Bas",
|
|
|
|
Comments: []*Comment{
|
|
|
|
&Comment{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 1,
|
2015-07-12 11:46:30 -04:00
|
|
|
Body: "foo",
|
|
|
|
},
|
|
|
|
&Comment{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 3,
|
2015-07-12 11:46:30 -04:00
|
|
|
Body: "bas",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
LatestComment: &Comment{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 1,
|
2015-07-12 11:46:30 -04:00
|
|
|
Body: "foo",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
CurrentPost: &Post{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 1,
|
2015-07-12 11:46:30 -04:00
|
|
|
Title: "Foo",
|
|
|
|
Body: "Bar",
|
|
|
|
Comments: []*Comment{
|
|
|
|
&Comment{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 1,
|
2015-07-12 11:46:30 -04:00
|
|
|
Body: "foo",
|
|
|
|
},
|
|
|
|
&Comment{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 2,
|
2015-07-12 11:46:30 -04:00
|
|
|
Body: "bar",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
LatestComment: &Comment{
|
2016-07-05 21:32:15 -04:00
|
|
|
ID: 1,
|
2015-07-12 11:46:30 -04:00
|
|
|
Body: "foo",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|