@@ -312,6 +312,97 @@ def test_post_single
312312 assert_jsonapi_response 201
313313 end
314314
315+ def test_post_polymorphic_with_has_many_relationship
316+ post '/people' , params :
317+ {
318+ 'data' => {
319+ 'type' => 'people' ,
320+ 'attributes' => {
321+ 'name' => 'Reo' ,
322+ 'email' => 'reo@xyz.fake' ,
323+ 'date_joined' => 'Thu, 01 Jan 2019 00:00:00 UTC +00:00' ,
324+ } ,
325+ 'relationships' => {
326+ 'vehicles' => {
327+ 'data' => [
328+ { 'type' => 'car' , 'id' => '1' } ,
329+ { 'type' => 'boat' , 'id' => '2' } ,
330+ { 'type' => 'car' , 'id' => '3' } ,
331+ { 'type' => 'car' , 'id' => '4' }
332+ ]
333+ }
334+ }
335+ }
336+ } . to_json ,
337+ headers : {
338+ 'CONTENT_TYPE' => JSONAPI ::MEDIA_TYPE ,
339+ 'Accept' => JSONAPI ::MEDIA_TYPE
340+ }
341+
342+ assert_jsonapi_response 201
343+
344+ body = JSON . parse ( response . body )
345+ person = Person . find ( body . dig ( "data" , "id" ) )
346+
347+ assert_equal "Reo" , person . name
348+ assert_equal 4 , person . vehicles . count
349+ assert_equal Car , person . vehicles . first . class
350+ assert_equal Boat , person . vehicles . second . class
351+ assert_equal Car , person . vehicles . third . class
352+ assert_equal Car , person . vehicles . fourth . class
353+ end
354+
355+ def test_post_polymorphic_invalid_with_wrong_type
356+ post '/people' , params :
357+ {
358+ 'data' => {
359+ 'type' => 'people' ,
360+ 'attributes' => {
361+ 'name' => 'Reo' ,
362+ 'email' => 'reo@xyz.fake' ,
363+ 'date_joined' => 'Thu, 01 Jan 2019 00:00:00 UTC +00:00' ,
364+ } ,
365+ 'relationships' => {
366+ 'vehicles' => { 'data' => [ { 'type' => 'author' , 'id' => '1' } ] } ,
367+ }
368+ }
369+ } . to_json ,
370+ headers : {
371+ 'CONTENT_TYPE' => JSONAPI ::MEDIA_TYPE ,
372+ 'Accept' => JSONAPI ::MEDIA_TYPE
373+ }
374+
375+ assert_jsonapi_response 400 , msg : "Submitting a thing as a vehicle should raise a type mismatch error"
376+ end
377+
378+ def test_post_polymorphic_invalid_with_not_matched_type_and_id
379+ post '/people' , params :
380+ {
381+ 'data' => {
382+ 'type' => 'people' ,
383+ 'attributes' => {
384+ 'name' => 'Reo' ,
385+ 'email' => 'reo@xyz.fake' ,
386+ 'date_joined' => 'Thu, 01 Jan 2019 00:00:00 UTC +00:00' ,
387+ } ,
388+ 'relationships' => {
389+ 'vehicles' => {
390+ 'data' => [
391+ { 'type' => 'car' , 'id' => '1' } ,
392+ { 'type' => 'car' , 'id' => '2' } #vehicle 2 is actually a boat
393+ ]
394+ }
395+ }
396+ }
397+ } . to_json ,
398+ headers : {
399+ 'CONTENT_TYPE' => JSONAPI ::MEDIA_TYPE ,
400+ 'Accept' => JSONAPI ::MEDIA_TYPE
401+ }
402+
403+ assert_jsonapi_response 404 , msg : "Submitting a thing as a vehicle should raise a record not found"
404+ end
405+
315406 def test_post_single_missing_data_contents
316407 post '/posts' , params :
317408 {
@@ -523,6 +614,96 @@ def test_patch_content_type
523614 assert_match JSONAPI ::MEDIA_TYPE , headers [ 'Content-Type' ]
524615 end
525616
617+ def test_patch_polymorphic_with_has_many_relationship
618+ patch '/people/1000' , params :
619+ {
620+ 'data' => {
621+ 'id' => 1000 ,
622+ 'type' => 'people' ,
623+ 'attributes' => {
624+ 'name' => 'Reo' ,
625+ 'email' => 'reo@xyz.fake' ,
626+ 'date_joined' => 'Thu, 01 Jan 2019 00:00:00 UTC +00:00' ,
627+ } ,
628+ 'relationships' => {
629+ 'vehicles' => {
630+ 'data' => [
631+ { 'type' => 'car' , 'id' => '1' } ,
632+ { 'type' => 'boat' , 'id' => '2' }
633+ ]
634+ }
635+ }
636+ }
637+ } . to_json ,
638+ headers : {
639+ 'CONTENT_TYPE' => JSONAPI ::MEDIA_TYPE ,
640+ 'Accept' => JSONAPI ::MEDIA_TYPE
641+ }
642+
643+ assert_jsonapi_response 200
644+
645+ body = JSON . parse ( response . body )
646+ person = Person . find ( body . dig ( "data" , "id" ) )
647+
648+ assert_equal "Reo" , person . name
649+ assert_equal 2 , person . vehicles . count
650+ assert_equal Car , person . vehicles . first . class
651+ assert_equal Boat , person . vehicles . second . class
652+ end
653+
654+ def test_patch_polymorphic_invalid_with_wrong_type
655+ patch '/people/1000' , params :
656+ {
657+ 'data' => {
658+ 'id' => 1000 ,
659+ 'type' => 'people' ,
660+ 'attributes' => {
661+ 'name' => 'Reo' ,
662+ 'email' => 'reo@xyz.fake' ,
663+ 'date_joined' => 'Thu, 01 Jan 2019 00:00:00 UTC +00:00' ,
664+ } ,
665+ 'relationships' => {
666+ 'vehicles' => { 'data' => [ { 'type' => 'author' , 'id' => '1' } ] } ,
667+ }
668+ }
669+ } . to_json ,
670+ headers : {
671+ 'CONTENT_TYPE' => JSONAPI ::MEDIA_TYPE ,
672+ 'Accept' => JSONAPI ::MEDIA_TYPE
673+ }
674+
675+ assert_jsonapi_response 400 , msg : "Submitting a thing as a vehicle should raise a type mismatch error"
676+ end
677+
678+ def test_patch_polymorphic_invalid_with_not_matched_type_and_id
679+ patch '/people/1000' , params :
680+ {
681+ 'data' => {
682+ 'id' => 1000 ,
683+ 'type' => 'people' ,
684+ 'attributes' => {
685+ 'name' => 'Reo' ,
686+ 'email' => 'reo@xyz.fake' ,
687+ 'date_joined' => 'Thu, 01 Jan 2019 00:00:00 UTC +00:00' ,
688+ } ,
689+ 'relationships' => {
690+ 'vehicles' => {
691+ 'data' => [
692+ { 'type' => 'car' , 'id' => '1' } ,
693+ { 'type' => 'car' , 'id' => '2' } #vehicle 2 is actually a boat
694+ ]
695+ }
696+ }
697+ }
698+ } . to_json ,
699+ headers : {
700+ 'CONTENT_TYPE' => JSONAPI ::MEDIA_TYPE ,
701+ 'Accept' => JSONAPI ::MEDIA_TYPE
702+ }
703+
704+ assert_jsonapi_response 404 , msg : "Submitting a thing as a vehicle should raise a record not found"
705+ end
706+
526707 def test_post_correct_content_type
527708 post '/posts' , params :
528709 {
@@ -1278,8 +1459,8 @@ def test_include_parameter_openquoted
12781459
12791460 def test_getting_different_resources_when_sti
12801461 assert_cacheable_jsonapi_get '/vehicles'
1281- types = json_response [ 'data' ] . map { |r | r [ 'type' ] } . sort
1282- assert_array_equals [ 'boats ', 'cars' ] , types
1462+ types = json_response [ 'data' ] . map { |r | r [ 'type' ] } . to_set
1463+ assert types == Set [ 'cars ', 'boats' ]
12831464 end
12841465
12851466 def test_getting_resource_with_correct_type_when_sti
0 commit comments