| 1 | use strict; |
|---|
| 2 | use warnings; |
|---|
| 3 | use Data::Dumper; $Data::Dumper::Indent = 1; |
|---|
| 4 | use Test::More tests => 93; |
|---|
| 5 | |
|---|
| 6 | use Atompub::Client; |
|---|
| 7 | use Atompub::DateTime qw( datetime ); |
|---|
| 8 | use Atompub::MediaType qw( media_type ); |
|---|
| 9 | use File::Slurp; |
|---|
| 10 | use FindBin; |
|---|
| 11 | use HTTP::Status; |
|---|
| 12 | use XML::Atom::Entry; |
|---|
| 13 | |
|---|
| 14 | #system "sqlite3 $FindBin::Bin/../test.db < $FindBin::Bin/../init.sql" || die; |
|---|
| 15 | |
|---|
| 16 | |
|---|
| 17 | my $client = Atompub::Client->new; |
|---|
| 18 | |
|---|
| 19 | $client->username('foo'); |
|---|
| 20 | $client->password('foo'); |
|---|
| 21 | |
|---|
| 22 | |
|---|
| 23 | # Service |
|---|
| 24 | |
|---|
| 25 | my $serv = $client->getService('http://localhost:3000/service'); |
|---|
| 26 | isa_ok $serv, 'XML::Atom::Service'; |
|---|
| 27 | |
|---|
| 28 | my @work = $serv->workspaces; |
|---|
| 29 | is @work, 1; |
|---|
| 30 | |
|---|
| 31 | is $work[0]->title, 'My Blog'; |
|---|
| 32 | |
|---|
| 33 | my @coll = $work[0]->collections; |
|---|
| 34 | is @coll, 2; |
|---|
| 35 | |
|---|
| 36 | is $coll[0]->title, 'Diary'; |
|---|
| 37 | is $coll[0]->href, 'http://localhost:3000/entrycollection'; |
|---|
| 38 | |
|---|
| 39 | is $coll[1]->title, 'Photo'; |
|---|
| 40 | is $coll[1]->href, 'http://localhost:3000/mediacollection'; |
|---|
| 41 | |
|---|
| 42 | |
|---|
| 43 | # Create Entry Resource |
|---|
| 44 | |
|---|
| 45 | my $entry = XML::Atom::Entry->new; |
|---|
| 46 | $entry->title('Entry 1'); |
|---|
| 47 | $entry->content('This is the 1st entry'); |
|---|
| 48 | |
|---|
| 49 | my $category = XML::Atom::Category->new; |
|---|
| 50 | $category->term('animal'); |
|---|
| 51 | $category->scheme('http://example.com/dogs/big3'); |
|---|
| 52 | $entry->add_category($category); |
|---|
| 53 | |
|---|
| 54 | ok ! $client->createEntry( $coll[0]->href, $entry, 'Entry 1' ); |
|---|
| 55 | like $client->errstr, qr{Forbidden category}i; |
|---|
| 56 | |
|---|
| 57 | $category->scheme('http://example.com/cats/big3'); |
|---|
| 58 | |
|---|
| 59 | ok my $uri = $client->createEntry( $coll[0]->href, $entry, 'Entry 1' ); |
|---|
| 60 | is $uri, 'http://localhost:3000/entrycollection/entry_1.atom'; |
|---|
| 61 | |
|---|
| 62 | is $client->res->code, RC_CREATED; |
|---|
| 63 | is $client->res->location, 'http://localhost:3000/entrycollection/entry_1.atom'; |
|---|
| 64 | ok $client->res->etag; |
|---|
| 65 | #ok $client->res->last_modified; |
|---|
| 66 | ok media_type( $client->res->content_type )->is_a('entry'); |
|---|
| 67 | |
|---|
| 68 | $entry = $client->rc; |
|---|
| 69 | is $entry->title, 'Entry 1'; |
|---|
| 70 | is $entry->id, 'http://localhost:3000/entrycollection/entry_1.atom'; |
|---|
| 71 | is $entry->link->href, 'http://localhost:3000/entrycollection/entry_1.atom'; |
|---|
| 72 | ok $entry->edited; |
|---|
| 73 | ok $entry->updated; |
|---|
| 74 | is $entry->category->term, 'animal'; |
|---|
| 75 | like $entry->content->body, qr{This is the 1st entry}; |
|---|
| 76 | |
|---|
| 77 | ok $client->createEntry( $coll[0]->href, $entry, 'Entry 1' ); # same slug |
|---|
| 78 | |
|---|
| 79 | |
|---|
| 80 | # List Entry Resources |
|---|
| 81 | |
|---|
| 82 | ok my $feed = $client->getFeed( $coll[0]->href ); |
|---|
| 83 | |
|---|
| 84 | is $client->res->code, RC_OK; |
|---|
| 85 | ok media_type( $client->res->content_type )->is_a('feed'); |
|---|
| 86 | |
|---|
| 87 | is $feed->title, 'Diary'; |
|---|
| 88 | ok $feed->updated; |
|---|
| 89 | is $feed->id, 'http://localhost:3000/entrycollection'; |
|---|
| 90 | |
|---|
| 91 | is $feed->self_link, 'http://localhost:3000/entrycollection'; |
|---|
| 92 | is $feed->first_link, 'http://localhost:3000/entrycollection'; |
|---|
| 93 | is $feed->next_link, undef; |
|---|
| 94 | |
|---|
| 95 | my @entries = $feed->entries; |
|---|
| 96 | is @entries, 2; |
|---|
| 97 | is $entries[0]->title, 'Entry 1'; |
|---|
| 98 | |
|---|
| 99 | |
|---|
| 100 | # Read Entry Resource |
|---|
| 101 | |
|---|
| 102 | ok $entry = $client->getEntry( $uri ); |
|---|
| 103 | |
|---|
| 104 | is $client->res->code, RC_NOT_MODIFIED; |
|---|
| 105 | |
|---|
| 106 | |
|---|
| 107 | # Update Entry Resource |
|---|
| 108 | |
|---|
| 109 | $entry->title('Entry 1, ver.2'); |
|---|
| 110 | |
|---|
| 111 | ok $client->updateEntry( $uri, $entry ); |
|---|
| 112 | |
|---|
| 113 | is $client->res->code, RC_OK; |
|---|
| 114 | ok $client->res->etag; |
|---|
| 115 | #ok $client->res->last_modified; |
|---|
| 116 | ok media_type( $client->res->content_type )->is_a('entry'); |
|---|
| 117 | |
|---|
| 118 | $entry = $client->rc; |
|---|
| 119 | is $entry->title, 'Entry 1, ver.2'; |
|---|
| 120 | |
|---|
| 121 | |
|---|
| 122 | # Delete Entry Resource |
|---|
| 123 | |
|---|
| 124 | ok $client->deleteEntry( $uri ); |
|---|
| 125 | |
|---|
| 126 | ok $feed = $client->getFeed( $coll[0]->href ); |
|---|
| 127 | is $feed->entries, 1; |
|---|
| 128 | |
|---|
| 129 | |
|---|
| 130 | # Create Media Resource |
|---|
| 131 | |
|---|
| 132 | ok ! $client->createMedia( $coll[1]->href, 't/samples/media1.gif', 'text/plain', 'Media 1' ); |
|---|
| 133 | like $client->errstr, qr{unsupported media type}i; |
|---|
| 134 | |
|---|
| 135 | ok $uri = $client->createMedia( $coll[1]->href, 't/samples/media1.gif', 'image/gif', 'Media 1' ); |
|---|
| 136 | is $uri, 'http://localhost:3000/mediacollection/media_1.atom'; |
|---|
| 137 | |
|---|
| 138 | is $client->res->code, RC_CREATED; |
|---|
| 139 | is $client->res->location, 'http://localhost:3000/mediacollection/media_1.atom'; |
|---|
| 140 | ok $client->res->etag; |
|---|
| 141 | #ok $client->res->last_modified; |
|---|
| 142 | ok media_type( $client->res->content_type )->is_a('entry'); |
|---|
| 143 | |
|---|
| 144 | $entry = $client->rc; |
|---|
| 145 | is $entry->title, 'Media 1'; |
|---|
| 146 | ok $entry->edited; |
|---|
| 147 | ok $entry->updated; |
|---|
| 148 | is $entry->id, 'http://localhost:3000/mediacollection/media_1.atom'; |
|---|
| 149 | |
|---|
| 150 | is $entry->edit_link, 'http://localhost:3000/mediacollection/media_1.atom'; |
|---|
| 151 | is my $media_uri = $entry->edit_media_link, 'http://localhost:3000/mediacollection/media_1.gif'; |
|---|
| 152 | |
|---|
| 153 | is $entry->content->src, 'http://localhost:3000/mediacollection/media_1.gif'; |
|---|
| 154 | |
|---|
| 155 | ok $client->createMedia( $coll[1]->href, 't/samples/media1.gif', 'image/gif', |
|---|
| 156 | 'Media 1' ); # same slug |
|---|
| 157 | |
|---|
| 158 | |
|---|
| 159 | # List Media Link Entries |
|---|
| 160 | |
|---|
| 161 | ok $feed = $client->getFeed( $coll[1]->href ); |
|---|
| 162 | |
|---|
| 163 | is $client->res->code, RC_OK; |
|---|
| 164 | ok media_type( $client->res->content_type )->is_a('feed'); |
|---|
| 165 | |
|---|
| 166 | is $feed->title, 'Photo'; |
|---|
| 167 | ok $feed->updated; |
|---|
| 168 | is $feed->id, 'http://localhost:3000/mediacollection'; |
|---|
| 169 | |
|---|
| 170 | is $feed->self_link, 'http://localhost:3000/mediacollection'; |
|---|
| 171 | is $feed->first_link, 'http://localhost:3000/mediacollection'; |
|---|
| 172 | is $feed->next_link, undef; |
|---|
| 173 | |
|---|
| 174 | @entries = $feed->entries; |
|---|
| 175 | is @entries, 2; |
|---|
| 176 | is $entries[0]->title, 'Media 1'; |
|---|
| 177 | |
|---|
| 178 | |
|---|
| 179 | # Read Media Link Entry |
|---|
| 180 | |
|---|
| 181 | ok $entry = $client->getEntry( $uri ); |
|---|
| 182 | |
|---|
| 183 | is $client->res->code, RC_NOT_MODIFIED; |
|---|
| 184 | |
|---|
| 185 | |
|---|
| 186 | # Update Media Link Entry |
|---|
| 187 | |
|---|
| 188 | $entry->title('Media 1, ver.2'); |
|---|
| 189 | |
|---|
| 190 | ok $client->updateEntry( $uri, $entry ); |
|---|
| 191 | |
|---|
| 192 | is $client->res->code, RC_OK; |
|---|
| 193 | ok $client->res->etag; |
|---|
| 194 | #ok $client->res->last_modified; |
|---|
| 195 | ok media_type( $client->res->content_type )->is_a('entry'); |
|---|
| 196 | |
|---|
| 197 | $entry = $client->rc; |
|---|
| 198 | is $entry->title, 'Media 1, ver.2'; |
|---|
| 199 | |
|---|
| 200 | |
|---|
| 201 | # Read Media Resource |
|---|
| 202 | |
|---|
| 203 | ok my $media = $client->getMedia( $media_uri ); |
|---|
| 204 | |
|---|
| 205 | is $client->res->code, RC_OK; |
|---|
| 206 | ok $client->res->etag; |
|---|
| 207 | #ok $client->res->last_modified; |
|---|
| 208 | |
|---|
| 209 | is $media, read_file( 't/samples/media1.gif', binmode => ':raw' ); |
|---|
| 210 | |
|---|
| 211 | ok $client->getMedia( $media_uri ); |
|---|
| 212 | is $client->res->code, RC_NOT_MODIFIED; |
|---|
| 213 | |
|---|
| 214 | |
|---|
| 215 | # Update Media Resource |
|---|
| 216 | |
|---|
| 217 | # XXX Entry can not have app:edited, you SHOULD get it from Feed generally |
|---|
| 218 | my $prev_edited = $entry->edited; |
|---|
| 219 | sleep 1; |
|---|
| 220 | |
|---|
| 221 | ok $client->updateMedia( $media_uri, 't/samples/media2.png', 'image/png' ); |
|---|
| 222 | |
|---|
| 223 | is $client->res->code, RC_OK; |
|---|
| 224 | ok $client->res->etag; |
|---|
| 225 | #ok $client->res->last_modified; |
|---|
| 226 | |
|---|
| 227 | is $client->rc, read_file( 't/samples/media2.png', binmode => ':raw' ); |
|---|
| 228 | |
|---|
| 229 | # XXX Entry can not have app:edited, you SHOULD get it from Feed generally |
|---|
| 230 | ok datetime( $client->getEntry( $uri )->edited ) > datetime( $prev_edited ); |
|---|
| 231 | |
|---|
| 232 | |
|---|
| 233 | # Delete Entry Resource |
|---|
| 234 | |
|---|
| 235 | ok $client->deleteMedia( $media_uri ); |
|---|
| 236 | |
|---|
| 237 | ok $feed = $client->getFeed( $coll[1]->href ); |
|---|
| 238 | is $feed->entries, 1; |
|---|