Browse Source

Add mote tests for validation rules

shalvah 3 years ago
parent
commit
e822b4ca20

+ 1 - 1
src/Extracting/ParamHelpers.php

@@ -54,7 +54,7 @@ trait ParamHelpers
         return $fakeFactories[$baseType] ?? $fakeFactories['string'];
     }
 
-    private function getDummyDataGeneratorBetween(string $type, $min, $max = null): \Closure
+    private function getDummyDataGeneratorBetween(string $type, $min, $max = 9000): \Closure
     {
         $baseType = $type;
         $isListType = false;

+ 9 - 4
src/Extracting/ParsesValidationRules.php

@@ -370,19 +370,20 @@ trait ParsesValidationRules
                     $parameterData['description'] .= ' ' . $this->getDescription(
                             $rule, [':min' => $arguments[0]], $this->getLaravelValidationBaseTypeMapping($parameterData['type'])
                         );
-                    $parameterData['setter'] = $this->getDummyDataGeneratorBetween($parameterData['type'], $arguments[0]);
+                    $parameterData['setter'] = $this->getDummyDataGeneratorBetween($parameterData['type'], floatval($arguments[0]));
                     break;
                 case 'max':
                     $parameterData['description'] .= ' ' . $this->getDescription(
                             $rule, [':max' => $arguments[0]], $this->getLaravelValidationBaseTypeMapping($parameterData['type'])
                         );
-                    $parameterData['setter'] = $this->getDummyDataGeneratorBetween($parameterData['type'], 0, $arguments[0]);
+                    $parameterData['setter'] = $this->getDummyDataGeneratorBetween($parameterData['type'], 0, floatval($arguments[0]));
                     break;
                 case 'between':
                     $parameterData['description'] .= ' ' . $this->getDescription(
                             $rule, [':min' => $arguments[0], ':max' => $arguments[1]], $this->getLaravelValidationBaseTypeMapping($parameterData['type'])
                         );
-                    $parameterData['setter'] = $this->getDummyDataGeneratorBetween($parameterData['type'], $arguments[0], $arguments[1]);
+                    // Avoid exponentially complex operations by using the minimum length
+                    $parameterData['setter'] = $this->getDummyDataGeneratorBetween($parameterData['type'], floatval($arguments[0]), floatval($arguments[0]) + 1);
                     break;
 
                 /**
@@ -478,7 +479,7 @@ trait ParsesValidationRules
     {
         $ruleArguments = [];
 
-        // Convert any Rule objects to strings
+        // Convert any custom Rule objects to strings
         if ($rule instanceof Rule) {
             $className = substr(strrchr(get_class($rule), "\\"), 1);
             return [$className, []];
@@ -650,6 +651,10 @@ trait ParsesValidationRules
 
     protected function getDescription(string $rule, array $arguments = [], $baseType = 'string'): string
     {
+        if ($rule == 'regex') {
+            return "Must match the regex {$arguments[':regex']}.";
+        }
+
         $description = trans("validation.{$rule}");
         // For rules that can apply to multiple types (eg 'max' rule), Laravel returns an array of possible messages
         // 'numeric' => 'The :attribute must not be greater than :max'

+ 3 - 1
tests/TestHelpers.php

@@ -23,6 +23,8 @@ trait TestHelpers
 
     protected function generate(array $flags = []): mixed
     {
-        return $this->artisan('scribe:generate', array_merge(['--no-upgrade-check' => true], $flags));
+        return $this->artisan(
+            'scribe:generate', array_merge(['--no-upgrade-check' => true], $flags)
+        );
     }
 }

+ 74 - 0
tests/Unit/ValidationRuleParsingTest.php

@@ -4,6 +4,7 @@ namespace Knuckles\Scribe\Tests\Unit;
 
 use Illuminate\Foundation\Application;
 use Illuminate\Support\Facades\Validator;
+use Illuminate\Validation\Rule;
 use Illuminate\Validation\ValidationException;
 use Knuckles\Scribe\Extracting\ParsesValidationRules;
 use Knuckles\Scribe\Tests\BaseLaravelTest;
@@ -55,6 +56,18 @@ class ValidationRuleParsingTest extends BaseLaravelTest
         }
     }
 
+    /** @test */
+    public function can_parse_rule_objects()
+    {
+        $results = $this->strategy->parse([
+            'in_param' => ['numeric', Rule::in([3,5,6])]
+        ]);
+        $this->assertEquals(
+            'Must be one of <code>3</code>, <code>5</code>, or <code>6</code>.',
+            $results['in_param']['description']
+        );
+    }
+
 
     /** @test */
     public function can_transform_arrays_and_objects()
@@ -150,6 +163,14 @@ class ValidationRuleParsingTest extends BaseLaravelTest
                 'type' => 'file',
             ],
         ];
+        yield 'image' => [
+            ['image_param' => 'image|required'],
+            [],
+            [
+                'description' => "Must be an image.",
+                'type' => 'file',
+            ],
+        ];
         yield 'timezone' => [
             ['timezone_param' => 'timezone|required'],
             [],
@@ -365,6 +386,41 @@ class ValidationRuleParsingTest extends BaseLaravelTest
             [],
             ['description' => "Must be a file. Must not be greater than 6 kilobytes."],
         ];
+        yield 'min (number)' => [
+            ['min_param' => 'numeric|min:6'],
+            [],
+            ['description' => "Must be at least 6."],
+        ];
+        yield 'min (string)' => [
+            ['min_param' => 'string|min:6'],
+            [],
+            ['description' => "Must be at least 6 characters."],
+        ];
+        yield 'min (file)' => [
+            ['min_param' => 'file|min:6'],
+            [],
+            ['description' => "Must be a file. Must be at least 6 kilobytes."],
+        ];
+        yield 'between (number)' => [
+            ['between_param' => 'numeric|between:1,2'],
+            [],
+            ['description' => "Must be between 1 and 2."],
+        ];
+        yield 'between (string)' => [
+            ['between_param' => 'string|between:1,2'],
+            [],
+            ['description' => "Must be between 1 and 2 characters."],
+        ];
+        yield 'between (file)' => [
+            ['between_param' => 'file|between:1,2'],
+            [],
+            ['description' => "Must be a file. Must be between 1 and 2 kilobytes."],
+        ];
+        yield 'regex' => [
+            ['regex_param' => 'regex:/\d/'],
+            [],
+            ['description' => 'Must match the regex /\d/.'],
+        ];
         yield 'accepted' => [
             ['accepted_param' => 'accepted'],
             [],
@@ -373,6 +429,11 @@ class ValidationRuleParsingTest extends BaseLaravelTest
                 'description' => 'Must be accepted.',
             ],
         ];
+        yield 'unsupported' => [
+            ['unsupported_param' => [new DummyValidationRule, 'bail']],
+            ['unsupported_param' => ['description' => $description]],
+            ['description' => "$description."],
+        ];
         if (version_compare(Application::VERSION, '8.53', '>=')) {
             yield 'accepted_if' => [
                 ['accepted_if_param' => 'accepted_if:another_field,a_value'],
@@ -385,3 +446,16 @@ class ValidationRuleParsingTest extends BaseLaravelTest
         }
     }
 }
+
+class DummyValidationRule implements \Illuminate\Contracts\Validation\Rule
+{
+    public function passes($attribute, $value)
+    {
+        return true;
+    }
+
+    public function message()
+    {
+        return '.';
+    }
+}