mailgun-php/tests/Api/TestCase.php
David Garcia 66fd858a02
PHP 8.x support (#727)
* Set dependencies for 7.3 and 8.x

* Set GitHub Actions for PHP 7.3, 7.4 and 8.0

* Set Ubuntu version that supports PHP from 7.1 to 7.4

According to warnings raised by GitHub Actions, the alias for the latest
Ubuntu version will upgrade soon to the newer 20.04 LTS instead of 18.04.

Aiming to ensure the compatibility with previous PHP versions, it's safer
to force the Ubuntu 18.04 that has the previous PHP version as built-in
versions in the OS

https://github.com/marketplace/actions/setup-php-action#github-hosted-runners

* Fix dependencies for PHP ^7.3 and ^8.0 support

* Run test suite with PHP versions from 7.3 to 8.1

* Broken Prophecy dependency for PHPUnit on PHP 8.1

This broken dependency doesn't allow us to run PHPUnit tests and ensure it works. Keeping the ^8.0 version should allow installations for non-maintainers on newer versions too.

https://packagist.org/packages/phpspec/prophecy#1.12.2

requires
- php: ^7.2 || ~8.0, <8.1
- ...

* Use the latest Ubuntu version instead of a specific version

* Prepare Changelog for PHP 8.0
2021-01-30 07:39:30 +01:00

257 lines
7.3 KiB
PHP

<?php
declare(strict_types=1);
/*
* Copyright (C) 2013 Mailgun
*
* This software may be modified and distributed under the terms
* of the MIT license. See the LICENSE file for details.
*/
namespace Mailgun\Tests\Api;
use GuzzleHttp\Psr7\Request;
use GuzzleHttp\Psr7\Response;
use Mailgun\Hydrator\ModelHydrator;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\ResponseInterface;
/**
* @author Tobias Nyholm <tobias.nyholm@gmail.com>
* @author Contributors of https://github.com/KnpLabs/php-github-api
*/
abstract class TestCase extends \PHPUnit\Framework\TestCase
{
private $requestMethod;
private $requestUri;
private $requestHeaders = [];
private $requestBody;
private $httpResponse;
private $hydratedResponse;
private $hydrateClass;
protected function setUp(): void
{
$this->reset();
}
abstract protected function getApiClass();
/**
* This will give you a mocked API. Optionally you can provide mocked dependencies.
*/
protected function getApiMock($httpClient = null, $requestClient = null, $hydrator = null)
{
if (null === $httpClient) {
$httpClient = $this->getMockBuilder(ClientInterface::class)
->setMethods(['sendRequest'])
->getMock();
$httpClient
->expects($this->any())
->method('sendRequest');
}
if (null === $requestClient) {
$requestClient = $this->getMockBuilder('Mailgun\HttpClient\RequestBuilder')
->setMethods(['create'])
->getMock();
}
if (null === $hydrator) {
$hydrator = $this->getMockBuilder('Mailgun\Hydrator\Hydrator')
->setMethods(['hydrate'])
->getMock();
}
return $this->getMockBuilder($this->getApiClass())
->setMethods(['httpGet', 'httpPost', 'httpPostRaw', 'httpDelete', 'httpPut'])
->setConstructorArgs([$httpClient, $requestClient, $hydrator])
->getMock();
}
/**
* This will return you a real API instance with mocked dependencies.
* This will make use of the "setHydratedResponse" and "setRequestMethod" etc..
*/
protected function getApiInstance($apiKey = null)
{
$httpClient = $this->getMockBuilder(ClientInterface::class)
->setMethods(['sendRequest'])
->getMock();
$httpClient
->method('sendRequest')
->willReturn(null === $this->httpResponse ? new Response() : $this->httpResponse);
$requestClient = $this->getMockBuilder('Mailgun\HttpClient\RequestBuilder')
->setMethods(['create'])
->getMock();
if (null !== $this->requestMethod
|| null !== $this->requestUri
|| !empty($this->requestHeaders)
|| !empty($this->requestBody)
) {
$requestClient
->expects($this->once())
->method('create')
->with(
$this->callback([$this, 'validateRequestMethod']),
$this->callback([$this, 'validateRequestUri']),
$this->callback([$this, 'validateRequestHeaders']),
$this->callback([$this, 'validateRequestBody'])
)
->willReturn(new Request('GET', '/'));
}
$hydrator = new ModelHydrator();
if (null === $this->httpResponse) {
$hydrator = $this->getMockBuilder('Mailgun\Hydrator\Hydrator')
->setMethods(['hydrate'])
->getMock();
$hydratorModelClass = $this->hydrateClass;
$hydrateMethod = $hydrator->method('hydrate')
->with(
$this->callback(function ($response) {
return $response instanceof ResponseInterface;
}),
$this->callback(function ($class) use ($hydratorModelClass) {
return null === $hydratorModelClass || $class === $hydratorModelClass;
}));
if (null !== $this->hydratedResponse) {
$hydrateMethod->willReturn($this->hydratedResponse);
}
}
$class = $this->getApiClass();
if (null !== $apiKey) {
return new $class($httpClient, $requestClient, $hydrator, $apiKey);
}
return new $class($httpClient, $requestClient, $hydrator);
}
public function validateRequestMethod($method)
{
return $this->verifyProperty($this->requestMethod, $method);
}
public function validateRequestUri($uri)
{
return $this->verifyProperty($this->requestUri, $uri);
}
public function validateRequestHeaders($headers)
{
return $this->verifyProperty($this->requestHeaders, $headers);
}
public function validateRequestBody($body)
{
if ($this->verifyProperty($this->requestBody, $body)) {
return true;
}
// Assert: $body is prepared for a "multipart stream".
// Check length
if (count($this->requestBody) !== count($body)) {
return false;
}
// Check every item in body.
foreach ($body as $item) {
if ('resource' === $this->requestBody[$item['name']] && is_resource($item['content'])) {
continue;
}
if ($this->requestBody[$item['name']] !== $item['content']) {
return false;
}
}
return true;
}
protected function reset()
{
$this->httpResponse = null;
$this->hydratedResponse = null;
$this->requestMethod = null;
$this->requestUri = null;
$this->requestHeaders = null;
$this->requestBody = null;
$this->hydrateClass = null;
}
/**
* Set a response that you want to client to respond with.
*/
public function setHttpResponse(ResponseInterface $httpResponse)
{
$this->httpResponse = $httpResponse;
}
/**
* The data you want the hydrator to return.
*/
public function setHydratedResponse($hydratedResponse)
{
$this->hydratedResponse = $hydratedResponse;
}
/**
* Set request http method.
*/
public function setRequestMethod(string $httpMethod)
{
$this->requestMethod = $httpMethod;
}
public function setRequestUri(string $requestUri)
{
$this->requestUri = $requestUri;
}
public function setRequestHeaders(array $requestHeaders)
{
$this->requestHeaders = $requestHeaders;
}
public function setRequestBody($requestBody)
{
$this->requestBody = $requestBody;
}
/**
* The class we should hydrate to.
*
* @param string $hydrateClass
*/
public function setHydrateClass($hydrateClass)
{
$this->hydrateClass = $hydrateClass;
}
/**
* @param mixed|callable $property Example $this->requestMethod
* @param mixed $value the actual value from the user
*
* @return bool
*/
private function verifyProperty($property, $value)
{
if (null === $property) {
return true;
}
return is_callable($property) ? call_user_func($property, $value) : $value === $property;
}
}