blob: 54f2a8f07980f80b9fadd548d656a7aa23d2a27d [file] [log] [blame]
Akron0e1ed242018-10-11 13:22:00 +02001use Mojo::Base -strict;
2use Test::Mojo;
3use Test::More;
Akron32396632018-10-11 17:08:37 +02004use Mojo::File qw/path/;
Akron909ed082019-12-11 21:38:27 +01005use Kalamar::Controller::Search;
Akron32396632018-10-11 17:08:37 +02006
7
8#####################
9# Start Fake server #
10#####################
Akron63d963b2019-07-05 15:35:51 +020011my $mount_point = '/realapi/';
Akron32396632018-10-11 17:08:37 +020012$ENV{KALAMAR_API} = $mount_point;
Akron0e1ed242018-10-11 13:22:00 +020013
Akronc4177492023-11-29 08:35:37 +010014my $t = Test::Mojo->new('Kalamar' => {
15 Localize => {
16 dict => {
17 title_addon => 'Test'
18 }
19 }
20});
Akron0e1ed242018-10-11 13:22:00 +020021
Akron32396632018-10-11 17:08:37 +020022# Mount fake backend
23# Get the fixture path
Akron73f36082018-10-25 15:34:59 +020024my $fixtures_path = path(Mojo::File->new(__FILE__)->dirname, 'server');
Akron32396632018-10-11 17:08:37 +020025my $fake_backend = $t->app->plugin(
26 Mount => {
27 $mount_point =>
Akron73f36082018-10-25 15:34:59 +020028 $fixtures_path->child('mock.pl')
Akron32396632018-10-11 17:08:37 +020029 }
30);
31# Configure fake backend
32$fake_backend->pattern->defaults->{app}->log($t->app->log);
33
Akronbc6b3f22021-01-13 14:53:12 +010034my $q = qr!(?:\"|")!;
35
Akron0e1ed242018-10-11 13:22:00 +020036# Query passed
Akron58c60992021-09-07 13:11:43 +020037my $err = $t->get_ok('/?q=baum')
Akron0e1ed242018-10-11 13:22:00 +020038 ->status_is(200)
Akron69481a42021-03-22 10:31:16 +010039 ->content_type_is('text/html;charset=UTF-8')
Akron8ea84292018-10-24 13:41:52 +020040
Akronc4177492023-11-29 08:35:37 +010041 ->text_is('title', 'KorAP-Test: Find »baum« with Poliqarp')
42 ->element_exists('meta[name="DC.title"][content="KorAP-Test: Find »baum« with Poliqarp"]')
Akron0e1ed242018-10-11 13:22:00 +020043 ->element_exists('body[itemscope][itemtype="http://schema.org/SearchResultsPage"]')
Akrondffa9392018-10-12 16:26:09 +020044
45 # Total results
Akron32396632018-10-11 17:08:37 +020046 ->text_is('#total-results', 51)
Akrondffa9392018-10-12 16:26:09 +020047
48 # Total pages
Akron18a2a272020-06-16 11:47:38 +020049 ->element_count_is('#pagination > a', 5)
Akrondffa9392018-10-12 16:26:09 +020050
Akron9bd140e2021-07-27 16:20:03 +020051 ->element_exists_not('#resultinfo > #pagination')
52
Akrondffa9392018-10-12 16:26:09 +020053 # api_response
Akronbc6b3f22021-01-13 14:53:12 +010054 ->content_like(qr/${q}authorized${q}:null/)
55 ->content_like(qr/${q}pubDate${q},${q}subTitle${q},${q}author${q}/)
Akrondffa9392018-10-12 16:26:09 +020056
Akron8ea84292018-10-24 13:41:52 +020057 # No cutOff
Akronbc6b3f22021-01-13 14:53:12 +010058 ->content_unlike(qr!${q}cutOff${q}:true!)
Akron8ea84292018-10-24 13:41:52 +020059
Akrondffa9392018-10-12 16:26:09 +020060 ->element_exists('li[data-text-sigle=GOE/AGI/00000]')
61 ->element_exists('li:nth-of-type(1) div.flop')
62 ->element_exists('li[data-text-sigle=GOE/AGI/00001]')
63 ->element_exists('li:nth-of-type(2) div.flip')
64
65 # Match1
66 ->element_exists('li:nth-of-type(1)' .
67 '[data-match-id="p2030-2031"]' .
68 '[data-text-sigle="GOE/AGI/00000"]' .
69 '[id="GOE/AGI/00000#p2030-2031"]' .
70 '[data-available-info^="base/s=spans"]' .
71 '[data-info^="{"]')
72 ->text_is('li:nth-of-type(1) div.meta', 'GOE/AGI/00000')
73 ->element_exists('li:nth-of-type(1) div.match-main div.match-wrap div.snippet')
74 ->element_exists('li:nth-of-type(1) div.snippet.startMore.endMore')
75 ->text_like('li:nth-of-type(1) div.snippet span.context-left',qr!sie etwas bedeuten!)
76 ->text_like('li:nth-of-type(1) div.snippet span.context-left',qr!sie etwas bedeuten!)
77 ->text_is('li:nth-of-type(1) div.snippet span.match mark','Baum')
78 ->text_like('li:nth-of-type(1) div.snippet span.context-right',qr!es war!)
79 ->text_is('li:nth-of-type(1) p.ref strong', 'Italienische Reise')
80 ->text_like('li:nth-of-type(1) p.ref', qr!by Goethe, Johann Wolfgang!)
81 ->text_is('li:nth-of-type(1) p.ref time[datetime=1982]', 1982)
82 ->text_is('li:nth-of-type(1) p.ref span.sigle', '[GOE/AGI/00000]')
Akron8ea84292018-10-24 13:41:52 +020083 ->header_isnt('X-Kalamar-Cache', 'true')
Akron26d57f22021-09-10 16:48:57 +020084 ->attr_is('#pagination','data-page','1')
85 ->attr_is('#pagination','data-total','3')
86 ->attr_is('#pagination','data-count','25')
Akron58c60992021-09-07 13:11:43 +020087 ->tx->res->dom->at('#error')
Akron0e1ed242018-10-11 13:22:00 +020088 ;
Akron3422d452024-05-14 11:14:07 +020089
Akron58c60992021-09-07 13:11:43 +020090is(defined $err ? $err->text : '', '');
91
Akron3422d452024-05-14 11:14:07 +020092# Query passed
93$t->app->defaults(items_per_page => 20);
94
95$t->get_ok('/?q=baum')
96 ->status_is(200)
97 ->content_type_is('text/html;charset=UTF-8')
98 ->element_count_is('#pagination > a', 5)
99 ->attr_is('#pagination','data-page','1')
100 ->attr_is('#pagination','data-total','3')
101 ->attr_is('#pagination','data-count','20')
102;
103
104$t->app->defaults(items_per_page => 25);
Akron0e1ed242018-10-11 13:22:00 +0200105
Akron8ea84292018-10-24 13:41:52 +0200106$t->get_ok('/?q=[orth=das')
Akron7093b812018-10-19 17:28:21 +0200107 ->status_is(400)
108 ->text_is('div.notify-error:nth-of-type(1)', '302: Parantheses/brackets unbalanced.')
Akronbc33beb2018-11-30 13:46:08 +0100109 ->element_exists('#search')
Akron7093b812018-10-19 17:28:21 +0200110 ->text_like('div.notify-error:nth-of-type(2)', qr!302: Could not parse query .+? \[orth=das.+?!)
111 ;
112
Akron73f36082018-10-25 15:34:59 +0200113# Check for query error with ql (from remote.t)
114$t->get_ok('/?q=[orth=das&ql=poliqarp')
115 ->element_exists('.notify-error')
116 ->text_is('.notify-error', '302: Parantheses/brackets unbalanced.')
Akronbc6b3f22021-01-13 14:53:12 +0100117 ->content_like(qr!data-koralquery=!)
Akron3c390c42020-03-30 09:06:21 +0200118 ->text_is('.no-results:nth-of-type(1)', 'Unable to perform the action.')
Akron73f36082018-10-25 15:34:59 +0200119 ;
120
121
Akron8ea84292018-10-24 13:41:52 +0200122# Query with partial cache (for total results)
Akron58c60992021-09-07 13:11:43 +0200123$err = $t->get_ok('/?q=baum')
Akron8ea84292018-10-24 13:41:52 +0200124 ->status_is(200)
Akronc4177492023-11-29 08:35:37 +0100125 ->text_is('title', 'KorAP-Test: Find »baum« with Poliqarp')
126 ->element_exists('meta[name="DC.title"][content="KorAP-Test: Find »baum« with Poliqarp"]')
Akron8ea84292018-10-24 13:41:52 +0200127 ->element_exists('body[itemscope][itemtype="http://schema.org/SearchResultsPage"]')
128 ->header_isnt('X-Kalamar-Cache', 'true')
Akronbc6b3f22021-01-13 14:53:12 +0100129 ->content_like(qr!${q}cutOff${q}:true!)
Akron8ea84292018-10-24 13:41:52 +0200130 ->text_is('#total-results', 51)
Akron58c60992021-09-07 13:11:43 +0200131 ->tx->res->dom->at('#error')
Akron8ea84292018-10-24 13:41:52 +0200132 ;
Akron58c60992021-09-07 13:11:43 +0200133is(defined $err ? $err->text : '', '');
Akron8ea84292018-10-24 13:41:52 +0200134
Akron385249d2018-10-29 12:26:29 +0100135# Query without partial cache (unfortunately) (but no total results)
Akron58c60992021-09-07 13:11:43 +0200136$err = $t->get_ok('/?q=baum&cutoff=true')
Akron385249d2018-10-29 12:26:29 +0100137 ->status_is(200)
Akronc4177492023-11-29 08:35:37 +0100138 ->text_is('title', 'KorAP-Test: Find »baum« with Poliqarp')
139 ->element_exists('meta[name="DC.title"][content="KorAP-Test: Find »baum« with Poliqarp"]')
Akron385249d2018-10-29 12:26:29 +0100140 ->element_exists('body[itemscope][itemtype="http://schema.org/SearchResultsPage"]')
141 ->header_isnt('X-Kalamar-Cache', 'true')
Akronbc6b3f22021-01-13 14:53:12 +0100142 ->content_like(qr!${q}cutOff${q}:true!)
Akron385249d2018-10-29 12:26:29 +0100143 ->element_exists_not('#total-results')
Akron58c60992021-09-07 13:11:43 +0200144 ->tx->res->dom->at('#error')
Akron385249d2018-10-29 12:26:29 +0100145 ;
Akron58c60992021-09-07 13:11:43 +0200146is(defined $err ? $err->text : '', '');
Akron385249d2018-10-29 12:26:29 +0100147
148# Query with partial cache (but no total results)
Akron58c60992021-09-07 13:11:43 +0200149$err = $t->get_ok('/?q=baum&cutoff=true')
Akron385249d2018-10-29 12:26:29 +0100150 ->status_is(200)
Akronc4177492023-11-29 08:35:37 +0100151 ->text_is('title', 'KorAP-Test: Find »baum« with Poliqarp')
152 ->element_exists('meta[name="DC.title"][content="KorAP-Test: Find »baum« with Poliqarp"]')
Akron385249d2018-10-29 12:26:29 +0100153 ->element_exists('body[itemscope][itemtype="http://schema.org/SearchResultsPage"]')
154 ->header_is('X-Kalamar-Cache', 'true')
Akronbc6b3f22021-01-13 14:53:12 +0100155 ->content_like(qr!${q}cutOff${q}:true!)
Akron385249d2018-10-29 12:26:29 +0100156 ->element_exists_not('#total-results')
Akron58c60992021-09-07 13:11:43 +0200157 ->tx->res->dom->at('#error')
Akron385249d2018-10-29 12:26:29 +0100158 ;
Akron58c60992021-09-07 13:11:43 +0200159is(defined $err ? $err->text : '', '');
160
Akron385249d2018-10-29 12:26:29 +0100161
Akron8ea84292018-10-24 13:41:52 +0200162# Query with full cache
Akron58c60992021-09-07 13:11:43 +0200163$err = $t->get_ok('/?q=baum')
Akron8ea84292018-10-24 13:41:52 +0200164 ->status_is(200)
Akronc4177492023-11-29 08:35:37 +0100165 ->text_is('title', 'KorAP-Test: Find »baum« with Poliqarp')
166 ->element_exists('meta[name="DC.title"][content="KorAP-Test: Find »baum« with Poliqarp"]')
Akron8ea84292018-10-24 13:41:52 +0200167 ->element_exists('body[itemscope][itemtype="http://schema.org/SearchResultsPage"]')
168 ->header_is('X-Kalamar-Cache', 'true')
Akronbc6b3f22021-01-13 14:53:12 +0100169 ->content_like(qr!${q}cutOff${q}:true!)
Akron8ea84292018-10-24 13:41:52 +0200170 ->text_is('#total-results', 51)
Akron58c60992021-09-07 13:11:43 +0200171 ->tx->res->dom->at('#error')
Akron8ea84292018-10-24 13:41:52 +0200172 ;
Akron58c60992021-09-07 13:11:43 +0200173is(defined $err ? $err->text : '', '');
Akron8ea84292018-10-24 13:41:52 +0200174
175
176# Query with page information
Akronc23ce662021-12-14 12:39:42 +0100177$err = $t->get_ok('/?q=der&p=1&count=2' => { 'Accept-Language' => 'en-US, en, de-DE' })
Akron8ea84292018-10-24 13:41:52 +0200178 ->status_is(200)
Akronc4177492023-11-29 08:35:37 +0100179 ->text_is('title', 'KorAP-Test: Find »der« with Poliqarp')
Akron8ea84292018-10-24 13:41:52 +0200180
181 # Total results
182 ->text_is('#total-results', '14,581')
183
184 # Total pages
Akron18a2a272020-06-16 11:47:38 +0200185 ->element_count_is('#pagination > a', 7)
Akronc23ce662021-12-14 12:39:42 +0100186 ->text_is('#pagination a:nth-of-type(6) span', '7,291')
Akrona4b17f72021-11-04 15:37:02 +0100187 ->element_exists('#pagination a.ellipsis.inactive')
Akronbc6b3f22021-01-13 14:53:12 +0100188 ->content_like(qr!${q}count${q}:2!)
189 ->content_like(qr!${q}startIndex${q}:0!)
190 ->content_like(qr!${q}itemsPerPage${q}:2!)
Akron8ea84292018-10-24 13:41:52 +0200191
192 # No caching
193 ->header_isnt('X-Kalamar-Cache', 'true')
194
195 # Not searched for "der" before
Akronbc6b3f22021-01-13 14:53:12 +0100196 ->content_unlike(qr!${q}cutOff${q}:true!)
Akron26d57f22021-09-10 16:48:57 +0200197
198 ->attr_is('#pagination','data-page','1')
199 ->attr_is('#pagination','data-total','7291')
200 ->attr_is('#pagination','data-count','2')
201
Akron58c60992021-09-07 13:11:43 +0200202 ->tx->res->dom->at('#error')
Akron8ea84292018-10-24 13:41:52 +0200203 ;
Akron58c60992021-09-07 13:11:43 +0200204is(defined $err ? $err->text : '', '');
205
Akron8ea84292018-10-24 13:41:52 +0200206
Akron4c7cf952019-08-29 09:31:35 +0200207# Check pagination repetion of page
208my $next_href = $t->get_ok('/?q=der&p=1&count=2')
209 ->tx->res->dom->at('#pagination a[rel=next]')->attr('href');
210like($next_href, qr/p=2/);
211unlike($next_href, qr/p=1/);
212
Akron8ea84292018-10-24 13:41:52 +0200213# Query with page information - next page
Akronc23ce662021-12-14 12:39:42 +0100214$err = $t->get_ok('/?q=der&p=2&count=2' => { 'Accept-Language' => 'de-DE, en-US, en' })
Akron8ea84292018-10-24 13:41:52 +0200215 ->status_is(200)
Akronc4177492023-11-29 08:35:37 +0100216 ->text_is('div.logoaddon', 'Test')
217 ->text_is('title', 'KorAP-Test: Finde »der« mit Poliqarp')
Akronbc33beb2018-11-30 13:46:08 +0100218 ->element_exists('#search')
Akron8ea84292018-10-24 13:41:52 +0200219
220 # Total results
Akronc23ce662021-12-14 12:39:42 +0100221 ->text_is('#total-results', '14.581')
Akron8ea84292018-10-24 13:41:52 +0200222
223 # Total pages
Akron18a2a272020-06-16 11:47:38 +0200224 ->element_count_is('#pagination > a', 7)
Akronc23ce662021-12-14 12:39:42 +0100225 ->text_is('#pagination a:nth-of-type(6) span', '7.291')
Akronbc6b3f22021-01-13 14:53:12 +0100226 ->content_like(qr!${q}count${q}:2!)
227 ->content_like(qr!${q}itemsPerPage${q}:2!)
228 ->content_like(qr!${q}startIndex${q}:2!)
Akron8ea84292018-10-24 13:41:52 +0200229
Akron26d57f22021-09-10 16:48:57 +0200230 ->attr_is('#pagination','data-page','2')
231 ->attr_is('#pagination','data-total','7291')
232 ->attr_is('#pagination','data-count','2')
233
Akron8ea84292018-10-24 13:41:52 +0200234 # No caching
235 ->header_isnt('X-Kalamar-Cache', 'true')
Akronbc6b3f22021-01-13 14:53:12 +0100236 ->content_like(qr!${q}cutOff${q}:true!)
Akron58c60992021-09-07 13:11:43 +0200237 ->tx->res->dom->at('#error')
Akron8ea84292018-10-24 13:41:52 +0200238 ;
Akron58c60992021-09-07 13:11:43 +0200239is(defined $err ? $err->text : '', '');
240
Akron8ea84292018-10-24 13:41:52 +0200241
Akronc4be8192018-10-25 16:07:53 +0200242# Query with failing parameters
243$t->get_ok('/?q=fantastisch&ql=Fabelsprache')
244 ->status_is(400)
Akroncb5c1712021-01-26 18:01:04 +0100245 ->text_is('#notifications div.notify-error', 'Parameter "ql" invalid')
Akronbc33beb2018-11-30 13:46:08 +0100246 ->element_exists('#search')
Akroncb5c1712021-01-26 18:01:04 +0100247 ->element_count_is('#notifications div.notify-error', 1)
Akronc4be8192018-10-25 16:07:53 +0200248 ;
249$t->get_ok('/?q=fantastisch&cutoff=no')
250 ->status_is(400)
Akroncb5c1712021-01-26 18:01:04 +0100251 ->text_is('#notifications div.notify-error', 'Parameter "cutoff" invalid')
252 ->element_count_is('#notifications div.notify-error', 1)
Akronc4be8192018-10-25 16:07:53 +0200253 ;
254$t->get_ok('/?q=fantastisch&p=hui&o=hui&count=-8')
255 ->status_is(400)
Akroncb5c1712021-01-26 18:01:04 +0100256 ->text_like('#notifications div.notify-error', qr!Parameter ".+?" invalid!)
257 ->element_count_is('#notifications div.notify-error', 3)
Akronc4be8192018-10-25 16:07:53 +0200258 ;
Akron8ea84292018-10-24 13:41:52 +0200259
Marc Kupietz4dc3d502022-07-06 16:50:14 +0200260# Long, but not too long query
261my $long_query = 'b' x 4096;
Akron58c60992021-09-07 13:11:43 +0200262$err = $t->get_ok('/?q=' . $long_query)
Akrond1ff8d82018-11-08 13:16:55 +0100263 ->status_is(400)
Marc Kupietz4dc3d502022-07-06 16:50:14 +0200264 ->text_like('#notifications div.notify-error', qr!Unable to load query response from!)
265 ->tx->res->dom->at('#error')
266 ;
267
268# Query too long
269my $too_long_query = 'b' x 4097;
270$err = $t->get_ok('/?q=' . $too_long_query)
271 ->status_is(400)
Akroncb5c1712021-01-26 18:01:04 +0100272 ->text_like('#notifications div.notify-error', qr!Parameter ".+?" invalid!)
Akron58c60992021-09-07 13:11:43 +0200273 ->tx->res->dom->at('#error')
Akrond1ff8d82018-11-08 13:16:55 +0100274 ;
Akron58c60992021-09-07 13:11:43 +0200275is(defined $err ? $err->text : '', '');
Akrond1ff8d82018-11-08 13:16:55 +0100276
Akrona3c353c2019-02-14 23:50:00 +0100277# Query with timeout
278$t->get_ok('/?q=timeout')
279 ->status_is(200)
Akroncb5c1712021-01-26 18:01:04 +0100280 ->text_like('#notifications div.notify-warn', qr!Response time exceeded!)
Akrona3c353c2019-02-14 23:50:00 +0100281 ->text_is('#total-results', '> 4,274,841');
282;
283
Akroncce055c2021-07-02 12:18:03 +0200284# Query with error
285$t->get_ok('/?q=error')
286 ->status_is(400)
287 ->text_is('#notifications .notify-error','500: Internal Server Error')
288;
289
Akrona3c353c2019-02-14 23:50:00 +0100290# Do not cache
291$t->get_ok('/?q=timeout')
292 ->status_is(200)
Akroncb5c1712021-01-26 18:01:04 +0100293 # ->text_like('#notifications div.notify-warning', qr!Response time exceeded!)
Akroncd42a142019-07-12 18:55:37 +0200294 ->element_exists("input#cq")
295 ->element_exists_not("input#cq[value]")
Akrona3c353c2019-02-14 23:50:00 +0100296 ->text_is('#total-results', '> 4,274,841');
297 ;
298
Akron91a76852019-08-28 12:35:37 +0200299$t->app->defaults(no_cache => 1);
300
Akroncd42a142019-07-12 18:55:37 +0200301# Query with collection
Akron58c60992021-09-07 13:11:43 +0200302$err = $t->get_ok('/?q=baum&collection=availability+%3D+%2FCC-BY.*%2F')
Akroncd42a142019-07-12 18:55:37 +0200303 ->status_is(200)
304 ->element_exists("input#cq[value='availability = /CC-BY.*/']")
Akronbc6b3f22021-01-13 14:53:12 +0100305 ->content_like(qr!${q}availability${q}!)
Akron58c60992021-09-07 13:11:43 +0200306 ->tx->res->dom->at('#error')
Akroncd42a142019-07-12 18:55:37 +0200307 ;
Akron58c60992021-09-07 13:11:43 +0200308is(defined $err ? $err->text : '', '');
309
Akroncd42a142019-07-12 18:55:37 +0200310
Akron4cdc4fc2020-04-28 12:19:11 +0200311$t->app->hook(
Akron7c87c1a2020-04-28 12:35:55 +0200312 after_search => sub {
Akron4cdc4fc2020-04-28 12:19:11 +0200313 my $c = shift;
314 $c->content_for('after_search_results' => '<p id="special">Funny</p>');
315 }
316);
317
Akroncd42a142019-07-12 18:55:37 +0200318# Query with corpus query
Akron58c60992021-09-07 13:11:43 +0200319$err = $t->get_ok('/?q=baum&cq=availability+%3D+%2FCC-BY.*%2F')
Akroncd42a142019-07-12 18:55:37 +0200320 ->status_is(200)
321 ->element_exists("input#cq[value='availability = /CC-BY.*/']")
Akronbc6b3f22021-01-13 14:53:12 +0100322 ->content_like(qr!${q}availability${q}!)
Akron4cdc4fc2020-04-28 12:19:11 +0200323 ->text_is('#special', 'Funny')
Akron58c60992021-09-07 13:11:43 +0200324 ->tx->res->dom->at('#error')
Akroncd42a142019-07-12 18:55:37 +0200325 ;
Akron58c60992021-09-07 13:11:43 +0200326is(defined $err ? $err->text : '', '');
Akron8ea84292018-10-24 13:41:52 +0200327
Akron909ed082019-12-11 21:38:27 +0100328my $match = {
329 matchID => 'match-FOLK/00070-SE-01/T-04-p5441-5442',
330 textSigle => 'FOLK/00070-SE-01/T-04'
331};
332
333$match = Kalamar::Controller::Search::_map_match($match);
334
335is($match->{matchID}, 'p5441-5442');
336
Akron7b9a1962020-07-02 09:52:53 +0200337# Query with pipe
Akron58c60992021-09-07 13:11:43 +0200338$err = $t->get_ok('/?q=baum&pipe=glemm')
Akron7b9a1962020-07-02 09:52:53 +0200339 ->status_is(200)
Akronbc6b3f22021-01-13 14:53:12 +0100340 ->content_like(qr/${q}pipes${q}:${q}glemm${q}/)
Akron58c60992021-09-07 13:11:43 +0200341 ->tx->res->dom->at('#error')
Akron7b9a1962020-07-02 09:52:53 +0200342 ;
Akron58c60992021-09-07 13:11:43 +0200343is(defined $err ? $err->text : '', '');
Akron7b9a1962020-07-02 09:52:53 +0200344
Akron909ed082019-12-11 21:38:27 +0100345
Akron0e1ed242018-10-11 13:22:00 +0200346done_testing;
Akron8ea84292018-10-24 13:41:52 +0200347__END__