Passed
Pull Request — master (#72)
by Wilmer
11:03
created

anonymous//tests/Rule/NumberTest.php$1   A

Complexity

Total Complexity 2

Size/Duplication

Total Lines 11
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 11
rs 10
wmc 2
1
<?php
2
3
namespace Yiisoft\Validator\Tests\Rule;
4
5
use PHPUnit\Framework\TestCase;
6
use Yiisoft\Validator\DataSetInterface;
7
use Yiisoft\Validator\MissingAttributeException;
8
use Yiisoft\Validator\Rule\Number;
9
10
/**
11
 * @group validators
12
 */
13
class NumberTest extends TestCase
14
{
15
    private $commaDecimalLocales = ['fr_FR.UTF-8', 'fr_FR.UTF8', 'fr_FR.utf-8', 'fr_FR.utf8', 'French_France.1252'];
16
    private $pointDecimalLocales = ['en_US.UTF-8', 'en_US.UTF8', 'en_US.utf-8', 'en_US.utf8', 'English_United States.1252'];
17
    private $oldLocale;
18
19
    private function setCommaDecimalLocale(): void
20
    {
21
        if ($this->oldLocale === false) {
22
            $this->markTestSkipped('Your platform does not support locales.');
23
        }
24
25
        if (setlocale(LC_NUMERIC, $this->commaDecimalLocales) === false) {
26
            $this->markTestSkipped('Could not set any of required locales: ' . implode(', ', $this->commaDecimalLocales));
27
        }
28
    }
29
30
    private function setPointDecimalLocale(): void
31
    {
32
        if ($this->oldLocale === false) {
33
            $this->markTestSkipped('Your platform does not support locales.');
34
        }
35
36
        if (setlocale(LC_NUMERIC, $this->pointDecimalLocales) === false) {
37
            $this->markTestSkipped('Could not set any of required locales: ' . implode(', ', $this->pointDecimalLocales));
38
        }
39
    }
40
41
    private function restoreLocale(): void
42
    {
43
        setlocale(LC_NUMERIC, $this->oldLocale);
44
    }
45
46
    protected function setUp(): void
47
    {
48
        parent::setUp();
49
50
        $this->oldLocale = setlocale(LC_NUMERIC, 0);
51
    }
52
53
    public function testValidateSimple(): void
54
    {
55
        $rule = new Number();
56
        $this->assertTrue($rule->validate(20)->isValid());
57
        $this->assertTrue($rule->validate(0)->isValid());
58
        $this->assertTrue($rule->validate(-20)->isValid());
59
        $this->assertTrue($rule->validate('20')->isValid());
60
        $this->assertTrue($rule->validate(25.45)->isValid());
61
62
        $this->setPointDecimalLocale();
63
        $this->assertFalse($rule->validate('25,45')->isValid());
64
        $this->setCommaDecimalLocale();
65
        $this->assertTrue($rule->validate('25,45')->isValid());
66
        $this->restoreLocale();
67
68
        $this->assertFalse($rule->validate('12:45')->isValid());
69
    }
70
71
    public function testValidateSimpleInteger(): void
72
    {
73
        $rule = (new Number())
74
            ->integer();
75
76
        $this->assertTrue($rule->validate(20)->isValid());
77
        $this->assertTrue($rule->validate(0)->isValid());
78
        $this->assertFalse($rule->validate(25.45)->isValid());
79
        $this->assertTrue($rule->validate('20')->isValid());
80
        $this->assertFalse($rule->validate('25,45')->isValid());
81
        $this->assertTrue($rule->validate('020')->isValid());
82
        $this->assertTrue($rule->validate(0x14)->isValid());
83
        $this->assertFalse($rule->validate('0x14')->isValid()); // todo check this
84
    }
85
86
    public function testValidateAdvanced(): void
87
    {
88
        $rule = new Number();
89
        $this->assertTrue($rule->validate('-1.23')->isValid()); // signed float
90
        $this->assertTrue($rule->validate('-4.423e-12')->isValid()); // signed float + exponent
91
        $this->assertTrue($rule->validate('12E3')->isValid()); // integer + exponent
92
        $this->assertFalse($rule->validate('e12')->isValid()); // just exponent
93
        $this->assertFalse($rule->validate('-e3')->isValid());
94
        $this->assertFalse($rule->validate('-4.534-e-12')->isValid()); // 'signed' exponent
95
        $this->assertFalse($rule->validate('12.23^4')->isValid()); // expression instead of value
96
    }
97
98
    public function testValidateAdvancedInteger(): void
99
    {
100
        $rule = (new Number())->integer();
101
        $this->assertFalse($rule->validate('-1.23')->isValid());
102
        $this->assertFalse($rule->validate('-4.423e-12')->isValid());
103
        $this->assertFalse($rule->validate('12E3')->isValid());
104
        $this->assertFalse($rule->validate('e12')->isValid());
105
        $this->assertFalse($rule->validate('-e3')->isValid());
106
        $this->assertFalse($rule->validate('-4.534-e-12')->isValid());
107
        $this->assertFalse($rule->validate('12.23^4')->isValid());
108
    }
109
110
    public function testValidateWithLocaleWhereDecimalPointIsComma(): void
111
    {
112
        $rule = new Number();
113
114
        $this->setPointDecimalLocale();
115
        $this->assertTrue($rule->validate(.5)->isValid());
116
117
        $this->setCommaDecimalLocale();
118
        $this->assertTrue($rule->validate(.5)->isValid());
119
120
        $this->restoreLocale();
121
    }
122
123
    public function testValidateMin(): void
124
    {
125
        $rule = (new Number())
126
            ->min(1);
127
128
        $this->assertTrue($rule->validate(1)->isValid());
129
130
        $result = $rule->validate(-1);
131
        $this->assertFalse($result->isValid());
132
        $this->assertStringContainsString('must be no less than 1.', $result->getErrors()[0]);
133
134
        $this->assertFalse($rule->validate('22e-12')->isValid());
135
        $this->assertTrue($rule->validate(PHP_INT_MAX + 1)->isValid());
136
    }
137
138
    public function testValidateMinInteger(): void
139
    {
140
        $rule = (new Number())
141
            ->min(1)
142
            ->integer();
143
144
        $this->assertTrue($rule->validate(1)->isValid(), '1 is a valid integer');
145
        $this->assertFalse($rule->validate(-1)->isValid(), '-1 is not a valid integer');
146
        $this->assertFalse($rule->validate('22e-12')->isValid(), '22e-12 is not a valid integer');
147
    }
148
149
    public function testValidateMax(): void
150
    {
151
        $rule = (new Number())
152
            ->max(1.25);
153
154
        $this->assertTrue($rule->validate(1)->isValid());
155
        $this->assertFalse($rule->validate(1.5)->isValid());
156
        $this->assertTrue($rule->validate('22e-12')->isValid());
157
        $this->assertTrue($rule->validate('125e-2')->isValid());
158
    }
159
160
    public function testValidateMaxInteger(): void
161
    {
162
        $rule = (new Number())
163
            ->max(1.25)
164
            ->integer();
165
166
        $this->assertTrue($rule->validate(1)->isValid());
167
        $this->assertFalse($rule->validate(1.5)->isValid());
168
        $this->assertFalse($rule->validate('22e-12')->isValid());
169
        $this->assertFalse($rule->validate('125e-2')->isValid());
170
    }
171
172
    public function testValidateRange(): void
173
    {
174
        $rule = (new Number())
175
            ->min(-10)
176
            ->max(20);
177
178
        $this->assertTrue($rule->validate(0)->isValid());
179
        $this->assertTrue($rule->validate(-10)->isValid());
180
        $this->assertFalse($rule->validate(-11)->isValid());
181
        $this->assertFalse($rule->validate(21)->isValid());
182
    }
183
184
    public function testValidateRangeInteger(): void
185
    {
186
        $rule = (new Number())
187
            ->min(-10)
188
            ->max(20)
189
            ->integer();
190
191
        $this->assertTrue($rule->validate(0)->isValid());
192
        $this->assertFalse($rule->validate(-11)->isValid());
193
        $this->assertFalse($rule->validate(22)->isValid());
194
        $this->assertFalse($rule->validate('20e-1')->isValid());
195
    }
196
197
    public function testScientificFormat(): void
198
    {
199
        $rule = new Number();
200
        $result = $rule->validate('5.5e1');
201
        $this->assertTrue($result->isValid());
202
    }
203
204
    public function testExpressionFormat(): void
205
    {
206
        $rule = new Number();
207
        $result = $rule->validate('43^32');
208
        $this->assertFalse($result->isValid());
209
    }
210
211
    public function testMinEdge(): void
212
    {
213
        $rule = (new Number())
214
            ->min(10);
215
216
        $result = $rule->validate(10);
217
        $this->assertTrue($result->isValid());
218
    }
219
220
    public function testLessThanMin(): void
221
    {
222
        $rule = (new Number())
223
            ->min(10);
224
225
        $result = $rule->validate(5);
226
        $this->assertFalse($result->isValid());
227
    }
228
229
    public function testMaxEdge(): void
230
    {
231
        $rule = (new Number())
232
            ->max(10);
233
234
        $result = $rule->validate(10);
235
        $this->assertTrue($result->isValid());
236
    }
237
238
    public function testMaxEdgeInteger(): void
239
    {
240
        $rule = (new Number())
241
            ->max(10)
242
            ->integer();
243
244
        $result = $rule->validate(10);
245
        $this->assertTrue($result->isValid());
246
    }
247
248
    public function testMoreThanMax(): void
249
    {
250
        $rule = (new Number())
251
            ->max(10);
252
253
        $result = $rule->validate(15);
254
        $this->assertFalse($result->isValid());
255
    }
256
257
    public function testFloatWithInteger(): void
258
    {
259
        $rule = (new Number())
260
            ->max(10)
261
            ->integer();
262
263
        $result = $rule->validate(3.43);
264
        $this->assertFalse($result->isValid());
265
    }
266
267
    public function testArray(): void
268
    {
269
        $rule = (new Number())
270
            ->min(1);
271
272
        $result = $rule->validate([1, 2, 3]);
273
        $this->assertFalse($result->isValid());
274
    }
275
276
    /**
277
     * @see https://github.com/yiisoft/yii2/issues/11672
278
     */
279
    public function testStdClass(): void
280
    {
281
        $rule = (new Number())
282
            ->min(1);
283
284
        $result = $rule->validate(new \stdClass());
285
        $this->assertFalse($result->isValid());
286
    }
287
288
    public function getDataSet(array $attributeValues): DataSetInterface
289
    {
290
        return new class($attributeValues) implements DataSetInterface {
291
            private array $data;
292
293
            public function __construct(array $data)
294
            {
295
                $this->data = $data;
296
            }
297
298
            public function getAttributeValue(string $attribute)
299
            {
300
                if (!$this->hasAttribute($attribute)) {
301
                    throw new MissingAttributeException("There is no \"$attribute\" attribute in the class.");
302
                }
303
304
                return $this->data[$attribute];
305
            }
306
307
            public function hasAttribute(string $attribute): bool
308
            {
309
                return isset($this->data[$attribute]);
310
            }
311
        };
312
    }
313
314
    public function testEnsureCustomMessageIsSetOnvalidate(): void
315
    {
316
        $rule = (new Number())
317
            ->min(5)
318
            ->tooSmallMessage('Value is too small.');
319
320
        $result = $rule->validate(0);
321
        $this->assertFalse($result->isValid());
322
        $this->assertCount(1, $result->getErrors());
323
        $errors = $result->getErrors();
324
        $this->assertSame('Value is too small.', $errors[0]);
325
    }
326
327
    public function testValidateObject(): void
328
    {
329
        $rule = new Number();
330
        $value = new \stdClass();
331
        $this->assertFalse($rule->validate($value)->isValid());
332
    }
333
334
    public function testValidateResource(): void
335
    {
336
        $rule = new Number();
337
        $fp = fopen('php://stdin', 'r');
338
        $this->assertFalse($rule->validate($fp)->isValid());
339
340
        $result = $rule->validate($fp);
341
        $this->assertFalse($result->isValid());
342
343
        // the check is here for HHVM that
344
        // was losing handler for unknown reason
345
        if (is_resource($fp)) {
346
            fclose($fp);
347
        }
348
    }
349
350
    public function testValidateToString(): void
351
    {
352
        $rule = new Number();
353
        $object = new class('10') {
354
            public $foo;
355
356
            public function __construct($foo)
357
            {
358
                $this->foo = $foo;
359
            }
360
361
            public function __toString(): string
362
            {
363
                return $this->foo;
364
            }
365
        };
366
        $this->assertTrue($rule->validate($object)->isValid());
367
    }
368
}
369