mirror of
https://github.com/Neur0toxine/pock.git
synced 2024-12-01 01:16:07 +03:00
matchers, symfony serializer support, more tests and fixes
This commit is contained in:
parent
25654d921f
commit
c85693cbcd
@ -37,7 +37,8 @@
|
||||
"jms/serializer": "^2 | ^3.12",
|
||||
"symfony/phpunit-bridge": "^5.2",
|
||||
"symfony/var-dumper": "^5.2",
|
||||
"symfony/serializer": "^5.2"
|
||||
"symfony/serializer": "^5.2",
|
||||
"symfony/property-access": "^5.2"
|
||||
},
|
||||
"provide": {
|
||||
"psr/http-client-implementation": "1.0",
|
||||
|
@ -1,13 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="vendor/squizlabs/php_codesniffer/phpcs.xsd">
|
||||
<arg name="basepath" value="."/>
|
||||
<arg name="cache" value=".php_cs.cache"/>
|
||||
<arg name="colors"/>
|
||||
<arg name="extensions" value="php"/>
|
||||
|
||||
<rule ref="PSR12"/>
|
||||
<ruleset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" name="pock ruleset" xsi:noNamespaceSchemaLocation="vendor/squizlabs/php_codesniffer/phpcs.xsd">
|
||||
<description>Ruleset for pock</description>
|
||||
|
||||
<file>src/</file>
|
||||
<file>tests/</file>
|
||||
|
||||
<arg name="basepath" value="."/>
|
||||
<arg name="colors"/>
|
||||
<arg name="cache" pattern=".php_cs.cache"/>
|
||||
|
||||
<rule ref="PSR12"/>
|
||||
</ruleset>
|
||||
|
70
src/Creator/AbstractSymfonySerializerCreator.php
Normal file
70
src/Creator/AbstractSymfonySerializerCreator.php
Normal file
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category AbstractSymfonySerializerCreator
|
||||
* @package Pock\Creator
|
||||
*/
|
||||
|
||||
namespace Pock\Creator;
|
||||
|
||||
use Pock\Serializer\SerializerInterface;
|
||||
use Pock\Serializer\SymfonySerializerDecorator;
|
||||
|
||||
/**
|
||||
* Class AbstractSymfonySerializerCreator
|
||||
*
|
||||
* @category AbstractSymfonySerializerCreator
|
||||
* @package Pock\Creator
|
||||
*/
|
||||
abstract class AbstractSymfonySerializerCreator implements SerializerCreatorInterface
|
||||
{
|
||||
private const OBJECT_NORMALIZER_CLASS = '\Symfony\Component\Serializer\Normalizer\ObjectNormalizer';
|
||||
private const SERIALIZER_CLASS = '\Symfony\Component\Serializer\Serializer';
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public static function create(): ?SerializerInterface
|
||||
{
|
||||
if (self::isAvailable()) {
|
||||
$serializer = self::SERIALIZER_CLASS;
|
||||
$normalizer = self::OBJECT_NORMALIZER_CLASS;
|
||||
$encoder = static::getEncoderClass();
|
||||
|
||||
return new SymfonySerializerDecorator(
|
||||
new $serializer([new $normalizer()], [new $encoder()]),
|
||||
static::getFormat()
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if serializer can be instantiated.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function isAvailable(): bool
|
||||
{
|
||||
return class_exists(self::SERIALIZER_CLASS) &&
|
||||
class_exists(self::OBJECT_NORMALIZER_CLASS) &&
|
||||
class_exists(static::getEncoderClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns format for the serializer;
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected static function getFormat(): string;
|
||||
|
||||
/**
|
||||
* Returns format for the serializer;
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
abstract protected static function getEncoderClass(): string;
|
||||
}
|
35
src/Creator/SymfonyJsonSerializerCreator.php
Normal file
35
src/Creator/SymfonyJsonSerializerCreator.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category SymfonyJsonSerializerCreator
|
||||
* @package Pock\Creator
|
||||
*/
|
||||
|
||||
namespace Pock\Creator;
|
||||
|
||||
/**
|
||||
* Class SymfonyJsonSerializerCreator
|
||||
*
|
||||
* @category SymfonyJsonSerializerCreator
|
||||
* @package Pock\Creator
|
||||
*/
|
||||
class SymfonyJsonSerializerCreator extends AbstractSymfonySerializerCreator
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected static function getFormat(): string
|
||||
{
|
||||
return 'json';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected static function getEncoderClass(): string
|
||||
{
|
||||
return '\Symfony\Component\Serializer\Encoder\JsonEncoder';
|
||||
}
|
||||
}
|
35
src/Creator/SymfonyXmlSerializerCreator.php
Normal file
35
src/Creator/SymfonyXmlSerializerCreator.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category SymfonyXmlSerializerCreator
|
||||
* @package Pock\Creator
|
||||
*/
|
||||
|
||||
namespace Pock\Creator;
|
||||
|
||||
/**
|
||||
* Class SymfonyXmlSerializerCreator
|
||||
*
|
||||
* @category SymfonyXmlSerializerCreator
|
||||
* @package Pock\Creator
|
||||
*/
|
||||
class SymfonyXmlSerializerCreator extends AbstractSymfonySerializerCreator
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected static function getFormat(): string
|
||||
{
|
||||
return 'xml';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected static function getEncoderClass(): string
|
||||
{
|
||||
return '\Symfony\Component\Serializer\Encoder\XmlEncoder';
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.3
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category JsonException
|
||||
* @package Pock\Exception
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.3
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category XmlException
|
||||
* @package Pock\Exception
|
||||
|
@ -10,6 +10,7 @@
|
||||
namespace Pock\Factory;
|
||||
|
||||
use Pock\Creator\JmsJsonSerializerCreator;
|
||||
use Pock\Creator\SymfonyJsonSerializerCreator;
|
||||
use Pock\Serializer\SerializerInterface;
|
||||
|
||||
/**
|
||||
@ -30,6 +31,7 @@ class JsonSerializerFactory extends AbstractSerializerFactory
|
||||
{
|
||||
return [
|
||||
JmsJsonSerializerCreator::class,
|
||||
SymfonyJsonSerializerCreator::class
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,7 @@
|
||||
namespace Pock\Factory;
|
||||
|
||||
use Pock\Creator\JmsXmlSerializerCreator;
|
||||
use Pock\Creator\SymfonyXmlSerializerCreator;
|
||||
use Pock\Serializer\SerializerInterface;
|
||||
|
||||
/**
|
||||
@ -29,7 +30,8 @@ class XmlSerializerFactory extends AbstractSerializerFactory
|
||||
protected static function getCreators(): array
|
||||
{
|
||||
return [
|
||||
JmsXmlSerializerCreator::class
|
||||
JmsXmlSerializerCreator::class,
|
||||
SymfonyXmlSerializerCreator::class
|
||||
];
|
||||
}
|
||||
|
||||
|
120
src/Matchers/AbstractArrayPoweredComponent.php
Normal file
120
src/Matchers/AbstractArrayPoweredComponent.php
Normal file
@ -0,0 +1,120 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category AbstractArrayPoweredComponent
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Matchers;
|
||||
|
||||
/**
|
||||
* Class AbstractArrayPoweredComponent
|
||||
*
|
||||
* @category AbstractArrayPoweredComponent
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
abstract class AbstractArrayPoweredComponent
|
||||
{
|
||||
/**
|
||||
* Returns true if both arrays are equal recursively.
|
||||
*
|
||||
* @phpstan-ignore-next-line
|
||||
* @param array $first
|
||||
* @phpstan-ignore-next-line
|
||||
* @param array $second
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected static function recursiveCompareArrays(array $first, array $second): bool
|
||||
{
|
||||
if (count($first) !== count($second)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!empty(array_diff(array_keys($first), array_keys($second)))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($first as $key => $value) {
|
||||
if (is_array($value) && !self::recursiveCompareArrays($value, $second[$key])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($value !== $second[$key]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if two one-dimensional string arrays are equal.
|
||||
*
|
||||
* @phpstan-ignore-next-line
|
||||
* @param array $first
|
||||
* @phpstan-ignore-next-line
|
||||
* @param array $second
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected static function compareStringArrays(array $first, array $second): bool
|
||||
{
|
||||
return count($first) === count($second) &&
|
||||
array_diff($first, $second) === array_diff($second, $first);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if all needle values is present in haystack.
|
||||
* Doesn't work for multidimensional arrays.
|
||||
*
|
||||
* @phpstan-ignore-next-line
|
||||
* @param array $needle
|
||||
* @phpstan-ignore-next-line
|
||||
* @param array $haystack
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected static function isNeedlePresentInHaystack(array $needle, array $haystack): bool
|
||||
{
|
||||
foreach ($needle as $value) {
|
||||
if (!in_array($value, $haystack, true)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if all needle values is present in haystack.
|
||||
* Works for multidimensional arrays. Internal arrays will be treated as values (e.g. will be compared recursively).
|
||||
*
|
||||
* @phpstan-ignore-next-line
|
||||
* @param array $needle
|
||||
* @phpstan-ignore-next-line
|
||||
* @param array $haystack
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected static function recursiveNeedlePresentInHaystack(array $needle, array $haystack): bool
|
||||
{
|
||||
if (!empty(array_diff(array_keys($needle), array_keys($haystack)))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($needle as $key => $value) {
|
||||
if (is_array($value) && !self::recursiveCompareArrays($value, $haystack[$key])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ($value !== $haystack[$key]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
69
src/Matchers/AbstractSerializedBodyMatcher.php
Normal file
69
src/Matchers/AbstractSerializedBodyMatcher.php
Normal file
@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category AbstractSerializedBodyMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Matchers;
|
||||
|
||||
use Pock\Traits\SeekableStreamDataExtractor;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Class AbstractSerializedBodyMatcher
|
||||
*
|
||||
* @category AbstractSerializedBodyMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
abstract class AbstractSerializedBodyMatcher extends AbstractArrayPoweredComponent implements RequestMatcherInterface
|
||||
{
|
||||
use SeekableStreamDataExtractor;
|
||||
|
||||
/** @var array */
|
||||
private $data; // @phpstan-ignore-line
|
||||
|
||||
/**
|
||||
* AbstractSerializedBodyMatcher constructor.
|
||||
*
|
||||
* @phpstan-ignore-next-line
|
||||
*
|
||||
* @param array $data
|
||||
*/
|
||||
public function __construct(array $data)
|
||||
{
|
||||
$this->data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function matches(RequestInterface $request): bool
|
||||
{
|
||||
$body = static::getStreamData($request->getBody());
|
||||
|
||||
if ('' === $body) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$bodyData = $this->deserialize($body);
|
||||
|
||||
if (null === $bodyData) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return self::recursiveCompareArrays($bodyData, $this->data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array with deserialized data.
|
||||
*
|
||||
* @param string $data
|
||||
*
|
||||
* @phpstan-ignore-next-line
|
||||
* @return array|null
|
||||
*/
|
||||
abstract protected function deserialize(string $data): ?array;
|
||||
}
|
73
src/Matchers/BodyMatcher.php
Normal file
73
src/Matchers/BodyMatcher.php
Normal file
@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category BodyMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Matchers;
|
||||
|
||||
use Pock\Traits\SeekableStreamDataExtractor;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
/**
|
||||
* Class BodyMatcher
|
||||
*
|
||||
* @category BodyMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
class BodyMatcher implements RequestMatcherInterface
|
||||
{
|
||||
use SeekableStreamDataExtractor;
|
||||
|
||||
/** @var string */
|
||||
protected $contents = '';
|
||||
|
||||
/**
|
||||
* BodyMatcher constructor.
|
||||
*
|
||||
* @param \Psr\Http\Message\StreamInterface|resource|string $contents
|
||||
*/
|
||||
public function __construct($contents)
|
||||
{
|
||||
if (is_string($contents)) {
|
||||
$this->contents = $contents;
|
||||
}
|
||||
|
||||
if ($contents instanceof StreamInterface) {
|
||||
$this->contents = static::getStreamData($contents);
|
||||
}
|
||||
|
||||
if (is_resource($contents)) {
|
||||
$this->contents = static::readAllResource($contents);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function matches(RequestInterface $request): bool
|
||||
{
|
||||
if (0 === $request->getBody()->getSize()) {
|
||||
return '' === $this->contents;
|
||||
}
|
||||
|
||||
return static::getStreamData($request->getBody()) === $this->contents;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads entire resource data.
|
||||
*
|
||||
* @param resource $resource
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function readAllResource($resource): string
|
||||
{
|
||||
fseek($resource, 0);
|
||||
return (string) stream_get_contents($resource);
|
||||
}
|
||||
}
|
42
src/Matchers/CallbackRequestMatcher.php
Normal file
42
src/Matchers/CallbackRequestMatcher.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category CallbackRequestMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Matchers;
|
||||
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Class CallbackRequestMatcher
|
||||
*
|
||||
* @category CallbackRequestMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
class CallbackRequestMatcher implements RequestMatcherInterface
|
||||
{
|
||||
/** @var callable */
|
||||
private $callback;
|
||||
|
||||
/**
|
||||
* CallbackRequestMatcher constructor.
|
||||
*
|
||||
* @param callable $callback
|
||||
*/
|
||||
public function __construct(callable $callback)
|
||||
{
|
||||
$this->callback = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function matches(RequestInterface $request): bool
|
||||
{
|
||||
return call_user_func($this->callback, $request);
|
||||
}
|
||||
}
|
33
src/Matchers/ExactHeaderMatcher.php
Normal file
33
src/Matchers/ExactHeaderMatcher.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category ExactHeaderMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Matchers;
|
||||
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Class ExactHeaderMatcher
|
||||
*
|
||||
* @category ExactHeaderMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
class ExactHeaderMatcher extends HeaderMatcher
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function matches(RequestInterface $request): bool
|
||||
{
|
||||
if (!$request->hasHeader($this->header)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return self::compareStringArrays($request->getHeader($this->header), $this->value);
|
||||
}
|
||||
}
|
81
src/Matchers/ExactHeadersMatcher.php
Normal file
81
src/Matchers/ExactHeadersMatcher.php
Normal file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category ExactHeadersMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Matchers;
|
||||
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Class ExactHeadersMatcher
|
||||
*
|
||||
* @category ExactHeadersMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
class ExactHeadersMatcher extends HeadersMatcher
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function matches(RequestInterface $request): bool
|
||||
{
|
||||
$requestHeaders = [];
|
||||
|
||||
foreach ($request->getHeaders() as $header => $value) {
|
||||
$requestHeaders[strtolower($header)] = $value;
|
||||
}
|
||||
|
||||
if (isset($requestHeaders['host']) && !$this->expectHeader('host')) {
|
||||
unset($requestHeaders['host']);
|
||||
}
|
||||
|
||||
if (!static::headerValuesEqual(array_keys($this->headers), array_keys($requestHeaders))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($requestHeaders as $header => $value) {
|
||||
$expectedValue = is_string($this->headers[$header]) ? [$this->headers[$header]] : $this->headers[$header];
|
||||
|
||||
if (!static::headerValuesEqual($value, $expectedValue)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if provided header is expected by the mock.
|
||||
*
|
||||
* @param string $name
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private function expectHeader(string $name): bool
|
||||
{
|
||||
foreach (array_keys($this->headers) as $header) {
|
||||
if (strtolower($header) === strtolower($name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string[] $first
|
||||
* @param string[] $second
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
private static function headerValuesEqual(array $first, array $second): bool
|
||||
{
|
||||
return count($first) === count($second) &&
|
||||
array_diff($first, $second) === array_diff($second, $first);
|
||||
}
|
||||
}
|
35
src/Matchers/ExactQueryMatcher.php
Normal file
35
src/Matchers/ExactQueryMatcher.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category ExactQueryMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Matchers;
|
||||
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Class ExactQueryMatcher
|
||||
*
|
||||
* @category ExactQueryMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
class ExactQueryMatcher extends QueryMatcher
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function matches(RequestInterface $request): bool
|
||||
{
|
||||
$query = static::parseQuery($request->getUri()->getQuery());
|
||||
|
||||
if (empty($query)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return self::recursiveCompareArrays($this->query, $query);
|
||||
}
|
||||
}
|
51
src/Matchers/HeaderLineMatcher.php
Normal file
51
src/Matchers/HeaderLineMatcher.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category HeaderLineMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Matchers;
|
||||
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Class HeaderLineMatcher
|
||||
*
|
||||
* @category HeaderLineMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
class HeaderLineMatcher implements RequestMatcherInterface
|
||||
{
|
||||
/** @var string */
|
||||
private $header;
|
||||
|
||||
/** @var string */
|
||||
private $value;
|
||||
|
||||
/**
|
||||
* HeaderLineMatcher constructor.
|
||||
*
|
||||
* @param string $header
|
||||
* @param string $value
|
||||
*/
|
||||
public function __construct(string $header, string $value)
|
||||
{
|
||||
$this->header = $header;
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function matches(RequestInterface $request): bool
|
||||
{
|
||||
if (!$request->hasHeader($this->header)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $request->getHeaderLine($this->header) === $this->value;
|
||||
}
|
||||
}
|
51
src/Matchers/HeaderLineRegexpMatcher.php
Normal file
51
src/Matchers/HeaderLineRegexpMatcher.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category HeaderLineRegexpMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Matchers;
|
||||
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Class HeaderLineRegexpMatcher
|
||||
*
|
||||
* @category HeaderLineRegexpMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
class HeaderLineRegexpMatcher implements RequestMatcherInterface
|
||||
{
|
||||
/** @var string */
|
||||
private $header;
|
||||
|
||||
/** @var string */
|
||||
private $pattern;
|
||||
|
||||
/**
|
||||
* HeaderLineRegexpMatcher constructor.
|
||||
*
|
||||
* @param string $header
|
||||
* @param string $pattern
|
||||
*/
|
||||
public function __construct(string $header, string $pattern)
|
||||
{
|
||||
$this->header = $header;
|
||||
$this->pattern = $pattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function matches(RequestInterface $request): bool
|
||||
{
|
||||
if (!$request->hasHeader($this->header)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return 1 === preg_match($this->pattern, $request->getHeaderLine($this->header));
|
||||
}
|
||||
}
|
56
src/Matchers/HeaderMatcher.php
Normal file
56
src/Matchers/HeaderMatcher.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category HeaderMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Matchers;
|
||||
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Class HeaderMatcher
|
||||
*
|
||||
* @category HeaderMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
class HeaderMatcher extends AbstractArrayPoweredComponent implements RequestMatcherInterface
|
||||
{
|
||||
/** @var string */
|
||||
protected $header;
|
||||
|
||||
/** @var string[] */
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
* HeaderMatcher constructor.
|
||||
*
|
||||
* @param string $header
|
||||
* @param string|string[] $value
|
||||
*/
|
||||
public function __construct(string $header, $value)
|
||||
{
|
||||
$this->header = $header;
|
||||
|
||||
if (is_string($value)) {
|
||||
$this->value = [$value];
|
||||
} elseif (is_array($value)) {
|
||||
$this->value = $value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function matches(RequestInterface $request): bool
|
||||
{
|
||||
if (!$request->hasHeader($this->header)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return self::isNeedlePresentInHaystack($this->value, $request->getHeader($this->header));
|
||||
}
|
||||
}
|
58
src/Matchers/HeadersMatcher.php
Normal file
58
src/Matchers/HeadersMatcher.php
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category HeadersMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Matchers;
|
||||
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Class HeadersMatcher
|
||||
*
|
||||
* @category HeadersMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
class HeadersMatcher extends AbstractArrayPoweredComponent implements RequestMatcherInterface
|
||||
{
|
||||
/** @var array<string, string|string[]> */
|
||||
protected $headers;
|
||||
|
||||
/**
|
||||
* HeadersMatcher constructor.
|
||||
*
|
||||
* @param array<string, string|string[]> $headers
|
||||
*/
|
||||
public function __construct(array $headers)
|
||||
{
|
||||
$this->headers = $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function matches(RequestInterface $request): bool
|
||||
{
|
||||
foreach (array_keys($this->headers) as $header) {
|
||||
if (!$request->hasHeader($header)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($this->headers as $name => $value) {
|
||||
if (is_string($value)) {
|
||||
$value = [$value];
|
||||
}
|
||||
|
||||
if (!static::isNeedlePresentInHaystack($value, $request->getHeader($name))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
37
src/Matchers/JsonBodyMatcher.php
Normal file
37
src/Matchers/JsonBodyMatcher.php
Normal file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category JsonBodyMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Matchers;
|
||||
|
||||
use Pock\Exception\JsonException;
|
||||
use Pock\Traits\JsonDecoderTrait;
|
||||
|
||||
/**
|
||||
* Class JsonBodyMatcher
|
||||
*
|
||||
* @category JsonBodyMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
class JsonBodyMatcher extends AbstractSerializedBodyMatcher
|
||||
{
|
||||
use JsonDecoderTrait;
|
||||
|
||||
/**
|
||||
* @phpstan-ignore-next-line
|
||||
* @inheritDoc
|
||||
*/
|
||||
protected function deserialize(string $data): ?array
|
||||
{
|
||||
try {
|
||||
return self::jsonDecode($data, true);
|
||||
} catch (JsonException $exception) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.3
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category MethodMatcher
|
||||
* @package Pock\Matchers
|
||||
|
47
src/Matchers/PathMatcher.php
Normal file
47
src/Matchers/PathMatcher.php
Normal file
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category PathMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Matchers;
|
||||
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Class PathMatcher
|
||||
*
|
||||
* @category PathMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
class PathMatcher implements RequestMatcherInterface
|
||||
{
|
||||
/** @var string */
|
||||
private $path;
|
||||
|
||||
/**
|
||||
* PathMatcher constructor.
|
||||
*
|
||||
* @param string $path
|
||||
*/
|
||||
public function __construct(string $path)
|
||||
{
|
||||
if (('' !== $path) && '/' === $path[0]) {
|
||||
$path = substr($path, 1);
|
||||
}
|
||||
|
||||
$this->path = $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function matches(RequestInterface $request): bool
|
||||
{
|
||||
return $request->getUri()->getPath() === $this->path ||
|
||||
$request->getUri()->getPath() === '/' . $this->path;
|
||||
}
|
||||
}
|
67
src/Matchers/QueryMatcher.php
Normal file
67
src/Matchers/QueryMatcher.php
Normal file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category QueryMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Matchers;
|
||||
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Psr\Http\Message\UriInterface;
|
||||
|
||||
/**
|
||||
* Class QueryMatcher
|
||||
*
|
||||
* @category QueryMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
class QueryMatcher extends AbstractArrayPoweredComponent implements RequestMatcherInterface
|
||||
{
|
||||
/** @var array<string, mixed> */
|
||||
protected $query;
|
||||
|
||||
/**
|
||||
* QueryMatcher constructor.
|
||||
*
|
||||
* @param array<string, mixed> $query
|
||||
*/
|
||||
public function __construct(array $query)
|
||||
{
|
||||
$this->query = $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function matches(RequestInterface $request): bool
|
||||
{
|
||||
$query = static::parseQuery($request->getUri()->getQuery());
|
||||
|
||||
if (empty($query)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return self::isNeedlePresentInHaystack($this->query, $query);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses query, returns result.
|
||||
*
|
||||
* @param string $queryString
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
protected static function parseQuery(string $queryString): array
|
||||
{
|
||||
$query = [];
|
||||
|
||||
if ('' !== $queryString) {
|
||||
parse_str($queryString, $query);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
}
|
@ -87,6 +87,14 @@ class Mock implements MockInterface
|
||||
*/
|
||||
public function getResponse(): ?ResponseInterface
|
||||
{
|
||||
if (
|
||||
null !== $this->response &&
|
||||
null !== $this->response->getBody() &&
|
||||
$this->response->getBody()->isSeekable()
|
||||
) {
|
||||
$this->response->getBody()->seek(0);
|
||||
}
|
||||
|
||||
return $this->response;
|
||||
}
|
||||
|
||||
|
@ -9,25 +9,47 @@
|
||||
|
||||
namespace Pock;
|
||||
|
||||
use Diff\ArrayComparer\StrictArrayComparer;
|
||||
use Pock\Enum\RequestMethod;
|
||||
use Pock\Enum\RequestScheme;
|
||||
use Pock\Matchers\AnyRequestMatcher;
|
||||
use Pock\Matchers\BodyMatcher;
|
||||
use Pock\Matchers\CallbackRequestMatcher;
|
||||
use Pock\Matchers\ExactHeaderMatcher;
|
||||
use Pock\Matchers\ExactHeadersMatcher;
|
||||
use Pock\Matchers\ExactQueryMatcher;
|
||||
use Pock\Matchers\HeaderLineMatcher;
|
||||
use Pock\Matchers\HeaderLineRegexpMatcher;
|
||||
use Pock\Matchers\HeaderMatcher;
|
||||
use Pock\Matchers\HeadersMatcher;
|
||||
use Pock\Matchers\HostMatcher;
|
||||
use Pock\Matchers\JsonBodyMatcher;
|
||||
use Pock\Matchers\MethodMatcher;
|
||||
use Pock\Matchers\MultipleMatcher;
|
||||
use Pock\Matchers\PathMatcher;
|
||||
use Pock\Matchers\QueryMatcher;
|
||||
use Pock\Matchers\RequestMatcherInterface;
|
||||
use Pock\Matchers\SchemeMatcher;
|
||||
use Pock\Matchers\UriMatcher;
|
||||
use Pock\Traits\JsonDecoderTrait;
|
||||
use Pock\Traits\JsonSerializerAwareTrait;
|
||||
use Psr\Http\Client\ClientInterface;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* Class PockBuilder
|
||||
*
|
||||
* @category PockBuilder
|
||||
* @package Pock
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
* @SuppressWarnings(PHPMD.TooManyPublicMethods)
|
||||
*/
|
||||
class PockBuilder
|
||||
{
|
||||
use JsonDecoderTrait;
|
||||
use JsonSerializerAwareTrait;
|
||||
|
||||
/** @var \Pock\Matchers\MultipleMatcher */
|
||||
private $matcher;
|
||||
|
||||
@ -59,7 +81,7 @@ class PockBuilder
|
||||
*
|
||||
* @param string $method
|
||||
*
|
||||
* @return $this
|
||||
* @return self
|
||||
*/
|
||||
public function matchMethod(string $method): self
|
||||
{
|
||||
@ -102,6 +124,167 @@ class PockBuilder
|
||||
return $this->addMatcher(new UriMatcher($uri));
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches request by header value or several values. Header can have other values which are not specified here.
|
||||
* @see PockBuilder::matchExactHeader() if you want to match exact header values.
|
||||
*
|
||||
* @param string $header
|
||||
* @param string|string[] $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function matchHeader(string $header, $value): self
|
||||
{
|
||||
return $this->addMatcher(new HeaderMatcher($header, $value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches request by headers values or several values. Headers can have other values which are not specified here.
|
||||
* @see PockBuilder::matchExactHeaders() if you want to match exact headers collection.
|
||||
*
|
||||
* @param array<string, string|string[]> $headers
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function matchHeaders(array $headers): self
|
||||
{
|
||||
return $this->addMatcher(new HeadersMatcher($headers));
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches request by the exact header pattern or values.
|
||||
*
|
||||
* @param string $header
|
||||
* @param string|string[] $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function matchExactHeader(string $header, $value): self
|
||||
{
|
||||
return $this->addMatcher(new ExactHeaderMatcher($header, $value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches request by headers values or several values.
|
||||
* Note: only host header will be dropped. Any other headers will not be excluded and can result in the problems
|
||||
* with the exact matching.
|
||||
*
|
||||
* @param array<string, string|string[]> $headers
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function matchExactHeaders(array $headers): self
|
||||
{
|
||||
return $this->addMatcher(new ExactHeadersMatcher($headers));
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches request by the unparsed header line.
|
||||
*
|
||||
* @param string $header
|
||||
* @param string $value
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function matchHeaderLine(string $header, string $value): self
|
||||
{
|
||||
return $this->addMatcher(new HeaderLineMatcher($header, $value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches request by the unparsed header line using provided regular expression.
|
||||
*
|
||||
* @param string $header
|
||||
* @param string $pattern
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function matchHeaderLineRegexp(string $header, string $pattern): self
|
||||
{
|
||||
return $this->addMatcher(new HeaderLineRegexpMatcher($header, $pattern));
|
||||
}
|
||||
|
||||
/**
|
||||
* Match request by its path. Path with and without slash at the start will be treated as the same path.
|
||||
* It's not the same for the path with slash at the end of it.
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function matchPath(string $path): self
|
||||
{
|
||||
return $this->addMatcher(new PathMatcher($path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Match request by its query. Request can contain other query variables.
|
||||
* @see PockBuilder::matchExactQuery() if you want to match an entire query string.
|
||||
*
|
||||
* @param array<string, mixed> $query
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function matchQuery(array $query): self
|
||||
{
|
||||
return $this->addMatcher(new QueryMatcher($query));
|
||||
}
|
||||
|
||||
/**
|
||||
* Match request by its query. Additional query parameters aren't allowed.
|
||||
*
|
||||
* @param array<string, mixed> $query
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function matchExactQuery(array $query): self
|
||||
{
|
||||
return $this->addMatcher(new ExactQueryMatcher($query));
|
||||
}
|
||||
|
||||
/**
|
||||
* Match entire request body.
|
||||
*
|
||||
* @param \Psr\Http\Message\StreamInterface|resource|string $data
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function matchBody($data): self
|
||||
{
|
||||
return $this->addMatcher(new BodyMatcher($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Match JSON request body.
|
||||
*
|
||||
* @param mixed $data
|
||||
*
|
||||
* @return self
|
||||
* @throws \Pock\Exception\JsonException
|
||||
*/
|
||||
public function matchJsonBody($data): self
|
||||
{
|
||||
return $this->addMatcher(new JsonBodyMatcher(
|
||||
self::jsonDecode(
|
||||
self::serializeJson($data) ?? '',
|
||||
true
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Match request using provided callback. Callback should receive RequestInterface and return boolean.
|
||||
* If returned value is true then request is matched.
|
||||
*
|
||||
* @param callable $callback
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function matchCallback(callable $callback): self
|
||||
{
|
||||
return $this->addMatcher(new CallbackRequestMatcher($callback));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add custom matcher to the mock.
|
||||
*
|
||||
@ -123,7 +306,7 @@ class PockBuilder
|
||||
*
|
||||
* @param int $hits
|
||||
*
|
||||
* @return $this
|
||||
* @return self
|
||||
*/
|
||||
public function repeat(int $hits): self
|
||||
{
|
||||
@ -134,6 +317,20 @@ class PockBuilder
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throw an exception when request is being sent.
|
||||
*
|
||||
* @param \Throwable $throwable
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function throwException(Throwable $throwable): self
|
||||
{
|
||||
$this->throwable = $throwable;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $statusCode
|
||||
*
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.3
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category PockResponseBuilder
|
||||
* @package Pock
|
||||
@ -12,11 +12,8 @@ namespace Pock;
|
||||
use InvalidArgumentException;
|
||||
use JsonSerializable;
|
||||
use Nyholm\Psr7\Factory\Psr17Factory;
|
||||
use Pock\Exception\JsonException;
|
||||
use Pock\Exception\XmlException;
|
||||
use Pock\Factory\JsonSerializerFactory;
|
||||
use Pock\Factory\XmlSerializerFactory;
|
||||
use Pock\Serializer\SerializerInterface;
|
||||
use Pock\Traits\JsonSerializerAwareTrait;
|
||||
use Pock\Traits\XmlSerializerAwareTrait;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use RuntimeException;
|
||||
|
||||
@ -28,18 +25,15 @@ use RuntimeException;
|
||||
*/
|
||||
class PockResponseBuilder
|
||||
{
|
||||
use JsonSerializerAwareTrait;
|
||||
use XmlSerializerAwareTrait;
|
||||
|
||||
/** @var \Psr\Http\Message\ResponseInterface */
|
||||
protected $response;
|
||||
|
||||
/** @var Psr17Factory */
|
||||
protected $factory;
|
||||
|
||||
/** @var SerializerInterface|null */
|
||||
protected static $jsonSerializer;
|
||||
|
||||
/** @var SerializerInterface|null */
|
||||
protected static $xmlSerializer;
|
||||
|
||||
/**
|
||||
* PockResponseBuilder constructor.
|
||||
*
|
||||
@ -66,7 +60,7 @@ class PockResponseBuilder
|
||||
}
|
||||
|
||||
/**
|
||||
* Respond with specified header value.
|
||||
* Respond with specified header pattern.
|
||||
* @see \Psr\Http\Message\MessageInterface::withHeader()
|
||||
*
|
||||
* @param string $name
|
||||
@ -82,7 +76,7 @@ class PockResponseBuilder
|
||||
}
|
||||
|
||||
/**
|
||||
* Respond with specified header value appended to existing header.
|
||||
* Respond with specified header pattern appended to existing header.
|
||||
* @see \Psr\Http\Message\MessageInterface::withAddedHeader()
|
||||
*
|
||||
* @param string $name
|
||||
@ -132,8 +126,8 @@ class PockResponseBuilder
|
||||
/**
|
||||
* Reply with specified body. It can be:
|
||||
* - PSR-7 StreamInterface - it will be used without any changes.
|
||||
* - string - it will be used as stream contents.
|
||||
* - resource - it's data will be used as stream contents.
|
||||
* - string - it will be used as contents contents.
|
||||
* - resource - it's data will be used as contents contents.
|
||||
*
|
||||
* @param \Psr\Http\Message\StreamInterface|resource|string $stream
|
||||
*
|
||||
@ -189,20 +183,10 @@ class PockResponseBuilder
|
||||
*/
|
||||
public function withJson($data): self
|
||||
{
|
||||
if (is_string($data) || is_numeric($data)) {
|
||||
return $this->withBody((string) $data);
|
||||
}
|
||||
$result = static::serializeJson($data);
|
||||
|
||||
if (is_array($data)) {
|
||||
return $this->withBody(static::jsonEncode($data));
|
||||
}
|
||||
|
||||
if (is_object($data)) {
|
||||
if ($data instanceof JsonSerializable) {
|
||||
return $this->withBody(static::jsonEncode($data));
|
||||
}
|
||||
|
||||
return $this->withBody(static::jsonSerializer()->serialize($data));
|
||||
if (null !== $result) {
|
||||
return $this->withBody($result);
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException('Cannot serialize data with type ' . gettype($data));
|
||||
@ -216,12 +200,10 @@ class PockResponseBuilder
|
||||
*/
|
||||
public function withXml($data): self
|
||||
{
|
||||
if (is_string($data)) {
|
||||
return $this->withBody($data);
|
||||
}
|
||||
$result = static::serializeXml($data);
|
||||
|
||||
if (is_array($data) || is_object($data)) {
|
||||
return $this->withBody(static::xmlSerializer()->serialize($data));
|
||||
if (null !== $result) {
|
||||
return $this->withBody($result);
|
||||
}
|
||||
|
||||
throw new InvalidArgumentException('Cannot serialize data with type ' . gettype($data));
|
||||
@ -234,69 +216,4 @@ class PockResponseBuilder
|
||||
{
|
||||
return $this->response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode JSON, throw an exception on error.
|
||||
*
|
||||
* @param mixed $data
|
||||
*
|
||||
* @return string
|
||||
* @throws \Pock\Exception\JsonException
|
||||
*/
|
||||
protected static function jsonEncode($data): string
|
||||
{
|
||||
$data = json_encode($data);
|
||||
|
||||
if (JSON_ERROR_NONE !== json_last_error()) {
|
||||
throw new JsonException(json_last_error_msg(), json_last_error());
|
||||
}
|
||||
|
||||
return (string) $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Pock\Serializer\SerializerInterface
|
||||
* @throws \Pock\Exception\JsonException
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.StaticAccess)
|
||||
*/
|
||||
protected static function jsonSerializer(): SerializerInterface
|
||||
{
|
||||
if (null !== static::$jsonSerializer) {
|
||||
return static::$jsonSerializer;
|
||||
}
|
||||
|
||||
$serializer = JsonSerializerFactory::create();
|
||||
|
||||
if (null === $serializer) {
|
||||
throw new JsonException('No JSON serializer available');
|
||||
}
|
||||
|
||||
static::$jsonSerializer = $serializer;
|
||||
|
||||
return $serializer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Pock\Serializer\SerializerInterface
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.StaticAccess)
|
||||
* @throws \Pock\Exception\XmlException
|
||||
*/
|
||||
protected static function xmlSerializer(): SerializerInterface
|
||||
{
|
||||
if (null !== static::$xmlSerializer) {
|
||||
return static::$xmlSerializer;
|
||||
}
|
||||
|
||||
$serializer = XmlSerializerFactory::create();
|
||||
|
||||
if (null === $serializer) {
|
||||
throw new XmlException('No XML serializer available');
|
||||
}
|
||||
|
||||
static::$xmlSerializer = $serializer;
|
||||
|
||||
return $serializer;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.3
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category CallbackSerializerDecorator
|
||||
* @package Pock\Serializer
|
||||
|
20
src/Serializer/SymfonySerializerDecorator.php
Normal file
20
src/Serializer/SymfonySerializerDecorator.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category SymfonySerializerDecorator
|
||||
* @package Pock\Serializer
|
||||
*/
|
||||
|
||||
namespace Pock\Serializer;
|
||||
|
||||
/**
|
||||
* Class SymfonySerializerDecorator
|
||||
*
|
||||
* @category SymfonySerializerDecorator
|
||||
* @package Pock\Serializer
|
||||
*/
|
||||
class SymfonySerializerDecorator extends JmsSerializerDecorator
|
||||
{
|
||||
}
|
50
src/Traits/JsonDecoderTrait.php
Normal file
50
src/Traits/JsonDecoderTrait.php
Normal file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category JsonDecoderTrait
|
||||
* @package Pock\Traits
|
||||
*/
|
||||
|
||||
namespace Pock\Traits;
|
||||
|
||||
use Pock\Exception\JsonException;
|
||||
|
||||
/**
|
||||
* Trait JsonDecoderTrait
|
||||
*
|
||||
* @category JsonDecoderTrait
|
||||
* @package Pock\Traits
|
||||
*/
|
||||
trait JsonDecoderTrait
|
||||
{
|
||||
/**
|
||||
* json_decode which throws exception on error.
|
||||
*
|
||||
* @param string $json
|
||||
* @param bool|null $associative
|
||||
* @param int $depth
|
||||
*
|
||||
* @param int $flags
|
||||
*
|
||||
* @return mixed
|
||||
* @throws \Pock\Exception\JsonException
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.BooleanArgumentFlag)
|
||||
*/
|
||||
public static function jsonDecode(
|
||||
string $json,
|
||||
?bool $associative = false,
|
||||
int $depth = 512,
|
||||
int $flags = 0
|
||||
) {
|
||||
$result = json_decode($json, $associative, $depth, $flags);
|
||||
|
||||
if (JSON_ERROR_NONE !== json_last_error()) {
|
||||
throw new JsonException(json_last_error_msg(), json_last_error());
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
42
src/Traits/JsonEncoderTrait.php
Normal file
42
src/Traits/JsonEncoderTrait.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category JsonEncoderTrait
|
||||
* @package Pock\Traits
|
||||
*/
|
||||
|
||||
namespace Pock\Traits;
|
||||
|
||||
use Pock\Exception\JsonException;
|
||||
|
||||
/**
|
||||
* Trait JsonEncoderTrait
|
||||
*
|
||||
* @category JsonEncoderTrait
|
||||
* @package Pock\Traits
|
||||
*/
|
||||
trait JsonEncoderTrait
|
||||
{
|
||||
/**
|
||||
* json_encode which throws exception on error.
|
||||
*
|
||||
* @param mixed $data
|
||||
* @param int $flags
|
||||
* @param int $depth
|
||||
*
|
||||
* @return string
|
||||
* @throws \Pock\Exception\JsonException
|
||||
*/
|
||||
public static function jsonEncode($data, int $flags = 0, int $depth = 512): string
|
||||
{
|
||||
$result = json_encode($data, $flags, $depth);
|
||||
|
||||
if (JSON_ERROR_NONE !== json_last_error()) {
|
||||
throw new JsonException(json_last_error_msg(), json_last_error());
|
||||
}
|
||||
|
||||
return (string) $result;
|
||||
}
|
||||
}
|
82
src/Traits/JsonSerializerAwareTrait.php
Normal file
82
src/Traits/JsonSerializerAwareTrait.php
Normal file
@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category JsonSerializerAwareTrait
|
||||
* @package Pock\Traits
|
||||
*/
|
||||
|
||||
namespace Pock\Traits;
|
||||
|
||||
use JsonSerializable;
|
||||
use Pock\Exception\JsonException;
|
||||
use Pock\Factory\JsonSerializerFactory;
|
||||
use Pock\Serializer\SerializerInterface;
|
||||
|
||||
/**
|
||||
* Trait JsonSerializerAwareTrait
|
||||
*
|
||||
* @category JsonSerializerAwareTrait
|
||||
* @package Pock\Traits
|
||||
*/
|
||||
trait JsonSerializerAwareTrait
|
||||
{
|
||||
use JsonEncoderTrait;
|
||||
|
||||
/** @var SerializerInterface|null */
|
||||
protected static $jsonSerializer;
|
||||
|
||||
/**
|
||||
* Returns JSON string if serialization was successful. Returns null otherwise.
|
||||
* String input value will be treated as JSON and will not be processed in any way.
|
||||
*
|
||||
* @param mixed $data
|
||||
*
|
||||
* @return string|null
|
||||
* @throws \Pock\Exception\JsonException
|
||||
*/
|
||||
protected static function serializeJson($data): ?string
|
||||
{
|
||||
if (is_string($data) || is_numeric($data)) {
|
||||
return (string) $data;
|
||||
}
|
||||
|
||||
if (is_array($data)) {
|
||||
return static::jsonEncode($data);
|
||||
}
|
||||
|
||||
if (is_object($data)) {
|
||||
if ($data instanceof JsonSerializable) {
|
||||
return static::jsonEncode($data);
|
||||
}
|
||||
|
||||
return static::jsonSerializer()->serialize($data);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Pock\Serializer\SerializerInterface
|
||||
* @throws \Pock\Exception\JsonException
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.StaticAccess)
|
||||
*/
|
||||
protected static function jsonSerializer(): SerializerInterface
|
||||
{
|
||||
if (null !== static::$jsonSerializer) {
|
||||
return static::$jsonSerializer;
|
||||
}
|
||||
|
||||
$serializer = JsonSerializerFactory::create();
|
||||
|
||||
if (null === $serializer) {
|
||||
throw new JsonException('No JSON serializer available');
|
||||
}
|
||||
|
||||
static::$jsonSerializer = $serializer;
|
||||
|
||||
return $serializer;
|
||||
}
|
||||
}
|
33
src/Traits/SeekableStreamDataExtractor.php
Normal file
33
src/Traits/SeekableStreamDataExtractor.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category SeekableStreamDataExtractor
|
||||
* @package Pock\Traits
|
||||
*/
|
||||
|
||||
namespace Pock\Traits;
|
||||
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
|
||||
/**
|
||||
* Trait SeekableStreamDataExtractor
|
||||
*
|
||||
* @category SeekableStreamDataExtractor
|
||||
* @package Pock\Traits
|
||||
*/
|
||||
trait SeekableStreamDataExtractor
|
||||
{
|
||||
/**
|
||||
* Returns contents contents without honoring a contents pointer.
|
||||
*
|
||||
* @param \Psr\Http\Message\StreamInterface $stream
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected static function getStreamData(StreamInterface $stream): string
|
||||
{
|
||||
return $stream->isSeekable() ? $stream->__toString() : $stream->getContents();
|
||||
}
|
||||
}
|
71
src/Traits/XmlSerializerAwareTrait.php
Normal file
71
src/Traits/XmlSerializerAwareTrait.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category XmlSerializerAwareTrait
|
||||
* @package Pock\Traits
|
||||
*/
|
||||
|
||||
namespace Pock\Traits;
|
||||
|
||||
use Pock\Exception\XmlException;
|
||||
use Pock\Factory\XmlSerializerFactory;
|
||||
use Pock\Serializer\SerializerInterface;
|
||||
|
||||
/**
|
||||
* Trait XmlSerializerAwareTrait
|
||||
*
|
||||
* @category XmlSerializerAwareTrait
|
||||
* @package Pock\Traits
|
||||
*/
|
||||
trait XmlSerializerAwareTrait
|
||||
{
|
||||
/** @var SerializerInterface|null */
|
||||
protected static $xmlSerializer;
|
||||
|
||||
/**
|
||||
* Returns XML string if serialization was successful. Returns null otherwise.
|
||||
* String input value will be treated as XML and will not be processed in any way.
|
||||
*
|
||||
* @param mixed $data
|
||||
*
|
||||
* @return string|null
|
||||
* @throws \Pock\Exception\XmlException
|
||||
*/
|
||||
protected static function serializeXml($data): ?string
|
||||
{
|
||||
if (is_string($data)) {
|
||||
return $data;
|
||||
}
|
||||
|
||||
if (is_array($data) || is_object($data)) {
|
||||
return static::xmlSerializer()->serialize($data);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Pock\Serializer\SerializerInterface
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.StaticAccess)
|
||||
* @throws \Pock\Exception\XmlException
|
||||
*/
|
||||
protected static function xmlSerializer(): SerializerInterface
|
||||
{
|
||||
if (null !== static::$xmlSerializer) {
|
||||
return static::$xmlSerializer;
|
||||
}
|
||||
|
||||
$serializer = XmlSerializerFactory::create();
|
||||
|
||||
if (null === $serializer) {
|
||||
throw new XmlException('No XML serializer available');
|
||||
}
|
||||
|
||||
static::$xmlSerializer = $serializer;
|
||||
|
||||
return $serializer;
|
||||
}
|
||||
}
|
@ -27,6 +27,6 @@ class JmsXmlSerializerCreatorTest extends TestCase
|
||||
$serializer = JmsXmlSerializerCreator::create();
|
||||
|
||||
self::assertInstanceOf(SerializerInterface::class, $serializer);
|
||||
self::assertEquals(SimpleObject::XML, $serializer->serialize(new SimpleObject()));
|
||||
self::assertEquals(SimpleObject::JMS_XML, $serializer->serialize(new SimpleObject()));
|
||||
}
|
||||
}
|
||||
|
32
tests/src/Creator/SymfonyJsonSerializerCreatorTest.php
Normal file
32
tests/src/Creator/SymfonyJsonSerializerCreatorTest.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category SymfonyJsonSerializerCreatorTest
|
||||
* @package Pock\Tests\Creator
|
||||
*/
|
||||
|
||||
namespace Pock\Tests\Creator;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Pock\Creator\SymfonyJsonSerializerCreator;
|
||||
use Pock\Serializer\SerializerInterface;
|
||||
use Pock\TestUtils\SimpleObject;
|
||||
|
||||
/**
|
||||
* Class SymfonyJsonSerializerCreatorTest
|
||||
*
|
||||
* @category SymfonyJsonSerializerCreatorTest
|
||||
* @package Pock\Tests\Creator
|
||||
*/
|
||||
class SymfonyJsonSerializerCreatorTest extends TestCase
|
||||
{
|
||||
public function testCreate(): void
|
||||
{
|
||||
$serializer = SymfonyJsonSerializerCreator::create();
|
||||
|
||||
self::assertInstanceOf(SerializerInterface::class, $serializer);
|
||||
self::assertEquals(SimpleObject::JSON, $serializer->serialize(new SimpleObject()));
|
||||
}
|
||||
}
|
32
tests/src/Creator/SymfonyXmlSerializerCreatorTest.php
Normal file
32
tests/src/Creator/SymfonyXmlSerializerCreatorTest.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category SymfonyXmlSerializerCreatorTest
|
||||
* @package Pock\Tests\Creator
|
||||
*/
|
||||
|
||||
namespace Pock\Tests\Creator;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Pock\Creator\SymfonyXmlSerializerCreator;
|
||||
use Pock\Serializer\SerializerInterface;
|
||||
use Pock\TestUtils\SimpleObject;
|
||||
|
||||
/**
|
||||
* Class SymfonyXmlSerializerCreatorTest
|
||||
*
|
||||
* @category SymfonyXmlSerializerCreatorTest
|
||||
* @package Pock\Tests\Creator
|
||||
*/
|
||||
class SymfonyXmlSerializerCreatorTest extends TestCase
|
||||
{
|
||||
public function testCreate(): void
|
||||
{
|
||||
$serializer = SymfonyXmlSerializerCreator::create();
|
||||
|
||||
self::assertInstanceOf(SerializerInterface::class, $serializer);
|
||||
self::assertEquals(SimpleObject::SYMFONY_XML, $serializer->serialize(new SimpleObject()));
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.3
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category CallbackSerializerDecoratorTest
|
||||
* @package Pock\Tests\Decorator
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.3
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category AbstractSerializerFactoryTest
|
||||
* @package Pock\Tests\Factory
|
||||
|
@ -27,6 +27,6 @@ class XmlSerializerFactoryTest extends TestCase
|
||||
$serializer = XmlSerializerFactory::create();
|
||||
|
||||
self::assertInstanceOf(SerializerInterface::class, $serializer);
|
||||
self::assertEquals(SimpleObject::XML, $serializer->serialize(new SimpleObject()));
|
||||
self::assertEquals(SimpleObject::JMS_XML, $serializer->serialize(new SimpleObject()));
|
||||
}
|
||||
}
|
||||
|
61
tests/src/Matchers/BodyMatcherTest.php
Normal file
61
tests/src/Matchers/BodyMatcherTest.php
Normal file
@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category BodyMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Tests\Matchers;
|
||||
|
||||
use Pock\Enum\RequestMethod;
|
||||
use Pock\Matchers\BodyMatcher;
|
||||
use Pock\TestUtils\PockTestCase;
|
||||
|
||||
/**
|
||||
* Class BodyMatcherTest
|
||||
*
|
||||
* @category BodyMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
class BodyMatcherTest extends PockTestCase
|
||||
{
|
||||
public function testNoMatches(): void
|
||||
{
|
||||
$request = self::getTestRequest(RequestMethod::POST)
|
||||
->withBody(self::getPsr17Factory()->createStream('test1'));
|
||||
$matcher = new BodyMatcher('test');
|
||||
|
||||
self::assertFalse($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testMatchesString(): void
|
||||
{
|
||||
$request = self::getTestRequest(RequestMethod::POST)
|
||||
->withBody(self::getPsr17Factory()->createStream('test'));
|
||||
$matcher = new BodyMatcher('test');
|
||||
|
||||
self::assertTrue($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testMatchesStream(): void
|
||||
{
|
||||
$request = self::getTestRequest(RequestMethod::POST)
|
||||
->withBody(self::getPsr17Factory()->createStream('test'));
|
||||
$matcher = new BodyMatcher(self::getPsr17Factory()->createStream('test'));
|
||||
|
||||
self::assertTrue($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testMatchesResource(): void
|
||||
{
|
||||
$resource = fopen(__FILE__, 'rb');
|
||||
$request = self::getTestRequest(RequestMethod::POST)->withBody(self::getPsr17Factory()->createStream(
|
||||
stream_get_contents($resource)
|
||||
));
|
||||
$matcher = new BodyMatcher($resource);
|
||||
|
||||
self::assertTrue($matcher->matches($request));
|
||||
}
|
||||
}
|
40
tests/src/Matchers/CallbackRequestMatcherTest.php
Normal file
40
tests/src/Matchers/CallbackRequestMatcherTest.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category CallbackRequestMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Tests\Matchers;
|
||||
|
||||
use Pock\Matchers\CallbackRequestMatcher;
|
||||
use Pock\TestUtils\PockTestCase;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Class CallbackRequestMatcherTest
|
||||
*
|
||||
* @category CallbackRequestMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
class CallbackRequestMatcherTest extends PockTestCase
|
||||
{
|
||||
public function testMatches(): void
|
||||
{
|
||||
$matcher = new CallbackRequestMatcher(function (RequestInterface $request) {
|
||||
return '' !== $request->getUri()->getQuery();
|
||||
});
|
||||
|
||||
self::assertFalse($matcher->matches(self::getTestRequest()));
|
||||
self::assertTrue($matcher->matches(
|
||||
self::getTestRequest()
|
||||
->withUri(
|
||||
self::getTestRequest()
|
||||
->getUri()
|
||||
->withQuery('param=value')
|
||||
)
|
||||
));
|
||||
}
|
||||
}
|
60
tests/src/Matchers/ExactHeaderMatcherTest.php
Normal file
60
tests/src/Matchers/ExactHeaderMatcherTest.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category ExactHeaderMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Tests\Matchers;
|
||||
|
||||
use Pock\Matchers\ExactHeaderMatcher;
|
||||
use Pock\TestUtils\PockTestCase;
|
||||
|
||||
/**
|
||||
* Class ExactHeaderMatcherTest
|
||||
*
|
||||
* @category ExactHeaderMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
class ExactHeaderMatcherTest extends PockTestCase
|
||||
{
|
||||
public function testNoMatch(): void
|
||||
{
|
||||
$matcher = new ExactHeaderMatcher('x-test-header', 'test value');
|
||||
self::assertFalse($matcher->matches(self::getTestRequest()));
|
||||
}
|
||||
|
||||
public function testMatchStringValue(): void
|
||||
{
|
||||
$request = self::getTestRequest()->withHeader('x-test-header', 'test value');
|
||||
$matcher = new ExactHeaderMatcher('x-test-header', 'test value');
|
||||
|
||||
self::assertTrue($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testMatchArrayValue(): void
|
||||
{
|
||||
$request = self::getTestRequest()->withHeader('x-test-header', 'test value');
|
||||
$matcher = new ExactHeaderMatcher('x-test-header', ['test value']);
|
||||
|
||||
self::assertTrue($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testNotMatchArrayValues(): void
|
||||
{
|
||||
$request = self::getTestRequest()->withHeader('x-test-header', ['test value1', 'test value2']);
|
||||
$matcher = new ExactHeaderMatcher('x-test-header', ['test value1']);
|
||||
|
||||
self::assertFalse($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testMatchArrayValues(): void
|
||||
{
|
||||
$request = self::getTestRequest()->withHeader('x-test-header', ['test value1', 'test value2']);
|
||||
$matcher = new ExactHeaderMatcher('x-test-header', ['test value2', 'test value1']);
|
||||
|
||||
self::assertTrue($matcher->matches($request));
|
||||
}
|
||||
}
|
63
tests/src/Matchers/ExactHeadersMatcherTest.php
Normal file
63
tests/src/Matchers/ExactHeadersMatcherTest.php
Normal file
@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category ExactHeadersMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Tests\Matchers;
|
||||
|
||||
use Pock\Matchers\ExactHeadersMatcher;
|
||||
use Pock\TestUtils\PockTestCase;
|
||||
|
||||
/**
|
||||
* Class ExactHeadersMatcherTest
|
||||
*
|
||||
* @category ExactHeadersMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
class ExactHeadersMatcherTest extends PockTestCase
|
||||
{
|
||||
public function testNoMatch(): void
|
||||
{
|
||||
$matcher = new ExactHeadersMatcher(['x-test-header' => 'test value']);
|
||||
self::assertFalse($matcher->matches(self::getTestRequest()));
|
||||
}
|
||||
|
||||
public function testMatchStringValue(): void
|
||||
{
|
||||
$request = self::getTestRequest()->withHeader('x-test-header', 'test value');
|
||||
$matcher = new ExactHeadersMatcher(['x-test-header' => 'test value']);
|
||||
|
||||
self::assertTrue($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testMatchArrayValue(): void
|
||||
{
|
||||
$request = self::getTestRequest()->withHeader('x-test-header', 'test value');
|
||||
$matcher = new ExactHeadersMatcher(['x-test-header' => ['test value']]);
|
||||
|
||||
self::assertTrue($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testNotMatchArrayValues(): void
|
||||
{
|
||||
$request = self::getTestRequest()->withHeader('x-test-header', ['test value1', 'test value2']);
|
||||
$matcher = new ExactHeadersMatcher(['x-test-header' => ['test value1']]);
|
||||
|
||||
self::assertFalse($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testNoMatchArrayValues(): void
|
||||
{
|
||||
$request = self::getTestRequest()->withHeader(
|
||||
'x-test-header',
|
||||
['test value1', 'test value2', 'test value 3']
|
||||
);
|
||||
$matcher = new ExactHeadersMatcher(['x-test-header' => ['test value2', 'test value1']]);
|
||||
|
||||
self::assertFalse($matcher->matches($request));
|
||||
}
|
||||
}
|
89
tests/src/Matchers/ExactQueryMatcherTest.php
Normal file
89
tests/src/Matchers/ExactQueryMatcherTest.php
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category ExactQueryMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Tests\Matchers;
|
||||
|
||||
use Pock\Matchers\ExactQueryMatcher;
|
||||
use Pock\TestUtils\PockTestCase;
|
||||
|
||||
/**
|
||||
* Class ExactQueryMatcherTest
|
||||
*
|
||||
* @category ExactQueryMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
class ExactQueryMatcherTest extends PockTestCase
|
||||
{
|
||||
public function testNoMatches(): void
|
||||
{
|
||||
$request = self::getTestRequest()->withUri(self::getTestRequest()->getUri());
|
||||
$matcher = new ExactQueryMatcher(['var' => 'ok']);
|
||||
|
||||
self::assertFalse($matcher->matches($request));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider matchesProvider
|
||||
*/
|
||||
public function testMatches(array $expected, string $actual, bool $result): void
|
||||
{
|
||||
$request = self::getTestRequest()->withUri(
|
||||
self::getTestRequest()
|
||||
->getUri()
|
||||
->withQuery($actual)
|
||||
);
|
||||
$matcher = new ExactQueryMatcher($expected);
|
||||
|
||||
self::assertEquals($result, $matcher->matches($request));
|
||||
}
|
||||
|
||||
public function matchesProvider(): array
|
||||
{
|
||||
return [
|
||||
[
|
||||
['var' => 'ok'],
|
||||
'var=ok',
|
||||
true
|
||||
],
|
||||
[
|
||||
['var' => 'ok'],
|
||||
'var=ok&var1=true',
|
||||
false
|
||||
],
|
||||
[
|
||||
[
|
||||
'var' => 'ok',
|
||||
'var1' => 'true',
|
||||
],
|
||||
'var=ok&var1=true',
|
||||
true
|
||||
],
|
||||
[
|
||||
[
|
||||
'var' => 'ok',
|
||||
'var1' => 'true',
|
||||
],
|
||||
'var=ok',
|
||||
false
|
||||
],
|
||||
[
|
||||
[
|
||||
'var' => 'ok',
|
||||
'x' => [
|
||||
0 => 'alpha',
|
||||
1 => 'beta',
|
||||
'gamma' => ['lambda']
|
||||
],
|
||||
],
|
||||
'var=ok&x[]=alpha&x[]=beta&x[gamma][]=lambda',
|
||||
true
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
38
tests/src/Matchers/HeaderLineMatcherTest.php
Normal file
38
tests/src/Matchers/HeaderLineMatcherTest.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category HeaderLineMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Tests\Matchers;
|
||||
|
||||
use Pock\Matchers\HeaderLineMatcher;
|
||||
use Pock\TestUtils\PockTestCase;
|
||||
|
||||
/**
|
||||
* Class HeaderLineMatcherTest
|
||||
*
|
||||
* @category HeaderLineMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
class HeaderLineMatcherTest extends PockTestCase
|
||||
{
|
||||
public function testNoMatches(): void
|
||||
{
|
||||
$request = self::getTestRequest()->withHeader('x-test-header', ['first', 'second']);
|
||||
$matcher = new HeaderLineMatcher('x-test-header', 'second, first');
|
||||
|
||||
self::assertFalse($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testMatches(): void
|
||||
{
|
||||
$request = self::getTestRequest()->withHeader('x-test-header', ['first', 'second']);
|
||||
$matcher = new HeaderLineMatcher('x-test-header', 'first, second');
|
||||
|
||||
self::assertTrue($matcher->matches($request));
|
||||
}
|
||||
}
|
38
tests/src/Matchers/HeaderLineRegexpMatcherTest.php
Normal file
38
tests/src/Matchers/HeaderLineRegexpMatcherTest.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category HeaderLineRegexpMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Tests\Matchers;
|
||||
|
||||
use Pock\Matchers\HeaderLineRegexpMatcher;
|
||||
use Pock\TestUtils\PockTestCase;
|
||||
|
||||
/**
|
||||
* Class HeaderLineRegexpMatcherTest
|
||||
*
|
||||
* @category HeaderLineRegexpMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
class HeaderLineRegexpMatcherTest extends PockTestCase
|
||||
{
|
||||
public function testNoMatches(): void
|
||||
{
|
||||
$request = self::getTestRequest()->withHeader('x-test-header', ['first', 'second']);
|
||||
$matcher = new HeaderLineRegexpMatcher('x-test-header', '/first$/');
|
||||
|
||||
self::assertFalse($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testMatches(): void
|
||||
{
|
||||
$request = self::getTestRequest()->withHeader('x-test-header', ['first', 'second']);
|
||||
$matcher = new HeaderLineRegexpMatcher('x-test-header', '/^first/');
|
||||
|
||||
self::assertTrue($matcher->matches($request));
|
||||
}
|
||||
}
|
52
tests/src/Matchers/HeaderMatcherTest.php
Normal file
52
tests/src/Matchers/HeaderMatcherTest.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category HeaderMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Tests\Matchers;
|
||||
|
||||
use Pock\Matchers\HeaderMatcher;
|
||||
use Pock\TestUtils\PockTestCase;
|
||||
|
||||
/**
|
||||
* Class HeaderMatcherTest
|
||||
*
|
||||
* @category HeaderMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
class HeaderMatcherTest extends PockTestCase
|
||||
{
|
||||
public function testNoMatch(): void
|
||||
{
|
||||
$matcher = new HeaderMatcher('x-test-header', 'test value');
|
||||
self::assertFalse($matcher->matches(self::getTestRequest()));
|
||||
}
|
||||
|
||||
public function testMatchStringValue(): void
|
||||
{
|
||||
$request = self::getTestRequest()->withHeader('x-test-header', 'test value');
|
||||
$matcher = new HeaderMatcher('x-test-header', 'test value');
|
||||
|
||||
self::assertTrue($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testMatchArrayValue(): void
|
||||
{
|
||||
$request = self::getTestRequest()->withHeader('x-test-header', 'test value');
|
||||
$matcher = new HeaderMatcher('x-test-header', ['test value']);
|
||||
|
||||
self::assertTrue($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testMatchArrayValues(): void
|
||||
{
|
||||
$request = self::getTestRequest()->withHeader('x-test-header', ['test value1', 'test value2']);
|
||||
$matcher = new HeaderMatcher('x-test-header', ['test value1']);
|
||||
|
||||
self::assertTrue($matcher->matches($request));
|
||||
}
|
||||
}
|
60
tests/src/Matchers/HeadersMatcherTest.php
Normal file
60
tests/src/Matchers/HeadersMatcherTest.php
Normal file
@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category HeadersMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Tests\Matchers;
|
||||
|
||||
use Pock\Matchers\HeadersMatcher;
|
||||
use Pock\TestUtils\PockTestCase;
|
||||
|
||||
/**
|
||||
* Class HeadersMatcherTest
|
||||
*
|
||||
* @category HeadersMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
class HeadersMatcherTest extends PockTestCase
|
||||
{
|
||||
public function testNoMatch(): void
|
||||
{
|
||||
$matcher = new HeadersMatcher(['x-test-header' => 'test value']);
|
||||
self::assertFalse($matcher->matches(self::getTestRequest()));
|
||||
}
|
||||
|
||||
public function testMatchStringValue(): void
|
||||
{
|
||||
$request = self::getTestRequest()->withHeader('x-test-header', 'test value');
|
||||
$matcher = new HeadersMatcher(['x-test-header' => 'test value']);
|
||||
|
||||
self::assertTrue($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testMatchArrayValue(): void
|
||||
{
|
||||
$request = self::getTestRequest()->withHeader('x-test-header', 'test value');
|
||||
$matcher = new HeadersMatcher(['x-test-header' => ['test value']]);
|
||||
|
||||
self::assertTrue($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testMatchArrayValues(): void
|
||||
{
|
||||
$request = self::getTestRequest()->withHeader('x-test-header', ['test value1', 'test value2']);
|
||||
$matcher = new HeadersMatcher(['x-test-header' => ['test value1']]);
|
||||
|
||||
self::assertTrue($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testNoMatchArrayValues(): void
|
||||
{
|
||||
$request = self::getTestRequest()->withHeader('x-test-header', ['test value2']);
|
||||
$matcher = new HeadersMatcher(['x-test-header' => ['test value1']]);
|
||||
|
||||
self::assertFalse($matcher->matches($request));
|
||||
}
|
||||
}
|
@ -20,6 +20,11 @@ use Pock\TestUtils\PockTestCase;
|
||||
*/
|
||||
class HostMatcherTest extends PockTestCase
|
||||
{
|
||||
public function testNotMatches(): void
|
||||
{
|
||||
self::assertFalse((new HostMatcher('test.com'))->matches(static::getTestRequest()));
|
||||
}
|
||||
|
||||
public function testMatches(): void
|
||||
{
|
||||
self::assertTrue((new HostMatcher(self::TEST_HOST))->matches(static::getTestRequest()));
|
||||
|
65
tests/src/Matchers/JsonBodyMatcherTest.php
Normal file
65
tests/src/Matchers/JsonBodyMatcherTest.php
Normal file
@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category JsonBodyMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Tests\Matchers;
|
||||
|
||||
use Pock\Enum\RequestMethod;
|
||||
use Pock\Matchers\JsonBodyMatcher;
|
||||
use Pock\TestUtils\PockTestCase;
|
||||
|
||||
/**
|
||||
* Class JsonBodyMatcherTest
|
||||
*
|
||||
* @category JsonBodyMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
class JsonBodyMatcherTest extends PockTestCase
|
||||
{
|
||||
public function testInvalidJson(): void
|
||||
{
|
||||
$request = self::getTestRequest(RequestMethod::POST)
|
||||
->withBody(self::getPsr17Factory()->createStream('test1'));
|
||||
$matcher = new JsonBodyMatcher(['field' => 'value']);
|
||||
|
||||
self::assertFalse($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testNoMatches(): void
|
||||
{
|
||||
$data = [
|
||||
'field' => [
|
||||
'items' => [
|
||||
'another' => 'value'
|
||||
]
|
||||
]
|
||||
];
|
||||
$request = self::getTestRequest(RequestMethod::POST)
|
||||
->withBody(self::getPsr17Factory()->createStream(json_encode($data)));
|
||||
$data['field']['items']['another2'] = 'value2';
|
||||
$matcher = new JsonBodyMatcher($data);
|
||||
|
||||
self::assertFalse($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testMatches(): void
|
||||
{
|
||||
$data = [
|
||||
'field' => [
|
||||
'items' => [
|
||||
'another' => 'value'
|
||||
]
|
||||
]
|
||||
];
|
||||
$request = self::getTestRequest(RequestMethod::POST)
|
||||
->withBody(self::getPsr17Factory()->createStream(json_encode($data)));
|
||||
$matcher = new JsonBodyMatcher($data);
|
||||
|
||||
self::assertTrue($matcher->matches($request));
|
||||
}
|
||||
}
|
51
tests/src/Matchers/PathMatcherTest.php
Normal file
51
tests/src/Matchers/PathMatcherTest.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category PathMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Tests\Matchers;
|
||||
|
||||
use Pock\Matchers\PathMatcher;
|
||||
use Pock\TestUtils\PockTestCase;
|
||||
|
||||
/**
|
||||
* Class PathMatcherTest
|
||||
*
|
||||
* @category PathMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
class PathMatcherTest extends PockTestCase
|
||||
{
|
||||
public function testNoMatches(): void
|
||||
{
|
||||
$request = self::getTestRequest()->withUri(self::getTestRequest()->getUri()->withPath('/test/path'));
|
||||
$matcher = new PathMatcher('/test/path/here');
|
||||
|
||||
self::assertFalse($matcher->matches($request));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider matchesProvider
|
||||
*/
|
||||
public function testMatches(string $expected, string $actual): void
|
||||
{
|
||||
$request = self::getTestRequest()->withUri(self::getTestRequest()->getUri()->withPath($actual));
|
||||
$matcher = new PathMatcher($expected);
|
||||
|
||||
self::assertTrue($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function matchesProvider(): array
|
||||
{
|
||||
return [
|
||||
['/test/path', '/test/path'],
|
||||
['/test/path', 'test/path'],
|
||||
['test/path', '/test/path'],
|
||||
['test/path', 'test/path']
|
||||
];
|
||||
}
|
||||
}
|
89
tests/src/Matchers/QueryMatcherTest.php
Normal file
89
tests/src/Matchers/QueryMatcherTest.php
Normal file
@ -0,0 +1,89 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category QueryMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Tests\Matchers;
|
||||
|
||||
use Pock\Matchers\QueryMatcher;
|
||||
use Pock\TestUtils\PockTestCase;
|
||||
|
||||
/**
|
||||
* Class QueryMatcherTest
|
||||
*
|
||||
* @category QueryMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
class QueryMatcherTest extends PockTestCase
|
||||
{
|
||||
public function testNoMatches(): void
|
||||
{
|
||||
$request = self::getTestRequest()->withUri(self::getTestRequest()->getUri());
|
||||
$matcher = new QueryMatcher(['var' => 'ok']);
|
||||
|
||||
self::assertFalse($matcher->matches($request));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider matchesProvider
|
||||
*/
|
||||
public function testMatches(array $expected, string $actual, bool $result): void
|
||||
{
|
||||
$request = self::getTestRequest()->withUri(
|
||||
self::getTestRequest()
|
||||
->getUri()
|
||||
->withQuery($actual)
|
||||
);
|
||||
$matcher = new QueryMatcher($expected);
|
||||
|
||||
self::assertEquals($result, $matcher->matches($request));
|
||||
}
|
||||
|
||||
public function matchesProvider(): array
|
||||
{
|
||||
return [
|
||||
[
|
||||
['var' => 'ok'],
|
||||
'var=ok',
|
||||
true
|
||||
],
|
||||
[
|
||||
['var' => 'ok'],
|
||||
'var=ok&var1=true',
|
||||
true
|
||||
],
|
||||
[
|
||||
[
|
||||
'var' => 'ok',
|
||||
'var1' => 'true',
|
||||
],
|
||||
'var=ok&var1=true',
|
||||
true
|
||||
],
|
||||
[
|
||||
[
|
||||
'var' => 'ok',
|
||||
'var1' => 'true',
|
||||
],
|
||||
'var=ok',
|
||||
false
|
||||
],
|
||||
[
|
||||
[
|
||||
'var' => 'ok',
|
||||
'x' => [
|
||||
0 => 'alpha',
|
||||
1 => 'beta',
|
||||
'gamma' => ['lambda']
|
||||
],
|
||||
],
|
||||
'var=ok&x[]=alpha&x[]=beta&x[gamma][]=lambda',
|
||||
true
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
@ -21,6 +21,11 @@ use Pock\TestUtils\PockTestCase;
|
||||
*/
|
||||
class SchemeMatcherTest extends PockTestCase
|
||||
{
|
||||
public function testNotMatches(): void
|
||||
{
|
||||
self::assertFalse((new SchemeMatcher(RequestScheme::HTTP))->matches(static::getTestRequest()));
|
||||
}
|
||||
|
||||
public function testMatches(): void
|
||||
{
|
||||
self::assertTrue((new SchemeMatcher(RequestScheme::HTTPS))->matches(static::getTestRequest()));
|
||||
|
@ -22,6 +22,7 @@ class UriMatcherTest extends PockTestCase
|
||||
{
|
||||
public function testMatches(): void
|
||||
{
|
||||
self::assertFalse((new UriMatcher('https://test.com'))->matches(static::getTestRequest()));
|
||||
self::assertTrue((new UriMatcher(self::TEST_URI))->matches(static::getTestRequest()));
|
||||
self::assertTrue((new UriMatcher(static::getPsr17Factory()->createUri(self::TEST_URI)))
|
||||
->matches(static::getTestRequest()));
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.3
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category PockBuilderTest
|
||||
* @package Pock\Tests
|
||||
@ -11,9 +11,13 @@ namespace Pock\Tests;
|
||||
|
||||
use Pock\Enum\RequestMethod;
|
||||
use Pock\Enum\RequestScheme;
|
||||
use Pock\Exception\UniversalMockException;
|
||||
use Pock\Exception\UnsupportedRequestException;
|
||||
use Pock\PockBuilder;
|
||||
use Pock\TestUtils\PockTestCase;
|
||||
use Psr\Http\Client\ClientExceptionInterface;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* Class PockBuilderTest
|
||||
@ -27,7 +31,179 @@ class PockBuilderTest extends PockTestCase
|
||||
{
|
||||
$this->expectException(UnsupportedRequestException::class);
|
||||
(new PockBuilder())->getClient()->sendRequest(self::getPsr17Factory()
|
||||
->createRequest(RequestMethod::GET, 'https://example.com'));
|
||||
->createRequest(RequestMethod::GET, self::TEST_URI));
|
||||
}
|
||||
|
||||
public function testThrowException(): void
|
||||
{
|
||||
$this->expectException(ClientExceptionInterface::class);
|
||||
|
||||
$builder = new PockBuilder();
|
||||
$builder->matchMethod(RequestMethod::GET)
|
||||
->matchScheme(RequestScheme::HTTPS)
|
||||
->matchHost(self::TEST_HOST)
|
||||
->throwException(new UniversalMockException('Boom!'));
|
||||
|
||||
$builder->getClient()->sendRequest(
|
||||
self::getPsr17Factory()->createRequest(RequestMethod::GET, self::TEST_URI)
|
||||
);
|
||||
}
|
||||
|
||||
public function testMatchHeader(): void
|
||||
{
|
||||
$builder = new PockBuilder();
|
||||
$builder->matchMethod(RequestMethod::GET)
|
||||
->matchScheme(RequestScheme::HTTPS)
|
||||
->matchHost(self::TEST_HOST)
|
||||
->matchHeader('Authorization', 'Token token')
|
||||
->reply(200)
|
||||
->withHeader('Content-Type', 'text/plain')
|
||||
->withBody('Successful');
|
||||
|
||||
$response = $builder->getClient()->sendRequest(
|
||||
self::getPsr17Factory()
|
||||
->createRequest(RequestMethod::GET, self::TEST_URI)
|
||||
->withHeader('Authorization', 'Token token')
|
||||
);
|
||||
|
||||
self::assertEquals(200, $response->getStatusCode());
|
||||
self::assertEquals(['Content-Type' => ['text/plain']], $response->getHeaders());
|
||||
self::assertEquals('Successful', $response->getBody()->getContents());
|
||||
}
|
||||
|
||||
public function testMatchHeaders(): void
|
||||
{
|
||||
$builder = new PockBuilder();
|
||||
$builder->matchMethod(RequestMethod::GET)
|
||||
->matchScheme(RequestScheme::HTTPS)
|
||||
->matchHost(self::TEST_HOST)
|
||||
->matchHeaders(['Authorization' => 'Token token'])
|
||||
->reply(200)
|
||||
->withHeader('Content-Type', 'text/plain')
|
||||
->withBody('Successful');
|
||||
|
||||
$response = $builder->getClient()->sendRequest(
|
||||
self::getPsr17Factory()
|
||||
->createRequest(RequestMethod::GET, self::TEST_URI)
|
||||
->withHeader('Authorization', 'Token token')
|
||||
);
|
||||
|
||||
self::assertEquals(200, $response->getStatusCode());
|
||||
self::assertEquals(['Content-Type' => ['text/plain']], $response->getHeaders());
|
||||
self::assertEquals('Successful', $response->getBody()->getContents());
|
||||
}
|
||||
|
||||
public function testMatchExactHeader(): void
|
||||
{
|
||||
$builder = new PockBuilder();
|
||||
$builder->matchMethod(RequestMethod::GET)
|
||||
->matchScheme(RequestScheme::HTTPS)
|
||||
->matchHost(self::TEST_HOST)
|
||||
->matchExactHeader('Authorization', ['Token token', 'Token second_token'])
|
||||
->reply(200)
|
||||
->withHeader('Content-Type', 'text/plain')
|
||||
->withBody('Successful');
|
||||
|
||||
$response = $builder->getClient()->sendRequest(
|
||||
self::getPsr17Factory()
|
||||
->createRequest(RequestMethod::GET, self::TEST_URI)
|
||||
->withHeader('Authorization', ['Token token', 'Token second_token'])
|
||||
);
|
||||
|
||||
self::assertEquals(200, $response->getStatusCode());
|
||||
self::assertEquals(['Content-Type' => ['text/plain']], $response->getHeaders());
|
||||
self::assertEquals('Successful', $response->getBody()->getContents());
|
||||
}
|
||||
|
||||
public function testMatchHeaderLine(): void
|
||||
{
|
||||
$builder = new PockBuilder();
|
||||
$builder->matchMethod(RequestMethod::GET)
|
||||
->matchScheme(RequestScheme::HTTPS)
|
||||
->matchHost(self::TEST_HOST)
|
||||
->matchHeaderLine('Authorization', 'Token token, Token second_token')
|
||||
->reply(200)
|
||||
->withHeader('Content-Type', 'text/plain')
|
||||
->withBody('Successful');
|
||||
|
||||
$response = $builder->getClient()->sendRequest(
|
||||
self::getPsr17Factory()
|
||||
->createRequest(RequestMethod::GET, self::TEST_URI)
|
||||
->withHeader('Authorization', ['Token token', 'Token second_token'])
|
||||
);
|
||||
|
||||
self::assertEquals(200, $response->getStatusCode());
|
||||
self::assertEquals(['Content-Type' => ['text/plain']], $response->getHeaders());
|
||||
self::assertEquals('Successful', $response->getBody()->getContents());
|
||||
}
|
||||
|
||||
public function testMatchHeaderLineRegexp(): void
|
||||
{
|
||||
$builder = new PockBuilder();
|
||||
$builder->matchMethod(RequestMethod::GET)
|
||||
->matchScheme(RequestScheme::HTTPS)
|
||||
->matchHost(self::TEST_HOST)
|
||||
->matchHeaderLineRegexp('Authorization', '/^Token [a-z_]+$/')
|
||||
->reply(200)
|
||||
->withHeader('Content-Type', 'text/plain')
|
||||
->withBody('Successful');
|
||||
|
||||
$response = $builder->getClient()->sendRequest(
|
||||
self::getPsr17Factory()
|
||||
->createRequest(RequestMethod::GET, self::TEST_URI)
|
||||
->withHeader('Authorization', 'Token token')
|
||||
);
|
||||
|
||||
self::assertEquals(200, $response->getStatusCode());
|
||||
self::assertEquals(['Content-Type' => ['text/plain']], $response->getHeaders());
|
||||
self::assertEquals('Successful', $response->getBody()->getContents());
|
||||
}
|
||||
|
||||
public function testMatchPathResponse(): void
|
||||
{
|
||||
$builder = new PockBuilder();
|
||||
$builder->matchMethod(RequestMethod::GET)
|
||||
->matchScheme(RequestScheme::HTTPS)
|
||||
->matchHost(self::TEST_HOST)
|
||||
->matchPath('/test')
|
||||
->reply(403)
|
||||
->withHeader('Content-Type', 'text/plain')
|
||||
->withBody('Forbidden');
|
||||
|
||||
$response = $builder->getClient()->sendRequest(
|
||||
self::getPsr17Factory()
|
||||
->createRequest(RequestMethod::GET, self::TEST_URI)
|
||||
->withUri(self::getPsr17Factory()->createUri(self::TEST_URI . 'test'))
|
||||
);
|
||||
|
||||
self::assertEquals(403, $response->getStatusCode());
|
||||
self::assertEquals(['Content-Type' => ['text/plain']], $response->getHeaders());
|
||||
self::assertEquals('Forbidden', $response->getBody()->getContents());
|
||||
}
|
||||
|
||||
public function testMatchCallback(): void
|
||||
{
|
||||
$builder = new PockBuilder();
|
||||
$builder->matchMethod(RequestMethod::GET)
|
||||
->matchScheme(RequestScheme::HTTPS)
|
||||
->matchHost(self::TEST_HOST)
|
||||
->matchPath('/test')
|
||||
->matchCallback(static function (RequestInterface $request) {
|
||||
return '' === $request->getUri()->getQuery();
|
||||
})
|
||||
->reply(403)
|
||||
->withHeader('Content-Type', 'text/plain')
|
||||
->withBody('Forbidden');
|
||||
|
||||
$response = $builder->getClient()->sendRequest(
|
||||
self::getPsr17Factory()
|
||||
->createRequest(RequestMethod::GET, self::TEST_URI)
|
||||
->withUri(self::getPsr17Factory()->createUri(self::TEST_URI . 'test'))
|
||||
);
|
||||
|
||||
self::assertEquals(403, $response->getStatusCode());
|
||||
self::assertEquals(['Content-Type' => ['text/plain']], $response->getHeaders());
|
||||
self::assertEquals('Forbidden', $response->getBody()->getContents());
|
||||
}
|
||||
|
||||
public function testTextResponse(): void
|
||||
@ -35,13 +211,14 @@ class PockBuilderTest extends PockTestCase
|
||||
$builder = new PockBuilder();
|
||||
$builder->matchMethod(RequestMethod::GET)
|
||||
->matchScheme(RequestScheme::HTTPS)
|
||||
->matchHost('example.com')
|
||||
->matchHost(self::TEST_HOST)
|
||||
->reply(403)
|
||||
->withHeader('Content-Type', 'text/plain')
|
||||
->withBody('Forbidden');
|
||||
|
||||
$response = $builder->getClient()->sendRequest(self::getPsr17Factory()
|
||||
->createRequest(RequestMethod::GET, 'https://example.com'));
|
||||
$response = $builder->getClient()->sendRequest(
|
||||
self::getPsr17Factory()->createRequest(RequestMethod::GET, self::TEST_URI)
|
||||
);
|
||||
|
||||
self::assertEquals(403, $response->getStatusCode());
|
||||
self::assertEquals(['Content-Type' => ['text/plain']], $response->getHeaders());
|
||||
@ -53,13 +230,14 @@ class PockBuilderTest extends PockTestCase
|
||||
$builder = new PockBuilder();
|
||||
$builder->matchMethod(RequestMethod::GET)
|
||||
->matchScheme(RequestScheme::HTTPS)
|
||||
->matchHost('example.com')
|
||||
->matchHost(self::TEST_HOST)
|
||||
->reply(403)
|
||||
->withHeader('Content-Type', 'application/json')
|
||||
->withJson(['error' => 'Forbidden']);
|
||||
|
||||
$response = $builder->getClient()->sendRequest(self::getPsr17Factory()
|
||||
->createRequest(RequestMethod::GET, 'https://example.com'));
|
||||
$response = $builder->getClient()->sendRequest(
|
||||
self::getPsr17Factory()->createRequest(RequestMethod::GET, self::TEST_URI)
|
||||
);
|
||||
|
||||
self::assertEquals(403, $response->getStatusCode());
|
||||
self::assertEquals(['Content-Type' => ['application/json']], $response->getHeaders());
|
||||
@ -80,16 +258,151 @@ EOF;
|
||||
$builder = new PockBuilder();
|
||||
$builder->matchMethod(RequestMethod::GET)
|
||||
->matchScheme(RequestScheme::HTTPS)
|
||||
->matchHost('example.com')
|
||||
->matchHost(self::TEST_HOST)
|
||||
->reply(403)
|
||||
->withHeader('Content-Type', 'text/xml')
|
||||
->withXml(['error' => 'Forbidden']);
|
||||
|
||||
$response = $builder->getClient()->sendRequest(self::getPsr17Factory()
|
||||
->createRequest(RequestMethod::GET, 'https://example.com'));
|
||||
$response = $builder->getClient()->sendRequest(
|
||||
self::getPsr17Factory()->createRequest(RequestMethod::GET, self::TEST_URI)
|
||||
);
|
||||
|
||||
self::assertEquals(403, $response->getStatusCode());
|
||||
self::assertEquals(['Content-Type' => ['text/xml']], $response->getHeaders());
|
||||
self::assertEquals($xml, $response->getBody()->getContents());
|
||||
}
|
||||
|
||||
public function testSeveralMocks(): void
|
||||
{
|
||||
$builder = new PockBuilder();
|
||||
|
||||
$builder->matchMethod(RequestMethod::GET)
|
||||
->matchScheme(RequestScheme::HTTPS)
|
||||
->matchHost(self::TEST_HOST)
|
||||
->matchPath('/ping')
|
||||
->matchHeader('Authorization', 'Token token_1')
|
||||
->repeat(2)
|
||||
->reply(200)
|
||||
->withHeader('Content-Type', 'text/plain')
|
||||
->withBody('First token');
|
||||
|
||||
$builder->matchMethod(RequestMethod::GET)
|
||||
->matchScheme(RequestScheme::HTTPS)
|
||||
->matchHost(self::TEST_HOST)
|
||||
->matchPath('/ping')
|
||||
->matchHeader('Authorization', 'Token token_2')
|
||||
->reply(200)
|
||||
->withHeader('Content-Type', 'text/plain')
|
||||
->withBody('Second token');
|
||||
|
||||
$builder->matchMethod(RequestMethod::GET)
|
||||
->matchScheme(RequestScheme::HTTPS)
|
||||
->matchHost(self::TEST_HOST)
|
||||
->matchPath('/ping')
|
||||
->matchExactQuery(['param1' => 'value'])
|
||||
->matchHeader('Authorization', 'Token token_2')
|
||||
->reply(200)
|
||||
->withHeader('Content-Type', 'text/plain')
|
||||
->withBody('Second token (exact query params)');
|
||||
|
||||
$builder->matchMethod(RequestMethod::GET)
|
||||
->matchScheme(RequestScheme::HTTPS)
|
||||
->matchHost(self::TEST_HOST)
|
||||
->matchPath('/ping')
|
||||
->matchQuery(['param1' => 'value'])
|
||||
->matchHeader('Authorization', 'Token token_2')
|
||||
->reply(200)
|
||||
->withHeader('Content-Type', 'text/plain')
|
||||
->withBody('Second token (query params)');
|
||||
|
||||
$builder->matchMethod(RequestMethod::POST)
|
||||
->matchScheme(RequestScheme::HTTPS)
|
||||
->matchHost(self::TEST_HOST)
|
||||
->matchPath('/ping')
|
||||
->matchHeaders([
|
||||
'Authorization' => 'Token token_2',
|
||||
'Content-Type' => 'application/json'
|
||||
])
|
||||
->matchJsonBody(['field' => 'value'])
|
||||
->reply(200)
|
||||
->withHeader('Content-Type', 'text/plain')
|
||||
->withBody('Second token (post json)');
|
||||
|
||||
$builder->matchMethod(RequestMethod::POST)
|
||||
->matchScheme(RequestScheme::HTTPS)
|
||||
->matchHost(self::TEST_HOST)
|
||||
->matchPath('/ping')
|
||||
->matchHeader('Authorization', 'Token token_2')
|
||||
->matchBody('test data')
|
||||
->reply(200)
|
||||
->withHeader('Content-Type', 'text/plain')
|
||||
->withBody('Second token (post)');
|
||||
|
||||
$client = $builder->getClient();
|
||||
|
||||
for ($i = 0; $i < 2; $i++) {
|
||||
$response = $client->sendRequest(
|
||||
self::getPsr17Factory()
|
||||
->createRequest(RequestMethod::GET, self::TEST_URI)
|
||||
->withHeader('Authorization', 'Token token_1')
|
||||
->withUri(self::getPsr17Factory()->createUri(self::TEST_URI . 'ping'))
|
||||
);
|
||||
self::assertEquals(
|
||||
'First token',
|
||||
$response->getBody()->getContents(),
|
||||
'Attempt #' . ($i + 1) . ' for repeatable mock'
|
||||
);
|
||||
}
|
||||
|
||||
$response = $client->sendRequest(
|
||||
self::getPsr17Factory()
|
||||
->createRequest(RequestMethod::GET, self::TEST_URI)
|
||||
->withHeader('Authorization', 'Token token_2')
|
||||
->withUri(self::getPsr17Factory()->createUri(self::TEST_URI . 'ping'))
|
||||
);
|
||||
self::assertEquals('Second token', $response->getBody()->getContents());
|
||||
|
||||
$response = $client->sendRequest(
|
||||
self::getPsr17Factory()
|
||||
->createRequest(RequestMethod::GET, self::TEST_URI)
|
||||
->withHeader('Authorization', 'Token token_2')
|
||||
->withUri(
|
||||
self::getPsr17Factory()
|
||||
->createUri(self::TEST_URI . 'ping')
|
||||
->withQuery('param1=value')
|
||||
)
|
||||
);
|
||||
self::assertEquals('Second token (exact query params)', $response->getBody()->getContents());
|
||||
|
||||
$response = $client->sendRequest(
|
||||
self::getPsr17Factory()
|
||||
->createRequest(RequestMethod::GET, self::TEST_URI)
|
||||
->withHeader('Authorization', 'Token token_2')
|
||||
->withUri(
|
||||
self::getPsr17Factory()
|
||||
->createUri(self::TEST_URI . 'ping')
|
||||
->withQuery('param1=value¶m2=value')
|
||||
)
|
||||
);
|
||||
self::assertEquals('Second token (query params)', $response->getBody()->getContents());
|
||||
|
||||
$response = $client->sendRequest(
|
||||
self::getPsr17Factory()
|
||||
->createRequest(RequestMethod::POST, self::TEST_URI)
|
||||
->withHeader('Authorization', 'Token token_2')
|
||||
->withHeader('Content-Type', 'application/json')
|
||||
->withUri(self::getPsr17Factory()->createUri(self::TEST_URI . 'ping'))
|
||||
->withBody(self::getPsr17Factory()->createStream('{"field": "value"}'))
|
||||
);
|
||||
self::assertEquals('Second token (post json)', $response->getBody()->getContents());
|
||||
|
||||
$response = $client->sendRequest(
|
||||
self::getPsr17Factory()
|
||||
->createRequest(RequestMethod::POST, self::TEST_URI)
|
||||
->withHeader('Authorization', 'Token token_2')
|
||||
->withUri(self::getPsr17Factory()->createUri(self::TEST_URI . 'ping'))
|
||||
->withBody(self::getPsr17Factory()->createStream('test data'))
|
||||
);
|
||||
self::assertEquals('Second token (post)', $response->getBody()->getContents());
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.3
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category PockResponseBuilderTest
|
||||
* @package Pock\Tests
|
||||
@ -157,7 +157,7 @@ class PockResponseBuilderTest extends PockTestCase
|
||||
return [
|
||||
[1, '1'],
|
||||
['{}', '{}'],
|
||||
[['key' => 'value'], '{"key":"value"}'],
|
||||
[['key' => 'pattern'], '{"key":"pattern"}'],
|
||||
[new SimpleObjectJsonSerializable(), SimpleObjectJsonSerializable::JSON],
|
||||
[new SimpleObject(), SimpleObject::JSON]
|
||||
];
|
||||
@ -176,8 +176,8 @@ class PockResponseBuilderTest extends PockTestCase
|
||||
EOF;
|
||||
|
||||
return [
|
||||
[SimpleObject::XML, SimpleObject::XML],
|
||||
[new SimpleObject(), SimpleObject::XML],
|
||||
[SimpleObject::JMS_XML, SimpleObject::JMS_XML],
|
||||
[new SimpleObject(), SimpleObject::JMS_XML],
|
||||
[[new SimpleObject()], $xmlArray]
|
||||
];
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.3
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category EmptyJsonSerializerDecorator
|
||||
* @package Pock\TestUtils
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.3
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category EmptyXmlSerializerDecorator
|
||||
* @package Pock\TestUtils
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.3
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category PockBuilderTestCase
|
||||
* @package Pock\TestUtils
|
||||
|
@ -32,11 +32,13 @@ abstract class PockTestCase extends TestCase
|
||||
protected static $psr17Factory;
|
||||
|
||||
/**
|
||||
* @param string|null $method
|
||||
*
|
||||
* @return \Psr\Http\Message\RequestInterface
|
||||
*/
|
||||
protected static function getTestRequest(): RequestInterface
|
||||
protected static function getTestRequest(?string $method = null): RequestInterface
|
||||
{
|
||||
return static::getPsr17Factory()->createRequest(static::TEST_METHOD, static::TEST_URI);
|
||||
return static::getPsr17Factory()->createRequest($method ?? static::TEST_METHOD, static::TEST_URI);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -20,13 +20,19 @@ use JMS\Serializer\Annotation as JMS;
|
||||
class SimpleObject
|
||||
{
|
||||
public const JSON = '{"field":"test"}';
|
||||
public const XML = <<<'EOF'
|
||||
public const JMS_XML = <<<'EOF'
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<result>
|
||||
<field><![CDATA[test]]></field>
|
||||
</result>
|
||||
|
||||
EOF;
|
||||
public const SYMFONY_XML = <<<'EOF'
|
||||
<?xml version="1.0"?>
|
||||
<response><field>test</field></response>
|
||||
|
||||
EOF;
|
||||
|
||||
|
||||
/**
|
||||
* @var string
|
||||
@ -34,5 +40,5 @@ EOF;
|
||||
* @JMS\Type("string")
|
||||
* @JMS\SerializedName("field")
|
||||
*/
|
||||
protected $field = 'test';
|
||||
public $field = 'test';
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP 7.3
|
||||
* PHP 7.1
|
||||
*
|
||||
* @category SimpleObjectJsonSerializable
|
||||
* @package Pock\TestUtils
|
||||
|
Loading…
Reference in New Issue
Block a user