From 7dbcad5226f62bfd69ef5dc2ae23aa67f04f96bb Mon Sep 17 00:00:00 2001 From: "tien.xuan.vo" Date: Thu, 26 Sep 2024 15:24:24 +0700 Subject: [PATCH] refactor: Wrap ffi call > set interaction attributes methods --- helper/FFI/ClientTrait.php | 85 +++++++++++++++++++ .../Driver/Interaction/AbstractDriver.php | 11 ++- src/PhpPact/FFI/Client.php | 40 +++++++++ src/PhpPact/FFI/ClientInterface.php | 8 ++ .../Interaction/InteractionDriverTest.php | 43 +++------- .../Driver/Interaction/MessageDriverTest.php | 43 +++------- tests/PhpPact/FFI/ClientTest.php | 24 ++++++ .../Interaction/SyncMessageDriverTest.php | 43 +++------- 8 files changed, 203 insertions(+), 94 deletions(-) diff --git a/helper/FFI/ClientTrait.php b/helper/FFI/ClientTrait.php index 0bf0ed55..e759ef97 100644 --- a/helper/FFI/ClientTrait.php +++ b/helper/FFI/ClientTrait.php @@ -2,6 +2,9 @@ namespace PhpPactTest\Helper\FFI; +use PhpPact\Consumer\Driver\Exception\InteractionCommentNotSetException; +use PhpPact\Consumer\Driver\Exception\InteractionKeyNotSetException; +use PhpPact\Consumer\Driver\Exception\InteractionPendingNotSetException; use PhpPact\FFI\ClientInterface; use PHPUnit\Framework\Constraint\Constraint; use PHPUnit\Framework\Constraint\IsIdentical; @@ -29,4 +32,86 @@ protected function assertClientCalls(array $calls): void return $return; }); } + + protected function expectsSetInteractionKey(int $interaction, string $description, ?string $key, bool $result): void + { + $this->client + ->expects($this->exactly($key === null ? 0 : 1)) + ->method('setKey') + ->with($interaction, $key) + ->willReturn($result); + if (!$result) { + $this->expectException(InteractionKeyNotSetException::class); + $this->expectExceptionMessage("Can not set the key '$key' for the interaction '{$description}'"); + } + } + + protected function expectsSetInteractionPending(int $interaction, string $description, ?bool $pending, bool $result): void + { + $this->client + ->expects($this->exactly($pending === null ? 0 : 1)) + ->method('setPending') + ->with($interaction, $pending) + ->willReturn($result); + if (!$result) { + $this->expectException(InteractionPendingNotSetException::class); + $this->expectExceptionMessage("Can not mark interaction '{$description}' as pending"); + } + } + + /** + * @param array $comments + */ + protected function expectsSetComments(int $interaction, string $description, array $comments, bool $result): void + { + $calls = []; + $lastKey = array_key_last($comments); + foreach ($comments as $key => $value) { + $calls[] = [$interaction, $key, (is_string($value) || is_null($value)) ? $value : json_encode($value), $key === $lastKey ? $result : true]; + } + $this->client + ->expects($this->exactly(count($calls))) + ->method('setComment') + ->willReturnCallback(function (...$args) use (&$calls) { + $call = array_shift($calls); + $return = array_pop($call); + foreach ($args as $key => $arg) { + $this->assertThat($arg, $call[$key] instanceof Constraint ? $call[$key] : new IsIdentical($call[$key])); + } + + return $return; + }); + if (!$result) { + $this->expectException(InteractionCommentNotSetException::class); + $this->expectExceptionMessage("Can not add comment '$key' to the interaction '{$description}'"); + } + } + + /** + * @param string[] $comments + */ + protected function expectsAddTextComments(int $interaction, string $description, array $comments, bool $result): void + { + $calls = []; + $lastKey = array_key_last($comments); + foreach ($comments as $key => $comment) { + $calls[] = [$interaction, $comment, $key === $lastKey ? $result : true]; + } + $this->client + ->expects($this->exactly(count($calls))) + ->method('addTextComment') + ->willReturnCallback(function (...$args) use (&$calls) { + $call = array_shift($calls); + $return = array_pop($call); + foreach ($args as $key => $arg) { + $this->assertThat($arg, $call[$key] instanceof Constraint ? $call[$key] : new IsIdentical($call[$key])); + } + + return $return; + }); + if (!$result) { + $this->expectException(InteractionCommentNotSetException::class); + $this->expectExceptionMessage("Can not add text comment '$comment' to the interaction '{$description}'"); + } + } } diff --git a/src/PhpPact/Consumer/Driver/Interaction/AbstractDriver.php b/src/PhpPact/Consumer/Driver/Interaction/AbstractDriver.php index 0347ebb0..e6226064 100644 --- a/src/PhpPact/Consumer/Driver/Interaction/AbstractDriver.php +++ b/src/PhpPact/Consumer/Driver/Interaction/AbstractDriver.php @@ -22,7 +22,7 @@ protected function setKey(Interaction|Message $interaction): void if (null === $key) { return; } - $success = $this->client->call('pactffi_set_key', $interaction->getHandle(), $key); + $success = $this->client->setKey($interaction->getHandle(), $key); if (!$success) { throw new InteractionKeyNotSetException(sprintf("Can not set the key '%s' for the interaction '%s'", $key, $interaction->getDescription())); } @@ -34,7 +34,7 @@ protected function setPending(Interaction|Message $interaction): void if (null === $pending) { return; } - $success = $this->client->call('pactffi_set_pending', $interaction->getHandle(), $pending); + $success = $this->client->setPending($interaction->getHandle(), $pending); if (!$success) { throw new InteractionPendingNotSetException(sprintf("Can not mark interaction '%s' as pending", $interaction->getDescription())); } @@ -44,13 +44,16 @@ protected function setComments(Interaction|Message $interaction): void { foreach ($interaction->getComments() as $key => $value) { $value = (is_string($value) || is_null($value)) ? $value : json_encode($value); - $success = $this->client->call('pactffi_set_comment', $interaction->getHandle(), $key, $value); + if (is_bool($value)) { + throw new InteractionCommentNotSetException(sprintf("Can not json encode value of comment '%s'", $key)); + } + $success = $this->client->setComment($interaction->getHandle(), $key, $value); if (!$success) { throw new InteractionCommentNotSetException(sprintf("Can not add comment '%s' to the interaction '%s'", $key, $interaction->getDescription())); } } foreach ($interaction->getTextComments() as $value) { - $success = $this->client->call('pactffi_add_text_comment', $interaction->getHandle(), $value); + $success = $this->client->addTextComment($interaction->getHandle(), $value); if (!$success) { throw new InteractionCommentNotSetException(sprintf("Can not add text comment '%s' to the interaction '%s'", $value, $interaction->getDescription())); } diff --git a/src/PhpPact/FFI/Client.php b/src/PhpPact/FFI/Client.php index 59d0e856..0a64c3f2 100644 --- a/src/PhpPact/FFI/Client.php +++ b/src/PhpPact/FFI/Client.php @@ -61,6 +61,46 @@ public function withMultipartFileV2(int $interaction, int $part, string $content throw new InvalidResultException(sprintf('Invalid result of "%s". Neither ok or failed', $method)); } + public function setKey(int $interaction, string $key): bool + { + $method = 'pactffi_set_key'; + $result = $this->call($method, $interaction, $key); + if (!is_bool($result)) { + throw new InvalidResultException(sprintf('Invalid result of "%s". Expected "boolean", but got "%s"', $method, get_debug_type($result))); + } + return $result; + } + + public function setPending(int $interaction, bool $pending): bool + { + $method = 'pactffi_set_pending'; + $result = $this->call($method, $interaction, $pending); + if (!is_bool($result)) { + throw new InvalidResultException(sprintf('Invalid result of "%s". Expected "boolean", but got "%s"', $method, get_debug_type($result))); + } + return $result; + } + + public function setComment(int $interaction, string $key, ?string $value): bool + { + $method = 'pactffi_set_comment'; + $result = $this->call($method, $interaction, $key, $value); + if (!is_bool($result)) { + throw new InvalidResultException(sprintf('Invalid result of "%s". Expected "boolean", but got "%s"', $method, get_debug_type($result))); + } + return $result; + } + + public function addTextComment(int $interaction, string $value): bool + { + $method = 'pactffi_add_text_comment'; + $result = $this->call($method, $interaction, $value); + if (!is_bool($result)) { + throw new InvalidResultException(sprintf('Invalid result of "%s". Expected "boolean", but got "%s"', $method, get_debug_type($result))); + } + return $result; + } + public function getInteractionPartRequest(): int { return $this->getEnum('InteractionPart_Request'); diff --git a/src/PhpPact/FFI/ClientInterface.php b/src/PhpPact/FFI/ClientInterface.php index 2c5105db..f454dc08 100644 --- a/src/PhpPact/FFI/ClientInterface.php +++ b/src/PhpPact/FFI/ClientInterface.php @@ -13,6 +13,14 @@ public function withBody(int $interaction, int $part, string $contentType, strin public function withMultipartFileV2(int $interaction, int $part, string $contentType, string $path, string $name, string $boundary): Result; + public function setKey(int $interaction, string $key): bool; + + public function setPending(int $interaction, bool $pending): bool; + + public function setComment(int $interaction, string $key, ?string $value): bool; + + public function addTextComment(int $interaction, string $value): bool; + public function getInteractionPartRequest(): int; public function getInteractionPartResponse(): int; diff --git a/tests/PhpPact/Consumer/Driver/Interaction/InteractionDriverTest.php b/tests/PhpPact/Consumer/Driver/Interaction/InteractionDriverTest.php index 12dba255..8ca2af31 100644 --- a/tests/PhpPact/Consumer/Driver/Interaction/InteractionDriverTest.php +++ b/tests/PhpPact/Consumer/Driver/Interaction/InteractionDriverTest.php @@ -128,13 +128,7 @@ public function testSetKey(?string $key, bool $success): void ['pactffi_given_with_param', $this->interactionHandle, 'item exist', 'name', 'abc', null], ['pactffi_upon_receiving', $this->interactionHandle, $this->description, null], ]; - if (is_string($key)) { - $calls[] = ['pactffi_set_key', $this->interactionHandle, $key, $success]; - } - if (!$success) { - $this->expectException(InteractionKeyNotSetException::class); - $this->expectExceptionMessage("Can not set the key '$key' for the interaction '{$this->description}'"); - } + $this->expectsSetInteractionKey($this->interactionHandle, $this->description, $key, $success); $this->assertClientCalls($calls); $this->driver->registerInteraction($this->interaction, false); } @@ -159,13 +153,7 @@ public function testSetPending(?bool $pending, bool $success): void ['pactffi_given_with_param', $this->interactionHandle, 'item exist', 'name', 'abc', null], ['pactffi_upon_receiving', $this->interactionHandle, $this->description, null], ]; - if (is_bool($pending)) { - $calls[] = ['pactffi_set_pending', $this->interactionHandle, $pending, $success]; - } - if (!$success) { - $this->expectException(InteractionPendingNotSetException::class); - $this->expectExceptionMessage("Can not mark interaction '{$this->description}' as pending"); - } + $this->expectsSetInteractionPending($this->interactionHandle, $this->description, $pending, $success); $this->assertClientCalls($calls); $this->driver->registerInteraction($this->interaction, false); } @@ -194,22 +182,21 @@ public function testSetComments(array $comments, bool $success): void ['pactffi_given_with_param', $this->interactionHandle, 'item exist', 'name', 'abc', null], ['pactffi_upon_receiving', $this->interactionHandle, $this->description, null], ]; - foreach ($comments as $key => $value) { - $calls[] = ['pactffi_set_comment', $this->interactionHandle, $key, (is_string($value) || is_null($value)) ? $value : json_encode($value), $success]; - if (!$success) { - $this->expectException(InteractionCommentNotSetException::class); - $this->expectExceptionMessage("Can not add comment '$key' to the interaction '{$this->description}'"); - } - } + $this->expectsSetComments($this->interactionHandle, $this->description, $comments, $success); $this->assertClientCalls($calls); $this->driver->registerInteraction($this->interaction, false); } - #[TestWith(['comment 1', false])] - #[TestWith(['comment 2', true])] - public function testAddTextComment(string $comment, bool $success): void + /** + * @param string[] $comments + */ + #[TestWith([['comment 1', 'comment 2'], false])] + #[TestWith([['comment 1', 'comment 2'], true])] + public function testAddTextComment(array $comments, bool $success): void { - $this->interaction->addTextComment($comment); + foreach ($comments as $comment) { + $this->interaction->addTextComment($comment); + } $this->pactDriver ->expects($this->once()) ->method('getPact') @@ -220,12 +207,8 @@ public function testAddTextComment(string $comment, bool $success): void ['pactffi_given_with_param', $this->interactionHandle, 'item exist', 'id', '12', null], ['pactffi_given_with_param', $this->interactionHandle, 'item exist', 'name', 'abc', null], ['pactffi_upon_receiving', $this->interactionHandle, $this->description, null], - ['pactffi_add_text_comment', $this->interactionHandle, $comment, $success], ]; - if (!$success) { - $this->expectException(InteractionCommentNotSetException::class); - $this->expectExceptionMessage("Can not add text comment '$comment' to the interaction '{$this->description}'"); - } + $this->expectsAddTextComments($this->interactionHandle, $this->description, $comments, $success); $this->assertClientCalls($calls); $this->driver->registerInteraction($this->interaction, false); } diff --git a/tests/PhpPact/Consumer/Driver/Interaction/MessageDriverTest.php b/tests/PhpPact/Consumer/Driver/Interaction/MessageDriverTest.php index 9f8a0238..e7608ed5 100644 --- a/tests/PhpPact/Consumer/Driver/Interaction/MessageDriverTest.php +++ b/tests/PhpPact/Consumer/Driver/Interaction/MessageDriverTest.php @@ -126,13 +126,7 @@ public function testSetKey(?string $key, bool $success): void ['pactffi_message_with_metadata_v2', $this->messageHandle, 'key1', 'value1', null], ['pactffi_message_with_metadata_v2', $this->messageHandle, 'key2', 'value2', null], ]; - if (is_string($key)) { - $calls[] = ['pactffi_set_key', $this->messageHandle, $key, $success]; - } - if (!$success) { - $this->expectException(InteractionKeyNotSetException::class); - $this->expectExceptionMessage("Can not set the key '$key' for the interaction '{$this->description}'"); - } + $this->expectsSetInteractionKey($this->messageHandle, $this->description, $key, $success); $this->assertClientCalls($calls); $this->driver->registerMessage($this->message); } @@ -159,13 +153,7 @@ public function testSetPending(?bool $pending, bool $success): void ['pactffi_message_with_metadata_v2', $this->messageHandle, 'key1', 'value1', null], ['pactffi_message_with_metadata_v2', $this->messageHandle, 'key2', 'value2', null], ]; - if (is_bool($pending)) { - $calls[] = ['pactffi_set_pending', $this->messageHandle, $pending, $success]; - } - if (!$success) { - $this->expectException(InteractionPendingNotSetException::class); - $this->expectExceptionMessage("Can not mark interaction '{$this->description}' as pending"); - } + $this->expectsSetInteractionPending($this->messageHandle, $this->description, $pending, $success); $this->assertClientCalls($calls); $this->driver->registerMessage($this->message); } @@ -196,22 +184,21 @@ public function testSetComments(array $comments, bool $success): void ['pactffi_message_with_metadata_v2', $this->messageHandle, 'key1', 'value1', null], ['pactffi_message_with_metadata_v2', $this->messageHandle, 'key2', 'value2', null], ]; - foreach ($comments as $key => $value) { - $calls[] = ['pactffi_set_comment', $this->messageHandle, $key, (is_string($value) || is_null($value)) ? $value : json_encode($value), $success]; - if (!$success) { - $this->expectException(InteractionCommentNotSetException::class); - $this->expectExceptionMessage("Can not add comment '$key' to the interaction '{$this->description}'"); - } - } + $this->expectsSetComments($this->messageHandle, $this->description, $comments, $success); $this->assertClientCalls($calls); $this->driver->registerMessage($this->message); } - #[TestWith(['comment 1', false])] - #[TestWith(['comment 2', true])] - public function testAddTextComment(string $comment, bool $success): void + /** + * @param string[] $comments + */ + #[TestWith([['comment 1', 'comment 2'], false])] + #[TestWith([['comment 1', 'comment 2'], true])] + public function testAddTextComment(array $comments, bool $success): void { - $this->message->addTextComment($comment); + foreach ($comments as $comment) { + $this->message->addTextComment($comment); + } $this->pactDriver ->expects($this->once()) ->method('getPact') @@ -224,12 +211,8 @@ public function testAddTextComment(string $comment, bool $success): void ['pactffi_message_expects_to_receive', $this->messageHandle, $this->description, null], ['pactffi_message_with_metadata_v2', $this->messageHandle, 'key1', 'value1', null], ['pactffi_message_with_metadata_v2', $this->messageHandle, 'key2', 'value2', null], - ['pactffi_add_text_comment', $this->messageHandle, $comment, $success], ]; - if (!$success) { - $this->expectException(InteractionCommentNotSetException::class); - $this->expectExceptionMessage("Can not add text comment '$comment' to the interaction '{$this->description}'"); - } + $this->expectsAddTextComments($this->messageHandle, $this->description, $comments, $success); $this->assertClientCalls($calls); $this->driver->registerMessage($this->message); } diff --git a/tests/PhpPact/FFI/ClientTest.php b/tests/PhpPact/FFI/ClientTest.php index d8cfc7a2..8e22f313 100644 --- a/tests/PhpPact/FFI/ClientTest.php +++ b/tests/PhpPact/FFI/ClientTest.php @@ -36,6 +36,30 @@ public function testWithMultipartFileV2(): void $this->assertSame('with_multipart_file: Interaction handle is invalid', $result->message); } + public function testSetKey(): void + { + $result = $this->client->setKey(1, 'test'); + $this->assertFalse($result); + } + + public function testSetPending(): void + { + $result = $this->client->setPending(1, true); + $this->assertFalse($result); + } + + public function testSetComment(): void + { + $result = $this->client->setComment(1, 'key', 'value'); + $this->assertFalse($result); + } + + public function testAddTextComment(): void + { + $result = $this->client->addTextComment(1, 'test'); + $this->assertFalse($result); + } + public function testGetInteractionPartRequest(): void { $this->assertSame(0, $this->client->getInteractionPartRequest()); diff --git a/tests/PhpPact/SyncMessage/Driver/Interaction/SyncMessageDriverTest.php b/tests/PhpPact/SyncMessage/Driver/Interaction/SyncMessageDriverTest.php index 3c2ffc68..fde2fe65 100644 --- a/tests/PhpPact/SyncMessage/Driver/Interaction/SyncMessageDriverTest.php +++ b/tests/PhpPact/SyncMessage/Driver/Interaction/SyncMessageDriverTest.php @@ -128,13 +128,7 @@ public function testSetKey(?string $key, bool $success): void ['pactffi_message_with_metadata_v2', $this->messageHandle, 'key1', 'value1', null], ['pactffi_message_with_metadata_v2', $this->messageHandle, 'key2', 'value2', null], ]; - if (is_string($key)) { - $calls[] = ['pactffi_set_key', $this->messageHandle, $key, $success]; - } - if (!$success) { - $this->expectException(InteractionKeyNotSetException::class); - $this->expectExceptionMessage("Can not set the key '$key' for the interaction '{$this->description}'"); - } + $this->expectsSetInteractionKey($this->messageHandle, $this->description, $key, $success); $this->assertClientCalls($calls); $this->driver->registerMessage($this->message); } @@ -161,13 +155,7 @@ public function testSetPending(?bool $pending, bool $success): void ['pactffi_message_with_metadata_v2', $this->messageHandle, 'key1', 'value1', null], ['pactffi_message_with_metadata_v2', $this->messageHandle, 'key2', 'value2', null], ]; - if (is_bool($pending)) { - $calls[] = ['pactffi_set_pending', $this->messageHandle, $pending, $success]; - } - if (!$success) { - $this->expectException(InteractionPendingNotSetException::class); - $this->expectExceptionMessage("Can not mark interaction '{$this->description}' as pending"); - } + $this->expectsSetInteractionPending($this->messageHandle, $this->description, $pending, $success); $this->assertClientCalls($calls); $this->driver->registerMessage($this->message); } @@ -198,22 +186,21 @@ public function testSetComments(array $comments, bool $success): void ['pactffi_message_with_metadata_v2', $this->messageHandle, 'key1', 'value1', null], ['pactffi_message_with_metadata_v2', $this->messageHandle, 'key2', 'value2', null], ]; - foreach ($comments as $key => $value) { - $calls[] = ['pactffi_set_comment', $this->messageHandle, $key, (is_string($value) || is_null($value)) ? $value : json_encode($value), $success]; - if (!$success) { - $this->expectException(InteractionCommentNotSetException::class); - $this->expectExceptionMessage("Can not add comment '$key' to the interaction '{$this->description}'"); - } - } + $this->expectsSetComments($this->messageHandle, $this->description, $comments, $success); $this->assertClientCalls($calls); $this->driver->registerMessage($this->message); } - #[TestWith(['comment 1', false])] - #[TestWith(['comment 2', true])] - public function testAddTextComment(string $comment, bool $success): void + /** + * @param string[] $comments + */ + #[TestWith([['comment 1', 'comment 2'], false])] + #[TestWith([['comment 1', 'comment 2'], true])] + public function testAddTextComment(array $comments, bool $success): void { - $this->message->addTextComment($comment); + foreach ($comments as $comment) { + $this->message->addTextComment($comment); + } $this->pactDriver ->expects($this->once()) ->method('getPact') @@ -226,12 +213,8 @@ public function testAddTextComment(string $comment, bool $success): void ['pactffi_message_expects_to_receive', $this->messageHandle, $this->description, null], ['pactffi_message_with_metadata_v2', $this->messageHandle, 'key1', 'value1', null], ['pactffi_message_with_metadata_v2', $this->messageHandle, 'key2', 'value2', null], - ['pactffi_add_text_comment', $this->messageHandle, $comment, $success], ]; - if (!$success) { - $this->expectException(InteractionCommentNotSetException::class); - $this->expectExceptionMessage("Can not add text comment '$comment' to the interaction '{$this->description}'"); - } + $this->expectsAddTextComments($this->messageHandle, $this->description, $comments, $success); $this->assertClientCalls($calls); $this->driver->registerMessage($this->message); }