CakePHP
  • Documentation
    • Book
    • API
    • Videos
    • Logos & Trademarks
  • Business Solutions
  • Swag
  • Road Trip
  • Team
  • Community
    • Community
    • Team
    • Issues (Github)
    • YouTube Channel
    • Get Involved
    • Bakery
    • Featured Resources
    • Newsletter
    • Certification
    • My CakePHP
    • CakeFest
    • Facebook
    • Twitter
    • Help & Support
    • Forum
    • Stack Overflow
    • IRC
    • Slack
    • Paid Support
CakePHP

C CakePHP 3.8 Red Velvet API

  • Overview
  • Tree
  • Deprecated
  • Version:
    • 3.8
      • 3.8
      • 3.7
      • 3.6
      • 3.5
      • 3.4
      • 3.3
      • 3.2
      • 3.1
      • 3.0
      • 2.10
      • 2.9
      • 2.8
      • 2.7
      • 2.6
      • 2.5
      • 2.4
      • 2.3
      • 2.2
      • 2.1
      • 2.0
      • 1.3
      • 1.2

Namespaces

  • Cake
    • Auth
      • Storage
    • Cache
      • Engine
    • Collection
      • Iterator
    • Command
    • Console
      • Exception
    • Controller
      • Component
      • Exception
    • Core
      • Configure
        • Engine
      • Exception
      • Retry
    • Database
      • Driver
      • Exception
      • Expression
      • Schema
      • Statement
      • Type
    • Datasource
      • Exception
    • Error
      • Middleware
    • Event
      • Decorator
    • Filesystem
    • Form
    • Http
      • Client
        • Adapter
        • Auth
      • Cookie
      • Exception
      • Middleware
      • Session
    • I18n
      • Formatter
      • Middleware
      • Parser
    • Log
      • Engine
    • Mailer
      • Exception
      • Transport
    • Network
      • Exception
    • ORM
      • Association
      • Behavior
        • Translate
      • Exception
      • Locator
      • Rule
    • Routing
      • Exception
      • Filter
      • Middleware
      • Route
    • Shell
      • Helper
      • Task
    • TestSuite
      • Fixture
      • Stub
    • Utility
      • Exception
    • Validation
    • View
      • Exception
      • Form
      • Helper
      • Widget
  • None

Classes

  • ConsoleIntegrationTestCase
  • IntegrationTestCase
  • LegacyCommandRunner
  • LegacyShellDispatcher
  • TestCase
  • TestEmailTransport
  • TestSuite

Traits

  • ConsoleIntegrationTestTrait
  • EmailAssertTrait
  • EmailTrait
  • IntegrationTestTrait
  • StringCompareTrait
   1: <?php
   2: /**
   3:  * CakePHP(tm) : Rapid Development Framework (https://cakephp.org)
   4:  * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
   5:  *
   6:  * Licensed under The MIT License
   7:  * For full copyright and license information, please see the LICENSE.txt
   8:  * Redistributions of files must retain the above copyright notice
   9:  *
  10:  * @copyright     Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org)
  11:  * @since         3.7.0
  12:  * @license       https://opensource.org/licenses/mit-license.php MIT License
  13:  */
  14: namespace Cake\TestSuite;
  15: 
  16: use Cake\Core\Configure;
  17: use Cake\Database\Exception as DatabaseException;
  18: use Cake\Http\ServerRequest;
  19: use Cake\Http\Session;
  20: use Cake\Routing\Router;
  21: use Cake\TestSuite\Constraint\Response\BodyContains;
  22: use Cake\TestSuite\Constraint\Response\BodyEmpty;
  23: use Cake\TestSuite\Constraint\Response\BodyEquals;
  24: use Cake\TestSuite\Constraint\Response\BodyNotContains;
  25: use Cake\TestSuite\Constraint\Response\BodyNotEmpty;
  26: use Cake\TestSuite\Constraint\Response\BodyNotEquals;
  27: use Cake\TestSuite\Constraint\Response\BodyNotRegExp;
  28: use Cake\TestSuite\Constraint\Response\BodyRegExp;
  29: use Cake\TestSuite\Constraint\Response\ContentType;
  30: use Cake\TestSuite\Constraint\Response\CookieEncryptedEquals;
  31: use Cake\TestSuite\Constraint\Response\CookieEquals;
  32: use Cake\TestSuite\Constraint\Response\CookieNotSet;
  33: use Cake\TestSuite\Constraint\Response\CookieSet;
  34: use Cake\TestSuite\Constraint\Response\FileSent;
  35: use Cake\TestSuite\Constraint\Response\FileSentAs;
  36: use Cake\TestSuite\Constraint\Response\HeaderContains;
  37: use Cake\TestSuite\Constraint\Response\HeaderEquals;
  38: use Cake\TestSuite\Constraint\Response\HeaderNotContains;
  39: use Cake\TestSuite\Constraint\Response\HeaderNotSet;
  40: use Cake\TestSuite\Constraint\Response\HeaderSet;
  41: use Cake\TestSuite\Constraint\Response\StatusCode;
  42: use Cake\TestSuite\Constraint\Response\StatusError;
  43: use Cake\TestSuite\Constraint\Response\StatusFailure;
  44: use Cake\TestSuite\Constraint\Response\StatusOk;
  45: use Cake\TestSuite\Constraint\Response\StatusSuccess;
  46: use Cake\TestSuite\Constraint\Session\FlashParamEquals;
  47: use Cake\TestSuite\Constraint\Session\SessionEquals;
  48: use Cake\TestSuite\Constraint\View\LayoutFileEquals;
  49: use Cake\TestSuite\Constraint\View\TemplateFileEquals;
  50: use Cake\TestSuite\Stub\TestExceptionRenderer;
  51: use Cake\Utility\CookieCryptTrait;
  52: use Cake\Utility\Hash;
  53: use Cake\Utility\Security;
  54: use Cake\Utility\Text;
  55: use Cake\View\Helper\SecureFieldTokenTrait;
  56: use Exception;
  57: use LogicException;
  58: use PHPUnit\Exception as PhpunitException;
  59: use Zend\Diactoros\Uri;
  60: 
  61: /**
  62:  * A trait intended to make integration tests of your controllers easier.
  63:  *
  64:  * This test class provides a number of helper methods and features
  65:  * that make dispatching requests and checking their responses simpler.
  66:  * It favours full integration tests over mock objects as you can test
  67:  * more of your code easily and avoid some of the maintenance pitfalls
  68:  * that mock objects create.
  69:  */
  70: trait IntegrationTestTrait
  71: {
  72:     use CookieCryptTrait;
  73:     use SecureFieldTokenTrait;
  74: 
  75:     /**
  76:      * Track whether or not tests are run against
  77:      * the PSR7 HTTP stack.
  78:      *
  79:      * @var bool
  80:      */
  81:     protected $_useHttpServer = false;
  82: 
  83:     /**
  84:      * The customized application class name.
  85:      *
  86:      * @var string|null
  87:      */
  88:     protected $_appClass;
  89: 
  90:     /**
  91:      * The customized application constructor arguments.
  92:      *
  93:      * @var array|null
  94:      */
  95:     protected $_appArgs;
  96: 
  97:     /**
  98:      * The data used to build the next request.
  99:      *
 100:      * @var array
 101:      */
 102:     protected $_request = [];
 103: 
 104:     /**
 105:      * The response for the most recent request.
 106:      *
 107:      * @var \Cake\Http\Response|null
 108:      */
 109:     protected $_response;
 110: 
 111:     /**
 112:      * The exception being thrown if the case.
 113:      *
 114:      * @var \Exception|null
 115:      */
 116:     protected $_exception;
 117: 
 118:     /**
 119:      * Session data to use in the next request.
 120:      *
 121:      * @var array
 122:      */
 123:     protected $_session = [];
 124: 
 125:     /**
 126:      * Cookie data to use in the next request.
 127:      *
 128:      * @var array
 129:      */
 130:     protected $_cookie = [];
 131: 
 132:     /**
 133:      * The controller used in the last request.
 134:      *
 135:      * @var \Cake\Controller\Controller|null
 136:      */
 137:     protected $_controller;
 138: 
 139:     /**
 140:      * The last rendered view
 141:      *
 142:      * @var string|null
 143:      */
 144:     protected $_viewName;
 145: 
 146:     /**
 147:      * The last rendered layout
 148:      *
 149:      * @var string|null
 150:      */
 151:     protected $_layoutName;
 152: 
 153:     /**
 154:      * The session instance from the last request
 155:      *
 156:      * @var \Cake\Http\Session|null
 157:      */
 158:     protected $_requestSession;
 159: 
 160:     /**
 161:      * Boolean flag for whether or not the request should have
 162:      * a SecurityComponent token added.
 163:      *
 164:      * @var bool
 165:      */
 166:     protected $_securityToken = false;
 167: 
 168:     /**
 169:      * Boolean flag for whether or not the request should have
 170:      * a CSRF token added.
 171:      *
 172:      * @var bool
 173:      */
 174:     protected $_csrfToken = false;
 175: 
 176:     /**
 177:      * Boolean flag for whether or not the request should re-store
 178:      * flash messages
 179:      *
 180:      * @var bool
 181:      */
 182:     protected $_retainFlashMessages = false;
 183: 
 184:     /**
 185:      * Stored flash messages before render
 186:      *
 187:      * @var array|null
 188:      */
 189:     protected $_flashMessages;
 190: 
 191:     /**
 192:      *
 193:      * @var string|null
 194:      */
 195:     protected $_cookieEncryptionKey;
 196: 
 197:     /**
 198:      * List of fields that are excluded from field validation.
 199:      *
 200:      * @var string[]
 201:      */
 202:     protected $_unlockedFields = [];
 203: 
 204:     /**
 205:      * Auto-detect if the HTTP middleware stack should be used.
 206:      *
 207:      * @before
 208:      * @return void
 209:      */
 210:     public function setupServer()
 211:     {
 212:         $namespace = Configure::read('App.namespace');
 213:         $this->_useHttpServer = class_exists($namespace . '\Application');
 214:     }
 215: 
 216:     /**
 217:      * Clears the state used for requests.
 218:      *
 219:      * @after
 220:      * @return void
 221:      */
 222:     public function cleanup()
 223:     {
 224:         $this->_request = [];
 225:         $this->_session = [];
 226:         $this->_cookie = [];
 227:         $this->_response = null;
 228:         $this->_exception = null;
 229:         $this->_controller = null;
 230:         $this->_viewName = null;
 231:         $this->_layoutName = null;
 232:         $this->_requestSession = null;
 233:         $this->_appClass = null;
 234:         $this->_appArgs = null;
 235:         $this->_securityToken = false;
 236:         $this->_csrfToken = false;
 237:         $this->_retainFlashMessages = false;
 238:         $this->_useHttpServer = false;
 239:     }
 240: 
 241:     /**
 242:      * Toggle whether or not you want to use the HTTP Server stack.
 243:      *
 244:      * @param bool $enable Enable/disable the usage of the HTTP Stack.
 245:      * @return void
 246:      */
 247:     public function useHttpServer($enable)
 248:     {
 249:         $this->_useHttpServer = (bool)$enable;
 250:     }
 251: 
 252:     /**
 253:      * Configure the application class to use in integration tests.
 254:      *
 255:      * Combined with `useHttpServer()` to customize the class name and constructor arguments
 256:      * of your application class.
 257:      *
 258:      * @param string $class The application class name.
 259:      * @param array|null $constructorArgs The constructor arguments for your application class.
 260:      * @return void
 261:      */
 262:     public function configApplication($class, $constructorArgs)
 263:     {
 264:         $this->_appClass = $class;
 265:         $this->_appArgs = $constructorArgs;
 266:     }
 267: 
 268:     /**
 269:      * Calling this method will enable a SecurityComponent
 270:      * compatible token to be added to request data. This
 271:      * lets you easily test actions protected by SecurityComponent.
 272:      *
 273:      * @return void
 274:      */
 275:     public function enableSecurityToken()
 276:     {
 277:         $this->_securityToken = true;
 278:     }
 279: 
 280:     /**
 281:      * Set list of fields that are excluded from field validation.
 282:      *
 283:      * @param string[] $unlockedFields List of fields that are excluded from field validation.
 284:      * @return void
 285:      */
 286:     public function setUnlockedFields(array $unlockedFields = [])
 287:     {
 288:         $this->_unlockedFields = $unlockedFields;
 289:     }
 290: 
 291:     /**
 292:      * Calling this method will add a CSRF token to the request.
 293:      *
 294:      * Both the POST data and cookie will be populated when this option
 295:      * is enabled. The default parameter names will be used.
 296:      *
 297:      * @return void
 298:      */
 299:     public function enableCsrfToken()
 300:     {
 301:         $this->_csrfToken = true;
 302:     }
 303: 
 304:     /**
 305:      * Calling this method will re-store flash messages into the test session
 306:      * after being removed by the FlashHelper
 307:      *
 308:      * @return void
 309:      */
 310:     public function enableRetainFlashMessages()
 311:     {
 312:         $this->_retainFlashMessages = true;
 313:     }
 314: 
 315:     /**
 316:      * Configures the data for the *next* request.
 317:      *
 318:      * This data is cleared in the tearDown() method.
 319:      *
 320:      * You can call this method multiple times to append into
 321:      * the current state.
 322:      *
 323:      * @param array $data The request data to use.
 324:      * @return void
 325:      */
 326:     public function configRequest(array $data)
 327:     {
 328:         $this->_request = $data + $this->_request;
 329:     }
 330: 
 331:     /**
 332:      * Sets session data.
 333:      *
 334:      * This method lets you configure the session data
 335:      * you want to be used for requests that follow. The session
 336:      * state is reset in each tearDown().
 337:      *
 338:      * You can call this method multiple times to append into
 339:      * the current state.
 340:      *
 341:      * @param array $data The session data to use.
 342:      * @return void
 343:      */
 344:     public function session(array $data)
 345:     {
 346:         $this->_session = $data + $this->_session;
 347:     }
 348: 
 349:     /**
 350:      * Sets a request cookie for future requests.
 351:      *
 352:      * This method lets you configure the session data
 353:      * you want to be used for requests that follow. The session
 354:      * state is reset in each tearDown().
 355:      *
 356:      * You can call this method multiple times to append into
 357:      * the current state.
 358:      *
 359:      * @param string $name The cookie name to use.
 360:      * @param mixed $value The value of the cookie.
 361:      * @return void
 362:      */
 363:     public function cookie($name, $value)
 364:     {
 365:         $this->_cookie[$name] = $value;
 366:     }
 367: 
 368:     /**
 369:      * Returns the encryption key to be used.
 370:      *
 371:      * @return string
 372:      */
 373:     protected function _getCookieEncryptionKey()
 374:     {
 375:         if (isset($this->_cookieEncryptionKey)) {
 376:             return $this->_cookieEncryptionKey;
 377:         }
 378: 
 379:         return Security::getSalt();
 380:     }
 381: 
 382:     /**
 383:      * Sets a encrypted request cookie for future requests.
 384:      *
 385:      * The difference from cookie() is this encrypts the cookie
 386:      * value like the CookieComponent.
 387:      *
 388:      * @param string $name The cookie name to use.
 389:      * @param mixed $value The value of the cookie.
 390:      * @param string|bool $encrypt Encryption mode to use.
 391:      * @param string|null $key Encryption key used. Defaults
 392:      *   to Security.salt.
 393:      * @return void
 394:      * @see \Cake\Utility\CookieCryptTrait::_encrypt()
 395:      */
 396:     public function cookieEncrypted($name, $value, $encrypt = 'aes', $key = null)
 397:     {
 398:         $this->_cookieEncryptionKey = $key;
 399:         $this->_cookie[$name] = $this->_encrypt($value, $encrypt);
 400:     }
 401: 
 402:     /**
 403:      * Performs a GET request using the current request data.
 404:      *
 405:      * The response of the dispatched request will be stored as
 406:      * a property. You can use various assert methods to check the
 407:      * response.
 408:      *
 409:      * @param string|array $url The URL to request.
 410:      * @return void
 411:      * @throws \PHPUnit\Exception
 412:      */
 413:     public function get($url)
 414:     {
 415:         $this->_sendRequest($url, 'GET');
 416:     }
 417: 
 418:     /**
 419:      * Performs a POST request using the current request data.
 420:      *
 421:      * The response of the dispatched request will be stored as
 422:      * a property. You can use various assert methods to check the
 423:      * response.
 424:      *
 425:      * @param string|array $url The URL to request.
 426:      * @param string|array|null $data The data for the request.
 427:      * @return void
 428:      * @throws \PHPUnit\Exception
 429:      */
 430:     public function post($url, $data = [])
 431:     {
 432:         $this->_sendRequest($url, 'POST', $data);
 433:     }
 434: 
 435:     /**
 436:      * Performs a PATCH request using the current request data.
 437:      *
 438:      * The response of the dispatched request will be stored as
 439:      * a property. You can use various assert methods to check the
 440:      * response.
 441:      *
 442:      * @param string|array $url The URL to request.
 443:      * @param string|array|null $data The data for the request.
 444:      * @return void
 445:      * @throws \PHPUnit\Exception
 446:      */
 447:     public function patch($url, $data = [])
 448:     {
 449:         $this->_sendRequest($url, 'PATCH', $data);
 450:     }
 451: 
 452:     /**
 453:      * Performs a PUT request using the current request data.
 454:      *
 455:      * The response of the dispatched request will be stored as
 456:      * a property. You can use various assert methods to check the
 457:      * response.
 458:      *
 459:      * @param string|array $url The URL to request.
 460:      * @param string|array|null $data The data for the request.
 461:      * @return void
 462:      * @throws \PHPUnit\Exception
 463:      */
 464:     public function put($url, $data = [])
 465:     {
 466:         $this->_sendRequest($url, 'PUT', $data);
 467:     }
 468: 
 469:     /**
 470:      * Performs a DELETE request using the current request data.
 471:      *
 472:      * The response of the dispatched request will be stored as
 473:      * a property. You can use various assert methods to check the
 474:      * response.
 475:      *
 476:      * @param string|array $url The URL to request.
 477:      * @return void
 478:      * @throws \PHPUnit\Exception
 479:      */
 480:     public function delete($url)
 481:     {
 482:         $this->_sendRequest($url, 'DELETE');
 483:     }
 484: 
 485:     /**
 486:      * Performs a HEAD request using the current request data.
 487:      *
 488:      * The response of the dispatched request will be stored as
 489:      * a property. You can use various assert methods to check the
 490:      * response.
 491:      *
 492:      * @param string|array $url The URL to request.
 493:      * @return void
 494:      * @throws \PHPUnit\Exception
 495:      */
 496:     public function head($url)
 497:     {
 498:         $this->_sendRequest($url, 'HEAD');
 499:     }
 500: 
 501:     /**
 502:      * Performs an OPTIONS request using the current request data.
 503:      *
 504:      * The response of the dispatched request will be stored as
 505:      * a property. You can use various assert methods to check the
 506:      * response.
 507:      *
 508:      * @param string|array $url The URL to request.
 509:      * @return void
 510:      * @throws \PHPUnit\Exception
 511:      */
 512:     public function options($url)
 513:     {
 514:         $this->_sendRequest($url, 'OPTIONS');
 515:     }
 516: 
 517:     /**
 518:      * Creates and send the request into a Dispatcher instance.
 519:      *
 520:      * Receives and stores the response for future inspection.
 521:      *
 522:      * @param string|array $url The URL
 523:      * @param string $method The HTTP method
 524:      * @param string|array|null $data The request data.
 525:      * @return void
 526:      * @throws \PHPUnit\Exception
 527:      */
 528:     protected function _sendRequest($url, $method, $data = [])
 529:     {
 530:         $dispatcher = $this->_makeDispatcher();
 531:         $url = $dispatcher->resolveUrl($url);
 532: 
 533:         try {
 534:             $request = $this->_buildRequest($url, $method, $data);
 535:             $response = $dispatcher->execute($request);
 536:             $this->_requestSession = $request['session'];
 537:             if ($this->_retainFlashMessages && $this->_flashMessages) {
 538:                 $this->_requestSession->write('Flash', $this->_flashMessages);
 539:             }
 540:             $this->_response = $response;
 541:         } catch (PhpUnitException $e) {
 542:             throw $e;
 543:         } catch (DatabaseException $e) {
 544:             throw $e;
 545:         } catch (LogicException $e) {
 546:             throw $e;
 547:         } catch (Exception $e) {
 548:             $this->_exception = $e;
 549:             // Simulate the global exception handler being invoked.
 550:             $this->_handleError($e);
 551:         }
 552:     }
 553: 
 554:     /**
 555:      * Get the correct dispatcher instance.
 556:      *
 557:      * @return \Cake\TestSuite\MiddlewareDispatcher|\Cake\TestSuite\LegacyRequestDispatcher A dispatcher instance
 558:      */
 559:     protected function _makeDispatcher()
 560:     {
 561:         if ($this->_useHttpServer) {
 562:             return new MiddlewareDispatcher($this, $this->_appClass, $this->_appArgs);
 563:         }
 564: 
 565:         return new LegacyRequestDispatcher($this);
 566:     }
 567: 
 568:     /**
 569:      * Adds additional event spies to the controller/view event manager.
 570:      *
 571:      * @param \Cake\Event\Event $event A dispatcher event.
 572:      * @param \Cake\Controller\Controller|null $controller Controller instance.
 573:      * @return void
 574:      */
 575:     public function controllerSpy($event, $controller = null)
 576:     {
 577:         if (!$controller) {
 578:             /** @var \Cake\Controller\Controller $controller */
 579:             $controller = $event->getSubject();
 580:         }
 581:         $this->_controller = $controller;
 582:         $events = $controller->getEventManager();
 583:         $events->on('View.beforeRender', function ($event, $viewFile) use ($controller) {
 584:             if (!$this->_viewName) {
 585:                 $this->_viewName = $viewFile;
 586:             }
 587:             if ($this->_retainFlashMessages) {
 588:                 $this->_flashMessages = $controller->getRequest()->getSession()->read('Flash');
 589:             }
 590:         });
 591:         $events->on('View.beforeLayout', function ($event, $viewFile) {
 592:             $this->_layoutName = $viewFile;
 593:         });
 594:     }
 595: 
 596:     /**
 597:      * Attempts to render an error response for a given exception.
 598:      *
 599:      * This method will attempt to use the configured exception renderer.
 600:      * If that class does not exist, the built-in renderer will be used.
 601:      *
 602:      * @param \Exception $exception Exception to handle.
 603:      * @return void
 604:      * @throws \Exception
 605:      */
 606:     protected function _handleError($exception)
 607:     {
 608:         $class = Configure::read('Error.exceptionRenderer');
 609:         if (empty($class) || !class_exists($class)) {
 610:             $class = 'Cake\Error\ExceptionRenderer';
 611:         }
 612:         /** @var \Cake\Error\ExceptionRenderer $instance */
 613:         $instance = new $class($exception);
 614:         $this->_response = $instance->render();
 615:     }
 616: 
 617:     /**
 618:      * Creates a request object with the configured options and parameters.
 619:      *
 620:      * @param string|array $url The URL
 621:      * @param string $method The HTTP method
 622:      * @param string|array|null $data The request data.
 623:      * @return array The request context
 624:      */
 625:     protected function _buildRequest($url, $method, $data)
 626:     {
 627:         $sessionConfig = (array)Configure::read('Session') + [
 628:             'defaults' => 'php',
 629:         ];
 630:         $session = Session::create($sessionConfig);
 631:         $session->write($this->_session);
 632:         list($url, $query, $hostInfo) = $this->_url($url);
 633:         $tokenUrl = $url;
 634: 
 635:         if ($query) {
 636:             $tokenUrl .= '?' . $query;
 637:         }
 638: 
 639:         parse_str($query, $queryData);
 640:         $props = [
 641:             'url' => $url,
 642:             'session' => $session,
 643:             'query' => $queryData,
 644:             'files' => [],
 645:         ];
 646:         if (is_string($data)) {
 647:             $props['input'] = $data;
 648:         }
 649:         if (!isset($props['input'])) {
 650:             $data = $this->_addTokens($tokenUrl, $data);
 651:             $props['post'] = $this->_castToString($data);
 652:         }
 653:         $props['cookies'] = $this->_cookie;
 654: 
 655:         $env = [
 656:             'REQUEST_METHOD' => $method,
 657:             'QUERY_STRING' => $query,
 658:             'REQUEST_URI' => $url,
 659:         ];
 660:         if (!empty($hostInfo['ssl'])) {
 661:             $env['HTTPS'] = 'on';
 662:         }
 663:         if (isset($hostInfo['host'])) {
 664:             $env['HTTP_HOST'] = $hostInfo['host'];
 665:         }
 666:         if (isset($this->_request['headers'])) {
 667:             foreach ($this->_request['headers'] as $k => $v) {
 668:                 $name = strtoupper(str_replace('-', '_', $k));
 669:                 if (!in_array($name, ['CONTENT_LENGTH', 'CONTENT_TYPE'])) {
 670:                     $name = 'HTTP_' . $name;
 671:                 }
 672:                 $env[$name] = $v;
 673:             }
 674:             unset($this->_request['headers']);
 675:         }
 676:         $props['environment'] = $env;
 677:         $props = Hash::merge($props, $this->_request);
 678: 
 679:         return $props;
 680:     }
 681: 
 682:     /**
 683:      * Add the CSRF and Security Component tokens if necessary.
 684:      *
 685:      * @param string $url The URL the form is being submitted on.
 686:      * @param array $data The request body data.
 687:      * @return array The request body with tokens added.
 688:      */
 689:     protected function _addTokens($url, $data)
 690:     {
 691:         if ($this->_securityToken === true) {
 692:             $fields = array_diff_key($data, array_flip($this->_unlockedFields));
 693: 
 694:             $keys = array_map(function ($field) {
 695:                 return preg_replace('/(\.\d+)+$/', '', $field);
 696:             }, array_keys(Hash::flatten($fields)));
 697: 
 698:             $tokenData = $this->_buildFieldToken($url, array_unique($keys), $this->_unlockedFields);
 699: 
 700:             $data['_Token'] = $tokenData;
 701:             $data['_Token']['debug'] = 'SecurityComponent debug data would be added here';
 702:         }
 703: 
 704:         if ($this->_csrfToken === true) {
 705:             if (!isset($this->_cookie['csrfToken'])) {
 706:                 $this->_cookie['csrfToken'] = Text::uuid();
 707:             }
 708:             if (!isset($data['_csrfToken'])) {
 709:                 $data['_csrfToken'] = $this->_cookie['csrfToken'];
 710:             }
 711:         }
 712: 
 713:         return $data;
 714:     }
 715: 
 716:     /**
 717:      * Recursively casts all data to string as that is how data would be POSTed in
 718:      * the real world
 719:      *
 720:      * @param array $data POST data
 721:      * @return array
 722:      */
 723:     protected function _castToString($data)
 724:     {
 725:         foreach ($data as $key => $value) {
 726:             if (is_scalar($value)) {
 727:                 $data[$key] = $value === false ? '0' : (string)$value;
 728: 
 729:                 continue;
 730:             }
 731: 
 732:             if (is_array($value)) {
 733:                 $looksLikeFile = isset($value['error'], $value['tmp_name'], $value['size']);
 734:                 if ($looksLikeFile) {
 735:                     continue;
 736:                 }
 737: 
 738:                 $data[$key] = $this->_castToString($value);
 739:             }
 740:         }
 741: 
 742:         return $data;
 743:     }
 744: 
 745:     /**
 746:      * Creates a valid request url and parameter array more like Request::_url()
 747:      *
 748:      * @param string|array $url The URL
 749:      * @return array Qualified URL, the query parameters, and host data
 750:      */
 751:     protected function _url($url)
 752:     {
 753:         $uri = new Uri($url);
 754:         $path = $uri->getPath();
 755:         $query = $uri->getQuery();
 756: 
 757:         $hostData = [];
 758:         if ($uri->getHost()) {
 759:             $hostData['host'] = $uri->getHost();
 760:         }
 761:         if ($uri->getScheme()) {
 762:             $hostData['ssl'] = $uri->getScheme() === 'https';
 763:         }
 764: 
 765:         return [$path, $query, $hostData];
 766:     }
 767: 
 768:     /**
 769:      * Get the response body as string
 770:      *
 771:      * @return string The response body.
 772:      */
 773:     protected function _getBodyAsString()
 774:     {
 775:         if (!$this->_response) {
 776:             $this->fail('No response set, cannot assert content.');
 777:         }
 778: 
 779:         return (string)$this->_response->getBody();
 780:     }
 781: 
 782:     /**
 783:      * Fetches a view variable by name.
 784:      *
 785:      * If the view variable does not exist, null will be returned.
 786:      *
 787:      * @param string $name The view variable to get.
 788:      * @return mixed The view variable if set.
 789:      */
 790:     public function viewVariable($name)
 791:     {
 792:         if (empty($this->_controller->viewVars)) {
 793:             $this->fail('There are no view variables, perhaps you need to run a request?');
 794:         }
 795:         if (isset($this->_controller->viewVars[$name])) {
 796:             return $this->_controller->viewVars[$name];
 797:         }
 798: 
 799:         return null;
 800:     }
 801: 
 802:     /**
 803:      * Asserts that the response status code is in the 2xx range.
 804:      *
 805:      * @param string $message Custom message for failure.
 806:      * @return void
 807:      */
 808:     public function assertResponseOk($message = null)
 809:     {
 810:         $verboseMessage = $this->extractVerboseMessage($message);
 811:         $this->assertThat(null, new StatusOk($this->_response), $verboseMessage);
 812:     }
 813: 
 814:     /**
 815:      * Asserts that the response status code is in the 2xx/3xx range.
 816:      *
 817:      * @param string $message Custom message for failure.
 818:      * @return void
 819:      */
 820:     public function assertResponseSuccess($message = null)
 821:     {
 822:         $verboseMessage = $this->extractVerboseMessage($message);
 823:         $this->assertThat(null, new StatusSuccess($this->_response), $verboseMessage);
 824:     }
 825: 
 826:     /**
 827:      * Asserts that the response status code is in the 4xx range.
 828:      *
 829:      * @param string $message Custom message for failure.
 830:      * @return void
 831:      */
 832:     public function assertResponseError($message = null)
 833:     {
 834:         $this->assertThat(null, new StatusError($this->_response), $message);
 835:     }
 836: 
 837:     /**
 838:      * Asserts that the response status code is in the 5xx range.
 839:      *
 840:      * @param string $message Custom message for failure.
 841:      * @return void
 842:      */
 843:     public function assertResponseFailure($message = null)
 844:     {
 845:         $this->assertThat(null, new StatusFailure($this->_response), $message);
 846:     }
 847: 
 848:     /**
 849:      * Asserts a specific response status code.
 850:      *
 851:      * @param int $code Status code to assert.
 852:      * @param string $message Custom message for failure.
 853:      * @return void
 854:      */
 855:     public function assertResponseCode($code, $message = null)
 856:     {
 857:         $this->assertThat($code, new StatusCode($this->_response), $message);
 858:     }
 859: 
 860:     /**
 861:      * Asserts that the Location header is correct.
 862:      *
 863:      * @param string|array|null $url The URL you expected the client to go to. This
 864:      *   can either be a string URL or an array compatible with Router::url(). Use null to
 865:      *   simply check for the existence of this header.
 866:      * @param string $message The failure message that will be appended to the generated message.
 867:      * @return void
 868:      */
 869:     public function assertRedirect($url = null, $message = '')
 870:     {
 871:         $verboseMessage = $this->extractVerboseMessage($message);
 872:         $this->assertThat(null, new HeaderSet($this->_response, 'Location'), $verboseMessage);
 873: 
 874:         if ($url) {
 875:             $this->assertThat(Router::url($url, ['_full' => true]), new HeaderEquals($this->_response, 'Location'), $verboseMessage);
 876:         }
 877:     }
 878: 
 879:     /**
 880:      * Asserts that the Location header contains a substring
 881:      *
 882:      * @param string $url The URL you expected the client to go to.
 883:      * @param string $message The failure message that will be appended to the generated message.
 884:      * @return void
 885:      */
 886:     public function assertRedirectContains($url, $message = '')
 887:     {
 888:         $verboseMessage = $this->extractVerboseMessage($message);
 889:         $this->assertThat(null, new HeaderSet($this->_response, 'Location'), $verboseMessage);
 890:         $this->assertThat($url, new HeaderContains($this->_response, 'Location'), $verboseMessage);
 891:     }
 892: 
 893:     /**
 894:      * Asserts that the Location header does not contain a substring
 895:      *
 896:      * @param string $url The URL you expected the client to go to.
 897:      * @param string $message The failure message that will be appended to the generated message.
 898:      * @return void
 899:      */
 900:     public function assertRedirectNotContains($url, $message = '')
 901:     {
 902:         $verboseMessage = $this->extractVerboseMessage($message);
 903:         $this->assertThat(null, new HeaderSet($this->_response, 'Location'), $verboseMessage);
 904:         $this->assertThat($url, new HeaderNotContains($this->_response, 'Location'), $verboseMessage);
 905:     }
 906: 
 907:     /**
 908:      * Asserts that the Location header is not set.
 909:      *
 910:      * @param string $message The failure message that will be appended to the generated message.
 911:      * @return void
 912:      */
 913:     public function assertNoRedirect($message = '')
 914:     {
 915:         $verboseMessage = $this->extractVerboseMessage($message);
 916:         $this->assertThat(null, new HeaderNotSet($this->_response, 'Location'), $verboseMessage);
 917:     }
 918: 
 919:     /**
 920:      * Asserts response headers
 921:      *
 922:      * @param string $header The header to check
 923:      * @param string $content The content to check for.
 924:      * @param string $message The failure message that will be appended to the generated message.
 925:      * @return void
 926:      */
 927:     public function assertHeader($header, $content, $message = '')
 928:     {
 929:         $verboseMessage = $this->extractVerboseMessage($message);
 930:         $this->assertThat(null, new HeaderSet($this->_response, $header), $verboseMessage);
 931:         $this->assertThat($content, new HeaderEquals($this->_response, $header), $verboseMessage);
 932:     }
 933: 
 934:     /**
 935:      * Asserts response header contains a string
 936:      *
 937:      * @param string $header The header to check
 938:      * @param string $content The content to check for.
 939:      * @param string $message The failure message that will be appended to the generated message.
 940:      * @return void
 941:      */
 942:     public function assertHeaderContains($header, $content, $message = '')
 943:     {
 944:         $verboseMessage = $this->extractVerboseMessage($message);
 945:         $this->assertThat(null, new HeaderSet($this->_response, $header), $verboseMessage);
 946:         $this->assertThat($content, new HeaderContains($this->_response, $header), $verboseMessage);
 947:     }
 948: 
 949:     /**
 950:      * Asserts response header does not contain a string
 951:      *
 952:      * @param string $header The header to check
 953:      * @param string $content The content to check for.
 954:      * @param string $message The failure message that will be appended to the generated message.
 955:      * @return void
 956:      */
 957:     public function assertHeaderNotContains($header, $content, $message = '')
 958:     {
 959:         $verboseMessage = $this->extractVerboseMessage($message);
 960:         $this->assertThat(null, new HeaderSet($this->_response, $header), $verboseMessage);
 961:         $this->assertThat($content, new HeaderNotContains($this->_response, $header), $verboseMessage);
 962:     }
 963: 
 964:     /**
 965:      * Asserts content type
 966:      *
 967:      * @param string $type The content-type to check for.
 968:      * @param string $message The failure message that will be appended to the generated message.
 969:      * @return void
 970:      */
 971:     public function assertContentType($type, $message = '')
 972:     {
 973:         $verboseMessage = $this->extractVerboseMessage($message);
 974:         $this->assertThat($type, new ContentType($this->_response), $verboseMessage);
 975:     }
 976: 
 977:     /**
 978:      * Asserts content in the response body equals.
 979:      *
 980:      * @param mixed $content The content to check for.
 981:      * @param string $message The failure message that will be appended to the generated message.
 982:      * @return void
 983:      */
 984:     public function assertResponseEquals($content, $message = '')
 985:     {
 986:         $verboseMessage = $this->extractVerboseMessage($message);
 987:         $this->assertThat($content, new BodyEquals($this->_response), $verboseMessage);
 988:     }
 989: 
 990:     /**
 991:      * Asserts content in the response body not equals.
 992:      *
 993:      * @param mixed $content The content to check for.
 994:      * @param string $message The failure message that will be appended to the generated message.
 995:      * @return void
 996:      */
 997:     public function assertResponseNotEquals($content, $message = '')
 998:     {
 999:         $verboseMessage = $this->extractVerboseMessage($message);
1000:         $this->assertThat($content, new BodyNotEquals($this->_response), $verboseMessage);
1001:     }
1002: 
1003:     /**
1004:      * Asserts content exists in the response body.
1005:      *
1006:      * @param string $content The content to check for.
1007:      * @param string $message The failure message that will be appended to the generated message.
1008:      * @param bool $ignoreCase A flag to check whether we should ignore case or not.
1009:      * @return void
1010:      */
1011:     public function assertResponseContains($content, $message = '', $ignoreCase = false)
1012:     {
1013:         $verboseMessage = $this->extractVerboseMessage($message);
1014:         $this->assertThat($content, new BodyContains($this->_response, $ignoreCase), $verboseMessage);
1015:     }
1016: 
1017:     /**
1018:      * Asserts content does not exist in the response body.
1019:      *
1020:      * @param string $content The content to check for.
1021:      * @param string $message The failure message that will be appended to the generated message.
1022:      * @param bool $ignoreCase A flag to check whether we should ignore case or not.
1023:      * @return void
1024:      */
1025:     public function assertResponseNotContains($content, $message = '', $ignoreCase = false)
1026:     {
1027:         $verboseMessage = $this->extractVerboseMessage($message);
1028:         $this->assertThat($content, new BodyNotContains($this->_response, $ignoreCase), $verboseMessage);
1029:     }
1030: 
1031:     /**
1032:      * Asserts that the response body matches a given regular expression.
1033:      *
1034:      * @param string $pattern The pattern to compare against.
1035:      * @param string $message The failure message that will be appended to the generated message.
1036:      * @return void
1037:      */
1038:     public function assertResponseRegExp($pattern, $message = '')
1039:     {
1040:         $verboseMessage = $this->extractVerboseMessage($message);
1041:         $this->assertThat($pattern, new BodyRegExp($this->_response), $verboseMessage);
1042:     }
1043: 
1044:     /**
1045:      * Asserts that the response body does not match a given regular expression.
1046:      *
1047:      * @param string $pattern The pattern to compare against.
1048:      * @param string $message The failure message that will be appended to the generated message.
1049:      * @return void
1050:      */
1051:     public function assertResponseNotRegExp($pattern, $message = '')
1052:     {
1053:         $verboseMessage = $this->extractVerboseMessage($message);
1054:         $this->assertThat($pattern, new BodyNotRegExp($this->_response), $verboseMessage);
1055:     }
1056: 
1057:     /**
1058:      * Assert response content is not empty.
1059:      *
1060:      * @param string $message The failure message that will be appended to the generated message.
1061:      * @return void
1062:      */
1063:     public function assertResponseNotEmpty($message = '')
1064:     {
1065:         $this->assertThat(null, new BodyNotEmpty($this->_response), $message);
1066:     }
1067: 
1068:     /**
1069:      * Assert response content is empty.
1070:      *
1071:      * @param string $message The failure message that will be appended to the generated message.
1072:      * @return void
1073:      */
1074:     public function assertResponseEmpty($message = '')
1075:     {
1076:         $this->assertThat(null, new BodyEmpty($this->_response), $message);
1077:     }
1078: 
1079:     /**
1080:      * Asserts that the search string was in the template name.
1081:      *
1082:      * @param string $content The content to check for.
1083:      * @param string $message The failure message that will be appended to the generated message.
1084:      * @return void
1085:      */
1086:     public function assertTemplate($content, $message = '')
1087:     {
1088:         $verboseMessage = $this->extractVerboseMessage($message);
1089:         $this->assertThat($content, new TemplateFileEquals($this->_viewName), $verboseMessage);
1090:     }
1091: 
1092:     /**
1093:      * Asserts that the search string was in the layout name.
1094:      *
1095:      * @param string $content The content to check for.
1096:      * @param string $message The failure message that will be appended to the generated message.
1097:      * @return void
1098:      */
1099:     public function assertLayout($content, $message = '')
1100:     {
1101:         $verboseMessage = $this->extractVerboseMessage($message);
1102:         $this->assertThat($content, new LayoutFileEquals($this->_layoutName), $verboseMessage);
1103:     }
1104: 
1105:     /**
1106:      * Asserts session contents
1107:      *
1108:      * @param string $expected The expected contents.
1109:      * @param string $path The session data path. Uses Hash::get() compatible notation
1110:      * @param string $message The failure message that will be appended to the generated message.
1111:      * @return void
1112:      */
1113:     public function assertSession($expected, $path, $message = '')
1114:     {
1115:         $verboseMessage = $this->extractVerboseMessage($message);
1116:         $this->assertThat($expected, new SessionEquals($this->_requestSession, $path), $verboseMessage);
1117:     }
1118: 
1119:     /**
1120:      * Asserts a flash message was set
1121:      *
1122:      * @param string $expected Expected message
1123:      * @param string $key Flash key
1124:      * @param string $message Assertion failure message
1125:      * @return void
1126:      */
1127:     public function assertFlashMessage($expected, $key = 'flash', $message = '')
1128:     {
1129:         $verboseMessage = $this->extractVerboseMessage($message);
1130:         $this->assertThat($expected, new FlashParamEquals($this->_requestSession, $key, 'message'), $verboseMessage);
1131:     }
1132: 
1133:     /**
1134:      * Asserts a flash message was set at a certain index
1135:      *
1136:      * @param int $at Flash index
1137:      * @param string $expected Expected message
1138:      * @param string $key Flash key
1139:      * @param string $message Assertion failure message
1140:      * @return void
1141:      */
1142:     public function assertFlashMessageAt($at, $expected, $key = 'flash', $message = '')
1143:     {
1144:         $verboseMessage = $this->extractVerboseMessage($message);
1145:         $this->assertThat($expected, new FlashParamEquals($this->_requestSession, $key, 'message', $at), $verboseMessage);
1146:     }
1147: 
1148:     /**
1149:      * Asserts a flash element was set
1150:      *
1151:      * @param string $expected Expected element name
1152:      * @param string $key Flash key
1153:      * @param string $message Assertion failure message
1154:      * @return void
1155:      */
1156:     public function assertFlashElement($expected, $key = 'flash', $message = '')
1157:     {
1158:         $verboseMessage = $this->extractVerboseMessage($message);
1159:         $this->assertThat($expected, new FlashParamEquals($this->_requestSession, $key, 'element'), $verboseMessage);
1160:     }
1161: 
1162:     /**
1163:      * Asserts a flash element was set at a certain index
1164:      *
1165:      * @param int $at Flash index
1166:      * @param string $expected Expected element name
1167:      * @param string $key Flash key
1168:      * @param string $message Assertion failure message
1169:      * @return void
1170:      */
1171:     public function assertFlashElementAt($at, $expected, $key = 'flash', $message = '')
1172:     {
1173:         $verboseMessage = $this->extractVerboseMessage($message);
1174:         $this->assertThat($expected, new FlashParamEquals($this->_requestSession, $key, 'element', $at), $verboseMessage);
1175:     }
1176: 
1177:     /**
1178:      * Asserts cookie values
1179:      *
1180:      * @param string $expected The expected contents.
1181:      * @param string $name The cookie name.
1182:      * @param string $message The failure message that will be appended to the generated message.
1183:      * @return void
1184:      */
1185:     public function assertCookie($expected, $name, $message = '')
1186:     {
1187:         $verboseMessage = $this->extractVerboseMessage($message);
1188:         $this->assertThat($name, new CookieSet($this->_response), $verboseMessage);
1189:         $this->assertThat($expected, new CookieEquals($this->_response, $name), $verboseMessage);
1190:     }
1191: 
1192:     /**
1193:      * Asserts a cookie has not been set in the response
1194:      *
1195:      * @param string $cookie The cookie name to check
1196:      * @param string $message The failure message that will be appended to the generated message.
1197:      * @return void
1198:      */
1199:     public function assertCookieNotSet($cookie, $message = '')
1200:     {
1201:         $verboseMessage = $this->extractVerboseMessage($message);
1202:         $this->assertThat($cookie, new CookieNotSet($this->_response), $verboseMessage);
1203:     }
1204: 
1205:     /**
1206:      * Disable the error handler middleware.
1207:      *
1208:      * By using this function, exceptions are no longer caught by the ErrorHandlerMiddleware
1209:      * and are instead re-thrown by the TestExceptionRenderer. This can be helpful
1210:      * when trying to diagnose/debug unexpected failures in test cases.
1211:      *
1212:      * @return void
1213:      */
1214:     public function disableErrorHandlerMiddleware()
1215:     {
1216:         Configure::write('Error.exceptionRenderer', TestExceptionRenderer::class);
1217:     }
1218: 
1219:     /**
1220:      * Asserts cookie values which are encrypted by the
1221:      * CookieComponent.
1222:      *
1223:      * The difference from assertCookie() is this decrypts the cookie
1224:      * value like the CookieComponent for this assertion.
1225:      *
1226:      * @param string $expected The expected contents.
1227:      * @param string $name The cookie name.
1228:      * @param string|bool $encrypt Encryption mode to use.
1229:      * @param string|null $key Encryption key used. Defaults
1230:      *   to Security.salt.
1231:      * @param string $message The failure message that will be appended to the generated message.
1232:      * @return void
1233:      * @see \Cake\Utility\CookieCryptTrait::_encrypt()
1234:      */
1235:     public function assertCookieEncrypted($expected, $name, $encrypt = 'aes', $key = null, $message = '')
1236:     {
1237:         $verboseMessage = $this->extractVerboseMessage($message);
1238:         $this->assertThat($name, new CookieSet($this->_response), $verboseMessage);
1239: 
1240:         $this->_cookieEncryptionKey = $key;
1241:         $this->assertThat($expected, new CookieEncryptedEquals($this->_response, $name, $encrypt, $this->_getCookieEncryptionKey()));
1242:     }
1243: 
1244:     /**
1245:      * Asserts that a file with the given name was sent in the response
1246:      *
1247:      * @param string $expected The absolute file path that should be sent in the response.
1248:      * @param string $message The failure message that will be appended to the generated message.
1249:      * @return void
1250:      */
1251:     public function assertFileResponse($expected, $message = '')
1252:     {
1253:         $verboseMessage = $this->extractVerboseMessage($message);
1254:         $this->assertThat(null, new FileSent($this->_response), $verboseMessage);
1255:         $this->assertThat($expected, new FileSentAs($this->_response), $verboseMessage);
1256:     }
1257: 
1258:     /**
1259:      * Inspect controller to extract possible causes of the failed assertion
1260:      *
1261:      * @param string $message Original message to use as a base
1262:      * @return string|null
1263:      */
1264:     protected function extractVerboseMessage($message = null)
1265:     {
1266:         if ($this->_exception instanceof \Exception) {
1267:             $message .= $this->extractExceptionMessage($this->_exception);
1268:         }
1269:         if ($this->_controller === null) {
1270:             return $message;
1271:         }
1272:         $error = Hash::get($this->_controller->viewVars, 'error');
1273:         if ($error instanceof \Exception) {
1274:             $message .= $this->extractExceptionMessage($this->viewVariable('error'));
1275:         }
1276: 
1277:         return $message;
1278:     }
1279: 
1280:     /**
1281:      * Extract verbose message for existing exception
1282:      *
1283:      * @param \Exception $exception Exception to extract
1284:      * @return string
1285:      */
1286:     protected function extractExceptionMessage(\Exception $exception)
1287:     {
1288:         return PHP_EOL .
1289:             sprintf('Possibly related to %s: "%s" ', get_class($exception), $exception->getMessage()) .
1290:             PHP_EOL .
1291:             $exception->getTraceAsString();
1292:     }
1293: }
1294: 
Follow @CakePHP
#IRC
OpenHub
Rackspace
  • Business Solutions
  • Showcase
  • Documentation
  • Book
  • API
  • Videos
  • Logos & Trademarks
  • Community
  • Team
  • Issues (Github)
  • YouTube Channel
  • Get Involved
  • Bakery
  • Featured Resources
  • Newsletter
  • Certification
  • My CakePHP
  • CakeFest
  • Facebook
  • Twitter
  • Help & Support
  • Forum
  • Stack Overflow
  • IRC
  • Slack
  • Paid Support

Generated using CakePHP API Docs