Skip to content

Commit

Permalink
Add FromConveyorSchemaProviderTest, exceptions tests
Browse files Browse the repository at this point in the history
  • Loading branch information
msmakouz committed Jan 30, 2024
1 parent d967a61 commit 7c0d68e
Show file tree
Hide file tree
Showing 5 changed files with 296 additions and 0 deletions.
159 changes: 159 additions & 0 deletions tests/Feature/Schema/Provider/FromConveyorSchemaProviderTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Yii\Cycle\Tests\Feature\Schema\Provider;

use Cycle\Database\Config\DatabaseConfig;
use Cycle\Database\Config\SQLite\MemoryConnectionConfig;
use Cycle\Database\Config\SQLiteDriverConfig;
use Cycle\Database\DatabaseManager;
use Cycle\Database\DatabaseProviderInterface;
use Cycle\ORM\Mapper\Mapper;
use Cycle\ORM\SchemaInterface;
use Cycle\ORM\Select\Repository;
use Cycle\ORM\Select\Source;
use Cycle\Schema\Generator\ForeignKeys;
use Cycle\Schema\Generator\GenerateModifiers;
use Cycle\Schema\Generator\GenerateRelations;
use Cycle\Schema\Generator\GenerateTypecast;
use Cycle\Schema\Generator\RenderModifiers;
use Cycle\Schema\Generator\RenderRelations;
use Cycle\Schema\Generator\RenderTables;
use Cycle\Schema\Generator\ResetTables;
use Cycle\Schema\Generator\ValidateEntities;
use Cycle\Schema\GeneratorInterface;
use Yiisoft\Aliases\Aliases;
use Yiisoft\Test\Support\Container\SimpleContainer;
use Yiisoft\Yii\Cycle\Schema\Conveyor\AttributedSchemaConveyor;
use Yiisoft\Yii\Cycle\Schema\Provider\FromConveyorSchemaProvider;
use Yiisoft\Yii\Cycle\Schema\SchemaConveyorInterface;
use Yiisoft\Yii\Cycle\Schema\SchemaProviderInterface;
use Yiisoft\Yii\Cycle\Tests\Feature\Schema\Provider\Stub\FakePost;
use Yiisoft\Yii\Cycle\Tests\Feature\Schema\Stub\ArraySchemaProvider;

final class FromConveyorSchemaProviderTest extends BaseSchemaProvider
{
private SimpleContainer $container;
private DatabaseManager $dbal;

protected function setUp(): void
{
$this->container = new SimpleContainer([
Aliases::class => new Aliases(),
ResetTables::class => new ResetTables(),
GenerateRelations::class => new GenerateRelations(),
GenerateModifiers::class => new GenerateModifiers(),
ValidateEntities::class => new ValidateEntities(),
RenderTables::class => new RenderTables(),
RenderRelations::class => new RenderRelations(),
RenderModifiers::class => new RenderModifiers(),
ForeignKeys::class => new ForeignKeys(),
GenerateTypecast::class => new GenerateTypecast(),
]);

$this->dbal = new DatabaseManager(new DatabaseConfig([
'default' => 'default',
'databases' => ['default' => ['connection' => 'sqlite']],
'connections' => [
'sqlite' => new SQLiteDriverConfig(connection: new MemoryConnectionConfig()),
],
]));
}

public function testWithEmptyConfig(): void
{
$conveyor = $this->createMock(SchemaConveyorInterface::class);
$conveyor->expects($this->once())->method('getGenerators')->willReturn([]);
$conveyor->expects($this->never())->method('addGenerator');

$provider = $this->createSchemaProvider(conveyor: $conveyor);

$provider->withConfig([]);

$this->assertSame([], $provider->read());
}

public function testWithConfig(): void
{
$provider = $this->createSchemaProvider();
$generator = $this->createMock(GeneratorInterface::class);

$provider = $provider->withConfig(['generators' => [$generator]]);

$ref = new \ReflectionProperty($provider, 'generators');
$ref->setAccessible(true);

$this->assertSame([$generator], $ref->getValue($provider));
}

public function testReadFromConveyor(): void
{
$attributed = new AttributedSchemaConveyor($this->container);
$attributed->addEntityPaths([__DIR__ . '/Stub']);

$provider = $this->createSchemaProvider(conveyor: $attributed, dbal: $this->dbal);

$this->assertEquals([
'fakePost' => [
SchemaInterface::ENTITY => FakePost::class,
SchemaInterface::MAPPER => Mapper::class,
SchemaInterface::SOURCE => Source::class,
SchemaInterface::REPOSITORY => Repository::class,
SchemaInterface::DATABASE => 'default',
SchemaInterface::TABLE => 'fake_post',
SchemaInterface::PRIMARY_KEY => ['id'],
SchemaInterface::FIND_BY_KEYS => ['id'],
SchemaInterface::COLUMNS => ['id' => 'id', 'title' => 'title', 'createdAt' => 'created_at'],
SchemaInterface::RELATIONS => [],
SchemaInterface::SCOPE => null,
SchemaInterface::TYPECAST => ['id' => 'int', 'createdAt' => 'datetime'],
SchemaInterface::SCHEMA => [],
SchemaInterface::TYPECAST_HANDLER => null
]
], $provider->read());
}

public function testReadFromConveyorAndNextProvider(): void
{
if (!is_dir(__DIR__ . '/Stub/Foo')) {
mkdir(__DIR__ . '/Stub/Foo', 0777, true);
}

$attributed = new AttributedSchemaConveyor($this->container);
$attributed->addEntityPaths([__DIR__ . '/Stub/Foo']);

$provider = $this->createSchemaProvider(conveyor: $attributed, dbal: $this->dbal);

$this->assertEquals(
self::READ_CONFIG_SCHEMA,
$provider->read(new ArraySchemaProvider(self::READ_CONFIG_SCHEMA))
);

if (is_dir(__DIR__ . '/Stub/Foo')) {
rmdir(__DIR__ . '/Stub/Foo');
}
}

protected function createSchemaProvider(
array $config = null,
SchemaConveyorInterface $conveyor = null,
DatabaseProviderInterface $dbal = null
): SchemaProviderInterface {
$provider = new FromConveyorSchemaProvider(
$conveyor ?? $this->createMock(SchemaConveyorInterface::class),
$dbal ?? $this->createMock(DatabaseProviderInterface::class),
);

return $config === null ? $provider : $provider->withConfig($config);
}

public function testWithConfigImmutability(): void
{
$schemaProvider1 = $this->createSchemaProvider();
$schemaProvider2 = $schemaProvider1->withConfig(self::READ_CONFIG);

$this->assertNotSame($schemaProvider1, $schemaProvider2);
}
}

21 changes: 21 additions & 0 deletions tests/Feature/Schema/Provider/Stub/FakePost.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Yii\Cycle\Tests\Feature\Schema\Provider\Stub;

use Cycle\Annotated\Annotation\Column;
use Cycle\Annotated\Annotation\Entity;

#[Entity]
class FakePost
{
#[Column(type: 'primary')]
public int $id;

#[Column(type: 'string')]
public string $title;

#[Column(type: 'datetime')]
public \DateTimeImmutable $createdAt;
}
37 changes: 37 additions & 0 deletions tests/Unit/Exception/NotFoundExceptionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Yii\Cycle\Tests\Unit\Exception;

use PHPUnit\Framework\TestCase;
use Yiisoft\FriendlyException\FriendlyExceptionInterface;
use Yiisoft\Yii\Cycle\Exception\NotFoundException;

final class NotFoundExceptionTest extends TestCase
{
public function testDefaultState(): void
{
$exception = new NotFoundException(\stdClass::class);

$this->assertInstanceOf(\Exception::class, $exception);
$this->assertSame(
\sprintf('No definition or class found or resolvable for "%s".', \stdClass::class),
$exception->getMessage()
);
$this->assertSame(0, $exception->getCode());
$this->assertNull( $exception->getPrevious());
}

public function testFriendly(): void
{
$exception = new NotFoundException(\stdClass::class);

$this->assertInstanceOf(FriendlyExceptionInterface::class, $exception);
$this->assertSame('Repository not found', $exception->getName());
$this->assertSame(
'Check if the class exists or if the class is properly defined.',
$exception->getSolution()
);
}
}
38 changes: 38 additions & 0 deletions tests/Unit/Exception/NotInstantiableClassExceptionTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Yii\Cycle\Tests\Unit\Exception;

use Cycle\ORM\RepositoryInterface;
use PHPUnit\Framework\TestCase;
use Yiisoft\FriendlyException\FriendlyExceptionInterface;
use Yiisoft\Yii\Cycle\Exception\NotInstantiableClassException;

final class NotInstantiableClassExceptionTest extends TestCase
{
public function testDefaultState(): void
{
$exception = new NotInstantiableClassException(\stdClass::class);

$this->assertInstanceOf(\Exception::class, $exception);
$this->assertSame(\sprintf('Can not instantiate "%s" because it is not a subclass of "%s".',
\stdClass::class,
RepositoryInterface::class
), $exception->getMessage());
$this->assertSame(0, $exception->getCode());
$this->assertNull( $exception->getPrevious());
}

public function testFriendly(): void
{
$exception = new NotInstantiableClassException(\stdClass::class);

$this->assertInstanceOf(FriendlyExceptionInterface::class, $exception);
$this->assertSame('Repository not instantiable', $exception->getName());
$this->assertSame(
'Make sure that the class is instantiable and implements Cycle\ORM\RepositoryInterface',
$exception->getSolution()
);
}
}
41 changes: 41 additions & 0 deletions tests/Unit/Factory/DbalFactory/DbalFactoryTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

declare(strict_types=1);

namespace Yiisoft\Yii\Cycle\Tests\Unit\Factory\DbalFactory;

use Cycle\Database\Config\DatabaseConfig;
use Yiisoft\Yii\Cycle\Factory\DbalFactory;
use Yiisoft\Yii\Cycle\Tests\Unit\Stub\FakeConnectionConfig;
use Yiisoft\Yii\Cycle\Tests\Unit\Stub\FakeDriver;
use Yiisoft\Yii\Cycle\Tests\Unit\Stub\FakeDriverConfig;

final class DbalFactoryTest extends BaseDbalFactory
{
public function testPrepareConfig(): void
{
$config = [
'query-logger' => 'foo',
'default' => 'default',
'aliases' => [],
'databases' => [
'default' => ['connection' => 'fake'],
],
'connections' => [
'fake' => new FakeDriverConfig(
connection: new FakeConnectionConfig(),
driver: FakeDriver::class,
),
],
];

$factory = new DbalFactory([]);
$ref = new \ReflectionMethod($factory, 'prepareConfig');
$ref->setAccessible(true);

$this->assertEquals(new DatabaseConfig($config), $ref->invoke($factory, $config));

$obj = new DatabaseConfig($config);
$this->assertSame($obj, $ref->invoke($factory, $obj));
}
}

0 comments on commit 7c0d68e

Please sign in to comment.