Skip to content

Commit

Permalink
AssertListItem: fix passing correct item type to inner validator
Browse files Browse the repository at this point in the history
  • Loading branch information
JanTvrdik committed Aug 11, 2023
1 parent 9cba310 commit 7e91d8a
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 6 deletions.
3 changes: 2 additions & 1 deletion src/Compiler/Validator/Array/AssertListItem.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,10 @@ public function compile(Expr $value, TypeNode $type, Expr $path, PhpCodeBuilder

foreach ($this->validators as $validator) {
$itemValue = $builder->var($itemVariableName);
$itemType = PhpDocTypeUtils::inferGenericParameter($type, 'list', 0);
$itemPath = $builder->arrayImmutableAppend($path, $builder->var($indexVariableName));

foreach ($validator->compile($itemValue, $type, $itemPath, $builder) as $statement) {
foreach ($validator->compile($itemValue, $itemType, $itemPath, $builder) as $statement) {
$foreachBody[] = $statement;
}
}
Expand Down
10 changes: 5 additions & 5 deletions tests/Compiler/Mapper/MapperCompilerTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ protected function compileMapper(
$mapperDir = strtr(str_replace('ShipMonkTests\InputMapper', __DIR__ . '/../..', $mapperNamespace), '\\', '/');
$mapperPath = "{$mapperDir}/{$mapperShortClassName}.php";

if (!class_exists($mapperClassName, autoload: false)) {
$builder = new PhpCodeBuilder();
$printer = new PhpCodePrinter();
$mapperCode = $printer->prettyPrintFile($builder->mapperFile($mapperClassName, $mapperCompiler));
$builder = new PhpCodeBuilder();
$printer = new PhpCodePrinter();
$mapperCode = $printer->prettyPrintFile($builder->mapperFile($mapperClassName, $mapperCompiler));
self::assertSnapshot($mapperPath, $mapperCode);

self::assertSnapshot($mapperPath, $mapperCode);
if (!class_exists($mapperClassName, autoload: false)) {
require $mapperPath;
}

Expand Down
26 changes: 26 additions & 0 deletions tests/Compiler/Validator/Array/AssertListItemTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@

namespace ShipMonkTests\InputMapper\Compiler\Validator\Array;

use PhpParser\Node\Expr;
use PHPStan\PhpDocParser\Ast\Type\IdentifierTypeNode;
use ShipMonk\InputMapper\Compiler\Mapper\Array\MapList;
use ShipMonk\InputMapper\Compiler\Mapper\Scalar\MapInt;
use ShipMonk\InputMapper\Compiler\Php\PhpCodeBuilder;
use ShipMonk\InputMapper\Compiler\Validator\Array\AssertListItem;
use ShipMonk\InputMapper\Compiler\Validator\Int\AssertIntMultipleOf;
use ShipMonk\InputMapper\Compiler\Validator\Int\AssertPositiveInt;
use ShipMonk\InputMapper\Compiler\Validator\ValidatorCompiler;
use ShipMonk\InputMapper\Runtime\Exception\MappingFailedException;
use ShipMonkTests\InputMapper\Compiler\Validator\ValidatorCompilerTestCase;

Expand Down Expand Up @@ -51,4 +55,26 @@ public function testListItemValidatorWithMultipleValidators(): void
);
}

public function testInnerValidatorIsCalledWithCorrectItemType(): void
{
$itemValidator = $this->createMock(ValidatorCompiler::class);

$itemValidator->expects(self::once())
->method('compile')
->with(
self::isInstanceOf(Expr::class),
self::equalTo(new IdentifierTypeNode('int')),
self::isInstanceOf(Expr::class),
self::isInstanceOf(PhpCodeBuilder::class),
);

$itemValidator->expects(self::once())
->method('getInputType')
->willReturn(new IdentifierTypeNode('int'));

$mapperCompiler = new MapList(new MapInt());
$validatorCompiler = new AssertListItem([$itemValidator]);
$this->compileValidator('ListItemValidatorCalledWithCorrectItemType', $mapperCompiler, $validatorCompiler);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php declare (strict_types=1);

namespace ShipMonkTests\InputMapper\Compiler\Validator\Array\Data;

use ShipMonk\InputMapper\Compiler\Mapper\Wrapper\ValidatedMapperCompiler;
use ShipMonk\InputMapper\Runtime\Exception\MappingFailedException;
use ShipMonk\InputMapper\Runtime\Mapper;
use ShipMonk\InputMapper\Runtime\MapperProvider;
use function array_is_list;
use function is_array;
use function is_int;

/**
* Generated mapper by {@see ValidatedMapperCompiler}. Do not edit directly.
*
* @implements Mapper<list<int>>
*/
class ListItemValidatorCalledWithCorrectItemTypeMapper implements Mapper
{
public function __construct(private readonly MapperProvider $provider)
{
}

/**
* @param list<string|int> $path
* @return list<int>
* @throws MappingFailedException
*/
public function map(mixed $data, array $path = []): array
{
if (!is_array($data) || !array_is_list($data)) {
throw MappingFailedException::incorrectType($data, $path, 'list');
}

$mapped = [];

foreach ($data as $index => $item) {
if (!is_int($item)) {
throw MappingFailedException::incorrectType($item, [...$path, $index], 'int');
}

$mapped[] = $item;
}

foreach ($mapped as $index2 => $item2) {
}

return $mapped;
}
}

0 comments on commit 7e91d8a

Please sign in to comment.