77use Codeception \Util \Debug ;
88use Symfony \Component \BrowserKit \AbstractBrowser as Client ;
99use Symfony \Component \BrowserKit \Cookie ;
10+ use Symfony \Component \BrowserKit \CookieJar ;
11+ use Symfony \Component \BrowserKit \History ;
1012use Symfony \Component \BrowserKit \Response ;
1113use Yii ;
1214use yii \base \ExitException ;
1517use yii \mail \MessageInterface ;
1618use yii \web \Application ;
1719use yii \web \ErrorHandler ;
20+ use yii \web \IdentityInterface ;
1821use yii \web \Request ;
1922use yii \web \Response as YiiResponse ;
23+ use yii \web \User ;
2024
2125class Yii2 extends Client
2226{
@@ -81,34 +85,30 @@ class Yii2 extends Client
8185 /**
8286 * @var bool whether to close the session in between requests inside a single test, if recreateApplication is set to true
8387 */
84- public $ closeSessionOnRecreateApplication = true ;
88+ public bool $ closeSessionOnRecreateApplication = true ;
8589
8690 /**
87- * @var string The FQN of the application class to use. In a default Yii setup, should be either `yii\web\Application`
91+ * @var class- string The FQN of the application class to use. In a default Yii setup, should be either `yii\web\Application`
8892 * or `yii\console\Application`
8993 */
90- public $ applicationClass = null ;
94+ public string | null $ applicationClass = null ;
9195
9296
93- private $ emails = [];
97+ private array $ emails = [];
9498
9599 /**
96- * @return \yii\web\Application
97- *
98100 * @deprecated since 2.5, will become protected in 3.0. Directly access to \Yii::$app if you need to interact with it.
101+ * @internal
99102 */
100- public function getApplication ()
103+ public function getApplication (): \ yii \ base \ Application
101104 {
102105 if (!isset (Yii::$ app )) {
103106 $ this ->startApp ();
104107 }
105108 return Yii::$ app ;
106109 }
107110
108- /**
109- * @param bool $closeSession
110- */
111- public function resetApplication ($ closeSession = true )
111+ public function resetApplication (bool $ closeSession = true ): void
112112 {
113113 codecept_debug ('Destroying application ' );
114114 if (true === $ closeSession ) {
@@ -127,40 +127,28 @@ public function resetApplication($closeSession = true)
127127 /**
128128 * Finds and logs in a user
129129 * @internal
130- * @param $user
131130 * @throws ConfigurationException
132131 * @throws \RuntimeException
133132 */
134- public function findAndLoginUser ($ user )
133+ public function findAndLoginUser (int | string | IdentityInterface $ user ): void
135134 {
136135 $ app = $ this ->getApplication ();
137- if (!$ app ->has ('user ' )) {
136+ $ user = $ app ->get ('user ' );
137+ if (!$ user instanceof User) {
138138 throw new ConfigurationException ('The user component is not configured ' );
139139 }
140140
141141 if ($ user instanceof \yii \web \IdentityInterface) {
142142 $ identity = $ user ;
143143 } else {
144144 // class name implementing IdentityInterface
145- $ identityClass = $ app -> user ->identityClass ;
145+ $ identityClass = $ user ->identityClass ;
146146 $ identity = call_user_func ([$ identityClass , 'findIdentity ' ], $ user );
147147 if (!isset ($ identity )) {
148148 throw new \RuntimeException ('User not found ' );
149149 }
150150 }
151- $ app ->user ->login ($ identity );
152- }
153-
154- /**
155- * Masks a value
156- * @internal
157- * @param string $val
158- * @return string
159- * @see \yii\base\Security::maskToken
160- */
161- public function maskToken ($ val )
162- {
163- return $ this ->getApplication ()->security ->maskToken ($ val );
151+ $ user ->login ($ identity );
164152 }
165153
166154 /**
@@ -169,7 +157,7 @@ public function maskToken($val)
169157 * @param string $value The value of the cookie
170158 * @return string The value to send to the browser
171159 */
172- public function hashCookieData ($ name , $ value )
160+ public function hashCookieData ($ name , $ value ): string
173161 {
174162 $ app = $ this ->getApplication ();
175163 if (!$ app ->request ->enableCookieValidation ) {
@@ -182,7 +170,7 @@ public function hashCookieData($name, $value)
182170 * @internal
183171 * @return array List of regex patterns for recognized domain names
184172 */
185- public function getInternalDomains ()
173+ public function getInternalDomains (): array
186174 {
187175 /** @var \yii\web\UrlManager $urlManager */
188176 $ urlManager = $ this ->getApplication ()->urlManager ;
@@ -202,7 +190,7 @@ public function getInternalDomains()
202190 * @internal
203191 * @return array List of sent emails
204192 */
205- public function getEmails ()
193+ public function getEmails (): array
206194 {
207195 return $ this ->emails ;
208196 }
@@ -211,7 +199,7 @@ public function getEmails()
211199 * Deletes all stored emails.
212200 * @internal
213201 */
214- public function clearEmails ()
202+ public function clearEmails (): void
215203 {
216204 $ this ->emails = [];
217205 }
@@ -230,11 +218,8 @@ public function getComponent($name)
230218
231219 /**
232220 * Getting domain regex from rule host template
233- *
234- * @param string $template
235- * @return string
236221 */
237- private function getDomainRegex ($ template )
222+ private function getDomainRegex (string $ template ): string
238223 {
239224 if (preg_match ('#https?://(.*)# ' , $ template , $ matches )) {
240225 $ template = $ matches [1 ];
@@ -259,24 +244,13 @@ function ($matches) use (&$parameters) {
259244 /**
260245 * Gets the name of the CSRF param.
261246 * @internal
262- * @return string
263247 */
264- public function getCsrfParamName ()
248+ public function getCsrfParamName (): string
265249 {
266250 return $ this ->getApplication ()->request ->csrfParam ;
267251 }
268252
269- /**
270- * @internal
271- * @param $params
272- * @return mixed
273- */
274- public function createUrl ($ params )
275- {
276- return is_array ($ params ) ?$ this ->getApplication ()->getUrlManager ()->createUrl ($ params ) : $ params ;
277- }
278-
279- public function startApp (\yii \log \Logger $ logger = null )
253+ public function startApp (\yii \log \Logger $ logger = null ): void
280254 {
281255 codecept_debug ('Starting application ' );
282256 $ config = require ($ this ->configFile );
@@ -306,12 +280,9 @@ public function startApp(\yii\log\Logger $logger = null)
306280 }
307281
308282 /**
309- *
310283 * @param \Symfony\Component\BrowserKit\Request $request
311- *
312- * @return \Symfony\Component\BrowserKit\Response
313284 */
314- public function doRequest (object $ request )
285+ public function doRequest (object $ request ): \ Symfony \ Component \ BrowserKit \ Response
315286 {
316287 $ _COOKIE = $ request ->getCookies ();
317288 $ _SERVER = $ request ->getServer ();
@@ -343,6 +314,9 @@ public function doRequest(object $request)
343314 $ this ->beforeRequest ();
344315
345316 $ app = $ this ->getApplication ();
317+ if (!$ app instanceof Application) {
318+ throw new ConfigurationException ("Application is not a web application " );
319+ }
346320
347321 // disabling logging. Logs are slowing test execution down
348322 foreach ($ app ->log ->targets as $ target ) {
@@ -407,22 +381,22 @@ protected function revertErrorHandler()
407381
408382 /**
409383 * Encodes the cookies and adds them to the headers.
410- * @param \yii\web\Response $response
411384 * @throws \yii\base\InvalidConfigException
412385 */
413386 protected function encodeCookies (
414387 YiiResponse $ response ,
415388 Request $ request ,
416389 Security $ security
417- ) {
390+ ): void {
418391 if ($ request ->enableCookieValidation ) {
419392 $ validationKey = $ request ->cookieValidationKey ;
420393 }
421394
422395 foreach ($ response ->getCookies () as $ cookie ) {
423396 /** @var \yii\web\Cookie $cookie */
424397 $ value = $ cookie ->value ;
425- if ($ cookie ->expire != 1 && isset ($ validationKey )) {
398+ // Expire = 1 means we're removing the cookie
399+ if ($ cookie ->expire !== 1 && isset ($ validationKey )) {
426400 $ data = version_compare (Yii::getVersion (), '2.0.2 ' , '> ' )
427401 ? [$ cookie ->name , $ cookie ->value ]
428402 : $ cookie ->value ;
@@ -443,10 +417,10 @@ protected function encodeCookies(
443417
444418 /**
445419 * Replace mailer with in memory mailer
446- * @param array $config Original configuration
447- * @return array New configuration
420+ * @param array<string, mixed> $config Original configuration
421+ * @return array<string, mixed> New configuration
448422 */
449- protected function mockMailer (array $ config )
423+ protected function mockMailer (array $ config ): array
450424 {
451425 // options that make sense for mailer mock
452426 $ allowedOptions = [
@@ -489,30 +463,23 @@ public function restart(): void
489463 /**
490464 * Return an assoc array with the client context: cookieJar, history.
491465 *
492- * @return array
466+ * @internal
467+ * @return array{ cookieJar: CookieJar, history: History }
493468 */
494- public function getContext ()
469+ public function getContext (): array
495470 {
496471 return [
497472 'cookieJar ' => $ this ->cookieJar ,
498473 'history ' => $ this ->history ,
499474 ];
500475 }
501476
502- /**
503- * Reset the client context: empty cookieJar and history.
504- */
505- public function removeContext ()
506- {
507- parent ::restart ();
508- }
509-
510477 /**
511478 * Set the context, see getContext().
512479 *
513- * @param array $context
480+ * @param array{ cookieJar: CookieJar, history: History } $context
514481 */
515- public function setContext (array $ context )
482+ public function setContext (array $ context ): void
516483 {
517484 $ this ->cookieJar = $ context ['cookieJar ' ];
518485 $ this ->history = $ context ['history ' ];
@@ -522,18 +489,19 @@ public function setContext(array $context)
522489 * This functions closes the session of the application, if the application exists and has a session.
523490 * @internal
524491 */
525- public function closeSession ()
492+ public function closeSession (): void
526493 {
527- if (isset (\Yii::$ app ) && \Yii::$ app ->has ('session ' , true )) {
528- \Yii::$ app ->session ->close ();
494+ $ app = \Yii::$ app ;
495+ if ($ app instanceof \yii \web \Application && $ app ->has ('session ' , true )) {
496+ $ app ->session ->close ();
529497 }
530498 }
531499
532500 /**
533501 * Resets the applications' response object.
534502 * The method used depends on the module configuration.
535503 */
536- protected function resetResponse (Application $ app )
504+ protected function resetResponse (Application $ app ): void
537505 {
538506 $ method = $ this ->responseCleanMethod ;
539507 // First check the current response object.
@@ -566,7 +534,7 @@ protected function resetResponse(Application $app)
566534 }
567535 }
568536
569- protected function resetRequest (Application $ app )
537+ protected function resetRequest (Application $ app ): void
570538 {
571539 $ method = $ this ->requestCleanMethod ;
572540 $ request = $ app ->request ;
@@ -596,8 +564,8 @@ protected function resetRequest(Application $app)
596564 $ request ->setScriptFile (null );
597565 $ request ->setScriptUrl (null );
598566 $ request ->setUrl (null );
599- $ request ->setPort (null );
600- $ request ->setSecurePort (null );
567+ $ request ->setPort (0 );
568+ $ request ->setSecurePort (0 );
601569 $ request ->setAcceptableContentTypes (null );
602570 $ request ->setAcceptableLanguages (null );
603571
@@ -610,7 +578,7 @@ protected function resetRequest(Application $app)
610578 /**
611579 * Called before each request, preparation happens here.
612580 */
613- protected function beforeRequest ()
581+ protected function beforeRequest (): void
614582 {
615583 if ($ this ->recreateApplication ) {
616584 $ this ->resetApplication ($ this ->closeSessionOnRecreateApplication );
@@ -619,6 +587,9 @@ protected function beforeRequest()
619587
620588 $ application = $ this ->getApplication ();
621589
590+ if (!$ application instanceof Application) {
591+ throw new ConfigurationException ('Application must be an instance of web application when doing requests ' );
592+ }
622593 $ this ->resetResponse ($ application );
623594 $ this ->resetRequest ($ application );
624595
0 commit comments