Bug 25411: Regression tests
[koha.git] / t / db_dependent / Koha / REST / Plugin / PluginRoutes.t
1 #!/usr/bin/perl
2
3 # This file is part of Koha.
4 #
5 # Koha is free software; you can redistribute it and/or modify it
6 # under the terms of the GNU General Public License as published by
7 # the Free Software Foundation; either version 3 of the License, or
8 # (at your option) any later version.
9 #
10 # Koha is distributed in the hope that it will be useful, but
11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License
16 # along with Koha; if not, see <http://www.gnu.org/licenses>.
17
18 use Modern::Perl;
19
20 use Test::More tests => 4;
21 use Test::Mojo;
22 use Test::Warn;
23
24 use File::Basename;
25 use t::lib::Mocks;
26
27 use JSON::Validator::OpenAPI::Mojolicious;
28
29 # Dummy app for testing the plugin
30 use Mojolicious::Lite;
31
32 BEGIN {
33     # Mock pluginsdir before loading Plugins module
34     my $path = dirname(__FILE__) . '/../../../../lib';
35     t::lib::Mocks::mock_config( 'pluginsdir', $path );
36 }
37
38 use Koha::Database;
39 use Koha::Plugins;
40
41 my $schema = Koha::Database->new->schema;
42
43 subtest 'Bad plugins tests' => sub {
44
45     plan tests => 3;
46
47     $schema->storage->txn_begin;
48
49     # enable plugins
50     t::lib::Mocks::mock_config( 'enable_plugins', 1 );
51
52     # remove any existing plugins that might interfere
53     Koha::Plugins::Methods->search->delete;
54     my $plugins = Koha::Plugins->new;
55     $plugins->InstallPlugins;
56
57     my @plugins = $plugins->GetPlugins( { all => 1 } );
58     foreach my $plugin (@plugins) {
59         $plugin->enable;
60     }
61
62     # initialize Koha::REST::V1 after mocking
63     my $t;
64     warning_is
65         { $t = Test::Mojo->new('Koha::REST::V1'); }
66         'The resulting spec is invalid. Skipping Bad API Route Plugin',
67         'Bad plugins raise warning';
68
69     my $routes = get_defined_routes($t);
70     # Support placeholders () and <>  (latter style used starting with Mojolicious::Plugin::OpenAPI@1.28)
71     # TODO: remove () if minimum version is bumped to at least 1.28.
72     ok( !exists $routes->{'/contrib/badass/patrons/bother_wrong'}, 'Route doesn\'t exist' );
73     ok( exists $routes->{'/contrib/testplugin/patrons/bother'}, 'Route exists' );
74
75     $schema->storage->txn_rollback;
76 };
77
78 subtest 'Disabled plugins tests' => sub {
79
80     plan tests => 2;
81
82     $schema->storage->txn_begin;
83
84     # enable plugins
85     t::lib::Mocks::mock_config( 'enable_plugins', 1 );
86
87     my $good_plugin;
88
89     my $plugins = Koha::Plugins->new;
90     $plugins->InstallPlugins;
91
92     my @plugins = $plugins->GetPlugins( { all => 1 } );
93     foreach my $plugin (@plugins) {
94         $plugin->disable;
95         $good_plugin = $plugin
96             if $plugin->{metadata}->{description} eq 'Test plugin';
97     }
98
99     # initialize Koha::REST::V1 after mocking
100     my $t = Test::Mojo->new('Koha::REST::V1');
101
102     my $routes = get_defined_routes($t);
103     # Support placeholders () and <>  (latter style used starting with Mojolicious::Plugin::OpenAPI@1.28)
104     # TODO: remove () if minimum version is bumped to at least 1.28.
105     ok( !exists $routes->{'/contrib/testplugin/patrons/bother'},
106         'Plugin disabled, route not defined' );
107
108     $good_plugin->enable;
109
110     $t      = Test::Mojo->new('Koha::REST::V1');
111     $routes = get_defined_routes($t);
112
113     # Support placeholders () and <>  (latter style used starting with Mojolicious::Plugin::OpenAPI@1.28)
114     # TODO: remove () if minimum version is bumped to at least 1.28.
115     ok( exists $routes->{'/contrib/testplugin/patrons/bother'},
116         'Plugin enabled, route defined' );
117
118     $schema->storage->txn_rollback;
119 };
120
121 subtest 'Anonymous access routes plugins tests' => sub {
122
123     plan tests => 9;
124
125     $schema->storage->txn_begin;
126
127     # enable plugins
128     t::lib::Mocks::mock_config( 'enable_plugins', 1 );
129
130     # remove any existing plugins that might interfere
131     Koha::Plugins::Methods->search->delete;
132     my $plugins = Koha::Plugins->new;
133     $plugins->InstallPlugins;
134
135     my @plugins = $plugins->GetPlugins( { all => 1 } );
136     foreach my $plugin (@plugins) {
137         $plugin->enable;
138     }
139
140     # initialize Koha::REST::V1 after mocking
141     my $t;
142     warning_is
143         { $t = Test::Mojo->new('Koha::REST::V1'); }
144         'The resulting spec is invalid. Skipping Bad API Route Plugin',
145         'Bad plugins raise warning';
146
147     my $routes = get_defined_routes($t);
148     ok( exists $routes->{'/contrib/testplugin/patrons/bother'}, 'Route exists' );
149     ok( exists $routes->{'/contrib/testplugin/public/patrons/bother'}, 'Route exists' );
150
151     C4::Context->set_preference( 'RESTPublicAnonymousRequests', 0 );
152
153    $t->get_ok('/api/v1/contrib/testplugin/public/patrons/bother')
154      ->status_is(200, 'Plugin routes not affected by RESTPublicAnonymousRequests')
155      ->json_is( { bothered => Mojo::JSON->true } );
156
157     C4::Context->set_preference( 'RESTPublicAnonymousRequests', 1 );
158
159     $t->get_ok('/api/v1/contrib/testplugin/public/patrons/bother')
160       ->status_is(200, 'Plugin routes not affected by RESTPublicAnonymousRequests')
161       ->json_is( { bothered => Mojo::JSON->true } );
162
163     $schema->storage->txn_rollback;
164 };
165
166 subtest 'needs_install use case tests' => sub {
167
168     plan tests => 2;
169
170     $schema->storage->txn_begin;
171
172     # enable plugins
173     t::lib::Mocks::mock_config( 'enable_plugins', 1 );
174
175     my $good_plugin;
176
177     my $plugins = Koha::Plugins->new;
178     $plugins->InstallPlugins;
179
180     # mock Version before initializing the API class
181     t::lib::Mocks::mock_preference('Version', undef);
182     # initialize Koha::REST::V1 after mocking
183
184     my $t      = Test::Mojo->new('Koha::REST::V1');
185     my $routes = get_defined_routes($t);
186
187     # Support placeholders () and <>  (latter style used starting with Mojolicious::Plugin::OpenAPI@1.28)
188     # TODO: remove () if minimum version is bumped to at least 1.28.
189     ok(
190         !exists $routes->{'/contrib/testplugin/patrons/bother'},
191         'Plugin enabled, route not defined as C4::Context->needs_install is true'
192     );
193
194     t::lib::Mocks::mock_preference('Version', '3.0.0');
195
196     $schema->resultset('PluginData')->delete;
197     $plugins->InstallPlugins;
198
199     # re-initialize Koha::REST::V1 after mocking
200     $t      = Test::Mojo->new('Koha::REST::V1');
201     $routes = get_defined_routes($t);
202
203     # Support placeholders () and <>  (latter style used starting with Mojolicious::Plugin::OpenAPI@1.28)
204     # TODO: remove () if minimum version is bumped to at least 1.28.
205     ok(
206         exists $routes->{'/contrib/testplugin/patrons/bother'},
207         'Plugin enabled, route defined as C4::Context->needs_install is false'
208     );
209
210     $schema->storage->txn_rollback;
211 };
212
213 sub get_defined_routes {
214     my ($t) = @_;
215     my $routes = {};
216     traverse_routes( $_, 0, $routes ) for @{ $t->app->routes->children };
217
218     return $routes;
219 }
220
221 sub traverse_routes {
222     my ( $route, $depth, $routes ) = @_;
223
224     # Pattern
225     my $path = $route->pattern->unparsed || '/';
226
227     # Methods
228     my $via = $route->via;
229     my $verb = !$via ? '*' : uc join ',', @$via;
230     $routes->{$path}->{$verb} = 1;
231
232     $depth++;
233     traverse_routes( $_, $depth, $routes ) for @{ $route->children };
234     $depth--;
235 }