a8777591203134e9269e036364e7390fc5d632bf
[catagits/Catalyst-Controller-DBIC-API.git] / t / rpc / update.t
1 use strict;
2 use warnings;
3
4 use lib 't/lib';
5
6 my $base = 'http://localhost';
7 my $content_type = [ 'Content-Type', 'application/x-www-form-urlencoded' ];
8
9 use RestTest;
10 use DBICTest;
11 use Test::More;
12 use Test::WWW::Mechanize::Catalyst 'RestTest';
13 use HTTP::Request::Common;
14 use JSON;
15
16 my $json = JSON->new->utf8;
17
18 my $mech = Test::WWW::Mechanize::Catalyst->new;
19 ok( my $schema = DBICTest->init_schema(), 'got schema' );
20
21 my $track         = $schema->resultset('Track')->first;
22 my %original_cols = $track->get_columns;
23
24 my $track_update_url = "$base/api/rpc/track/id/" . $track->id . "/update";
25 my $any_track_update_url =
26     "$base/api/rpc/any/track/id/" . $track->id . "/update";
27 my $tracks_update_url = "$base/api/rpc/track/update";
28
29 my $artist_update_url = "$base/api/rpc/artist/id/1/update";
30
31 # test invalid track id caught
32 {
33     diag 'DBIx::Class warns about a non-numeric id which is ok because we test for that too';
34     foreach my $wrong_id ( 'sdsdsdsd', 3434234 ) {
35         my $incorrect_url = "$base/api/rpc/track/id/" . $wrong_id . "/update";
36         my $req = POST( $incorrect_url, { title => 'value' } );
37
38         $mech->request( $req, $content_type );
39         cmp_ok( $mech->status, '==', 400,
40             'Attempt with invalid track id caught' );
41
42         my $response = $json->decode( $mech->content );
43         like(
44             $response->{messages}->[0],
45             qr/No object found for id/,
46             'correct message returned'
47         );
48
49         $track->discard_changes;
50         is_deeply(
51             { $track->get_columns },
52             \%original_cols,
53             'no update occurred'
54         );
55     }
56 }
57
58 # validation when no params sent
59 {
60     my $req = POST( $track_update_url, { wrong_param => 'value' } );
61     $mech->request( $req, $content_type );
62     cmp_ok( $mech->status, '==', 400, 'Update with no keys causes error' );
63
64     my $response = $json->decode( $mech->content );
65     is_deeply( $response->{messages}, ['No valid keys passed'],
66         'correct message returned' );
67
68     $track->discard_changes;
69     is_deeply(
70         { $track->get_columns },
71         \%original_cols,
72         'no update occurred'
73     );
74 }
75
76 {
77     my $req = POST( $track_update_url, { wrong_param => 'value' } );
78     $mech->request( $req, $content_type );
79     cmp_ok( $mech->status, '==', 400, 'Update with no keys causes error' );
80
81     my $response = $json->decode( $mech->content );
82     is_deeply( $response->{messages}, ['No valid keys passed'],
83         'correct message returned' );
84
85     $track->discard_changes;
86     is_deeply(
87         { $track->get_columns },
88         \%original_cols,
89         'no update occurred'
90     );
91 }
92
93 {
94     my $req = POST( $track_update_url, { title => undef } );
95     $mech->request( $req, $content_type );
96     cmp_ok( $mech->status, '==', 200, 'Update with key with no value okay' );
97
98     $track->discard_changes;
99     isnt( $track->title, $original_cols{title}, 'Title changed' );
100     is( $track->title, '', 'Title changed to undef' );
101 }
102
103 {
104     my $req = POST( $track_update_url, { title => 'monkey monkey' } );
105     $mech->request( $req, $content_type );
106     cmp_ok( $mech->status, '==', 200, 'Update with key with value okay' );
107
108     $track->discard_changes;
109     is( $track->title, 'monkey monkey', 'Title changed to "monkey monkey"' );
110 }
111
112 {
113     my $req = POST(
114         $track_update_url,
115         {   title     => 'sheep sheep',
116             'cd.year' => '2009'
117         }
118     );
119     $mech->request( $req, $content_type );
120     cmp_ok( $mech->status, '==', 200,
121         'Update with key with value and related key okay' );
122
123     $track->discard_changes;
124     is( $track->title,    'sheep sheep', 'Title changed' );
125     is( $track->cd->year, '2009',        'Related field changed"' );
126 }
127
128 {
129     my $test_data = $json->encode(
130         { name => 'Caterwauler B. McCrae',
131           cds => [
132             {
133                 cdid => 1,
134                 title => 'All the bees are gone',
135                 year => 3030,
136             },
137             {
138                 cdid => 2,
139                 title => 'All the crops are gone',
140                 year => 3031
141             }
142           ]
143         }
144     );
145
146     my $req = POST( $artist_update_url, Content => $test_data );
147     $req->content_type('text/x-json');
148     $mech->request($req);
149
150     cmp_ok( $mech->status, '==', 200, 'Multi-row update returned 200 OK' );
151
152     my $artist = $schema->resultset('Artist')->search({ artistid => 1 });
153     ok ($artist->next->name eq "Caterwauler B. McCrae", "mutliple related row parent record update");
154
155     # make sure the old cds don't exist, it's possible we just inserted the new rows instead of updating them
156     my $old_cds = $artist->search_related('cds', { title => ['Spoonful of bees', 'Forkful of bees'] } )->count;
157     ok ($old_cds == 0, 'update performed update and not create on related rows');
158
159     my @cds = $artist->search_related('cds', { year => ['3030', '3031'] }, { order_by => 'year' })->all;
160     ok (@cds == 2, 'update modified proper number of related rows');
161     ok ($cds[0]->title eq 'All the bees are gone', 'update modified column on related row');
162     ok ($cds[1]->title eq 'All the crops are gone', 'update modified column on second related row');
163 }
164
165 # update related rows using only unique_constraint on CD vs. primary key
166 # update the year on constraint match
167 {
168     my $test_data = $json->encode(
169         { name => 'Caterwauler McCrae',
170           cds => [
171             {
172                 artist => 1,
173                 title => 'All the bees are gone',
174                 year => 3032,
175             },
176             {
177                 artist => 1,
178                 title => 'All the crops are gone',
179                 year => 3032
180             }
181           ]
182         }
183     );
184
185     my $req = POST( $artist_update_url, Content => $test_data );
186     $req->content_type('text/x-json');
187     $mech->request($req);
188
189     cmp_ok( $mech->status, '==', 200, 'Multi-row unique constraint update returned 200 OK' );
190
191     my $artist = $schema->resultset('Artist')->search({ artistid => 1 });
192     ok ($artist->next->name eq "Caterwauler McCrae", "multi-row unique constraint related row parent record updated");
193
194     my $old_cds = $artist->search_related('cds', { year => ['3030', '3031'] }, { order_by => 'year' })->count;
195     ok ( $old_cds == 0, 'multi-row update with unique constraint updated year' );
196
197     my $cds = $artist->search_related('cds', { 'year' => 3032 } )->count;
198     ok ( $cds == 2, 'multi-row update with unique constraint okay' );
199 }
200
201 {
202     my $req = POST( $any_track_update_url, { title => 'baa' } );
203     $mech->request( $req, $content_type );
204     cmp_ok( $mech->status, '==', 200, 'Stash update okay' );
205
206     $track->discard_changes;
207     is( $track->title, 'baa', 'Title changed' );
208 }
209
210 {
211     my $req = POST( $any_track_update_url, { position => '14' } );
212     $mech->request( $req, $content_type );
213     cmp_ok( $mech->status, '==', 200, 'Position update okay' );
214
215     $track->discard_changes;
216     is( $track->get_column('position'), '14', 'Position changed' );
217 }
218
219
220 # bulk_update existing objects
221 {
222
223     # order to get a stable order of rows
224     my $tracks_rs =
225         $schema->resultset('Track')
226         ->search( undef, { order_by => 'trackid', rows => 3 } );
227     my $test_data = $json->encode(
228         {   list => [
229                 map +{ id => $_->id, title => 'Track ' . $_->id },
230                 $tracks_rs->all
231             ]
232         }
233     );
234     my $req = POST( $tracks_update_url, Content => $test_data );
235     $req->content_type('text/x-json');
236     $mech->request($req);
237     cmp_ok( $mech->status, '==', 200, 'Attempt to update three tracks ok' );
238
239     $tracks_rs->reset;
240     while ( my $track = $tracks_rs->next ) {
241         is( $track->title, 'Track ' . $track->id, 'Title changed' );
242     }
243 }
244
245 # bulk_update nonexisting objects
246 {
247
248     # order to get a stable order of rows
249     my $test_data = $json->encode(
250         {   list => [
251                 map +{ id => $_, title => 'Track ' . $_ },
252                 ( 1000 .. 1002 )
253             ]
254         }
255     );
256     my $req = POST( $tracks_update_url, Content => $test_data );
257     $req->content_type('text/x-json');
258     $mech->request($req);
259     cmp_ok( $mech->status, '==', 400,
260         'Attempt to update three nonexisting tracks fails' );
261     my $response = $json->decode( $mech->content );
262     is( $response->{success}, 'false',
263         'success property returns quoted false' );
264     like(
265         $response->{messages}->[0],
266         qr/No object found for id/,
267         'correct message returned'
268     );
269 }
270
271 done_testing();