Skip to content

Commit

Permalink
chore: Add form urlencoded example
Browse files Browse the repository at this point in the history
  • Loading branch information
tienvx committed Oct 30, 2024
1 parent 0e38dd2 commit 66e97e1
Show file tree
Hide file tree
Showing 10 changed files with 377 additions and 1 deletion.
8 changes: 7 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@
"composer run-example:protobuf-sync-message",
"composer run-example:stub-server",
"composer run-example:xml",
"composer run-example:graphql"
"composer run-example:graphql",
"composer run-example:form-urlencoded"
],
"run-example:binary": [
"rm -f example/binary/pacts/binaryConsumer-binaryProvider.json",
Expand Down Expand Up @@ -137,6 +138,11 @@
"rm -f example/graphql/pacts/graphqlConsumer-graphqlProvider.json",
"cd example/graphql/consumer && phpunit",
"cd example/graphql/provider && phpunit"
],
"run-example:form-urlencoded": [
"rm -f example/graphql/pacts/formUrlEncodedConsumer-formUrlEncodedProvider.json",
"cd example/form-urlencoded/consumer && phpunit",
"cd example/form-urlencoded/provider && phpunit"
]
},
"extra": {
Expand Down
5 changes: 5 additions & 0 deletions example/form-urlencoded/consumer/autoload.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?php

$loader = require __DIR__ . '/../../../vendor/autoload.php';
$loader->addPsr4('FormUrlEncodedConsumer\\', __DIR__ . '/src');
$loader->addPsr4('FormUrlEncodedConsumer\\Tests\\', __DIR__ . '/tests');
11 changes: 11 additions & 0 deletions example/form-urlencoded/consumer/phpunit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="./autoload.php" colors="true">
<testsuites>
<testsuite name="PhpPact Example Tests">
<directory>./tests</directory>
</testsuite>
</testsuites>
<php>
<env name="PACT_LOGLEVEL" value="DEBUG"/>
</php>
</phpunit>
40 changes: 40 additions & 0 deletions example/form-urlencoded/consumer/src/Service/HttpClientService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace FormUrlEncodedConsumer\Service;

use GuzzleHttp\Client;
use GuzzleHttp\Psr7\Uri;

class HttpClientService
{
private Client $httpClient;

private string $baseUri;

public function __construct(string $baseUri)
{
$this->httpClient = new Client();
$this->baseUri = $baseUri;
}

public function createUser(): string
{
$response = $this->httpClient->post(new Uri("{$this->baseUri}/users"), [
'body' => http_build_query([
'empty' => '',
'agree' => 'true',
'fullname' => 'First Last Name',
'email' => '[email protected]',
'password' => 'very@secure&password123',
'age' => 41,
]) .
'&roles[]=User&roles[]=Manager',
'headers' => [
'Accept' => 'application/json',
'Content-Type' => 'application/x-www-form-urlencoded',
],
]);

return $response->getBody();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php

namespace FormUrlEncodedConsumer\Tests\Service;

use PhpPact\Consumer\Matcher\Matcher;
use FormUrlEncodedConsumer\Service\HttpClientService;
use PhpPact\Consumer\InteractionBuilder;
use PhpPact\Consumer\Model\Body\Text;
use PhpPact\Consumer\Model\ConsumerRequest;
use PhpPact\Consumer\Model\ProviderResponse;
use PhpPact\Standalone\MockService\MockServerConfig;
use PHPUnit\Framework\TestCase;

class HttpClientServiceTest extends TestCase
{
public function testGetMovies()
{
$matcher = new Matcher();

$request = new ConsumerRequest();
$request
->setMethod('POST')
->setPath('/users')
->addHeader('Content-Type', 'application/x-www-form-urlencoded')
->addHeader('Accept', 'application/json')
->setBody(
new Text(
json_encode([
'empty' => $matcher->equal(''),
'agree' => $matcher->regex('false', 'true|false'),
'fullname' => $matcher->string('User name'),
'email' => $matcher->email('[email protected]'),
'password' => $matcher->regex('user@password111', '^[\w\d@$!%*#?&^_-]{8,}$'),
'age' => $matcher->number(27),
'roles[]' => $matcher->eachValue(['User'], [$matcher->regex('User', 'Admin|User|Manager')]),
// Null, boolean and object values are not supported, so the values and matchers will be ignored
'null' => $matcher->nullValue(),
'boolean' => $matcher->booleanV3(true),
'object' => $matcher->like([
'key' => $matcher->string('value')
]),
]),
'application/x-www-form-urlencoded'
)
)
;

$response = new ProviderResponse();
$response
->setStatus(201)
->addHeader('Content-Type', 'application/json')
->setBody([
'id' => $matcher->uuid('6e58b1df-ff80-4031-b7b9-5191e4c74ee8'),
]);

$config = new MockServerConfig();
$config
->setConsumer('formUrlEncodedConsumer')
->setProvider('formUrlEncodedProvider')
->setPactDir(__DIR__.'/../../../pacts');
if ($logLevel = \getenv('PACT_LOGLEVEL')) {
$config->setLogLevel($logLevel);
}
$builder = new InteractionBuilder($config);
$builder
->given('Endpoint is protected')
->uponReceiving('A post request to /users')
->with($request)
->willRespondWith($response);

$service = new HttpClientService($config->getBaseUri());
$body = json_decode($service->createUser(), true);
$verifyResult = $builder->verify();

$this->assertTrue($verifyResult);
$this->assertArrayHasKey('id', $body);
$pattern = Matcher::UUID_V4_FORMAT;
$this->assertEquals(1, preg_match("/{$pattern}/", $body['id']));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
{
"consumer": {
"name": "formUrlEncodedConsumer"
},
"interactions": [
{
"description": "A post request to /users",
"providerStates": [
{
"name": "Endpoint is protected"
}
],
"request": {
"body": "age=27&agree=false&email=user%40email.test&empty=&fullname=User+name&password=user%40password111&roles%5B%5D=User",
"headers": {
"Accept": "application/json",
"Content-Type": "application/x-www-form-urlencoded"
},
"matchingRules": {
"body": {
"$.age": {
"combine": "AND",
"matchers": [
{
"match": "number"
}
]
},
"$.agree": {
"combine": "AND",
"matchers": [
{
"match": "regex",
"regex": "true|false"
}
]
},
"$.email": {
"combine": "AND",
"matchers": [
{
"match": "regex",
"regex": "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+.[a-zA-Z]{2,}$"
}
]
},
"$.empty": {
"combine": "AND",
"matchers": [
{
"match": "equality"
}
]
},
"$.fullname": {
"combine": "AND",
"matchers": [
{
"match": "type"
}
]
},
"$.object.key": {
"combine": "AND",
"matchers": [
{
"match": "type"
}
]
},
"$.password": {
"combine": "AND",
"matchers": [
{
"match": "regex",
"regex": "^[\\w\\d@$!%*#?&^_-]{8,}$"
}
]
},
"$['roles[]']": {
"combine": "AND",
"matchers": [
{
"match": "eachValue",
"rules": [
{
"match": "regex",
"regex": "Admin|User|Manager"
}
],
"value": "[\"User\"]"
}
]
}
}
},
"method": "POST",
"path": "/users"
},
"response": {
"body": {
"id": "6e58b1df-ff80-4031-b7b9-5191e4c74ee8"
},
"headers": {
"Content-Type": "application/json"
},
"matchingRules": {
"body": {
"$.id": {
"combine": "AND",
"matchers": [
{
"match": "regex",
"regex": "^[0-9a-f]{8}(-[0-9a-f]{4}){3}-[0-9a-f]{12}$"
}
]
}
}
},
"status": 201
}
}
],
"metadata": {
"pactRust": {
"ffi": "0.4.24",
"mockserver": "1.2.10",
"models": "1.2.5"
},
"pactSpecification": {
"version": "3.0.0"
}
},
"provider": {
"name": "formUrlEncodedProvider"
}
}
4 changes: 4 additions & 0 deletions example/form-urlencoded/provider/autoload.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?php

$loader = require __DIR__ . '/../../../vendor/autoload.php';
$loader->addPsr4('FormUrlEncodedProvider\\Tests\\', __DIR__ . '/tests');
11 changes: 11 additions & 0 deletions example/form-urlencoded/provider/phpunit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit bootstrap="./autoload.php" colors="true">
<testsuites>
<testsuite name="PhpPact Example Tests">
<directory>./tests</directory>
</testsuite>
</testsuites>
<php>
<env name="PACT_LOGLEVEL" value="DEBUG"/>
</php>
</phpunit>
30 changes: 30 additions & 0 deletions example/form-urlencoded/provider/public/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

use React\Http\Message\Response;
use Psr\Http\Message\ServerRequestInterface;

require __DIR__ . '/../../../../vendor/autoload.php';

$app = new FrameworkX\App();

$app->post('/users', function (ServerRequestInterface $request) {
$response = new Response();
$auth = $request->getHeaderLine('Authorization');
if ($auth != 'Bearer 1a2b3c4d5e6f7g8h9i0k') {
return $response->withStatus(403);
}

error_log(sprintf('request body: %s', (string) $request->getBody()));

$response->getBody()->write(\json_encode(['id' => '49dcfd3f-a5c9-49cb-a09e-a40a1da936b9']));

return $response
->withStatus(201)
->withHeader('Content-Type', 'application/json');
});

$app->post('/pact-change-state', function (ServerRequestInterface $request) {
return new Response();
});

$app->run();
Loading

0 comments on commit 66e97e1

Please sign in to comment.