Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support sync message #374

Merged
merged 1 commit into from
Dec 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ private function expectsToReceive(string $description): self
/**
* @param ProviderState[] $providerStates
*/
private function given(array $providerStates): self
protected function given(array $providerStates): self
{
foreach ($providerStates as $providerState) {
$this->client->call('pactffi_message_given', $this->id, $providerState->getName());
Expand Down
31 changes: 31 additions & 0 deletions src/PhpPact/SyncMessage/Driver/Interaction/SyncMessageDriver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace PhpPact\SyncMessage\Driver\Interaction;

use PhpPact\Consumer\Driver\Pact\PactDriverInterface;
use PhpPact\Consumer\Model\Message;
use PhpPact\Consumer\Registry\Interaction\MessageRegistryInterface;
use PhpPact\Consumer\Service\MockServerInterface;

class SyncMessageDriver implements SyncMessageDriverInterface
{
public function __construct(
private PactDriverInterface $pactDriver,
private MessageRegistryInterface $messageRegistry,
private MockServerInterface $mockServer
) {
}

public function verifyMessage(): bool
{
return $this->mockServer->verify();
}

public function registerMessage(Message $message): void
{
$this->pactDriver->setUp();
$this->messageRegistry->registerMessage($message);

$this->mockServer->start();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

namespace PhpPact\SyncMessage\Driver\Interaction;

use PhpPact\Consumer\Model\Message;

interface SyncMessageDriverInterface
{
public function verifyMessage(): bool;

public function registerMessage(Message $message): void;
}
39 changes: 39 additions & 0 deletions src/PhpPact/SyncMessage/Driver/Pact/AbstractPluginPactDriver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace PhpPact\SyncMessage\Driver\Pact;

use PhpPact\Consumer\Driver\Pact\PactDriver;
use PhpPact\SyncMessage\Exception\PluginNotSupportedBySpecificationException;

abstract class AbstractPluginPactDriver extends PactDriver
{
public function cleanUp(): void
{
$this->client->call('pactffi_cleanup_plugins', $this->pactRegistry->getId());
parent::cleanUp();
}

public function setUp(): void
{
parent::setUp();
$this->usingPlugin();
}

abstract protected function getPluginName(): string;

protected function getPluginVersion(): ?string
{
return null;
}

private function usingPlugin(): self
{
if ($this->getSpecification() < $this->client->get('PactSpecification_V4')) {
throw new PluginNotSupportedBySpecificationException($this->config->getPactSpecificationVersion());
}

$this->client->call('pactffi_using_plugin', $this->pactRegistry->getId(), $this->getPluginName(), $this->getPluginVersion());

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

namespace PhpPact\SyncMessage\Exception;

use Exception;

class InteractionContentNotAddedException extends Exception
{
public function __construct(int $code)
{
$message = match ($code) {
1 => 'A general panic was caught.',
2 => 'The mock server has already been started.',
3 => 'The interaction handle is invalid.',
4 => 'The content type is not valid.',
5 => 'The contents JSON is not valid JSON.',
6 => 'The plugin returned an error.',
default => 'Unknown error',
};
parent::__construct($message, $code);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php

namespace PhpPact\SyncMessage\Exception;

use Exception;

class PluginNotSupportedBySpecificationException extends Exception
{
public function __construct(string $specification)
{
parent::__construct(sprintf(
'Plugin is not supported by specification %s, use 4.0.0 or above',
$specification,
));
}
}
26 changes: 26 additions & 0 deletions src/PhpPact/SyncMessage/Factory/SyncMessageDriverFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace PhpPact\SyncMessage\Factory;

use PhpPact\Consumer\Driver\Pact\PactDriver;
use PhpPact\Consumer\Registry\Pact\PactRegistry;
use PhpPact\Consumer\Service\MockServer;
use PhpPact\FFI\Client;
use PhpPact\SyncMessage\Driver\Interaction\SyncMessageDriver;
use PhpPact\SyncMessage\Driver\Interaction\SyncMessageDriverInterface;
use PhpPact\SyncMessage\Registry\Interaction\SyncMessageRegistry;
use PhpPact\Standalone\MockService\MockServerConfigInterface;

class SyncMessageDriverFactory implements SyncMessageDriverFactoryInterface
{
public function create(MockServerConfigInterface $config): SyncMessageDriverInterface
{
$client = new Client();
$pactRegistry = new PactRegistry($client);
$pactDriver = new PactDriver($client, $config, $pactRegistry);
$messageRegistry = new SyncMessageRegistry($client, $pactRegistry);
$mockServer = new MockServer($client, $pactRegistry, $config);

return new SyncMessageDriver($pactDriver, $messageRegistry, $mockServer);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace PhpPact\SyncMessage\Factory;

use PhpPact\SyncMessage\Driver\Interaction\SyncMessageDriverInterface;
use PhpPact\Standalone\MockService\MockServerConfigInterface;

interface SyncMessageDriverFactoryInterface
{
public function create(MockServerConfigInterface $config): SyncMessageDriverInterface;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace PhpPact\SyncMessage\Registry\Interaction\Contents;

use PhpPact\Consumer\Registry\Interaction\Body\BodyRegistryInterface;
use PhpPact\FFI\ClientInterface;
use PhpPact\SyncMessage\Exception\InteractionContentNotAddedException;

abstract class AbstractContentsRegistry implements BodyRegistryInterface
{
public function __construct(protected ClientInterface $client)
{
}

public function withContents(?string $contentType = null, ?string $contents = null): void
{
if (is_null($contents) || is_null($contentType)) {
// Pact Plugin require content type to be set, or it will panic.
return;
}
$error = $this->client->call('pactffi_interaction_contents', $this->getInteractionId(), $this->getPart(), $contentType, $contents);
if ($error) {
throw new InteractionContentNotAddedException($error);
}
}

abstract protected function getInteractionId(): int;

abstract protected function getPart(): int;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace PhpPact\SyncMessage\Registry\Interaction;

use PhpPact\Consumer\Model\ProviderState;
use PhpPact\Consumer\Registry\Interaction\MessageRegistry;

class SyncMessageRegistry extends MessageRegistry
{
protected function newInteraction(string $description): self
{
$this->id = $this->client->call('pactffi_new_sync_message_interaction', $this->pactRegistry->getId(), $description);

return $this;
}

/**
* @param ProviderState[] $providerStates
*/
protected function given(array $providerStates): self
{
foreach ($providerStates as $providerState) {
$this->client->call('pactffi_given', $this->id, $providerState->getName());
foreach ($providerState->getParams() as $key => $value) {
$this->client->call('pactffi_given_with_param', $this->id, $providerState->getName(), (string) $key, (string) $value);
}
}

return $this;
}
}
30 changes: 30 additions & 0 deletions src/PhpPact/SyncMessage/SyncMessageBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace PhpPact\SyncMessage;

use PhpPact\Consumer\AbstractMessageBuilder;
use PhpPact\SyncMessage\Driver\Interaction\SyncMessageDriverInterface;
use PhpPact\SyncMessage\Factory\SyncMessageDriverFactory;
use PhpPact\SyncMessage\Factory\SyncMessageDriverFactoryInterface;
use PhpPact\Standalone\MockService\MockServerConfigInterface;

class SyncMessageBuilder extends AbstractMessageBuilder
{
private SyncMessageDriverInterface $driver;

public function __construct(MockServerConfigInterface $config, ?SyncMessageDriverFactoryInterface $driverFactory = null)
{
parent::__construct();
$this->driver = ($driverFactory ?? new SyncMessageDriverFactory())->create($config);
}

public function registerMessage(): void
{
$this->driver->registerMessage($this->message);
}

public function verify(): bool
{
return $this->driver->verifyMessage();
}
}