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