Extend test capability for HTTP Requests
This commit is contained in:
parent
a3d0404290
commit
d4a233a149
4 changed files with 166 additions and 30 deletions
|
@ -9,6 +9,7 @@ use Friendica\Network\HTTPClient;
|
|||
use Friendica\Network\IHTTPClient;
|
||||
use Friendica\Util\Profiler;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\HandlerStack;
|
||||
use GuzzleHttp\RequestOptions;
|
||||
use mattwright\URLResolver;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
@ -33,7 +34,14 @@ class HTTPClientFactory extends BaseFactory
|
|||
$this->baseUrl = $baseUrl;
|
||||
}
|
||||
|
||||
public function createClient(): IHTTPClient
|
||||
/**
|
||||
* Creates a IHTTPClient for communications with HTTP endpoints
|
||||
*
|
||||
* @param HandlerStack|null $handlerStack (optional) A handler replacement (just usefull at test environments)
|
||||
*
|
||||
* @return IHTTPClient
|
||||
*/
|
||||
public function createClient(HandlerStack $handlerStack = null): IHTTPClient
|
||||
{
|
||||
$proxy = $this->config->get('system', 'proxy');
|
||||
|
||||
|
@ -84,6 +92,7 @@ class HTTPClientFactory extends BaseFactory
|
|||
RequestOptions::HEADERS => [
|
||||
'User-Agent' => $userAgent,
|
||||
],
|
||||
'handler' => $handlerStack ?? HandlerStack::create(),
|
||||
]);
|
||||
|
||||
$resolver = new URLResolver();
|
||||
|
|
|
@ -21,47 +21,45 @@
|
|||
|
||||
namespace Friendica\Test;
|
||||
|
||||
use Dice\Dice;
|
||||
use Friendica\DI;
|
||||
use Friendica\Network\HTTPClient;
|
||||
use Friendica\Factory\HTTPClientFactory;
|
||||
use Friendica\Network\IHTTPClient;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\HandlerStack;
|
||||
use mattwright\URLResolver;
|
||||
|
||||
/**
|
||||
* This class mocks some DICE dependencies because they're not direct usable for test environments
|
||||
* (Like fetching data from external endpoints)
|
||||
* This class injects a mockable handler into the IHTTPClient dependency per Dice
|
||||
*/
|
||||
trait DiceTestTrait
|
||||
trait DiceHttpMockHandlerTrait
|
||||
{
|
||||
/**
|
||||
* Handler for mocking requests anywhere for testing purpose
|
||||
*
|
||||
* @var HandlerStack
|
||||
*/
|
||||
protected static $httpRequestHandler;
|
||||
protected $httpRequestHandler;
|
||||
|
||||
protected static function setUpDice(): void
|
||||
protected function setupHttpMockHandler(): void
|
||||
{
|
||||
if (!empty(self::$httpRequestHandler) && self::$httpRequestHandler instanceof HandlerStack) {
|
||||
if (!empty($this->httpRequestHandler) && $this->httpRequestHandler instanceof HandlerStack) {
|
||||
return;
|
||||
}
|
||||
|
||||
self::$httpRequestHandler = HandlerStack::create();
|
||||
$this->httpRequestHandler = HandlerStack::create();
|
||||
|
||||
$client = new Client(['handler' => self::$httpRequestHandler]);
|
||||
$dice = DI::getDice();
|
||||
// addRule() clones the current instance and returns a new one, so no concurrency problems :-)
|
||||
$newDice = $dice->addRule(IHTTPClient::class, [
|
||||
'instanceOf' => HTTPClientFactory::class,
|
||||
'call' => [
|
||||
['createClient', [$this->httpRequestHandler], Dice::CHAIN_CALL],
|
||||
],
|
||||
]);
|
||||
|
||||
$resolver = \Mockery::mock(URLResolver::class);
|
||||
|
||||
$httpClient = new HTTPClient(DI::logger(), DI::profiler(), $client, $resolver);
|
||||
|
||||
$dice = DI::getDice();
|
||||
$newDice = \Mockery::mock($dice)->makePartial();
|
||||
$newDice->shouldReceive('create')->with(IHTTPClient::class)->andReturn($httpClient);
|
||||
DI::init($newDice);
|
||||
}
|
||||
|
||||
protected function tearDown() : void
|
||||
protected function tearDown(): void
|
||||
{
|
||||
\Mockery::close();
|
||||
|
|
@ -3,10 +3,21 @@
|
|||
namespace Friendica\Test\src\Network;
|
||||
|
||||
use Friendica\Network\Probe;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Friendica\Test\DiceHttpMockHandlerTrait;
|
||||
use Friendica\Test\FixtureTest;
|
||||
use GuzzleHttp\Middleware;
|
||||
|
||||
class ProbeTest extends TestCase
|
||||
class ProbeTest extends FixtureTest
|
||||
{
|
||||
use DiceHttpMockHandlerTrait;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->setupHttpMockHandler();
|
||||
}
|
||||
|
||||
const TEMPLATENOBASE = '
|
||||
<!DOCTYPE html>
|
||||
<html lang="en-us">
|
||||
|
@ -105,4 +116,122 @@ class ProbeTest extends TestCase
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function dataUri()
|
||||
{
|
||||
return [
|
||||
'@-first' => [
|
||||
'uri' => '@Artists4Future_Muenchen@climatejustice.global',
|
||||
'assertUri' => 'Artists4Future_Muenchen@climatejustice.global',
|
||||
'assertInfos' => [
|
||||
'name' => 'Artists4Future München',
|
||||
'nick' => 'Artists4Future_Muenchen',
|
||||
'url' => 'https://climatejustice.global/users/Artists4Future_Muenchen',
|
||||
'alias' => 'https://climatejustice.global/@Artists4Future_Muenchen',
|
||||
'photo' => 'https://cdn.masto.host/climatejusticeglobal/accounts/avatars/000/021/220/original/05ee9e827a5b47fc.jpg',
|
||||
'header' => 'https://cdn.masto.host/climatejusticeglobal/accounts/headers/000/021/220/original/9b98b75cf696cd11.jpg',
|
||||
'account-type' => 0,
|
||||
'about' => 'Wir sind Künstler oder einfach gerne kreativ tätig und setzen uns unabhängig von politischen Parteien für den Klimaschutz ein. Die Bedingungen zu schaffen, die die [url=https://climatejustice.global/tags/Klimakrise]#Klimakrise[/url] verhindern/eindämmen (gemäß den Forderungen der [url=https://climatejustice.global/tags/Fridays4Future]#Fridays4Future[/url]) ist Aufgabe der Politik, muss aber gesamtgesellschaftlich getragen werden. Mit unseren künstlerischen Aktionen wollen wir einen anderen Zugang anbieten für wissenschaftlich rationale Argumente, speziell zur Erderwärmung und ihre Konsequenzen.',
|
||||
'hide' => 0,
|
||||
'batch' => 'https://climatejustice.global/inbox',
|
||||
'notify' => 'https://climatejustice.global/users/Artists4Future_Muenchen/inbox',
|
||||
'poll' => 'https://climatejustice.global/users/Artists4Future_Muenchen/outbox',
|
||||
'subscribe' => 'https://climatejustice.global/authorize_interaction?uri={uri}',
|
||||
'following' => 'https://climatejustice.global/users/Artists4Future_Muenchen/following',
|
||||
'followers' => 'https://climatejustice.global/users/Artists4Future_Muenchen/followers',
|
||||
'inbox' => 'https://climatejustice.global/users/Artists4Future_Muenchen/inbox',
|
||||
'outbox' => 'https://climatejustice.global/users/Artists4Future_Muenchen/outbox',
|
||||
'sharedinbox' => 'https://climatejustice.global/inbox',
|
||||
'priority' => 0,
|
||||
'network' => 'apub',
|
||||
'pubkey' => '-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6pYKPuDKb+rmBB869uPV
|
||||
uLYFPosGxMUfenWqfWmFKzEqJ87rAft0IQDAL6dCoYE55ov/lEDNROhasTZLirZf
|
||||
M5b7/1JmwMrAfEiaciuYqDWT3/yDpnekOIdzP5iSClg4zt7e6HRFuClqo4+b6hIE
|
||||
DTMV4ksItvq/92MIu62pZ2SZr5ADPPZ/914lJ86hIH5BanbE8ZFzDS9vJA7V74rt
|
||||
Vvkr5c/OiUyuODNYApSl87Ez8cuj8Edt89YWkDCajQn3EkmXGeJY/VRjEDfcyk6r
|
||||
AvdUa0ArjXud3y3NkakVFZ0d7tmB20Vn9s/CfYHU8FXzbI1kFkov2BX899VVP5Ay
|
||||
xQIDAQAB
|
||||
-----END PUBLIC KEY-----',
|
||||
'manually-approve' => 0,
|
||||
'baseurl' => 'https://climatejustice.global',
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataUri
|
||||
*/
|
||||
public function testCleanUri(string $uri, string $assertUri, array $assertInfos)
|
||||
{
|
||||
self::markTestIncomplete('hard work due mocking 19 different http-requests');
|
||||
|
||||
/**
|
||||
* Requests:
|
||||
*
|
||||
* GET : https://climatejustice.global/.well-known/webfinger?resource=acct:Artists4Future_Muenchen%40climatejustice.global
|
||||
* 200
|
||||
* GET : http://localhost/.well-known/nodeinfo
|
||||
* 200
|
||||
* GET : http://localhost/statistics.json
|
||||
* 404
|
||||
* GET : http://localhost
|
||||
* 200
|
||||
* GET : http://localhost/friendica/json
|
||||
* 404
|
||||
* GET : http://localhost/friendika/json
|
||||
* 404
|
||||
* GET : http://localhost/poco
|
||||
* 403
|
||||
* GET : http://localhost/api/v1/directory?limit=1
|
||||
* 200
|
||||
* GET : http://localhost/.well-known/x-social-relay
|
||||
* 200
|
||||
* GET : http://localhost/friendica
|
||||
* 404
|
||||
* GET : https://climatejustice.global/users/Artists4Future_Muenchen
|
||||
* 200
|
||||
* GET : https://climatejustice.global/users/Artists4Future_Muenchen/following
|
||||
* 200
|
||||
* GET : https://climatejustice.global/users/Artists4Future_Muenchen/followers
|
||||
* 200
|
||||
* GET : https://climatejustice.global/users/Artists4Future_Muenchen/outbox
|
||||
* 200
|
||||
* GET : https://climatejustice.global/.well-known/nodeinfo
|
||||
* 200
|
||||
* GET : https://climatejustice.global/nodeinfo/2.0
|
||||
* 200
|
||||
* GET : https://climatejustice.global/poco
|
||||
* 404
|
||||
* GET : https://climatejustice.global/api/v1/directory?limit=1
|
||||
* 200
|
||||
* GET : https://climatejustice.global/.well-known/webfinger?resource=acct%3AArtists4Future_Muenchen%40climatejustice.global
|
||||
* 200
|
||||
*
|
||||
*/
|
||||
|
||||
$container = [];
|
||||
$history = Middleware::history($container);
|
||||
|
||||
$this->httpRequestHandler->push($history);
|
||||
|
||||
$cleaned = Probe::cleanURI($uri);
|
||||
self::assertEquals($assertUri, $cleaned);
|
||||
self::assertArraySubset($assertInfos, Probe::uri($cleaned, '', 0));
|
||||
|
||||
|
||||
// Iterate over the requests and responses
|
||||
foreach ($container as $transaction) {
|
||||
echo $transaction['request']->getMethod() . " : " . $transaction['request']->getUri() . PHP_EOL;
|
||||
//> GET, HEAD
|
||||
if ($transaction['response']) {
|
||||
echo $transaction['response']->getStatusCode() . PHP_EOL;
|
||||
//> 200, 200
|
||||
} elseif ($transaction['error']) {
|
||||
echo $transaction['error'];
|
||||
//> exception
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace Friendica\Test\src\Util;
|
||||
|
||||
use Friendica\Test\DiceTestTrait;
|
||||
use Friendica\Test\DiceHttpMockHandlerTrait;
|
||||
use Friendica\Test\MockedTest;
|
||||
use Friendica\Util\Images;
|
||||
use GuzzleHttp\Handler\MockHandler;
|
||||
|
@ -10,13 +10,13 @@ use GuzzleHttp\Psr7\Response;
|
|||
|
||||
class ImagesTest extends MockedTest
|
||||
{
|
||||
use DiceTestTrait;
|
||||
use DiceHttpMockHandlerTrait;
|
||||
|
||||
public static function setUpBeforeClass(): void
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUpBeforeClass();
|
||||
parent::setUp();
|
||||
|
||||
self::setUpDice();
|
||||
$this->setupHttpMockHandler();
|
||||
}
|
||||
|
||||
public function dataImages()
|
||||
|
@ -56,13 +56,13 @@ class ImagesTest extends MockedTest
|
|||
}
|
||||
|
||||
/**
|
||||
* Test the Images::getInfoFromURL() method
|
||||
* Test the Images::getInfoFromURL() method (only remote images, not local/relative!)
|
||||
*
|
||||
* @dataProvider dataImages
|
||||
*/
|
||||
public function testGetInfoFromURL(string $url, array $headers, string $data, array $assertion)
|
||||
public function testGetInfoFromRemotURL(string $url, array $headers, string $data, array $assertion)
|
||||
{
|
||||
self::$httpRequestHandler->setHandler(new MockHandler([
|
||||
$this->httpRequestHandler->setHandler(new MockHandler([
|
||||
new Response(200, $headers, $data),
|
||||
]));
|
||||
|
||||
|
|
Loading…
Reference in a new issue