3 # This file is part of Koha.
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.
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.
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>.
20 use Test::More tests => 6;
23 use t::lib::TestBuilder;
26 use Koha::Preservation::Trains;
29 my $schema = Koha::Database->new->schema;
30 my $builder = t::lib::TestBuilder->new;
32 my $t = Test::Mojo->new('Koha::REST::V1');
33 t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
35 subtest 'list() tests' => sub {
39 $schema->storage->txn_begin;
41 Koha::Preservation::Trains->search->delete;
43 my $librarian = $builder->build_object(
45 class => 'Koha::Patrons',
46 value => { flags => 2**30 }
49 my $password = 'thePassword123';
50 $librarian->set_password( { password => $password, skip_validation => 1 } );
51 my $userid = $librarian->userid;
53 my $patron = $builder->build_object(
55 class => 'Koha::Patrons',
56 value => { flags => 0 }
60 $patron->set_password( { password => $password, skip_validation => 1 } );
61 my $unauth_userid = $patron->userid;
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)
68 my $train = $builder->build_object(
70 class => 'Koha::Preservation::Trains',
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 ] );
79 $t->get_ok("//$unauth_userid:$password@/api/v1/preservation/trains")
82 $schema->storage->txn_rollback;
85 subtest 'get() tests' => sub {
89 $schema->storage->txn_begin;
92 $builder->build_object( { class => 'Koha::Preservation::Trains' } );
93 my $default_processing = $train->default_processing;
94 my $librarian = $builder->build_object(
96 class => 'Koha::Patrons',
97 value => { flags => 2**30 }
100 my $password = 'thePassword123';
101 $librarian->set_password( { password => $password, skip_validation => 1 } );
102 my $userid = $librarian->userid;
104 my $patron = $builder->build_object(
106 class => 'Koha::Patrons',
107 value => { flags => 0 }
111 $patron->set_password( { password => $password, skip_validation => 1 } );
112 my $unauth_userid = $patron->userid;
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 );
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 });
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 => [] } } );
129 # Unauthorized access
130 $t->get_ok( "//$unauth_userid:$password@/api/v1/preservation/trains/"
131 . $train->train_id )->status_is(403);
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;
139 $t->get_ok("//$userid:$password@/api/v1/preservation/trains/$non_existent_id")
140 ->status_is(404)->json_is( '/error' => 'Train not found' );
142 $schema->storage->txn_rollback;
145 subtest 'add() tests' => sub {
149 $schema->storage->txn_begin;
151 my $librarian = $builder->build_object(
153 class => 'Koha::Patrons',
154 value => { flags => 2**30 }
157 my $password = 'thePassword123';
158 $librarian->set_password( { password => $password, skip_validation => 1 } );
159 my $userid = $librarian->userid;
161 my $patron = $builder->build_object(
163 class => 'Koha::Patrons',
164 value => { flags => 0 }
168 $patron->set_password( { password => $password, skip_validation => 1 } );
169 my $unauth_userid = $patron->userid;
171 my $default_processing = $builder->build_object({class => 'Koha::Preservation::Processings'});
173 name => "train name",
174 description => "train description",
175 default_processing_id => $default_processing->processing_id,
179 # Unauthorized attempt to write
180 $t->post_ok( "//$unauth_userid:$password@/api/v1/preservation/trains" => json =>
181 $train )->status_is(403);
183 # Authorized attempt to write invalid data
184 my $train_with_invalid_field = {
185 blah => "train Blah",
189 $t->post_ok( "//$userid:$password@/api/v1/preservation/trains" => json =>
190 $train_with_invalid_field )->status_is(400)->json_is(
193 message => "Properties not allowed: blah.",
199 # Authorized attempt to write
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*|,
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};
212 # Authorized attempt to create with null id
213 $train->{train_id} = undef;
215 "//$userid:$password@/api/v1/preservation/trains" => json => $train )
216 ->status_is(400)->json_has('/errors');
218 # Authorized attempt to create with existing id
219 $train->{train_id} = $train_id;
221 "//$userid:$password@/api/v1/preservation/trains" => json => $train )
222 ->status_is(400)->json_is(
225 message => "Read-only.",
226 path => "/body/train_id"
231 $schema->storage->txn_rollback;
234 subtest 'update() tests' => sub {
238 $schema->storage->txn_begin;
240 my $librarian = $builder->build_object(
242 class => 'Koha::Patrons',
243 value => { flags => 2**30 }
246 my $password = 'thePassword123';
247 $librarian->set_password( { password => $password, skip_validation => 1 } );
248 my $userid = $librarian->userid;
250 my $patron = $builder->build_object(
252 class => 'Koha::Patrons',
253 value => { flags => 0 }
257 $patron->set_password( { password => $password, skip_validation => 1 } );
258 my $unauth_userid = $patron->userid;
261 $builder->build_object( { class => 'Koha::Preservation::Trains' } )->train_id;
263 # Unauthorized attempt to update
265 "//$unauth_userid:$password@/api/v1/preservation/trains/$train_id" =>
266 json => { name => 'New unauthorized name change' } )->status_is(403);
268 # Attempt partial update on a PUT
269 my $train_with_missing_field = {
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" } ] );
278 my $default_processing = $builder->build_object({class => 'Koha::Preservation::Processings'});
279 # Full object update on PUT
280 my $train_with_updated_field = {
282 description => "train description",
283 default_processing_id => $default_processing->processing_id,
288 "//$userid:$password@/api/v1/preservation/trains/$train_id" => json =>
289 $train_with_updated_field )->status_is(200)
290 ->json_is( '/name' => 'New name' );
292 # Authorized attempt to write invalid data
293 my $train_with_invalid_field = {
294 blah => "train Blah",
295 %$train_with_updated_field,
299 "//$userid:$password@/api/v1/preservation/trains/$train_id" => json =>
300 $train_with_invalid_field )->status_is(400)->json_is(
303 message => "Properties not allowed: blah.",
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;
315 $t->put_ok( "//$userid:$password@/api/v1/preservation/trains/$non_existent_id" =>
316 json => $train_with_updated_field )->status_is(404);
318 # Wrong method (POST)
319 $train_with_updated_field->{train_id} = 2;
322 "//$userid:$password@/api/v1/preservation/trains/$train_id" => json =>
323 $train_with_updated_field )->status_is(404);
325 $schema->storage->txn_rollback;
328 subtest 'delete() tests' => sub {
332 $schema->storage->txn_begin;
334 my $librarian = $builder->build_object(
336 class => 'Koha::Patrons',
337 value => { flags => 2**30 }
340 my $password = 'thePassword123';
341 $librarian->set_password( { password => $password, skip_validation => 1 } );
342 my $userid = $librarian->userid;
344 my $patron = $builder->build_object(
346 class => 'Koha::Patrons',
347 value => { flags => 0 }
351 $patron->set_password( { password => $password, skip_validation => 1 } );
352 my $unauth_userid = $patron->userid;
355 $builder->build_object( { class => 'Koha::Preservation::Trains' } )->train_id;
357 # Unauthorized attempt to delete
359 "//$unauth_userid:$password@/api/v1/preservation/trains/$train_id")
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' );
366 # Attempt to delete non-existent train
367 $t->delete_ok("//$userid:$password@/api/v1/preservation/trains/$train_id")
370 $schema->storage->txn_rollback;
373 subtest '*_item() tests' => sub {
377 $schema->storage->txn_begin;
379 my $librarian = $builder->build_object(
381 class => 'Koha::Patrons',
382 value => { flags => 2**30 }
385 my $password = 'thePassword123';
386 $librarian->set_password( { password => $password, skip_validation => 1 } );
387 my $userid = $librarian->userid;
389 my $not_for_loan_waiting_list_in = 24;
390 my $not_for_loan_train_in = 42;
392 t::lib::Mocks::mock_preference( 'PreservationNotForLoanWaitingListIn',
393 $not_for_loan_waiting_list_in );
395 my $default_processing =
396 $builder->build_object( { class => 'Koha::Preservation::Processings' } );
397 my $another_processing =
398 $builder->build_object( { class => 'Koha::Preservation::Processings' } );
403 type => 'authorised_value',
404 option_source => 'COLORS'
406 { name => 'title', type => 'db_column', option_source => '245$a' },
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;
420 my $train = $builder->build_object(
422 class => 'Koha::Preservation::Trains',
424 not_for_loan => $not_for_loan_train_in,
425 default_processing_id => $default_processing->processing_id,
428 received_on => undef,
432 my $train_id = $train->train_id;
434 my $item_1 = $builder->build_sample_item;
435 my $item_2 = $builder->build_sample_item;
436 my $item_3 = $builder->build_sample_item;
438 # Add item not in waiting list
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' } );
444 $item_1->notforloan($not_for_loan_waiting_list_in)->store;
446 # Add item in waiting list
447 my $item_attributes = [
449 processing_attribute_id => $color_attribute->processing_attribute_id,
453 processing_attribute_id => $title_attribute->processing_attribute_id,
459 "//$userid:$password@/api/v1/preservation/trains/$train_id/items" =>
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);
469 "//$userid:$password@/api/v1/preservation/trains/$train_id/items/$train_item_id"
470 => { 'x-koha-embed' => 'attributes' } )->status_is(200)->json_is(
472 %{ $train_item->to_api },
473 attributes => $train_item->attributes->to_api
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" );
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' } );
489 my $new_item_attributes = [
491 processing_attribute_id => $title_attribute->processing_attribute_id,
492 value => 'my new title'
495 processing_attribute_id => $height_attribute->processing_attribute_id,
500 "//$userid:$password@/api/v1/preservation/trains/$train_id/items/$train_item_id"
502 item_id => $item_1->itemnumber,
503 attributes => $new_item_attributes,
508 "//$userid:$password@/api/v1/preservation/trains/$train_id/items/$train_item_id"
509 => { 'x-koha-embed' => 'attributes' } )->status_is(200)->json_is(
511 %{ $train_item->to_api },
512 attributes => $train_item->attributes->to_api
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' );
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' );
524 $schema->storage->txn_rollback;