input mapping
This commit is contained in:
parent
bba10b455f
commit
fc46fe20ee
29 changed files with 193 additions and 887 deletions
211
tests/Rules/RulesTest.php
Normal file
211
tests/Rules/RulesTest.php
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Rules;
|
||||
|
||||
use Icefox\DTO\Attributes\Flat;
|
||||
use Icefox\DTO\Attributes\Overwrite;
|
||||
use Icefox\DTO\RuleFactory;
|
||||
use Illuminate\Support\Collection;
|
||||
|
||||
readonly class BasicPrimitives
|
||||
{
|
||||
public function __construct(
|
||||
public string $text,
|
||||
public int $number,
|
||||
public bool $flag,
|
||||
public ?array $items,
|
||||
public float $floating = 0.0,
|
||||
) {}
|
||||
}
|
||||
|
||||
test('required rules', function () {
|
||||
expect(RuleFactory::instance()->make(BasicPrimitives::class))->toBe([
|
||||
'text' => ['required'],
|
||||
'number' => ['required', 'numeric'],
|
||||
'flag' => ['required', 'boolean'],
|
||||
'items' => ['nullable', 'array'],
|
||||
'floating' => ['sometimes', 'numeric'],
|
||||
]);
|
||||
});
|
||||
|
||||
readonly class AnnotatedArray
|
||||
{
|
||||
/**
|
||||
* @param array<int,float> $items
|
||||
*/
|
||||
public function __construct(public array $items) {}
|
||||
}
|
||||
test('annotated array', function () {
|
||||
expect(RuleFactory::instance()->make(AnnotatedArray::class))->toBe([
|
||||
'items' => ['required', 'array'],
|
||||
'items.*' => ['required', 'numeric'],
|
||||
]);
|
||||
});
|
||||
|
||||
readonly class AnnotatedArrayNullableValue
|
||||
{
|
||||
/**
|
||||
* @param array<?float> $items
|
||||
*/
|
||||
public function __construct(public array $items) {}
|
||||
}
|
||||
test('annotated array with nullable items', function () {
|
||||
expect(RuleFactory::instance()->make(AnnotatedArrayNullableValue::class))->toBe([
|
||||
'items' => ['required', 'array'],
|
||||
'items.*' => ['nullable', 'numeric'],
|
||||
]);
|
||||
});
|
||||
|
||||
readonly class PlainLeaf
|
||||
{
|
||||
public function __construct(public string $name) {}
|
||||
}
|
||||
readonly class PlainRoot
|
||||
{
|
||||
public function __construct(public int $value, public PlainLeaf $leaf) {}
|
||||
}
|
||||
|
||||
test('plain nesting', function () {
|
||||
expect(RuleFactory::instance()->make(PlainRoot::class))->toBe([
|
||||
'value' => ['required', 'numeric'],
|
||||
'leaf' => ['required'],
|
||||
'leaf.name' => ['required'],
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
readonly class AnnotatedArrayItem
|
||||
{
|
||||
public function __construct(public int $value) {}
|
||||
}
|
||||
|
||||
readonly class AnnotatedArrayObject
|
||||
{
|
||||
/**
|
||||
* @param ?array<AnnotatedArrayItem> $items
|
||||
*/
|
||||
public function __construct(public ?array $items) {}
|
||||
}
|
||||
|
||||
test('annotated array with object', function () {
|
||||
expect(RuleFactory::instance()->make(AnnotatedArrayObject::class))->toBe([
|
||||
'items' => ['nullable', 'array'],
|
||||
'items.*' => ['required'],
|
||||
'items.*.value' => ['required', 'numeric'],
|
||||
]);
|
||||
});
|
||||
|
||||
readonly class FlattenedLeaf
|
||||
{
|
||||
public function __construct(public ?bool $flag) {}
|
||||
}
|
||||
|
||||
readonly class NotFlattenedLeaf
|
||||
{
|
||||
public function __construct(public string $description) {}
|
||||
}
|
||||
|
||||
readonly class FlattenedNode
|
||||
{
|
||||
public function __construct(
|
||||
public string $id,
|
||||
public NotFlattenedLeaf $leaf,
|
||||
#[Flat]
|
||||
public FlattenedLeaf $squish,
|
||||
public int $level = 1,
|
||||
) {}
|
||||
}
|
||||
|
||||
readonly class FlattenedRoot
|
||||
{
|
||||
public function __construct(
|
||||
public int $value,
|
||||
#[Flat]
|
||||
public FlattenedNode $node,
|
||||
) {}
|
||||
}
|
||||
|
||||
test('flattened basic', function () {
|
||||
expect(RuleFactory::instance()->make(FlattenedRoot::class))->toBe([
|
||||
'value' => ['required', 'numeric'],
|
||||
'id' => ['required' ],
|
||||
'leaf' => ['required'],
|
||||
'leaf.description' => ['required'],
|
||||
'flag' => ['nullable', 'boolean'],
|
||||
'level' => ['sometimes', 'numeric'],
|
||||
]);
|
||||
});
|
||||
|
||||
readonly class AnnotatedCollectionItem
|
||||
{
|
||||
public function __construct(public int $value) {}
|
||||
}
|
||||
|
||||
readonly class AnnotatedCollection
|
||||
{
|
||||
/**
|
||||
* @param Collection<AnnotatedCollectionItem> $group
|
||||
*/
|
||||
public function __construct(public Collection $group) {}
|
||||
}
|
||||
|
||||
test('annotated collection', function () {
|
||||
expect(RuleFactory::instance()->make(AnnotatedCollection::class))->toBe([
|
||||
'group' => ['required', 'array'],
|
||||
'group.*' => ['required'],
|
||||
'group.*.value' => ['required', 'numeric'],
|
||||
]);
|
||||
});
|
||||
|
||||
|
||||
readonly class MergedRules
|
||||
{
|
||||
public function __construct(public int $value, public string $text) {}
|
||||
|
||||
/**
|
||||
* @return array<string,array<int,string>>
|
||||
*/
|
||||
public static function rules(): array
|
||||
{
|
||||
// only customized fields need to be provided
|
||||
return [
|
||||
'value' => ['min:20'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
test('merging rules', function () {
|
||||
expect(RuleFactory::instance()->make(MergedRules::class))->toBe([
|
||||
'value' => ['required', 'numeric', 'min:20'],
|
||||
'text' => ['required'],
|
||||
]);
|
||||
});
|
||||
|
||||
readonly class OverwriteRules
|
||||
{
|
||||
// union types are not supported, generated rules are undefined
|
||||
public function __construct(public int|bool $value, public string $text) {}
|
||||
|
||||
/**
|
||||
* @return array<string,array<int,mixed>>
|
||||
*/
|
||||
#[Overwrite]
|
||||
public static function rules(): array
|
||||
{
|
||||
// when overwriting, all fields must be provided with all rules, disables rules inference.
|
||||
return [
|
||||
'value' => ['required', function ($attribute, $value, $fail) {
|
||||
if (!is_int($value) && !is_bool($value)) {
|
||||
$fail("$attribute must be an integer or an array.");
|
||||
}
|
||||
}],
|
||||
'text' => ['required'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
test('overwriting rules', function () {
|
||||
expect(RuleFactory::instance()->make(OverwriteRules::class))->toHaveKeys(['value', 'text']);
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue