mirror of
https://github.com/danog/Valinor.git
synced 2024-11-30 04:39:05 +01:00
feat: display more information in mapping error message
The message will now display the source and the number of errors, and even the original error message if only one error was encountered.
This commit is contained in:
parent
2c1c7cf38a
commit
9c1e7c928b
@ -4,7 +4,9 @@ declare(strict_types=1);
|
||||
|
||||
namespace CuyZ\Valinor\Mapper;
|
||||
|
||||
use CuyZ\Valinor\Mapper\Tree\Message\MessagesFlattener;
|
||||
use CuyZ\Valinor\Mapper\Tree\Node;
|
||||
use CuyZ\Valinor\Utility\ValueDumper;
|
||||
use RuntimeException;
|
||||
|
||||
/** @api */
|
||||
@ -16,10 +18,21 @@ final class MappingError extends RuntimeException
|
||||
{
|
||||
$this->node = $node;
|
||||
|
||||
parent::__construct(
|
||||
"Could not map type `{$node->type()}` with the given source.",
|
||||
1617193185
|
||||
);
|
||||
$source = ValueDumper::dump($node->sourceValue());
|
||||
|
||||
$errors = (new MessagesFlattener($node))->errors();
|
||||
$errorsCount = count($errors);
|
||||
|
||||
$body = "Could not map type `{$node->type()}` with value $source. A total of $errorsCount errors were encountered.";
|
||||
|
||||
if ($errorsCount === 1) {
|
||||
$body = $errors->getIterator()->current()
|
||||
->withParameter('root_type', $node->type())
|
||||
->withBody("Could not map type `{root_type}`. An error occurred at path {node_path}: {original_message}")
|
||||
->toString();
|
||||
}
|
||||
|
||||
parent::__construct($body, 1617193185);
|
||||
}
|
||||
|
||||
public function node(): Node
|
||||
|
@ -7,8 +7,8 @@ namespace CuyZ\Valinor\Mapper\Tree\Message;
|
||||
use Countable;
|
||||
use CuyZ\Valinor\Mapper\Tree\Node;
|
||||
use CuyZ\Valinor\Mapper\Tree\NodeTraverser;
|
||||
use Iterator;
|
||||
use IteratorAggregate;
|
||||
use Traversable;
|
||||
|
||||
use function array_filter;
|
||||
use function count;
|
||||
@ -66,9 +66,9 @@ final class MessagesFlattener implements IteratorAggregate, Countable
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Traversable<NodeMessage>
|
||||
* @return Iterator<NodeMessage>
|
||||
*/
|
||||
public function getIterator(): Traversable
|
||||
public function getIterator(): Iterator
|
||||
{
|
||||
yield from $this->messages;
|
||||
}
|
||||
|
51
tests/Integration/Mapping/MappingErrorTest.php
Normal file
51
tests/Integration/Mapping/MappingErrorTest.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace CuyZ\Valinor\Tests\Integration\Mapping;
|
||||
|
||||
use CuyZ\Valinor\Mapper\MappingError;
|
||||
use CuyZ\Valinor\MapperBuilder;
|
||||
use CuyZ\Valinor\Tests\Integration\IntegrationTest;
|
||||
|
||||
final class MappingErrorTest extends IntegrationTest
|
||||
{
|
||||
public function test_mapping_error_code_is_correct(): void
|
||||
{
|
||||
try {
|
||||
(new MapperBuilder())->mapper()->map('string', ['foo']);
|
||||
|
||||
self::fail();
|
||||
} catch (MappingError $exception) {
|
||||
self::assertSame(1617193185, $exception->getCode());
|
||||
}
|
||||
}
|
||||
|
||||
public function test_single_error_details_are_reported_in_exception_message(): void
|
||||
{
|
||||
try {
|
||||
(new MapperBuilder())->mapper()->map('string', ['foo']);
|
||||
|
||||
self::fail();
|
||||
} catch (MappingError $exception) {
|
||||
self::assertSame("Could not map type `string`. An error occurred at path *root*: Value array{0: 'foo'} does not match type `string`.", $exception->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public function test_several_errors_count_are_reported_in_exception_message(): void
|
||||
{
|
||||
try {
|
||||
(new MapperBuilder())->mapper()->map(
|
||||
'array{foo: string, bar: int}',
|
||||
['foo' => 42, 'bar' => 'some string']
|
||||
);
|
||||
|
||||
self::fail();
|
||||
} catch (MappingError $exception) {
|
||||
self::assertSame(
|
||||
"Could not map type `array{foo: string, bar: int}` with value array{foo: 42, bar: 'some string'}. A total of 2 errors were encountered.",
|
||||
$exception->getMessage()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user