Skip to content

Commit

Permalink
Merge pull request #599 from tienvx/formatter-factory-method
Browse files Browse the repository at this point in the history
Formatter factory method
  • Loading branch information
tienvx committed May 11, 2024
2 parents d9b24d7 + 825cb86 commit e07f7a1
Show file tree
Hide file tree
Showing 135 changed files with 2,748 additions and 594 deletions.
3 changes: 1 addition & 2 deletions example/csv/consumer/tests/Service/HttpClientServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
use CsvConsumer\Service\HttpClientService;
use PhpPact\Consumer\Driver\Enum\InteractionPart;
use PhpPact\Consumer\InteractionBuilder;
use PhpPact\Consumer\Matcher\Formatters\PluginFormatter;
use PhpPact\Consumer\Matcher\Matcher;
use PhpPact\Consumer\Model\Body\Text;
use PhpPact\Consumer\Model\ConsumerRequest;
Expand All @@ -18,7 +17,7 @@ class HttpClientServiceTest extends TestCase
{
public function testGetCsvFile(): void
{
$matcher = new Matcher(new PluginFormatter());
$matcher = new Matcher(plugin: true);

$request = new ConsumerRequest();
$request
Expand Down
4 changes: 4 additions & 0 deletions example/matchers/consumer/tests/Service/MatchersTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ public function testGetMatchers(): void
$this->matcher->atMost(3),
],
),
'atLeast' => $this->matcher->atLeast(2), // Not useful when outside of `matchAll`
'atMost' => $this->matcher->atMost(4), // Not useful when outside of `matchAll`

// Don't mind this. This is for demonstrating what query values provider will received.
'query' => [
Expand Down Expand Up @@ -218,6 +220,8 @@ public function testGetMatchers(): void
],
'url' => 'http://localhost:8080/users/1234/posts/latest',
'matchAll' => ['desktop' => '2000 usd'],
'atLeast' => [null, null],
'atMost' => [null],

// Don't mind this. This is for demonstrating what query values provider will received.
'query' => [
Expand Down
25 changes: 25 additions & 0 deletions example/matchers/pacts/matchersConsumer-matchersProvider.json
Original file line number Diff line number Diff line change
Expand Up @@ -135,13 +135,20 @@
111,
"2fbd41cc-4bbc-44ea-a419-67f767691407"
],
"atLeast": [
null,
null
],
"atLeastLike": [
1,
1,
1,
1,
1
],
"atMost": [
null
],
"atMostLike": [
1
],
Expand Down Expand Up @@ -278,6 +285,15 @@
}
]
},
"$.atLeast": {
"combine": "AND",
"matchers": [
{
"match": "type",
"min": 2
}
]
},
"$.atLeastLike": {
"combine": "AND",
"matchers": [
Expand All @@ -287,6 +303,15 @@
}
]
},
"$.atMost": {
"combine": "AND",
"matchers": [
{
"match": "type",
"max": 4
}
]
},
"$.atMostLike": {
"combine": "AND",
"matchers": [
Expand Down
12 changes: 11 additions & 1 deletion example/matchers/provider/public/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@
'likeBool' => false,
'likeInt' => 34,
'likeDecimal' => 24.12,
// 'likeDecimal' => 24, // Becareful, int is accepted
'boolean' => true,
'integer' => 11,
'decimal' => 25.1,
'decimal' => 25.1, // int is not accepted
'hexadecimal' => '20AC',
'uuid' => 'e9d2f3a5-6ecc-4bff-8935-84bb6141325a',
'ipv4Address' => '192.168.1.1',
Expand Down Expand Up @@ -78,6 +79,15 @@
'tablet' => '300 usd',
'laptop' => '1200 usd',
],
'atLeast' => [
null,
null,
],
'atMost' => [
null,
],

// Don't mind this. This is for demonstrating what query values provider will received.
'query' => $request->getQueryParams(),
]));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace ProtobufAsyncMessageConsumer\Tests\MessageHandler;

use Library\Person;
use PhpPact\Consumer\Matcher\Matcher;
use PhpPact\Consumer\MessageBuilder;
use PhpPact\Consumer\Model\Body\Text;
use PhpPact\Plugins\Protobuf\Factory\ProtobufMessageDriverFactory;
Expand All @@ -16,9 +17,11 @@ class PersonMessageHandlerTest extends TestCase
private SayHelloService $service;
private string $given = 'Given';
private string $surname = 'Surname';
private Matcher $matcher;

protected function setUp(): void
{
$this->matcher = new Matcher(plugin: true);
$service = $this->createMock(SayHelloService::class);
$service
->expects($this->once())
Expand Down Expand Up @@ -50,10 +53,10 @@ public function testInvoke(): void
'pact:proto' => __DIR__ . '/../../../library/proto/say_hello.proto',
'pact:message-type' => 'Person',
'pact:content-type' => 'application/protobuf',
'id' => "matching(regex, '^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$', '{$id}')",
'id' => $this->matcher->regex($id, '^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$'),
'name' => [
'given' => "matching(type, '{$this->given}')",
'surname' => "matching(type, '{$this->surname}')"
'given' => $this->matcher->like($this->given),
'surname' => $this->matcher->like($this->surname),
],
]),
'application/protobuf'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace ProtobufSyncMessageConsumer\Tests;

use PhpPact\Consumer\Matcher\Formatters\PluginFormatter;
use PhpPact\Consumer\Matcher\Matcher;
use PhpPact\Consumer\Model\Body\Text;
use PhpPact\Plugins\Protobuf\Factory\ProtobufSyncMessageDriverFactory;
Expand All @@ -17,7 +16,7 @@ class ProtobufClientTest extends TestCase
{
public function testCalculateArea(): void
{
$matcher = new Matcher(new PluginFormatter());
$matcher = new Matcher(plugin: true);
$protoPath = __DIR__ . '/../../library/proto/area_calculator.proto';

$config = new MockServerConfig();
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace PhpPact\Consumer\Matcher\Formatters\Expression;

use PhpPact\Consumer\Matcher\Exception\InvalidValueException;
use PhpPact\Consumer\Matcher\Exception\MatcherNotSupportedException;
use PhpPact\Consumer\Matcher\Model\ExpressionFormatterInterface;
use PhpPact\Consumer\Matcher\Model\MatcherInterface;

abstract class AbstractExpressionFormatter implements ExpressionFormatterInterface
{
protected function normalize(mixed $value): string
{
if (is_string($value) && str_contains($value, "'")) {
throw new InvalidValueException(sprintf('String value "%s" should not contains single quote', $value));
}
return match (gettype($value)) {
'string' => sprintf("'%s'", $value),
'boolean' => $value ? 'true' : 'false',
'integer' => (string) $value,
'double' => (string) $value,
'NULL' => 'null',
default => throw new InvalidValueException(sprintf("Expression doesn't support value of type %s", gettype($value))),
};
}

protected function getMatcherNotSupportedException(MatcherInterface $matcher): MatcherNotSupportedException
{
return new MatcherNotSupportedException(sprintf('Matcher %s is not supported by %s', $matcher->getType(), static::class));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace PhpPact\Consumer\Matcher\Formatters\Expression;

use PhpPact\Consumer\Matcher\Exception\InvalidValueException;
use PhpPact\Consumer\Matcher\Matchers\Boolean;
use PhpPact\Consumer\Matcher\Model\MatcherInterface;

class BooleanFormatter extends AbstractExpressionFormatter
{
public function format(MatcherInterface $matcher): string
{
if (!$matcher instanceof Boolean) {
throw $this->getMatcherNotSupportedException($matcher);
}
$value = $matcher->getValue();
if (!is_bool($value)) {
throw new InvalidValueException(sprintf("Boolean formatter doesn't support value of type %s", gettype($value)));
}

return sprintf('matching(boolean, %s)', $this->normalize($value));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace PhpPact\Consumer\Matcher\Formatters\Expression;

use PhpPact\Consumer\Matcher\Matchers\ContentType;
use PhpPact\Consumer\Matcher\Model\MatcherInterface;

class ContentTypeFormatter extends AbstractExpressionFormatter
{
public function format(MatcherInterface $matcher): string
{
if (!$matcher instanceof ContentType) {
throw $this->getMatcherNotSupportedException($matcher);
}

return sprintf("matching(contentType, %s, %s)", $this->normalize($matcher->getContentType()), $this->normalize($matcher->getValue()));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace PhpPact\Consumer\Matcher\Formatters\Expression;

use PhpPact\Consumer\Matcher\Exception\InvalidValueException;
use PhpPact\Consumer\Matcher\Matchers\AbstractDateTime;
use PhpPact\Consumer\Matcher\Model\MatcherInterface;

class DateTimeFormatter extends AbstractExpressionFormatter
{
public function format(MatcherInterface $matcher): string
{
if (!$matcher instanceof AbstractDateTime) {
throw $this->getMatcherNotSupportedException($matcher);
}
$value = $matcher->getValue();
if (!is_string($value)) {
throw new InvalidValueException(sprintf("DateTime formatter doesn't support value of type %s", gettype($value)));
}

return sprintf("matching(%s, %s, %s)", $matcher->getType(), $this->normalize($matcher->getFormat()), $this->normalize($value));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

namespace PhpPact\Consumer\Matcher\Formatters\Expression;

use PhpPact\Consumer\Matcher\Exception\InvalidValueException;
use PhpPact\Consumer\Matcher\Matchers\Decimal;
use PhpPact\Consumer\Matcher\Model\MatcherInterface;

class DecimalFormatter extends AbstractExpressionFormatter
{
public function format(MatcherInterface $matcher): string
{
if (!$matcher instanceof Decimal) {
throw $this->getMatcherNotSupportedException($matcher);
}
$value = $matcher->getValue();
if (!is_float($value)) {
throw new InvalidValueException(sprintf("Decimal formatter doesn't support value of type %s", gettype($value)));
}

return sprintf('matching(decimal, %s)', $this->normalize($value));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace PhpPact\Consumer\Matcher\Formatters\Expression;

use PhpPact\Consumer\Matcher\Exception\MatchingExpressionException;
use PhpPact\Consumer\Matcher\Matchers\EachKey;
use PhpPact\Consumer\Matcher\Model\MatcherInterface;

class EachKeyFormatter extends AbstractExpressionFormatter
{
public function format(MatcherInterface $matcher): string
{
if (!$matcher instanceof EachKey) {
throw $this->getMatcherNotSupportedException($matcher);
}
$rules = $matcher->getRules();
if (count($rules) !== 1) {
throw new MatchingExpressionException(sprintf("Matcher 'eachKey' only support 1 rule in expression, %d provided", count($rules)));
}
$rule = reset($rules);

return sprintf('eachKey(%s)', $rule->createExpressionFormatter()->format($rule));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace PhpPact\Consumer\Matcher\Formatters\Expression;

use PhpPact\Consumer\Matcher\Exception\MatchingExpressionException;
use PhpPact\Consumer\Matcher\Matchers\EachValue;
use PhpPact\Consumer\Matcher\Model\MatcherInterface;

class EachValueFormatter extends AbstractExpressionFormatter
{
public function format(MatcherInterface $matcher): string
{
if (!$matcher instanceof EachValue) {
throw $this->getMatcherNotSupportedException($matcher);
}
$rules = $matcher->getRules();
if (count($rules) !== 1) {
throw new MatchingExpressionException(sprintf("Matcher 'eachValue' only support 1 rule in expression, %d provided", count($rules)));
}
$rule = reset($rules);

return sprintf('eachValue(%s)', $rule->createExpressionFormatter()->format($rule));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

namespace PhpPact\Consumer\Matcher\Formatters\Expression;

use PhpPact\Consumer\Matcher\Matchers\Equality;
use PhpPact\Consumer\Matcher\Model\MatcherInterface;

class EqualityFormatter extends AbstractExpressionFormatter
{
public function format(MatcherInterface $matcher): string
{
if (!$matcher instanceof Equality) {
throw $this->getMatcherNotSupportedException($matcher);
}

return sprintf('matching(equalTo, %s)', $this->normalize($matcher->getValue()));
}
}
Loading

0 comments on commit e07f7a1

Please sign in to comment.