Skip to content

Commit

Permalink
refactor: Apply Factory Method pattern to formatter
Browse files Browse the repository at this point in the history
  • Loading branch information
tienvx committed May 5, 2024
1 parent f161c44 commit f68181d
Show file tree
Hide file tree
Showing 132 changed files with 2,706 additions and 593 deletions.
4 changes: 2 additions & 2 deletions example/csv/consumer/tests/Service/HttpClientServiceTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use CsvConsumer\Service\HttpClientService;
use PhpPact\Consumer\Driver\Enum\InteractionPart;
use PhpPact\Consumer\InteractionBuilder;
use PhpPact\Consumer\Matcher\Formatters\PluginFormatter;
use PhpPact\Consumer\Matcher\Enum\Format;
use PhpPact\Consumer\Matcher\Matcher;
use PhpPact\Consumer\Model\Body\Text;
use PhpPact\Consumer\Model\ConsumerRequest;
Expand All @@ -18,7 +18,7 @@ class HttpClientServiceTest extends TestCase
{
public function testGetCsvFile(): void
{
$matcher = new Matcher(new PluginFormatter());
$matcher = new Matcher(Format::EXPRESSION);

$request = new ConsumerRequest();
$request
Expand Down
3 changes: 2 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
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
namespace ProtobufAsyncMessageConsumer\Tests\MessageHandler;

use Library\Person;
use PhpPact\Consumer\Matcher\Enum\Format;
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 +18,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(Format::EXPRESSION);
$service = $this->createMock(SayHelloService::class);
$service
->expects($this->once())
Expand Down Expand Up @@ -50,10 +54,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,7 @@

namespace ProtobufSyncMessageConsumer\Tests;

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

$config = new MockServerConfig();
Expand Down
9 changes: 9 additions & 0 deletions src/PhpPact/Consumer/Matcher/Enum/Format.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace PhpPact\Consumer\Matcher\Enum;

enum Format
{
case JSON;
case EXPRESSION;
}

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\FormatterInterface;
use PhpPact\Consumer\Matcher\Model\MatcherInterface;

abstract class AbstractExpressionFormatter implements FormatterInterface
{
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,25 @@
<?php

namespace PhpPact\Consumer\Matcher\Formatters\Expression;

use PhpPact\Consumer\Matcher\Enum\Format;
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->createFormatter(Format::EXPRESSION)->format($rule));

Check failure on line 23 in src/PhpPact/Consumer/Matcher/Formatters/Expression/EachKeyFormatter.php

View workflow job for this annotation

GitHub Actions / php-cs

Parameter #2 ...$values of function sprintf expects bool|float|int|string|null, array<string, mixed>|string given.
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

namespace PhpPact\Consumer\Matcher\Formatters\Expression;

use PhpPact\Consumer\Matcher\Enum\Format;
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->createFormatter(Format::EXPRESSION)->format($rule));

Check failure on line 23 in src/PhpPact/Consumer/Matcher/Formatters/Expression/EachValueFormatter.php

View workflow job for this annotation

GitHub Actions / php-cs

Parameter #2 ...$values of function sprintf expects bool|float|int|string|null, array<string, mixed>|string given.
}
}
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()));
}
}
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\Includes;
use PhpPact\Consumer\Matcher\Model\MatcherInterface;

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

return sprintf('matching(include, %s)', $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\Integer;
use PhpPact\Consumer\Matcher\Model\MatcherInterface;

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

return sprintf('matching(integer, %d)', $value);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

namespace PhpPact\Consumer\Matcher\Formatters\Expression;

use PhpPact\Consumer\Matcher\Enum\Format;
use PhpPact\Consumer\Matcher\Exception\MatchingExpressionException;
use PhpPact\Consumer\Matcher\Matchers\MatchAll;
use PhpPact\Consumer\Matcher\Model\MatcherInterface;

class MatchAllFormatter extends AbstractExpressionFormatter
{
public function format(MatcherInterface $matcher): string
{
if (!$matcher instanceof MatchAll) {
throw $this->getMatcherNotSupportedException($matcher);
}
$matchers = $matcher->getMatchers();
if (empty($matchers)) {
throw new MatchingExpressionException("Matcher 'matchAll' need at least 1 matchers");
}

return implode(', ', array_map(
fn (MatcherInterface $matcher): string => $matcher->createFormatter(Format::EXPRESSION)->format($matcher),

Check failure on line 23 in src/PhpPact/Consumer/Matcher/Formatters/Expression/MatchAllFormatter.php

View workflow job for this annotation

GitHub Actions / php-cs

Anonymous function should return string but returns array<string, mixed>|string.
$matchers
));
}
}
Loading

0 comments on commit f68181d

Please sign in to comment.