Bug 18309: UNIMARC update from IFLA - authority (fr) (SAUTTIT)
[koha.git] / t / SimpleMARC.t
blobd32ac88bf503f14215404dea9b1b44a3ab4ee561
1 use Modern::Perl;
3 use Test::More tests => 11;
5 use_ok("MARC::Field");
6 use_ok("MARC::Record");
7 use_ok("Koha::SimpleMARC");
9 sub new_record {
10     my $record = MARC::Record->new;
11     $record->leader('03174nam a2200445 a 4500');
12     my @fields = (
13         MARC::Field->new(
14             '008', '120829t20132012nyu bk 001 0ceng',
15         ),
16         MARC::Field->new(
17             100, '1', ' ',
18             a => 'Knuth, Donald Ervin',
19             d => '1938',
20         ),
21         MARC::Field->new(
22             245, '1', '4',
23             a => 'The art of computer programming',
24             c => 'Donald E. Knuth.',
25         ),
26         MARC::Field->new(
27             650, ' ', '0',
28             a => 'Computer programming.',
29             9 => '462',
30         ),
31         MARC::Field->new(
32             952, ' ', ' ',
33             p => '3010023917',
34             y => 'BK',
35             c => 'GEN',
36             d => '2001-06-25',
37         ),
38     );
39     $record->append_fields(@fields);
40     return $record;
43 # field_exists
44 subtest 'field_exists' => sub {
45     plan tests => 3;
46     my $record = new_record;
47     is_deeply(
48         field_exists( { record => $record, field => '650', subfield => 'a' } ),
49         [1],
50         '650$a exists'
51     );
52     is_deeply(
53         field_exists( { record => $record, field => '650', subfield => 'b' } ),
54         [],
55         '650$b does not exist'
56     );
58     $record->append_fields(
59         MARC::Field->new(
60             650, ' ', '0',
61             a => 'Computer algorithms.',
62             9 => '463',
63         )
64     );
66     is_deeply(
67         field_exists( { record => $record, field => '650', subfield => 'a' } ),
68         [ 1, 2 ],
69         '650$a exists, field_exists returns the 2 field numbers'
70     );
73 # read_field
74 subtest 'read_field' => sub {
75     plan tests              => 2;
76     subtest 'read subfield' => sub {
77         plan tests => 5;
78         my $record = new_record;
79         $record->append_fields(
80             MARC::Field->new(
81                 650, ' ', '0',
82                 a => 'Computer algorithms.',
83                 9 => '463',
84             )
85         );
87         my @fields_650a =
88           read_field( { record => $record, field => '650', subfield => 'a' } );
89         is_deeply( $fields_650a[0], 'Computer programming.', 'first 650$a' );
90         is_deeply( $fields_650a[1], 'Computer algorithms.',  'second 650$a' );
91         is_deeply(
92             [
93                 read_field(
94                     {
95                         record        => $record,
96                         field         => '650',
97                         subfield      => 'a',
98                         field_numbers => [1]
99                     }
100                 )
101             ],
102             ['Computer programming.'],
103             'first 650$a bis'
104         );
105         is_deeply(
106             [
107                 read_field(
108                     {
109                         record        => $record,
110                         field         => '650',
111                         subfield      => 'a',
112                         field_numbers => [2]
113                     }
114                 )
115             ],
116             ['Computer algorithms.'],
117             'second 650$a bis'
118         );
119         is_deeply(
120             [
121                 read_field(
122                     {
123                         record        => $record,
124                         field         => '650',
125                         subfield      => 'a',
126                         field_numbers => [3]
127                     }
128                 )
129             ],
130             [],
131             'There is no 3 650$a'
132         );
133     };
134     subtest 'read field' => sub {
135         plan tests => 4;
136         my $record = new_record;
137         $record->append_fields(
138             MARC::Field->new(
139                 650, ' ', '0',
140                 a => 'Computer algorithms.',
141                 9 => '463',
142             )
143         );
144         is_deeply(
145             [
146                 read_field(
147                     {
148                         record => $record,
149                         field  => '650'
150                     }
151                 )
152             ],
153             [ 'Computer programming.', '462', 'Computer algorithms.', '463' ],
154             'Get the all subfield values for field 650'
155         );
156         is_deeply(
157             [
158                 read_field(
159                     {
160                         record        => $record,
161                         field         => '650',
162                         field_numbers => [1]
163                     }
164                 )
165             ],
166             [ 'Computer programming.', '462' ],
167             'Get the all subfield values for the first field 650'
168         );
169         is_deeply(
170             [
171                 read_field(
172                     { record => $record, field => '650', field_numbers => [2] }
173                 )
174             ],
175             [ 'Computer algorithms.', '463' ],
176             'Get the all subfield values for the second field 650'
177         );
178         is_deeply(
179             [
180                 read_field(
181                     { record => $record, field => '650', field_numbers => [3] }
182                 )
183             ],
184             [],
185 'Get the all subfield values for the third field 650 which does not exist'
186         );
187     };
190 # update_field
191 subtest 'update_field' => sub {
192     plan tests                => 1;
193     subtest 'update subfield' => sub {
194         plan tests => 5;
195         my $record = new_record;
197         update_field(
198             {
199                 record   => $record,
200                 field    => '952',
201                 subfield => 'p',
202                 values   => ['3010023918']
203             }
204         );
205         is_deeply(
206             [
207                 read_field(
208                     { record => $record, field => '952', subfield => 'p' }
209                 )
210             ],
211             ['3010023918'],
212             'update existing subfield 952$p'
213         );
214         delete_field( { record => $record, field => '952' } );
215         update_field(
216             {
217                 record   => $record,
218                 field    => '952',
219                 subfield => 'p',
220                 values   => ['3010023918']
221             }
222         );
223         update_field(
224             {
225                 record   => $record,
226                 field    => '952',
227                 subfield => 'y',
228                 values   => ['BK']
229             }
230         );
231         is_deeply(
232             [
233                 read_field(
234                     { record => $record, field => '952', subfield => 'p' }
235                 )
236             ],
237             ['3010023918'],
238             'create subfield 952$p'
239         );
240         is_deeply(
241             read_field(
242                 { record => $record, field => '952', subfield => 'y' }
243             ),
244             'BK',
245             'create subfield 952$k on existing 952 field'
246         );
248         $record->append_fields(
249             MARC::Field->new(
250                 952, ' ', ' ',
251                 p => '3010023917',
252                 y => 'BK',
253             ),
254         );
255         update_field(
256             {
257                 record   => $record,
258                 field    => '952',
259                 subfield => 'p',
260                 values   => ['3010023919']
261             }
262         );
263         my @fields_952p =
264           read_field( { record => $record, field => '952', subfield => 'p' } );
265         is_deeply(
266             \@fields_952p,
267             [ '3010023919', '3010023919' ],
268             'update all subfields 952$p with the same value'
269         );
271         update_field(
272             {
273                 record   => $record,
274                 field    => '952',
275                 subfield => 'p',
276                 values   => [ '3010023917', '3010023918' ]
277             }
278         );
279         @fields_952p =
280           read_field( { record => $record, field => '952', subfield => 'p' } );
281         is_deeply(
282             \@fields_952p,
283             [ '3010023917', '3010023918' ],
284             'update all subfields 952$p with the different values'
285         );
286     };
289 # copy_field - subfield
290 subtest 'copy_field' => sub {
291     plan tests              => 2;
292     subtest 'copy subfield' => sub {
293         plan tests => 20;
294         my $record = new_record;
295         $record->append_fields(
296             MARC::Field->new(
297                 650, ' ', '0',
298                 a => 'Computer algorithms.',
299                 9 => '463',
300             )
301         );
302         copy_field(
303             {
304                 record        => $record,
305                 from_field    => '245',
306                 from_subfield => 'a',
307                 to_field      => '246',
308                 to_subfield   => 'a'
309             }
310         );
311         is_deeply(
312             [
313                 read_field(
314                     { record => $record, field => '245', subfield => 'a' }
315                 )
316             ],
317             ['The art of computer programming'],
318             'After copy 245$a still exists'
319         );
320         is_deeply(
321             [
322                 read_field(
323                     { record => $record, field => '246', subfield => 'a' }
324                 )
325             ],
326             ['The art of computer programming'],
327             '246$a is a new field'
328         );
329         delete_field( { record => $record, field => '246' } );
330         is_deeply(
331             field_exists(
332                 { record => $record, field => '246', subfield => 'a' }
333             ),
334             [],
335             '246$a does not exist anymore'
336         );
338         copy_field(
339             {
340                 record        => $record,
341                 from_field    => '650',
342                 from_subfield => 'a',
343                 to_field      => '651',
344                 to_subfield   => 'a'
345             }
346         );
347         my @fields_651a =
348           read_field( { record => $record, field => '651', subfield => 'a' } );
349         is_deeply(
350             \@fields_651a,
351             [ 'Computer programming.', 'Computer algorithms.' ],
352             'Copy multivalued field'
353         );
354         delete_field( { record => $record, field => '651' } );
356         copy_field(
357             {
358                 record        => $record,
359                 from_field    => '650',
360                 from_subfield => 'a',
361                 to_field      => '651',
362                 to_subfield   => 'a',
363                 field_numbers => [1]
364             }
365         );
366         is_deeply(
367             [
368                 read_field(
369                     { record => $record, field => '651', subfield => 'a' }
370                 )
371             ],
372             ['Computer programming.'],
373             'Copy first field 650$a'
374         );
375         delete_field( { record => $record, field => '652' } );
377         copy_field(
378             {
379                 record        => $record,
380                 from_field    => '650',
381                 from_subfield => 'a',
382                 to_field      => '651',
383                 to_subfield   => 'a',
384                 field_numbers => [2]
385             }
386         );
387         is_deeply(
388             [
389                 read_field(
390                     { record => $record, field => '651', subfield => 'a' }
391                 )
392             ],
393             ['Computer programming.', 'Computer algorithms.'],
394             'Copy second field 650$a'
395         );
396         delete_field( { record => $record, field => '651' } );
398         copy_field(
399             {
400                 record        => $record,
401                 from_field    => '650',
402                 from_subfield => 'a',
403                 to_field      => '651',
404                 to_subfield   => 'a',
405                 regex => { search => 'Computer', replace => 'The art of' }
406             }
407         );
408         @fields_651a =
409           read_field( { record => $record, field => '651', subfield => 'a' } );
410         is_deeply(
411             \@fields_651a,
412             [ 'The art of programming.', 'The art of algorithms.' ],
413             'Copy field using regex'
414         );
415         delete_field( { record => $record, field => '651' } );
417         copy_field(
418             {
419                 record        => $record,
420                 from_field    => '650',
421                 from_subfield => 'a',
422                 to_field      => '651',
423                 to_subfield   => 'a',
424                 regex => { search => 'Computer', replace => 'The mistake of' }
425             }
426         );
427         @fields_651a =
428           read_field( { record => $record, field => '651', subfield => 'a' } );
429         is_deeply(
430             \@fields_651a,
431             [ 'The mistake of programming.', 'The mistake of algorithms.' ],
432             'Copy fields using regex on existing fields'
433         );
434         delete_field( { record => $record, field => '651' } );
436         copy_field(
437             {
438                 record        => $record,
439                 from_field    => '650',
440                 from_subfield => 'a',
441                 to_field      => '651',
442                 to_subfield   => 'a',
443                 regex => { search => 'Computer', replace => 'The art of' }
444             }
445         );
446         @fields_651a =
447           read_field( { record => $record, field => '651', subfield => 'a' } );
448         is_deeply(
449             \@fields_651a,
450             [ 'The art of programming.', 'The art of algorithms.', ],
451             'Copy all fields using regex'
452         );
453         delete_field( { record => $record, field => '651' } );
455         copy_field(
456             {
457                 record        => $record,
458                 from_field    => '650',
459                 from_subfield => 'a',
460                 to_field      => '651',
461                 to_subfield   => 'a',
462                 regex => { search => 'Computer', replace => 'The art of' },
463                 field_numbers => [1]
464             }
465         );
466         @fields_651a =
467           read_field( { record => $record, field => '651', subfield => 'a' } );
468         is_deeply(
469             \@fields_651a,
470             [ 'The art of programming.', ],
471             'Copy first field using regex'
472         );
473         delete_field( { record => $record, field => '651' } );
475         # Copy with regex modifiers
476         $record = new_record;
477         $record->append_fields(
478             MARC::Field->new(
479                 650, ' ', '0',
480                 a => 'Computer algorithms.',
481                 9 => '463',
482             )
483         );
484         copy_field(
485             {
486                 record        => $record,
487                 from_field    => '650',
488                 from_subfield => 'a',
489                 to_field      => '652',
490                 to_subfield   => 'a',
491                 regex         => { search => 'o', replace => 'foo' }
492             }
493         );
494         my @fields_652a =
495           read_field( { record => $record, field => '652', subfield => 'a' } );
496         is_deeply(
497             \@fields_652a,
498             [ 'Cfoomputer programming.', 'Cfoomputer algorithms.' ],
499             'Copy field using regex'
500         );
502         copy_field(
503             {
504                 record        => $record,
505                 from_field    => '650',
506                 from_subfield => 'a',
507                 to_field      => '653',
508                 to_subfield   => 'a',
509                 regex => { search => 'o', replace => 'foo', modifiers => 'g' }
510             }
511         );
512         my @fields_653a =
513           read_field( { record => $record, field => '653', subfield => 'a' } );
514         is_deeply(
515             \@fields_653a,
516             [ 'Cfoomputer prfoogramming.', 'Cfoomputer algfoorithms.' ],
517             'Copy field using regex'
518         );
520         copy_field(
521             {
522                 record        => $record,
523                 from_field    => '650',
524                 from_subfield => 'a',
525                 to_field      => '654',
526                 to_subfield   => 'a',
527                 regex => { search => 'O', replace => 'foo', modifiers => 'i' }
528             }
529         );
530         my @fields_654a =
531           read_field( { record => $record, field => '654', subfield => 'a' } );
532         is_deeply(
533             \@fields_654a,
534             [ 'Cfoomputer programming.', 'Cfoomputer algorithms.' ],
535             'Copy field using regex'
536         );
538         copy_field(
539             {
540                 record        => $record,
541                 from_field    => '650',
542                 from_subfield => 'a',
543                 to_field      => '655',
544                 to_subfield   => 'a',
545                 regex => { search => 'O', replace => 'foo', modifiers => 'gi' }
546             }
547         );
548         my @fields_655a =
549           read_field( { record => $record, field => '655', subfield => 'a' } );
550         is_deeply(
551             \@fields_655a,
552             [ 'Cfoomputer prfoogramming.', 'Cfoomputer algfoorithms.' ],
553             'Copy field using regex'
554         );
556         $record = new_record;
557         $record->append_fields(
558             MARC::Field->new(
559                 952, ' ', ' ',
560                 p => '3010023917',
561                 y => 'BK',
562             ),
563         );
565         copy_field(
566             {
567                 record        => $record,
568                 from_field    => '952',
569                 from_subfield => 'd',
570                 to_field      => '952',
571                 to_subfield   => 'd'
572             }
573         );
574         my @fields_952d =
575           read_field( { record => $record, field => '952', subfield => 'd' } );
576         # FIXME We need a new action "duplicate" if we don't want to modify the original field
577         is_deeply(
578             \@fields_952d,
579             [ '2001-06-25', '2001-06-25', '2001-06-25' ],
580             'copy 952$d into others 952 field'
581         );
583         copy_field(
584             {
585                 record        => $record,
586                 from_field    => '111',
587                 from_subfield => '1',
588                 to_field      => '999',
589                 to_subfield   => '9'
590             }
591         );
592         my @fields_9999 =
593           read_field( { record => $record, field => '999', subfield => '9' } );
594         is_deeply( \@fields_9999, [],
595             'copy a nonexistent subfield does not create a new one' );
597         $record = new_record;
598         copy_field(
599             {
600                 record        => $record,
601                 from_field    => 245,
602                 from_subfield => 'a',
603                 to_field      => 245,
604                 to_subfield   => 'a',
605                 regex         => { search => '^', replace => 'BEGIN ' }
606             }
607         );
608         is_deeply(
609             [
610                 read_field(
611                     { record => $record, field => '245', subfield => 'a' }
612                 )
613             ],
614             ['The art of computer programming', 'BEGIN The art of computer programming'],
615             'Update a subfield: add a string at the beginning'
616         );
618         $record = new_record;
619         copy_field(
620             {
621                 record        => $record,
622                 from_field    => 245,
623                 from_subfield => 'a',
624                 to_field      => 245,
625                 to_subfield   => 'a',
626                 regex         => { search => '$', replace => ' END' }
627             }
628         );
629         is_deeply(
630             [
631                 read_field(
632                     { record => $record, field => '245', subfield => 'a' }
633                 )
634             ],
635             ['The art of computer programming', 'The art of computer programming END'],
636             'Update a subfield: add a string at the end'
637         );
639         $record = new_record;
640         copy_field(
641             {
642                 record        => $record,
643                 from_field    => 245,
644                 from_subfield => 'c',
645                 to_field      => 650,
646                 to_subfield   => 'c',
647             }
648         );
650         is_deeply(
651             [
652                 read_field(
653                     { record => $record, field => '650' }
654                 )
655             ],
656             [ 'Computer programming.', '462', 'Donald E. Knuth.' ],
657             'Copy a subfield to an existent field but inexistent subfield'
658         );
660         $record = new_record;
661         copy_field(
662             {
663                 record        => $record,
664                 from_field    => 245,
665                 from_subfield => 'c',
666                 to_field      => 650,
667                 to_subfield   => '9',
668             }
669         );
671         is_deeply(
672             [
673                 read_field(
674                     { record => $record, field => '650' }
675                 )
676             ],
677             [ 'Computer programming.', '462', 'Donald E. Knuth.' ],
678             'Copy a subfield to an existent field / subfield'
679         );
680     };
682     subtest 'copy field' => sub {
683         plan tests => 14;
684         my $record = new_record;
685         $record->append_fields(
686             MARC::Field->new(
687                 952, ' ', ' ',
688                 p => '3010023918',
689                 y => 'CD',
690             ),
691         );
693         #- copy all fields
694         copy_field(
695             { record => $record, from_field => '952', to_field => '953' } );
696         my @fields_952 = read_field( { record => $record, field => '952' } );
697         is_deeply(
698             [
699                 read_field(
700                     { record => $record, field => '952', field_numbers => [1] }
701                 )
702             ],
703             [ '3010023917', 'BK', 'GEN', '2001-06-25' ],
704             "copy all: original first field still exists"
705         );
706         is_deeply(
707             [
708                 read_field(
709                     { record => $record, field => '952', field_numbers => [2] }
710                 )
711             ],
712             [ '3010023918', 'CD' ],
713             "copy all: original second field still exists"
714         );
715         is_deeply(
716             [
717                 read_field(
718                     { record => $record, field => '953', field_numbers => [1] }
719                 )
720             ],
721             [ '3010023917', 'BK', 'GEN', '2001-06-25' ],
722             "copy all: first original fields has been copied"
723         );
724         is_deeply(
725             [
726                 read_field(
727                     { record => $record, field => '953', field_numbers => [2] }
728                 )
729             ],
730             [ '3010023918', 'CD' ],
731             "copy all: second original fields has been copied"
732         );
734         #- copy only the first field
735         copy_field(
736             {
737                 record        => $record,
738                 from_field    => '953',
739                 to_field      => '954',
740                 field_numbers => [1]
741             }
742         );
743         is_deeply(
744             [
745                 read_field(
746                     { record => $record, field => '953', field_numbers => [1] }
747                 )
748             ],
749             [ '3010023917', 'BK', 'GEN', '2001-06-25' ],
750             "copy first: first original fields has been copied"
751         );
752         is_deeply(
753             [
754                 read_field(
755                     { record => $record, field => '953', field_numbers => [2] }
756                 )
757             ],
758             [ '3010023918', 'CD' ],
759             "copy first: second original fields has been copied"
760         );
761         is_deeply(
762             [ read_field( { record => $record, field => '954' } ) ],
763             [ '3010023917', 'BK', 'GEN', '2001-06-25' ],
764             "copy first: only first, first 953 has been copied"
765         );
767         $record = new_record;
768         $record->append_fields(
769             MARC::Field->new(
770                 952, ' ', ' ',
771                 p => '3010023918',
772                 y => 'CD',
773             ),
774         );
776         #- copy all fields and modify values using a regex
777         copy_field(
778             {
779                 record     => $record,
780                 from_field => '952',
781                 to_field   => '953',
782                 regex      => { search => '30100', replace => '42424' }
783             }
784         );
785         is_deeply(
786             [
787                 read_field(
788                     { record => $record, field => '952', field_numbers => [1] }
789                 )
790             ],
791             [ '3010023917', 'BK', 'GEN', '2001-06-25' ],
792             "copy all with regex: original first field still exists"
793         );
794         is_deeply(
795             [
796                 read_field(
797                     { record => $record, field => '952', field_numbers => [2] }
798                 )
799             ],
800             [ '3010023918', 'CD' ],
801             "copy all with regex: original second field still exists"
802         );
803         is_deeply(
804             [
805                 read_field(
806                     { record => $record, field => '953', field_numbers => [1] }
807                 )
808             ],
809             [ '4242423917', 'BK', 'GEN', '2001-06-25' ],
810             "copy all with regex: first original fields has been copied"
811         );
812         is_deeply(
813             [
814                 read_field(
815                     { record => $record, field => '953', field_numbers => [2] }
816                 )
817             ],
818             [ '4242423918', 'CD' ],
819             "copy all with regex: second original fields has been copied"
820         );
821         copy_field(
822             {
823                 record     => $record,
824                 from_field => '111',
825                 to_field   => '999',
826             }
827         );
828         my @fields_9999 =
829           read_field( { record => $record, field => '999', subfield => '9' } );
830         is_deeply( \@fields_9999, [],
831             'copy a nonexistent field does not create a new one' );
833         $record = new_record;
834         copy_field(
835             {
836                 record        => $record,
837                 from_field    => 245,
838                 to_field      => 650,
839             }
840         );
842         is_deeply(
843             [
844                 read_field(
845                     { record => $record, field => '650', field_numbers => [2] }
846                 )
847             ],
848             [ 'The art of computer programming', 'Donald E. Knuth.' ],
849             'Copy a field to existent fields should create a new field'
850         );
851         is_deeply(
852             [
853                 read_field(
854                     { record => $record, field => '650', field_numbers => [1] }
855                 )
856             ],
857             [ 'Computer programming.', '462' ],
858             'Copy a field to existent fields should create a new field, the original one should not have been updated'
859         );
860     };
863 # copy_and_replace_field - subfield
864 subtest 'copy_and_replace_field' => sub {
865     plan tests              => 2;
866     subtest 'copy and replace subfield' => sub {
867         plan tests => 19;
868         my $record = new_record;
869         $record->append_fields(
870             MARC::Field->new(
871                 650, ' ', '0',
872                 a => 'Computer algorithms.',
873                 9 => '463',
874             )
875         );
876         copy_and_replace_field(
877             {
878                 record        => $record,
879                 from_field    => '245',
880                 from_subfield => 'a',
881                 to_field      => '246',
882                 to_subfield   => 'a'
883             }
884         );
885         is_deeply(
886             [
887                 read_field(
888                     { record => $record, field => '245', subfield => 'a' }
889                 )
890             ],
891             ['The art of computer programming'],
892             'Copy and replace should not have modify original subfield 245$a (same as copy)'
893         );
894         is_deeply(
895             [
896                 read_field(
897                     { record => $record, field => '246', subfield => 'a' }
898                 )
899             ],
900             ['The art of computer programming'],
901             'Copy and replace should create a new 246$a (same as copy)'
902         );
904         $record = new_record;
905         $record->append_fields(
906             MARC::Field->new(
907                 650, ' ', '0',
908                 a => 'Computer algorithms.',
909                 9 => '463',
910             )
911         );
912         copy_and_replace_field(
913             {
914                 record        => $record,
915                 from_field    => '650',
916                 from_subfield => 'a',
917                 to_field      => '651',
918                 to_subfield   => 'a'
919             }
920         );
921         my @fields_651a =
922           read_field( { record => $record, field => '651', subfield => 'a' } );
923         is_deeply(
924             \@fields_651a,
925             [ 'Computer programming.', 'Computer algorithms.' ],
926             'Copy and replace multivalued field (same as copy)'
927         );
928         delete_field( { record => $record, field => '651' } );
930         copy_and_replace_field(
931             {
932                 record        => $record,
933                 from_field    => '650',
934                 from_subfield => 'a',
935                 to_field      => '651',
936                 to_subfield   => 'a',
937                 field_numbers => [1]
938             }
939         );
940         is_deeply(
941             [
942                 read_field(
943                     { record => $record, field => '651', subfield => 'a' }
944                 )
945             ],
946             ['Computer programming.'],
947             'Copy and replace first field 650$a should only copy the 1st (same as copy)'
948         );
950         copy_and_replace_field(
951             {
952                 record        => $record,
953                 from_field    => '650',
954                 from_subfield => 'a',
955                 to_field      => '651',
956                 to_subfield   => 'a',
957                 field_numbers => [2]
958             }
959         );
960         is_deeply(
961             [
962                 read_field(
963                     { record => $record, field => '651', subfield => 'a' }
964                 )
965             ],
966             ['Computer algorithms.'],
967             'Copy and replace second field 650$a should erase 651$a'
968         );
969         delete_field( { record => $record, field => '651' } );
971         copy_and_replace_field(
972             {
973                 record        => $record,
974                 from_field    => '650',
975                 from_subfield => 'a',
976                 to_field      => '651',
977                 to_subfield   => 'a',
978                 regex => { search => 'Computer', replace => 'The art of' }
979             }
980         );
981         @fields_651a =
982           read_field( { record => $record, field => '651', subfield => 'a' } );
983         is_deeply(
984             \@fields_651a,
985             [ 'The art of programming.', 'The art of algorithms.' ],
986             'Copy and replace field using regex (same as copy)'
987         );
988         delete_field( { record => $record, field => '651' } );
990         copy_and_replace_field(
991             {
992                 record        => $record,
993                 from_field    => '650',
994                 from_subfield => 'a',
995                 to_field      => '651',
996                 to_subfield   => 'a',
997                 regex => { search => 'Computer', replace => 'The mistake of' }
998             }
999         );
1000         @fields_651a =
1001           read_field( { record => $record, field => '651', subfield => 'a' } );
1002         is_deeply(
1003             \@fields_651a,
1004             [ 'The mistake of programming.', 'The mistake of algorithms.' ],
1005             'Copy and replace fields using regex on existing fields (same as copy)'
1006         );
1007         delete_field( { record => $record, field => '651' } );
1009         copy_and_replace_field(
1010             {
1011                 record        => $record,
1012                 from_field    => '650',
1013                 from_subfield => 'a',
1014                 to_field      => '651',
1015                 to_subfield   => 'a',
1016                 regex => { search => 'Computer', replace => 'The art of' }
1017             }
1018         );
1019         @fields_651a =
1020           read_field( { record => $record, field => '651', subfield => 'a' } );
1021         is_deeply(
1022             \@fields_651a,
1023             [ 'The art of programming.', 'The art of algorithms.', ],
1024             'Copy and replace all fields using regex (same as copy)'
1025         );
1026         delete_field( { record => $record, field => '651' } );
1028         copy_and_replace_field(
1029             {
1030                 record        => $record,
1031                 from_field    => '650',
1032                 from_subfield => 'a',
1033                 to_field      => '651',
1034                 to_subfield   => 'a',
1035                 regex => { search => 'Computer', replace => 'The art of' },
1036                 field_numbers => [1]
1037             }
1038         );
1039         @fields_651a =
1040           read_field( { record => $record, field => '651', subfield => 'a' } );
1041         is_deeply(
1042             \@fields_651a,
1043             [ 'The art of programming.', ],
1044             'Copy and replace first field using regex (same as copy)'
1045         );
1046         delete_field( { record => $record, field => '651' } );
1048         # Copy and replace with regex modifiers
1049         $record = new_record;
1050         $record->append_fields(
1051             MARC::Field->new(
1052                 650, ' ', '0',
1053                 a => 'Computer algorithms.',
1054                 9 => '463',
1055             )
1056         );
1057         copy_and_replace_field(
1058             {
1059                 record        => $record,
1060                 from_field    => '650',
1061                 from_subfield => 'a',
1062                 to_field      => '652',
1063                 to_subfield   => 'a',
1064                 regex         => { search => 'o', replace => 'foo' }
1065             }
1066         );
1067         my @fields_652a =
1068           read_field( { record => $record, field => '652', subfield => 'a' } );
1069         is_deeply(
1070             \@fields_652a,
1071             [ 'Cfoomputer programming.', 'Cfoomputer algorithms.' ],
1072             'Copy and replace field using regex (same as copy)'
1073         );
1075         copy_and_replace_field(
1076             {
1077                 record        => $record,
1078                 from_field    => '650',
1079                 from_subfield => 'a',
1080                 to_field      => '653',
1081                 to_subfield   => 'a',
1082                 regex => { search => 'o', replace => 'foo', modifiers => 'g' }
1083             }
1084         );
1085         my @fields_653a =
1086           read_field( { record => $record, field => '653', subfield => 'a' } );
1087         is_deeply(
1088             \@fields_653a,
1089             [ 'Cfoomputer prfoogramming.', 'Cfoomputer algfoorithms.' ],
1090             'Copy and replace field using regex (same as copy)'
1091         );
1093         copy_and_replace_field(
1094             {
1095                 record        => $record,
1096                 from_field    => '650',
1097                 from_subfield => 'a',
1098                 to_field      => '654',
1099                 to_subfield   => 'a',
1100                 regex => { search => 'O', replace => 'foo', modifiers => 'i' }
1101             }
1102         );
1103         my @fields_654a =
1104           read_field( { record => $record, field => '654', subfield => 'a' } );
1105         is_deeply(
1106             \@fields_654a,
1107             [ 'Cfoomputer programming.', 'Cfoomputer algorithms.' ],
1108             'Copy and replace field using regex (same as copy)'
1109         );
1111         copy_and_replace_field(
1112             {
1113                 record        => $record,
1114                 from_field    => '650',
1115                 from_subfield => 'a',
1116                 to_field      => '655',
1117                 to_subfield   => 'a',
1118                 regex => { search => 'O', replace => 'foo', modifiers => 'gi' }
1119             }
1120         );
1121         my @fields_655a =
1122           read_field( { record => $record, field => '655', subfield => 'a' } );
1123         is_deeply(
1124             \@fields_655a,
1125             [ 'Cfoomputer prfoogramming.', 'Cfoomputer algfoorithms.' ],
1126             'Copy and replace field using regex (same as copy)'
1127         );
1129         $record = new_record;
1130         $record->append_fields(
1131             MARC::Field->new(
1132                 952, ' ', ' ',
1133                 p => '3010023917',
1134                 y => 'BK',
1135             ),
1136         );
1138         copy_and_replace_field(
1139             {
1140                 record        => $record,
1141                 from_field    => '952',
1142                 from_subfield => 'd',
1143                 to_field      => '952',
1144                 to_subfield   => 'd'
1145             }
1146         );
1147         my @fields_952d =
1148           read_field( { record => $record, field => '952', subfield => 'd' } );
1149         is_deeply(
1150             \@fields_952d,
1151             [ '2001-06-25', '2001-06-25' ],
1152             'copy and replace 952$d into others 952 field'
1153         );
1155         copy_and_replace_field(
1156             {
1157                 record        => $record,
1158                 from_field    => '111',
1159                 from_subfield => '1',
1160                 to_field      => '999',
1161                 to_subfield   => '9'
1162             }
1163         );
1164         my @fields_9999 =
1165           read_field( { record => $record, field => '999', subfield => '9' } );
1166         is_deeply( \@fields_9999, [],
1167             'copy and replace a nonexistent subfield does not create a new one (same as copy)' );
1169         $record = new_record;
1170         copy_and_replace_field(
1171             {
1172                 record        => $record,
1173                 from_field    => 245,
1174                 from_subfield => 'a',
1175                 to_field      => 245,
1176                 to_subfield   => 'a',
1177                 regex         => { search => '^', replace => 'BEGIN ' }
1178             }
1179         );
1180         # This is the same as update the subfield
1181         is_deeply(
1182             [
1183                 read_field(
1184                     { record => $record, field => '245', subfield => 'a' }
1185                 )
1186             ],
1187             ['BEGIN The art of computer programming'],
1188             'Copy and replace - Update a subfield: add a string at the beginning'
1189         );
1191         $record = new_record;
1192         copy_and_replace_field(
1193             {
1194                 record        => $record,
1195                 from_field    => 245,
1196                 from_subfield => 'a',
1197                 to_field      => 245,
1198                 to_subfield   => 'a',
1199                 regex         => { search => '$', replace => ' END' }
1200             }
1201         );
1202         # This is the same as update the subfield
1203         is_deeply(
1204             [
1205                 read_field(
1206                     { record => $record, field => '245', subfield => 'a' }
1207                 )
1208             ],
1209             ['The art of computer programming END'],
1210             'Copy and replace - Update a subfield: add a string at the end'
1211         );
1213         $record = new_record;
1214         copy_and_replace_field(
1215             {
1216                 record        => $record,
1217                 from_field    => 245,
1218                 from_subfield => 'c',
1219                 to_field      => 650,
1220                 to_subfield   => 'c',
1221             }
1222         );
1224         is_deeply(
1225             [
1226                 read_field(
1227                     { record => $record, field => '650' }
1228                 )
1229             ],
1230             [ 'Computer programming.', '462', 'Donald E. Knuth.' ],
1231             'Copy and replace a subfield to an existent field but inexistent subfield (same as copy)'
1232         );
1234         $record = new_record;
1235         copy_and_replace_field(
1236             {
1237                 record        => $record,
1238                 from_field    => 245,
1239                 from_subfield => 'c',
1240                 to_field      => 650,
1241                 to_subfield   => '9',
1242             }
1243         );
1245         is_deeply(
1246             [
1247                 read_field(
1248                     { record => $record, field => '650' }
1249                 )
1250             ],
1251             [ 'Computer programming.', 'Donald E. Knuth.' ],
1252             'Copy and replace a subfield to an existent field / subfield, the origin subfield is replaced'
1253         );
1254     };
1256     subtest 'copy and replace field' => sub {
1257         plan tests => 14;
1258         my $record = new_record;
1259         $record->append_fields(
1260             MARC::Field->new(
1261                 952, ' ', ' ',
1262                 p => '3010023918',
1263                 y => 'CD',
1264             ),
1265         );
1267         #- copy all fields
1268         copy_and_replace_field(
1269             { record => $record, from_field => '952', to_field => '953' } );
1270         my @fields_952 = read_field( { record => $record, field => '952' } );
1271         is_deeply(
1272             [
1273                 read_field(
1274                     { record => $record, field => '952', field_numbers => [1] }
1275                 )
1276             ],
1277             [ '3010023917', 'BK', 'GEN', '2001-06-25' ],
1278             "copy all: original first field still exists (same as copy)"
1279         );
1280         is_deeply(
1281             [
1282                 read_field(
1283                     { record => $record, field => '952', field_numbers => [2] }
1284                 )
1285             ],
1286             [ '3010023918', 'CD' ],
1287             "copy all: original second field still exists (same as copy)"
1288         );
1289         is_deeply(
1290             [
1291                 read_field(
1292                     { record => $record, field => '953', field_numbers => [1] }
1293                 )
1294             ],
1295             [ '3010023917', 'BK', 'GEN', '2001-06-25' ],
1296             "copy all: first original fields has been copied (same as copy)"
1297         );
1298         is_deeply(
1299             [
1300                 read_field(
1301                     { record => $record, field => '953', field_numbers => [2] }
1302                 )
1303             ],
1304             [ '3010023918', 'CD' ],
1305             "copy all: second original fields has been copied (same as copy)"
1306         );
1308         #- copy only the first field
1309         copy_and_replace_field(
1310             {
1311                 record        => $record,
1312                 from_field    => '953',
1313                 to_field      => '954',
1314                 field_numbers => [1]
1315             }
1316         );
1317         is_deeply(
1318             [
1319                 read_field(
1320                     { record => $record, field => '953', field_numbers => [1] }
1321                 )
1322             ],
1323             [ '3010023917', 'BK', 'GEN', '2001-06-25' ],
1324             "copy and replace first: first original fields has been copied (same as copy)"
1325         );
1326         is_deeply(
1327             [
1328                 read_field(
1329                     { record => $record, field => '953', field_numbers => [2] }
1330                 )
1331             ],
1332             [ '3010023918', 'CD' ],
1333             "copy and replace first: second original fields has been copied (same as copy)"
1334         );
1335         is_deeply(
1336             [ read_field( { record => $record, field => '954' } ) ],
1337             [ '3010023917', 'BK', 'GEN', '2001-06-25' ],
1338             "copy and replace first: only first, first 953 has been copied (same as copy)"
1339         );
1341         $record = new_record;
1342         $record->append_fields(
1343             MARC::Field->new(
1344                 952, ' ', ' ',
1345                 p => '3010023918',
1346                 y => 'CD',
1347             ),
1348         );
1350         #- copy and replace all fields and modify values using a regex
1351         copy_and_replace_field(
1352             {
1353                 record     => $record,
1354                 from_field => '952',
1355                 to_field   => '953',
1356                 regex      => { search => '30100', replace => '42424' }
1357             }
1358         );
1359         is_deeply(
1360             [
1361                 read_field(
1362                     { record => $record, field => '952', field_numbers => [1] }
1363                 )
1364             ],
1365             [ '3010023917', 'BK', 'GEN', '2001-06-25' ],
1366             "copy and replace all with regex: original first field still exists (same as copy)"
1367         );
1368         is_deeply(
1369             [
1370                 read_field(
1371                     { record => $record, field => '952', field_numbers => [2] }
1372                 )
1373             ],
1374             [ '3010023918', 'CD' ],
1375             "copy and replace all with regex: original second field still exists (same as copy)"
1376         );
1377         is_deeply(
1378             [
1379                 read_field(
1380                     { record => $record, field => '953', field_numbers => [1] }
1381                 )
1382             ],
1383             [ '4242423917', 'BK', 'GEN', '2001-06-25' ],
1384             "copy and replace all with regex: first original fields has been copied (same as copy)"
1385         );
1386         is_deeply(
1387             [
1388                 read_field(
1389                     { record => $record, field => '953', field_numbers => [2] }
1390                 )
1391             ],
1392             [ '4242423918', 'CD' ],
1393             "copy and replace all with regex: second original fields has been copied (same as copy)"
1394         );
1395         copy_and_replace_field(
1396             {
1397                 record     => $record,
1398                 from_field => '111',
1399                 to_field   => '999',
1400             }
1401         );
1402         my @fields_9999 =
1403           read_field( { record => $record, field => '999', subfield => '9' } );
1404         is_deeply( \@fields_9999, [],
1405             'copy and replace a nonexistent field does not create a new one (same as copy)' );
1407         $record = new_record;
1408         copy_and_replace_field(
1409             {
1410                 record        => $record,
1411                 from_field    => 245,
1412                 to_field      => 650,
1413             }
1414         );
1416         is_deeply(
1417             [
1418                 read_field(
1419                     { record => $record, field => '650', field_numbers => [1] }
1420                 )
1421             ],
1422             [ 'The art of computer programming', 'Donald E. Knuth.' ],
1423             'Copy and replace to an existent field should erase the original field'
1424         );
1425         is_deeply(
1426             [
1427                 read_field(
1428                     { record => $record, field => '650', field_numbers => [2] }
1429                 )
1430             ],
1431             [],
1432             'Copy and replace to an existent field should not create a new field'
1433         );
1434     };
1437 # move_field - subfields
1438 subtest 'move_field' => sub {
1439     plan tests              => 2;
1440     subtest 'move subfield' => sub {
1441         plan tests => 7;
1442         my $record = new_record;
1443         my ( @fields_952d, @fields_952c, @fields_954c, @fields_954p );
1444         $record->append_fields(
1445             MARC::Field->new(
1446                 952, ' ', ' ',
1447                 p => '3010023917',
1448                 y => 'BK',
1449             ),
1450         );
1451         move_field(
1452             {
1453                 record        => $record,
1454                 from_field    => '952',
1455                 from_subfield => 'c',
1456                 to_field      => '954',
1457                 to_subfield   => 'c'
1458             }
1459         );
1460         @fields_952c =
1461           read_field( { record => $record, field => '952', subfield => 'c' } );
1462         @fields_954c =
1463           read_field( { record => $record, field => '954', subfield => 'c' } );
1464         is_deeply( \@fields_952c, [],      'The 952$c has moved' );
1465         is_deeply( \@fields_954c, ['GEN'], 'Now 954$c exists' );
1467         move_field(
1468             {
1469                 record        => $record,
1470                 from_field    => '952',
1471                 from_subfield => 'p',
1472                 to_field      => '954',
1473                 to_subfield   => 'p',
1474                 field_numbers => [1]
1475             }
1476         );    # Move the first field
1477         my @fields_952p =
1478           read_field( { record => $record, field => '952', subfield => 'p' } );
1479         @fields_954p =
1480           read_field( { record => $record, field => '954', subfield => 'p' } );
1481         is_deeply( \@fields_952p, ['3010023917'], 'One of 952$p has moved' );
1482         is_deeply( \@fields_954p, ['3010023917'], 'Now 954$p exists' );
1484         $record = new_record;
1485         $record->append_fields(
1486             MARC::Field->new(
1487                 952, ' ', ' ',
1488                 p => '3010023917',
1489                 y => 'BK',
1490             ),
1491         );
1493         move_field(
1494             {
1495                 record        => $record,
1496                 from_field    => '952',
1497                 from_subfield => 'p',
1498                 to_field      => '954',
1499                 to_subfield   => 'p'
1500             }
1501         );    # Move all field
1502         @fields_952p =
1503           read_field( { record => $record, field => '952', subfield => 'p' } );
1504         @fields_954p =
1505           read_field( { record => $record, field => '954', subfield => 'p' } );
1506         is_deeply( \@fields_952p, [], 'All 952$p have moved' );
1507         is_deeply(
1508             \@fields_954p,
1509             [ '3010023917', '3010023917' ],
1510             'Now 2 954$p exist'
1511         );
1513         move_field(
1514             {
1515                 record        => $record,
1516                 from_field    => '111',
1517                 from_subfield => '1',
1518                 to_field      => '999',
1519                 to_subfield   => '9'
1520             }
1521         );
1522         my @fields_9999 =
1523           read_field( { record => $record, field => '999', subfield => '9' } );
1524         is_deeply( \@fields_9999, [],
1525             'move a nonexistent subfield does not create a new one' );
1526     };
1528     subtest 'move field' => sub {
1529         plan tests => 9;
1531         # move_field - fields
1532         my $record = new_record;
1533         $record->append_fields(
1534             MARC::Field->new(
1535                 952, ' ', ' ',
1536                 p => '3010023917',
1537                 y => 'BK',
1538             ),
1539         );
1541         #- Move all fields
1542         move_field(
1543             { record => $record, from_field => '952', to_field => '953' } );
1544         is_deeply( [ read_field( { record => $record, field => '952' } ) ],
1545             [], "original fields don't exist" );
1546         is_deeply(
1547             [
1548                 read_field(
1549                     { record => $record, field => '953', field_numbers => [1] }
1550                 )
1551             ],
1552             [ '3010023917', 'BK', 'GEN', '2001-06-25' ],
1553             "first original fields has been copied"
1554         );
1555         is_deeply(
1556             [
1557                 read_field(
1558                     { record => $record, field => '953', field_numbers => [2] }
1559                 )
1560             ],
1561             [ '3010023917', 'BK' ],
1562             "second original fields has been copied"
1563         );
1565         #- Move only the first field
1566         move_field(
1567             {
1568                 record        => $record,
1569                 from_field    => '953',
1570                 to_field      => '954',
1571                 field_numbers => [1]
1572             }
1573         );
1574         is_deeply(
1575             [ read_field( { record => $record, field => '953' } ) ],
1576             [ '3010023917', 'BK' ],
1577             "only first, the second 953 still exists"
1578         );
1579         is_deeply(
1580             [ read_field( { record => $record, field => '954' } ) ],
1581             [ '3010023917', 'BK', 'GEN', '2001-06-25' ],
1582             "only first, first 953 has been copied"
1583         );
1585         $record = new_record;
1586         $record->append_fields(
1587             MARC::Field->new(
1588                 952, ' ', ' ',
1589                 p => '3010023917',
1590                 y => 'BK',
1591             ),
1592         );
1594         #- Move all fields and modify values using a regex
1595         move_field(
1596             {
1597                 record     => $record,
1598                 from_field => '952',
1599                 to_field   => '953',
1600                 regex      => { search => 'BK', replace => 'DVD' }
1601             }
1602         );
1603         is_deeply( [ read_field( { record => $record, field => '952' } ) ],
1604             [], "use a regex, original fields don't exist" );
1605         is_deeply(
1606             [
1607                 read_field(
1608                     { record => $record, field => '953', field_numbers => [1] }
1609                 )
1610             ],
1611             [ '3010023917', 'DVD', 'GEN', '2001-06-25' ],
1612             "use a regex, first original fields has been copied"
1613         );
1614         is_deeply(
1615             [
1616                 read_field(
1617                     { record => $record, field => '953', field_numbers => [2] }
1618                 )
1619             ],
1620             [ '3010023917', 'DVD' ],
1621             "use a regex, second original fields has been copied"
1622         );
1624         move_field(
1625             {
1626                 record     => $record,
1627                 from_field => '111',
1628                 to_field   => '999',
1629             }
1630         );
1631         my @fields_9999 =
1632           read_field( { record => $record, field => '999', subfield => '9' } );
1633         is_deeply( \@fields_9999, [],
1634             'move a nonexistent field does not create a new one' );
1636     };
1639 # delete_field
1640 subtest 'delete_field' => sub {
1641     plan tests                => 2;
1642     subtest 'delete subfield' => sub {
1643         plan tests => 2;
1644         my $record = new_record;
1645         $record->append_fields(
1646             MARC::Field->new(
1647                 952, ' ', ' ',
1648                 p => '3010023917',
1649                 y => 'BK',
1650             ),
1651         );
1653         delete_field(
1654             {
1655                 record        => $record,
1656                 field         => '952',
1657                 subfield      => 'p',
1658                 field_numbers => [1]
1659             }
1660         );
1661         my @fields_952p =
1662           read_field( { record => $record, field => '952', subfield => 'p' } );
1663         is_deeply( \@fields_952p, ['3010023917'], 'Delete first 952$p' );
1665         $record = new_record;
1666         $record->append_fields(
1667             MARC::Field->new(
1668                 952, ' ', ' ',
1669                 p => '3010023917',
1670                 y => 'BK',
1671             ),
1672         );
1673         delete_field( { record => $record, field => '952', subfield => 'p' } );
1674         @fields_952p =
1675           read_field( { record => $record, field => '952', subfield => 'p' } );
1676         is_deeply( \@fields_952p, [], 'Delete all 952$p' );
1677     };
1679     subtest 'delete field' => sub {
1680         plan tests => 2;
1681         my $record = new_record;
1682         delete_field( { record => $record, field => '952' } );
1683         my @fields_952 = read_field( { record => $record, field => '952' } );
1684         is_deeply( \@fields_952, [], 'Delete all 952, 1 deleted' );
1686         $record = new_record;
1687         $record->append_fields(
1688             MARC::Field->new(
1689                 952, ' ', ' ',
1690                 p => '3010023917',
1691                 y => 'BK',
1692             ),
1693         );
1694         delete_field( { record => $record, field => '952' } );
1695         @fields_952 = read_field( { record => $record, field => '952' } );
1696         is_deeply( \@fields_952, [], 'Delete all 952, 2 deleted' );
1697     };
1700 subtest 'field_equals' => sub {
1701     plan tests => 2;
1702     my $record = new_record;
1703     subtest 'standard MARC fields' => sub {
1704         plan tests => 2;
1705         my $match = Koha::SimpleMARC::field_equals({
1706                 record => $record,
1707                 value => 'Donald',
1708                 field => '100',
1709                 subfield => 'a',
1710             });
1711         is_deeply( $match, [], '100$a not equal to "Donald"' );
1713         $match = Koha::SimpleMARC::field_equals({
1714                 record => $record,
1715                 value => 'Donald',
1716                 field => '100',
1717                 subfield => 'a',
1718                 is_regex => 1,
1719             });
1720         is_deeply( $match, [1], 'first 100$a matches "Donald"');
1721     };
1723     subtest 'control fields' => sub {
1724         plan tests => 2;
1725         my $match = Koha::SimpleMARC::field_equals({
1726                 record => $record,
1727                 value => 'eng',
1728                 field => '008',
1729                 subfield => '',
1730             });
1731         is_deeply( $match, [], '008 control field not equal to "eng"' );
1733         $match = Koha::SimpleMARC::field_equals({
1734                 record => $record,
1735                 value => 'eng',
1736                 field => '008',
1737                 subfield => '',
1738                 is_regex => 1,
1739             });
1740         is_deeply( $match, [1], 'first 008 control field matches "eng"' );
1741     };