Passed
Pull Request — master (#441)
by Sergei
02:24
created

CompositeTest.php$1 ➔ testOptionsWithNotRule()   A

Complexity

Conditions 1

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
c 0
b 0
f 0
dl 0
loc 12
rs 9.8666
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Validator\Tests\Rule;
6
7
use InvalidArgumentException;
8
use Yiisoft\Validator\Result;
9
use Yiisoft\Validator\Rule\Composite;
10
use Yiisoft\Validator\Rule\CompositeHandler;
11
use Yiisoft\Validator\Rule\Equal;
12
use Yiisoft\Validator\Rule\Number;
13
use Yiisoft\Validator\Rule\Required;
14
use Yiisoft\Validator\Tests\Rule\Base\DifferentRuleInHandlerTestTrait;
15
use Yiisoft\Validator\Tests\Rule\Base\RuleTestCase;
16
use Yiisoft\Validator\Tests\Rule\Base\RuleWithOptionsTestTrait;
17
use Yiisoft\Validator\Tests\Rule\Base\SkipOnErrorTestTrait;
18
use Yiisoft\Validator\Tests\Rule\Base\WhenTestTrait;
19
use Yiisoft\Validator\Tests\Support\Rule\RuleWithoutOptions;
20
21
final class CompositeTest extends RuleTestCase
22
{
23
    use DifferentRuleInHandlerTestTrait;
24
    use RuleWithOptionsTestTrait;
25
    use SkipOnErrorTestTrait;
26
    use WhenTestTrait;
27
28
    public function testGetName(): void
29
    {
30
        $rule = new Composite([]);
31
        $this->assertSame('composite', $rule->getName());
32
    }
33
34
    public function dataOptions(): array
35
    {
36
        return [
37
            [
38
                new Composite([
39
                    new Number(max: 13, integerPattern: '/1/', numberPattern: '/1/'),
40
                    new Number(max: 14, integerPattern: '/2/', numberPattern: '/2/'),
41
                ]),
42
                [
43
                    'skipOnEmpty' => false,
44
                    'skipOnError' => false,
45
                    'rules' => [
46
                        [
47
                            'number',
48
                            'asInteger' => false,
49
                            'min' => null,
50
                            'max' => 13,
51
                            'incorrectInputMessage' => [
52
                                'template' => 'The allowed types are integer, float and string.',
53
                                'parameters' => [],
54
                            ],
55
                            'notNumberMessage' => [
56
                                'template' => 'Value must be a number.',
57
                                'parameters' => [],
58
                            ],
59
                            'tooSmallMessage' => [
60
                                'template' => 'Value must be no less than {min}.',
61
                                'parameters' => ['min' => null],
62
                            ],
63
                            'tooBigMessage' => [
64
                                'template' => 'Value must be no greater than {max}.',
65
                                'parameters' => ['max' => 13],
66
                            ],
67
                            'skipOnEmpty' => false,
68
                            'skipOnError' => false,
69
                            'integerPattern' => '/1/',
70
                            'numberPattern' => '/1/',
71
                        ],
72
                        [
73
                            'number',
74
                            'asInteger' => false,
75
                            'min' => null,
76
                            'max' => 14,
77
                            'incorrectInputMessage' => [
78
                                'template' => 'The allowed types are integer, float and string.',
79
                                'parameters' => [],
80
                            ],
81
                            'notNumberMessage' => [
82
                                'template' => 'Value must be a number.',
83
                                'parameters' => [],
84
                            ],
85
                            'tooSmallMessage' => [
86
                                'template' => 'Value must be no less than {min}.',
87
                                'parameters' => ['min' => null],
88
                            ],
89
                            'tooBigMessage' => [
90
                                'template' => 'Value must be no greater than {max}.',
91
                                'parameters' => ['max' => 14],
92
                            ],
93
                            'skipOnEmpty' => false,
94
                            'skipOnError' => false,
95
                            'integerPattern' => '/2/',
96
                            'numberPattern' => '/2/',
97
                        ],
98
                    ],
99
                ],
100
            ],
101
            'rule without options' => [
102
                new Composite([
103
                    new Number(max: 13, integerPattern: '/1/', numberPattern: '/1/'),
104
                    new RuleWithoutOptions(),
105
                ]),
106
                [
107
                    'skipOnEmpty' => false,
108
                    'skipOnError' => false,
109
                    'rules' => [
110
                        [
111
                            'number',
112
                            'asInteger' => false,
113
                            'min' => null,
114
                            'max' => 13,
115
                            'incorrectInputMessage' => [
116
                                'template' => 'The allowed types are integer, float and string.',
117
                                'parameters' => [],
118
                            ],
119
                            'notNumberMessage' => [
120
                                'template' => 'Value must be a number.',
121
                                'parameters' => [],
122
                            ],
123
                            'tooSmallMessage' => [
124
                                'template' => 'Value must be no less than {min}.',
125
                                'parameters' => [
126
                                    'min' => null,
127
                                ],
128
                            ],
129
                            'tooBigMessage' => [
130
                                'template' => 'Value must be no greater than {max}.',
131
                                'parameters' => [
132
                                    'max' => 13,
133
                                ],
134
                            ],
135
                            'skipOnEmpty' => false,
136
                            'skipOnError' => false,
137
                            'integerPattern' => '/1/',
138
                            'numberPattern' => '/1/',
139
                        ],
140
                        [
141
                            'test',
142
                        ],
143
                    ],
144
                ],
145
            ],
146
            'callable' => [
147
                new Composite([
148
                    static fn () => (new Result())->addError('Bad value.'),
149
                ]),
150
                [
151
                    'skipOnEmpty' => false,
152
                    'skipOnError' => false,
153
                    'rules' => [
154
                        [
155
                            'callback',
156
                            'method' => null,
157
                            'skipOnEmpty' => false,
158
                            'skipOnError' => false,
159
                        ],
160
                    ],
161
                ],
162
            ],
163
            'inheritance' => [
164
                new class extends Composite {
165
                    public function getRules(): iterable
166
                    {
167
                        return [
168
                            new Required(),
169
                        ];
170
                    }
171
                },
172
                [
173
                    'skipOnEmpty' => false,
174
                    'skipOnError' => false,
175
                    'rules' => [
176
                        [
177
                            'required',
178
                            'message' => [
179
                                'template' => 'Value cannot be blank.',
180
                                'parameters' => [],
181
                            ],
182
                            'notPassedMessage' => [
183
                                'template' => 'Value not passed.',
184
                                'parameters' => [],
185
                            ],
186
                            'skipOnError' => false,
187
                        ],
188
                    ],
189
                ],
190
            ],
191
        ];
192
    }
193
194
    public function testOptionsWithNotRule(): void
195
    {
196
        $rule = new Composite([
197
            new Number(max: 13, integerPattern: '/1/', numberPattern: '/1/'),
198
            new class () {
199
            },
200
        ]);
201
202
        $this->expectException(InvalidArgumentException::class);
203
        $message = 'Rule should be either an instance of Yiisoft\Validator\RuleInterface or a callable, class@anonymous given.';
204
        $this->expectExceptionMessage($message);
205
        $rule->getOptions();
206
    }
207
208
    public function dataValidationPassed(): array
209
    {
210
        return [
211
            [
212
                20,
213
                [
214
                    new Composite(
215
                        rules: [new Number(max: 13)],
216
                        when: fn () => false,
217
                    ),
218
                ],
219
            ],
220
            'override constructor' => [
221
                20,
222
                [
223
                    new class extends Composite {
224
                        public function __construct() { }
225
                    }
226
                ],
227
            ],
228
            [
229
                null,
230
                [
231
                    new Composite(
232
                        rules: [new Number(max: 13)],
233
                        skipOnEmpty: true,
234
                    ),
235
                ],
236
            ],
237
        ];
238
    }
239
240
    public function dataValidationFailed(): array
241
    {
242
        return [
243
            'callable' => [
244
                20,
245
                [
246
                    new Composite(
247
                        rules: [
248
                            static fn () => (new Result())->addError('Bad value.'),
249
                            static fn () => (new Result())->addError('Very bad value.'),
250
                        ],
251
                    ),
252
                ],
253
                [
254
                    '' => [
255
                        'Bad value.',
256
                        'Very bad value.',
257
                    ],
258
                ],
259
            ],
260
            'when true' => [
261
                20,
262
                [
263
                    new Composite(
264
                        rules: [new Number(max: 13), new Number(min: 21)],
265
                        when: fn () => true,
266
                    ),
267
                ],
268
                [
269
                    '' => [
270
                        'Value must be no greater than 13.',
271
                        'Value must be no less than 21.',
272
                    ],
273
                ],
274
            ],
275
            'skip on error with previous error' => [
276
                20,
277
                [
278
                    new Equal(19),
279
                    new Composite(
280
                        rules: [new Number(max: 13)],
281
                        skipOnError: true,
282
                    ),
283
                ],
284
                [
285
                    '' => ['Value must be equal to "19".'],
286
                ],
287
            ],
288
            'skip on error without previous error' => [
289
                20,
290
                [
291
                    new Composite(
292
                        rules: [new Number(max: 13)],
293
                        skipOnError: true,
294
                    ),
295
                ],
296
                [
297
                    '' => ['Value must be no greater than 13.'],
298
                ],
299
            ],
300
            'custom error' => [
301
                20,
302
                [
303
                    new Composite(
304
                        rules: [new Number(max: 13, tooBigMessage: 'Custom error')],
305
                        when: fn () => true,
306
                    ),
307
                ],
308
                ['' => ['Custom error']],
309
            ],
310
            'override constructor' => [
311
                null,
312
                [
313
                    new class extends Composite {
314
                        public function __construct()
315
                        {
316
                            $this->rules = [new Required()];
317
                        }
318
                    }
319
                ],
320
                ['' => ['Value cannot be blank.']],
321
            ],
322
        ];
323
    }
324
325
    public function testSkipOnError(): void
326
    {
327
        $this->testSkipOnErrorInternal(new Composite([]), new Composite([], skipOnError: true));
328
    }
329
330
    public function testWhen(): void
331
    {
332
        $when = static fn (mixed $value): bool => $value !== null;
333
        $this->testWhenInternal(new Composite([]), new Composite([], when: $when));
334
    }
335
336
    protected function getDifferentRuleInHandlerItems(): array
337
    {
338
        return [Composite::class, CompositeHandler::class];
339
    }
340
}
341