data-transfer-object/tests/DataObjectTest.php
2026-02-18 19:24:17 -03:00

223 lines
7.1 KiB
PHP

<?php
namespace Tests;
use Icefox\DTO\Support\RuleFactory;
use Illuminate\Validation\ValidationException;
use Tests\Classes\ArrayDataObject;
use Tests\Classes\CollectionDataObject;
use Tests\Classes\FromInputObject;
use Tests\Classes\ObjectWithoutMapper;
use Tests\Classes\OptionalData;
use Tests\Classes\OptionalNullableData;
use Tests\Classes\PrimitiveData;
use Tests\Classes\RecursiveDataObject;
use Tests\Classes\WithMapperObject;
describe('primitive data test', function () {
it('creates required rules', function () {
$rules = RuleFactory::buildRules(RuleFactory::getParametersMeta(PrimitiveData::class), '');
expect($rules)->toMatchArray([
'string' => ['required'],
'int' => ['required', 'numeric'],
'float' => ['required', 'numeric'],
'bool' => ['required', 'boolean'],
]);
});
it('creates object with all required properties', function () {
$object = PrimitiveData::fromArray([
'string' => 'abc',
'int' => 0,
'float' => 3.14,
'bool' => true,
]);
expect($object)->toBeInstanceOf(PrimitiveData::class);
expect($object->string)->toBe('abc');
expect($object->int)->toBe(0);
expect($object->float)->toEqualWithDelta(3.14, 0.0001);
expect($object->bool)->toBeTrue();
});
});
describe('optional data', function () {
it('creates optional rules', function () {
$rules = RuleFactory::buildRules(RuleFactory::getParametersMeta(OptionalData::class), '');
expect($rules)->toMatchArray([
'string' => ['sometimes'],
'int' => ['sometimes', 'numeric'],
'float' => ['sometimes', 'numeric'],
'bool' => ['sometimes', 'boolean'],
]);
});
it('creates object with default values', function () {
$object = OptionalData::fromArray([]);
expect($object)->toBeInstanceOf(OptionalData::class);
expect($object->string)->toBe('xyz');
expect($object->int)->toBe(3);
expect($object->float)->toEqualWithDelta(0.777, 0.0001);
expect($object->bool)->toBeFalse();
});
});
describe('nullable data', function () {
it('creates nullable rules', function () {
$rules = RuleFactory::buildRules(RuleFactory::getParametersMeta(OptionalNullableData::class), '');
expect($rules)->toMatchArray([
'string' => ['required'],
'int' => ['nullable', 'numeric'],
'float' => ['sometimes', 'numeric'],
'bool' => ['sometimes', 'boolean'],
]);
});
it('accepts explicit null', function () {
$object = OptionalNullableData::fromArray([
'string' => 'ijk',
'int' => null,
]);
expect($object)->toBeInstanceOf(OptionalNullableData::class);
expect($object->string)->toBe('ijk');
expect($object->int)->toBeNull();
});
it('accepts implicit null', function () {
$object = OptionalNullableData::fromArray(['string' => 'dfg']);
expect($object)->toBeInstanceOf(OptionalNullableData::class);
expect($object->string)->toBe('dfg');
expect($object->int)->toBeNull();
});
});
describe('reference other DataObject', function () {
it('creates recursive rules', function () {
$rules = RuleFactory::buildRules(
RuleFactory::getParametersMeta(RecursiveDataObject::class),
'',
);
expect($rules)->toMatchArray([
'string' => ['required'],
'extra.string' => ['required'],
'extra.int' => ['required', 'numeric'],
'extra.float' => ['required', 'numeric'],
'extra.bool' => ['required', 'boolean'],
]);
});
});
describe('primitive array', function () {
it('creates array rules', function () {
$rules = RuleFactory::buildRules(RuleFactory::getParametersMeta(ArrayDataObject::class), '');
expect($rules)->toMatchArray([
'values' => ['required', 'array'],
'values.*' => ['required', 'numeric'],
]);
});
});
describe('object array', function () {
it('creates array rules', function () {
$rules = RuleFactory::buildRules(
RuleFactory::getParametersMeta(CollectionDataObject::class),
'',
);
expect($rules)->toMatchArray([
'values' => ['required', 'array'],
'values.*' => ['required'],
'values.*.string' => ['required'],
'values.*.int' => ['nullable', 'numeric'],
'values.*.float' => ['sometimes', 'numeric'],
'values.*.bool' => ['sometimes', 'boolean'],
]);
});
});
describe('can map input names', function () {
it('creates rules with property names', function () {
$rules = RuleFactory::buildRules(RuleFactory::getParametersMeta(FromInputObject::class), '');
expect($rules)->toMatchArray([
'text' => ['required' ],
'standard' => ['required', 'numeric'],
]);
});
it('maps input name', function () {
$object = FromInputObject::fromArray([
'other_name' => 'xyz',
'standard' => 1,
]);
expect($object->text)->toBe('xyz');
expect($object->standard)->toBe(1);
});
it('prioritizes the mapped input', function () {
$object = FromInputObject::fromArray([
'other_name' => 'xyz',
'text' => 'abc',
'standard' => 1,
]);
expect($object->text)->toBe('xyz');
expect($object->standard)->toBe(1);
});
});
describe('with mapper object', function () {
it('uses mapper', function () {
$object = WithMapperObject::fromArray([
'period' => [
'start' => '1980-01-01',
'end' => '1990-01-01',
],
'standard' => 1,
]);
expect($object->period->startsAt('1980-01-01'))->toBeTrue();
expect($object->period->endsAt('1990-01-01'))->toBeTrue();
});
it('uses mapper as validator', function () {
$object = WithMapperObject::fromArray([
'period' => [
'end' => '1990-01-01',
],
'standard' => 1,
]);
})->throws(ValidationException::class);
});
test('failed validation throws ValidationException', function () {
$object = PrimitiveData::fromArray([
'int' => 0,
'float' => 3.14,
'bool' => true,
]);
})->throws(ValidationException::class);
test('tries to resolve without mapper', function () {
$object = ObjectWithoutMapper::fromArray(['date' => '1990-04-01']);
expect($object->date->isSameDay('1990-04-01'))->toBeTrue();
})->group('object-without-mapper');
test('creates collection', function () {
$object = CollectionDataObject::fromArray([
'values' => [
[
'string' => 'x',
'int' => 1,
'float' => 3.3,
],
[
'string' => 'y',
'int' => null,
],
],
]);
expect($object->values->count())->toBe(2);
expect($object->values[0]->string)->toBe('x');
expect($object->values[1]->int)->toBeNull();
});