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 => 5;
23 use t::lib::TestBuilder;
28 my $schema = Koha::Database->new->schema;
29 my $builder = t::lib::TestBuilder->new();
31 my $t = Test::Mojo->new('Koha::REST::V1');
33 t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
35 subtest 'list_patron_attributes() tests' => sub {
39 $schema->storage->txn_begin;
41 my $patron = $builder->build_object({
42 class => 'Koha::Patrons',
43 value => { flags => 2 ** 4 } # 'borrowers' flag == 4
45 my $password = 'thePassword123';
46 $patron->set_password({ password => $password, skip_validation => 1 });
47 my $userid = $patron->userid;
49 $t->get_ok("//$userid:$password@/api/v1/patrons/" . $patron->id . '/extended_attributes')
50 ->status_is( 200, 'SWAGGER3.2.2' )
53 # Let's add 3 attributes
54 foreach my $i ( 1..5 ) {
55 $builder->build_object({ class => 'Koha::Patron::Attributes', value => { borrowernumber => $patron->id } });
58 $t->get_ok("//$userid:$password@/api/v1/patrons/" . $patron->id . '/extended_attributes')
59 ->status_is( 200, 'SWAGGER3.2.2' )
60 ->json_is( '' => $patron->extended_attributes->to_api, 'Extended attributes retrieved correctly' );
62 my $non_existent_patron = $builder->build_object({ class => 'Koha::Patrons' });
63 my $non_existent_patron_id = $non_existent_patron->id;
64 # get rid of the patron
65 $non_existent_patron->delete;
67 $t->get_ok("//$userid:$password@/api/v1/patrons/" . $non_existent_patron_id . '/extended_attributes')
69 ->json_is( '/error' => 'Patron not found' );
71 $schema->storage->txn_rollback;
74 subtest 'add() tests' => sub {
78 $schema->storage->txn_begin;
80 my $patron = $builder->build_object({
81 class => 'Koha::Patrons',
82 value => { flags => 2 ** 4 } # 'borrowers' flag == 4
84 my $password = 'thePassword123';
85 $patron->set_password({ password => $password, skip_validation => 1 });
86 my $userid = $patron->userid;
88 my $mandatory_attr_type = $builder->build_object(
90 class => 'Koha::Patron::Attribute::Types',
95 category_code => undef
99 my $repeatable_attr_type = $builder->build_object(
101 class => 'Koha::Patron::Attribute::Types',
106 category_code => undef
110 my $unique_attr_type = $builder->build_object(
112 class => 'Koha::Patron::Attribute::Types',
117 category_code => undef
122 my $non_existent_patron = $builder->build_object({ class => 'Koha::Patrons' });
123 my $non_existent_patron_id = $non_existent_patron->id;
124 # get rid of the patron
125 $non_existent_patron->delete;
127 $t->post_ok( "//$userid:$password@/api/v1/patrons/"
128 . $non_existent_patron_id
129 . '/extended_attributes' => json =>
130 { type => $repeatable_attr_type->code, value => 'something' } )
131 ->status_is(404)->json_is( '/error' => 'Patron not found' );
133 my $response = $t->post_ok( "//$userid:$password@/api/v1/patrons/"
135 . '/extended_attributes' => json =>
136 { type => $repeatable_attr_type->code, value => 'something' } )
137 ->status_is(201)->tx->res->json;
140 Koha::Patron::Attributes->find( $response->{extended_attribute_id} )->to_api,
142 "The returned object is on the DB"
145 subtest 'Repeatability tests' => sub {
146 $t->post_ok( "//$userid:$password@/api/v1/patrons/"
148 . '/extended_attributes' => json =>
149 { type => $repeatable_attr_type->code, value => 'something' } )
150 ->status_is(201, 'Repeatable attributes go through');
152 # Let's add a non-repeatable one
153 $patron->add_extended_attribute(
154 { code => $unique_attr_type->code, attribute => 'non_repeatable_1' } );
155 $t->post_ok( "//$userid:$password@/api/v1/patrons/"
157 . '/extended_attributes' => json =>
158 { type => $unique_attr_type->code, value => 'non_repeatable_2' } )
160 ->json_is( '/error' =>
161 'Tried to add more than one non-repeatable attributes. type='
162 . $unique_attr_type->code
163 . ' value=non_repeatable_2' );
166 subtest 'Attribute uniqueness tests' => sub {
170 my $patron_2 = $builder->build_object( { class => 'Koha::Patrons' } );
171 $t->post_ok( "//$userid:$password@/api/v1/patrons/"
173 . '/extended_attributes' => json =>
174 { type => $unique_attr_type->code, value => 'non_repeatable_1' } )
176 ->json_is( '/error' =>
177 'Your action breaks a unique constraint on the attribute. type='
178 . $unique_attr_type->code
179 . ' value=non_repeatable_1' );
182 subtest 'Invalid type tests' => sub {
186 my $invalid_type_obj = $builder->build_object({ class => 'Koha::Patron::Attribute::Types' });
187 my $invalid_type = $invalid_type_obj->code;
188 $invalid_type_obj->delete;
190 $t->post_ok( "//$userid:$password@/api/v1/patrons/"
192 . '/extended_attributes' => json =>
193 { type => $invalid_type, value => 'blah' } )
195 ->json_is( '/error' => "Tried to use an invalid attribute type. type=$invalid_type" );
198 $schema->storage->txn_rollback;
201 subtest 'overwrite() tests' => sub {
205 $schema->storage->txn_begin;
207 Koha::Patron::Attribute::Types->delete;
209 my $patron = $builder->build_object({
210 class => 'Koha::Patrons',
211 value => { flags => 2 ** 4 } # 'borrowers' flag == 4
213 my $password = 'thePassword123';
214 $patron->set_password({ password => $password, skip_validation => 1 });
215 my $userid = $patron->userid;
217 my $mandatory_attr_type = $builder->build_object(
219 class => 'Koha::Patron::Attribute::Types',
224 category_code => undef
228 my $repeatable_attr_type = $builder->build_object(
230 class => 'Koha::Patron::Attribute::Types',
235 category_code => undef
239 my $unique_attr_type = $builder->build_object(
241 class => 'Koha::Patron::Attribute::Types',
246 category_code => undef
250 my $invalid_type_obj = $builder->build_object(
252 class => 'Koha::Patron::Attribute::Types'
255 my $invalid_type = $invalid_type_obj->code;
256 $invalid_type_obj->delete;
258 my $non_existent_patron = $builder->build_object({ class => 'Koha::Patrons' });
259 my $non_existent_patron_id = $non_existent_patron->id;
260 # get rid of the patron
261 $non_existent_patron->delete;
263 $t->put_ok( "//$userid:$password@/api/v1/patrons/"
264 . $non_existent_patron_id
265 . '/extended_attributes' => json =>
266 [ { type => $repeatable_attr_type->code, value => 'something' } ] )
268 ->json_is( '/error' => 'Patron not found' );
270 $t->put_ok( "//$userid:$password@/api/v1/patrons/"
272 . '/extended_attributes' => json =>
273 [ { type => $invalid_type, value => 'something' } ] )
275 ->json_is( '/error' => "Tried to use an invalid attribute type. type=$invalid_type" );
277 my $unique_value = 'The only one!';
278 my $dummy_patron = $builder->build_object({ class => 'Koha::Patrons' });
279 $dummy_patron->add_extended_attribute({ code => $unique_attr_type->code, attribute => $unique_value });
281 $t->put_ok( "//$userid:$password@/api/v1/patrons/"
283 . '/extended_attributes' => json =>
284 [ { type => $unique_attr_type->code, value => $unique_value } ] )
286 ->json_is( '/error' => "Your action breaks a unique constraint on the attribute. type=" . $unique_attr_type->code . " value=$unique_value" );
288 my $value_1 = 'value_1';
289 my $value_2 = 'value_2';
291 $t->put_ok( "//$userid:$password@/api/v1/patrons/"
293 . '/extended_attributes' => json =>
294 [ { type => $unique_attr_type->code, value => $value_1 },
295 { type => $unique_attr_type->code, value => $value_2 } ] )
297 ->json_is( '/error' => "Tried to add more than one non-repeatable attributes. type=" . $unique_attr_type->code . " value=$value_2" );
299 $t->put_ok( "//$userid:$password@/api/v1/patrons/"
301 . '/extended_attributes' => json =>
302 [ { type => $unique_attr_type->code, value => $value_1 } ] )
304 ->json_is( '/error' => "Missing mandatory extended attribute (type=" . $mandatory_attr_type->code . ')' );
306 $patron->add_extended_attribute({ code => $repeatable_attr_type->code, attribute => 'repeatable_1' });
307 $patron->add_extended_attribute({ code => $repeatable_attr_type->code, attribute => 'repeatable_2' });
308 $patron->add_extended_attribute({ code => $mandatory_attr_type->code, attribute => 'mandatory' });
309 $patron->add_extended_attribute({ code => $unique_attr_type->code, attribute => 'unique' });
311 $t->get_ok("//$userid:$password@/api/v1/patrons/" . $patron->id . '/extended_attributes')
312 ->status_is( 200, 'SWAGGER3.2.2' )
313 ->json_is( '' => $patron->extended_attributes->to_api, 'Extended attributes retrieved correctly' );
315 my $updated_attributes = [
317 type => $repeatable_attr_type->code,
318 value => 'updated_repeatable_1'
321 type => $repeatable_attr_type->code,
322 value => 'updated_repeatable_2'
325 type => $repeatable_attr_type->code,
326 value => 'updated_repeatable_3'
329 type => $mandatory_attr_type->code,
330 value => 'updated_mandatory'
334 $t->put_ok( "//$userid:$password@/api/v1/patrons/"
336 . '/extended_attributes' => json => $updated_attributes )
338 ->json_is( '/0/type' => $updated_attributes->[0]->{type} )
339 ->json_is( '/0/value' => $updated_attributes->[0]->{value} )
340 ->json_is( '/1/type' => $updated_attributes->[1]->{type} )
341 ->json_is( '/1/value' => $updated_attributes->[1]->{value} )
342 ->json_is( '/2/type' => $updated_attributes->[2]->{type} )
343 ->json_is( '/2/value' => $updated_attributes->[2]->{value} )
344 ->json_is( '/3/type' => $updated_attributes->[3]->{type} )
345 ->json_is( '/3/value' => $updated_attributes->[3]->{value} )
348 $schema->storage->txn_rollback;
351 subtest 'delete() tests' => sub {
355 $schema->storage->txn_begin;
357 my $patron = $builder->build_object({
358 class => 'Koha::Patrons',
359 value => { flags => 2 ** 4 } # 'borrowers' flag == 4
361 my $password = 'thePassword123';
362 $patron->set_password({ password => $password, skip_validation => 1 });
363 my $userid = $patron->userid;
365 my $attr_type = $builder->build_object(
367 class => 'Koha::Patron::Attribute::Types',
372 category_code => undef
377 my $dummy_patron = $builder->build_object({ class => 'Koha::Patrons' });
379 my $attr = $dummy_patron->add_extended_attribute({ code => $attr_type->code, attribute => 'blah' });
381 $t->delete_ok("//$userid:$password@/api/v1/patrons/" . $dummy_patron->id . '/extended_attributes/' . $attr->id )
382 ->status_is(204, 'SWAGGER3.2.4')
383 ->content_is('', 'SWAGGER3.3.4');
385 $t->delete_ok("//$userid:$password@/api/v1/patrons/" . $dummy_patron->id . '/extended_attributes/' . $attr->id )
387 ->json_is( '/error' => 'Attribute not found' );
389 $dummy_patron->delete;
391 $t->delete_ok("//$userid:$password@/api/v1/patrons/" . $dummy_patron->id . '/extended_attributes/' . $attr->id )
393 ->json_is( '/error' => 'Patron not found' );
395 $schema->storage->txn_rollback;
398 subtest 'update() tests' => sub {
402 $schema->storage->txn_begin;
404 my $patron = $builder->build_object(
406 class => 'Koha::Patrons',
407 value => { flags => 2**4 } # 'borrowers' flag == 4
410 my $password = 'thePassword123';
411 $patron->set_password( { password => $password, skip_validation => 1 } );
412 my $userid = $patron->userid;
414 my $repeatable_attr_type = $builder->build_object(
416 class => 'Koha::Patron::Attribute::Types',
421 category_code => undef
425 my $unique_attr_type = $builder->build_object(
427 class => 'Koha::Patron::Attribute::Types',
432 category_code => undef
437 # Add a unique attribute to our patron
438 my $unique_attribute = $patron->add_extended_attribute(
440 code => $unique_attr_type->code,
445 # Let's have an attribute ID we are sure doesn't exist on the DB
446 my $non_existent_attribute = $patron->add_extended_attribute(
448 code => $repeatable_attr_type->code,
452 my $non_existent_attribute_id = $non_existent_attribute->id;
453 $non_existent_attribute->delete;
455 my $non_existent_patron =
456 $builder->build_object( { class => 'Koha::Patrons' } );
457 my $non_existent_patron_id = $non_existent_patron->id;
459 # get rid of the patron
460 $non_existent_patron->delete;
462 $t->patch_ok( "//$userid:$password@/api/v1/patrons/"
463 . $non_existent_patron_id
464 . '/extended_attributes/'
465 . 123 => json => { value => 'something' } )->status_is(404)
466 ->json_is( '/error' => 'Patron not found' );
468 $t->patch_ok( "//$userid:$password@/api/v1/patrons/"
470 . '/extended_attributes/'
471 . $non_existent_attribute_id => json => { value => 'something' } )
472 ->status_is(404)->json_is( '/error' => 'Attribute not found' );
475 $t->patch_ok( "//$userid:$password@/api/v1/patrons/"
477 . '/extended_attributes/'
478 . $unique_attribute->id => json => { value => 'HEY' } )
479 ->status_is(200)->tx->res->json;
482 Koha::Patron::Attributes->find( $response->{extended_attribute_id} )
485 "The returned object is on the DB"
488 my $unique_value = 'HEHE';
490 # Add a patron with the unique attribute to test changing to it
491 $builder->build_object( { class => 'Koha::Patrons' } )
492 ->add_extended_attribute(
494 code => $unique_attr_type->code,
495 attribute => $unique_value
499 $t->patch_ok( "//$userid:$password@/api/v1/patrons/"
501 . '/extended_attributes/'
502 . $unique_attribute->id => json => { value => $unique_value } )
504 ->json_is( '/error' =>
505 "Your action breaks a unique constraint on the attribute. type="
506 . $unique_attr_type->code
507 . " value=$unique_value" );
509 $schema->storage->txn_rollback;