Bug 30831: Unit test
[koha-ffzg.git] / t / db_dependent / ImportBatch.t
1 #!/usr/bin/perl
2
3 use Modern::Perl;
4 use Test::More tests => 19;
5 use utf8;
6 use File::Basename;
7 use File::Temp qw/tempfile/;
8
9 use t::lib::Mocks;
10 use t::lib::TestBuilder;
11
12 use Koha::Database;
13
14 BEGIN {
15     # Mock pluginsdir before loading Plugins module
16     my $path = dirname(__FILE__) . '/../lib/plugins';
17     t::lib::Mocks::mock_config( 'pluginsdir', $path );
18
19     use_ok('Koha::Plugins');
20     use_ok('C4::ImportBatch', qw( AddImportBatch GetImportBatch AddBiblioToBatch AddItemsToImportBiblio GetRecordFromImportBiblio SetMatchedBiblionumber GetImportBiblios GetItemNumbersFromImportBatch CleanBatch DeleteBatch RecordsFromMarcPlugin ));
21 }
22
23 # Start transaction
24 my $schema  = Koha::Database->new->schema;
25 $schema->storage->txn_begin;
26 my $builder = t::lib::TestBuilder->new;
27 my $dbh = C4::Context->dbh;
28
29 # clear
30 $dbh->do('DELETE FROM import_batches');
31
32 my $sample_import_batch1 = {
33     matcher_id => 1,
34     template_id => 1,
35     branchcode => 'QRT',
36     overlay_action => 'create_new',
37     nomatch_action => 'create_new',
38     item_action => 'always_add',
39     import_status => 'staged',
40     batch_type => 'z3950',
41     file_name => 'test.mrc',
42     comments => 'test',
43     record_type => 'auth',
44 };
45
46 my $sample_import_batch2 = {
47     matcher_id => 2,
48     template_id => 2,
49     branchcode => 'QRZ',
50     overlay_action => 'create_new',
51     nomatch_action => 'create_new',
52     item_action => 'always_add',
53     import_status => 'staged',
54     batch_type => 'z3950',
55     file_name => 'test.mrc',
56     comments => 'test',
57     record_type => 'auth',
58 };
59
60 my $id_import_batch1 = C4::ImportBatch::AddImportBatch($sample_import_batch1);
61 my $id_import_batch2 = C4::ImportBatch::AddImportBatch($sample_import_batch2);
62
63 like( $id_import_batch1, '/^\d+$/', "AddImportBatch for sample_import_batch1 return an id" );
64 like( $id_import_batch2, '/^\d+$/', "AddImportBatch for sample_import_batch2 return an id" );
65
66 #Test GetImportBatch
67 my $importbatch2 = C4::ImportBatch::GetImportBatch( $id_import_batch2 );
68 delete $importbatch2->{upload_timestamp};
69 delete $importbatch2->{import_batch_id};
70 delete $importbatch2->{num_records};
71 delete $importbatch2->{num_items};
72 delete $importbatch2->{profile_id};
73 delete $importbatch2->{profile};
74
75 is_deeply( $importbatch2, $sample_import_batch2,
76     "GetImportBatch returns the right informations about $sample_import_batch2" );
77
78 my $importbatch1 = C4::ImportBatch::GetImportBatch( $id_import_batch1 );
79 delete $importbatch1->{upload_timestamp};
80 delete $importbatch1->{import_batch_id};
81 delete $importbatch1->{num_records};
82 delete $importbatch1->{num_items};
83 delete $importbatch1->{profile_id};
84 delete $importbatch1->{profile};
85
86 is_deeply( $importbatch1, $sample_import_batch1,
87     "GetImportBatch returns the right informations about $sample_import_batch1" );
88
89 my $record = MARC::Record->new;
90 # FIXME Create another MARC::Record which won't be modified
91 # AddItemsToImportBiblio will remove the items field from the record passed in parameter.
92 my $original_record = MARC::Record->new;
93 $record->leader('03174nam a2200445 a 4500');
94 $original_record->leader('03174nam a2200445 a 4500');
95 my ($item_tag, $item_subfield) = C4::Biblio::GetMarcFromKohaField( 'items.itemnumber' );
96 my @fields = (
97     MARC::Field->new(
98         100, '1', ' ',
99         a => 'Knuth, Donald Ervin',
100         d => '1938',
101     ),
102     MARC::Field->new(
103         245, '1', '4',
104         a => 'The art of computer programming',
105         c => 'Donald E. Knuth.',
106     ),
107     MARC::Field->new(
108         650, ' ', '0',
109         a => 'Computer programming.',
110         9 => '462',
111     ),
112     MARC::Field->new(
113         $item_tag, ' ', ' ',
114         e => 'my edition ❤',
115         i => 'my item part',
116     ),
117     MARC::Field->new(
118         $item_tag, ' ', ' ',
119         e => 'my edition 2',
120         i => 'my item part 2',
121     ),
122 );
123 $record->append_fields(@fields);
124 $original_record->append_fields(@fields);
125 my $import_record_id = AddBiblioToBatch( $id_import_batch1, 0, $record, 'utf8', int(rand(99999)), 0 );
126 AddItemsToImportBiblio( $id_import_batch1, $import_record_id, $record, 0 );
127
128 my $record_from_import_biblio_with_items = C4::ImportBatch::GetRecordFromImportBiblio( $import_record_id, 'embed_items' );
129 $original_record->leader($record_from_import_biblio_with_items->leader());
130 is_deeply( $record_from_import_biblio_with_items, $original_record, 'GetRecordFromImportBiblio should return the record with items if specified' );
131 my $utf8_field = $record_from_import_biblio_with_items->subfield($item_tag, 'e');
132 is($utf8_field, 'my edition ❤');
133 $original_record->delete_fields($original_record->field($item_tag)); #Remove items fields
134 my $record_from_import_biblio_without_items = C4::ImportBatch::GetRecordFromImportBiblio( $import_record_id );
135 $original_record->leader($record_from_import_biblio_without_items->leader());
136 is_deeply( $record_from_import_biblio_without_items, $original_record, 'GetRecordFromImportBiblio should return the record without items by default' );
137
138 my $another_biblio = $builder->build_sample_biblio;
139 C4::ImportBatch::SetMatchedBiblionumber( $import_record_id, $another_biblio->biblionumber );
140 my $import_biblios = GetImportBiblios( $import_record_id );
141 is( $import_biblios->[0]->{matched_biblionumber}, $another_biblio->biblionumber, 'SetMatchedBiblionumber  should set the correct biblionumber' );
142
143 # Add a few tests for GetItemNumbersFromImportBatch
144 my @a = GetItemNumbersFromImportBatch( $id_import_batch1 );
145 is( @a, 0, 'No item numbers expected since we did not commit' );
146 my $itemno = $builder->build_sample_item->itemnumber;
147 # Link this item to the import item to fool GetItemNumbersFromImportBatch
148 my $sql = "UPDATE import_items SET itemnumber=? WHERE import_record_id=?";
149 $dbh->do( $sql, undef, $itemno, $import_record_id );
150 @a = GetItemNumbersFromImportBatch( $id_import_batch1 );
151 is( @a, 2, 'Expecting two items now' );
152 is( $a[0], $itemno, 'Check the first returned itemnumber' );
153 # Now delete the item and check again
154 $dbh->do( "DELETE FROM items WHERE itemnumber=?", undef, $itemno );
155 @a = GetItemNumbersFromImportBatch( $id_import_batch1 );
156 is( @a, 0, 'No item numbers expected since we deleted the item' );
157 $dbh->do( $sql, undef, undef, $import_record_id ); # remove link again
158
159 # fresh data
160 my $sample_import_batch3 = {
161     matcher_id => 3,
162     template_id => 3,
163     branchcode => 'QRT',
164     overlay_action => 'create_new',
165     nomatch_action => 'create_new',
166     item_action => 'always_add',
167     import_status => 'staged',
168     batch_type => 'z3950',
169     file_name => 'test.mrc',
170     comments => 'test',
171     record_type => 'auth',
172 };
173
174 my $id_import_batch3 = C4::ImportBatch::AddImportBatch($sample_import_batch3);
175
176 # Test CleanBatch
177 C4::ImportBatch::CleanBatch( $id_import_batch3 );
178 my $import_record = get_import_record( $id_import_batch3 );
179 is( $import_record, "0E0", "Batch 3 has been cleaned" );
180
181 # Test DeleteBatch
182 C4::ImportBatch::DeleteBatch( $id_import_batch3 );
183 my $import_batch = C4::ImportBatch::GetImportBatch( $id_import_batch3 );
184 is( $import_batch, undef, "Batch 3 has been deleted");
185
186 subtest "BatchCommitItems" => sub {
187     plan tests => 3;
188
189     my $exist_item = $builder->build_sample_item;
190     my $import_item = $builder->build_object({ class => 'Koha::Import::Record::Items', value => {
191         marcxml => q{<?xml version="1.0" encoding="UTF-8"?>
192 <collection
193   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
194   xsi:schemaLocation="http://www.loc.gov/MARC21/slim http://www.loc.gov/standards/marcxml/schema/MARC21slim.xsd"
195   xmlns="http://www.loc.gov/MARC21/slim">
196
197 <record>
198   <leader>00000    a              </leader>
199   <datafield tag="952" ind1=" " ind2=" ">
200     <subfield code="a">CPL</subfield>
201     <subfield code="b">CPL</subfield>
202     <subfield code="c">GEN</subfield>
203     <subfield code="p">}.$exist_item->barcode.q{</subfield>
204     <subfield code="y">BK</subfield>
205   </datafield>
206 </record>
207 </collection>
208         },
209     }});
210
211     my ( $num_items_added, $num_items_replaced, $num_items_errored ) =
212         C4::ImportBatch::BatchCommitItems( $import_item->import_record_id, 32, 'always_add',64 );
213     is( $num_items_errored, 1, "Item with duplicate barcode fails when action always_add" );
214     $import_item->discard_changes();
215     is( $import_item->status, 'error', "Import item marked as error when duplicate barcode and action always_add");
216     is( $import_item->import_error, 'duplicate item barcode', 'Error correctly set when import item has duplicate barcode and action always_add' );
217 };
218
219 subtest "RecordsFromMarcPlugin" => sub {
220     plan tests => 5;
221
222     # Create a test file
223     my ( $fh, $name ) = tempfile();
224     print $fh q|
225 003 = NLAmRIJ
226 100,a = Author
227 245,ind2 = 0
228 245,a = Silence in the library
229 500 , a= Some note
230
231 100,a = Another
232 245,a = Noise in the library|;
233     close $fh;
234
235     t::lib::Mocks::mock_config( 'enable_plugins', 1 );
236
237     my $plugins = Koha::Plugins->new;
238     $plugins->InstallPlugins;
239     my ($plugin) = $plugins->GetPlugins({ all => 1, metadata => { name => 'MarcFieldValues' } });
240     isnt( $plugin, undef, "Plugin found" );
241     my $records = C4::ImportBatch::RecordsFromMarcPlugin( $name, ref $plugin, 'UTF-8' );
242     is( @$records, 2, 'Two results returned' );
243     is( ref $records->[0], 'MARC::Record', 'Returned MARC::Record object' );
244     is( $records->[0]->subfield('245', 'a'), 'Silence in the library',
245         'Checked one field in first record' );
246     is( $records->[1]->subfield('100', 'a'), 'Another',
247         'Checked one field in second record' );
248 };
249
250 subtest "_get_commit_action" => sub {
251     plan tests => 24;
252     my $mock_import = Test::MockModule->new("C4::ImportBatch");
253
254     $mock_import->mock( GetBestRecordMatch => sub { return 5; } );
255     foreach my $record_type ( ('biblio','authority') ){
256         foreach my $match_action ( ('replace','create_new','ignore') ){
257             foreach my $no_match_action ( ('create_new','ignore') ){
258                 my ($result, $match, $item_result) =
259                     C4::ImportBatch::_get_commit_action($match_action, $no_match_action, 'always_add', 'auto_match', 42, $record_type);
260                 is( $result, $match_action, "When match found amd chosen we return the match_action for $record_type records with match action $match_action and no match action $no_match_action");
261             }
262         }
263     }
264
265     $mock_import->mock( GetBestRecordMatch => sub { my $matches = undef; return $matches; } );
266     foreach my $record_type ( ('biblio','authority') ){
267         foreach my $match_action ( ('replace','create_new','ignore') ){
268             foreach my $no_match_action ( ('create_new','ignore') ){
269                 my ($result, $match, $item_result) =
270                     C4::ImportBatch::_get_commit_action($match_action, $no_match_action, 'always_add', 'auto_match', 42, $record_type);
271                 is( $result, $no_match_action, "When no match found or chosen we return the match_action for $record_type records with match action $match_action and no match action $no_match_action");
272             }
273         }
274     }
275
276 };
277
278 sub get_import_record {
279     my $id_import_batch = shift;
280     return $dbh->do('SELECT * FROM import_records WHERE import_batch_id = ?', undef, $id_import_batch);
281 }
282
283 $schema->storage->txn_rollback;