From 569c5dca80a69a01b530c508e0cf353bfea92e9e Mon Sep 17 00:00:00 2001 From: Layla Tichy Date: Sun, 5 Apr 2026 00:34:47 +0100 Subject: [PATCH 1/6] test(mapper): add nullable-aware tests for Integer, Float, and Boolean casters --- .../Mapper/Casters/BooleanCasterTest.php | 25 +++++++++- .../Mapper/Casters/FloatCasterTest.php | 50 +++++++++++++++++++ .../Mapper/Casters/IntegerCasterTest.php | 50 +++++++++++++++++++ 3 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 tests/Integration/Mapper/Casters/FloatCasterTest.php create mode 100644 tests/Integration/Mapper/Casters/IntegerCasterTest.php diff --git a/tests/Integration/Mapper/Casters/BooleanCasterTest.php b/tests/Integration/Mapper/Casters/BooleanCasterTest.php index 5d87c39013..9d889772c6 100644 --- a/tests/Integration/Mapper/Casters/BooleanCasterTest.php +++ b/tests/Integration/Mapper/Casters/BooleanCasterTest.php @@ -2,12 +2,14 @@ namespace Tests\Tempest\Integration\Mapper\Casters; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\Attributes\TestWith; use Tempest\Mapper\Casters\BooleanCaster; use Tests\Tempest\Integration\FrameworkIntegrationTestCase; final class BooleanCasterTest extends FrameworkIntegrationTestCase { + #[Test] #[TestWith(['true', true])] #[TestWith(['false', false])] #[TestWith([true, true])] @@ -21,8 +23,29 @@ final class BooleanCasterTest extends FrameworkIntegrationTestCase #[TestWith(['off', false])] #[TestWith(['disabled', false])] #[TestWith(['no', false])] - public function test_cast(mixed $input, bool $expected): void + public function cast(mixed $input, bool $expected): void { $this->assertSame($expected, new BooleanCaster()->cast($input)); } + + #[Test] + #[TestWith(['true', true])] + #[TestWith([true, true])] + #[TestWith(['false', false])] + #[TestWith([false, false])] + #[TestWith(['on', true])] + #[TestWith(['off', false])] + public function nullable_cast_with_values(mixed $input, bool $expected): void + { + $this->assertSame($expected, new BooleanCaster(nullable: true)->cast($input)); + } + + #[Test] + #[TestWith([null])] + #[TestWith([''])] + #[TestWith(['null'])] + public function nullable_cast_returns_null_for_empty_input(mixed $input): void + { + $this->assertNull(new BooleanCaster(nullable: true)->cast($input)); + } } diff --git a/tests/Integration/Mapper/Casters/FloatCasterTest.php b/tests/Integration/Mapper/Casters/FloatCasterTest.php new file mode 100644 index 0000000000..fb6293e2b5 --- /dev/null +++ b/tests/Integration/Mapper/Casters/FloatCasterTest.php @@ -0,0 +1,50 @@ +assertSame($expected, $caster->cast($input)); + } + + #[Test] + #[TestWith(['3.14', 3.14])] + #[TestWith([3.14, 3.14])] + #[TestWith(['0', 0.0])] + #[TestWith([0, 0.0])] + public function nullable_cast_with_values(mixed $input, float $expected): void + { + $caster = new FloatCaster(nullable: true); + + $this->assertSame($expected, $caster->cast($input)); + } + + #[Test] + #[TestWith([null])] + #[TestWith([''])] + #[TestWith(['null'])] + public function nullable_cast_returns_null_for_empty_input(mixed $input): void + { + $caster = new FloatCaster(nullable: true); + + $this->assertNull($caster->cast($input)); + } +} diff --git a/tests/Integration/Mapper/Casters/IntegerCasterTest.php b/tests/Integration/Mapper/Casters/IntegerCasterTest.php new file mode 100644 index 0000000000..2d64b7ac6f --- /dev/null +++ b/tests/Integration/Mapper/Casters/IntegerCasterTest.php @@ -0,0 +1,50 @@ +assertSame($expected, $caster->cast($input)); + } + + #[Test] + #[TestWith(['42', 42])] + #[TestWith([42, 42])] + #[TestWith(['0', 0])] + #[TestWith([0, 0])] + public function nullable_cast_with_values(mixed $input, int $expected): void + { + $caster = new IntegerCaster(nullable: true); + + $this->assertSame($expected, $caster->cast($input)); + } + + #[Test] + #[TestWith([null])] + #[TestWith([''])] + #[TestWith(['null'])] + public function nullable_cast_returns_null_for_empty_input(mixed $input): void + { + $caster = new IntegerCaster(nullable: true); + + $this->assertNull($caster->cast($input)); + } +} From 257c1423e12b49ef4c92dd8d4cf05dcdbc518edd Mon Sep 17 00:00:00 2001 From: Layla Tichy Date: Sun, 5 Apr 2026 00:36:17 +0100 Subject: [PATCH 2/6] fix(mapper): make Integer, Float, and Boolean casters nullable-aware via ConfigurableCaster --- packages/mapper/src/Casters/BooleanCaster.php | 19 +++++++++++++++++-- packages/mapper/src/Casters/FloatCaster.php | 19 +++++++++++++++++-- packages/mapper/src/Casters/IntegerCaster.php | 19 +++++++++++++++++-- 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/packages/mapper/src/Casters/BooleanCaster.php b/packages/mapper/src/Casters/BooleanCaster.php index a2eac02b85..cb2b458d4d 100644 --- a/packages/mapper/src/Casters/BooleanCaster.php +++ b/packages/mapper/src/Casters/BooleanCaster.php @@ -6,13 +6,19 @@ use Tempest\Core\Priority; use Tempest\Mapper\Caster; +use Tempest\Mapper\ConfigurableCaster; +use Tempest\Mapper\Context; use Tempest\Mapper\DynamicCaster; use Tempest\Reflection\PropertyReflector; use Tempest\Reflection\TypeReflector; #[Priority(Priority::NORMAL)] -final readonly class BooleanCaster implements Caster, DynamicCaster +final readonly class BooleanCaster implements Caster, DynamicCaster, ConfigurableCaster { + public function __construct( + private bool $nullable = false, + ) {} + public static function accepts(PropertyReflector|TypeReflector $input): bool { $type = $input instanceof PropertyReflector @@ -22,12 +28,21 @@ public static function accepts(PropertyReflector|TypeReflector $input): bool return in_array($type->getName(), ['bool', 'boolean'], strict: true); } - public function cast(mixed $input): bool + public static function configure(PropertyReflector $property, Context $context): self + { + return new self(nullable: $property->isNullable()); + } + + public function cast(mixed $input): ?bool { if (is_string($input)) { $input = mb_strtolower($input); } + if ($this->nullable && ($input === null || $input === '' || $input === 'null')) { + return null; + } + return match ($input) { 1, '1', true, 'true', 'enabled', 'on', 'yes' => true, default => false, diff --git a/packages/mapper/src/Casters/FloatCaster.php b/packages/mapper/src/Casters/FloatCaster.php index cc0f0ddb11..343902c251 100644 --- a/packages/mapper/src/Casters/FloatCaster.php +++ b/packages/mapper/src/Casters/FloatCaster.php @@ -6,13 +6,19 @@ use Tempest\Core\Priority; use Tempest\Mapper\Caster; +use Tempest\Mapper\ConfigurableCaster; +use Tempest\Mapper\Context; use Tempest\Mapper\DynamicCaster; use Tempest\Reflection\PropertyReflector; use Tempest\Reflection\TypeReflector; #[Priority(Priority::NORMAL)] -final readonly class FloatCaster implements Caster, DynamicCaster +final readonly class FloatCaster implements Caster, DynamicCaster, ConfigurableCaster { + public function __construct( + private bool $nullable = false, + ) {} + public static function accepts(PropertyReflector|TypeReflector $input): bool { $type = $input instanceof PropertyReflector @@ -22,8 +28,17 @@ public static function accepts(PropertyReflector|TypeReflector $input): bool return in_array($type->getName(), ['float', 'double'], strict: true); } - public function cast(mixed $input): float + public static function configure(PropertyReflector $property, Context $context): self { + return new self(nullable: $property->isNullable()); + } + + public function cast(mixed $input): ?float + { + if ($this->nullable && ($input === null || $input === '' || $input === 'null')) { + return null; + } + return floatval($input); } } diff --git a/packages/mapper/src/Casters/IntegerCaster.php b/packages/mapper/src/Casters/IntegerCaster.php index 954284b645..2284cc9bfc 100644 --- a/packages/mapper/src/Casters/IntegerCaster.php +++ b/packages/mapper/src/Casters/IntegerCaster.php @@ -6,13 +6,19 @@ use Tempest\Core\Priority; use Tempest\Mapper\Caster; +use Tempest\Mapper\ConfigurableCaster; +use Tempest\Mapper\Context; use Tempest\Mapper\DynamicCaster; use Tempest\Reflection\PropertyReflector; use Tempest\Reflection\TypeReflector; #[Priority(Priority::NORMAL)] -final readonly class IntegerCaster implements Caster, DynamicCaster +final readonly class IntegerCaster implements Caster, DynamicCaster, ConfigurableCaster { + public function __construct( + private bool $nullable = false, + ) {} + public static function accepts(PropertyReflector|TypeReflector $input): bool { $type = $input instanceof PropertyReflector @@ -22,8 +28,17 @@ public static function accepts(PropertyReflector|TypeReflector $input): bool return in_array($type->getName(), ['int', 'integer'], strict: true); } - public function cast(mixed $input): int + public static function configure(PropertyReflector $property, Context $context): self { + return new self(nullable: $property->isNullable()); + } + + public function cast(mixed $input): ?int + { + if ($this->nullable && ($input === null || $input === '' || $input === 'null')) { + return null; + } + return intval($input); } } From 28bfa87257ede58dcc9e2b46d986e857b8145428 Mon Sep 17 00:00:00 2001 From: Layla Tichy Date: Sun, 5 Apr 2026 00:56:17 +0100 Subject: [PATCH 3/6] fix(mapper): case-insensitive null string check in Integer/Float casters, add factory integration tests for nullable path --- packages/mapper/src/Casters/FloatCaster.php | 4 ++++ packages/mapper/src/Casters/IntegerCaster.php | 4 ++++ tests/Integration/Mapper/CasterFactoryTest.php | 3 +++ tests/Integration/Mapper/Casters/FloatCasterTest.php | 2 ++ tests/Integration/Mapper/Casters/IntegerCasterTest.php | 2 ++ .../Mapper/Fixtures/ObjectWithSerializerProperties.php | 6 ++++++ .../Mapper/Serializers/ArrayOfObjectsSerializerTest.php | 3 +++ 7 files changed, 24 insertions(+) diff --git a/packages/mapper/src/Casters/FloatCaster.php b/packages/mapper/src/Casters/FloatCaster.php index 343902c251..16ef83acc8 100644 --- a/packages/mapper/src/Casters/FloatCaster.php +++ b/packages/mapper/src/Casters/FloatCaster.php @@ -35,6 +35,10 @@ public static function configure(PropertyReflector $property, Context $context): public function cast(mixed $input): ?float { + if (is_string($input)) { + $input = mb_strtolower($input); + } + if ($this->nullable && ($input === null || $input === '' || $input === 'null')) { return null; } diff --git a/packages/mapper/src/Casters/IntegerCaster.php b/packages/mapper/src/Casters/IntegerCaster.php index 2284cc9bfc..74294613ad 100644 --- a/packages/mapper/src/Casters/IntegerCaster.php +++ b/packages/mapper/src/Casters/IntegerCaster.php @@ -35,6 +35,10 @@ public static function configure(PropertyReflector $property, Context $context): public function cast(mixed $input): ?int { + if (is_string($input)) { + $input = mb_strtolower($input); + } + if ($this->nullable && ($input === null || $input === '' || $input === 'null')) { return null; } diff --git a/tests/Integration/Mapper/CasterFactoryTest.php b/tests/Integration/Mapper/CasterFactoryTest.php index a2e9651602..8d0b703031 100644 --- a/tests/Integration/Mapper/CasterFactoryTest.php +++ b/tests/Integration/Mapper/CasterFactoryTest.php @@ -24,8 +24,11 @@ public function test_for_property(): void $class = reflect(ObjectWithSerializerProperties::class); $this->assertInstanceOf(IntegerCaster::class, $factory->forProperty($class->getProperty('intProp'))); + $this->assertInstanceOf(IntegerCaster::class, $factory->forProperty($class->getProperty('nullableIntProp'))); $this->assertInstanceOf(FloatCaster::class, $factory->forProperty($class->getProperty('floatProp'))); + $this->assertInstanceOf(FloatCaster::class, $factory->forProperty($class->getProperty('nullableFloatProp'))); $this->assertInstanceOf(BooleanCaster::class, $factory->forProperty($class->getProperty('boolProp'))); + $this->assertInstanceOf(BooleanCaster::class, $factory->forProperty($class->getProperty('nullableBoolProp'))); $this->assertInstanceOf(NativeDateTimeCaster::class, $factory->forProperty($class->getProperty('nativeDateTimeImmutableProp'))); $this->assertInstanceOf(NativeDateTimeCaster::class, $factory->forProperty($class->getProperty('nativeDateTimeProp'))); $this->assertInstanceOf(NativeDateTimeCaster::class, $factory->forProperty($class->getProperty('nativeDateTimeInterfaceProp'))); diff --git a/tests/Integration/Mapper/Casters/FloatCasterTest.php b/tests/Integration/Mapper/Casters/FloatCasterTest.php index fb6293e2b5..b90d037360 100644 --- a/tests/Integration/Mapper/Casters/FloatCasterTest.php +++ b/tests/Integration/Mapper/Casters/FloatCasterTest.php @@ -41,6 +41,8 @@ public function nullable_cast_with_values(mixed $input, float $expected): void #[TestWith([null])] #[TestWith([''])] #[TestWith(['null'])] + #[TestWith(['NULL'])] + #[TestWith(['Null'])] public function nullable_cast_returns_null_for_empty_input(mixed $input): void { $caster = new FloatCaster(nullable: true); diff --git a/tests/Integration/Mapper/Casters/IntegerCasterTest.php b/tests/Integration/Mapper/Casters/IntegerCasterTest.php index 2d64b7ac6f..0e19423294 100644 --- a/tests/Integration/Mapper/Casters/IntegerCasterTest.php +++ b/tests/Integration/Mapper/Casters/IntegerCasterTest.php @@ -41,6 +41,8 @@ public function nullable_cast_with_values(mixed $input, int $expected): void #[TestWith([null])] #[TestWith([''])] #[TestWith(['null'])] + #[TestWith(['NULL'])] + #[TestWith(['Null'])] public function nullable_cast_returns_null_for_empty_input(mixed $input): void { $caster = new IntegerCaster(nullable: true); diff --git a/tests/Integration/Mapper/Fixtures/ObjectWithSerializerProperties.php b/tests/Integration/Mapper/Fixtures/ObjectWithSerializerProperties.php index 3531a95a85..6b3b92ffd9 100644 --- a/tests/Integration/Mapper/Fixtures/ObjectWithSerializerProperties.php +++ b/tests/Integration/Mapper/Fixtures/ObjectWithSerializerProperties.php @@ -18,10 +18,16 @@ final class ObjectWithSerializerProperties public int $intProp = 1; + public ?int $nullableIntProp = null; + public float $floatProp = 0.1; + public ?float $nullableFloatProp = null; + public bool $boolProp = true; + public ?bool $nullableBoolProp = null; + public array $arrayProp = ['a']; #[SerializeWith(DoubleStringSerializer::class)] diff --git a/tests/Integration/Mapper/Serializers/ArrayOfObjectsSerializerTest.php b/tests/Integration/Mapper/Serializers/ArrayOfObjectsSerializerTest.php index ed03a31f63..34f09bab14 100644 --- a/tests/Integration/Mapper/Serializers/ArrayOfObjectsSerializerTest.php +++ b/tests/Integration/Mapper/Serializers/ArrayOfObjectsSerializerTest.php @@ -18,8 +18,11 @@ public function test_serialize(): void 'stringProp' => 'a', 'stringableProp' => 'a', 'intProp' => '1', + 'nullableIntProp' => null, 'floatProp' => '0.1', + 'nullableFloatProp' => null, 'boolProp' => 'true', + 'nullableBoolProp' => null, 'arrayProp' => '["a"]', 'serializeWithProp' => 'aa', 'doubleStringProp' => 'aa', From db2f45a518e80491caee5795027e70b086aef2cb Mon Sep 17 00:00:00 2001 From: Layla Tichy Date: Sun, 5 Apr 2026 01:40:26 +0100 Subject: [PATCH 4/6] test(mapper): add nullable empty-input tests for EnumCaster --- .../Mapper/Casters/EnumCasterTest.php | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/tests/Integration/Mapper/Casters/EnumCasterTest.php b/tests/Integration/Mapper/Casters/EnumCasterTest.php index 59bbe5eb3c..1453415327 100644 --- a/tests/Integration/Mapper/Casters/EnumCasterTest.php +++ b/tests/Integration/Mapper/Casters/EnumCasterTest.php @@ -2,6 +2,7 @@ namespace Tests\Tempest\Integration\Mapper\Casters; +use PHPUnit\Framework\Attributes\Test; use PHPUnit\Framework\Attributes\TestWith; use Tempest\Mapper\Casters\EnumCaster; use Tests\Tempest\Integration\FrameworkIntegrationTestCase; @@ -11,12 +12,35 @@ final class EnumCasterTest extends FrameworkIntegrationTestCase { + #[Test] #[TestWith(['FOO', UnitEnumToSerialize::FOO, UnitEnumToSerialize::class])] #[TestWith(['BAR', UnitEnumToSerialize::BAR, UnitEnumToSerialize::class])] #[TestWith(['foo', BackedEnumToSerialize::FOO, BackedEnumToSerialize::class])] #[TestWith(['bar', BackedEnumToSerialize::BAR, BackedEnumToSerialize::class])] - public function test_cast(mixed $input, UnitEnum $expected, string $class): void + public function cast(mixed $input, UnitEnum $expected, string $class): void { $this->assertSame($expected, new EnumCaster($class)->cast($input)); } + + #[Test] + #[TestWith([null])] + #[TestWith([''])] + #[TestWith(['null'])] + #[TestWith(['NULL'])] + public function nullable_cast_returns_null_for_empty_input(mixed $input): void + { + $caster = new EnumCaster(enum: BackedEnumToSerialize::class, nullable: true); + + $this->assertNull($caster->cast($input)); + } + + #[Test] + #[TestWith(['foo', BackedEnumToSerialize::FOO])] + #[TestWith(['bar', BackedEnumToSerialize::BAR])] + public function nullable_cast_with_valid_values(mixed $input, UnitEnum $expected): void + { + $caster = new EnumCaster(enum: BackedEnumToSerialize::class, nullable: true); + + $this->assertSame($expected, $caster->cast($input)); + } } From f10dc51290fac8caea5916f7e5be85de78e70a86 Mon Sep 17 00:00:00 2001 From: Layla Tichy Date: Sun, 5 Apr 2026 01:41:41 +0100 Subject: [PATCH 5/6] fix(mapper): make EnumCaster null-aware for empty string and null-like input --- packages/mapper/src/Casters/EnumCaster.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/mapper/src/Casters/EnumCaster.php b/packages/mapper/src/Casters/EnumCaster.php index 7de8fba526..fa06e0cd40 100644 --- a/packages/mapper/src/Casters/EnumCaster.php +++ b/packages/mapper/src/Casters/EnumCaster.php @@ -22,6 +22,7 @@ */ public function __construct( private string $enum, + private bool $nullable = false, ) {} public static function accepts(PropertyReflector|TypeReflector $input): bool @@ -35,11 +36,18 @@ public static function accepts(PropertyReflector|TypeReflector $input): bool public static function configure(PropertyReflector $property, Context $context): self { - return new self(enum: $property->getType()->getName()); + return new self( + enum: $property->getType()->getName(), + nullable: $property->isNullable(), + ); } public function cast(mixed $input): ?object { + if ($this->nullable && ($input === null || $input === '' || is_string($input) && mb_strtolower($input) === 'null')) { + return null; + } + if ($input === null) { return null; } From 13d07e9e741da13a193cdaf16e524c0b4b57bcbf Mon Sep 17 00:00:00 2001 From: Layla Tichy Date: Sun, 5 Apr 2026 02:27:57 +0100 Subject: [PATCH 6/6] fix(mapper): trim whitespace-only string input in all casters before nullable check --- packages/mapper/src/Casters/BooleanCaster.php | 2 +- packages/mapper/src/Casters/EnumCaster.php | 4 ++++ packages/mapper/src/Casters/FloatCaster.php | 2 +- packages/mapper/src/Casters/IntegerCaster.php | 2 +- tests/Integration/Mapper/Casters/BooleanCasterTest.php | 1 + tests/Integration/Mapper/Casters/EnumCasterTest.php | 1 + tests/Integration/Mapper/Casters/FloatCasterTest.php | 2 ++ tests/Integration/Mapper/Casters/IntegerCasterTest.php | 2 ++ 8 files changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/mapper/src/Casters/BooleanCaster.php b/packages/mapper/src/Casters/BooleanCaster.php index cb2b458d4d..903fad2254 100644 --- a/packages/mapper/src/Casters/BooleanCaster.php +++ b/packages/mapper/src/Casters/BooleanCaster.php @@ -36,7 +36,7 @@ public static function configure(PropertyReflector $property, Context $context): public function cast(mixed $input): ?bool { if (is_string($input)) { - $input = mb_strtolower($input); + $input = mb_strtolower(trim($input)); } if ($this->nullable && ($input === null || $input === '' || $input === 'null')) { diff --git a/packages/mapper/src/Casters/EnumCaster.php b/packages/mapper/src/Casters/EnumCaster.php index fa06e0cd40..8480feee73 100644 --- a/packages/mapper/src/Casters/EnumCaster.php +++ b/packages/mapper/src/Casters/EnumCaster.php @@ -44,6 +44,10 @@ enum: $property->getType()->getName(), public function cast(mixed $input): ?object { + if (is_string($input)) { + $input = trim($input); + } + if ($this->nullable && ($input === null || $input === '' || is_string($input) && mb_strtolower($input) === 'null')) { return null; } diff --git a/packages/mapper/src/Casters/FloatCaster.php b/packages/mapper/src/Casters/FloatCaster.php index 16ef83acc8..40aeda53c8 100644 --- a/packages/mapper/src/Casters/FloatCaster.php +++ b/packages/mapper/src/Casters/FloatCaster.php @@ -36,7 +36,7 @@ public static function configure(PropertyReflector $property, Context $context): public function cast(mixed $input): ?float { if (is_string($input)) { - $input = mb_strtolower($input); + $input = mb_strtolower(trim($input)); } if ($this->nullable && ($input === null || $input === '' || $input === 'null')) { diff --git a/packages/mapper/src/Casters/IntegerCaster.php b/packages/mapper/src/Casters/IntegerCaster.php index 74294613ad..1f9478850e 100644 --- a/packages/mapper/src/Casters/IntegerCaster.php +++ b/packages/mapper/src/Casters/IntegerCaster.php @@ -36,7 +36,7 @@ public static function configure(PropertyReflector $property, Context $context): public function cast(mixed $input): ?int { if (is_string($input)) { - $input = mb_strtolower($input); + $input = mb_strtolower(trim($input)); } if ($this->nullable && ($input === null || $input === '' || $input === 'null')) { diff --git a/tests/Integration/Mapper/Casters/BooleanCasterTest.php b/tests/Integration/Mapper/Casters/BooleanCasterTest.php index 9d889772c6..ccd676a19e 100644 --- a/tests/Integration/Mapper/Casters/BooleanCasterTest.php +++ b/tests/Integration/Mapper/Casters/BooleanCasterTest.php @@ -44,6 +44,7 @@ public function nullable_cast_with_values(mixed $input, bool $expected): void #[TestWith([null])] #[TestWith([''])] #[TestWith(['null'])] + #[TestWith([' '])] public function nullable_cast_returns_null_for_empty_input(mixed $input): void { $this->assertNull(new BooleanCaster(nullable: true)->cast($input)); diff --git a/tests/Integration/Mapper/Casters/EnumCasterTest.php b/tests/Integration/Mapper/Casters/EnumCasterTest.php index 1453415327..03aac20196 100644 --- a/tests/Integration/Mapper/Casters/EnumCasterTest.php +++ b/tests/Integration/Mapper/Casters/EnumCasterTest.php @@ -27,6 +27,7 @@ public function cast(mixed $input, UnitEnum $expected, string $class): void #[TestWith([''])] #[TestWith(['null'])] #[TestWith(['NULL'])] + #[TestWith([' '])] public function nullable_cast_returns_null_for_empty_input(mixed $input): void { $caster = new EnumCaster(enum: BackedEnumToSerialize::class, nullable: true); diff --git a/tests/Integration/Mapper/Casters/FloatCasterTest.php b/tests/Integration/Mapper/Casters/FloatCasterTest.php index b90d037360..240185022f 100644 --- a/tests/Integration/Mapper/Casters/FloatCasterTest.php +++ b/tests/Integration/Mapper/Casters/FloatCasterTest.php @@ -30,6 +30,7 @@ public function cast(mixed $input, float $expected): void #[TestWith([3.14, 3.14])] #[TestWith(['0', 0.0])] #[TestWith([0, 0.0])] + #[TestWith([' 3.14 ', 3.14])] public function nullable_cast_with_values(mixed $input, float $expected): void { $caster = new FloatCaster(nullable: true); @@ -43,6 +44,7 @@ public function nullable_cast_with_values(mixed $input, float $expected): void #[TestWith(['null'])] #[TestWith(['NULL'])] #[TestWith(['Null'])] + #[TestWith([' '])] public function nullable_cast_returns_null_for_empty_input(mixed $input): void { $caster = new FloatCaster(nullable: true); diff --git a/tests/Integration/Mapper/Casters/IntegerCasterTest.php b/tests/Integration/Mapper/Casters/IntegerCasterTest.php index 0e19423294..a0d9da7102 100644 --- a/tests/Integration/Mapper/Casters/IntegerCasterTest.php +++ b/tests/Integration/Mapper/Casters/IntegerCasterTest.php @@ -30,6 +30,7 @@ public function cast(mixed $input, int $expected): void #[TestWith([42, 42])] #[TestWith(['0', 0])] #[TestWith([0, 0])] + #[TestWith([' 42 ', 42])] public function nullable_cast_with_values(mixed $input, int $expected): void { $caster = new IntegerCaster(nullable: true); @@ -43,6 +44,7 @@ public function nullable_cast_with_values(mixed $input, int $expected): void #[TestWith(['null'])] #[TestWith(['NULL'])] #[TestWith(['Null'])] + #[TestWith([' '])] public function nullable_cast_returns_null_for_empty_input(mixed $input): void { $caster = new IntegerCaster(nullable: true);