with cast tests

This commit is contained in:
icefox 2026-02-18 20:29:13 -03:00
parent afb47c1977
commit 3a26a2e0c2
No known key found for this signature in database
8 changed files with 154 additions and 3 deletions

View file

@ -0,0 +1,71 @@
<?php
declare(strict_types=1);
namespace Tests;
use Illuminate\Validation\ValidationException;
use Tests\Casters\SimpleValue;
use Tests\Casters\SimpleValueCaster;
use Tests\Casters\WithGlobalCaster;
use Tests\Casters\WithSpecificCaster;
use Tests\Casters\WithoutCaster;
describe('caster priority', function () {
beforeEach(function () {
config(['dto.cast' => []]);
});
it('uses CastWith attribute over global config caster', function () {
$globalCaster = function (mixed $value): SimpleValue {
return new SimpleValue($value['value'] * 3);
};
config(['dto.cast.' . SimpleValue::class => $globalCaster]);
$object = WithSpecificCaster::fromArray([
'value' => ['value' => 5],
]);
expect($object->value->value)->toBe(10); // 5 * 2
});
it('falls back to global config caster when no CastWith attribute', function () {
$globalCaster = function (mixed $value): SimpleValue {
return new SimpleValue($value['value'] * 3);
};
config(['dto.cast.' . SimpleValue::class => $globalCaster]);
$object = WithGlobalCaster::fromArray([
'value' => ['value' => 5],
]);
expect($object->value->value)->toBe(15); // 5 * 3
});
it('falls back to default construction when no caster exists', function () {
$object = WithoutCaster::fromArray([
'value' => ['value' => 5],
]);
expect($object)->toBeInstanceOf(WithoutCaster::class);
});
});
describe('caster with rules', function () {
beforeEach(function () {
config(['dto.cast' => []]);
});
it('validates input using caster rules before casting', function () {
expect(fn() => WithSpecificCaster::fromArray([
'value' => [],
]))->toThrow(ValidationException::class);
});
it('accepts valid input and casts correctly', function () {
$object = WithSpecificCaster::fromArray([
'value' => ['value' => 10],
]);
expect($object->value->value)->toBe(20); // 10 * 2
});
});

View file

@ -0,0 +1,10 @@
<?php
declare(strict_types=1);
namespace Tests\Casters;
class SimpleValue
{
public function __construct(public readonly int $value) {}
}

View file

@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
namespace Tests\Casters;
class SimpleValueCaster
{
public function cast(mixed $value): SimpleValue
{
return new SimpleValue($value['value'] * 2);
}
public static function rules(): array
{
return [
'value' => ['required', 'numeric'],
];
}
}

View file

@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
namespace Tests\Casters;
use Icefox\DTO\DataObject;
readonly class WithGlobalCaster
{
use DataObject;
public function __construct(
public SimpleValue $value,
) {}
}

View file

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace Tests\Casters;
use Icefox\DTO\Attributes\CastWith;
use Icefox\DTO\DataObject;
readonly class WithSpecificCaster
{
use DataObject;
public function __construct(
#[CastWith(SimpleValueCaster::class)]
public SimpleValue $value,
) {}
}

View file

@ -0,0 +1,16 @@
<?php
declare(strict_types=1);
namespace Tests\Casters;
use Icefox\DTO\DataObject;
readonly class WithoutCaster
{
use DataObject;
public function __construct(
public SimpleValue $value,
) {}
}