Valinor/tests/Integration/Mapping/Source/SourceTest.php
Nathan Boiron ad51039cc3
feat: introduce a source builder
The `Source` class is a new entry point for sources that are not plain 
array or iterable. It allows accessing other features like camel-case 
keys or custom paths mapping in a convenient way.

It should be used as follows:

```php
$source = \CuyZ\Valinor\Mapper\Source\Source::json($jsonString)
    ->camelCaseKeys()
    ->map([
        'towns' => 'cities',
        'towns.*.label' => 'name',
    ]);

$result = (new \CuyZ\Valinor\MapperBuilder())
    ->mapper()
    ->map(SomeClass::class, $source);
```
2022-03-24 14:23:03 +01:00

163 lines
4.7 KiB
PHP

<?php
declare(strict_types=1);
namespace CuyZ\Valinor\Tests\Integration\Mapping\Source;
use CuyZ\Valinor\Mapper\MappingError;
use CuyZ\Valinor\Mapper\Source\Source;
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
use IteratorAggregate;
use Traversable;
final class SourceTest extends IntegrationTest
{
public function test_iterable_source(): void
{
try {
$object = $this->mapperBuilder->mapper()->map(
SomeClassWithSubProperty::class,
Source::iterable(new SomeIterableClass())
);
} catch (MappingError $error) {
$this->mappingFail($error);
}
self::assertSame('foo', $object->someNestedValue->someValue);
}
public function test_array_source(): void
{
try {
$object = $this->mapperBuilder->mapper()->map(
SomeClassWithSubProperty::class,
Source::array(['someNestedValue' => ['someValue' => 'foo']])
);
} catch (MappingError $error) {
$this->mappingFail($error);
}
self::assertSame('foo', $object->someNestedValue->someValue);
}
public function test_json_source(): void
{
try {
$object = $this->mapperBuilder->mapper()->map(
SomeClassWithSubProperty::class,
Source::json('{"someNestedValue": {"someValue": "foo"}}')
);
} catch (MappingError $error) {
$this->mappingFail($error);
}
self::assertSame('foo', $object->someNestedValue->someValue);
}
public function test_yaml_source(): void
{
try {
$object = $this->mapperBuilder->mapper()->map(
SomeClassWithSubProperty::class,
Source::yaml("someNestedValue:\n someValue: foo")
);
} catch (MappingError $error) {
$this->mappingFail($error);
}
self::assertSame('foo', $object->someNestedValue->someValue);
}
public function test_camel_case_keys(): void
{
try {
$object = $this->mapperBuilder->mapper()->map(
SomeClassWithSubProperty::class,
Source::json('{"some nested value": {"some value": "foo"}}')
->camelCaseKeys()
);
} catch (MappingError $error) {
$this->mappingFail($error);
}
self::assertSame('foo', $object->someNestedValue->someValue);
}
public function test_path_mapping(): void
{
try {
$object = $this->mapperBuilder->mapper()->map(
SomeClassWithSubProperty::class,
Source::json('{"A": {"B": "foo"}}')
->map([
'A' => 'someNestedValue',
'A.B' => 'someValue',
])
);
} catch (MappingError $error) {
$this->mappingFail($error);
}
self::assertSame('foo', $object->someNestedValue->someValue);
}
public function test_camel_case_keys_then_path_mapping(): void
{
try {
$object = $this->mapperBuilder->mapper()->map(
SomeClassWithSubProperty::class,
Source::json('{"level-one": {"level-two": "foo"}}')
->camelCaseKeys()
->map([
'levelOne' => 'someNestedValue',
'levelOne.levelTwo' => 'someValue',
])
);
} catch (MappingError $error) {
$this->mappingFail($error);
}
self::assertSame('foo', $object->someNestedValue->someValue);
}
public function test_path_mapping_then_camel_case_keys(): void
{
try {
$object = $this->mapperBuilder->mapper()->map(
SomeClassWithSubProperty::class,
Source::json('{"level-one": {"level-two": "foo"}}')
->map([
'level-one' => 'some-nested-value',
'level-one.level-two' => 'some-value',
])
->camelCaseKeys()
);
} catch (MappingError $error) {
$this->mappingFail($error);
}
self::assertSame('foo', $object->someNestedValue->someValue);
}
}
final class SomeClassWithSingleProperty
{
public string $someValue;
}
final class SomeClassWithSubProperty
{
public SomeClassWithSingleProperty $someNestedValue;
}
/**
* @implements IteratorAggregate<mixed>
*/
final class SomeIterableClass implements IteratorAggregate
{
public function getIterator(): Traversable
{
yield from ['someNestedValue' => ['someValue' => 'foo']];
}
}