Bug 23177: (QA follow-up) Move rollback to the end
[koha.git] / t / db_dependent / Breeding.t
1 #!/usr/bin/perl
2
3 # Copyright 2014 Rijksmuseum
4 #
5 # This file is part of Koha.
6 #
7 # Koha is free software; you can redistribute it and/or modify it under the
8 # terms of the GNU General Public License as published by the Free Software
9 # Foundation; either version 3 of the License, or (at your option) any later
10 # version.
11 #
12 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License along
17 # with Koha; if not, write to the Free Software Foundation, Inc.,
18 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20 use Modern::Perl;
21
22 use FindBin;
23 use Test::More tests => 4;
24 use Test::Warn;
25 use t::lib::Mocks qw( mock_preference );
26
27 use C4::Context;
28 use C4::Breeding;
29 use Koha::XSLT_Handler;
30
31 #Main object of this unit test is the Breeding module and its subroutines
32 #A start has been made to define tests for subroutines of Z3950Search.
33 #These subroutines are actually internal, but these tests may pave the way for
34 #a more comprehensive test of Z3950Search itself.
35 #TODO
36 #Furthermore, we need additional tests for:
37 #Z3950SearchAuth, BreedingSearch, ImportBreedingAuth
38
39 #Group 1: testing _build_query and _translate_query (part of Z3950Search)
40 subtest '_build_query' => sub {
41     plan tests => 14;
42     test_build_translate_query();
43 };
44 #Group 2: testing _create_connection (part of Z3950Search)
45 subtest '_create_connection' => sub {
46     plan tests => 5;
47     test_create_connection();
48 };
49 #Group 3: testing _do_xslt_proc (part of Z3950Search)
50 subtest '_do_xslt_proc' => sub {
51     plan tests => 6;
52     test_do_xslt();
53 };
54 #Group 4: testing _add_rowdata (part of Z3950Search)
55 subtest '_add_rowdata' => sub {
56     plan tests => 5;
57     test_add_rowdata();
58 };
59
60 #-------------------------------------------------------------------------------
61
62 sub test_build_translate_query {
63     my $str;
64     #First pass no parameters
65     my @queries= C4::Breeding::_bib_build_query( {} );
66     is( defined $queries[0] && $queries[0] eq '' && defined $queries[1] &&
67         $queries[1] eq '', 1, '_bib_build_query gets no parameters');
68
69     #We now pass one parameter
70     my $pars1= { isbn => '234567' };
71     @queries= C4::Breeding::_bib_build_query( $pars1 );
72     #Passed only one par: zquery should start with @attr 1=\d+
73     is( $queries[0] =~ /^\@attr 1=\d+/, 1, 'Z39.50 query with one parameter');
74     $str=$pars1->{isbn};
75     #Find back ISBN?
76     is( $queries[0] =~ /$str/, 1, 'First Z39.50 query contains ISBN');
77     #SRU query should contain translation for ISBN
78     my $server= { sru_fields => 'isbn=ie-es-bee-en,srchany=overal' };
79     my $squery= C4::Breeding::_translate_query( $server, $queries[1] );
80     is( $squery =~ /ie-es-bee-en/, 1, 'SRU query has translated ISBN index');
81     #Another try with fallback to any
82     $server= { sru_fields => 'srchany=overal' };
83     $squery= C4::Breeding::_translate_query( $server, $queries[1] );
84     is( $squery =~ /overal/, 1, 'SRU query fallback to translated any');
85     #Another try even without any
86     $server= { sru_fields => 'this,is,bad,input' };
87     $squery= C4::Breeding::_translate_query( $server, $queries[1] );
88     is( $squery =~ /$str/ && $squery !~ /=/, 1, 'SRU query without indexes');
89
90     #We now pass two parameters
91     my $pars2= { isbn => '123456', title => 'You should read this.' };
92     @queries= C4::Breeding::_bib_build_query( $pars2 );
93     #The Z39.50 query should start with @and (we passed two pars)
94     is( $queries[0] =~ /^\@and/, 1, 'Second Z39.50 query starts with @and');
95     #We should also find two @attr 1=\d+
96     my @matches= $queries[0] =~ /\@attr 1=\d+/g;
97     is( @matches == 2, 1, 'Second Z39.50 query includes two @attr 1=');
98     #We should find text of both parameters in the query
99     $str= $pars2->{isbn};
100     is( $queries[0] =~ /\"$str\"/, 1,
101         'Second query contains ISBN enclosed by double quotes');
102     $str= $pars2->{title};
103     is( $queries[0] =~ /\"$str\"/, 1,
104         'Second query contains title enclosed by double quotes');
105
106     #SRU revisited
107     $server= { sru_fields => 'isbn=nb,title=dc.title,srchany=overal' };
108     $squery= C4::Breeding::_translate_query( $server, $queries[1] );
109     is ( $squery =~ /dc.title/ && $squery =~ / and / &&
110         $squery =~ /nb=/, 1, 'SRU query with two parameters');
111
112     #We now pass a third wrong parameter (should not make a difference)
113     my $pars3= { isbn => '123456', title => 'You should read this.', xyz => 1 };
114     my @queries2= C4::Breeding::_bib_build_query( $pars3 );
115     is( $queries[0] eq $queries2[0] && $queries[1] eq $queries2[1], 1,
116         'Third query makes no difference');
117
118     # Check that indexes with equal signs are ok
119     $server = { sru_fields => 'subjectsubdiv=aut.type=ram_pe and aut.accesspoint' };
120     my $pars4 = { subjectsubdiv => 'mysubjectsubdiv' };
121     @queries = C4::Breeding::_auth_build_query( $pars4 );
122     my $zquery = C4::Breeding::_translate_query( $server, $queries[1] );
123     is ( $zquery, 'aut.type=ram_pe and aut.accesspoint="mysubjectsubdiv"', 'SRU query with equal sign in index');
124
125     # Check that indexes with double-quotes are ok
126     $server = { sru_fields => 'subject=(aut.type any "geo ram_nc ram_ge ram_pe ram_co") and aut.accesspoint' };
127     my $pars5 = { subject => 'mysubject' };
128     @queries = C4::Breeding::_auth_build_query( $pars5 );
129     $zquery = C4::Breeding::_translate_query( $server, $queries[1] );
130     is ( $zquery, '(aut.type any "geo ram_nc ram_ge ram_pe ram_co") and aut.accesspoint="mysubject"', 'SRU query with double quotes in index');
131 }
132
133 sub test_create_connection {
134     #TODO This is just a *simple* start
135
136     my $str;
137     my $server= { servertype => 'zed', db => 'MyDatabase',
138         host => 'really-not-a-domain-i-hope.nl', port => 80,
139     };
140     my $obj= C4::Breeding::_create_connection( $server );
141
142     #We should get back an object, even if it did not connect
143     is( ref $obj eq 'ZOOM::Connection', 1, 'Got back a ZOOM connection');
144
145     #Remember: it is async
146     my $i= ZOOM::event( [ $obj ] );
147     if( $i == 1 ) {
148         #We could examine ZOOM::event_str( $obj->last_event )
149         #For now we are satisfied with an error message
150         #Probably: Connect failed
151         is( ($obj->errmsg//'') ne '', 1, 'Connection failed as expected');
152
153     } else {
154         ok( 1, 'No ZOOM event found: skipped errmsg' );
155     }
156
157     #Checking the databaseName for Z39.50 server
158     $str=$obj->option('databaseName')//'';
159     is( $str eq $server->{db}, 1, 'Check ZOOM option for database');
160
161     #Another test for SRU
162     $obj->destroy();
163     $server->{ servertype } = 'sru';
164     $server->{ sru_options } =  'just_testing=fun';
165     $obj= C4::Breeding::_create_connection( $server );
166     #In this case we expect no databaseName, but we expect just_testing
167     $str=$obj->option('databaseName');
168     is( $str, undef, 'No databaseName for SRU connection');
169     $str=$obj->option('just_testing')//'';
170     is( $str eq 'fun', 1, 'Additional ZOOM option for SRU found');
171     $obj->destroy();
172 }
173
174 sub test_do_xslt {
175     my $biblio = MARC::Record->new();
176     $biblio->append_fields(
177         MARC::Field->new('100', ' ', ' ', a => 'John Writer'),
178         MARC::Field->new('245', ' ', ' ', a => 'Just a title'),
179     );
180     my $file= $FindBin::Bin.'/XSLT_Handler/test01.xsl';
181     my $server= { add_xslt => $file };
182     my $engine=Koha::XSLT_Handler->new;
183
184     #ready for the main test
185     my @res = C4::Breeding::_do_xslt_proc( $biblio, $server, $engine );
186     is( $res[1], undef, 'No error returned' );
187     is( ref $res[0], 'MARC::Record', 'Got back MARC record');
188     is( $res[0]->subfield('990','a'), 'I saw you', 'Found 990a in the record');
189
190     #forcing an error on the xslt side
191     $server->{add_xslt} = 'notafile.xsl';
192     @res = C4::Breeding::_do_xslt_proc( $biblio, $server, $engine );
193     is( $res[1], Koha::XSLT_Handler::XSLTH_ERR_2, 'Error code found' );
194     #We still expect the original record back
195     is( ref $res[0], 'MARC::Record', 'Still got back MARC record' );
196     is ( $res[0]->subfield('245','a'), 'Just a title',
197         'At least the title is the same :)' );
198 }
199
200 sub test_add_rowdata {
201     t::lib::Mocks::mock_preference('AdditionalFieldsInZ3950ResultSearch','');
202
203     my $row = {
204        biblionumber => 0,
205        server => "testServer",
206        breedingid => 0
207    };
208
209     my $biblio = MARC::Record->new();
210     $biblio->append_fields(
211         MARC::Field->new('245', ' ', ' ', a => 'Just a title'), #title
212     );
213
214     my $returned_row = C4::Breeding::_add_rowdata($row, $biblio);
215
216     is($returned_row->{title}, "Just a title", "_add_rowdata returns the title of a biblio");
217     is($returned_row->{addnumberfields}[0], undef, "_add_rowdata returns undef if it has no additionnal field");
218
219     t::lib::Mocks::mock_preference('AdditionalFieldsInZ3950ResultSearch',"245\$a, 035\$a");
220
221     $row = {
222        biblionumber => 0,
223        server => "testServer",
224        breedingid => 0
225    };
226    $biblio = MARC::Record->new();
227    $biblio->append_fields(
228         MARC::Field->new('245', ' ', ' ', a => 'Just a title'), #title
229         MARC::Field->new('035', ' ', ' ', a => 'First 035'),
230         MARC::Field->new('035', ' ', ' ', a => 'Second 035')
231    );
232    $returned_row = C4::Breeding::_add_rowdata($row, $biblio);
233
234    is($returned_row->{title}, "Just a title", "_add_rowdata returns the title of a biblio");
235    is($returned_row->{addnumberfields}[0], "245\$a", "_add_rowdata returns the field number chosen in the AdditionalFieldsInZ3950ResultSearch preference");
236
237    # Test repeatble tags,the trailing whitespace is a normal side-effect of _add_custom_row_data
238    is_deeply(\$returned_row->{"035\$a"}, \["First 035 ", "Second 035 "],"_add_rowdata supports repeatable tags");
239 }