Bug 24430: Unit tests
[koha.git] / t / db_dependent / Koha / Biblio.t
1 #!/usr/bin/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 => 11;
21
22 use C4::Biblio;
23 use Koha::Database;
24 use Koha::Acquisition::Orders;
25
26 use t::lib::TestBuilder;
27 use t::lib::Mocks;
28
29 BEGIN {
30     use_ok('Koha::Biblio');
31     use_ok('Koha::Biblios');
32 }
33
34 my $schema  = Koha::Database->new->schema;
35 my $builder = t::lib::TestBuilder->new;
36
37 subtest 'metadata() tests' => sub {
38
39     plan tests => 4;
40
41     $schema->storage->txn_begin;
42
43     my $title = 'Oranges and Peaches';
44
45     my $record = MARC::Record->new();
46     my $field = MARC::Field->new('245','','','a' => $title);
47     $record->append_fields( $field );
48     my ($biblionumber) = C4::Biblio::AddBiblio($record, '');
49
50     my $biblio = Koha::Biblios->find( $biblionumber );
51     is( ref $biblio, 'Koha::Biblio', 'Found a Koha::Biblio object' );
52
53     my $metadata = $biblio->metadata;
54     is( ref $metadata, 'Koha::Biblio::Metadata', 'Method metadata() returned a Koha::Biblio::Metadata object' );
55
56     my $record2 = $metadata->record;
57     is( ref $record2, 'MARC::Record', 'Method record() returned a MARC::Record object' );
58
59     is( $record2->field('245')->subfield("a"), $title, 'Title in 245$a matches title from original record object' );
60
61     $schema->storage->txn_rollback;
62 };
63
64 subtest 'hidden_in_opac() tests' => sub {
65
66     plan tests => 4;
67
68     $schema->storage->txn_begin;
69
70     my $biblio = $builder->build_sample_biblio();
71
72     ok( !$biblio->hidden_in_opac({ rules => { withdrawn => [ 2 ] } }), 'Biblio not hidden if there is no item attached' );
73
74     my $item_1 = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
75     my $item_2 = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
76
77     $item_1->withdrawn( 1 )->store->discard_changes;
78     $item_2->withdrawn( 1 )->store->discard_changes;
79
80     ok( !$biblio->hidden_in_opac({ rules => { withdrawn => [ 2 ] } }), 'Biblio not hidden' );
81
82     $item_2->withdrawn( 2 )->store->discard_changes;
83     $biblio->discard_changes; # refresh
84
85     ok( !$biblio->hidden_in_opac({ rules => { withdrawn => [ 2 ] } }), 'Biblio not hidden' );
86
87     $item_1->withdrawn( 2 )->store->discard_changes;
88     $biblio->discard_changes; # refresh
89
90     ok( $biblio->hidden_in_opac({ rules => { withdrawn => [ 2 ] } }), 'Biblio hidden' );
91
92     $schema->storage->txn_rollback;
93 };
94
95 subtest 'items() tests' => sub {
96
97     plan tests => 3;
98
99     $schema->storage->txn_begin;
100
101     my $biblio = $builder->build_sample_biblio();
102     my $item_1 = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
103     my $item_2 = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
104
105     my $items = $biblio->items;
106     is( ref($items), 'Koha::Items', 'Returns a Koha::Items resultset' );
107     is( $items->count, 2, 'Two items in resultset' );
108
109     my @items = $biblio->items->as_list;
110     is( scalar @items, 2, 'Same result, but in list context' );
111
112     $schema->storage->txn_rollback;
113
114 };
115
116 subtest 'get_coins and get_openurl' => sub {
117
118     plan tests => 3;
119
120     $schema->storage->txn_begin;
121
122     my $builder = t::lib::TestBuilder->new;
123     my $biblio = $builder->build_sample_biblio({
124             title => 'Title 1',
125             author => 'Author 1'
126         });
127
128     is(
129         $biblio->get_coins,
130         'ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=book&amp;rft.btitle=Title%201&amp;rft.au=Author%201',
131         'GetCOinsBiblio returned right metadata'
132     );
133
134     t::lib::Mocks::mock_preference("OpenURLResolverURL", "https://koha.example.com/");
135     is(
136         $biblio->get_openurl,
137         'https://koha.example.com/?ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=book&amp;rft.btitle=Title%201&amp;rft.au=Author%201',
138         'Koha::Biblio->get_openurl returned right URL'
139     );
140
141     t::lib::Mocks::mock_preference("OpenURLResolverURL", "https://koha.example.com/?client_id=ci1");
142     is(
143         $biblio->get_openurl,
144         'https://koha.example.com/?client_id=ci1&amp;ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=book&amp;rft.btitle=Title%201&amp;rft.au=Author%201',
145         'Koha::Biblio->get_openurl returned right URL'
146     );
147
148     $schema->storage->txn_rollback;
149 };
150
151 subtest 'is_serial() tests' => sub {
152
153     plan tests => 3;
154
155     $schema->storage->txn_begin;
156
157     my $biblio = $builder->build_sample_biblio();
158
159     $biblio->serial( 1 )->store->discard_changes;
160     ok( $biblio->is_serial, 'Bibliographic record is serial' );
161
162     $biblio->serial( 0 )->store->discard_changes;
163     ok( !$biblio->is_serial, 'Bibliographic record is not serial' );
164
165     my $record = $biblio->metadata->record;
166     $record->leader('00142nas a22     7a 4500');
167     ModBiblio($record, $biblio->biblionumber );
168     $biblio = Koha::Biblios->find($biblio->biblionumber);
169
170     ok( $biblio->is_serial, 'Bibliographic record is serial' );
171
172     $schema->storage->txn_rollback;
173 };
174
175 subtest 'pickup_locations' => sub {
176     plan tests => 29;
177
178     $schema->storage->txn_begin;
179
180     my $dbh = C4::Context->dbh;
181
182     # Cleanup database
183     Koha::Holds->search->delete;
184     Koha::Patrons->search->delete;
185     Koha::Items->search->delete;
186     Koha::Libraries->search->delete;
187     $dbh->do('DELETE FROM issues');
188     $dbh->do('DELETE FROM issuingrules');
189     $dbh->do(
190         q{INSERT INTO issuingrules (categorycode, branchcode, itemtype, reservesallowed)
191         VALUES (?, ?, ?, ?)},
192         {},
193         '*', '*', '*', 25
194     );
195     $dbh->do('DELETE FROM circulation_rules');
196
197     my $root1 = $builder->build_object( { class => 'Koha::Library::Groups', value => { ft_local_hold_group => 1 } } );
198     my $root2 = $builder->build_object( { class => 'Koha::Library::Groups', value => { ft_local_hold_group => 1 } } );
199     my $root3 = $builder->build_object( { class => 'Koha::Library::Groups', value => { ft_local_hold_group => 1 } } );
200
201     my $library1 = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 1 } } );
202     my $library2 = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 1 } } );
203     my $library3 = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 0 } } );
204     my $library4 = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 1 } } );
205     my $library5 = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 1 } } );
206     my $library6 = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 1 } } );
207     my $library7 = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 1 } } );
208     my $library8 = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 0 } } );
209
210     Koha::CirculationRules->set_rules(
211         {
212             branchcode => $library1->branchcode,
213             itemtype   => undef,
214             categorycode => undef,
215             rules => {
216                 holdallowed => 1,
217                 hold_fulfillment_policy => 'any',
218                 returnbranch => 'any'
219             }
220         }
221     );
222
223     Koha::CirculationRules->set_rules(
224         {
225             branchcode => $library2->branchcode,
226             itemtype   => undef,
227             categorycode => undef,
228             rules => {
229                 holdallowed => 3,
230                 hold_fulfillment_policy => 'holdgroup',
231                 returnbranch => 'any'
232             }
233         }
234     );
235
236     Koha::CirculationRules->set_rules(
237         {
238             branchcode => $library3->branchcode,
239             itemtype   => undef,
240             categorycode => undef,
241             rules => {
242                 holdallowed => 3,
243                 hold_fulfillment_policy => 'patrongroup',
244                 returnbranch => 'any'
245             }
246         }
247     );
248
249     Koha::CirculationRules->set_rules(
250         {
251             branchcode => $library4->branchcode,
252             itemtype   => undef,
253             categorycode => undef,
254             rules => {
255                 holdallowed => 2,
256                 hold_fulfillment_policy => 'holdingbranch',
257                 returnbranch => 'any'
258             }
259         }
260     );
261
262     Koha::CirculationRules->set_rules(
263         {
264             branchcode => $library5->branchcode,
265             itemtype   => undef,
266             categorycode => undef,
267             rules => {
268                 holdallowed => 2,
269                 hold_fulfillment_policy => 'homebranch',
270                 returnbranch => 'any'
271             }
272         }
273     );
274
275     Koha::CirculationRules->set_rules(
276         {
277             branchcode => $library6->branchcode,
278             itemtype   => undef,
279             categorycode => undef,
280             rules => {
281                 holdallowed => 1,
282                 hold_fulfillment_policy => 'holdgroup',
283                 returnbranch => 'any'
284             }
285         }
286     );
287
288     Koha::CirculationRules->set_rules(
289         {
290             branchcode => $library7->branchcode,
291             itemtype   => undef,
292             categorycode => undef,
293             rules => {
294                 holdallowed => 3,
295                 hold_fulfillment_policy => 'holdingbranch',
296                 returnbranch => 'any'
297             }
298         }
299     );
300
301
302     Koha::CirculationRules->set_rules(
303         {
304             branchcode => $library8->branchcode,
305             itemtype   => undef,
306             categorycode => undef,
307             rules => {
308                 holdallowed => 2,
309                 hold_fulfillment_policy => 'patrongroup',
310                 returnbranch => 'any'
311             }
312         }
313     );
314
315     my $group1_1 = $builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root1->id, branchcode => $library1->branchcode } } );
316     my $group1_2 = $builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root1->id, branchcode => $library2->branchcode } } );
317
318     my $group2_3 = $builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root2->id, branchcode => $library3->branchcode } } );
319     my $group2_4 = $builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root2->id, branchcode => $library4->branchcode } } );
320
321     my $group3_5 = $builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root3->id, branchcode => $library5->branchcode } } );
322     my $group3_6 = $builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root3->id, branchcode => $library6->branchcode } } );
323     my $group3_7 = $builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root3->id, branchcode => $library7->branchcode } } );
324     my $group3_8 = $builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root3->id, branchcode => $library8->branchcode } } );
325
326     my $biblio1  = $builder->build_object( { class => 'Koha::Biblios', value => {title => '1'} } );
327     my $biblioitem1 = $builder->build_object( { class => 'Koha::Biblioitems', value => { biblionumber => $biblio1->biblionumber } } );
328     my $biblio2  = $builder->build_object( { class => 'Koha::Biblios', value => {title => '2'} } );
329     my $biblioitem2 = $builder->build_object( { class => 'Koha::Biblioitems', value => { biblionumber => $biblio2->biblionumber } } );
330
331     my $item1_1  = Koha::Item->new({
332         biblionumber     => $biblio1->biblionumber,
333         biblioitemnumber => $biblioitem1->biblioitemnumber,
334         homebranch       => $library1->branchcode,
335         holdingbranch    => $library2->branchcode,
336         itype            => 'test',
337         barcode          => "item11barcode",
338     })->store;
339
340     my $item1_3  = Koha::Item->new({
341         biblionumber     => $biblio1->biblionumber,
342         biblioitemnumber => $biblioitem1->biblioitemnumber,
343         homebranch       => $library3->branchcode,
344         holdingbranch    => $library4->branchcode,
345         itype            => 'test',
346         barcode          => "item13barcode",
347     })->store;
348
349     my $item1_7  = Koha::Item->new({
350         biblionumber     => $biblio1->biblionumber,
351         biblioitemnumber => $biblioitem1->biblioitemnumber,
352         homebranch       => $library7->branchcode,
353         holdingbranch    => $library4->branchcode,
354         itype            => 'test',
355         barcode          => "item17barcode",
356     })->store;
357
358     my $item2_2  = Koha::Item->new({
359         biblionumber     => $biblio2->biblionumber,
360         biblioitemnumber => $biblioitem2->biblioitemnumber,
361         homebranch       => $library2->branchcode,
362         holdingbranch    => $library1->branchcode,
363         itype            => 'test',
364         barcode          => "item22barcode",
365     })->store;
366
367     my $item2_4  = Koha::Item->new({
368         biblionumber     => $biblio2->biblionumber,
369         biblioitemnumber => $biblioitem2->biblioitemnumber,
370         homebranch       => $library4->branchcode,
371         holdingbranch    => $library3->branchcode,
372         itype            => 'test',
373         barcode          => "item23barcode",
374     })->store;
375
376     my $item2_6  = Koha::Item->new({
377         biblionumber     => $biblio2->biblionumber,
378         biblioitemnumber => $biblioitem2->biblioitemnumber,
379         homebranch       => $library6->branchcode,
380         holdingbranch    => $library4->branchcode,
381         itype            => 'test',
382         barcode          => "item26barcode",
383     })->store;
384
385     my $patron1 = $builder->build_object( { class => 'Koha::Patrons', value => { firstname=>'1', branchcode => $library1->branchcode } } );
386     my $patron8 = $builder->build_object( { class => 'Koha::Patrons', value => { firstname=>'8', branchcode => $library8->branchcode } } );
387
388     my $results = {
389         "ItemHomeLibrary-1-1" => 6,
390         "ItemHomeLibrary-1-8" => 1,
391         "ItemHomeLibrary-2-1" => 2,
392         "ItemHomeLibrary-2-8" => 0,
393         "PatronLibrary-1-1" => 6,
394         "PatronLibrary-1-8" => 3,
395         "PatronLibrary-2-1" => 0,
396         "PatronLibrary-2-8" => 3,
397     };
398
399     sub _doTest {
400         my ( $cbranch, $biblio, $patron, $results ) = @_;
401         t::lib::Mocks::mock_preference('ReservesControlBranch', $cbranch);
402
403         my @pl = $biblio->pickup_locations( { patron => $patron} );
404
405         foreach my $pickup_location (@pl) {
406             is( ref($pickup_location), 'Koha::Library', 'Object type is correct' );
407         }
408
409         ok(
410             scalar(@pl) == $results->{ $cbranch . '-'
411                   . $biblio->title . '-'
412                   . $patron->firstname },
413             'ReservesControlBranch: '
414               . $cbranch
415               . ', biblio'
416               . $biblio->title
417               . ', patron'
418               . $patron->firstname
419               . ' should return '
420               . $results->{ $cbranch . '-'
421                   . $biblio->title . '-'
422                   . $patron->firstname }
423               . ' but returns '
424               . scalar(@pl)
425         );
426     }
427
428     foreach my $cbranch ('ItemHomeLibrary','PatronLibrary') {
429         foreach my $biblio ($biblio1, $biblio2) {
430             foreach my $patron ($patron1, $patron8) {
431                 _doTest($cbranch, $biblio, $patron, $results);
432             }
433         }
434     }
435
436     $schema->storage->txn_rollback;
437 };
438
439 subtest 'to_api() tests' => sub {
440
441     $schema->storage->txn_begin;
442
443     my $biblio = $builder->build_sample_biblio();
444     my $item = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
445
446     my $biblioitem_api = $biblio->biblioitem->to_api;
447     my $biblio_api     = $biblio->to_api;
448
449     plan tests => (scalar keys %{ $biblioitem_api }) + 1;
450
451     foreach my $key ( keys %{ $biblioitem_api } ) {
452         is( $biblio_api->{$key}, $biblioitem_api->{$key}, "$key is added to the biblio object" );
453     }
454
455     $biblio_api = $biblio->to_api({ embed => { items => {} } });
456     is_deeply( $biblio_api->{items}, [ $item->to_api ], 'Item correctly embedded' );
457
458     $schema->storage->txn_rollback;
459 };
460
461 subtest 'suggestions() tests' => sub {
462
463     plan tests => 3;
464
465     $schema->storage->txn_begin;
466
467     my $biblio     = $builder->build_sample_biblio();
468
469     is( ref($biblio->suggestions), 'Koha::Suggestions', 'Return type is correct' );
470
471     is_deeply(
472         $biblio->suggestions->unblessed,
473         [],
474         '->suggestions returns an empty Koha::Suggestions resultset'
475     );
476
477     my $suggestion = $builder->build_object(
478         {
479             class => 'Koha::Suggestions',
480             value => { biblionumber => $biblio->biblionumber }
481         }
482     );
483
484     my $suggestions = $biblio->suggestions->unblessed;
485
486     is_deeply(
487         $biblio->suggestions->unblessed,
488         [ $suggestion->unblessed ],
489         '->suggestions returns the related Koha::Suggestion objects'
490     );
491
492     $schema->storage->txn_rollback;
493 };
494
495 subtest 'orders() and active_orders_count() tests' => sub {
496
497     plan tests => 4;
498
499     $schema->storage->txn_begin;
500
501     my $biblio = $builder->build_sample_biblio();
502
503     my $orders = $biblio->orders;
504     my $active_orders_count = $biblio->active_orders_count;
505
506     is( ref($orders), 'Koha::Acquisition::Orders', 'Result type is correct' );
507     is( $orders->count, $active_orders_count, '->orders_count returns the count for the resultset' );
508
509     # Add a couple orders
510     foreach (1..2) {
511         $builder->build_object(
512             {
513                 class => 'Koha::Acquisition::Orders',
514                 value => {
515                     biblionumber => $biblio->biblionumber,
516                     datecancellationprinted => '2019-12-31'
517                 }
518             }
519         );
520     }
521
522     $builder->build_object(
523         {
524             class => 'Koha::Acquisition::Orders',
525             value => {
526                 biblionumber => $biblio->biblionumber,
527                 datecancellationprinted => undef
528             }
529         }
530     );
531
532     $orders = $biblio->orders;
533     $active_orders_count = $biblio->active_orders_count;
534
535     is( ref($orders), 'Koha::Acquisition::Orders', 'Result type is correct' );
536     is( $orders->count, $active_orders_count + 2, '->active_orders_count returns the rigt count' );
537
538     $schema->storage->txn_rollback;
539 };