diff --git a/docs/03-handling-exceptions.md b/docs/03-handling-exceptions.md index 490ad053d..75ba08d85 100644 --- a/docs/03-handling-exceptions.md +++ b/docs/03-handling-exceptions.md @@ -19,7 +19,7 @@ try { The code above generates the following output: ```no-highlight -- All the required rules must pass for "The Respect Panda" +- "The Respect Panda" must pass all the rules - "The Respect Panda" must contain only letters (a-z) and digits (0-9) - "The Respect Panda" must contain only lowercase letters ``` @@ -44,7 +44,7 @@ The code above generates the following output: ```no-highlight Array ( - [__root__] => All the required rules must pass for "The Respect Panda" + [__root__] => "The Respect Panda" must pass all the rules [alnum] => "The Respect Panda" must contain only letters (a-z) and digits (0-9) [lowercase] => "The Respect Panda" must contain only lowercase letters ) diff --git a/docs/rules/AllOf.md b/docs/rules/AllOf.md index f35d07c8f..41c5bf91f 100644 --- a/docs/rules/AllOf.md +++ b/docs/rules/AllOf.md @@ -12,17 +12,21 @@ v::allOf(v::intVal(), v::positive())->isValid(15); // true ### `AllOf::TEMPLATE_SOME` -| Mode | Template | -|------------|----------------------------------------| -| `default` | These rules must pass for {{name}} | -| `inverted` | These rules must not pass for {{name}} | +Used when some rules must be failed. -### `AllOf::TEMPLATE_NONE` +| Mode | Template | +|------------|------------------------------| +| `default` | {{name}} must pass the rules | +| `inverted` | {{name}} must pass the rules | -| Mode | Template | -|------------|-----------------------------------------------| -| `default` | All the required rules must pass for {{name}} | -| `inverted` | None of these rules must pass for {{name}} | +### `AllOf::TEMPLATE_ALL` + +Used when all rules have failed. + +| Mode | Template | +|------------|----------------------------------| +| `default` | {{name}} must pass all the rules | +| `inverted` | {{name}} must pass all the rules | ## Template placeholders diff --git a/docs/rules/AnyOf.md b/docs/rules/AnyOf.md index 4c79ef547..afdfdf77c 100644 --- a/docs/rules/AnyOf.md +++ b/docs/rules/AnyOf.md @@ -17,10 +17,10 @@ so `AnyOf()` returns true. ### `AnyOf::TEMPLATE_STANDARD` -| Mode | Template | -|------------|--------------------------------------------------------| -| `default` | At least one of these rules must pass for {{name}} | -| `inverted` | At least one of these rules must not pass for {{name}} | +| Mode | Template | +|------------|----------------------------------------------| +| `default` | {{name}} must pass at least one of the rules | +| `inverted` | {{name}} must pass at least one of the rules | ## Template placeholders diff --git a/docs/rules/Attributes.md b/docs/rules/Attributes.md index c5061cb53..f1d81b51c 100644 --- a/docs/rules/Attributes.md +++ b/docs/rules/Attributes.md @@ -49,10 +49,10 @@ v::attributes()->assert(new Person('John Doe', 'john.doe@gmail.com', '2020-06-23 v::attributes()->assert(new Person('', 'not an email', 'not a date', 'not a phone number')); // Full message: -// - All the required rules must pass for `Person { +$name="" +$email="not an email" +$birthdate="not a date" +$phone="not a phone number" }` +// - `Person { +$name="" +$email="not an email" +$birthdate="not a date" +$phone="not a phone number" }` must pass all the rules // - name must not be empty // - email must be a valid email address -// - All the required rules must pass for birthdate +// - birthdate must pass all the rules // - birthdate must be a valid date in the format "2005-12-30" // - For comparison with now, birthdate must be a valid datetime // - phone must be a valid telephone number or must be null diff --git a/docs/rules/NoneOf.md b/docs/rules/NoneOf.md index 0126efb70..19317a537 100644 --- a/docs/rules/NoneOf.md +++ b/docs/rules/NoneOf.md @@ -15,12 +15,23 @@ In the sample above, 'foo' isn't a integer nor a float, so noneOf returns true. ## Templates -### `NoneOf::TEMPLATE_STANDARD` +### `NoneOf::TEMPLATE_SOME` -| Mode | Template | -|------------|--------------------------------------------| -| `default` | None of these rules must pass for {{name}} | -| `inverted` | All of these rules must pass for {{name}} | +Used when some rules have passed. + +| Mode | Template | +|------------|------------------------------| +| `default` | {{name}} must pass the rules | +| `inverted` | {{name}} must pass the rules | + +### `NoneOf::TEMPLATE_ALL` + +Used when all rules have passed. + +| Mode | Template | +|------------|----------------------------------| +| `default` | {{name}} must pass all the rules | +| `inverted` | {{name}} must pass all the rules | ## Template placeholders diff --git a/docs/rules/OneOf.md b/docs/rules/OneOf.md index a2ee84e62..858e3aa58 100644 --- a/docs/rules/OneOf.md +++ b/docs/rules/OneOf.md @@ -16,12 +16,23 @@ character, one or the other, but not neither nor both. ## Templates -### `OneOf::TEMPLATE_STANDARD` +### `OneOf::TEMPLATE_NONE` -| Mode | Template | -|------------|----------------------------------------------------| -| `default` | Only one of these rules must pass for {{name}} | -| `inverted` | Only one of these rules must not pass for {{name}} | +Used when none of the rules have passed. + +| Mode | Template | +|------------|-------------------------------------| +| `default` | {{name}} must pass one of the rules | +| `inverted` | {{name}} must pass one of the rules | + +### `OneOf::TEMPLATE_MORE_THAN_ONE` + +Used when more than one rule has passed. + +| Mode | Template | +|------------|------------------------------------------| +| `default` | {{name}} must pass only one of the rules | +| `inverted` | {{name}} must pass only one of the rules | ## Template placeholders diff --git a/library/Rules/AllOf.php b/library/Rules/AllOf.php index 6f3602ff1..19452103c 100644 --- a/library/Rules/AllOf.php +++ b/library/Rules/AllOf.php @@ -22,18 +22,18 @@ #[Attribute(Attribute::TARGET_PROPERTY | Attribute::IS_REPEATABLE)] #[Template( - 'These rules must pass for {{name}}', - 'These rules must not pass for {{name}}', + '{{name}} must pass the rules', + '{{name}} must pass the rules', self::TEMPLATE_SOME, )] #[Template( - 'All the required rules must pass for {{name}}', - 'None of these rules must pass for {{name}}', - self::TEMPLATE_NONE, + '{{name}} must pass all the rules', + '{{name}} must pass all the rules', + self::TEMPLATE_ALL, )] final class AllOf extends Composite { - public const TEMPLATE_NONE = '__none__'; + public const TEMPLATE_ALL = '__all__'; public const TEMPLATE_SOME = '__some__'; public function evaluate(mixed $input): Result @@ -43,7 +43,7 @@ public function evaluate(mixed $input): Result $failed = array_filter($children, static fn (Result $result): bool => !$result->isValid); $template = self::TEMPLATE_SOME; if (count($children) === count($failed)) { - $template = self::TEMPLATE_NONE; + $template = self::TEMPLATE_ALL; } return (new Result($valid, $input, $this, [], $template))->withChildren(...$children); diff --git a/library/Rules/AnyOf.php b/library/Rules/AnyOf.php index adf170587..feea7b80a 100644 --- a/library/Rules/AnyOf.php +++ b/library/Rules/AnyOf.php @@ -20,8 +20,8 @@ #[Attribute(Attribute::TARGET_PROPERTY | Attribute::IS_REPEATABLE)] #[Template( - 'At least one of these rules must pass for {{name}}', - 'At least one of these rules must not pass for {{name}}', + '{{name}} must pass at least one of the rules', + '{{name}} must pass at least one of the rules', )] final class AnyOf extends Composite { diff --git a/library/Rules/NoneOf.php b/library/Rules/NoneOf.php index 953a4d1b8..5b1b571db 100644 --- a/library/Rules/NoneOf.php +++ b/library/Rules/NoneOf.php @@ -15,24 +15,37 @@ use Respect\Validation\Rule; use Respect\Validation\Rules\Core\Composite; +use function array_filter; use function array_map; use function array_reduce; +use function count; #[Attribute(Attribute::TARGET_PROPERTY | Attribute::IS_REPEATABLE)] #[Template( - 'None of these rules must pass for {{name}}', - 'All of these rules must pass for {{name}}', + '{{name}} must pass the rules', + '{{name}} must pass the rules', + self::TEMPLATE_SOME, +)] +#[Template( + '{{name}} must pass all the rules', + '{{name}} must pass all the rules', + self::TEMPLATE_ALL, )] final class NoneOf extends Composite { + public const TEMPLATE_ALL = '__all__'; + public const TEMPLATE_SOME = '__some__'; + public function evaluate(mixed $input): Result { - $children = array_map( - static fn (Rule $rule) => $rule->evaluate($input)->withInvertedMode(), - $this->rules - ); + $children = array_map(static fn (Rule $rule) => $rule->evaluate($input)->withInvertedMode(), $this->rules); $valid = array_reduce($children, static fn (bool $carry, Result $result) => $carry && $result->isValid, true); + $failed = array_filter($children, static fn (Result $result): bool => !$result->isValid); + $template = self::TEMPLATE_SOME; + if (count($children) === count($failed)) { + $template = self::TEMPLATE_ALL; + } - return (new Result($valid, $input, $this))->withChildren(...$children); + return (new Result($valid, $input, $this, [], $template))->withChildren(...$children); } } diff --git a/library/Rules/OneOf.php b/library/Rules/OneOf.php index 567d5c0bf..b47375bd3 100644 --- a/library/Rules/OneOf.php +++ b/library/Rules/OneOf.php @@ -15,21 +15,45 @@ use Respect\Validation\Rule; use Respect\Validation\Rules\Core\Composite; +use function array_filter; use function array_map; use function array_reduce; +use function count; +use function usort; #[Attribute(Attribute::TARGET_PROPERTY | Attribute::IS_REPEATABLE)] #[Template( - 'Only one of these rules must pass for {{name}}', - 'Only one of these rules must not pass for {{name}}', + '{{name}} must pass one of the rules', + '{{name}} must pass one of the rules', + self::TEMPLATE_NONE, +)] +#[Template( + '{{name}} must pass only one of the rules', + '{{name}} must pass only one of the rules', + self::TEMPLATE_MORE_THAN_ONE, )] final class OneOf extends Composite { + public const TEMPLATE_NONE = '__none__'; + public const TEMPLATE_MORE_THAN_ONE = '__more_than_one__'; + public function evaluate(mixed $input): Result { $children = array_map(static fn (Rule $rule) => $rule->evaluate($input), $this->rules); $valid = array_reduce($children, static fn (bool $carry, Result $result) => $carry xor $result->isValid, false); + $validChildren = array_filter($children, static fn (Result $result): bool => $result->isValid); + $template = self::TEMPLATE_NONE; + if (count($validChildren) > 1) { + // Put the failed children at the top, so it makes sense in the main error message + usort($children, static fn (Result $a, Result $b): int => $a->isValid <=> $b->isValid); + + $template = self::TEMPLATE_MORE_THAN_ONE; + $children = array_map( + static fn (Result $child) => $child->isValid ? $child->withInvertedValidation() : $child, + $children + ); + } - return (new Result($valid, $input, $this))->withChildren(...$children); + return (new Result($valid, $input, $this, [], $template))->withChildren(...$children); } } diff --git a/tests/feature/AssertWithKeysTest.php b/tests/feature/AssertWithKeysTest.php index e1705c7a2..521cc0d5c 100644 --- a/tests/feature/AssertWithKeysTest.php +++ b/tests/feature/AssertWithKeysTest.php @@ -37,13 +37,13 @@ ], ]), <<<'FULL_MESSAGE' - - All the required rules must pass for the given data - - All the required rules must pass for mysql + - the given data must pass all the rules + - mysql must pass all the rules - host must be a string - user must be present - password must be present - schema must be a string - - All the required rules must pass for postgresql + - postgresql must pass all the rules - host must be present - user must be a string - password must be a string diff --git a/tests/feature/AssertWithPropertiesTest.php b/tests/feature/AssertWithPropertiesTest.php index 8e953d626..a57bbd4f2 100644 --- a/tests/feature/AssertWithPropertiesTest.php +++ b/tests/feature/AssertWithPropertiesTest.php @@ -45,10 +45,10 @@ function (): void { ->assert($object); }, <<<'FULL_MESSAGE' - - All the required rules must pass for the given data - - These rules must pass for mysql + - the given data must pass all the rules + - mysql must pass the rules - host must be a string - - These rules must pass for postgresql + - postgresql must pass the rules - user must be a string FULL_MESSAGE, )); diff --git a/tests/feature/GetFullMessageShouldIncludeAllValidationMessagesInAChainTest.php b/tests/feature/GetFullMessageShouldIncludeAllValidationMessagesInAChainTest.php index 4167114b5..9a86cb9de 100644 --- a/tests/feature/GetFullMessageShouldIncludeAllValidationMessagesInAChainTest.php +++ b/tests/feature/GetFullMessageShouldIncludeAllValidationMessagesInAChainTest.php @@ -12,7 +12,7 @@ test('Scenario #1', expectFullMessage( fn() => Validator::stringType()->lengthBetween(2, 15)->assert(0), <<<'FULL_MESSAGE' - - All the required rules must pass for 0 + - 0 must pass all the rules - 0 must be a string - 0 must be a countable value or a string FULL_MESSAGE, diff --git a/tests/feature/GetMessagesShouldIncludeAllValidationMessagesInAChainTest.php b/tests/feature/GetMessagesShouldIncludeAllValidationMessagesInAChainTest.php index e391be986..e329867c3 100644 --- a/tests/feature/GetMessagesShouldIncludeAllValidationMessagesInAChainTest.php +++ b/tests/feature/GetMessagesShouldIncludeAllValidationMessagesInAChainTest.php @@ -20,7 +20,7 @@ function (): void { ->assert(['username' => 'u', 'birthdate' => 'Not a date', 'password' => '']); }, [ - '__root__' => 'All the required rules must pass for `["username": "u", "birthdate": "Not a date", "password": ""]`', + '__root__' => '`["username": "u", "birthdate": "Not a date", "password": ""]` must pass all the rules', 'username' => 'The length of username must be between 2 and 32', 'birthdate' => 'birthdate must be a valid date/time', 'password' => 'password must not be empty', diff --git a/tests/feature/GetMessagesTest.php b/tests/feature/GetMessagesTest.php index a18315667..b12b234c1 100644 --- a/tests/feature/GetMessagesTest.php +++ b/tests/feature/GetMessagesTest.php @@ -20,16 +20,16 @@ ->key('schema', v::stringType())) ->assert(['mysql' => ['host' => 42, 'schema' => 42], 'postgresql' => ['user' => 42, 'password' => 42]]), [ - '__root__' => 'All the required rules must pass for `["mysql": ["host": 42, "schema": 42], "postgresql": ["user": 42, "password": 42]]`', + '__root__' => '`["mysql": ["host": 42, "schema": 42], "postgresql": ["user": 42, "password": 42]]` must pass all the rules', 'mysql' => [ - '__root__' => 'All the required rules must pass for mysql', + '__root__' => 'mysql must pass all the rules', 'host' => 'host must be a string', 'user' => 'user must be present', 'password' => 'password must be present', 'schema' => 'schema must be a string', ], 'postgresql' => [ - '__root__' => 'All the required rules must pass for postgresql', + '__root__' => 'postgresql must pass all the rules', 'host' => 'host must be present', 'user' => 'user must be a string', 'password' => 'password must be a string', diff --git a/tests/feature/GetMessagesWithReplacementsTest.php b/tests/feature/GetMessagesWithReplacementsTest.php index c44d8ce5b..c57cf13ee 100644 --- a/tests/feature/GetMessagesWithReplacementsTest.php +++ b/tests/feature/GetMessagesWithReplacementsTest.php @@ -49,16 +49,16 @@ function (): void { ); }, [ - '__root__' => 'All the required rules must pass for `["mysql": ["host": 42, "schema": 42], "postgresql": ["user": 42, "password": 42]]`', + '__root__' => '`["mysql": ["host": 42, "schema": 42], "postgresql": ["user": 42, "password": 42]]` must pass all the rules', 'mysql' => [ - '__root__' => 'All the required rules must pass for mysql', + '__root__' => 'mysql must pass all the rules', 'host' => '`host` should be a MySQL host', 'user' => 'Value should be a MySQL username', 'password' => 'password must be present', 'schema' => 'schema must be a string', ], 'postgresql' => [ - '__root__' => 'All the required rules must pass for postgresql', + '__root__' => 'postgresql must pass all the rules', 'host' => 'host must be present', 'user' => 'user must be a string', 'password' => 'password must be a string', diff --git a/tests/feature/Issues/Issue1289Test.php b/tests/feature/Issues/Issue1289Test.php index ad8e9aae4..9bb2767b0 100644 --- a/tests/feature/Issues/Issue1289Test.php +++ b/tests/feature/Issues/Issue1289Test.php @@ -47,17 +47,17 @@ ]), 'default must be a string', <<<'FULL_MESSAGE' - - These rules must pass for `["default": 2, "description": [], "children": ["nope"]]` - - Only one of these rules must pass for default + - `["default": 2, "description": [], "children": ["nope"]]` must pass the rules + - default must pass one of the rules - default must be a string - default must be a boolean - description must be a string value FULL_MESSAGE, [ 0 => [ - '__root__' => 'These rules must pass for `["default": 2, "description": [], "children": ["nope"]]`', + '__root__' => '`["default": 2, "description": [], "children": ["nope"]]` must pass the rules', 'default' => [ - '__root__' => 'Only one of these rules must pass for default', + '__root__' => 'default must pass one of the rules', 'stringType' => 'default must be a string', 'boolType' => 'default must be a boolean', ], diff --git a/tests/feature/Issues/Issue1333Test.php b/tests/feature/Issues/Issue1333Test.php index ea391ddbd..a633826f6 100644 --- a/tests/feature/Issues/Issue1333Test.php +++ b/tests/feature/Issues/Issue1333Test.php @@ -11,12 +11,12 @@ fn() => v::noWhitespace()->email()->setName('User Email')->assert('not email'), 'User Email must not contain whitespaces', <<<'FULL_MESSAGE' - - All the required rules must pass for User Email + - User Email must pass all the rules - User Email must not contain whitespaces - User Email must be a valid email address FULL_MESSAGE, [ - '__root__' => 'All the required rules must pass for User Email', + '__root__' => 'User Email must pass all the rules', 'noWhitespace' => 'User Email must not contain whitespaces', 'email' => 'User Email must be a valid email address', ], diff --git a/tests/feature/Issues/Issue1334Test.php b/tests/feature/Issues/Issue1334Test.php index a37e4e3eb..8a7b676fc 100644 --- a/tests/feature/Issues/Issue1334Test.php +++ b/tests/feature/Issues/Issue1334Test.php @@ -25,20 +25,20 @@ function (): void { 'street must be present', <<<'FULL_MESSAGE' - Each item in `[["region": "Oregon", "country": "USA", "other": 123], ["street": "", "region": "Oregon", "country": "USA"], ["s ... ]` must be valid - - These rules must pass for `["region": "Oregon", "country": "USA", "other": 123]` + - `["region": "Oregon", "country": "USA", "other": 123]` must pass the rules - street must be present - - These rules must pass for other + - other must pass the rules - other must be a string or must be null - - These rules must pass for `["street": "", "region": "Oregon", "country": "USA"]` + - `["street": "", "region": "Oregon", "country": "USA"]` must pass the rules - street must not be empty - - These rules must pass for `["street": 123, "region": "Oregon", "country": "USA"]` + - `["street": 123, "region": "Oregon", "country": "USA"]` must pass the rules - street must be a string FULL_MESSAGE, [ 'each' => [ '__root__' => 'Each item in `[["region": "Oregon", "country": "USA", "other": 123], ["street": "", "region": "Oregon", "country": "USA"], ["s ... ]` must be valid', 0 => [ - '__root__' => 'These rules must pass for `["region": "Oregon", "country": "USA", "other": 123]`', + '__root__' => '`["region": "Oregon", "country": "USA", "other": 123]` must pass the rules', 'street' => 'street must be present', 'other' => 'other must be a string or must be null', ], diff --git a/tests/feature/Issues/Issue1348Test.php b/tests/feature/Issues/Issue1348Test.php deleted file mode 100644 index ef8219496..000000000 --- a/tests/feature/Issues/Issue1348Test.php +++ /dev/null @@ -1,82 +0,0 @@ - - * SPDX-License-Identifier: MIT - */ - -declare(strict_types=1); - -use Respect\Validation\Validator; - -$cars = [ - ['manufacturer' => 'Honda', 'model' => 'Accord'], - ['manufacturer' => 'Toyota', 'model' => 'Rav4'], - ['manufacturer' => 'Ford', 'model' => 'not real'], - ['manufacturer' => 'Honda', 'model' => 'not valid'], -]; - -test('https://github.com/Respect/Validation/issues/1289', expectAll( - fn() => v::arrayType()->each( - v::oneOf( - v::key('manufacturer', v::equals('Honda'))->key('model', v::in(['Accord', 'Fit'])), - v::key('manufacturer', v::equals('Toyota'))->key('model', v::in(['Rav4', 'Camry'])), - v::key('manufacturer', v::equals('Ford'))->key('model', Validator::in(['F150', 'Bronco'])), - ), - )->assert($cars), - 'manufacturer must be equal to "Honda"', - <<<'FULL_MESSAGE' - - Each item in `[["manufacturer": "Honda", "model": "Accord"], ["manufacturer": "Toyota", "model": "Rav4"], ["manufacturer": "Fo ... ]` must be valid - - Only one of these rules must pass for `["manufacturer": "Ford", "model": "not real"]` - - All the required rules must pass for `["manufacturer": "Ford", "model": "not real"]` - - manufacturer must be equal to "Honda" - - model must be in `["Accord", "Fit"]` - - All the required rules must pass for `["manufacturer": "Ford", "model": "not real"]` - - manufacturer must be equal to "Toyota" - - model must be in `["Rav4", "Camry"]` - - These rules must pass for `["manufacturer": "Ford", "model": "not real"]` - - model must be in `["F150", "Bronco"]` - - Only one of these rules must pass for `["manufacturer": "Honda", "model": "not valid"]` - - These rules must pass for `["manufacturer": "Honda", "model": "not valid"]` - - model must be in `["Accord", "Fit"]` - - All the required rules must pass for `["manufacturer": "Honda", "model": "not valid"]` - - manufacturer must be equal to "Toyota" - - model must be in `["Rav4", "Camry"]` - - All the required rules must pass for `["manufacturer": "Honda", "model": "not valid"]` - - manufacturer must be equal to "Ford" - - model must be in `["F150", "Bronco"]` - FULL_MESSAGE, - [ - 'each' => [ - '__root__' => 'Each item in `[["manufacturer": "Honda", "model": "Accord"], ["manufacturer": "Toyota", "model": "Rav4"], ["manufacturer": "Fo ... ]` must be valid', - 2 => [ - '__root__' => 'Only one of these rules must pass for `["manufacturer": "Ford", "model": "not real"]`', - 'allOf.1' => [ - '__root__' => 'All the required rules must pass for `["manufacturer": "Ford", "model": "not real"]`', - 'manufacturer' => 'manufacturer must be equal to "Honda"', - 'model' => 'model must be in `["Accord", "Fit"]`', - ], - 'allOf.2' => [ - '__root__' => 'All the required rules must pass for `["manufacturer": "Ford", "model": "not real"]`', - 'manufacturer' => 'manufacturer must be equal to "Toyota"', - 'model' => 'model must be in `["Rav4", "Camry"]`', - ], - 'allOf.3' => 'model must be in `["F150", "Bronco"]`', - ], - 3 => [ - '__root__' => 'Only one of these rules must pass for `["manufacturer": "Honda", "model": "not valid"]`', - 'allOf.1' => 'model must be in `["Accord", "Fit"]`', - 'allOf.2' => [ - '__root__' => 'All the required rules must pass for `["manufacturer": "Honda", "model": "not valid"]`', - 'manufacturer' => 'manufacturer must be equal to "Toyota"', - 'model' => 'model must be in `["Rav4", "Camry"]`', - ], - 'allOf.3' => [ - '__root__' => 'All the required rules must pass for `["manufacturer": "Honda", "model": "not valid"]`', - 'manufacturer' => 'manufacturer must be equal to "Ford"', - 'model' => 'model must be in `["F150", "Bronco"]`', - ], - ], - ], - ], -)); diff --git a/tests/feature/Issues/Issue1376Test.php b/tests/feature/Issues/Issue1376Test.php index 3f1bb038f..3671c121c 100644 --- a/tests/feature/Issues/Issue1376Test.php +++ b/tests/feature/Issues/Issue1376Test.php @@ -16,20 +16,20 @@ ->assert((object) ['author' => 'foo']), 'title must be present', <<<'FULL_MESSAGE' - - All the required rules must pass for `stdClass { +$author="foo" }` + - `stdClass { +$author="foo" }` must pass all the rules - title must be present - description must be present - - All the required rules must pass for author + - author must pass all the rules - author must be an integer - The length of author must be between 1 and 2 - user must be present FULL_MESSAGE, [ - '__root__' => 'All the required rules must pass for `stdClass { +$author="foo" }`', + '__root__' => '`stdClass { +$author="foo" }` must pass all the rules', 'title' => 'title must be present', 'description' => 'description must be present', 'author' => [ - '__root__' => 'All the required rules must pass for author', + '__root__' => 'author must pass all the rules', 'intType' => 'author must be an integer', 'lengthBetween' => 'The length of author must be between 1 and 2', ], diff --git a/tests/feature/Issues/Issue179Test.php b/tests/feature/Issues/Issue179Test.php index ac47a6526..f94f18258 100644 --- a/tests/feature/Issues/Issue179Test.php +++ b/tests/feature/Issues/Issue179Test.php @@ -25,12 +25,12 @@ function (): void { }, 'host must be a string', <<<'FULL_MESSAGE' - - These rules must pass for Settings + - Settings must pass the rules - host must be a string - user must be present FULL_MESSAGE, [ - '__root__' => 'These rules must pass for Settings', + '__root__' => 'Settings must pass the rules', 'host' => 'host must be a string', 'user' => 'user must be present', ], diff --git a/tests/feature/Issues/Issue796Test.php b/tests/feature/Issues/Issue796Test.php index 66d2c7492..8fe9842ca 100644 --- a/tests/feature/Issues/Issue796Test.php +++ b/tests/feature/Issues/Issue796Test.php @@ -42,14 +42,14 @@ ]), 'host must be a string', <<<'FULL_MESSAGE' - - All the required rules must pass for the given data - - These rules must pass for mysql + - the given data must pass all the rules + - mysql must pass the rules - host must be a string - - These rules must pass for postgresql + - postgresql must pass the rules - user must be a string FULL_MESSAGE, [ - '__root__' => 'All the required rules must pass for the given data', + '__root__' => 'the given data must pass all the rules', 'mysql' => 'host must be a string', 'postgresql' => 'user must be a string', ], diff --git a/tests/feature/Issues/Issue799Test.php b/tests/feature/Issues/Issue799Test.php index e428e486c..e8075a7af 100644 --- a/tests/feature/Issues/Issue799Test.php +++ b/tests/feature/Issues/Issue799Test.php @@ -20,12 +20,12 @@ ->assert($input), '1 must be an array value', <<<'FULL_MESSAGE' - - All the required rules must pass for 1 + - 1 must pass all the rules - 1 must be an array value - scheme must be present FULL_MESSAGE, [ - '__root__' => 'All the required rules must pass for 1', + '__root__' => '1 must pass all the rules', 'arrayVal' => '1 must be an array value', 'scheme' => 'scheme must be present', ], diff --git a/tests/feature/KeysAsValidatorNamesTest.php b/tests/feature/KeysAsValidatorNamesTest.php index 2bbe86612..37a74aa92 100644 --- a/tests/feature/KeysAsValidatorNamesTest.php +++ b/tests/feature/KeysAsValidatorNamesTest.php @@ -20,7 +20,7 @@ function (): void { ->assert(['username' => '0', 'birthdate' => 'Whatever']); }, <<<'FULL_MESSAGE' - - All the required rules must pass for User Subscription Form + - User Subscription Form must pass all the rules - The length of username must be between 2 and 32 - birthdate must be a valid date/time FULL_MESSAGE, diff --git a/tests/feature/NotWithRecursionTest.php b/tests/feature/NotWithRecursionTest.php index c7dcfc6fb..ca029b5a6 100644 --- a/tests/feature/NotWithRecursionTest.php +++ b/tests/feature/NotWithRecursionTest.php @@ -35,7 +35,7 @@ ), )->assert(2), <<<'FULL_MESSAGE' - - These rules must not pass for 2 + - 2 must pass the rules - 2 must not be an integer value - 2 must not be a positive number FULL_MESSAGE, diff --git a/tests/feature/Readme/CustomMessagesTest.php b/tests/feature/Readme/CustomMessagesTest.php index 98b1d72d4..ce21ab7ea 100644 --- a/tests/feature/Readme/CustomMessagesTest.php +++ b/tests/feature/Readme/CustomMessagesTest.php @@ -17,7 +17,7 @@ 'length' => '{{name}} must not have more than 15 chars', ]), [ - '__root__' => 'All the required rules must pass for "really messed up screen#name"', + '__root__' => '"really messed up screen#name" must pass all the rules', 'alnum' => '"really messed up screen#name" must contain only letters and digits', 'noWhitespace' => '"really messed up screen#name" cannot contain spaces', 'lengthBetween' => 'The length of "really messed up screen#name" must be between 1 and 15', diff --git a/tests/feature/Readme/ExampleTest.php b/tests/feature/Readme/ExampleTest.php index 6541d774b..6b540d184 100644 --- a/tests/feature/Readme/ExampleTest.php +++ b/tests/feature/Readme/ExampleTest.php @@ -10,7 +10,7 @@ test('Scenario #1', expectFullMessage( fn() => v::alnum()->noWhitespace()->lengthBetween(1, 15)->assert('really messed up screen#name'), <<<'FULL_MESSAGE' - - All the required rules must pass for "really messed up screen#name" + - "really messed up screen#name" must pass all the rules - "really messed up screen#name" must contain only letters (a-z) and digits (0-9) - "really messed up screen#name" must not contain whitespaces - The length of "really messed up screen#name" must be between 1 and 15 diff --git a/tests/feature/Readme/GettingMessagesAsAnArrayTest.php b/tests/feature/Readme/GettingMessagesAsAnArrayTest.php index 58d1ce9d9..16b5e6267 100644 --- a/tests/feature/Readme/GettingMessagesAsAnArrayTest.php +++ b/tests/feature/Readme/GettingMessagesAsAnArrayTest.php @@ -10,7 +10,7 @@ test('Scenario #1', expectMessages( fn() => v::alnum()->noWhitespace()->lengthBetween(1, 15)->assert('really messed up screen#name'), [ - '__root__' => 'All the required rules must pass for "really messed up screen#name"', + '__root__' => '"really messed up screen#name" must pass all the rules', 'alnum' => '"really messed up screen#name" must contain only letters (a-z) and digits (0-9)', 'noWhitespace' => '"really messed up screen#name" must not contain whitespaces', 'lengthBetween' => 'The length of "really messed up screen#name" must be between 1 and 15', diff --git a/tests/feature/Rules/AllOfTest.php b/tests/feature/Rules/AllOfTest.php index aa0f3c7d7..d215b7a24 100644 --- a/tests/feature/Rules/AllOfTest.php +++ b/tests/feature/Rules/AllOfTest.php @@ -7,33 +7,74 @@ declare(strict_types=1); -test('Two rules', expectAll( - fn() => v::allOf(v::intType(), v::negative())->assert('2'), - '"2" must be an integer', +test('Default: fail, fail', expectAll( + fn() => v::allOf(v::intType(), v::negative())->assert('string'), + '"string" must be an integer', <<<'FULL_MESSAGE' - - All the required rules must pass for "2" - - "2" must be an integer - - "2" must be a negative number + - "string" must pass all the rules + - "string" must be an integer + - "string" must be a negative number FULL_MESSAGE, [ - '__root__' => 'All the required rules must pass for "2"', - 'intType' => '"2" must be an integer', - 'negative' => '"2" must be a negative number', + '__root__' => '"string" must pass all the rules', + 'intType' => '"string" must be an integer', + 'negative' => '"string" must be a negative number', ], )); -test('Wrapped by "not"', expectAll( - fn() => v::not(v::allOf(v::intType(), v::positive()))->assert(3), - '3 must not be an integer', +test('Default: fail, pass', expectAll( + fn() => v::allOf(v::intType(), v::stringType())->assert('string'), + '"string" must be an integer', <<<'FULL_MESSAGE' - - These rules must not pass for 3 - - 3 must not be an integer - - 3 must not be a positive number + - "string" must be an integer FULL_MESSAGE, [ - '__root__' => 'These rules must not pass for 3', - 'intType' => '3 must not be an integer', - 'positive' => '3 must not be a positive number', + 'intType' => '"string" must be an integer', + ], +)); + +test('Default: fail, fail, pass', expectAll( + fn() => v::allOf(v::intType(), v::positive(), v::stringType())->assert('string'), + '"string" must be an integer', + <<<'FULL_MESSAGE' + - "string" must pass the rules + - "string" must be an integer + - "string" must be a positive number + FULL_MESSAGE, + [ + '__root__' => '"string" must pass the rules', + 'intType' => '"string" must be an integer', + 'positive' => '"string" must be a positive number', + ], +)); + +test('Inverted: pass, pass', expectAll( + fn() => v::not(v::allOf(v::intType(), v::negative()))->assert(-1), + '-1 must not be an integer', + <<<'FULL_MESSAGE' + - -1 must pass the rules + - -1 must not be an integer + - -1 must not be a negative number + FULL_MESSAGE, + [ + '__root__' => '-1 must pass the rules', + 'intType' => '-1 must not be an integer', + 'negative' => '-1 must not be a negative number', + ], +)); + +test('Inverted: pass, fail, fail', expectAll( + fn() => v::allOf(v::intType(), v::alpha(), v::stringType())->assert(2), + '2 must contain only letters (a-z)', + <<<'FULL_MESSAGE' + - 2 must pass the rules + - 2 must contain only letters (a-z) + - 2 must be a string + FULL_MESSAGE, + [ + '__root__' => '2 must pass the rules', + 'alpha' => '2 must contain only letters (a-z)', + 'stringType' => '2 must be a string', ], )); diff --git a/tests/feature/Rules/AnyOfTest.php b/tests/feature/Rules/AnyOfTest.php new file mode 100644 index 000000000..a66c66fde --- /dev/null +++ b/tests/feature/Rules/AnyOfTest.php @@ -0,0 +1,53 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +test('Default: fail, fail', expectAll( + fn() => v::anyOf(v::intType(), v::negative())->assert('string'), + '"string" must be an integer', + <<<'FULL_MESSAGE' + - "string" must pass at least one of the rules + - "string" must be an integer + - "string" must be a negative number + FULL_MESSAGE, + [ + '__root__' => '"string" must pass at least one of the rules', + 'intType' => '"string" must be an integer', + 'negative' => '"string" must be a negative number', + ], +)); + +test('Inverted: pass, pass', expectAll( + fn() => v::not(v::anyOf(v::intType(), v::negative()))->assert(-1), + '-1 must not be an integer', + <<<'FULL_MESSAGE' + - -1 must pass at least one of the rules + - -1 must not be an integer + - -1 must not be a negative number + FULL_MESSAGE, + [ + '__root__' => '-1 must pass at least one of the rules', + 'intType' => '-1 must not be an integer', + 'negative' => '-1 must not be a negative number', + ], +)); + +test('Inverted: pass, pass, fail', expectAll( + fn() => v::not(v::anyOf(v::intType(), v::negative(), v::stringType()))->assert(-1), + '-1 must not be an integer', + <<<'FULL_MESSAGE' + - -1 must pass at least one of the rules + - -1 must not be an integer + - -1 must not be a negative number + FULL_MESSAGE, + [ + '__root__' => '-1 must pass at least one of the rules', + 'intType' => '-1 must not be an integer', + 'negative' => '-1 must not be a negative number', + ], +)); diff --git a/tests/feature/Rules/AttributesTest.php b/tests/feature/Rules/AttributesTest.php index 2da23495c..902be09fa 100644 --- a/tests/feature/Rules/AttributesTest.php +++ b/tests/feature/Rules/AttributesTest.php @@ -41,20 +41,20 @@ fn() => v::attributes()->assert(new WithAttributes('', 'not an email', 'not a date', 'not a phone number')), 'name must not be empty', <<<'FULL_MESSAGE' - - All the required rules must pass for `Respect\Validation\Test\Stubs\WithAttributes { +$name="" +$email="not an email" +$birthdate="not a date" +$phone ... }` + - `Respect\Validation\Test\Stubs\WithAttributes { +$name="" +$email="not an email" +$birthdate="not a date" +$phone ... }` must pass all the rules - name must not be empty - email must be a valid email address - - All the required rules must pass for birthdate + - birthdate must pass all the rules - birthdate must be a valid date in the format "2005-12-30" - For comparison with now, birthdate must be a valid datetime - phone must be a valid telephone number or must be null FULL_MESSAGE, [ - '__root__' => 'All the required rules must pass for `Respect\\Validation\\Test\\Stubs\\WithAttributes { +$name="" +$email="not an email" +$birthdate="not a date" +$phone ... }`', + '__root__' => '`Respect\\Validation\\Test\\Stubs\\WithAttributes { +$name="" +$email="not an email" +$birthdate="not a date" +$phone ... }` must pass all the rules', 'name' => 'name must not be empty', 'email' => 'email must be a valid email address', 'birthdate' => [ - '__root__' => 'All the required rules must pass for birthdate', + '__root__' => 'birthdate must pass all the rules', 'date' => 'birthdate must be a valid date in the format "2005-12-30"', 'dateTimeDiffLessThanOrEqual' => 'For comparison with now, birthdate must be a valid datetime', ], diff --git a/tests/feature/Rules/DateTimeDiffTest.php b/tests/feature/Rules/DateTimeDiffTest.php index 326406ffc..26bd07839 100644 --- a/tests/feature/Rules/DateTimeDiffTest.php +++ b/tests/feature/Rules/DateTimeDiffTest.php @@ -116,12 +116,12 @@ fn() => v::dateTimeDiff('years', v::primeNumber()->between(2, 5))->assert('1 year ago'), 'The number of years between now and "1 year ago" must be a prime number', <<<'FULL_MESSAGE' - - All the required rules must pass for "1 year ago" + - "1 year ago" must pass all the rules - The number of years between now and "1 year ago" must be a prime number - The number of years between now and "1 year ago" must be between 2 and 5 FULL_MESSAGE, [ - '__root__' => 'All the required rules must pass for "1 year ago"', + '__root__' => '"1 year ago" must pass all the rules', 'dateTimeDiffPrimeNumber' => 'The number of years between now and "1 year ago" must be a prime number', 'dateTimeDiffBetween' => 'The number of years between now and "1 year ago" must be between 2 and 5', ], @@ -136,12 +136,12 @@ ])->assert('1 year ago'), 'The number of years between now and "1 year ago" must be a prime number', <<<'FULL_MESSAGE' - - All the required rules must pass for "1 year ago" + - "1 year ago" must pass all the rules - The number of years between now and "1 year ago" must be a prime number - The number of years between now and "1 year ago" must be between 2 and 5 FULL_MESSAGE, [ - '__root__' => 'All the required rules must pass for "1 year ago"', + '__root__' => '"1 year ago" must pass all the rules', 'dateTimeDiffPrimeNumber' => 'The number of years between now and "1 year ago" must be a prime number', 'dateTimeDiffBetween' => 'The number of years between now and "1 year ago" must be between 2 and 5', ], diff --git a/tests/feature/Rules/EachTest.php b/tests/feature/Rules/EachTest.php index 4939ad749..5110ff574 100644 --- a/tests/feature/Rules/EachTest.php +++ b/tests/feature/Rules/EachTest.php @@ -245,22 +245,22 @@ '2 must be between 5 and 7', <<<'FULL_MESSAGE' - Each item in `[2, 4]` must be valid - - All the required rules must pass for 2 + - 2 must pass all the rules - 2 must be between 5 and 7 - 2 must be an odd number - - All the required rules must pass for 4 + - 4 must pass all the rules - 4 must be between 5 and 7 - 4 must be an odd number FULL_MESSAGE, [ '__root__' => 'Each item in `[2, 4]` must be valid', 0 => [ - '__root__' => 'All the required rules must pass for 2', + '__root__' => '2 must pass all the rules', 'between' => '2 must be between 5 and 7', 'odd' => '2 must be an odd number', ], 1 => [ - '__root__' => 'All the required rules must pass for 4', + '__root__' => '4 must pass all the rules', 'between' => '4 must be between 5 and 7', 'odd' => '4 must be an odd number', ], @@ -272,11 +272,11 @@ 'my_int must be present', <<<'FULL_MESSAGE' - Each item in `[["not_int": "wrong"], ["my_int": 2], "not an array"]` must be valid - - These rules must pass for `["not_int": "wrong"]` + - `["not_int": "wrong"]` must pass the rules - my_int must be present - - These rules must pass for `["my_int": 2]` + - `["my_int": 2]` must pass the rules - my_int must be an odd number - - All the required rules must pass for "not an array" + - "not an array" must pass all the rules - "not an array" must be an array - my_int must be present FULL_MESSAGE, @@ -285,7 +285,7 @@ 0 => 'my_int must be present', 1 => 'my_int must be an odd number', 2 => [ - '__root__' => 'All the required rules must pass for "not an array"', + '__root__' => '"not an array" must pass all the rules', 'arrayType' => '"not an array" must be an array', 'my_int' => 'my_int must be present', ], diff --git a/tests/feature/Rules/LengthTest.php b/tests/feature/Rules/LengthTest.php index a8edb476a..9b946dc76 100644 --- a/tests/feature/Rules/LengthTest.php +++ b/tests/feature/Rules/LengthTest.php @@ -46,12 +46,12 @@ fn() => v::length(v::between(5, 7)->odd())->assert([]), 'The length of `[]` must be between 5 and 7', <<<'FULL_MESSAGE' - - All the required rules must pass for `[]` + - `[]` must pass all the rules - The length of `[]` must be between 5 and 7 - The length of `[]` must be an odd number FULL_MESSAGE, [ - '__root__' => 'All the required rules must pass for `[]`', + '__root__' => '`[]` must pass all the rules', 'lengthBetween' => 'The length of `[]` must be between 5 and 7', 'lengthOdd' => 'The length of `[]` must be an odd number', ], diff --git a/tests/feature/Rules/MaxTest.php b/tests/feature/Rules/MaxTest.php index afe05fcf1..10e0d57b5 100644 --- a/tests/feature/Rules/MaxTest.php +++ b/tests/feature/Rules/MaxTest.php @@ -74,12 +74,12 @@ fn() => v::max(v::between(5, 7)->odd())->assert([1, 2, 3, 4]), 'The maximum of `[1, 2, 3, 4]` must be between 5 and 7', <<<'FULL_MESSAGE' - - All the required rules must pass for `[1, 2, 3, 4]` + - `[1, 2, 3, 4]` must pass all the rules - The maximum of `[1, 2, 3, 4]` must be between 5 and 7 - The maximum of `[1, 2, 3, 4]` must be an odd number FULL_MESSAGE, [ - '__root__' => 'All the required rules must pass for `[1, 2, 3, 4]`', + '__root__' => '`[1, 2, 3, 4]` must pass all the rules', 'maxBetween' => 'The maximum of `[1, 2, 3, 4]` must be between 5 and 7', 'maxOdd' => 'The maximum of `[1, 2, 3, 4]` must be an odd number', ], diff --git a/tests/feature/Rules/MinTest.php b/tests/feature/Rules/MinTest.php index 3ffd58b29..ff41b4638 100644 --- a/tests/feature/Rules/MinTest.php +++ b/tests/feature/Rules/MinTest.php @@ -39,12 +39,12 @@ fn() => v::min(v::between(5, 7)->odd())->assert([2, 3, 4]), 'The minimum of `[2, 3, 4]` must be between 5 and 7', <<<'FULL_MESSAGE' - - All the required rules must pass for `[2, 3, 4]` + - `[2, 3, 4]` must pass all the rules - The minimum of `[2, 3, 4]` must be between 5 and 7 - The minimum of `[2, 3, 4]` must be an odd number FULL_MESSAGE, [ - '__root__' => 'All the required rules must pass for `[2, 3, 4]`', + '__root__' => '`[2, 3, 4]` must pass all the rules', 'minBetween' => 'The minimum of `[2, 3, 4]` must be between 5 and 7', 'minOdd' => 'The minimum of `[2, 3, 4]` must be an odd number', ], diff --git a/tests/feature/Rules/NamedTest.php b/tests/feature/Rules/NamedTest.php index 4f31fb85e..aa23b9d1b 100644 --- a/tests/feature/Rules/NamedTest.php +++ b/tests/feature/Rules/NamedTest.php @@ -71,13 +71,13 @@ )->assert(['vegetables' => ['root' => 12, 'stems' => 12]]), 'root must be a string', <<<'FULL_MESSAGE' - - All the required rules must pass for Vegetables + - Vegetables must pass all the rules - root must be a string - stems must be a string - fruits must be present FULL_MESSAGE, [ - '__root__' => 'All the required rules must pass for Vegetables', + '__root__' => 'Vegetables must pass all the rules', 'root' => 'root must be a string', 'stems' => 'stems must be a string', 'fruits' => 'fruits must be present', diff --git a/tests/feature/Rules/NoneOfTest.php b/tests/feature/Rules/NoneOfTest.php index ca5a15a89..97c796ed5 100644 --- a/tests/feature/Rules/NoneOfTest.php +++ b/tests/feature/Rules/NoneOfTest.php @@ -7,30 +7,58 @@ declare(strict_types=1); -test('Scenario #1', expectMessage( - fn() => v::noneOf(v::intType(), v::positive())->assert(42), - '42 must not be an integer', +test('Default: fail, fail', expectAll( + fn() => v::noneOf(v::intType(), v::negative())->assert(-1), + '-1 must not be an integer', + <<<'FULL_MESSAGE' + - -1 must pass all the rules + - -1 must not be an integer + - -1 must not be a negative number + FULL_MESSAGE, + [ + '__root__' => '-1 must pass all the rules', + 'intType' => '-1 must not be an integer', + 'negative' => '-1 must not be a negative number', + ], )); -test('Scenario #2', expectMessage( - fn() => v::not(v::noneOf(v::intType(), v::positive()))->assert('-1'), - '"-1" must be an integer', +test('Default: pass, fail', expectAll( + fn() => v::noneOf(v::intType(), v::stringType())->assert('string'), + '"string" must not be a string', + <<<'FULL_MESSAGE' + - "string" must not be a string + FULL_MESSAGE, + [ + 'stringType' => '"string" must not be a string', + ], )); -test('Scenario #3', expectFullMessage( - fn() => v::noneOf(v::intType(), v::positive())->assert(42), +test('Default: pass, fail, fail', expectAll( + fn() => v::noneOf(v::intType(), v::alpha(), v::stringType())->assert('string'), + '"string" must not contain letters (a-z)', <<<'FULL_MESSAGE' - - None of these rules must pass for 42 - - 42 must not be an integer - - 42 must not be a positive number + - "string" must pass the rules + - "string" must not contain letters (a-z) + - "string" must not be a string FULL_MESSAGE, + [ + '__root__' => '"string" must pass the rules', + 'alpha' => '"string" must not contain letters (a-z)', + 'stringType' => '"string" must not be a string', + ], )); -test('Scenario #4', expectFullMessage( - fn() => v::not(v::noneOf(v::intType(), v::positive()))->assert('-1'), +test('Inverted: fail, fail', expectAll( + fn() => v::not(v::noneOf(v::intType(), v::negative()))->assert('string'), + '"string" must be an integer', <<<'FULL_MESSAGE' -- All of these rules must pass for "-1" - - "-1" must be an integer - - "-1" must be a positive number -FULL_MESSAGE, + - "string" must pass the rules + - "string" must be an integer + - "string" must be a negative number + FULL_MESSAGE, + [ + '__root__' => '"string" must pass the rules', + 'intType' => '"string" must be an integer', + 'negative' => '"string" must be a negative number', + ], )); diff --git a/tests/feature/Rules/NullOrTest.php b/tests/feature/Rules/NullOrTest.php index 16b24b91a..0cd2c41eb 100644 --- a/tests/feature/Rules/NullOrTest.php +++ b/tests/feature/Rules/NullOrTest.php @@ -81,12 +81,12 @@ fn() => v::nullOr(v::alpha()->stringType())->assert(1234), '1234 must contain only letters (a-z) or must be null', <<<'FULL_MESSAGE' - - All the required rules must pass for 1234 + - 1234 must pass all the rules - 1234 must contain only letters (a-z) or must be null - 1234 must be a string or must be null FULL_MESSAGE, [ - '__root__' => 'All the required rules must pass for 1234', + '__root__' => '1234 must pass all the rules', 'nullOrAlpha' => '1234 must contain only letters (a-z) or must be null', 'nullOrStringType' => '1234 must be a string or must be null', ], @@ -99,12 +99,12 @@ ]), 'Should be nul or alpha', <<<'FULL_MESSAGE' - - All the required rules must pass for 1234 + - 1234 must pass all the rules - Should be nul or alpha - Should be nul or string type FULL_MESSAGE, [ - '__root__' => 'All the required rules must pass for 1234', + '__root__' => '1234 must pass all the rules', 'nullOrAlpha' => 'Should be nul or alpha', 'nullOrStringType' => 'Should be nul or string type', ], diff --git a/tests/feature/Rules/OneOfTest.php b/tests/feature/Rules/OneOfTest.php new file mode 100644 index 000000000..7aaf3b8c5 --- /dev/null +++ b/tests/feature/Rules/OneOfTest.php @@ -0,0 +1,92 @@ + + * SPDX-License-Identifier: MIT + */ + +declare(strict_types=1); + +test('Default: fail, fail', expectAll( + fn() => v::oneOf(v::intType(), v::negative())->assert('string'), + '"string" must be an integer', + <<<'FULL_MESSAGE' + - "string" must pass one of the rules + - "string" must be an integer + - "string" must be a negative number + FULL_MESSAGE, + [ + '__root__' => '"string" must pass one of the rules', + 'intType' => '"string" must be an integer', + 'negative' => '"string" must be a negative number', + ], +)); + +test('Default: fail, pass, pass', expectAll( + fn() => v::oneOf(v::intType(), v::stringType(), v::alpha())->assert('string'), + '"string" must be an integer', + <<<'FULL_MESSAGE' + - "string" must pass only one of the rules + - "string" must be an integer + - "string" must be a string + - "string" must contain only letters (a-z) + FULL_MESSAGE, + [ + '__root__' => '"string" must pass only one of the rules', + 'intType' => '"string" must be an integer', + 'stringType' => '"string" must be a string', + 'alpha' => '"string" must contain only letters (a-z)', + ], +)); + +test('Default: pass, fail, pass', expectAll( + fn() => v::oneOf(v::stringType(), v::intType(), v::alpha())->assert('string'), + '"string" must be an integer', + <<<'FULL_MESSAGE' + - "string" must pass only one of the rules + - "string" must be an integer + - "string" must be a string + - "string" must contain only letters (a-z) + FULL_MESSAGE, + [ + '__root__' => '"string" must pass only one of the rules', + 'intType' => '"string" must be an integer', + 'stringType' => '"string" must be a string', + 'alpha' => '"string" must contain only letters (a-z)', + ], +)); + +test('Default: pass, pass, fail', expectAll( + fn() => v::oneOf(v::stringType(), v::alpha(), v::intType())->assert('string'), + '"string" must be an integer', + <<<'FULL_MESSAGE' + - "string" must pass only one of the rules + - "string" must be an integer + - "string" must be a string + - "string" must contain only letters (a-z) + FULL_MESSAGE, + [ + '__root__' => '"string" must pass only one of the rules', + 'intType' => '"string" must be an integer', + 'stringType' => '"string" must be a string', + 'alpha' => '"string" must contain only letters (a-z)', + ], +)); + +test('Inverted: fail, pass', expectAll( + fn() => v::not(v::oneOf(v::intType(), v::positive()))->assert(-1), + '-1 must not be an integer', + '- -1 must not be an integer', + [ + 'intType' => '-1 must not be an integer', + ], +)); + +test('Inverted: fail, fail, pass', expectAll( + fn() => v::not(v::oneOf(v::stringType(), v::alpha(), v::negative()))->assert(-1), + '-1 must not be a negative number', + '- -1 must not be a negative number', + [ + 'negative' => '-1 must not be a negative number', + ], +)); diff --git a/tests/feature/Rules/SizeTest.php b/tests/feature/Rules/SizeTest.php index f5bf95d5f..6a102a3b7 100644 --- a/tests/feature/Rules/SizeTest.php +++ b/tests/feature/Rules/SizeTest.php @@ -61,12 +61,12 @@ fn() => v::size('KB', v::between(5, 7)->odd())->assert($this->file2Kb->url()), 'The size in kilobytes of "vfs://root/2kb.txt" must be between 5 and 7', <<<'FULL_MESSAGE' - - All the required rules must pass for "vfs://root/2kb.txt" + - "vfs://root/2kb.txt" must pass all the rules - The size in kilobytes of "vfs://root/2kb.txt" must be between 5 and 7 - The size in kilobytes of "vfs://root/2kb.txt" must be an odd number FULL_MESSAGE, [ - '__root__' => 'All the required rules must pass for "vfs://root/2kb.txt"', + '__root__' => '"vfs://root/2kb.txt" must pass all the rules', 'sizeBetween' => 'The size in kilobytes of "vfs://root/2kb.txt" must be between 5 and 7', 'sizeOdd' => 'The size in kilobytes of "vfs://root/2kb.txt" must be an odd number', ], diff --git a/tests/feature/Rules/UndefOrTest.php b/tests/feature/Rules/UndefOrTest.php index fd4753b64..dd6627942 100644 --- a/tests/feature/Rules/UndefOrTest.php +++ b/tests/feature/Rules/UndefOrTest.php @@ -81,12 +81,12 @@ fn() => v::undefOr(v::alpha()->stringType())->assert(1234), '1234 must contain only letters (a-z) or must be undefined', <<<'FULL_MESSAGE' - - All the required rules must pass for 1234 + - 1234 must pass all the rules - 1234 must contain only letters (a-z) or must be undefined - 1234 must be a string or must be undefined FULL_MESSAGE, [ - '__root__' => 'All the required rules must pass for 1234', + '__root__' => '1234 must pass all the rules', 'undefOrAlpha' => '1234 must contain only letters (a-z) or must be undefined', 'undefOrStringType' => '1234 must be a string or must be undefined', ], @@ -99,12 +99,12 @@ ]), 'Should be nul or alpha', <<<'FULL_MESSAGE' - - All the required rules must pass for 1234 + - 1234 must pass all the rules - Should be nul or alpha - Should be nul or string type FULL_MESSAGE, [ - '__root__' => 'All the required rules must pass for 1234', + '__root__' => '1234 must pass all the rules', 'undefOrAlpha' => 'Should be nul or alpha', 'undefOrStringType' => 'Should be nul or string type', ], diff --git a/tests/feature/TranslatorTest.php b/tests/feature/TranslatorTest.php index c0a4f550c..3ceae6f4b 100644 --- a/tests/feature/TranslatorTest.php +++ b/tests/feature/TranslatorTest.php @@ -14,7 +14,7 @@ test('Various translations', expectFullMessage( function (): void { ValidatorDefaults::setTranslator(new ArrayTranslator([ - 'All the required rules must pass for {{name}}' => 'Todas as regras requeridas devem passar para {{name}}', + '{{name}} must pass all the rules' => 'Todas as regras requeridas devem passar para {{name}}', 'The length of' => 'O comprimento de', '{{name}} must be a string' => '{{name}} deve ser uma string', '{{name}} must be between {{minValue}} and {{maxValue}}' => '{{name}} deve possuir de {{minValue}} a {{maxValue}} caracteres',