Skip to content

Commit

Permalink
Add tests to Doctrine Types functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
benr77 committed May 25, 2024
1 parent 22fc220 commit 311e908
Show file tree
Hide file tree
Showing 18 changed files with 454 additions and 17 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
composer.lock
src/_generated
var/
vendor/
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"symfony/config": "^6.0 || ^7.0",
"symfony/dependency-injection": "^6.0 || ^7.0",
"symfony/http-kernel": "^6.0 || ^7.0",
"doctrine/doctrine-bundle": "^2.0"
"doctrine/doctrine-bundle": "^2.0",
"symfony/uid": "^7.0"
},
"require-dev": {
"phpunit/phpunit": "^10.0",
Expand Down
4 changes: 2 additions & 2 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd"
bootstrap="vendor/autoload.php"
bootstrap="tests/bootstrap.php"
cacheDirectory="var/cache/.phpunit.cache"
executionOrder="depends,defects"
requireCoverageMetadata="true"
beStrictAboutCoverageMetadata="true"
beStrictAboutCoverageMetadata="false"
beStrictAboutOutputDuringTests="true"
displayDetailsOnTestsThatTriggerWarnings="true"
failOnRisky="true"
Expand Down
2 changes: 1 addition & 1 deletion src/Types/CandidateType.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

final class CandidateType
{
private string $baseTypeClass;
private string $baseTypeClass = '';

/**
* @param class-string $objectClass
Expand Down
3 changes: 3 additions & 0 deletions src/Types/StandardTypes/AbstractIntegerMappingType.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

abstract class AbstractIntegerMappingType extends Type
{
/**
* @codeCoverageIgnore
*/
public function getSQLDeclaration(array $column, AbstractPlatform $platform): string
{
return $platform->getIntegerTypeDeclarationSQL($column);
Expand Down
9 changes: 4 additions & 5 deletions src/Types/StandardTypes/AbstractStringMappingType.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

abstract class AbstractStringMappingType extends Type
{
/**
* @codeCoverageIgnore
*/
public function getSQLDeclaration(array $column, AbstractPlatform $platform): string
{
return $platform->getStringTypeDeclarationSQL($column);
Expand All @@ -32,11 +35,7 @@ public function convertToPHPValue($value, AbstractPlatform $platform): ?object
*/
public function convertToDatabaseValue($value, AbstractPlatform $platform): ?string
{
if ($value === null) {
return null;
}

return $value->asString(); // @phpstan-ignore-line
return $value?->asString(); // @phpstan-ignore-line
}

abstract public function getName(): string;
Expand Down
12 changes: 10 additions & 2 deletions src/Types/StandardTypes/AbstractUuidMappingType.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,20 @@

use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\Type;
use Symfony\Component\Uid\Uuid;

abstract class AbstractUuidMappingType extends Type
{
/**
* @codeCoverageIgnore
*/
public function getSQLDeclaration(array $column, AbstractPlatform $platform): string
{
return $platform->getGuidTypeDeclarationSQL($column);
}

/**
* @param string|null $value
* @param Uuid|string|null $value
*/
public function convertToPHPValue($value, AbstractPlatform $platform): ?object
{
Expand All @@ -24,7 +28,11 @@ public function convertToPHPValue($value, AbstractPlatform $platform): ?object

$class = $this->getClass();

return $class::fromString($value);
if (is_string($value)) {
return $class::fromString($value);
}

return $class::create($value);
}

/**
Expand Down
24 changes: 24 additions & 0 deletions tests/Attribute/DoctrineTypeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php
declare(strict_types=1);

namespace Headsnet\DoctrineToolsBundle\Tests\Attribute;

use Headsnet\DoctrineToolsBundle\Attribute\DoctrineType;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;

#[CoversClass(DoctrineType::class)]
class DoctrineTypeTest extends TestCase
{
#[Test]
public function name_can_be_specified(): void
{
$sut = new DoctrineType(
name: 'custom_name',
type: 'string',
);

$this->assertEquals('custom_name', $sut->name);
}
}
6 changes: 0 additions & 6 deletions tests/HeadsnetDoctrineToolsBundleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,13 @@
namespace Headsnet\DoctrineToolsBundle\Tests;

use Headsnet\DoctrineToolsBundle\HeadsnetDoctrineToolsBundle;
use Headsnet\DoctrineToolsBundle\Mapping\CarbonTypeMappingsCompilerPass;
use Headsnet\DoctrineToolsBundle\Mapping\DoctrineTypeMappingsCompilerPass;
use Headsnet\DoctrineToolsBundle\Types\DoctrineTypesCompilerPass;
use Nyholm\BundleTest\TestKernel;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\HttpKernel\KernelInterface;

#[CoversClass(HeadsnetDoctrineToolsBundle::class)]
#[CoversClass(CarbonTypeMappingsCompilerPass::class)]
#[CoversClass(DoctrineTypeMappingsCompilerPass::class)]
#[CoversClass(DoctrineTypesCompilerPass::class)]
class HeadsnetDoctrineToolsBundleTest extends KernelTestCase
{
protected static function getKernelClass(): string
Expand Down
64 changes: 64 additions & 0 deletions tests/Types/DoctrineTypesCompilerPassTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php
declare(strict_types=1);

namespace Headsnet\DoctrineToolsBundle\Tests\Types;

use Headsnet\DoctrineToolsBundle\HeadsnetDoctrineToolsBundle;
use Headsnet\DoctrineToolsBundle\Types\CandidateType;
use Headsnet\DoctrineToolsBundle\Types\DoctrineTypesCompilerPass;
use Headsnet\DoctrineToolsBundle\Types\StandardTypes\IntegerMappingPrototype;
use Headsnet\DoctrineToolsBundle\Types\StandardTypes\StringMappingPrototype;
use Headsnet\DoctrineToolsBundle\Types\StandardTypes\UuidMappingPrototype;
use Nyholm\BundleTest\TestKernel;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\Test;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Symfony\Component\HttpKernel\KernelInterface;

#[CoversClass(DoctrineTypesCompilerPass::class)]
#[CoversClass(StringMappingPrototype::class)]
#[CoversClass(IntegerMappingPrototype::class)]
#[CoversClass(UuidMappingPrototype::class)]
#[CoversClass(CandidateType::class)]
class DoctrineTypesCompilerPassTest extends KernelTestCase
{
protected static function getKernelClass(): string
{
return TestKernel::class;
}

/**
* @param array{debug?: bool, environment?: string} $options
*/
protected static function createKernel(array $options = []): KernelInterface
{
/** @var TestKernel $kernel $kernel */
$kernel = parent::createKernel($options);
$kernel->addTestBundle(HeadsnetDoctrineToolsBundle::class);
$kernel->addTestConfig(__DIR__ . '/Fixtures/config.yaml');
$kernel->handleOptions($options);

return $kernel;
}

#[Test]
public function can_find_and_register_types(): void
{
$kernel = self::bootKernel();
$container = $kernel->getContainer();
$result = $container->getParameter('doctrine.dbal.connection_factory.types');

$expected = [
'dummy_string' => [
'class' => 'Headsnet\DoctrineToolsBundle\_generated\HeadsnetDoctrineTools\Types\DummyStringObjectType',
],
'dummy_integer' => [
'class' => 'Headsnet\DoctrineToolsBundle\_generated\HeadsnetDoctrineTools\Types\DummyIntegerObjectType',
],
'dummy_uuid' => [
'class' => 'Headsnet\DoctrineToolsBundle\_generated\HeadsnetDoctrineTools\Types\DummyUuidObjectType',
],
];
$this->assertEquals($expected, $result);
}
}
25 changes: 25 additions & 0 deletions tests/Types/Fixtures/DummyIntegerObject.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);

namespace Headsnet\DoctrineToolsBundle\Tests\Types\Fixtures;

use Headsnet\DoctrineToolsBundle\Attribute\DoctrineType;

#[DoctrineType(name: 'dummy_integer', type: 'integer')]
class DummyIntegerObject
{
public function __construct(
private readonly int $value
) {
}

public static function create(int $value): self
{
return new self($value);
}

public function asInteger(): int
{
return $this->value;
}
}
25 changes: 25 additions & 0 deletions tests/Types/Fixtures/DummyStringObject.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
declare(strict_types=1);

namespace Headsnet\DoctrineToolsBundle\Tests\Types\Fixtures;

use Headsnet\DoctrineToolsBundle\Attribute\DoctrineType;

#[DoctrineType(name: 'dummy_string', type: 'string')]
class DummyStringObject
{
public function __construct(
private readonly string $value
) {
}

public static function create(string $value): self
{
return new self($value);
}

public function asString(): string
{
return $this->value;
}
}
31 changes: 31 additions & 0 deletions tests/Types/Fixtures/DummyUuidObject.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php
declare(strict_types=1);

namespace Headsnet\DoctrineToolsBundle\Tests\Types\Fixtures;

use Headsnet\DoctrineToolsBundle\Attribute\DoctrineType;
use Symfony\Component\Uid\Uuid;

#[DoctrineType(name: 'dummy_uuid', type: 'uuid')]
class DummyUuidObject
{
public function __construct(
private readonly Uuid $value
) {
}

public static function create(Uuid $value): self
{
return new self($value);
}

public static function fromString(string $value): self
{
return new self(Uuid::fromString($value));
}

public function asString(): string
{
return $this->value->toRfc4122();
}
}
13 changes: 13 additions & 0 deletions tests/Types/Fixtures/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

headsnet_doctrine_tools:
root_namespace: Headsnet\DoctrineToolsBundle
custom_types:
scan_dirs:
- './tests/Types/Fixtures'
carbon_mappings:
enabled: false
custom_mappings:
scan_dirs: []

parameters:
doctrine.dbal.connection_factory.types: []
77 changes: 77 additions & 0 deletions tests/Types/StandardTypes/AbstractIntegerMappingTypeTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<?php
declare(strict_types=1);

namespace Headsnet\DoctrineToolsBundle\Tests\Types\StandardTypes;

use Doctrine\DBAL\Platforms\AbstractPlatform;
use Headsnet\DoctrineToolsBundle\Tests\Types\Fixtures\DummyIntegerObject;
use Headsnet\DoctrineToolsBundle\Types\StandardTypes\AbstractIntegerMappingType;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;

#[CoversClass(AbstractIntegerMappingType::class)]
class AbstractIntegerMappingTypeTest extends TestCase
{
#[Test]
#[DataProvider('phpDataProvider')]
public function converting_to_php_value(int|null $value, object|null $expectedResult): void
{
$sut = $this->buildSut();

$result = $sut->convertToPHPValue(
$value,
$this->createMock(AbstractPlatform::class)
);

$this->assertEquals($expectedResult, $result);
}

/**
* @return iterable<array{0: int|null, 1: DummyIntegerObject|null}>
*/
public static function phpDataProvider(): iterable
{
yield [42, DummyIntegerObject::create(42)];
yield [null, null];
}

#[Test]
#[DataProvider('databaseDataProvider')]
public function converting_to_database_value(object|null $value, int|null $expectedResult): void
{
$sut = $this->buildSut();

$result = $sut->convertToDatabaseValue(
$value,
$this->createMock(AbstractPlatform::class)
);

$this->assertEquals($expectedResult, $result);
}

/**
* @return iterable<array{0: DummyIntegerObject|null, 1: int|null}>
*/
public static function databaseDataProvider(): iterable
{
yield [DummyIntegerObject::create(42), 42];
yield [null, null];
}

private function buildSut(): AbstractIntegerMappingType
{
return new class() extends AbstractIntegerMappingType {
public function getName(): string
{
return 'dummy';
}

public function getClass(): string
{
return DummyIntegerObject::class;
}
};
}
}
Loading

0 comments on commit 311e908

Please sign in to comment.