Completed
Push — master ( d8e1d0...dc28c7 )
by Mark
24s queued 10s
created

IntegrationTestTrait::assertRedirectEquals()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 9

Duplication

Lines 9
Ratio 100 %

Importance

Changes 0
Metric Value
cc 2
nc 2
nop 2
dl 9
loc 9
rs 9.9666
c 0
b 0
f 0
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) {
0 ignored issues
show
Documentation introduced by
function ($event, $viewF...>read('Flash'); } } is of type object<Closure>, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
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) {
0 ignored issues
show
Documentation introduced by
function ($event, $viewF...youtName = $viewFile; } is of type object<Closure>, but the function expects a array.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
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);
0 ignored issues
show
Bug introduced by
It seems like $data can also be of type null or string; however, Cake\TestSuite\IntegrationTestTrait::_addTokens() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
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);
0 ignored issues
show
Bug introduced by
It seems like $url defined by parameter $url on line 751 can also be of type array; however, Zend\Diactoros\Uri::__construct() does only seem to accept string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
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.');
0 ignored issues
show
Bug introduced by
It seems like fail() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
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?');
0 ignored issues
show
Bug introduced by
It seems like fail() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
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);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
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);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
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);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
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);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
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);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
858
    }
859
860
    /**
861
     * Asserts that the Location header is correct. Comparison is made against a full URL.
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 View Code Duplication
    public function assertRedirect($url = null, $message = '')
870
    {
871
        $verboseMessage = $this->extractVerboseMessage($message);
872
        $this->assertThat(null, new HeaderSet($this->_response, 'Location'), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
873
874
        if ($url) {
875
            $this->assertThat(Router::url($url, ['_full' => true]), new HeaderEquals($this->_response, 'Location'), $verboseMessage);
0 ignored issues
show
Documentation introduced by
array('_full' => true) is of type array<string,boolean,{"_full":"boolean"}>, but the function expects a boolean.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
876
        }
877
    }
878
879
    /**
880
     * Asserts that the Location header is correct. Comparison is made against exactly the URL provided.
881
     *
882
     * @param string|array|null $url The URL you expected the client to go to. This
883
     *   can either be a string URL or an array compatible with Router::url(). Use null to
884
     *   simply check for the existence of this header.
885
     * @param string $message The failure message that will be appended to the generated message.
886
     * @return void
887
     */
888 View Code Duplication
    public function assertRedirectEquals($url = null, $message = '')
889
    {
890
        $verboseMessage = $this->extractVerboseMessage($message);
891
        $this->assertThat(null, new HeaderSet($this->_response, 'Location'), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
892
893
        if ($url) {
894
            $this->assertThat(Router::url($url), new HeaderEquals($this->_response, 'Location'), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
895
        }
896
    }
897
898
    /**
899
     * Asserts that the Location header contains a substring
900
     *
901
     * @param string $url The URL you expected the client to go to.
902
     * @param string $message The failure message that will be appended to the generated message.
903
     * @return void
904
     */
905
    public function assertRedirectContains($url, $message = '')
906
    {
907
        $verboseMessage = $this->extractVerboseMessage($message);
908
        $this->assertThat(null, new HeaderSet($this->_response, 'Location'), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
909
        $this->assertThat($url, new HeaderContains($this->_response, 'Location'), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
910
    }
911
912
    /**
913
     * Asserts that the Location header does not contain a substring
914
     *
915
     * @param string $url The URL you expected the client to go to.
916
     * @param string $message The failure message that will be appended to the generated message.
917
     * @return void
918
     */
919
    public function assertRedirectNotContains($url, $message = '')
920
    {
921
        $verboseMessage = $this->extractVerboseMessage($message);
922
        $this->assertThat(null, new HeaderSet($this->_response, 'Location'), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
923
        $this->assertThat($url, new HeaderNotContains($this->_response, 'Location'), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
924
    }
925
926
    /**
927
     * Asserts that the Location header is not set.
928
     *
929
     * @param string $message The failure message that will be appended to the generated message.
930
     * @return void
931
     */
932
    public function assertNoRedirect($message = '')
933
    {
934
        $verboseMessage = $this->extractVerboseMessage($message);
935
        $this->assertThat(null, new HeaderNotSet($this->_response, 'Location'), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
936
    }
937
938
    /**
939
     * Asserts response headers
940
     *
941
     * @param string $header The header to check
942
     * @param string $content The content to check for.
943
     * @param string $message The failure message that will be appended to the generated message.
944
     * @return void
945
     */
946
    public function assertHeader($header, $content, $message = '')
947
    {
948
        $verboseMessage = $this->extractVerboseMessage($message);
949
        $this->assertThat(null, new HeaderSet($this->_response, $header), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
950
        $this->assertThat($content, new HeaderEquals($this->_response, $header), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
951
    }
952
953
    /**
954
     * Asserts response header contains a string
955
     *
956
     * @param string $header The header to check
957
     * @param string $content The content to check for.
958
     * @param string $message The failure message that will be appended to the generated message.
959
     * @return void
960
     */
961
    public function assertHeaderContains($header, $content, $message = '')
962
    {
963
        $verboseMessage = $this->extractVerboseMessage($message);
964
        $this->assertThat(null, new HeaderSet($this->_response, $header), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
965
        $this->assertThat($content, new HeaderContains($this->_response, $header), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
966
    }
967
968
    /**
969
     * Asserts response header does not contain a string
970
     *
971
     * @param string $header The header to check
972
     * @param string $content The content to check for.
973
     * @param string $message The failure message that will be appended to the generated message.
974
     * @return void
975
     */
976
    public function assertHeaderNotContains($header, $content, $message = '')
977
    {
978
        $verboseMessage = $this->extractVerboseMessage($message);
979
        $this->assertThat(null, new HeaderSet($this->_response, $header), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
980
        $this->assertThat($content, new HeaderNotContains($this->_response, $header), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
981
    }
982
983
    /**
984
     * Asserts content type
985
     *
986
     * @param string $type The content-type to check for.
987
     * @param string $message The failure message that will be appended to the generated message.
988
     * @return void
989
     */
990
    public function assertContentType($type, $message = '')
991
    {
992
        $verboseMessage = $this->extractVerboseMessage($message);
993
        $this->assertThat($type, new ContentType($this->_response), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
994
    }
995
996
    /**
997
     * Asserts content in the response body equals.
998
     *
999
     * @param mixed $content The content to check for.
1000
     * @param string $message The failure message that will be appended to the generated message.
1001
     * @return void
1002
     */
1003
    public function assertResponseEquals($content, $message = '')
1004
    {
1005
        $verboseMessage = $this->extractVerboseMessage($message);
1006
        $this->assertThat($content, new BodyEquals($this->_response), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
1007
    }
1008
1009
    /**
1010
     * Asserts content in the response body not equals.
1011
     *
1012
     * @param mixed $content The content to check for.
1013
     * @param string $message The failure message that will be appended to the generated message.
1014
     * @return void
1015
     */
1016
    public function assertResponseNotEquals($content, $message = '')
1017
    {
1018
        $verboseMessage = $this->extractVerboseMessage($message);
1019
        $this->assertThat($content, new BodyNotEquals($this->_response), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
1020
    }
1021
1022
    /**
1023
     * Asserts content exists in the response body.
1024
     *
1025
     * @param string $content The content to check for.
1026
     * @param string $message The failure message that will be appended to the generated message.
1027
     * @param bool $ignoreCase A flag to check whether we should ignore case or not.
1028
     * @return void
1029
     */
1030
    public function assertResponseContains($content, $message = '', $ignoreCase = false)
1031
    {
1032
        $verboseMessage = $this->extractVerboseMessage($message);
1033
        $this->assertThat($content, new BodyContains($this->_response, $ignoreCase), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
1034
    }
1035
1036
    /**
1037
     * Asserts content does not exist in the response body.
1038
     *
1039
     * @param string $content The content to check for.
1040
     * @param string $message The failure message that will be appended to the generated message.
1041
     * @param bool $ignoreCase A flag to check whether we should ignore case or not.
1042
     * @return void
1043
     */
1044
    public function assertResponseNotContains($content, $message = '', $ignoreCase = false)
1045
    {
1046
        $verboseMessage = $this->extractVerboseMessage($message);
1047
        $this->assertThat($content, new BodyNotContains($this->_response, $ignoreCase), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
1048
    }
1049
1050
    /**
1051
     * Asserts that the response body matches a given regular expression.
1052
     *
1053
     * @param string $pattern The pattern to compare against.
1054
     * @param string $message The failure message that will be appended to the generated message.
1055
     * @return void
1056
     */
1057
    public function assertResponseRegExp($pattern, $message = '')
1058
    {
1059
        $verboseMessage = $this->extractVerboseMessage($message);
1060
        $this->assertThat($pattern, new BodyRegExp($this->_response), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
1061
    }
1062
1063
    /**
1064
     * Asserts that the response body does not match a given regular expression.
1065
     *
1066
     * @param string $pattern The pattern to compare against.
1067
     * @param string $message The failure message that will be appended to the generated message.
1068
     * @return void
1069
     */
1070
    public function assertResponseNotRegExp($pattern, $message = '')
1071
    {
1072
        $verboseMessage = $this->extractVerboseMessage($message);
1073
        $this->assertThat($pattern, new BodyNotRegExp($this->_response), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
1074
    }
1075
1076
    /**
1077
     * Assert response content is not empty.
1078
     *
1079
     * @param string $message The failure message that will be appended to the generated message.
1080
     * @return void
1081
     */
1082
    public function assertResponseNotEmpty($message = '')
1083
    {
1084
        $this->assertThat(null, new BodyNotEmpty($this->_response), $message);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
1085
    }
1086
1087
    /**
1088
     * Assert response content is empty.
1089
     *
1090
     * @param string $message The failure message that will be appended to the generated message.
1091
     * @return void
1092
     */
1093
    public function assertResponseEmpty($message = '')
1094
    {
1095
        $this->assertThat(null, new BodyEmpty($this->_response), $message);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
1096
    }
1097
1098
    /**
1099
     * Asserts that the search string was in the template name.
1100
     *
1101
     * @param string $content The content to check for.
1102
     * @param string $message The failure message that will be appended to the generated message.
1103
     * @return void
1104
     */
1105
    public function assertTemplate($content, $message = '')
1106
    {
1107
        $verboseMessage = $this->extractVerboseMessage($message);
1108
        $this->assertThat($content, new TemplateFileEquals($this->_viewName), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
1109
    }
1110
1111
    /**
1112
     * Asserts that the search string was in the layout name.
1113
     *
1114
     * @param string $content The content to check for.
1115
     * @param string $message The failure message that will be appended to the generated message.
1116
     * @return void
1117
     */
1118
    public function assertLayout($content, $message = '')
1119
    {
1120
        $verboseMessage = $this->extractVerboseMessage($message);
1121
        $this->assertThat($content, new LayoutFileEquals($this->_layoutName), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
1122
    }
1123
1124
    /**
1125
     * Asserts session contents
1126
     *
1127
     * @param string $expected The expected contents.
1128
     * @param string $path The session data path. Uses Hash::get() compatible notation
1129
     * @param string $message The failure message that will be appended to the generated message.
1130
     * @return void
1131
     */
1132
    public function assertSession($expected, $path, $message = '')
1133
    {
1134
        $verboseMessage = $this->extractVerboseMessage($message);
1135
        $this->assertThat($expected, new SessionEquals($this->_requestSession, $path), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
1136
    }
1137
1138
    /**
1139
     * Asserts a flash message was set
1140
     *
1141
     * @param string $expected Expected message
1142
     * @param string $key Flash key
1143
     * @param string $message Assertion failure message
1144
     * @return void
1145
     */
1146
    public function assertFlashMessage($expected, $key = 'flash', $message = '')
1147
    {
1148
        $verboseMessage = $this->extractVerboseMessage($message);
1149
        $this->assertThat($expected, new FlashParamEquals($this->_requestSession, $key, 'message'), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
1150
    }
1151
1152
    /**
1153
     * Asserts a flash message was set at a certain index
1154
     *
1155
     * @param int $at Flash index
1156
     * @param string $expected Expected message
1157
     * @param string $key Flash key
1158
     * @param string $message Assertion failure message
1159
     * @return void
1160
     */
1161
    public function assertFlashMessageAt($at, $expected, $key = 'flash', $message = '')
1162
    {
1163
        $verboseMessage = $this->extractVerboseMessage($message);
1164
        $this->assertThat($expected, new FlashParamEquals($this->_requestSession, $key, 'message', $at), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
1165
    }
1166
1167
    /**
1168
     * Asserts a flash element was set
1169
     *
1170
     * @param string $expected Expected element name
1171
     * @param string $key Flash key
1172
     * @param string $message Assertion failure message
1173
     * @return void
1174
     */
1175
    public function assertFlashElement($expected, $key = 'flash', $message = '')
1176
    {
1177
        $verboseMessage = $this->extractVerboseMessage($message);
1178
        $this->assertThat($expected, new FlashParamEquals($this->_requestSession, $key, 'element'), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
1179
    }
1180
1181
    /**
1182
     * Asserts a flash element was set at a certain index
1183
     *
1184
     * @param int $at Flash index
1185
     * @param string $expected Expected element name
1186
     * @param string $key Flash key
1187
     * @param string $message Assertion failure message
1188
     * @return void
1189
     */
1190
    public function assertFlashElementAt($at, $expected, $key = 'flash', $message = '')
1191
    {
1192
        $verboseMessage = $this->extractVerboseMessage($message);
1193
        $this->assertThat($expected, new FlashParamEquals($this->_requestSession, $key, 'element', $at), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
1194
    }
1195
1196
    /**
1197
     * Asserts cookie values
1198
     *
1199
     * @param string $expected The expected contents.
1200
     * @param string $name The cookie name.
1201
     * @param string $message The failure message that will be appended to the generated message.
1202
     * @return void
1203
     */
1204
    public function assertCookie($expected, $name, $message = '')
1205
    {
1206
        $verboseMessage = $this->extractVerboseMessage($message);
1207
        $this->assertThat($name, new CookieSet($this->_response), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
1208
        $this->assertThat($expected, new CookieEquals($this->_response, $name), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
1209
    }
1210
1211
    /**
1212
     * Asserts a cookie has not been set in the response
1213
     *
1214
     * @param string $cookie The cookie name to check
1215
     * @param string $message The failure message that will be appended to the generated message.
1216
     * @return void
1217
     */
1218
    public function assertCookieNotSet($cookie, $message = '')
1219
    {
1220
        $verboseMessage = $this->extractVerboseMessage($message);
1221
        $this->assertThat($cookie, new CookieNotSet($this->_response), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
1222
    }
1223
1224
    /**
1225
     * Disable the error handler middleware.
1226
     *
1227
     * By using this function, exceptions are no longer caught by the ErrorHandlerMiddleware
1228
     * and are instead re-thrown by the TestExceptionRenderer. This can be helpful
1229
     * when trying to diagnose/debug unexpected failures in test cases.
1230
     *
1231
     * @return void
1232
     */
1233
    public function disableErrorHandlerMiddleware()
1234
    {
1235
        Configure::write('Error.exceptionRenderer', TestExceptionRenderer::class);
1236
    }
1237
1238
    /**
1239
     * Asserts cookie values which are encrypted by the
1240
     * CookieComponent.
1241
     *
1242
     * The difference from assertCookie() is this decrypts the cookie
1243
     * value like the CookieComponent for this assertion.
1244
     *
1245
     * @param string $expected The expected contents.
1246
     * @param string $name The cookie name.
1247
     * @param string|bool $encrypt Encryption mode to use.
1248
     * @param string|null $key Encryption key used. Defaults
1249
     *   to Security.salt.
1250
     * @param string $message The failure message that will be appended to the generated message.
1251
     * @return void
1252
     * @see \Cake\Utility\CookieCryptTrait::_encrypt()
1253
     */
1254
    public function assertCookieEncrypted($expected, $name, $encrypt = 'aes', $key = null, $message = '')
1255
    {
1256
        $verboseMessage = $this->extractVerboseMessage($message);
1257
        $this->assertThat($name, new CookieSet($this->_response), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
1258
1259
        $this->_cookieEncryptionKey = $key;
1260
        $this->assertThat($expected, new CookieEncryptedEquals($this->_response, $name, $encrypt, $this->_getCookieEncryptionKey()));
0 ignored issues
show
Bug introduced by
It seems like $encrypt defined by parameter $encrypt on line 1254 can also be of type boolean; however, Cake\TestSuite\Constrain...edEquals::__construct() does only seem to accept string, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
1261
    }
1262
1263
    /**
1264
     * Asserts that a file with the given name was sent in the response
1265
     *
1266
     * @param string $expected The absolute file path that should be sent in the response.
1267
     * @param string $message The failure message that will be appended to the generated message.
1268
     * @return void
1269
     */
1270
    public function assertFileResponse($expected, $message = '')
1271
    {
1272
        $verboseMessage = $this->extractVerboseMessage($message);
1273
        $this->assertThat(null, new FileSent($this->_response), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
1274
        $this->assertThat($expected, new FileSentAs($this->_response), $verboseMessage);
0 ignored issues
show
Bug introduced by
It seems like assertThat() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
1275
    }
1276
1277
    /**
1278
     * Inspect controller to extract possible causes of the failed assertion
1279
     *
1280
     * @param string $message Original message to use as a base
1281
     * @return string|null
1282
     */
1283
    protected function extractVerboseMessage($message = null)
1284
    {
1285
        if ($this->_exception instanceof \Exception) {
1286
            $message .= $this->extractExceptionMessage($this->_exception);
1287
        }
1288
        if ($this->_controller === null) {
1289
            return $message;
1290
        }
1291
        $error = Hash::get($this->_controller->viewVars, 'error');
1292
        if ($error instanceof \Exception) {
1293
            $message .= $this->extractExceptionMessage($this->viewVariable('error'));
1294
        }
1295
1296
        return $message;
1297
    }
1298
1299
    /**
1300
     * Extract verbose message for existing exception
1301
     *
1302
     * @param \Exception $exception Exception to extract
1303
     * @return string
1304
     */
1305
    protected function extractExceptionMessage(\Exception $exception)
1306
    {
1307
        return PHP_EOL .
1308
            sprintf('Possibly related to %s: "%s" ', get_class($exception), $exception->getMessage()) .
1309
            PHP_EOL .
1310
            $exception->getTraceAsString();
1311
    }
1312
}
1313