From b806bc9390162137efdb958e574e9a01ee4f08d0 Mon Sep 17 00:00:00 2001 From: "tien.xuan.vo" Date: Sun, 5 May 2024 17:20:11 +0700 Subject: [PATCH 1/3] refactor: Apply Factory Method pattern to formatters --- .../tests/Service/HttpClientServiceTest.php | 3 +- example/matchers/provider/public/index.php | 3 +- .../PersonMessageHandlerTest.php | 9 +- .../consumer/tests/ProtobufClientTest.php | 3 +- .../Formatters/CombinedMatchersFormatter.php | 24 ---- .../AbstractExpressionFormatter.php | 31 ++++ .../Expression/BooleanFormatter.php | 23 +++ .../Expression/ContentTypeFormatter.php | 18 +++ .../Expression/DateTimeFormatter.php | 23 +++ .../Expression/DecimalFormatter.php | 23 +++ .../Expression/EachKeyFormatter.php | 24 ++++ .../Expression/EachValueFormatter.php | 24 ++++ .../Expression/EqualityFormatter.php | 18 +++ .../Expression/IncludesFormatter.php | 18 +++ .../Expression/IntegerFormatter.php | 23 +++ .../Expression/MatchAllFormatter.php | 26 ++++ .../Expression/MatchingFieldFormatter.php | 18 +++ .../Expression/MaxTypeFormatter.php | 18 +++ .../Expression/MinTypeFormatter.php | 18 +++ .../Expression/NotEmptyFormatter.php | 18 +++ .../Expression/NullValueFormatter.php | 13 ++ .../Formatters/Expression/NumberFormatter.php | 23 +++ .../Formatters/Expression/RegexFormatter.php | 23 +++ .../Formatters/Expression/SemverFormatter.php | 23 +++ .../Expression/StringValueFormatter.php | 18 +++ .../Formatters/Expression/TypeFormatter.php | 18 +++ .../Formatters/Json/ContentTypeFormatter.php | 26 ++++ .../Formatters/Json/HasGeneratorFormatter.php | 32 +++++ .../Formatters/Json/MatchAllFormatter.php | 26 ++++ .../NoGeneratorFormatter.php} | 9 +- .../Formatters/Json/NullValueFormatter.php | 19 +++ .../Formatters/Json/StringValueFormatter.php | 25 ++++ .../Matcher/Formatters/PluginFormatter.php | 135 ------------------ .../Formatters/ValueOptionalFormatter.php | 36 ----- .../Formatters/ValueRequiredFormatter.php | 18 --- .../{ => Xml}/XmlContentFormatter.php | 5 +- .../{ => Xml}/XmlElementFormatter.php | 11 +- src/PhpPact/Consumer/Matcher/Matcher.php | 13 +- .../Matcher/Matchers/AbstractDateTime.php | 15 ++ .../Matcher/Matchers/AbstractMatcher.php | 5 + .../Matcher/Matchers/ArrayContains.php | 17 ++- .../Consumer/Matcher/Matchers/Boolean.php | 14 ++ .../Matcher/Matchers/CombinedMatchers.php | 3 +- .../Consumer/Matcher/Matchers/ContentType.php | 24 +++- .../Consumer/Matcher/Matchers/Decimal.php | 14 ++ .../Consumer/Matcher/Matchers/EachKey.php | 14 ++ .../Consumer/Matcher/Matchers/EachValue.php | 14 ++ .../Consumer/Matcher/Matchers/Equality.php | 15 ++ .../Consumer/Matcher/Matchers/Includes.php | 15 ++ .../Consumer/Matcher/Matchers/Integer.php | 14 ++ .../Consumer/Matcher/Matchers/MatchAll.php | 15 ++ .../Matcher/Matchers/MatchingField.php | 26 +++- .../Consumer/Matcher/Matchers/MaxType.php | 20 +++ .../Consumer/Matcher/Matchers/MinMaxType.php | 15 ++ .../Consumer/Matcher/Matchers/MinType.php | 20 +++ .../Consumer/Matcher/Matchers/NotEmpty.php | 15 ++ .../Consumer/Matcher/Matchers/NullValue.php | 20 ++- .../Consumer/Matcher/Matchers/Number.php | 14 ++ .../Consumer/Matcher/Matchers/Regex.php | 14 ++ .../Consumer/Matcher/Matchers/Semver.php | 14 ++ .../Consumer/Matcher/Matchers/StatusCode.php | 14 ++ .../Consumer/Matcher/Matchers/StringValue.php | 17 ++- .../Consumer/Matcher/Matchers/Type.php | 15 ++ .../Consumer/Matcher/Matchers/Values.php | 15 ++ .../Model/ExpressionFormatterInterface.php | 8 ++ .../Model/FormatterFactoryInterface.php | 10 ++ .../Matcher/Model/JsonFormatterInterface.php | 11 ++ .../Matcher/Model/MatcherInterface.php | 2 +- .../Matcher/Trait/FormatterAwareTrait.php | 6 - .../Xml/Model/Builder/ElementTrait.php | 2 +- src/PhpPact/Xml/Model/Builder/TextTrait.php | 2 +- .../CombinedMatchersFormatterTest.php | 30 ---- .../Expression/BooleanFormatterTest.php | 46 ++++++ .../Expression/ContentTypeFormatterTest.php | 48 +++++++ .../Expression/DateTimeFormatterTest.php | 58 ++++++++ .../Expression/DecimalFormatterTest.php | 48 +++++++ .../Expression/EachKeyFormatterTest.php | 51 +++++++ .../Expression/EachValueFormatterTest.php | 51 +++++++ .../Expression/EqualityFormatterTest.php | 61 ++++++++ .../Expression/IncludesFormatterTest.php | 45 ++++++ .../Expression/IntegerFormatterTest.php | 46 ++++++ .../Expression/MatchAllFormatterTest.php | 53 +++++++ .../Expression/MatchingFieldFormatterTest.php | 45 ++++++ .../Expression/MaxTypeFormatterTest.php | 36 +++++ .../Expression/MinTypeFormatterTest.php | 36 +++++ .../Expression/NotEmptyFormatterTest.php | 58 ++++++++ .../Expression/NullValueFormatterTest.php | 26 ++++ .../Expression/NumberFormatterTest.php | 48 +++++++ .../Expression/RegexFormatterTest.php | 55 +++++++ .../Expression/SemverFormatterTest.php | 53 +++++++ .../Expression/StringValueFormatterTest.php | 45 ++++++ .../Expression/TypeFormatterTest.php | 63 ++++++++ .../Json/ContentTypeFormatterTest.php | 40 ++++++ .../Json/HasGeneratorFormatterTest.php | 42 ++++++ .../Formatters/Json/MatchAllFormatterTest.php | 111 ++++++++++++++ .../Json/NoGeneratorFormatterTest.php | 43 ++++++ .../Json/NullValueFormatterTest.php | 28 ++++ .../Json/StringValueFormatterTest.php | 42 ++++++ .../Formatters/MinimalFormatterTest.php | 26 ---- .../Formatters/PluginFormatterTest.php | 124 ---------------- .../Formatters/ValueOptionalFormatterTest.php | 27 ---- .../Formatters/ValueRequiredFormatterTest.php | 27 ---- .../{ => Xml}/XmlContentFormatterTest.php | 4 +- .../{ => Xml}/XmlElementFormatterTest.php | 4 +- .../PhpPact/Consumer/Matcher/MatcherTest.php | 21 ++- .../Matchers/AbstractDateTimeTestCase.php | 21 +++ .../Matcher/Matchers/ArrayContainsTest.php | 15 ++ .../Consumer/Matcher/Matchers/BooleanTest.php | 23 ++- .../Matcher/Matchers/ContentTypeTest.php | 14 ++ .../Consumer/Matcher/Matchers/DateTest.php | 9 +- .../Matcher/Matchers/DateTimeTest.php | 9 +- .../Consumer/Matcher/Matchers/DecimalTest.php | 21 ++- .../Consumer/Matcher/Matchers/EachKeyTest.php | 14 ++ .../Matcher/Matchers/EachValueTest.php | 14 ++ .../Matcher/Matchers/EqualityTest.php | 14 ++ .../Matcher/Matchers/IncludesTest.php | 14 ++ .../Consumer/Matcher/Matchers/IntegerTest.php | 21 ++- .../Matcher/Matchers/MatchAllTest.php | 14 ++ .../Matcher/Matchers/MatchingFieldTest.php | 40 +++--- .../Consumer/Matcher/Matchers/MaxTypeTest.php | 14 ++ .../Matcher/Matchers/MinMaxTypeTest.php | 15 ++ .../Consumer/Matcher/Matchers/MinTypeTest.php | 14 ++ .../Matcher/Matchers/NotEmptyTest.php | 14 ++ .../Matcher/Matchers/NullValueTest.php | 14 ++ .../Consumer/Matcher/Matchers/NumberTest.php | 23 ++- .../Consumer/Matcher/Matchers/RegexTest.php | 14 ++ .../Consumer/Matcher/Matchers/SemverTest.php | 21 ++- .../Matcher/Matchers/StatusCodeTest.php | 36 +++-- .../Matcher/Matchers/StringValueTest.php | 21 ++- .../Consumer/Matcher/Matchers/TimeTest.php | 9 +- .../Consumer/Matcher/Matchers/TypeTest.php | 14 ++ .../Consumer/Matcher/Matchers/ValuesTest.php | 15 ++ tests/PhpPact/Xml/XmlTextTest.php | 17 ++- 133 files changed, 2708 insertions(+), 594 deletions(-) delete mode 100644 src/PhpPact/Consumer/Matcher/Formatters/CombinedMatchersFormatter.php create mode 100644 src/PhpPact/Consumer/Matcher/Formatters/Expression/AbstractExpressionFormatter.php create mode 100644 src/PhpPact/Consumer/Matcher/Formatters/Expression/BooleanFormatter.php create mode 100644 src/PhpPact/Consumer/Matcher/Formatters/Expression/ContentTypeFormatter.php create mode 100644 src/PhpPact/Consumer/Matcher/Formatters/Expression/DateTimeFormatter.php create mode 100644 src/PhpPact/Consumer/Matcher/Formatters/Expression/DecimalFormatter.php create mode 100644 src/PhpPact/Consumer/Matcher/Formatters/Expression/EachKeyFormatter.php create mode 100644 src/PhpPact/Consumer/Matcher/Formatters/Expression/EachValueFormatter.php create mode 100644 src/PhpPact/Consumer/Matcher/Formatters/Expression/EqualityFormatter.php create mode 100644 src/PhpPact/Consumer/Matcher/Formatters/Expression/IncludesFormatter.php create mode 100644 src/PhpPact/Consumer/Matcher/Formatters/Expression/IntegerFormatter.php create mode 100644 src/PhpPact/Consumer/Matcher/Formatters/Expression/MatchAllFormatter.php create mode 100644 src/PhpPact/Consumer/Matcher/Formatters/Expression/MatchingFieldFormatter.php create mode 100644 src/PhpPact/Consumer/Matcher/Formatters/Expression/MaxTypeFormatter.php create mode 100644 src/PhpPact/Consumer/Matcher/Formatters/Expression/MinTypeFormatter.php create mode 100644 src/PhpPact/Consumer/Matcher/Formatters/Expression/NotEmptyFormatter.php create mode 100644 src/PhpPact/Consumer/Matcher/Formatters/Expression/NullValueFormatter.php create mode 100644 src/PhpPact/Consumer/Matcher/Formatters/Expression/NumberFormatter.php create mode 100644 src/PhpPact/Consumer/Matcher/Formatters/Expression/RegexFormatter.php create mode 100644 src/PhpPact/Consumer/Matcher/Formatters/Expression/SemverFormatter.php create mode 100644 src/PhpPact/Consumer/Matcher/Formatters/Expression/StringValueFormatter.php create mode 100644 src/PhpPact/Consumer/Matcher/Formatters/Expression/TypeFormatter.php create mode 100644 src/PhpPact/Consumer/Matcher/Formatters/Json/ContentTypeFormatter.php create mode 100644 src/PhpPact/Consumer/Matcher/Formatters/Json/HasGeneratorFormatter.php create mode 100644 src/PhpPact/Consumer/Matcher/Formatters/Json/MatchAllFormatter.php rename src/PhpPact/Consumer/Matcher/Formatters/{MinimalFormatter.php => Json/NoGeneratorFormatter.php} (53%) create mode 100644 src/PhpPact/Consumer/Matcher/Formatters/Json/NullValueFormatter.php create mode 100644 src/PhpPact/Consumer/Matcher/Formatters/Json/StringValueFormatter.php delete mode 100644 src/PhpPact/Consumer/Matcher/Formatters/PluginFormatter.php delete mode 100644 src/PhpPact/Consumer/Matcher/Formatters/ValueOptionalFormatter.php delete mode 100644 src/PhpPact/Consumer/Matcher/Formatters/ValueRequiredFormatter.php rename src/PhpPact/Consumer/Matcher/Formatters/{ => Xml}/XmlContentFormatter.php (83%) rename src/PhpPact/Consumer/Matcher/Formatters/{ => Xml}/XmlElementFormatter.php (65%) create mode 100644 src/PhpPact/Consumer/Matcher/Model/ExpressionFormatterInterface.php create mode 100644 src/PhpPact/Consumer/Matcher/Model/FormatterFactoryInterface.php create mode 100644 src/PhpPact/Consumer/Matcher/Model/JsonFormatterInterface.php delete mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/CombinedMatchersFormatterTest.php create mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/Expression/BooleanFormatterTest.php create mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/Expression/ContentTypeFormatterTest.php create mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/Expression/DateTimeFormatterTest.php create mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/Expression/DecimalFormatterTest.php create mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/Expression/EachKeyFormatterTest.php create mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/Expression/EachValueFormatterTest.php create mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/Expression/EqualityFormatterTest.php create mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/Expression/IncludesFormatterTest.php create mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/Expression/IntegerFormatterTest.php create mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/Expression/MatchAllFormatterTest.php create mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/Expression/MatchingFieldFormatterTest.php create mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/Expression/MaxTypeFormatterTest.php create mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/Expression/MinTypeFormatterTest.php create mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/Expression/NotEmptyFormatterTest.php create mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/Expression/NullValueFormatterTest.php create mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/Expression/NumberFormatterTest.php create mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/Expression/RegexFormatterTest.php create mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/Expression/SemverFormatterTest.php create mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/Expression/StringValueFormatterTest.php create mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/Expression/TypeFormatterTest.php create mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/Json/ContentTypeFormatterTest.php create mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/Json/HasGeneratorFormatterTest.php create mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/Json/MatchAllFormatterTest.php create mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/Json/NoGeneratorFormatterTest.php create mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/Json/NullValueFormatterTest.php create mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/Json/StringValueFormatterTest.php delete mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/MinimalFormatterTest.php delete mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/PluginFormatterTest.php delete mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/ValueOptionalFormatterTest.php delete mode 100644 tests/PhpPact/Consumer/Matcher/Formatters/ValueRequiredFormatterTest.php rename tests/PhpPact/Consumer/Matcher/Formatters/{ => Xml}/XmlContentFormatterTest.php (89%) rename tests/PhpPact/Consumer/Matcher/Formatters/{ => Xml}/XmlElementFormatterTest.php (92%) create mode 100644 tests/PhpPact/Consumer/Matcher/Matchers/AbstractDateTimeTestCase.php diff --git a/example/csv/consumer/tests/Service/HttpClientServiceTest.php b/example/csv/consumer/tests/Service/HttpClientServiceTest.php index 153fa029..02261c85 100644 --- a/example/csv/consumer/tests/Service/HttpClientServiceTest.php +++ b/example/csv/consumer/tests/Service/HttpClientServiceTest.php @@ -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; @@ -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 diff --git a/example/matchers/provider/public/index.php b/example/matchers/provider/public/index.php index 613b1a29..66a7ff0f 100644 --- a/example/matchers/provider/public/index.php +++ b/example/matchers/provider/public/index.php @@ -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', diff --git a/example/protobuf-async-message/consumer/tests/MessageHandler/PersonMessageHandlerTest.php b/example/protobuf-async-message/consumer/tests/MessageHandler/PersonMessageHandlerTest.php index aa0793fd..3b4c683e 100644 --- a/example/protobuf-async-message/consumer/tests/MessageHandler/PersonMessageHandlerTest.php +++ b/example/protobuf-async-message/consumer/tests/MessageHandler/PersonMessageHandlerTest.php @@ -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; @@ -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()) @@ -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' diff --git a/example/protobuf-sync-message/consumer/tests/ProtobufClientTest.php b/example/protobuf-sync-message/consumer/tests/ProtobufClientTest.php index 5bf4784c..53add48d 100644 --- a/example/protobuf-sync-message/consumer/tests/ProtobufClientTest.php +++ b/example/protobuf-sync-message/consumer/tests/ProtobufClientTest.php @@ -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; @@ -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(); diff --git a/src/PhpPact/Consumer/Matcher/Formatters/CombinedMatchersFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/CombinedMatchersFormatter.php deleted file mode 100644 index d2632d2c..00000000 --- a/src/PhpPact/Consumer/Matcher/Formatters/CombinedMatchersFormatter.php +++ /dev/null @@ -1,24 +0,0 @@ - - */ - public function format(MatcherInterface $matcher): array - { - if ($matcher instanceof CombinedMatchersInterface) { - return [ - 'pact:matcher:type' => $matcher->getMatchers(), - 'value' => $matcher->getValue(), - ]; - } - - return parent::format($matcher); - } -} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/Expression/AbstractExpressionFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Expression/AbstractExpressionFormatter.php new file mode 100644 index 00000000..d15ea96b --- /dev/null +++ b/src/PhpPact/Consumer/Matcher/Formatters/Expression/AbstractExpressionFormatter.php @@ -0,0 +1,31 @@ + 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)); + } +} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/Expression/BooleanFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Expression/BooleanFormatter.php new file mode 100644 index 00000000..c7e4efeb --- /dev/null +++ b/src/PhpPact/Consumer/Matcher/Formatters/Expression/BooleanFormatter.php @@ -0,0 +1,23 @@ +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)); + } +} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/Expression/ContentTypeFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Expression/ContentTypeFormatter.php new file mode 100644 index 00000000..c440effe --- /dev/null +++ b/src/PhpPact/Consumer/Matcher/Formatters/Expression/ContentTypeFormatter.php @@ -0,0 +1,18 @@ +getMatcherNotSupportedException($matcher); + } + + return sprintf("matching(contentType, %s, %s)", $this->normalize($matcher->getContentType()), $this->normalize($matcher->getValue())); + } +} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/Expression/DateTimeFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Expression/DateTimeFormatter.php new file mode 100644 index 00000000..55ba830e --- /dev/null +++ b/src/PhpPact/Consumer/Matcher/Formatters/Expression/DateTimeFormatter.php @@ -0,0 +1,23 @@ +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)); + } +} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/Expression/DecimalFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Expression/DecimalFormatter.php new file mode 100644 index 00000000..f3fd0868 --- /dev/null +++ b/src/PhpPact/Consumer/Matcher/Formatters/Expression/DecimalFormatter.php @@ -0,0 +1,23 @@ +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)); + } +} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/Expression/EachKeyFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Expression/EachKeyFormatter.php new file mode 100644 index 00000000..1de593f8 --- /dev/null +++ b/src/PhpPact/Consumer/Matcher/Formatters/Expression/EachKeyFormatter.php @@ -0,0 +1,24 @@ +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)); + } +} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/Expression/EachValueFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Expression/EachValueFormatter.php new file mode 100644 index 00000000..dfe9d8d5 --- /dev/null +++ b/src/PhpPact/Consumer/Matcher/Formatters/Expression/EachValueFormatter.php @@ -0,0 +1,24 @@ +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)); + } +} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/Expression/EqualityFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Expression/EqualityFormatter.php new file mode 100644 index 00000000..bb9941e4 --- /dev/null +++ b/src/PhpPact/Consumer/Matcher/Formatters/Expression/EqualityFormatter.php @@ -0,0 +1,18 @@ +getMatcherNotSupportedException($matcher); + } + + return sprintf('matching(equalTo, %s)', $this->normalize($matcher->getValue())); + } +} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/Expression/IncludesFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Expression/IncludesFormatter.php new file mode 100644 index 00000000..e67a0f37 --- /dev/null +++ b/src/PhpPact/Consumer/Matcher/Formatters/Expression/IncludesFormatter.php @@ -0,0 +1,18 @@ +getMatcherNotSupportedException($matcher); + } + + return sprintf('matching(include, %s)', $this->normalize($matcher->getValue())); + } +} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/Expression/IntegerFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Expression/IntegerFormatter.php new file mode 100644 index 00000000..7d7bba14 --- /dev/null +++ b/src/PhpPact/Consumer/Matcher/Formatters/Expression/IntegerFormatter.php @@ -0,0 +1,23 @@ +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); + } +} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/Expression/MatchAllFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Expression/MatchAllFormatter.php new file mode 100644 index 00000000..7f00041e --- /dev/null +++ b/src/PhpPact/Consumer/Matcher/Formatters/Expression/MatchAllFormatter.php @@ -0,0 +1,26 @@ +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->createExpressionFormatter()->format($matcher), + $matchers + )); + } +} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/Expression/MatchingFieldFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Expression/MatchingFieldFormatter.php new file mode 100644 index 00000000..58321804 --- /dev/null +++ b/src/PhpPact/Consumer/Matcher/Formatters/Expression/MatchingFieldFormatter.php @@ -0,0 +1,18 @@ +getMatcherNotSupportedException($matcher); + } + + return sprintf("matching($%s)", $this->normalize($matcher->getFieldName())); + } +} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/Expression/MaxTypeFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Expression/MaxTypeFormatter.php new file mode 100644 index 00000000..e3760d8a --- /dev/null +++ b/src/PhpPact/Consumer/Matcher/Formatters/Expression/MaxTypeFormatter.php @@ -0,0 +1,18 @@ +getMatcherNotSupportedException($matcher); + } + + return sprintf('atMost(%u)', $matcher->getMax()); + } +} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/Expression/MinTypeFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Expression/MinTypeFormatter.php new file mode 100644 index 00000000..22855e77 --- /dev/null +++ b/src/PhpPact/Consumer/Matcher/Formatters/Expression/MinTypeFormatter.php @@ -0,0 +1,18 @@ +getMatcherNotSupportedException($matcher); + } + + return sprintf('atLeast(%u)', $matcher->getMin()); + } +} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/Expression/NotEmptyFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Expression/NotEmptyFormatter.php new file mode 100644 index 00000000..56689db0 --- /dev/null +++ b/src/PhpPact/Consumer/Matcher/Formatters/Expression/NotEmptyFormatter.php @@ -0,0 +1,18 @@ +getMatcherNotSupportedException($matcher); + } + + return sprintf('notEmpty(%s)', $this->normalize($matcher->getValue())); + } +} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/Expression/NullValueFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Expression/NullValueFormatter.php new file mode 100644 index 00000000..c08ea8e1 --- /dev/null +++ b/src/PhpPact/Consumer/Matcher/Formatters/Expression/NullValueFormatter.php @@ -0,0 +1,13 @@ +getMatcherNotSupportedException($matcher); + } + $value = $matcher->getValue(); + if (null === $value) { + throw new InvalidValueException(sprintf("Number formatter doesn't support value of type %s", gettype($value))); + } + + return sprintf('matching(number, %s)', $this->normalize($value)); + } +} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/Expression/RegexFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Expression/RegexFormatter.php new file mode 100644 index 00000000..4ebbde5f --- /dev/null +++ b/src/PhpPact/Consumer/Matcher/Formatters/Expression/RegexFormatter.php @@ -0,0 +1,23 @@ +getMatcherNotSupportedException($matcher); + } + $value = $matcher->getValue(); + if (!is_string($value)) { + throw new InvalidValueException(sprintf("Regex formatter doesn't support value of type %s", gettype($value))); + } + + return sprintf("matching(regex, %s, %s)", $this->normalize($matcher->getRegex()), $this->normalize($value)); + } +} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/Expression/SemverFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Expression/SemverFormatter.php new file mode 100644 index 00000000..5f323fb2 --- /dev/null +++ b/src/PhpPact/Consumer/Matcher/Formatters/Expression/SemverFormatter.php @@ -0,0 +1,23 @@ +getMatcherNotSupportedException($matcher); + } + $value = $matcher->getValue(); + if (!is_string($value)) { + throw new InvalidValueException(sprintf("Semver formatter doesn't support value of type %s", gettype($value))); + } + + return sprintf('matching(semver, %s)', $this->normalize($value)); + } +} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/Expression/StringValueFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Expression/StringValueFormatter.php new file mode 100644 index 00000000..c7e32bc5 --- /dev/null +++ b/src/PhpPact/Consumer/Matcher/Formatters/Expression/StringValueFormatter.php @@ -0,0 +1,18 @@ +getMatcherNotSupportedException($matcher); + } + + return sprintf('matching(type, %s)', $this->normalize($matcher->getValue())); + } +} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/Expression/TypeFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Expression/TypeFormatter.php new file mode 100644 index 00000000..4a51435b --- /dev/null +++ b/src/PhpPact/Consumer/Matcher/Formatters/Expression/TypeFormatter.php @@ -0,0 +1,18 @@ +getMatcherNotSupportedException($matcher); + } + + return sprintf('matching(type, %s)', $this->normalize($matcher->getValue())); + } +} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/Json/ContentTypeFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Json/ContentTypeFormatter.php new file mode 100644 index 00000000..8359e3da --- /dev/null +++ b/src/PhpPact/Consumer/Matcher/Formatters/Json/ContentTypeFormatter.php @@ -0,0 +1,26 @@ + + */ + public function format(MatcherInterface $matcher): array + { + if (!$matcher instanceof ContentType) { + throw new MatcherNotSupportedException(sprintf('Matcher %s is not supported by %s', $matcher->getType(), self::class)); + } + + return [ + 'pact:matcher:type' => $matcher->getType(), + 'value' => $matcher->getContentType(), + ]; + } +} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/Json/HasGeneratorFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Json/HasGeneratorFormatter.php new file mode 100644 index 00000000..8583c25d --- /dev/null +++ b/src/PhpPact/Consumer/Matcher/Formatters/Json/HasGeneratorFormatter.php @@ -0,0 +1,32 @@ + + */ + public function format(MatcherInterface $matcher): array + { + if (!$matcher instanceof GeneratorAwareInterface) { + throw new MatcherNotSupportedException(sprintf('Matcher %s is not supported by %s', $matcher->getType(), self::class)); + } + + $generator = $matcher->getGenerator(); + + if ($generator) { + return [ + 'pact:matcher:type' => $matcher->getType(), + 'pact:generator:type' => $generator->getType(), + ...$matcher->getAttributes()->merge($generator->getAttributes())->getData(), + ]; + } + + return parent::format($matcher); + } +} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/Json/MatchAllFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Json/MatchAllFormatter.php new file mode 100644 index 00000000..4a8c0e63 --- /dev/null +++ b/src/PhpPact/Consumer/Matcher/Formatters/Json/MatchAllFormatter.php @@ -0,0 +1,26 @@ + + */ + public function format(MatcherInterface $matcher): array + { + if (!$matcher instanceof MatchAll) { + throw new MatcherNotSupportedException(sprintf('Matcher %s is not supported by %s', $matcher->getType(), self::class)); + } + + return [ + 'pact:matcher:type' => $matcher->getMatchers(), + 'value' => $matcher->getValue(), + ]; + } +} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/MinimalFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Json/NoGeneratorFormatter.php similarity index 53% rename from src/PhpPact/Consumer/Matcher/Formatters/MinimalFormatter.php rename to src/PhpPact/Consumer/Matcher/Formatters/Json/NoGeneratorFormatter.php index 0b4f6a74..74e1d9d4 100644 --- a/src/PhpPact/Consumer/Matcher/Formatters/MinimalFormatter.php +++ b/src/PhpPact/Consumer/Matcher/Formatters/Json/NoGeneratorFormatter.php @@ -1,20 +1,21 @@ + * @return array */ public function format(MatcherInterface $matcher): array { return [ 'pact:matcher:type' => $matcher->getType(), ...$matcher->getAttributes()->getData(), + 'value' => $matcher->getValue(), ]; } } diff --git a/src/PhpPact/Consumer/Matcher/Formatters/Json/NullValueFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Json/NullValueFormatter.php new file mode 100644 index 00000000..e90426f2 --- /dev/null +++ b/src/PhpPact/Consumer/Matcher/Formatters/Json/NullValueFormatter.php @@ -0,0 +1,19 @@ + + */ + public function format(MatcherInterface $matcher): array + { + return [ + 'pact:matcher:type' => 'null', + ]; + } +} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/Json/StringValueFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Json/StringValueFormatter.php new file mode 100644 index 00000000..beedb0b9 --- /dev/null +++ b/src/PhpPact/Consumer/Matcher/Formatters/Json/StringValueFormatter.php @@ -0,0 +1,25 @@ + + */ + public function format(MatcherInterface $matcher): array + { + if (!$matcher instanceof StringValue) { + throw new MatcherNotSupportedException(sprintf('Matcher %s is not supported by %s', $matcher->getType(), self::class)); + } + + return [ + ...parent::format($matcher), + 'value' => $matcher->getValue(), + ]; + } +} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/PluginFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/PluginFormatter.php deleted file mode 100644 index 566b97ca..00000000 --- a/src/PhpPact/Consumer/Matcher/Formatters/PluginFormatter.php +++ /dev/null @@ -1,135 +0,0 @@ -getGenerator()) { - throw new GeneratorNotRequiredException('Generator is not support in plugin'); - } - - if ($matcher instanceof MatchingField) { - return $this->formatMatchingFieldMatcher($matcher); - } - if ($matcher instanceof NotEmpty) { - return $this->formatNotEmptyMatcher($matcher); - } - if ($matcher instanceof EachKey || $matcher instanceof EachValue) { - return $this->formatEachKeyAndEachValueMatchers($matcher); - } - if ($matcher instanceof NullValue) { - return $this->formatMatchersWithoutConfig(new Type(null)); - } - if ($matcher instanceof MinType) { - return $this->formatMinTypeMatcher($matcher); - } - if ($matcher instanceof MaxType) { - return $this->formatMaxTypeMatcher($matcher); - } - - if (in_array($matcher->getType(), self::MATCHERS_WITHOUT_CONFIG)) { - return $this->formatMatchersWithoutConfig($matcher); - } - if ($matcher instanceof AbstractDateTime || $matcher instanceof Regex || $matcher instanceof ContentType) { - return $this->formatMatchersWithConfig($matcher); - } - if ($matcher instanceof MatchAll) { - return $this->formatMatchAllMatchers($matcher); - } - - throw new MatcherNotSupportedException(sprintf("Matcher '%s' is not supported by plugin", $matcher->getType())); - } - - private function formatMatchingFieldMatcher(MatchingField $matcher): string - { - return sprintf("matching($%s)", $this->normalize($matcher->getFieldName())); - } - - private function formatMatchersWithoutConfig(MatcherInterface $matcher): string - { - $type = $matcher->getType() === 'equality' ? 'equalTo' : $matcher->getType(); - - return sprintf('matching(%s, %s)', $type, $this->normalize($matcher->getValue())); - } - - private function formatMatchersWithConfig(AbstractDateTime|Regex|ContentType $matcher): string - { - $config = match (true) { - $matcher instanceof AbstractDateTime => $matcher->getFormat(), - $matcher instanceof Regex => $matcher->getRegex(), - $matcher instanceof ContentType => $matcher->getValue(), - }; - - return sprintf("matching(%s, %s, %s)", $matcher->getType(), $this->normalize($config), $this->normalize($matcher->getValue())); - } - - private function formatNotEmptyMatcher(NotEmpty $matcher): string - { - return sprintf('notEmpty(%s)', $this->normalize($matcher->getValue())); - } - - private function formatEachKeyAndEachValueMatchers(EachKey|EachValue $matcher): string - { - $rules = $matcher->getRules(); - if (count($rules) === 0 || count($rules) > 1) { - throw new MatchingExpressionException(sprintf("Matcher '%s' only support 1 rule, %d provided", $matcher->getType(), count($rules))); - } - $rule = reset($rules); - - return sprintf('%s(%s)', $matcher->getType(), $this->format($rule)); - } - - private function formatMatchAllMatchers(MatchAll $matcher): string - { - return implode(', ', array_map(fn (MatcherInterface $rule) => $this->format($rule), $matcher->getMatchers())); - } - - private function formatMinTypeMatcher(MinType $matcher): string - { - return sprintf('atLeast(%s)', $this->normalize($matcher->getAttributes()->get('min'))); - } - - private function formatMaxTypeMatcher(MaxType $matcher): string - { - return sprintf('atMost(%s)', $this->normalize($matcher->getAttributes()->get('max'))); - } - - private 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 MatchingExpressionException(sprintf("Plugin formatter doesn't support value of type %s", gettype($value))), - }; - } -} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/ValueOptionalFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/ValueOptionalFormatter.php deleted file mode 100644 index 61ce2a0f..00000000 --- a/src/PhpPact/Consumer/Matcher/Formatters/ValueOptionalFormatter.php +++ /dev/null @@ -1,36 +0,0 @@ - - */ - public function format(MatcherInterface $matcher): array - { - $data = [ - 'pact:matcher:type' => $matcher->getType(), - ]; - $attributes = $matcher->getAttributes(); - $generator = $matcher instanceof GeneratorAwareInterface ? $matcher->getGenerator() : null; - - if ($generator) { - return [ - ...$data, - 'pact:generator:type' => $generator->getType(), - ...$attributes->merge($generator->getAttributes())->getData(), - ]; - } - - return [ - ...$data, - ...$attributes->getData(), - 'value' => $matcher->getValue(), - ]; - } -} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/ValueRequiredFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/ValueRequiredFormatter.php deleted file mode 100644 index 7e367b05..00000000 --- a/src/PhpPact/Consumer/Matcher/Formatters/ValueRequiredFormatter.php +++ /dev/null @@ -1,18 +0,0 @@ - - */ - public function format(MatcherInterface $matcher): array - { - return [ - ...parent::format($matcher), - 'value' => $matcher->getValue()]; - } -} diff --git a/src/PhpPact/Consumer/Matcher/Formatters/XmlContentFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Xml/XmlContentFormatter.php similarity index 83% rename from src/PhpPact/Consumer/Matcher/Formatters/XmlContentFormatter.php rename to src/PhpPact/Consumer/Matcher/Formatters/Xml/XmlContentFormatter.php index a554b964..859f0a97 100644 --- a/src/PhpPact/Consumer/Matcher/Formatters/XmlContentFormatter.php +++ b/src/PhpPact/Consumer/Matcher/Formatters/Xml/XmlContentFormatter.php @@ -1,12 +1,13 @@ diff --git a/src/PhpPact/Consumer/Matcher/Formatters/XmlElementFormatter.php b/src/PhpPact/Consumer/Matcher/Formatters/Xml/XmlElementFormatter.php similarity index 65% rename from src/PhpPact/Consumer/Matcher/Formatters/XmlElementFormatter.php rename to src/PhpPact/Consumer/Matcher/Formatters/Xml/XmlElementFormatter.php index 3520b61a..05ef94c2 100644 --- a/src/PhpPact/Consumer/Matcher/Formatters/XmlElementFormatter.php +++ b/src/PhpPact/Consumer/Matcher/Formatters/Xml/XmlElementFormatter.php @@ -1,12 +1,13 @@ @@ -18,7 +19,11 @@ public function format(MatcherInterface $matcher): array throw new InvalidValueException('Value must be xml element'); } - $result = parent::format($matcher); + $result = [ + 'pact:matcher:type' => $matcher->getType(), + ...$matcher->getAttributes()->getData(), + 'value' => $matcher->getValue(), + ]; $examples = $value->getExamples(); if (null !== $examples) { diff --git a/src/PhpPact/Consumer/Matcher/Matcher.php b/src/PhpPact/Consumer/Matcher/Matcher.php index 0cca8bb8..8650a8bd 100644 --- a/src/PhpPact/Consumer/Matcher/Matcher.php +++ b/src/PhpPact/Consumer/Matcher/Matcher.php @@ -33,8 +33,6 @@ use PhpPact\Consumer\Matcher\Matchers\Time; use PhpPact\Consumer\Matcher\Matchers\Type; use PhpPact\Consumer\Matcher\Matchers\Values; -use PhpPact\Consumer\Matcher\Model\FormatterAwareInterface; -use PhpPact\Consumer\Matcher\Model\FormatterInterface; use PhpPact\Consumer\Matcher\Model\GeneratorAwareInterface; use PhpPact\Consumer\Matcher\Model\MatcherInterface; @@ -55,7 +53,7 @@ class Matcher public const IPV6_FORMAT = '^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))$'; public const HEX_FORMAT = '^[0-9a-fA-F]+$'; - public function __construct(private ?FormatterInterface $formatter = null) + public function __construct(private bool $plugin = false) { } @@ -485,11 +483,14 @@ public function atMost(int $max): MatcherInterface return $this->atMostLike(null, $max); } - private function withFormatter(MatcherInterface&FormatterAwareInterface $matcher): MatcherInterface + private function withFormatter(MatcherInterface $matcher): MatcherInterface { - if ($this->formatter) { - $matcher->setFormatter($this->formatter); + if ($this->plugin) { + $formatter = $matcher->createExpressionFormatter(); + } else { + $formatter = $matcher->createJsonFormatter(); } + $matcher->setFormatter($formatter); return $matcher; } diff --git a/src/PhpPact/Consumer/Matcher/Matchers/AbstractDateTime.php b/src/PhpPact/Consumer/Matcher/Matchers/AbstractDateTime.php index 65ea9f50..c4061848 100644 --- a/src/PhpPact/Consumer/Matcher/Matchers/AbstractDateTime.php +++ b/src/PhpPact/Consumer/Matcher/Matchers/AbstractDateTime.php @@ -2,6 +2,11 @@ namespace PhpPact\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\DateTimeFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\HasGeneratorFormatter; +use PhpPact\Consumer\Matcher\Model\ExpressionFormatterInterface; +use PhpPact\Consumer\Matcher\Model\JsonFormatterInterface; + abstract class AbstractDateTime extends GeneratorAwareMatcher { public function __construct(protected string $format, private ?string $value = null) @@ -26,4 +31,14 @@ public function getValue(): ?string { return $this->value; } + + public function createJsonFormatter(): JsonFormatterInterface + { + return new HasGeneratorFormatter(); + } + + public function createExpressionFormatter(): ExpressionFormatterInterface + { + return new DateTimeFormatter(); + } } diff --git a/src/PhpPact/Consumer/Matcher/Matchers/AbstractMatcher.php b/src/PhpPact/Consumer/Matcher/Matchers/AbstractMatcher.php index d7d7b956..8c3f2558 100644 --- a/src/PhpPact/Consumer/Matcher/Matchers/AbstractMatcher.php +++ b/src/PhpPact/Consumer/Matcher/Matchers/AbstractMatcher.php @@ -10,6 +10,11 @@ abstract class AbstractMatcher implements MatcherInterface { use FormatterAwareTrait; + public function __construct() + { + $this->setFormatter($this->createJsonFormatter()); + } + /** * @return string|array */ diff --git a/src/PhpPact/Consumer/Matcher/Matchers/ArrayContains.php b/src/PhpPact/Consumer/Matcher/Matchers/ArrayContains.php index 4e4dbaf3..dbce8c31 100644 --- a/src/PhpPact/Consumer/Matcher/Matchers/ArrayContains.php +++ b/src/PhpPact/Consumer/Matcher/Matchers/ArrayContains.php @@ -2,7 +2,10 @@ namespace PhpPact\Consumer\Matcher\Matchers; -use PhpPact\Consumer\Matcher\Formatters\ValueRequiredFormatter; +use PhpPact\Consumer\Matcher\Exception\MatcherNotSupportedException; +use PhpPact\Consumer\Matcher\Formatters\Json\NoGeneratorFormatter; +use PhpPact\Consumer\Matcher\Model\ExpressionFormatterInterface; +use PhpPact\Consumer\Matcher\Model\JsonFormatterInterface; /** * Checks if all the variants are present in an array. @@ -14,7 +17,7 @@ class ArrayContains extends AbstractMatcher */ public function __construct(private array $variants) { - $this->setFormatter(new ValueRequiredFormatter()); + parent::__construct(); } /** @@ -37,4 +40,14 @@ public function getType(): string { return 'arrayContains'; } + + public function createJsonFormatter(): JsonFormatterInterface + { + return new NoGeneratorFormatter(); + } + + public function createExpressionFormatter(): ExpressionFormatterInterface + { + throw new MatcherNotSupportedException("ArrayContains matcher doesn't support expression formatter"); + } } diff --git a/src/PhpPact/Consumer/Matcher/Matchers/Boolean.php b/src/PhpPact/Consumer/Matcher/Matchers/Boolean.php index 96f2a59b..51f46454 100644 --- a/src/PhpPact/Consumer/Matcher/Matchers/Boolean.php +++ b/src/PhpPact/Consumer/Matcher/Matchers/Boolean.php @@ -2,7 +2,11 @@ namespace PhpPact\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\BooleanFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\HasGeneratorFormatter; use PhpPact\Consumer\Matcher\Generators\RandomBoolean; +use PhpPact\Consumer\Matcher\Model\ExpressionFormatterInterface; +use PhpPact\Consumer\Matcher\Model\JsonFormatterInterface; /** * Match if the value is a boolean value (booleans and the string values `true` and `false`) @@ -31,4 +35,14 @@ public function getValue(): ?bool { return $this->value; } + + public function createJsonFormatter(): JsonFormatterInterface + { + return new HasGeneratorFormatter(); + } + + public function createExpressionFormatter(): ExpressionFormatterInterface + { + return new BooleanFormatter(); + } } diff --git a/src/PhpPact/Consumer/Matcher/Matchers/CombinedMatchers.php b/src/PhpPact/Consumer/Matcher/Matchers/CombinedMatchers.php index 8fbd8704..2fe3cfba 100644 --- a/src/PhpPact/Consumer/Matcher/Matchers/CombinedMatchers.php +++ b/src/PhpPact/Consumer/Matcher/Matchers/CombinedMatchers.php @@ -3,7 +3,6 @@ namespace PhpPact\Consumer\Matcher\Matchers; use PhpPact\Consumer\Matcher\Exception\MatcherNotSupportedException; -use PhpPact\Consumer\Matcher\Formatters\CombinedMatchersFormatter; use PhpPact\Consumer\Matcher\Model\CombinedMatchersInterface; use PhpPact\Consumer\Matcher\Model\MatcherInterface; use PhpPact\Consumer\Matcher\Trait\MatchersTrait; @@ -24,7 +23,7 @@ public function __construct(private object|array $value, array $matchers) } $this->addMatcher($matcher); } - $this->setFormatter(new CombinedMatchersFormatter()); + parent::__construct(); } protected function getAttributesData(): array diff --git a/src/PhpPact/Consumer/Matcher/Matchers/ContentType.php b/src/PhpPact/Consumer/Matcher/Matchers/ContentType.php index 340a6875..9e075cb8 100644 --- a/src/PhpPact/Consumer/Matcher/Matchers/ContentType.php +++ b/src/PhpPact/Consumer/Matcher/Matchers/ContentType.php @@ -2,12 +2,17 @@ namespace PhpPact\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\ContentTypeFormatter as ExpressionFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\ContentTypeFormatter as JsonFormatter; +use PhpPact\Consumer\Matcher\Model\ExpressionFormatterInterface; +use PhpPact\Consumer\Matcher\Model\JsonFormatterInterface; + /** * Match binary data by its content type (magic file check) */ class ContentType extends AbstractMatcher { - public function __construct(private string $contentType) + public function __construct(private string $contentType, private string $value = '') { parent::__construct(); } @@ -19,11 +24,26 @@ protected function getAttributesData(): array public function getValue(): string { - return $this->contentType; + return $this->value; } public function getType(): string { return 'contentType'; } + + public function getContentType(): string + { + return $this->contentType; + } + + public function createJsonFormatter(): JsonFormatterInterface + { + return new JsonFormatter(); + } + + public function createExpressionFormatter(): ExpressionFormatterInterface + { + return new ExpressionFormatter(); + } } diff --git a/src/PhpPact/Consumer/Matcher/Matchers/Decimal.php b/src/PhpPact/Consumer/Matcher/Matchers/Decimal.php index f1f00f82..cd5a7004 100644 --- a/src/PhpPact/Consumer/Matcher/Matchers/Decimal.php +++ b/src/PhpPact/Consumer/Matcher/Matchers/Decimal.php @@ -2,7 +2,11 @@ namespace PhpPact\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\DecimalFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\HasGeneratorFormatter; use PhpPact\Consumer\Matcher\Generators\RandomDecimal; +use PhpPact\Consumer\Matcher\Model\ExpressionFormatterInterface; +use PhpPact\Consumer\Matcher\Model\JsonFormatterInterface; /** * This checks if the type of the value is a number with decimal places. @@ -31,4 +35,14 @@ public function getValue(): ?float { return $this->value; } + + public function createJsonFormatter(): JsonFormatterInterface + { + return new HasGeneratorFormatter(); + } + + public function createExpressionFormatter(): ExpressionFormatterInterface + { + return new DecimalFormatter(); + } } diff --git a/src/PhpPact/Consumer/Matcher/Matchers/EachKey.php b/src/PhpPact/Consumer/Matcher/Matchers/EachKey.php index 028e1e8a..f13aaf6b 100644 --- a/src/PhpPact/Consumer/Matcher/Matchers/EachKey.php +++ b/src/PhpPact/Consumer/Matcher/Matchers/EachKey.php @@ -2,6 +2,10 @@ namespace PhpPact\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\EachKeyFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\NoGeneratorFormatter; +use PhpPact\Consumer\Matcher\Model\ExpressionFormatterInterface; +use PhpPact\Consumer\Matcher\Model\JsonFormatterInterface; use PhpPact\Consumer\Matcher\Model\MatcherInterface; /** @@ -46,4 +50,14 @@ public function getRules(): array { return $this->rules; } + + public function createJsonFormatter(): JsonFormatterInterface + { + return new NoGeneratorFormatter(); + } + + public function createExpressionFormatter(): ExpressionFormatterInterface + { + return new EachKeyFormatter(); + } } diff --git a/src/PhpPact/Consumer/Matcher/Matchers/EachValue.php b/src/PhpPact/Consumer/Matcher/Matchers/EachValue.php index 08aecb8a..c7f319e5 100644 --- a/src/PhpPact/Consumer/Matcher/Matchers/EachValue.php +++ b/src/PhpPact/Consumer/Matcher/Matchers/EachValue.php @@ -2,6 +2,10 @@ namespace PhpPact\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\EachValueFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\NoGeneratorFormatter; +use PhpPact\Consumer\Matcher\Model\ExpressionFormatterInterface; +use PhpPact\Consumer\Matcher\Model\JsonFormatterInterface; use PhpPact\Consumer\Matcher\Model\MatcherInterface; /** @@ -46,4 +50,14 @@ public function getRules(): array { return $this->rules; } + + public function createJsonFormatter(): JsonFormatterInterface + { + return new NoGeneratorFormatter(); + } + + public function createExpressionFormatter(): ExpressionFormatterInterface + { + return new EachValueFormatter(); + } } diff --git a/src/PhpPact/Consumer/Matcher/Matchers/Equality.php b/src/PhpPact/Consumer/Matcher/Matchers/Equality.php index f0e1cf8b..de433bb2 100644 --- a/src/PhpPact/Consumer/Matcher/Matchers/Equality.php +++ b/src/PhpPact/Consumer/Matcher/Matchers/Equality.php @@ -2,6 +2,11 @@ namespace PhpPact\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\EqualityFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\NoGeneratorFormatter; +use PhpPact\Consumer\Matcher\Model\ExpressionFormatterInterface; +use PhpPact\Consumer\Matcher\Model\JsonFormatterInterface; + /** * This is the default matcher, and relies on the equals operator */ @@ -32,4 +37,14 @@ public function getType(): string { return 'equality'; } + + public function createJsonFormatter(): JsonFormatterInterface + { + return new NoGeneratorFormatter(); + } + + public function createExpressionFormatter(): ExpressionFormatterInterface + { + return new EqualityFormatter(); + } } diff --git a/src/PhpPact/Consumer/Matcher/Matchers/Includes.php b/src/PhpPact/Consumer/Matcher/Matchers/Includes.php index 803d2682..c04514f5 100644 --- a/src/PhpPact/Consumer/Matcher/Matchers/Includes.php +++ b/src/PhpPact/Consumer/Matcher/Matchers/Includes.php @@ -2,6 +2,11 @@ namespace PhpPact\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\IncludesFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\NoGeneratorFormatter; +use PhpPact\Consumer\Matcher\Model\ExpressionFormatterInterface; +use PhpPact\Consumer\Matcher\Model\JsonFormatterInterface; + /** * This checks if the string representation of a value contains the substring. */ @@ -26,4 +31,14 @@ public function getType(): string { return 'include'; } + + public function createJsonFormatter(): JsonFormatterInterface + { + return new NoGeneratorFormatter(); + } + + public function createExpressionFormatter(): ExpressionFormatterInterface + { + return new IncludesFormatter(); + } } diff --git a/src/PhpPact/Consumer/Matcher/Matchers/Integer.php b/src/PhpPact/Consumer/Matcher/Matchers/Integer.php index 9fe9a8ff..a3d1c0d4 100644 --- a/src/PhpPact/Consumer/Matcher/Matchers/Integer.php +++ b/src/PhpPact/Consumer/Matcher/Matchers/Integer.php @@ -2,7 +2,11 @@ namespace PhpPact\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\IntegerFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\HasGeneratorFormatter; use PhpPact\Consumer\Matcher\Generators\RandomInt; +use PhpPact\Consumer\Matcher\Model\ExpressionFormatterInterface; +use PhpPact\Consumer\Matcher\Model\JsonFormatterInterface; /** * This checks if the type of the value is an integer. @@ -31,4 +35,14 @@ public function getValue(): ?int { return $this->value; } + + public function createJsonFormatter(): JsonFormatterInterface + { + return new HasGeneratorFormatter(); + } + + public function createExpressionFormatter(): ExpressionFormatterInterface + { + return new IntegerFormatter(); + } } diff --git a/src/PhpPact/Consumer/Matcher/Matchers/MatchAll.php b/src/PhpPact/Consumer/Matcher/Matchers/MatchAll.php index 0da295fc..68ed6c1e 100644 --- a/src/PhpPact/Consumer/Matcher/Matchers/MatchAll.php +++ b/src/PhpPact/Consumer/Matcher/Matchers/MatchAll.php @@ -2,10 +2,25 @@ namespace PhpPact\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\MatchAllFormatter as ExpressionFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\MatchAllFormatter as JsonFormatter; +use PhpPact\Consumer\Matcher\Model\ExpressionFormatterInterface; +use PhpPact\Consumer\Matcher\Model\JsonFormatterInterface; + class MatchAll extends CombinedMatchers { public function getType(): string { return 'matchAll'; } + + public function createJsonFormatter(): JsonFormatterInterface + { + return new JsonFormatter(); + } + + public function createExpressionFormatter(): ExpressionFormatterInterface + { + return new ExpressionFormatter(); + } } diff --git a/src/PhpPact/Consumer/Matcher/Matchers/MatchingField.php b/src/PhpPact/Consumer/Matcher/Matchers/MatchingField.php index e2c11833..14701d9d 100644 --- a/src/PhpPact/Consumer/Matcher/Matchers/MatchingField.php +++ b/src/PhpPact/Consumer/Matcher/Matchers/MatchingField.php @@ -3,13 +3,15 @@ namespace PhpPact\Consumer\Matcher\Matchers; use PhpPact\Consumer\Matcher\Exception\MatcherNotSupportedException; +use PhpPact\Consumer\Matcher\Formatters\Expression\MatchingFieldFormatter; +use PhpPact\Consumer\Matcher\Model\ExpressionFormatterInterface; +use PhpPact\Consumer\Matcher\Model\JsonFormatterInterface; class MatchingField extends AbstractMatcher { - public const MATCHER_NOT_SUPPORTED_EXCEPTION_MESSAGE = 'MatchingField matcher only work with plugin'; - public function __construct(private string $fieldName) { + $this->setFormatter($this->createExpressionFormatter()); } public function getFieldName(): string @@ -17,28 +19,38 @@ public function getFieldName(): string return $this->fieldName; } - public function getValue(): mixed + public function getValue(): string { - throw new MatcherNotSupportedException(self::MATCHER_NOT_SUPPORTED_EXCEPTION_MESSAGE); + return $this->getFieldName(); } public function getType(): string { - throw new MatcherNotSupportedException(self::MATCHER_NOT_SUPPORTED_EXCEPTION_MESSAGE); + return 'matchingField'; } protected function getAttributesData(): array { - throw new MatcherNotSupportedException(self::MATCHER_NOT_SUPPORTED_EXCEPTION_MESSAGE); + return []; } public function jsonSerialize(): string { $result = parent::jsonSerialize(); if (is_array($result)) { - throw new MatcherNotSupportedException(self::MATCHER_NOT_SUPPORTED_EXCEPTION_MESSAGE); + throw new MatcherNotSupportedException("MatchingField matcher doesn't support json formatter"); } return $result; } + + public function createJsonFormatter(): JsonFormatterInterface + { + throw new MatcherNotSupportedException("MatchingField matcher doesn't support json formatter"); + } + + public function createExpressionFormatter(): ExpressionFormatterInterface + { + return new MatchingFieldFormatter(); + } } diff --git a/src/PhpPact/Consumer/Matcher/Matchers/MaxType.php b/src/PhpPact/Consumer/Matcher/Matchers/MaxType.php index dede0193..971b1289 100644 --- a/src/PhpPact/Consumer/Matcher/Matchers/MaxType.php +++ b/src/PhpPact/Consumer/Matcher/Matchers/MaxType.php @@ -2,6 +2,11 @@ namespace PhpPact\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\MaxTypeFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\NoGeneratorFormatter; +use PhpPact\Consumer\Matcher\Model\ExpressionFormatterInterface; +use PhpPact\Consumer\Matcher\Model\JsonFormatterInterface; + /** * This executes a type based match against the values, that is, they are equal if they are the same type. * In addition, if the values represent a collection, the length of the actual value is compared against the maximum. @@ -38,4 +43,19 @@ public function getType(): string { return 'type'; } + + public function getMax(): int + { + return $this->max; + } + + public function createJsonFormatter(): JsonFormatterInterface + { + return new NoGeneratorFormatter(); + } + + public function createExpressionFormatter(): ExpressionFormatterInterface + { + return new MaxTypeFormatter(); + } } diff --git a/src/PhpPact/Consumer/Matcher/Matchers/MinMaxType.php b/src/PhpPact/Consumer/Matcher/Matchers/MinMaxType.php index 10a29238..a1caed5b 100644 --- a/src/PhpPact/Consumer/Matcher/Matchers/MinMaxType.php +++ b/src/PhpPact/Consumer/Matcher/Matchers/MinMaxType.php @@ -2,6 +2,11 @@ namespace PhpPact\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Exception\MatcherNotSupportedException; +use PhpPact\Consumer\Matcher\Formatters\Json\NoGeneratorFormatter; +use PhpPact\Consumer\Matcher\Model\ExpressionFormatterInterface; +use PhpPact\Consumer\Matcher\Model\JsonFormatterInterface; + /** * This executes a type based match against the values, that is, they are equal if they are the same type. * In addition, if the values represent a collection, the length of the actual value is compared against the minimum and maximum. @@ -42,4 +47,14 @@ public function getType(): string { return 'type'; } + + public function createJsonFormatter(): JsonFormatterInterface + { + return new NoGeneratorFormatter(); + } + + public function createExpressionFormatter(): ExpressionFormatterInterface + { + throw new MatcherNotSupportedException("MinMaxType matcher doesn't support expression formatter"); + } } diff --git a/src/PhpPact/Consumer/Matcher/Matchers/MinType.php b/src/PhpPact/Consumer/Matcher/Matchers/MinType.php index 4f709ad6..0874117a 100644 --- a/src/PhpPact/Consumer/Matcher/Matchers/MinType.php +++ b/src/PhpPact/Consumer/Matcher/Matchers/MinType.php @@ -2,6 +2,11 @@ namespace PhpPact\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\MinTypeFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\NoGeneratorFormatter; +use PhpPact\Consumer\Matcher\Model\ExpressionFormatterInterface; +use PhpPact\Consumer\Matcher\Model\JsonFormatterInterface; + /** * This executes a type based match against the values, that is, they are equal if they are the same type. * In addition, if the values represent a collection, the length of the actual value is compared against the minimum. @@ -38,4 +43,19 @@ public function getValue(): array { return array_values($this->values); } + + public function getMin(): int + { + return $this->min; + } + + public function createJsonFormatter(): JsonFormatterInterface + { + return new NoGeneratorFormatter(); + } + + public function createExpressionFormatter(): ExpressionFormatterInterface + { + return new MinTypeFormatter(); + } } diff --git a/src/PhpPact/Consumer/Matcher/Matchers/NotEmpty.php b/src/PhpPact/Consumer/Matcher/Matchers/NotEmpty.php index f044a5a7..fd28b8e1 100644 --- a/src/PhpPact/Consumer/Matcher/Matchers/NotEmpty.php +++ b/src/PhpPact/Consumer/Matcher/Matchers/NotEmpty.php @@ -2,6 +2,11 @@ namespace PhpPact\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\NotEmptyFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\NoGeneratorFormatter; +use PhpPact\Consumer\Matcher\Model\ExpressionFormatterInterface; +use PhpPact\Consumer\Matcher\Model\JsonFormatterInterface; + /** * Value must be present and not empty (not null or the empty string) */ @@ -32,4 +37,14 @@ public function getType(): string { return 'notEmpty'; } + + public function createJsonFormatter(): JsonFormatterInterface + { + return new NoGeneratorFormatter(); + } + + public function createExpressionFormatter(): ExpressionFormatterInterface + { + return new NotEmptyFormatter(); + } } diff --git a/src/PhpPact/Consumer/Matcher/Matchers/NullValue.php b/src/PhpPact/Consumer/Matcher/Matchers/NullValue.php index 82715007..8350ff77 100644 --- a/src/PhpPact/Consumer/Matcher/Matchers/NullValue.php +++ b/src/PhpPact/Consumer/Matcher/Matchers/NullValue.php @@ -2,18 +2,16 @@ namespace PhpPact\Consumer\Matcher\Matchers; -use PhpPact\Consumer\Matcher\Formatters\MinimalFormatter; +use PhpPact\Consumer\Matcher\Formatters\Expression\NullValueFormatter as ExpressionFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\NullValueFormatter as JsonFormatter; +use PhpPact\Consumer\Matcher\Model\ExpressionFormatterInterface; +use PhpPact\Consumer\Matcher\Model\JsonFormatterInterface; /** * Match if the value is a null value (this is content specific, for JSON will match a JSON null) */ class NullValue extends AbstractMatcher { - public function __construct() - { - $this->setFormatter(new MinimalFormatter()); - } - public function getType(): string { return 'null'; @@ -31,4 +29,14 @@ public function getValue(): mixed { return null; } + + public function createJsonFormatter(): JsonFormatterInterface + { + return new JsonFormatter(); + } + + public function createExpressionFormatter(): ExpressionFormatterInterface + { + return new ExpressionFormatter(); + } } diff --git a/src/PhpPact/Consumer/Matcher/Matchers/Number.php b/src/PhpPact/Consumer/Matcher/Matchers/Number.php index 83cac53b..4acae2fb 100644 --- a/src/PhpPact/Consumer/Matcher/Matchers/Number.php +++ b/src/PhpPact/Consumer/Matcher/Matchers/Number.php @@ -2,7 +2,11 @@ namespace PhpPact\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\NumberFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\HasGeneratorFormatter; use PhpPact\Consumer\Matcher\Generators\RandomInt; +use PhpPact\Consumer\Matcher\Model\ExpressionFormatterInterface; +use PhpPact\Consumer\Matcher\Model\JsonFormatterInterface; /** * This checks if the type of the value is a number. @@ -31,4 +35,14 @@ public function getValue(): int|float|null { return $this->value; } + + public function createJsonFormatter(): JsonFormatterInterface + { + return new HasGeneratorFormatter(); + } + + public function createExpressionFormatter(): ExpressionFormatterInterface + { + return new NumberFormatter(); + } } diff --git a/src/PhpPact/Consumer/Matcher/Matchers/Regex.php b/src/PhpPact/Consumer/Matcher/Matchers/Regex.php index d7822e9a..642353c3 100644 --- a/src/PhpPact/Consumer/Matcher/Matchers/Regex.php +++ b/src/PhpPact/Consumer/Matcher/Matchers/Regex.php @@ -3,7 +3,11 @@ namespace PhpPact\Consumer\Matcher\Matchers; use PhpPact\Consumer\Matcher\Exception\InvalidRegexException; +use PhpPact\Consumer\Matcher\Formatters\Expression\RegexFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\HasGeneratorFormatter; use PhpPact\Consumer\Matcher\Generators\Regex as RegexGenerator; +use PhpPact\Consumer\Matcher\Model\ExpressionFormatterInterface; +use PhpPact\Consumer\Matcher\Model\JsonFormatterInterface; use function preg_last_error; use function preg_match; @@ -73,4 +77,14 @@ public function getRegex(): string { return $this->regex; } + + public function createJsonFormatter(): JsonFormatterInterface + { + return new HasGeneratorFormatter(); + } + + public function createExpressionFormatter(): ExpressionFormatterInterface + { + return new RegexFormatter(); + } } diff --git a/src/PhpPact/Consumer/Matcher/Matchers/Semver.php b/src/PhpPact/Consumer/Matcher/Matchers/Semver.php index 03521ce2..6f36e587 100644 --- a/src/PhpPact/Consumer/Matcher/Matchers/Semver.php +++ b/src/PhpPact/Consumer/Matcher/Matchers/Semver.php @@ -2,7 +2,11 @@ namespace PhpPact\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\SemverFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\HasGeneratorFormatter; use PhpPact\Consumer\Matcher\Generators\Regex; +use PhpPact\Consumer\Matcher\Model\ExpressionFormatterInterface; +use PhpPact\Consumer\Matcher\Model\JsonFormatterInterface; /** * Value must be valid based on the semver specification @@ -31,4 +35,14 @@ public function getValue(): ?string { return $this->value; } + + public function createJsonFormatter(): JsonFormatterInterface + { + return new HasGeneratorFormatter(); + } + + public function createExpressionFormatter(): ExpressionFormatterInterface + { + return new SemverFormatter(); + } } diff --git a/src/PhpPact/Consumer/Matcher/Matchers/StatusCode.php b/src/PhpPact/Consumer/Matcher/Matchers/StatusCode.php index 15db5716..8d1b5226 100644 --- a/src/PhpPact/Consumer/Matcher/Matchers/StatusCode.php +++ b/src/PhpPact/Consumer/Matcher/Matchers/StatusCode.php @@ -3,8 +3,12 @@ namespace PhpPact\Consumer\Matcher\Matchers; use PhpPact\Consumer\Matcher\Exception\InvalidHttpStatusException; +use PhpPact\Consumer\Matcher\Exception\MatcherNotSupportedException; +use PhpPact\Consumer\Matcher\Formatters\Json\HasGeneratorFormatter; use PhpPact\Consumer\Matcher\Generators\RandomInt; use PhpPact\Consumer\Matcher\HttpStatus; +use PhpPact\Consumer\Matcher\Model\ExpressionFormatterInterface; +use PhpPact\Consumer\Matcher\Model\JsonFormatterInterface; /** * Matches the response status code. @@ -51,4 +55,14 @@ public function getValue(): ?int { return $this->value; } + + public function createJsonFormatter(): JsonFormatterInterface + { + return new HasGeneratorFormatter(); + } + + public function createExpressionFormatter(): ExpressionFormatterInterface + { + throw new MatcherNotSupportedException("StatusCode matcher doesn't support expression formatter"); + } } diff --git a/src/PhpPact/Consumer/Matcher/Matchers/StringValue.php b/src/PhpPact/Consumer/Matcher/Matchers/StringValue.php index f0267bcf..611e8080 100644 --- a/src/PhpPact/Consumer/Matcher/Matchers/StringValue.php +++ b/src/PhpPact/Consumer/Matcher/Matchers/StringValue.php @@ -2,8 +2,11 @@ namespace PhpPact\Consumer\Matcher\Matchers; -use PhpPact\Consumer\Matcher\Formatters\ValueRequiredFormatter; +use PhpPact\Consumer\Matcher\Formatters\Expression\StringValueFormatter as ExpressionFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\StringValueFormatter as JsonFormatter; use PhpPact\Consumer\Matcher\Generators\RandomString; +use PhpPact\Consumer\Matcher\Model\ExpressionFormatterInterface; +use PhpPact\Consumer\Matcher\Model\JsonFormatterInterface; /** * There is no matcher for string. We re-use `type` matcher. @@ -17,7 +20,7 @@ public function __construct(private ?string $value = null) if ($value === null) { $this->setGenerator(new RandomString()); } - $this->setFormatter(new ValueRequiredFormatter()); + parent::__construct(); } public function getType(): string @@ -42,4 +45,14 @@ public function getValue(): string { return $this->value ?? self::DEFAULT_VALUE; } + + public function createJsonFormatter(): JsonFormatterInterface + { + return new JsonFormatter(); + } + + public function createExpressionFormatter(): ExpressionFormatterInterface + { + return new ExpressionFormatter(); + } } diff --git a/src/PhpPact/Consumer/Matcher/Matchers/Type.php b/src/PhpPact/Consumer/Matcher/Matchers/Type.php index 46b9b51c..f79c0d38 100644 --- a/src/PhpPact/Consumer/Matcher/Matchers/Type.php +++ b/src/PhpPact/Consumer/Matcher/Matchers/Type.php @@ -2,6 +2,11 @@ namespace PhpPact\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\TypeFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\NoGeneratorFormatter; +use PhpPact\Consumer\Matcher\Model\ExpressionFormatterInterface; +use PhpPact\Consumer\Matcher\Model\JsonFormatterInterface; + /** * This executes a type based match against the values, that is, they are equal if they are the same type. */ @@ -32,4 +37,14 @@ public function getType(): string { return 'type'; } + + public function createJsonFormatter(): JsonFormatterInterface + { + return new NoGeneratorFormatter(); + } + + public function createExpressionFormatter(): ExpressionFormatterInterface + { + return new TypeFormatter(); + } } diff --git a/src/PhpPact/Consumer/Matcher/Matchers/Values.php b/src/PhpPact/Consumer/Matcher/Matchers/Values.php index 7e68cce4..0daa67e0 100644 --- a/src/PhpPact/Consumer/Matcher/Matchers/Values.php +++ b/src/PhpPact/Consumer/Matcher/Matchers/Values.php @@ -2,6 +2,11 @@ namespace PhpPact\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Exception\MatcherNotSupportedException; +use PhpPact\Consumer\Matcher\Formatters\Json\NoGeneratorFormatter; +use PhpPact\Consumer\Matcher\Model\ExpressionFormatterInterface; +use PhpPact\Consumer\Matcher\Model\JsonFormatterInterface; + /** * Match the values in a map, ignoring the keys * @@ -34,4 +39,14 @@ public function getType(): string { return 'values'; } + + public function createJsonFormatter(): JsonFormatterInterface + { + return new NoGeneratorFormatter(); + } + + public function createExpressionFormatter(): ExpressionFormatterInterface + { + throw new MatcherNotSupportedException("Values matcher doesn't support expression formatter"); + } } diff --git a/src/PhpPact/Consumer/Matcher/Model/ExpressionFormatterInterface.php b/src/PhpPact/Consumer/Matcher/Model/ExpressionFormatterInterface.php new file mode 100644 index 00000000..bf683237 --- /dev/null +++ b/src/PhpPact/Consumer/Matcher/Model/ExpressionFormatterInterface.php @@ -0,0 +1,8 @@ + + */ + public function format(MatcherInterface $matcher): array; +} diff --git a/src/PhpPact/Consumer/Matcher/Model/MatcherInterface.php b/src/PhpPact/Consumer/Matcher/Model/MatcherInterface.php index f5a7672c..d0ab5876 100644 --- a/src/PhpPact/Consumer/Matcher/Model/MatcherInterface.php +++ b/src/PhpPact/Consumer/Matcher/Model/MatcherInterface.php @@ -4,7 +4,7 @@ use JsonSerializable; -interface MatcherInterface extends JsonSerializable, FormatterAwareInterface +interface MatcherInterface extends JsonSerializable, FormatterAwareInterface, FormatterFactoryInterface { public function getType(): string; diff --git a/src/PhpPact/Consumer/Matcher/Trait/FormatterAwareTrait.php b/src/PhpPact/Consumer/Matcher/Trait/FormatterAwareTrait.php index d6931257..9b1e43b1 100644 --- a/src/PhpPact/Consumer/Matcher/Trait/FormatterAwareTrait.php +++ b/src/PhpPact/Consumer/Matcher/Trait/FormatterAwareTrait.php @@ -2,18 +2,12 @@ namespace PhpPact\Consumer\Matcher\Trait; -use PhpPact\Consumer\Matcher\Formatters\ValueOptionalFormatter; use PhpPact\Consumer\Matcher\Model\FormatterInterface; trait FormatterAwareTrait { private FormatterInterface $formatter; - public function __construct() - { - $this->formatter = new ValueOptionalFormatter(); - } - public function setFormatter(FormatterInterface $formatter): void { $this->formatter = $formatter; diff --git a/src/PhpPact/Xml/Model/Builder/ElementTrait.php b/src/PhpPact/Xml/Model/Builder/ElementTrait.php index d593fe75..0d088f05 100644 --- a/src/PhpPact/Xml/Model/Builder/ElementTrait.php +++ b/src/PhpPact/Xml/Model/Builder/ElementTrait.php @@ -2,7 +2,7 @@ namespace PhpPact\Xml\Model\Builder; -use PhpPact\Consumer\Matcher\Formatters\XmlElementFormatter; +use PhpPact\Consumer\Matcher\Formatters\Xml\XmlElementFormatter; use PhpPact\Consumer\Matcher\Matchers\Type; use PhpPact\Consumer\Matcher\Model\MatcherInterface; use PhpPact\Xml\XmlElement; diff --git a/src/PhpPact/Xml/Model/Builder/TextTrait.php b/src/PhpPact/Xml/Model/Builder/TextTrait.php index 4fe8a7f2..e82ea791 100644 --- a/src/PhpPact/Xml/Model/Builder/TextTrait.php +++ b/src/PhpPact/Xml/Model/Builder/TextTrait.php @@ -2,7 +2,7 @@ namespace PhpPact\Xml\Model\Builder; -use PhpPact\Consumer\Matcher\Formatters\XmlContentFormatter; +use PhpPact\Consumer\Matcher\Formatters\Xml\XmlContentFormatter; use PhpPact\Consumer\Matcher\Matchers\Type; use PhpPact\Consumer\Matcher\Model\MatcherInterface; use PhpPact\Xml\XmlElement; diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/CombinedMatchersFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/CombinedMatchersFormatterTest.php deleted file mode 100644 index f3d1c710..00000000 --- a/tests/PhpPact/Consumer/Matcher/Formatters/CombinedMatchersFormatterTest.php +++ /dev/null @@ -1,30 +0,0 @@ - 123], [ - new MinType([], 1), - new MaxType([], 2), - new EachKey([], [new Includes('test')]), - new EachValue([], [new Integer(123)]), - ]); - $formatter = new CombinedMatchersFormatter(); - $jsonEncoded = json_encode($formatter->format($matcher)); - $this->assertIsString($jsonEncoded); - $this->assertJsonStringEqualsJsonString('{"pact:matcher:type":[{"pact:matcher:type":"type","min":1,"value":[]},{"pact:matcher:type":"type","max":2,"value":[]},{"pact:matcher:type":"eachKey","rules":[{"pact:matcher:type":"include","value":"test"}],"value":[]},{"pact:matcher:type":"eachValue","rules":[{"pact:matcher:type":"integer","value":123}],"value":[]}],"value":{"test 123":123}}', $jsonEncoded); - } -} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Expression/BooleanFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/BooleanFormatterTest.php new file mode 100644 index 00000000..a8c252ce --- /dev/null +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/BooleanFormatterTest.php @@ -0,0 +1,46 @@ +formatter = new BooleanFormatter(); + } + + public function testNotSupportedMatcher(): void + { + $matcher = new NullValue(); + $this->expectException(MatcherNotSupportedException::class); + $this->expectExceptionMessage(sprintf('Matcher %s is not supported by %s', $matcher->getType(), $this->formatter::class)); + $this->formatter->format($matcher); + } + + public function testInvalidValue(): void + { + $matcher = new Boolean(); + $this->expectException(InvalidValueException::class); + $this->expectExceptionMessage(sprintf("Boolean formatter doesn't support value of type %s", gettype(null))); + $this->formatter->format($matcher); + } + + #[TestWith([new Boolean(true), '"matching(boolean, true)"'])] + #[TestWith([new Boolean(false), '"matching(boolean, false)"'])] + public function testFormat(MatcherInterface $matcher, string $expression): void + { + $this->assertSame($expression, json_encode($this->formatter->format($matcher))); + } +} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Expression/ContentTypeFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/ContentTypeFormatterTest.php new file mode 100644 index 00000000..08691f06 --- /dev/null +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/ContentTypeFormatterTest.php @@ -0,0 +1,48 @@ +formatter = new ContentTypeFormatter(); + } + + public function testNotSupportedMatcher(): void + { + $matcher = new NullValue(); + $this->expectException(MatcherNotSupportedException::class); + $this->expectExceptionMessage(sprintf('Matcher %s is not supported by %s', $matcher->getType(), $this->formatter::class)); + $this->formatter->format($matcher); + } + + #[TestWith([new ContentType("it's invalid type", 'testing'), "it's invalid type"])] + #[TestWith([new ContentType('plain/text', "it's invalid text"), "it's invalid text"])] + public function testInvalidString(MatcherInterface $matcher, string $value): void + { + $this->expectException(InvalidValueException::class); + $this->expectExceptionMessage(sprintf('String value "%s" should not contains single quote', $value)); + $this->formatter->format($matcher); + } + + #[TestWith([new ContentType('plain/text'), '"matching(contentType, \'plain\/text\', \'\')"'])] + #[TestWith([new ContentType('application/json', '{"key":"value"}'), '"matching(contentType, \'application\/json\', \'{\"key\":\"value\"}\')"'])] + #[TestWith([new ContentType('application/xml', ''), '"matching(contentType, \'application\/xml\', \'\')"'])] + public function testFormat(MatcherInterface $matcher, string $expression): void + { + $this->assertSame($expression, json_encode($this->formatter->format($matcher))); + } +} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Expression/DateTimeFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/DateTimeFormatterTest.php new file mode 100644 index 00000000..b3477cd3 --- /dev/null +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/DateTimeFormatterTest.php @@ -0,0 +1,58 @@ +formatter = new DateTimeFormatter(); + } + + public function testNotSupportedMatcher(): void + { + $matcher = new NullValue(); + $this->expectException(MatcherNotSupportedException::class); + $this->expectExceptionMessage(sprintf('Matcher %s is not supported by %s', $matcher->getType(), $this->formatter::class)); + $this->formatter->format($matcher); + } + + public function testInvalidValue(): void + { + $matcher = new Time('HH:mm'); + $this->expectException(InvalidValueException::class); + $this->expectExceptionMessage(sprintf("DateTime formatter doesn't support value of type %s", gettype(null))); + $this->formatter->format($matcher); + } + + #[TestWith([new Time("it's invalid format", 'testing'), "it's invalid format"])] + #[TestWith([new Time('HH:mm', "it's invalid value"), "it's invalid value"])] + public function testInvalidString(MatcherInterface $matcher, string $value): void + { + $this->expectException(InvalidValueException::class); + $this->expectExceptionMessage(sprintf('String value "%s" should not contains single quote', $value)); + $this->formatter->format($matcher); + } + + #[TestWith([new DateTime('yyyy-MM-dd HH:mm:ssZZZZZ', '2020-05-21 16:44:32+10:00'), '"matching(datetime, \'yyyy-MM-dd HH:mm:ssZZZZZ\', \'2020-05-21 16:44:32+10:00\')"'])] + #[TestWith([new Date('yyyy-MM-dd', '2012-04-12'), '"matching(date, \'yyyy-MM-dd\', \'2012-04-12\')"'])] + #[TestWith([new Time('HH:mm', '22:04'), '"matching(time, \'HH:mm\', \'22:04\')"'])] + public function testFormat(MatcherInterface $matcher, string $expression): void + { + $this->assertSame($expression, json_encode($this->formatter->format($matcher))); + } +} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Expression/DecimalFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/DecimalFormatterTest.php new file mode 100644 index 00000000..f36eb0d0 --- /dev/null +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/DecimalFormatterTest.php @@ -0,0 +1,48 @@ +formatter = new DecimalFormatter(); + } + + public function testNotSupportedMatcher(): void + { + $matcher = new NullValue(); + $this->expectException(MatcherNotSupportedException::class); + $this->expectExceptionMessage(sprintf('Matcher %s is not supported by %s', $matcher->getType(), $this->formatter::class)); + $this->formatter->format($matcher); + } + + public function testInvalidValue(): void + { + $matcher = new Decimal(); + $this->expectException(InvalidValueException::class); + $this->expectExceptionMessage(sprintf("Decimal formatter doesn't support value of type %s", gettype(null))); + $this->formatter->format($matcher); + } + + #[TestWith([new Decimal(-99), '"matching(decimal, -99)"'])] // Provider verification will fail on this case + #[TestWith([new Decimal(100), '"matching(decimal, 100)"'])] // Provider verification will fail on this case + #[TestWith([new Decimal(100.01), '"matching(decimal, 100.01)"'])] + #[TestWith([new Decimal(-100.003), '"matching(decimal, -100.003)"'])] + public function testFormat(MatcherInterface $matcher, string $expression): void + { + $this->assertSame($expression, json_encode($this->formatter->format($matcher))); + } +} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Expression/EachKeyFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/EachKeyFormatterTest.php new file mode 100644 index 00000000..e80f3561 --- /dev/null +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/EachKeyFormatterTest.php @@ -0,0 +1,51 @@ +formatter = new EachKeyFormatter(); + } + + public function testNotSupportedMatcher(): void + { + $matcher = new NullValue(); + $this->expectException(MatcherNotSupportedException::class); + $this->expectExceptionMessage(sprintf('Matcher %s is not supported by %s', $matcher->getType(), $this->formatter::class)); + $this->formatter->format($matcher); + } + + #[TestWith([new EachKey(['value'], [])])] + #[TestWith([new EachKey(['value'], [new Type(1), new Type(2)])])] + public function testInvalidRules(EachKey $matcher): void + { + $this->expectException(MatchingExpressionException::class); + $this->expectExceptionMessage(sprintf("Matcher 'eachKey' only support 1 rule in expression, %d provided", count($matcher->getRules()))); + $this->formatter->format($matcher); + } + + #[TestWith([new EachKey(['value'], [new Integer(123)]), '"eachKey(matching(integer, 123))"'])] + #[TestWith([new EachKey(new stdClass(), [new Regex('\w+', 'example value')]), '"eachKey(matching(regex, \'\\\\w+\', \'example value\'))"'])] + public function testFormat(MatcherInterface $matcher, string $expression): void + { + $this->assertSame($expression, json_encode($this->formatter->format($matcher))); + } +} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Expression/EachValueFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/EachValueFormatterTest.php new file mode 100644 index 00000000..31ce1705 --- /dev/null +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/EachValueFormatterTest.php @@ -0,0 +1,51 @@ +formatter = new EachValueFormatter(); + } + + public function testNotSupportedMatcher(): void + { + $matcher = new NullValue(); + $this->expectException(MatcherNotSupportedException::class); + $this->expectExceptionMessage(sprintf('Matcher %s is not supported by %s', $matcher->getType(), $this->formatter::class)); + $this->formatter->format($matcher); + } + + #[TestWith([new EachValue(['value'], [])])] + #[TestWith([new EachValue(['value'], [new Type(1), new Type(2), new Type(3)])])] + public function testInvalidRules(EachValue $matcher): void + { + $this->expectException(MatchingExpressionException::class); + $this->expectExceptionMessage(sprintf("Matcher 'eachValue' only support 1 rule in expression, %d provided", count($matcher->getRules()))); + $this->formatter->format($matcher); + } + + #[TestWith([new EachValue(['value'], [new StringValue('example value')]), '"eachValue(matching(type, \'example value\'))"'])] + #[TestWith([new EachValue(new stdClass(), [new Regex('\w \d', 'a 1')]), '"eachValue(matching(regex, \'\\\\w \\\\d\', \'a 1\'))"'])] + public function testFormat(MatcherInterface $matcher, string $expression): void + { + $this->assertSame($expression, json_encode($this->formatter->format($matcher))); + } +} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Expression/EqualityFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/EqualityFormatterTest.php new file mode 100644 index 00000000..806c3c9a --- /dev/null +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/EqualityFormatterTest.php @@ -0,0 +1,61 @@ +formatter = new EqualityFormatter(); + } + + public function testNotSupportedMatcher(): void + { + $matcher = new NullValue(); + $this->expectException(MatcherNotSupportedException::class); + $this->expectExceptionMessage(sprintf('Matcher %s is not supported by %s', $matcher->getType(), $this->formatter::class)); + $this->formatter->format($matcher); + } + + #[TestWith([new Equality(new \stdClass()), 'object'])] + #[TestWith([new Equality(['key' => 'value']), 'array'])] + public function testInvalidValue(MatcherInterface $matcher, string $type): void + { + $this->expectException(InvalidValueException::class); + $this->expectExceptionMessage(sprintf("Expression doesn't support value of type %s", $type)); + $this->formatter->format($matcher); + } + + #[TestWith([new Equality("it's invalid value"), "it's invalid value"])] + public function testInvalidString(MatcherInterface $matcher, string $value): void + { + $this->expectException(InvalidValueException::class); + $this->expectExceptionMessage(sprintf('String value "%s" should not contains single quote', $value)); + $this->formatter->format($matcher); + } + + #[TestWith([new Equality('example value'), '"matching(equalTo, \'example value\')"'])] + #[TestWith([new Equality(100.09), '"matching(equalTo, 100.09)"'])] + #[TestWith([new Equality(-99.99), '"matching(equalTo, -99.99)"'])] + #[TestWith([new Equality(100), '"matching(equalTo, 100)"'])] + #[TestWith([new Equality(-99), '"matching(equalTo, -99)"'])] + #[TestWith([new Equality(true), '"matching(equalTo, true)"'])] + #[TestWith([new Equality(false), '"matching(equalTo, false)"'])] + #[TestWith([new Equality(null), '"matching(equalTo, null)"'])] + public function testFormat(MatcherInterface $matcher, string $expression): void + { + $this->assertSame($expression, json_encode($this->formatter->format($matcher))); + } +} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Expression/IncludesFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/IncludesFormatterTest.php new file mode 100644 index 00000000..32d6b7eb --- /dev/null +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/IncludesFormatterTest.php @@ -0,0 +1,45 @@ +formatter = new IncludesFormatter(); + } + + public function testNotSupportedMatcher(): void + { + $matcher = new NullValue(); + $this->expectException(MatcherNotSupportedException::class); + $this->expectExceptionMessage(sprintf('Matcher %s is not supported by %s', $matcher->getType(), $this->formatter::class)); + $this->formatter->format($matcher); + } + + #[TestWith([new Includes("it's invalid value"), "it's invalid value"])] + public function testInvalidString(MatcherInterface $matcher, string $value): void + { + $this->expectException(InvalidValueException::class); + $this->expectExceptionMessage(sprintf('String value "%s" should not contains single quote', $value)); + $this->formatter->format($matcher); + } + + #[TestWith([new Includes('example value'), '"matching(include, \'example value\')"'])] + public function testFormat(MatcherInterface $matcher, string $expression): void + { + $this->assertSame($expression, json_encode($this->formatter->format($matcher))); + } +} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Expression/IntegerFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/IntegerFormatterTest.php new file mode 100644 index 00000000..abd2dd4c --- /dev/null +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/IntegerFormatterTest.php @@ -0,0 +1,46 @@ +formatter = new IntegerFormatter(); + } + + public function testNotSupportedMatcher(): void + { + $matcher = new NullValue(); + $this->expectException(MatcherNotSupportedException::class); + $this->expectExceptionMessage(sprintf('Matcher %s is not supported by %s', $matcher->getType(), $this->formatter::class)); + $this->formatter->format($matcher); + } + + public function testInvalidValue(): void + { + $matcher = new Integer(); + $this->expectException(InvalidValueException::class); + $this->expectExceptionMessage(sprintf("Integer formatter doesn't support value of type %s", gettype(null))); + $this->formatter->format($matcher); + } + + #[TestWith([new Integer(-99), '"matching(integer, -99)"'])] + #[TestWith([new Integer(100), '"matching(integer, 100)"'])] + public function testFormat(MatcherInterface $matcher, string $expression): void + { + $this->assertSame($expression, json_encode($this->formatter->format($matcher))); + } +} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Expression/MatchAllFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/MatchAllFormatterTest.php new file mode 100644 index 00000000..bf503a46 --- /dev/null +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/MatchAllFormatterTest.php @@ -0,0 +1,53 @@ +formatter = new MatchAllFormatter(); + } + + public function testNotSupportedMatcher(): void + { + $matcher = new NullValue(); + $this->expectException(MatcherNotSupportedException::class); + $this->expectExceptionMessage(sprintf('Matcher %s is not supported by %s', $matcher->getType(), $this->formatter::class)); + $this->formatter->format($matcher); + } + + #[TestWith([new MatchAll(['value'], [])])] + public function testInvalidMatchers(MatchAll $matcher): void + { + $this->expectException(MatchingExpressionException::class); + $this->expectExceptionMessage("Matcher 'matchAll' need at least 1 matchers"); + $this->formatter->format($matcher); + } + + #[TestWith([new MatchAll(['abc' => 1, 'def' => 234], [new MinType([null], 2)]), '"atLeast(2)"'])] + #[TestWith([new MatchAll(['abc' => 1, 'def' => 234], [new MinType([null], 1), new MaxType([null], 2), new EachKey(["doesn't matter"], [new Regex('\w+', 'abc')]), new EachValue(["doesn't matter"], [new Type(100)])]), '"atLeast(1), atMost(2), eachKey(matching(regex, \'\\\\w+\', \'abc\')), eachValue(matching(type, 100))"'])] + public function testFormat(MatcherInterface $matcher, string $expression): void + { + $this->assertSame($expression, json_encode($this->formatter->format($matcher))); + } +} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Expression/MatchingFieldFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/MatchingFieldFormatterTest.php new file mode 100644 index 00000000..9e11bf7c --- /dev/null +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/MatchingFieldFormatterTest.php @@ -0,0 +1,45 @@ +formatter = new MatchingFieldFormatter(); + } + + public function testNotSupportedMatcher(): void + { + $matcher = new NullValue(); + $this->expectException(MatcherNotSupportedException::class); + $this->expectExceptionMessage(sprintf('Matcher %s is not supported by %s', $matcher->getType(), $this->formatter::class)); + $this->formatter->format($matcher); + } + + #[TestWith([new MatchingField("it's invalid field"), "it's invalid field"])] + public function testInvalidString(MatcherInterface $matcher, string $value): void + { + $this->expectException(InvalidValueException::class); + $this->expectExceptionMessage(sprintf('String value "%s" should not contains single quote', $value)); + $this->formatter->format($matcher); + } + + #[TestWith([new MatchingField('product'), '"matching($\'product\')"'])] + public function testFormat(MatcherInterface $matcher, string $expression): void + { + $this->assertSame($expression, json_encode($this->formatter->format($matcher))); + } +} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Expression/MaxTypeFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/MaxTypeFormatterTest.php new file mode 100644 index 00000000..7903521d --- /dev/null +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/MaxTypeFormatterTest.php @@ -0,0 +1,36 @@ +formatter = new MaxTypeFormatter(); + } + + public function testNotSupportedMatcher(): void + { + $matcher = new NullValue(); + $this->expectException(MatcherNotSupportedException::class); + $this->expectExceptionMessage(sprintf('Matcher %s is not supported by %s', $matcher->getType(), $this->formatter::class)); + $this->formatter->format($matcher); + } + + #[TestWith([new MaxType(['example value'], 2), '"atMost(2)"'])] + public function testFormat(MatcherInterface $matcher, string $expression): void + { + $this->assertSame($expression, json_encode($this->formatter->format($matcher))); + } +} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Expression/MinTypeFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/MinTypeFormatterTest.php new file mode 100644 index 00000000..0065e46f --- /dev/null +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/MinTypeFormatterTest.php @@ -0,0 +1,36 @@ +formatter = new MinTypeFormatter(); + } + + public function testNotSupportedMatcher(): void + { + $matcher = new NullValue(); + $this->expectException(MatcherNotSupportedException::class); + $this->expectExceptionMessage(sprintf('Matcher %s is not supported by %s', $matcher->getType(), $this->formatter::class)); + $this->formatter->format($matcher); + } + + #[TestWith([new MinType(['example value'], 1), '"atLeast(1)"'])] + public function testFormat(MatcherInterface $matcher, string $expression): void + { + $this->assertSame($expression, json_encode($this->formatter->format($matcher))); + } +} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Expression/NotEmptyFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/NotEmptyFormatterTest.php new file mode 100644 index 00000000..3bdc7c3a --- /dev/null +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/NotEmptyFormatterTest.php @@ -0,0 +1,58 @@ +formatter = new NotEmptyFormatter(); + } + + public function testNotSupportedMatcher(): void + { + $matcher = new NullValue(); + $this->expectException(MatcherNotSupportedException::class); + $this->expectExceptionMessage(sprintf('Matcher %s is not supported by %s', $matcher->getType(), $this->formatter::class)); + $this->formatter->format($matcher); + } + + #[TestWith([new NotEmpty(new \stdClass()), 'object'])] + #[TestWith([new NotEmpty(['key' => 'value']), 'array'])] + public function testInvalidValue(MatcherInterface $matcher, string $type): void + { + $this->expectException(InvalidValueException::class); + $this->expectExceptionMessage(sprintf("Expression doesn't support value of type %s", $type)); + $this->formatter->format($matcher); + } + + #[TestWith([new NotEmpty("it's invalid value"), "it's invalid value"])] + public function testInvalidString(MatcherInterface $matcher, string $value): void + { + $this->expectException(InvalidValueException::class); + $this->expectExceptionMessage(sprintf('String value "%s" should not contains single quote', $value)); + $this->formatter->format($matcher); + } + + #[TestWith([new NotEmpty('example value'), '"notEmpty(\'example value\')"'])] + #[TestWith([new NotEmpty(100.09), '"notEmpty(100.09)"'])] + #[TestWith([new NotEmpty(100), '"notEmpty(100)"'])] + #[TestWith([new NotEmpty(true), '"notEmpty(true)"'])] + #[TestWith([new NotEmpty(false), '"notEmpty(false)"'])] + public function testFormat(MatcherInterface $matcher, string $expression): void + { + $this->assertSame($expression, json_encode($this->formatter->format($matcher))); + } +} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Expression/NullValueFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/NullValueFormatterTest.php new file mode 100644 index 00000000..f379035c --- /dev/null +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/NullValueFormatterTest.php @@ -0,0 +1,26 @@ +formatter = new NullValueFormatter(); + } + + #[TestWith([new NullValue(), '"matching(type, null)"'])] + public function testFormat(MatcherInterface $matcher, string $expression): void + { + $this->assertSame($expression, json_encode($this->formatter->format($matcher))); + } +} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Expression/NumberFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/NumberFormatterTest.php new file mode 100644 index 00000000..793b8fe8 --- /dev/null +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/NumberFormatterTest.php @@ -0,0 +1,48 @@ +formatter = new NumberFormatter(); + } + + public function testNotSupportedMatcher(): void + { + $matcher = new NullValue(); + $this->expectException(MatcherNotSupportedException::class); + $this->expectExceptionMessage(sprintf('Matcher %s is not supported by %s', $matcher->getType(), $this->formatter::class)); + $this->formatter->format($matcher); + } + + public function testInvalidValue(): void + { + $matcher = new Number(); + $this->expectException(InvalidValueException::class); + $this->expectExceptionMessage(sprintf("Number formatter doesn't support value of type %s", gettype(null))); + $this->formatter->format($matcher); + } + + #[TestWith([new Number(-99), '"matching(number, -99)"'])] + #[TestWith([new Number(100), '"matching(number, 100)"'])] + #[TestWith([new Number(100.01), '"matching(number, 100.01)"'])] + #[TestWith([new Number(-100.003), '"matching(number, -100.003)"'])] + public function testFormat(MatcherInterface $matcher, string $expression): void + { + $this->assertSame($expression, json_encode($this->formatter->format($matcher))); + } +} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Expression/RegexFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/RegexFormatterTest.php new file mode 100644 index 00000000..d326b2d2 --- /dev/null +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/RegexFormatterTest.php @@ -0,0 +1,55 @@ +formatter = new RegexFormatter(); + } + + public function testNotSupportedMatcher(): void + { + $matcher = new NullValue(); + $this->expectException(MatcherNotSupportedException::class); + $this->expectExceptionMessage(sprintf('Matcher %s is not supported by %s', $matcher->getType(), $this->formatter::class)); + $this->formatter->format($matcher); + } + + #[TestWith([new Regex('\w \d'), 'NULL'])] + #[TestWith([new Regex('\w \d', ['key' => 'value']), 'array'])] + public function testInvalidValue(MatcherInterface $matcher, string $type): void + { + $this->expectException(InvalidValueException::class); + $this->expectExceptionMessage(sprintf("Regex formatter doesn't support value of type %s", $type)); + $this->formatter->format($matcher); + } + + #[TestWith([new Regex("it's invalid regex", 'value'), "it's invalid regex"])] + #[TestWith([new Regex('\w \d', "it's invalid value"), "it's invalid value"])] + public function testInvalidString(MatcherInterface $matcher, string $value): void + { + $this->expectException(InvalidValueException::class); + $this->expectExceptionMessage(sprintf('String value "%s" should not contains single quote', $value)); + $this->formatter->format($matcher); + } + + #[TestWith([new Regex('\\w{3}\\d+', 'abc123'), '"matching(regex, \'\\\\w{3}\\\\d+\', \'abc123\')"'])] + public function testFormat(MatcherInterface $matcher, string $expression): void + { + $this->assertSame($expression, json_encode($this->formatter->format($matcher))); + } +} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Expression/SemverFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/SemverFormatterTest.php new file mode 100644 index 00000000..4b02a3a5 --- /dev/null +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/SemverFormatterTest.php @@ -0,0 +1,53 @@ +formatter = new SemverFormatter(); + } + + public function testNotSupportedMatcher(): void + { + $matcher = new NullValue(); + $this->expectException(MatcherNotSupportedException::class); + $this->expectExceptionMessage(sprintf('Matcher %s is not supported by %s', $matcher->getType(), $this->formatter::class)); + $this->formatter->format($matcher); + } + + #[TestWith([new Semver(), 'NULL'])] + public function testInvalidValue(MatcherInterface $matcher, string $type): void + { + $this->expectException(InvalidValueException::class); + $this->expectExceptionMessage(sprintf("Semver formatter doesn't support value of type %s", $type)); + $this->formatter->format($matcher); + } + + #[TestWith([new Semver("it's invalid value"), "it's invalid value"])] + public function testInvalidString(MatcherInterface $matcher, string $value): void + { + $this->expectException(InvalidValueException::class); + $this->expectExceptionMessage(sprintf('String value "%s" should not contains single quote', $value)); + $this->formatter->format($matcher); + } + + #[TestWith([new Semver('1.0.0'), '"matching(semver, \'1.0.0\')"'])] + public function testFormat(MatcherInterface $matcher, string $expression): void + { + $this->assertSame($expression, json_encode($this->formatter->format($matcher))); + } +} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Expression/StringValueFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/StringValueFormatterTest.php new file mode 100644 index 00000000..c60d1082 --- /dev/null +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/StringValueFormatterTest.php @@ -0,0 +1,45 @@ +formatter = new StringValueFormatter(); + } + + public function testNotSupportedMatcher(): void + { + $matcher = new NullValue(); + $this->expectException(MatcherNotSupportedException::class); + $this->expectExceptionMessage(sprintf('Matcher %s is not supported by %s', $matcher->getType(), $this->formatter::class)); + $this->formatter->format($matcher); + } + + #[TestWith([new StringValue("it's invalid value"), "it's invalid value"])] + public function testInvalidString(MatcherInterface $matcher, string $value): void + { + $this->expectException(InvalidValueException::class); + $this->expectExceptionMessage(sprintf('String value "%s" should not contains single quote', $value)); + $this->formatter->format($matcher); + } + + #[TestWith([new StringValue('value'), '"matching(type, \'value\')"'])] + public function testFormat(MatcherInterface $matcher, string $expression): void + { + $this->assertSame($expression, json_encode($this->formatter->format($matcher))); + } +} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Expression/TypeFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/TypeFormatterTest.php new file mode 100644 index 00000000..23d636e8 --- /dev/null +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/TypeFormatterTest.php @@ -0,0 +1,63 @@ +formatter = new TypeFormatter(); + } + + public function testNotSupportedMatcher(): void + { + $matcher = new NullValue(); + $this->expectException(MatcherNotSupportedException::class); + $this->expectExceptionMessage(sprintf('Matcher %s is not supported by %s', $matcher->getType(), $this->formatter::class)); + $this->formatter->format($matcher); + } + + #[TestWith([new Type(new \stdClass()), 'object'])] + #[TestWith([new Type(['key' => 'value']), 'array'])] + public function testInvalidValue(MatcherInterface $matcher, string $type): void + { + $this->expectException(InvalidValueException::class); + $this->expectExceptionMessage(sprintf("Expression doesn't support value of type %s", $type)); + $this->formatter->format($matcher); + } + + #[TestWith([new Type("it's invalid value"), "it's invalid value"])] + public function testInvalidString(MatcherInterface $matcher, string $value): void + { + $this->expectException(InvalidValueException::class); + $this->expectExceptionMessage(sprintf('String value "%s" should not contains single quote', $value)); + $this->formatter->format($matcher); + } + + #[TestWith([new Type('example value'), '"matching(type, \'example value\')"'])] + #[TestWith([new Type(100.09), '"matching(type, 100.09)"'])] + #[TestWith([new Type(-99.99), '"matching(type, -99.99)"'])] + #[TestWith([new Type(100), '"matching(type, 100)"'])] + #[TestWith([new Type(-99), '"matching(type, -99)"'])] + #[TestWith([new Type(true), '"matching(type, true)"'])] + #[TestWith([new Type(false), '"matching(type, false)"'])] + #[TestWith([new Type(null), '"matching(type, null)"'])] + public function testFormat(MatcherInterface $matcher, string $expression): void + { + $this->assertSame($expression, json_encode($this->formatter->format($matcher))); + } +} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Json/ContentTypeFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Json/ContentTypeFormatterTest.php new file mode 100644 index 00000000..ec72ff9c --- /dev/null +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Json/ContentTypeFormatterTest.php @@ -0,0 +1,40 @@ +formatter = new ContentTypeFormatter(); + } + + public function testNotSupportedMatcher(): void + { + $matcher = new NullValue(); + $this->expectException(MatcherNotSupportedException::class); + $this->expectExceptionMessage(sprintf('Matcher %s is not supported by %s', $matcher->getType(), $this->formatter::class)); + $this->formatter->format($matcher); + } + + #[TestWith([new ContentType('plain/text'), '{"pact:matcher:type": "contentType", "value": "plain/text"}'])] + #[TestWith([new ContentType('application/json', '{"key":"value"}'), '{"pact:matcher:type": "contentType", "value": "application/json"}'])] + #[TestWith([new ContentType('application/xml', ''), '{"pact:matcher:type": "contentType", "value": "application/xml"}'])] + public function testFormat(MatcherInterface $matcher, string $json): void + { + $jsonEncoded = json_encode($this->formatter->format($matcher)); + $this->assertIsString($jsonEncoded); + $this->assertJsonStringEqualsJsonString($json, $jsonEncoded); + } +} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Json/HasGeneratorFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Json/HasGeneratorFormatterTest.php new file mode 100644 index 00000000..0c7e0236 --- /dev/null +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Json/HasGeneratorFormatterTest.php @@ -0,0 +1,42 @@ +formatter = new HasGeneratorFormatter(); + } + + public function testNotSupportedMatcher(): void + { + $matcher = new NullValue(); + $this->expectException(MatcherNotSupportedException::class); + $this->expectExceptionMessage(sprintf('Matcher %s is not supported by %s', $matcher->getType(), $this->formatter::class)); + $this->formatter->format($matcher); + } + + #[TestWith([new Time('HH:mm'), true, '{"pact:matcher:type": "time", "pact:generator:type": "Regex", "format": "HH:mm", "regex": "\\\\d{2}:\\\\d{2}"}'])] + #[TestWith([new Time('HH:mm', '12:34'), false, '{"pact:matcher:type": "time", "format": "HH:mm", "value": "12:34"}'])] + public function testFormat(Time $matcher, bool $hasGenerator, string $json): void + { + if ($hasGenerator) { + $matcher->setGenerator(new Regex('\d{2}:\d{2}')); + } + $jsonEncoded = json_encode($this->formatter->format($matcher)); + $this->assertIsString($jsonEncoded); + $this->assertJsonStringEqualsJsonString($json, $jsonEncoded); + } +} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Json/MatchAllFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Json/MatchAllFormatterTest.php new file mode 100644 index 00000000..4f878b6b --- /dev/null +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Json/MatchAllFormatterTest.php @@ -0,0 +1,111 @@ +formatter = new MatchAllFormatter(); + } + + public function testNotSupportedMatcher(): void + { + $matcher = new NullValue(); + $this->expectException(MatcherNotSupportedException::class); + $this->expectExceptionMessage(sprintf('Matcher %s is not supported by %s', $matcher->getType(), $this->formatter::class)); + $this->formatter->format($matcher); + } + + #[TestWith([new MatchAll(['abc' => 1, 'def' => 234], [new MinType([null], 2)]), << 1, 'def' => 234], [new MinType([null], 1), new MaxType([null], 2), new EachKey(["doesn't matter"], [new Regex('\w+', 'abc')]), new EachValue(["doesn't matter"], [new Type(100)])]), <<formatter->format($matcher)); + $this->assertIsString($jsonEncoded); + $this->assertJsonStringEqualsJsonString($json, $jsonEncoded); + } +} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Json/NoGeneratorFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Json/NoGeneratorFormatterTest.php new file mode 100644 index 00000000..20c320c7 --- /dev/null +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Json/NoGeneratorFormatterTest.php @@ -0,0 +1,43 @@ +formatter = new NoGeneratorFormatter(); + } + + #[TestWith([new EachKey(['key' => 'value'], [new Includes('value')]), <<formatter->format($matcher)); + $this->assertIsString($jsonEncoded); + $this->assertJsonStringEqualsJsonString($json, $jsonEncoded); + } +} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Json/NullValueFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Json/NullValueFormatterTest.php new file mode 100644 index 00000000..fc93c515 --- /dev/null +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Json/NullValueFormatterTest.php @@ -0,0 +1,28 @@ +formatter = new NullValueFormatter(); + } + + #[TestWith([new NullValue(), '{"pact:matcher:type": "null"}'])] + public function testFormat(MatcherInterface $matcher, string $json): void + { + $jsonEncoded = json_encode($this->formatter->format($matcher)); + $this->assertIsString($jsonEncoded); + $this->assertJsonStringEqualsJsonString($json, $jsonEncoded); + } +} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Json/StringValueFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Json/StringValueFormatterTest.php new file mode 100644 index 00000000..ea911947 --- /dev/null +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Json/StringValueFormatterTest.php @@ -0,0 +1,42 @@ +formatter = new StringValueFormatter(); + } + + public function testNotSupportedMatcher(): void + { + $matcher = new NullValue(); + $this->expectException(MatcherNotSupportedException::class); + $this->expectExceptionMessage(sprintf('Matcher %s is not supported by %s', $matcher->getType(), $this->formatter::class)); + $this->formatter->format($matcher); + } + + #[TestWith([new StringValue(), true, '{"pact:matcher:type": "type", "pact:generator:type": "Regex", "regex": "\\\\w{3}", "value": "some string"}'])] + #[TestWith([new StringValue('example text'), false, '{"pact:matcher:type": "type", "value": "example text"}'])] + public function testFormat(StringValue $matcher, bool $hasGenerator, string $json): void + { + if ($hasGenerator) { + $matcher->setGenerator(new Regex('\w{3}')); + } + $jsonEncoded = json_encode($this->formatter->format($matcher)); + $this->assertIsString($jsonEncoded); + $this->assertJsonStringEqualsJsonString($json, $jsonEncoded); + } +} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/MinimalFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/MinimalFormatterTest.php deleted file mode 100644 index 718d8b2d..00000000 --- a/tests/PhpPact/Consumer/Matcher/Formatters/MinimalFormatterTest.php +++ /dev/null @@ -1,26 +0,0 @@ -assertSame([ - 'pact:matcher:type' => 'date', - 'format' => 'yyyy-MM-dd', - ], $formatter->format($matcher)); - } -} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/PluginFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/PluginFormatterTest.php deleted file mode 100644 index aef59c39..00000000 --- a/tests/PhpPact/Consumer/Matcher/Formatters/PluginFormatterTest.php +++ /dev/null @@ -1,124 +0,0 @@ -formatter = new PluginFormatter(); - } - - public function testFormatWithGenerator(): void - { - $this->expectException(GeneratorNotRequiredException::class); - $this->expectExceptionMessage('Generator is not support in plugin'); - $matcher = new StringValue('example value'); - $matcher->setGenerator(new RandomString()); - $this->formatter->format($matcher); - } - - #[TestWith([new EachKey(["doesn't matter"], [])])] - #[TestWith([new EachValue(["doesn't matter"], [])])] - #[TestWith([new EachKey(["doesn't matter"], [new Type(1), new Type(2)])])] - #[TestWith([new EachValue(["doesn't matter"], [new Type(1), new Type(2), new Type(3)])])] - public function testInvalidRules(EachKey|EachValue $matcher): void - { - $this->expectException(MatchingExpressionException::class); - $this->expectExceptionMessage(sprintf("Matcher '%s' only support 1 rule, %d provided", $matcher->getType(), count($matcher->getRules()))); - $this->formatter->format($matcher); - } - - #[TestWith([new Type(new \stdClass()), 'object'])] - #[TestWith([new Type(['key' => 'value']), 'array'])] - #[TestWith([new MinMaxType(['Example value'], 1, 2), 'array'])] - public function testInvalidValue(MatcherInterface $matcher, string $type): void - { - $this->expectException(MatchingExpressionException::class); - $this->expectExceptionMessage(sprintf("Plugin formatter doesn't support value of type %s", $type)); - $this->formatter->format($matcher); - } - - public function testInvalidString(): void - { - $value = "string contains single quote (')"; - $this->expectException(InvalidValueException::class); - $this->expectExceptionMessage(sprintf('String value "%s" should not contains single quote', $value)); - $this->formatter->format(new Type($value)); - } - - #[TestWith([new Values([1, 2, 3])])] - #[TestWith([new ArrayContains([new Equality(1)])])] - #[TestWith([new StatusCode('clientError', 405)])] - public function testNotSupportedMatcher(MatcherInterface $matcher): void - { - $this->expectException(MatcherNotSupportedException::class); - $this->expectExceptionMessage(sprintf("Matcher '%s' is not supported by plugin", $matcher->getType())); - $this->formatter->format($matcher); - } - - #[TestWith([new MatchingField('product'), '"matching($\'product\')"'])] - #[TestWith([new NotEmpty('test'), '"notEmpty(\'test\')"'])] - #[TestWith([new EachKey(["doesn't matter"], [new Regex('\$(\.\w+)+', '$.test.one')]), '"eachKey(matching(regex, \'\\\\$(\\\\.\\\\w+)+\', \'$.test.one\'))"'])] - #[TestWith([new EachValue(["doesn't matter"], [new Type(100)]), '"eachValue(matching(type, 100))"'])] - #[TestWith([new Equality('Example value'), '"matching(equalTo, \'Example value\')"'])] - #[TestWith([new Type('Example value'), '"matching(type, \'Example value\')"'])] - #[TestWith([new Number(100.09), '"matching(number, 100.09)"'])] - #[TestWith([new Integer(100), '"matching(integer, 100)"'])] - #[TestWith([new Decimal(100.01), '"matching(decimal, 100.01)"'])] - #[TestWith([new Includes('testing'), '"matching(include, \'testing\')"'])] - #[TestWith([new Boolean(true), '"matching(boolean, true)"'])] - #[TestWith([new Semver('1.0.0'), '"matching(semver, \'1.0.0\')"'])] - #[TestWith([new DateTime('yyyy-MM-dd HH:mm:ssZZZZZ', '2020-05-21 16:44:32+10:00'), '"matching(datetime, \'yyyy-MM-dd HH:mm:ssZZZZZ\', \'2020-05-21 16:44:32+10:00\')"'])] - #[TestWith([new Date('yyyy-MM-dd', '2012-04-12'), '"matching(date, \'yyyy-MM-dd\', \'2012-04-12\')"'])] - #[TestWith([new Time('HH:mm', '22:04'), '"matching(time, \'HH:mm\', \'22:04\')"'])] - #[TestWith([new Regex('\\w{3}\\d+', 'abc123'), '"matching(regex, \'\\\\w{3}\\\\d+\', \'abc123\')"'])] - #[TestWith([new ContentType('application/xml'), '"matching(contentType, \'application\/xml\', \'application\/xml\')"'])] - #[TestWith([new NullValue(), '"matching(type, null)"'])] - #[TestWith([new MinType(['Example value'], 1), '"atLeast(1)"'])] - #[TestWith([new MaxType(['Example value'], 2), '"atMost(2)"'])] - #[TestWith([new MatchAll(['abc' => 1, 'def' => 234], [new MinType([null], 1), new MaxType([null], 2), new EachKey(["doesn't matter"], [new Regex('\w+', 'abc')]), new EachValue(["doesn't matter"], [new Type(100)])]), '"atLeast(1), atMost(2), eachKey(matching(regex, \'\\\\w+\', \'abc\')), eachValue(matching(type, 100))"'])] - public function testFormat(MatcherInterface $matcher, string $json): void - { - $this->assertSame($json, json_encode($this->formatter->format($matcher))); - } -} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/ValueOptionalFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/ValueOptionalFormatterTest.php deleted file mode 100644 index 3d383898..00000000 --- a/tests/PhpPact/Consumer/Matcher/Formatters/ValueOptionalFormatterTest.php +++ /dev/null @@ -1,27 +0,0 @@ -setGenerator($generator); - $formatter = new ValueOptionalFormatter(); - $jsonEncoded = json_encode($formatter->format($matcher)); - $this->assertIsString($jsonEncoded); - $this->assertJsonStringEqualsJsonString($result, $jsonEncoded); - } -} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/ValueRequiredFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/ValueRequiredFormatterTest.php deleted file mode 100644 index b93caa9d..00000000 --- a/tests/PhpPact/Consumer/Matcher/Formatters/ValueRequiredFormatterTest.php +++ /dev/null @@ -1,27 +0,0 @@ -setGenerator($generator); - $formatter = new ValueRequiredFormatter(); - $jsonEncoded = json_encode($formatter->format($matcher)); - $this->assertIsString($jsonEncoded); - $this->assertJsonStringEqualsJsonString($result, $jsonEncoded); - } -} diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/XmlContentFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Xml/XmlContentFormatterTest.php similarity index 89% rename from tests/PhpPact/Consumer/Matcher/Formatters/XmlContentFormatterTest.php rename to tests/PhpPact/Consumer/Matcher/Formatters/Xml/XmlContentFormatterTest.php index 8fdb5164..ae6f60d7 100644 --- a/tests/PhpPact/Consumer/Matcher/Formatters/XmlContentFormatterTest.php +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Xml/XmlContentFormatterTest.php @@ -1,8 +1,8 @@ expectException(MatcherNotSupportedException::class); + $this->expectExceptionMessage("MatchingField matcher doesn't support json formatter"); + $this->matcher->matchingField('address'); + } + public function testMatchingField(): void { - $this->assertInstanceOf(MatchingField::class, $this->matcher->matchingField('address')); + $matcher = new Matcher(plugin: true); + $this->assertInstanceOf(MatchingField::class, $matcher->matchingField('address')); } public function testMatchAll(): void @@ -373,9 +382,9 @@ public function testAtMost(): void public function testWithFormatter(): void { $uuid = $this->matcher->uuid(); - $this->assertInstanceOf(ValueOptionalFormatter::class, $uuid->getFormatter()); - $matcher = new Matcher($formatter = new MinimalFormatter()); + $this->assertInstanceOf(HasGeneratorFormatter::class, $uuid->getFormatter()); + $matcher = new Matcher(plugin: true); $uuid = $matcher->uuid(); - $this->assertSame($formatter, $uuid->getFormatter()); + $this->assertInstanceOf(RegexFormatter::class, $uuid->getFormatter()); } } diff --git a/tests/PhpPact/Consumer/Matcher/Matchers/AbstractDateTimeTestCase.php b/tests/PhpPact/Consumer/Matcher/Matchers/AbstractDateTimeTestCase.php new file mode 100644 index 00000000..46ec7f0b --- /dev/null +++ b/tests/PhpPact/Consumer/Matcher/Matchers/AbstractDateTimeTestCase.php @@ -0,0 +1,21 @@ +getMatcherWithoutExampleValue(); + $this->assertInstanceOf(HasGeneratorFormatter::class, $matcher->createJsonFormatter()); + } + + public function testCreateExpressionFormatter(): void + { + $matcher = $this->getMatcherWithoutExampleValue(); + $this->assertInstanceOf(DateTimeFormatter::class, $matcher->createExpressionFormatter()); + } +} diff --git a/tests/PhpPact/Consumer/Matcher/Matchers/ArrayContainsTest.php b/tests/PhpPact/Consumer/Matcher/Matchers/ArrayContainsTest.php index 77e5ed99..23e3ae79 100644 --- a/tests/PhpPact/Consumer/Matcher/Matchers/ArrayContainsTest.php +++ b/tests/PhpPact/Consumer/Matcher/Matchers/ArrayContainsTest.php @@ -2,6 +2,8 @@ namespace PhpPactTest\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Exception\MatcherNotSupportedException; +use PhpPact\Consumer\Matcher\Formatters\Json\NoGeneratorFormatter; use PhpPact\Consumer\Matcher\Matchers\ArrayContains; use PhpPact\Consumer\Matcher\Matchers\Integer; use PhpPact\Consumer\Matcher\Matchers\Type; @@ -21,4 +23,17 @@ public function testSerialize(): void json_encode($array) ); } + + public function testCreateJsonFormatter(): void + { + $matcher = new ArrayContains([]); + $this->assertInstanceOf(NoGeneratorFormatter::class, $matcher->createJsonFormatter()); + } + + public function testCreateExpressionFormatter(): void + { + $matcher = new ArrayContains([]); + $this->expectExceptionObject(new MatcherNotSupportedException("ArrayContains matcher doesn't support expression formatter")); + $matcher->createExpressionFormatter(); + } } diff --git a/tests/PhpPact/Consumer/Matcher/Matchers/BooleanTest.php b/tests/PhpPact/Consumer/Matcher/Matchers/BooleanTest.php index edca058e..e21f2509 100644 --- a/tests/PhpPact/Consumer/Matcher/Matchers/BooleanTest.php +++ b/tests/PhpPact/Consumer/Matcher/Matchers/BooleanTest.php @@ -2,8 +2,11 @@ namespace PhpPactTest\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\BooleanFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\HasGeneratorFormatter; use PhpPact\Consumer\Matcher\Matchers\Boolean; use PhpPact\Consumer\Matcher\Matchers\GeneratorAwareMatcher; +use PHPUnit\Framework\Attributes\TestWith; class BooleanTest extends GeneratorAwareMatcherTestCase { @@ -17,14 +20,24 @@ protected function getMatcherWithExampleValue(): GeneratorAwareMatcher return new Boolean(false); } - /** - * @testWith [null, "{\"pact:matcher:type\":\"boolean\",\"pact:generator:type\":\"RandomBoolean\"}"] - * [true, "{\"pact:matcher:type\":\"boolean\",\"value\":true}"] - * [false, "{\"pact:matcher:type\":\"boolean\",\"value\":false}"] - */ + #[TestWith([null, '{"pact:matcher:type":"boolean","pact:generator:type":"RandomBoolean"}'])] + #[TestWith([true, '{"pact:matcher:type":"boolean","value":true}'])] + #[TestWith([false, '{"pact:matcher:type":"boolean","value":false}'])] public function testSerialize(?bool $value, string $json): void { $matcher = new Boolean($value); $this->assertSame($json, json_encode($matcher)); } + + public function testCreateJsonFormatter(): void + { + $matcher = $this->getMatcherWithoutExampleValue(); + $this->assertInstanceOf(HasGeneratorFormatter::class, $matcher->createJsonFormatter()); + } + + public function testCreateExpressionFormatter(): void + { + $matcher = $this->getMatcherWithoutExampleValue(); + $this->assertInstanceOf(BooleanFormatter::class, $matcher->createExpressionFormatter()); + } } diff --git a/tests/PhpPact/Consumer/Matcher/Matchers/ContentTypeTest.php b/tests/PhpPact/Consumer/Matcher/Matchers/ContentTypeTest.php index 021b1d05..53a90658 100644 --- a/tests/PhpPact/Consumer/Matcher/Matchers/ContentTypeTest.php +++ b/tests/PhpPact/Consumer/Matcher/Matchers/ContentTypeTest.php @@ -2,6 +2,8 @@ namespace PhpPactTest\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\ContentTypeFormatter as ExpressionFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\ContentTypeFormatter as JsonFormatter; use PhpPact\Consumer\Matcher\Matchers\ContentType; use PHPUnit\Framework\TestCase; @@ -17,4 +19,16 @@ public function testSerialize(): void $jsonEncoded ); } + + public function testCreateJsonFormatter(): void + { + $matcher = new ContentType('text/plain'); + $this->assertInstanceOf(JsonFormatter::class, $matcher->createJsonFormatter()); + } + + public function testCreateExpressionFormatter(): void + { + $matcher = new ContentType('text/plain'); + $this->assertInstanceOf(ExpressionFormatter::class, $matcher->createExpressionFormatter()); + } } diff --git a/tests/PhpPact/Consumer/Matcher/Matchers/DateTest.php b/tests/PhpPact/Consumer/Matcher/Matchers/DateTest.php index ea03cebc..49cb0911 100644 --- a/tests/PhpPact/Consumer/Matcher/Matchers/DateTest.php +++ b/tests/PhpPact/Consumer/Matcher/Matchers/DateTest.php @@ -4,8 +4,9 @@ use PhpPact\Consumer\Matcher\Matchers\Date; use PhpPact\Consumer\Matcher\Matchers\GeneratorAwareMatcher; +use PHPUnit\Framework\Attributes\TestWith; -class DateTest extends GeneratorAwareMatcherTestCase +class DateTest extends AbstractDateTimeTestCase { protected function getMatcherWithoutExampleValue(): GeneratorAwareMatcher { @@ -17,10 +18,8 @@ protected function getMatcherWithExampleValue(): GeneratorAwareMatcher return new Date('yyyy-MM-dd', '2001-09-17'); } - /** - * @testWith [null, "{\"pact:matcher:type\":\"date\",\"pact:generator:type\":\"Date\",\"format\":\"yyyy-MM-dd\"}"] - * ["1995-02-04", "{\"pact:matcher:type\":\"date\",\"format\":\"yyyy-MM-dd\",\"value\":\"1995-02-04\"}"] - */ + #[TestWith([null, '{"pact:matcher:type":"date","pact:generator:type":"Date","format":"yyyy-MM-dd"}'])] + #[TestWith(['1995-02-04', '{"pact:matcher:type":"date","format":"yyyy-MM-dd","value":"1995-02-04"}'])] public function testSerialize(?string $value, string $json): void { $format = 'yyyy-MM-dd'; diff --git a/tests/PhpPact/Consumer/Matcher/Matchers/DateTimeTest.php b/tests/PhpPact/Consumer/Matcher/Matchers/DateTimeTest.php index 5c7f4f3e..08ca50fb 100644 --- a/tests/PhpPact/Consumer/Matcher/Matchers/DateTimeTest.php +++ b/tests/PhpPact/Consumer/Matcher/Matchers/DateTimeTest.php @@ -4,8 +4,9 @@ use PhpPact\Consumer\Matcher\Matchers\DateTime; use PhpPact\Consumer\Matcher\Matchers\GeneratorAwareMatcher; +use PHPUnit\Framework\Attributes\TestWith; -class DateTimeTest extends GeneratorAwareMatcherTestCase +class DateTimeTest extends AbstractDateTimeTestCase { protected function getMatcherWithoutExampleValue(): GeneratorAwareMatcher { @@ -17,10 +18,8 @@ protected function getMatcherWithExampleValue(): GeneratorAwareMatcher return new DateTime("yyyy-MM-dd HH:mm", '2011-07-13 16:41'); } - /** - * @testWith [null, "{\"pact:matcher:type\":\"datetime\",\"pact:generator:type\":\"DateTime\",\"format\":\"yyyy-MM-dd'T'HH:mm:ss\"}"] - * ["1995-02-04T22:45:00", "{\"pact:matcher:type\":\"datetime\",\"format\":\"yyyy-MM-dd'T'HH:mm:ss\",\"value\":\"1995-02-04T22:45:00\"}"] - */ + #[TestWith([null, '{"pact:matcher:type":"datetime","pact:generator:type":"DateTime","format":"yyyy-MM-dd\'T\'HH:mm:ss"}'])] + #[TestWith(['1995-02-04T22:45:00', '{"pact:matcher:type":"datetime","format":"yyyy-MM-dd\'T\'HH:mm:ss","value":"1995-02-04T22:45:00"}'])] public function testSerialize(?string $value, string $json): void { $format = "yyyy-MM-dd'T'HH:mm:ss"; diff --git a/tests/PhpPact/Consumer/Matcher/Matchers/DecimalTest.php b/tests/PhpPact/Consumer/Matcher/Matchers/DecimalTest.php index ce6330e4..c4c8fd85 100644 --- a/tests/PhpPact/Consumer/Matcher/Matchers/DecimalTest.php +++ b/tests/PhpPact/Consumer/Matcher/Matchers/DecimalTest.php @@ -2,8 +2,11 @@ namespace PhpPactTest\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\DecimalFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\HasGeneratorFormatter; use PhpPact\Consumer\Matcher\Matchers\Decimal; use PhpPact\Consumer\Matcher\Matchers\GeneratorAwareMatcher; +use PHPUnit\Framework\Attributes\TestWith; class DecimalTest extends GeneratorAwareMatcherTestCase { @@ -17,13 +20,23 @@ protected function getMatcherWithExampleValue(): GeneratorAwareMatcher return new Decimal(15.68); } - /** - * @testWith [null, "{\"pact:matcher:type\":\"decimal\",\"pact:generator:type\":\"RandomDecimal\",\"digits\":10}"] - * [1.23, "{\"pact:matcher:type\":\"decimal\",\"value\":1.23}"] - */ + #[TestWith([null, '{"pact:matcher:type":"decimal","pact:generator:type":"RandomDecimal","digits":10}'])] + #[TestWith([1.23, '{"pact:matcher:type":"decimal","value":1.23}'])] public function testSerialize(?float $value, string $json): void { $matcher = new Decimal($value); $this->assertSame($json, json_encode($matcher)); } + + public function testCreateJsonFormatter(): void + { + $matcher = $this->getMatcherWithoutExampleValue(); + $this->assertInstanceOf(HasGeneratorFormatter::class, $matcher->createJsonFormatter()); + } + + public function testCreateExpressionFormatter(): void + { + $matcher = $this->getMatcherWithoutExampleValue(); + $this->assertInstanceOf(DecimalFormatter::class, $matcher->createExpressionFormatter()); + } } diff --git a/tests/PhpPact/Consumer/Matcher/Matchers/EachKeyTest.php b/tests/PhpPact/Consumer/Matcher/Matchers/EachKeyTest.php index a61b5015..88859d6c 100644 --- a/tests/PhpPact/Consumer/Matcher/Matchers/EachKeyTest.php +++ b/tests/PhpPact/Consumer/Matcher/Matchers/EachKeyTest.php @@ -2,6 +2,8 @@ namespace PhpPactTest\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\EachKeyFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\NoGeneratorFormatter; use PhpPact\Consumer\Matcher\Matchers\EachKey; use PhpPact\Consumer\Matcher\Matchers\Regex; use PhpPact\Consumer\Matcher\Matchers\Type; @@ -30,4 +32,16 @@ public function testSerialize(): void $jsonEncoded ); } + + public function testCreateJsonFormatter(): void + { + $matcher = new EachKey([], []); + $this->assertInstanceOf(NoGeneratorFormatter::class, $matcher->createJsonFormatter()); + } + + public function testCreateExpressionFormatter(): void + { + $matcher = new EachKey([], []); + $this->assertInstanceOf(EachKeyFormatter::class, $matcher->createExpressionFormatter()); + } } diff --git a/tests/PhpPact/Consumer/Matcher/Matchers/EachValueTest.php b/tests/PhpPact/Consumer/Matcher/Matchers/EachValueTest.php index 97b2eb41..f220d5b9 100644 --- a/tests/PhpPact/Consumer/Matcher/Matchers/EachValueTest.php +++ b/tests/PhpPact/Consumer/Matcher/Matchers/EachValueTest.php @@ -2,6 +2,8 @@ namespace PhpPactTest\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\EachValueFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\NoGeneratorFormatter; use PhpPact\Consumer\Matcher\Matchers\EachValue; use PhpPact\Consumer\Matcher\Matchers\Regex; use PhpPact\Consumer\Matcher\Matchers\Type; @@ -28,4 +30,16 @@ public function testSerialize(): void $jsonEncoded ); } + + public function testCreateJsonFormatter(): void + { + $matcher = new EachValue([], []); + $this->assertInstanceOf(NoGeneratorFormatter::class, $matcher->createJsonFormatter()); + } + + public function testCreateExpressionFormatter(): void + { + $matcher = new EachValue([], []); + $this->assertInstanceOf(EachValueFormatter::class, $matcher->createExpressionFormatter()); + } } diff --git a/tests/PhpPact/Consumer/Matcher/Matchers/EqualityTest.php b/tests/PhpPact/Consumer/Matcher/Matchers/EqualityTest.php index 1cffba46..d1c373a2 100644 --- a/tests/PhpPact/Consumer/Matcher/Matchers/EqualityTest.php +++ b/tests/PhpPact/Consumer/Matcher/Matchers/EqualityTest.php @@ -2,6 +2,8 @@ namespace PhpPactTest\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\EqualityFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\NoGeneratorFormatter; use PhpPact\Consumer\Matcher\Matchers\Equality; use PHPUnit\Framework\TestCase; @@ -15,4 +17,16 @@ public function testSerialize(): void json_encode($string) ); } + + public function testCreateJsonFormatter(): void + { + $matcher = new Equality(null); + $this->assertInstanceOf(NoGeneratorFormatter::class, $matcher->createJsonFormatter()); + } + + public function testCreateExpressionFormatter(): void + { + $matcher = new Equality(null); + $this->assertInstanceOf(EqualityFormatter::class, $matcher->createExpressionFormatter()); + } } diff --git a/tests/PhpPact/Consumer/Matcher/Matchers/IncludesTest.php b/tests/PhpPact/Consumer/Matcher/Matchers/IncludesTest.php index 6310f3fe..903a54e8 100644 --- a/tests/PhpPact/Consumer/Matcher/Matchers/IncludesTest.php +++ b/tests/PhpPact/Consumer/Matcher/Matchers/IncludesTest.php @@ -2,6 +2,8 @@ namespace PhpPactTest\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\IncludesFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\NoGeneratorFormatter; use PhpPact\Consumer\Matcher\Matchers\Includes; use PHPUnit\Framework\TestCase; @@ -15,4 +17,16 @@ public function testSerialize(): void json_encode($string) ); } + + public function testCreateJsonFormatter(): void + { + $matcher = new Includes('text'); + $this->assertInstanceOf(NoGeneratorFormatter::class, $matcher->createJsonFormatter()); + } + + public function testCreateExpressionFormatter(): void + { + $matcher = new Includes('text'); + $this->assertInstanceOf(IncludesFormatter::class, $matcher->createExpressionFormatter()); + } } diff --git a/tests/PhpPact/Consumer/Matcher/Matchers/IntegerTest.php b/tests/PhpPact/Consumer/Matcher/Matchers/IntegerTest.php index b36c74ba..8fdba186 100644 --- a/tests/PhpPact/Consumer/Matcher/Matchers/IntegerTest.php +++ b/tests/PhpPact/Consumer/Matcher/Matchers/IntegerTest.php @@ -2,8 +2,11 @@ namespace PhpPactTest\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\IntegerFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\HasGeneratorFormatter; use PhpPact\Consumer\Matcher\Matchers\GeneratorAwareMatcher; use PhpPact\Consumer\Matcher\Matchers\Integer; +use PHPUnit\Framework\Attributes\TestWith; class IntegerTest extends GeneratorAwareMatcherTestCase { @@ -17,13 +20,23 @@ protected function getMatcherWithExampleValue(): GeneratorAwareMatcher return new Integer(189); } - /** - * @testWith [null, "{\"pact:matcher:type\":\"integer\",\"pact:generator:type\":\"RandomInt\",\"min\":0,\"max\":10}"] - * [123, "{\"pact:matcher:type\":\"integer\",\"value\":123}"] - */ + #[TestWith([null, '{"pact:matcher:type":"integer","pact:generator:type":"RandomInt","min":0,"max":10}'])] + #[TestWith([123, '{"pact:matcher:type":"integer","value":123}'])] public function testSerialize(?int $value, string $json): void { $matcher = new Integer($value); $this->assertSame($json, json_encode($matcher)); } + + public function testCreateJsonFormatter(): void + { + $matcher = new Integer(123); + $this->assertInstanceOf(HasGeneratorFormatter::class, $matcher->createJsonFormatter()); + } + + public function testCreateExpressionFormatter(): void + { + $matcher = new Integer(123); + $this->assertInstanceOf(IntegerFormatter::class, $matcher->createExpressionFormatter()); + } } diff --git a/tests/PhpPact/Consumer/Matcher/Matchers/MatchAllTest.php b/tests/PhpPact/Consumer/Matcher/Matchers/MatchAllTest.php index 9840d876..c2effb9d 100644 --- a/tests/PhpPact/Consumer/Matcher/Matchers/MatchAllTest.php +++ b/tests/PhpPact/Consumer/Matcher/Matchers/MatchAllTest.php @@ -3,6 +3,8 @@ namespace PhpPactTest\Consumer\Matcher\Matchers; use PhpPact\Consumer\Matcher\Exception\MatcherNotSupportedException; +use PhpPact\Consumer\Matcher\Formatters\Expression\MatchAllFormatter as ExpressionFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\MatchAllFormatter as JsonFormatter; use PhpPact\Consumer\Matcher\Matchers\EachKey; use PhpPact\Consumer\Matcher\Matchers\EachValue; use PhpPact\Consumer\Matcher\Matchers\MatchAll; @@ -25,4 +27,16 @@ public function testSerialize(): void $matcher = new MatchAll(['key' => 123], [new MinType([], 1), new MaxType([], 2), new EachKey([], [new Type('test')]), new EachValue([], [new Type(123)])]); $this->assertSame('{"pact:matcher:type":[{"pact:matcher:type":"type","min":1,"value":[]},{"pact:matcher:type":"type","max":2,"value":[]},{"pact:matcher:type":"eachKey","rules":[{"pact:matcher:type":"type","value":"test"}],"value":[]},{"pact:matcher:type":"eachValue","rules":[{"pact:matcher:type":"type","value":123}],"value":[]}],"value":{"key":123}}', json_encode($matcher)); } + + public function testCreateJsonFormatter(): void + { + $matcher = new MatchAll([], []); + $this->assertInstanceOf(JsonFormatter::class, $matcher->createJsonFormatter()); + } + + public function testCreateExpressionFormatter(): void + { + $matcher = new MatchAll([], []); + $this->assertInstanceOf(ExpressionFormatter::class, $matcher->createExpressionFormatter()); + } } diff --git a/tests/PhpPact/Consumer/Matcher/Matchers/MatchingFieldTest.php b/tests/PhpPact/Consumer/Matcher/Matchers/MatchingFieldTest.php index 5034462b..8ea9755e 100644 --- a/tests/PhpPact/Consumer/Matcher/Matchers/MatchingFieldTest.php +++ b/tests/PhpPact/Consumer/Matcher/Matchers/MatchingFieldTest.php @@ -2,14 +2,9 @@ namespace PhpPactTest\Consumer\Matcher\Matchers; -use PhpPact\Consumer\Matcher\Exception\InvalidValueException; use PhpPact\Consumer\Matcher\Exception\MatcherNotSupportedException; -use PhpPact\Consumer\Matcher\Formatters\MinimalFormatter; -use PhpPact\Consumer\Matcher\Formatters\PluginFormatter; -use PhpPact\Consumer\Matcher\Formatters\ValueOptionalFormatter; -use PhpPact\Consumer\Matcher\Formatters\ValueRequiredFormatter; -use PhpPact\Consumer\Matcher\Formatters\XmlContentFormatter; -use PhpPact\Consumer\Matcher\Formatters\XmlElementFormatter; +use PhpPact\Consumer\Matcher\Formatters\Expression\MatchingFieldFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\NoGeneratorFormatter; use PhpPact\Consumer\Matcher\Matchers\MatchingField; use PhpPact\Consumer\Matcher\Model\FormatterInterface; use PHPUnit\Framework\Attributes\TestWith; @@ -17,36 +12,35 @@ class MatchingFieldTest extends TestCase { - public function testInvalidField(): void - { - $this->expectException(InvalidValueException::class); - $this->expectExceptionMessage('String value "probably doesn\'t work" should not contains single quote'); - $matcher = new MatchingField("probably doesn't work"); - $matcher->setFormatter(new PluginFormatter()); - json_encode($matcher); - } - public function testSerialize(): void { $matcher = new MatchingField('person'); - $matcher->setFormatter(new PluginFormatter()); $this->assertSame( "\"matching($'person')\"", json_encode($matcher) ); } - #[TestWith([new MinimalFormatter()])] - #[TestWith([new ValueOptionalFormatter()])] - #[TestWith([new ValueRequiredFormatter()])] - #[TestWith([new XmlContentFormatter()])] - #[TestWith([new XmlElementFormatter()])] + #[TestWith([new NoGeneratorFormatter()])] public function testNotSupportedFormatter(FormatterInterface $formatter): void { $this->expectException(MatcherNotSupportedException::class); - $this->expectExceptionMessage('MatchingField matcher only work with plugin'); + $this->expectExceptionMessage("MatchingField matcher doesn't support json formatter"); $matcher = new MatchingField('person'); $matcher->setFormatter($formatter); json_encode($matcher); } + + public function testCreateJsonFormatter(): void + { + $matcher = new MatchingField('product'); + $this->expectExceptionObject(new MatcherNotSupportedException("MatchingField matcher doesn't support json formatter")); + $matcher->createJsonFormatter(); + } + + public function testCreateExpressionFormatter(): void + { + $matcher = new MatchingField('product'); + $this->assertInstanceOf(MatchingFieldFormatter::class, $matcher->createExpressionFormatter()); + } } diff --git a/tests/PhpPact/Consumer/Matcher/Matchers/MaxTypeTest.php b/tests/PhpPact/Consumer/Matcher/Matchers/MaxTypeTest.php index 2c034c90..cd33bccf 100644 --- a/tests/PhpPact/Consumer/Matcher/Matchers/MaxTypeTest.php +++ b/tests/PhpPact/Consumer/Matcher/Matchers/MaxTypeTest.php @@ -2,6 +2,8 @@ namespace PhpPactTest\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\MaxTypeFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\NoGeneratorFormatter; use PhpPact\Consumer\Matcher\Matchers\MaxType; use PHPUnit\Framework\TestCase; @@ -18,4 +20,16 @@ public function testSerialize(): void json_encode($array) ); } + + public function testCreateJsonFormatter(): void + { + $matcher = new MaxType([], 0); + $this->assertInstanceOf(NoGeneratorFormatter::class, $matcher->createJsonFormatter()); + } + + public function testCreateExpressionFormatter(): void + { + $matcher = new MaxType([], 0); + $this->assertInstanceOf(MaxTypeFormatter::class, $matcher->createExpressionFormatter()); + } } diff --git a/tests/PhpPact/Consumer/Matcher/Matchers/MinMaxTypeTest.php b/tests/PhpPact/Consumer/Matcher/Matchers/MinMaxTypeTest.php index 49271a75..bfaffe16 100644 --- a/tests/PhpPact/Consumer/Matcher/Matchers/MinMaxTypeTest.php +++ b/tests/PhpPact/Consumer/Matcher/Matchers/MinMaxTypeTest.php @@ -2,6 +2,8 @@ namespace PhpPactTest\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Exception\MatcherNotSupportedException; +use PhpPact\Consumer\Matcher\Formatters\Json\NoGeneratorFormatter; use PhpPact\Consumer\Matcher\Matchers\MinMaxType; use PHPUnit\Framework\TestCase; @@ -19,4 +21,17 @@ public function testSerialize(): void json_encode($array) ); } + + public function testCreateJsonFormatter(): void + { + $matcher = new MinMaxType([], 0, 1); + $this->assertInstanceOf(NoGeneratorFormatter::class, $matcher->createJsonFormatter()); + } + + public function testCreateExpressionFormatter(): void + { + $matcher = new MinMaxType([], 0, 1); + $this->expectExceptionObject(new MatcherNotSupportedException("MinMaxType matcher doesn't support expression formatter")); + $matcher->createExpressionFormatter(); + } } diff --git a/tests/PhpPact/Consumer/Matcher/Matchers/MinTypeTest.php b/tests/PhpPact/Consumer/Matcher/Matchers/MinTypeTest.php index dba58a43..246d4f15 100644 --- a/tests/PhpPact/Consumer/Matcher/Matchers/MinTypeTest.php +++ b/tests/PhpPact/Consumer/Matcher/Matchers/MinTypeTest.php @@ -2,6 +2,8 @@ namespace PhpPactTest\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\MinTypeFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\NoGeneratorFormatter; use PhpPact\Consumer\Matcher\Matchers\MinType; use PHPUnit\Framework\TestCase; @@ -20,4 +22,16 @@ public function testSerialize(): void json_encode($array) ); } + + public function testCreateJsonFormatter(): void + { + $matcher = new MinType([], 0); + $this->assertInstanceOf(NoGeneratorFormatter::class, $matcher->createJsonFormatter()); + } + + public function testCreateExpressionFormatter(): void + { + $matcher = new MinType([], 0); + $this->assertInstanceOf(MinTypeFormatter::class, $matcher->createExpressionFormatter()); + } } diff --git a/tests/PhpPact/Consumer/Matcher/Matchers/NotEmptyTest.php b/tests/PhpPact/Consumer/Matcher/Matchers/NotEmptyTest.php index fd5d89f5..18f0b332 100644 --- a/tests/PhpPact/Consumer/Matcher/Matchers/NotEmptyTest.php +++ b/tests/PhpPact/Consumer/Matcher/Matchers/NotEmptyTest.php @@ -2,6 +2,8 @@ namespace PhpPactTest\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\NotEmptyFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\NoGeneratorFormatter; use PhpPact\Consumer\Matcher\Matchers\NotEmpty; use PHPUnit\Framework\TestCase; @@ -15,4 +17,16 @@ public function testSerialize(): void json_encode($array) ); } + + public function testCreateJsonFormatter(): void + { + $matcher = new NotEmpty('test'); + $this->assertInstanceOf(NoGeneratorFormatter::class, $matcher->createJsonFormatter()); + } + + public function testCreateExpressionFormatter(): void + { + $matcher = new NotEmpty('test'); + $this->assertInstanceOf(NotEmptyFormatter::class, $matcher->createExpressionFormatter()); + } } diff --git a/tests/PhpPact/Consumer/Matcher/Matchers/NullValueTest.php b/tests/PhpPact/Consumer/Matcher/Matchers/NullValueTest.php index 4e7906d0..7b73fdda 100644 --- a/tests/PhpPact/Consumer/Matcher/Matchers/NullValueTest.php +++ b/tests/PhpPact/Consumer/Matcher/Matchers/NullValueTest.php @@ -2,6 +2,8 @@ namespace PhpPactTest\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\NullValueFormatter as ExpressionFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\NullValueFormatter as JsonFormatter; use PhpPact\Consumer\Matcher\Matchers\NullValue; use PHPUnit\Framework\TestCase; @@ -15,4 +17,16 @@ public function testSerialize(): void json_encode($null) ); } + + public function testCreateJsonFormatter(): void + { + $matcher = new NullValue(); + $this->assertInstanceOf(JsonFormatter::class, $matcher->createJsonFormatter()); + } + + public function testCreateExpressionFormatter(): void + { + $matcher = new NullValue(); + $this->assertInstanceOf(ExpressionFormatter::class, $matcher->createExpressionFormatter()); + } } diff --git a/tests/PhpPact/Consumer/Matcher/Matchers/NumberTest.php b/tests/PhpPact/Consumer/Matcher/Matchers/NumberTest.php index 0505623e..3fa237c0 100644 --- a/tests/PhpPact/Consumer/Matcher/Matchers/NumberTest.php +++ b/tests/PhpPact/Consumer/Matcher/Matchers/NumberTest.php @@ -2,8 +2,11 @@ namespace PhpPactTest\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\NumberFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\HasGeneratorFormatter; use PhpPact\Consumer\Matcher\Matchers\GeneratorAwareMatcher; use PhpPact\Consumer\Matcher\Matchers\Number; +use PHPUnit\Framework\Attributes\TestWith; class NumberTest extends GeneratorAwareMatcherTestCase { @@ -17,14 +20,24 @@ protected function getMatcherWithExampleValue(): GeneratorAwareMatcher return new Number(56.73); } - /** - * @testWith [null, "{\"pact:matcher:type\":\"number\",\"pact:generator:type\":\"RandomInt\",\"min\":0,\"max\":10}"] - * [123, "{\"pact:matcher:type\":\"number\",\"value\":123}"] - * [12.3, "{\"pact:matcher:type\":\"number\",\"value\":12.3}"] - */ + #[TestWith([null, '{"pact:matcher:type":"number","pact:generator:type":"RandomInt","min":0,"max":10}'])] + #[TestWith([123, '{"pact:matcher:type":"number","value":123}'])] + #[TestWith([12.3, '{"pact:matcher:type":"number","value":12.3}'])] public function testSerialize(int|float|null $value, string $json): void { $matcher = new Number($value); $this->assertSame($json, json_encode($matcher)); } + + public function testCreateJsonFormatter(): void + { + $matcher = new Number(123); + $this->assertInstanceOf(HasGeneratorFormatter::class, $matcher->createJsonFormatter()); + } + + public function testCreateExpressionFormatter(): void + { + $matcher = new Number(123); + $this->assertInstanceOf(NumberFormatter::class, $matcher->createExpressionFormatter()); + } } diff --git a/tests/PhpPact/Consumer/Matcher/Matchers/RegexTest.php b/tests/PhpPact/Consumer/Matcher/Matchers/RegexTest.php index 1d95e4b4..6aa8171c 100644 --- a/tests/PhpPact/Consumer/Matcher/Matchers/RegexTest.php +++ b/tests/PhpPact/Consumer/Matcher/Matchers/RegexTest.php @@ -3,6 +3,8 @@ namespace PhpPactTest\Consumer\Matcher\Matchers; use PhpPact\Consumer\Matcher\Exception\InvalidRegexException; +use PhpPact\Consumer\Matcher\Formatters\Expression\RegexFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\HasGeneratorFormatter; use PhpPact\Consumer\Matcher\Matchers\GeneratorAwareMatcher; use PhpPact\Consumer\Matcher\Matchers\Regex; use PHPUnit\Framework\Attributes\TestWith; @@ -39,4 +41,16 @@ public function testSerialize(string|array|null $values, ?string $json): void $matcher = new Regex($this->regex, $values); $this->assertSame($json, json_encode($matcher)); } + + public function testCreateJsonFormatter(): void + { + $matcher = new Regex($this->regex); + $this->assertInstanceOf(HasGeneratorFormatter::class, $matcher->createJsonFormatter()); + } + + public function testCreateExpressionFormatter(): void + { + $matcher = new Regex($this->regex); + $this->assertInstanceOf(RegexFormatter::class, $matcher->createExpressionFormatter()); + } } diff --git a/tests/PhpPact/Consumer/Matcher/Matchers/SemverTest.php b/tests/PhpPact/Consumer/Matcher/Matchers/SemverTest.php index 4178634d..fe75828b 100644 --- a/tests/PhpPact/Consumer/Matcher/Matchers/SemverTest.php +++ b/tests/PhpPact/Consumer/Matcher/Matchers/SemverTest.php @@ -2,8 +2,11 @@ namespace PhpPactTest\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\SemverFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\HasGeneratorFormatter; use PhpPact\Consumer\Matcher\Matchers\GeneratorAwareMatcher; use PhpPact\Consumer\Matcher\Matchers\Semver; +use PHPUnit\Framework\Attributes\TestWith; class SemverTest extends GeneratorAwareMatcherTestCase { @@ -17,13 +20,23 @@ protected function getMatcherWithExampleValue(): GeneratorAwareMatcher return new Semver('10.21.0-rc.1'); } - /** - * @testWith [null, "{\"pact:matcher:type\":\"semver\",\"pact:generator:type\":\"Regex\",\"regex\":\"\\\\d+\\\\.\\\\d+\\\\.\\\\d+\"}"] - * ["1.2.3", "{\"pact:matcher:type\":\"semver\",\"value\":\"1.2.3\"}"] - */ + #[TestWith([null, '{"pact:matcher:type":"semver","pact:generator:type":"Regex","regex":"\\\\d+\\\\.\\\\d+\\\\.\\\\d+"}'])] + #[TestWith(['1.2.3', '{"pact:matcher:type":"semver","value":"1.2.3"}'])] public function testSerialize(?string $value, string $json): void { $matcher = new Semver($value); $this->assertSame($json, json_encode($matcher)); } + + public function testCreateJsonFormatter(): void + { + $matcher = new Semver(); + $this->assertInstanceOf(HasGeneratorFormatter::class, $matcher->createJsonFormatter()); + } + + public function testCreateExpressionFormatter(): void + { + $matcher = new Semver(); + $this->assertInstanceOf(SemverFormatter::class, $matcher->createExpressionFormatter()); + } } diff --git a/tests/PhpPact/Consumer/Matcher/Matchers/StatusCodeTest.php b/tests/PhpPact/Consumer/Matcher/Matchers/StatusCodeTest.php index ffa5c2ec..309e0837 100644 --- a/tests/PhpPact/Consumer/Matcher/Matchers/StatusCodeTest.php +++ b/tests/PhpPact/Consumer/Matcher/Matchers/StatusCodeTest.php @@ -3,8 +3,11 @@ namespace PhpPactTest\Consumer\Matcher\Matchers; use PhpPact\Consumer\Matcher\Exception\InvalidHttpStatusException; +use PhpPact\Consumer\Matcher\Exception\MatcherNotSupportedException; +use PhpPact\Consumer\Matcher\Formatters\Json\HasGeneratorFormatter; use PhpPact\Consumer\Matcher\Matchers\GeneratorAwareMatcher; use PhpPact\Consumer\Matcher\Matchers\StatusCode; +use PHPUnit\Framework\Attributes\TestWith; class StatusCodeTest extends GeneratorAwareMatcherTestCase { @@ -18,17 +21,15 @@ protected function getMatcherWithExampleValue(): GeneratorAwareMatcher return new StatusCode('error', 404); } - /** - * @testWith ["invalid", null, null] - * ["info", null, "{\"pact:matcher:type\":\"statusCode\",\"pact:generator:type\":\"RandomInt\",\"status\":\"info\",\"min\":100,\"max\":199}"] - * ["success", null, "{\"pact:matcher:type\":\"statusCode\",\"pact:generator:type\":\"RandomInt\",\"status\":\"success\",\"min\":200,\"max\":299}"] - * ["redirect", null, "{\"pact:matcher:type\":\"statusCode\",\"pact:generator:type\":\"RandomInt\",\"status\":\"redirect\",\"min\":300,\"max\":399}"] - * ["clientError", null, "{\"pact:matcher:type\":\"statusCode\",\"pact:generator:type\":\"RandomInt\",\"status\":\"clientError\",\"min\":400,\"max\":499}"] - * ["serverError", null, "{\"pact:matcher:type\":\"statusCode\",\"pact:generator:type\":\"RandomInt\",\"status\":\"serverError\",\"min\":500,\"max\":599}"] - * ["nonError", null, "{\"pact:matcher:type\":\"statusCode\",\"pact:generator:type\":\"RandomInt\",\"status\":\"nonError\",\"min\":100,\"max\":399}"] - * ["error", null, "{\"pact:matcher:type\":\"statusCode\",\"pact:generator:type\":\"RandomInt\",\"status\":\"error\",\"min\":400,\"max\":599}"] - * ["info", 123, "{\"pact:matcher:type\":\"statusCode\",\"status\":\"info\",\"value\":123}"] - */ + #[TestWith(['invalid', null, null])] + #[TestWith(['info', null, '{"pact:matcher:type":"statusCode","pact:generator:type":"RandomInt","status":"info","min":100,"max":199}'])] + #[TestWith(['success', null, '{"pact:matcher:type":"statusCode","pact:generator:type":"RandomInt","status":"success","min":200,"max":299}'])] + #[TestWith(['redirect', null, '{"pact:matcher:type":"statusCode","pact:generator:type":"RandomInt","status":"redirect","min":300,"max":399}'])] + #[TestWith(['clientError', null, '{"pact:matcher:type":"statusCode","pact:generator:type":"RandomInt","status":"clientError","min":400,"max":499}'])] + #[TestWith(['serverError', null, '{"pact:matcher:type":"statusCode","pact:generator:type":"RandomInt","status":"serverError","min":500,"max":599}'])] + #[TestWith(['nonError', null, '{"pact:matcher:type":"statusCode","pact:generator:type":"RandomInt","status":"nonError","min":100,"max":399}'])] + #[TestWith(['error', null, '{"pact:matcher:type":"statusCode","pact:generator:type":"RandomInt","status":"error","min":400,"max":599}'])] + #[TestWith(['info', 123, '{"pact:matcher:type":"statusCode","status":"info","value":123}'])] public function testSerialize(string $status, ?int $value, ?string $json): void { if (!$json) { @@ -40,4 +41,17 @@ public function testSerialize(string $status, ?int $value, ?string $json): void $this->assertIsString($jsonEncoded); $this->assertJsonStringEqualsJsonString($json, $jsonEncoded); } + + public function testCreateJsonFormatter(): void + { + $matcher = new StatusCode('success'); + $this->assertInstanceOf(HasGeneratorFormatter::class, $matcher->createJsonFormatter()); + } + + public function testCreateExpressionFormatter(): void + { + $matcher = new StatusCode('success'); + $this->expectExceptionObject(new MatcherNotSupportedException("StatusCode matcher doesn't support expression formatter")); + $matcher->createExpressionFormatter(); + } } diff --git a/tests/PhpPact/Consumer/Matcher/Matchers/StringValueTest.php b/tests/PhpPact/Consumer/Matcher/Matchers/StringValueTest.php index 8f77b3ce..ac1698a2 100644 --- a/tests/PhpPact/Consumer/Matcher/Matchers/StringValueTest.php +++ b/tests/PhpPact/Consumer/Matcher/Matchers/StringValueTest.php @@ -2,15 +2,16 @@ namespace PhpPactTest\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\StringValueFormatter as ExpressionFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\StringValueFormatter as JsonFormatter; use PhpPact\Consumer\Matcher\Matchers\StringValue; +use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\TestCase; class StringValueTest extends TestCase { - /** - * @testWith [null, "{\"pact:matcher:type\":\"type\",\"value\":\"some string\",\"pact:generator:type\":\"RandomString\",\"size\":10}"] - * ["test", "{\"pact:matcher:type\":\"type\",\"value\":\"test\"}"] - */ + #[TestWith([null, '{"pact:matcher:type":"type","value":"some string","pact:generator:type":"RandomString","size":10}'])] + #[TestWith(['test', '{"pact:matcher:type":"type","value":"test"}'])] public function testSerialize(?string $value, string $json): void { $matcher = new StringValue($value); @@ -18,4 +19,16 @@ public function testSerialize(?string $value, string $json): void $this->assertIsString($jsonEncoded); $this->assertJsonStringEqualsJsonString($json, $jsonEncoded); } + + public function testCreateJsonFormatter(): void + { + $matcher = new StringValue('abc'); + $this->assertInstanceOf(JsonFormatter::class, $matcher->createJsonFormatter()); + } + + public function testCreateExpressionFormatter(): void + { + $matcher = new StringValue('abc'); + $this->assertInstanceOf(ExpressionFormatter::class, $matcher->createExpressionFormatter()); + } } diff --git a/tests/PhpPact/Consumer/Matcher/Matchers/TimeTest.php b/tests/PhpPact/Consumer/Matcher/Matchers/TimeTest.php index 3a6c7933..94329db4 100644 --- a/tests/PhpPact/Consumer/Matcher/Matchers/TimeTest.php +++ b/tests/PhpPact/Consumer/Matcher/Matchers/TimeTest.php @@ -4,8 +4,9 @@ use PhpPact\Consumer\Matcher\Matchers\GeneratorAwareMatcher; use PhpPact\Consumer\Matcher\Matchers\Time; +use PHPUnit\Framework\Attributes\TestWith; -class TimeTest extends GeneratorAwareMatcherTestCase +class TimeTest extends AbstractDateTimeTestCase { protected function getMatcherWithoutExampleValue(): GeneratorAwareMatcher { @@ -17,10 +18,8 @@ protected function getMatcherWithExampleValue(): GeneratorAwareMatcher return new Time('HH:mm', '21:15'); } - /** - * @testWith [null, "{\"pact:matcher:type\":\"time\",\"pact:generator:type\":\"Time\",\"format\":\"HH:mm:ss\"}"] - * ["12:02::34", "{\"pact:matcher:type\":\"time\",\"format\":\"HH:mm:ss\",\"value\":\"12:02::34\"}"] - */ + #[TestWith([null, '{"pact:matcher:type":"time","pact:generator:type":"Time","format":"HH:mm:ss"}'])] + #[TestWith(['12:02::34', '{"pact:matcher:type":"time","format":"HH:mm:ss","value":"12:02::34"}'])] public function testSerialize(?string $value, string $json): void { $format = 'HH:mm:ss'; diff --git a/tests/PhpPact/Consumer/Matcher/Matchers/TypeTest.php b/tests/PhpPact/Consumer/Matcher/Matchers/TypeTest.php index 3501c291..6363311e 100644 --- a/tests/PhpPact/Consumer/Matcher/Matchers/TypeTest.php +++ b/tests/PhpPact/Consumer/Matcher/Matchers/TypeTest.php @@ -2,6 +2,8 @@ namespace PhpPactTest\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Formatters\Expression\TypeFormatter; +use PhpPact\Consumer\Matcher\Formatters\Json\NoGeneratorFormatter; use PhpPact\Consumer\Matcher\Matchers\Type; use PHPUnit\Framework\TestCase; @@ -16,4 +18,16 @@ public function testSerialize(): void json_encode($object) ); } + + public function testCreateJsonFormatter(): void + { + $matcher = new Type('abc'); + $this->assertInstanceOf(NoGeneratorFormatter::class, $matcher->createJsonFormatter()); + } + + public function testCreateExpressionFormatter(): void + { + $matcher = new Type('abc'); + $this->assertInstanceOf(TypeFormatter::class, $matcher->createExpressionFormatter()); + } } diff --git a/tests/PhpPact/Consumer/Matcher/Matchers/ValuesTest.php b/tests/PhpPact/Consumer/Matcher/Matchers/ValuesTest.php index b512b5ad..cb1de138 100644 --- a/tests/PhpPact/Consumer/Matcher/Matchers/ValuesTest.php +++ b/tests/PhpPact/Consumer/Matcher/Matchers/ValuesTest.php @@ -2,6 +2,8 @@ namespace PhpPactTest\Consumer\Matcher\Matchers; +use PhpPact\Consumer\Matcher\Exception\MatcherNotSupportedException; +use PhpPact\Consumer\Matcher\Formatters\Json\NoGeneratorFormatter; use PhpPact\Consumer\Matcher\Matchers\Values; use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\TestCase; @@ -18,4 +20,17 @@ public function testSerialize(array $values, string $json): void $array = new Values($values); $this->assertSame($json, json_encode($array)); } + + public function testCreateJsonFormatter(): void + { + $matcher = new Values([]); + $this->assertInstanceOf(NoGeneratorFormatter::class, $matcher->createJsonFormatter()); + } + + public function testCreateExpressionFormatter(): void + { + $matcher = new Values([]); + $this->expectExceptionObject(new MatcherNotSupportedException("Values matcher doesn't support expression formatter")); + $matcher->createExpressionFormatter(); + } } diff --git a/tests/PhpPact/Xml/XmlTextTest.php b/tests/PhpPact/Xml/XmlTextTest.php index 4094b9e4..ee0e3ee3 100644 --- a/tests/PhpPact/Xml/XmlTextTest.php +++ b/tests/PhpPact/Xml/XmlTextTest.php @@ -2,22 +2,21 @@ namespace PhpPactTest\Xml; -use PhpPact\Consumer\Matcher\Formatters\XmlContentFormatter; +use PhpPact\Consumer\Matcher\Formatters\Xml\XmlContentFormatter; use PhpPact\Consumer\Matcher\Generators\RandomInt; use PhpPact\Consumer\Matcher\Matchers\Integer; +use PHPUnit\Framework\Attributes\TestWith; use PHPUnit\Framework\TestCase; use PhpPact\Xml\XmlText; class XmlTextTest extends TestCase { - /** - * @testWith ["example text"] - * [1.23] - * [481] - * [false] - * [true] - * [null] - */ + #[TestWith(['example text'])] + #[TestWith([1.23])] + #[TestWith([481])] + #[TestWith([false])] + #[TestWith([true])] + #[TestWith([null])] public function testJsonSerializePredefinedTypes(mixed $content): void { $text = new XmlText($content); From 6f2b603c6fc985541b513f093c8c9ac723dd06fb Mon Sep 17 00:00:00 2001 From: "tien.xuan.vo" Date: Sat, 11 May 2024 18:27:15 +0700 Subject: [PATCH 2/3] test: Test atLeast atMost not useful outside matchAll --- .../consumer/tests/Service/MatchersTest.php | 4 +++ .../matchersConsumer-matchersProvider.json | 25 +++++++++++++++++++ example/matchers/provider/public/index.php | 9 +++++++ 3 files changed, 38 insertions(+) diff --git a/example/matchers/consumer/tests/Service/MatchersTest.php b/example/matchers/consumer/tests/Service/MatchersTest.php index 9cbec9bf..923d781c 100644 --- a/example/matchers/consumer/tests/Service/MatchersTest.php +++ b/example/matchers/consumer/tests/Service/MatchersTest.php @@ -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' => [ @@ -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' => [ diff --git a/example/matchers/pacts/matchersConsumer-matchersProvider.json b/example/matchers/pacts/matchersConsumer-matchersProvider.json index d3a17bce..879465cd 100644 --- a/example/matchers/pacts/matchersConsumer-matchersProvider.json +++ b/example/matchers/pacts/matchersConsumer-matchersProvider.json @@ -135,6 +135,10 @@ 111, "2fbd41cc-4bbc-44ea-a419-67f767691407" ], + "atLeast": [ + null, + null + ], "atLeastLike": [ 1, 1, @@ -142,6 +146,9 @@ 1, 1 ], + "atMost": [ + null + ], "atMostLike": [ 1 ], @@ -278,6 +285,15 @@ } ] }, + "$.atLeast": { + "combine": "AND", + "matchers": [ + { + "match": "type", + "min": 2 + } + ] + }, "$.atLeastLike": { "combine": "AND", "matchers": [ @@ -287,6 +303,15 @@ } ] }, + "$.atMost": { + "combine": "AND", + "matchers": [ + { + "match": "type", + "max": 4 + } + ] + }, "$.atMostLike": { "combine": "AND", "matchers": [ diff --git a/example/matchers/provider/public/index.php b/example/matchers/provider/public/index.php index 66a7ff0f..9debe29e 100644 --- a/example/matchers/provider/public/index.php +++ b/example/matchers/provider/public/index.php @@ -79,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(), ])); From 825cb86d95f6abcc1cb8800a5ee56377ac14256f Mon Sep 17 00:00:00 2001 From: "tien.xuan.vo" Date: Sat, 11 May 2024 18:30:47 +0700 Subject: [PATCH 3/3] test: Test values doesn't matter for atLeast and atMost formatters --- .../Matcher/Formatters/Expression/MaxTypeFormatterTest.php | 1 + .../Matcher/Formatters/Expression/MinTypeFormatterTest.php | 1 + 2 files changed, 2 insertions(+) diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Expression/MaxTypeFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/MaxTypeFormatterTest.php index 7903521d..c4c5ffbe 100644 --- a/tests/PhpPact/Consumer/Matcher/Formatters/Expression/MaxTypeFormatterTest.php +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/MaxTypeFormatterTest.php @@ -28,6 +28,7 @@ public function testNotSupportedMatcher(): void $this->formatter->format($matcher); } + #[TestWith([new MaxType([], 2), '"atMost(2)"'])] #[TestWith([new MaxType(['example value'], 2), '"atMost(2)"'])] public function testFormat(MatcherInterface $matcher, string $expression): void { diff --git a/tests/PhpPact/Consumer/Matcher/Formatters/Expression/MinTypeFormatterTest.php b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/MinTypeFormatterTest.php index 0065e46f..d6910ee6 100644 --- a/tests/PhpPact/Consumer/Matcher/Formatters/Expression/MinTypeFormatterTest.php +++ b/tests/PhpPact/Consumer/Matcher/Formatters/Expression/MinTypeFormatterTest.php @@ -28,6 +28,7 @@ public function testNotSupportedMatcher(): void $this->formatter->format($matcher); } + #[TestWith([new MinType([], 1), '"atLeast(1)"'])] #[TestWith([new MinType(['example value'], 1), '"atLeast(1)"'])] public function testFormat(MatcherInterface $matcher, string $expression): void {