class DrupalTestBrowser

Same name and namespace in other branches
  1. 9 core/tests/Drupal/Tests/DrupalTestBrowser.php \Drupal\Tests\DrupalTestBrowser
  2. 10 core/tests/Drupal/Tests/DrupalTestBrowser.php \Drupal\Tests\DrupalTestBrowser

Enables a BrowserKitDriver mink driver to use a Guzzle client.

This code is heavily based on the following projects:

Hierarchy

  • class \Drupal\Tests\DrupalTestBrowser extends \Symfony\Component\BrowserKit\AbstractBrowser

Expanded class hierarchy of DrupalTestBrowser

2 files declare their use of DrupalTestBrowser
BrowserTestBaseTest.php in core/tests/Drupal/Tests/Core/Test/BrowserTestBaseTest.php
BuildTestBase.php in core/tests/Drupal/BuildTests/Framework/BuildTestBase.php

File

core/tests/Drupal/Tests/DrupalTestBrowser.php, line 22

Namespace

Drupal\Tests
View source
class DrupalTestBrowser extends AbstractBrowser {
    
    /**
     * The Guzzle client.
     *
     * @var \GuzzleHttp\ClientInterface
     */
    protected $client;
    
    /**
     * Sets the Guzzle client.
     *
     * @param \GuzzleHttp\ClientInterface $client
     *   The Guzzle client.
     *
     * @return $this
     */
    public function setClient(ClientInterface $client) {
        $this->client = $client;
        if ($this->getServerParameter('HTTP_HOST', NULL) !== NULL || ($base_uri = $client->getConfig('base_uri') === NULL)) {
            return $this;
        }
        $path = $base_uri->getPath();
        if ($path !== '' && $path !== '/') {
            throw new \InvalidArgumentException('Setting a path in the Guzzle "base_uri" config option is not supported by DrupalTestBrowser.');
        }
        if ($this->getServerParameter('HTTPS', NULL) === NULL && $base_uri->getScheme() === 'https') {
            $this->setServerParameter('HTTPS', 'on');
        }
        $host = $base_uri->getHost();
        if (($port = $base_uri->getPort()) !== NULL) {
            $host .= ":{$port}";
        }
        $this->setServerParameter('HTTP_HOST', $host);
        return $this;
    }
    
    /**
     * Gets the Guzzle client.
     *
     * @return \GuzzleHttp\ClientInterface
     *   The Guzzle client.
     */
    public function getClient() {
        if (!$this->client) {
            $this->client = new Client([
                'allow_redirects' => FALSE,
                'cookies' => TRUE,
            ]);
        }
        return $this->client;
    }
    
    /**
     * {@inheritdoc}
     */
    protected function doRequest($request) : object {
        $headers = [];
        foreach ($request->getServer() as $key => $val) {
            $key = strtolower(str_replace('_', '-', $key));
            $content_headers = [
                'content-length' => TRUE,
                'content-md5' => TRUE,
                'content-type' => TRUE,
            ];
            if (str_starts_with($key, 'http-')) {
                $headers[substr($key, 5)] = $val;
            }
            elseif (isset($content_headers[$key])) {
                $headers[$key] = $val;
            }
        }
        $cookies = CookieJar::fromArray($this->getCookieJar()
            ->allRawValues($request->getUri()), parse_url($request->getUri(), PHP_URL_HOST));
        $request_options = [
            'cookies' => $cookies,
            'allow_redirects' => FALSE,
        ];
        if (!\in_array($request->getMethod(), [
            'GET',
            'HEAD',
        ], TRUE)) {
            if (NULL !== ($content = $request->getContent())) {
                $request_options['body'] = $content;
            }
            else {
                if ($files = $request->getFiles()) {
                    $request_options['multipart'] = [];
                    $this->addPostFields($request->getParameters(), $request_options['multipart']);
                    $this->addPostFiles($files, $request_options['multipart']);
                }
                else {
                    $request_options['form_params'] = $request->getParameters();
                }
            }
        }
        if (!empty($headers)) {
            $request_options['headers'] = $headers;
        }
        $method = $request->getMethod();
        $uri = $request->getUri();
        // Let BrowserKit handle redirects
        try {
            $response = $this->getClient()
                ->request($method, $uri, $request_options);
        } catch (RequestException $e) {
            if (!$e->hasResponse()) {
                throw $e;
            }
            $response = $e->getResponse();
        }
        return $this->createResponse($response);
    }
    
    /**
     * Adds files to the $multipart array.
     *
     * @param array $files
     *   The files.
     * @param array $multipart
     *   A reference to the multipart array to add the files to.
     * @param string $array_name
     *   Internal parameter used by recursive calls.
     */
    protected function addPostFiles(array $files, array &$multipart, $array_name = '') {
        if (empty($files)) {
            return;
        }
        foreach ($files as $name => $info) {
            if (!empty($array_name)) {
                $name = $array_name . '[' . $name . ']';
            }
            $file = [
                'name' => $name,
            ];
            if (\is_array($info)) {
                if (isset($info['tmp_name'])) {
                    if ($info['tmp_name'] !== '') {
                        $file['contents'] = fopen($info['tmp_name'], 'r');
                        if (isset($info['name'])) {
                            $file['filename'] = $info['name'];
                        }
                    }
                    else {
                        continue;
                    }
                }
                else {
                    $this->addPostFiles($info, $multipart, $name);
                    continue;
                }
            }
            else {
                $file['contents'] = fopen($info, 'r');
            }
            $multipart[] = $file;
        }
    }
    
    /**
     * Adds form parameters to the $multipart array.
     *
     * @param array $formParams
     *   The form parameters.
     * @param array $multipart
     *   A reference to the multipart array to add the form parameters to.
     * @param string $array_name
     *   Internal parameter used by recursive calls.
     */
    public function addPostFields(array $formParams, array &$multipart, $array_name = '') {
        foreach ($formParams as $name => $value) {
            if (!empty($array_name)) {
                $name = $array_name . '[' . $name . ']';
            }
            if (\is_array($value)) {
                $this->addPostFields($value, $multipart, $name);
            }
            else {
                $multipart[] = [
                    'name' => $name,
                    'contents' => $value,
                ];
            }
        }
    }
    
    /**
     * Converts a Guzzle response to a BrowserKit response.
     *
     * @param \Psr\Http\Message\ResponseInterface $response
     *   The Guzzle response.
     *
     * @return \Symfony\Component\BrowserKit\Response
     *   A BrowserKit Response instance.
     */
    protected function createResponse(ResponseInterface $response) {
        return new Response((string) $response->getBody(), $response->getStatusCode(), $response->getHeaders());
    }

}

Members

Title Sort descending Modifiers Object type Summary
DrupalTestBrowser::$client protected property The Guzzle client.
DrupalTestBrowser::addPostFields public function Adds form parameters to the $multipart array.
DrupalTestBrowser::addPostFiles protected function Adds files to the $multipart array.
DrupalTestBrowser::createResponse protected function Converts a Guzzle response to a BrowserKit response.
DrupalTestBrowser::doRequest protected function
DrupalTestBrowser::getClient public function Gets the Guzzle client.
DrupalTestBrowser::setClient public function Sets the Guzzle client.

Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.