newInstanceWithoutConstructor(); return $ref->getMethod('coerceForValidation')->invoke($instance, $value, $field); } public static function intTypedFields(): array { return [ 'validate.type int' => [['type' => 'select', 'validate' => ['type' => 'int']]], 'validate.type number' => [['type' => 'text', 'validate' => ['type' => 'number']]], 'field type number' => [['type' => 'number']], ]; } #[Test] #[DataProvider('intTypedFields')] public function booleans_become_ints_for_int_typed_fields(array $field): void { $this->assertSame(1, $this->coerce(true, $field)); $this->assertSame(0, $this->coerce(false, $field)); } #[Test] public function int_typed_field_leaves_non_booleans_untouched(): void { $field = ['type' => 'select', 'validate' => ['type' => 'int']]; $this->assertSame(1, $this->coerce(1, $field)); $this->assertSame('1', $this->coerce('1', $field)); $this->assertSame(-1, $this->coerce(-1, $field)); } #[Test] public function non_int_fields_leave_booleans_untouched(): void { // A genuine boolean field (toggle/bool) must keep its bool — only // int/number-typed fields get the leniency. $this->assertTrue($this->coerce(true, ['type' => 'toggle', 'validate' => ['type' => 'bool']])); $this->assertSame('text', $this->coerce('text', ['type' => 'text'])); $this->assertTrue($this->coerce(true, ['type' => 'text'])); } }