From 2d14ab28cc1ca6af69d7cc4bc28836d2847d53ad Mon Sep 17 00:00:00 2001 From: Pavel Buchnev Date: Thu, 9 Dec 2021 12:41:12 +0300 Subject: [PATCH] Refactors tests (#7) * Refactors tests - Adds tests for typecast handler - Adds tests for macros - Adds tests for relations - Adds tests for STI - Adds tests for JTI * Apply fixes from StyleCI * Fixes CS * Added tests for cycle/orm v2 * Added schema constants via ConstantsInterface * Fixes tests for CycleORM v1 and v2. * Adds missed test * Renames discriminator column property name * Fixes tests Co-authored-by: Aleksei Gagarin --- .github/workflows/main-v2.yml | 68 +++++ .github/workflows/main.yml | 4 +- .styleci.yml | 2 + .../Renderer/ColumnsRenderer.php | 10 +- .../Renderer/CustomPropertiesRenderer.php | 29 +- src/ConsoleRenderer/Renderer/KeysRenderer.php | 2 +- .../Renderer/MacrosRenderer.php | 45 ++- .../Renderer/PropertyRenderer.php | 14 +- .../Renderer/RelationsRenderer.php | 27 +- .../Renderer/TitleRenderer.php | 2 +- src/ConstantsInterface.php | 13 + src/OutputSchemaRenderer.php | 33 +-- src/SchemaConstants.php | 18 ++ src/SchemaToArrayConverter.php | 22 +- tests/Schema/Renderer/BaseTest.php | 27 ++ .../ConsoleRenderer/OutputRendererTest.php | 4 +- .../Renderer/ColumnsRendererTest.php | 4 +- .../Renderer/CustomPropertiesRendererTest.php | 56 ++++ .../Renderer/KeysRendererTest.php | 4 +- .../Renderer/MacrosRendererTest.php | 96 ++++++ .../Renderer/PropertyRendererTest.php | 4 +- .../Renderer/RelationsRendererTest.php | 277 ++++++++++++++++++ .../Renderer/TitleRendererTest.php | 4 +- tests/Schema/Renderer/Fixture/Admin.php | 9 + tests/Schema/Renderer/Fixture/Guest.php | 9 + .../Renderer/Fixture/console_output.stub.txt | 4 +- .../Fixture/console_output_plain.stub.txt | 27 +- ...ole_output_with_custom_properties.stub.txt | 4 +- .../Fixture/generated_schema_v2.stub.php | 82 ++++++ .../CommonTest.php} | 18 +- .../JoinedTableInheritanceTest.php | 64 ++++ .../OutputSchemaRenderer/MacrosTest.php | 171 +++++++++++ .../SingleTableInheritanceTest.php | 114 +++++++ .../TypecastHandlerTest.php | 111 +++++++ .../Schema/Renderer/PhpSchemaRendererTest.php | 11 +- .../CycleOrmV1Test.php} | 14 +- .../SchemaToArrayConverter/CycleOrmV2Test.php | 111 +++++++ 37 files changed, 1386 insertions(+), 128 deletions(-) create mode 100644 .github/workflows/main-v2.yml create mode 100644 src/ConstantsInterface.php create mode 100644 src/SchemaConstants.php create mode 100644 tests/Schema/Renderer/BaseTest.php create mode 100644 tests/Schema/Renderer/ConsoleRenderer/Renderer/CustomPropertiesRendererTest.php create mode 100644 tests/Schema/Renderer/ConsoleRenderer/Renderer/MacrosRendererTest.php create mode 100644 tests/Schema/Renderer/ConsoleRenderer/Renderer/RelationsRendererTest.php create mode 100644 tests/Schema/Renderer/Fixture/Admin.php create mode 100644 tests/Schema/Renderer/Fixture/Guest.php create mode 100644 tests/Schema/Renderer/Fixture/generated_schema_v2.stub.php rename tests/Schema/Renderer/{OutputSchemaRendererTest.php => OutputSchemaRenderer/CommonTest.php} (87%) create mode 100644 tests/Schema/Renderer/OutputSchemaRenderer/JoinedTableInheritanceTest.php create mode 100644 tests/Schema/Renderer/OutputSchemaRenderer/MacrosTest.php create mode 100644 tests/Schema/Renderer/OutputSchemaRenderer/SingleTableInheritanceTest.php create mode 100644 tests/Schema/Renderer/OutputSchemaRenderer/TypecastHandlerTest.php rename tests/Schema/Renderer/{SchemaToArrayConverterTest.php => SchemaToArrayConverter/CycleOrmV1Test.php} (95%) create mode 100644 tests/Schema/Renderer/SchemaToArrayConverter/CycleOrmV2Test.php diff --git a/.github/workflows/main-v2.yml b/.github/workflows/main-v2.yml new file mode 100644 index 0000000..19b384d --- /dev/null +++ b/.github/workflows/main-v2.yml @@ -0,0 +1,68 @@ +name: build-v2 + +on: + push: + pull_request: + schedule: + - cron: '0 0 * * *' + +jobs: + test: + name: Build (${{matrix.php}}, ${{ matrix.os }}, ${{ matrix.stability }}) + runs-on: ${{ matrix.os }} + + strategy: + fail-fast: false + matrix: + php: [ '8.0', '8.1' ] + os: [ ubuntu-latest ] + stability: [ prefer-lowest, prefer-stable ] + + steps: + - name: Set Git To Use LF + run: | + git config --global core.autocrlf false + git config --global core.eol lf + - name: Checkout + uses: actions/checkout@v2 + + # Install PHP Dependencies + - name: Setup PHP ${{ matrix.php }} + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + # PHP Extras + extensions: pdo, pdo_mysql, pdo_sqlite, sockets + coverage: pcov + tools: pecl + ini-values: "memory_limit=-1" + - name: Validate Composer + run: composer validate + - name: Get Composer Cache Directory + # Docs: + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + - name: Restore Composer Cache + uses: actions/cache@v2 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-${{ matrix.php }}-${{ matrix.stability }}-composer-${{ hashFiles('**/composer.json') }} + restore-keys: ${{ runner.os }}-${{ matrix.php }}-composer- + + - name: Install dependencies with composer + if: matrix.php-version != '8.1' + run: composer update --with cycle/orm:2.0.x-dev --${{ matrix.stability }} --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi + + - name: Install dependencies with composer php 8.1 + if: matrix.php-version == '8.1' + run: composer update --with cycle/orm:2.0.x-dev --${{ matrix.stability }} --prefer-dist --no-interaction --no-progress --optimize-autoloader --ansi --ignore-platform-reqs + + # Execution + - name: Execute Tests + run: vendor/bin/phpunit --coverage-clover=coverage.xml + - name: Upload Coverage To Codecov + uses: codecov/codecov-action@v1 + with: + token: ${{ secrets.CODECOV_TOKEN }} + file: ./coverage.xml + fail_ci_if_error: false diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c87aec8..3d8e875 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,4 +1,4 @@ -name: build +name: build-v1 on: push: @@ -46,7 +46,7 @@ jobs: uses: actions/cache@v2 with: path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-${{ matrix.php }}-composer-${{ hashFiles('**/composer.json') }} + key: ${{ runner.os }}-${{ matrix.php }}-${{ matrix.stability }}-composer-${{ hashFiles('**/composer.json') }} restore-keys: ${{ runner.os }}-${{ matrix.php }}-composer- - name: Install dependencies with composer diff --git a/.styleci.yml b/.styleci.yml index 4fe219f..dd8ece2 100644 --- a/.styleci.yml +++ b/.styleci.yml @@ -4,6 +4,8 @@ risky: true version: 7 finder: + exclude: + - "tests" not-name: - "*.stub.txt" diff --git a/src/ConsoleRenderer/Renderer/ColumnsRenderer.php b/src/ConsoleRenderer/Renderer/ColumnsRenderer.php index 4322e94..5f57667 100644 --- a/src/ConsoleRenderer/Renderer/ColumnsRenderer.php +++ b/src/ConsoleRenderer/Renderer/ColumnsRenderer.php @@ -15,9 +15,9 @@ public function render(Formatter $formatter, array $schema, string $role): ?stri $rows = []; $columns = $schema[SchemaInterface::COLUMNS] ?? []; - $title = sprintf('%s:', $formatter->title('Fields')); + $title = \sprintf('%s:', $formatter->title('Fields')); - if (! \is_array($columns) || count($columns) === 0) { + if (! \is_array($columns) || \count($columns) === 0) { return $title . ' ' . $formatter->error('not defined'); } @@ -25,7 +25,7 @@ public function render(Formatter $formatter, array $schema, string $role): ?stri $rows[] = $title; - $rows[] = sprintf( + $rows[] = \sprintf( '%s(%s -> %s -> %s)', $padding, $formatter->property('property'), @@ -37,7 +37,7 @@ public function render(Formatter $formatter, array $schema, string $role): ?stri foreach ($columns as $property => $field) { $typecast = $types[$property] ?? $types[$field] ?? null; - $row = sprintf( + $row = \sprintf( '%s%s -> %s', $padding, $formatter->property((string)$property), @@ -45,7 +45,7 @@ public function render(Formatter $formatter, array $schema, string $role): ?stri ); if ($typecast !== null && $typecast !== [] && $typecast !== '') { - $row .= sprintf( + $row .= \sprintf( ' -> %s', $formatter->typecast(\implode('::', (array)$typecast)) ); diff --git a/src/ConsoleRenderer/Renderer/CustomPropertiesRenderer.php b/src/ConsoleRenderer/Renderer/CustomPropertiesRenderer.php index fb15dfc..e4339cb 100644 --- a/src/ConsoleRenderer/Renderer/CustomPropertiesRenderer.php +++ b/src/ConsoleRenderer/Renderer/CustomPropertiesRenderer.php @@ -12,7 +12,7 @@ class CustomPropertiesRenderer implements Renderer private array $exclude; /** - * @param array $exclude Values list that should be excluded + * @param array $exclude Values list that should be excluded */ public function __construct(array $exclude) { @@ -21,26 +21,43 @@ public function __construct(array $exclude) public function render(Formatter $formatter, array $schema, string $role): ?string { - $customProperties = array_diff(array_keys($schema), $this->exclude); + $customProperties = \array_diff(\array_keys($schema), $this->exclude); if ($customProperties === []) { return null; } $rows = [ - sprintf('%s:', $formatter->title('Custom props')), + \sprintf('%s:', $formatter->title('Custom props')), ]; foreach ($customProperties as $property) { $data = $schema[$property] ?? null; - $rows[] = sprintf( - ' %s: %s', + $rows[] = \sprintf( + '%s%s: %s', + $formatter->title(' '), $property, - $formatter->typecast(print_r($data, true)) + $formatter->typecast($this->printValue($data, $formatter)) ); } return \implode($formatter::LINE_SEPARATOR, $rows); } + + /** + * @param mixed $value + */ + private function printValue($value, Formatter $formatter): string + { + $data = \trim(\var_export($value, true), '\''); + $data = \array_map( + static fn (string $row): string => $formatter->title(' ') . $row, + \explode("\n", $data) + ); + + return \ltrim( + \implode("\n", $data) + ); + } } diff --git a/src/ConsoleRenderer/Renderer/KeysRenderer.php b/src/ConsoleRenderer/Renderer/KeysRenderer.php index f8a5c73..7af3226 100644 --- a/src/ConsoleRenderer/Renderer/KeysRenderer.php +++ b/src/ConsoleRenderer/Renderer/KeysRenderer.php @@ -28,7 +28,7 @@ public function render(Formatter $formatter, array $schema, string $role): ?stri { $keys = $schema[$this->key] ?? null; - $row = sprintf('%s: ', $formatter->title($this->title)); + $row = \sprintf('%s: ', $formatter->title($this->title)); if ($keys === null || $keys === '' || $keys === []) { return $this->required ? $row . $formatter->error('not defined') : null; diff --git a/src/ConsoleRenderer/Renderer/MacrosRenderer.php b/src/ConsoleRenderer/Renderer/MacrosRenderer.php index 19c3ff0..7f18572 100644 --- a/src/ConsoleRenderer/Renderer/MacrosRenderer.php +++ b/src/ConsoleRenderer/Renderer/MacrosRenderer.php @@ -4,25 +4,34 @@ namespace Cycle\Schema\Renderer\ConsoleRenderer\Renderer; -use Cycle\ORM\SchemaInterface; use Cycle\Schema\Renderer\ConsoleRenderer\Formatter; use Cycle\Schema\Renderer\ConsoleRenderer\Renderer; class MacrosRenderer implements Renderer { + private int $property; + private string $title; + + public function __construct(int $property, string $title) + { + $this->property = $property; + $this->title = $title; + } + public function render(Formatter $formatter, array $schema, string $role): ?string { - if (! \defined(SchemaInterface::class . '::MACROS')) { + if (! isset($schema[$this->property])) { return null; } - $macrosList = (array)($schema[SchemaInterface::MACROS] ?? []); + + $macrosList = (array)($schema[$this->property] ?? []); if ($macrosList === []) { return null; } $rows = [ - sprintf('%s:', $formatter->title('Entity macros')), + \sprintf('%s:', $formatter->title($this->title)), ]; foreach ($macrosList as $definition) { @@ -32,24 +41,26 @@ public function render(Formatter $formatter, array $schema, string $role): ?stri $class = \is_string($data[0] ?? null) ? $formatter->typecast($data[0]) : $formatter->error('undefined'); - $rows[] = sprintf(' %s', $class); + $rows[] = \sprintf('%s%s', $formatter->title(' '), $class); // macros params $params = $data[1] ?? null; if ($params === null) { continue; } - if (is_array($params)) { + if (\is_array($params)) { foreach ($params as $key => $value) { - $row = ' '; + $row = $formatter->title(' ') . ' - '; if (\is_string($key)) { $row .= $formatter->property($key) . ' : '; } - $row .= $formatter->info($this->printValue($formatter, $value)); + $row .= $formatter->info($this->printValue($value, $formatter)); $rows[] = $row; } + } elseif (is_string($params)) { + $rows[] = $formatter->title(' ') . ' - ' . $formatter->info($this->printValue($params, $formatter)); } else { - $rows[] = $formatter->typecast($this->printValue($formatter, $data)); + $rows[] = $formatter->typecast($this->printValue($data, $formatter)); } } @@ -57,14 +68,18 @@ public function render(Formatter $formatter, array $schema, string $role): ?stri } /** - * @param mixed $value + * @param mixed $value */ - private function printValue(Formatter $formatter, $value): string + private function printValue($value, Formatter $formatter): string { - return str_replace( - ["\r\n", "\n"], - $formatter::LINE_SEPARATOR . ' ', - print_r($value, true) + $data = \trim(\var_export($value, true), '\''); + $data = \array_map( + static fn (string $row): string => $formatter->title(' ') . $row, + \explode("\n", $data) + ); + + return \ltrim( + \implode("\n", $data) ); } } diff --git a/src/ConsoleRenderer/Renderer/PropertyRenderer.php b/src/ConsoleRenderer/Renderer/PropertyRenderer.php index e79fe66..61da161 100644 --- a/src/ConsoleRenderer/Renderer/PropertyRenderer.php +++ b/src/ConsoleRenderer/Renderer/PropertyRenderer.php @@ -22,7 +22,7 @@ public function __construct(int $property, string $title, bool $required = false public function render(Formatter $formatter, array $schema, string $role): ?string { - $row = sprintf('%s: ', $formatter->title($this->title)); + $row = \sprintf('%s: ', $formatter->title($this->title)); if (! isset($schema[$this->property])) { return $this->required ? $row . $formatter->error('not defined') : null; @@ -30,14 +30,14 @@ public function render(Formatter $formatter, array $schema, string $role): ?stri $propertyValue = $schema[$this->property]; - if (is_array($propertyValue)) { - if (count($propertyValue) >= 1) { + if (\is_array($propertyValue)) { + if (\count($propertyValue) >= 1) { return $row . $this->convertArrayToString($formatter, $propertyValue); } $propertyValue = '[]'; } - return sprintf( + return \sprintf( '%s%s', $row, $formatter->typecast($propertyValue) @@ -46,15 +46,15 @@ public function render(Formatter $formatter, array $schema, string $role): ?stri private function convertArrayToString(Formatter $formatter, array $values): string { - $string = implode( + $string = \implode( "\n", - array_map(static fn ($property) => sprintf( + \array_map(static fn ($property) => \sprintf( ' %s%s', $formatter->title(' '), $formatter->typecast($property) ), $values) ); - return ltrim($string); + return \ltrim($string); } } diff --git a/src/ConsoleRenderer/Renderer/RelationsRenderer.php b/src/ConsoleRenderer/Renderer/RelationsRenderer.php index a3734ca..af80138 100644 --- a/src/ConsoleRenderer/Renderer/RelationsRenderer.php +++ b/src/ConsoleRenderer/Renderer/RelationsRenderer.php @@ -12,6 +12,7 @@ class RelationsRenderer implements Renderer { private const STR_RELATION = [ + Relation::EMBEDDED => 'has embedded', Relation::HAS_ONE => 'has one', Relation::HAS_MANY => 'has many', Relation::BELONGS_TO => 'belongs to', @@ -29,10 +30,10 @@ class RelationsRenderer implements Renderer public function render(Formatter $formatter, array $schema, string $role): ?string { - $title = sprintf('%s:', $formatter->title('Relations')); + $title = \sprintf('%s:', $formatter->title('Relations')); $relations = $schema[SchemaInterface::RELATIONS] ?? []; - if (count($relations) === 0) { + if (\count($relations) === 0) { return $title . ' ' . $formatter->error('not defined'); } @@ -59,7 +60,7 @@ public function render(Formatter $formatter, array $schema, string $role): ?stri $mmWhere = $relSchema[Relation::THROUGH_WHERE] ?? []; // print - $row = sprintf( + $row = \sprintf( ' %s->%s %s %s', $formatter->entity($role), $formatter->property($field), @@ -68,16 +69,16 @@ public function render(Formatter $formatter, array $schema, string $role): ?stri ); if ($morphKey !== null) { - $row .= sprintf( + $row .= \sprintf( ', %s: %s', $formatter->title('morphed key'), $this->renderKeys($formatter, $morphKey) ); } - $rows[] = $row . sprintf(', %s loading, %s', $formatter->info($loading), $formatter->info($cascadeStr)); + $rows[] = $row . \sprintf(', %s loading, %s', $formatter->info($loading), $formatter->info($cascadeStr)); - $row = sprintf( + $row = \sprintf( ' %s %s.%s <=', $nullableStr, $formatter->entity($role), @@ -85,7 +86,7 @@ public function render(Formatter $formatter, array $schema, string $role): ?stri ); if ($mmEntity !== null) { - $row .= sprintf( + $row .= \sprintf( ' %s.%s | %s.%s ', $formatter->entity($mmEntity), $this->renderKeys($formatter, $mmInnerKey), @@ -95,17 +96,17 @@ public function render(Formatter $formatter, array $schema, string $role): ?stri } // todo: composite $outerKey - $rows[] = $row . sprintf( + $rows[] = $row . \sprintf( '=> %s.%s', $formatter->entity($target), $this->renderKeys($formatter, $outerKey) ); if (count($where)) { - $rows[] = sprintf( + $rows[] = \sprintf( '%s: %s', $formatter->title('Where'), - str_replace( + \str_replace( ["\r\n", "\n"], $formatter::LINE_SEPARATOR . ' ', $formatter::LINE_SEPARATOR . print_r($where, true) @@ -114,10 +115,10 @@ public function render(Formatter $formatter, array $schema, string $role): ?stri } if (count($mmWhere)) { - $rows[] = sprintf( + $rows[] = \sprintf( '%s: %s', $formatter->title('Through where'), - str_replace( + \str_replace( ["\r\n", "\n"], $formatter::LINE_SEPARATOR . ' ', $formatter::LINE_SEPARATOR . print_r($mmWhere, true) @@ -141,7 +142,7 @@ private function renderKeys(Formatter $formatter, $keys): string $keys ); - return sprintf( + return \sprintf( '%s%s%s', $braces ? '[' : '', \implode(', ', $keys), diff --git a/src/ConsoleRenderer/Renderer/TitleRenderer.php b/src/ConsoleRenderer/Renderer/TitleRenderer.php index 373f656..f45800b 100644 --- a/src/ConsoleRenderer/Renderer/TitleRenderer.php +++ b/src/ConsoleRenderer/Renderer/TitleRenderer.php @@ -15,7 +15,7 @@ public function render(Formatter $formatter, array $schema, string $role): ?stri $database = $schema[SchemaInterface::DATABASE] ?? ''; $table = $schema[SchemaInterface::TABLE] ?? ''; - return sprintf( + return \sprintf( '%s :: %s.%s', $formatter->entity("[{$role}]"), $formatter->column($database), diff --git a/src/ConstantsInterface.php b/src/ConstantsInterface.php new file mode 100644 index 0000000..52ab597 --- /dev/null +++ b/src/ConstantsInterface.php @@ -0,0 +1,13 @@ + + */ + public function all(): array; +} diff --git a/src/OutputSchemaRenderer.php b/src/OutputSchemaRenderer.php index fb6c7e1..ad9eeba 100644 --- a/src/OutputSchemaRenderer.php +++ b/src/OutputSchemaRenderer.php @@ -32,14 +32,14 @@ final class OutputSchemaRenderer extends OutputRenderer 'REPOSITORY' => 'Repository', ]; - public function __construct(int $format = self::FORMAT_CONSOLE_COLOR) + public function __construct(int $format = self::FORMAT_CONSOLE_COLOR, ?ConstantsInterface $constants = null) { $formatter = $format === self::FORMAT_CONSOLE_COLOR ? new StyledFormatter() : new PlainFormatter(); parent::__construct($formatter); - $constants = $this->getOrmConstants(); + $constants = ($constants ?? new SchemaConstants())->all(); $properties = $this->getOrmProperties($constants); $this->addRenderer(...[ @@ -56,27 +56,32 @@ public function __construct(int $format = self::FORMAT_CONSOLE_COLOR) // JTI support if (isset($constants['PARENT'], $constants['PARENT_KEY'])) { $this->addRenderer(...[ - new PropertyRenderer($constants['PARENT'], 'Children'), - new KeysRenderer($constants['PARENT_KEY'], 'STI key', false), + new PropertyRenderer($constants['PARENT'], 'Parent'), + new KeysRenderer($constants['PARENT_KEY'], 'Parent key', false), ]); } // STI support - if (isset($constants['CHILDREN'], $constants['DISCRIMINATOR'])) { - $this->addRenderer(...[ - new PropertyRenderer($constants['CHILDREN'], 'Parent'), - new KeysRenderer($constants['DISCRIMINATOR'], 'Parent key', false), - ]); + if (isset($constants['CHILDREN'])) { + $this->addRenderer(new PropertyRenderer($constants['CHILDREN'], 'Children')); + } + + if (isset($constants['DISCRIMINATOR'])) { + $this->addRenderer(new KeysRenderer($constants['DISCRIMINATOR'], 'Discriminator', false)); } $this->addRenderer(new ColumnsRenderer()); if (isset($constants['TYPECAST_HANDLER'])) { $this->addRenderer(new PropertyRenderer($constants['TYPECAST_HANDLER'], 'Typecast')); } + + if (isset($constants['MACROS'])) { + $this->addRenderer(new MacrosRenderer($constants['MACROS'], 'Macros')); + } + $this->addRenderer( new RelationsRenderer(), new CustomPropertiesRenderer(array_values($constants)), - new MacrosRenderer(), ); } @@ -96,12 +101,4 @@ private function getOrmProperties(array $constants): array } return $result; } - - private function getOrmConstants(): array - { - return array_filter( - (new \ReflectionClass(SchemaInterface::class))->getConstants(), - 'is_int' - ); - } } diff --git a/src/SchemaConstants.php b/src/SchemaConstants.php new file mode 100644 index 0000000..38bf730 --- /dev/null +++ b/src/SchemaConstants.php @@ -0,0 +1,18 @@ +getConstants(), + 'is_int' + ); + } +} diff --git a/src/SchemaToArrayConverter.php b/src/SchemaToArrayConverter.php index 5a546f9..63ec0b7 100644 --- a/src/SchemaToArrayConverter.php +++ b/src/SchemaToArrayConverter.php @@ -11,6 +11,14 @@ */ final class SchemaToArrayConverter { + /** @var array */ + private array $constants; + + public function __construct(?ConstantsInterface $constants = null) + { + $this->constants = ($constants ?? new SchemaConstants())->all(); + } + /** * @param SchemaInterface $schema * @param array $customProperties @@ -26,7 +34,7 @@ public function convert(SchemaInterface $schema, array $customProperties = []): $result = []; - $properties = array_merge($this->getSchemaConstants(), $customProperties); + $properties = array_merge($this->constants, $customProperties); foreach ($schema->getRoles() as $role) { foreach ($properties as $property) { @@ -41,16 +49,4 @@ public function convert(SchemaInterface $schema, array $customProperties = []): return $result; } - - /** - * @return array - */ - private function getSchemaConstants(): array - { - $result = array_filter( - (new \ReflectionClass(SchemaInterface::class))->getConstants(), - static fn ($value): bool => is_int($value) - ); - return array_values($result); - } } diff --git a/tests/Schema/Renderer/BaseTest.php b/tests/Schema/Renderer/BaseTest.php new file mode 100644 index 0000000..b5b8bc7 --- /dev/null +++ b/tests/Schema/Renderer/BaseTest.php @@ -0,0 +1,27 @@ + 1; + } +} diff --git a/tests/Schema/Renderer/ConsoleRenderer/OutputRendererTest.php b/tests/Schema/Renderer/ConsoleRenderer/OutputRendererTest.php index a5a2453..56ce309 100644 --- a/tests/Schema/Renderer/ConsoleRenderer/OutputRendererTest.php +++ b/tests/Schema/Renderer/ConsoleRenderer/OutputRendererTest.php @@ -12,11 +12,11 @@ use Cycle\Schema\Renderer\ConsoleRenderer\OutputRenderer; use Cycle\Schema\Renderer\ConsoleRenderer\Renderer\TitleRenderer; use Cycle\Schema\Renderer\SchemaToArrayConverter; +use Cycle\Schema\Renderer\Tests\BaseTest; use Cycle\Schema\Renderer\Tests\Fixture\Tag; use Cycle\Schema\Renderer\Tests\Fixture\TagContext; -use PHPUnit\Framework\TestCase; -class OutputRendererTest extends TestCase +class OutputRendererTest extends BaseTest { private array $schemaArray; diff --git a/tests/Schema/Renderer/ConsoleRenderer/Renderer/ColumnsRendererTest.php b/tests/Schema/Renderer/ConsoleRenderer/Renderer/ColumnsRendererTest.php index 92e81ee..03ecc83 100644 --- a/tests/Schema/Renderer/ConsoleRenderer/Renderer/ColumnsRendererTest.php +++ b/tests/Schema/Renderer/ConsoleRenderer/Renderer/ColumnsRendererTest.php @@ -8,9 +8,9 @@ use Cycle\Schema\Renderer\ConsoleRenderer\Formatter; use Cycle\Schema\Renderer\ConsoleRenderer\Formatter\PlainFormatter; use Cycle\Schema\Renderer\ConsoleRenderer\Renderer\ColumnsRenderer; -use PHPUnit\Framework\TestCase; +use Cycle\Schema\Renderer\Tests\BaseTest; -class ColumnsRendererTest extends TestCase +class ColumnsRendererTest extends BaseTest { private Formatter $formatter; diff --git a/tests/Schema/Renderer/ConsoleRenderer/Renderer/CustomPropertiesRendererTest.php b/tests/Schema/Renderer/ConsoleRenderer/Renderer/CustomPropertiesRendererTest.php new file mode 100644 index 0000000..f37e9bb --- /dev/null +++ b/tests/Schema/Renderer/ConsoleRenderer/Renderer/CustomPropertiesRendererTest.php @@ -0,0 +1,56 @@ +formatter = new PlainFormatter(); + } + + public function testCustomPropertiesShouldBeRendered() + { + $renderer = new CustomPropertiesRenderer(['bar', 'baz']); + + $object = new User(); + + $result = $renderer->render($this->formatter, [ + 'bar' => 1, + 'baz' => 2, + 'int' => 3, + 'string' => 'Hello world', + 'array' => ['foo' => 'bar'], + 'object' => $object, + 'bool' => false, + ], 'foo'); + + $this->assertSame( + <<<'OUTPUT' + Custom props: + int: 3 + string: Hello world + array: array ( + 'foo' => 'bar', + ) + object: Cycle\Schema\Renderer\Tests\Fixture\User::__set_state(array( + )) + bool: false +OUTPUT + , + $result + ); + } +} diff --git a/tests/Schema/Renderer/ConsoleRenderer/Renderer/KeysRendererTest.php b/tests/Schema/Renderer/ConsoleRenderer/Renderer/KeysRendererTest.php index 16a57e2..29430cd 100644 --- a/tests/Schema/Renderer/ConsoleRenderer/Renderer/KeysRendererTest.php +++ b/tests/Schema/Renderer/ConsoleRenderer/Renderer/KeysRendererTest.php @@ -7,9 +7,9 @@ use Cycle\Schema\Renderer\ConsoleRenderer\Formatter; use Cycle\Schema\Renderer\ConsoleRenderer\Formatter\PlainFormatter; use Cycle\Schema\Renderer\ConsoleRenderer\Renderer\KeysRenderer; -use PHPUnit\Framework\TestCase; +use Cycle\Schema\Renderer\Tests\BaseTest; -class KeysRendererTest extends TestCase +class KeysRendererTest extends BaseTest { private Formatter $formatter; diff --git a/tests/Schema/Renderer/ConsoleRenderer/Renderer/MacrosRendererTest.php b/tests/Schema/Renderer/ConsoleRenderer/Renderer/MacrosRendererTest.php new file mode 100644 index 0000000..949d6ee --- /dev/null +++ b/tests/Schema/Renderer/ConsoleRenderer/Renderer/MacrosRendererTest.php @@ -0,0 +1,96 @@ +formatter = new PlainFormatter(); + } + + public function testRenderNotExistsProperty() + { + $renderer = new MacrosRenderer(1, 'Foo'); + + $result = $renderer->render($this->formatter, [], 'baz'); + + $this->assertNull($result); + } + + public function testRenderStringProperty() + { + $renderer = new MacrosRenderer(1, 'Foo'); + + $result = $renderer->render($this->formatter, [ + 1 => 'bar', + ], 'baz'); + + $this->assertSame( + <<<'OUTPUT' + Foo: + bar +OUTPUT + , + $result + ); + } + + public function testRenderArrayProperty() + { + $renderer = new MacrosRenderer(1, 'Foo'); + + $result = $renderer->render($this->formatter, [ + 1 => ['foo-macros', 'bar-macros'], + ], 'baz'); + + $this->assertSame( + <<<'OUTPUT' + Foo: + foo-macros + bar-macros +OUTPUT + , + $result + ); + } + + public function testRenderAssocArrayProperty() + { + $renderer = new MacrosRenderer(1, 'Foo'); + + $result = $renderer->render($this->formatter, [ + 1 => [ + ['foo-macros', []], + ['bar-macros', ['baz' => 'bar', 'baz1', 'baz2']], + ['baz-macros', 'baz'], + ], + ], 'baz'); + + $this->assertSame( + <<<'OUTPUT' + Foo: + foo-macros + bar-macros + - baz : bar + - baz1 + - baz2 + baz-macros + - baz +OUTPUT + , + $result + ); + } +} diff --git a/tests/Schema/Renderer/ConsoleRenderer/Renderer/PropertyRendererTest.php b/tests/Schema/Renderer/ConsoleRenderer/Renderer/PropertyRendererTest.php index 88e2706..9d1415c 100644 --- a/tests/Schema/Renderer/ConsoleRenderer/Renderer/PropertyRendererTest.php +++ b/tests/Schema/Renderer/ConsoleRenderer/Renderer/PropertyRendererTest.php @@ -7,9 +7,9 @@ use Cycle\Schema\Renderer\ConsoleRenderer\Formatter; use Cycle\Schema\Renderer\ConsoleRenderer\Formatter\PlainFormatter; use Cycle\Schema\Renderer\ConsoleRenderer\Renderer\PropertyRenderer; -use PHPUnit\Framework\TestCase; +use Cycle\Schema\Renderer\Tests\BaseTest; -class PropertyRendererTest extends TestCase +class PropertyRendererTest extends BaseTest { private Formatter $formatter; diff --git a/tests/Schema/Renderer/ConsoleRenderer/Renderer/RelationsRendererTest.php b/tests/Schema/Renderer/ConsoleRenderer/Renderer/RelationsRendererTest.php new file mode 100644 index 0000000..6658500 --- /dev/null +++ b/tests/Schema/Renderer/ConsoleRenderer/Renderer/RelationsRendererTest.php @@ -0,0 +1,277 @@ +formatter = new PlainFormatter(); + $this->renderer = new RelationsRenderer(); + } + + public function testRenderBelongsToRelation() + { + $result = $this->renderer->render($this->formatter, [ + SchemaInterface::RELATIONS => [ + 'user' => [ + Relation::TYPE => Relation::BELONGS_TO, + Relation::TARGET => 'guest', + Relation::SCHEMA => [ + Relation::NULLABLE => false, + Relation::CASCADE => true, + Relation::INNER_KEY => ['parent_key1', 'parent_key2'], + Relation::OUTER_KEY => ['key1', 'key2'], + ], + ], + ], + ], 'foo'); + + $this->assertSame( + <<<'OUTPUT' + Relations: + foo->user belongs to guest, default loading, cascaded + not null foo.[parent_key1, parent_key2] <==> guest.[key1, key2] +OUTPUT + , + $result + ); + } + + public function testRenderHasOneRelation() + { + $result = $this->renderer->render($this->formatter, [ + SchemaInterface::RELATIONS => [ + 'user' => [ + Relation::TYPE => Relation::HAS_ONE, + Relation::TARGET => 'guest', + Relation::SCHEMA => [ + Relation::CASCADE => true, + Relation::INNER_KEY => ['key1', 'key2'], + Relation::OUTER_KEY => ['parent_key1', 'parent_key2'], + ], + ], + ], + ], 'foo'); + + $this->assertSame( + <<<'OUTPUT' + Relations: + foo->user has one guest, default loading, cascaded + n/a foo.[key1, key2] <==> guest.[parent_key1, parent_key2] +OUTPUT + , + $result + ); + } + + public function testRenderRefersToRelation() + { + $result = $this->renderer->render($this->formatter, [ + SchemaInterface::RELATIONS => [ + 'user' => [ + Relation::TYPE => Relation::REFERS_TO, + Relation::TARGET => 'tag', + Relation::SCHEMA => [ + Relation::CASCADE => true, + Relation::INNER_KEY => 'tag_id', + Relation::OUTER_KEY => 'id', + ], + ], + ], + ], 'foo'); + + $this->assertSame( + <<<'OUTPUT' + Relations: + foo->user refers to tag, default loading, cascaded + n/a foo.tag_id <==> tag.id +OUTPUT + , + $result + ); + } + + public function testRenderEmbeddedRelation() + { + $result = $this->renderer->render($this->formatter, [ + SchemaInterface::RELATIONS => [ + 'user' => [ + Relation::TYPE => Relation::EMBEDDED, + Relation::TARGET => 'user:credentials', + Relation::LOAD => Relation::LOAD_PROMISE, + Relation::SCHEMA => [], + ], + ], + ], 'foo'); + + $this->assertSame( + <<<'OUTPUT' + Relations: + foo->user has embedded user:credentials, lazy loading, not cascaded + n/a foo.? <==> user:credentials.? +OUTPUT + , + $result + ); + } + + public function testRenderHasManyRelation() + { + $result = $this->renderer->render($this->formatter, [ + SchemaInterface::RELATIONS => [ + 'user' => [ + Relation::TYPE => Relation::HAS_MANY, + Relation::TARGET => 'tag', + Relation::SCHEMA => [ + Relation::NULLABLE => true, + Relation::CASCADE => true, + Relation::INNER_KEY => 'id', + Relation::OUTER_KEY => 'user_id', + ], + ], + ], + ], 'foo'); + + $this->assertSame( + <<<'OUTPUT' + Relations: + foo->user has many tag, default loading, cascaded + nullable foo.id <==> tag.user_id +OUTPUT + , + $result + ); + } + + public function testRenderManyToManyRelation() + { + $result = $this->renderer->render($this->formatter, [ + SchemaInterface::RELATIONS => [ + 'user' => [ + Relation::TYPE => Relation::MANY_TO_MANY, + Relation::TARGET => 'tag', + Relation::SCHEMA => [ + Relation::CASCADE => true, + Relation::THROUGH_ENTITY => 'tag_context', + Relation::INNER_KEY => 'id', + Relation::OUTER_KEY => 'id', + Relation::THROUGH_INNER_KEY => 'user_id', + Relation::THROUGH_OUTER_KEY => 'tag_id', + ], + ], + ], + ], 'foo'); + + $this->assertSame( + <<<'OUTPUT' + Relations: + foo->user many to many tag, default loading, cascaded + n/a foo.id <= tag_context.user_id | tag_context.tag_id => tag.id +OUTPUT + , + $result + ); + } + + public function testRenderBelongsToMorphedRelation() + { + $result = $this->renderer->render($this->formatter, [ + SchemaInterface::RELATIONS => [ + 'user' => [ + Relation::TYPE => Relation::BELONGS_TO_MORPHED, + Relation::TARGET => 'image', + Relation::LOAD => Relation::LOAD_PROMISE, + + Relation::SCHEMA => [ + Relation::NULLABLE => true, + Relation::CASCADE => true, + Relation::OUTER_KEY => 'id', + Relation::INNER_KEY => 'parentId', + Relation::MORPH_KEY => 'parentType', + ], + ], + ], + ], 'foo'); + + $this->assertSame( + <<<'OUTPUT' + Relations: + foo->user belongs to morphed image, morphed key: parentType, lazy loading, cascaded + nullable foo.parentId <==> image.id +OUTPUT + , + $result + ); + } + + public function testRenderHasOneMorphedRelation() + { + $result = $this->renderer->render($this->formatter, [ + SchemaInterface::RELATIONS => [ + 'image' => [ + Relation::TYPE => Relation::MORPHED_HAS_ONE, + Relation::TARGET => 'user', + Relation::SCHEMA => [ + Relation::CASCADE => true, + Relation::INNER_KEY => 'id', + Relation::OUTER_KEY => 'parentId', + Relation::MORPH_KEY => 'parentType', + ], + ], + ], + ], 'foo'); + + $this->assertSame( + <<<'OUTPUT' + Relations: + foo->image morphed has one user, morphed key: parentType, default loading, cascaded + n/a foo.id <==> user.parentId +OUTPUT + , + $result + ); + } + + public function testRenderHasManyMorphedRelation() + { + $result = $this->renderer->render($this->formatter, [ + SchemaInterface::RELATIONS => [ + 'post' => [ + Relation::TYPE => Relation::MORPHED_HAS_MANY, + Relation::TARGET => 'comment', + Relation::SCHEMA => [ + Relation::CASCADE => true, + Relation::INNER_KEY => 'id', + Relation::OUTER_KEY => 'parent_id', + Relation::MORPH_KEY => 'parent_type', + ], + ], + ], + ], 'foo'); + + $this->assertSame( + <<<'OUTPUT' + Relations: + foo->post morphed has many comment, morphed key: parent_type, default loading, cascaded + n/a foo.id <==> comment.parent_id +OUTPUT + , + $result + ); + } +} diff --git a/tests/Schema/Renderer/ConsoleRenderer/Renderer/TitleRendererTest.php b/tests/Schema/Renderer/ConsoleRenderer/Renderer/TitleRendererTest.php index c91d293..4ca1e2e 100644 --- a/tests/Schema/Renderer/ConsoleRenderer/Renderer/TitleRendererTest.php +++ b/tests/Schema/Renderer/ConsoleRenderer/Renderer/TitleRendererTest.php @@ -8,9 +8,9 @@ use Cycle\Schema\Renderer\ConsoleRenderer\Formatter; use Cycle\Schema\Renderer\ConsoleRenderer\Formatter\PlainFormatter; use Cycle\Schema\Renderer\ConsoleRenderer\Renderer\TitleRenderer; -use PHPUnit\Framework\TestCase; +use Cycle\Schema\Renderer\Tests\BaseTest; -class TitleRendererTest extends TestCase +class TitleRendererTest extends BaseTest { private Formatter $formatter; diff --git a/tests/Schema/Renderer/Fixture/Admin.php b/tests/Schema/Renderer/Fixture/Admin.php new file mode 100644 index 0000000..9a09cf6 --- /dev/null +++ b/tests/Schema/Renderer/Fixture/Admin.php @@ -0,0 +1,9 @@ + email 2 -> balance -> float Relations: - user->tags many to many tag, default loading, cascaded - n/a user.id <= tag_context.user_id | tag_context.tag_id => tag.id - user->tag belongs to tag, default loading, cascaded - n/a user.tag_id <==> tag.id + Cycle\Schema\Renderer\Tests\Fixture\User->tags many to many Cycle\Schema\Renderer\Tests\Fixture\Tag, default loading, cascaded + n/a Cycle\Schema\Renderer\Tests\Fixture\User.id <= tag_context.user_id | tag_context.tag_id => Cycle\Schema\Renderer\Tests\Fixture\Tag.id + Cycle\Schema\Renderer\Tests\Fixture\User->tag belongs to Cycle\Schema\Renderer\Tests\Fixture\Tag, default loading, cascaded + n/a Cycle\Schema\Renderer\Tests\Fixture\User.tag_id <==> Cycle\Schema\Renderer\Tests\Fixture\Tag.id -[tag] :: default.tag - Entity: Cycle\Schema\Renderer\Tests\Fixture\Tag +[Cycle\Schema\Renderer\Tests\Fixture\Tag] :: default.tag + Role: tag Mapper: Cycle\ORM\Mapper\Mapper App\FooMapper Primary key: id, name @@ -23,13 +23,16 @@ 0 -> id -> int 1 -> name Relations: - tag->user belongs to user, default loading, cascaded - n/a tag.user_id <==> user.id + Cycle\Schema\Renderer\Tests\Fixture\Tag->user belongs to Cycle\Schema\Renderer\Tests\Fixture\User, default loading, cascaded + n/a Cycle\Schema\Renderer\Tests\Fixture\Tag.user_id <==> Cycle\Schema\Renderer\Tests\Fixture\User.id -[tag_context] :: default.tag_user_map - Entity: Cycle\Schema\Renderer\Tests\Fixture\TagContext +[Cycle\Schema\Renderer\Tests\Fixture\TagContext] :: default.tag_user_map + Role: tag_context Mapper: Cycle\ORM\Mapper\Mapper Primary key: not defined Fields: not defined Relations: not defined + Custom props: + my_custom_property: super_value + 25: super_value diff --git a/tests/Schema/Renderer/Fixture/console_output_with_custom_properties.stub.txt b/tests/Schema/Renderer/Fixture/console_output_with_custom_properties.stub.txt index 51bb88f..9666e13 100644 --- a/tests/Schema/Renderer/Fixture/console_output_with_custom_properties.stub.txt +++ b/tests/Schema/Renderer/Fixture/console_output_with_custom_properties.stub.txt @@ -34,6 +34,6 @@ Fields: not defined Relations: not defined Custom props: - my_custom_property: super_value - 25: super_value + my_custom_property: super_value + 25: super_value diff --git a/tests/Schema/Renderer/Fixture/generated_schema_v2.stub.php b/tests/Schema/Renderer/Fixture/generated_schema_v2.stub.php new file mode 100644 index 0000000..5321ef4 --- /dev/null +++ b/tests/Schema/Renderer/Fixture/generated_schema_v2.stub.php @@ -0,0 +1,82 @@ + [ + Schema::MAPPER => 'Cycle\\ORM\\Mapper\\Mapper', + Schema::DATABASE => 'default', + Schema::TABLE => 'user', + Schema::PRIMARY_KEY => 'id', + Schema::COLUMNS => ['id', 'email', 'balance'], + Schema::TYPECAST => [ + 'id' => 'int', + 'balance' => 'float', + ], + Schema::SCHEMA => [], + Schema::RELATIONS => [ + 'tags' => [ + Relation::TYPE => Relation::MANY_TO_MANY, + Relation::TARGET => 'tag', + Relation::SCHEMA => [ + Relation::CASCADE => true, + Relation::THROUGH_ENTITY => 'tag_context', + Relation::INNER_KEY => 'id', + Relation::OUTER_KEY => 'id', + Relation::THROUGH_INNER_KEY => 'user_id', + Relation::THROUGH_OUTER_KEY => 'tag_id', + ], + ], + 'tag' => [ + Relation::TYPE => Relation::BELONGS_TO, + Relation::TARGET => 'tag', + Relation::SCHEMA => [ + Relation::CASCADE => true, + Relation::INNER_KEY => 'tag_id', + Relation::OUTER_KEY => 'id', + ], + ], + ], + Schema::ENTITY => 'Cycle\\Schema\\Renderer\\Tests\\Fixture\\User', + ], + 'tag' => [ + Schema::MAPPER => 'Cycle\\ORM\\Mapper\\Mapper', + Schema::DATABASE => 'default', + Schema::TABLE => 'tag', + Schema::PRIMARY_KEY => ['id', 'name'], + Schema::COLUMNS => ['id', 'name'], + Schema::TYPECAST => [ + 'id' => 'int', + ], + Schema::SCHEMA => [], + Schema::RELATIONS => [ + 'user' => [ + Relation::TYPE => Relation::BELONGS_TO, + Relation::TARGET => 'user', + Relation::SCHEMA => [ + Relation::CASCADE => true, + Relation::INNER_KEY => 'user_id', + Relation::OUTER_KEY => 'id', + ], + ], + ], + Schema::ENTITY => 'Cycle\\Schema\\Renderer\\Tests\\Fixture\\Tag', + ], + 'tag_context' => [ + Schema::MAPPER => 'Cycle\\ORM\\Mapper\\Mapper', + Schema::DATABASE => 'default', + Schema::TABLE => 'tag_user_map', + Schema::COLUMNS => [], + Schema::TYPECAST => [ + 'id' => 'int', + 'user_id' => 'int', + 'tag_id' => 'int', + ], + Schema::SCHEMA => [], + Schema::RELATIONS => [], + Schema::ENTITY => 'Cycle\\Schema\\Renderer\\Tests\\Fixture\\TagContext', + ], +]; diff --git a/tests/Schema/Renderer/OutputSchemaRendererTest.php b/tests/Schema/Renderer/OutputSchemaRenderer/CommonTest.php similarity index 87% rename from tests/Schema/Renderer/OutputSchemaRendererTest.php rename to tests/Schema/Renderer/OutputSchemaRenderer/CommonTest.php index 0800721..608cffd 100644 --- a/tests/Schema/Renderer/OutputSchemaRendererTest.php +++ b/tests/Schema/Renderer/OutputSchemaRenderer/CommonTest.php @@ -2,21 +2,19 @@ declare(strict_types=1); -namespace Cycle\Schema\Renderer\Tests; +namespace Cycle\Schema\Renderer\Tests\OutputSchemaRenderer; use Cycle\ORM\Mapper\Mapper; use Cycle\ORM\Relation; -use Cycle\ORM\Schema; use Cycle\ORM\SchemaInterface; use Cycle\Schema\Renderer\ConsoleRenderer\Renderer\PropertyRenderer; use Cycle\Schema\Renderer\OutputSchemaRenderer; -use Cycle\Schema\Renderer\SchemaToArrayConverter; use Cycle\Schema\Renderer\Tests\Fixture\Tag; use Cycle\Schema\Renderer\Tests\Fixture\TagContext; use Cycle\Schema\Renderer\Tests\Fixture\User; use PHPUnit\Framework\TestCase; -final class OutputSchemaRendererTest extends TestCase +final class CommonTest extends TestCase { private array $schemaArray; @@ -104,9 +102,7 @@ public function testSchemaShouldBeRendered(): void { $renderer = new OutputSchemaRenderer(OutputSchemaRenderer::FORMAT_CONSOLE_COLOR); - echo $renderer->render($this->schemaArray); - - $expected = file_get_contents(__DIR__ . '/Fixture/console_output.stub.txt'); + $expected = file_get_contents(__DIR__ . '/../Fixture/console_output.stub.txt'); $this->assertSame( $expected, @@ -116,15 +112,13 @@ public function testSchemaShouldBeRendered(): void public function testPlainFormat(): void { - $schema = new Schema($this->schemaArray); - $schemaArray = (new SchemaToArrayConverter())->convert($schema); $renderer = new OutputSchemaRenderer(OutputSchemaRenderer::FORMAT_PLAIN_TEXT); - $expected = file_get_contents(__DIR__ . '/Fixture/console_output_plain.stub.txt'); + $expected = file_get_contents(__DIR__ . '/../Fixture/console_output_plain.stub.txt'); $this->assertSame( $expected, - $renderer->render($schemaArray) + $renderer->render($this->schemaArray) ); } @@ -133,7 +127,7 @@ public function testSchemaWithExtraPropertiesShouldBeRendered(): void $renderer = new OutputSchemaRenderer(OutputSchemaRenderer::FORMAT_CONSOLE_COLOR); $renderer->addRenderer(new PropertyRenderer(SchemaInterface::SOURCE, 'Source')); - $expected = file_get_contents(__DIR__ . '/Fixture/console_output_with_custom_properties.stub.txt'); + $expected = file_get_contents(__DIR__ . '/../Fixture/console_output_with_custom_properties.stub.txt'); $this->assertSame( $expected, diff --git a/tests/Schema/Renderer/OutputSchemaRenderer/JoinedTableInheritanceTest.php b/tests/Schema/Renderer/OutputSchemaRenderer/JoinedTableInheritanceTest.php new file mode 100644 index 0000000..6b760e7 --- /dev/null +++ b/tests/Schema/Renderer/OutputSchemaRenderer/JoinedTableInheritanceTest.php @@ -0,0 +1,64 @@ +constantSupported('PARENT', 'PARENT_KEY')) { + $this->markTestSkipped('Only CycleORM v2 supports JTI'); + } + + $schemaArray = [ + Guest::class => [ + SchemaInterface::ROLE => 'guest', + SchemaInterface::SOURCE => 'test', + SchemaInterface::MAPPER => Mapper::class, + SchemaInterface::DATABASE => 'default', + SchemaInterface::TABLE => 'guest', + SchemaInterface::PRIMARY_KEY => 'id', + SchemaInterface::COLUMNS => ['id', 'email', 'balance'], + SchemaInterface::TYPECAST => ['id' => 'int', 'balance' => 'float'], + SchemaInterface::PARENT => User::class, + SchemaInterface::PARENT_KEY => 'id', + ], + ]; + + $schema = new Schema($schemaArray); + $schemaArray = (new SchemaToArrayConverter())->convert($schema); + $renderer = new OutputSchemaRenderer(OutputSchemaRenderer::FORMAT_PLAIN_TEXT); + + $this->assertSame( + <<<'OUTPUT' +[guest] :: default.guest + Entity: Cycle\Schema\Renderer\Tests\Fixture\Guest + Mapper: Cycle\ORM\Mapper\Mapper + Primary key: id + Parent: Cycle\Schema\Renderer\Tests\Fixture\User + Parent key: id + Fields: + (property -> db.field -> typecast) + 0 -> id -> int + 1 -> email + 2 -> balance -> float + Relations: not defined + + +OUTPUT + , + $renderer->render($schemaArray) + ); + } +} diff --git a/tests/Schema/Renderer/OutputSchemaRenderer/MacrosTest.php b/tests/Schema/Renderer/OutputSchemaRenderer/MacrosTest.php new file mode 100644 index 0000000..b6c8676 --- /dev/null +++ b/tests/Schema/Renderer/OutputSchemaRenderer/MacrosTest.php @@ -0,0 +1,171 @@ +constantSupported('MACROS')) { + $this->markTestSkipped('Only CycleORM v2 supports macros'); + } + } + + public function testSchemaWithMacrosPropertyAsStringShouldBeRendered() + { + $schemaArray = [ + User::class => [ + SchemaInterface::ROLE => 'user', + SchemaInterface::SOURCE => 'test', + SchemaInterface::MAPPER => Mapper::class, + SchemaInterface::DATABASE => 'default', + SchemaInterface::TABLE => 'user', + SchemaInterface::PRIMARY_KEY => 'id', + SchemaInterface::COLUMNS => ['id', 'email', 'balance'], + SchemaInterface::TYPECAST => ['id' => 'int', 'balance' => 'float'], + SchemaInterface::MACROS => 'foo-macros', + ], + ]; + + $schema = new Schema($schemaArray); + $schemaArray = (new SchemaToArrayConverter())->convert($schema); + $renderer = new OutputSchemaRenderer(OutputSchemaRenderer::FORMAT_PLAIN_TEXT); + + $this->assertSame( + <<<'OUTPUT' +[user] :: default.user + Entity: Cycle\Schema\Renderer\Tests\Fixture\User + Mapper: Cycle\ORM\Mapper\Mapper + Primary key: id + Fields: + (property -> db.field -> typecast) + 0 -> id -> int + 1 -> email + 2 -> balance -> float + Macros: + foo-macros + Relations: not defined + + +OUTPUT + , + $renderer->render($schemaArray) + ); + } + + public function testSchemaWithMacrosPropertyAsArrayShouldBeRendered() + { + $schemaArray = [ + User::class => [ + SchemaInterface::ROLE => 'user', + SchemaInterface::SOURCE => 'test', + SchemaInterface::MAPPER => Mapper::class, + SchemaInterface::DATABASE => 'default', + SchemaInterface::TABLE => 'user', + SchemaInterface::PRIMARY_KEY => 'id', + SchemaInterface::COLUMNS => ['id', 'email', 'balance'], + SchemaInterface::TYPECAST => ['id' => 'int', 'balance' => 'float'], + SchemaInterface::MACROS => [ + 'foo-macros', + 'bar-macros', + ], + ], + ]; + + $schema = new Schema($schemaArray); + $schemaArray = (new SchemaToArrayConverter())->convert($schema); + $renderer = new OutputSchemaRenderer(OutputSchemaRenderer::FORMAT_PLAIN_TEXT); + + $this->assertSame( + <<<'OUTPUT' +[user] :: default.user + Entity: Cycle\Schema\Renderer\Tests\Fixture\User + Mapper: Cycle\ORM\Mapper\Mapper + Primary key: id + Fields: + (property -> db.field -> typecast) + 0 -> id -> int + 1 -> email + 2 -> balance -> float + Macros: + foo-macros + bar-macros + Relations: not defined + + +OUTPUT + , + $renderer->render($schemaArray) + ); + } + + public function testSchemaWithMacrosPropertyAsAssocArrayShouldBeRendered() + { + $schemaArray = [ + User::class => [ + SchemaInterface::ROLE => 'user', + SchemaInterface::SOURCE => 'test', + SchemaInterface::MAPPER => Mapper::class, + SchemaInterface::DATABASE => 'default', + SchemaInterface::TABLE => 'user', + SchemaInterface::PRIMARY_KEY => 'id', + SchemaInterface::COLUMNS => ['id', 'email', 'balance'], + SchemaInterface::TYPECAST => ['id' => 'int', 'balance' => 'float'], + SchemaInterface::MACROS => [ + ['foo-macros', []], + ['bar-macros', ['baz' => 'bar', 'baz1', 'baz2']], + ['baz-macros', 'baz'], + ['baz-macros', true], + ], + ], + ]; + + $schema = new Schema($schemaArray); + $schemaArray = (new SchemaToArrayConverter())->convert($schema); + $renderer = new OutputSchemaRenderer(OutputSchemaRenderer::FORMAT_PLAIN_TEXT); + + $this->assertSame( + <<<'OUTPUT' +[user] :: default.user + Entity: Cycle\Schema\Renderer\Tests\Fixture\User + Mapper: Cycle\ORM\Mapper\Mapper + Primary key: id + Fields: + (property -> db.field -> typecast) + 0 -> id -> int + 1 -> email + 2 -> balance -> float + Macros: + foo-macros + bar-macros + - baz : bar + - baz1 + - baz2 + baz-macros + - baz + baz-macros +array ( + 0 => 'baz-macros', + 1 => true, + ) + Relations: not defined + + +OUTPUT + , + $renderer->render($schemaArray) + ); + } +} diff --git a/tests/Schema/Renderer/OutputSchemaRenderer/SingleTableInheritanceTest.php b/tests/Schema/Renderer/OutputSchemaRenderer/SingleTableInheritanceTest.php new file mode 100644 index 0000000..eefa874 --- /dev/null +++ b/tests/Schema/Renderer/OutputSchemaRenderer/SingleTableInheritanceTest.php @@ -0,0 +1,114 @@ + [ + SchemaInterface::ROLE => 'user', + SchemaInterface::SOURCE => 'test', + SchemaInterface::MAPPER => Mapper::class, + SchemaInterface::DATABASE => 'default', + SchemaInterface::TABLE => 'user', + SchemaInterface::PRIMARY_KEY => 'id', + SchemaInterface::COLUMNS => ['id', 'email', 'balance'], + SchemaInterface::TYPECAST => ['id' => 'int', 'balance' => 'float'], + SchemaInterface::CHILDREN => [ + 'guest' => Guest::class, + 'admin' => Admin::class, + ], + ], + ]; + + $schema = new Schema($schemaArray); + $schemaArray = (new SchemaToArrayConverter())->convert($schema); + $renderer = new OutputSchemaRenderer(OutputSchemaRenderer::FORMAT_PLAIN_TEXT); + + $this->assertSame( + <<<'OUTPUT' +[user] :: default.user + Entity: Cycle\Schema\Renderer\Tests\Fixture\User + Mapper: Cycle\ORM\Mapper\Mapper + Primary key: id + Children: Cycle\Schema\Renderer\Tests\Fixture\Guest + Cycle\Schema\Renderer\Tests\Fixture\Admin + Fields: + (property -> db.field -> typecast) + 0 -> id -> int + 1 -> email + 2 -> balance -> float + Relations: not defined + + +OUTPUT + , + $renderer->render($schemaArray) + ); + } + + public function testSchemaWithChildrenAndDiscriminatorPropertiesShouldBeRendered(): void + { + if (! $this->constantSupported('CHILDREN', 'DISCRIMINATOR')) { + $this->markTestSkipped('Only CycleORM v2 supports STI with discriminator'); + } + + $schemaArray = [ + User::class => [ + SchemaInterface::ROLE => 'user', + SchemaInterface::SOURCE => 'test', + SchemaInterface::MAPPER => Mapper::class, + SchemaInterface::DATABASE => 'default', + SchemaInterface::TABLE => 'user', + SchemaInterface::PRIMARY_KEY => 'id', + SchemaInterface::COLUMNS => ['id', 'email', 'balance'], + SchemaInterface::TYPECAST => ['id' => 'int', 'balance' => 'float'], + SchemaInterface::CHILDREN => [ + 'guest' => Guest::class, + 'admin' => Admin::class, + ], + SchemaInterface::DISCRIMINATOR => 'type', + ], + ]; + + $schema = new Schema($schemaArray); + $schemaArray = (new SchemaToArrayConverter())->convert($schema); + $renderer = new OutputSchemaRenderer(OutputSchemaRenderer::FORMAT_PLAIN_TEXT); + + $this->assertSame( + <<<'OUTPUT' +[user] :: default.user + Entity: Cycle\Schema\Renderer\Tests\Fixture\User + Mapper: Cycle\ORM\Mapper\Mapper + Primary key: id + Children: Cycle\Schema\Renderer\Tests\Fixture\Guest + Cycle\Schema\Renderer\Tests\Fixture\Admin +Discriminator: type + Fields: + (property -> db.field -> typecast) + 0 -> id -> int + 1 -> email + 2 -> balance -> float + Relations: not defined + + +OUTPUT + , + $renderer->render($schemaArray) + ); + } +} diff --git a/tests/Schema/Renderer/OutputSchemaRenderer/TypecastHandlerTest.php b/tests/Schema/Renderer/OutputSchemaRenderer/TypecastHandlerTest.php new file mode 100644 index 0000000..dbee708 --- /dev/null +++ b/tests/Schema/Renderer/OutputSchemaRenderer/TypecastHandlerTest.php @@ -0,0 +1,111 @@ +constantSupported('TYPECAST_HANDLER')) { + $this->markTestSkipped('Only CycleORM v2 supports typecast handlers'); + } + } + + public function testSchemaWithTypecastHandlerPropertyAsStringShouldBeRendered(): void + { + $schemaArray = [ + User::class => [ + SchemaInterface::ROLE => 'user', + SchemaInterface::SOURCE => 'test', + SchemaInterface::MAPPER => Mapper::class, + SchemaInterface::DATABASE => 'default', + SchemaInterface::TABLE => 'user', + SchemaInterface::PRIMARY_KEY => 'id', + SchemaInterface::COLUMNS => ['id', 'email', 'balance'], + SchemaInterface::TYPECAST => ['id' => 'int', 'balance' => 'float'], + SchemaInterface::TYPECAST_HANDLER => 'foo-handler', + ], + ]; + + $schema = new Schema($schemaArray); + $schemaArray = (new SchemaToArrayConverter())->convert($schema); + $renderer = new OutputSchemaRenderer(OutputSchemaRenderer::FORMAT_PLAIN_TEXT); + + $this->assertSame( + <<<'OUTPUT' +[user] :: default.user + Entity: Cycle\Schema\Renderer\Tests\Fixture\User + Mapper: Cycle\ORM\Mapper\Mapper + Primary key: id + Fields: + (property -> db.field -> typecast) + 0 -> id -> int + 1 -> email + 2 -> balance -> float + Typecast: foo-handler + Relations: not defined + + +OUTPUT + , + $renderer->render($schemaArray) + ); + } + + public function testSchemaWithTypecastHandlerPropertyAsArrayShouldBeRendered(): void + { + $schemaArray = [ + User::class => [ + SchemaInterface::ROLE => 'user', + SchemaInterface::SOURCE => 'test', + SchemaInterface::MAPPER => Mapper::class, + SchemaInterface::DATABASE => 'default', + SchemaInterface::TABLE => 'user', + SchemaInterface::PRIMARY_KEY => 'id', + SchemaInterface::COLUMNS => ['id', 'email', 'balance'], + SchemaInterface::TYPECAST => ['id' => 'int', 'balance' => 'float'], + SchemaInterface::TYPECAST_HANDLER => [ + 'foo-handler', + 'bat-handler', + ], + ], + ]; + + $schema = new Schema($schemaArray); + $schemaArray = (new SchemaToArrayConverter())->convert($schema); + $renderer = new OutputSchemaRenderer(OutputSchemaRenderer::FORMAT_PLAIN_TEXT); + + $this->assertSame( + <<<'OUTPUT' +[user] :: default.user + Entity: Cycle\Schema\Renderer\Tests\Fixture\User + Mapper: Cycle\ORM\Mapper\Mapper + Primary key: id + Fields: + (property -> db.field -> typecast) + 0 -> id -> int + 1 -> email + 2 -> balance -> float + Typecast: foo-handler + bat-handler + Relations: not defined + + +OUTPUT + , + $renderer->render($schemaArray) + ); + } +} diff --git a/tests/Schema/Renderer/PhpSchemaRendererTest.php b/tests/Schema/Renderer/PhpSchemaRendererTest.php index b25e9d6..7872870 100644 --- a/tests/Schema/Renderer/PhpSchemaRendererTest.php +++ b/tests/Schema/Renderer/PhpSchemaRendererTest.php @@ -8,14 +8,13 @@ use Cycle\ORM\Relation; use Cycle\ORM\Schema; use Cycle\ORM\SchemaInterface; -use Cycle\Schema\Renderer\SchemaToArrayConverter; use Cycle\Schema\Renderer\PhpSchemaRenderer; +use Cycle\Schema\Renderer\SchemaToArrayConverter; use Cycle\Schema\Renderer\Tests\Fixture\Tag; use Cycle\Schema\Renderer\Tests\Fixture\TagContext; use Cycle\Schema\Renderer\Tests\Fixture\User; -use PHPUnit\Framework\TestCase; -final class PhpSchemaRendererTest extends TestCase +final class PhpSchemaRendererTest extends BaseTest { private array $schema; @@ -96,7 +95,11 @@ protected function setUp(): void public function testRenderSchemaToPhpCode(): void { $renderer = new PhpSchemaRenderer(); - $expected = file_get_contents(__DIR__ . '/Fixture/generated_schema.stub.php'); + if ($this->isOrmV2()) { + $expected = file_get_contents(__DIR__.'/Fixture/generated_schema_v2.stub.php'); + } else { + $expected = file_get_contents(__DIR__.'/Fixture/generated_schema.stub.php'); + } $this->assertSame( $expected, diff --git a/tests/Schema/Renderer/SchemaToArrayConverterTest.php b/tests/Schema/Renderer/SchemaToArrayConverter/CycleOrmV1Test.php similarity index 95% rename from tests/Schema/Renderer/SchemaToArrayConverterTest.php rename to tests/Schema/Renderer/SchemaToArrayConverter/CycleOrmV1Test.php index 717122a..2567caf 100644 --- a/tests/Schema/Renderer/SchemaToArrayConverterTest.php +++ b/tests/Schema/Renderer/SchemaToArrayConverter/CycleOrmV1Test.php @@ -2,19 +2,19 @@ declare(strict_types=1); -namespace Cycle\Schema\Renderer\Tests; +namespace Cycle\Schema\Renderer\Tests\SchemaToArrayConverter; use Cycle\ORM\Mapper\Mapper; use Cycle\ORM\Relation; use Cycle\ORM\Schema; use Cycle\ORM\SchemaInterface; use Cycle\Schema\Renderer\SchemaToArrayConverter; +use Cycle\Schema\Renderer\Tests\BaseTest; use Cycle\Schema\Renderer\Tests\Fixture\Tag; use Cycle\Schema\Renderer\Tests\Fixture\TagContext; use Cycle\Schema\Renderer\Tests\Fixture\User; -use PHPUnit\Framework\TestCase; -class SchemaToArrayConverterTest extends TestCase +class CycleOrmV1Test extends BaseTest { private Schema $schema; @@ -22,6 +22,10 @@ protected function setUp(): void { parent::setUp(); + if ($this->isOrmV2()) { + $this->markTestSkipped('Test for CycleORM v1'); + } + $this->schema = new Schema([ User::class => [ SchemaInterface::SOURCE => 'users', @@ -63,7 +67,7 @@ protected function setUp(): void public function testObjectShouldBeConvertedToArray() { - $this->assertSame([ + $this->assertEquals([ 'user' => [ SchemaInterface::ENTITY => User::class, SchemaInterface::MAPPER => Mapper::class, @@ -106,7 +110,7 @@ public function testObjectShouldBeConvertedToArray() public function testObjectWithCustomPropertiesShouldBeConvertedToArray() { - $this->assertSame([ + $this->assertEquals([ 'user' => [ SchemaInterface::ENTITY => User::class, SchemaInterface::MAPPER => Mapper::class, diff --git a/tests/Schema/Renderer/SchemaToArrayConverter/CycleOrmV2Test.php b/tests/Schema/Renderer/SchemaToArrayConverter/CycleOrmV2Test.php new file mode 100644 index 0000000..31daa1a --- /dev/null +++ b/tests/Schema/Renderer/SchemaToArrayConverter/CycleOrmV2Test.php @@ -0,0 +1,111 @@ +isOrmV2()) { + $this->markTestSkipped('Test for CycleORM v2'); + } + + $this->schema = new Schema([ + User::class => [ + SchemaInterface::SOURCE => 'users', + SchemaInterface::ROLE => 'user', + SchemaInterface::MAPPER => Mapper::class, + SchemaInterface::DATABASE => 'default', + SchemaInterface::TABLE => 'user', + SchemaInterface::PRIMARY_KEY => 'id', + SchemaInterface::COLUMNS => ['id', 'email', 'balance'], + SchemaInterface::TYPECAST => ['id' => 'int', 'balance' => 'float'], + SchemaInterface::SCHEMA => [], + SchemaInterface::RELATIONS => [ + 'tags' => [ + Relation::TYPE => Relation::MANY_TO_MANY, + Relation::TARGET => Tag::class, + Relation::SCHEMA => [ + Relation::CASCADE => true, + Relation::THROUGH_ENTITY => TagContext::class, + Relation::INNER_KEY => 'id', + Relation::OUTER_KEY => 'id', + Relation::THROUGH_INNER_KEY => 'user_id', + Relation::THROUGH_OUTER_KEY => 'tag_id', + ], + ], + 'tag' => [ + Relation::TYPE => Relation::BELONGS_TO, + Relation::TARGET => Tag::class, + Relation::SCHEMA => [ + Relation::CASCADE => true, + Relation::INNER_KEY => 'tag_id', + Relation::OUTER_KEY => 'id', + ], + ], + ], + 123 => 'value', + ], + ]); + } + + public function testObjectShouldBeConvertedToArray() + { + $this->assertEquals([ + 'user' => [ + SchemaInterface::ENTITY => User::class, + SchemaInterface::MAPPER => Mapper::class, + SchemaInterface::SOURCE => 'users', + SchemaInterface::DATABASE => 'default', + SchemaInterface::TABLE => 'user', + SchemaInterface::PRIMARY_KEY => 'id', + SchemaInterface::COLUMNS => ['id', 'email', 'balance'], + SchemaInterface::RELATIONS => [ + 'tags' => [ + Relation::TYPE => Relation::MANY_TO_MANY, + Relation::TARGET => 'Cycle\Schema\Renderer\Tests\Fixture\Tag', + Relation::SCHEMA => [ + Relation::CASCADE => true, + Relation::THROUGH_ENTITY => 'Cycle\Schema\Renderer\Tests\Fixture\TagContext', + Relation::INNER_KEY => 'id', + Relation::OUTER_KEY => 'id', + Relation::THROUGH_INNER_KEY => 'user_id', + Relation::THROUGH_OUTER_KEY => 'tag_id', + ], + ], + 'tag' => [ + Relation::TYPE => 12, + Relation::TARGET => 'Cycle\Schema\Renderer\Tests\Fixture\Tag', + Relation::SCHEMA => [ + Relation::CASCADE => true, + Relation::INNER_KEY => 'tag_id', + Relation::OUTER_KEY => 'id', + ], + ], + ], + SchemaInterface::TYPECAST => [ + 'id' => 'int', + 'balance' => 'float', + ], + SchemaInterface::SCHEMA => [], + 123 => 'value', + ], + ], (new SchemaToArrayConverter())->convert($this->schema)); + } +}