1
0
mirror of synced 2024-11-27 15:56:06 +03:00
api-client-php/tests/utils/TestCase/AbstractApiResourceGroupTestCase.php
2023-02-27 16:08:34 +03:00

333 lines
9.5 KiB
PHP

<?php
/**
* PHP version 7.3
*
* @category AbstractApiResourceGroupTestCase
* @package RetailCrm\TestUtils\TestCase
*/
namespace RetailCrm\TestUtils\TestCase;
use Closure;
use DateTime;
use Http\Discovery\Psr17FactoryDiscovery;
use InvalidArgumentException;
use Liip\Serializer\SerializerInterface;
use PHPUnit\Framework\TestCase;
use RetailCrm\TestUtils\PockBuilder;
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamFactoryInterface;
use RetailCrm\Api\Builder\FormEncoderBuilder;
use RetailCrm\Api\Component\Utils;
use RetailCrm\Api\Factory\SerializerFactory;
use RetailCrm\Api\Interfaces\FormEncoderInterface;
use RetailCrm\Api\Interfaces\RequestInterface as RetailCrmRequestInterface;
use RetailCrm\Api\Interfaces\ResponseInterface as RetailCrmResponseInterface;
use RetailCrm\TestUtils\TestConfig;
use RuntimeException;
/**
* Class AbstractApiResourceGroupTestCase
*
* @category AbstractApiResourceGroupTestCase
* @package RetailCrm\TestUtils\TestCase
*/
abstract class AbstractApiResourceGroupTestCase extends TestCase
{
/** @var SerializerInterface */
protected static $serializer;
/** @var \RetailCrm\Api\Interfaces\FormEncoderInterface */
protected static $formEncoder;
/** @var ResponseFactoryInterface */
protected static $responseFactory;
/** @var StreamFactoryInterface */
protected static $streamFactory;
/**
* @param string $pathFragment
*
* @return \RetailCrm\TestUtils\PockBuilder
*/
protected static function createApiMockBuilder(string $pathFragment): PockBuilder
{
$testDataPath = parse_url(TestConfig::getApiUrl(), PHP_URL_PATH);
return (new PockBuilder())
->matchScheme((string) parse_url(TestConfig::getApiUrl(), PHP_URL_SCHEME))
->matchHost((string) parse_url(TestConfig::getApiUrl(), PHP_URL_HOST))
->matchHeader('X-Api-Key', TestConfig::getApiKey())
->matchPath(
(empty($testDataPath) || '/' === $testDataPath)
? '/api/v5/' . $pathFragment
: trim($testDataPath, '/') . '/' . $pathFragment
);
}
/**
* @param int $code
* @param object|mixed[]|string $response
*
* @return \Psr\Http\Message\ResponseInterface
* @throws InvalidArgumentException
*/
protected static function responseJson(int $code, $response): ResponseInterface
{
$data = null;
switch (gettype($response)) {
case 'string':
$data = static::getStreamFactory()->createStream((string) $response);
break;
case 'array':
case 'object':
$data = static::getStreamFactory()->createStream(static::getSerializer()->serialize($response, 'json'));
break;
default:
throw new InvalidArgumentException(sprintf(
'Expected string, object, or array, got "%s"',
gettype($response)
));
}
return static::getResponseFactory()->createResponse($code)
->withHeader('Content-Type', 'application/json')
->withBody($data);
}
/**
* @param string $path
* @param bool $header
*
* @return \RetailCrm\TestUtils\PockBuilder
*/
protected static function createUnversionedApiMockBuilder(string $path = '', bool $header = true): PockBuilder
{
$testDataPath = parse_url(TestConfig::getApiUrl(), PHP_URL_PATH);
$builder = (new PockBuilder())
->matchScheme((string) parse_url(TestConfig::getApiUrl(), PHP_URL_SCHEME))
->matchHost((string) parse_url(TestConfig::getApiUrl(), PHP_URL_HOST))
->matchPath(
(empty($testDataPath) || '/' === $testDataPath)
? '/api/' . $path
: trim(Utils::removeVersionFromUri($testDataPath), '/') . '/' . $path
);
if ($header) {
$builder->matchHeader('X-Api-Key', TestConfig::getApiKey());
} else {
$builder->matchQuery(['apiKey' => TestConfig::getApiKey()]);
}
return $builder;
}
/**
* @param \RetailCrm\Api\Interfaces\RequestInterface $request
*
* @return string
* @throws \ReflectionException
*/
public static function encodeForm(RetailCrmRequestInterface $request): string
{
return static::getFormEncoder()->encode($request);
}
/**
* @param \RetailCrm\Api\Interfaces\RequestInterface $request
*
* @return mixed[]
* @throws \ReflectionException
*/
public static function encodeFormArray(RetailCrmRequestInterface $request): array
{
return static::clearArray(static::getFormEncoder()->encodeArray($request));
}
/**
* @param mixed $value
*
* @return string
*/
public static function serialize($value): string
{
return static::getSerializer()->serialize($value, 'json');
}
/**
* @param mixed $value
*
* @return mixed[]
*/
public static function serializeArray($value): array
{
return static::getSerializer()->toArray($value);
}
/**
* Removes all empty fields from arrays, works for nested arrays
*
* @param mixed[] $arr
*
* @return mixed
*/
public static function clearArray(array $arr)
{
if (!is_array($arr)) {
return $arr;
}
$result = [];
foreach ($arr as $index => $node) {
if (null === $node) {
continue;
}
$result[$index] = is_array($node) === true ? static::clearArray($node) : trim($node);
if (
'' === $result[$index] ||
(is_array($result[$index]) && count($result[$index]) < 1)
) {
unset($result[$index]);
}
}
return $result;
}
/**
* @param string $expectedJson
* @param \RetailCrm\Api\Interfaces\ResponseInterface $response
* @param bool $stripNilValues
*
* @throws \JsonException
*/
protected static function assertModelEqualsToResponse(
string $expectedJson,
RetailCrmResponseInterface $response,
bool $stripNilValues = false
): void {
$expected = json_decode($expectedJson, true, 512, JSON_THROW_ON_ERROR);
$actual = self::getSerializer()->toArray($response);
if ($stripNilValues) {
$expected = static::clearArray($expected);
$actual = static::clearArray($actual);
}
self::assertEquals($expected, $actual);
}
/**
* @param string $expectedJson
* @param \RetailCrm\Api\Interfaces\ResponseInterface $response
* @param \Closure $callback
*
* @throws \JsonException
*/
protected static function assertModelsCallback(
string $expectedJson,
RetailCrmResponseInterface $response,
Closure $callback
): void {
$expected = json_decode($expectedJson, true, 512, JSON_THROW_ON_ERROR);
$actual = self::getSerializer()->toArray($response);
$callback($expected, $actual);
}
/**
* @param string $text
*
* @return string
*/
private static function addTrailingSlash(string $text): string
{
if ('' === $text) {
return '';
}
if ('/' !== $text[strlen($text) - 1]) {
return $text . '/';
}
return $text;
}
/**
* @return \Psr\Http\Message\StreamFactoryInterface
*/
protected static function getStreamFactory(): StreamFactoryInterface
{
if (null === static::$streamFactory) {
static::$streamFactory = Psr17FactoryDiscovery::findStreamFactory();
}
return static::$streamFactory;
}
/**
* @return \Psr\Http\Message\ResponseFactoryInterface
*/
protected static function getResponseFactory(): ResponseFactoryInterface
{
if (null === static::$responseFactory) {
static::$responseFactory = Psr17FactoryDiscovery::findResponseFactory();
}
return static::$responseFactory;
}
/**
* @return \Liip\Serializer\SerializerInterface
*/
protected static function getSerializer(): SerializerInterface
{
if (null === static::$serializer) {
static::$serializer = SerializerFactory::create();
}
return static::$serializer;
}
/**
* @param string $format
* @param string $dateTime
*
* @return \DateTime
*/
protected static function dateTimeFromFormat(string $format, string $dateTime): DateTime
{
$result = DateTime::createFromFormat($format, $dateTime);
if (!($result instanceof DateTime)) {
throw new RuntimeException(sprintf(
'Cannot create DateTime with data "%s" with format "%s"',
$format,
$dateTime
));
}
return $result;
}
/**
* @return \RetailCrm\Api\Interfaces\FormEncoderInterface
* @throws \RetailCrm\Api\Exception\BuilderException
*/
private static function getFormEncoder(): FormEncoderInterface
{
if (null === static::$formEncoder) {
static::$formEncoder = (new FormEncoderBuilder())->build();
}
return static::$formEncoder;
}
}