yiisoft /
validator
| 1 | <?php |
||
| 2 | |||
| 3 | declare(strict_types=1); |
||
| 4 | |||
| 5 | namespace Yiisoft\Validator\Tests\RulesProvider; |
||
| 6 | |||
| 7 | use JetBrains\PhpStorm\Deprecated; |
||
| 8 | use PHPUnit\Framework\TestCase; |
||
| 9 | use ReflectionProperty; |
||
| 10 | use Traversable; |
||
| 11 | use Yiisoft\Validator\Rule\Length; |
||
| 12 | use Yiisoft\Validator\Rule\TrueValue; |
||
| 13 | use Yiisoft\Validator\Rule\Number; |
||
| 14 | use Yiisoft\Validator\Rule\Required; |
||
| 15 | use Yiisoft\Validator\RuleInterface; |
||
| 16 | use Yiisoft\Validator\RulesProvider\AttributesRulesProvider; |
||
| 17 | use Yiisoft\Validator\Tests\Support\Data\ObjectWithDifferentPropertyVisibility; |
||
| 18 | |||
| 19 | final class AttributesRulesProviderTest extends TestCase |
||
| 20 | { |
||
| 21 | public function dataBase(): array |
||
| 22 | { |
||
| 23 | return [ |
||
| 24 | 'class-name' => [ |
||
| 25 | [ |
||
| 26 | 'name' => [Required::class], |
||
| 27 | 'age' => [Number::class], |
||
| 28 | 'number' => [Number::class], |
||
| 29 | ], |
||
| 30 | ObjectWithDifferentPropertyVisibility::class, |
||
| 31 | ], |
||
| 32 | 'object' => [ |
||
| 33 | [ |
||
| 34 | 'name' => [Required::class], |
||
| 35 | 'age' => [Number::class], |
||
| 36 | 'number' => [Number::class], |
||
| 37 | ], |
||
| 38 | new ObjectWithDifferentPropertyVisibility(), |
||
| 39 | ], |
||
| 40 | 'object with no properties' => [ |
||
| 41 | [], |
||
| 42 | new class () { |
||
| 43 | }, |
||
| 44 | ], |
||
| 45 | 'object with properties without rule attributes' => [ |
||
| 46 | [ |
||
| 47 | 'title' => [Length::class], |
||
| 48 | ], |
||
| 49 | new class () { |
||
| 50 | #[Deprecated(reason: 'test reason', replacement: 'test replacement')] |
||
| 51 | private int $viewsCount = 1; |
||
|
0 ignored issues
–
show
introduced
by
Loading history...
|
|||
| 52 | |||
| 53 | private bool $active = true; |
||
|
0 ignored issues
–
show
|
|||
| 54 | |||
| 55 | #[Length(max: 255)] |
||
| 56 | private string $title = 'Test title'; |
||
|
0 ignored issues
–
show
|
|||
| 57 | }, |
||
| 58 | ], |
||
| 59 | ]; |
||
| 60 | } |
||
| 61 | |||
| 62 | /** |
||
| 63 | * @dataProvider dataBase |
||
| 64 | */ |
||
| 65 | public function testBase(array $expectedRuleClassNames, string|object $source): void |
||
| 66 | { |
||
| 67 | $rulesProvider = new AttributesRulesProvider($source); |
||
| 68 | $ruleClassNames = $this->convertRulesToClassNames($rulesProvider->getRules()); |
||
| 69 | |||
| 70 | $this->assertSame($expectedRuleClassNames, $ruleClassNames); |
||
| 71 | } |
||
| 72 | |||
| 73 | public function dataPropertyVisibility(): array |
||
| 74 | { |
||
| 75 | return [ |
||
| 76 | 'class-name-and-private-protected-public' => [ |
||
| 77 | [ |
||
| 78 | 'name' => [Required::class], |
||
| 79 | 'age' => [Number::class], |
||
| 80 | 'number' => [Number::class], |
||
| 81 | ], |
||
| 82 | ObjectWithDifferentPropertyVisibility::class, |
||
| 83 | ReflectionProperty::IS_PRIVATE | ReflectionProperty::IS_PROTECTED | ReflectionProperty::IS_PUBLIC, |
||
| 84 | ], |
||
| 85 | 'class-name-and-private' => [ |
||
| 86 | [ |
||
| 87 | 'number' => [Number::class], |
||
| 88 | ], |
||
| 89 | ObjectWithDifferentPropertyVisibility::class, |
||
| 90 | ReflectionProperty::IS_PRIVATE, |
||
| 91 | ], |
||
| 92 | 'class-name-and-protected' => [ |
||
| 93 | [ |
||
| 94 | 'age' => [Number::class], |
||
| 95 | ], |
||
| 96 | ObjectWithDifferentPropertyVisibility::class, |
||
| 97 | ReflectionProperty::IS_PROTECTED, |
||
| 98 | ], |
||
| 99 | 'class-name-and-public' => [ |
||
| 100 | [ |
||
| 101 | 'name' => [Required::class], |
||
| 102 | ], |
||
| 103 | ObjectWithDifferentPropertyVisibility::class, |
||
| 104 | ReflectionProperty::IS_PUBLIC, |
||
| 105 | ], |
||
| 106 | 'object-and-private-protected-public' => [ |
||
| 107 | [ |
||
| 108 | 'name' => [Required::class], |
||
| 109 | 'age' => [Number::class], |
||
| 110 | 'number' => [Number::class], |
||
| 111 | ], |
||
| 112 | new ObjectWithDifferentPropertyVisibility(), |
||
| 113 | ReflectionProperty::IS_PRIVATE | ReflectionProperty::IS_PROTECTED | ReflectionProperty::IS_PUBLIC, |
||
| 114 | ], |
||
| 115 | 'object-and-private' => [ |
||
| 116 | [ |
||
| 117 | 'number' => [Number::class], |
||
| 118 | ], |
||
| 119 | new ObjectWithDifferentPropertyVisibility(), |
||
| 120 | ReflectionProperty::IS_PRIVATE, |
||
| 121 | ], |
||
| 122 | 'object-and-protected' => [ |
||
| 123 | [ |
||
| 124 | 'age' => [Number::class], |
||
| 125 | ], |
||
| 126 | new ObjectWithDifferentPropertyVisibility(), |
||
| 127 | ReflectionProperty::IS_PROTECTED, |
||
| 128 | ], |
||
| 129 | 'object-and-public' => [ |
||
| 130 | [ |
||
| 131 | 'name' => [Required::class], |
||
| 132 | ], |
||
| 133 | new ObjectWithDifferentPropertyVisibility(), |
||
| 134 | ReflectionProperty::IS_PUBLIC, |
||
| 135 | ], |
||
| 136 | ]; |
||
| 137 | } |
||
| 138 | |||
| 139 | /** |
||
| 140 | * @dataProvider dataPropertyVisibility |
||
| 141 | */ |
||
| 142 | public function testPropertyVisibility( |
||
| 143 | array $expectedRuleClassNames, |
||
| 144 | string|object $source, |
||
| 145 | int $propertyVisibility, |
||
| 146 | ): void { |
||
| 147 | $rulesProvider = new AttributesRulesProvider($source, $propertyVisibility); |
||
| 148 | |||
| 149 | $ruleClassNames = $this->convertRulesToClassNames($rulesProvider->getRules()); |
||
| 150 | |||
| 151 | $this->assertSame($expectedRuleClassNames, $ruleClassNames); |
||
| 152 | } |
||
| 153 | |||
| 154 | public function dataStaticProperties(): array |
||
| 155 | { |
||
| 156 | return [ |
||
| 157 | [ |
||
| 158 | ['a' => [Required::class], 'b' => [TrueValue::class]], |
||
| 159 | new class () { |
||
| 160 | #[Required] |
||
| 161 | public int $a = 1; |
||
| 162 | #[TrueValue] |
||
| 163 | public static bool $b = false; |
||
| 164 | }, |
||
| 165 | null, |
||
| 166 | ], |
||
| 167 | [ |
||
| 168 | ['a' => [Required::class]], |
||
| 169 | new class () { |
||
| 170 | #[Required] |
||
| 171 | public int $a = 1; |
||
| 172 | #[TrueValue] |
||
| 173 | public static bool $b = false; |
||
| 174 | }, |
||
| 175 | true, |
||
| 176 | ], |
||
| 177 | [ |
||
| 178 | ['a' => [Required::class], 'b' => [TrueValue::class]], |
||
| 179 | new class () { |
||
| 180 | #[Required] |
||
| 181 | public int $a = 1; |
||
| 182 | #[TrueValue] |
||
| 183 | public static bool $b = false; |
||
| 184 | }, |
||
| 185 | false, |
||
| 186 | ], |
||
| 187 | ]; |
||
| 188 | } |
||
| 189 | |||
| 190 | /** |
||
| 191 | * @dataProvider dataStaticProperties |
||
| 192 | */ |
||
| 193 | public function testStaticProperties( |
||
| 194 | array $expectedRuleClassNames, |
||
| 195 | object $source, |
||
| 196 | ?bool $skipStaticProperties, |
||
| 197 | ): void { |
||
| 198 | $rulesProvider = $skipStaticProperties === null |
||
| 199 | ? new AttributesRulesProvider($source) |
||
| 200 | : new AttributesRulesProvider($source, skipStaticProperties: $skipStaticProperties); |
||
| 201 | |||
| 202 | $ruleClassNames = $this->convertRulesToClassNames($rulesProvider->getRules()); |
||
| 203 | |||
| 204 | $this->assertSame($expectedRuleClassNames, $ruleClassNames); |
||
| 205 | } |
||
| 206 | |||
| 207 | private function convertRulesToClassNames(iterable $rules): array |
||
| 208 | { |
||
| 209 | $classNames = []; |
||
| 210 | foreach ($rules as $attribute => $attributeRules) { |
||
| 211 | $classNames[$attribute] = array_map( |
||
| 212 | static fn (RuleInterface $rule): string => $rule::class, |
||
| 213 | $attributeRules instanceof Traversable ? iterator_to_array($attributeRules) : $attributeRules |
||
| 214 | ); |
||
| 215 | } |
||
| 216 | |||
| 217 | return $classNames; |
||
| 218 | } |
||
| 219 | } |
||
| 220 |