Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:

strategy:
matrix:
php: [7.3, 7.4, 8.0]
php: [7.4, 8.0]

steps:
- name: Checkout code
Expand Down
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@
],
"minimum-stability": "RC",
"require": {
"php": "^7.3 || ^8.0",
"php": "^7.4 || ^8.0",
"ext-json": "*",
"guzzlehttp/guzzle": "^7.3",
"codeception/lib-innerbrowser": "^1.5 || *@dev",
"codeception/codeception": "^5.0 || *@dev"
},
"require-dev": {
"ext-curl": "*",
"aws/aws-sdk-php": "^3.199",
"codeception/module-rest": "^1.3 || *@dev"
},
"conflict": {
Expand Down
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ A Codeception module for testing web application over HTTP.

## Requirements

* `PHP 7.3` or higher.
* `PHP 7.4` or higher.

## Installation

Expand Down
91 changes: 49 additions & 42 deletions src/Codeception/Lib/Connector/Guzzle.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@

namespace Codeception\Lib\Connector;

use Aws\Credentials\Credentials;
use Aws\Signature\SignatureV4;
use Aws\Credentials\Credentials as AwsCredentials;
use Aws\Signature\SignatureV4 as AwsSignatureV4;
use Codeception\Util\Uri;
use GuzzleHttp\Client as GuzzleClient;
use GuzzleHttp\Cookie\CookieJar;
use GuzzleHttp\Cookie\CookieJar as GuzzleCookieJar;
use GuzzleHttp\Cookie\SetCookie;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Handler\CurlHandler;
use GuzzleHttp\Handler\StreamHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\HandlerStack as GuzzleHandlerStack;
use GuzzleHttp\Psr7\Request as Psr7Request;
use GuzzleHttp\Psr7\Response as Psr7Response;
use GuzzleHttp\Psr7\Uri as Psr7Uri;
Expand All @@ -23,33 +23,18 @@

class Guzzle extends AbstractBrowser
{
/**
* @var array
*/
protected $requestOptions = [
protected array $requestOptions = [
'allow_redirects' => false,
'headers' => [],
];

/**
* @var int
*/
protected $refreshMaxInterval = 0;
protected int $refreshMaxInterval = 0;

/**
* @var \Aws\Credentials\Credentials|null
*/
protected $awsCredentials;
protected ?AwsCredentials $awsCredentials = null;

/**
* @var \Aws\Signature\SignatureV4|null
*/
protected $awsSignature;
protected ?AwsSignatureV4 $awsSignature = null;

/**
* @var GuzzleClient
*/
protected $client;
protected ?GuzzleClient $client = null;

/**
* Sets the maximum allowable timeout interval for a meta tag refresh to
Expand Down Expand Up @@ -108,13 +93,12 @@ public function setAuth(string $username, string $password, string $type = 'basi
unset($this->requestOptions['auth']);
return;
}

$this->requestOptions['auth'] = [$username, $password, $type];
}

/**
* Taken from Mink\BrowserKitDriver
*
* @return BrowserKitResponse
*/
protected function createResponse(Psr7Response $psr7Response): BrowserKitResponse
{
Expand All @@ -126,6 +110,7 @@ protected function createResponse(Psr7Response $psr7Response): BrowserKitRespons
if (isset($headers['Content-Type'])) {
$contentType = reset($headers['Content-Type']);
}

if (!$contentType) {
$contentType = 'text/html';
}
Expand All @@ -134,6 +119,7 @@ protected function createResponse(Psr7Response $psr7Response): BrowserKitRespons
if (preg_match('#<meta[^>]+charset *= *["\']?([a-zA-Z\-0-9]+)#i', $body, $matches)) {
$contentType .= ';charset=' . $matches[1];
}

$headers['Content-Type'] = [$contentType];
}

Expand Down Expand Up @@ -182,17 +168,19 @@ protected function getAbsoluteUri($uri)

return Uri::appendPath((string)$baseUri, $uri);
}

// relative url
if (!$this->getHistory()->isEmpty()) {
return Uri::mergeUrls((string)$this->getHistory()->current()->getUri(), $uri);
}
}

return Uri::mergeUrls((string)$baseUri, $uri);
}

protected function doRequest($request)
{
/** @var $request BrowserKitRequest **/
/** @var $request BrowserKitRequest **/
$guzzleRequest = new Psr7Request(
$request->getMethod(),
$request->getUri(),
Expand All @@ -217,15 +205,20 @@ protected function doRequest($request)
} else {
$response = $this->client->send($guzzleRequest, $options);
}
} catch (RequestException $e) {
if (!$e->hasResponse()) {
throw $e;
} catch (RequestException $exception) {
if (!$exception->hasResponse()) {
throw $exception;
}
$response = $e->getResponse();

$response = $exception->getResponse();
}

return $this->createResponse($response);
}

/**
* @return array<string, mixed>
*/
protected function extractHeaders(BrowserKitRequest $request): array
{
$headers = [];
Expand All @@ -240,6 +233,7 @@ protected function extractHeaders(BrowserKitRequest $request): array
$headers[$header] = $val;
}
}

return $headers;
}

Expand All @@ -255,9 +249,11 @@ protected function extractFormData(BrowserKitRequest $browserKitRequest): ?array
if (isset($headers['HTTP_CONTENT_TYPE']) && $headers['HTTP_CONTENT_TYPE'] !== 'application/x-www-form-urlencoded') {
return null;
}

if ($browserKitRequest->getContent() !== null) {
return null;
}

return $browserKitRequest->getParameters();
}

Expand All @@ -275,6 +271,7 @@ protected function extractMultipartFormData(BrowserKitRequest $browserKitRequest
foreach ($browserKitRequest->getParameters() as $k => $parameter) {
$parts = $this->formatMultipart($parts, $k, $parameter);
}

return $parts;
}

Expand All @@ -284,8 +281,10 @@ protected function formatMultipart($parts, $key, $value)
foreach ($value as $subKey => $subValue) {
$parts = array_merge($this->formatMultipart([], $key.sprintf('[%s]', $subKey), $subValue), $parts);
}

return $parts;
}

$parts[] = ['name' => $key, 'contents' => (string) $value];
return $parts;
}
Expand Down Expand Up @@ -313,6 +312,7 @@ protected function mapFiles($requestFiles, $arrayName = ''): array
'content-type' => $info['type']
];
}

$files[] = $file;
}
} else {
Expand All @@ -329,7 +329,7 @@ protected function mapFiles($requestFiles, $arrayName = ''): array
return $files;
}

protected function extractCookies($host): \GuzzleHttp\Cookie\CookieJar
protected function extractCookies($host): GuzzleCookieJar
{
$jar = [];
$cookies = $this->getCookieJar()->all();
Expand All @@ -338,34 +338,41 @@ protected function extractCookies($host): \GuzzleHttp\Cookie\CookieJar
if (!$setCookie->getDomain()) {
$setCookie->setDomain($host);
}

$jar[] = $setCookie;
}
return new CookieJar(false, $jar);

return new GuzzleCookieJar(false, $jar);
}

public static function createHandler($handler): \GuzzleHttp\HandlerStack
public static function createHandler($handler): GuzzleHandlerStack
{
if ($handler instanceof HandlerStack) {
if ($handler instanceof GuzzleHandlerStack) {
return $handler;
}

if ($handler === 'curl') {
return HandlerStack::create(new CurlHandler());
return GuzzleHandlerStack::create(new CurlHandler());
}

if ($handler === 'stream') {
return HandlerStack::create(new StreamHandler());
return GuzzleHandlerStack::create(new StreamHandler());
}

if (is_string($handler) && class_exists($handler)) {
return HandlerStack::create(new $handler);
return GuzzleHandlerStack::create(new $handler);
}

if (is_callable($handler)) {
return HandlerStack::create($handler);
return GuzzleHandlerStack::create($handler);
}
return HandlerStack::create();

return GuzzleHandlerStack::create();
}

public function setAwsAuth($config): void
{
$this->awsCredentials = new Credentials($config['key'], $config['secret']);
$this->awsSignature = new SignatureV4($config['service'], $config['region']);
$this->awsCredentials = new AwsCredentials($config['key'], $config['secret']);
$this->awsSignature = new AwsSignatureV4($config['service'], $config['region']);
}
}
17 changes: 10 additions & 7 deletions src/Codeception/Module/PhpBrowser.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
use GuzzleHttp\Client as GuzzleClient;

/**
* Uses [Guzzle](http://guzzlephp.org/) to interact with your application over CURL.
* Uses [Guzzle](https://docs.guzzlephp.org/en/stable/) to interact with your application over CURL.
* Module works over CURL and requires **PHP CURL extension** to be enabled.
*
* Use to perform web acceptance tests with non-javascript browser.
Expand Down Expand Up @@ -106,7 +106,7 @@ class PhpBrowser extends InnerBrowser implements Remote, MultiSession
/**
* @var string[]
*/
protected $guzzleConfigFields = [
protected array $guzzleConfigFields = [
'auth',
'proxy',
'verify',
Expand All @@ -125,10 +125,7 @@ class PhpBrowser extends InnerBrowser implements Remote, MultiSession
*/
public $client;

/**
* @var GuzzleClient
*/
public $guzzle;
public ?GuzzleClient $guzzle = null;

public function _initialize()
{
Expand All @@ -140,6 +137,7 @@ public function _before(TestInterface $test)
if (!$this->client) {
$this->client = new Guzzle();
}

$this->_prepareSession();
}

Expand Down Expand Up @@ -171,6 +169,7 @@ public function amOnUrl($url): void
if ($page === '') {
$page = '/';
}

$this->debugSection('Host', $host);
$this->amOnPage($page);
}
Expand Down Expand Up @@ -214,6 +213,9 @@ public function executeInGuzzle(Closure $function)
return $function($this->guzzle);
}

/**
* @return int|string
*/
public function _getResponseCode()
{
return $this->getResponseStatusCode();
Expand All @@ -226,7 +228,7 @@ public function _initializeSession(): void
$this->_prepareSession();
}

public function _prepareSession()
public function _prepareSession(): void
{
$defaults = array_intersect_key($this->config, array_flip($this->guzzleConfigFields));
$curlOptions = [];
Expand All @@ -248,6 +250,7 @@ public function _prepareSession()
$handler->push($middleware);
}
}

$defaults['handler'] = $handler;
$this->guzzle = new GuzzleClient($defaults);

Expand Down
Loading