Passed
Pull Request — master (#415)
by
unknown
29:22 queued 26:39
created

CallbackTest.php$0 ➔ validateName()   A

Complexity

Conditions 2

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
dl 0
loc 10
rs 9.9332
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Validator\Tests\Rule;
6
7
use InvalidArgumentException;
8
use RuntimeException;
9
use stdClass;
10
use Yiisoft\Validator\DataSet\ObjectDataSet;
11
use Yiisoft\Validator\Exception\InvalidCallbackReturnTypeException;
12
use Yiisoft\Validator\Result;
13
use Yiisoft\Validator\Rule\Callback;
14
use Yiisoft\Validator\Rule\CallbackHandler;
15
use Yiisoft\Validator\RuleInterface;
16
use Yiisoft\Validator\Tests\Rule\Base\DifferentRuleInHandlerTestTrait;
17
use Yiisoft\Validator\Tests\Rule\Base\RuleTestCase;
18
use Yiisoft\Validator\Tests\Rule\Base\RuleWithOptionsTestTrait;
19
use Yiisoft\Validator\Tests\Rule\Base\SkipOnErrorTestTrait;
20
use Yiisoft\Validator\Tests\Rule\Base\WhenTestTrait;
21
use Yiisoft\Validator\Tests\Support\ValidatorFactory;
22
use Yiisoft\Validator\ValidationContext;
23
24
final class CallbackTest extends RuleTestCase
25
{
26
    use DifferentRuleInHandlerTestTrait;
27
    use RuleWithOptionsTestTrait;
28
    use SkipOnErrorTestTrait;
29
    use WhenTestTrait;
30
31
    public function testInitWithNoCallbackAndMethodException(): void
32
    {
33
        $this->expectException(InvalidArgumentException::class);
34
        $this->expectExceptionMessage('Either "$callback" or "$method" must be specified.');
35
        new Callback();
36
    }
37
38
    public function testInitWithBothCallbackAndMethodException(): void
39
    {
40
        $this->expectException(InvalidArgumentException::class);
41
        $this->expectExceptionMessage('"$callback" and "$method" are mutually exclusive.');
42
        new Callback(callback: static fn (): Result => new Result(), method: 'test');
43
    }
44
45
    public function testGetName(): void
46
    {
47
        $rule = new Callback(callback: static fn (): Result => new Result());
48
        $this->assertSame('callback', $rule->getName());
49
    }
50
51
    public function testGetMethod(): void
52
    {
53
        $rule = new Callback(method: 'test');
54
        $this->assertSame('test', $rule->getMethod());
55
    }
56
57
    public function testAfterInitAttributeWithNoMethod(): void
58
    {
59
        $rule = new Callback(callback: static fn (): Result => new Result());
60
        $callback = $rule->getCallback();
61
        $this->assertIsCallable($callback);
62
        $this->assertNull($rule->getMethod());
63
64
        $rule->afterInitAttribute(new ObjectDataSet(new stdClass()));
65
        $this->assertIsCallable($callback);
66
        $this->assertNull($rule->getMethod());
67
        $this->assertSame($callback, $rule->getCallback());
68
    }
69
70
    public function dataOptions(): array
71
    {
72
        return [
73
            [
74
                new Callback(
75
                    static fn (mixed $value, object $rule, ValidationContext $context): Result => new Result(),
0 ignored issues
show
Unused Code introduced by
The parameter $rule is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

75
                    static fn (mixed $value, /** @scrutinizer ignore-unused */ object $rule, ValidationContext $context): Result => new Result(),

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $context is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

75
                    static fn (mixed $value, object $rule, /** @scrutinizer ignore-unused */ ValidationContext $context): Result => new Result(),

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $value is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

75
                    static fn (/** @scrutinizer ignore-unused */ mixed $value, object $rule, ValidationContext $context): Result => new Result(),

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
76
                ),
77
                [
78
                    'method' => null,
79
                    'skipOnEmpty' => false,
80
                    'skipOnError' => false,
81
                ],
82
            ],
83
            [
84
                new Callback(
85
                    static fn (mixed $value, object $rule, ValidationContext $context): Result => new Result(),
0 ignored issues
show
Unused Code introduced by
The parameter $context is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

85
                    static fn (mixed $value, object $rule, /** @scrutinizer ignore-unused */ ValidationContext $context): Result => new Result(),

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $rule is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

85
                    static fn (mixed $value, /** @scrutinizer ignore-unused */ object $rule, ValidationContext $context): Result => new Result(),

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $value is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

85
                    static fn (/** @scrutinizer ignore-unused */ mixed $value, object $rule, ValidationContext $context): Result => new Result(),

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
86
                    skipOnEmpty: true,
87
                ),
88
                [
89
                    'method' => null,
90
                    'skipOnEmpty' => true,
91
                    'skipOnError' => false,
92
                ],
93
            ],
94
            [
95
                new Callback(method: 'test'),
96
                [
97
                    'method' => 'test',
98
                    'skipOnEmpty' => false,
99
                    'skipOnError' => false,
100
                ],
101
            ],
102
        ];
103
    }
104
105
    public function dataValidationPassed(): array
106
    {
107
        return [
108
            [
109
                42,
110
                [
111
                    new Callback(static function (mixed $value, object $rule, ValidationContext $context): Result {
0 ignored issues
show
Unused Code introduced by
The parameter $rule is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

111
                    new Callback(static function (mixed $value, /** @scrutinizer ignore-unused */ object $rule, ValidationContext $context): Result {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $context is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

111
                    new Callback(static function (mixed $value, object $rule, /** @scrutinizer ignore-unused */ ValidationContext $context): Result {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
112
                        $result = new Result();
113
                        if ($value !== 42) {
114
                            $result->addError('Value should be 42!');
115
                        }
116
117
                        return $result;
118
                    }),
119
                ],
120
            ],
121
        ];
122
    }
123
124
    public function dataValidationFailed(): array
125
    {
126
        return [
127
            [
128
                41,
129
                [
130
                    new Callback(static function (mixed $value, object $rule, ValidationContext $context): Result {
0 ignored issues
show
Unused Code introduced by
The parameter $context is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

130
                    new Callback(static function (mixed $value, object $rule, /** @scrutinizer ignore-unused */ ValidationContext $context): Result {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $rule is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

130
                    new Callback(static function (mixed $value, /** @scrutinizer ignore-unused */ object $rule, ValidationContext $context): Result {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
131
                        $result = new Result();
132
                        if ($value !== 42) {
133
                            $result->addError('Value should be 42!');
134
                        }
135
136
                        return $result;
137
                    }),
138
                ],
139
                ['' => ['Value should be 42!']],
140
            ],
141
            'custom error' => [
142
                41,
143
                [
144
                    new Callback(static function (mixed $value, object $rule, ValidationContext $context): Result {
0 ignored issues
show
Unused Code introduced by
The parameter $context is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

144
                    new Callback(static function (mixed $value, object $rule, /** @scrutinizer ignore-unused */ ValidationContext $context): Result {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $rule is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

144
                    new Callback(static function (mixed $value, /** @scrutinizer ignore-unused */ object $rule, ValidationContext $context): Result {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
145
                        $result = new Result();
146
                        if ($value !== 42) {
147
                            $result->addError('Custom error');
148
                        }
149
150
                        return $result;
151
                    }),
152
                ],
153
                ['' => ['Custom error']],
154
            ],
155
            'non-static callable' => [
156
                new class (1) {
157
                    public function __construct(
158
                        #[Callback(method: 'validateName')]
159
                        #[Callback(method: 'staticValidateName')]
160
                        private $age,
161
                    ) {
162
                    }
163
164
                    private function validateName(mixed $value, RuleInterface $rule, ValidationContext $context): Result
0 ignored issues
show
Unused Code introduced by
The parameter $rule is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

164
                    private function validateName(mixed $value, /** @scrutinizer ignore-unused */ RuleInterface $rule, ValidationContext $context): Result

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $context is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

164
                    private function validateName(mixed $value, RuleInterface $rule, /** @scrutinizer ignore-unused */ ValidationContext $context): Result

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The method validateName() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
165
                    {
166
                        if ($value !== $this->age) {
167
                            throw new RuntimeException('Method scope was not bound to the object.');
168
                        }
169
170
                        $result = new Result();
171
                        $result->addError('Hello from non-static method.');
172
173
                        return $result;
174
                    }
175
176
                    private static function staticValidateName(
0 ignored issues
show
Unused Code introduced by
The method staticValidateName() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
177
                        mixed $value,
178
                        RuleInterface $rule,
0 ignored issues
show
Unused Code introduced by
The parameter $rule is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

178
                        /** @scrutinizer ignore-unused */ RuleInterface $rule,

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
179
                        ValidationContext $context
180
                    ): Result {
181
                        if ($value !== $context->getDataSet()?->getAttributeValue('age')) {
182
                            throw new RuntimeException('Method scope was not bound to the object.');
183
                        }
184
185
                        $result = new Result();
186
                        $result->addError('Hello from static method.');
187
188
                        return $result;
189
                    }
190
                },
191
                null,
192
                ['age' => ['Hello from non-static method.', 'Hello from static method.']],
193
            ],
194
        ];
195
    }
196
197
    public function testThrowExceptionWithInvalidReturn(): void
198
    {
199
        $callback = static fn (mixed $value, object $rule, ValidationContext $context): string => 'invalid return';
0 ignored issues
show
Unused Code introduced by
The parameter $value is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

199
        $callback = static fn (/** @scrutinizer ignore-unused */ mixed $value, object $rule, ValidationContext $context): string => 'invalid return';

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $rule is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

199
        $callback = static fn (mixed $value, /** @scrutinizer ignore-unused */ object $rule, ValidationContext $context): string => 'invalid return';

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Unused Code introduced by
The parameter $context is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

199
        $callback = static fn (mixed $value, object $rule, /** @scrutinizer ignore-unused */ ValidationContext $context): string => 'invalid return';

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
200
        $rule = new Callback($callback);
201
        $validator = ValidatorFactory::make();
202
203
        $this->expectException(InvalidCallbackReturnTypeException::class);
204
        $message = 'Return value of callback must be an instance of Yiisoft\Validator\Result, string returned.';
205
        $this->expectExceptionMessage($message);
206
        $validator->validate(null, [$rule]);
207
    }
208
209
    public function testValidateUsingMethodOutsideAttributeScope(): void
210
    {
211
        $rule = new Callback(method: 'validateName');
212
        $validator = ValidatorFactory::make();
213
214
        $this->expectException(InvalidArgumentException::class);
215
        $this->expectExceptionMessage('Using method outside of attribute scope is prohibited.');
216
        $validator->validate(null, [$rule]);
217
    }
218
219
    public function testSkipOnError(): void
220
    {
221
        $this->testSkipOnErrorInternal(
222
            new Callback(callback: static fn (): Result => new Result()),
223
            new Callback(callback: static fn (): Result => new Result(), skipOnError: true),
224
        );
225
    }
226
227
    public function testWhen(): void
228
    {
229
        $when = static fn (mixed $value): bool => $value !== null;
230
        $this->testWhenInternal(
231
            new Callback(callback: static fn (): Result => new Result()),
232
            new Callback(callback: static fn (): Result => new Result(), when: $when),
233
        );
234
    }
235
236
    protected function getDifferentRuleInHandlerItems(): array
237
    {
238
        return [Callback::class, CallbackHandler::class];
239
    }
240
}
241