diff --git a/phpunit.xml b/phpunit.xml index 82ce746..1fba752 100644 --- a/phpunit.xml +++ b/phpunit.xml @@ -19,6 +19,9 @@ tests/Unit + + tests/Integration + diff --git a/src/Attribute/Message.php b/src/Attribute/Message.php index 73f8d98..793ceb6 100644 --- a/src/Attribute/Message.php +++ b/src/Attribute/Message.php @@ -17,6 +17,7 @@ public function __construct( public readonly string $name, public array $properties = [], public array $channels = [], + public array $operations = [], ) { } @@ -26,6 +27,7 @@ public function toArray(): array 'name' => $this->name, 'properties' => array_map(static fn(PropertyInterface $property) => $property->toArray(), $this->properties), 'channels' => array_map(static fn(Channel $channel) => $channel->toArray(), $this->channels), + 'operations' => array_map(static fn(Operation $operation) => $operation->toArray(), $this->operations), ]; } @@ -39,6 +41,11 @@ public function addChannel(Channel $channel): void $this->channels[] = $channel; } + public function addOperation(Operation $operation): void + { + $this->operations[] = $operation; + } + public function enrich(self $self): self { // UPDATE EXISTING diff --git a/src/Attribute/Operation.php b/src/Attribute/Operation.php new file mode 100644 index 0000000..f52fcdb --- /dev/null +++ b/src/Attribute/Operation.php @@ -0,0 +1,36 @@ + $this->name, + 'type' => $this->type->value, + 'channels' => array_map( + static fn (Channel $channel) => $channel->toArray(), + $this->channels + ), + ]; + } + + public function addChannel(Channel $channel): void + { + $this->channels[] = $channel; + } +} diff --git a/src/DocumentationStrategy/AttributeDocumentationStrategy.php b/src/DocumentationStrategy/AttributeDocumentationStrategy.php index d3fe12b..9978569 100644 --- a/src/DocumentationStrategy/AttributeDocumentationStrategy.php +++ b/src/DocumentationStrategy/AttributeDocumentationStrategy.php @@ -6,6 +6,7 @@ use Ferror\AsyncapiDocBundle\Attribute\Channel; use Ferror\AsyncapiDocBundle\Attribute\Message; +use Ferror\AsyncapiDocBundle\Attribute\Operation; use ReflectionAttribute; use ReflectionClass; use ReflectionException; @@ -50,6 +51,14 @@ public function document(string $class): Message $message->addChannel($channelAttribute->newInstance()); } + // Channels are optional as it's possible to document just Messages. + /** @var ReflectionAttribute[] $operationAttributes */ + $operationAttributes = $reflection->getAttributes(Operation::class); + + foreach ($operationAttributes as $operationAttribute) { + $message->addOperation($operationAttribute->newInstance()); + } + return $message; } } diff --git a/src/Schema/V3/OperationRenderer.php b/src/Schema/V3/OperationRenderer.php new file mode 100644 index 0000000..ac86384 --- /dev/null +++ b/src/Schema/V3/OperationRenderer.php @@ -0,0 +1,26 @@ + $operation['type'], + 'channel' => [ + '$ref' => '#/channels/' . $channel['name'], + ], + ]; + } + } + + return $operations; + } +} diff --git a/src/Schema/V3/OperationType.php b/src/Schema/V3/OperationType.php new file mode 100644 index 0000000..2f6e302 --- /dev/null +++ b/src/Schema/V3/OperationType.php @@ -0,0 +1,12 @@ +assertEquals($expectedDisplay, $display); } - public function testExecuteYaml(): void + public function testExecuteYamlV2(): void { + if ($this->isV3()) { + $this->markTestSkipped('Skipping schema V2 test on V3 variable'); + } + $kernel = self::bootKernel(); $application = new Application($kernel); @@ -195,6 +199,141 @@ public function testExecuteYaml(): void } } + public function testExecuteYamlV3(): void + { + if (false === $this->isV3()) { + $this->markTestSkipped('Skipping schema V3 test on V2 variable'); + } + + $kernel = self::bootKernel(); + $application = new Application($kernel); + + $command = $application->find('ferror:asyncapi:dump'); + $commandTester = new CommandTester($command); + $commandTester->execute(['format' => 'yaml']); + + $commandTester->assertCommandIsSuccessful(); + + $display = $commandTester->getDisplay(); + + $expectedDisplay = <<assertEquals($expectedDisplay, $display); + + mkdir(dirname(__DIR__) . '/../var/' . $this->getSchemaVersion()); + + $content = file_put_contents(dirname(__DIR__) . '/../var/' . $this->getSchemaVersion() . '/asyncapi.yaml', $display); + + if (false === $content) { + throw new RuntimeException('Schema file was not save'); + } + } + public function testExecuteJson(): void { $kernel = self::bootKernel(); diff --git a/tests/Unit/DocumentationEditorTest.php b/tests/Unit/DocumentationEditorTest.php index b75b995..c08dfac 100644 --- a/tests/Unit/DocumentationEditorTest.php +++ b/tests/Unit/DocumentationEditorTest.php @@ -43,6 +43,7 @@ public function testDocument(): void ], ], 'channels' => [], + 'operations' => [], ]; $this->assertEquals($expected, $actual); diff --git a/tests/Unit/DocumentationStrategy/AttributeDocumentationStrategyTest.php b/tests/Unit/DocumentationStrategy/AttributeDocumentationStrategyTest.php index 3f723da..6e00d7c 100644 --- a/tests/Unit/DocumentationStrategy/AttributeDocumentationStrategyTest.php +++ b/tests/Unit/DocumentationStrategy/AttributeDocumentationStrategyTest.php @@ -60,6 +60,7 @@ public function testUserSignedUp(): void 'type' => 'subscribe', ], ], + 'operations' => [], ]; $this->assertEquals($expected, $actual); @@ -154,6 +155,7 @@ public function testProductCreated(): void 'type' => 'subscribe', ], ], + 'operations' => [], ]; $this->assertEquals($expected, $actual); diff --git a/tests/Unit/DocumentationStrategy/ReflectionDocumentationStrategyTest.php b/tests/Unit/DocumentationStrategy/ReflectionDocumentationStrategyTest.php index daf47b6..5c18bc2 100644 --- a/tests/Unit/DocumentationStrategy/ReflectionDocumentationStrategyTest.php +++ b/tests/Unit/DocumentationStrategy/ReflectionDocumentationStrategyTest.php @@ -52,6 +52,7 @@ public function test(): void ], ], 'channels' => [], + 'operations' => [], ]; $this->assertEquals($expected, $documentation->document(UserSignedUp::class)->toArray()); @@ -98,9 +99,9 @@ public function testEnum(): void ], ], 'channels' => [], + 'operations' => [], ]; - $actual = $documentation->document(ProductCreated::class)->toArray(); $this->assertEquals($expected, $actual); diff --git a/tests/Unit/Schema/V3/OperationRendererTest.php b/tests/Unit/Schema/V3/OperationRendererTest.php new file mode 100644 index 0000000..ddc835f --- /dev/null +++ b/tests/Unit/Schema/V3/OperationRendererTest.php @@ -0,0 +1,82 @@ + 'UserSignedUp', + 'properties' => [], + 'operations' => [ + [ + 'name' => 'UserSignedUpOperation', + 'type' => 'send', + 'channels' => [ + [ + 'name' => 'UserSignedUpChannel', + 'type' => 'subscribe', + ] + ], + ] + ], + ]; + + $actual = $renderer->render($document); + + $expected = [ + 'UserSignedUpOperation' => [ + 'action' => 'send', + 'channel' => [ + '$ref' => '#/channels/UserSignedUpChannel', + ] + ] + ]; + + $this->assertEquals($expected, $actual); + } + + public function testItRendersReceiveAction(): void + { + $renderer = new OperationRenderer(); + + $document = [ + 'name' => 'UserSignedUp', + 'properties' => [], + 'operations' => [ + [ + 'name' => 'UserSignedUpOperation', + 'type' => 'receive', + 'channels' => [ + [ + 'name' => 'UserSignedUpChannel', + 'type' => 'subscribe', + ] + ], + ] + ], + ]; + + $actual = $renderer->render($document); + + $expected = [ + 'UserSignedUpOperation' => [ + 'action' => 'receive', + 'channel' => [ + '$ref' => '#/channels/UserSignedUpChannel', + ] + ] + ]; + + $this->assertEquals($expected, $actual); + } +}