Bug 11175: Add 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 => 18;
21 use Test::Warn;
22
23 use C4::Biblio qw( AddBiblio ModBiblio ModBiblioMarc );
24 use Koha::Database;
25 use Koha::Caches;
26 use Koha::Acquisition::Orders;
27 use Koha::AuthorisedValueCategories;
28 use Koha::AuthorisedValues;
29 use Koha::MarcSubfieldStructures;
30 use Koha::Exceptions::Exception;
31
32 use MARC::Field;
33 use MARC::Record;
34
35 use t::lib::TestBuilder;
36 use t::lib::Mocks;
37 use Test::MockModule;
38
39 BEGIN {
40     use_ok('Koha::Biblio');
41     use_ok('Koha::Biblios');
42 }
43
44 my $schema  = Koha::Database->new->schema;
45 my $builder = t::lib::TestBuilder->new;
46
47 subtest 'metadata() tests' => sub {
48
49     plan tests => 4;
50
51     $schema->storage->txn_begin;
52
53     my $title = 'Oranges and Peaches';
54
55     my $record = MARC::Record->new();
56     my $field = MARC::Field->new('245','','','a' => $title);
57     $record->append_fields( $field );
58     my ($biblionumber) = C4::Biblio::AddBiblio($record, '');
59
60     my $biblio = Koha::Biblios->find( $biblionumber );
61     is( ref $biblio, 'Koha::Biblio', 'Found a Koha::Biblio object' );
62
63     my $metadata = $biblio->metadata;
64     is( ref $metadata, 'Koha::Biblio::Metadata', 'Method metadata() returned a Koha::Biblio::Metadata object' );
65
66     my $record2 = $metadata->record;
67     is( ref $record2, 'MARC::Record', 'Method record() returned a MARC::Record object' );
68
69     is( $record2->field('245')->subfield("a"), $title, 'Title in 245$a matches title from original record object' );
70
71     $schema->storage->txn_rollback;
72 };
73
74 subtest 'hidden_in_opac() tests' => sub {
75
76     plan tests => 6;
77
78     $schema->storage->txn_begin;
79
80     my $biblio = $builder->build_sample_biblio();
81     my $rules  = { withdrawn => [ 2 ] };
82
83     t::lib::Mocks::mock_preference( 'OpacHiddenItemsHidesRecord', 0 );
84
85     ok(
86         !$biblio->hidden_in_opac({ rules => $rules }),
87         'Biblio not hidden if there is no item attached (!OpacHiddenItemsHidesRecord)'
88     );
89
90     t::lib::Mocks::mock_preference( 'OpacHiddenItemsHidesRecord', 1 );
91
92     ok(
93         !$biblio->hidden_in_opac({ rules => $rules }),
94         'Biblio not hidden if there is no item attached (OpacHiddenItemsHidesRecord)'
95     );
96
97     my $item_1 = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
98     my $item_2 = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
99
100     $item_1->withdrawn( 1 )->store->discard_changes;
101     $item_2->withdrawn( 1 )->store->discard_changes;
102
103     ok( !$biblio->hidden_in_opac({ rules => $rules }), 'Biblio not hidden' );
104
105     $item_2->withdrawn( 2 )->store->discard_changes;
106     $biblio->discard_changes; # refresh
107
108     ok( !$biblio->hidden_in_opac({ rules => $rules }), 'Biblio not hidden' );
109
110     $item_1->withdrawn( 2 )->store->discard_changes;
111     $biblio->discard_changes; # refresh
112
113     ok( $biblio->hidden_in_opac({ rules => $rules }), 'Biblio hidden' );
114
115     t::lib::Mocks::mock_preference( 'OpacHiddenItemsHidesRecord', 0 );
116     ok(
117         !$biblio->hidden_in_opac( { rules => $rules } ),
118         'Biblio hidden (!OpacHiddenItemsHidesRecord)'
119     );
120
121
122     $schema->storage->txn_rollback;
123 };
124
125 subtest 'items() tests' => sub {
126
127     plan tests => 4;
128
129     $schema->storage->txn_begin;
130
131     my $biblio = $builder->build_sample_biblio();
132
133     is( $biblio->items->count, 0, 'No items, count is 0' );
134
135     my $item_1 = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
136     my $item_2 = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
137
138     my $items = $biblio->items;
139     is( ref($items), 'Koha::Items', 'Returns a Koha::Items resultset' );
140     is( $items->count, 2, 'Two items in resultset' );
141
142     my @items = $biblio->items->as_list;
143     is( scalar @items, 2, 'Same result, but in list context' );
144
145     $schema->storage->txn_rollback;
146
147 };
148
149 subtest 'get_coins and get_openurl' => sub {
150
151     plan tests => 4;
152
153     $schema->storage->txn_begin;
154
155     my $builder = t::lib::TestBuilder->new;
156     my $biblio = $builder->build_sample_biblio({
157             title => 'Title 1',
158             author => 'Author 1'
159         });
160     is(
161         $biblio->get_coins,
162         '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',
163         'GetCOinsBiblio returned right metadata'
164     );
165
166     my $record = MARC::Record->new();
167     $record->append_fields( MARC::Field->new('100','','','a' => 'Author 2'), MARC::Field->new('880','','','a' => 'Something') );
168     my ( $biblionumber ) = C4::Biblio::AddBiblio($record, '');
169     my $biblio_no_title = Koha::Biblios->find($biblionumber);
170     is(
171         $biblio_no_title->get_coins,
172         'ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Abook&amp;rft.genre=book&amp;rft.au=Author%202',
173         'GetCOinsBiblio returned right metadata if biblio does not have a title'
174     );
175
176     t::lib::Mocks::mock_preference("OpenURLResolverURL", "https://koha.example.com/");
177     is(
178         $biblio->get_openurl,
179         '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',
180         'Koha::Biblio->get_openurl returned right URL'
181     );
182
183     t::lib::Mocks::mock_preference("OpenURLResolverURL", "https://koha.example.com/?client_id=ci1");
184     is(
185         $biblio->get_openurl,
186         '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',
187         'Koha::Biblio->get_openurl returned right URL'
188     );
189
190     $schema->storage->txn_rollback;
191 };
192
193 subtest 'is_serial() tests' => sub {
194
195     plan tests => 3;
196
197     $schema->storage->txn_begin;
198
199     my $biblio = $builder->build_sample_biblio();
200
201     $biblio->serial( 1 )->store->discard_changes;
202     ok( $biblio->is_serial, 'Bibliographic record is serial' );
203
204     $biblio->serial( 0 )->store->discard_changes;
205     ok( !$biblio->is_serial, 'Bibliographic record is not serial' );
206
207     my $record = $biblio->metadata->record;
208     $record->leader('00142nas a22     7a 4500');
209     ModBiblio($record, $biblio->biblionumber );
210     $biblio = Koha::Biblios->find($biblio->biblionumber);
211
212     ok( $biblio->is_serial, 'Bibliographic record is serial' );
213
214     $schema->storage->txn_rollback;
215 };
216
217 subtest 'pickup_locations' => sub {
218     plan tests => 9;
219
220     $schema->storage->txn_begin;
221
222     Koha::CirculationRules->search->delete;
223     Koha::CirculationRules->set_rules(
224         {
225             categorycode => undef,
226             itemtype     => undef,
227             branchcode   => undef,
228             rules        => {
229                 reservesallowed => 25,
230             }
231         }
232     );
233
234     my $root1 = $builder->build_object( { class => 'Koha::Library::Groups', value => { ft_local_hold_group => 1 } } );
235     my $root2 = $builder->build_object( { class => 'Koha::Library::Groups', value => { ft_local_hold_group => 1 } } );
236     my $root3 = $builder->build_object( { class => 'Koha::Library::Groups', value => { ft_local_hold_group => 1 } } );
237
238     my $library1 = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 1, branchname => 'zzz' } } );
239     my $library2 = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 1, branchname => 'AAA' } } );
240     my $library3 = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 0, branchname => 'FFF' } } );
241     my $library4 = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 1, branchname => 'CCC' } } );
242     my $library5 = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 1, branchname => 'eee' } } );
243     my $library6 = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 1, branchname => 'BBB' } } );
244     my $library7 = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 1, branchname => 'DDD' } } );
245     my $library8 = $builder->build_object( { class => 'Koha::Libraries', value => { pickup_location => 0, branchname => 'GGG' } } );
246
247     our @branchcodes = map { $_->branchcode } ($library1, $library2, $library3, $library4, $library5, $library6, $library7, $library8);
248
249     Koha::CirculationRules->set_rules(
250         {
251             branchcode => $library1->branchcode,
252             itemtype   => undef,
253             rules => {
254                 holdallowed => 'from_home_library',
255                 hold_fulfillment_policy => 'any',
256                 returnbranch => 'any'
257             }
258         }
259     );
260
261     Koha::CirculationRules->set_rules(
262         {
263             branchcode => $library2->branchcode,
264             itemtype   => undef,
265             rules => {
266                 holdallowed => 'from_local_hold_group',
267                 hold_fulfillment_policy => 'holdgroup',
268                 returnbranch => 'any'
269             }
270         }
271     );
272
273     Koha::CirculationRules->set_rules(
274         {
275             branchcode => $library3->branchcode,
276             itemtype   => undef,
277             rules => {
278                 holdallowed => 'from_local_hold_group',
279                 hold_fulfillment_policy => 'patrongroup',
280                 returnbranch => 'any'
281             }
282         }
283     );
284
285     Koha::CirculationRules->set_rules(
286         {
287             branchcode => $library4->branchcode,
288             itemtype   => undef,
289             rules => {
290                 holdallowed => 'from_any_library',
291                 hold_fulfillment_policy => 'holdingbranch',
292                 returnbranch => 'any'
293             }
294         }
295     );
296
297     Koha::CirculationRules->set_rules(
298         {
299             branchcode => $library5->branchcode,
300             itemtype   => undef,
301             rules => {
302                 holdallowed => 'from_any_library',
303                 hold_fulfillment_policy => 'homebranch',
304                 returnbranch => 'any'
305             }
306         }
307     );
308
309     Koha::CirculationRules->set_rules(
310         {
311             branchcode => $library6->branchcode,
312             itemtype   => undef,
313             rules => {
314                 holdallowed => 'from_home_library',
315                 hold_fulfillment_policy => 'holdgroup',
316                 returnbranch => 'any'
317             }
318         }
319     );
320
321     Koha::CirculationRules->set_rules(
322         {
323             branchcode => $library7->branchcode,
324             itemtype   => undef,
325             rules => {
326                 holdallowed => 'from_local_hold_group',
327                 hold_fulfillment_policy => 'holdingbranch',
328                 returnbranch => 'any'
329             }
330         }
331     );
332
333
334     Koha::CirculationRules->set_rules(
335         {
336             branchcode => $library8->branchcode,
337             itemtype   => undef,
338             rules => {
339                 holdallowed => 'from_any_library',
340                 hold_fulfillment_policy => 'patrongroup',
341                 returnbranch => 'any'
342             }
343         }
344     );
345
346     my $group1_1 = $builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root1->id, branchcode => $library1->branchcode } } );
347     my $group1_2 = $builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root1->id, branchcode => $library2->branchcode } } );
348
349     my $group2_3 = $builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root2->id, branchcode => $library3->branchcode } } );
350     my $group2_4 = $builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root2->id, branchcode => $library4->branchcode } } );
351
352     my $group3_5 = $builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root3->id, branchcode => $library5->branchcode } } );
353     my $group3_6 = $builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root3->id, branchcode => $library6->branchcode } } );
354     my $group3_7 = $builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root3->id, branchcode => $library7->branchcode } } );
355     my $group3_8 = $builder->build_object( { class => 'Koha::Library::Groups', value => { parent_id => $root3->id, branchcode => $library8->branchcode } } );
356
357     my $biblio1  = $builder->build_sample_biblio({ title => '1' });
358     my $biblio2  = $builder->build_sample_biblio({ title => '2' });
359
360     my $item1_1  = $builder->build_sample_item({
361         biblionumber     => $biblio1->biblionumber,
362         homebranch       => $library1->branchcode,
363         holdingbranch    => $library2->branchcode,
364     })->store;
365
366     my $item1_3  = $builder->build_sample_item({
367         biblionumber     => $biblio1->biblionumber,
368         homebranch       => $library3->branchcode,
369         holdingbranch    => $library4->branchcode,
370     })->store;
371
372     my $item1_7  = $builder->build_sample_item({
373         biblionumber     => $biblio1->biblionumber,
374         homebranch       => $library7->branchcode,
375         holdingbranch    => $library4->branchcode,
376     })->store;
377
378     my $item2_2  = $builder->build_sample_item({
379         biblionumber     => $biblio2->biblionumber,
380         homebranch       => $library2->branchcode,
381         holdingbranch    => $library1->branchcode,
382     })->store;
383
384     my $item2_4  = $builder->build_sample_item({
385         biblionumber     => $biblio2->biblionumber,
386         homebranch       => $library4->branchcode,
387         holdingbranch    => $library3->branchcode,
388     })->store;
389
390     my $item2_6  = $builder->build_sample_item({
391         biblionumber     => $biblio2->biblionumber,
392         homebranch       => $library6->branchcode,
393         holdingbranch    => $library4->branchcode,
394     })->store;
395
396     my $patron1 = $builder->build_object( { class => 'Koha::Patrons', value => { firstname=>'1', branchcode => $library1->branchcode } } );
397     my $patron8 = $builder->build_object( { class => 'Koha::Patrons', value => { firstname=>'8', branchcode => $library8->branchcode } } );
398
399     my $results = {
400         "ItemHomeLibrary-1-1" => 6,
401         "ItemHomeLibrary-1-8" => 1,
402         "ItemHomeLibrary-2-1" => 2,
403         "ItemHomeLibrary-2-8" => 0,
404         "PatronLibrary-1-1" => 6,
405         "PatronLibrary-1-8" => 3,
406         "PatronLibrary-2-1" => 0,
407         "PatronLibrary-2-8" => 3,
408     };
409
410     sub _doTest {
411         my ( $cbranch, $biblio, $patron, $results ) = @_;
412         t::lib::Mocks::mock_preference('ReservesControlBranch', $cbranch);
413
414         my @pl = map {
415             my $pickup_location = $_;
416             grep { $pickup_location->branchcode eq $_ } @branchcodes
417         } $biblio->pickup_locations( { patron => $patron } )->as_list;
418
419         ok(
420             scalar(@pl) == $results->{ $cbranch . '-'
421                   . $biblio->title . '-'
422                   . $patron->firstname },
423             'ReservesControlBranch: '
424               . $cbranch
425               . ', biblio'
426               . $biblio->title
427               . ', patron'
428               . $patron->firstname
429               . ' should return '
430               . $results->{ $cbranch . '-'
431                   . $biblio->title . '-'
432                   . $patron->firstname }
433               . ' but returns '
434               . scalar(@pl)
435         );
436     }
437
438     foreach my $cbranch ('ItemHomeLibrary','PatronLibrary') {
439         foreach my $biblio ($biblio1, $biblio2) {
440             foreach my $patron ($patron1, $patron8) {
441                 _doTest($cbranch, $biblio, $patron, $results);
442             }
443         }
444     }
445
446     my @pl_names = map { $_->branchname } $biblio1->pickup_locations( { patron => $patron1 } )->as_list;
447     my $pl_ori_str = join('|', @pl_names);
448     my $pl_sorted_str = join('|', sort { lc($a) cmp lc($b) } @pl_names);
449     ok(
450         $pl_ori_str eq $pl_sorted_str,
451         'Libraries must be sorted by name'
452     );
453     $schema->storage->txn_rollback;
454 };
455
456 subtest 'to_api() tests' => sub {
457
458     $schema->storage->txn_begin;
459
460     my $biblio = $builder->build_sample_biblio();
461     my $item = $builder->build_sample_item({ biblionumber => $biblio->biblionumber });
462
463     my $biblioitem_api = $biblio->biblioitem->to_api;
464     my $biblio_api     = $biblio->to_api;
465
466     plan tests => (scalar keys %{ $biblioitem_api }) + 1;
467
468     foreach my $key ( keys %{ $biblioitem_api } ) {
469         is( $biblio_api->{$key}, $biblioitem_api->{$key}, "$key is added to the biblio object" );
470     }
471
472     $biblio_api = $biblio->to_api({ embed => { items => {} } });
473     is_deeply( $biblio_api->{items}, [ $item->to_api ], 'Item correctly embedded' );
474
475     $schema->storage->txn_rollback;
476 };
477
478 subtest 'suggestions() tests' => sub {
479
480     plan tests => 3;
481
482     $schema->storage->txn_begin;
483
484     my $biblio     = $builder->build_sample_biblio();
485
486     is( ref($biblio->suggestions), 'Koha::Suggestions', 'Return type is correct' );
487
488     is_deeply(
489         $biblio->suggestions->unblessed,
490         [],
491         '->suggestions returns an empty Koha::Suggestions resultset'
492     );
493
494     my $suggestion = $builder->build_object(
495         {
496             class => 'Koha::Suggestions',
497             value => { biblionumber => $biblio->biblionumber }
498         }
499     );
500
501     my $suggestions = $biblio->suggestions->unblessed;
502
503     is_deeply(
504         $biblio->suggestions->unblessed,
505         [ $suggestion->unblessed ],
506         '->suggestions returns the related Koha::Suggestion objects'
507     );
508
509     $schema->storage->txn_rollback;
510 };
511
512 subtest 'get_marc_components() tests' => sub {
513
514     plan tests => 5;
515
516     $schema->storage->txn_begin;
517
518     my ($host_bibnum) = C4::Biblio::AddBiblio(host_record(), '');
519     my $host_biblio = Koha::Biblios->find($host_bibnum);
520     t::lib::Mocks::mock_preference( 'SearchEngine', 'Zebra' );
521     my $search_mod = Test::MockModule->new( 'Koha::SearchEngine::Zebra::Search' );
522     $search_mod->mock( 'simple_search_compat', \&search_component_record2 );
523
524     my $components = $host_biblio->get_marc_components;
525     is( ref($components), 'ARRAY', 'Return type is correct' );
526
527     is_deeply(
528         $components,
529         [],
530         '->get_marc_components returns an empty ARRAY'
531     );
532
533     $search_mod->unmock( 'simple_search_compat');
534     $search_mod->mock( 'simple_search_compat', \&search_component_record1 );
535     my $component_record = component_record1()->as_xml();
536
537     is_deeply(
538         $host_biblio->get_marc_components,
539         [$component_record],
540         '->get_marc_components returns the related component part record'
541     );
542     $search_mod->unmock( 'simple_search_compat');
543
544     $search_mod->mock( 'simple_search_compat',
545         sub { Koha::Exceptions::Exception->throw("error searching analytics") }
546     );
547     warning_like { $components = $host_biblio->get_marc_components }
548         qr{^Warning from simple_search_compat: 'error searching analytics'};
549
550     is_deeply(
551         $host_biblio->messages,
552         [
553             {
554                 type    => 'error',
555                 message => 'component_search',
556                 payload => "error searching analytics"
557             }
558         ]
559     );
560     $search_mod->unmock( 'simple_search_compat');
561
562     $schema->storage->txn_rollback;
563 };
564
565 subtest 'get_components_query' => sub {
566     plan tests => 3;
567
568     my $biblio = $builder->build_sample_biblio();
569     my $biblionumber = $biblio->biblionumber;
570     my $record = $biblio->metadata->record;
571
572     t::lib::Mocks::mock_preference( 'UseControlNumber', '0' );
573     is($biblio->get_components_query, "Host-item:(Some boring read)", "UseControlNumber disabled");
574
575     t::lib::Mocks::mock_preference( 'UseControlNumber', '1' );
576     my $marc_001_field = MARC::Field->new('001', $biblionumber);
577     $record->append_fields($marc_001_field);
578     C4::Biblio::ModBiblio( $record, $biblio->biblionumber );
579     $biblio = Koha::Biblios->find( $biblio->biblionumber);
580
581     is($biblio->get_components_query, "(rcn:$biblionumber AND (bib-level:a OR bib-level:b))", "UseControlNumber enabled without MarcOrgCode");
582
583     my $marc_003_field = MARC::Field->new('003', 'OSt');
584     $record->append_fields($marc_003_field);
585     C4::Biblio::ModBiblio( $record, $biblio->biblionumber );
586     $biblio = Koha::Biblios->find( $biblio->biblionumber);
587
588     is($biblio->get_components_query, "(((rcn:$biblionumber AND cni:OSt) OR rcn:\"OSt $biblionumber\") AND (bib-level:a OR bib-level:b))", "UseControlNumber enabled with MarcOrgCode");
589 };
590
591 subtest 'orders() and active_orders() tests' => sub {
592
593     plan tests => 5;
594
595     $schema->storage->txn_begin;
596
597     my $biblio = $builder->build_sample_biblio();
598
599     my $orders        = $biblio->orders;
600     my $active_orders = $biblio->active_orders;
601
602     is( ref($orders), 'Koha::Acquisition::Orders', 'Result type is correct' );
603     is( $biblio->orders->count, $biblio->active_orders->count, '->orders->count returns the count for the resultset' );
604
605     # Add a couple orders
606     foreach (1..2) {
607         $builder->build_object(
608             {
609                 class => 'Koha::Acquisition::Orders',
610                 value => {
611                     biblionumber => $biblio->biblionumber,
612                     datecancellationprinted => '2019-12-31'
613                 }
614             }
615         );
616     }
617
618     $builder->build_object(
619         {
620             class => 'Koha::Acquisition::Orders',
621             value => {
622                 biblionumber => $biblio->biblionumber,
623                 datecancellationprinted => undef
624             }
625         }
626     );
627
628     $orders = $biblio->orders;
629     $active_orders = $biblio->active_orders;
630
631     is( ref($orders), 'Koha::Acquisition::Orders', 'Result type is correct' );
632     is( ref($active_orders), 'Koha::Acquisition::Orders', 'Result type is correct' );
633     is( $orders->count, $active_orders->count + 2, '->active_orders->count returns the rigt count' );
634
635     $schema->storage->txn_rollback;
636 };
637
638 subtest 'subscriptions() tests' => sub {
639
640     plan tests => 4;
641
642     $schema->storage->txn_begin;
643
644     my $biblio = $builder->build_sample_biblio;
645
646     my $subscriptions = $biblio->subscriptions;
647     is( ref($subscriptions), 'Koha::Subscriptions',
648         'Koha::Biblio->subscriptions should return a Koha::Subscriptions object'
649     );
650     is( $subscriptions->count, 0, 'Koha::Biblio->subscriptions should return the correct number of subscriptions');
651
652     # Add two subscriptions
653     foreach (1..2) {
654         $builder->build_object(
655             {
656                 class => 'Koha::Subscriptions',
657                 value => { biblionumber => $biblio->biblionumber }
658             }
659         );
660     }
661
662     $subscriptions = $biblio->subscriptions;
663     is( ref($subscriptions), 'Koha::Subscriptions',
664         'Koha::Biblio->subscriptions should return a Koha::Subscriptions object'
665     );
666     is( $subscriptions->count, 2, 'Koha::Biblio->subscriptions should return the correct number of subscriptions');
667
668     $schema->storage->txn_rollback;
669 };
670
671 subtest 'get_marc_notes() MARC21 tests' => sub {
672     plan tests => 13;
673
674     $schema->storage->txn_begin;
675
676     t::lib::Mocks::mock_preference( 'NotesToHide', '520' );
677
678     my $biblio = $builder->build_sample_biblio;
679     my $record = $biblio->metadata->record;
680     $record->append_fields(
681         MARC::Field->new( '500', '', '', a => 'Note1' ),
682         MARC::Field->new( '505', '', '', a => 'Note2', u => 'http://someserver.com' ),
683         MARC::Field->new( '520', '', '', a => 'Note3 skipped' ),
684         MARC::Field->new( '541', '0', '', a => 'Note4 skipped on opac' ),
685         MARC::Field->new( '541', '', '', a => 'Note5' ),
686         MARC::Field->new( '590', '', '', a => 'CODE' ),
687     );
688
689     Koha::AuthorisedValueCategory->new({ category_name => 'TEST' })->store;
690     Koha::AuthorisedValue->new({ category => 'TEST', authorised_value => 'CODE', lib => 'Description should show', lib_opac => 'Description should show OPAC' })->store;
691     my $mss = Koha::MarcSubfieldStructures->find({tagfield => "590", tagsubfield => "a", frameworkcode => $biblio->frameworkcode });
692     $mss->update({ authorised_value => "TEST" });
693
694     my $cache = Koha::Caches->get_instance;
695     $cache->clear_from_cache("MarcStructure-0-");
696     $cache->clear_from_cache("MarcStructure-1-");
697     $cache->clear_from_cache("default_value_for_mod_marc-");
698     $cache->clear_from_cache("MarcSubfieldStructure-");
699
700     C4::Biblio::ModBiblio( $record, $biblio->biblionumber );
701     $biblio = Koha::Biblios->find( $biblio->biblionumber);
702
703     my $notes = $biblio->get_marc_notes({ marcflavour => 'MARC21' });
704     is( $notes->[0]->{marcnote}, 'Note1', 'First note' );
705     is( $notes->[1]->{marcnote}, 'Note2', 'Second note' );
706     is( $notes->[2]->{marcnote}, 'http://someserver.com', 'URL separated' );
707     is( $notes->[3]->{marcnote}, 'Note4 skipped on opac',"Not shows if not opac" );
708     is( $notes->[4]->{marcnote}, 'Note5', 'Fifth note' );
709     is( $notes->[5]->{marcnote}, 'Description should show', 'Authorised value is correctly parsed to show description rather than code' );
710     is( @$notes, 6, 'No more notes' );
711     $notes = $biblio->get_marc_notes({ marcflavour => 'MARC21', opac => 1 });
712     is( $notes->[0]->{marcnote}, 'Note1', 'First note' );
713     is( $notes->[1]->{marcnote}, 'Note2', 'Second note' );
714     is( $notes->[2]->{marcnote}, 'http://someserver.com', 'URL separated' );
715     is( $notes->[3]->{marcnote}, 'Note5', 'Fifth note shows after fourth skipped' );
716     is( $notes->[4]->{marcnote}, 'Description should show OPAC', 'Authorised value is correctly parsed for OPAC to show description rather than code' );
717     is( @$notes, 5, 'No more notes' );
718
719     $cache->clear_from_cache("MarcStructure-0-");
720     $cache->clear_from_cache("MarcStructure-1-");
721     $cache->clear_from_cache("default_value_for_mod_marc-");
722     $cache->clear_from_cache("MarcSubfieldStructure-");
723
724     $schema->storage->txn_rollback;
725 };
726
727 subtest 'get_marc_notes() UNIMARC tests' => sub {
728     plan tests => 3;
729
730     $schema->storage->txn_begin;
731
732     t::lib::Mocks::mock_preference( 'NotesToHide', '310' );
733
734     my $biblio = $builder->build_sample_biblio;
735     my $record = $biblio->metadata->record;
736     $record->append_fields(
737         MARC::Field->new( '300', '', '', a => 'Note1' ),
738         MARC::Field->new( '300', '', '', a => 'Note2' ),
739         MARC::Field->new( '310', '', '', a => 'Note3 skipped' ),
740     );
741     C4::Biblio::ModBiblio( $record, $biblio->biblionumber );
742     $biblio = Koha::Biblios->find( $biblio->biblionumber);
743     my $notes = $biblio->get_marc_notes({ marcflavour => 'UNIMARC' });
744     is( $notes->[0]->{marcnote}, 'Note1', 'First note' );
745     is( $notes->[1]->{marcnote}, 'Note2', 'Second note' );
746     is( @$notes, 2, 'No more notes' );
747
748     $schema->storage->txn_rollback;
749 };
750
751 subtest 'host_items() tests' => sub {
752     plan tests => 6;
753
754     $schema->storage->txn_begin;
755
756     my $biblio = $builder->build_sample_biblio( { frameworkcode => '' } );
757
758     t::lib::Mocks::mock_preference( 'EasyAnalyticalRecords', 1 );
759     my $host_items = $biblio->host_items;
760     is( ref($host_items),   'Koha::Items' );
761     is( $host_items->count, 0 );
762
763     my $item_1 =
764       $builder->build_sample_item( { biblionumber => $biblio->biblionumber } );
765     my $host_item_1 = $builder->build_sample_item;
766     my $host_item_2 = $builder->build_sample_item;
767
768     my $record = $biblio->metadata->record;
769     $record->append_fields(
770         MARC::Field->new(
771             '773', '', '',
772             9 => $host_item_1->itemnumber,
773             9 => $host_item_2->itemnumber
774         ),
775     );
776     C4::Biblio::ModBiblio( $record, $biblio->biblionumber );
777     $biblio = $biblio->get_from_storage;
778     $host_items = $biblio->host_items;
779     is( $host_items->count, 2 );
780     is_deeply( [ $host_items->get_column('itemnumber') ],
781         [ $host_item_1->itemnumber, $host_item_2->itemnumber ] );
782
783     t::lib::Mocks::mock_preference( 'EasyAnalyticalRecords', 0 );
784     $host_items = $biblio->host_items;
785     is( ref($host_items),   'Koha::Items' );
786     is( $host_items->count, 0 );
787
788     $schema->storage->txn_rollback;
789 };
790
791 subtest 'article_requests() tests' => sub {
792
793     plan tests => 3;
794
795     $schema->storage->txn_begin;
796
797     my $item   = $builder->build_sample_item;
798     my $biblio = $item->biblio;
799
800     my $article_requests = $biblio->article_requests;
801     is( ref($article_requests), 'Koha::ArticleRequests',
802         'In scalar context, type is correct' );
803     is( $article_requests->count, 0, 'No article requests' );
804
805     foreach my $i ( 0 .. 3 ) {
806
807         my $patron = $builder->build_object( { class => 'Koha::Patrons' } );
808
809         Koha::ArticleRequest->new(
810             {
811                 borrowernumber => $patron->id,
812                 biblionumber   => $biblio->id,
813                 itemnumber     => $item->id,
814                 title          => $biblio->title,
815             }
816         )->request;
817     }
818
819     $article_requests = $biblio->article_requests;
820     is( $article_requests->count, 4, '4 article requests' );
821
822     $schema->storage->txn_rollback;
823 };
824
825 sub component_record1 {
826     my $marc = MARC::Record->new;
827     $marc->append_fields(
828         MARC::Field->new( '001', '3456' ),
829         MARC::Field->new( '245', '', '', a => 'Some title 1' ),
830         MARC::Field->new( '773', '', '', w => '(FIRST)1234' ),
831     );
832     return $marc;
833 }
834 sub search_component_record1 {
835     my @results = ( component_record1()->as_xml() );
836     return ( undef, \@results, 1 );
837 }
838
839 sub search_component_record2 {
840     my @results;
841     return ( undef, \@results, 0 );
842 }
843
844 sub host_record {
845     my $marc = MARC::Record->new;
846     $marc->append_fields(
847         MARC::Field->new( '001', '1234' ),
848         MARC::Field->new( '003', 'FIRST' ),
849         MARC::Field->new( '245', '', '', a => 'Some title' ),
850     );
851     return $marc;
852 }