Issues (138)

RulesProvider/AttributesRulesProviderTest.php (3 issues)

Severity
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
The private property $viewsCount is not used, and could be removed.
Loading history...
52
53
                    private bool $active = true;
0 ignored issues
show
The private property $active is not used, and could be removed.
Loading history...
54
55
                    #[Length(max: 255)]
56
                    private string $title = 'Test title';
0 ignored issues
show
The private property $title is not used, and could be removed.
Loading history...
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