Bug 24545: Fix license statements
[koha.git] / t / db_dependent / api / v1 / cities.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
6 # under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # Koha is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18 use Modern::Perl;
19
20 use Test::More tests => 5;
21 use Test::Mojo;
22
23 use t::lib::TestBuilder;
24 use t::lib::Mocks;
25
26 use Koha::Cities;
27 use Koha::Database;
28
29 my $schema  = Koha::Database->new->schema;
30 my $builder = t::lib::TestBuilder->new;
31
32 my $t = Test::Mojo->new('Koha::REST::V1');
33 t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
34
35 subtest 'list() tests' => sub {
36
37     plan tests => 20;
38
39     $schema->storage->txn_begin;
40
41     Koha::Cities->search->delete;
42
43     my $librarian = $builder->build_object(
44         {
45             class => 'Koha::Patrons',
46             value => { flags => 2 ** 2 } # catalogue flag = 2
47         }
48     );
49     my $password = 'thePassword123';
50     $librarian->set_password( { password => $password, skip_validation => 1 } );
51     my $userid = $librarian->userid;
52
53     my $patron = $builder->build_object(
54         {
55             class => 'Koha::Patrons',
56             value => { flags => 0 }
57         }
58     );
59
60     $patron->set_password( { password => $password, skip_validation => 1 } );
61     my $unauth_userid = $patron->userid;
62
63     ## Authorized user tests
64     # No cities, so empty array should be returned
65     $t->get_ok("//$userid:$password@/api/v1/cities")
66       ->status_is(200)
67       ->json_is( [] );
68
69     my $city = $builder->build_object({ class => 'Koha::Cities' });
70
71     # One city created, should get returned
72     $t->get_ok("//$userid:$password@/api/v1/cities")
73       ->status_is(200)
74       ->json_is( [$city->to_api] );
75
76     my $another_city = $builder->build_object(
77         { class => 'Koha::Cities', value => { city_country => $city->city_country } } );
78     my $city_with_another_country = $builder->build_object({ class => 'Koha::Cities' });
79
80     # Two cities created, they should both be returned
81     $t->get_ok("//$userid:$password@/api/v1/cities")
82       ->status_is(200)
83       ->json_is([$city->to_api,
84                  $another_city->to_api,
85                  $city_with_another_country->to_api
86                  ] );
87
88     # Filtering works, two cities sharing city_country
89     $t->get_ok("//$userid:$password@/api/v1/cities?country=" . $city->city_country )
90       ->status_is(200)
91       ->json_is([ $city->to_api,
92                   $another_city->to_api
93                   ]);
94
95     $t->get_ok("//$userid:$password@/api/v1/cities?name=" . $city->city_name )
96       ->status_is(200)
97       ->json_is( [$city->to_api] );
98
99     # Warn on unsupported query parameter
100     $t->get_ok("//$userid:$password@/api/v1/cities?city_blah=blah" )
101       ->status_is(400)
102       ->json_is( [{ path => '/query/city_blah', message => 'Malformed query string'}] );
103
104     # Unauthorized access
105     $t->get_ok("//$unauth_userid:$password@/api/v1/cities")
106       ->status_is(403);
107
108     $schema->storage->txn_rollback;
109 };
110
111 subtest 'get() tests' => sub {
112
113     plan tests => 8;
114
115     $schema->storage->txn_begin;
116
117     my $city = $builder->build_object({ class => 'Koha::Cities' });
118     my $librarian = $builder->build_object(
119         {
120             class => 'Koha::Patrons',
121             value => { flags => 2**2 }    # catalogue flag = 2
122         }
123     );
124     my $password = 'thePassword123';
125     $librarian->set_password( { password => $password, skip_validation => 1 } );
126     my $userid = $librarian->userid;
127
128     my $patron = $builder->build_object(
129         {
130             class => 'Koha::Patrons',
131             value => { flags => 0 }
132         }
133     );
134
135     $patron->set_password( { password => $password, skip_validation => 1 } );
136     my $unauth_userid = $patron->userid;
137
138     $t->get_ok( "//$userid:$password@/api/v1/cities/" . $city->cityid )
139       ->status_is(200)
140       ->json_is($city->to_api);
141
142     $t->get_ok( "//$unauth_userid:$password@/api/v1/cities/" . $city->cityid )
143       ->status_is(403);
144
145     my $city_to_delete = $builder->build_object({ class => 'Koha::Cities' });
146     my $non_existent_id = $city_to_delete->id;
147     $city_to_delete->delete;
148
149     $t->get_ok( "//$userid:$password@/api/v1/cities/$non_existent_id" )
150       ->status_is(404)
151       ->json_is( '/error' => 'City not found' );
152
153     $schema->storage->txn_rollback;
154 };
155
156 subtest 'add() tests' => sub {
157
158     plan tests => 18;
159
160     $schema->storage->txn_begin;
161
162     my $librarian = $builder->build_object(
163         {
164             class => 'Koha::Patrons',
165             value => { flags => 2**3 }    # parameters flag = 2
166         }
167     );
168     my $password = 'thePassword123';
169     $librarian->set_password( { password => $password, skip_validation => 1 } );
170     my $userid = $librarian->userid;
171
172     my $patron = $builder->build_object(
173         {
174             class => 'Koha::Patrons',
175             value => { flags => 0 }
176         }
177     );
178
179     $patron->set_password( { password => $password, skip_validation => 1 } );
180     my $unauth_userid = $patron->userid;
181
182     my $city = {
183         name        => "City Name",
184         state       => "City State",
185         postal_code => "City Zipcode",
186         country     => "City Country"
187     };
188
189     # Unauthorized attempt to write
190     $t->post_ok("//$unauth_userid:$password@/api/v1/cities" => json => $city)
191       ->status_is(403);
192
193     # Authorized attempt to write invalid data
194     my $city_with_invalid_field = {
195         blah        => "City Blah",
196         state       => "City State",
197         postal_code => "City Zipcode",
198         country     => "City Country"
199     };
200
201     $t->post_ok( "//$userid:$password@/api/v1/cities" => json => $city_with_invalid_field )
202       ->status_is(400)
203       ->json_is(
204         "/errors" => [
205             {
206                 message => "Properties not allowed: blah.",
207                 path    => "/body"
208             }
209         ]
210       );
211
212     # Authorized attempt to write
213     my $city_id =
214       $t->post_ok( "//$userid:$password@/api/v1/cities" => json => $city )
215         ->status_is( 201, 'SWAGGER3.2.1' )
216         ->header_like(
217             Location => qr|^\/api\/v1\/cities/\d*|,
218             'SWAGGER3.4.1'
219             )
220         ->json_is( '/name'        => $city->{name} )
221         ->json_is( '/state'       => $city->{state} )
222         ->json_is( '/postal_code' => $city->{postal_code} )
223         ->json_is( '/country'     => $city->{country} )
224         ->tx->res->json->{city_id};
225
226     # Authorized attempt to create with null id
227     $city->{city_id} = undef;
228     $t->post_ok( "//$userid:$password@/api/v1/cities" => json => $city )
229       ->status_is(400)
230       ->json_has('/errors');
231
232     # Authorized attempt to create with existing id
233     $city->{city_id} = $city_id;
234     $t->post_ok( "//$userid:$password@/api/v1/cities" => json => $city )
235       ->status_is(400)
236       ->json_is(
237         "/errors" => [
238             {
239                 message => "Read-only.",
240                 path    => "/body/city_id"
241             }
242         ]
243     );
244
245     $schema->storage->txn_rollback;
246 };
247
248 subtest 'update() tests' => sub {
249
250     plan tests => 15;
251
252     $schema->storage->txn_begin;
253
254     my $librarian = $builder->build_object(
255         {
256             class => 'Koha::Patrons',
257             value => { flags => 2**3 }    # parameters flag = 2
258         }
259     );
260     my $password = 'thePassword123';
261     $librarian->set_password( { password => $password, skip_validation => 1 } );
262     my $userid = $librarian->userid;
263
264     my $patron = $builder->build_object(
265         {
266             class => 'Koha::Patrons',
267             value => { flags => 0 }
268         }
269     );
270
271     $patron->set_password( { password => $password, skip_validation => 1 } );
272     my $unauth_userid = $patron->userid;
273
274     my $city_id = $builder->build_object({ class => 'Koha::Cities' } )->id;
275
276     # Unauthorized attempt to update
277     $t->put_ok( "//$unauth_userid:$password@/api/v1/cities/$city_id" => json => { name => 'New unauthorized name change' } )
278       ->status_is(403);
279
280     # Attempt partial update on a PUT
281     my $city_with_missing_field = {
282         name    => 'New name',
283         state   => 'New state',
284         country => 'New country'
285     };
286
287     $t->put_ok( "//$userid:$password@/api/v1/cities/$city_id" => json => $city_with_missing_field )
288       ->status_is(400)
289       ->json_is( "/errors" =>
290           [ { message => "Missing property.", path => "/body/postal_code" } ]
291       );
292
293     # Full object update on PUT
294     my $city_with_updated_field = {
295         name        => "London",
296         state       => "City State",
297         postal_code => "City Zipcode",
298         country     => "City Country"
299     };
300
301     $t->put_ok( "//$userid:$password@/api/v1/cities/$city_id" => json => $city_with_updated_field )
302       ->status_is(200)
303       ->json_is( '/name' => 'London' );
304
305     # Authorized attempt to write invalid data
306     my $city_with_invalid_field = {
307         blah        => "City Blah",
308         state       => "City State",
309         postal_code => "City Zipcode",
310         country     => "City Country"
311     };
312
313     $t->put_ok( "//$userid:$password@/api/v1/cities/$city_id" => json => $city_with_invalid_field )
314       ->status_is(400)
315       ->json_is(
316         "/errors" => [
317             {
318                 message => "Properties not allowed: blah.",
319                 path    => "/body"
320             }
321         ]
322     );
323
324     my $city_to_delete = $builder->build_object({ class => 'Koha::Cities' });
325     my $non_existent_id = $city_to_delete->id;
326     $city_to_delete->delete;
327
328     $t->put_ok( "//$userid:$password@/api/v1/cities/$non_existent_id" => json => $city_with_updated_field )
329       ->status_is(404);
330
331     # Wrong method (POST)
332     $city_with_updated_field->{city_id} = 2;
333
334     $t->post_ok( "//$userid:$password@/api/v1/cities/$city_id" => json => $city_with_updated_field )
335       ->status_is(404);
336
337     $schema->storage->txn_rollback;
338 };
339
340 subtest 'delete() tests' => sub {
341
342     plan tests => 7;
343
344     $schema->storage->txn_begin;
345
346     my $librarian = $builder->build_object(
347         {
348             class => 'Koha::Patrons',
349             value => { flags => 2**3 }    # parameters flag = 2
350         }
351     );
352     my $password = 'thePassword123';
353     $librarian->set_password( { password => $password, skip_validation => 1 } );
354     my $userid = $librarian->userid;
355
356     my $patron = $builder->build_object(
357         {
358             class => 'Koha::Patrons',
359             value => { flags => 0 }
360         }
361     );
362
363     $patron->set_password( { password => $password, skip_validation => 1 } );
364     my $unauth_userid = $patron->userid;
365
366     my $city_id = $builder->build_object({ class => 'Koha::Cities' })->id;
367
368     # Unauthorized attempt to delete
369     $t->delete_ok( "//$unauth_userid:$password@/api/v1/cities/$city_id" )
370       ->status_is(403);
371
372     $t->delete_ok("//$userid:$password@/api/v1/cities/$city_id")
373       ->status_is(200)
374       ->content_is('""');
375
376     $t->delete_ok("//$userid:$password@/api/v1/cities/$city_id")
377       ->status_is(404);
378
379     $schema->storage->txn_rollback;
380 };