Skip to content

Commit

Permalink
Merge pull request #630 from tienvx/add-form-urlencoded-example
Browse files Browse the repository at this point in the history
chore: Add form urlencoded example
  • Loading branch information
tienvx authored Jan 4, 2025
2 parents 0f5db6e + 5fd2247 commit e005fd7
Show file tree
Hide file tree
Showing 10 changed files with 550 additions and 3 deletions.
12 changes: 9 additions & 3 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,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 @@ -136,17 +137,22 @@
"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": {
"downloads": {
"pact-ffi-headers": {
"version": "0.4.23",
"version": "0.4.26",
"url": "https://github.com/pact-foundation/pact-reference/releases/download/libpact_ffi-v{$version}/pact.h",
"path": "bin/pact-ffi-headers/pact.h"
},
"pact-ffi-lib": {
"version": "0.4.23",
"version": "0.4.26",
"variables": {
"{$prefix}": "PHP_OS_FAMILY === 'Windows' ? 'pact_ffi' : 'libpact_ffi'",
"{$os}": "PHP_OS === 'Darwin' ? 'macos' : strtolower(PHP_OS_FAMILY)",
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>
50 changes: 50 additions & 0 deletions example/form-urlencoded/consumer/src/Service/HttpClientService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?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,
'ampersand' => '&',
'slash' => '/',
'question-mark' => '?',
'equals-sign' => '=',
'&' => 'ampersand',
'/' => 'slash',
'?' => 'question-mark',
'=' => 'equals-sign',
]) .
'&=first&=second&=third' .
'&roles[]=User&roles[]=Manager' .
'&orders[]=&orders[]=ASC&orders[]=DESC',
'headers' => [
'Accept' => 'application/x-www-form-urlencoded',
'Content-Type' => 'application/x-www-form-urlencoded',
],
]);

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

namespace FormUrlEncodedConsumer\Tests\Service;

use PhpPact\Consumer\Matcher\Generators\RandomInt;
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/x-www-form-urlencoded')
->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')]),
'orders[]' => $matcher->arrayContaining([
$matcher->equal('DESC'),
$matcher->equal('ASC'),
$matcher->equal(''),
]),
// Empty string keys are supported
'' => ['first', 'second', 'third'],
// 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')
]),
// special characters are encoded
'ampersand' => $matcher->equal('&'),
'slash' => '/',
'question-mark' => '?',
'equals-sign' => '=',
'&' => 'ampersand',
'/' => 'slash',
'?' => 'question-mark',
'=' => 'equals-sign',
]),
'application/x-www-form-urlencoded'
)
)
;

$response = new ProviderResponse();
$response
->setStatus(201)
->addHeader('Content-Type', 'application/x-www-form-urlencoded')
->setBody(
new Text(
json_encode([
'id' => $matcher->uuid(),
'age' => $matcher->integerV3()->withGenerator(new RandomInt(0, 130)),
'name[]' => [
$matcher->regex(null, $gender = 'Mr\.|Mrs\.|Miss|Ms\.'),
$matcher->string(),
$matcher->string(),
$matcher->string(),
],
]),
'application/x-www-form-urlencoded'
)
);

$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());
parse_str($service->createUser(), $params);
$verifyResult = $builder->verify();

$this->assertTrue(condition: $verifyResult);
$this->assertArrayHasKey('id', $params);
$pattern = Matcher::UUID_V4_FORMAT;
$this->assertMatchesRegularExpression("/{$pattern}/", $params['id']);
$this->assertArrayHasKey('age', $params);
$this->assertLessThanOrEqual(130, $params['age']);
$this->assertGreaterThanOrEqual(0, $params['age']);
$this->assertArrayHasKey('name', $params);
$this->assertIsArray($params['name']);
$this->assertCount(4, $params['name']);
$this->assertMatchesRegularExpression("/{$gender}/", $params['name'][0]);
}
}
Loading

0 comments on commit e005fd7

Please sign in to comment.