1<?php 2/* 3 +------------------------------------------------------------------------+ 4 | Phalcon Framework | 5 +------------------------------------------------------------------------+ 6 | Copyright (c) 2011-2017 Phalcon Team (https://phalconphp.com) | 7 +------------------------------------------------------------------------+ 8 | This source file is subject to the New BSD License that is bundled | 9 | with this package in the file LICENSE.txt. | 10 | | 11 | If you did not receive a copy of the license and are unable to | 12 | obtain it through the world-wide-web, please send an email | 13 | to license@phalconphp.com so we can send you a copy immediately. | 14 +------------------------------------------------------------------------+ 15 */ 16 17namespace Phalcon\Test\Unit\Mvc; 18 19use Phalcon\Mvc\Micro; 20use Phalcon\Events\Event; 21use Phalcon\Events\Manager; 22use Phalcon\Di\FactoryDefault; 23use Phalcon\Test\Module\UnitTest; 24 25/** 26 * Phalcon\Test\Unit\Mvc\MicroTest 27 * 28 * Tests the Phalcon\Mvc\Micro component 29 * 30 * @package Phalcon\Test\Unit\Mvc 31 */ 32class MicroTest extends UnitTest 33{ 34 /** 35 * Tests after binding event 36 * 37 * @author Wojciech Ślawski <jurigag@gmail.com> 38 * @since 2016-11-19 39 */ 40 public function testAfterBindingEvent() 41 { 42 $this->specify( 43 'afterBinding event should be fired', 44 function () { 45 $di = new FactoryDefault(); 46 $micro = new Micro($di); 47 $manager = new Manager(); 48 $manager->attach( 49 'micro:afterBinding', 50 function (Event $event, Micro $micro) { 51 return false; 52 } 53 ); 54 $micro->setEventsManager($manager); 55 $micro->get( 56 '/test', 57 function () { 58 return 'test'; 59 } 60 ); 61 expect($micro->handle('/test'))->isEmpty(); 62 } 63 ); 64 } 65 66 /** 67 * Tests after binding middleware 68 * 69 * @author Wojciech Ślawski <jurigag@gmail.com> 70 * @since 2016-11-19 71 */ 72 public function testAfterBindingMiddleware() 73 { 74 $this->specify( 75 'afterBinding middleware should be called', 76 function () { 77 $di = new FactoryDefault(); 78 $micro = new Micro($di); 79 $micro->afterBinding( 80 function () { 81 return false; 82 } 83 ); 84 $micro->get( 85 '/test', 86 function () { 87 return 'test'; 88 } 89 ); 90 expect($micro->handle('/test'))->equals('test'); 91 } 92 ); 93 } 94 95 public function testStopMiddlewareOnAfterBindingClosure() 96 { 97 $this->specify( 98 "afterBinding middleware doesn't work as expected", 99 function () { 100 $di = new FactoryDefault(); 101 $micro = new Micro($di); 102 $micro->afterBinding( 103 function () use ($micro) { 104 $micro->stop(); 105 106 return false; 107 } 108 ); 109 $micro->get( 110 '/test', 111 function () { 112 return 'test'; 113 } 114 ); 115 expect($micro->handle('/test'))->isEmpty(); 116 } 117 ); 118 } 119 120 public function testStopMiddlewareOnAfterBindingClassFirst() 121 { 122 $this->specify( 123 "afterBinding middleware doesn't work as expected", 124 function () { 125 $di = new FactoryDefault(); 126 $micro = new Micro($di); 127 $middleware = new \MyMiddleware(); 128 $middlewareStop = new \MyMiddlewareStop(); 129 $micro->afterBinding($middlewareStop); 130 $micro->afterBinding($middleware); 131 $micro->afterBinding($middleware); 132 $micro->afterBinding($middleware); 133 $micro->get( 134 '/test', 135 function () { 136 return 'test'; 137 } 138 ); 139 expect($micro->handle('/test'))->isEmpty(); 140 expect($middlewareStop->getNumber())->equals(1); 141 expect($middleware->getNumber())->equals(0); 142 } 143 ); 144 } 145 146 public function testStopMiddlewareOnAfterBindingClass() 147 { 148 $this->specify( 149 "afterBinding middleware doesn't work as expected", 150 function () { 151 $di = new FactoryDefault(); 152 $micro = new Micro($di); 153 $middleware = new \MyMiddleware(); 154 $middlewareStop = new \MyMiddlewareStop(); 155 $micro->afterBinding($middleware); 156 $micro->afterBinding($middleware); 157 $micro->afterBinding($middleware); 158 $micro->afterBinding($middlewareStop); 159 $micro->afterBinding($middleware); 160 $micro->get( 161 '/test', 162 function () { 163 return 'test'; 164 } 165 ); 166 expect($micro->handle('/test'))->isEmpty(); 167 expect($middleware->getNumber())->equals(3); 168 expect($middlewareStop->getNumber())->equals(1); 169 } 170 ); 171 } 172 173 public function testMicroClass() 174 { 175 $this->specify( 176 "MVC Micro doesn't work as expected", 177 function () { 178 $handler = new \RestHandler(); 179 180 $app = new Micro(); 181 182 $app->get("/api/site", [$handler, "find"]); 183 $app->post("/api/site/save", [$handler, "save"]); 184 $app->delete("/api/site/delete/1", [$handler, "delete"]); 185 186 //Getting the url from _url using GET 187 $_SERVER["REQUEST_METHOD"] = "GET"; 188 $_GET["_url"] = "/api/site"; 189 190 $app->handle(); 191 192 expect($handler->getNumberAccess())->equals(1); 193 expect($handler->getTrace())->equals(["find"]); 194 195 //Getting the url from _url using POST 196 $_SERVER["REQUEST_METHOD"] = "POST"; 197 $_GET["_url"] = "/api/site/save"; 198 199 $app->handle(); 200 201 expect($handler->getNumberAccess())->equals(2); 202 expect($handler->getTrace())->equals(["find", "save"]); 203 204 //Passing directly a URI 205 $_SERVER["REQUEST_METHOD"] = "DELETE"; 206 $_GET["_url"] = null; 207 208 $app->handle("/api/site/delete/1"); 209 210 expect($handler->getNumberAccess())->equals(3); 211 expect($handler->getTrace())->equals(["find", "save", "delete"]); 212 } 213 ); 214 } 215 216 /** 217 * Tests the notFound 218 * 219 * @issue T169 220 * @author Nikos Dimopoulos <nikos@niden.net> 221 * @since 2012-11-06 222 */ 223 public function testMicroNotFoundT169() 224 { 225 $this->specify( 226 "MVC Micro notFound doesn't work", 227 function () { 228 $handler = new \RestHandler(); 229 230 $app = new Micro(); 231 232 $app->get("/api/site", [$handler, "find"]); 233 $app->post("/api/site/save", [$handler, "save"]); 234 235 $flag = false; 236 237 $app->notFound( 238 function () use (&$flag) { 239 $flag = true; 240 } 241 ); 242 243 $_SERVER["REQUEST_METHOD"] = "GET"; 244 $_GET["_url"] = "/fourohfour"; 245 246 $app->handle(); 247 248 expect($flag)->true(); 249 } 250 ); 251 } 252 253 public function testMicroBeforeHandlers() 254 { 255 $this->specify( 256 "Micro::before event handlers don't work as expected", 257 function () { 258 $trace = []; 259 260 $app = new Micro(); 261 262 $app->before( 263 function () use ($app, &$trace) { 264 $trace[] = 1; 265 $app->stop(); 266 267 return false; 268 } 269 ); 270 271 $app->before( 272 function () use ($app, &$trace) { 273 $trace[] = 1; 274 $app->stop(); 275 276 return false; 277 } 278 ); 279 280 $app->map( 281 "/blog", 282 function () use (&$trace) { 283 $trace[] = 1; 284 } 285 ); 286 287 $app->handle("/blog"); 288 289 expect($trace)->count(1); 290 } 291 ); 292 } 293 294 public function testMicroAfterHandlers() 295 { 296 $this->specify( 297 "Micro::after event handlers don't work as expected", 298 function () { 299 $trace = []; 300 301 $app = new Micro(); 302 303 $app->after( 304 function () use (&$trace) { 305 $trace[] = 1; 306 } 307 ); 308 309 $app->after( 310 function () use (&$trace) { 311 $trace[] = 1; 312 } 313 ); 314 315 $app->map( 316 "/blog", 317 function () use (&$trace) { 318 $trace[] = 1; 319 } 320 ); 321 322 $app->handle("/blog"); 323 324 expect($trace)->count(3); 325 } 326 ); 327 } 328 329 public function testMicroAfterHandlersIfOneStop() 330 { 331 $this->specify( 332 "Micro::finish event handlers don't work as expected", 333 function () { 334 $trace = array(); 335 336 $app = new Micro(); 337 338 $app->after( 339 function () use (&$trace) { 340 $trace[] = 1; 341 } 342 ); 343 344 $app->after( 345 function () use ($app, &$trace) { 346 $trace[] = 1; 347 $app->stop(); 348 } 349 ); 350 351 $app->after( 352 function () use (&$trace) { 353 $trace[] = 1; 354 } 355 ); 356 357 $app->map( 358 '/blog', 359 function () use (&$trace) { 360 $trace[] = 1; 361 } 362 ); 363 364 $app->handle('/blog'); 365 366 expect($trace)->count(3); 367 } 368 ); 369 } 370 371 public function testMicroFinishHandlers() 372 { 373 $this->specify( 374 "Micro::finish event handlers don't work as expected", 375 function () { 376 $trace = []; 377 378 $app = new Micro(); 379 380 $app->finish( 381 function () use (&$trace) { 382 $trace[] = 1; 383 } 384 ); 385 386 $app->finish( 387 function () use (&$trace) { 388 $trace[] = 1; 389 } 390 ); 391 392 $app->map( 393 "/blog", 394 function () use (&$trace) { 395 $trace[] = 1; 396 } 397 ); 398 399 $app->handle("/blog"); 400 401 expect($trace)->count(3); 402 } 403 ); 404 } 405 406 public function testMicroFinishHandlersIfOneStop() 407 { 408 $this->specify( 409 "Micro::finish event handlers don't work as expected", 410 function () { 411 $trace = array(); 412 413 $app = new Micro(); 414 415 $app->finish( 416 function () use (&$trace) { 417 $trace[] = 1; 418 } 419 ); 420 421 $app->finish( 422 function () use ($app, &$trace) { 423 $trace[] = 1; 424 $app->stop(); 425 } 426 ); 427 428 $app->finish( 429 function () use (&$trace) { 430 $trace[] = 1; 431 } 432 ); 433 434 $app->map( 435 '/blog', 436 function () use (&$trace) { 437 $trace[] = 1; 438 } 439 ); 440 441 $app->handle('/blog'); 442 443 expect($trace)->count(3); 444 } 445 ); 446 } 447 448 public function testMicroEvents() 449 { 450 $this->specify( 451 "Micro event handlers don't work as expected", 452 function () { 453 $trace = []; 454 455 $eventsManager = new Manager(); 456 457 $eventsManager->attach( 458 'micro', 459 function ($event) use (&$trace) { 460 $trace[$event->getType()] = true; 461 } 462 ); 463 464 $app = new Micro(); 465 466 $app->setEventsManager($eventsManager); 467 468 $app->map( 469 "/blog", 470 function () { 471 } 472 ); 473 474 $app->handle("/blog"); 475 476 expect($trace)->equals( 477 [ 478 'beforeHandleRoute' => true, 479 'beforeExecuteRoute' => true, 480 'afterExecuteRoute' => true, 481 'afterHandleRoute' => true, 482 'afterBinding' => true, 483 ] 484 ); 485 } 486 ); 487 } 488 489 public function testMicroMiddlewareSimple() 490 { 491 $this->specify( 492 "Micro before/after/finish events don't work as expected", 493 function () { 494 $app = new Micro(); 495 496 $app->map( 497 "/api/site", 498 function () { 499 return true; 500 } 501 ); 502 503 $trace = 0; 504 505 $app->before( 506 function () use (&$trace) { 507 $trace++; 508 } 509 ); 510 511 $app->before( 512 function () use (&$trace) { 513 $trace++; 514 } 515 ); 516 517 $app->after( 518 function () use (&$trace) { 519 $trace++; 520 } 521 ); 522 523 $app->after( 524 function () use (&$trace) { 525 $trace++; 526 } 527 ); 528 529 $app->finish( 530 function () use (&$trace) { 531 $trace++; 532 } 533 ); 534 535 $app->finish( 536 function () use (&$trace) { 537 $trace++; 538 } 539 ); 540 541 $app->handle("/api/site"); 542 543 expect($trace)->equals(6); 544 } 545 ); 546 } 547 548 public function testMicroMiddlewareClasses() 549 { 550 $this->specify( 551 "Micro middleware events don't work as expected", 552 function () { 553 $app = new Micro(); 554 555 $app->map( 556 "/api/site", 557 function () { 558 return true; 559 } 560 ); 561 562 $middleware = new \MyMiddleware(); 563 564 $app->before($middleware); 565 $app->before($middleware); 566 567 $app->after($middleware); 568 $app->after($middleware); 569 570 $app->finish($middleware); 571 $app->finish($middleware); 572 573 $app->handle("/api/site"); 574 575 expect($middleware->getNumber())->equals(6); 576 } 577 ); 578 } 579 580 public function testMicroStopMiddlewareOnBeforeClasses() 581 { 582 $this->specify( 583 "Micro middleware events don't work as expected", 584 function () { 585 $app = new Micro(); 586 587 $app->map( 588 "/api/site", 589 function () { 590 return true; 591 } 592 ); 593 594 $middleware = new \MyMiddlewareStop(); 595 596 $app->before($middleware); 597 $app->before($middleware); 598 599 $app->after($middleware); 600 $app->after($middleware); 601 602 $app->finish($middleware); 603 $app->finish($middleware); 604 605 $app->handle("/api/site"); 606 607 expect($middleware->getNumber())->equals(1); 608 } 609 ); 610 } 611 612 public function testMicroStopMiddlewareOnAfterAndFinishClasses() 613 { 614 $this->specify( 615 "Micro middleware events don't work as expected", 616 function () { 617 $app = new Micro(); 618 619 $app->map( 620 '/api/site', 621 function () { 622 return true; 623 } 624 ); 625 626 $middleware = new \MyMiddlewareStop(); 627 628 $app->after($middleware); 629 $app->after($middleware); 630 631 $app->finish($middleware); 632 $app->finish($middleware); 633 634 $app->handle('/api/site'); 635 636 expect($middleware->getNumber())->equals(2); 637 } 638 ); 639 } 640 641 public function testMicroResponseAlreadySentError() 642 { 643 $this->specify( 644 "Micro::handle method doesn't work as expected", 645 function () { 646 $app = new Micro(); 647 $app->after( 648 function () use ($app) { 649 $content = $app->getReturnedValue(); 650 $app->response->setJsonContent($content)->send(); 651 } 652 ); 653 $app->map( 654 '/api', 655 function () { 656 return 'success'; 657 } 658 ); 659 expect($app->handle('/api'))->equals('success'); 660 } 661 ); 662 } 663 664 public function testMicroCollectionVia() 665 { 666 $this->specify( 667 "Adding collection via doesn't work as exepected", 668 function () { 669 $app = new Micro(); 670 $collection = new Micro\Collection(); 671 $collection->setHandler(new \Test2Controller()); 672 $collection->mapVia( 673 "/test", 674 'indexAction', 675 ["POST", "GET"], 676 "test" 677 ); 678 $app->mount($collection); 679 expect($app->getRouter()->getRouteByName("test")->getHttpMethods())->equals(["POST", "GET"]); 680 } 681 ); 682 } 683} 684