Skip to content

Commit 05a0afe

Browse files
chore: improve test coverage in unit tests (#384)
1 parent 8679690 commit 05a0afe

File tree

8 files changed

+205
-28
lines changed

8 files changed

+205
-28
lines changed

src/MartinGeorgiev/Doctrine/DBAL/Types/ValueObject/Point.php

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
*/
1212
final class Point implements \Stringable
1313
{
14-
private const POINT_REGEX = '/\((-?\d+(?:\.\d{1,6})?),\s*(-?\d+(?:\.\d{1,6})?)\)/';
14+
private const COORDINATE_PATTERN = '-?\d+(?:\.\d{1,6})?';
15+
16+
private const POINT_REGEX = '/\(('.self::COORDINATE_PATTERN.'),\s*('.self::COORDINATE_PATTERN.')\)/';
1517

1618
public function __construct(
1719
private readonly float $x,
@@ -51,7 +53,8 @@ private function validateCoordinate(float $value, string $name): void
5153
{
5254
$stringValue = (string) $value;
5355

54-
if (!\preg_match('/^-?\d+(\.\d{1,6})?$/', $stringValue)) {
56+
$floatRegex = '/^'.self::COORDINATE_PATTERN.'$/';
57+
if (!\preg_match($floatRegex, $stringValue)) {
5558
throw new \InvalidArgumentException(
5659
\sprintf('Invalid %s coordinate format: %s', $name, $stringValue)
5760
);

tests/Unit/MartinGeorgiev/Doctrine/DBAL/Types/BaseFloatArrayTestCase.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
namespace Tests\Unit\MartinGeorgiev\Doctrine\DBAL\Types;
66

7-
use Doctrine\DBAL\Types\ConversionException;
87
use MartinGeorgiev\Doctrine\DBAL\Types\BaseFloatArray;
8+
use MartinGeorgiev\Doctrine\DBAL\Types\Exceptions\InvalidFloatArrayItemForPHPException;
99
use PHPUnit\Framework\Attributes\DataProvider;
1010
use PHPUnit\Framework\Attributes\Test;
1111
use PHPUnit\Framework\TestCase;
@@ -64,7 +64,7 @@ abstract public static function provideValidTransformations(): array;
6464
#[Test]
6565
public function throws_domain_exception_when_invalid_array_item_value(): void
6666
{
67-
$this->expectException(ConversionException::class);
67+
$this->expectException(InvalidFloatArrayItemForPHPException::class);
6868
$this->expectExceptionMessage('cannot be transformed to valid PHP float');
6969

7070
$this->fixture->transformArrayItemForPHP('1.e234');

tests/Unit/MartinGeorgiev/Doctrine/DBAL/Types/BaseNetworkTypeArrayTest.php

Lines changed: 37 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use Doctrine\DBAL\Platforms\AbstractPlatform;
88
use MartinGeorgiev\Doctrine\DBAL\Types\BaseNetworkTypeArray;
9+
use PHPUnit\Framework\Attributes\DataProvider;
910
use PHPUnit\Framework\Attributes\Test;
1011
use PHPUnit\Framework\MockObject\MockObject;
1112
use PHPUnit\Framework\TestCase;
@@ -55,24 +56,28 @@ public function has_name(): void
5556
}
5657

5758
#[Test]
58-
public function can_convert_null_to_database_value(): void
59+
#[DataProvider('provideValidTransformations')]
60+
public function can_convert_to_php_value(?array $phpValue, ?string $postgresValue): void
5961
{
60-
self::assertNull($this->fixture->convertToDatabaseValue(null, $this->platform));
62+
self::assertEquals($phpValue, $this->fixture->convertToPHPValue($postgresValue, $this->platform));
6163
}
6264

63-
#[Test]
64-
public function can_convert_empty_array_to_database_value(): void
65+
public static function provideValidTransformations(): array
6566
{
66-
self::assertEquals('{}', $this->fixture->convertToDatabaseValue([], $this->platform));
67-
}
68-
69-
#[Test]
70-
public function can_convert_valid_array_to_database_value(): void
71-
{
72-
self::assertEquals(
73-
'{"valid_address","valid_address"}',
74-
$this->fixture->convertToDatabaseValue(['valid_address', 'valid_address'], $this->platform)
75-
);
67+
return [
68+
'null' => [
69+
'phpValue' => null,
70+
'postgresValue' => null,
71+
],
72+
'empty array' => [
73+
'phpValue' => [],
74+
'postgresValue' => '{}',
75+
],
76+
'valid array' => [
77+
'phpValue' => ['valid_address', 'valid_address'],
78+
'postgresValue' => '{"valid_address","valid_address"}',
79+
],
80+
];
7681
}
7782

7883
#[Test]
@@ -84,23 +89,31 @@ public function throws_exception_for_invalid_type(): void
8489
}
8590

8691
#[Test]
87-
public function can_convert_null_to_php_value(): void
92+
#[DataProvider('provideInvalidValues')]
93+
public function throws_exception_for_invalid_values(mixed $arrayItem, string $exceptionMessage): void
8894
{
89-
self::assertNull($this->fixture->convertToPHPValue(null, $this->platform));
95+
$this->expectException(\InvalidArgumentException::class);
96+
$this->expectExceptionMessage($exceptionMessage);
97+
$this->fixture->transformArrayItemForPHP($arrayItem);
9098
}
9199

92-
#[Test]
93-
public function can_convert_empty_array_to_php_value(): void
100+
public static function provideInvalidValues(): array
94101
{
95-
self::assertEquals([], $this->fixture->convertToPHPValue('{}', $this->platform));
102+
return [
103+
'invalid type' => [
104+
'arrayItem' => [],
105+
'exceptionMessage' => 'Invalid type',
106+
],
107+
'invalid format' => [
108+
'arrayItem' => '"invalid_address"',
109+
'exceptionMessage' => 'Invalid format',
110+
],
111+
];
96112
}
97113

98114
#[Test]
99-
public function can_convert_valid_string_to_php_value(): void
115+
public function transform_array_item_for_php_handles_valid_string(): void
100116
{
101-
self::assertEquals(
102-
['valid_address', 'valid_address'],
103-
$this->fixture->convertToPHPValue('{"valid_address","valid_address"}', $this->platform)
104-
);
117+
$this->assertSame('valid_address', $this->fixture->transformArrayItemForPHP('"valid_address"'));
105118
}
106119
}

tests/Unit/MartinGeorgiev/Doctrine/DBAL/Types/PointArrayTest.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,4 +191,37 @@ public function returns_empty_array_for_non_standard_postgres_array_format(): vo
191191
self::assertEquals([], $result1);
192192
self::assertEquals([], $result2);
193193
}
194+
195+
#[Test]
196+
public function transform_array_item_for_php_returns_null_for_null(): void
197+
{
198+
$this->assertNull($this->fixture->transformArrayItemForPHP(null));
199+
}
200+
201+
#[Test]
202+
#[DataProvider('provideInvalidTypes')]
203+
public function transform_array_item_for_php_throws_for_invalid_type(mixed $value): void
204+
{
205+
$this->expectException(InvalidPointArrayItemForPHPException::class);
206+
$this->fixture->transformArrayItemForPHP($value);
207+
}
208+
209+
#[Test]
210+
#[DataProvider('provideInvalidTypes')]
211+
public function transform_postgres_array_to_php_array_returns_empty_for_invalid_format(mixed $value): void
212+
{
213+
$reflectionObject = new \ReflectionObject($this->fixture);
214+
$reflectionMethod = $reflectionObject->getMethod('transformPostgresArrayToPHPArray');
215+
$reflectionMethod->setAccessible(true);
216+
$this->assertSame([], $reflectionMethod->invoke($this->fixture, $value));
217+
}
218+
219+
public static function provideInvalidTypes(): array
220+
{
221+
return [
222+
[123],
223+
['not-a-point-instance'],
224+
['{invalid}'],
225+
];
226+
}
194227
}

tests/Unit/MartinGeorgiev/Doctrine/DBAL/Types/PointTest.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,4 +122,19 @@ public static function provideInvalidDatabaseValues(): array
122122
'float precision is too granular' => ['(1.23456789,7.89)'],
123123
];
124124
}
125+
126+
#[Test]
127+
public function allows_coordinate_with_exactly_6_decimal_places(): void
128+
{
129+
$point = new PointValueObject(1.123456, 2.654321);
130+
$this->assertSame(1.123456, $point->getX());
131+
$this->assertSame(2.654321, $point->getY());
132+
}
133+
134+
#[Test]
135+
public function throws_for_coordinate_with_more_than_6_decimal_places(): void
136+
{
137+
$this->expectException(\InvalidArgumentException::class);
138+
new PointValueObject(1.1234567, 2.0);
139+
}
125140
}

tests/Unit/MartinGeorgiev/Doctrine/ORM/Query/AST/Functions/BaseVariadicFunctionTestCase.php

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,10 @@
77
use Doctrine\ORM\Configuration;
88
use Doctrine\ORM\EntityManager;
99
use Doctrine\ORM\Query;
10+
use Doctrine\ORM\Query\AST\Node;
1011
use Doctrine\ORM\Query\Parser;
1112
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\BaseVariadicFunction;
13+
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\InvalidArgumentForVariadicFunctionException;
1214
use MartinGeorgiev\Doctrine\ORM\Query\AST\Functions\Exception\ParserException;
1315
use PHPUnit\Framework\Attributes\Test;
1416

@@ -38,4 +40,70 @@ public function throws_an_exception_when_lexer_is_not_populated_with_a_lookahead
3840
$reflectionMethod->setAccessible(true);
3941
$reflectionMethod->invoke($baseVariadicFunction, $parser, 'ArithmeticPrimary');
4042
}
43+
44+
#[Test]
45+
public function throws_exception_when_argument_count_is_too_low(): void
46+
{
47+
$function = new class('TEST') extends BaseVariadicFunction {
48+
protected function getFunctionName(): string
49+
{
50+
return 'TEST';
51+
}
52+
53+
protected function getNodeMappingPattern(): array
54+
{
55+
return ['StringPrimary'];
56+
}
57+
58+
protected function getMinArgumentCount(): int
59+
{
60+
return 2;
61+
}
62+
63+
protected function getMaxArgumentCount(): int
64+
{
65+
return 3;
66+
}
67+
};
68+
$this->expectException(InvalidArgumentForVariadicFunctionException::class);
69+
$reflectionClass = new \ReflectionClass($function);
70+
$reflectionMethod = $reflectionClass->getMethod('validateArguments');
71+
$reflectionMethod->setAccessible(true);
72+
73+
$node = $this->createMock(Node::class);
74+
$reflectionMethod->invoke($function, $node); // 1 argument when min 2 are required
75+
}
76+
77+
#[Test]
78+
public function throws_exception_when_argument_count_is_too_high(): void
79+
{
80+
$function = new class('TEST') extends BaseVariadicFunction {
81+
protected function getFunctionName(): string
82+
{
83+
return 'TEST';
84+
}
85+
86+
protected function getNodeMappingPattern(): array
87+
{
88+
return ['StringPrimary'];
89+
}
90+
91+
protected function getMinArgumentCount(): int
92+
{
93+
return 1;
94+
}
95+
96+
protected function getMaxArgumentCount(): int
97+
{
98+
return 2;
99+
}
100+
};
101+
$this->expectException(InvalidArgumentForVariadicFunctionException::class);
102+
$reflectionClass = new \ReflectionClass($function);
103+
$reflectionMethod = $reflectionClass->getMethod('validateArguments');
104+
$reflectionMethod->setAccessible(true);
105+
106+
$node = $this->createMock(Node::class);
107+
$reflectionMethod->invoke($function, $node, $node, $node); // 3 arguments when max 2 are required
108+
}
41109
}

tests/Unit/MartinGeorgiev/Utils/PHPArrayToPostgresValueTransformerTest.php

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,18 @@ public static function provideValidTransformations(): array
104104
'phpValue' => ['Hello 世界', '🌍 Earth'],
105105
'postgresValue' => '{"Hello 世界","🌍 Earth"}',
106106
],
107+
'with only nulls' => [
108+
'phpValue' => [null, null],
109+
'postgresValue' => '{NULL,NULL}',
110+
],
111+
'with only booleans' => [
112+
'phpValue' => [true, false, true],
113+
'postgresValue' => '{true,false,true}',
114+
],
115+
'with empty empty strings' => [
116+
'phpValue' => ['', ''],
117+
'postgresValue' => '{"",""}',
118+
],
107119
];
108120
}
109121

@@ -237,4 +249,17 @@ public static function provideMultiDimensionalArrays(): array
237249
],
238250
];
239251
}
252+
253+
#[Test]
254+
public function can_transform_array_with_gd_resource(): void
255+
{
256+
if (!\function_exists('imagecreatetruecolor')) {
257+
$this->markTestSkipped('GD extension not available');
258+
}
259+
260+
$resource = \imagecreatetruecolor(1, 1);
261+
$result = PHPArrayToPostgresValueTransformer::transformToPostgresTextArray([$resource]);
262+
$this->assertStringContainsString('GdImage', $result);
263+
\imagedestroy($resource);
264+
}
240265
}

tests/Unit/MartinGeorgiev/Utils/PostgresArrayToPHPArrayTransformerTest.php

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,26 @@ public static function provideValidTransformations(): array
122122
'phpValue' => ['quoted', 'unquoted'],
123123
'postgresValue' => '{"quoted",unquoted}',
124124
],
125+
'only whitespace' => [
126+
'phpValue' => [],
127+
'postgresValue' => ' ',
128+
],
129+
'with trailing comma' => [
130+
'phpValue' => ['a'],
131+
'postgresValue' => '{a,}}',
132+
],
133+
'with only backslashes' => [
134+
'phpValue' => ['\\'],
135+
'postgresValue' => '{\}',
136+
],
137+
'with only double quotes' => [
138+
'phpValue' => ['"'],
139+
'postgresValue' => '{"\""}',
140+
],
141+
'with empty quoted strings' => [
142+
'phpValue' => ['', ''],
143+
'postgresValue' => '{"",""}',
144+
],
125145
];
126146
}
127147

0 commit comments

Comments
 (0)