diff --git a/system/Validation/StrictRules/Rules.php b/system/Validation/StrictRules/Rules.php index 8861ab727852..af8970122f5c 100644 --- a/system/Validation/StrictRules/Rules.php +++ b/system/Validation/StrictRules/Rules.php @@ -71,20 +71,36 @@ public function exact_length($str, string $val): bool /** * Greater than * - * @param mixed $str + * @param mixed $str expects int|string */ public function greater_than($str, string $min): bool { + if (is_int($str)) { + $str = (string) $str; + } + + if (! is_string($str)) { + return false; + } + return $this->nonStrictRules->greater_than($str, $min); } /** * Equal to or Greater than * - * @param mixed $str + * @param mixed $str expects int|string */ public function greater_than_equal_to($str, string $min): bool { + if (is_int($str)) { + $str = (string) $str; + } + + if (! is_string($str)) { + return false; + } + return $this->nonStrictRules->greater_than_equal_to($str, $min); } @@ -141,20 +157,36 @@ public function is_unique($str, string $field, array $data): bool /** * Less than * - * @param mixed $str + * @param mixed $str expects int|string */ public function less_than($str, string $max): bool { + if (is_int($str)) { + $str = (string) $str; + } + + if (! is_string($str)) { + return false; + } + return $this->nonStrictRules->less_than($str, $max); } /** * Equal to or Less than * - * @param mixed $str + * @param mixed $str expects int|string */ public function less_than_equal_to($str, string $max): bool { + if (is_int($str)) { + $str = (string) $str; + } + + if (! is_string($str)) { + return false; + } + return $this->nonStrictRules->less_than_equal_to($str, $max); } diff --git a/tests/system/Validation/RulesTest.php b/tests/system/Validation/RulesTest.php index 9430cc83fda2..419070714599 100644 --- a/tests/system/Validation/RulesTest.php +++ b/tests/system/Validation/RulesTest.php @@ -19,11 +19,13 @@ /** * @internal + * + * @no-final */ -final class RulesTest extends CIUnitTestCase +class RulesTest extends CIUnitTestCase { - private Validation $validation; - private array $config = [ + protected Validation $validation; + protected array $config = [ 'ruleSets' => [ Rules::class, FormatRules::class, diff --git a/tests/system/Validation/StrictRules/RulesTest.php b/tests/system/Validation/StrictRules/RulesTest.php index f3f8ce946020..e6d2e034d12c 100644 --- a/tests/system/Validation/StrictRules/RulesTest.php +++ b/tests/system/Validation/StrictRules/RulesTest.php @@ -11,20 +11,18 @@ namespace CodeIgniter\Validation\StrictRules; -use CodeIgniter\Test\CIUnitTestCase; +use CodeIgniter\Validation\RulesTest as TraditionalRulesTest; use CodeIgniter\Validation\Validation; -use Config\Services; use Generator; -use stdClass; use Tests\Support\Validation\TestRules; /** * @internal */ -final class RulesTest extends CIUnitTestCase +final class RulesTest extends TraditionalRulesTest { - private Validation $validation; - private array $config = [ + protected Validation $validation; + protected array $config = [ 'ruleSets' => [ Rules::class, FormatRules::class, @@ -42,91 +40,16 @@ final class RulesTest extends CIUnitTestCase ], ]; - protected function setUp(): void - { - parent::setUp(); - $this->validation = new Validation((object) $this->config, Services::renderer()); - $this->validation->reset(); - } - - /** - * @dataProvider provideRequiredCases - */ - public function testRequired(array $data, bool $expected): void - { - $this->validation->setRules(['foo' => 'required']); - $this->assertSame($expected, $this->validation->run($data)); - } - - public function provideRequiredCases(): Generator - { - yield from [ - [['foo' => null], false], - [['foo' => 123], true], - [['foo' => null, 'bar' => 123], false], - [['foo' => [123]], true], - [['foo' => []], false], - [['foo' => new stdClass()], true], - ]; - } - - /** - * @dataProvider ifExistProvider - */ - public function testIfExist(array $rules, array $data, bool $expected): void - { - $this->validation->setRules($rules); - $this->assertSame($expected, $this->validation->run($data)); - } - - public function ifExistProvider(): Generator - { - yield from [ - [ - ['foo' => 'required'], - ['foo' => ''], - false, - ], - [ - ['foo' => 'required'], - ['foo' => null], - false, - ], - [ - ['foo' => 'if_exist|required'], - ['foo' => ''], - false, - ], - // Input data does not exist then the other rules will be ignored - [ - ['foo' => 'if_exist|required'], - [], - true, - ], - // Testing for multi-dimensional data - [ - ['foo.bar' => 'if_exist|required'], - ['foo' => ['bar' => '']], - false, - ], - [ - ['foo.bar' => 'if_exist|required'], - ['foo' => []], - true, - ], - ]; - } - /** - * @dataProvider providePermitEmptyCases + * @dataProvider providePermitEmptyCasesStrict */ - public function testPermitEmpty(array $rules, array $data, bool $expected): void + public function testPermitEmptyStrict(array $rules, array $data, bool $expected): void { $this->validation->setRules($rules); $this->assertSame($expected, $this->validation->run($data)); } - public function providePermitEmptyCases(): Generator + public function providePermitEmptyCasesStrict(): Generator { yield from [ [ @@ -159,462 +82,101 @@ public function providePermitEmptyCases(): Generator ['foo' => false], true, ], - [ - ['foo' => 'permit_empty|valid_email'], - ['foo' => ''], - true, - ], - [ - ['foo' => 'permit_empty|valid_email'], - ['foo' => 'user@domain.tld'], - true, - ], - [ - ['foo' => 'permit_empty|valid_email'], - ['foo' => 'invalid'], - false, - ], - // Required has more priority - [ - ['foo' => 'permit_empty|required|valid_email'], - ['foo' => ''], - false, - ], - [ - ['foo' => 'permit_empty|required'], - ['foo' => ''], - false, - ], - [ - ['foo' => 'permit_empty|required'], - ['foo' => null], - false, - ], - [ - ['foo' => 'permit_empty|required'], - ['foo' => false], - false, - ], - // This tests will return true because the input data is trimmed - [ - ['foo' => 'permit_empty|required'], - ['foo' => '0'], - true, - ], - [ - ['foo' => 'permit_empty|required'], - ['foo' => 0], - true, - ], - [ - ['foo' => 'permit_empty|required'], - ['foo' => 0.0], - true, - ], - [ - ['foo' => 'permit_empty|required_with[bar]'], - ['foo' => ''], - true, - ], - [ - ['foo' => 'permit_empty|required_with[bar]'], - ['foo' => 0], - true, - ], - [ - ['foo' => 'permit_empty|required_with[bar]'], - ['foo' => 0.0, 'bar' => 1], - true, - ], - [ - ['foo' => 'permit_empty|required_with[bar]'], - ['foo' => '', 'bar' => 1], - false, - ], - [ - ['foo' => 'permit_empty|required_without[bar]'], - ['foo' => ''], - false, - ], - [ - ['foo' => 'permit_empty|required_without[bar]'], - ['foo' => 0], - true, - ], - [ - ['foo' => 'permit_empty|required_without[bar]'], - ['foo' => 0.0, 'bar' => 1], - true, - ], - [ - ['foo' => 'permit_empty|required_without[bar]'], - ['foo' => '', 'bar' => 1], - true, - ], - ]; - } - - /** - * @dataProvider provideMatchesCases - */ - public function testMatches(array $data, bool $expected): void - { - $this->validation->setRules(['foo' => 'matches[bar]']); - $this->assertSame($expected, $this->validation->run($data)); - } - - public function provideMatchesCases(): Generator - { - yield from [ - [['foo' => null, 'bar' => null], true], - [['foo' => 'match', 'bar' => 'match'], true], - [['foo' => 'match', 'bar' => 'nope'], false], - ]; - } - - /** - * @dataProvider provideMatchesNestedCases - */ - public function testMatchesNested(array $data, bool $expected): void - { - $this->validation->setRules(['nested.foo' => 'matches[nested.bar]']); - $this->assertSame($expected, $this->validation->run($data)); - } - - public function provideMatchesNestedCases(): Generator - { - yield from [ - [['nested' => ['foo' => 'match', 'bar' => 'match']], true], - [['nested' => ['foo' => 'match', 'bar' => 'nope']], false], ]; } /** - * @dataProvider provideMatchesCases + * @dataProvider provideGreaterThanEqualStrict + * + * @param int $value */ - public function testDiffers(array $data, bool $expected): void + public function testGreaterThanEqualStrict($value, string $param, bool $expected): void { - $this->validation->setRules(['foo' => 'differs[bar]']); - $this->assertSame(! $expected, $this->validation->run($data)); - } + $this->validation->setRules(['foo' => "greater_than_equal_to[{$param}]"]); - /** - * @dataProvider provideMatchesNestedCases - */ - public function testDiffersNested(array $data, bool $expected): void - { - $this->validation->setRules(['nested.foo' => 'differs[nested.bar]']); - $this->assertSame(! $expected, $this->validation->run($data)); - } - - /** - * @dataProvider provideEqualsCases - */ - public function testEquals(array $data, string $param, bool $expected): void - { - $this->validation->setRules(['foo' => "equals[{$param}]"]); + $data = ['foo' => $value]; $this->assertSame($expected, $this->validation->run($data)); } - public function provideEqualsCases(): Generator - { - yield from [ - 'null' => [['foo' => null], '', false], - 'empty' => [['foo' => ''], '', true], - 'fail' => [['foo' => 'bar'], 'notbar', false], - 'pass' => [['foo' => 'bar'], 'bar', true], - 'casing' => [['foo' => 'bar'], 'Bar', false], - ]; - } - - /** - * @dataProvider provideMinLengthCases - */ - public function testMinLength(?string $data, string $length, bool $expected): void - { - $this->validation->setRules(['foo' => "min_length[{$length}]"]); - $this->assertSame($expected, $this->validation->run(['foo' => $data])); - } - - public function provideMinLengthCases(): Generator + public function provideGreaterThanEqualStrict(): Generator { yield from [ - 'null' => [null, '2', false], - 'less' => ['bar', '2', true], - 'equal' => ['bar', '3', true], - 'greater' => ['bar', '4', false], + [0, '0', true], + [1, '0', true], + [-1, '0', false], + [true, '0', false], ]; } /** - * @dataProvider provideMinLengthCases - */ - public function testMaxLength(?string $data, string $length, bool $expected): void - { - $this->validation->setRules(['foo' => "max_length[{$length}]"]); - $this->assertSame(! $expected || $length === '3', $this->validation->run(['foo' => $data])); - } - - public function testMaxLengthReturnsFalseWithNonNumericVal(): void - { - $this->validation->setRules(['foo' => 'max_length[bar]']); - $this->assertFalse($this->validation->run(['foo' => 'bar'])); - } - - /** - * @dataProvider provideExactLengthCases + * @dataProvider provideGreaterThanStrict + * + * @param int $value */ - public function testExactLength(?string $data, bool $expected): void - { - $this->validation->setRules(['foo' => 'exact_length[3]']); - $this->assertSame($expected, $this->validation->run(['foo' => $data])); - } - - public function provideExactLengthCases(): Generator + public function testGreaterThanStrict($value, string $param, bool $expected): void { - yield from [ - 'null' => [null, false], - 'exact' => ['bar', true], - 'less' => ['ba', false], - 'greater' => ['bars', false], - ]; - } + $this->validation->setRules(['foo' => "greater_than[{$param}]"]); - public function testExactLengthDetectsBadLength(): void - { - $data = ['foo' => 'bar']; - $this->validation->setRules(['foo' => 'exact_length[abc]']); - $this->assertFalse($this->validation->run($data)); - } - - /** - * @dataProvider greaterThanProvider - */ - public function testGreaterThan(?string $first, ?string $second, bool $expected): void - { - $data = ['foo' => $first]; - $this->validation->setRules(['foo' => "greater_than[{$second}]"]); + $data = ['foo' => $value]; $this->assertSame($expected, $this->validation->run($data)); } - public function greaterThanProvider(): Generator + public function provideGreaterThanStrict(): Generator { yield from [ - ['-10', '-11', true], - ['10', '9', true], - ['10', '10', false], - ['10', 'a', false], - ['10a', '10', false], - [null, null, false], + [-10, '-11', true], + [10, '9', true], + [10, '10', false], + [10, 'a', false], + [true, '0', false], ]; } /** - * @dataProvider greaterThanEqualProvider + * @dataProvider provideLessThanStrict + * + * @param int $value */ - public function testGreaterThanEqual(?string $first, ?string $second, bool $expected): void - { - $data = ['foo' => $first]; - $this->validation->setRules(['foo' => "greater_than_equal_to[{$second}]"]); - $this->assertSame($expected, $this->validation->run($data)); - } - - public function greaterThanEqualProvider(): Generator + public function testLessThanStrict($value, string $param, bool $expected): void { - yield from [ - ['0', '0', true], - ['1', '0', true], - ['-1', '0', false], - ['10a', '0', false], - [null, null, false], - ['1', null, true], - [null, '1', false], - ]; - } + $this->validation->setRules(['foo' => "less_than[{$param}]"]); - /** - * @dataProvider lessThanProvider - */ - public function testLessThan(?string $first, ?string $second, bool $expected): void - { - $data = ['foo' => $first]; - $this->validation->setRules(['foo' => "less_than[{$second}]"]); + $data = ['foo' => $value]; $this->assertSame($expected, $this->validation->run($data)); } - public function lessThanProvider(): Generator + public function provideLessThanStrict(): Generator { yield from [ - ['-10', '-11', false], - ['9', '10', true], - ['10', '9', false], - ['10', '10', false], - ['10', 'a', true], - ['10a', '10', false], - [null, null, false], + [-10, '-11', false], + [9, '10', true], + [10, '9', false], + [10, '10', false], + [10, 'a', true], + [true, '0', false], ]; } /** - * @dataProvider lessThanEqualProvider + * @dataProvider provideLessThanEqualStrict + * + * @param int $value */ - public function testLessEqualThan(?string $first, ?string $second, bool $expected): void + public function testLessEqualThanStrict($value, ?string $param, bool $expected): void { - $data = ['foo' => $first]; - $this->validation->setRules(['foo' => "less_than_equal_to[{$second}]"]); - $this->assertSame($expected, $this->validation->run($data)); - } + $this->validation->setRules(['foo' => "less_than_equal_to[{$param}]"]); - public function lessThanEqualProvider(): Generator - { - yield from [ - ['0', '0', true], - ['1', '0', false], - ['-1', '0', true], - ['10a', '0', false], - [null, null, false], - ['1', null, false], - [null, '1', false], - ]; - } - - /** - * @dataProvider inListProvider - */ - public function testInList(?string $first, ?string $second, bool $expected): void - { - $data = ['foo' => $first]; - $this->validation->setRules(['foo' => "in_list[{$second}]"]); - $this->assertSame($expected, $this->validation->run($data)); - } - - /** - * @dataProvider inListProvider - */ - public function testNotInList(?string $first, ?string $second, bool $expected): void - { - $data = ['foo' => $first]; - $this->validation->setRules(['foo' => "not_in_list[{$second}]"]); - $this->assertSame(! $expected, $this->validation->run($data)); - } - - public function inListProvider(): Generator - { - yield from [ - ['red', 'red,Blue,123', true], - ['Blue', 'red, Blue,123', true], - ['Blue', 'red,Blue,123', true], - ['123', 'red,Blue,123', true], - ['Red', 'red,Blue,123', false], - [' red', 'red,Blue,123', false], - ['1234', 'red,Blue,123', false], - [null, 'red,Blue,123', false], - ['red', null, false], - ]; - } - - /** - * @dataProvider requiredWithProvider - */ - public function testRequiredWith(?string $field, ?string $check, bool $expected): void - { - $data = [ - 'foo' => 'bar', - 'bar' => 'something', - 'baz' => null, - 'array' => [ - 'nonEmptyField1' => 'value1', - 'nonEmptyField2' => 'value2', - 'emptyField1' => null, - 'emptyField2' => null, - ], - ]; - - $this->validation->setRules([$field => "required_with[{$check}]"]); + $data = ['foo' => $value]; $this->assertSame($expected, $this->validation->run($data)); } - public function requiredWithProvider(): Generator + public function provideLessThanEqualStrict(): Generator { yield from [ - ['nope', 'bar', false], - ['foo', 'bar', true], - ['nope', 'baz', true], - [null, null, true], - [null, 'foo', false], - ['foo', null, true], - [ - 'array.emptyField1', - 'array.emptyField2', - true, - ], - [ - 'array.nonEmptyField1', - 'array.emptyField2', - true, - ], - [ - 'array.emptyField1', - 'array.nonEmptyField2', - false, - ], - [ - 'array.nonEmptyField1', - 'array.nonEmptyField2', - true, - ], - ]; - } - - /** - * @dataProvider requiredWithoutProvider - */ - public function testRequiredWithout(?string $field, ?string $check, bool $expected): void - { - $data = [ - 'foo' => 'bar', - 'bar' => 'something', - 'baz' => null, - 'array' => [ - 'nonEmptyField1' => 'value1', - 'nonEmptyField2' => 'value2', - 'emptyField1' => null, - 'emptyField2' => null, - ], - ]; - - $this->validation->setRules([$field => "required_without[{$check}]"]); - $this->assertSame($expected, $this->validation->run($data)); - } - - public function requiredWithoutProvider(): Generator - { - yield from [ - ['nope', 'bars', false], - ['foo', 'nope', true], - [null, null, false], - [null, 'foo', true], - ['foo', null, true], - [ - 'array.emptyField1', - 'array.emptyField2', - false, - ], - [ - 'array.nonEmptyField1', - 'array.emptyField2', - true, - ], - [ - 'array.emptyField1', - 'array.nonEmptyField2', - true, - ], - [ - 'array.nonEmptyField1', - 'array.nonEmptyField2', - true, - ], + [0, '0', true], + [1, '0', false], + [-1, '0', true], + [true, '0', false], ]; } }