HttpKernelUiHelperTrait.php
Same filename and directory in other branches
Namespace
Drupal\TestsFile
-
core/
tests/ Drupal/ Tests/ HttpKernelUiHelperTrait.php
View source
<?php
declare (strict_types=1);
namespace Drupal\Tests;
use Behat\Mink\Driver\BrowserKitDriver;
use Behat\Mink\Driver\DriverInterface;
use Behat\Mink\Mink;
use Behat\Mink\Selector\SelectorsHandler;
use Behat\Mink\Session;
use Drupal\Core\Url;
use Symfony\Component\HttpKernel\HttpKernelBrowser;
/**
* Provides UI helper methods using the HTTP kernel to make requests.
*
* This is for use by Kernel tests, with the following limitations:
* - There is no logged in user. Use \Drupal\Tests\user\Traits\UserCreationTrait
* to set a current user.
* - There is no active theme. To place blocks, a test must first install a
* theme and then set it as active.
* - Session semantics differ from normal page requests. Do not rely on session
* state beyond its existence (no persistence or regeneration).
* - Page caching modules will not work. See \Drupal\Tests\Traits\Core\Cache\PageCachePolicyTrait
* for how to set them up.
*/
trait HttpKernelUiHelperTrait {
use BrowserHtmlDebugTrait;
/**
* Mink session manager.
*
* This is lazily initialized by the first call to self::drupalGet().
*
* @var \Behat\Mink\Mink|null
*/
protected ?Mink $mink;
/**
* Retrieves a Drupal path.
*
* Requests are sent to the HTTP kernel.
*
* @param \Drupal\Core\Url|string $path
* The Drupal path to load into Mink controlled browser, as a string or a
* Url object. (Note that the Symfony browser's functionality of paths
* relative to the previous request is not available, because an initial '/'
* is assumed if not present.)
* @param array $options
* (optional) Options to be forwarded to the URL generator. The 'absolute'
* option is not supported.
* @param string[] $headers
* An array containing additional HTTP request headers, the array keys are
* the header names and the array values the header values. This is useful
* to set for example the "Accept-Language" header for requesting the page
* in a different language. Note that Mink's BrowserKitDriver normalizes
* header names to uppercase, while Symfony's HTTP classes normalize to
* lower case, which may cause a header to not be found with certain APIs.
*
* @return string
* The retrieved HTML string.
*
* @see \Drupal\Tests\BrowserTestBase::getHttpClient()
*/
protected function drupalGet($path, array $options = [], array $headers = []) : string {
$session = $this->getSession();
if (is_string($path) && !str_starts_with($path, '/')) {
$path = '/' . $path;
}
if (is_object($path) || $options) {
$path = $this->buildUrl($path, $options);
}
foreach ($headers as $header_name => $header_value) {
assert(is_string($header_name));
$session->setRequestHeader($header_name, $header_value);
}
$session->visit($path);
$out = $session->getPage()
->getContent();
if ($this->htmlOutputEnabled) {
$html_output = 'GET request to: ' . $path;
$html_output .= '<hr />' . $out;
$html_output .= $this->getHtmlOutputHeaders();
$this->htmlOutput($html_output);
}
return $out;
}
/**
* Follows a link by complete name.
*
* Will click the first link found with this link text unless $index is
* specified.
*
* If the link is not found, an assertion will fail, halting the test.
*
* @param string|\Stringable $label
* Text between the anchor tags.
* @param int $index
* (optional) The index number for cases where multiple links have the same
* text. Defaults to 0.
*/
protected function clickLink(string|\Stringable $label, int $index = 0) : void {
$label = (string) $label;
$links = $this->getSession()
->getPage()
->findAll('named', [
'link',
$label,
]);
$this->assertArrayHasKey($index, $links, 'The link ' . $label . ' was not found on the page.');
// Use static::drupalGet() rather than the click() method on the element,
// because that will not produce HTML debug output.
$this->drupalGet($links[$index]->getAttribute('href'));
}
/**
* Builds a URL from a system path or a URL object.
*
* @param string|\Drupal\Core\Url $path
* A system path or a URL object.
* @param array $options
* Options to be passed to Url::fromUri(). If $path is a Url object, any
* options it has will take priority over this parameter.
*
* @return string
* A URL string.
*/
protected function buildUrl(Url|string $path, array $options = []) : string {
assert(empty($options['absolute']), 'Absolute URLs are not usable with drupalGet().');
if ($path instanceof Url) {
if ($options) {
$url_options = $path->getOptions();
$options = $url_options + $options;
$path->setOptions($options);
}
return $path->toString();
}
$uri = $path === '<front>' ? 'base:/' : 'base:/' . $path;
return Url::fromUri($uri, $options)->toString();
}
/**
* Returns Mink session.
*
* The lazily initializes Mink the first time it is called.
*
* @param string $name
* (optional) Name of the session. Defaults to the active session.
*
* @return \Behat\Mink\Session
* The active Mink session object.
*/
public function getSession($name = NULL) : Session {
// Lazily initialize the Mink session. We do this because unlike Browser
// tests where there should definitely be requests made, this is not
// necessarily the case with Kernel tests.
if (!isset($this->mink)) {
$this->initMink();
// Set up the browser test output file.
$this->initBrowserOutputFile();
}
return $this->mink
->getSession($name);
}
/**
* Initializes Mink sessions.
*
* Helper for static::getSession().
*/
protected function initMink() : void {
$driver = $this->getDefaultDriverInstance();
$selectors_handler = new SelectorsHandler([
'hidden_field_selector' => new HiddenFieldSelector(),
]);
$session = new Session($driver, $selectors_handler);
$this->mink = new Mink();
$this->mink
->registerSession('default', $session);
$this->mink
->setDefaultSessionName('default');
}
/**
* Gets an instance of the default Mink driver.
*
* @return \Behat\Mink\Driver\DriverInterface
* Instance of default Mink driver.
*
* @throws \InvalidArgumentException
* When provided default Mink driver class can't be instantiated.
*/
protected function getDefaultDriverInstance() : DriverInterface {
$http_kernel = $this->container
->get('http_kernel');
$browserkit_client = new HttpKernelBrowser($http_kernel);
$driver = new BrowserKitDriver($browserkit_client);
return $driver;
}
/**
* Returns WebAssert object.
*
* @param string $name
* (optional) Name of the session. Defaults to the active session.
*
* @return \Drupal\Tests\WebAssert
* A new web-assert option for asserting the presence of elements with.
*/
public function assertSession($name = NULL) : WebAssert {
$this->addToAssertionCount(1);
return new WebAssert($this->getSession($name));
}
/**
* Performs an xpath search on the contents of the internal browser.
*
* The search is relative to the root element (HTML tag normally) of the page.
*
* This method is identical to \Drupal\Tests\BrowserTestBase::xpath() and
* should be used when converting Browser tests to Kernel tests, as
* \Drupal\KernelTests\AssertContentTrait::xpath() which Kernel tests use does
* not have the same return type.
*
* @param string $xpath
* The xpath string to use in the search.
* @param array $arguments
* An array of arguments with keys in the form ':name' matching the
* placeholders in the query. The values may be either strings or numeric
* values.
*
* @return \Behat\Mink\Element\NodeElement[]
* The list of elements matching the xpath expression.
*/
protected function getNodeElementsByXpath($xpath, array $arguments = []) : array {
$xpath = $this->assertSession()
->buildXPathQuery($xpath, $arguments);
return $this->getSession()
->getPage()
->findAll('xpath', $xpath);
}
/**
* Gets the current URL from the browser.
*
* @see \Drupal\Tests\UiHelperTrait::getUrl
*/
protected function getUrl() : string {
return $this->getSession()
->getCurrentUrl();
}
}
Traits
| Title | Deprecated | Summary |
|---|---|---|
| HttpKernelUiHelperTrait | Provides UI helper methods using the HTTP kernel to make requests. |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.