Tests: Cleanup/refactor around HTTP client mocking

This commit is contained in:
Aleksander Machniak
2025-04-06 14:54:20 +02:00
parent 18486929a0
commit 093231905d
4 changed files with 84 additions and 61 deletions

View File

@@ -3,10 +3,9 @@
namespace Roundcube\Tests\Actions\Utils;
use Roundcube\Tests\ActionTestCase;
use Roundcube\Tests\HttpClientMock;
use Roundcube\Tests\OutputHtmlMock;
use function Roundcube\Tests\setHttpClientMock;
/**
* Test class to test rcmail_action_utils_modcss
*/
@@ -52,9 +51,9 @@ class ModcssTest extends ActionTestCase
// Valid url pointing to non-existing resource
$_SESSION['modcssurls'][$key] = $url;
setHttpClientMock([
['code' => 404],
['code' => 200, 'headers' => ['Content-Type' => 'text/css'], 'response' => 'div.pre { display: none; }'],
HttpClientMock::setResponses([
[404],
[200, ['Content-Type' => 'text/css'], 'div.pre { display: none; }'],
]);
$this->runAndAssert($action, OutputHtmlMock::E_EXIT);

51
tests/HttpClientMock.php Normal file
View File

@@ -0,0 +1,51 @@
<?php
namespace Roundcube\Tests;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;
/*
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| |
| Copyright (C) The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| An exception thrown by output classes instead of the `exit` call |
+-----------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |
+-----------------------------------------------------------------------+
*/
/**
* A helper to mock Roundcube HTTP client
*/
class HttpClientMock
{
public static function setResponses(array $responses)
{
foreach ($responses as $idx => $response) {
if ($response instanceof Response) {
$responses[$idx] = $response;
} elseif (is_array($response)) {
$responses[$idx] = new Response(
$response[0] ?? 200,
$response[1] ?? [],
$response[2] ?? ''
);
}
}
$mock = new MockHandler($responses);
$handler = HandlerStack::create($mock);
$rcube = \rcube::get_instance();
$rcube->config->set('http_client', ['handler' => $handler]);
}
}

View File

@@ -2,11 +2,9 @@
namespace Roundcube\Tests\Rcmail;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;
use Roundcube\Tests\ActionTestCase;
use Roundcube\Tests\ExitException;
use Roundcube\Tests\HttpClientMock;
use Roundcube\Tests\OutputHtmlMock;
use Roundcube\Tests\StderrMock;
@@ -151,17 +149,15 @@ class OauthTest extends ActionTestCase
'jwks_uri' => 'https://test/jwks',
];
$mock = new MockHandler([
new Response(200, ['Content-Type' => 'application/json'], json_encode($config_answer)),
HttpClientMock::setResponses([
[200, ['Content-Type' => 'application/json'], json_encode($config_answer)],
]);
$handler = HandlerStack::create($mock);
// provide only the config
$oauth = new \rcmail_oauth([
'provider' => 'example',
'config_uri' => 'https://test/config',
'client_id' => 'some-client',
'http_options' => ['handler' => $handler],
]);
$oauth->init();
@@ -249,13 +245,11 @@ class OauthTest extends ActionTestCase
'scope' => 'openid profile email',
];
$mock = new MockHandler([
new Response(200, ['Content-Type' => 'application/json'], json_encode($payload)),
]);
$handler = HandlerStack::create($mock);
$oauth = new \rcmail_oauth((array) $this->config + [
'http_options' => ['handler' => $handler],
HttpClientMock::setResponses([
[200, ['Content-Type' => 'application/json'], json_encode($payload)],
]);
$oauth = new \rcmail_oauth((array) $this->config);
$oauth->init();
$_SESSION['oauth_state'] = 'random-state'; // ensure state identiquals
@@ -286,13 +280,11 @@ class OauthTest extends ActionTestCase
'scope' => 'openid profile email',
];
$mock = new MockHandler([
new Response(200, ['Content-Type' => 'application/json'], json_encode($payload)),
]);
$handler = HandlerStack::create($mock);
$oauth = new \rcmail_oauth((array) $this->config + [
'http_options' => ['handler' => $handler],
HttpClientMock::setResponses([
[200, ['Content-Type' => 'application/json'], json_encode($payload)],
]);
$oauth = new \rcmail_oauth((array) $this->config);
$oauth->init();
$_SESSION['oauth_state'] = 'random-state'; // ensure state identiquals
@@ -326,15 +318,12 @@ class OauthTest extends ActionTestCase
];
// TODO should create a specific Mock to check request and validate it
$mock = new MockHandler([
new Response(200, ['Content-Type' => 'application/json'], json_encode($payload)), // the request access
new Response(200, ['Content-Type' => 'application/json'], json_encode($this->identity)), // call to userinfo
HttpClientMock::setResponses([
[200, ['Content-Type' => 'application/json'], json_encode($payload)], // the request access
[200, ['Content-Type' => 'application/json'], json_encode($this->identity)], // call to userinfo
]);
$handler = HandlerStack::create($mock);
$oauth = new \rcmail_oauth((array) $this->config + [
'http_options' => ['handler' => $handler],
]);
$oauth = new \rcmail_oauth((array) $this->config);
$oauth->init();
$_SESSION['oauth_state'] = 'random-state'; // ensure state identiquals

View File

@@ -2,9 +2,9 @@
namespace Roundcube\Tests;
use GuzzleHttp\Handler\MockHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Psr7\Response;
use Dom\HTMLDocument;
use Dom\NodeList;
use Dom\XPath;
use Masterminds\HTML5;
/*
@@ -116,36 +116,20 @@ function setProperty($object, $name, $value, $class = null): void
* @param string $html HTML content
* @param string $xpath_query XPath query
*
* @return \DOMNodeList List of nodes found
* @return \DOMNodeList|NodeList List of nodes found
*/
function getHTMLNodes($html, $xpath_query)
{
$html5 = new HTML5(['disable_html_ns' => true]);
$doc = $html5->loadHTML($html);
$xpath = new \DOMXPath($doc);
// Try HTML5 parser available in PHP >= 8.4
if (class_exists(HTMLDocument::class)) {
$options = constant('Dom\HTML_NO_DEFAULT_NS') | \LIBXML_COMPACT | \LIBXML_NOERROR;
$doc = HTMLDocument::createFromString($html, $options, RCUBE_CHARSET);
$xpath = new XPath($doc);
} else {
$html5 = new HTML5(['disable_html_ns' => true]);
$doc = $html5->loadHTML($html);
$xpath = new \DOMXPath($doc);
}
return $xpath->query($xpath_query);
}
/**
* Mock Guzzle HTTP Client
*/
function setHttpClientMock(array $responses)
{
foreach ($responses as $idx => $response) {
if (is_array($response)) {
$responses[$idx] = new Response(
$response['code'] ?? 200,
$response['headers'] ?? [],
$response['response'] ?? ''
);
}
}
$mock = new MockHandler($responses);
$handler = HandlerStack::create($mock);
$rcube = \rcube::get_instance();
$rcube->config->set('http_client', ['handler' => $handler]);
}