Bug 24545: Fix license statements
[srvgit] / t / db_dependent / api / v1 / acquisitions_orders.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 use Test::Warn;
23
24 use t::lib::TestBuilder;
25 use t::lib::Mocks;
26
27 use Koha::Acquisition::Orders;
28 use Koha::Database;
29
30 my $schema  = Koha::Database->new->schema;
31 my $builder = t::lib::TestBuilder->new;
32
33 t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
34
35 my $t = Test::Mojo->new('Koha::REST::V1');
36
37 subtest 'list() tests' => sub {
38     plan tests => 8;
39
40     $schema->storage->txn_begin;
41
42     my $patron = $builder->build_object({
43         class => 'Koha::Patrons',
44         value => { flags => 1 }
45     });
46     my $password = 'thePassword123';
47     $patron->set_password({ password => $password, skip_validation => 1 });
48     my $userid = $patron->userid;
49
50     my $basket = $builder->build_object({ class => 'Koha::Acquisition::Baskets' });
51     # Create test context
52     my $order = $builder->build_object(
53         {
54             class => 'Koha::Acquisition::Orders',
55             value => { basketno => $basket->basketno, orderstatus => 'new' }
56         }
57     );
58     my $another_order = $order->unblessed; # create a copy of $order but make
59     delete $another_order->{ordernumber};  # sure ordernumber will be regenerated
60     $another_order = $builder->build_object({ class => 'Koha::Acquisition::Orders', value => $another_order });
61
62     ## Authorized user tests
63     my $count_of_orders = Koha::Acquisition::Orders->search->count;
64     # Make sure we are returned with the correct amount of orders
65     $t->get_ok( "//$userid:$password@/api/v1/acquisitions/orders" )
66       ->status_is( 200, 'SWAGGER3.2.2' )
67       ->json_has('/'.($count_of_orders-1).'/order_id')
68       ->json_hasnt('/'.($count_of_orders).'/order_id');
69
70     subtest 'query parameters' => sub {
71
72         my $fields = {
73             biblio_id => 'biblionumber',
74             basket_id => 'basketno',
75             fund_id   => 'budget_id',
76         };
77
78         my $size = keys %{$fields};
79
80         plan tests => $size * 3;
81
82         foreach my $field ( keys %{$fields} ) {
83             my $model_field = $fields->{ $field };
84             my $result =
85             $t->get_ok("//$userid:$password@/api/v1/acquisitions/orders?$field=" . $order->$model_field)
86               ->status_is(200)
87               ->json_is( [ $order->to_api, $another_order->to_api ] );
88         }
89     };
90
91     # Warn on unsupported query parameter
92     $t->get_ok( "//$userid:$password@/api/v1/acquisitions/orders?order_blah=blah" )
93       ->status_is(400)
94       ->json_is( [{ path => '/query/order_blah', message => 'Malformed query string'}] );
95
96     $schema->storage->txn_rollback;
97 };
98
99 subtest 'get() tests' => sub {
100
101     plan tests => 6;
102
103     $schema->storage->txn_begin;
104
105     my $order = $builder->build_object(
106         {
107             class => 'Koha::Acquisition::Orders',
108             value => { orderstatus => 'new' }
109         }
110     );
111     my $patron = $builder->build_object({
112         class => 'Koha::Patrons',
113         value => { flags => 2048 }
114     });
115     my $password = 'thePassword123';
116     $patron->set_password({ password => $password, skip_validation => 1 });
117     my $userid = $patron->userid;
118
119     $t->get_ok( "//$userid:$password@/api/v1/acquisitions/orders/" . $order->ordernumber )
120       ->status_is( 200, 'SWAGGER3.2.2' )
121       ->json_is( '' => $order->to_api, 'SWAGGER3.3.2' );
122
123     my $non_existent_order_id = $order->ordernumber;
124     $order->delete;
125
126     $t->get_ok( "//$userid:$password@/api/v1/acquisitions/orders/" . $non_existent_order_id )
127       ->status_is(404)
128       ->json_is( '/error' => 'Order not found' );
129
130     $schema->storage->txn_rollback;
131 };
132
133 subtest 'add() tests' => sub {
134
135     plan tests => 17;
136
137     $schema->storage->txn_begin;
138
139     my $authorized_patron = $builder->build_object({
140         class => 'Koha::Patrons',
141         value => { flags => 1 }
142     });
143     my $password = 'thePassword123';
144     $authorized_patron->set_password({ password => $password, skip_validation => 1 });
145     my $auth_userid = $authorized_patron->userid;
146
147     my $unauthorized_patron = $builder->build_object({
148         class => 'Koha::Patrons',
149         value => { flags => 4 }
150     });
151     $unauthorized_patron->set_password({ password => $password, skip_validation => 1 });
152     my $unauth_userid = $unauthorized_patron->userid;
153
154     my $order_obj = $builder->build_object(
155         {
156             class => 'Koha::Acquisition::Orders',
157             value => {
158                 orderstatus => 'new',
159                 unitprice   => 10,
160                 replacementprice => 10,
161                 quantity    => 2,
162                 quantityreceived => 0,
163                 datecancellationprinted => undef,
164                 order_internalnote => 'This is a dummy note for testing'
165             }
166         }
167     );
168     my $order = $order_obj->to_api;
169     $order_obj->delete;
170     delete $order->{ordernumber};
171     $order->{uncertain_price} = Mojo::JSON->false;
172
173     # Unauthorized attempt to write
174     $t->post_ok( "//$unauth_userid:$password@/api/v1/acquisitions/orders" => json => $order )
175       ->status_is(403);
176
177     # Authorized attempt to write invalid data
178     my $order_with_invalid_field = { %$order };
179     $order_with_invalid_field->{'orderinvalid'} = 'Order invalid';
180
181     $t->post_ok( "//$auth_userid:$password@/api/v1/acquisitions/orders" => json => $order_with_invalid_field )
182       ->status_is(400)
183       ->json_is(
184         "/errors" => [
185             {
186                 message => "Properties not allowed: orderinvalid.",
187                 path    => "/body"
188             }
189         ]
190     );
191
192     # Authorized attempt to write
193     $t->post_ok( "//$auth_userid:$password@/api/v1/acquisitions/orders" => json => $order )
194       ->status_is( 201, 'SWAGGER3.2.1' )
195       ->json_is( '/internal_note' => $order->{internal_note}, 'SWAGGER3.3.1' )
196       ->header_like( Location => qr/\/api\/v1\/acquisitions\/orders\/\d*/, 'SWAGGER3.4.1' );
197
198     # save the order_id
199     my $order_id = $order->{order_id};
200     # Authorized attempt to create with null id
201     $order->{order_id} = undef;
202
203     $t->post_ok( "//$auth_userid:$password@/api/v1/acquisitions/orders" => json => $order )
204       ->status_is(400)
205       ->json_has('/errors');
206
207     # Authorized attempt to create with existing id
208     $order->{order_id} = $order_id;
209
210     warning_like {
211         $t->post_ok( "//$auth_userid:$password@/api/v1/acquisitions/orders" => json => $order )
212           ->status_is(409)
213           ->json_has( '/error' => "Fails when trying to add an existing order_id")
214           ->json_like( '/conflict' => qr/(aqorders\.)?PRIMARY/ ); }
215         qr/^DBD::mysql::st execute failed: Duplicate entry '(.*)' for key '(aqorders\.)?PRIMARY'/;
216
217     $schema->storage->txn_rollback;
218 };
219
220 subtest 'update() tests' => sub {
221     plan tests => 13;
222
223     $schema->storage->txn_begin;
224
225     my $authorized_patron = $builder->build_object({
226         class => 'Koha::Patrons',
227         value => { flags => 1 }
228     });
229     my $password = 'thePassword123';
230     $authorized_patron->set_password({ password => $password, skip_validation => 1 });
231     my $auth_userid = $authorized_patron->userid;
232
233     my $unauthorized_patron = $builder->build_object({
234         class => 'Koha::Patrons',
235         value => { flags => 4 }
236     });
237     $unauthorized_patron->set_password({ password => $password, skip_validation => 1 });
238     my $unauth_userid = $unauthorized_patron->userid;
239
240     my $library    = $builder->build_object({ class => 'Koha::Libraries' });
241     my $library_id = $library->branchcode;
242
243     # Unauthorized attempt to update
244     $t->put_ok( "//$unauth_userid:$password@/api/v1/libraries/$library_id"
245                     => json => { name => 'New unauthorized name change' } )
246       ->status_is(403);
247
248     # Attempt partial update on a PUT
249     my $library_with_missing_field = {
250         address1 => "New library address",
251     };
252
253     $t->put_ok( "//$auth_userid:$password@/api/v1/libraries/$library_id" => json => $library_with_missing_field )
254       ->status_is(400)
255       ->json_has( "/errors" =>
256           [ { message => "Missing property.", path => "/body/address2" } ]
257       );
258
259     my $deleted_library = $builder->build_object( { class => 'Koha::Libraries' } );
260     my $library_with_updated_field = $deleted_library->to_api;
261     $library_with_updated_field->{library_id} = $library_id;
262     $deleted_library->delete;
263
264     $t->put_ok( "//$auth_userid:$password@/api/v1/libraries/$library_id" => json => $library_with_updated_field )
265       ->status_is(200, 'SWAGGER3.2.1')
266       ->json_is( '' => $library_with_updated_field, 'SWAGGER3.3.3' );
267
268     # Authorized attempt to write invalid data
269     my $library_with_invalid_field = { %$library_with_updated_field };
270     $library_with_invalid_field->{'branchinvalid'} = 'Library invalid';
271
272     $t->put_ok( "//$auth_userid:$password@/api/v1/libraries/$library_id" => json => $library_with_invalid_field )
273       ->status_is(400)
274       ->json_is(
275         "/errors" => [
276             {
277                 message => "Properties not allowed: branchinvalid.",
278                 path    => "/body"
279             }
280         ]
281     );
282
283     my $non_existent_code = 'nope'.int(rand(10000));
284     $t->put_ok("//$auth_userid:$password@/api/v1/libraries/$non_existent_code" => json => $library_with_updated_field)
285       ->status_is(404);
286
287     $schema->storage->txn_rollback;
288 };
289
290 subtest 'delete() tests' => sub {
291     plan tests => 7;
292
293     $schema->storage->txn_begin;
294
295     my $authorized_patron = $builder->build_object({
296         class => 'Koha::Patrons',
297         value => { flags => 1 }
298     });
299     my $password = 'thePassword123';
300     $authorized_patron->set_password({ password => $password, skip_validation => 1 });
301     my $auth_userid = $authorized_patron->userid;
302
303     my $unauthorized_patron = $builder->build_object({
304         class => 'Koha::Patrons',
305         value => { flags => 4 }
306     });
307     $unauthorized_patron->set_password({ password => $password, skip_validation => 1 });
308     my $unauth_userid = $unauthorized_patron->userid;
309
310     my $order = $builder->build_object( { class => 'Koha::Acquisition::Orders' } );
311
312     # Unauthorized attempt to delete
313     $t->delete_ok( "//$unauth_userid:$password@/api/v1/acquisitions/orders/" . $order->ordernumber )
314       ->status_is(403);
315
316     $t->delete_ok( "//$auth_userid:$password@/api/v1/acquisitions/orders/" . $order->ordernumber )
317       ->status_is(204, 'SWAGGER3.2.4')
318       ->content_is('', 'SWAGGER3.3.4');
319
320     $t->delete_ok( "//$auth_userid:$password@/api/v1/acquisitions/orders/" . $order->ordernumber )
321       ->status_is(404);
322
323     $schema->storage->txn_rollback;
324 };