github.com/seeker-insurance/kit@v0.0.13/jsonapi/request_test.go (about) 1 package jsonapi 2 3 import ( 4 "bytes" 5 "encoding/json" 6 "fmt" 7 "io" 8 "reflect" 9 "sort" 10 "strings" 11 "testing" 12 "time" 13 ) 14 15 func TestUnmarshall_attrStringSlice(t *testing.T) { 16 out := &Book{} 17 tags := []string{"fiction", "sale"} 18 data := map[string]interface{}{ 19 "data": map[string]interface{}{ 20 "type": "books", 21 "id": "1", 22 "attributes": map[string]interface{}{"tags": tags}, 23 }, 24 } 25 b, err := json.Marshal(data) 26 if err != nil { 27 t.Fatal(err) 28 } 29 30 if err := UnmarshalPayload(bytes.NewReader(b), out); err != nil { 31 t.Fatal(err) 32 } 33 34 if e, a := len(tags), len(out.Tags); e != a { 35 t.Fatalf("Was expecting %d tags, got %d", e, a) 36 } 37 38 sort.Strings(tags) 39 sort.Strings(out.Tags) 40 41 for i, tag := range tags { 42 if e, a := tag, out.Tags[i]; e != a { 43 t.Fatalf("At index %d, was expecting %s got %s", i, e, a) 44 } 45 } 46 } 47 48 func TestUnmarshalToStructWithPointerAttr(t *testing.T) { 49 out := new(WithPointer) 50 in := map[string]interface{}{ 51 "name": "The name", 52 "is-active": true, 53 "int-val": 8, 54 "float-val": 1.1, 55 } 56 if err := UnmarshalPayload(sampleWithPointerPayload(in), out); err != nil { 57 t.Fatal(err) 58 } 59 if *out.Name != "The name" { 60 t.Fatalf("Error unmarshalling to string ptr") 61 } 62 if !*out.IsActive { 63 t.Fatalf("Error unmarshalling to bool ptr") 64 } 65 if *out.IntVal != 8 { 66 t.Fatalf("Error unmarshalling to int ptr") 67 } 68 if *out.FloatVal != 1.1 { 69 t.Fatalf("Error unmarshalling to float ptr") 70 } 71 } 72 73 func TestUnmarshalPayload_ptrsAllNil(t *testing.T) { 74 out := new(WithPointer) 75 if err := UnmarshalPayload( 76 strings.NewReader(`{"data": {}}`), out); err != nil { 77 t.Fatalf("Error unmarshalling to Foo") 78 } 79 80 if out.ID != nil { 81 t.Fatalf("Error unmarshalling; expected ID ptr to be nil") 82 } 83 } 84 85 func TestUnmarshalPayloadWithPointerID(t *testing.T) { 86 out := new(WithPointer) 87 attrs := map[string]interface{}{} 88 89 if err := UnmarshalPayload(sampleWithPointerPayload(attrs), out); err != nil { 90 t.Fatalf("Error unmarshalling to Foo") 91 } 92 93 // these were present in the payload -- expect val to be not nil 94 if out.ID == nil { 95 t.Fatalf("Error unmarshalling; expected ID ptr to be not nil") 96 } 97 if e, a := uint64(2), *out.ID; e != a { 98 t.Fatalf("Was expecting the ID to have a value of %d, got %d", e, a) 99 } 100 } 101 102 func TestUnmarshalPayloadWithPointerAttr_AbsentVal(t *testing.T) { 103 out := new(WithPointer) 104 in := map[string]interface{}{ 105 "name": "The name", 106 "is-active": true, 107 } 108 109 if err := UnmarshalPayload(sampleWithPointerPayload(in), out); err != nil { 110 t.Fatalf("Error unmarshalling to Foo") 111 } 112 113 // these were present in the payload -- expect val to be not nil 114 if out.Name == nil || out.IsActive == nil { 115 t.Fatalf("Error unmarshalling; expected ptr to be not nil") 116 } 117 118 // these were absent in the payload -- expect val to be nil 119 if out.IntVal != nil || out.FloatVal != nil { 120 t.Fatalf("Error unmarshalling; expected ptr to be nil") 121 } 122 } 123 124 func TestUnmarshalToStructWithPointerAttr_BadType(t *testing.T) { 125 out := new(WithPointer) 126 in := map[string]interface{}{ 127 "name": true, // This is the wrong type. 128 } 129 expectedErrorMessage := ErrUnsupportedPtrType.Error() 130 131 err := UnmarshalPayload(sampleWithPointerPayload(in), out) 132 133 if err == nil { 134 t.Fatalf("Expected error due to invalid type.") 135 } 136 if err.Error() != expectedErrorMessage { 137 t.Fatalf("Unexpected error message: %s", err.Error()) 138 } 139 } 140 141 func TestStringPointerField(t *testing.T) { 142 // Build Book payload 143 description := "Hello World!" 144 data := map[string]interface{}{ 145 "data": map[string]interface{}{ 146 "type": "books", 147 "id": "5", 148 "attributes": map[string]interface{}{ 149 "author": "aren55555", 150 "description": description, 151 "isbn": "", 152 }, 153 }, 154 } 155 payload, err := json.Marshal(data) 156 if err != nil { 157 t.Fatal(err) 158 } 159 160 // Parse JSON API payload 161 book := new(Book) 162 if err := UnmarshalPayload(bytes.NewReader(payload), book); err != nil { 163 t.Fatal(err) 164 } 165 166 if book.Description == nil { 167 t.Fatal("Was not expecting a nil pointer for book.Description") 168 } 169 if expected, actual := description, *book.Description; expected != actual { 170 t.Fatalf("Was expecting descript to be `%s`, got `%s`", expected, actual) 171 } 172 } 173 174 func TestMalformedTag(t *testing.T) { 175 out := new(BadModel) 176 err := UnmarshalPayload(samplePayload(), out) 177 if err == nil || err != ErrBadJSONAPIStructTag { 178 t.Fatalf("Did not error out with wrong number of arguments in tag") 179 } 180 } 181 182 func TestUnmarshalInvalidJSON(t *testing.T) { 183 in := strings.NewReader("{}") 184 out := new(Blog) 185 186 err := UnmarshalPayload(in, out) 187 188 if err == nil { 189 t.Fatalf("Did not error out the invalid JSON.") 190 } 191 } 192 193 func TestUnmarshalInvalidJSON_BadType(t *testing.T) { 194 var badTypeTests = []struct { 195 Field string 196 BadValue interface{} 197 Error error 198 }{ // The `Field` values here correspond to the `ModelBadTypes` jsonapi fields. 199 {Field: "string_field", BadValue: 0, Error: ErrUnknownFieldNumberType}, // Expected string. 200 {Field: "float_field", BadValue: "A string.", Error: ErrInvalidType}, // Expected float64. 201 {Field: "time_field", BadValue: "A string.", Error: ErrInvalidTime}, // Expected int64. 202 {Field: "time_ptr_field", BadValue: "A string.", Error: ErrInvalidTime}, // Expected *time / int64. 203 } 204 for _, test := range badTypeTests { 205 t.Run(fmt.Sprintf("Test_%s", test.Field), func(t *testing.T) { 206 out := new(ModelBadTypes) 207 in := map[string]interface{}{} 208 in[test.Field] = test.BadValue 209 expectedErrorMessage := test.Error.Error() 210 211 err := UnmarshalPayload(samplePayloadWithBadTypes(in), out) 212 213 if err == nil { 214 t.Fatalf("Expected error due to invalid type.") 215 } 216 if err.Error() != expectedErrorMessage { 217 t.Fatalf("Unexpected error message: %s", err.Error()) 218 } 219 }) 220 } 221 } 222 223 func TestUnmarshalSetsID(t *testing.T) { 224 in := samplePayloadWithID() 225 out := new(Blog) 226 227 if err := UnmarshalPayload(in, out); err != nil { 228 t.Fatal(err) 229 } 230 231 if out.ID != 2 { 232 t.Fatalf("Did not set ID on dst interface") 233 } 234 } 235 236 func TestUnmarshal_nonNumericID(t *testing.T) { 237 data := samplePayloadWithoutIncluded() 238 data["data"].(map[string]interface{})["id"] = "non-numeric-id" 239 payload, _ := payload(data) 240 in := bytes.NewReader(payload) 241 out := new(Post) 242 243 if err := UnmarshalPayload(in, out); err != ErrBadJSONAPIID { 244 t.Fatalf( 245 "Was expecting a `%s` error, got `%s`", 246 ErrBadJSONAPIID, 247 err, 248 ) 249 } 250 } 251 252 func TestUnmarshalSetsAttrs(t *testing.T) { 253 out, err := unmarshalSamplePayload() 254 if err != nil { 255 t.Fatal(err) 256 } 257 258 if out.CreatedAt.IsZero() { 259 t.Fatalf("Did not parse time") 260 } 261 262 if out.ViewCount != 1000 { 263 t.Fatalf("View count not properly serialized") 264 } 265 } 266 267 func TestUnmarshalParsesISO8601(t *testing.T) { 268 payload := &OnePayload{ 269 Data: &Node{ 270 Type: "timestamps", 271 Attributes: map[string]interface{}{ 272 "timestamp": "2016-08-17T08:27:12Z", 273 }, 274 }, 275 } 276 277 in := bytes.NewBuffer(nil) 278 json.NewEncoder(in).Encode(payload) 279 280 out := new(Timestamp) 281 282 if err := UnmarshalPayload(in, out); err != nil { 283 t.Fatal(err) 284 } 285 286 expected := time.Date(2016, 8, 17, 8, 27, 12, 0, time.UTC) 287 288 if !out.Time.Equal(expected) { 289 t.Fatal("Parsing the ISO8601 timestamp failed") 290 } 291 } 292 293 func TestUnmarshalParsesISO8601TimePointer(t *testing.T) { 294 payload := &OnePayload{ 295 Data: &Node{ 296 Type: "timestamps", 297 Attributes: map[string]interface{}{ 298 "next": "2016-08-17T08:27:12Z", 299 }, 300 }, 301 } 302 303 in := bytes.NewBuffer(nil) 304 json.NewEncoder(in).Encode(payload) 305 306 out := new(Timestamp) 307 308 if err := UnmarshalPayload(in, out); err != nil { 309 t.Fatal(err) 310 } 311 312 expected := time.Date(2016, 8, 17, 8, 27, 12, 0, time.UTC) 313 314 if !out.Next.Equal(expected) { 315 t.Fatal("Parsing the ISO8601 timestamp failed") 316 } 317 } 318 319 func TestUnmarshalInvalidISO8601(t *testing.T) { 320 payload := &OnePayload{ 321 Data: &Node{ 322 Type: "timestamps", 323 Attributes: map[string]interface{}{ 324 "timestamp": "17 Aug 16 08:027 MST", 325 }, 326 }, 327 } 328 329 in := bytes.NewBuffer(nil) 330 json.NewEncoder(in).Encode(payload) 331 332 out := new(Timestamp) 333 334 if err := UnmarshalPayload(in, out); err != ErrInvalidISO8601 { 335 t.Fatalf("Expected ErrInvalidISO8601, got %v", err) 336 } 337 } 338 339 func TestUnmarshalRelationshipsWithoutIncluded(t *testing.T) { 340 data, _ := payload(samplePayloadWithoutIncluded()) 341 in := bytes.NewReader(data) 342 out := new(Post) 343 344 if err := UnmarshalPayload(in, out); err != nil { 345 t.Fatal(err) 346 } 347 348 // Verify each comment has at least an ID 349 for _, comment := range out.Comments { 350 if comment.ID == 0 { 351 t.Fatalf("The comment did not have an ID") 352 } 353 } 354 } 355 356 func TestUnmarshalRelationships(t *testing.T) { 357 out, err := unmarshalSamplePayload() 358 if err != nil { 359 t.Fatal(err) 360 } 361 362 if out.CurrentPost == nil { 363 t.Fatalf("Current post was not materialized") 364 } 365 366 if out.CurrentPost.Title != "Bas" || out.CurrentPost.Body != "Fuubar" { 367 t.Fatalf("Attributes were not set") 368 } 369 370 if len(out.Posts) != 2 { 371 t.Fatalf("There should have been 2 posts") 372 } 373 } 374 375 func TestUnmarshalNullRelationship(t *testing.T) { 376 sample := map[string]interface{}{ 377 "data": map[string]interface{}{ 378 "type": "posts", 379 "id": "1", 380 "attributes": map[string]interface{}{ 381 "body": "Hello", 382 "title": "World", 383 }, 384 "relationships": map[string]interface{}{ 385 "latest_comment": map[string]interface{}{ 386 "data": nil, // empty to-one relationship 387 }, 388 }, 389 }, 390 } 391 data, err := json.Marshal(sample) 392 if err != nil { 393 t.Fatal(err) 394 } 395 396 in := bytes.NewReader(data) 397 out := new(Post) 398 399 if err := UnmarshalPayload(in, out); err != nil { 400 t.Fatal(err) 401 } 402 403 if out.LatestComment != nil { 404 t.Fatalf("Latest Comment was not set to nil") 405 } 406 } 407 408 func TestUnmarshalNullRelationshipInSlice(t *testing.T) { 409 sample := map[string]interface{}{ 410 "data": map[string]interface{}{ 411 "type": "posts", 412 "id": "1", 413 "attributes": map[string]interface{}{ 414 "body": "Hello", 415 "title": "World", 416 }, 417 "relationships": map[string]interface{}{ 418 "comments": map[string]interface{}{ 419 "data": []interface{}{}, // empty to-many relationships 420 }, 421 }, 422 }, 423 } 424 data, err := json.Marshal(sample) 425 if err != nil { 426 t.Fatal(err) 427 } 428 429 in := bytes.NewReader(data) 430 out := new(Post) 431 432 if err := UnmarshalPayload(in, out); err != nil { 433 t.Fatal(err) 434 } 435 436 if len(out.Comments) != 0 { 437 t.Fatalf("Wrong number of comments; Comments should be empty") 438 } 439 } 440 441 func TestUnmarshalNestedRelationships(t *testing.T) { 442 out, err := unmarshalSamplePayload() 443 if err != nil { 444 t.Fatal(err) 445 } 446 447 if out.CurrentPost == nil { 448 t.Fatalf("Current post was not materialized") 449 } 450 451 if out.CurrentPost.Comments == nil { 452 t.Fatalf("Did not materialize nested records, comments") 453 } 454 455 if len(out.CurrentPost.Comments) != 2 { 456 t.Fatalf("Wrong number of comments") 457 } 458 } 459 460 func TestUnmarshalRelationshipsSerializedEmbedded(t *testing.T) { 461 out := sampleSerializedEmbeddedTestModel() 462 463 if out.CurrentPost == nil { 464 t.Fatalf("Current post was not materialized") 465 } 466 467 if out.CurrentPost.Title != "Foo" || out.CurrentPost.Body != "Bar" { 468 t.Fatalf("Attributes were not set") 469 } 470 471 if len(out.Posts) != 2 { 472 t.Fatalf("There should have been 2 posts") 473 } 474 475 if out.Posts[0].LatestComment.Body != "foo" { 476 t.Fatalf("The comment body was not set") 477 } 478 } 479 480 func TestUnmarshalNestedRelationshipsEmbedded(t *testing.T) { 481 out := bytes.NewBuffer(nil) 482 if err := MarshalOnePayloadEmbedded(out, testModel()); err != nil { 483 t.Fatal(err) 484 } 485 486 model := new(Blog) 487 488 if err := UnmarshalPayload(out, model); err != nil { 489 t.Fatal(err) 490 } 491 492 if model.CurrentPost == nil { 493 t.Fatalf("Current post was not materialized") 494 } 495 496 if model.CurrentPost.Comments == nil { 497 t.Fatalf("Did not materialize nested records, comments") 498 } 499 500 if len(model.CurrentPost.Comments) != 2 { 501 t.Fatalf("Wrong number of comments") 502 } 503 504 if model.CurrentPost.Comments[0].Body != "foo" { 505 t.Fatalf("Comment body not set") 506 } 507 } 508 509 func TestUnmarshalRelationshipsSideloaded(t *testing.T) { 510 payload := samplePayloadWithSideloaded() 511 out := new(Blog) 512 513 if err := UnmarshalPayload(payload, out); err != nil { 514 t.Fatal(err) 515 } 516 517 if out.CurrentPost == nil { 518 t.Fatalf("Current post was not materialized") 519 } 520 521 if out.CurrentPost.Title != "Foo" || out.CurrentPost.Body != "Bar" { 522 t.Fatalf("Attributes were not set") 523 } 524 525 if len(out.Posts) != 2 { 526 t.Fatalf("There should have been 2 posts") 527 } 528 } 529 530 func TestUnmarshalNestedRelationshipsSideloaded(t *testing.T) { 531 payload := samplePayloadWithSideloaded() 532 out := new(Blog) 533 534 if err := UnmarshalPayload(payload, out); err != nil { 535 t.Fatal(err) 536 } 537 538 if out.CurrentPost == nil { 539 t.Fatalf("Current post was not materialized") 540 } 541 542 if out.CurrentPost.Comments == nil { 543 t.Fatalf("Did not materialize nested records, comments") 544 } 545 546 if len(out.CurrentPost.Comments) != 2 { 547 t.Fatalf("Wrong number of comments") 548 } 549 550 if out.CurrentPost.Comments[0].Body != "foo" { 551 t.Fatalf("Comment body not set") 552 } 553 } 554 555 func TestUnmarshalNestedRelationshipsEmbedded_withClientIDs(t *testing.T) { 556 model := new(Blog) 557 558 if err := UnmarshalPayload(samplePayload(), model); err != nil { 559 t.Fatal(err) 560 } 561 562 if model.Posts[0].ClientID == "" { 563 t.Fatalf("ClientID not set from request on related record") 564 } 565 } 566 567 func unmarshalSamplePayload() (*Blog, error) { 568 in := samplePayload() 569 out := new(Blog) 570 571 if err := UnmarshalPayload(in, out); err != nil { 572 return nil, err 573 } 574 575 return out, nil 576 } 577 578 func TestUnmarshalManyPayload(t *testing.T) { 579 sample := map[string]interface{}{ 580 "data": []interface{}{ 581 map[string]interface{}{ 582 "type": "posts", 583 "id": "1", 584 "attributes": map[string]interface{}{ 585 "body": "First", 586 "title": "Post", 587 }, 588 }, 589 map[string]interface{}{ 590 "type": "posts", 591 "id": "2", 592 "attributes": map[string]interface{}{ 593 "body": "Second", 594 "title": "Post", 595 }, 596 }, 597 }, 598 } 599 600 data, err := json.Marshal(sample) 601 if err != nil { 602 t.Fatal(err) 603 } 604 in := bytes.NewReader(data) 605 606 posts, err := UnmarshalManyPayload(in, reflect.TypeOf(new(Post))) 607 if err != nil { 608 t.Fatal(err) 609 } 610 611 if len(posts) != 2 { 612 t.Fatal("Wrong number of posts") 613 } 614 615 for _, p := range posts { 616 _, ok := p.(*Post) 617 if !ok { 618 t.Fatal("Was expecting a Post") 619 } 620 } 621 } 622 623 func TestManyPayload_withLinks(t *testing.T) { 624 firstPageURL := "http://somesite.com/movies?page[limit]=50&page[offset]=50" 625 prevPageURL := "http://somesite.com/movies?page[limit]=50&page[offset]=0" 626 nextPageURL := "http://somesite.com/movies?page[limit]=50&page[offset]=100" 627 lastPageURL := "http://somesite.com/movies?page[limit]=50&page[offset]=500" 628 629 sample := map[string]interface{}{ 630 "data": []interface{}{ 631 map[string]interface{}{ 632 "type": "posts", 633 "id": "1", 634 "attributes": map[string]interface{}{ 635 "body": "First", 636 "title": "Post", 637 }, 638 }, 639 map[string]interface{}{ 640 "type": "posts", 641 "id": "2", 642 "attributes": map[string]interface{}{ 643 "body": "Second", 644 "title": "Post", 645 }, 646 }, 647 }, 648 "links": map[string]interface{}{ 649 KeyFirstPage: firstPageURL, 650 KeyPreviousPage: prevPageURL, 651 KeyNextPage: nextPageURL, 652 KeyLastPage: lastPageURL, 653 }, 654 } 655 656 data, err := json.Marshal(sample) 657 if err != nil { 658 t.Fatal(err) 659 } 660 in := bytes.NewReader(data) 661 662 payload := new(ManyPayload) 663 if err = json.NewDecoder(in).Decode(payload); err != nil { 664 t.Fatal(err) 665 } 666 667 if payload.Links == nil { 668 t.Fatal("Was expecting a non nil ptr Link field") 669 } 670 671 links := *payload.Links 672 673 first, ok := links[KeyFirstPage] 674 if !ok { 675 t.Fatal("Was expecting a non nil ptr Link field") 676 } 677 if e, a := firstPageURL, first; e != a { 678 t.Fatalf("Was expecting links.%s to have a value of %s, got %s", KeyFirstPage, e, a) 679 } 680 681 prev, ok := links[KeyPreviousPage] 682 if !ok { 683 t.Fatal("Was expecting a non nil ptr Link field") 684 } 685 if e, a := prevPageURL, prev; e != a { 686 t.Fatalf("Was expecting links.%s to have a value of %s, got %s", KeyPreviousPage, e, a) 687 } 688 689 next, ok := links[KeyNextPage] 690 if !ok { 691 t.Fatal("Was expecting a non nil ptr Link field") 692 } 693 if e, a := nextPageURL, next; e != a { 694 t.Fatalf("Was expecting links.%s to have a value of %s, got %s", KeyNextPage, e, a) 695 } 696 697 last, ok := links[KeyLastPage] 698 if !ok { 699 t.Fatal("Was expecting a non nil ptr Link field") 700 } 701 if e, a := lastPageURL, last; e != a { 702 t.Fatalf("Was expecting links.%s to have a value of %s, got %s", KeyLastPage, e, a) 703 } 704 } 705 706 func TestEmbeddedStructs_nonNilStructPtr(t *testing.T) { 707 originalVehicle := &Vehicle{ 708 Make: "VW", 709 Model: "R32", 710 Year: 2008, 711 Engine: Engine{ 712 NumberOfCylinders: 6, 713 HorsePower: 250, 714 }, 715 BlockHeater: &BlockHeater{ 716 Watts: 150, 717 }, 718 } 719 720 // Serialize as JSON 721 jsonVehicle, err := json.Marshal(originalVehicle) 722 if err != nil { 723 t.Fatal(err) 724 } 725 726 jsonUnmarshalledVehicle := &Vehicle{} 727 json.Unmarshal(jsonVehicle, jsonUnmarshalledVehicle) 728 729 // Proves that the JSON standard lib will allocate a BlockHeater 730 if jsonUnmarshalledVehicle.BlockHeater == nil { 731 t.Fatal("was expecting a non nil Block Heater ptr") 732 } 733 if e, a := originalVehicle.BlockHeater.Watts, jsonUnmarshalledVehicle.BlockHeater.Watts; e != a { 734 t.Fatalf("was expecting watts to be %v, got %v", e, a) 735 } 736 737 // Serialize as JSONAPI 738 jsonAPIVehicle := new(bytes.Buffer) 739 if err = MarshalPayload(jsonAPIVehicle, originalVehicle); err != nil { 740 t.Fatal(err) 741 } 742 743 jsonAPIUnmarshalledVehicle := &Vehicle{} 744 if err = UnmarshalPayload(jsonAPIVehicle, jsonAPIUnmarshalledVehicle); err != nil { 745 t.Fatal(err) 746 } 747 748 if jsonAPIUnmarshalledVehicle.BlockHeater == nil { 749 t.Fatal("was expecting a non nil Block Heater ptr") 750 } 751 if e, a := originalVehicle.BlockHeater.Watts, jsonAPIUnmarshalledVehicle.BlockHeater.Watts; e != a { 752 t.Fatalf("was expecting watts to be %v, got %v", e, a) 753 } 754 } 755 756 func TestEmbeddedStructs_nilStructPtr(t *testing.T) { 757 originalVehicle := &Vehicle{ 758 Make: "VW", 759 Model: "R32", 760 Year: 2008, 761 Engine: Engine{ 762 NumberOfCylinders: 6, 763 HorsePower: 250, 764 }, 765 } 766 767 // Serialize as JSON 768 jsonVehicle, err := json.Marshal(originalVehicle) 769 if err != nil { 770 t.Fatal(err) 771 } 772 773 jsonUnmarshalledVehicle := &Vehicle{} 774 json.Unmarshal(jsonVehicle, jsonUnmarshalledVehicle) 775 776 // Proves that the JSON standard lib will NOT allocate a BlockHeater 777 if e, a := originalVehicle.BlockHeater, jsonUnmarshalledVehicle.BlockHeater; e != a { 778 t.Fatalf("was expecting BlockHeater to be %v, got %v", e, a) 779 } 780 781 // Serialize as JSONAPI 782 jsonAPIVehicle := new(bytes.Buffer) 783 if err = MarshalPayload(jsonAPIVehicle, originalVehicle); err != nil { 784 t.Fatal(err) 785 } 786 787 jsonAPIUnmarshalledVehicle := &Vehicle{} 788 if err = UnmarshalPayload(jsonAPIVehicle, jsonAPIUnmarshalledVehicle); err != nil { 789 t.Fatal(err) 790 } 791 792 if e, a := originalVehicle.BlockHeater, jsonAPIUnmarshalledVehicle.BlockHeater; e != a { 793 t.Fatalf("was expecting BlockHeater to be %v, got %v", e, a) 794 } 795 } 796 797 func samplePayloadWithoutIncluded() map[string]interface{} { 798 return map[string]interface{}{ 799 "data": map[string]interface{}{ 800 "type": "posts", 801 "id": "1", 802 "attributes": map[string]interface{}{ 803 "body": "Hello", 804 "title": "World", 805 }, 806 "relationships": map[string]interface{}{ 807 "comments": map[string]interface{}{ 808 "data": []interface{}{ 809 map[string]interface{}{ 810 "type": "comments", 811 "id": "123", 812 }, 813 map[string]interface{}{ 814 "type": "comments", 815 "id": "456", 816 }, 817 }, 818 }, 819 "latest_comment": map[string]interface{}{ 820 "data": map[string]interface{}{ 821 "type": "comments", 822 "id": "55555", 823 }, 824 }, 825 }, 826 }, 827 } 828 } 829 830 func payload(data map[string]interface{}) (result []byte, err error) { 831 result, err = json.Marshal(data) 832 return 833 } 834 835 func samplePayload() io.Reader { 836 payload := &OnePayload{ 837 Data: &Node{ 838 Type: "blogs", 839 Attributes: map[string]interface{}{ 840 "title": "New blog", 841 "created_at": 1436216820, 842 "view_count": 1000, 843 }, 844 Relationships: map[string]interface{}{ 845 "posts": &RelationshipManyNode{ 846 Data: []*Node{ 847 { 848 Type: "posts", 849 Attributes: map[string]interface{}{ 850 "title": "Foo", 851 "body": "Bar", 852 }, 853 ClientID: "1", 854 }, 855 { 856 Type: "posts", 857 Attributes: map[string]interface{}{ 858 "title": "X", 859 "body": "Y", 860 }, 861 ClientID: "2", 862 }, 863 }, 864 }, 865 "current_post": &RelationshipOneNode{ 866 Data: &Node{ 867 Type: "posts", 868 Attributes: map[string]interface{}{ 869 "title": "Bas", 870 "body": "Fuubar", 871 }, 872 ClientID: "3", 873 Relationships: map[string]interface{}{ 874 "comments": &RelationshipManyNode{ 875 Data: []*Node{ 876 { 877 Type: "comments", 878 Attributes: map[string]interface{}{ 879 "body": "Great post!", 880 }, 881 ClientID: "4", 882 }, 883 { 884 Type: "comments", 885 Attributes: map[string]interface{}{ 886 "body": "Needs some work!", 887 }, 888 ClientID: "5", 889 }, 890 }, 891 }, 892 }, 893 }, 894 }, 895 }, 896 }, 897 } 898 899 out := bytes.NewBuffer(nil) 900 json.NewEncoder(out).Encode(payload) 901 902 return out 903 } 904 905 func samplePayloadWithID() io.Reader { 906 payload := &OnePayload{ 907 Data: &Node{ 908 ID: "2", 909 Type: "blogs", 910 Attributes: map[string]interface{}{ 911 "title": "New blog", 912 "view_count": 1000, 913 }, 914 }, 915 } 916 917 out := bytes.NewBuffer(nil) 918 json.NewEncoder(out).Encode(payload) 919 920 return out 921 } 922 923 func samplePayloadWithBadTypes(m map[string]interface{}) io.Reader { 924 payload := &OnePayload{ 925 Data: &Node{ 926 ID: "2", 927 Type: "badtypes", 928 Attributes: m, 929 }, 930 } 931 932 out := bytes.NewBuffer(nil) 933 json.NewEncoder(out).Encode(payload) 934 935 return out 936 } 937 938 func sampleWithPointerPayload(m map[string]interface{}) io.Reader { 939 payload := &OnePayload{ 940 Data: &Node{ 941 ID: "2", 942 Type: "with-pointers", 943 Attributes: m, 944 }, 945 } 946 947 out := bytes.NewBuffer(nil) 948 json.NewEncoder(out).Encode(payload) 949 950 return out 951 } 952 953 func testModel() *Blog { 954 return &Blog{ 955 ID: 5, 956 ClientID: "1", 957 Title: "Title 1", 958 CreatedAt: time.Now(), 959 Posts: []*Post{ 960 { 961 ID: 1, 962 Title: "Foo", 963 Body: "Bar", 964 Comments: []*Comment{ 965 { 966 ID: 1, 967 Body: "foo", 968 }, 969 { 970 ID: 2, 971 Body: "bar", 972 }, 973 }, 974 LatestComment: &Comment{ 975 ID: 1, 976 Body: "foo", 977 }, 978 }, 979 { 980 ID: 2, 981 Title: "Fuubar", 982 Body: "Bas", 983 Comments: []*Comment{ 984 { 985 ID: 1, 986 Body: "foo", 987 }, 988 { 989 ID: 3, 990 Body: "bas", 991 }, 992 }, 993 LatestComment: &Comment{ 994 ID: 1, 995 Body: "foo", 996 }, 997 }, 998 }, 999 CurrentPost: &Post{ 1000 ID: 1, 1001 Title: "Foo", 1002 Body: "Bar", 1003 Comments: []*Comment{ 1004 { 1005 ID: 1, 1006 Body: "foo", 1007 }, 1008 { 1009 ID: 2, 1010 Body: "bar", 1011 }, 1012 }, 1013 LatestComment: &Comment{ 1014 ID: 1, 1015 Body: "foo", 1016 }, 1017 }, 1018 } 1019 } 1020 1021 func samplePayloadWithSideloaded() io.Reader { 1022 testModel := testModel() 1023 1024 out := bytes.NewBuffer(nil) 1025 MarshalPayload(out, testModel) 1026 1027 return out 1028 } 1029 1030 func sampleSerializedEmbeddedTestModel() *Blog { 1031 out := bytes.NewBuffer(nil) 1032 MarshalOnePayloadEmbedded(out, testModel()) 1033 1034 blog := new(Blog) 1035 UnmarshalPayload(out, blog) 1036 1037 return blog 1038 }