Passed
Push — master ( e18482...3e6ebb )
by Alexander
11:33
created

testGetRulesExpectingAttributeInheritance()

Size

Total Lines 14
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 8
nc 1
nop 0
dl 0
loc 14
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Validator\Tests\Helper;
6
7
use Error;
8
use InvalidArgumentException;
9
use PHPUnit\Framework\TestCase;
10
use ReflectionObject;
11
use Yiisoft\Validator\Helper\ObjectParser;
12
use Yiisoft\Validator\Rule\Number;
13
use Yiisoft\Validator\Rule\Required;
14
use Yiisoft\Validator\Tests\Support\Data\ObjectForTestingCache1;
15
use Yiisoft\Validator\Tests\Support\Data\ObjectForTestingCache2;
16
use Yiisoft\Validator\Tests\Support\Data\ObjectForTestingDisabledCache;
17
use Yiisoft\Validator\Tests\Support\Data\SimpleDto;
18
use Yiisoft\Validator\Tests\Support\Rule\CustomUrlRuleSet;
19
20
final class ObjectParserTest extends TestCase
21
{
22
    public function testInvalidSource(): void
23
    {
24
        $this->expectException(InvalidArgumentException::class);
25
        $this->expectExceptionMessage('Class "non-exist-class" not found.');
26
        new ObjectParser('non-exist-class');
27
    }
28
29
    public function dataSkipStaticProperties(): array
30
    {
31
        return [
32
            [
33
                ['a' => 4, 'b' => 2],
34
                new class () {
35
                    public int $a = 4;
36
                    public static int $b = 2;
37
                },
38
                false,
39
            ],
40
            [
41
                ['a' => 4, 'c' => 'hello'],
42
                new class () {
43
                    public int $a = 4;
44
                    public static int $b = 2;
45
                    public string $c = 'hello';
46
                },
47
                true,
48
            ],
49
        ];
50
    }
51
52
    /**
53
     * @dataProvider dataSkipStaticProperties
54
     */
55
    public function testSkipStaticProperties(array $expectedData, object $object, bool $skipStaticProperties): void
56
    {
57
        $parser = new ObjectParser($object, skipStaticProperties: $skipStaticProperties);
58
59
        $this->assertSame($expectedData, $parser->getData());
60
    }
61
62
    public function testSkipStaticPropertiesDefault(): void
63
    {
64
        $object = new class () {
65
            public int $a = 4;
66
            public static int $b = 2;
67
        };
68
69
        $parser = new ObjectParser($object);
70
71
        $this->assertSame(['a' => 4, 'b' => 2], $parser->getData());
72
    }
73
74
    public function testDataWithClassString(): void
75
    {
76
        $parser = new ObjectParser(SimpleDto::class);
77
78
        $this->assertSame([], $parser->getData());
79
        $this->assertNull($parser->getAttributeValue('a'));
80
        $this->assertNull($parser->getAttributeValue('x'));
81
        $this->assertFalse($parser->hasAttribute('a'));
82
        $this->assertFalse($parser->hasAttribute('x'));
83
    }
84
85
    public function testGetRulesExpectingAttributeInheritance(): void
86
    {
87
        $object = new class () {
88
            #[CustomUrlRuleSet]
89
            public string $url;
90
        };
91
        $parser = new ObjectParser($object);
92
93
        $this->expectException(Error::class);
94
95
        $className = CustomUrlRuleSet::class;
96
        $this->expectExceptionMessage("Attempting to use non-attribute class \"$className\" as attribute");
97
98
        $parser->getRules();
99
    }
100
101
    public function testCache(): void
102
    {
103
        $parser1 = new ObjectParser(new ObjectForTestingCache1());
104
        $reflectionParser = new ReflectionObject($parser1);
105
106
        $cacheProperty = $reflectionParser->getProperty('cache');
107
        if (PHP_VERSION_ID < 80100) {
108
            $cacheProperty->setAccessible(true);
109
        }
110
111
        $cacheKey1 = 'Yiisoft\Validator\Tests\Support\Data\ObjectForTestingCache1_7_0';
112
        $this->assertArrayNotHasKey($cacheKey1, $cacheProperty->getValue());
113
114
        $expectedRules1 = [
115
            'a' => [new Required()],
116
            'b' => [new Number(min: 1)],
117
            'c' => [new Number(max: 2)],
118
        ];
119
        $expectedLabels1 = ['c' => 'd'];
120
        $rules1 = $parser1->getRules();
121
        $labels1 = $parser1->getLabels();
122
        $this->assertEquals($expectedRules1, $rules1);
123
        $cache = $cacheProperty->getValue();
124
        $this->assertArrayHasKey($cacheKey1, $cache);
125
        $this->assertArrayHasKey('rules', $cache[$cacheKey1]);
126
        $this->assertArrayHasKey('reflectionProperties', $cache[$cacheKey1]);
127
        $this->assertArrayHasKey('reflectionSource', $cache[$cacheKey1]);
128
        $this->assertArrayHasKey('labels', $cache[$cacheKey1]);
129
        $this->assertSame($rules1, $parser1->getRules());
130
        $this->assertSame($labels1,  $expectedLabels1);
0 ignored issues
show
Coding Style introduced by
Expected 1 space after comma in argument list; 2 found
Loading history...
131
132
        $parser2 = new ObjectParser(new ObjectForTestingCache2());
133
        $cacheKey2 = 'Yiisoft\Validator\Tests\Support\Data\ObjectForTestingCache2_7_0';
134
        $cache = $cacheProperty->getValue();
135
        $this->assertArrayHasKey($cacheKey1, $cache);
136
        $this->assertArrayNotHasKey($cacheKey2, $cache);
137
138
        $reflectionProperties2 = $parser2->getReflectionProperties();
139
        $cache = $cacheProperty->getValue();
140
        $this->assertArrayHasKey($cacheKey1, $cache);
141
        $this->assertArrayHasKey($cacheKey2, $cache);
142
        $this->assertArrayNotHasKey('rules', $cache[$cacheKey2]);
143
        $this->assertArrayHasKey('reflectionProperties', $cache[$cacheKey2]);
144
        $this->assertArrayHasKey('reflectionSource', $cache[$cacheKey2]);
145
        $this->assertSame($reflectionProperties2, $parser2->getReflectionProperties());
146
147
        $expectedRules2 = [
148
            'd' => [new Required()],
149
            'e' => [new Number(min: 5)],
150
            'f' => [new Number(max: 6)],
151
        ];
152
        $rules2 = $parser2->getRules();
153
        $this->assertEquals($expectedRules2, $parser2->getRules());
154
        $this->assertArrayHasKey('rules', $cacheProperty->getValue()[$cacheKey2]);
155
        $this->assertSame($rules2, $parser2->getRules());
156
        $this->assertSame($rules1, $parser1->getRules());
157
    }
158
159
    public function testDisabledCache(): void
160
    {
161
        $parser = new ObjectParser(new ObjectForTestingDisabledCache(), useCache: false);
162
        $reflectionParser = new ReflectionObject($parser);
163
164
        $cacheProperty = $reflectionParser->getProperty('cache');
165
        if (PHP_VERSION_ID < 80100) {
166
            $cacheProperty->setAccessible(true);
167
        }
168
169
        $cacheKey = 'Yiisoft\Validator\Tests\Support\Data\ObjectForTestingDisabledCache_7_0';
170
        $this->assertArrayNotHasKey($cacheKey, $cacheProperty->getValue());
171
172
        $expectedRules = [
173
            'a' => [new Required()],
174
            'b' => [new Number(min: 1)],
175
            'c' => [new Number(max: 2)],
176
        ];
177
        $expectedLabels = ['c' => 'label'];
178
        $rules = $parser->getRules();
179
        $labels = $parser->getLabels();
180
        $this->assertEquals($expectedRules, $rules);
181
        $this->assertSame($expectedLabels, $labels);
182
        $this->assertArrayNotHasKey($cacheKey, $cacheProperty->getValue());
183
        $this->assertEquals($expectedRules, $parser->getRules());
184
        $this->assertSame($expectedLabels, $parser->getLabels());
185
        $this->assertNotSame($rules, $parser->getRules());
186
        $this->assertArrayNotHasKey($cacheKey, $cacheProperty->getValue());
187
    }
188
}
189