mirror of
https://github.com/Neur0toxine/pock.git
synced 2024-12-01 09:26:02 +03:00
regexp, form-data and multipart form request matchers
This commit is contained in:
parent
064b07940c
commit
dd441f54db
@ -122,9 +122,9 @@ In order to use unsupported serializer you should create a decorator which imple
|
||||
- [x] `replyWithCallback` - reply using specified callback.
|
||||
- [x] `replyWithFactory` - reply using specified response factory (provide corresponding interface).
|
||||
- [x] Compare XML bodies using `DOMDocument`, fallback to text comparison in case of problems.
|
||||
- [ ] Regexp matchers for body, query and path.
|
||||
- [ ] Form Data body matcher (partial & exact)
|
||||
- [ ] Multipart form body matcher (partial & exact)
|
||||
- [x] Regexp matchers for body, query, URI and path.
|
||||
- [x] Form Data body matcher (partial & exact)
|
||||
- [x] Multipart form body matcher (just like callback matcher but parses the body as a multipart form data)
|
||||
- [ ] `symfony/http-client` support.
|
||||
- [ ] Real network response for mocked & unmatched requests.
|
||||
- [ ] Document everything (with examples if it’s feasible).
|
||||
|
@ -36,7 +36,8 @@
|
||||
"psr/http-client": "^1.0",
|
||||
"psr/http-message": "^1.0",
|
||||
"php-http/httplug": "^1.0 || ^2.0",
|
||||
"nyholm/psr7": "^1.4"
|
||||
"nyholm/psr7": "^1.4",
|
||||
"riverline/multipart-parser": "^2.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"squizlabs/php_codesniffer": "^3.6",
|
||||
@ -47,7 +48,8 @@
|
||||
"jms/serializer": "^2 | ^3.12",
|
||||
"symfony/phpunit-bridge": "^5.2",
|
||||
"symfony/serializer": "^5.2",
|
||||
"symfony/property-access": "^5.2"
|
||||
"symfony/property-access": "^5.2",
|
||||
"php-http/multipart-stream-builder": "^1.2"
|
||||
},
|
||||
"provide": {
|
||||
"psr/http-client-implementation": "1.0",
|
||||
|
41
src/Matchers/AbstractRegExpMatcher.php
Normal file
41
src/Matchers/AbstractRegExpMatcher.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP version 7.3
|
||||
*
|
||||
* @category AbstractRegExpMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Matchers;
|
||||
|
||||
/**
|
||||
* Class AbstractRegExpMatcher
|
||||
*
|
||||
* @category AbstractRegExpMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
abstract class AbstractRegExpMatcher implements RequestMatcherInterface
|
||||
{
|
||||
/** @var string */
|
||||
protected $expression;
|
||||
|
||||
/** @var int */
|
||||
protected $flags = 0;
|
||||
|
||||
/**
|
||||
* @param string $expression
|
||||
* @param int $flags
|
||||
*/
|
||||
public function __construct(string $expression, int $flags = 0)
|
||||
{
|
||||
$this->expression = $expression;
|
||||
$this->flags = $flags;
|
||||
}
|
||||
|
||||
protected function matchRegExp(string $content): bool
|
||||
{
|
||||
$matches = [];
|
||||
return 1 === preg_match($this->expression, $content, $matches, $this->flags);
|
||||
}
|
||||
}
|
40
src/Matchers/ExactFormDataMatcher.php
Normal file
40
src/Matchers/ExactFormDataMatcher.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP version 7.3
|
||||
*
|
||||
* @category ExactFormDataMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Matchers;
|
||||
|
||||
use Pock\Comparator\ComparatorLocator;
|
||||
use Pock\Comparator\RecursiveArrayComparator;
|
||||
use Pock\Traits\SeekableStreamDataExtractor;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Class ExactFormDataMatcher
|
||||
*
|
||||
* @category ExactFormDataMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
class ExactFormDataMatcher extends QueryMatcher
|
||||
{
|
||||
use SeekableStreamDataExtractor;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function matches(RequestInterface $request): bool
|
||||
{
|
||||
$query = static::parseQuery(static::getStreamData($request->getBody()));
|
||||
|
||||
if (empty($query)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ComparatorLocator::get(RecursiveArrayComparator::class)->compare($this->query, $query);
|
||||
}
|
||||
}
|
40
src/Matchers/FormDataMatcher.php
Normal file
40
src/Matchers/FormDataMatcher.php
Normal file
@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP version 7.3
|
||||
*
|
||||
* @category FormDataMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Matchers;
|
||||
|
||||
use Pock\Comparator\ComparatorLocator;
|
||||
use Pock\Comparator\RecursiveLtrArrayComparator;
|
||||
use Pock\Traits\SeekableStreamDataExtractor;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Class FormDataMatcher
|
||||
*
|
||||
* @category FormDataMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
class FormDataMatcher extends QueryMatcher
|
||||
{
|
||||
use SeekableStreamDataExtractor;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function matches(RequestInterface $request): bool
|
||||
{
|
||||
$query = static::parseQuery(static::getStreamData($request->getBody()));
|
||||
|
||||
if (empty($query)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ComparatorLocator::get(RecursiveLtrArrayComparator::class)->compare($this->query, $query);
|
||||
}
|
||||
}
|
57
src/Matchers/MultipartFormDataMatcher.php
Normal file
57
src/Matchers/MultipartFormDataMatcher.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP version 7.1
|
||||
*
|
||||
* @category MultipartFormDataMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Matchers;
|
||||
|
||||
use InvalidArgumentException;
|
||||
use Pock\Traits\SeekableStreamDataExtractor;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Riverline\MultiPartParser\StreamedPart;
|
||||
use Riverline\MultiPartParser\Converters\PSR7;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* Class MultipartFormDataMatcher
|
||||
*
|
||||
* @category MultipartFormDataMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
class MultipartFormDataMatcher implements RequestMatcherInterface
|
||||
{
|
||||
use SeekableStreamDataExtractor;
|
||||
|
||||
/** @var callable */
|
||||
private $callback;
|
||||
|
||||
/**
|
||||
* MultipartFormDataMatcher constructor.
|
||||
*
|
||||
* @param callable $callback Accepts Riverline\MultiPartParser\StreamedPart as an argument, returns true if matched.
|
||||
*/
|
||||
public function __construct(callable $callback)
|
||||
{
|
||||
$this->callback = $callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @SuppressWarnings(PHPMD.StaticAccess)
|
||||
*/
|
||||
public function matches(RequestInterface $request): bool
|
||||
{
|
||||
try {
|
||||
$part = PSR7::convert($request);
|
||||
$request->getBody()->rewind();
|
||||
} catch (InvalidArgumentException $exception) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return call_user_func($this->callback, $part);
|
||||
}
|
||||
}
|
32
src/Matchers/RegExpBodyMatcher.php
Normal file
32
src/Matchers/RegExpBodyMatcher.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP version 7.3
|
||||
*
|
||||
* @category RegExpBodyMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Matchers;
|
||||
|
||||
use Pock\Traits\SeekableStreamDataExtractor;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Class RegExpBodyMatcher
|
||||
*
|
||||
* @category RegExpBodyMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
class RegExpBodyMatcher extends AbstractRegExpMatcher
|
||||
{
|
||||
use SeekableStreamDataExtractor;
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function matches(RequestInterface $request): bool
|
||||
{
|
||||
return $this->matchRegExp(static::getStreamData($request->getBody()));
|
||||
}
|
||||
}
|
29
src/Matchers/RegExpPathMatcher.php
Normal file
29
src/Matchers/RegExpPathMatcher.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP version 7.3
|
||||
*
|
||||
* @category RegExpPathMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Matchers;
|
||||
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Class RegExpPathMatcher
|
||||
*
|
||||
* @category RegExpPathMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
class RegExpPathMatcher extends AbstractRegExpMatcher
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function matches(RequestInterface $request): bool
|
||||
{
|
||||
return $this->matchRegExp($request->getUri()->getPath());
|
||||
}
|
||||
}
|
29
src/Matchers/RegExpQueryMatcher.php
Normal file
29
src/Matchers/RegExpQueryMatcher.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP version 7.3
|
||||
*
|
||||
* @category RegExpQueryMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Matchers;
|
||||
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Class RegExpQueryMatcher
|
||||
*
|
||||
* @category RegExpQueryMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
class RegExpQueryMatcher extends AbstractRegExpMatcher
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function matches(RequestInterface $request): bool
|
||||
{
|
||||
return $this->matchRegExp($request->getUri()->getQuery());
|
||||
}
|
||||
}
|
29
src/Matchers/RegExpUriMatcher.php
Normal file
29
src/Matchers/RegExpUriMatcher.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP version 7.3
|
||||
*
|
||||
* @category RegExpUriMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Matchers;
|
||||
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
|
||||
/**
|
||||
* Class RegExpUriMatcher
|
||||
*
|
||||
* @category RegExpUriMatcher
|
||||
* @package Pock\Matchers
|
||||
*/
|
||||
class RegExpUriMatcher extends AbstractRegExpMatcher
|
||||
{
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function matches(RequestInterface $request): bool
|
||||
{
|
||||
return $this->matchRegExp((string) $request->getUri());
|
||||
}
|
||||
}
|
@ -9,22 +9,20 @@
|
||||
|
||||
namespace Pock;
|
||||
|
||||
use Diff\ArrayComparer\StrictArrayComparer;
|
||||
use DOMDocument;
|
||||
use Pock\Enum\RequestMethod;
|
||||
use Pock\Enum\RequestScheme;
|
||||
use Pock\Exception\PockClientException;
|
||||
use Pock\Exception\PockNetworkException;
|
||||
use Pock\Exception\PockRequestException;
|
||||
use Pock\Exception\XmlException;
|
||||
use Pock\Factory\CallbackReplyFactory;
|
||||
use Pock\Factory\ReplyFactoryInterface;
|
||||
use Pock\Matchers\AnyRequestMatcher;
|
||||
use Pock\Matchers\BodyMatcher;
|
||||
use Pock\Matchers\CallbackRequestMatcher;
|
||||
use Pock\Matchers\ExactFormDataMatcher;
|
||||
use Pock\Matchers\ExactHeaderMatcher;
|
||||
use Pock\Matchers\ExactHeadersMatcher;
|
||||
use Pock\Matchers\ExactQueryMatcher;
|
||||
use Pock\Matchers\FormDataMatcher;
|
||||
use Pock\Matchers\HeaderLineMatcher;
|
||||
use Pock\Matchers\HeaderLineRegexpMatcher;
|
||||
use Pock\Matchers\HeaderMatcher;
|
||||
@ -32,9 +30,14 @@ use Pock\Matchers\HeadersMatcher;
|
||||
use Pock\Matchers\HostMatcher;
|
||||
use Pock\Matchers\JsonBodyMatcher;
|
||||
use Pock\Matchers\MethodMatcher;
|
||||
use Pock\Matchers\MultipartFormDataMatcher;
|
||||
use Pock\Matchers\MultipleMatcher;
|
||||
use Pock\Matchers\PathMatcher;
|
||||
use Pock\Matchers\QueryMatcher;
|
||||
use Pock\Matchers\RegExpBodyMatcher;
|
||||
use Pock\Matchers\RegExpPathMatcher;
|
||||
use Pock\Matchers\RegExpQueryMatcher;
|
||||
use Pock\Matchers\RegExpUriMatcher;
|
||||
use Pock\Matchers\RequestMatcherInterface;
|
||||
use Pock\Matchers\SchemeMatcher;
|
||||
use Pock\Matchers\UriMatcher;
|
||||
@ -55,6 +58,7 @@ use Throwable;
|
||||
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
||||
* @SuppressWarnings(PHPMD.TooManyPublicMethods)
|
||||
* @SuppressWarnings(PHPMD.TooManyMethods)
|
||||
* @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
|
||||
*/
|
||||
class PockBuilder
|
||||
{
|
||||
@ -169,6 +173,19 @@ class PockBuilder
|
||||
return $this->addMatcher(new UriMatcher($uri));
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches request by the whole URI using regular expression.
|
||||
*
|
||||
* @param string $expression
|
||||
* @param int $flags
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function matchUriRegExp(string $expression, int $flags = 0): self
|
||||
{
|
||||
return $this->addMatcher(new RegExpUriMatcher($expression, $flags));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
@ -262,6 +279,20 @@ class PockBuilder
|
||||
return $this->addMatcher(new PathMatcher($path));
|
||||
}
|
||||
|
||||
/**
|
||||
* Match request by its path using regular expression. This matcher doesn't care about prefix slash
|
||||
* since it's pretty easy to do it using regular expression.
|
||||
*
|
||||
* @param string $expression
|
||||
* @param int $flags
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function matchPathRegExp(string $expression, int $flags = 0): self
|
||||
{
|
||||
return $this->addMatcher(new RegExpPathMatcher($expression, $flags));
|
||||
}
|
||||
|
||||
/**
|
||||
* Match request by its query. Request can contain other query variables.
|
||||
* @see PockBuilder::matchExactQuery() if you want to match an entire query string.
|
||||
@ -275,6 +306,19 @@ class PockBuilder
|
||||
return $this->addMatcher(new QueryMatcher($query));
|
||||
}
|
||||
|
||||
/**
|
||||
* Match request by its query using regular expression.
|
||||
*
|
||||
* @param string $expression
|
||||
* @param int $flags
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function matchQueryRegExp(string $expression, int $flags = 0): self
|
||||
{
|
||||
return $this->addMatcher(new RegExpQueryMatcher($expression, $flags));
|
||||
}
|
||||
|
||||
/**
|
||||
* Match request by its query. Additional query parameters aren't allowed.
|
||||
*
|
||||
@ -287,6 +331,44 @@ class PockBuilder
|
||||
return $this->addMatcher(new ExactQueryMatcher($query));
|
||||
}
|
||||
|
||||
/**
|
||||
* Match request with form-data.
|
||||
*
|
||||
* @param array<string, mixed> $formFields
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function matchFormData(array $formFields): self
|
||||
{
|
||||
return $this->addMatcher(new FormDataMatcher($formFields));
|
||||
}
|
||||
|
||||
/**
|
||||
* Match request with form-data. Additional fields aren't allowed.
|
||||
*
|
||||
* @param array<string, mixed> $formFields
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function matchExactFormData(array $formFields): self
|
||||
{
|
||||
return $this->addMatcher(new ExactFormDataMatcher($formFields));
|
||||
}
|
||||
|
||||
/**
|
||||
* Match request multipart form data. Will not match the request if body is not multipart.
|
||||
* Uses third-party library to parse the data.
|
||||
*
|
||||
* @param callable $callback Accepts Riverline\MultiPartParser\StreamedPart as an argument, returns true if matched.
|
||||
*
|
||||
* @return self
|
||||
* @see https://github.com/Riverline/multipart-parser#usage
|
||||
*/
|
||||
public function matchMultipartFormData(callable $callback): self
|
||||
{
|
||||
return $this->addMatcher(new MultipartFormDataMatcher($callback));
|
||||
}
|
||||
|
||||
/**
|
||||
* Match entire request body.
|
||||
*
|
||||
@ -299,6 +381,19 @@ class PockBuilder
|
||||
return $this->addMatcher(new BodyMatcher($data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Match entire request body using provided regular expression.
|
||||
*
|
||||
* @param string $expression
|
||||
* @param int $flags
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function matchBodyRegExp(string $expression, int $flags = 0): self
|
||||
{
|
||||
return $this->addMatcher(new RegExpBodyMatcher($expression, $flags));
|
||||
}
|
||||
|
||||
/**
|
||||
* Match JSON request body.
|
||||
*
|
||||
@ -373,7 +468,7 @@ class PockBuilder
|
||||
* Match request using provided callback. Callback should receive RequestInterface and return boolean.
|
||||
* If returned value is true then request is matched.
|
||||
*
|
||||
* @param callable $callback
|
||||
* @param callable $callback Callable that accepts PSR-7 RequestInterface as it's first argument.
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
|
62
tests/src/Matchers/ExactFormDataMatcherTest.php
Normal file
62
tests/src/Matchers/ExactFormDataMatcherTest.php
Normal file
@ -0,0 +1,62 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP version 7.3
|
||||
*
|
||||
* @category ExactFormDataMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Tests\Matchers;
|
||||
|
||||
use Pock\Matchers\ExactFormDataMatcher;
|
||||
use Pock\TestUtils\PockTestCase;
|
||||
|
||||
/**
|
||||
* Class ExactFormDataMatcherTest
|
||||
*
|
||||
* @category ExactFormDataMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
class ExactFormDataMatcherTest extends PockTestCase
|
||||
{
|
||||
public function testInvalidData(): void
|
||||
{
|
||||
$matcher = new ExactFormDataMatcher(['field3' => 'value3']);
|
||||
$request = self::getRequestWithBody('doesn\'t look like form-data at all');
|
||||
|
||||
self::assertFalse($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testNoMatches(): void
|
||||
{
|
||||
$matcher = new ExactFormDataMatcher(['field3' => 'value3']);
|
||||
$request = self::getRequestWithBody('field1=value1&field2=value2');
|
||||
|
||||
self::assertFalse($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testNoMatchesByValue(): void
|
||||
{
|
||||
$matcher = new ExactFormDataMatcher(['field1' => 'value2']);
|
||||
$request = self::getRequestWithBody('field1=value1&field2=value2');
|
||||
|
||||
self::assertFalse($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testNoMatchesRedundantParam(): void
|
||||
{
|
||||
$matcher = new ExactFormDataMatcher(['field2' => 'value2']);
|
||||
$request = self::getRequestWithBody('field1=value1&field2=value2');
|
||||
|
||||
self::assertFalse($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testMatches(): void
|
||||
{
|
||||
$matcher = new ExactFormDataMatcher(['field1' => 'value1', 'field2' => 'value2']);
|
||||
$request = self::getRequestWithBody('field1=value1&field2=value2');
|
||||
|
||||
self::assertTrue($matcher->matches($request));
|
||||
}
|
||||
}
|
54
tests/src/Matchers/FormDataMatcherTest.php
Normal file
54
tests/src/Matchers/FormDataMatcherTest.php
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP version 7.3
|
||||
*
|
||||
* @category FormDataMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Tests\Matchers;
|
||||
|
||||
use Pock\Matchers\FormDataMatcher;
|
||||
use Pock\TestUtils\PockTestCase;
|
||||
|
||||
/**
|
||||
* Class FormDataMatcherTest
|
||||
*
|
||||
* @category FormDataMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
class FormDataMatcherTest extends PockTestCase
|
||||
{
|
||||
public function testInvalidData(): void
|
||||
{
|
||||
$matcher = new FormDataMatcher(['field3' => 'value3']);
|
||||
$request = self::getRequestWithBody('doesn\'t look like form-data at all');
|
||||
|
||||
self::assertFalse($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testNoMatches(): void
|
||||
{
|
||||
$matcher = new FormDataMatcher(['field3' => 'value3']);
|
||||
$request = self::getRequestWithBody('field1=value1&field2=value2');
|
||||
|
||||
self::assertFalse($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testNoMatchesByValue(): void
|
||||
{
|
||||
$matcher = new FormDataMatcher(['field1' => 'value2']);
|
||||
$request = self::getRequestWithBody('field1=value1&field2=value2');
|
||||
|
||||
self::assertFalse($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testMatches(): void
|
||||
{
|
||||
$matcher = new FormDataMatcher(['field2' => 'value2']);
|
||||
$request = self::getRequestWithBody('field1=value1&field2=value2');
|
||||
|
||||
self::assertTrue($matcher->matches($request));
|
||||
}
|
||||
}
|
59
tests/src/Matchers/MultipartFormDataMatcherTest.php
Normal file
59
tests/src/Matchers/MultipartFormDataMatcherTest.php
Normal file
@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP version 7.3
|
||||
*
|
||||
* @category MultipartFormDataMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Tests\Matchers;
|
||||
|
||||
use Http\Message\MultipartStream\MultipartStreamBuilder;
|
||||
use Pock\Matchers\MultipartFormDataMatcher;
|
||||
use Pock\TestUtils\PockTestCase;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Riverline\MultiPartParser\StreamedPart;
|
||||
|
||||
/**
|
||||
* Class MultipartFormDataMatcherTest
|
||||
*
|
||||
* @category MultipartFormDataMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
class MultipartFormDataMatcherTest extends PockTestCase
|
||||
{
|
||||
public function testNoMatchesNotMultipart(): void
|
||||
{
|
||||
$matcher = new MultipartFormDataMatcher(function (StreamedPart $part) {
|
||||
return $part->isMultiPart();
|
||||
});
|
||||
|
||||
self::assertFalse($matcher->matches(self::getTestRequest()));
|
||||
self::assertFalse($matcher->matches(self::getRequestWithBody('param=value¶m2=value')));
|
||||
}
|
||||
|
||||
public function testMatches(): void
|
||||
{
|
||||
$matcher = new MultipartFormDataMatcher(function (StreamedPart $part) {
|
||||
return $part->isMultiPart() &&
|
||||
1 === count($part->getPartsByName('param1')) &&
|
||||
1 === count($part->getPartsByName('param2')) &&
|
||||
'value1' === $part->getPartsByName('param1')[0]->getBody() &&
|
||||
'value2' === $part->getPartsByName('param2')[0]->getBody() &&
|
||||
'text/plain' === $part->getPartsByName('param1')[0]->getHeader('Content-Type');
|
||||
});
|
||||
$builder = new MultipartStreamBuilder(self::getPsr17Factory());
|
||||
$builder->addResource('param1', 'value1', ['headers' => ['Content-Type' => 'text/plain']])
|
||||
->addResource('param2', 'value2');
|
||||
|
||||
self::assertTrue($matcher->matches(self::getMultipartRequest($builder)));
|
||||
}
|
||||
|
||||
private static function getMultipartRequest(MultipartStreamBuilder $builder): RequestInterface
|
||||
{
|
||||
return self::getPsr17Factory()->createRequest('POST', 'https://example.com')
|
||||
->withHeader('Content-Type', 'multipart/form-data; boundary="' . $builder->getBoundary() . '"')
|
||||
->withBody($builder->build());
|
||||
}
|
||||
}
|
38
tests/src/Matchers/RegExpBodyMatcherTest.php
Normal file
38
tests/src/Matchers/RegExpBodyMatcherTest.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP version 7.3
|
||||
*
|
||||
* @category RegExpBodyMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Tests\Matchers;
|
||||
|
||||
use Pock\Matchers\RegExpBodyMatcher;
|
||||
use Pock\TestUtils\PockTestCase;
|
||||
|
||||
/**
|
||||
* Class RegExpBodyMatcherTest
|
||||
*
|
||||
* @category RegExpBodyMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
class RegExpBodyMatcherTest extends PockTestCase
|
||||
{
|
||||
public function testNoMatches(): void
|
||||
{
|
||||
$matcher = new RegExpBodyMatcher('/\d+-\d+/m');
|
||||
$request = static::getRequestWithBody('test unmatchable request');
|
||||
|
||||
self::assertFalse($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testMatches(): void
|
||||
{
|
||||
$matcher = new RegExpBodyMatcher('/\d+-\d+/m', PREG_UNMATCHED_AS_NULL);
|
||||
$request = static::getRequestWithBody('23-900');
|
||||
|
||||
self::assertTrue($matcher->matches($request));
|
||||
}
|
||||
}
|
38
tests/src/Matchers/RegExpPathMatcherTest.php
Normal file
38
tests/src/Matchers/RegExpPathMatcherTest.php
Normal file
@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP version 7.3
|
||||
*
|
||||
* @category RegExpPathMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Tests\Matchers;
|
||||
|
||||
use Pock\Matchers\RegExpPathMatcher;
|
||||
use Pock\TestUtils\PockTestCase;
|
||||
|
||||
/**
|
||||
* Class RegExpPathMatcherTest
|
||||
*
|
||||
* @category RegExpPathMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
class RegExpPathMatcherTest extends PockTestCase
|
||||
{
|
||||
public function testNoMatches(): void
|
||||
{
|
||||
$matcher = new RegExpPathMatcher('/\/?\d+-\d+/m');
|
||||
$request = static::getTestRequest()->withUri(static::getPsr17Factory()->createUri('https://test.com/test'));
|
||||
|
||||
self::assertFalse($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testMatches(): void
|
||||
{
|
||||
$matcher = new RegExpPathMatcher('/\d+-\d+/m', PREG_UNMATCHED_AS_NULL);
|
||||
$request = static::getTestRequest()->withUri(static::getPsr17Factory()->createUri('https://test.com/23-900'));
|
||||
|
||||
self::assertTrue($matcher->matches($request));
|
||||
}
|
||||
}
|
44
tests/src/Matchers/RegExpQueryMatcherTest.php
Normal file
44
tests/src/Matchers/RegExpQueryMatcherTest.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP version 7.3
|
||||
*
|
||||
* @category RegExpQueryMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Tests\Matchers;
|
||||
|
||||
use Pock\Matchers\RegExpQueryMatcher;
|
||||
use Pock\TestUtils\PockTestCase;
|
||||
|
||||
/**
|
||||
* Class RegExpQueryMatcherTest
|
||||
*
|
||||
* @category RegExpQueryMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
class RegExpQueryMatcherTest extends PockTestCase
|
||||
{
|
||||
public function testNoMatches(): void
|
||||
{
|
||||
$matcher = new RegExpQueryMatcher('/\d+-\d+/m');
|
||||
$request = static::getTestRequest()->withUri(
|
||||
static::getPsr17Factory()->createUri('https://test.com')
|
||||
->withQuery('param=value')
|
||||
);
|
||||
|
||||
self::assertFalse($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testMatches(): void
|
||||
{
|
||||
$matcher = new RegExpQueryMatcher('/\d+-\d+/m', PREG_UNMATCHED_AS_NULL);
|
||||
$request = static::getTestRequest()->withUri(
|
||||
static::getPsr17Factory()->createUri('https://test.com')
|
||||
->withQuery('param=23-900')
|
||||
);
|
||||
|
||||
self::assertTrue($matcher->matches($request));
|
||||
}
|
||||
}
|
41
tests/src/Matchers/RegExpUriMatcherTest.php
Normal file
41
tests/src/Matchers/RegExpUriMatcherTest.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* PHP version 7.3
|
||||
*
|
||||
* @category RegExpUriMatcherTest
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
|
||||
namespace Pock\Tests\Matchers;
|
||||
|
||||
use Pock\Matchers\RegExpUriMatcher;
|
||||
use Pock\TestUtils\PockTestCase;
|
||||
|
||||
/**
|
||||
* Class RegExpUriMatcherTest
|
||||
*
|
||||
* @category RegExpUriMatcher
|
||||
* @package Pock\Tests\Matchers
|
||||
*/
|
||||
class RegExpUriMatcherTest extends PockTestCase
|
||||
{
|
||||
public function testNoMatches(): void
|
||||
{
|
||||
$matcher = new RegExpUriMatcher('/https\:\/\/\w+\.com\/\d+-\d+\?param=\d+-\d+/m');
|
||||
$request = static::getTestRequest();
|
||||
|
||||
self::assertFalse($matcher->matches($request));
|
||||
}
|
||||
|
||||
public function testMatches(): void
|
||||
{
|
||||
$matcher = new RegExpUriMatcher('/https\:\/\/\w+\.com\/\d+-\d+\?param=\d+-\d+/m', PREG_UNMATCHED_AS_NULL);
|
||||
$request = static::getTestRequest()->withUri(
|
||||
static::getPsr17Factory()->createUri('https://example.com/23-900')
|
||||
->withQuery('param=23-900')
|
||||
);
|
||||
|
||||
self::assertTrue($matcher->matches($request));
|
||||
}
|
||||
}
|
@ -10,6 +10,7 @@
|
||||
namespace Pock\Tests;
|
||||
|
||||
use DOMDocument;
|
||||
use Http\Message\MultipartStream\MultipartStreamBuilder;
|
||||
use Pock\Enum\RequestMethod;
|
||||
use Pock\Enum\RequestScheme;
|
||||
use Pock\Exception\UnsupportedRequestException;
|
||||
@ -23,6 +24,7 @@ use Psr\Http\Client\ClientExceptionInterface;
|
||||
use Psr\Http\Client\NetworkExceptionInterface;
|
||||
use Psr\Http\Client\RequestExceptionInterface;
|
||||
use Psr\Http\Message\RequestInterface;
|
||||
use Riverline\MultiPartParser\StreamedPart;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
@ -579,6 +581,127 @@ EOF;
|
||||
self::assertEquals($xml, $response->getBody()->getContents());
|
||||
}
|
||||
|
||||
public function testMultipartFormDataMock(): void
|
||||
{
|
||||
$builder = new PockBuilder();
|
||||
$builder->matchMethod(RequestMethod::POST)
|
||||
->matchScheme(RequestScheme::HTTPS)
|
||||
->matchHost(self::TEST_HOST)
|
||||
->matchMultipartFormData(function (StreamedPart $part) {
|
||||
return $part->isMultiPart() &&
|
||||
1 === count($part->getPartsByName('param1')) &&
|
||||
1 === count($part->getPartsByName('param2')) &&
|
||||
'value1' === $part->getPartsByName('param1')[0]->getBody() &&
|
||||
'value2' === $part->getPartsByName('param2')[0]->getBody() &&
|
||||
'text/plain' === $part->getPartsByName('param1')[0]->getHeader('Content-Type');
|
||||
})->reply(200)
|
||||
->withHeader('Content-Type', 'text/plain')
|
||||
->withBody('ok');
|
||||
|
||||
$streamBuilder = (new MultipartStreamBuilder(self::getPsr17Factory()))
|
||||
->addResource('param1', 'value1', ['headers' => ['Content-Type' => 'text/plain']])
|
||||
->addResource('param2', 'value2');
|
||||
$response = $builder->getClient()->sendRequest(
|
||||
self::getPsr17Factory()
|
||||
->createRequest(RequestMethod::POST, self::TEST_URI)
|
||||
->withHeader('Content-Type', 'multipart/form-data; boundary="' . $streamBuilder->getBoundary() . '"')
|
||||
->withBody($streamBuilder->build())
|
||||
);
|
||||
|
||||
self::assertEquals(200, $response->getStatusCode());
|
||||
self::assertEquals(['Content-Type' => ['text/plain']], $response->getHeaders());
|
||||
self::assertEquals('ok', $response->getBody()->getContents());
|
||||
}
|
||||
|
||||
public function testMatchBodyRegExp(): void
|
||||
{
|
||||
$builder = new PockBuilder();
|
||||
$builder->matchMethod(RequestMethod::GET)
|
||||
->matchUri(self::TEST_URI)
|
||||
->matchBodyRegExp('/\d+-\d+/')
|
||||
->reply(200);
|
||||
|
||||
$response = $builder->getClient()->sendRequest(static::getRequestWithBody('test matchable 23-900'));
|
||||
|
||||
self::assertEquals(200, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function testMatchPathRegExp(): void
|
||||
{
|
||||
$builder = new PockBuilder();
|
||||
$builder->matchMethod(RequestMethod::GET)
|
||||
->matchOrigin(self::TEST_HOST)
|
||||
->matchPathRegExp('/^\/?test$/')
|
||||
->reply(200);
|
||||
|
||||
$response = $builder->getClient()->sendRequest(
|
||||
static::getTestRequest()->withUri(static::getPsr17Factory()->createUri('https://test.com/test'))
|
||||
);
|
||||
|
||||
self::assertEquals(200, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function testMatchQueryRegExp(): void
|
||||
{
|
||||
$builder = new PockBuilder();
|
||||
$builder->matchMethod(RequestMethod::GET)
|
||||
->matchOrigin(self::TEST_HOST)
|
||||
->matchQueryRegExp('/\d+-\d+/')
|
||||
->reply(200);
|
||||
|
||||
$response = $builder->getClient()->sendRequest(
|
||||
static::getTestRequest()->withUri(
|
||||
static::getPsr17Factory()->createUri(self::TEST_URI)
|
||||
->withQuery('param=23-900')
|
||||
)
|
||||
);
|
||||
|
||||
self::assertEquals(200, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function testMatchUriRegExp(): void
|
||||
{
|
||||
$builder = new PockBuilder();
|
||||
$builder->matchMethod(RequestMethod::GET)
|
||||
->matchUriRegExp('/https\:\/\/\w+\.com\/\d+-\d+\?param=\d+-\d+/')
|
||||
->reply(200);
|
||||
|
||||
$response = $builder->getClient()->sendRequest(
|
||||
static::getTestRequest()->withUri(
|
||||
static::getPsr17Factory()->createUri('https://example.com/23-900')
|
||||
->withQuery('param=23-900')
|
||||
)
|
||||
);
|
||||
|
||||
self::assertEquals(200, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function testMatchFormData(): void
|
||||
{
|
||||
$builder = new PockBuilder();
|
||||
$builder->matchMethod(RequestMethod::GET)
|
||||
->matchUri(self::TEST_URI)
|
||||
->matchFormData(['field2' => 'value2'])
|
||||
->reply(200);
|
||||
|
||||
$response = $builder->getClient()->sendRequest(self::getRequestWithBody('field1=value1&field2=value2'));
|
||||
|
||||
self::assertEquals(200, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function testMatchExactFormData(): void
|
||||
{
|
||||
$builder = new PockBuilder();
|
||||
$builder->matchMethod(RequestMethod::GET)
|
||||
->matchUri(self::TEST_URI)
|
||||
->matchExactFormData(['field2' => 'value2'])
|
||||
->reply(200);
|
||||
|
||||
$response = $builder->getClient()->sendRequest(self::getRequestWithBody('field2=value2'));
|
||||
|
||||
self::assertEquals(200, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function testFirstExampleApiMock(): void
|
||||
{
|
||||
$data = [
|
||||
|
Loading…
Reference in New Issue
Block a user