.../rest/tests/src/Functional/ResourceTestBase.php | 2 +- core/tests/Drupal/Tests/BrowserTestBase.php | 33 ++++++++- .../Drupal/Tests/Core/Test/BrowserTestBaseTest.php | 82 ++++++++++++++++++++++ 3 files changed, 114 insertions(+), 3 deletions(-) diff --git a/core/modules/rest/tests/src/Functional/ResourceTestBase.php b/core/modules/rest/tests/src/Functional/ResourceTestBase.php index 0a0e34c..db7f25b 100644 --- a/core/modules/rest/tests/src/Functional/ResourceTestBase.php +++ b/core/modules/rest/tests/src/Functional/ResourceTestBase.php @@ -335,7 +335,7 @@ protected function request($method, Url $url, array $request_options) { $request_options[RequestOptions::HTTP_ERRORS] = FALSE; $request_options[RequestOptions::ALLOW_REDIRECTS] = FALSE; $request_options = $this->decorateWithXdebugCookie($request_options); - $client = $this->getSession()->getDriver()->getClient()->getClient(); + $client = $this->getHttpClient(); return $client->request($method, $url->setAbsolute(TRUE)->toString(), $request_options); } diff --git a/core/tests/Drupal/Tests/BrowserTestBase.php b/core/tests/Drupal/Tests/BrowserTestBase.php index abdedd9..2507560 100644 --- a/core/tests/Drupal/Tests/BrowserTestBase.php +++ b/core/tests/Drupal/Tests/BrowserTestBase.php @@ -548,6 +548,33 @@ public function getSession($name = NULL) { } /** + * Obtain the HTTP client for the system under test. + * + * Use this method for arbitrary HTTP requests to the site under test. For + * most tests, you should not get the HTTP client and instead use navigation + * methods such as drupalGet() and clickLink() in order to benefit from + * assertions. + * + * Subclasses which substitute a different Mink driver should override this + * method and provide a Guzzle client if the Mink driver provides one. + * + * @return \GuzzleHttp\ClientInterface + * The client with BrowserTestBase configuration. + * + * @throws \RuntimeException + * If the Mink driver does not support a Guzzle HTTP client, throw an + * exception. + */ + protected function getHttpClient() { + /* @var $mink_driver \Behat\Mink\Driver\DriverInterface */ + $mink_driver = $this->getSession()->getDriver(); + if ($mink_driver instanceof GoutteDriver) { + return $mink_driver->getClient()->getClient(); + } + throw new \RuntimeException ('The Mink client type ' . get_class($mink_driver) . ' does not support getHttpClient().'); + } + + /** * Returns WebAssert object. * * @param string $name @@ -626,11 +653,13 @@ protected function buildUrl($path, array $options = []) { * to set for example the "Accept-Language" header for requesting the page * in a different language. Note that not all headers are supported, for * example the "Accept" header is always overridden by the browser. For - * testing REST APIs it is recommended to directly use an HTTP client such - * as Guzzle instead. + * testing REST APIs it is recommended to obtain a separate HTTP client + * using getHttpClient() and performing requests that way. * * @return string * The retrieved HTML string, also available as $this->getRawContent() + * + * @see \Drupal\Tests\BrowserTestBase::getHttpClient() */ protected function drupalGet($path, array $options = [], array $headers = []) { $options['absolute'] = TRUE; diff --git a/core/tests/Drupal/Tests/Core/Test/BrowserTestBaseTest.php b/core/tests/Drupal/Tests/Core/Test/BrowserTestBaseTest.php new file mode 100644 index 0000000..a8eb65f --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Test/BrowserTestBaseTest.php @@ -0,0 +1,82 @@ +getMockBuilder(Session::class) + ->disableOriginalConstructor() + ->setMethods(['getDriver']) + ->getMock(); + $session->expects($this->once()) + ->method('getDriver') + ->willReturn($driver); + + $btb = $this->getMockBuilder(BrowserTestBase::class) + ->disableOriginalConstructor() + ->setMethods(['getSession']) + ->getMockForAbstractClass(); + $btb->expects($this->once()) + ->method('getSession') + ->willReturn($session); + + return $btb; + } + + /** + * @covers ::getHttpClient + */ + public function testGetHttpClient() { + // Our stand-in for the Guzzle client object. + $expected = new \stdClass(); + + $browserkit_client = $this->getMockBuilder(Client::class) + ->setMethods(['getClient']) + ->getMockForAbstractClass(); + $browserkit_client->expects($this->once()) + ->method('getClient') + ->willReturn($expected); + + // Because the driver is a GoutteDriver, we'll get back a client. + $driver = $this->getMockBuilder(GoutteDriver::class) + ->setMethods(['getClient']) + ->getMock(); + $driver->expects($this->once()) + ->method('getClient') + ->willReturn($browserkit_client); + + $btb = $this->mockBrowserTestBaseWithDriver($driver); + + $ref_gethttpclient = new \ReflectionMethod($btb, 'getHttpClient'); + $ref_gethttpclient->setAccessible(TRUE); + + $this->assertSame(get_class($expected), get_class($ref_gethttpclient->invoke($btb))); + } + + /** + * @covers ::getHttpClient + */ + public function testGetHttpClientException() { + // A driver type that isn't GoutteDriver. This should cause a + // RuntimeException. + $btb = $this->mockBrowserTestBaseWithDriver(new \stdClass()); + + $ref_gethttpclient = new \ReflectionMethod($btb, 'getHttpClient'); + $ref_gethttpclient->setAccessible(TRUE); + + $this->setExpectedException(\RuntimeException::class, 'The Mink client type stdClass does not support getHttpClient().'); + $ref_gethttpclient->invoke($btb); + } + +}