Skip to content

Commit

Permalink
feat: Support http request binary body
Browse files Browse the repository at this point in the history
  • Loading branch information
tienvx committed Aug 21, 2023
1 parent 3d8a055 commit 9c30bfb
Show file tree
Hide file tree
Showing 44 changed files with 521 additions and 150 deletions.
4 changes: 2 additions & 2 deletions .cirrus.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ linux_arm64_task:
container:
image: php:$VERSION
pre_req_script:
- apt update --yes && apt install --yes zip unzip git libffi-dev
- apt update --yes && apt install --yes zip unzip git libffi-dev shared-mime-info
- curl -sS https://getcomposer.org/installer -o /tmp/composer-setup.php
- php /tmp/composer-setup.php --install-dir=/usr/local/bin --filename=composer
- docker-php-ext-install sockets
Expand All @@ -46,7 +46,7 @@ macos_arm64_task:
macos_instance:
image: ghcr.io/cirruslabs/macos-ventura-base:latest
pre_req_script:
- brew install php@$VERSION composer
- brew install php@$VERSION composer shared-mime-info
version_check_script:
- php --version
<< : *BUILD_TEST_TASK_TEMPLATE
6 changes: 5 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@
"MessageConsumer\\": "example/message/consumer/src",
"MessageConsumer\\Tests\\": "example/message/consumer/tests",
"MessageProvider\\": "example/message/provider/src",
"MessageProvider\\Tests\\": "example/message/provider/tests"
"MessageProvider\\Tests\\": "example/message/provider/tests",
"BinaryConsumer\\": "example/binary/consumer/src",
"BinaryConsumer\\Tests\\": "example/binary/consumer/tests",
"BinaryProvider\\": "example/binary/provider/src",
"BinaryProvider\\Tests\\": "example/binary/provider/tests"
}
},
"scripts": {
Expand Down
11 changes: 11 additions & 0 deletions example/binary/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="../../../vendor/autoload.php" colors="true">
<testsuites>
<testsuite name="PhpPact Example Tests">
<directory>./tests</directory>
</testsuite>
</testsuites>
<php>
<env name="PACT_LOGLEVEL" value="DEBUG"/>
</php>
</phpunit>
31 changes: 31 additions & 0 deletions example/binary/consumer/src/Service/HttpClientService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace BinaryConsumer\Service;

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

/**
* Example HTTP Service
*/
class HttpClientService
{
private Client $httpClient;

private string $baseUri;

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

public function getImageContent(): string
{
$response = $this->httpClient->get(new Uri("{$this->baseUri}/image.jpg"), [
'headers' => ['Accept' => 'image/jpeg']
]);

return $response->getBody();
}
}
53 changes: 53 additions & 0 deletions example/binary/consumer/tests/Service/HttpClientServiceTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

namespace BinaryConsumer\Tests\Service;

use BinaryConsumer\Service\HttpClientService;
use PhpPact\Consumer\InteractionBuilder;
use PhpPact\Consumer\Model\Body\Binary;
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 testGetImageContent()
{
$imageContent = file_get_contents(__DIR__ . '/../_resource/image.jpg');

$request = new ConsumerRequest();
$request
->setMethod('GET')
->setPath('/image.jpg')
->addHeader('Accept', 'image/jpeg');

$response = new ProviderResponse();
$response
->setStatus(200)
->addHeader('Content-Type', 'image/jpeg')
->setBody(new Binary($imageContent, in_array(php_uname('m'), ['AMD64', 'arm64']) ? 'application/octet-stream' : 'image/jpeg'));

$config = new MockServerConfig();
$config
->setConsumer('binaryConsumer')
->setProvider('binaryProvider')
->setPactDir(__DIR__.'/../../../pacts');
if ($logLevel = \getenv('PACT_LOGLEVEL')) {
$config->setLogLevel($logLevel);
}
$builder = new InteractionBuilder($config);
$builder
->given('Image file image.jpg exists')
->uponReceiving('A get request to /image.jpg')
->with($request)
->willRespondWith($response);

$service = new HttpClientService($config->getBaseUri());
$imageContentResult = $service->getImageContent();
$verifyResult = $builder->verify();

$this->assertTrue($verifyResult);
$this->assertEquals($imageContent, $imageContentResult);
}
}
Binary file added example/binary/consumer/tests/_resource/image.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
56 changes: 56 additions & 0 deletions example/binary/pacts/binaryConsumer-binaryProvider.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"consumer": {
"name": "binaryConsumer"
},
"interactions": [
{
"description": "A get request to /image.jpg",
"providerStates": [
{
"name": "Image file image.jpg exists"
}
],
"request": {
"headers": {
"Accept": "image/jpeg"
},
"method": "GET",
"path": "/image.jpg"
},
"response": {
"body": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/wAALCAAPAA8BAREA/8QAFgABAQEAAAAAAAAAAAAAAAAAAgME/8QAIBAAAgIDAAIDAQAAAAAAAAAAAQIDBAUREhMhACIxUf/aAAgBAQAAPwBNlclNW6S0s7wbvv4K6iNI2HJcp9Rrnk+T0ByNofwZIjdnyYx0stWrYWAP5y03SBjt+GQ/YnmHbaUkfoA107Br40Wa+DrRLNXhjchECDwyjjlXPpdFSo3Gw5CbDFdmUVOrHcfEU4JYb2PWSJCzbVPUEmh7PQaOZHOyD0x/hHz/2Q==",
"headers": {
"Content-Type": "image/jpeg"
},
"matchingRules": {
"body": {
"$": {
"combine": "AND",
"matchers": [
{
"match": "contentType",
"value": "image/jpeg"
}
]
}
},
"header": {}
},
"status": 200
}
}
],
"metadata": {
"pactRust": {
"ffi": "0.4.7",
"mockserver": "1.2.3",
"models": "1.1.9"
},
"pactSpecification": {
"version": "3.0.0"
}
},
"provider": {
"name": "binaryProvider"
}
}
11 changes: 11 additions & 0 deletions example/binary/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="../../../vendor/autoload.php" colors="true">
<testsuites>
<testsuite name="PhpPact Example Tests">
<directory>./tests</directory>
</testsuite>
</testsuites>
<php>
<env name="PACT_LOGLEVEL" value="DEBUG"/>
</php>
</phpunit>
Binary file added example/binary/provider/public/image.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
62 changes: 62 additions & 0 deletions example/binary/provider/tests/PactVerifyTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

namespace BinaryConsumer\Tests;

use PhpPact\Standalone\ProviderVerifier\Model\VerifierConfig;
use PhpPact\Standalone\ProviderVerifier\Verifier;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Process\Process;

class PactVerifyTest extends TestCase
{
private Process $process;

/**
* Run the PHP build-in web server.
*/
protected function setUp(): void
{
$this->process = new Process(['php', '-S', '127.0.0.1:7202', '-t', __DIR__ . '/../public/']);

$this->process->start();
$this->process->waitUntil(function (): bool {
$fp = @fsockopen('127.0.0.1', 7202);
$isOpen = is_resource($fp);
if ($isOpen) {
fclose($fp);
}

return $isOpen;
});
}

/**
* Stop the web server process once complete.
*/
protected function tearDown(): void
{
$this->process->stop();
}

/**
* This test will run after the web server is started.
*/
public function testPactVerifyConsumer()
{
$config = new VerifierConfig();
$config->getProviderInfo()
->setName('binaryProvider') // Providers name to fetch.
->setHost('localhost')
->setPort(7202);
if ($level = \getenv('PACT_LOGLEVEL')) {
$config->setLogLevel($level);
}

$verifier = new Verifier($config);
$verifier->addFile(__DIR__ . '/../../pacts/binaryConsumer-binaryProvider.json');

$verifyResult = $verifier->verify();

$this->assertTrue($verifyResult);
}
}
4 changes: 1 addition & 3 deletions example/json/provider/tests/PactVerifyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@ class PactVerifyTest extends TestCase
*/
protected function setUp(): void
{
$publicPath = __DIR__ . '/../public/';

$this->process = new Process(['php', '-S', '127.0.0.1:7202', '-t', $publicPath]);
$this->process = new Process(['php', '-S', '127.0.0.1:7202', '-t', __DIR__ . '/../public/']);

$this->process->start();
$this->process->waitUntil(function (): bool {
Expand Down
6 changes: 6 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@
<testsuite name="PhpPact Json Provider Example Tests">
<directory>./example/json/provider/tests</directory>
</testsuite>
<testsuite name="PhpPact Binary Consumer Example Tests">
<directory>./example/binary/consumer/tests</directory>
</testsuite>
<testsuite name="PhpPact Binary Provider Example Tests">
<directory>./example/binary/provider/tests</directory>
</testsuite>
<testsuite name="PhpPact Message Consumer Example Tests">
<directory>./example/message/consumer/tests</directory>
</testsuite>
Expand Down
7 changes: 0 additions & 7 deletions src/PhpPact/Consumer/AbstractMessageBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,4 @@ public function withContent(mixed $contents): self

return $this;
}

public function withContentType(?string $contentType): self
{
$this->message->setContentType($contentType);

return $this;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace PhpPact\Consumer\Exception;

use Exception;

class MessageContentsNotAddedException extends Exception
{
}
30 changes: 30 additions & 0 deletions src/PhpPact/Consumer/Model/Body/Binary.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace PhpPact\Consumer\Model\Body;

use PhpPact\FFI\Model\StringData;

class Binary
{
use ContentTypeTrait;

private StringData $contents;

public function __construct(string $contents, string $contentType)
{
$this->setContents(StringData::createFrom($contents, false));
$this->setContentType($contentType);
}

public function getContents(): StringData
{
return $this->contents;
}

public function setContents(StringData $contents): self
{
$this->contents = $contents;

return $this;
}
}
20 changes: 20 additions & 0 deletions src/PhpPact/Consumer/Model/Body/ContentTypeTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace PhpPact\Consumer\Model\Body;

trait ContentTypeTrait
{
private string $contentType;

public function getContentType(): string
{
return $this->contentType;
}

public function setContentType(string $contentType): self
{
$this->contentType = $contentType;

return $this;
}
}
28 changes: 28 additions & 0 deletions src/PhpPact/Consumer/Model/Body/Text.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace PhpPact\Consumer\Model\Body;

class Text
{
use ContentTypeTrait;

private string $contents;

public function __construct(string $contents, string $contentType)
{
$this->setContents($contents);
$this->setContentType($contentType);
}

public function getContents(): string
{
return $this->contents;
}

public function setContents(string $contents): self
{
$this->contents = $contents;

return $this;
}
}

0 comments on commit 9c30bfb

Please sign in to comment.