Bug 25570: (follow-up) Fix tests
[koha.git] / t / db_dependent / api / v1 / libraries.t
1 #!/usr/bin/env perl
2
3 # This file is part of Koha.
4 #
5 # Koha is free software; you can redistribute it and/or modify it under the
6 # terms of the GNU General Public License as published by the Free Software
7 # Foundation; either version 3 of the License, or (at your option) any later
8 # version.
9 #
10 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
11 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
12 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License along
15 # with Koha; if not, write to the Free Software Foundation, Inc.,
16 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
18 use Modern::Perl;
19
20 use Test::More tests => 5;
21 use Test::Mojo;
22 use Test::Warn;
23
24 use t::lib::TestBuilder;
25 use t::lib::Mocks;
26
27 use List::Util qw(min);
28
29 use Koha::Libraries;
30 use Koha::Database;
31
32 my $schema  = Koha::Database->new->schema;
33 my $builder = t::lib::TestBuilder->new;
34
35 t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
36
37 my $t = Test::Mojo->new('Koha::REST::V1');
38
39 subtest 'list() tests' => sub {
40     plan tests => 7;
41
42     $schema->storage->txn_begin;
43
44     my $patron = $builder->build_object({
45         class => 'Koha::Patrons',
46         value => { flags => 4 }
47     });
48     my $password = 'thePassword123';
49     $patron->set_password({ password => $password, skip_validation => 1 });
50     my $userid = $patron->userid;
51
52     # Create test context
53     my $library = $builder->build_object({ class => 'Koha::Libraries' });
54     my $another_library = $library->unblessed; # create a copy of $library but make
55     delete $another_library->{branchcode};     # sure branchcode will be regenerated
56     $another_library = $builder->build_object({ class => 'Koha::Libraries', value => $another_library });
57
58     ## Authorized user tests
59     # Make sure we are returned with the correct amount of libraries
60     $t->get_ok( "//$userid:$password@/api/v1/libraries" )
61       ->status_is( 200, 'SWAGGER3.2.2' );
62
63     my $response_count = scalar @{ $t->tx->res->json };
64     my $expected_count = min( Koha::Libraries->count, C4::Context->preference('RESTdefaultPageSize') );
65     is( $response_count, $expected_count, 'Results count is paginated');
66
67     subtest 'query parameters' => sub {
68
69         my $fields = {
70             name              => 'branchname',
71             address1          => 'branchaddress1',
72             address2          => 'branchaddress2',
73             address3          => 'branchaddress3',
74             postal_code       => 'branchzip',
75             city              => 'branchcity',
76             state             => 'branchstate',
77             country           => 'branchcountry',
78             phone             => 'branchphone',
79             fax               => 'branchfax',
80             email             => 'branchemail',
81             reply_to_email    => 'branchreplyto',
82             return_path_email => 'branchreturnpath',
83             url               => 'branchurl',
84             ip                => 'branchip',
85             notes             => 'branchnotes',
86             opac_info         => 'opac_info',
87         };
88
89         my $size = keys %{$fields};
90
91         plan tests => $size * (2 + 2 * $size);
92
93         foreach my $field ( keys %{$fields} ) {
94             my $model_field = $fields->{ $field };
95             my $result = $t->get_ok("//$userid:$password@/api/v1/libraries?$field=" . $library->$model_field)
96               ->status_is(200);
97             foreach my $key ( keys %{$fields} ) {
98               my $key_field = $fields->{ $key };
99               $result->json_is( "/0/$key", $library->$key_field );
100               $result->json_is( "/1/$key", $another_library->$key_field );
101             }
102         }
103     };
104
105     # Warn on unsupported query parameter
106     $t->get_ok( "//$userid:$password@/api/v1/libraries?library_blah=blah" )
107       ->status_is(400)
108       ->json_is( [{ path => '/query/library_blah', message => 'Malformed query string'}] );
109
110     $schema->storage->txn_rollback;
111 };
112
113 subtest 'get() tests' => sub {
114
115     plan tests => 6;
116
117     $schema->storage->txn_begin;
118
119     my $library = $builder->build_object( { class => 'Koha::Libraries' } );
120     my $patron = $builder->build_object({
121         class => 'Koha::Patrons',
122         value => { flags => 4 }
123     });
124     my $password = 'thePassword123';
125     $patron->set_password({ password => $password, skip_validation => 1 });
126     my $userid = $patron->userid;
127
128     $t->get_ok( "//$userid:$password@/api/v1/libraries/" . $library->branchcode )
129       ->status_is( 200, 'SWAGGER3.2.2' )
130       ->json_is( '' => Koha::REST::V1::Library::_to_api( $library->TO_JSON ), 'SWAGGER3.3.2' );
131
132     my $non_existent_code = $library->branchcode;
133     $library->delete;
134
135     $t->get_ok( "//$userid:$password@/api/v1/libraries/" . $non_existent_code )
136       ->status_is(404)
137       ->json_is( '/error' => 'Library not found' );
138
139     $schema->storage->txn_rollback;
140 };
141
142 subtest 'add() tests' => sub {
143
144     plan tests => 17;
145
146     $schema->storage->txn_begin;
147
148     my $authorized_patron = $builder->build_object({
149         class => 'Koha::Patrons',
150         value => { flags => 1 }
151     });
152     my $password = 'thePassword123';
153     $authorized_patron->set_password({ password => $password, skip_validation => 1 });
154     my $auth_userid = $authorized_patron->userid;
155
156     my $unauthorized_patron = $builder->build_object({
157         class => 'Koha::Patrons',
158         value => { flags => 4 }
159     });
160     $unauthorized_patron->set_password({ password => $password, skip_validation => 1 });
161     my $unauth_userid = $unauthorized_patron->userid;
162
163     my $library_obj = $builder->build_object({ class => 'Koha::Libraries' });
164     my $library     = Koha::REST::V1::Library::_to_api( $library_obj->TO_JSON );
165     $library_obj->delete;
166
167     # Unauthorized attempt to write
168     $t->post_ok( "//$unauth_userid:$password@/api/v1/libraries" => json => $library )
169       ->status_is(403);
170
171     # Authorized attempt to write invalid data
172     my $library_with_invalid_field = { %$library };
173     $library_with_invalid_field->{'branchinvalid'} = 'Library invalid';
174
175     $t->post_ok( "//$auth_userid:$password@/api/v1/libraries" => json => $library_with_invalid_field )
176       ->status_is(400)
177       ->json_is(
178         "/errors" => [
179             {
180                 message => "Properties not allowed: branchinvalid.",
181                 path    => "/body"
182             }
183         ]
184     );
185
186     # Authorized attempt to write
187     $t->post_ok( "//$auth_userid:$password@/api/v1/libraries" => json => $library )
188       ->status_is( 201, 'SWAGGER3.2.1' )
189       ->json_is( '' => $library, 'SWAGGER3.3.1' )
190       ->header_is( Location => '/api/v1/libraries/' . $library->{library_id}, 'SWAGGER3.4.1' );
191
192     # save the library_id
193     my $library_id = $library->{library_id};
194     # Authorized attempt to create with null id
195     $library->{library_id} = undef;
196
197     $t->post_ok( "//$auth_userid:$password@/api/v1/libraries" => json => $library )
198       ->status_is(400)
199       ->json_has('/errors');
200
201     # Authorized attempt to create with existing id
202     $library->{library_id} = $library_id;
203
204     warning_like {
205         $t->post_ok( "//$auth_userid:$password@/api/v1/libraries" => json => $library )
206           ->status_is(409)
207           ->json_has( '/error' => "Fails when trying to add an existing library_id")
208           ->json_is(  '/conflict', 'PRIMARY' ); } # WTF
209         qr/^DBD::mysql::st execute failed: Duplicate entry '(.*)' for key 'PRIMARY'/;
210
211     $schema->storage->txn_rollback;
212 };
213
214 subtest 'update() tests' => sub {
215     plan tests => 13;
216
217     $schema->storage->txn_begin;
218
219     my $authorized_patron = $builder->build_object({
220         class => 'Koha::Patrons',
221         value => { flags => 1 }
222     });
223     my $password = 'thePassword123';
224     $authorized_patron->set_password({ password => $password, skip_validation => 1 });
225     my $auth_userid = $authorized_patron->userid;
226
227     my $unauthorized_patron = $builder->build_object({
228         class => 'Koha::Patrons',
229         value => { flags => 4 }
230     });
231     $unauthorized_patron->set_password({ password => $password, skip_validation => 1 });
232     my $unauth_userid = $unauthorized_patron->userid;
233
234     my $library    = $builder->build_object({ class => 'Koha::Libraries' });
235     my $library_id = $library->branchcode;
236
237     # Unauthorized attempt to update
238     $t->put_ok( "//$unauth_userid:$password@/api/v1/libraries/$library_id"
239                     => json => { name => 'New unauthorized name change' } )
240       ->status_is(403);
241
242     # Attempt partial update on a PUT
243     my $library_with_missing_field = {
244         address1 => "New library address",
245     };
246
247     $t->put_ok( "//$auth_userid:$password@/api/v1/libraries/$library_id" => json => $library_with_missing_field )
248       ->status_is(400)
249       ->json_has( "/errors" =>
250           [ { message => "Missing property.", path => "/body/address2" } ]
251       );
252
253     my $deleted_library = $builder->build_object( { class => 'Koha::Libraries' } );
254     my $library_with_updated_field = Koha::REST::V1::Library::_to_api( $deleted_library->TO_JSON );
255     $library_with_updated_field->{library_id} = $library_id;
256     $deleted_library->delete;
257
258     $t->put_ok( "//$auth_userid:$password@/api/v1/libraries/$library_id" => json => $library_with_updated_field )
259       ->status_is(200, 'SWAGGER3.2.1')
260       ->json_is( '' => $library_with_updated_field, 'SWAGGER3.3.3' );
261
262     # Authorized attempt to write invalid data
263     my $library_with_invalid_field = { %$library_with_updated_field };
264     $library_with_invalid_field->{'branchinvalid'} = 'Library invalid';
265
266     $t->put_ok( "//$auth_userid:$password@/api/v1/libraries/$library_id" => json => $library_with_invalid_field )
267       ->status_is(400)
268       ->json_is(
269         "/errors" => [
270             {
271                 message => "Properties not allowed: branchinvalid.",
272                 path    => "/body"
273             }
274         ]
275     );
276
277     my $non_existent_code = 'nope'.int(rand(10000));
278     $t->put_ok("//$auth_userid:$password@/api/v1/libraries/$non_existent_code" => json => $library_with_updated_field)
279       ->status_is(404);
280
281     $schema->storage->txn_rollback;
282 };
283
284 subtest 'delete() tests' => sub {
285     plan tests => 7;
286
287     $schema->storage->txn_begin;
288
289     my $authorized_patron = $builder->build_object({
290         class => 'Koha::Patrons',
291         value => { flags => 1 }
292     });
293     my $password = 'thePassword123';
294     $authorized_patron->set_password({ password => $password, skip_validation => 1 });
295     my $auth_userid = $authorized_patron->userid;
296
297     my $unauthorized_patron = $builder->build_object({
298         class => 'Koha::Patrons',
299         value => { flags => 4 }
300     });
301     $unauthorized_patron->set_password({ password => $password, skip_validation => 1 });
302     my $unauth_userid = $unauthorized_patron->userid;
303
304     my $library_id = $builder->build( { source => 'Branch' } )->{branchcode};
305
306     # Unauthorized attempt to delete
307     $t->delete_ok( "//$unauth_userid:$password@/api/v1/libraries/$library_id" )
308       ->status_is(403);
309
310     $t->delete_ok( "//$auth_userid:$password@/api/v1/libraries/$library_id" )
311       ->status_is(204, 'SWAGGER3.2.4')
312       ->content_is('', 'SWAGGER3.3.4');
313
314     $t->delete_ok( "//$auth_userid:$password@/api/v1/libraries/$library_id" )
315       ->status_is(404);
316
317     $schema->storage->txn_rollback;
318 };