]> git.koha-community.org Git - koha.git/blob - t/db_dependent/api/v1/preservation_Trains.t
Bug 30708: Add tests
[koha.git] / t / db_dependent / api / v1 / preservation_Trains.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 => 6;
21 use Test::Mojo;
22
23 use t::lib::TestBuilder;
24 use t::lib::Mocks;
25
26 use Koha::Preservation::Trains;
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 => 8;
38
39     $schema->storage->txn_begin;
40
41     Koha::Preservation::Trains->search->delete;
42
43     my $librarian = $builder->build_object(
44         {
45             class => 'Koha::Patrons',
46             value => { flags => 2**30 }
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 trains, so empty array should be returned
65     $t->get_ok("//$userid:$password@/api/v1/preservation/trains")->status_is(200)
66       ->json_is( [] );
67
68     my $train = $builder->build_object(
69         {
70             class => 'Koha::Preservation::Trains',
71         }
72     );
73
74     # One train created, should get returned
75     $t->get_ok("//$userid:$password@/api/v1/preservation/trains")->status_is(200)
76       ->json_is( [ $train->to_api ] );
77
78     # Unauthorized access
79     $t->get_ok("//$unauth_userid:$password@/api/v1/preservation/trains")
80       ->status_is(403);
81
82     $schema->storage->txn_rollback;
83 };
84
85 subtest 'get() tests' => sub {
86
87     plan tests => 14;
88
89     $schema->storage->txn_begin;
90
91     my $train =
92       $builder->build_object( { class => 'Koha::Preservation::Trains' } );
93     my $default_processing = $train->default_processing;
94     my $librarian = $builder->build_object(
95         {
96             class => 'Koha::Patrons',
97             value => { flags => 2**30 }
98         }
99     );
100     my $password = 'thePassword123';
101     $librarian->set_password( { password => $password, skip_validation => 1 } );
102     my $userid = $librarian->userid;
103
104     my $patron = $builder->build_object(
105         {
106             class => 'Koha::Patrons',
107             value => { flags => 0 }
108         }
109     );
110
111     $patron->set_password( { password => $password, skip_validation => 1 } );
112     my $unauth_userid = $patron->userid;
113
114     # This train exists, should get returned
115     $t->get_ok( "//$userid:$password@/api/v1/preservation/trains/"
116           . $train->train_id )->status_is(200)
117       ->json_is( $train->to_api );
118
119     # Return one train with some embeds
120     $t->get_ok( "//$userid:$password@/api/v1/preservation/trains/"
121           . $train->train_id  => {'x-koha-embed' => 'items,default_processing'} )->status_is(200)
122       ->json_is( { %{ $train->to_api }, items => [], default_processing => $default_processing->unblessed });
123
124     # Return one train with all embeds
125     $t->get_ok( "//$userid:$password@/api/v1/preservation/trains/"
126           . $train->train_id => { 'x-koha-embed' => 'items,items.attributes,items.attributes.processing_attribute,default_processing,default_processing.attributes' } )
127       ->status_is(200)->json_is( { %{ $train->to_api }, items => [], default_processing => { %{ $default_processing->unblessed }, attributes => [] } } );
128
129     # Unauthorized access
130     $t->get_ok( "//$unauth_userid:$password@/api/v1/preservation/trains/"
131           . $train->train_id )->status_is(403);
132
133     # Attempt to get non-existent train
134     my $train_to_delete =
135       $builder->build_object( { class => 'Koha::Preservation::Trains' } );
136     my $non_existent_id = $train_to_delete->train_id;
137     $train_to_delete->delete;
138
139     $t->get_ok("//$userid:$password@/api/v1/preservation/trains/$non_existent_id")
140       ->status_is(404)->json_is( '/error' => 'Train not found' );
141
142     $schema->storage->txn_rollback;
143 };
144
145 subtest 'add() tests' => sub {
146
147     plan tests => 18;
148
149     $schema->storage->txn_begin;
150
151     my $librarian = $builder->build_object(
152         {
153             class => 'Koha::Patrons',
154             value => { flags => 2**30 }
155         }
156     );
157     my $password = 'thePassword123';
158     $librarian->set_password( { password => $password, skip_validation => 1 } );
159     my $userid = $librarian->userid;
160
161     my $patron = $builder->build_object(
162         {
163             class => 'Koha::Patrons',
164             value => { flags => 0 }
165         }
166     );
167
168     $patron->set_password( { password => $password, skip_validation => 1 } );
169     my $unauth_userid = $patron->userid;
170
171     my $default_processing = $builder->build_object({class => 'Koha::Preservation::Processings'});
172     my $train = {
173         name             => "train name",
174         description      => "train description",
175         default_processing_id => $default_processing->processing_id,
176         not_for_loan => 42,
177     };
178
179     # Unauthorized attempt to write
180     $t->post_ok( "//$unauth_userid:$password@/api/v1/preservation/trains" => json =>
181           $train )->status_is(403);
182
183     # Authorized attempt to write invalid data
184     my $train_with_invalid_field = {
185         blah             => "train Blah",
186         %$train,
187     };
188
189     $t->post_ok( "//$userid:$password@/api/v1/preservation/trains" => json =>
190           $train_with_invalid_field )->status_is(400)->json_is(
191         "/errors" => [
192             {
193                 message => "Properties not allowed: blah.",
194                 path    => "/body"
195             }
196         ]
197           );
198
199     # Authorized attempt to write
200     my $train_id =
201       $t->post_ok(
202         "//$userid:$password@/api/v1/preservation/trains" => json => $train )
203       ->status_is( 201, 'SWAGGER3.2.1' )->header_like(
204         Location => qr|^/api/v1/preservation/trains/\d*|,
205         'SWAGGER3.4.1'
206     )->json_is( '/name'                   => $train->{name} )
207       ->json_is( '/description'           => $train->{description} )
208       ->json_is( '/default_processing_id' => $train->{default_processing_id} )
209       ->json_is( '/not_for_loan'          => $train->{not_for_loan} )
210       ->tx->res->json->{train_id};
211
212     # Authorized attempt to create with null id
213     $train->{train_id} = undef;
214     $t->post_ok(
215         "//$userid:$password@/api/v1/preservation/trains" => json => $train )
216       ->status_is(400)->json_has('/errors');
217
218     # Authorized attempt to create with existing id
219     $train->{train_id} = $train_id;
220     $t->post_ok(
221         "//$userid:$password@/api/v1/preservation/trains" => json => $train )
222       ->status_is(400)->json_is(
223         "/errors" => [
224             {
225                 message => "Read-only.",
226                 path    => "/body/train_id"
227             }
228         ]
229       );
230
231     $schema->storage->txn_rollback;
232 };
233
234 subtest 'update() tests' => sub {
235
236     plan tests => 15;
237
238     $schema->storage->txn_begin;
239
240     my $librarian = $builder->build_object(
241         {
242             class => 'Koha::Patrons',
243             value => { flags => 2**30 }
244         }
245     );
246     my $password = 'thePassword123';
247     $librarian->set_password( { password => $password, skip_validation => 1 } );
248     my $userid = $librarian->userid;
249
250     my $patron = $builder->build_object(
251         {
252             class => 'Koha::Patrons',
253             value => { flags => 0 }
254         }
255     );
256
257     $patron->set_password( { password => $password, skip_validation => 1 } );
258     my $unauth_userid = $patron->userid;
259
260     my $train_id =
261       $builder->build_object( { class => 'Koha::Preservation::Trains' } )->train_id;
262
263     # Unauthorized attempt to update
264     $t->put_ok(
265         "//$unauth_userid:$password@/api/v1/preservation/trains/$train_id" =>
266           json => { name => 'New unauthorized name change' } )->status_is(403);
267
268     # Attempt partial update on a PUT
269     my $train_with_missing_field = {
270     };
271
272     $t->put_ok(
273         "//$userid:$password@/api/v1/preservation/trains/$train_id" => json =>
274           $train_with_missing_field )->status_is(400)
275       ->json_is( "/errors" =>
276           [ { message => "Missing property.", path => "/body/name" } ] );
277
278     my $default_processing = $builder->build_object({class => 'Koha::Preservation::Processings'});
279     # Full object update on PUT
280     my $train_with_updated_field = {
281         name             => "New name",
282         description      => "train description",
283         default_processing_id => $default_processing->processing_id,
284         not_for_loan => 42,
285     };
286
287     $t->put_ok(
288         "//$userid:$password@/api/v1/preservation/trains/$train_id" => json =>
289           $train_with_updated_field )->status_is(200)
290       ->json_is( '/name' => 'New name' );
291
292     # Authorized attempt to write invalid data
293     my $train_with_invalid_field = {
294         blah             => "train Blah",
295         %$train_with_updated_field,
296     };
297
298     $t->put_ok(
299         "//$userid:$password@/api/v1/preservation/trains/$train_id" => json =>
300           $train_with_invalid_field )->status_is(400)->json_is(
301         "/errors" => [
302             {
303                 message => "Properties not allowed: blah.",
304                 path    => "/body"
305             }
306         ]
307           );
308
309     # Attempt to update non-existent train
310     my $train_to_delete =
311       $builder->build_object( { class => 'Koha::Preservation::Trains' } );
312     my $non_existent_id = $train_to_delete->train_id;
313     $train_to_delete->delete;
314
315     $t->put_ok( "//$userid:$password@/api/v1/preservation/trains/$non_existent_id" =>
316           json => $train_with_updated_field )->status_is(404);
317
318     # Wrong method (POST)
319     $train_with_updated_field->{train_id} = 2;
320
321     $t->post_ok(
322         "//$userid:$password@/api/v1/preservation/trains/$train_id" => json =>
323           $train_with_updated_field )->status_is(404);
324
325     $schema->storage->txn_rollback;
326 };
327
328 subtest 'delete() tests' => sub {
329
330     plan tests => 7;
331
332     $schema->storage->txn_begin;
333
334     my $librarian = $builder->build_object(
335         {
336             class => 'Koha::Patrons',
337             value => { flags => 2**30 }
338         }
339     );
340     my $password = 'thePassword123';
341     $librarian->set_password( { password => $password, skip_validation => 1 } );
342     my $userid = $librarian->userid;
343
344     my $patron = $builder->build_object(
345         {
346             class => 'Koha::Patrons',
347             value => { flags => 0 }
348         }
349     );
350
351     $patron->set_password( { password => $password, skip_validation => 1 } );
352     my $unauth_userid = $patron->userid;
353
354     my $train_id =
355       $builder->build_object( { class => 'Koha::Preservation::Trains' } )->train_id;
356
357     # Unauthorized attempt to delete
358     $t->delete_ok(
359         "//$unauth_userid:$password@/api/v1/preservation/trains/$train_id")
360       ->status_is(403);
361
362     # Delete existing train
363     $t->delete_ok("//$userid:$password@/api/v1/preservation/trains/$train_id")
364       ->status_is( 204, 'SWAGGER3.2.4' )->content_is( '', 'SWAGGER3.3.4' );
365
366     # Attempt to delete non-existent train
367     $t->delete_ok("//$userid:$password@/api/v1/preservation/trains/$train_id")
368       ->status_is(404);
369
370     $schema->storage->txn_rollback;
371 };
372
373 subtest '*_item() tests' => sub {
374
375     plan tests => 26;
376
377     $schema->storage->txn_begin;
378
379     my $librarian = $builder->build_object(
380         {
381             class => 'Koha::Patrons',
382             value => { flags => 2**30 }
383         }
384     );
385     my $password = 'thePassword123';
386     $librarian->set_password( { password => $password, skip_validation => 1 } );
387     my $userid = $librarian->userid;
388
389     my $not_for_loan_waiting_list_in = 24;
390     my $not_for_loan_train_in        = 42;
391
392     t::lib::Mocks::mock_preference( 'PreservationNotForLoanWaitingListIn',
393         $not_for_loan_waiting_list_in );
394
395     my $default_processing =
396       $builder->build_object( { class => 'Koha::Preservation::Processings' } );
397     my $another_processing =
398       $builder->build_object( { class => 'Koha::Preservation::Processings' } );
399
400     my $attributes = [
401         {
402             name          => 'color',
403             type          => 'authorised_value',
404             option_source => 'COLORS'
405         },
406         { name => 'title', type => 'db_column', option_source => '245$a' },
407         {
408             name => 'height',
409             type => 'free_text'
410         },
411     ];
412     my $processing_attributes = $default_processing->attributes($attributes);
413     my $color_attribute =
414       $processing_attributes->search( { name => 'color' } )->next;
415     my $title_attribute =
416       $processing_attributes->search( { name => 'title' } )->next;
417     my $height_attribute =
418       $processing_attributes->search( { name => 'height' } )->next;
419
420     my $train = $builder->build_object(
421         {
422             class => 'Koha::Preservation::Trains',
423             value => {
424                 not_for_loan          => $not_for_loan_train_in,
425                 default_processing_id => $default_processing->processing_id,
426                 closed_on             => undef,
427                 sent_on               => undef,
428                 received_on           => undef,
429             }
430         }
431     );
432     my $train_id = $train->train_id;
433
434     my $item_1 = $builder->build_sample_item;
435     my $item_2 = $builder->build_sample_item;
436     my $item_3 = $builder->build_sample_item;
437
438     # Add item not in waiting list
439     $t->post_ok(
440         "//$userid:$password@/api/v1/preservation/trains/$train_id/items" =>
441           json => { item_id => $item_1->itemnumber } )->status_is(400)
442       ->json_is( { error => 'Item not in waiting list' } );
443
444     $item_1->notforloan($not_for_loan_waiting_list_in)->store;
445
446     # Add item in waiting list
447     my $item_attributes = [
448         {
449             processing_attribute_id => $color_attribute->processing_attribute_id,
450             value => 'red'
451         },
452         {
453             processing_attribute_id => $title_attribute->processing_attribute_id,
454             value => 'my title'
455         },
456     ];
457     my $train_item_id =
458       $t->post_ok(
459         "//$userid:$password@/api/v1/preservation/trains/$train_id/items" =>
460           json =>
461           { item_id => $item_1->itemnumber, attributes => $item_attributes } )
462       ->status_is( 201, 'SWAGGER3.2.1' )
463       ->json_is( '/item_id'       => $item_1->itemnumber )
464       ->json_is( '/processing_id' => $train->default_processing_id )
465       ->json_has('/added_on')->tx->res->json->{train_item_id};
466     my $train_item = Koha::Preservation::Train::Items->find($train_item_id);
467
468     $t->get_ok(
469         "//$userid:$password@/api/v1/preservation/trains/$train_id/items/$train_item_id"
470           => { 'x-koha-embed' => 'attributes' } )->status_is(200)->json_is(
471         {
472             %{ $train_item->to_api },
473             attributes => $train_item->attributes->to_api
474         }
475           );
476
477     is( $item_1->get_from_storage->notforloan,
478         $train->not_for_loan,
479         "Item not for loan has been set to train's not for loan" );
480
481     # Add deleted item
482     $item_2->delete;
483     $t->post_ok(
484         "//$userid:$password@/api/v1/preservation/trains/$train_id/items" =>
485           json => { item_id => $item_2->itemnumber } )->status_is(404)
486       ->json_is( { error => 'Item not found' } );
487
488     # Update item
489     my $new_item_attributes = [
490         {
491             processing_attribute_id => $title_attribute->processing_attribute_id,
492             value => 'my new title'
493         },
494         {
495             processing_attribute_id => $height_attribute->processing_attribute_id,
496             value => '24cm'
497         },
498     ];
499     $t->put_ok(
500         "//$userid:$password@/api/v1/preservation/trains/$train_id/items/$train_item_id"
501           => json => {
502             item_id    => $item_1->itemnumber,
503             attributes => $new_item_attributes,
504           }
505     )->status_is(200);
506
507     $t->get_ok(
508         "//$userid:$password@/api/v1/preservation/trains/$train_id/items/$train_item_id"
509           => { 'x-koha-embed' => 'attributes' } )->status_is(200)->json_is(
510         {
511             %{ $train_item->to_api },
512             attributes => $train_item->attributes->to_api
513         }
514           );
515
516     # Delete existing item
517     $t->delete_ok("//$userid:$password@/api/v1/preservation/trains/$train_id/items/$train_item_id")
518       ->status_is( 204, 'SWAGGER3.2.4' )->content_is( '', 'SWAGGER3.3.4' );
519
520     # Delete non existing item
521     $t->delete_ok("//$userid:$password@/api/v1/preservation/trains/$train_id/items/$train_item_id")
522       ->status_is(404)->json_is( '/error' => 'Train item not found' );
523
524     $schema->storage->txn_rollback;
525 };