Passed
Pull Request — master (#441)
by Alexander
04:49 queued 02:19
created

CompositeTest.php$0 ➔ dataValidationPassed()   A

Complexity

Conditions 1

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
c 0
b 0
f 0
dl 0
loc 18
rs 9.6666
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
            ],
230
            [
231
                null,
232
                [
233
                    new Composite(
234
                        rules: [new Number(max: 13)],
235
                        skipOnEmpty: true,
236
                    ),
237
                ],
238
            ],
239
        ];
240
    }
241
242
    public function dataValidationFailed(): array
243
    {
244
        return [
245
            'callable' => [
246
                20,
247
                [
248
                    new Composite(
249
                        rules: [
250
                            static fn () => (new Result())->addError('Bad value.'),
251
                            static fn () => (new Result())->addError('Very bad value.'),
252
                        ],
253
                    ),
254
                ],
255
                [
256
                    '' => [
257
                        'Bad value.',
258
                        'Very bad value.',
259
                    ],
260
                ],
261
            ],
262
            'when true' => [
263
                20,
264
                [
265
                    new Composite(
266
                        rules: [new Number(max: 13), new Number(min: 21)],
267
                        when: fn () => true,
268
                    ),
269
                ],
270
                [
271
                    '' => [
272
                        'Value must be no greater than 13.',
273
                        'Value must be no less than 21.',
274
                    ],
275
                ],
276
            ],
277
            'skip on error with previous error' => [
278
                20,
279
                [
280
                    new Equal(19),
281
                    new Composite(
282
                        rules: [new Number(max: 13)],
283
                        skipOnError: true,
284
                    ),
285
                ],
286
                [
287
                    '' => ['Value must be equal to "19".'],
288
                ],
289
            ],
290
            'skip on error without previous error' => [
291
                20,
292
                [
293
                    new Composite(
294
                        rules: [new Number(max: 13)],
295
                        skipOnError: true,
296
                    ),
297
                ],
298
                [
299
                    '' => ['Value must be no greater than 13.'],
300
                ],
301
            ],
302
            'custom error' => [
303
                20,
304
                [
305
                    new Composite(
306
                        rules: [new Number(max: 13, tooBigMessage: 'Custom error')],
307
                        when: fn () => true,
308
                    ),
309
                ],
310
                ['' => ['Custom error']],
311
            ],
312
            'override constructor' => [
313
                null,
314
                [
315
                    new class () extends Composite {
316
                        public function __construct()
317
                        {
318
                            $this->rules = [new Required()];
319
                        }
320
                    },
321
                ],
322
                ['' => ['Value cannot be blank.']],
323
            ],
324
        ];
325
    }
326
327
    public function testSkipOnError(): void
328
    {
329
        $this->testSkipOnErrorInternal(new Composite([]), new Composite([], skipOnError: true));
330
    }
331
332
    public function testWhen(): void
333
    {
334
        $when = static fn (mixed $value): bool => $value !== null;
335
        $this->testWhenInternal(new Composite([]), new Composite([], when: $when));
336
    }
337
338
    protected function getDifferentRuleInHandlerItems(): array
339
    {
340
        return [Composite::class, CompositeHandler::class];
341
    }
342
}
343