From b56249d8660a68abd3870f700ce342892ca86586 Mon Sep 17 00:00:00 2001 From: Tavo Nieves J Date: Wed, 12 May 2021 18:16:20 -0500 Subject: [PATCH 1/2] Code standards updated to PHP 7.1 --- .github/workflows/main.yml | 2 +- composer.json | 74 ++++++------ readme.md | 4 + src/Codeception/Lib/Connector/Guzzle.php | 110 ++++++++++-------- src/Codeception/Module/PhpBrowser.php | 29 +++-- .../Codeception/Module/PhpBrowserRestTest.php | 4 +- .../Codeception/Module/PhpBrowserTest.php | 6 +- .../Codeception/Module/TestsForBrowsers.php | 3 + tests/unit/Codeception/Module/TestsForWeb.php | 3 + 9 files changed, 135 insertions(+), 100 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0e8081c..0a77212 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: - php: [5.6, 7.0, 7.1, 7.2, 7.3, 7.4, 8.0] + php: [7.1, 7.2, 7.3, 7.4, 8.0] steps: - name: Checkout code diff --git a/composer.json b/composer.json index d8108d9..b4d69e0 100644 --- a/composer.json +++ b/composer.json @@ -1,38 +1,40 @@ { - "name":"codeception/module-phpbrowser", - "description":"Codeception module for testing web application over HTTP", - "keywords":["codeception", "http", "functional-testing"], - "homepage":"http://codeception.com/", - "type":"library", - "license":"MIT", - "authors":[ - { - "name":"Michael Bodnarchuk" - }, - { - "name":"Gintautas Miselis" - } - ], - "minimum-stability": "RC", - "require": { - "php": ">=5.6.0 <9.0", - "guzzlehttp/guzzle": "^6.3|^7.0", - "codeception/lib-innerbrowser": "^1.3", - "codeception/codeception": "*@dev" - }, - "require-dev": { - "codeception/module-rest": "^1.0" - }, - "conflict": { - "codeception/codeception": "<4.0" - }, - "suggest": { - "codeception/phpbuiltinserver": "Start and stop PHP built-in web server for your tests" - }, - "autoload":{ - "classmap": ["src/"] - }, - "config": { - "classmap-authoritative": true - } + "name": "codeception/module-phpbrowser", + "description": "Codeception module for testing web application over HTTP", + "keywords": [ "codeception", "http", "functional-testing" ], + "homepage": "https://codeception.com/", + "type": "library", + "license": "MIT", + "authors": [ + { + "name": "Michael Bodnarchuk" + }, + { + "name": "Gintautas Miselis" + } + ], + "minimum-stability": "RC", + "require": { + "php": "^7.1 || ^8.0", + "guzzlehttp/guzzle": "^6.3|^7.0", + "codeception/lib-innerbrowser": "^1.3", + "codeception/codeception": "*@dev" + }, + "require-dev": { + "codeception/module-rest": "^1.0" + }, + "conflict": { + "codeception/codeception": "<4.0" + }, + "suggest": { + "codeception/phpbuiltinserver": "Start and stop PHP built-in web server for your tests" + }, + "autoload": { + "classmap": [ + "src/" + ] + }, + "config": { + "classmap-authoritative": true + } } diff --git a/readme.md b/readme.md index b12122d..c5de470 100644 --- a/readme.md +++ b/readme.md @@ -7,6 +7,10 @@ A Codeception module for testing web application over HTTP. [![Total Downloads](https://poser.pugx.org/codeception/module-phpbrowser/downloads)](https://packagist.org/packages/codeception/module-phpbrowser) [![License](https://poser.pugx.org/codeception/module-phpbrowser/license)](/LICENSE) +## Requirements + +* `PHP 7.1` or higher. + ## Installation ``` diff --git a/src/Codeception/Lib/Connector/Guzzle.php b/src/Codeception/Lib/Connector/Guzzle.php index 7d68629..d8b0064 100644 --- a/src/Codeception/Lib/Connector/Guzzle.php +++ b/src/Codeception/Lib/Connector/Guzzle.php @@ -1,4 +1,7 @@ false, 'headers' => [], ]; + + /** + * @var int + */ protected $refreshMaxInterval = 0; + /** + * @var \Aws\Credentials\Credentials|null + */ protected $awsCredentials; + + /** + * @var \Aws\Signature\SignatureV4|null + */ protected $awsSignature; - /** @var GuzzleClient */ + /** + * @var GuzzleClient + */ protected $client; /** @@ -43,14 +62,14 @@ class Guzzle extends Client * * @param int $seconds Number of seconds */ - public function setRefreshMaxInterval($seconds) + public function setRefreshMaxInterval(int $seconds): void { $this->refreshMaxInterval = $seconds; } - public function setClient(GuzzleClient $client) + public function setClient(GuzzleClient $guzzleClient): void { - $this->client = $client; + $this->client = $guzzleClient; } /** @@ -63,9 +82,9 @@ public function setClient(GuzzleClient $client) * @param string $name the name of the header * @param string $value the value of the header */ - public function setHeader($name, $value) + public function setHeader(string $name, string $value): void { - if ((string)$value === '') { + if ($value === '') { $this->deleteHeader($name); } else { $this->requestOptions['headers'][$name] = $value; @@ -78,19 +97,14 @@ public function setHeader($name, $value) * * @param string $name the name of the header to delete. */ - public function deleteHeader($name) + public function deleteHeader(string $name): void { unset($this->requestOptions['headers'][$name]); } - /** - * @param string $username - * @param string $password - * @param string $type Default: 'basic' - */ - public function setAuth($username, $password, $type = 'basic') + public function setAuth(string $username, string $password, string $type = 'basic'): void { - if (!$username) { + if ($username === '') { unset($this->requestOptions['auth']); return; } @@ -100,14 +114,12 @@ public function setAuth($username, $password, $type = 'basic') /** * Taken from Mink\BrowserKitDriver * - * @param Psr7Response $response - * * @return BrowserKitResponse */ - protected function createResponse(Psr7Response $response) + protected function createResponse(Psr7Response $psr7Response): BrowserKitResponse { - $body = (string) $response->getBody(); - $headers = $response->getHeaders(); + $body = (string) $psr7Response->getBody(); + $headers = $psr7Response->getHeaders(); $contentType = null; @@ -119,18 +131,18 @@ protected function createResponse(Psr7Response $response) } if (strpos($contentType, 'charset=') === false) { - if (preg_match('/]+charset *= *["\']?([a-zA-Z\-0-9]+)/i', $body, $matches)) { + if (preg_match('#]+charset *= *["\']?([a-zA-Z\-0-9]+)#i', $body, $matches)) { $contentType .= ';charset=' . $matches[1]; } $headers['Content-Type'] = [$contentType]; } - $status = $response->getStatusCode(); + $status = $psr7Response->getStatusCode(); if ($status < 300 || $status >= 400) { $matches = []; $matchesMeta = preg_match( - '/]+http-equiv="refresh" content="\s*(\d*)\s*;\s*url=(.*?)"/i', + '#]+http-equiv="refresh" content="\s*(\d*)\s*;\s*url=(.*?)"#i', $body, $matches ); @@ -138,7 +150,7 @@ protected function createResponse(Psr7Response $response) if (!$matchesMeta && isset($headers['Refresh'])) { // match by header preg_match( - '/^\s*(\d*)\s*;\s*url=(.*)/i', + '#^\s*(\d*)\s*;\s*url=(.*)#i', (string) reset($headers['Refresh']), $matches ); @@ -150,7 +162,7 @@ protected function createResponse(Psr7Response $response) if ($uri->withFragment('') !== $currentUri->withFragment('')) { $status = 302; - $headers['Location'] = $matchesMeta ? htmlspecialchars_decode($uri) : (string)$uri; + $headers['Location'] = $matchesMeta ? htmlspecialchars_decode((string) $uri) : (string)$uri; } } } @@ -158,7 +170,7 @@ protected function createResponse(Psr7Response $response) return new BrowserKitResponse($body, $status, $headers); } - public function getAbsoluteUri($uri) + protected function getAbsoluteUri($uri) { $baseUri = $this->client->getConfig('base_uri'); if (strpos($uri, '://') === false && strpos($uri, '//') !== 0) { @@ -172,7 +184,7 @@ public function getAbsoluteUri($uri) } // relative url if (!$this->getHistory()->isEmpty()) { - return Uri::mergeUrls((string)$this->getHistory()->current()->getUri(), $uri); + return Uri::mergeUrls($this->getHistory()->current()->getUri(), $uri); } } return Uri::mergeUrls($baseUri, $uri); @@ -214,7 +226,7 @@ protected function doRequest($request) return $this->createResponse($response); } - protected function extractHeaders(BrowserKitRequest $request) + protected function extractHeaders(BrowserKitRequest $request): array { $headers = []; $server = $request->getServer(); @@ -231,39 +243,37 @@ protected function extractHeaders(BrowserKitRequest $request) return $headers; } - protected function extractFormData(BrowserKitRequest $request) + protected function extractFormData(BrowserKitRequest $browserKitRequest): ?array { - if (!in_array(strtoupper($request->getMethod()), ['POST', 'PUT', 'PATCH', 'DELETE'])) { + if (!in_array(strtoupper($browserKitRequest->getMethod()), ['POST', 'PUT', 'PATCH', 'DELETE'])) { return null; } // guessing if it is a form data - $headers = $request->getServer(); - if (isset($headers['HTTP_CONTENT_TYPE'])) { - // not a form - if ($headers['HTTP_CONTENT_TYPE'] !== 'application/x-www-form-urlencoded') { - return null; - } + $headers = $browserKitRequest->getServer(); + // not a form + if (isset($headers['HTTP_CONTENT_TYPE']) && $headers['HTTP_CONTENT_TYPE'] !== 'application/x-www-form-urlencoded') { + return null; } - if ($request->getContent() !== null) { + if ($browserKitRequest->getContent() !== null) { return null; } - return $request->getParameters(); + return $browserKitRequest->getParameters(); } - protected function extractMultipartFormData(BrowserKitRequest $request) + protected function extractMultipartFormData(BrowserKitRequest $browserKitRequest) { - if (!in_array(strtoupper($request->getMethod()), ['POST', 'PUT', 'PATCH'])) { + if (!in_array(strtoupper($browserKitRequest->getMethod()), ['POST', 'PUT', 'PATCH'])) { return []; } - $parts = $this->mapFiles($request->getFiles()); + $parts = $this->mapFiles($browserKitRequest->getFiles()); if (empty($parts)) { return []; } - foreach ($request->getParameters() as $k => $v) { - $parts = $this->formatMultipart($parts, $k, $v); + foreach ($browserKitRequest->getParameters() as $k => $parameter) { + $parts = $this->formatMultipart($parts, $k, $parameter); } return $parts; } @@ -272,7 +282,7 @@ protected function formatMultipart($parts, $key, $value) { if (is_array($value)) { foreach ($value as $subKey => $subValue) { - $parts = array_merge($this->formatMultipart([], $key."[$subKey]", $subValue), $parts); + $parts = array_merge($this->formatMultipart([], $key.sprintf('[%s]', $subKey), $subValue), $parts); } return $parts; } @@ -280,7 +290,7 @@ protected function formatMultipart($parts, $key, $value) return $parts; } - protected function mapFiles($requestFiles, $arrayName = '') + protected function mapFiles($requestFiles, $arrayName = ''): array { $files = []; foreach ($requestFiles as $name => $info) { @@ -292,7 +302,7 @@ protected function mapFiles($requestFiles, $arrayName = '') if (isset($info['tmp_name'])) { if ($info['tmp_name']) { $handle = fopen($info['tmp_name'], 'rb'); - $filename = isset($info['name']) ? $info['name'] : null; + $filename = $info['name'] ?? null; $file = [ 'name' => $name, 'contents' => $handle, @@ -319,7 +329,7 @@ protected function mapFiles($requestFiles, $arrayName = '') return $files; } - protected function extractCookies($host) + protected function extractCookies($host): \GuzzleHttp\Cookie\CookieJar { $jar = []; $cookies = $this->getCookieJar()->all(); @@ -333,7 +343,7 @@ protected function extractCookies($host) return new CookieJar(false, $jar); } - public static function createHandler($handler) + public static function createHandler($handler): \GuzzleHttp\HandlerStack { if ($handler instanceof HandlerStack) { return $handler; @@ -353,7 +363,7 @@ public static function createHandler($handler) return HandlerStack::create(); } - public function setAwsAuth($config) + public function setAwsAuth($config): void { $this->awsCredentials = new Credentials($config['key'], $config['secret']); $this->awsSignature = new SignatureV4($config['service'], $config['region']); diff --git a/src/Codeception/Module/PhpBrowser.php b/src/Codeception/Module/PhpBrowser.php index bbf2ce8..d9cbb7c 100644 --- a/src/Codeception/Module/PhpBrowser.php +++ b/src/Codeception/Module/PhpBrowser.php @@ -1,4 +1,7 @@ [], 'verify' => false, @@ -95,6 +103,9 @@ class PhpBrowser extends InnerBrowser implements Remote, MultiSession 'cookies' => true, ]; + /** + * @var string[] + */ protected $guzzleConfigFields = [ 'auth', 'proxy', @@ -143,17 +154,17 @@ public function _getUrl() * @param $name * @param $value */ - public function setHeader($name, $value) + public function setHeader($name, $value): void { $this->haveHttpHeader($name, $value); } - public function amHttpAuthenticated($username, $password) + public function amHttpAuthenticated($username, $password): void { $this->client->setAuth($username, $password); } - public function amOnUrl($url) + public function amOnUrl($url): void { $host = Uri::retrieveHost($url); $config = $this->config; @@ -167,11 +178,12 @@ public function amOnUrl($url) $this->amOnPage($page); } - public function amOnSubdomain($subdomain) + public function amOnSubdomain($subdomain): void { $url = $this->config['url']; - $url = preg_replace('~(https?://)(.*\.)(.*\.)~', "$1$3", $url); // removing current subdomain - $url = preg_replace('~(https?://)(.*)~', "$1$subdomain.$2", $url); // inserting new + $url = preg_replace('#(https?://)(.*\.)(.*\.)#', "$1$3", $url); // removing current subdomain + $url = preg_replace('#(https?://)(.*)#', sprintf('$1%s.$2', $subdomain), $url); + // inserting new $config = $this->config; $config['url'] = $url; $this->_reconfigure($config); @@ -193,13 +205,11 @@ protected function onReconfigure() * $I->executeInGuzzle(function (\GuzzleHttp\Client $client) { * $client->get('/get', ['query' => ['foo' => 'bar']]); * }); - * ?> * ``` * * It is not recommended to use this command on a regular basis. * If Codeception lacks important Guzzle Client methods, implement them and submit patches. * - * @param Closure $function * @return mixed */ public function executeInGuzzle(Closure $function) @@ -207,7 +217,6 @@ public function executeInGuzzle(Closure $function) return $function($this->guzzle); } - public function _getResponseCode() { return $this->getResponseStatusCode(); diff --git a/tests/unit/Codeception/Module/PhpBrowserRestTest.php b/tests/unit/Codeception/Module/PhpBrowserRestTest.php index 58b85f0..a86a6eb 100644 --- a/tests/unit/Codeception/Module/PhpBrowserRestTest.php +++ b/tests/unit/Codeception/Module/PhpBrowserRestTest.php @@ -1,9 +1,11 @@ module->seeResponseCodeIs(200); $this->module->dontSee('Unauthorized'); $this->module->see("Welcome, davert"); - $this->module->amHttpAuthenticated(null, null); + $this->module->amHttpAuthenticated('', ''); $this->module->amOnPage('/auth'); $this->module->seeResponseCodeIs(401); $this->module->amHttpAuthenticated('davert', '123456'); diff --git a/tests/unit/Codeception/Module/TestsForBrowsers.php b/tests/unit/Codeception/Module/TestsForBrowsers.php index bbf3b55..d0df175 100644 --- a/tests/unit/Codeception/Module/TestsForBrowsers.php +++ b/tests/unit/Codeception/Module/TestsForBrowsers.php @@ -1,4 +1,7 @@ Date: Tue, 18 May 2021 12:57:50 -0500 Subject: [PATCH 2/2] Added more typehints --- src/Codeception/Module/PhpBrowser.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Codeception/Module/PhpBrowser.php b/src/Codeception/Module/PhpBrowser.php index d9cbb7c..abcd394 100644 --- a/src/Codeception/Module/PhpBrowser.php +++ b/src/Codeception/Module/PhpBrowser.php @@ -150,11 +150,8 @@ public function _getUrl() /** * Alias to `haveHttpHeader` - * - * @param $name - * @param $value */ - public function setHeader($name, $value): void + public function setHeader(string $name, string $value): void { $this->haveHttpHeader($name, $value); }