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