├── .releaserc.json ├── LICENSE ├── composer.json ├── ecs.php ├── phpstan-baseline.neon └── src └── Codeception ├── Lib └── Connector │ ├── Yii2.php │ └── Yii2 │ ├── ConnectionWatcher.php │ ├── FixturesStore.php │ ├── Logger.php │ ├── TestMailer.php │ └── TransactionForcer.php └── Module └── Yii2.php /.releaserc.json: -------------------------------------------------------------------------------- 1 | { 2 | "branches": ["master"], 3 | "plugins": [ 4 | ["@semantic-release/commit-analyzer", { 5 | "preset": "conventionalcommits", 6 | "presetConfig": {} 7 | }], 8 | "@semantic-release/github", 9 | "@semantic-release/release-notes-generator"] 10 | } 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011 Michael Bodnarchuk and contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name":"codeception/module-yii2", 3 | "description":"Codeception module for Yii2 framework", 4 | "keywords":["codeception", "yii2"], 5 | "homepage":"https://codeception.com/", 6 | "type":"library", 7 | "license":"MIT", 8 | "authors":[ 9 | { 10 | "name":"Alexander Makarov" 11 | }, 12 | { 13 | "name":"Sam Mouse" 14 | }, 15 | { 16 | "name":"Michael Bodnarchuk" 17 | } 18 | ], 19 | "minimum-stability": "RC", 20 | "require": { 21 | "php": "^8.3", 22 | "codeception/codeception": "^5.0.8", 23 | "codeception/lib-innerbrowser": "^3.0 | ^4.0" 24 | }, 25 | "require-dev": { 26 | "yiisoft/yii2": "dev-master", 27 | "yiisoft/yii2-app-advanced": "dev-master", 28 | "codeception/verify": "^3.0", 29 | "codeception/module-asserts": ">= 3.0", 30 | "codeception/module-filesystem": "> 3.0", 31 | "phpstan/phpstan": "^2", 32 | "symplify/easy-coding-standard": "^12.5" 33 | }, 34 | "autoload":{ 35 | "classmap": ["src/"] 36 | }, 37 | "autoload-dev": { 38 | "classmap": [ 39 | "vendor/yiisoft/yii2/Yii.php", 40 | "tests/cases" 41 | ] 42 | }, 43 | "config": { 44 | "allow-plugins": { 45 | "yiisoft/yii2-composer": true 46 | }, 47 | "classmap-authoritative": true 48 | }, 49 | "repositories": [ 50 | { 51 | "type": "composer", 52 | "url": "https://asset-packagist.org" 53 | } 54 | ] 55 | } 56 | -------------------------------------------------------------------------------- /ecs.php: -------------------------------------------------------------------------------- 1 | parallel(); 22 | 23 | $ecsConfig->cacheDirectory('.ecs-cache'); 24 | // Paths 25 | $ecsConfig->paths([ 26 | __DIR__ . '/src', __DIR__ . '/tests', __DIR__ . '/ecs.php' 27 | ]); 28 | 29 | // A. full sets 30 | $ecsConfig->sets([SetList::PSR_12, SetList::SPACES, SetList::STRICT, SetList::DOCBLOCK]); 31 | 32 | $ecsConfig->rule(NotOperatorWithSuccessorSpaceFixer::class); 33 | $ecsConfig->rule(ArraySyntaxFixer::class); 34 | $ecsConfig->ruleWithConfiguration(GeneralPhpdocAnnotationRemoveFixer::class, [ 35 | 'annotations' => ['author', 'inheritdoc', 'package'] 36 | ]); 37 | $ecsConfig->rule(NoBlankLinesAfterPhpdocFixer::class); 38 | $ecsConfig->ruleWithConfiguration(NoSuperfluousPhpdocTagsFixer::class, [ 39 | 'allow_mixed' => true 40 | ]); 41 | $ecsConfig->rule(NoEmptyPhpdocFixer::class); 42 | $ecsConfig->rule(NoUnusedImportsFixer::class); 43 | $ecsConfig->ruleWithConfiguration(FinalInternalClassFixer::class, [ 44 | 'annotation_exclude' => ['@not-fix', '@internal'], 45 | 'annotation_include' => [], 46 | 'consider_absent_docblock_as_internal_class' => true 47 | ]); 48 | $ecsConfig->ruleWithConfiguration(ForbiddenFunctionsSniff::class, [ 49 | 'forbiddenFunctions' => [ 50 | 'passthru' => null, 51 | 'var_dump' => null, 52 | ] 53 | ]); 54 | $ecsConfig->rule(PhpdocIndentFixer::class); 55 | $ecsConfig->rule(\PhpCsFixer\Fixer\Phpdoc\AlignMultilineCommentFixer::class); 56 | 57 | $ecsConfig->skip([ 58 | ForbiddenFunctionsSniff::class => [ 59 | 'tests/**', 60 | 'console/**' 61 | ], 62 | 'tests/_support/_generated' 63 | ]); 64 | 65 | // $ecsConfig->skip([ 66 | // FinalClassFixer::class => [ 67 | // 'tests/**' 68 | // ] 69 | // ]); 70 | }; 71 | -------------------------------------------------------------------------------- /phpstan-baseline.neon: -------------------------------------------------------------------------------- 1 | parameters: 2 | ignoreErrors: 3 | - 4 | message: '#^Method tests\\FunctionalTester\:\:assertArrayHasKey\(\) has no return type specified\.$#' 5 | identifier: missingType.return 6 | count: 1 7 | path: tests/_support/FunctionalTester.php 8 | 9 | - 10 | message: '#^Method tests\\FunctionalTester\:\:assertArrayHasKey\(\) has parameter \$array with generic interface ArrayAccess but does not specify its types\: TKey, TValue$#' 11 | identifier: missingType.generics 12 | count: 1 13 | path: tests/_support/FunctionalTester.php 14 | 15 | - 16 | message: '#^Method tests\\FunctionalTester\:\:assertArrayHasKey\(\) has parameter \$array with no value type specified in iterable type array\.$#' 17 | identifier: missingType.iterableValue 18 | count: 1 19 | path: tests/_support/FunctionalTester.php 20 | 21 | - 22 | message: '#^Method tests\\FunctionalTester\:\:assertArrayNotHasKey\(\) has no return type specified\.$#' 23 | identifier: missingType.return 24 | count: 1 25 | path: tests/_support/FunctionalTester.php 26 | 27 | - 28 | message: '#^Method tests\\FunctionalTester\:\:assertArrayNotHasKey\(\) has parameter \$array with generic interface ArrayAccess but does not specify its types\: TKey, TValue$#' 29 | identifier: missingType.generics 30 | count: 1 31 | path: tests/_support/FunctionalTester.php 32 | 33 | - 34 | message: '#^Method tests\\FunctionalTester\:\:assertArrayNotHasKey\(\) has parameter \$array with no value type specified in iterable type array\.$#' 35 | identifier: missingType.iterableValue 36 | count: 1 37 | path: tests/_support/FunctionalTester.php 38 | 39 | - 40 | message: '#^Method tests\\FunctionalTester\:\:assertClassHasAttribute\(\) has no return type specified\.$#' 41 | identifier: missingType.return 42 | count: 1 43 | path: tests/_support/FunctionalTester.php 44 | 45 | - 46 | message: '#^Method tests\\FunctionalTester\:\:assertClassHasStaticAttribute\(\) has no return type specified\.$#' 47 | identifier: missingType.return 48 | count: 1 49 | path: tests/_support/FunctionalTester.php 50 | 51 | - 52 | message: '#^Method tests\\FunctionalTester\:\:assertClassNotHasAttribute\(\) has no return type specified\.$#' 53 | identifier: missingType.return 54 | count: 1 55 | path: tests/_support/FunctionalTester.php 56 | 57 | - 58 | message: '#^Method tests\\FunctionalTester\:\:assertClassNotHasStaticAttribute\(\) has no return type specified\.$#' 59 | identifier: missingType.return 60 | count: 1 61 | path: tests/_support/FunctionalTester.php 62 | 63 | - 64 | message: '#^Method tests\\FunctionalTester\:\:assertContains\(\) has no return type specified\.$#' 65 | identifier: missingType.return 66 | count: 1 67 | path: tests/_support/FunctionalTester.php 68 | 69 | - 70 | message: '#^Method tests\\FunctionalTester\:\:assertContains\(\) has parameter \$haystack with no value type specified in iterable type iterable\.$#' 71 | identifier: missingType.iterableValue 72 | count: 1 73 | path: tests/_support/FunctionalTester.php 74 | 75 | - 76 | message: '#^Method tests\\FunctionalTester\:\:assertContainsEquals\(\) has no return type specified\.$#' 77 | identifier: missingType.return 78 | count: 1 79 | path: tests/_support/FunctionalTester.php 80 | 81 | - 82 | message: '#^Method tests\\FunctionalTester\:\:assertContainsEquals\(\) has parameter \$haystack with no value type specified in iterable type iterable\.$#' 83 | identifier: missingType.iterableValue 84 | count: 1 85 | path: tests/_support/FunctionalTester.php 86 | 87 | - 88 | message: '#^Method tests\\FunctionalTester\:\:assertContainsOnly\(\) has no return type specified\.$#' 89 | identifier: missingType.return 90 | count: 1 91 | path: tests/_support/FunctionalTester.php 92 | 93 | - 94 | message: '#^Method tests\\FunctionalTester\:\:assertContainsOnly\(\) has parameter \$haystack with no value type specified in iterable type iterable\.$#' 95 | identifier: missingType.iterableValue 96 | count: 1 97 | path: tests/_support/FunctionalTester.php 98 | 99 | - 100 | message: '#^Method tests\\FunctionalTester\:\:assertContainsOnlyInstancesOf\(\) has no return type specified\.$#' 101 | identifier: missingType.return 102 | count: 1 103 | path: tests/_support/FunctionalTester.php 104 | 105 | - 106 | message: '#^Method tests\\FunctionalTester\:\:assertContainsOnlyInstancesOf\(\) has parameter \$haystack with no value type specified in iterable type iterable\.$#' 107 | identifier: missingType.iterableValue 108 | count: 1 109 | path: tests/_support/FunctionalTester.php 110 | 111 | - 112 | message: '#^Method tests\\FunctionalTester\:\:assertCount\(\) has no return type specified\.$#' 113 | identifier: missingType.return 114 | count: 1 115 | path: tests/_support/FunctionalTester.php 116 | 117 | - 118 | message: '#^Method tests\\FunctionalTester\:\:assertCount\(\) has parameter \$haystack with no value type specified in iterable type iterable\.$#' 119 | identifier: missingType.iterableValue 120 | count: 1 121 | path: tests/_support/FunctionalTester.php 122 | 123 | - 124 | message: '#^Method tests\\FunctionalTester\:\:assertDirectoryDoesNotExist\(\) has no return type specified\.$#' 125 | identifier: missingType.return 126 | count: 1 127 | path: tests/_support/FunctionalTester.php 128 | 129 | - 130 | message: '#^Method tests\\FunctionalTester\:\:assertDirectoryExists\(\) has no return type specified\.$#' 131 | identifier: missingType.return 132 | count: 1 133 | path: tests/_support/FunctionalTester.php 134 | 135 | - 136 | message: '#^Method tests\\FunctionalTester\:\:assertDirectoryIsNotReadable\(\) has no return type specified\.$#' 137 | identifier: missingType.return 138 | count: 1 139 | path: tests/_support/FunctionalTester.php 140 | 141 | - 142 | message: '#^Method tests\\FunctionalTester\:\:assertDirectoryIsNotWritable\(\) has no return type specified\.$#' 143 | identifier: missingType.return 144 | count: 1 145 | path: tests/_support/FunctionalTester.php 146 | 147 | - 148 | message: '#^Method tests\\FunctionalTester\:\:assertDirectoryIsReadable\(\) has no return type specified\.$#' 149 | identifier: missingType.return 150 | count: 1 151 | path: tests/_support/FunctionalTester.php 152 | 153 | - 154 | message: '#^Method tests\\FunctionalTester\:\:assertDirectoryIsWritable\(\) has no return type specified\.$#' 155 | identifier: missingType.return 156 | count: 1 157 | path: tests/_support/FunctionalTester.php 158 | 159 | - 160 | message: '#^Method tests\\FunctionalTester\:\:assertDoesNotMatchRegularExpression\(\) has no return type specified\.$#' 161 | identifier: missingType.return 162 | count: 1 163 | path: tests/_support/FunctionalTester.php 164 | 165 | - 166 | message: '#^Method tests\\FunctionalTester\:\:assertEmpty\(\) has no return type specified\.$#' 167 | identifier: missingType.return 168 | count: 1 169 | path: tests/_support/FunctionalTester.php 170 | 171 | - 172 | message: '#^Method tests\\FunctionalTester\:\:assertEquals\(\) has no return type specified\.$#' 173 | identifier: missingType.return 174 | count: 1 175 | path: tests/_support/FunctionalTester.php 176 | 177 | - 178 | message: '#^Method tests\\FunctionalTester\:\:assertEqualsCanonicalizing\(\) has no return type specified\.$#' 179 | identifier: missingType.return 180 | count: 1 181 | path: tests/_support/FunctionalTester.php 182 | 183 | - 184 | message: '#^Method tests\\FunctionalTester\:\:assertEqualsIgnoringCase\(\) has no return type specified\.$#' 185 | identifier: missingType.return 186 | count: 1 187 | path: tests/_support/FunctionalTester.php 188 | 189 | - 190 | message: '#^Method tests\\FunctionalTester\:\:assertEqualsWithDelta\(\) has no return type specified\.$#' 191 | identifier: missingType.return 192 | count: 1 193 | path: tests/_support/FunctionalTester.php 194 | 195 | - 196 | message: '#^Method tests\\FunctionalTester\:\:assertFalse\(\) has no return type specified\.$#' 197 | identifier: missingType.return 198 | count: 1 199 | path: tests/_support/FunctionalTester.php 200 | 201 | - 202 | message: '#^Method tests\\FunctionalTester\:\:assertFileDoesNotExist\(\) has no return type specified\.$#' 203 | identifier: missingType.return 204 | count: 1 205 | path: tests/_support/FunctionalTester.php 206 | 207 | - 208 | message: '#^Method tests\\FunctionalTester\:\:assertFileEquals\(\) has no return type specified\.$#' 209 | identifier: missingType.return 210 | count: 1 211 | path: tests/_support/FunctionalTester.php 212 | 213 | - 214 | message: '#^Method tests\\FunctionalTester\:\:assertFileEqualsCanonicalizing\(\) has no return type specified\.$#' 215 | identifier: missingType.return 216 | count: 1 217 | path: tests/_support/FunctionalTester.php 218 | 219 | - 220 | message: '#^Method tests\\FunctionalTester\:\:assertFileEqualsIgnoringCase\(\) has no return type specified\.$#' 221 | identifier: missingType.return 222 | count: 1 223 | path: tests/_support/FunctionalTester.php 224 | 225 | - 226 | message: '#^Method tests\\FunctionalTester\:\:assertFileExists\(\) has no return type specified\.$#' 227 | identifier: missingType.return 228 | count: 1 229 | path: tests/_support/FunctionalTester.php 230 | 231 | - 232 | message: '#^Method tests\\FunctionalTester\:\:assertFileIsNotReadable\(\) has no return type specified\.$#' 233 | identifier: missingType.return 234 | count: 1 235 | path: tests/_support/FunctionalTester.php 236 | 237 | - 238 | message: '#^Method tests\\FunctionalTester\:\:assertFileIsNotWritable\(\) has no return type specified\.$#' 239 | identifier: missingType.return 240 | count: 1 241 | path: tests/_support/FunctionalTester.php 242 | 243 | - 244 | message: '#^Method tests\\FunctionalTester\:\:assertFileIsReadable\(\) has no return type specified\.$#' 245 | identifier: missingType.return 246 | count: 1 247 | path: tests/_support/FunctionalTester.php 248 | 249 | - 250 | message: '#^Method tests\\FunctionalTester\:\:assertFileIsWritable\(\) has no return type specified\.$#' 251 | identifier: missingType.return 252 | count: 1 253 | path: tests/_support/FunctionalTester.php 254 | 255 | - 256 | message: '#^Method tests\\FunctionalTester\:\:assertFileNotEquals\(\) has no return type specified\.$#' 257 | identifier: missingType.return 258 | count: 1 259 | path: tests/_support/FunctionalTester.php 260 | 261 | - 262 | message: '#^Method tests\\FunctionalTester\:\:assertFileNotEqualsCanonicalizing\(\) has no return type specified\.$#' 263 | identifier: missingType.return 264 | count: 1 265 | path: tests/_support/FunctionalTester.php 266 | 267 | - 268 | message: '#^Method tests\\FunctionalTester\:\:assertFileNotEqualsIgnoringCase\(\) has no return type specified\.$#' 269 | identifier: missingType.return 270 | count: 1 271 | path: tests/_support/FunctionalTester.php 272 | 273 | - 274 | message: '#^Method tests\\FunctionalTester\:\:assertFileNotExists\(\) has no return type specified\.$#' 275 | identifier: missingType.return 276 | count: 1 277 | path: tests/_support/FunctionalTester.php 278 | 279 | - 280 | message: '#^Method tests\\FunctionalTester\:\:assertFinite\(\) has no return type specified\.$#' 281 | identifier: missingType.return 282 | count: 1 283 | path: tests/_support/FunctionalTester.php 284 | 285 | - 286 | message: '#^Method tests\\FunctionalTester\:\:assertGreaterOrEquals\(\) has no return type specified\.$#' 287 | identifier: missingType.return 288 | count: 1 289 | path: tests/_support/FunctionalTester.php 290 | 291 | - 292 | message: '#^Method tests\\FunctionalTester\:\:assertGreaterThan\(\) has no return type specified\.$#' 293 | identifier: missingType.return 294 | count: 1 295 | path: tests/_support/FunctionalTester.php 296 | 297 | - 298 | message: '#^Method tests\\FunctionalTester\:\:assertGreaterThanOrEqual\(\) has no return type specified\.$#' 299 | identifier: missingType.return 300 | count: 1 301 | path: tests/_support/FunctionalTester.php 302 | 303 | - 304 | message: '#^Method tests\\FunctionalTester\:\:assertInfinite\(\) has no return type specified\.$#' 305 | identifier: missingType.return 306 | count: 1 307 | path: tests/_support/FunctionalTester.php 308 | 309 | - 310 | message: '#^Method tests\\FunctionalTester\:\:assertInstanceOf\(\) has no return type specified\.$#' 311 | identifier: missingType.return 312 | count: 1 313 | path: tests/_support/FunctionalTester.php 314 | 315 | - 316 | message: '#^Method tests\\FunctionalTester\:\:assertIsArray\(\) has no return type specified\.$#' 317 | identifier: missingType.return 318 | count: 1 319 | path: tests/_support/FunctionalTester.php 320 | 321 | - 322 | message: '#^Method tests\\FunctionalTester\:\:assertIsBool\(\) has no return type specified\.$#' 323 | identifier: missingType.return 324 | count: 1 325 | path: tests/_support/FunctionalTester.php 326 | 327 | - 328 | message: '#^Method tests\\FunctionalTester\:\:assertIsCallable\(\) has no return type specified\.$#' 329 | identifier: missingType.return 330 | count: 1 331 | path: tests/_support/FunctionalTester.php 332 | 333 | - 334 | message: '#^Method tests\\FunctionalTester\:\:assertIsClosedResource\(\) has no return type specified\.$#' 335 | identifier: missingType.return 336 | count: 1 337 | path: tests/_support/FunctionalTester.php 338 | 339 | - 340 | message: '#^Method tests\\FunctionalTester\:\:assertIsEmpty\(\) has no return type specified\.$#' 341 | identifier: missingType.return 342 | count: 1 343 | path: tests/_support/FunctionalTester.php 344 | 345 | - 346 | message: '#^Method tests\\FunctionalTester\:\:assertIsFloat\(\) has no return type specified\.$#' 347 | identifier: missingType.return 348 | count: 1 349 | path: tests/_support/FunctionalTester.php 350 | 351 | - 352 | message: '#^Method tests\\FunctionalTester\:\:assertIsInt\(\) has no return type specified\.$#' 353 | identifier: missingType.return 354 | count: 1 355 | path: tests/_support/FunctionalTester.php 356 | 357 | - 358 | message: '#^Method tests\\FunctionalTester\:\:assertIsIterable\(\) has no return type specified\.$#' 359 | identifier: missingType.return 360 | count: 1 361 | path: tests/_support/FunctionalTester.php 362 | 363 | - 364 | message: '#^Method tests\\FunctionalTester\:\:assertIsNotArray\(\) has no return type specified\.$#' 365 | identifier: missingType.return 366 | count: 1 367 | path: tests/_support/FunctionalTester.php 368 | 369 | - 370 | message: '#^Method tests\\FunctionalTester\:\:assertIsNotBool\(\) has no return type specified\.$#' 371 | identifier: missingType.return 372 | count: 1 373 | path: tests/_support/FunctionalTester.php 374 | 375 | - 376 | message: '#^Method tests\\FunctionalTester\:\:assertIsNotCallable\(\) has no return type specified\.$#' 377 | identifier: missingType.return 378 | count: 1 379 | path: tests/_support/FunctionalTester.php 380 | 381 | - 382 | message: '#^Method tests\\FunctionalTester\:\:assertIsNotClosedResource\(\) has no return type specified\.$#' 383 | identifier: missingType.return 384 | count: 1 385 | path: tests/_support/FunctionalTester.php 386 | 387 | - 388 | message: '#^Method tests\\FunctionalTester\:\:assertIsNotFloat\(\) has no return type specified\.$#' 389 | identifier: missingType.return 390 | count: 1 391 | path: tests/_support/FunctionalTester.php 392 | 393 | - 394 | message: '#^Method tests\\FunctionalTester\:\:assertIsNotInt\(\) has no return type specified\.$#' 395 | identifier: missingType.return 396 | count: 1 397 | path: tests/_support/FunctionalTester.php 398 | 399 | - 400 | message: '#^Method tests\\FunctionalTester\:\:assertIsNotIterable\(\) has no return type specified\.$#' 401 | identifier: missingType.return 402 | count: 1 403 | path: tests/_support/FunctionalTester.php 404 | 405 | - 406 | message: '#^Method tests\\FunctionalTester\:\:assertIsNotNumeric\(\) has no return type specified\.$#' 407 | identifier: missingType.return 408 | count: 1 409 | path: tests/_support/FunctionalTester.php 410 | 411 | - 412 | message: '#^Method tests\\FunctionalTester\:\:assertIsNotObject\(\) has no return type specified\.$#' 413 | identifier: missingType.return 414 | count: 1 415 | path: tests/_support/FunctionalTester.php 416 | 417 | - 418 | message: '#^Method tests\\FunctionalTester\:\:assertIsNotReadable\(\) has no return type specified\.$#' 419 | identifier: missingType.return 420 | count: 1 421 | path: tests/_support/FunctionalTester.php 422 | 423 | - 424 | message: '#^Method tests\\FunctionalTester\:\:assertIsNotResource\(\) has no return type specified\.$#' 425 | identifier: missingType.return 426 | count: 1 427 | path: tests/_support/FunctionalTester.php 428 | 429 | - 430 | message: '#^Method tests\\FunctionalTester\:\:assertIsNotScalar\(\) has no return type specified\.$#' 431 | identifier: missingType.return 432 | count: 1 433 | path: tests/_support/FunctionalTester.php 434 | 435 | - 436 | message: '#^Method tests\\FunctionalTester\:\:assertIsNotString\(\) has no return type specified\.$#' 437 | identifier: missingType.return 438 | count: 1 439 | path: tests/_support/FunctionalTester.php 440 | 441 | - 442 | message: '#^Method tests\\FunctionalTester\:\:assertIsNotWritable\(\) has no return type specified\.$#' 443 | identifier: missingType.return 444 | count: 1 445 | path: tests/_support/FunctionalTester.php 446 | 447 | - 448 | message: '#^Method tests\\FunctionalTester\:\:assertIsNumeric\(\) has no return type specified\.$#' 449 | identifier: missingType.return 450 | count: 1 451 | path: tests/_support/FunctionalTester.php 452 | 453 | - 454 | message: '#^Method tests\\FunctionalTester\:\:assertIsObject\(\) has no return type specified\.$#' 455 | identifier: missingType.return 456 | count: 1 457 | path: tests/_support/FunctionalTester.php 458 | 459 | - 460 | message: '#^Method tests\\FunctionalTester\:\:assertIsReadable\(\) has no return type specified\.$#' 461 | identifier: missingType.return 462 | count: 1 463 | path: tests/_support/FunctionalTester.php 464 | 465 | - 466 | message: '#^Method tests\\FunctionalTester\:\:assertIsResource\(\) has no return type specified\.$#' 467 | identifier: missingType.return 468 | count: 1 469 | path: tests/_support/FunctionalTester.php 470 | 471 | - 472 | message: '#^Method tests\\FunctionalTester\:\:assertIsScalar\(\) has no return type specified\.$#' 473 | identifier: missingType.return 474 | count: 1 475 | path: tests/_support/FunctionalTester.php 476 | 477 | - 478 | message: '#^Method tests\\FunctionalTester\:\:assertIsString\(\) has no return type specified\.$#' 479 | identifier: missingType.return 480 | count: 1 481 | path: tests/_support/FunctionalTester.php 482 | 483 | - 484 | message: '#^Method tests\\FunctionalTester\:\:assertIsWritable\(\) has no return type specified\.$#' 485 | identifier: missingType.return 486 | count: 1 487 | path: tests/_support/FunctionalTester.php 488 | 489 | - 490 | message: '#^Method tests\\FunctionalTester\:\:assertJson\(\) has no return type specified\.$#' 491 | identifier: missingType.return 492 | count: 1 493 | path: tests/_support/FunctionalTester.php 494 | 495 | - 496 | message: '#^Method tests\\FunctionalTester\:\:assertJsonFileEqualsJsonFile\(\) has no return type specified\.$#' 497 | identifier: missingType.return 498 | count: 1 499 | path: tests/_support/FunctionalTester.php 500 | 501 | - 502 | message: '#^Method tests\\FunctionalTester\:\:assertJsonFileNotEqualsJsonFile\(\) has no return type specified\.$#' 503 | identifier: missingType.return 504 | count: 1 505 | path: tests/_support/FunctionalTester.php 506 | 507 | - 508 | message: '#^Method tests\\FunctionalTester\:\:assertJsonStringEqualsJsonFile\(\) has no return type specified\.$#' 509 | identifier: missingType.return 510 | count: 1 511 | path: tests/_support/FunctionalTester.php 512 | 513 | - 514 | message: '#^Method tests\\FunctionalTester\:\:assertJsonStringEqualsJsonString\(\) has no return type specified\.$#' 515 | identifier: missingType.return 516 | count: 1 517 | path: tests/_support/FunctionalTester.php 518 | 519 | - 520 | message: '#^Method tests\\FunctionalTester\:\:assertJsonStringNotEqualsJsonFile\(\) has no return type specified\.$#' 521 | identifier: missingType.return 522 | count: 1 523 | path: tests/_support/FunctionalTester.php 524 | 525 | - 526 | message: '#^Method tests\\FunctionalTester\:\:assertJsonStringNotEqualsJsonString\(\) has no return type specified\.$#' 527 | identifier: missingType.return 528 | count: 1 529 | path: tests/_support/FunctionalTester.php 530 | 531 | - 532 | message: '#^Method tests\\FunctionalTester\:\:assertLessOrEquals\(\) has no return type specified\.$#' 533 | identifier: missingType.return 534 | count: 1 535 | path: tests/_support/FunctionalTester.php 536 | 537 | - 538 | message: '#^Method tests\\FunctionalTester\:\:assertLessThan\(\) has no return type specified\.$#' 539 | identifier: missingType.return 540 | count: 1 541 | path: tests/_support/FunctionalTester.php 542 | 543 | - 544 | message: '#^Method tests\\FunctionalTester\:\:assertLessThanOrEqual\(\) has no return type specified\.$#' 545 | identifier: missingType.return 546 | count: 1 547 | path: tests/_support/FunctionalTester.php 548 | 549 | - 550 | message: '#^Method tests\\FunctionalTester\:\:assertMatchesRegularExpression\(\) has no return type specified\.$#' 551 | identifier: missingType.return 552 | count: 1 553 | path: tests/_support/FunctionalTester.php 554 | 555 | - 556 | message: '#^Method tests\\FunctionalTester\:\:assertNan\(\) has no return type specified\.$#' 557 | identifier: missingType.return 558 | count: 1 559 | path: tests/_support/FunctionalTester.php 560 | 561 | - 562 | message: '#^Method tests\\FunctionalTester\:\:assertNotContains\(\) has no return type specified\.$#' 563 | identifier: missingType.return 564 | count: 1 565 | path: tests/_support/FunctionalTester.php 566 | 567 | - 568 | message: '#^Method tests\\FunctionalTester\:\:assertNotContains\(\) has parameter \$haystack with no value type specified in iterable type iterable\.$#' 569 | identifier: missingType.iterableValue 570 | count: 1 571 | path: tests/_support/FunctionalTester.php 572 | 573 | - 574 | message: '#^Method tests\\FunctionalTester\:\:assertNotContainsEquals\(\) has no return type specified\.$#' 575 | identifier: missingType.return 576 | count: 1 577 | path: tests/_support/FunctionalTester.php 578 | 579 | - 580 | message: '#^Method tests\\FunctionalTester\:\:assertNotContainsEquals\(\) has parameter \$haystack with no value type specified in iterable type iterable\.$#' 581 | identifier: missingType.iterableValue 582 | count: 1 583 | path: tests/_support/FunctionalTester.php 584 | 585 | - 586 | message: '#^Method tests\\FunctionalTester\:\:assertNotContainsEquals\(\) has parameter \$needle with no type specified\.$#' 587 | identifier: missingType.parameter 588 | count: 1 589 | path: tests/_support/FunctionalTester.php 590 | 591 | - 592 | message: '#^Method tests\\FunctionalTester\:\:assertNotContainsOnly\(\) has no return type specified\.$#' 593 | identifier: missingType.return 594 | count: 1 595 | path: tests/_support/FunctionalTester.php 596 | 597 | - 598 | message: '#^Method tests\\FunctionalTester\:\:assertNotContainsOnly\(\) has parameter \$haystack with no value type specified in iterable type iterable\.$#' 599 | identifier: missingType.iterableValue 600 | count: 1 601 | path: tests/_support/FunctionalTester.php 602 | 603 | - 604 | message: '#^Method tests\\FunctionalTester\:\:assertNotCount\(\) has no return type specified\.$#' 605 | identifier: missingType.return 606 | count: 1 607 | path: tests/_support/FunctionalTester.php 608 | 609 | - 610 | message: '#^Method tests\\FunctionalTester\:\:assertNotCount\(\) has parameter \$haystack with no value type specified in iterable type iterable\.$#' 611 | identifier: missingType.iterableValue 612 | count: 1 613 | path: tests/_support/FunctionalTester.php 614 | 615 | - 616 | message: '#^Method tests\\FunctionalTester\:\:assertNotEmpty\(\) has no return type specified\.$#' 617 | identifier: missingType.return 618 | count: 1 619 | path: tests/_support/FunctionalTester.php 620 | 621 | - 622 | message: '#^Method tests\\FunctionalTester\:\:assertNotEquals\(\) has no return type specified\.$#' 623 | identifier: missingType.return 624 | count: 1 625 | path: tests/_support/FunctionalTester.php 626 | 627 | - 628 | message: '#^Method tests\\FunctionalTester\:\:assertNotEqualsCanonicalizing\(\) has no return type specified\.$#' 629 | identifier: missingType.return 630 | count: 1 631 | path: tests/_support/FunctionalTester.php 632 | 633 | - 634 | message: '#^Method tests\\FunctionalTester\:\:assertNotEqualsIgnoringCase\(\) has no return type specified\.$#' 635 | identifier: missingType.return 636 | count: 1 637 | path: tests/_support/FunctionalTester.php 638 | 639 | - 640 | message: '#^Method tests\\FunctionalTester\:\:assertNotEqualsWithDelta\(\) has no return type specified\.$#' 641 | identifier: missingType.return 642 | count: 1 643 | path: tests/_support/FunctionalTester.php 644 | 645 | - 646 | message: '#^Method tests\\FunctionalTester\:\:assertNotFalse\(\) has no return type specified\.$#' 647 | identifier: missingType.return 648 | count: 1 649 | path: tests/_support/FunctionalTester.php 650 | 651 | - 652 | message: '#^Method tests\\FunctionalTester\:\:assertNotInstanceOf\(\) has no return type specified\.$#' 653 | identifier: missingType.return 654 | count: 1 655 | path: tests/_support/FunctionalTester.php 656 | 657 | - 658 | message: '#^Method tests\\FunctionalTester\:\:assertNotNull\(\) has no return type specified\.$#' 659 | identifier: missingType.return 660 | count: 1 661 | path: tests/_support/FunctionalTester.php 662 | 663 | - 664 | message: '#^Method tests\\FunctionalTester\:\:assertNotRegExp\(\) has no return type specified\.$#' 665 | identifier: missingType.return 666 | count: 1 667 | path: tests/_support/FunctionalTester.php 668 | 669 | - 670 | message: '#^Method tests\\FunctionalTester\:\:assertNotSame\(\) has no return type specified\.$#' 671 | identifier: missingType.return 672 | count: 1 673 | path: tests/_support/FunctionalTester.php 674 | 675 | - 676 | message: '#^Method tests\\FunctionalTester\:\:assertNotSameSize\(\) has no return type specified\.$#' 677 | identifier: missingType.return 678 | count: 1 679 | path: tests/_support/FunctionalTester.php 680 | 681 | - 682 | message: '#^Method tests\\FunctionalTester\:\:assertNotSameSize\(\) has parameter \$actual with no value type specified in iterable type iterable\.$#' 683 | identifier: missingType.iterableValue 684 | count: 1 685 | path: tests/_support/FunctionalTester.php 686 | 687 | - 688 | message: '#^Method tests\\FunctionalTester\:\:assertNotSameSize\(\) has parameter \$expected with no value type specified in iterable type iterable\.$#' 689 | identifier: missingType.iterableValue 690 | count: 1 691 | path: tests/_support/FunctionalTester.php 692 | 693 | - 694 | message: '#^Method tests\\FunctionalTester\:\:assertNotTrue\(\) has no return type specified\.$#' 695 | identifier: missingType.return 696 | count: 1 697 | path: tests/_support/FunctionalTester.php 698 | 699 | - 700 | message: '#^Method tests\\FunctionalTester\:\:assertNull\(\) has no return type specified\.$#' 701 | identifier: missingType.return 702 | count: 1 703 | path: tests/_support/FunctionalTester.php 704 | 705 | - 706 | message: '#^Method tests\\FunctionalTester\:\:assertObjectHasAttribute\(\) has no return type specified\.$#' 707 | identifier: missingType.return 708 | count: 1 709 | path: tests/_support/FunctionalTester.php 710 | 711 | - 712 | message: '#^Method tests\\FunctionalTester\:\:assertObjectNotHasAttribute\(\) has no return type specified\.$#' 713 | identifier: missingType.return 714 | count: 1 715 | path: tests/_support/FunctionalTester.php 716 | 717 | - 718 | message: '#^Method tests\\FunctionalTester\:\:assertRegExp\(\) has no return type specified\.$#' 719 | identifier: missingType.return 720 | count: 1 721 | path: tests/_support/FunctionalTester.php 722 | 723 | - 724 | message: '#^Method tests\\FunctionalTester\:\:assertSame\(\) has no return type specified\.$#' 725 | identifier: missingType.return 726 | count: 1 727 | path: tests/_support/FunctionalTester.php 728 | 729 | - 730 | message: '#^Method tests\\FunctionalTester\:\:assertSameSize\(\) has no return type specified\.$#' 731 | identifier: missingType.return 732 | count: 1 733 | path: tests/_support/FunctionalTester.php 734 | 735 | - 736 | message: '#^Method tests\\FunctionalTester\:\:assertSameSize\(\) has parameter \$actual with no value type specified in iterable type iterable\.$#' 737 | identifier: missingType.iterableValue 738 | count: 1 739 | path: tests/_support/FunctionalTester.php 740 | 741 | - 742 | message: '#^Method tests\\FunctionalTester\:\:assertSameSize\(\) has parameter \$expected with no value type specified in iterable type iterable\.$#' 743 | identifier: missingType.iterableValue 744 | count: 1 745 | path: tests/_support/FunctionalTester.php 746 | 747 | - 748 | message: '#^Method tests\\FunctionalTester\:\:assertStringContainsString\(\) has no return type specified\.$#' 749 | identifier: missingType.return 750 | count: 1 751 | path: tests/_support/FunctionalTester.php 752 | 753 | - 754 | message: '#^Method tests\\FunctionalTester\:\:assertStringContainsStringIgnoringCase\(\) has no return type specified\.$#' 755 | identifier: missingType.return 756 | count: 1 757 | path: tests/_support/FunctionalTester.php 758 | 759 | - 760 | message: '#^Method tests\\FunctionalTester\:\:assertStringEndsNotWith\(\) has no return type specified\.$#' 761 | identifier: missingType.return 762 | count: 1 763 | path: tests/_support/FunctionalTester.php 764 | 765 | - 766 | message: '#^Method tests\\FunctionalTester\:\:assertStringEndsWith\(\) has no return type specified\.$#' 767 | identifier: missingType.return 768 | count: 1 769 | path: tests/_support/FunctionalTester.php 770 | 771 | - 772 | message: '#^Method tests\\FunctionalTester\:\:assertStringEqualsFile\(\) has no return type specified\.$#' 773 | identifier: missingType.return 774 | count: 1 775 | path: tests/_support/FunctionalTester.php 776 | 777 | - 778 | message: '#^Method tests\\FunctionalTester\:\:assertStringEqualsFileCanonicalizing\(\) has no return type specified\.$#' 779 | identifier: missingType.return 780 | count: 1 781 | path: tests/_support/FunctionalTester.php 782 | 783 | - 784 | message: '#^Method tests\\FunctionalTester\:\:assertStringEqualsFileIgnoringCase\(\) has no return type specified\.$#' 785 | identifier: missingType.return 786 | count: 1 787 | path: tests/_support/FunctionalTester.php 788 | 789 | - 790 | message: '#^Method tests\\FunctionalTester\:\:assertStringMatchesFormat\(\) has no return type specified\.$#' 791 | identifier: missingType.return 792 | count: 1 793 | path: tests/_support/FunctionalTester.php 794 | 795 | - 796 | message: '#^Method tests\\FunctionalTester\:\:assertStringMatchesFormatFile\(\) has no return type specified\.$#' 797 | identifier: missingType.return 798 | count: 1 799 | path: tests/_support/FunctionalTester.php 800 | 801 | - 802 | message: '#^Method tests\\FunctionalTester\:\:assertStringNotContainsString\(\) has no return type specified\.$#' 803 | identifier: missingType.return 804 | count: 1 805 | path: tests/_support/FunctionalTester.php 806 | 807 | - 808 | message: '#^Method tests\\FunctionalTester\:\:assertStringNotContainsStringIgnoringCase\(\) has no return type specified\.$#' 809 | identifier: missingType.return 810 | count: 1 811 | path: tests/_support/FunctionalTester.php 812 | 813 | - 814 | message: '#^Method tests\\FunctionalTester\:\:assertStringNotEqualsFile\(\) has no return type specified\.$#' 815 | identifier: missingType.return 816 | count: 1 817 | path: tests/_support/FunctionalTester.php 818 | 819 | - 820 | message: '#^Method tests\\FunctionalTester\:\:assertStringNotEqualsFileCanonicalizing\(\) has no return type specified\.$#' 821 | identifier: missingType.return 822 | count: 1 823 | path: tests/_support/FunctionalTester.php 824 | 825 | - 826 | message: '#^Method tests\\FunctionalTester\:\:assertStringNotEqualsFileIgnoringCase\(\) has no return type specified\.$#' 827 | identifier: missingType.return 828 | count: 1 829 | path: tests/_support/FunctionalTester.php 830 | 831 | - 832 | message: '#^Method tests\\FunctionalTester\:\:assertStringNotMatchesFormat\(\) has no return type specified\.$#' 833 | identifier: missingType.return 834 | count: 1 835 | path: tests/_support/FunctionalTester.php 836 | 837 | - 838 | message: '#^Method tests\\FunctionalTester\:\:assertStringNotMatchesFormatFile\(\) has no return type specified\.$#' 839 | identifier: missingType.return 840 | count: 1 841 | path: tests/_support/FunctionalTester.php 842 | 843 | - 844 | message: '#^Method tests\\FunctionalTester\:\:assertStringStartsNotWith\(\) has no return type specified\.$#' 845 | identifier: missingType.return 846 | count: 1 847 | path: tests/_support/FunctionalTester.php 848 | 849 | - 850 | message: '#^Method tests\\FunctionalTester\:\:assertStringStartsWith\(\) has no return type specified\.$#' 851 | identifier: missingType.return 852 | count: 1 853 | path: tests/_support/FunctionalTester.php 854 | 855 | - 856 | message: '#^Method tests\\FunctionalTester\:\:assertThat\(\) has no return type specified\.$#' 857 | identifier: missingType.return 858 | count: 1 859 | path: tests/_support/FunctionalTester.php 860 | 861 | - 862 | message: '#^Method tests\\FunctionalTester\:\:assertThatItsNot\(\) has no return type specified\.$#' 863 | identifier: missingType.return 864 | count: 1 865 | path: tests/_support/FunctionalTester.php 866 | 867 | - 868 | message: '#^Method tests\\FunctionalTester\:\:assertTrue\(\) has no return type specified\.$#' 869 | identifier: missingType.return 870 | count: 1 871 | path: tests/_support/FunctionalTester.php 872 | 873 | - 874 | message: '#^Method tests\\FunctionalTester\:\:assertXmlFileEqualsXmlFile\(\) has no return type specified\.$#' 875 | identifier: missingType.return 876 | count: 1 877 | path: tests/_support/FunctionalTester.php 878 | 879 | - 880 | message: '#^Method tests\\FunctionalTester\:\:assertXmlFileNotEqualsXmlFile\(\) has no return type specified\.$#' 881 | identifier: missingType.return 882 | count: 1 883 | path: tests/_support/FunctionalTester.php 884 | 885 | - 886 | message: '#^Method tests\\FunctionalTester\:\:assertXmlStringEqualsXmlFile\(\) has no return type specified\.$#' 887 | identifier: missingType.return 888 | count: 1 889 | path: tests/_support/FunctionalTester.php 890 | 891 | - 892 | message: '#^Method tests\\FunctionalTester\:\:assertXmlStringEqualsXmlString\(\) has no return type specified\.$#' 893 | identifier: missingType.return 894 | count: 1 895 | path: tests/_support/FunctionalTester.php 896 | 897 | - 898 | message: '#^Method tests\\FunctionalTester\:\:assertXmlStringNotEqualsXmlFile\(\) has no return type specified\.$#' 899 | identifier: missingType.return 900 | count: 1 901 | path: tests/_support/FunctionalTester.php 902 | 903 | - 904 | message: '#^Method tests\\FunctionalTester\:\:assertXmlStringNotEqualsXmlString\(\) has no return type specified\.$#' 905 | identifier: missingType.return 906 | count: 1 907 | path: tests/_support/FunctionalTester.php 908 | 909 | - 910 | message: '#^Method tests\\FunctionalTester\:\:attachFile\(\) has parameter \$field with no type specified\.$#' 911 | identifier: missingType.parameter 912 | count: 1 913 | path: tests/_support/FunctionalTester.php 914 | 915 | - 916 | message: '#^Method tests\\FunctionalTester\:\:canSee\(\) has parameter \$selector with no value type specified in iterable type array\.$#' 917 | identifier: missingType.iterableValue 918 | count: 1 919 | path: tests/_support/FunctionalTester.php 920 | 921 | - 922 | message: '#^Method tests\\FunctionalTester\:\:canSeeCheckboxIsChecked\(\) has parameter \$checkbox with no type specified\.$#' 923 | identifier: missingType.parameter 924 | count: 1 925 | path: tests/_support/FunctionalTester.php 926 | 927 | - 928 | message: '#^Method tests\\FunctionalTester\:\:canSeeCookie\(\) has parameter \$cookie with no type specified\.$#' 929 | identifier: missingType.parameter 930 | count: 1 931 | path: tests/_support/FunctionalTester.php 932 | 933 | - 934 | message: '#^Method tests\\FunctionalTester\:\:canSeeCookie\(\) has parameter \$params with no type specified\.$#' 935 | identifier: missingType.parameter 936 | count: 1 937 | path: tests/_support/FunctionalTester.php 938 | 939 | - 940 | message: '#^Method tests\\FunctionalTester\:\:canSeeElement\(\) has parameter \$attributes with no value type specified in iterable type array\.$#' 941 | identifier: missingType.iterableValue 942 | count: 1 943 | path: tests/_support/FunctionalTester.php 944 | 945 | - 946 | message: '#^Method tests\\FunctionalTester\:\:canSeeElement\(\) has parameter \$selector with no type specified\.$#' 947 | identifier: missingType.parameter 948 | count: 1 949 | path: tests/_support/FunctionalTester.php 950 | 951 | - 952 | message: '#^Method tests\\FunctionalTester\:\:canSeeInField\(\) has parameter \$field with no value type specified in iterable type array\.$#' 953 | identifier: missingType.iterableValue 954 | count: 1 955 | path: tests/_support/FunctionalTester.php 956 | 957 | - 958 | message: '#^Method tests\\FunctionalTester\:\:canSeeInField\(\) has parameter \$value with no type specified\.$#' 959 | identifier: missingType.parameter 960 | count: 1 961 | path: tests/_support/FunctionalTester.php 962 | 963 | - 964 | message: '#^Method tests\\FunctionalTester\:\:canSeeInFormFields\(\) has parameter \$formSelector with no type specified\.$#' 965 | identifier: missingType.parameter 966 | count: 1 967 | path: tests/_support/FunctionalTester.php 968 | 969 | - 970 | message: '#^Method tests\\FunctionalTester\:\:canSeeInFormFields\(\) has parameter \$params with no value type specified in iterable type array\.$#' 971 | identifier: missingType.iterableValue 972 | count: 1 973 | path: tests/_support/FunctionalTester.php 974 | 975 | - 976 | message: '#^Method tests\\FunctionalTester\:\:canSeeInTitle\(\) has parameter \$title with no type specified\.$#' 977 | identifier: missingType.parameter 978 | count: 1 979 | path: tests/_support/FunctionalTester.php 980 | 981 | - 982 | message: '#^Method tests\\FunctionalTester\:\:canSeeNumberOfElements\(\) has parameter \$selector with no type specified\.$#' 983 | identifier: missingType.parameter 984 | count: 1 985 | path: tests/_support/FunctionalTester.php 986 | 987 | - 988 | message: '#^Method tests\\FunctionalTester\:\:canSeeOptionIsSelected\(\) has parameter \$optionText with no type specified\.$#' 989 | identifier: missingType.parameter 990 | count: 1 991 | path: tests/_support/FunctionalTester.php 992 | 993 | - 994 | message: '#^Method tests\\FunctionalTester\:\:canSeeOptionIsSelected\(\) has parameter \$selector with no type specified\.$#' 995 | identifier: missingType.parameter 996 | count: 1 997 | path: tests/_support/FunctionalTester.php 998 | 999 | - 1000 | message: '#^Method tests\\FunctionalTester\:\:cantSee\(\) has parameter \$selector with no value type specified in iterable type array\.$#' 1001 | identifier: missingType.iterableValue 1002 | count: 1 1003 | path: tests/_support/FunctionalTester.php 1004 | 1005 | - 1006 | message: '#^Method tests\\FunctionalTester\:\:cantSeeCheckboxIsChecked\(\) has parameter \$checkbox with no type specified\.$#' 1007 | identifier: missingType.parameter 1008 | count: 1 1009 | path: tests/_support/FunctionalTester.php 1010 | 1011 | - 1012 | message: '#^Method tests\\FunctionalTester\:\:cantSeeCookie\(\) has parameter \$cookie with no type specified\.$#' 1013 | identifier: missingType.parameter 1014 | count: 1 1015 | path: tests/_support/FunctionalTester.php 1016 | 1017 | - 1018 | message: '#^Method tests\\FunctionalTester\:\:cantSeeCookie\(\) has parameter \$params with no type specified\.$#' 1019 | identifier: missingType.parameter 1020 | count: 1 1021 | path: tests/_support/FunctionalTester.php 1022 | 1023 | - 1024 | message: '#^Method tests\\FunctionalTester\:\:cantSeeElement\(\) has parameter \$attributes with no value type specified in iterable type array\.$#' 1025 | identifier: missingType.iterableValue 1026 | count: 1 1027 | path: tests/_support/FunctionalTester.php 1028 | 1029 | - 1030 | message: '#^Method tests\\FunctionalTester\:\:cantSeeElement\(\) has parameter \$selector with no type specified\.$#' 1031 | identifier: missingType.parameter 1032 | count: 1 1033 | path: tests/_support/FunctionalTester.php 1034 | 1035 | - 1036 | message: '#^Method tests\\FunctionalTester\:\:cantSeeInField\(\) has parameter \$field with no value type specified in iterable type array\.$#' 1037 | identifier: missingType.iterableValue 1038 | count: 1 1039 | path: tests/_support/FunctionalTester.php 1040 | 1041 | - 1042 | message: '#^Method tests\\FunctionalTester\:\:cantSeeInField\(\) has parameter \$value with no type specified\.$#' 1043 | identifier: missingType.parameter 1044 | count: 1 1045 | path: tests/_support/FunctionalTester.php 1046 | 1047 | - 1048 | message: '#^Method tests\\FunctionalTester\:\:cantSeeInFormFields\(\) has parameter \$formSelector with no type specified\.$#' 1049 | identifier: missingType.parameter 1050 | count: 1 1051 | path: tests/_support/FunctionalTester.php 1052 | 1053 | - 1054 | message: '#^Method tests\\FunctionalTester\:\:cantSeeInFormFields\(\) has parameter \$params with no value type specified in iterable type array\.$#' 1055 | identifier: missingType.iterableValue 1056 | count: 1 1057 | path: tests/_support/FunctionalTester.php 1058 | 1059 | - 1060 | message: '#^Method tests\\FunctionalTester\:\:cantSeeInTitle\(\) has parameter \$title with no type specified\.$#' 1061 | identifier: missingType.parameter 1062 | count: 1 1063 | path: tests/_support/FunctionalTester.php 1064 | 1065 | - 1066 | message: '#^Method tests\\FunctionalTester\:\:cantSeeOptionIsSelected\(\) has parameter \$optionText with no type specified\.$#' 1067 | identifier: missingType.parameter 1068 | count: 1 1069 | path: tests/_support/FunctionalTester.php 1070 | 1071 | - 1072 | message: '#^Method tests\\FunctionalTester\:\:cantSeeOptionIsSelected\(\) has parameter \$selector with no type specified\.$#' 1073 | identifier: missingType.parameter 1074 | count: 1 1075 | path: tests/_support/FunctionalTester.php 1076 | 1077 | - 1078 | message: '#^Method tests\\FunctionalTester\:\:checkOption\(\) has parameter \$option with no type specified\.$#' 1079 | identifier: missingType.parameter 1080 | count: 1 1081 | path: tests/_support/FunctionalTester.php 1082 | 1083 | - 1084 | message: '#^Method tests\\FunctionalTester\:\:click\(\) has parameter \$context with no type specified\.$#' 1085 | identifier: missingType.parameter 1086 | count: 1 1087 | path: tests/_support/FunctionalTester.php 1088 | 1089 | - 1090 | message: '#^Method tests\\FunctionalTester\:\:click\(\) has parameter \$link with no value type specified in iterable type array\.$#' 1091 | identifier: missingType.iterableValue 1092 | count: 1 1093 | path: tests/_support/FunctionalTester.php 1094 | 1095 | - 1096 | message: '#^Method tests\\FunctionalTester\:\:dontSee\(\) has parameter \$selector with no value type specified in iterable type array\.$#' 1097 | identifier: missingType.iterableValue 1098 | count: 1 1099 | path: tests/_support/FunctionalTester.php 1100 | 1101 | - 1102 | message: '#^Method tests\\FunctionalTester\:\:dontSeeCheckboxIsChecked\(\) has parameter \$checkbox with no type specified\.$#' 1103 | identifier: missingType.parameter 1104 | count: 1 1105 | path: tests/_support/FunctionalTester.php 1106 | 1107 | - 1108 | message: '#^Method tests\\FunctionalTester\:\:dontSeeCookie\(\) has parameter \$cookie with no type specified\.$#' 1109 | identifier: missingType.parameter 1110 | count: 1 1111 | path: tests/_support/FunctionalTester.php 1112 | 1113 | - 1114 | message: '#^Method tests\\FunctionalTester\:\:dontSeeCookie\(\) has parameter \$params with no type specified\.$#' 1115 | identifier: missingType.parameter 1116 | count: 1 1117 | path: tests/_support/FunctionalTester.php 1118 | 1119 | - 1120 | message: '#^Method tests\\FunctionalTester\:\:dontSeeElement\(\) has parameter \$attributes with no value type specified in iterable type array\.$#' 1121 | identifier: missingType.iterableValue 1122 | count: 1 1123 | path: tests/_support/FunctionalTester.php 1124 | 1125 | - 1126 | message: '#^Method tests\\FunctionalTester\:\:dontSeeElement\(\) has parameter \$selector with no type specified\.$#' 1127 | identifier: missingType.parameter 1128 | count: 1 1129 | path: tests/_support/FunctionalTester.php 1130 | 1131 | - 1132 | message: '#^Method tests\\FunctionalTester\:\:dontSeeInField\(\) has parameter \$field with no value type specified in iterable type array\.$#' 1133 | identifier: missingType.iterableValue 1134 | count: 1 1135 | path: tests/_support/FunctionalTester.php 1136 | 1137 | - 1138 | message: '#^Method tests\\FunctionalTester\:\:dontSeeInField\(\) has parameter \$value with no type specified\.$#' 1139 | identifier: missingType.parameter 1140 | count: 1 1141 | path: tests/_support/FunctionalTester.php 1142 | 1143 | - 1144 | message: '#^Method tests\\FunctionalTester\:\:dontSeeInFormFields\(\) has parameter \$formSelector with no type specified\.$#' 1145 | identifier: missingType.parameter 1146 | count: 1 1147 | path: tests/_support/FunctionalTester.php 1148 | 1149 | - 1150 | message: '#^Method tests\\FunctionalTester\:\:dontSeeInFormFields\(\) has parameter \$params with no value type specified in iterable type array\.$#' 1151 | identifier: missingType.iterableValue 1152 | count: 1 1153 | path: tests/_support/FunctionalTester.php 1154 | 1155 | - 1156 | message: '#^Method tests\\FunctionalTester\:\:dontSeeInTitle\(\) has parameter \$title with no type specified\.$#' 1157 | identifier: missingType.parameter 1158 | count: 1 1159 | path: tests/_support/FunctionalTester.php 1160 | 1161 | - 1162 | message: '#^Method tests\\FunctionalTester\:\:dontSeeOptionIsSelected\(\) has parameter \$optionText with no type specified\.$#' 1163 | identifier: missingType.parameter 1164 | count: 1 1165 | path: tests/_support/FunctionalTester.php 1166 | 1167 | - 1168 | message: '#^Method tests\\FunctionalTester\:\:dontSeeOptionIsSelected\(\) has parameter \$selector with no type specified\.$#' 1169 | identifier: missingType.parameter 1170 | count: 1 1171 | path: tests/_support/FunctionalTester.php 1172 | 1173 | - 1174 | message: '#^Method tests\\FunctionalTester\:\:fail\(\) has no return type specified\.$#' 1175 | identifier: missingType.return 1176 | count: 1 1177 | path: tests/_support/FunctionalTester.php 1178 | 1179 | - 1180 | message: '#^Method tests\\FunctionalTester\:\:fillField\(\) has parameter \$field with no type specified\.$#' 1181 | identifier: missingType.parameter 1182 | count: 1 1183 | path: tests/_support/FunctionalTester.php 1184 | 1185 | - 1186 | message: '#^Method tests\\FunctionalTester\:\:fillField\(\) has parameter \$value with no type specified\.$#' 1187 | identifier: missingType.parameter 1188 | count: 1 1189 | path: tests/_support/FunctionalTester.php 1190 | 1191 | - 1192 | message: '#^Method tests\\FunctionalTester\:\:grabAttributeFrom\(\) has parameter \$cssOrXpath with no type specified\.$#' 1193 | identifier: missingType.parameter 1194 | count: 1 1195 | path: tests/_support/FunctionalTester.php 1196 | 1197 | - 1198 | message: '#^Method tests\\FunctionalTester\:\:grabCookie\(\) has parameter \$params with no value type specified in iterable type array\.$#' 1199 | identifier: missingType.iterableValue 1200 | count: 1 1201 | path: tests/_support/FunctionalTester.php 1202 | 1203 | - 1204 | message: '#^Method tests\\FunctionalTester\:\:grabFixtures\(\) has invalid return type tests\\_generated\\Fixture\.$#' 1205 | identifier: class.notFound 1206 | count: 1 1207 | path: tests/_support/FunctionalTester.php 1208 | 1209 | - 1210 | message: '#^Method tests\\FunctionalTester\:\:grabMultiple\(\) has parameter \$cssOrXpath with no type specified\.$#' 1211 | identifier: missingType.parameter 1212 | count: 1 1213 | path: tests/_support/FunctionalTester.php 1214 | 1215 | - 1216 | message: '#^Method tests\\FunctionalTester\:\:grabRecord\(\) has invalid return type tests\\_generated\\ActiveRecordInterface\.$#' 1217 | identifier: class.notFound 1218 | count: 1 1219 | path: tests/_support/FunctionalTester.php 1220 | 1221 | - 1222 | message: '#^Method tests\\FunctionalTester\:\:grabRecord\(\) return type has no value type specified in iterable type array\.$#' 1223 | identifier: missingType.iterableValue 1224 | count: 1 1225 | path: tests/_support/FunctionalTester.php 1226 | 1227 | - 1228 | message: '#^Method tests\\FunctionalTester\:\:grabSentEmails\(\) has invalid return type tests\\_generated\\MessageInterface\.$#' 1229 | identifier: class.notFound 1230 | count: 1 1231 | path: tests/_support/FunctionalTester.php 1232 | 1233 | - 1234 | message: '#^Method tests\\FunctionalTester\:\:grabTextFrom\(\) has parameter \$cssOrXPathOrRegex with no type specified\.$#' 1235 | identifier: missingType.parameter 1236 | count: 1 1237 | path: tests/_support/FunctionalTester.php 1238 | 1239 | - 1240 | message: '#^Method tests\\FunctionalTester\:\:grabValueFrom\(\) has parameter \$field with no type specified\.$#' 1241 | identifier: missingType.parameter 1242 | count: 1 1243 | path: tests/_support/FunctionalTester.php 1244 | 1245 | - 1246 | message: '#^Method tests\\FunctionalTester\:\:markTestIncomplete\(\) has no return type specified\.$#' 1247 | identifier: missingType.return 1248 | count: 1 1249 | path: tests/_support/FunctionalTester.php 1250 | 1251 | - 1252 | message: '#^Method tests\\FunctionalTester\:\:markTestSkipped\(\) has no return type specified\.$#' 1253 | identifier: missingType.return 1254 | count: 1 1255 | path: tests/_support/FunctionalTester.php 1256 | 1257 | - 1258 | message: '#^Method tests\\FunctionalTester\:\:resetCookie\(\) has parameter \$cookie with no type specified\.$#' 1259 | identifier: missingType.parameter 1260 | count: 1 1261 | path: tests/_support/FunctionalTester.php 1262 | 1263 | - 1264 | message: '#^Method tests\\FunctionalTester\:\:resetCookie\(\) has parameter \$params with no type specified\.$#' 1265 | identifier: missingType.parameter 1266 | count: 1 1267 | path: tests/_support/FunctionalTester.php 1268 | 1269 | - 1270 | message: '#^Method tests\\FunctionalTester\:\:see\(\) has parameter \$selector with no value type specified in iterable type array\.$#' 1271 | identifier: missingType.iterableValue 1272 | count: 1 1273 | path: tests/_support/FunctionalTester.php 1274 | 1275 | - 1276 | message: '#^Method tests\\FunctionalTester\:\:seeCheckboxIsChecked\(\) has parameter \$checkbox with no type specified\.$#' 1277 | identifier: missingType.parameter 1278 | count: 1 1279 | path: tests/_support/FunctionalTester.php 1280 | 1281 | - 1282 | message: '#^Method tests\\FunctionalTester\:\:seeCookie\(\) has parameter \$cookie with no type specified\.$#' 1283 | identifier: missingType.parameter 1284 | count: 1 1285 | path: tests/_support/FunctionalTester.php 1286 | 1287 | - 1288 | message: '#^Method tests\\FunctionalTester\:\:seeCookie\(\) has parameter \$params with no type specified\.$#' 1289 | identifier: missingType.parameter 1290 | count: 1 1291 | path: tests/_support/FunctionalTester.php 1292 | 1293 | - 1294 | message: '#^Method tests\\FunctionalTester\:\:seeElement\(\) has parameter \$attributes with no value type specified in iterable type array\.$#' 1295 | identifier: missingType.iterableValue 1296 | count: 1 1297 | path: tests/_support/FunctionalTester.php 1298 | 1299 | - 1300 | message: '#^Method tests\\FunctionalTester\:\:seeElement\(\) has parameter \$selector with no type specified\.$#' 1301 | identifier: missingType.parameter 1302 | count: 1 1303 | path: tests/_support/FunctionalTester.php 1304 | 1305 | - 1306 | message: '#^Method tests\\FunctionalTester\:\:seeInField\(\) has parameter \$field with no value type specified in iterable type array\.$#' 1307 | identifier: missingType.iterableValue 1308 | count: 1 1309 | path: tests/_support/FunctionalTester.php 1310 | 1311 | - 1312 | message: '#^Method tests\\FunctionalTester\:\:seeInField\(\) has parameter \$value with no type specified\.$#' 1313 | identifier: missingType.parameter 1314 | count: 1 1315 | path: tests/_support/FunctionalTester.php 1316 | 1317 | - 1318 | message: '#^Method tests\\FunctionalTester\:\:seeInFormFields\(\) has parameter \$formSelector with no type specified\.$#' 1319 | identifier: missingType.parameter 1320 | count: 1 1321 | path: tests/_support/FunctionalTester.php 1322 | 1323 | - 1324 | message: '#^Method tests\\FunctionalTester\:\:seeInFormFields\(\) has parameter \$params with no value type specified in iterable type array\.$#' 1325 | identifier: missingType.iterableValue 1326 | count: 1 1327 | path: tests/_support/FunctionalTester.php 1328 | 1329 | - 1330 | message: '#^Method tests\\FunctionalTester\:\:seeInTitle\(\) has parameter \$title with no type specified\.$#' 1331 | identifier: missingType.parameter 1332 | count: 1 1333 | path: tests/_support/FunctionalTester.php 1334 | 1335 | - 1336 | message: '#^Method tests\\FunctionalTester\:\:seeNumberOfElements\(\) has parameter \$selector with no type specified\.$#' 1337 | identifier: missingType.parameter 1338 | count: 1 1339 | path: tests/_support/FunctionalTester.php 1340 | 1341 | - 1342 | message: '#^Method tests\\FunctionalTester\:\:seeOptionIsSelected\(\) has parameter \$optionText with no type specified\.$#' 1343 | identifier: missingType.parameter 1344 | count: 1 1345 | path: tests/_support/FunctionalTester.php 1346 | 1347 | - 1348 | message: '#^Method tests\\FunctionalTester\:\:seeOptionIsSelected\(\) has parameter \$selector with no type specified\.$#' 1349 | identifier: missingType.parameter 1350 | count: 1 1351 | path: tests/_support/FunctionalTester.php 1352 | 1353 | - 1354 | message: '#^Method tests\\FunctionalTester\:\:selectOption\(\) has parameter \$option with no type specified\.$#' 1355 | identifier: missingType.parameter 1356 | count: 1 1357 | path: tests/_support/FunctionalTester.php 1358 | 1359 | - 1360 | message: '#^Method tests\\FunctionalTester\:\:selectOption\(\) has parameter \$select with no type specified\.$#' 1361 | identifier: missingType.parameter 1362 | count: 1 1363 | path: tests/_support/FunctionalTester.php 1364 | 1365 | - 1366 | message: '#^Method tests\\FunctionalTester\:\:sendAjaxGetRequest\(\) has parameter \$params with no value type specified in iterable type array\.$#' 1367 | identifier: missingType.iterableValue 1368 | count: 1 1369 | path: tests/_support/FunctionalTester.php 1370 | 1371 | - 1372 | message: '#^Method tests\\FunctionalTester\:\:sendAjaxPostRequest\(\) has parameter \$params with no value type specified in iterable type array\.$#' 1373 | identifier: missingType.iterableValue 1374 | count: 1 1375 | path: tests/_support/FunctionalTester.php 1376 | 1377 | - 1378 | message: '#^Method tests\\FunctionalTester\:\:sendAjaxRequest\(\) has parameter \$params with no value type specified in iterable type array\.$#' 1379 | identifier: missingType.iterableValue 1380 | count: 1 1381 | path: tests/_support/FunctionalTester.php 1382 | 1383 | - 1384 | message: '#^Method tests\\FunctionalTester\:\:setServerParameters\(\) has parameter \$params with no value type specified in iterable type array\.$#' 1385 | identifier: missingType.iterableValue 1386 | count: 1 1387 | path: tests/_support/FunctionalTester.php 1388 | 1389 | - 1390 | message: '#^Method tests\\FunctionalTester\:\:submitForm\(\) has parameter \$params with no value type specified in iterable type array\.$#' 1391 | identifier: missingType.iterableValue 1392 | count: 1 1393 | path: tests/_support/FunctionalTester.php 1394 | 1395 | - 1396 | message: '#^Method tests\\FunctionalTester\:\:submitForm\(\) has parameter \$selector with no type specified\.$#' 1397 | identifier: missingType.parameter 1398 | count: 1 1399 | path: tests/_support/FunctionalTester.php 1400 | 1401 | - 1402 | message: '#^Method tests\\FunctionalTester\:\:uncheckOption\(\) has parameter \$option with no type specified\.$#' 1403 | identifier: missingType.parameter 1404 | count: 1 1405 | path: tests/_support/FunctionalTester.php 1406 | 1407 | - 1408 | message: '#^PHPDoc tag @return with type array\\|tests\\_generated\\ActiveRecordInterface\|null is not subtype of native type array\|yii\\db\\ActiveRecordInterface\|null\.$#' 1409 | identifier: return.phpDocType 1410 | count: 1 1411 | path: tests/_support/FunctionalTester.php 1412 | 1413 | - 1414 | message: '#^Parameter \#2 \$arguments of class Codeception\\Step\\Action constructor expects array\, list\ given\.$#' 1415 | identifier: argument.type 1416 | count: 193 1417 | path: tests/_support/FunctionalTester.php 1418 | 1419 | - 1420 | message: '#^Parameter \#2 \$arguments of class Codeception\\Step\\Assertion constructor expects array\, list\ given\.$#' 1421 | identifier: argument.type 1422 | count: 23 1423 | path: tests/_support/FunctionalTester.php 1424 | 1425 | - 1426 | message: '#^Parameter \#2 \$arguments of class Codeception\\Step\\Condition constructor expects array\, list\ given\.$#' 1427 | identifier: argument.type 1428 | count: 4 1429 | path: tests/_support/FunctionalTester.php 1430 | 1431 | - 1432 | message: '#^Parameter \#2 \$arguments of class Codeception\\Step\\ConditionalAssertion constructor expects array\, list\ given\.$#' 1433 | identifier: argument.type 1434 | count: 39 1435 | path: tests/_support/FunctionalTester.php 1436 | 1437 | - 1438 | message: '#^Method tests\\fixtures\\EmptyFixture\:\:load\(\) has no return type specified\.$#' 1439 | identifier: missingType.return 1440 | count: 1 1441 | path: tests/cases/closeConnections/fixtures/EmptyFixture.php 1442 | 1443 | - 1444 | message: '#^Method tests\\fixtures\\EmptyFixture\:\:unload\(\) has no return type specified\.$#' 1445 | identifier: missingType.return 1446 | count: 1 1447 | path: tests/cases/closeConnections/fixtures/EmptyFixture.php 1448 | 1449 | - 1450 | message: '#^Method tests\\closeConnections\\FixturesCest\:\:NoConnections\(\) has no return type specified\.$#' 1451 | identifier: missingType.return 1452 | count: 1 1453 | path: tests/cases/closeConnections/functional/FixturesCest.php 1454 | 1455 | - 1456 | message: '#^Method tests\\closeConnections\\FixturesCest\:\:NoConnections\(\) has parameter \$example with no value type specified in iterable type Codeception\\Example\.$#' 1457 | identifier: missingType.iterableValue 1458 | count: 1 1459 | path: tests/cases/closeConnections/functional/FixturesCest.php 1460 | 1461 | - 1462 | message: '#^Method tests\\closeConnections\\FixturesCest\:\:_fixtures\(\) has no return type specified\.$#' 1463 | identifier: missingType.return 1464 | count: 1 1465 | path: tests/cases/closeConnections/functional/FixturesCest.php 1466 | 1467 | - 1468 | message: '#^Method tests\\closeConnections\\FixturesCest\:\:numberProvider\(\) has no return type specified\.$#' 1469 | identifier: missingType.return 1470 | count: 1 1471 | path: tests/cases/closeConnections/functional/FixturesCest.php 1472 | 1473 | - 1474 | message: '#^Method tests\\closeConnections\\FixturesInBeforeCest\:\:NoConnections\(\) has no return type specified\.$#' 1475 | identifier: missingType.return 1476 | count: 1 1477 | path: tests/cases/closeConnections/functional/FixturesInBeforeCest.php 1478 | 1479 | - 1480 | message: '#^Method tests\\closeConnections\\FixturesInBeforeCest\:\:NoConnections\(\) has parameter \$example with no value type specified in iterable type Codeception\\Example\.$#' 1481 | identifier: missingType.iterableValue 1482 | count: 1 1483 | path: tests/cases/closeConnections/functional/FixturesInBeforeCest.php 1484 | 1485 | - 1486 | message: '#^Method tests\\closeConnections\\FixturesInBeforeCest\:\:_before\(\) has no return type specified\.$#' 1487 | identifier: missingType.return 1488 | count: 1 1489 | path: tests/cases/closeConnections/functional/FixturesInBeforeCest.php 1490 | 1491 | - 1492 | message: '#^Method tests\\closeConnections\\FixturesInBeforeCest\:\:numberProvider\(\) has no return type specified\.$#' 1493 | identifier: missingType.return 1494 | count: 1 1495 | path: tests/cases/closeConnections/functional/FixturesInBeforeCest.php 1496 | 1497 | - 1498 | message: '#^Method tests\\closeConnections\\NoFixturesCest\:\:NoConnections\(\) has no return type specified\.$#' 1499 | identifier: missingType.return 1500 | count: 1 1501 | path: tests/cases/closeConnections/functional/NoFixturesCest.php 1502 | 1503 | - 1504 | message: '#^Method tests\\closeConnections\\NoFixturesCest\:\:NoConnections\(\) has parameter \$example with no value type specified in iterable type Codeception\\Example\.$#' 1505 | identifier: missingType.iterableValue 1506 | count: 1 1507 | path: tests/cases/closeConnections/functional/NoFixturesCest.php 1508 | 1509 | - 1510 | message: '#^Method tests\\closeConnections\\NoFixturesCest\:\:numberProvider\(\) has no return type specified\.$#' 1511 | identifier: missingType.return 1512 | count: 1 1513 | path: tests/cases/closeConnections/functional/NoFixturesCest.php 1514 | 1515 | - 1516 | message: '#^Method tests\\helpers\\SqlliteHelper\:\:connectionCount\(\) has no return type specified\.$#' 1517 | identifier: missingType.return 1518 | count: 1 1519 | path: tests/cases/closeConnections/helpers/SqlliteHelper.php 1520 | 1521 | - 1522 | message: '#^Method tests\\helpers\\SqlliteHelper\:\:debug\(\) has no return type specified\.$#' 1523 | identifier: missingType.return 1524 | count: 1 1525 | path: tests/cases/closeConnections/helpers/SqlliteHelper.php 1526 | 1527 | - 1528 | message: '#^Method tests\\helpers\\SqlliteHelper\:\:getTmpFile\(\) has no return type specified\.$#' 1529 | identifier: missingType.return 1530 | count: 1 1531 | path: tests/cases/closeConnections/helpers/SqlliteHelper.php 1532 | 1533 | - 1534 | message: '#^Property tests\\helpers\\SqlliteHelper\:\:\$temp_name has no type specified\.$#' 1535 | identifier: missingType.property 1536 | count: 1 1537 | path: tests/cases/closeConnections/helpers/SqlliteHelper.php 1538 | 1539 | - 1540 | message: '#^Method tests\\closeConnectionsNoCleanup\\FixturesCest\:\:NoConnections1\(\) has no return type specified\.$#' 1541 | identifier: missingType.return 1542 | count: 1 1543 | path: tests/cases/closeConnectionsNoCleanup/functional/FixturesCest.php 1544 | 1545 | - 1546 | message: '#^Method tests\\closeConnectionsNoCleanup\\FixturesCest\:\:NoConnections2\(\) has no return type specified\.$#' 1547 | identifier: missingType.return 1548 | count: 1 1549 | path: tests/cases/closeConnectionsNoCleanup/functional/FixturesCest.php 1550 | 1551 | - 1552 | message: '#^Method tests\\closeConnectionsNoCleanup\\FixturesCest\:\:NoConnections3\(\) has no return type specified\.$#' 1553 | identifier: missingType.return 1554 | count: 1 1555 | path: tests/cases/closeConnectionsNoCleanup/functional/FixturesCest.php 1556 | 1557 | - 1558 | message: '#^Method tests\\closeConnectionsNoCleanup\\FixturesCest\:\:_fixtures\(\) has no return type specified\.$#' 1559 | identifier: missingType.return 1560 | count: 1 1561 | path: tests/cases/closeConnectionsNoCleanup/functional/FixturesCest.php 1562 | 1563 | - 1564 | message: '#^Method tests\\closeConnectionsNoCleanup\\FixturesInBeforeCest\:\:OnlyOneConnection1\(\) has no return type specified\.$#' 1565 | identifier: missingType.return 1566 | count: 1 1567 | path: tests/cases/closeConnectionsNoCleanup/functional/FixturesInBeforeCest.php 1568 | 1569 | - 1570 | message: '#^Method tests\\closeConnectionsNoCleanup\\FixturesInBeforeCest\:\:OnlyOneConnection2\(\) has no return type specified\.$#' 1571 | identifier: missingType.return 1572 | count: 1 1573 | path: tests/cases/closeConnectionsNoCleanup/functional/FixturesInBeforeCest.php 1574 | 1575 | - 1576 | message: '#^Method tests\\closeConnectionsNoCleanup\\FixturesInBeforeCest\:\:OnlyOneConnection3\(\) has no return type specified\.$#' 1577 | identifier: missingType.return 1578 | count: 1 1579 | path: tests/cases/closeConnectionsNoCleanup/functional/FixturesInBeforeCest.php 1580 | 1581 | - 1582 | message: '#^Method tests\\closeConnectionsNoCleanup\\FixturesInBeforeCest\:\:_before\(\) has no return type specified\.$#' 1583 | identifier: missingType.return 1584 | count: 1 1585 | path: tests/cases/closeConnectionsNoCleanup/functional/FixturesInBeforeCest.php 1586 | 1587 | - 1588 | message: '#^Method tests\\closeConnectionsNoCleanup\\ThirdCest\:\:NoConnections1\(\) has no return type specified\.$#' 1589 | identifier: missingType.return 1590 | count: 1 1591 | path: tests/cases/closeConnectionsNoCleanup/functional/ThirdCest.php 1592 | 1593 | - 1594 | message: '#^Method tests\\closeConnectionsNoCleanup\\ThirdCest\:\:OnlyOneConnection2\(\) has no return type specified\.$#' 1595 | identifier: missingType.return 1596 | count: 1 1597 | path: tests/cases/closeConnectionsNoCleanup/functional/ThirdCest.php 1598 | 1599 | - 1600 | message: '#^Method tests\\closeConnectionsNoCleanup\\ThirdCest\:\:OnlyOneConnection3\(\) has no return type specified\.$#' 1601 | identifier: missingType.return 1602 | count: 1 1603 | path: tests/cases/closeConnectionsNoCleanup/functional/ThirdCest.php 1604 | 1605 | - 1606 | message: '#^Cannot call method trigger\(\) on yii\\base\\Application\|null\.$#' 1607 | identifier: method.nonObject 1608 | count: 1 1609 | path: tests/cases/events/config.php 1610 | 1611 | - 1612 | message: '#^Method app\\controllers\\SiteController\:\:actionIndex\(\) has no return type specified\.$#' 1613 | identifier: missingType.return 1614 | count: 1 1615 | path: tests/cases/events/controllers/SiteController.php 1616 | 1617 | - 1618 | message: '#^Cannot call method on\(\) on yii\\base\\Application\|null\.$#' 1619 | identifier: method.nonObject 1620 | count: 6 1621 | path: tests/cases/events/functional/ResponseCest.php 1622 | 1623 | - 1624 | message: '#^Cannot call method startApp\(\) on Symfony\\Component\\BrowserKit\\AbstractBrowser\|null\.$#' 1625 | identifier: method.nonObject 1626 | count: 2 1627 | path: tests/cases/events/functional/ResponseCest.php 1628 | 1629 | - 1630 | message: '#^Method tests\\ResponseCest\:\:testAfterSend\(\) has no return type specified\.$#' 1631 | identifier: missingType.return 1632 | count: 1 1633 | path: tests/cases/events/functional/ResponseCest.php 1634 | 1635 | - 1636 | message: '#^Method tests\\ResponseCest\:\:testAfterSendWithForcedRecreate\(\) has no return type specified\.$#' 1637 | identifier: missingType.return 1638 | count: 1 1639 | path: tests/cases/events/functional/ResponseCest.php 1640 | 1641 | - 1642 | message: '#^Method tests\\ResponseCest\:\:testAfterSendWithRecreate\(\) has no return type specified\.$#' 1643 | identifier: missingType.return 1644 | count: 1 1645 | path: tests/cases/events/functional/ResponseCest.php 1646 | 1647 | - 1648 | message: '#^Cannot access property \$mailer on yii\\base\\Application\|null\.$#' 1649 | identifier: property.nonObject 1650 | count: 1 1651 | path: tests/cases/mock-mailer/controllers/SiteController.php 1652 | 1653 | - 1654 | message: '#^Method app\\mockmailer\\controllers\\SiteController\:\:actionIndex\(\) has no return type specified\.$#' 1655 | identifier: missingType.return 1656 | count: 1 1657 | path: tests/cases/mock-mailer/controllers/SiteController.php 1658 | 1659 | - 1660 | message: '#^Method app\\mockmailer\\controllers\\SiteController\:\:actionSendMailWithRedirect\(\) has no return type specified\.$#' 1661 | identifier: missingType.return 1662 | count: 1 1663 | path: tests/cases/mock-mailer/controllers/SiteController.php 1664 | 1665 | - 1666 | message: '#^Method app\\mockmailer\\controllers\\SiteController\:\:actionSendMailWithoutRedirect\(\) has no return type specified\.$#' 1667 | identifier: missingType.return 1668 | count: 1 1669 | path: tests/cases/mock-mailer/controllers/SiteController.php 1670 | 1671 | - 1672 | message: '#^Method app\\mockmailer\\controllers\\SiteController\:\:doSendMail\(\) has no return type specified\.$#' 1673 | identifier: missingType.return 1674 | count: 1 1675 | path: tests/cases/mock-mailer/controllers/SiteController.php 1676 | 1677 | - 1678 | message: '#^Method tests\\MockMailerCest\:\:testCountMailSentWithRedirect\(\) has no return type specified\.$#' 1679 | identifier: missingType.return 1680 | count: 1 1681 | path: tests/cases/mock-mailer/functional/MockMailerCest.php 1682 | 1683 | - 1684 | message: '#^Method tests\\MockMailerCest\:\:testCountMailSentWithoutRedirect\(\) has no return type specified\.$#' 1685 | identifier: missingType.return 1686 | count: 1 1687 | path: tests/cases/mock-mailer/functional/MockMailerCest.php 1688 | 1689 | - 1690 | message: '#^Method tests\\MockMailerCest\:\:testInstantiation\(\) has no return type specified\.$#' 1691 | identifier: missingType.return 1692 | count: 1 1693 | path: tests/cases/mock-mailer/functional/MockMailerCest.php 1694 | 1695 | - 1696 | message: '#^Method app\\pageCacheHeaderAlreadySent\\controllers\\UserController\:\:actionIndex\(\) has no return type specified\.$#' 1697 | identifier: missingType.return 1698 | count: 1 1699 | path: tests/cases/pageCacheHeaderAlreadySent/controllers/UserController.php 1700 | 1701 | - 1702 | message: '#^Method PageCest\:\:testCache\(\) has no return type specified\.$#' 1703 | identifier: missingType.return 1704 | count: 1 1705 | path: tests/cases/pageCacheHeaderAlreadySent/functional/PageCest.php 1706 | 1707 | - 1708 | message: '#^Access to an undefined property yii\\console\\Request\|yii\\web\\Request\:\:\$bodyParams\.$#' 1709 | identifier: property.notFound 1710 | count: 1 1711 | path: tests/cases/simple/controllers/SiteController.php 1712 | 1713 | - 1714 | message: '#^Access to an undefined property yii\\console\\Response\|yii\\web\\Response\:\:\$content\.$#' 1715 | identifier: property.notFound 1716 | count: 1 1717 | path: tests/cases/simple/controllers/SiteController.php 1718 | 1719 | - 1720 | message: '#^Access to an undefined property yii\\console\\Response\|yii\\web\\Response\:\:\$statusCode\.$#' 1721 | identifier: property.notFound 1722 | count: 2 1723 | path: tests/cases/simple/controllers/SiteController.php 1724 | 1725 | - 1726 | message: '#^Access to an undefined property yii\\console\\Response\|yii\\web\\Response\:\:\$stream\.$#' 1727 | identifier: property.notFound 1728 | count: 1 1729 | path: tests/cases/simple/controllers/SiteController.php 1730 | 1731 | - 1732 | message: '#^Cannot access property \$request on yii\\base\\Application\|null\.$#' 1733 | identifier: property.nonObject 1734 | count: 1 1735 | path: tests/cases/simple/controllers/SiteController.php 1736 | 1737 | - 1738 | message: '#^Cannot access property \$response on yii\\base\\Application\|null\.$#' 1739 | identifier: property.nonObject 1740 | count: 4 1741 | path: tests/cases/simple/controllers/SiteController.php 1742 | 1743 | - 1744 | message: '#^Cannot call method end\(\) on yii\\base\\Application\|null\.$#' 1745 | identifier: method.nonObject 1746 | count: 1 1747 | path: tests/cases/simple/controllers/SiteController.php 1748 | 1749 | - 1750 | message: '#^Method app\\simple\\controllers\\SiteController\:\:actionEmptyResponse\(\) has no return type specified\.$#' 1751 | identifier: missingType.return 1752 | count: 1 1753 | path: tests/cases/simple/controllers/SiteController.php 1754 | 1755 | - 1756 | message: '#^Method app\\simple\\controllers\\SiteController\:\:actionEnd\(\) has no return type specified\.$#' 1757 | identifier: missingType.return 1758 | count: 1 1759 | path: tests/cases/simple/controllers/SiteController.php 1760 | 1761 | - 1762 | message: '#^Method app\\simple\\controllers\\SiteController\:\:actionException\(\) has no return type specified\.$#' 1763 | identifier: missingType.return 1764 | count: 1 1765 | path: tests/cases/simple/controllers/SiteController.php 1766 | 1767 | - 1768 | message: '#^Method app\\simple\\controllers\\SiteController\:\:actionForm\(\) has no return type specified\.$#' 1769 | identifier: missingType.return 1770 | count: 1 1771 | path: tests/cases/simple/controllers/SiteController.php 1772 | 1773 | - 1774 | message: '#^Method app\\simple\\controllers\\SiteController\:\:actionIndex\(\) has no return type specified\.$#' 1775 | identifier: missingType.return 1776 | count: 1 1777 | path: tests/cases/simple/controllers/SiteController.php 1778 | 1779 | - 1780 | message: '#^Method app\\simple\\controllers\\SiteController\:\:actionPost\(\) has no return type specified\.$#' 1781 | identifier: missingType.return 1782 | count: 1 1783 | path: tests/cases/simple/controllers/SiteController.php 1784 | 1785 | - 1786 | message: '#^Cannot access property \$params on yii\\base\\Application\|null\.$#' 1787 | identifier: property.nonObject 1788 | count: 1 1789 | path: tests/cases/simple/functional/SimpleCest.php 1790 | 1791 | - 1792 | message: '#^Cannot access property \$user on yii\\base\\Application\|null\.$#' 1793 | identifier: property.nonObject 1794 | count: 1 1795 | path: tests/cases/simple/functional/SimpleCest.php 1796 | 1797 | - 1798 | message: '#^Method tests\\SimpleCest\:\:testEmptyResponse\(\) has no return type specified\.$#' 1799 | identifier: missingType.return 1800 | count: 1 1801 | path: tests/cases/simple/functional/SimpleCest.php 1802 | 1803 | - 1804 | message: '#^Method tests\\SimpleCest\:\:testException\(\) has no return type specified\.$#' 1805 | identifier: missingType.return 1806 | count: 1 1807 | path: tests/cases/simple/functional/SimpleCest.php 1808 | 1809 | - 1810 | message: '#^Method tests\\SimpleCest\:\:testExceptionInBeforeRequest\(\) has no return type specified\.$#' 1811 | identifier: missingType.return 1812 | count: 1 1813 | path: tests/cases/simple/functional/SimpleCest.php 1814 | 1815 | - 1816 | message: '#^Method tests\\SimpleCest\:\:testExitException\(\) has no return type specified\.$#' 1817 | identifier: missingType.return 1818 | count: 1 1819 | path: tests/cases/simple/functional/SimpleCest.php 1820 | 1821 | - 1822 | message: '#^Method tests\\SimpleCest\:\:testFormSubmit\(\) has no return type specified\.$#' 1823 | identifier: missingType.return 1824 | count: 1 1825 | path: tests/cases/simple/functional/SimpleCest.php 1826 | 1827 | - 1828 | message: '#^Method tests\\SimpleCest\:\:testFormSubmit2\(\) has no return type specified\.$#' 1829 | identifier: missingType.return 1830 | count: 1 1831 | path: tests/cases/simple/functional/SimpleCest.php 1832 | 1833 | - 1834 | message: '#^Method tests\\SimpleCest\:\:testInstantiation\(\) has no return type specified\.$#' 1835 | identifier: missingType.return 1836 | count: 1 1837 | path: tests/cases/simple/functional/SimpleCest.php 1838 | 1839 | - 1840 | message: '#^Method tests\\SimpleCest\:\:testMissingUser\(\) has no return type specified\.$#' 1841 | identifier: missingType.return 1842 | count: 1 1843 | path: tests/cases/simple/functional/SimpleCest.php 1844 | 1845 | - 1846 | message: '#^Method app\\simple\\helpers\\DummyUser\:\:findIdentity\(\) should return yii\\web\\IdentityInterface but returns null\.$#' 1847 | identifier: return.type 1848 | count: 1 1849 | path: tests/cases/simple/helpers/DummyUser.php 1850 | 1851 | - 1852 | message: '#^Method app\\simple\\helpers\\DummyUser\:\:findIdentityByAccessToken\(\) should return yii\\web\\IdentityInterface but return statement is missing\.$#' 1853 | identifier: return.missing 1854 | count: 1 1855 | path: tests/cases/simple/helpers/DummyUser.php 1856 | 1857 | - 1858 | message: '#^Method app\\simple\\helpers\\DummyUser\:\:getAuthKey\(\) should return string but return statement is missing\.$#' 1859 | identifier: return.missing 1860 | count: 1 1861 | path: tests/cases/simple/helpers/DummyUser.php 1862 | 1863 | - 1864 | message: '#^Method app\\simple\\helpers\\DummyUser\:\:getId\(\) should return int\|string but return statement is missing\.$#' 1865 | identifier: return.missing 1866 | count: 1 1867 | path: tests/cases/simple/helpers/DummyUser.php 1868 | 1869 | - 1870 | message: '#^Method app\\simple\\helpers\\DummyUser\:\:validateAuthKey\(\) should return bool but return statement is missing\.$#' 1871 | identifier: return.missing 1872 | count: 1 1873 | path: tests/cases/simple/helpers/DummyUser.php 1874 | 1875 | - 1876 | message: '#^Method app\\simple\\helpers\\EmptyString\:\:__construct\(\) has parameter \$value with no type specified\.$#' 1877 | identifier: missingType.parameter 1878 | count: 1 1879 | path: tests/cases/simple/helpers/EmptyString.php 1880 | 1881 | - 1882 | message: '#^Method app\\simple\\helpers\\EmptyString\:\:getValue\(\) has no return type specified\.$#' 1883 | identifier: missingType.return 1884 | count: 1 1885 | path: tests/cases/simple/helpers/EmptyString.php 1886 | 1887 | - 1888 | message: '#^Property app\\simple\\helpers\\EmptyString\:\:\$value has no type specified\.$#' 1889 | identifier: missingType.property 1890 | count: 1 1891 | path: tests/cases/simple/helpers/EmptyString.php 1892 | 1893 | - 1894 | message: '#^Cannot call method get\(\) on yii\\base\\Application\|null\.$#' 1895 | identifier: method.nonObject 1896 | count: 2 1897 | path: tests/cases/sqlite/fixtures/TestFixture.php 1898 | 1899 | - 1900 | message: '#^Method tests\\fixtures\\TestFixture\:\:load\(\) has no return type specified\.$#' 1901 | identifier: missingType.return 1902 | count: 1 1903 | path: tests/cases/sqlite/fixtures/TestFixture.php 1904 | 1905 | - 1906 | message: '#^Method tests\\fixtures\\TestFixture\:\:unload\(\) has no return type specified\.$#' 1907 | identifier: missingType.return 1908 | count: 1 1909 | path: tests/cases/sqlite/fixtures/TestFixture.php 1910 | 1911 | - 1912 | message: '#^Property tests\\fixtures\\TestFixture\:\:\$dbComponents has no type specified\.$#' 1913 | identifier: missingType.property 1914 | count: 1 1915 | path: tests/cases/sqlite/fixtures/TestFixture.php 1916 | 1917 | - 1918 | message: '#^Property tests\\fixtures\\TestFixture\:\:\$tableConfig has no type specified\.$#' 1919 | identifier: missingType.property 1920 | count: 1 1921 | path: tests/cases/sqlite/fixtures/TestFixture.php 1922 | 1923 | - 1924 | message: '#^Property tests\\fixtures\\TestFixture\:\:\$tableName has no type specified\.$#' 1925 | identifier: missingType.property 1926 | count: 1 1927 | path: tests/cases/sqlite/fixtures/TestFixture.php 1928 | 1929 | - 1930 | message: '#^Cannot call method get\(\) on yii\\base\\Application\|null\.$#' 1931 | identifier: method.nonObject 1932 | count: 4 1933 | path: tests/cases/sqlite/functional/SqLiteCest.php 1934 | 1935 | - 1936 | message: '#^Method tests\\SqLiteCest\:\:_fixtures\(\) has no return type specified\.$#' 1937 | identifier: missingType.return 1938 | count: 1 1939 | path: tests/cases/sqlite/functional/SqLiteCest.php 1940 | 1941 | - 1942 | message: '#^Method tests\\SqLiteCest\:\:testSharedPDO\(\) has no return type specified\.$#' 1943 | identifier: missingType.return 1944 | count: 1 1945 | path: tests/cases/sqlite/functional/SqLiteCest.php 1946 | 1947 | - 1948 | message: '#^Method tests\\SqLiteCest\:\:testTransaction\(\) has no return type specified\.$#' 1949 | identifier: missingType.return 1950 | count: 1 1951 | path: tests/cases/sqlite/functional/SqLiteCest.php 1952 | -------------------------------------------------------------------------------- /src/Codeception/Lib/Connector/Yii2.php: -------------------------------------------------------------------------------- 1 | 36 | * @internal This class is not part of the public API 37 | */ 38 | final class Yii2 extends Client 39 | { 40 | use Shared\PhpSuperGlobalsConverter; 41 | 42 | public const array MAIL_METHODS = [ 43 | self::MAIL_CATCH, 44 | self::MAIL_EVENT_AFTER, 45 | self::MAIL_EVENT_BEFORE, 46 | self::MAIL_IGNORE 47 | ]; 48 | 49 | public const string MAIL_CATCH = 'catch'; 50 | 51 | public const string MAIL_EVENT_AFTER = 'after'; 52 | 53 | public const string MAIL_EVENT_BEFORE = 'before'; 54 | 55 | public const string MAIL_IGNORE = 'ignore'; 56 | 57 | public const array CLEAN_METHODS = [ 58 | self::CLEAN_RECREATE, 59 | self::CLEAN_CLEAR, 60 | self::CLEAN_FORCE_RECREATE, 61 | self::CLEAN_MANUAL, 62 | ]; 63 | 64 | /** 65 | * Clean the response object by recreating it. 66 | * This might lose behaviors / event handlers / other changes that are done in the application bootstrap phase. 67 | */ 68 | public const string CLEAN_RECREATE = 'recreate'; 69 | 70 | /** 71 | * Same as recreate but will not warn when behaviors / event handlers are lost. 72 | */ 73 | public const string CLEAN_FORCE_RECREATE = 'force_recreate'; 74 | 75 | /** 76 | * Clean the response object by resetting specific properties via its' `clear()` method. 77 | * This will keep behaviors / event handlers, but could inadvertently leave some changes intact. 78 | * 79 | * @see \yii\web\Response::clear() 80 | */ 81 | public const string CLEAN_CLEAR = 'clear'; 82 | 83 | /** 84 | * Do not clean the response, instead the test writer will be responsible for manually resetting the response in 85 | * between requests during one test 86 | */ 87 | public const string CLEAN_MANUAL = 'manual'; 88 | 89 | /** 90 | * @var string application config file 91 | */ 92 | public string $configFile; 93 | 94 | /** 95 | * @var self::MAIL_CATCH|self::MAIL_IGNORE|self::MAIL_EVENT_AFTER|self::MAIL_EVENT_BEFORE method for handling mails 96 | */ 97 | public string $mailMethod; 98 | 99 | /** 100 | * @var string method for cleaning the response object before each request 101 | */ 102 | public string $responseCleanMethod; 103 | 104 | /** 105 | * @var string method for cleaning the request object before each request 106 | */ 107 | public string $requestCleanMethod; 108 | 109 | /** 110 | * @var string[] List of component names that must be recreated before each request 111 | */ 112 | public array $recreateComponents = []; 113 | 114 | /** 115 | * This option is there primarily for backwards compatibility. 116 | * It means you cannot make any modification to application state inside your app, since they will get discarded. 117 | * 118 | * @var bool whether to recreate the whole application before each request 119 | */ 120 | public bool $recreateApplication = false; 121 | 122 | /** 123 | * @var bool whether to close the session in between requests inside a single test, if recreateApplication is set to true 124 | */ 125 | public bool $closeSessionOnRecreateApplication = true; 126 | 127 | /** 128 | * @var class-string The FQN of the application class to use. In a default Yii setup, should be either `yii\web\Application` 129 | * or `yii\console\Application` 130 | */ 131 | public string|null $applicationClass = null; 132 | 133 | /** 134 | * @var list 135 | */ 136 | private array $emails = []; 137 | 138 | /** 139 | * @internal 140 | */ 141 | protected function getApplication(): \yii\base\Application 142 | { 143 | if (! isset(Yii::$app)) { 144 | $this->startApp(); 145 | } 146 | return Yii::$app ?? throw new RuntimeException('Failed to create Yii2 application'); 147 | } 148 | 149 | private function getWebRequest(): YiiRequest 150 | { 151 | $request = $this->getApplication()->request; 152 | if (! $request instanceof YiiRequest) { 153 | throw new RuntimeException('Request component is not of type ' . YiiRequest::class); 154 | } 155 | return $request; 156 | } 157 | 158 | public function resetApplication(bool $closeSession = true): void 159 | { 160 | codecept_debug('Destroying application'); 161 | if ($closeSession) { 162 | $this->closeSession(); 163 | } 164 | Yii::$app = null; 165 | \yii\web\UploadedFile::reset(); 166 | Event::offAll(); 167 | Yii::setLogger(null); 168 | // This resolves an issue with database connections not closing properly. 169 | gc_collect_cycles(); 170 | } 171 | 172 | /** 173 | * Finds and logs in a user 174 | * 175 | * @internal 176 | * @throws ConfigurationException|RuntimeException 177 | */ 178 | public function findAndLoginUser(int|string|IdentityInterface $user): void 179 | { 180 | $app = $this->getApplication(); 181 | $userComponent = $app->get('user'); 182 | if (! $userComponent instanceof User) { 183 | throw new ConfigurationException('The user component is not configured'); 184 | } 185 | 186 | $identity = $user instanceof IdentityInterface ? $user : ($userComponent->identityClass)::findIdentity($user); 187 | if ($identity === null) { 188 | throw new RuntimeException('User not found'); 189 | } 190 | $userComponent->login($identity); 191 | } 192 | 193 | /** 194 | * @internal 195 | * @param string $name The name of the cookie 196 | * @param string $value The value of the cookie 197 | * @return string The value to send to the browser 198 | */ 199 | public function hashCookieData(string $name, string $value): string 200 | { 201 | $request = $this->getWebRequest(); 202 | if (! $request->enableCookieValidation) { 203 | return $value; 204 | } 205 | return $this->getApplication()->security->hashData(serialize([$name, $value]), $request->cookieValidationKey); 206 | } 207 | 208 | /** 209 | * @internal 210 | * @return non-empty-list List of regex patterns for recognized domain names 211 | */ 212 | public function getInternalDomains(): array 213 | { 214 | $urlManager = $this->getApplication()->urlManager; 215 | 216 | $domains = [$this->getDomainRegex($urlManager->hostInfo)]; 217 | if ($urlManager->enablePrettyUrl) { 218 | foreach ($urlManager->rules as $rule) { 219 | if (isset($rule->host)) { 220 | $domains[] = $this->getDomainRegex($rule->host); 221 | } 222 | } 223 | } 224 | return array_values(array_unique($domains)); 225 | } 226 | 227 | /** 228 | * @internal 229 | * @return list List of sent emails 230 | */ 231 | public function getEmails(): array 232 | { 233 | return $this->emails; 234 | } 235 | 236 | /** 237 | * Deletes all stored emails. 238 | * 239 | * @internal 240 | */ 241 | public function clearEmails(): void 242 | { 243 | $this->emails = []; 244 | } 245 | 246 | /** 247 | * Getting domain regex from rule host template 248 | */ 249 | private function getDomainRegex(string $template): string 250 | { 251 | if (preg_match('#https?://(.*)#', $template, $matches)) { 252 | $template = $matches[1]; 253 | } 254 | $parameters = []; 255 | if (str_contains($template, '<')) { 256 | $template = preg_replace_callback( 257 | '/<(?:\w+):?([^>]+)?>/u', 258 | function ($matches) use (&$parameters): string { 259 | $key = '__' . count($parameters) . '__'; 260 | $parameters[$key] = $matches[1] ?? '\w+'; 261 | return $key; 262 | }, 263 | $template, 264 | ); 265 | } 266 | if ($template === null) { 267 | throw new RuntimeException("Failed to parse domain regex"); 268 | } 269 | $template = preg_quote($template); 270 | $template = strtr($template, $parameters); 271 | return '/^' . $template . '$/u'; 272 | } 273 | 274 | /** 275 | * Gets the name of the CSRF param. 276 | * 277 | * @internal 278 | */ 279 | public function getCsrfParamName(): string 280 | { 281 | return $this->getWebRequest()->csrfParam; 282 | } 283 | 284 | public function startApp(?\yii\log\Logger $logger = null): void 285 | { 286 | codecept_debug('Starting application'); 287 | $config = include $this->configFile; 288 | if (! isset($config['class'])) { 289 | $config['class'] = $this->applicationClass ?? \yii\web\Application::class; 290 | } 291 | 292 | if (isset($config['container'])) { 293 | Yii::configure(Yii::$container, $config['container']); 294 | unset($config['container']); 295 | } 296 | 297 | match ($this->mailMethod) { 298 | self::MAIL_CATCH => $config = $this->mockMailer($config), 299 | self::MAIL_EVENT_AFTER => $config['components']['mailer']['on ' . BaseMailer::EVENT_AFTER_SEND] = function (MailEvent $event): void { 300 | if ($event->isSuccessful) { 301 | $this->emails[] = $event->message; 302 | } 303 | }, 304 | self::MAIL_EVENT_BEFORE => $config['components']['mailer']['on ' . BaseMailer::EVENT_BEFORE_SEND] = fn (MailEvent $event) => $this->emails[] = $event->message, 305 | self::MAIL_IGNORE => null// Do nothing 306 | }; 307 | 308 | // @phpstan-ignore argument.templateType 309 | $app = Yii::createObject($config); 310 | if (! $app instanceof \yii\base\Application) { 311 | throw new ModuleConfigException($this, "Failed to initialize Yii2 app"); 312 | } 313 | \Yii::$app = $app; 314 | 315 | if ($logger instanceof \yii\log\Logger) { 316 | Yii::setLogger($logger); 317 | } else { 318 | Yii::setLogger(new Logger()); 319 | } 320 | } 321 | 322 | /** 323 | * @param BrowserkitRequest $request 324 | */ 325 | public function doRequest(object $request): Response 326 | { 327 | $_COOKIE = $request->getCookies(); 328 | $_SERVER = $request->getServer(); 329 | $_FILES = $this->remapFiles($request->getFiles()); 330 | $_REQUEST = $this->remapRequestParameters($request->getParameters()); 331 | $_POST = $_GET = []; 332 | 333 | if (strtoupper($request->getMethod()) === 'GET') { 334 | $_GET = $_REQUEST; 335 | } else { 336 | $_POST = $_REQUEST; 337 | } 338 | 339 | $uri = $request->getUri(); 340 | 341 | $pathString = parse_url($uri, PHP_URL_PATH); 342 | $queryString = parse_url($uri, PHP_URL_QUERY); 343 | $_SERVER['REQUEST_URI'] = $queryString === null ? $pathString : $pathString . '?' . $queryString; 344 | $_SERVER['REQUEST_METHOD'] = strtoupper($request->getMethod()); 345 | $_SERVER['QUERY_STRING'] = (string) $queryString; 346 | 347 | parse_str($queryString ?: '', $params); 348 | foreach ($params as $k => $v) { 349 | $_GET[$k] = $v; 350 | } 351 | 352 | ob_start(); 353 | 354 | $this->beforeRequest(); 355 | 356 | $app = $this->getApplication(); 357 | if (! $app instanceof Application) { 358 | throw new ConfigurationException("Application is not a web application"); 359 | } 360 | 361 | // disabling logging. Logs are slowing test execution down 362 | foreach ($app->log->targets as $target) { 363 | $target->enabled = false; 364 | } 365 | 366 | $yiiRequest = $app->getRequest(); 367 | if ($request->getContent() !== null) { 368 | $yiiRequest->setRawBody($request->getContent()); 369 | $yiiRequest->setBodyParams(null); 370 | } else { 371 | $yiiRequest->setRawBody(null); 372 | $yiiRequest->setBodyParams($_POST); 373 | } 374 | $yiiRequest->setQueryParams($_GET); 375 | 376 | try { 377 | /* 378 | * This is basically equivalent to $app->run() without sending the response. 379 | * Sending the response is problematic because it tries to send headers. 380 | */ 381 | $app->trigger($app::EVENT_BEFORE_REQUEST); 382 | $yiiResponse = $app->handleRequest($yiiRequest); 383 | $app->trigger($app::EVENT_AFTER_REQUEST); 384 | $yiiResponse->send(); 385 | } catch (\Exception $e) { 386 | if ($e instanceof UserException) { 387 | // Don't discard output and pass exception handling to Yii to be able 388 | // to expect error response codes in tests. 389 | $app->errorHandler->discardExistingOutput = false; 390 | $app->errorHandler->handleException($e); 391 | } elseif (! $e instanceof ExitException) { 392 | // for exceptions not related to Http, we pass them to Codeception 393 | throw $e; 394 | } 395 | $yiiResponse = $app->response; 396 | } 397 | 398 | $this->encodeCookies($yiiResponse, $yiiRequest, $app->security); 399 | 400 | if ($yiiResponse->isRedirection) { 401 | Debug::debug("[Redirect with headers]" . print_r($yiiResponse->getHeaders()->toArray(), true)); 402 | } 403 | 404 | $content = ob_get_clean(); 405 | if (empty($content) && ! empty($yiiResponse->content) && ! isset($yiiResponse->stream)) { 406 | throw new RuntimeException('No content was sent from Yii application'); 407 | } elseif ($content === false) { 408 | throw new RuntimeException('Failed to get output buffer'); 409 | } 410 | 411 | return new Response($content, $yiiResponse->statusCode, $yiiResponse->getHeaders()->toArray()); 412 | } 413 | 414 | /** 415 | * Encodes the cookies and adds them to the headers. 416 | * 417 | * @throws \yii\base\InvalidConfigException 418 | */ 419 | protected function encodeCookies( 420 | YiiResponse $response, 421 | YiiRequest $request, 422 | Security $security, 423 | ): void { 424 | if ($request->enableCookieValidation) { 425 | $validationKey = $request->cookieValidationKey; 426 | } 427 | 428 | foreach ($response->getCookies() as $cookie) { 429 | /** 430 | * @var \yii\web\Cookie $cookie 431 | */ 432 | $value = $cookie->value; 433 | // Expire = 1 means we're removing the cookie 434 | if ($cookie->expire !== 1 && isset($validationKey)) { 435 | $data = version_compare(Yii::getVersion(), '2.0.2', '>') 436 | ? [$cookie->name, $cookie->value] 437 | : $cookie->value; 438 | $value = $security->hashData(serialize($data), $validationKey); 439 | } 440 | $expires = is_int($cookie->expire) ? (string) $cookie->expire : null; 441 | $c = new Cookie( 442 | $cookie->name, 443 | $value, 444 | $expires, 445 | $cookie->path, 446 | $cookie->domain, 447 | $cookie->secure, 448 | $cookie->httpOnly, 449 | ); 450 | $this->getCookieJar()->set($c); 451 | } 452 | } 453 | 454 | /** 455 | * Replace mailer with in memory mailer 456 | * 457 | * @param array $config Original configuration 458 | * @return array New configuration 459 | */ 460 | protected function mockMailer(array $config): array 461 | { 462 | // options that make sense for mailer mock 463 | $allowedOptions = [ 464 | 'htmlLayout', 465 | 'textLayout', 466 | 'messageConfig', 467 | 'messageClass', 468 | 'useFileTransport', 469 | 'fileTransportPath', 470 | 'fileTransportCallback', 471 | 'view', 472 | 'viewPath', 473 | ]; 474 | 475 | $mailerConfig = [ 476 | 'class' => TestMailer::class, 477 | 'callback' => function (MessageInterface $message): void { 478 | $this->emails[] = $message; 479 | }, 480 | ]; 481 | 482 | if (isset($config['components'])) { 483 | if (! is_array($config['components'])) { 484 | throw new ModuleConfigException( 485 | $this, 486 | "Yii2 config does not contain components key is not of type array", 487 | ); 488 | } 489 | } else { 490 | $config['components'] = []; 491 | } 492 | if (isset($config['components']['mailer']) && is_array($config['components']['mailer'])) { 493 | foreach ($config['components']['mailer'] as $name => $value) { 494 | if (in_array($name, $allowedOptions, true)) { 495 | $mailerConfig[$name] = $value; 496 | } 497 | } 498 | } 499 | $config['components']['mailer'] = $mailerConfig; 500 | 501 | return $config; 502 | } 503 | 504 | public function restart(): void 505 | { 506 | parent::restart(); 507 | $this->resetApplication(); 508 | } 509 | 510 | /** 511 | * Return an assoc array with the client context: cookieJar, history. 512 | * 513 | * @internal 514 | * @return array{ cookieJar: CookieJar, history: History } 515 | */ 516 | public function getContext(): array 517 | { 518 | return [ 519 | 'cookieJar' => $this->cookieJar, 520 | 'history' => $this->history, 521 | ]; 522 | } 523 | 524 | /** 525 | * Set the context, see getContext(). 526 | * 527 | * @param array{ cookieJar: CookieJar, history: History } $context 528 | */ 529 | public function setContext(array $context): void 530 | { 531 | $this->cookieJar = $context['cookieJar']; 532 | $this->history = $context['history']; 533 | } 534 | 535 | /** 536 | * This functions closes the session of the application, if the application exists and has a session. 537 | * 538 | * @internal 539 | */ 540 | public function closeSession(): void 541 | { 542 | $app = $this->getApplication(); 543 | if ($app instanceof \yii\web\Application && $app->has('session', true)) { 544 | $app->session->close(); 545 | } 546 | } 547 | 548 | /** 549 | * Resets the applications' response object. 550 | * The method used depends on the module configuration. 551 | */ 552 | protected function resetResponse(Application $app): void 553 | { 554 | $method = $this->responseCleanMethod; 555 | // First check the current response object. 556 | if (($app->response->hasEventHandlers(YiiResponse::EVENT_BEFORE_SEND) 557 | || $app->response->hasEventHandlers(YiiResponse::EVENT_AFTER_SEND) 558 | || $app->response->hasEventHandlers(YiiResponse::EVENT_AFTER_PREPARE) 559 | || count($app->response->getBehaviors()) > 0) 560 | && $method === self::CLEAN_RECREATE 561 | ) { 562 | Debug::debug( 563 | << $app->set('response', $app->getComponents()['response']), 575 | self::CLEAN_CLEAR => $app->response->clear(), 576 | self::CLEAN_MANUAL => null, 577 | default => throw new InvalidArgumentException("Unknown method: $method"), 578 | }; 579 | } 580 | 581 | protected function resetRequest(Application $app): void 582 | { 583 | $method = $this->requestCleanMethod; 584 | $request = $app->request; 585 | 586 | // First check the current request object. 587 | if (count($request->getBehaviors()) > 0 && $method === self::CLEAN_RECREATE) { 588 | Debug::debug( 589 | << $app->set('request', $app->getComponents()['request']), 601 | self::CLEAN_CLEAR => (function () use ($request): void { 602 | $request->getHeaders()->removeAll(); 603 | $request->setBaseUrl(null); 604 | $request->setHostInfo(null); 605 | $request->setPathInfo(null); 606 | $request->setScriptFile(null); 607 | $request->setScriptUrl(null); 608 | $request->setUrl(null); 609 | $request->setPort(0); 610 | $request->setSecurePort(0); 611 | $request->setAcceptableContentTypes(null); 612 | $request->setAcceptableLanguages(null); 613 | })(), 614 | self::CLEAN_MANUAL => null, 615 | default => throw new InvalidArgumentException("Unknown method: $method"), 616 | }; 617 | } 618 | 619 | /** 620 | * Called before each request, preparation happens here. 621 | */ 622 | protected function beforeRequest(): void 623 | { 624 | if ($this->recreateApplication) { 625 | $this->resetApplication($this->closeSessionOnRecreateApplication); 626 | return; 627 | } 628 | 629 | $application = $this->getApplication(); 630 | 631 | if (! $application instanceof Application) { 632 | throw new ConfigurationException('Application must be an instance of web application when doing requests'); 633 | } 634 | $this->resetResponse($application); 635 | $this->resetRequest($application); 636 | 637 | $definitions = $application->getComponents(true); 638 | foreach ($this->recreateComponents as $component) { 639 | // Only recreate if it has actually been instantiated. 640 | if ($application->has($component, true)) { 641 | $application->set($component, $definitions[$component]); 642 | } 643 | } 644 | } 645 | } 646 | -------------------------------------------------------------------------------- /src/Codeception/Lib/Connector/Yii2/ConnectionWatcher.php: -------------------------------------------------------------------------------- 1 | 23 | */ 24 | private array $connections = []; 25 | 26 | public function __construct() 27 | { 28 | $this->handler = function (Event $event): void { 29 | if ($event->sender instanceof Connection) { 30 | $this->connectionOpened($event->sender); 31 | } 32 | }; 33 | } 34 | 35 | protected function connectionOpened(Connection $connection): void 36 | { 37 | $this->debug('Connection opened!'); 38 | $this->connections[] = $connection; 39 | } 40 | 41 | public function start(): void 42 | { 43 | Event::on(Connection::class, Connection::EVENT_AFTER_OPEN, $this->handler); 44 | $this->debug('watching new connections'); 45 | } 46 | 47 | public function stop(): void 48 | { 49 | Event::off(Connection::class, Connection::EVENT_AFTER_OPEN, $this->handler); 50 | $this->debug('no longer watching new connections'); 51 | } 52 | 53 | public function closeAll(): void 54 | { 55 | $count = count($this->connections); 56 | $this->debug("closing all ($count) connections"); 57 | foreach ($this->connections as $connection) { 58 | $connection->close(); 59 | } 60 | } 61 | 62 | /** 63 | * @param string|array|JsonSerializable $message 64 | */ 65 | protected function debug(string|array|JsonSerializable $message): void 66 | { 67 | $title = (new ReflectionClass($this))->getShortName(); 68 | if (is_array($message) || is_object($message)) { 69 | $message = stripslashes(json_encode($message, JSON_THROW_ON_ERROR)); 70 | } 71 | codecept_debug("[$title] $message"); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/Codeception/Lib/Connector/Yii2/FixturesStore.php: -------------------------------------------------------------------------------- 1 | data; 25 | } 26 | 27 | /** 28 | * @return array{initDbFixture: array{class: class-string}} 29 | */ 30 | public function globalFixtures(): array 31 | { 32 | return [ 33 | 'initDbFixture' => [ 34 | 'class' => InitDbFixture::class, 35 | ], 36 | ]; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Codeception/Lib/Connector/Yii2/Logger.php: -------------------------------------------------------------------------------- 1 | 17 | */ 18 | private SplQueue $logQueue; 19 | 20 | /** 21 | * @param array $config 22 | */ 23 | public function __construct( 24 | private readonly int $maxLogItems = 5, 25 | array $config = [] 26 | ) { 27 | parent::__construct($config); 28 | $this->logQueue = new SplQueue(); 29 | } 30 | 31 | public function init(): void 32 | { 33 | // overridden to prevent register_shutdown_function 34 | } 35 | 36 | /** 37 | * @param string|array|YiiException $message 38 | * @param self::LEVEL_INFO|self::LEVEL_WARNING|self::LEVEL_ERROR $level 39 | * @param string $category 40 | */ 41 | public function log($message, $level, $category = 'application'): void 42 | { 43 | if (! in_array( 44 | $level, 45 | [ 46 | self::LEVEL_INFO, 47 | self::LEVEL_WARNING, 48 | self::LEVEL_ERROR, 49 | ], 50 | true 51 | ) 52 | ) { 53 | return; 54 | } 55 | if (str_starts_with($category, 'yii\db\Command')) { 56 | return; // don't log queries 57 | } 58 | // https://github.com/Codeception/Codeception/issues/3696 59 | if ($message instanceof YiiException) { 60 | $message = $message->__toString(); 61 | } 62 | $logMessage = "[$category] " . VarDumper::export($message); 63 | Debug::debug($logMessage); 64 | $this->logQueue->enqueue($logMessage); 65 | if ($this->logQueue->count() > $this->maxLogItems) { 66 | $this->logQueue->dequeue(); 67 | } 68 | } 69 | 70 | public function getAndClearLog(): string 71 | { 72 | $logs = iterator_to_array($this->logQueue); 73 | $this->logQueue = new SplQueue(); 74 | return implode(PHP_EOL, $logs) . PHP_EOL; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/Codeception/Lib/Connector/Yii2/TestMailer.php: -------------------------------------------------------------------------------- 1 | callback)($message); 20 | return true; 21 | } 22 | 23 | protected function saveMessage(mixed $message): bool 24 | { 25 | ($this->callback)($message); 26 | return true; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Codeception/Lib/Connector/Yii2/TransactionForcer.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | private array $pdoCache = []; 20 | 21 | /** 22 | * @var array 23 | */ 24 | private array $dsnCache = []; 25 | 26 | /** 27 | * @var array 28 | */ 29 | private array $transactions = []; 30 | 31 | public function __construct( 32 | private readonly bool $ignoreCollidingDSN 33 | ) { 34 | parent::__construct(); 35 | } 36 | 37 | protected function connectionOpened(Connection $connection): void 38 | { 39 | parent::connectionOpened($connection); 40 | /** 41 | * We should check if the known PDO objects are the same, in which case we should reuse the PDO 42 | * object so only 1 transaction is started and multiple connections to the same database see the 43 | * same data (due to writes inside a transaction not being visible from the outside). 44 | */ 45 | $key = md5( 46 | json_encode( 47 | [ 48 | 'dsn' => $connection->dsn, 49 | 'user' => $connection->username, 50 | 'pass' => $connection->password, 51 | 'attributes' => $connection->attributes, 52 | 'emulatePrepare' => $connection->emulatePrepare, 53 | 'charset' => $connection->charset, 54 | ], 55 | JSON_THROW_ON_ERROR 56 | ) 57 | ); 58 | /* 59 | * If keys match we assume connections are "similar enough". 60 | */ 61 | if (isset($this->pdoCache[$key])) { 62 | $connection->pdo = $this->pdoCache[$key]; 63 | } elseif (isset($connection->pdo)) { 64 | $this->pdoCache[$key] = $connection->pdo; 65 | } 66 | if (isset($this->dsnCache[$connection->dsn]) 67 | && $this->dsnCache[$connection->dsn] !== $key 68 | && ! $this->ignoreCollidingDSN 69 | ) { 70 | $this->debug( 71 | <<dsn}) with different configuration. 73 | These connections will not see the same database state since we cannot share a transaction between different PDO 74 | instances. 75 | You can remove this message by adding 'ignoreCollidingDSN = true' in the module configuration. 76 | TEXT, 77 | ); 78 | Debug::pause(); 79 | } 80 | if (isset($this->transactions[$key])) { 81 | $this->debug('Reusing PDO, so no need for a new transaction'); 82 | return; 83 | } 84 | $this->debug('Transaction started for: ' . $connection->dsn); 85 | $this->transactions[$key] = $connection->beginTransaction(); 86 | } 87 | 88 | public function rollbackAll(): void 89 | { 90 | foreach ($this->transactions as $transaction) { 91 | if ($transaction->db->isActive) { 92 | $transaction->rollBack(); 93 | $this->debug('Transaction cancelled; all changes reverted.'); 94 | } 95 | } 96 | $this->transactions = []; 97 | $this->pdoCache = []; 98 | $this->dsnCache = []; 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/Codeception/Module/Yii2.php: -------------------------------------------------------------------------------- 1 | haveFixtures(['posts' => PostsFixture::class]); 149 | * ``` 150 | * 151 | * or, if you need to load fixtures before the test, you 152 | * can specify fixtures in the `_fixtures` method of a test case: 153 | * 154 | * ```php 155 | * PostsFixture::class] 160 | * } 161 | * ``` 162 | * 163 | * ## URL 164 | * 165 | * With this module you can also use Yii2's URL format for all codeception 166 | * commands that expect a URL: 167 | * 168 | * ```php 169 | * amOnPage('index-test.php?r=site/index'); 171 | * $I->amOnPage('http://localhost/index-test.php?r=site/index'); 172 | * $I->sendAjaxPostRequest(['/user/update', 'id' => 1], ['UserForm[name]' => 'G.Hopper']); 173 | * ``` 174 | * 175 | * ## Status 176 | * 177 | * Maintainer: **samdark** 178 | * Stability: **stable** 179 | * 180 | * @phpstan-type ModuleConfig array{ 181 | * configFile: string|null, 182 | * fixturesMethod: string, 183 | * cleanup: bool, 184 | * ignoreCollidingDSN: bool, 185 | * transaction: bool|null, 186 | * entryScript: string, 187 | * entryUrl: string, 188 | * responseCleanMethod: Yii2Connector::CLEAN_CLEAR|Yii2Connector::CLEAN_MANUAL|Yii2Connector::CLEAN_RECREATE, 189 | * requestCleanMethod: Yii2Connector::CLEAN_CLEAR|Yii2Connector::CLEAN_MANUAL|Yii2Connector::CLEAN_RECREATE, 190 | * mailMethod: Yii2Connector::MAIL_CATCH|Yii2Connector::MAIL_IGNORE|Yii2Connector::MAIL_EVENT_AFTER|Yii2Connector::MAIL_EVENT_BEFORE, 191 | * recreateComponents: list, 192 | * recreateApplication: bool, 193 | * closeSessionOnRecreateApplication: bool, 194 | * applicationClass: class-string<\yii\base\Application>|null 195 | * } 196 | * 197 | * @phpstan-type ClientConfig array{ 198 | * configFile: string, 199 | * responseCleanMethod: Yii2Connector::CLEAN_CLEAR|Yii2Connector::CLEAN_MANUAL|Yii2Connector::CLEAN_RECREATE, 200 | * requestCleanMethod: Yii2Connector::CLEAN_CLEAR|Yii2Connector::CLEAN_MANUAL|Yii2Connector::CLEAN_RECREATE, 201 | * mailMethod: Yii2Connector::MAIL_CATCH|Yii2Connector::MAIL_IGNORE|Yii2Connector::MAIL_EVENT_AFTER|Yii2Connector::MAIL_EVENT_BEFORE, 202 | * recreateComponents: list, 203 | * recreateApplication: bool, 204 | * closeSessionOnRecreateApplication: bool, 205 | * applicationClass: class-string<\yii\base\Application>|null 206 | * } 207 | * 208 | * @phpstan-type ValidConfig (ModuleConfig & array{ 209 | * transaction: bool|null, 210 | * configFile: string 211 | * }) 212 | */ 213 | final class Yii2 extends Framework implements ActiveRecord, PartedModule 214 | { 215 | /** 216 | * @var list 217 | */ 218 | public array $loadedFixtures = []; 219 | 220 | /** 221 | * Application config file must be set. 222 | * 223 | * @var ModuleConfig 224 | */ 225 | protected array $config = [ 226 | 'fixturesMethod' => '_fixtures', 227 | 'cleanup' => true, 228 | 'ignoreCollidingDSN' => false, 229 | 'transaction' => true, 230 | 'configFile' => null, 231 | 'entryScript' => '', 232 | 'entryUrl' => 'http://localhost/index-test.php', 233 | 'responseCleanMethod' => Yii2Connector::CLEAN_CLEAR, 234 | 'requestCleanMethod' => Yii2Connector::CLEAN_RECREATE, 235 | 'recreateComponents' => [], 236 | 'recreateApplication' => false, 237 | 'mailMethod' => Yii2Connector::MAIL_CATCH, 238 | 'closeSessionOnRecreateApplication' => true, 239 | 'applicationClass' => null, 240 | ]; 241 | 242 | /** 243 | * Helper to manage database connections 244 | */ 245 | private ConnectionWatcher $connectionWatcher; 246 | 247 | /** 248 | * Helper to force database transaction 249 | */ 250 | private TransactionForcer $transactionForcer; 251 | 252 | /** 253 | * @var array The contents of upon initialization of this object. 254 | * This is only used to restore it upon object destruction. 255 | * It MUST not be used anywhere else. 256 | */ 257 | private array $server; 258 | 259 | private null|Logger $yiiLogger = null; 260 | 261 | private function getClient(): Yii2Connector 262 | { 263 | if (! isset($this->client)) { 264 | throw new RuntimeException('Browser not initialized'); 265 | } 266 | if (! $this->client instanceof Yii2Connector) { 267 | throw new RuntimeException('The Yii2 module must be used with the Yii2 browser client'); 268 | } 269 | return $this->client; 270 | } 271 | 272 | public function _initialize(): void 273 | { 274 | if ($this->config['transaction'] === null) { 275 | $this->config['transaction'] = $this->backupConfig['transaction'] = $this->config['cleanup']; 276 | } 277 | 278 | $this->defineConstants(); 279 | $this->server = $_SERVER; 280 | // Adds the required server params. Note this is done separately from the request cycle since someone might call 281 | // `Url::to` before doing a request, which would instantiate the request component with incorrect server params. 282 | $_SERVER = [...$_SERVER, ...$this->getServerParams()]; 283 | } 284 | 285 | /** 286 | * Module configuration changed inside a test. 287 | * We always re-create the application. 288 | */ 289 | protected function onReconfigure(): void 290 | { 291 | parent::onReconfigure(); 292 | $this->getClient()->resetApplication(); 293 | $this->validateConfig(); 294 | $this->configureClient($this->config); 295 | $this->yiiLogger?->getAndClearLog(); 296 | $this->getClient()->startApp($this->yiiLogger); 297 | } 298 | 299 | /** 300 | * @return array{ 301 | * SCRIPT_FILENAME: string, 302 | * SCRIPT_NAME: string, 303 | * SERVER_NAME: string, 304 | * SERVER_PORT: string|int, 305 | * HTTPS: bool 306 | * } 307 | */ 308 | private function getServerParams(): array 309 | { 310 | $entryUrl = $this->config['entryUrl']; 311 | $parsedUrl = parse_url($entryUrl); 312 | $entryFile = $this->config['entryScript'] ?: basename($entryUrl); 313 | $entryScript = $this->config['entryScript'] ?: ($parsedUrl['path'] ?? ''); 314 | return [ 315 | 'SCRIPT_FILENAME' => $entryFile, 316 | 'SCRIPT_NAME' => $entryScript, 317 | 'SERVER_NAME' => $parsedUrl['host'] ?? '', 318 | 'SERVER_PORT' => $parsedUrl['port'] ?? '80', 319 | 'HTTPS' => isset($parsedUrl['scheme']) && $parsedUrl['scheme'] === 'https', 320 | ]; 321 | } 322 | 323 | /** 324 | * @phpstan-assert ValidConfig $this->config 325 | */ 326 | protected function validateConfig(): void 327 | { 328 | parent::validateConfig(); 329 | if (! isset($this->config['configFile'])) { 330 | throw new ModuleConfigException( 331 | self::class, 332 | "The application config file was not configured", 333 | ); 334 | } 335 | $pathToConfig = codecept_absolute_path($this->config['configFile']); 336 | if (! is_file($pathToConfig)) { 337 | throw new ModuleConfigException( 338 | self::class, 339 | "The application config file does not exist: " . $pathToConfig, 340 | ); 341 | } 342 | $validCleanMethods = implode(", ", Yii2Connector::CLEAN_METHODS); 343 | if (! in_array($this->config['responseCleanMethod'], Yii2Connector::CLEAN_METHODS, true)) { 344 | throw new ModuleConfigException( 345 | self::class, 346 | "The response clean method must be one of: " . $validCleanMethods, 347 | ); 348 | } 349 | $validMailMethods = implode(", ", Yii2Connector::MAIL_METHODS); 350 | if (! in_array($this->config['mailMethod'], Yii2Connector::MAIL_METHODS, true)) { 351 | throw new ModuleConfigException( 352 | self::class, 353 | "The mail method must be one of: " . $validMailMethods 354 | ); 355 | } 356 | if (! in_array($this->config['requestCleanMethod'], Yii2Connector::CLEAN_METHODS, true)) { 357 | throw new ModuleConfigException( 358 | self::class, 359 | "The request clean method must be one of: " . $validCleanMethods, 360 | ); 361 | } 362 | } 363 | 364 | /** 365 | * @param ClientConfig $settings 366 | */ 367 | private function configureClient(array $settings): void 368 | { 369 | $client = $this->getClient(); 370 | $client->configFile = codecept_absolute_path($settings['configFile']); 371 | $client->responseCleanMethod = $settings['responseCleanMethod']; 372 | $client->requestCleanMethod = $settings['requestCleanMethod']; 373 | $client->recreateApplication = $settings['recreateApplication']; 374 | $client->closeSessionOnRecreateApplication = $settings['closeSessionOnRecreateApplication']; 375 | $client->applicationClass = $settings['applicationClass']; 376 | $client->mailMethod = $settings['mailMethod']; 377 | $client->resetApplication(); 378 | } 379 | 380 | /** 381 | * Instantiates the client based on module configuration 382 | */ 383 | protected function recreateClient(): void 384 | { 385 | $this->client = new Yii2Connector($this->getServerParams()); 386 | $this->validateConfig(); 387 | $this->configureClient($this->config); 388 | } 389 | 390 | public function _before(TestInterface $test): void 391 | { 392 | $this->recreateClient(); 393 | $this->yiiLogger = new Yii2Connector\Logger(); 394 | $this->getClient()->startApp($this->yiiLogger); 395 | 396 | $this->connectionWatcher = new ConnectionWatcher(); 397 | $this->connectionWatcher->start(); 398 | 399 | // load fixtures before db transaction 400 | if ($test instanceof \Codeception\Test\Cest) { 401 | $this->loadFixtures($test->getTestInstance()); 402 | } elseif ($test instanceof \Codeception\Test\TestCaseWrapper) { 403 | $this->loadFixtures($test->getTestCase()); 404 | } else { 405 | $this->loadFixtures($test); 406 | } 407 | 408 | $this->startTransactions(); 409 | } 410 | 411 | /** 412 | * load fixtures before db transaction 413 | */ 414 | private function loadFixtures(object $test): void 415 | { 416 | $this->debugSection('Fixtures', 'Loading fixtures'); 417 | if ($this->loadedFixtures === [] 418 | && method_exists($test, $this->config['fixturesMethod']) 419 | ) { 420 | $connectionWatcher = new ConnectionWatcher(); 421 | $connectionWatcher->start(); 422 | $this->haveFixtures($test->{$this->config['fixturesMethod']}()); 423 | $connectionWatcher->stop(); 424 | $connectionWatcher->closeAll(); 425 | } 426 | $this->debugSection('Fixtures', 'Done'); 427 | } 428 | 429 | public function _after(TestInterface $test): void 430 | { 431 | $_SESSION = []; 432 | $_FILES = []; 433 | $_GET = []; 434 | $_POST = []; 435 | $_COOKIE = []; 436 | $_REQUEST = []; 437 | 438 | $this->rollbackTransactions(); 439 | 440 | if ($this->config['cleanup']) { 441 | foreach ($this->loadedFixtures as $fixture) { 442 | $fixture->unloadFixtures(); 443 | } 444 | $this->loadedFixtures = []; 445 | } 446 | 447 | $this->getClient()->resetApplication(); 448 | 449 | if (isset($this->connectionWatcher)) { 450 | $this->connectionWatcher->stop(); 451 | $this->connectionWatcher->closeAll(); 452 | unset($this->connectionWatcher); 453 | } 454 | 455 | parent::_after($test); 456 | } 457 | 458 | /** 459 | * @param Exception $fail 460 | */ 461 | public function _failed(TestInterface $test, $fail): void 462 | { 463 | $log = $this->yiiLogger?->getAndClearLog(); 464 | if (isset($log) && $log !== '') { 465 | $test->getMetadata()->addReport('yii-log', $log); 466 | } 467 | 468 | parent::_failed($test, $fail); 469 | } 470 | 471 | protected function startTransactions(): void 472 | { 473 | if ($this->config['transaction']) { 474 | $this->transactionForcer = new TransactionForcer($this->config['ignoreCollidingDSN']); 475 | $this->transactionForcer->start(); 476 | } 477 | } 478 | 479 | protected function rollbackTransactions(): void 480 | { 481 | if (isset($this->transactionForcer)) { 482 | $this->transactionForcer->rollbackAll(); 483 | $this->transactionForcer->stop(); 484 | unset($this->transactionForcer); 485 | } 486 | } 487 | 488 | /** 489 | * @return list 490 | */ 491 | public function _parts(): array 492 | { 493 | return ['orm', 'init', 'fixtures', 'email', 'route']; 494 | } 495 | 496 | /** 497 | * Authenticates a user on a site without submitting a login form. 498 | * Use it for fast pragmatic authorization in functional tests. 499 | * 500 | * ```php 501 | * amLoggedInAs(1); 504 | * 505 | * // User object is passed as parameter 506 | * $admin = \app\models\User::findByUsername('admin'); 507 | * $I->amLoggedInAs($admin); 508 | * ``` 509 | * Requires the `user` component to be enabled and configured. 510 | * 511 | * @throws \Codeception\Exception\ModuleException 512 | */ 513 | public function amLoggedInAs(int|string|IdentityInterface $user): void 514 | { 515 | try { 516 | $this->getClient()->findAndLoginUser($user); 517 | } catch (ConfigurationException | RuntimeException $e) { 518 | throw new ModuleException($this, $e->getMessage()); 519 | } 520 | } 521 | 522 | /** 523 | * Creates and loads fixtures from a config. 524 | * The signature is the same as for the `fixtures()` method of `yii\test\FixtureTrait` 525 | * 526 | * ```php 527 | * haveFixtures([ 529 | * 'posts' => PostsFixture::class, 530 | * 'user' => [ 531 | * 'class' => UserFixture::class, 532 | * 'dataFile' => '@tests/_data/models/user.php', 533 | * ], 534 | * ]); 535 | * ``` 536 | * 537 | * Note: if you need to load fixtures before a test (probably before the 538 | * cleanup transaction is started; `cleanup` option is `true` by default), 539 | * you can specify the fixtures in the `_fixtures()` method of a test case 540 | * 541 | * ```php 542 | * [ 547 | * 'class' => UserFixture::class, 548 | * 'dataFile' => codecept_data_dir() . 'user.php' 549 | * ] 550 | * ]; 551 | * } 552 | * ``` 553 | * instead of calling `haveFixtures` in Cest `_before` 554 | * 555 | * @part fixtures 556 | * @param array $fixtures 557 | */ 558 | public function haveFixtures(array $fixtures): void 559 | { 560 | if (empty($fixtures)) { 561 | return; 562 | } 563 | $fixturesStore = new Yii2Connector\FixturesStore($fixtures); 564 | $fixturesStore->unloadFixtures(); 565 | $fixturesStore->loadFixtures(); 566 | $this->loadedFixtures[] = $fixturesStore; 567 | } 568 | 569 | /** 570 | * Returns all loaded fixtures. 571 | * Array of fixture instances 572 | * 573 | * @part fixtures 574 | * @return array 575 | */ 576 | public function grabFixtures(): array 577 | { 578 | $result = []; 579 | foreach ($this->loadedFixtures as $store) { 580 | foreach ($store->getFixtures() as $name => $fixture) { 581 | $result[$name] = $fixture; 582 | } 583 | } 584 | return $result; 585 | } 586 | 587 | /** 588 | * Gets a fixture by name. 589 | * Returns a Fixture instance. If a fixture is an instance of 590 | * `\yii\test\BaseActiveFixture` a second parameter can be used to return a 591 | * specific model: 592 | * 593 | * ```php 594 | * haveFixtures(['users' => UserFixture::class]); 596 | * 597 | * $users = $I->grabFixture('users'); 598 | * 599 | * // get first user by key, if a fixture is an instance of ActiveFixture 600 | * $user = $I->grabFixture('users', 'user1'); 601 | * ``` 602 | * 603 | * @throws \Codeception\Exception\ModuleException if the fixture is not found 604 | * @part fixtures 605 | */ 606 | public function grabFixture(string $name, null|string $index = null): Fixture|\yii\db\ActiveRecord|null 607 | { 608 | $fixtures = $this->grabFixtures(); 609 | if (! isset($fixtures[$name])) { 610 | throw new ModuleException($this, "Fixture $name is not loaded"); 611 | } 612 | $fixture = $fixtures[$name]; 613 | return match (true) { 614 | $index === null => $fixture, 615 | $fixture instanceof \yii\test\BaseActiveFixture => $fixture->getModel($index), 616 | default => throw new ModuleException($this, "Fixture $name is not an instance of ActiveFixture and can't be loaded with second parameter"), 617 | }; 618 | } 619 | 620 | /** 621 | * Inserts a record into the database. 622 | * 623 | * ``` php 624 | * haveRecord(model: User::class, attributes: ['name' => 'Davert']); 626 | * ?> 627 | * ``` 628 | * 629 | * @template T of \yii\db\ActiveRecord 630 | * @param class-string $model 631 | * @param array $attributes 632 | * @part orm 633 | * @return int|string|array The primary key 634 | */ 635 | public function haveRecord(string $model, $attributes = []): int|string|array 636 | { 637 | /** 638 | * @var T $record 639 | */ 640 | $record = \Yii::createObject($model); 641 | $record->setAttributes($attributes, false); 642 | if (! $record->save(false)) { 643 | Assert::fail("Record $model was not saved: " . \yii\helpers\Json::encode($record->errors)); 644 | } 645 | return $record->getPrimaryKey(); 646 | } 647 | 648 | /** 649 | * Checks that a record exists in the database. 650 | * 651 | * ```php 652 | * $I->seeRecord(model: User::class, attributes: ['name' => 'davert']); 653 | * ``` 654 | * 655 | * @param class-string<\yii\db\ActiveRecord> $model 656 | * @param array $attributes 657 | * @part orm 658 | */ 659 | public function seeRecord(string $model, array $attributes = []): void 660 | { 661 | $record = $this->findRecord($model, $attributes); 662 | if (! $record) { 663 | Assert::fail("Couldn't find $model with " . json_encode($attributes)); 664 | } 665 | $this->debugSection($model, json_encode($record)); 666 | } 667 | 668 | /** 669 | * Checks that a record does not exist in the database. 670 | * 671 | * ```php 672 | * $I->dontSeeRecord(User::class, attributes: ['name' => 'davert']); 673 | * ``` 674 | * 675 | * @param class-string<\yii\db\ActiveRecord> $model 676 | * @param array $attributes 677 | * @part orm 678 | */ 679 | public function dontSeeRecord(string $model, array $attributes = []): void 680 | { 681 | $record = $this->findRecord($model, $attributes); 682 | $this->debugSection($model, json_encode($record)); 683 | if ($record) { 684 | Assert::fail("Unexpectedly managed to find $model with " . json_encode($attributes)); 685 | } 686 | } 687 | 688 | /** 689 | * Retrieves a record from the database 690 | * 691 | * ```php 692 | * $category = $I->grabRecord(User::class, attributes: ['name' => 'davert']); 693 | * ``` 694 | * 695 | * @param class-string<\yii\db\ActiveRecord> $model 696 | * @param array $attributes 697 | * @return ActiveRecordInterface|null|array 698 | * @part orm 699 | */ 700 | public function grabRecord(string $model, array $attributes = []): ActiveRecordInterface|null|array 701 | { 702 | return $this->findRecord($model, $attributes); 703 | } 704 | 705 | /** 706 | * @param class-string<\yii\db\ActiveRecord> $model Class name 707 | * @param array $attributes 708 | * @return ActiveRecordInterface|null|array 709 | */ 710 | protected function findRecord(string $model, array $attributes = []): ActiveRecordInterface|null|array 711 | { 712 | if (! class_exists($model)) { 713 | throw new RuntimeException("Class $model does not exist"); 714 | } 715 | $rc = new ReflectionClass($model); 716 | if ($rc->hasMethod('find') 717 | && ($findMethod = $rc->getMethod('find')) 718 | && $findMethod->isStatic() 719 | && $findMethod->isPublic() 720 | && $findMethod->getNumberOfRequiredParameters() === 0 721 | ) { 722 | $activeQuery = $findMethod->invoke(null); 723 | if ($activeQuery instanceof ActiveQueryInterface) { 724 | return $activeQuery->andWhere($attributes)->one(); 725 | } 726 | throw new RuntimeException("$model::find() must return an instance of yii\db\QueryInterface"); 727 | } 728 | throw new RuntimeException("Class $model does not have a public static find() method without required parameters"); 729 | } 730 | 731 | /** 732 | * Similar to `amOnPage` but accepts a route as first argument and params as second 733 | * 734 | * ``` 735 | * $I->amOnRoute('site/view', ['page' => 'about']); 736 | * ``` 737 | * 738 | * @param string $route A route 739 | * @param array $params Additional route parameters 740 | * @part route 741 | */ 742 | public function amOnRoute(string $route, array $params = []): void 743 | { 744 | if (Yii::$app?->controller === null) { 745 | $route = "/{$route}"; 746 | } 747 | 748 | array_unshift($params, $route); 749 | $this->amOnPage(Url::to($params)); 750 | } 751 | 752 | /** 753 | * Checks that an email is sent. 754 | * 755 | * ```php 756 | * seeEmailIsSent(); 759 | * 760 | * // check that only 3 emails were sent 761 | * $I->seeEmailIsSent(3); 762 | * ``` 763 | * 764 | * @throws \Codeception\Exception\ModuleException 765 | * @part email 766 | */ 767 | public function seeEmailIsSent(?int $num = null): void 768 | { 769 | if ($num === null) { 770 | $this->assertNotEmpty($this->grabSentEmails(), 'emails were sent'); 771 | return; 772 | } 773 | $this->assertSame($num, count($this->grabSentEmails()), 'number of sent emails is equal to ' . $num); 774 | } 775 | 776 | /** 777 | * Checks that no email was sent 778 | * 779 | * @part email 780 | */ 781 | public function dontSeeEmailIsSent(): void 782 | { 783 | $this->seeEmailIsSent(0); 784 | } 785 | 786 | /** 787 | * Returns array of all sent email messages. 788 | * Each message implements the `yii\mail\MessageInterface` interface. 789 | * Useful to perform additional checks using the `Asserts` module: 790 | * 791 | * ```php 792 | * seeEmailIsSent(); 794 | * $messages = $I->grabSentEmails(); 795 | * $I->assertSame('admin@site,com', $messages[0]->getTo()); 796 | * ``` 797 | * 798 | * @part email 799 | * @return list List of sent emails 800 | * @throws \Codeception\Exception\ModuleException 801 | */ 802 | public function grabSentEmails(): array 803 | { 804 | try { 805 | return $this->getClient()->getEmails(); 806 | } catch (ConfigurationException $e) { 807 | throw new ModuleException($this, $e->getMessage()); 808 | } 809 | } 810 | 811 | /** 812 | * Returns the last sent email: 813 | * 814 | * ```php 815 | * seeEmailIsSent(); 817 | * $message = $I->grabLastSentEmail(); 818 | * $I->assertSame('admin@site,com', $message->getTo()); 819 | * ``` 820 | * 821 | * @part email 822 | */ 823 | public function grabLastSentEmail(): MessageInterface|null 824 | { 825 | $this->seeEmailIsSent(); 826 | $messages = $this->grabSentEmails(); 827 | 828 | return $messages[array_key_last($messages)] ?? null; 829 | } 830 | 831 | /** 832 | * Returns a list of regex patterns for recognized domain names 833 | * 834 | * @return non-empty-list 835 | */ 836 | public function getInternalDomains(): array 837 | { 838 | return $this->getClient()->getInternalDomains(); 839 | } 840 | 841 | private function defineConstants(): void 842 | { 843 | defined('YII_DEBUG') || define('YII_DEBUG', true); 844 | defined('YII_ENV') || define('YII_ENV', 'test'); 845 | defined('YII_ENABLE_ERROR_HANDLER') || define('YII_ENABLE_ERROR_HANDLER', false); 846 | } 847 | 848 | /** 849 | * Sets a cookie and, if validation is enabled, signs it. 850 | * 851 | * @param string $name The name of the cookie 852 | * @param string $val The value of the cookie 853 | * @param array{domain?: string, path?: string, expires?: int, secure?:bool} $params Additional cookie params like `domain`, `path`, `expires` and `secure`. 854 | */ 855 | public function setCookie($name, $val, $params = []): void 856 | { 857 | parent::setCookie($name, $this->getClient()->hashCookieData($name, $val), $params); 858 | } 859 | 860 | /** 861 | * Creates the CSRF Cookie. 862 | * 863 | * @param string $val The value of the CSRF token 864 | * @return string[] Returns an array containing the name of the CSRF param and the masked CSRF token. 865 | */ 866 | public function createAndSetCsrfCookie(string $val): array 867 | { 868 | $masked = (new Security())->maskToken($val); 869 | $name = $this->getClient()->getCsrfParamName(); 870 | $this->setCookie($name, $val); 871 | return [$name, $masked]; 872 | } 873 | 874 | public function _afterSuite(): void 875 | { 876 | parent::_afterSuite(); 877 | codecept_debug('Suite done, restoring $_SERVER to original'); 878 | 879 | $_SERVER = $this->server; 880 | } 881 | } 882 | --------------------------------------------------------------------------------