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