Skip to content

Commit

Permalink
feat: Support generators in more matchers
Browse files Browse the repository at this point in the history
  • Loading branch information
tienvx committed Oct 10, 2024
1 parent d9cd08e commit 6161391
Show file tree
Hide file tree
Showing 12 changed files with 208 additions and 58 deletions.
29 changes: 23 additions & 6 deletions example/generators/consumer/tests/Service/GeneratorsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
use DateTime;
use GeneratorsConsumer\Service\HttpClientService;
use PhpPact\Consumer\InteractionBuilder;
use PhpPact\Consumer\Matcher\Generators\RandomString;
use PhpPact\Consumer\Matcher\Generators\Uuid;
use PhpPact\Consumer\Matcher\HttpStatus;
use PhpPact\Consumer\Matcher\Matcher;
use PhpPact\Consumer\Matcher\Matchers\StringValue;
Expand Down Expand Up @@ -39,9 +41,9 @@ public function testGetGenerators(): void
->addHeader('Content-Type', 'application/json')
->setBody([
'regex' => $this->matcher->regex(null, $regexWithoutAnchors = '\d+ (miles|kilometers)'),
'boolean' => $this->matcher->booleanV3(null),
'integer' => $this->matcher->integerV3(null),
'decimal' => $this->matcher->decimalV3(null),
'boolean_v3' => $this->matcher->booleanV3(null),
'integer_v3' => $this->matcher->integerV3(null),
'decimal_v3' => $this->matcher->decimalV3(null),
'hexadecimal' => $this->matcher->hexadecimal(null),
'uuid' => $this->matcher->uuid(null),
'date' => $this->matcher->date('yyyy-MM-dd', null),
Expand All @@ -50,6 +52,12 @@ public function testGetGenerators(): void
'string' => $this->matcher->string(null),
'number' => $this->matcher->number(null),
'url' => $this->matcher->url('http://localhost/users/1234/posts/latest', '.*(\\/users\\/\\d+\\/posts\\/latest)$'),
'notEmpty' => $this->matcher->notEmpty('text')->withGenerator(new RandomString()),
'equality' => $this->matcher->equal('Hello World!')->withGenerator(new RandomString()),
'like' => $this->matcher->like('6057401b-c539-4948-971a-24b702d79882')->withGenerator(new Uuid()),
'boolean' => $this->matcher->boolean(null),
'integer' => $this->matcher->integer(null),
'decimal' => $this->matcher->decimal(null),
'requestId' => 222,
]);

Expand Down Expand Up @@ -85,9 +93,9 @@ public function testGetGenerators(): void
)
);
$this->assertMatchesRegularExpression('/^' . $regexWithoutAnchors . '$/', $body['regex']);
$this->assertIsBool($body['boolean']);
$this->assertIsInt($body['integer']);
$this->assertIsFloat($body['decimal'] + 0);
$this->assertIsBool($body['boolean_v3']);
$this->assertIsInt($body['integer_v3']);
$this->assertIsFloat($body['decimal_v3'] + 0);
$this->assertMatchesRegularExpression('/' . Matcher::HEX_FORMAT . '/', $body['hexadecimal']);
$this->assertMatchesRegularExpression('/' . Matcher::UUID_V4_FORMAT . '/', $body['uuid']);
$this->assertTrue($this->validateDateTime($body['date'], 'Y-m-d'));
Expand All @@ -98,6 +106,15 @@ public function testGetGenerators(): void
$this->assertIsNumeric($body['number']);
$this->assertNotSame('http://localhost/users/1234/posts/latest', $body['url']);
$this->assertMatchesRegularExpression('/.*(\\/users\\/\\d+\\/posts\\/latest)$/', $body['url']);
$this->assertIsString($body['notEmpty']);
$this->assertNotEmpty($body['notEmpty']);
$this->assertIsString($body['equality']);
$this->assertNotSame('Hello World!', $body['equality']);
$this->assertIsString($body['like']);
$this->assertMatchesRegularExpression('/' . Matcher::UUID_V4_FORMAT . '/', $body['like']);
$this->assertIsBool($body['boolean']);
$this->assertIsInt($body['integer']);
$this->assertIsFloat($body['decimal'] + 0);
$this->assertSame(222, $body['requestId']);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,21 +45,26 @@
}
]
}
},
"header": {}
}
},
"method": "GET",
"path": "/generators"
},
"response": {
"body": {
"content": {
"boolean": null,
"boolean": true,
"boolean_v3": null,
"date": null,
"datetime": null,
"decimal": null,
"decimal": 13.01,
"decimal_v3": null,
"equality": "Hello World!",
"hexadecimal": null,
"integer": null,
"integer": 13,
"integer_v3": null,
"like": "6057401b-c539-4948-971a-24b702d79882",
"notEmpty": "text",
"number": null,
"regex": null,
"requestId": 222,
Expand All @@ -76,6 +81,9 @@
"$.boolean": {
"type": "RandomBoolean"
},
"$.boolean_v3": {
"type": "RandomBoolean"
},
"$.date": {
"format": "yyyy-MM-dd",
"type": "Date"
Expand All @@ -88,6 +96,14 @@
"digits": 10,
"type": "RandomDecimal"
},
"$.decimal_v3": {
"digits": 10,
"type": "RandomDecimal"
},
"$.equality": {
"size": 10,
"type": "RandomString"
},
"$.hexadecimal": {
"digits": 10,
"type": "RandomHexadecimal"
Expand All @@ -97,6 +113,18 @@
"min": 0,
"type": "RandomInt"
},
"$.integer_v3": {
"max": 10,
"min": 0,
"type": "RandomInt"
},
"$.like": {
"type": "Uuid"
},
"$.notEmpty": {
"size": 10,
"type": "RandomString"
},
"$.number": {
"max": 10,
"min": 0,
Expand Down Expand Up @@ -137,6 +165,14 @@
"matchingRules": {
"body": {
"$.boolean": {
"combine": "AND",
"matchers": [
{
"match": "type"
}
]
},
"$.boolean_v3": {
"combine": "AND",
"matchers": [
{
Expand All @@ -163,13 +199,29 @@
]
},
"$.decimal": {
"combine": "AND",
"matchers": [
{
"match": "type"
}
]
},
"$.decimal_v3": {
"combine": "AND",
"matchers": [
{
"match": "decimal"
}
]
},
"$.equality": {
"combine": "AND",
"matchers": [
{
"match": "equality"
}
]
},
"$.hexadecimal": {
"combine": "AND",
"matchers": [
Expand All @@ -180,13 +232,39 @@
]
},
"$.integer": {
"combine": "AND",
"matchers": [
{
"match": "type",
"max": 10,
"min": 0
}
]
},
"$.integer_v3": {
"combine": "AND",
"matchers": [
{
"match": "integer"
}
]
},
"$.like": {
"combine": "AND",
"matchers": [
{
"match": "type"
}
]
},
"$.notEmpty": {
"combine": "AND",
"matchers": [
{
"match": "notEmpty"
}
]
},
"$.number": {
"combine": "AND",
"matchers": [
Expand Down Expand Up @@ -240,7 +318,6 @@
]
}
},
"header": {},
"status": {
"$": {
"combine": "AND",
Expand All @@ -261,9 +338,9 @@
],
"metadata": {
"pactRust": {
"ffi": "0.4.22",
"mockserver": "1.2.9",
"models": "1.2.3"
"ffi": "0.4.23",
"mockserver": "1.2.10",
"models": "1.2.5"
},
"pactSpecification": {
"version": "4.0"
Expand Down
12 changes: 9 additions & 3 deletions example/generators/provider/public/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@

return Response::json([
'regex' => '800 kilometers',
'boolean' => true,
'integer' => 11,
'decimal' => 25.1,
'boolean_v3' => true,
'integer_v3' => 11,
'decimal_v3' => 25.1,
'hexadecimal' => '20AC',
'uuid' => 'e9d2f3a5-6ecc-4bff-8935-84bb6141325a',
'date' => '1997-12-11',
Expand All @@ -23,6 +23,12 @@
'string' => 'another string',
'number' => 112.3,
'url' => 'https://www.example.com/users/1234/posts/latest',
'notEmpty' => 123,
'equality' => 'Hello World!',
'like' => 'not uuid',
'boolean' => false,
'integer' => -99,
'decimal' => -810.22,
'requestId' => $body['id'],
])
->withStatus(400);
Expand Down
18 changes: 12 additions & 6 deletions src/PhpPact/Consumer/Matcher/Matcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
use PhpPact\Consumer\Matcher\Formatters\Json\JsonFormatter;
use PhpPact\Consumer\Matcher\Generators\MockServerURL;
use PhpPact\Consumer\Matcher\Generators\ProviderState;
use PhpPact\Consumer\Matcher\Generators\RandomBoolean;
use PhpPact\Consumer\Matcher\Generators\RandomDecimal;
use PhpPact\Consumer\Matcher\Generators\RandomHexadecimal;
use PhpPact\Consumer\Matcher\Generators\RandomInt;
use PhpPact\Consumer\Matcher\Generators\Uuid;
use PhpPact\Consumer\Matcher\Matchers\ArrayContains;
use PhpPact\Consumer\Matcher\Matchers\Boolean;
Expand Down Expand Up @@ -213,19 +216,22 @@ public function timestampRFC3339(string $value = 'Mon, 31 Oct 2016 15:21:41 -040
return $this->term($value, self::RFC3339_TIMESTAMP_FORMAT);
}

public function boolean(): Type
public function boolean(?bool $value = null): Type
{
return $this->like(true);
return $this->like($value ?? true)
->withGenerator(is_null($value) ? new RandomBoolean() : null);
}

public function integer(int $int = 13): Type
public function integer(?int $value = null): Type
{
return $this->like($int);
return $this->like($value ?? 13)
->withGenerator(is_null($value) ? new RandomInt() : null);
}

public function decimal(float $float = 13.01): Type
public function decimal(?float $value = null): Type
{
return $this->like($float);
return $this->like($value ?? 13.01)
->withGenerator(is_null($value) ? new RandomDecimal() : null);
}

public function booleanV3(?bool $value = null): Boolean
Expand Down
9 changes: 6 additions & 3 deletions src/PhpPact/Consumer/Matcher/Matchers/Equality.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,26 @@
use PhpPact\Consumer\Matcher\Model\Expression;
use PhpPact\Consumer\Matcher\Model\Matcher\ExpressionFormattableInterface;
use PhpPact\Consumer\Matcher\Model\Matcher\JsonFormattableInterface;
use PhpPact\Consumer\Matcher\Trait\JsonFormattableTrait;

/**
* This is the default matcher, and relies on the equals operator
*/
class Equality extends AbstractMatcher implements JsonFormattableInterface, ExpressionFormattableInterface
class Equality extends GeneratorAwareMatcher implements JsonFormattableInterface, ExpressionFormattableInterface
{
use JsonFormattableTrait;

public function __construct(private mixed $value)
{
parent::__construct();
}

public function formatJson(): Attributes
{
return new Attributes([
return $this->mergeJson(new Attributes([
'pact:matcher:type' => 'equality',
'value' => $this->value,
]);
]));
}

public function formatExpression(): Expression
Expand Down
9 changes: 6 additions & 3 deletions src/PhpPact/Consumer/Matcher/Matchers/NotEmpty.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,26 @@
use PhpPact\Consumer\Matcher\Model\Expression;
use PhpPact\Consumer\Matcher\Model\Matcher\ExpressionFormattableInterface;
use PhpPact\Consumer\Matcher\Model\Matcher\JsonFormattableInterface;
use PhpPact\Consumer\Matcher\Trait\JsonFormattableTrait;

/**
* Value must be present and not empty (not null or the empty string)
*/
class NotEmpty extends AbstractMatcher implements JsonFormattableInterface, ExpressionFormattableInterface
class NotEmpty extends GeneratorAwareMatcher implements JsonFormattableInterface, ExpressionFormattableInterface
{
use JsonFormattableTrait;

public function __construct(private mixed $value)
{
parent::__construct();
}

public function formatJson(): Attributes
{
return new Attributes([
return $this->mergeJson(new Attributes([
'pact:matcher:type' => 'notEmpty',
'value' => $this->value,
]);
]));
}

public function formatExpression(): Expression
Expand Down
Loading

0 comments on commit 6161391

Please sign in to comment.