Skip to content

Instantly share code, notes, and snippets.

@DavertMik
Created July 8, 2020 22:14
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DavertMik/5caf209236356ce6c2af036de6d06cdd to your computer and use it in GitHub Desktop.
Save DavertMik/5caf209236356ce6c2af036de6d06cdd to your computer and use it in GitHub Desktop.
Pact Helper for Codeception
<?php
namespace Codeception\Module;
use Codeception\Exception\ConfigurationException;
use Codeception\Exception\ModuleException;
use Codeception\Test\Test;
use Codeception\TestInterface;
use PhpPact\Consumer\Model\Interaction;
use PhpPact\Exception\ConnectionException;
use PhpPact\Http\GuzzleClient;
use PhpPact\Standalone\MockService\MockServerConfig;
use PhpPact\Standalone\MockService\Service\MockServerHttpService;
use PhpPact\Consumer\InteractionBuilder;
use PhpPact\Consumer\Model\ConsumerRequest;
use PhpPact\Consumer\Model\ProviderResponse;
use PhpPact\Standalone\MockService\MockServerConfigInterface;
use PhpPact\Standalone\MockService\MockServerEnvConfig;
use PhpPact\Standalone\MockService\Service\MockServerHttpServiceInterface;
class Pact extends \Codeception\Module
{
protected $requiredFields = [
'consumer',
'providers'
];
protected $config = [
'consumer' => null,
'providers' => []
];
/** @var MockServerHttpServiceInterface[] **/
protected $mockServices = [];
protected function validateConfig()
{
parent::validateConfig();
foreach ($this->config['providers'] as $providerConfig) {
$provider = key($providerConfig);
$serviceConfig = reset($providerConfig);
if (!isset($serviceConfig['mock_server_host'])) {
throw new ConfigurationException('mock_server_host required. Current config: ' . implode(', ', array_keys($serviceConfig)));
}
if (!isset($serviceConfig['mock_server_port'])) {
throw new ConfigurationException('mock_server_port required');
}
$config = new MockServerConfig();
$config->setHost($serviceConfig['mock_server_host']);
$config->setPort($serviceConfig['mock_server_port']);
$config->setConsumer($this->config['consumer']);
$config->setProvider($provider);
$this->debug("Provider mock for '$provider': " . json_encode($serviceConfig));
$this->mockServices[$provider] = new MockServerHttpService(new GuzzleClient(), $config);
}
}
public function _before(TestInterface $test)
{
foreach ($this->mockServices as $provider => $mockService) {
$mockService->deleteAllInteractions();
}
}
/**
* @param null $provider
* @return \Codeception\Pact\PactInteraction
*/
public function haveRequestTo($provider, $description)
{
if (!isset($this->mockServices[$provider])) {
throw new ModuleException("No mock service started for provider $provider");
}
return new PactInteraction($this->mockServices[$provider], $description);
}
public function _after(TestInterface $test)
{
foreach ($this->mockServices as $provider => $mockService) {
$mockService->verifyInteractions();
$this->assertTrue(true, 'interaction check');
$mockService->getPactJson();
}
}
}
class PactInteraction
{
protected $headers = [];
/** @var ConsumerRequest **/
protected $request;
/** @var ProviderResponse **/
protected $response;
/** @var MockServerEnvConfig **/
protected $config;
/** @var $given **/
protected $given;
private $description;
/** @var Interaction **/
private $interaction;
/** @var MockServerHttpServiceInterface **/
private $server;
public function __construct(MockServerHttpServiceInterface $server, $description)
{
$this->server = $server;
$this->interaction = new Interaction();
$this->description = $description;
}
public function haveHttpHeader($header, $value)
{
$this->headers[$header] = $value;
return $this;
}
public function request($method, $path, $body = null)
{
$request = new ConsumerRequest();
$request
->setMethod(strtoupper($method))
->setPath($path);
if ($body) {
$request->setBody($body);
}
foreach ($this->headers as $header => $val) {
$request->addHeader($header, $val);
}
$this->request = $request;
codecept_debug('Mocked Request: ' . json_encode($request->jsonSerialize()));
return $this;
}
public function resetHeaders()
{
$this->headers = [];
return $this;
}
public function requires($providerState)
{
$this->given = $providerState;
return $this;
}
public function response($code, $responseBody)
{
$response = new ProviderResponse();
$response
->setStatus($code)
->setBody($responseBody);
foreach ($this->headers as $header => $val) {
$response->addHeader($header, $val);
}
$this->response = $response;
$this->interaction
->setRequest($this->request)
->setResponse($this->response)
->setDescription($this->description);
if ($this->given) {
$this->interaction->setProviderState($this->given);
}
codecept_debug('Mocked Response: ' . json_encode($response->jsonSerialize()));
$this->server->registerInteraction($this->interaction);
codecept_debug('Interaction saved');
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment