195 lines
5 KiB
PHP
195 lines
5 KiB
PHP
<?php
|
|
|
|
namespace Tests\DataObject;
|
|
|
|
use Icefox\DTO\Attributes\FromInput;
|
|
use Icefox\DTO\Attributes\FromRouteParameter;
|
|
use Icefox\DTO\Factories\DataObjectFactory;
|
|
use Illuminate\Support\Collection;
|
|
use Psr\Log\NullLogger;
|
|
|
|
readonly class Element
|
|
{
|
|
public function __construct(public int $value) {}
|
|
}
|
|
|
|
readonly class Node
|
|
{
|
|
public function __construct(public Element $element) {}
|
|
}
|
|
|
|
test('basic nested object', function () {
|
|
$input = DataObjectFactory::mapInput(Node::class, ['element' => ['value' => 1 ] ], [], new NullLogger());
|
|
expect($input)->toBe(['element' => ['value' => 1]]);
|
|
});
|
|
|
|
readonly class MappedElement
|
|
{
|
|
public function __construct(#[FromInput('name')] public int $value) {}
|
|
}
|
|
|
|
readonly class MappedNode
|
|
{
|
|
public function __construct(public MappedElement $element) {}
|
|
}
|
|
|
|
test('basic nested input map', function () {
|
|
$input = DataObjectFactory::mapInput(MappedNode::class, ['element' => ['name' => 1 ] ], [], new NullLogger());
|
|
expect($input)->toBe(['element' => ['value' => 1]]);
|
|
});
|
|
|
|
readonly class MappedCollectionItem
|
|
{
|
|
public function __construct(#[FromInput('id_item')] public int $idItem) {}
|
|
}
|
|
|
|
readonly class MappedCollectionRoot
|
|
{
|
|
/**
|
|
* @param Collection<int, MappedCollectionItem> $items
|
|
*/
|
|
public function __construct(public string $text, #[FromInput('data')] public Collection $items) {}
|
|
}
|
|
|
|
test('using from input nested', function () {
|
|
$mapped = DataObjectFactory::mapInput(MappedCollectionRoot::class, [
|
|
'text' => 'abc',
|
|
'data' => [
|
|
[ 'id_item' => 1 ],
|
|
[ 'id_item' => 2 ],
|
|
[ 'id_item' => 4 ],
|
|
[ 'id_item' => 8 ],
|
|
],
|
|
], [], new NullLogger());
|
|
|
|
expect($mapped)->toBe([
|
|
'text' => 'abc',
|
|
'items' => [
|
|
[ 'idItem' => 1 ],
|
|
[ 'idItem' => 2 ],
|
|
[ 'idItem' => 4 ],
|
|
[ 'idItem' => 8 ],
|
|
],
|
|
]);
|
|
});
|
|
|
|
readonly class CollectionRoot
|
|
{
|
|
/**
|
|
* @param Collection<int, MappedCollectionItem> $items
|
|
*/
|
|
public function __construct(public string $text, public Collection $items) {}
|
|
}
|
|
|
|
test('using from input', function () {
|
|
$mapped = DataObjectFactory::mapInput(MappedCollectionRoot::class, [
|
|
'text' => 'abc',
|
|
'items' => [
|
|
[ 'id_item' => 1 ],
|
|
[ 'id_item' => 2 ],
|
|
[ 'id_item' => 4 ],
|
|
[ 'id_item' => 8 ],
|
|
],
|
|
], [], new NullLogger());
|
|
|
|
expect($mapped)->toBe([
|
|
'text' => 'abc',
|
|
'items' => [
|
|
[ 'idItem' => 1 ],
|
|
[ 'idItem' => 2 ],
|
|
[ 'idItem' => 4 ],
|
|
[ 'idItem' => 8 ],
|
|
],
|
|
]);
|
|
});
|
|
|
|
readonly class AnnotatedArrayItem
|
|
{
|
|
public function __construct(#[FromInput('name')] public float $value) {}
|
|
}
|
|
|
|
readonly class AnnotatedArray
|
|
{
|
|
/**
|
|
* @param array<int,AnnotatedArrayItem> $items
|
|
*/
|
|
public function __construct(public array $items) {}
|
|
}
|
|
|
|
test('annotated array', function () {
|
|
$mapped = DataObjectFactory::mapInput(
|
|
AnnotatedArray::class,
|
|
['items' => [['name' => 1], ['name' => 2]]],
|
|
[],
|
|
new NullLogger(),
|
|
);
|
|
|
|
expect($mapped)->toBe(['items' => [['value' => 1], ['value' => 2]]]);
|
|
});
|
|
|
|
test('route parameter priority over from input', function () {
|
|
$dto = new class (123) {
|
|
public function __construct(
|
|
#[FromRouteParameter('user_id')]
|
|
#[FromInput('user_id')]
|
|
public int $id,
|
|
) {}
|
|
};
|
|
|
|
$result = DataObjectFactory::mapInput(
|
|
$dto::class,
|
|
['user_id' => 456],
|
|
['user_id' => 123],
|
|
new \Psr\Log\NullLogger(),
|
|
);
|
|
|
|
expect($result['id'])->toBe(123);
|
|
});
|
|
|
|
test('multiple route parameters', function () {
|
|
$dto = new class (45, 89, 'A') {
|
|
public function __construct(
|
|
#[FromRouteParameter('course_id')]
|
|
public int $courseId,
|
|
#[FromRouteParameter('student_id')]
|
|
public int $studentId,
|
|
#[FromInput('grade')]
|
|
public string $grade,
|
|
) {}
|
|
};
|
|
|
|
$result = DataObjectFactory::mapInput(
|
|
$dto::class,
|
|
['grade' => 'A'],
|
|
['course_id' => 45, 'student_id' => 89],
|
|
new \Psr\Log\NullLogger(),
|
|
);
|
|
|
|
expect($result['courseId'])->toBe(45)
|
|
->and($result['studentId'])->toBe(89)
|
|
->and($result['grade'])->toBe('A');
|
|
});
|
|
|
|
test('route parameter with nested object', function () {
|
|
$addressDto = new class ('Main St') {
|
|
public function __construct(public string $street) {}
|
|
};
|
|
|
|
$dto = new class (123, $addressDto) {
|
|
public function __construct(
|
|
#[FromRouteParameter('user_id')]
|
|
public int $userId,
|
|
public $address,
|
|
) {}
|
|
};
|
|
|
|
$result = DataObjectFactory::mapInput(
|
|
$dto::class,
|
|
['user_id' => 456, 'address' => ['street' => 'Main St']],
|
|
['user_id' => 123],
|
|
new \Psr\Log\NullLogger(),
|
|
);
|
|
|
|
expect($result['userId'])->toBe(123)
|
|
->and($result['address']['street'])->toBe('Main St');
|
|
});
|