1use strict; 2use warnings; 3use utf8; 4use Test::More; 5use Plack::Test; 6use Encode 'encode_utf8'; 7use HTTP::Request::Common; 8 9subtest 'Query parameters' => sub { 10 { 11 package App::Basic; ## no critic 12 use Dancer2; 13 get '/' => sub { 14 my $params = query_parameters; 15 ::isa_ok( 16 $params, 17 'Hash::MultiValue', 18 'parameters keyword', 19 ); 20 21 ::is( $params->get('foo'), 'bar', 'Got single value' ); 22 ::is( 23 $params->get('bar'), 24 'quux', 25 'Got single value from multi key', 26 ); 27 28 ::is_deeply( 29 [ $params->get_all('bar') ], 30 ['baz', 'quux'], 31 'Got multi value from multi key', 32 ); 33 34 ::is( 35 $params->get('baz'), 36 'הלו', 37 'HMV interface returns encoded values', 38 ); 39 40 ::is( 41 params->{'baz'}, 42 'הלו', 43 'Regular interface returns encoded values' 44 ); 45 }; 46 } 47 48 my $app = Plack::Test->create( App::Basic->to_app ); 49 my $res = $app->request( GET '/?foo=bar&bar=baz&bar=quux&baz=הלו' ); 50 ok( $res->is_success, 'Successful request' ); 51}; 52 53subtest 'Body parameters' => sub { 54 { 55 package App::Body; ## no critic 56 use Dancer2; 57 post '/' => sub { 58 my $params = body_parameters; 59 ::isa_ok( 60 $params, 61 'Hash::MultiValue', 62 'parameters keyword', 63 ); 64 65 ::is( $params->get('foo'), 'bar', 'Got single value' ); 66 ::is( 67 $params->get('bar'), 68 'quux', 69 'Got single value from multi key', 70 ); 71 72 my $z = [ $params->get_all('bar') ]; 73 ::is_deeply( 74 [ $params->get_all('bar') ], 75 ['baz', 'quux'], 76 'Got multi value from multi key', 77 ); 78 79 ::is( 80 $params->get('baz'), 81 'הלו', 82 'HMV interface returns encoded values', 83 ); 84 85 ::is( 86 params->{'baz'}, 87 'הלו', 88 'Regular interface returns encoded values' 89 ); 90 }; 91 } 92 93 my $app = Plack::Test->create( App::Body->to_app ); 94 my $res = $app->request( 95 POST '/', 96 Content => [foo => 'bar', bar => 'baz', bar => 'quux', baz => 'הלו'] 97 ); 98 ok( $res->is_success, 'Successful request' ); 99}; 100 101subtest 'Body parameters with serialized data' => sub { 102 { 103 package App::Body::JSON; ## no critic 104 use Dancer2; 105 set serializer => 'JSON'; 106 post '/' => sub { 107 my $params = body_parameters; 108 ::isa_ok( 109 $params, 110 'Hash::MultiValue', 111 'parameters keyword', 112 ); 113 114 ::is( $params->get('foo'), 'bar', 'Got single value' ); 115 ::is( 116 $params->get('bar'), 117 'quux', 118 'Got single value from multi key', 119 ); 120 121 my $z = [ $params->get_all('bar') ]; 122 ::is_deeply( 123 [ $params->get_all('bar') ], 124 ['baz', 'quux'], 125 'Got multi value from multi key', 126 ); 127 128 ::is( 129 $params->get('baz'), 130 'הלו', 131 'HMV interface returns encoded values', 132 ); 133 134 ::is( 135 params->{'baz'}, 136 'הלו', 137 'Regular interface returns encoded values' 138 ); 139 140 return { ok => 1 }; 141 }; 142 } 143 144 my $app = Plack::Test->create( App::Body::JSON->to_app ); 145 my $baz = encode_utf8('הלו'); 146 my $res = $app->request( 147 POST '/', Content => qq{{"foo":"bar","bar":["baz","quux"],"baz":"$baz"}} 148 ); 149 ok( $res->is_success, 'Successful request' ); 150}; 151 152subtest 'Route parameters' => sub { 153 { 154 package App::Route; ## no critic 155 use Dancer2; 156 get '/:foo' => sub { 157 my $params = route_parameters; 158 ::isa_ok( 159 $params, 160 'Hash::MultiValue', 161 'parameters keyword', 162 ); 163 164 ::is( $params->get('foo'), 'bar', 'Got keyed value' ); 165 }; 166 167 get '/:name/:value' => sub { 168 my $params = route_parameters; 169 ::isa_ok( 170 $params, 171 'Hash::MultiValue', 172 'parameters keyword returns Hash::MultiValue object', 173 ); 174 175 ::is( $params->get('name'), 'foo', 'Got first value' ); 176 ::is( $params->get('value'), 'הלו', 'Got second value' ); 177 ::is( 178 params->{'value'}, 179 'הלו', 180 'Regular interface returns encoded values' 181 ); 182 }; 183 } 184 185 my $app = Plack::Test->create( App::Route->to_app ); 186 187 { 188 my $res = $app->request( GET '/bar' ); 189 ok( $res->is_success, 'Successful request' ); 190 } 191 192 { 193 my $res = $app->request( GET '/foo/הלו' ); 194 ok( $res->is_success, 'Successful request' ); 195 } 196}; 197 198subtest 'Splat and megasplat route parameters' => sub { 199 { 200 package App::Route::Splat; ## no critic 201 use Dancer2; 202 get '/*' => sub { 203 my $params = route_parameters; 204 ::isa_ok( 205 $params, 206 'Hash::MultiValue', 207 'parameters keyword', 208 ); 209 210 ::is_deeply( 211 { %{$params} }, 212 {}, 213 'All route parameters are empty', 214 ); 215 216 ::is_deeply( 217 [ splat ], 218 [ 'foo' ], 219 'Got splat values', 220 ); 221 }; 222 223 get '/*/*' => sub { 224 my $params = route_parameters; 225 ::isa_ok( 226 $params, 227 'Hash::MultiValue', 228 'parameters keyword returns Hash::MultiValue object', 229 ); 230 231 232 ::is_deeply( 233 { %{$params} }, 234 {}, 235 'All route parameters are empty', 236 ); 237 238 ::is_deeply( 239 [ splat ], 240 [ qw<foo bar> ], 241 'Got splat values', 242 ); 243 }; 244 245 # /foo/bar/baz/quux/quuks 246 get '/*/*/*/**' => sub { 247 my $params = route_parameters; 248 ::isa_ok( 249 $params, 250 'Hash::MultiValue', 251 'parameters keyword returns Hash::MultiValue object', 252 ); 253 254 255 ::is_deeply( 256 { %{$params} }, 257 {}, 258 'All route parameters are empty', 259 ); 260 261 ::is_deeply( 262 [ splat ], 263 [ qw<foo bar baz>, [ qw<quux quuks> ] ], 264 'Got splat values', 265 ); 266 }; 267 268 # /foo/bar/baz 269 get '/*/:foo/**' => sub { 270 my $params = route_parameters; 271 ::isa_ok( 272 $params, 273 'Hash::MultiValue', 274 'parameters keyword returns Hash::MultiValue object', 275 ); 276 277 ::is( $params->get('foo'), 'bar', 'Correct route parameter' ); 278 279 ::is_deeply( 280 [ splat ], 281 [ 'foo', ['baz', ''] ], 282 'Got splat values', 283 ); 284 }; 285 } 286 287 my $app = Plack::Test->create( App::Route::Splat->to_app ); 288 289 { 290 my $res = $app->request( GET '/foo' ); 291 ok( $res->is_success, 'Successful request' ); 292 } 293 294 { 295 my $res = $app->request( GET '/foo/bar' ); 296 ok( $res->is_success, 'Successful request' ); 297 } 298 299 { 300 my $res = $app->request( GET '/foo/bar/baz/quux/quuks' ); 301 ok( $res->is_success, 'Successful request' ); 302 } 303 304 { 305 my $res = $app->request( GET '/foo/bar/baz/' ); 306 ok( $res->is_success, 'Successful request' ); 307 } 308}; 309 310subtest 'Captured route parameters' => sub { 311 { 312 package App::Route::Capture; ## no critic 313 use Dancer2; 314 get qr{^/foo/([^/]+)$} => sub { 315 my $params = route_parameters; 316 ::isa_ok( 317 $params, 318 'Hash::MultiValue', 319 'parameters keyword', 320 ); 321 322 ::is_deeply( 323 { %{$params} }, 324 {}, 325 'All route parameters are empty', 326 ); 327 328 ::is_deeply( 329 [ splat ], 330 ['bar'], 331 'Correct splat values', 332 ); 333 334 ::is_deeply( 335 captures(), 336 +{}, 337 'capture values are empty', 338 ); 339 }; 340 } 341 342 my $app = Plack::Test->create( App::Route::Capture->to_app ); 343 344 { 345 my $res = $app->request( GET '/foo/bar' ); 346 ok( $res->is_success, 'Successful request' ); 347 } 348}; 349 350SKIP: { 351 Test::More::skip "named captures not available until 5.10", 1 352 if !$^V or $^V lt v5.10; 353 354 subtest 'Named captured route parameters' => sub { 355 { 356 package App::Route::NamedCapture; ## no critic 357 use Dancer2; 358 my $re = '^/bar/(?<baz>[^/]+)$'; 359 get qr{$re} => sub { 360 my $params = route_parameters; 361 362 ::isa_ok( 363 $params, 364 'Hash::MultiValue', 365 'parameters keyword', 366 ); 367 368 ::is_deeply( 369 { %{$params} }, 370 {}, 371 'All route parameters are empty', 372 ); 373 374 ::is_deeply( 375 [ splat ], 376 [], 377 'splat values are empty', 378 ); 379 380 ::is_deeply( 381 captures(), 382 { baz => 'quux' }, 383 'Correct capture values', 384 ); 385 }; 386 } 387 388 my $app = Plack::Test->create( App::Route::NamedCapture->to_app ); 389 390 { 391 my $res = $app->request( GET '/bar/quux' ); 392 ok( $res->is_success, 'Successful request' ); 393 }; 394 }; 395}; 396done_testing(); 397