Files
ednotif-bundle/tests/Unit/Bovin/Mapper/BovinNodeMappingTraitTest.php
tristan 366143ce36
Some checks failed
Auto Tag Develop / tag (push) Failing after 16s
test : tests adversariaux InventoryMapper + docblock EarTagSeriesDto (#3)
| Numéro du ticket | Titre du ticket |
|------------------|-----------------|
|                  |                 |

## Description de la PR

## Modification du .env

## Check list

- [ ] Pas de régression
- [ ] TU/TI/TF rédigée
- [ ] TU/TI/TF OK
- [ ] CHANGELOG modifié

Reviewed-on: #3
Co-authored-by: tristan <tristan@yuno.malio.fr>
Co-committed-by: tristan <tristan@yuno.malio.fr>
2026-04-21 15:52:24 +00:00

191 lines
5.3 KiB
PHP

<?php
declare(strict_types=1);
namespace Malio\EdnotifBundle\Tests\Unit\Bovin\Mapper;
use DateTimeImmutable;
use Malio\EdnotifBundle\Bovin\Mapper\BovinNodeMappingTrait;
use PHPUnit\Framework\Attributes\CoversTrait;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use stdClass;
/**
* @internal
*/
#[CoversTrait(BovinNodeMappingTrait::class)]
final class BovinNodeMappingTraitTest extends TestCase
{
// ---------- normalizeToList ----------
public function testNormalizeToListWithNullReturnsEmptyList(): void
{
self::assertSame([], self::adapter()->normalizeToList(null));
}
public function testNormalizeToListWithScalarWrapsIntoList(): void
{
self::assertSame(['foo'], self::adapter()->normalizeToList('foo'));
self::assertSame([42], self::adapter()->normalizeToList(42));
}
public function testNormalizeToListWithObjectWrapsIntoList(): void
{
$obj = new stdClass();
$result = self::adapter()->normalizeToList($obj);
self::assertCount(1, $result);
self::assertSame($obj, $result[0]);
}
public function testNormalizeToListWithListReturnsListUnchanged(): void
{
$input = ['a', 'b', 'c'];
self::assertSame($input, self::adapter()->normalizeToList($input));
}
public function testNormalizeToListWithAssociativeArrayDiscardsKeys(): void
{
$input = ['x' => 'a', 'y' => 'b'];
$result = self::adapter()->normalizeToList($input);
self::assertSame(['a', 'b'], $result);
}
#[DataProvider('toNullableStringProvider')]
public function testToNullableString(mixed $input, ?string $expected): void
{
self::assertSame($expected, self::adapter()->toNullableString($input));
}
// ---------- toNullableString ----------
/** @return iterable<string,array{mixed, ?string}> */
public static function toNullableStringProvider(): iterable
{
yield 'null' => [null, null];
yield 'empty string' => ['', null];
yield 'whitespace only' => [' ', null];
yield 'plain' => ['abc', 'abc'];
yield 'trimmed' => [' abc ', 'abc'];
yield 'int coerced to string' => [42, '42'];
yield 'zero preserved' => ['0', '0'];
}
#[DataProvider('toNullableIntProvider')]
public function testToNullableInt(mixed $input, ?int $expected): void
{
self::assertSame($expected, self::adapter()->toNullableInt($input));
}
// ---------- toNullableInt ----------
/** @return iterable<string,array{mixed, ?int}> */
public static function toNullableIntProvider(): iterable
{
yield 'null' => [null, null];
yield 'int passthrough' => [42, 42];
yield 'zero int' => [0, 0];
yield 'numeric string' => ['42', 42];
yield 'negative string' => ['-7', -7];
yield 'float-like string' => ['3.14', 3];
yield 'non-numeric' => ['abc', null];
yield 'empty string' => ['', null];
}
#[DataProvider('toNullableBoolProvider')]
public function testToNullableBool(mixed $input, ?bool $expected): void
{
self::assertSame($expected, self::adapter()->toNullableBool($input));
}
// ---------- toNullableBool ----------
/** @return iterable<string,array{mixed, ?bool}> */
public static function toNullableBoolProvider(): iterable
{
yield 'null' => [null, null];
yield 'true' => [true, true];
yield 'false' => [false, false];
yield 'string 1' => ['1', true];
yield 'string 0' => ['0', false];
yield 'empty string' => ['', false];
yield 'int 1' => [1, true];
yield 'int 0' => [0, false];
}
// ---------- toNullableDate ----------
public function testToNullableDateFromIsoString(): void
{
$result = self::adapter()->toNullableDate('2026-04-21');
self::assertEquals(new DateTimeImmutable('2026-04-21'), $result);
}
public function testToNullableDateFromDateTimeString(): void
{
$result = self::adapter()->toNullableDate('2026-04-21T10:30:00+02:00');
self::assertEquals(new DateTimeImmutable('2026-04-21T10:30:00+02:00'), $result);
}
#[DataProvider('toNullableDateFallbackProvider')]
public function testToNullableDateReturnsNullOnInvalidInput(mixed $input): void
{
self::assertNull(self::adapter()->toNullableDate($input));
}
/** @return iterable<string,array{mixed}> */
public static function toNullableDateFallbackProvider(): iterable
{
yield 'null' => [null];
yield 'empty string' => [''];
yield 'whitespace' => [' '];
yield 'non-string int' => [42];
yield 'non-string array' => [[]];
yield 'invalid date string' => ['not-a-date'];
}
/**
* Adapter anonyme : re-expose chaque helper protected en public pour le test,
* sans jamais instancier un vrai mapper (ceux-ci ont des dépendances DI).
*/
private static function adapter(): object
{
return new class {
use BovinNodeMappingTrait {
normalizeToList as public;
toNullableString as public;
toNullableInt as public;
toNullableBool as public;
toNullableDate as public;
}
};
}
}