Bug 32030: ERM - Add more API tests
[koha-ffzg.git] / t / db_dependent / api / v1 / search_filters.t
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
15 # along with Koha; if not, see <http://www.gnu.org/licenses>.
16
17 use Modern::Perl;
18
19 use Test::More tests => 5;
20 use Test::Mojo;
21 use Test::Warn;
22
23 use t::lib::TestBuilder;
24 use t::lib::Mocks;
25
26 use Koha::SearchFilters;
27 use Koha::Database;
28
29 my $schema  = Koha::Database->new->schema;
30 my $builder = t::lib::TestBuilder->new;
31
32 t::lib::Mocks::mock_preference( 'RESTBasicAuth', 1 );
33
34 my $t = Test::Mojo->new('Koha::REST::V1');
35
36 subtest 'list() tests' => sub {
37
38     plan tests => 6;
39
40     $schema->storage->txn_begin;
41
42     Koha::SearchFilters->search()->delete();
43
44     my $patron_1 = $builder->build_object({
45         class => 'Koha::Patrons',
46         value => { flags => 3 }
47     });
48     my $password = 'thePassword123';
49     $patron_1->set_password({ password => $password, skip_validation => 1 });
50     my $userid = $patron_1->userid;
51
52     # Create test context
53     my $search_filter_1 = $builder->build_object({ class => 'Koha::SearchFilters', value =>
54         {
55             name => 'Test1',
56             query => 'kw:this',
57             limits => 'mc-itype,phr:BK',
58             opac => 1,
59             staff_client => 1
60         }
61     });
62     my $search_filter_2 = $builder->build_object({ class => 'Koha::SearchFilters', value =>
63         {
64             name => 'Test2',
65             query => 'kw:that',
66             limits => 'mc-itype,phr:BK',
67             opac => 0,
68             staff_client => 1
69         }
70     });
71     my $search_filter_3 = $builder->build_object({ class => 'Koha::SearchFilters', value =>
72         {
73             name => 'Test3',
74             query => 'kw:any',
75             limits => 'mc-itype,phr:CD',
76             opac => 0,
77             staff_client => 0
78         }
79     });
80     my $search_filter_4 = $builder->build_object({ class => 'Koha::SearchFilters', value =>
81         {
82             name => 'Test4',
83             query => 'kw:some',
84             limits => 'mc-itype,phr:CD',
85             opac => 1,
86             staff_client => 0
87         }
88     });
89
90     # Make sure we are returned with the correct amount of macros
91     $t->get_ok( "//$userid:$password@/api/v1/search_filters" )
92       ->status_is( 200, 'SWAGGER3.2.2' )
93       ->json_has('/0/search_filter_id')
94       ->json_has('/1/search_filter_id')
95       ->json_has('/2/search_filter_id')
96       ->json_has('/3/search_filter_id');
97
98     $schema->storage->txn_rollback;
99 };
100
101 subtest 'get() tests' => sub {
102
103     plan tests => 9;
104
105     $schema->storage->txn_begin;
106
107     my $patron = $builder->build_object({
108         class => 'Koha::Patrons',
109         value => { flags => 3 }
110     });
111     my $password = 'thePassword123';
112     $patron->set_password({ password => $password, skip_validation => 1 });
113     my $userid = $patron->userid;
114
115     my $search_filter_1 = $builder->build_object( { class => 'Koha::SearchFilters' } );
116     my $search_filter_2 = $builder->build_object( { class => 'Koha::SearchFilters' } );
117     my $search_filter_3 = $builder->build_object( { class => 'Koha::SearchFilters' } );
118
119     $t->get_ok( "//$userid:$password@/api/v1/search_filters/" . $search_filter_1->id )
120       ->status_is( 200, 'Filter retrieved correctly' )
121       ->json_is( $search_filter_1->to_api );
122
123     my $non_existent_code = $search_filter_1->id;
124     $search_filter_1->delete;
125
126     $t->get_ok( "//$userid:$password@/api/v1/search_filters/" . $non_existent_code )
127       ->status_is(404)
128       ->json_is( '/error' => 'Search filter not found' );
129
130     $patron->flags(4)->store;
131     $t->get_ok( "//$userid:$password/api/v1/search_filters/" . $search_filter_2->id )
132       ->status_is( 401, 'Cannot search filters without permission' )
133       ->json_is( '/error' => 'Authentication failure.' );
134
135     $schema->storage->txn_rollback;
136 };
137
138 subtest 'add() tests' => sub {
139
140     plan tests => 17;
141
142     $schema->storage->txn_begin;
143
144     my $authorized_patron = $builder->build_object({
145         class => 'Koha::Patrons',
146         value => { flags => 0 }
147     });
148     $builder->build({
149         source => 'UserPermission',
150         value  => {
151             borrowernumber => $authorized_patron->borrowernumber,
152             module_bit     => 3,
153             code           => 'manage_search_filters',
154         },
155     });
156
157     my $password = 'thePassword123';
158     $authorized_patron->set_password({ password => $password, skip_validation => 1 });
159     my $auth_userid = $authorized_patron->userid;
160
161     my $unauthorized_patron = $builder->build_object({
162         class => 'Koha::Patrons',
163         value => { flags => 0 }
164     });
165     $unauthorized_patron->set_password({ password => $password, skip_validation => 1 });
166     my $unauth_userid = $unauthorized_patron->userid;
167
168     my $search_filter = $builder->build_object({ class => 'Koha::SearchFilters' });
169     my $search_filter_values = $search_filter->to_api;
170     delete $search_filter_values->{search_filter_id};
171     $search_filter->delete;
172
173     # Unauthorized attempt to write
174     $t->post_ok( "//$unauth_userid:$password@/api/v1/search_filters" => json => $search_filter_values )
175       ->status_is(403);
176
177     # Authorized attempt to write invalid data
178     my $search_filter_with_invalid_field = { %$search_filter_values };
179     $search_filter_with_invalid_field->{'coffee_filter'} = 'Chemex';
180
181     $t->post_ok( "//$auth_userid:$password@/api/v1/search_filters" => json => $search_filter_with_invalid_field )
182       ->status_is(400)
183       ->json_is(
184         "/errors" => [
185             {
186                 message => "Properties not allowed: coffee_filter.",
187                 path    => "/body"
188             }
189         ]
190     );
191
192     # Authorized attempt to write
193     $t->post_ok( "//$auth_userid:$password@/api/v1/search_filters" => json => $search_filter_values )
194       ->status_is( 201, 'SWAGGER3.2.1' )
195       ->json_has( '/search_filter_id', 'We generated a new id' )
196       ->json_is( '/name' => $search_filter_values->{name}, 'The name matches what we supplied' )
197       ->json_is( '/query' => $search_filter_values->{query}, 'The query matches what we supplied' )
198       ->json_is( '/limits' => $search_filter_values->{limits}, 'The limits match what we supplied' )
199       ->json_is( '/opac' => $search_filter_values->{opac}, 'The limits match what we supplied' )
200       ->json_is( '/staff_client' => $search_filter_values->{staff_client}, 'The limits match what we supplied' )
201       ->header_like( Location => qr|^\/api\/v1\/search_filters\/d*|, 'Correct location' );
202
203     # save the library_id
204     my $search_filter_id = 999;
205
206     # Authorized attempt to create with existing id
207     $search_filter_values->{search_filter_id} = $search_filter_id;
208
209     $t->post_ok( "//$auth_userid:$password@/api/v1/search_filters" => json => $search_filter_values )
210       ->status_is(400)
211       ->json_is( '/errors' => [
212             {
213                 message => "Read-only.",
214                 path   => "/body/search_filter_id"
215             }
216         ]
217     );
218
219     $schema->storage->txn_rollback;
220 };
221
222 subtest 'update() tests' => sub {
223
224     plan tests => 15;
225
226     $schema->storage->txn_begin;
227
228     my $authorized_patron = $builder->build_object({
229         class => 'Koha::Patrons',
230         value => { flags => 0 }
231     });
232     $builder->build({
233         source => 'UserPermission',
234         value  => {
235             borrowernumber => $authorized_patron->borrowernumber,
236             module_bit     => 3,
237             code           => 'manage_search_filters',
238         },
239     });
240
241     my $password = 'thePassword123';
242     $authorized_patron->set_password({ password => $password, skip_validation => 1 });
243     my $auth_userid = $authorized_patron->userid;
244
245     my $unauthorized_patron = $builder->build_object({
246         class => 'Koha::Patrons',
247         value => { flags => 0 }
248     });
249     $unauthorized_patron->set_password({ password => $password, skip_validation => 1 });
250     my $unauth_userid = $unauthorized_patron->userid;
251
252     my $search_filter = $builder->build_object({ class => 'Koha::SearchFilters' });
253     my $search_filter_id = $search_filter->id;
254     my $search_filter_values = $search_filter->to_api;
255     delete $search_filter_values->{search_filter_id};
256
257     # Unauthorized attempt to update
258     $t->put_ok( "//$unauth_userid:$password@/api/v1/search_filters/$search_filter_id"
259                     => json => { name => 'New unauthorized name change' } )
260       ->status_is(403);
261
262     my $search_filter_update = {
263         name   => "Filter update",
264         query  => "ti:The hobbit",
265         limits => "mc-ccode:fantasy",
266     };
267
268     my $test = $t->put_ok( "//$auth_userid:$password@/api/v1/search_filters/$search_filter_id" => json => $search_filter_update )
269       ->status_is(200, 'Authorized user can update a macro')
270       ->json_is( '/search_filter_id' => $search_filter_id, 'We get back the id' )
271       ->json_is( '/name'   => $search_filter_update->{name}, 'We get back the name' )
272       ->json_is( '/query'  => $search_filter_update->{query}, 'We get back our query' )
273       ->json_is( '/limits' => $search_filter_update->{limits}, 'We get back our limits' )
274       ->json_is( '/opac'   => 1, 'We get back our opac visibility unchanged' )
275       ->json_is( '/staff_client' => 1, 'We get back our staff client visibility unchanged' );
276
277     # Authorized attempt to write invalid data
278     my $search_filter_with_invalid_field = { %$search_filter_update };
279     $search_filter_with_invalid_field->{'coffee_filter'} = 'Chemex';
280
281     $t->put_ok( "//$auth_userid:$password@/api/v1/search_filters/$search_filter_id" => json => $search_filter_with_invalid_field )
282       ->status_is(400)
283       ->json_is(
284         "/errors" => [
285             {
286                 message => "Properties not allowed: coffee_filter.",
287                 path    => "/body"
288             }
289         ]
290     );
291
292     my $non_existent_macro = $builder->build_object({class => 'Koha::SearchFilters'});
293     my $non_existent_code = $non_existent_macro->id;
294     $non_existent_macro->delete;
295
296     $t->put_ok("//$auth_userid:$password@/api/v1/search_filters/$non_existent_code" => json => $search_filter_update)
297       ->status_is(404);
298
299     $schema->storage->txn_rollback;
300 };
301
302 subtest 'delete() tests' => sub {
303
304     plan tests => 4;
305
306     $schema->storage->txn_begin;
307
308     my $authorized_patron = $builder->build_object({
309         class => 'Koha::Patrons',
310         value => { flags => 0 }
311     });
312     $builder->build({
313         source => 'UserPermission',
314         value  => {
315             borrowernumber => $authorized_patron->borrowernumber,
316             module_bit     => 3,
317             code           => 'manage_search_filters',
318         },
319     });
320
321     my $password = 'thePassword123';
322     $authorized_patron->set_password({ password => $password, skip_validation => 1 });
323     my $auth_userid = $authorized_patron->userid;
324
325     my $unauthorized_patron = $builder->build_object({
326         class => 'Koha::Patrons',
327         value => { flags => 0 }
328     });
329     $unauthorized_patron->set_password({ password => $password, skip_validation => 1 });
330     my $unauth_userid = $unauthorized_patron->userid;
331
332     my $search_filter = $builder->build_object({ class => 'Koha::SearchFilters' });
333     my $search_filter_2 = $builder->build_object({ class => 'Koha::SearchFilters' });
334     my $search_filter_id = $search_filter->id;
335     my $search_filter_2_id = $search_filter_2->id;
336
337     # Unauthorized attempt to delete
338     $t->delete_ok( "//$unauth_userid:$password@/api/v1/search_filters/$search_filter_2_id")
339       ->status_is(403, "Cannot delete search filter without permission");
340
341     $t->delete_ok( "//$auth_userid:$password@/api/v1/search_filters/$search_filter_id")
342       ->status_is( 204, 'Can delete search filter with permission');
343
344     $schema->storage->txn_rollback;
345 };