Dancer2-Plugin-JsonApi/t/example.t

227 lines
6.6 KiB
Perl
Raw Normal View History

2023-10-31 20:18:51 +00:00
use 5.32.0;
use Test2::V0;
2023-11-15 18:25:43 +00:00
use Clone qw/ clone /;
2023-10-31 20:18:51 +00:00
use Dancer2::Plugin::JsonApi::Registry;
use experimental qw/ signatures /;
# example taken straight from https://www.npmjs.com/package/json-api-serializer
my $data = [
2023-11-12 17:29:35 +00:00
{ id => "1",
title => "JSON API paints my bikeshed!",
body => "The shortest article. Ever.",
created => "2015-05-22T14:56:29.000Z",
updated => "2015-05-22T14:56:28.000Z",
author => {
id => "1",
firstName => "Kaley",
lastName => "Maggio",
email => "Kaley-Maggio\@example.com",
age => "80",
gender => "male"
},
tags => [ "1", "2" ],
photos => [
"ed70cf44-9a34-4878-84e6-0c0e4a450cfe",
"24ba3666-a593-498c-9f5d-55a4ee08c72e",
"f386492d-df61-4573-b4e3-54f6f5d08acf"
],
comments => [
{ _id => "1",
body => "First !",
created => "2015-08-14T18:42:16.475Z"
},
{ _id => "2",
body => "I Like !",
created => "2015-09-14T18:42:12.475Z"
},
{ _id => "3",
body => "Awesome",
created => "2015-09-15T18:42:12.475Z"
}
]
}
2023-10-31 20:18:51 +00:00
];
my $registry = Dancer2::Plugin::JsonApi::Registry->new;
$registry->add_type(
2023-11-12 17:29:35 +00:00
'article',
{ top_level_meta => sub ( $data, $xtra ) {
return +{
2023-10-31 20:18:51 +00:00
count => $xtra->{count},
2023-11-12 17:29:35 +00:00
total => 0 + @$data,
};
2023-10-31 20:30:01 +00:00
},
2023-11-12 17:29:35 +00:00
top_level_links => { self => '/articles', },
links => {
self => sub ( $data, @ ) {
2023-10-31 20:30:01 +00:00
return "/articles/" . $data->{id};
},
2023-11-01 19:28:47 +00:00
},
relationships => {
2023-11-12 17:29:35 +00:00
'tags' => { type => 'tag' },
2023-11-01 21:39:15 +00:00
'comments' => { type => 'comment' },
2023-11-12 17:43:29 +00:00
photos => { type => 'photo' },
2023-11-01 21:39:15 +00:00
author => {
type => "people",
links => sub ( $data, @ ) {
return +{
self => "/articles/"
. $data->{id}
. "/relationships/author",
related => "/articles/" . $data->{id} . "/author"
};
}
},
2023-10-31 20:18:51 +00:00
}
}
);
2023-11-01 19:28:47 +00:00
$registry->add_type('tag');
2023-11-12 17:43:29 +00:00
$registry->add_type('photo');
2023-11-01 21:39:15 +00:00
$registry->add_type( 'comment',
{ id => '_id', allowed_attributes => ['body'] } );
$registry->add_type(
'people',
2023-11-12 17:43:29 +00:00
{ links => sub ( $data, @ ) { +{ self => '/peoples/' . $data->{id} } }
2023-11-12 17:29:35 +00:00
}
);
2023-11-01 19:28:47 +00:00
2023-11-12 17:29:35 +00:00
my $output = $registry->serialize( 'article', $data, { count => 2 } );
2023-10-31 20:18:51 +00:00
2023-11-12 17:43:29 +00:00
like $output->{data}[0]{relationships}{author},
{ links => {
"self" => "/articles/1/relationships/author",
"related" => "/articles/1/author"
}
};
2023-11-12 17:29:35 +00:00
like $output->{data}[0]{relationships}{author},
{ links => {
2023-11-01 21:39:15 +00:00
"self" => "/articles/1/relationships/author",
"related" => "/articles/1/author"
}
2023-11-12 17:29:35 +00:00
};
2023-11-01 21:39:15 +00:00
2023-10-31 20:18:51 +00:00
like $output => {
2023-11-12 17:29:35 +00:00
"jsonapi" => { "version" => "1.0" },
"meta" => {
"count" => 2,
"total" => 1
2023-11-01 19:28:47 +00:00
},
2023-11-12 17:29:35 +00:00
"links" => { "self" => "/articles" },
"data" => [
{ "type" => "article",
"id" => "1",
"attributes" => {
"title" => "JSON API paints my bikeshed!",
"body" => "The shortest article. Ever.",
"created" => "2015-05-22T14:56:29.000Z"
},
"relationships" => {
2023-11-12 17:43:29 +00:00
"author" => {
"data" => {
"type" => "people",
"id" => "1"
},
"links" => {
"self" => "/articles/1/relationships/author",
"related" => "/articles/1/author"
}
},
2023-11-12 17:29:35 +00:00
"tags" => {
"data" => [
{ "type" => "tag",
"id" => "1"
},
{ "type" => "tag",
"id" => "2"
}
]
},
2023-11-12 17:43:29 +00:00
"photos" => {
"data" => [
{ "type" => "photo",
"id" => "ed70cf44-9a34-4878-84e6-0c0e4a450cfe"
},
{ "type" => "photo",
"id" => "24ba3666-a593-498c-9f5d-55a4ee08c72e"
},
{ "type" => "photo",
"id" => "f386492d-df61-4573-b4e3-54f6f5d08acf"
}
]
},
"comments" => {
"data" => [
{ "type" => "comment",
"id" => "1"
},
{ "type" => "comment",
"id" => "2"
},
{ "type" => "comment",
"id" => "3"
}
]
}
},
"links" => { "self" => "/articles/1" }
2023-11-12 17:29:35 +00:00
}
],
2023-10-31 20:18:51 +00:00
};
2023-11-12 17:43:29 +00:00
is $output->{included}, bag {
item($_)
for (
{ "type" => "people",
"id" => "1",
"attributes" => {
"firstName" => "Kaley",
"lastName" => "Maggio",
"email" => "Kaley-Maggio\@example.com",
"age" => "80",
"gender" => "male"
},
"links" => { "self" => "/peoples/1" },
},
{ "type" => "comment",
"id" => "1",
"attributes" => { "body" => "First !" }
},
{ "type" => "comment",
"id" => "2",
"attributes" => { "body" => "I Like !" }
},
{ "type" => "comment",
"id" => "3",
"attributes" => { "body" => "Awesome" }
}
);
};
subtest 'comments only have the body attribute' => sub {
for
my $comment ( grep { $_->{type} eq 'comment' } $output->{included}->@* )
{
my @attr = keys $comment->{attributes}->%*;
is( \@attr => ['body'], "only the body for comments" );
}
};
2023-11-15 18:25:43 +00:00
subtest 'deserialize' => sub {
my $roundtrip = $registry->deserialize($output);
my $expected = clone($data);
delete $_->{created} for $expected->[0]{comments}->@*;
like $roundtrip => $expected;
};
2023-11-01 21:39:15 +00:00
done_testing;