[true, false, true], 'floats' => [42.404, 404.42], 'integers' => [42, 404, 1337], 'strings' => ['foo', 'bar', 'baz'], 'objects' => [ ['value' => 'foo'], ['value' => 'bar'], ['value' => 'baz'], ], 'objectsWithAlias' => [ ['value' => 'foo'], ['value' => 'bar'], ['value' => 'baz'], ], 'nonEmptyListOfStrings' => ['foo', 'bar', 'baz'], 'listOfStringsWithKeys' => [ 'foo' => 'foo', 'bar' => 'bar', 'baz' => 'baz', ], 'nonEmptyListOfStringsWithKeys' => [ 'foo' => 'foo', 'bar' => 'bar', 'baz' => 'baz', ], ]; foreach ([ListValues::class, ListValuesWithConstructor::class] as $class) { try { $result = $this->mapperBuilder->mapper()->map($class, $source); } catch (MappingError $error) { $this->mappingFail($error); } self::assertSame($source['booleans'], $result->booleans); self::assertSame($source['floats'], $result->floats); self::assertSame($source['integers'], $result->integers); self::assertSame($source['strings'], $result->strings); self::assertSame('foo', $result->objects[0]->value); self::assertSame('bar', $result->objects[1]->value); self::assertSame('baz', $result->objects[2]->value); self::assertSame('foo', $result->objectsWithAlias[0]->value); self::assertSame('bar', $result->objectsWithAlias[1]->value); self::assertSame('baz', $result->objectsWithAlias[2]->value); self::assertSame($source['nonEmptyListOfStrings'], $result->nonEmptyListOfStrings); self::assertSame(array_values($source['listOfStringsWithKeys']), $result->listOfStringsWithKeys); self::assertSame(array_values($source['nonEmptyListOfStringsWithKeys']), $result->nonEmptyListOfStringsWithKeys); } } public function test_empty_list_in_non_empty_list_throws_exception(): void { try { $this->mapperBuilder->mapper()->map(ListValues::class, [ 'nonEmptyListOfStrings' => [], ]); } catch (MappingError $exception) { $error = $exception->node()->children()['nonEmptyListOfStrings']->messages()[0]; self::assertSame('1630678334', $error->code()); self::assertSame('Empty array is not accepted by `non-empty-list`.', (string)$error); } } public function test_value_that_cannot_be_casted_throws_exception(): void { try { $this->mapperBuilder->mapper()->map(ListValues::class, [ 'integers' => ['foo'], ]); } catch (MappingError $exception) { $error = $exception->node()->children()['integers']->children()['0']->messages()[0]; self::assertSame('1618736242', $error->code()); self::assertSame('Cannot cast value of type `string` to `int`.', (string)$error); } } } class ListValues { /** @var list */ public array $booleans; /** @var list */ public array $floats; /** @var list */ public array $integers; /** @var list */ public array $strings; /** @var list */ public array $objects; /** @var list */ public array $objectsWithAlias; /** @var non-empty-list */ public array $nonEmptyListOfStrings = ['foo']; /** @var list */ public array $listOfStringsWithKeys; /** @var non-empty-list */ public array $nonEmptyListOfStringsWithKeys; } class ListValuesWithConstructor extends ListValues { /** * @param list $booleans * @param list $floats * @param list $integers * @param list $strings * @param list $objects * @param list $objectsWithAlias * @param non-empty-list $nonEmptyListOfStrings * @param list $listOfStringsWithKeys * @param non-empty-list $nonEmptyListOfStringsWithKeys */ public function __construct( array $booleans, array $floats, array $integers, array $strings, array $objects, array $objectsWithAlias, array $nonEmptyListOfStrings, array $listOfStringsWithKeys, array $nonEmptyListOfStringsWithKeys ) { $this->booleans = $booleans; $this->floats = $floats; $this->integers = $integers; $this->strings = $strings; $this->objects = $objects; $this->objectsWithAlias = $objectsWithAlias; $this->nonEmptyListOfStrings = $nonEmptyListOfStrings; $this->listOfStringsWithKeys = $listOfStringsWithKeys; $this->nonEmptyListOfStringsWithKeys = $nonEmptyListOfStringsWithKeys; } }