BUG 8010: Correct a few syntax errors, and moved tests
[koha.git] / t / db_dependent / Search / History.t
1 #!/usr/bin/env perl
2
3 use Modern::Perl;
4
5 use CGI qw ( -utf8 );
6 use Test::MockModule;
7 use List::MoreUtils qw/all any none/;
8 use t::lib::Mocks;
9 use t::lib::TestBuilder;
10
11 use C4::Auth;
12 use Koha::AuthUtils qw/hash_password/;
13 use Koha::Database;
14
15 use Test::More tests => 27;
16 use Test::Warn;
17 use URI::Escape;
18 use List::Util qw( shuffle );
19
20 use C4::Context;
21 use Koha::DateUtils;
22 my $dbh = C4::Context->dbh;
23 $dbh->{AutoCommit} = 0;
24 $dbh->{RaiseError} = 1;
25
26 use_ok('Koha::DateUtils');
27 use_ok('C4::Search::History');
28
29 my $userid = 123;
30 my $previous_sessionid = "PREVIOUS_SESSIONID";
31 my $current_sessionid = "CURRENT_SESSIONID";
32 my $total = 42;
33 my $query_cgi_b = q{idx=kw&idx=ti&idx=au%2Cwrdl&q=word1é&q=word2è&q=word3à&do=Search&sort_by=author_az};
34 my $query_cgi_a = q{op=do_search&type=opac&authtypecode=NP&operator=start&value=Harry&marclist=match&and_or=and&orderby=HeadingAsc};
35
36 # add
37 my $added = add( $userid, $current_sessionid, $previous_sessionid, $total, $query_cgi_b, $query_cgi_a );
38 is ( $added, 9, '9 searches are added' );
39
40 # get
41 my $searches_for_userid = C4::Search::History::get({
42     userid => $userid,
43 });
44 is( scalar(@$searches_for_userid), 9, 'There are 9 searches in all' );
45
46 my $searches_for_current_session = C4::Search::History::get({
47     userid => $userid,
48     sessionid => $current_sessionid,
49 });
50 is( scalar(@$searches_for_current_session), 5, 'There are 5 searches for the current session' );
51
52 my $searches_for_previous_sessions = C4::Search::History::get({
53     userid => $userid,
54     sessionid => $current_sessionid,
55     previous => 1,
56 });
57 is( scalar(@$searches_for_previous_sessions), 4, 'There are 4 searches for previous sessions' );
58
59 my $authority_searches_for_current_session = C4::Search::History::get({
60     userid => $userid,
61     sessionid => $current_sessionid,
62     type => 'authority',
63 });
64 is( scalar(@$authority_searches_for_current_session), 3, 'There are 3 authority searches for the current session' );
65
66 my $authority_searches_for_previous_session = C4::Search::History::get({
67     userid => $userid,
68     sessionid => $current_sessionid,
69     type => 'authority',
70     previous => 1,
71 });
72 is( scalar(@$authority_searches_for_previous_session), 2, 'There are 2 authority searches for previous sessions' );
73
74 my $biblio_searches_for_userid = C4::Search::History::get({
75     userid => $userid,
76     type => 'biblio',
77 });
78 is( scalar(@$biblio_searches_for_userid), 4, 'There are 5 searches for the current session' );
79
80 my $authority_searches_for_userid = C4::Search::History::get({
81     userid => $userid,
82     type => 'authority',
83 });
84 is( scalar(@$authority_searches_for_userid), 5, 'There are 4 searches for previous sessions' );
85
86 delete_all( $userid );
87
88 # delete
89 add( $userid, $current_sessionid, $previous_sessionid, $total, $query_cgi_b, $query_cgi_a );
90 C4::Search::History::delete({
91     userid => $userid,
92     sessionid => $current_sessionid,
93     type => 'authority',
94 });
95 my $all = C4::Search::History::get({userid => $userid});
96 is( scalar(@$all), 6, 'There are 6 searches in all after deleting current biblio searches' );
97 delete_all( $userid );
98
99 add( $userid, $current_sessionid, $previous_sessionid, $total, $query_cgi_b, $query_cgi_a );
100 C4::Search::History::delete({
101     userid => $userid,
102     sessionid => $current_sessionid,
103     type => 'biblio',
104     previous => 1,
105 });
106 $all = C4::Search::History::get({userid => $userid});
107 is( scalar(@$all), 7, 'There are 7 searches in all after deleting previous authority searches' );
108 delete_all( $userid );
109
110 add( $userid, $current_sessionid, $previous_sessionid, $total, $query_cgi_b, $query_cgi_a );
111 C4::Search::History::delete({
112     userid => $userid,
113     sessionid => $current_sessionid,
114     previous => 1,
115 });
116 $all = C4::Search::History::get({userid => $userid});
117 is( scalar(@$all), 5, 'There are 5 searches in all after deleting all previous searches' );
118 delete_all( $userid );
119
120 add( $userid, $current_sessionid, $previous_sessionid, $total, $query_cgi_b, $query_cgi_a );
121 C4::Search::History::delete({
122     userid => $userid,
123     sessionid => $current_sessionid,
124 });
125 $all = C4::Search::History::get({userid => $userid});
126 is( scalar(@$all), 4, 'There are 5 searches in all after deleting all searches for a sessionid' );
127 delete_all( $userid );
128
129 add( $userid, $current_sessionid, $previous_sessionid, $total, $query_cgi_b, $query_cgi_a );
130 C4::Search::History::delete({
131     userid => $userid,
132 });
133 $all = C4::Search::History::get({userid => $userid});
134 is( scalar(@$all), 0, 'There are 0 search after deleting all searches for a userid' );
135 delete_all( $userid );
136
137 add( $userid, $current_sessionid, $previous_sessionid, $total, $query_cgi_b, $query_cgi_a );
138 warning_like { C4::Search::History::delete({}) }
139           qr/^ERROR: userid, id or interval is required for history deletion/,
140           'Calling delete without userid raises warning';
141 $all = C4::Search::History::get({userid => $userid});
142 is( scalar(@$all), 9, 'There are still 9 searches after calling delete without userid' );
143 delete_all( $userid );
144
145 # Delete (with a given id)
146 add( $userid, $current_sessionid, $previous_sessionid, $total, $query_cgi_b, $query_cgi_a );
147 $all = C4::Search::History::get({ userid => $userid });
148 # Delete 5 searches
149 my $ids = [ shuffle map { $_->{id} } @$all ];
150 for my $id ( @$ids[ 0 .. 4 ] ) {
151     C4::Search::History::delete({ id => $id });
152 }
153 $all = C4::Search::History::get({ userid => $userid });
154 is( scalar(@$all), 4, 'There are 4 searches after calling 5 times delete with id' );
155 delete_all( $userid );
156
157 add( $userid, $current_sessionid, $previous_sessionid, $total, $query_cgi_b, $query_cgi_a );
158 $all = C4::Search::History::get({ userid => $userid });
159 # Delete 5 searches
160 $ids = [ shuffle map { $_->{id} } @$all ];
161 C4::Search::History::delete({ id => [ @$ids[0..4] ] });
162 $all = C4::Search::History::get({ userid => $userid });
163 is( scalar(@$all), 4, 'There are 4 searches after calling delete with 5 ids' );
164
165 delete_all( $userid );
166
167 # Test delete with interval
168 add( $userid, $current_sessionid, $previous_sessionid, $total, $query_cgi_b, $query_cgi_a );
169 C4::Search::History::delete({
170     userid => $userid,
171     interval => 10,
172 });
173 $all = C4::Search::History::get({userid => $userid});
174 is( scalar(@$all), 9, 'There are still 9 searches after calling delete with an interval = 10 days' );
175 C4::Search::History::delete({
176     userid => $userid,
177     interval => 6,
178 });
179 $all = C4::Search::History::get({userid => $userid});
180 is( scalar(@$all), 8, 'There are still 8 searches after calling delete with an interval = 6 days' );
181 C4::Search::History::delete({
182     userid => $userid,
183     interval => 2,
184 });
185 $all = C4::Search::History::get({userid => $userid});
186 is( scalar(@$all), 2, 'There are still 2 searches after calling delete with an interval = 2 days' );
187 delete_all( $userid );
188
189 add( $userid, $current_sessionid, $previous_sessionid, $total, $query_cgi_b, $query_cgi_a );
190 C4::Search::History::delete({
191     userid => $userid,
192     interval => 5,
193     type => 'biblio',
194 });
195 $all = C4::Search::History::get({userid => $userid});
196 is( scalar(@$all), 8, 'There are still 9 searches after calling delete with an interval = 5 days for biblio' );
197 C4::Search::History::delete({
198     userid => $userid,
199     interval => 5,
200     type => 'authority',
201 });
202 $all = C4::Search::History::get({userid => $userid});
203 is( scalar(@$all), 6, 'There are still 6 searches after calling delete with an interval = 5 days for authority' );
204 C4::Search::History::delete({
205     userid => $userid,
206     interval => -1,
207 });
208 $all = C4::Search::History::get({userid => $userid});
209 is( scalar(@$all), 0, 'There is no search after calling delete with an interval = -1 days' );
210
211 # If time is null, it must be set to NOW()
212 my $query_desc_b1_p = q{first previous biblio search};
213 C4::Search::History::add( {
214     userid => $userid,
215     sessionid => $previous_sessionid,
216     query_desc => $query_desc_b1_p,
217     query_cgi => $query_cgi_b,
218     total => $total,
219     type => 'biblio',
220 });
221 my $search_history_id = $dbh->last_insert_id( undef, undef, 'search_history', undef );
222 my $search_history = C4::Search::History::get({ id => $search_history_id });
223 is( output_pref({ dt => dt_from_string($search_history->[0]->{time}), dateonly => 1 }), output_pref({ dt => dt_from_string, dateonly => 1 }), "Inserting a new search history should handle undefined time" );
224
225
226 delete_all( $userid );
227
228 sub add {
229     my ( $userid, $current_session_id, $previous_sessionid, $total, $query_cgi_b, $query_cgi_a ) = @_;
230
231     my $days_ago_2 = dt_from_string()->add_duration( DateTime::Duration->new( days => -2 ) );
232     my $days_ago_4 = dt_from_string()->add_duration( DateTime::Duration->new( days => -4 ) );
233     my $days_ago_6 = dt_from_string()->add_duration( DateTime::Duration->new( days => -6 ) );
234     my $days_ago_8 = dt_from_string()->add_duration( DateTime::Duration->new( days => -8 ) );
235
236     my $query_desc_b1_p = q{first previous biblio search};
237     my $first_previous_biblio_search = {
238         userid => $userid,
239         sessionid => $previous_sessionid,
240         query_desc => $query_desc_b1_p,
241         query_cgi => $query_cgi_b,
242         total => $total,
243         type => 'biblio',
244         time => $days_ago_2,
245     };
246
247     my $query_desc_a1_p = q{first previous authority search};
248     my $first_previous_authority_search = {
249         userid => $userid,
250         sessionid => $previous_sessionid,
251         query_desc => $query_desc_a1_p,
252         query_cgi => $query_cgi_a,
253         total => $total,
254         type => 'authority',
255         time => $days_ago_2,
256     };
257
258     my $query_desc_b2_p = q{second previous biblio search};
259     my $second_previous_biblio_search = {
260         userid => $userid,
261         sessionid => $previous_sessionid,
262         query_desc => $query_desc_b2_p,
263         query_cgi => $query_cgi_b,
264         total => $total,
265         type => 'biblio',
266         time => $days_ago_4,
267     };
268
269     my $query_desc_a2_p = q{second previous authority search};
270     my $second_previous_authority_search = {
271         userid => $userid,
272         sessionid => $previous_sessionid,
273         query_desc => $query_desc_a2_p,
274         query_cgi => $query_cgi_a,
275         total => $total,
276         type => 'authority',
277         time => $days_ago_4,
278     };
279
280
281     my $query_desc_b1_c = q{first current biblio search};
282
283     my $first_current_biblio_search = {
284         userid => $userid,
285         sessionid => $current_sessionid,
286         query_desc => $query_desc_b1_c,
287         query_cgi => $query_cgi_b,
288         total => $total,
289         type => 'biblio',
290         time => $days_ago_4,
291     };
292
293     my $query_desc_a1_c = q{first current authority search};
294     my $first_current_authority_search = {
295         userid => $userid,
296         sessionid => $current_sessionid,
297         query_desc => $query_desc_a1_c,
298         query_cgi => $query_cgi_a,
299         total => $total,
300         type => 'authority',
301         time => $days_ago_4,
302     };
303
304     my $query_desc_b2_c = q{second current biblio search};
305     my $second_current_biblio_search = {
306         userid => $userid,
307         sessionid => $current_sessionid,
308         query_desc => $query_desc_b2_c,
309         query_cgi => $query_cgi_b,
310         total => $total,
311         type => 'biblio',
312         time => $days_ago_6,
313     };
314
315     my $query_desc_a2_c = q{second current authority search};
316     my $second_current_authority_search = {
317         userid => $userid,
318         sessionid => $current_sessionid,
319         query_desc => $query_desc_a2_c,
320         query_cgi => $query_cgi_a,
321         total => $total,
322         type => 'authority',
323         time => $days_ago_6,
324     };
325
326     my $query_desc_a3_c = q{third current authority search};
327     my $third_current_authority_search = {
328         userid => $userid,
329         sessionid => $current_sessionid,
330         query_desc => $query_desc_a3_c,
331         query_cgi => $query_cgi_a,
332         total => $total,
333         type => 'authority',
334         time => $days_ago_8,
335     };
336
337
338     my $r = 0;
339     $r += C4::Search::History::add( $first_current_biblio_search );
340     $r += C4::Search::History::add( $first_current_authority_search );
341     $r += C4::Search::History::add( $second_current_biblio_search );
342     $r += C4::Search::History::add( $second_current_authority_search );
343     $r += C4::Search::History::add( $first_previous_biblio_search );
344     $r += C4::Search::History::add( $first_previous_authority_search );
345     $r += C4::Search::History::add( $second_previous_biblio_search );
346     $r += C4::Search::History::add( $second_previous_authority_search );
347     $r += C4::Search::History::add( $third_current_authority_search );
348     return $r;
349 }
350
351 sub delete_all {
352     my $userid = shift;
353     C4::Search::History::delete({
354         userid => $userid,
355     });
356 }
357
358 subtest 'LoadSearchHistoryToTheFirstLoggedUser working' => sub {
359 plan tests =>2;
360
361 my $query = new CGI;
362
363 my $schema = Koha::Database->schema;
364 my $builder = t::lib::TestBuilder->new;
365
366 # Borrower Creation
367 my $hash = hash_password('password');
368 our $patron = $builder->build( { source => 'Borrower' } );
369 Koha::Patrons->find( $patron->{borrowernumber} )->update_password( $patron->{userid}, $hash );
370
371 my $session = C4::Auth::get_session("");
372 $session->flush;
373
374 sub myMockedget_from_session {
375     my $expected_recent_searches = [
376         {
377             'time' => 1374978877,
378             'query_cgi' => 'cgi_test',
379             'total' => 2,
380             'query_desc' => 'kw,wrdl: history, '
381         }
382     ];
383     return @{$expected_recent_searches};
384
385 }
386
387 my $getfrom = new Test::MockModule( 'C4::Search::History' );
388 $getfrom->mock( 'get_from_session', \&myMockedget_from_session );
389
390 my $cgi = new Test::MockModule( 'CGI');
391 $cgi->mock('cookie', sub {
392    my ($self, $key) = @_;
393   if (!ref($key) && $key eq 'CGISESSID'){
394          return 'ID';
395    }
396 });
397
398 sub MockedCheckauth {
399     my ($query,$authnotrequired,$flagsrequired,$type) = @_;
400     my $userid = $patron->{userid};
401     my $sessionID = 234;
402     my $flags = {
403         superlibrarian    => 1, acquisition       => 0,
404         borrowers         => 0,
405         catalogue         => 1, circulate         => 0,
406         coursereserves    => 0, editauthorities   => 0,
407         editcatalogue     => 0, management        => 0,
408         parameters        => 0, permissions       => 0,
409         plugins           => 0, reports           => 0,
410         reserveforothers  => 0, serials           => 0,
411         staffaccess       => 0, tools             => 0,
412         updatecharges     => 0
413     };
414
415     my $session_cookie = $query->cookie(
416         -name => 'CGISESSID',
417         -value    => '9884013ae2c441d12e0bc9376242d2a8',
418         -HttpOnly => 1
419     );
420     return ( $userid, $session_cookie, $sessionID, $flags );
421 }
422
423 # Mock checkauth
424 my $auth = new Test::MockModule( 'C4::Auth' );
425 $auth->mock( 'checkauth', \&MockedCheckauth );
426
427 $query->param('koha_login_context', 'opac');
428 $query->param('userid', $patron->{userid});
429 $query->param('password', 'password');
430
431 # Test when the syspref is disabled
432 t::lib::Mocks::mock_preference('LoadSearchHistoryToTheFirstLoggedUser', 0);
433 my $result = $schema->resultset('SearchHistory')->search()->count;
434
435 my ( $template, $loggedinuser, $cookies ) = get_template_and_user(
436     {
437         template_name   => "opac-user.tt",
438         query           => $query,
439         type            => "opac",
440         authnotrequired => 0,
441         debug           => 1
442     }
443 );
444
445 my $result2 = $schema->resultset('SearchHistory')->search()->count;
446 is($result2, $result, 'no new search added to borrower');
447
448 # Test when the syspref is enabled
449 t::lib::Mocks::mock_preference('LoadSearchHistoryToTheFirstLoggedUser', 1);
450 $query->param('koha_login_context', 'opac');
451 $query->param('userid', $patron->{userid});
452 $query->param('password', 'password');
453 $query->cookie(
454         -name     => 'CGISESSID',
455         -value    => $session->id,
456         -HttpOnly => 1
457 );
458
459 $result = $schema->resultset('SearchHistory')->search()->count;
460
461 ( $template, $loggedinuser, $cookies ) = get_template_and_user(
462     {
463         template_name   => "opac-user.tt",
464         query           => $query,
465         type            => "opac",
466         authnotrequired => 0,
467         debug           => 1
468     }
469 );
470
471 $result2 = $schema->resultset('SearchHistory')->search()->count;
472 is($result2, $result+1, 'new search added to borrower');
473 };
474
475 $dbh->rollback;
476
477 done_testing;