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