Line 0
Link Here
|
0 |
- |
1 |
#!/usr/bin/env perl |
|
|
2 |
|
3 |
# This file is part of Koha. |
4 |
# |
5 |
# Koha is free software; you can redistribute it and/or modify it under the |
6 |
# terms of the GNU General Public License as published by the Free Software |
7 |
# Foundation; either version 3 of the License, or (at your option) any later |
8 |
# version. |
9 |
# |
10 |
# Koha is distributed in the hope that it will be useful, but WITHOUT ANY |
11 |
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR |
12 |
# A PARTICULAR PURPOSE. See the GNU General Public License for more details. |
13 |
# |
14 |
# You should have received a copy of the GNU General Public License along |
15 |
# with Koha; if not, write to the Free Software Foundation, Inc., |
16 |
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
17 |
|
18 |
use Modern::Perl; |
19 |
|
20 |
use Test::More tests => 1; |
21 |
use Test::Mojo; |
22 |
use Test::Warn; |
23 |
|
24 |
use t::lib::TestBuilder; |
25 |
use t::lib::Mocks; |
26 |
|
27 |
use C4::Auth; |
28 |
|
29 |
use Koha::Database; |
30 |
use Koha::IssuingRules; |
31 |
|
32 |
my $schema = Koha::Database->new->schema; |
33 |
my $builder = t::lib::TestBuilder->new; |
34 |
|
35 |
# FIXME: sessionStorage defaults to mysql, but it seems to break transaction handling |
36 |
# this affects the other REST api tests |
37 |
t::lib::Mocks::mock_preference( 'SessionStorage', 'tmp' ); |
38 |
|
39 |
my $remote_address = '127.0.0.1'; |
40 |
my $t = Test::Mojo->new('Koha::REST::V1'); |
41 |
|
42 |
subtest 'get_effective() tests' => sub { |
43 |
|
44 |
plan tests => 27; |
45 |
|
46 |
$schema->storage->txn_begin; |
47 |
|
48 |
# Empty current issuign rules and create two random issuing rules |
49 |
Koha::IssuingRules->search->delete; |
50 |
|
51 |
my $context1 = create_test_context(); |
52 |
my $context2 = create_test_context(); |
53 |
my $context3 = create_test_context(); |
54 |
|
55 |
create_issuing_rule({ |
56 |
categorycode => '*', |
57 |
itemtype => '*', |
58 |
branchcode => '*' |
59 |
}); |
60 |
create_issuing_rule(); |
61 |
create_issuing_rule(); |
62 |
create_issuing_rule({ |
63 |
categorycode => $context1->{patron}->{categorycode}, |
64 |
itemtype => $context1->{item}->{itype}, |
65 |
branchcode => '*' |
66 |
}); |
67 |
create_issuing_rule({ |
68 |
categorycode => $context2->{patron}->{categorycode}, |
69 |
itemtype => $context2->{item}->{itype}, |
70 |
branchcode => $context2->{patron}->{branchcode} |
71 |
}); |
72 |
create_issuing_rule({ |
73 |
categorycode => $context3->{patron}->{categorycode}, |
74 |
itemtype => $context3->{item}->{itype}, |
75 |
branchcode => $context3->{item}->{homebranch} |
76 |
}); |
77 |
create_issuing_rule({ |
78 |
categorycode => $context3->{patron}->{categorycode}, |
79 |
itemtype => $context3->{item}->{itype}, |
80 |
branchcode => $context3->{item}->{holdingbranch} |
81 |
}); |
82 |
my ( $borrowernumber, $session_id ) = |
83 |
create_user_and_session( { authorized => 0 } ); |
84 |
|
85 |
my $tx = $t->ua->build_tx( GET => '/api/v1/issuingrules/effective' ); |
86 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
87 |
$t->request_ok($tx) |
88 |
->status_is(401); |
89 |
|
90 |
$tx = $t->ua->build_tx( GET => '/api/v1/issuingrules/effective' ); |
91 |
$tx->req->cookies( { name => 'CGISESSID', value => $session_id } ); |
92 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
93 |
$t->request_ok($tx) |
94 |
->status_is(403); |
95 |
|
96 |
( $borrowernumber, $session_id ) = |
97 |
create_user_and_session( { authorized => 1 } ); |
98 |
|
99 |
my $path = '/api/v1/issuingrules/effective'; |
100 |
my $params = {}; |
101 |
|
102 |
$tx = $t->ua->build_tx( GET => _query_params($path, $params) ); |
103 |
$tx->req->cookies( { name => 'CGISESSID', value => $session_id } ); |
104 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
105 |
$t->request_ok($tx) |
106 |
->status_is(200) |
107 |
->json_is('/branchcode' => '*') |
108 |
->json_is('/categorycode' => '*') |
109 |
->json_is('/itemtype' => '*'); |
110 |
|
111 |
$params = { |
112 |
branchcode => '', |
113 |
categorycode => '', |
114 |
itemtype => '' |
115 |
}; |
116 |
$tx = $t->ua->build_tx( GET => _query_params($path, $params) ); |
117 |
$tx->req->cookies( { name => 'CGISESSID', value => $session_id } ); |
118 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
119 |
$t->request_ok($tx) |
120 |
->status_is(200) |
121 |
->json_is('/branchcode' => '*') |
122 |
->json_is('/categorycode' => '*') |
123 |
->json_is('/itemtype' => '*'); |
124 |
|
125 |
$params = { itemtype => $context1->{item}->{itype} }; |
126 |
$tx = $t->ua->build_tx( GET => _query_params($path, $params) ); |
127 |
$tx->req->cookies( { name => 'CGISESSID', value => $session_id } ); |
128 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
129 |
$t->request_ok($tx) |
130 |
->status_is(200) |
131 |
->json_is('/branchcode' => '*') |
132 |
->json_is('/categorycode' => '*') |
133 |
->json_is('/itemtype' => '*'); |
134 |
|
135 |
$params = { |
136 |
categorycode => $context1->{patron}->{categorycode}, |
137 |
itemtype => $context1->{item}->{itype} |
138 |
}; |
139 |
$tx = $t->ua->build_tx( GET => _query_params($path, $params) ); |
140 |
$tx->req->cookies( { name => 'CGISESSID', value => $session_id } ); |
141 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
142 |
$t->request_ok($tx) |
143 |
->status_is(200) |
144 |
->json_is('/branchcode' => '*') |
145 |
->json_is('/categorycode' => $context1->{patron}->{categorycode}) |
146 |
->json_is('/itemtype' => $context1->{item}->{itype}); |
147 |
|
148 |
subtest 'CircControl = ItemHomeLibrary' => sub { |
149 |
plan tests => 15; |
150 |
|
151 |
t::lib::Mocks::mock_preference('CircControl', 'ItemHomeLibrary'); |
152 |
t::lib::Mocks::mock_preference('HomeOrHoldingBranch', 'homebranch'); |
153 |
|
154 |
create_issuing_rule({ |
155 |
categorycode => $context3->{patron}->{categorycode}, |
156 |
itemtype => $context3->{item}->{itype}, |
157 |
branchcode => '*' |
158 |
}); |
159 |
|
160 |
$params = { |
161 |
cardnumber => $context3->{patron}->{cardnumber}, |
162 |
barcode => $context3->{item}->{barcode} |
163 |
}; |
164 |
# Test exact match, item's homebranch |
165 |
$tx = $t->ua->build_tx( GET => _query_params($path, $params) ); |
166 |
$tx->req->cookies( { name => 'CGISESSID', value => $session_id } ); |
167 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
168 |
$t->request_ok($tx) |
169 |
->status_is(200) |
170 |
->json_is('/branchcode' => $context3->{item}->{homebranch}) |
171 |
->json_is('/categorycode' => $context3->{patron}->{categorycode}) |
172 |
->json_is('/itemtype' => $context3->{item}->{itype}); |
173 |
|
174 |
t::lib::Mocks::mock_preference('HomeOrHoldingBranch', 'holdingbranch'); |
175 |
$params = { |
176 |
cardnumber => $context3->{patron}->{cardnumber}, |
177 |
barcode => $context3->{item}->{barcode} |
178 |
}; |
179 |
# Test exact match, holdingbranch |
180 |
$tx = $t->ua->build_tx( GET => _query_params($path, $params) ); |
181 |
$tx->req->cookies( { name => 'CGISESSID', value => $session_id } ); |
182 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
183 |
$t->request_ok($tx) |
184 |
->status_is(200) |
185 |
->json_is('/branchcode' => $context3->{item}->{holdingbranch}) |
186 |
->json_is('/categorycode' => $context3->{patron}->{categorycode}) |
187 |
->json_is('/itemtype' => $context3->{item}->{itype}); |
188 |
|
189 |
# Test custom branch |
190 |
$params->{'branchcode'} = $context2->{patron}->{branchcode}; |
191 |
$tx = $t->ua->build_tx( GET => _query_params($path, $params) ); |
192 |
$tx->req->cookies( { name => 'CGISESSID', value => $session_id } ); |
193 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
194 |
$t->request_ok($tx) |
195 |
->status_is(200) |
196 |
->json_is('/branchcode' => '*') |
197 |
->json_is('/categorycode' => $context3->{patron}->{categorycode}) |
198 |
->json_is('/itemtype' => $context3->{item}->{itype}); |
199 |
}; |
200 |
|
201 |
subtest 'CircControl = PatronLibrary' => sub { |
202 |
plan tests => 10; |
203 |
|
204 |
t::lib::Mocks::mock_preference('CircControl', 'PatronLibrary'); |
205 |
create_issuing_rule({ |
206 |
categorycode => $context2->{patron}->{categorycode}, |
207 |
itemtype => $context2->{item}->{itype}, |
208 |
branchcode => '*' |
209 |
}); |
210 |
$params = { |
211 |
itemnumber => $context2->{item}->{itemnumber}, |
212 |
borrowernumber => $context2->{patron}->{borrowernumber} |
213 |
}; |
214 |
# Test exact match |
215 |
$tx = $t->ua->build_tx( GET => _query_params($path, $params) ); |
216 |
$tx->req->cookies( { name => 'CGISESSID', value => $session_id } ); |
217 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
218 |
$t->request_ok($tx) |
219 |
->status_is(200) |
220 |
->json_is('/branchcode' => $context2->{patron}->{branchcode}) |
221 |
->json_is('/categorycode' => $context2->{patron}->{categorycode}) |
222 |
->json_is('/itemtype' => $context2->{item}->{itype}); |
223 |
|
224 |
# Test custom branchcode |
225 |
$params->{'branchcode'} = $context3->{patron}->{branchcode}; |
226 |
$tx = $t->ua->build_tx( GET => _query_params($path, $params) ); |
227 |
$tx->req->cookies( { name => 'CGISESSID', value => $session_id } ); |
228 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
229 |
$t->request_ok($tx) |
230 |
->status_is(200) |
231 |
->json_is('/branchcode' => '*') |
232 |
->json_is('/categorycode' => $context2->{patron}->{categorycode}) |
233 |
->json_is('/itemtype' => $context2->{item}->{itype}); |
234 |
}; |
235 |
|
236 |
subtest 'CircControl = PickupLibrary' => sub { |
237 |
plan tests => 15; |
238 |
|
239 |
t::lib::Mocks::mock_preference('CircControl', 'PickupLibrary'); |
240 |
my $patron = Koha::Patrons->find($borrowernumber); |
241 |
create_issuing_rule({ |
242 |
categorycode => $context2->{patron}->{categorycode}, |
243 |
itemtype => $context2->{item}->{itype}, |
244 |
branchcode => $patron->branchcode |
245 |
}); |
246 |
$params = { |
247 |
cardnumber => $context2->{patron}->{cardnumber}, |
248 |
barcode => $context2->{item}->{barcode} |
249 |
}; |
250 |
$tx = $t->ua->build_tx( GET => _query_params($path, $params) ); |
251 |
$tx->req->cookies( { name => 'CGISESSID', value => $session_id } ); |
252 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
253 |
$t->request_ok($tx) |
254 |
->status_is(200) |
255 |
->json_is('/branchcode' => $patron->branchcode) |
256 |
->json_is('/categorycode' => $context2->{patron}->{categorycode}) |
257 |
->json_is('/itemtype' => $context2->{item}->{itype}); |
258 |
|
259 |
$params = { |
260 |
cardnumber => $context2->{patron}->{cardnumber}, |
261 |
barcode => $context2->{item}->{barcode}, |
262 |
branchcode => '', |
263 |
}; |
264 |
# Test all branches |
265 |
$tx = $t->ua->build_tx( GET => _query_params($path, $params) ); |
266 |
$tx->req->cookies( { name => 'CGISESSID', value => $session_id } ); |
267 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
268 |
$t->request_ok($tx) |
269 |
->status_is(200) |
270 |
->json_is('/branchcode' => '*') |
271 |
->json_is('/categorycode' => $context2->{patron}->{categorycode}) |
272 |
->json_is('/itemtype' => $context2->{item}->{itype}); |
273 |
|
274 |
# Test another branch, should still return rule for all branches because |
275 |
# there is no exact match to that branchcode |
276 |
$params->{branchcode} = $context1->{patron}->{branchcode}; |
277 |
$tx = $t->ua->build_tx( GET => _query_params($path, $params) ); |
278 |
$tx->req->cookies( { name => 'CGISESSID', value => $session_id } ); |
279 |
$tx->req->env( { REMOTE_ADDR => $remote_address } ); |
280 |
$t->request_ok($tx) |
281 |
->status_is(200) |
282 |
->json_is('/branchcode' => '*') |
283 |
->json_is('/categorycode' => $context2->{patron}->{categorycode}) |
284 |
->json_is('/itemtype' => $context2->{item}->{itype}); |
285 |
}; |
286 |
|
287 |
$schema->storage->txn_rollback; |
288 |
}; |
289 |
|
290 |
sub create_test_context { |
291 |
my $itemtype = $builder->build({ source => 'Itemtype'}); |
292 |
my $library = $builder->build({ source => 'Branch' }); |
293 |
my $library2 = $builder->build({ source => 'Branch' }); |
294 |
my $biblio = $builder->build({ source => 'Biblio' }); |
295 |
my $biblioitem = $builder->build({ |
296 |
source => 'Biblioitem', |
297 |
value => { |
298 |
biblionumber => $biblio->{biblionumber}, |
299 |
itemtype => $itemtype->{itemtype}, |
300 |
} |
301 |
}); |
302 |
my $item = $builder->build({ |
303 |
source => 'Item', |
304 |
value => { |
305 |
biblionumber => $biblio->{biblionumber}, |
306 |
biblioitemnumber => $biblioitem->{biblioitemnumber}, |
307 |
itype => $itemtype->{itemtype}, |
308 |
homebranch => $library->{branchcode}, |
309 |
holdingbranch => $library2->{branchcode}, |
310 |
} |
311 |
}); |
312 |
my $category = $builder->build({ source => 'Category' }); |
313 |
my $patron = $builder->build({ |
314 |
source => 'Borrower', |
315 |
value => { |
316 |
categorycode => $category->{categorycode} |
317 |
} |
318 |
}); |
319 |
|
320 |
return { |
321 |
biblio => $biblio, |
322 |
biblioitem => $biblioitem, |
323 |
category => $category, |
324 |
item => $item, |
325 |
itemtype => $itemtype, |
326 |
library => $library, |
327 |
library_two => $library2, |
328 |
patron => $patron, |
329 |
}; |
330 |
} |
331 |
|
332 |
sub create_issuing_rule { |
333 |
my ($params) = @_; |
334 |
|
335 |
my $rule = $builder->build({ |
336 |
source => 'Issuingrule', |
337 |
value => $params |
338 |
}); |
339 |
|
340 |
return $rule; |
341 |
} |
342 |
sub create_user_and_session { |
343 |
|
344 |
my $args = shift; |
345 |
my $flags = ( $args->{authorized} ) ? $args->{authorized} : 0; |
346 |
my $dbh = C4::Context->dbh; |
347 |
|
348 |
my $user = $builder->build( |
349 |
{ |
350 |
source => 'Borrower', |
351 |
value => { |
352 |
flags => $flags, |
353 |
} |
354 |
} |
355 |
); |
356 |
|
357 |
# Create a session for the authorized user |
358 |
my $session = C4::Auth::get_session(''); |
359 |
$session->param( 'number', $user->{borrowernumber} ); |
360 |
$session->param( 'id', $user->{userid} ); |
361 |
$session->param( 'ip', '127.0.0.1' ); |
362 |
$session->param( 'lasttime', time() ); |
363 |
$session->flush; |
364 |
|
365 |
if ( $args->{authorized} ) { |
366 |
$dbh->do( " |
367 |
INSERT INTO user_permissions (borrowernumber,module_bit,code) |
368 |
VALUES (?,3,'manage_circ_rules')", undef, |
369 |
$user->{borrowernumber} ); |
370 |
} |
371 |
|
372 |
return ( $user->{borrowernumber}, $session->id ); |
373 |
} |
374 |
|
375 |
sub _query_params { |
376 |
my ($path, $params) = @_; |
377 |
|
378 |
$path .= '?'; |
379 |
foreach my $param (keys %$params) { |
380 |
$path .= $param.'='.$params->{$param}.'&'; |
381 |
} |
382 |
$path =~ s/\&$//; |
383 |
return $path; |
384 |
} |
385 |
1; |