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.
[](https://packagist.org/packages/codeception/module-phpbrowser)
[](/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..abcd394 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',
@@ -139,21 +150,18 @@ public function _getUrl()
/**
* Alias to `haveHttpHeader`
- *
- * @param $name
- * @param $value
*/
- public function setHeader($name, $value)
+ public function setHeader(string $name, string $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 +175,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 +202,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 +214,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 @@