291 lines
8.0 KiB
PHP
291 lines
8.0 KiB
PHP
<?php
|
|
namespace Codeception\Module;
|
|
|
|
use Codeception\Lib\Connector\Guzzle6;
|
|
use Codeception\Lib\InnerBrowser;
|
|
use Codeception\Lib\Interfaces\MultiSession;
|
|
use Codeception\Lib\Interfaces\Remote;
|
|
use Codeception\Lib\Interfaces\RequiresPackage;
|
|
use Codeception\TestInterface;
|
|
use Codeception\Util\Uri;
|
|
use GuzzleHttp\Client as GuzzleClient;
|
|
|
|
/**
|
|
* Uses [Guzzle](http://guzzlephp.org/) 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.
|
|
*
|
|
* If test fails stores last shown page in 'output' dir.
|
|
*
|
|
* ## Status
|
|
*
|
|
* * Maintainer: **davert**
|
|
* * Stability: **stable**
|
|
* * Contact: codeception@codeception.com
|
|
*
|
|
*
|
|
* ## Configuration
|
|
*
|
|
* * url *required* - start url of your app
|
|
* * headers - default headers are set before each test.
|
|
* * handler (default: curl) - Guzzle handler to use. By default curl is used, also possible to pass `stream`, or any valid class name as [Handler](http://docs.guzzlephp.org/en/latest/handlers-and-middleware.html#handlers).
|
|
* * middleware - Guzzle middlewares to add. An array of valid callables is required.
|
|
* * curl - curl options
|
|
* * cookies - ...
|
|
* * auth - ...
|
|
* * verify - ...
|
|
* * .. those and other [Guzzle Request options](http://docs.guzzlephp.org/en/latest/request-options.html)
|
|
*
|
|
*
|
|
* ### Example (`acceptance.suite.yml`)
|
|
*
|
|
* modules:
|
|
* enabled:
|
|
* - PhpBrowser:
|
|
* url: 'http://localhost'
|
|
* auth: ['admin', '123345']
|
|
* curl:
|
|
* CURLOPT_RETURNTRANSFER: true
|
|
* cookies:
|
|
* cookie-1:
|
|
* Name: userName
|
|
* Value: john.doe
|
|
* cookie-2:
|
|
* Name: authToken
|
|
* Value: 1abcd2345
|
|
* Domain: subdomain.domain.com
|
|
* Path: /admin/
|
|
* Expires: 1292177455
|
|
* Secure: true
|
|
* HttpOnly: false
|
|
*
|
|
*
|
|
* All SSL certification checks are disabled by default.
|
|
* Use Guzzle request options to configure certifications and others.
|
|
*
|
|
* ## Public API
|
|
*
|
|
* Those properties and methods are expected to be used in Helper classes:
|
|
*
|
|
* Properties:
|
|
*
|
|
* * `guzzle` - contains [Guzzle](http://guzzlephp.org/) client instance: `\GuzzleHttp\Client`
|
|
* * `client` - Symfony BrowserKit instance.
|
|
*
|
|
*/
|
|
class PhpBrowser extends InnerBrowser implements Remote, MultiSession, RequiresPackage
|
|
{
|
|
|
|
private $isGuzzlePsr7;
|
|
protected $requiredFields = ['url'];
|
|
|
|
protected $config = [
|
|
'headers' => [],
|
|
'verify' => false,
|
|
'expect' => false,
|
|
'timeout' => 30,
|
|
'curl' => [],
|
|
'refresh_max_interval' => 10,
|
|
'handler' => 'curl',
|
|
'middleware' => null,
|
|
|
|
// required defaults (not recommended to change)
|
|
'allow_redirects' => false,
|
|
'http_errors' => false,
|
|
'cookies' => true,
|
|
];
|
|
|
|
protected $guzzleConfigFields = [
|
|
'auth',
|
|
'proxy',
|
|
'verify',
|
|
'cert',
|
|
'query',
|
|
'ssl_key',
|
|
'proxy',
|
|
'expect',
|
|
'version',
|
|
'timeout',
|
|
'connect_timeout'
|
|
];
|
|
|
|
/**
|
|
* @var \Codeception\Lib\Connector\Guzzle6
|
|
*/
|
|
public $client;
|
|
|
|
/**
|
|
* @var GuzzleClient
|
|
*/
|
|
public $guzzle;
|
|
|
|
public function _requires()
|
|
{
|
|
return ['GuzzleHttp\Client' => '"guzzlehttp/guzzle": ">=4.1.4 <7.0"'];
|
|
}
|
|
|
|
public function _initialize()
|
|
{
|
|
$this->_initializeSession();
|
|
}
|
|
|
|
protected function guessGuzzleConnector()
|
|
{
|
|
if (class_exists('GuzzleHttp\Url')) {
|
|
$this->isGuzzlePsr7 = false;
|
|
return new \Codeception\Lib\Connector\Guzzle();
|
|
}
|
|
$this->isGuzzlePsr7 = true;
|
|
return new \Codeception\Lib\Connector\Guzzle6();
|
|
}
|
|
|
|
public function _before(TestInterface $test)
|
|
{
|
|
if (!$this->client) {
|
|
$this->client = $this->guessGuzzleConnector();
|
|
}
|
|
$this->_prepareSession();
|
|
}
|
|
|
|
public function _getUrl()
|
|
{
|
|
return $this->config['url'];
|
|
}
|
|
|
|
/**
|
|
* Alias to `haveHttpHeader`
|
|
*
|
|
* @param $name
|
|
* @param $value
|
|
*/
|
|
public function setHeader($name, $value)
|
|
{
|
|
$this->haveHttpHeader($name, $value);
|
|
}
|
|
|
|
public function amHttpAuthenticated($username, $password)
|
|
{
|
|
$this->client->setAuth($username, $password);
|
|
}
|
|
|
|
public function amOnUrl($url)
|
|
{
|
|
$host = Uri::retrieveHost($url);
|
|
$this->_reconfigure(['url' => $host]);
|
|
$page = substr($url, strlen($host));
|
|
if ($page === '') {
|
|
$page = '/';
|
|
}
|
|
$this->debugSection('Host', $host);
|
|
$this->amOnPage($page);
|
|
}
|
|
|
|
public function amOnSubdomain($subdomain)
|
|
{
|
|
$url = $this->config['url'];
|
|
$url = preg_replace('~(https?:\/\/)(.*\.)(.*\.)~', "$1$3", $url); // removing current subdomain
|
|
$url = preg_replace('~(https?:\/\/)(.*)~', "$1$subdomain.$2", $url); // inserting new
|
|
$this->_reconfigure(['url' => $url]);
|
|
}
|
|
|
|
protected function onReconfigure()
|
|
{
|
|
$this->_prepareSession();
|
|
}
|
|
|
|
/**
|
|
* Low-level API method.
|
|
* If Codeception commands are not enough, use [Guzzle HTTP Client](http://guzzlephp.org/) methods directly
|
|
*
|
|
* Example:
|
|
*
|
|
* ``` php
|
|
* <?php
|
|
* $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 callable $function
|
|
*/
|
|
public function executeInGuzzle(\Closure $function)
|
|
{
|
|
return $function($this->guzzle);
|
|
}
|
|
|
|
|
|
public function _getResponseCode()
|
|
{
|
|
return $this->getResponseStatusCode();
|
|
}
|
|
|
|
public function _initializeSession()
|
|
{
|
|
// independent sessions need independent cookies
|
|
$this->client = $this->guessGuzzleConnector();
|
|
$this->_prepareSession();
|
|
}
|
|
|
|
public function _prepareSession()
|
|
{
|
|
$defaults = array_intersect_key($this->config, array_flip($this->guzzleConfigFields));
|
|
$curlOptions = [];
|
|
|
|
foreach ($this->config['curl'] as $key => $val) {
|
|
if (defined($key)) {
|
|
$curlOptions[constant($key)] = $val;
|
|
}
|
|
}
|
|
|
|
$this->headers = $this->config['headers'];
|
|
$this->setCookiesFromOptions();
|
|
|
|
if ($this->isGuzzlePsr7) {
|
|
$defaults['base_uri'] = $this->config['url'];
|
|
$defaults['curl'] = $curlOptions;
|
|
$handler = Guzzle6::createHandler($this->config['handler']);
|
|
if ($handler && is_array($this->config['middleware'])) {
|
|
foreach ($this->config['middleware'] as $middleware) {
|
|
$handler->push($middleware);
|
|
}
|
|
}
|
|
$defaults['handler'] = $handler;
|
|
$this->guzzle = new GuzzleClient($defaults);
|
|
} else {
|
|
$defaults['config']['curl'] = $curlOptions;
|
|
$this->guzzle = new GuzzleClient(['base_url' => $this->config['url'], 'defaults' => $defaults]);
|
|
$this->client->setBaseUri($this->config['url']);
|
|
}
|
|
|
|
$this->client->setRefreshMaxInterval($this->config['refresh_max_interval']);
|
|
$this->client->setClient($this->guzzle);
|
|
}
|
|
|
|
public function _backupSession()
|
|
{
|
|
return [
|
|
'client' => $this->client,
|
|
'guzzle' => $this->guzzle,
|
|
'crawler' => $this->crawler,
|
|
'headers' => $this->headers,
|
|
];
|
|
}
|
|
|
|
public function _loadSession($session)
|
|
{
|
|
foreach ($session as $key => $val) {
|
|
$this->$key = $val;
|
|
}
|
|
}
|
|
|
|
public function _closeSession($session = null)
|
|
{
|
|
unset($session);
|
|
}
|
|
}
|