Completed
Push — master ( 719e85...a85d2e )
by Dmitry
02:46
created

validDomainAllWithoutIdnProvider()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 7
rs 9.4285
cc 1
eloc 4
nc 1
nop 0
1
<?php
2
3
namespace kdn\yii2\validators;
4
5
use kdn\yii2\validators\mocks\ModelMock;
6
use stdClass;
7
use Yii;
8
9
/**
10
 * Class DomainValidatorTest.
11
 * @package kdn\yii2\validators
12
 * @covers kdn\yii2\validators\DomainValidator::init
13
 */
14
class DomainValidatorTest extends TestCase
15
{
16
    /**
17
     * @var DomainValidator
18
     */
19
    protected $validator;
20
21
    /**
22
     * @inheritdoc
23
     */
24
    protected function setUp()
25
    {
26
        parent::setUp();
27
        $this->validator = new DomainValidator(['labelNumberMin' => 1]);
28
    }
29
30
    public static function validDomainProvider()
31
    {
32
        return [
33
            'one domain name label' => ['localhost'],
34
            'two domain name labels' => ['example.com'],
35
            'domain name with trailing dot' => ['example.com.'],
36
            '127 levels, 253 characters and trailing dot' => [
37
                'a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.' .
38
                'a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.' .
39
                'a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.' .
40
                'a.a.a.a.',
41
            ],
42
            'domain name labels with 63 characters' => [
43
                'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.' .
44
                'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.' .
45
                'example.com',
46
            ],
47
            'domain name with various symbols' => ['1.a-B.c2'],
48
            'Punycode, mixed domain name' => ['xn--e1afmkfd.test.xn--80akhbyknj4f'],
49
        ];
50
    }
51
52
    public static function validDomainInUrlProvider()
53
    {
54
        return [
55
            'HTTP, one domain name label' => ['http://localhost'],
56
            'HTTP, two domain name labels' => ['http://example.com/index.html'],
57
            'FTP, domain name with trailing dot' => ['ftp://example.com./img/dir/'],
58
            // todo it causes empty array in "idn_to_ascii" $idnaInfo
59
            'HTTPS, 127 levels, 253 characters and trailing dot' => [
60
                'https://a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.' .
61
                'a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.' .
62
                'a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.a.' .
63
                'a.a.a.a./index.html',
64
            ],
65
            'missing scheme, domain name labels with 63 characters' => [
66
                '//aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.' .
67
                'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.' .
68
                'example.com',
69
            ],
70
            'complex URL, domain name with various symbols' => [
71
                'http://username:[email protected]:9090/path?a=b&c=d#anchor',
72
            ],
73
            'Punycode, FTP, mixed domain name' => ['ftp://xn--e1afmkfd.test.xn--80akhbyknj4f/img/dir/'],
74
        ];
75
    }
76
77
    public static function validDomainIdnProvider()
78
    {
79
        return [
80
            'IDN, one domain name label' => ['пример'],
81
            'IDN, two domain name labels' => ['пример.испытание'],
82
            'IDN, domain name with trailing dot' => ['пример.испытание.'],
83
            'IDN, mixed domain name' => ['пример.test.испытание'],
84
            'IDN, 34 levels, 253 characters (ф. == xn--t1a.) and trailing dot' => [
85
                'ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.s.s.s.',
86
            ],
87
            'IDN, domain name labels with 63 characters' => [
88
                'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.' .
89
                'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.' .
90
                'испытание'
91
            ],
92
            'IDN, domain name with various symbols' => ['1.a-B.cф2'],
93
            'IDN, hot beverage' => ['☕.us'],
94
            'IDN, full-width characters' => ['日本語。JP'],
95
            'IDN, box-drawing character' => ['ex╬ample.com'],
96
        ];
97
    }
98
99
    public static function validDomainIdnInUrlProvider()
100
    {
101
        return [
102
            'IDN, HTTP, one domain name label' => ['http://пример'],
103
            'IDN, HTTP, two domain name labels' => ['http://пример.испытание/index.html'],
104
            'IDN, FTP, domain name with trailing dot' => ['ftp://пример.испытание./img/dir/'],
105
            'IDN, FTP, mixed domain name' => ['ftp://пример.test.испытание/img/dir/'],
106
            // todo it causes empty array in "idn_to_ascii" $idnaInfo
107
            'IDN, HTTPS, 34 levels, 253 characters (ф. == xn--t1a.) and trailing dot' => [
108
                'https://ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.s.s.s./index.html',
109
            ],
110
            'IDN, missing scheme, domain name labels with 63 characters' => [
111
                '//ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.' .
112
                'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.' .
113
                'испытание'
114
            ],
115
            'IDN, complex URL, domain name with various symbols' => [
116
                'http://username:[email protected]ф2:9090/path?a=ф&c=d#-пример',
117
            ],
118
            'IDN, HTTP, hot beverage' => ['http://☕.us/index.html'],
119
            'IDN, HTTP, full-width characters' => ['http://日本語。JP/index.html'],
120
            'IDN, HTTP, box-drawing character' => ['http://ex╬ample.com/index.html'],
121
        ];
122
    }
123
124
    public static function validDomainAllWithoutIdnProvider()
125
    {
126
        return array_merge(
127
            static::validDomainProvider(),
128
            static::validDomainInUrlProvider()
129
        );
130
    }
131
132
    public static function validDomainAllOnlyIdnProvider()
133
    {
134
        return array_merge(
135
            static::validDomainIdnProvider(),
136
            static::validDomainIdnInUrlProvider()
137
        );
138
    }
139
140
    public static function validDomainAllProvider()
141
    {
142
        return array_merge(
143
            static::validDomainProvider(),
144
            static::validDomainInUrlProvider(),
145
            static::validDomainIdnProvider(),
146
            static::validDomainIdnInUrlProvider()
147
        );
148
    }
149
150
    /**
151
     * @param string $value
152
     * @covers       kdn\yii2\validators\DomainValidator::validateValue
153
     * @dataProvider validDomainAllWithoutIdnProvider
154
     * @small
155
     */
156
    public function testValidDomain($value)
157
    {
158
        $this->assertTrue($this->validator->validate($value));
159
    }
160
161
    /**
162
     * @param string $value
163
     * @covers       kdn\yii2\validators\DomainValidator::getDefaultErrorMessages
164
     * @covers       kdn\yii2\validators\DomainValidator::getErrorMessage
165
     * @covers       kdn\yii2\validators\DomainValidator::validateValue
166
     * @dataProvider validDomainAllOnlyIdnProvider
167
     * @small
168
     */
169
    public function testInvalidDomainWithDisabledIdn($value)
170
    {
171
        $this->assertFalse($this->validator->validate($value, $errorMessage));
172
        $this->assertEquals(
173
            'Each label of the input value can consist of only latin letters, numbers and hyphens.',
174
            $errorMessage
175
        );
176
    }
177
178
    /**
179
     * @param string $value
180
     * @covers       kdn\yii2\validators\DomainValidator::validateValue
181
     * @dataProvider validDomainAllProvider
182
     * @small
183
     */
184
    public function testValidDomainWithEnabledIdn($value)
185
    {
186
        if (!function_exists('idn_to_ascii')) {
187
            $this->markTestSkipped('intl extension required.');
188
            return;
189
        }
190
191
        $this->validator->enableIDN = true;
192
        $this->testValidDomain($value);
193
    }
194
195
    /**
196
     * @covers kdn\yii2\validators\DomainValidator::getDefaultErrorMessages
197
     * @covers kdn\yii2\validators\DomainValidator::getErrorMessage
198
     * @covers kdn\yii2\validators\DomainValidator::validateValue
199
     * @medium
200
     */
201
    public function testDns()
202
    {
203
        $validator = $this->validator;
204
        $nonExistingDomain = 'non-existing-subdomain.example.com';
205
        $this->assertTrue($validator->validate($nonExistingDomain));
206
        $validator->checkDNS = true;
207
        $this->assertFalse($validator->validate($nonExistingDomain, $errorMessage));
208
        $this->assertEquals('DNS record corresponding to the input value not found.', $errorMessage);
209
210
        $data = [
211
            'google.com',
212
            'http://username:[email protected]:9090/path?a=b&c=d#anchor',
213
        ];
214
        foreach ($data as $value) {
215
            $this->assertTrue(
216
                $validator->validate($value),
217
                "Failed to validate \"$value\" (checkDNS = true)."
218
            );
219
        }
220
    }
221
222
    /**
223
     * @covers kdn\yii2\validators\DomainValidator::getDefaultErrorMessages
224
     * @covers kdn\yii2\validators\DomainValidator::getErrorMessage
225
     * @covers kdn\yii2\validators\DomainValidator::validateValue
226
     * @medium
227
     */
228
    public function testDnsWithEnabledIdn()
229
    {
230
        if (!function_exists('idn_to_ascii')) {
231
            $this->markTestSkipped('intl extension required.');
232
            return;
233
        }
234
235
        $validator = $this->validator;
236
        $validator->checkDNS = true;
237
        // enabling of IDN should not affect error message
238
        $validator->enableIDN = true;
239
        $this->assertFalse($validator->validate('non-existing-subdomain.example.com', $errorMessage));
240
        $this->assertEquals('DNS record corresponding to the input value not found.', $errorMessage);
241
242
        $data = [
243
            'google.com',
244
            'http://username:[email protected]:9090/path?a=b&c=d#anchor',
245
            'яндекс.рф',
246
            'http://username:password@яндекс.рф:9090/path?a=ф&c=d#-пример',
247
        ];
248
        foreach ($data as $value) {
249
            $this->assertTrue(
250
                $validator->validate($value),
251
                "Failed to validate \"$value\" (checkDNS = true, enableIDN = true)."
252
            );
253
        }
254
    }
255
256
    /**
257
     * @covers kdn\yii2\validators\DomainValidator::getDefaultErrorMessages
258
     * @covers kdn\yii2\validators\DomainValidator::getErrorMessage
259
     * @covers kdn\yii2\validators\DomainValidator::validateValue
260
     * @small
261
     */
262
    public function testUnderscore()
263
    {
264
        $validator = $this->validator;
265
        $validator->allowUnderscore = true;
266
267
        $data = [
268
            'ex_ample.com',
269
            'http://username:password@ex_ample.com:9090/path?a=b&c=d#anchor',
270
        ];
271
        foreach ($data as $value) {
272
            $this->assertTrue(
273
                $validator->validate($value),
274
                "Failed to validate \"$value\" (allowUnderscore = true)."
275
            );
276
        }
277
278
        $this->assertFalse($validator->validate('a_@_a', $errorMessage));
279
        if ($validator->enableIDN) {
280
            $expectedErrorMessage =
281
                'Each label of the input value can consist of only letters, numbers, hyphens and underscores.';
282
        } else {
283
            $expectedErrorMessage =
284
                'Each label of the input value can consist of only latin letters, numbers, hyphens and underscores.';
285
        }
286
        $this->assertEquals($expectedErrorMessage, $errorMessage);
287
    }
288
289
    /**
290
     * @covers kdn\yii2\validators\DomainValidator::getDefaultErrorMessages
291
     * @covers kdn\yii2\validators\DomainValidator::getErrorMessage
292
     * @covers kdn\yii2\validators\DomainValidator::validateValue
293
     * @small
294
     */
295
    public function testUnderscoreWithEnabledIdn()
296
    {
297
        if (!function_exists('idn_to_ascii')) {
298
            $this->markTestSkipped('intl extension required.');
299
            return;
300
        }
301
302
        $this->validator->enableIDN = true;
303
        $this->testUnderscore();
304
    }
305
306
    public static function urlNotAllowedProvider()
307
    {
308
        return array_merge(
309
            static::arrayAddColumn(static::validDomainProvider(), true),
310
            static::arrayAddColumn(static::validDomainInUrlProvider(), false)
311
        );
312
    }
313
314
    /**
315
     * @param string $value
316
     * @param boolean $expectedResult
317
     * @covers       kdn\yii2\validators\DomainValidator::validateValue
318
     * @uses         kdn\yii2\validators\DomainValidator::getDefaultErrorMessages
319
     * @uses         kdn\yii2\validators\DomainValidator::getErrorMessage
320
     * @dataProvider urlNotAllowedProvider
321
     * @small
322
     */
323
    public function testUrlNotAllowed($value, $expectedResult)
324
    {
325
        $validator = $this->validator;
326
        $validator->allowURL = false;
327
        $this->assertEquals($expectedResult, $validator->validate($value));
328
    }
329
330
    public static function urlNotAllowedProviderWithEnabledIdn()
331
    {
332
        return array_merge(
333
            static::urlNotAllowedProvider(),
334
            static::arrayAddColumn(static::validDomainIdnProvider(), true),
335
            static::arrayAddColumn(static::validDomainIdnInUrlProvider(), false)
336
        );
337
    }
338
339
    /**
340
     * @param string $value
341
     * @param boolean $expectedResult
342
     * @covers       kdn\yii2\validators\DomainValidator::validateValue
343
     * @uses         kdn\yii2\validators\DomainValidator::getDefaultErrorMessages
344
     * @uses         kdn\yii2\validators\DomainValidator::getErrorMessage
345
     * @dataProvider urlNotAllowedProviderWithEnabledIdn
346
     * @small
347
     */
348
    public function testUrlNotAllowedWithEnabledIdn($value, $expectedResult)
349
    {
350
        if (!function_exists('idn_to_ascii')) {
351
            $this->markTestSkipped('intl extension required.');
352
            return;
353
        }
354
355
        $this->validator->enableIDN = true;
356
        $this->testUrlNotAllowed($value, $expectedResult);
357
    }
358
359
    /**
360
     * @covers kdn\yii2\validators\DomainValidator::getDefaultErrorMessages
361
     * @covers kdn\yii2\validators\DomainValidator::getErrorMessage
362
     * @covers kdn\yii2\validators\DomainValidator::validateValue
363
     * @small
364
     */
365
    public function testLabelNumberMin()
366
    {
367
        $validator = $this->validator;
368
        $validator->labelNumberMin = 2;
369
        $this->assertFalse($validator->validate('localhost', $errorMessage));
370
        $this->assertEquals('the input value should consist of at least 2 labels separated by dot.', $errorMessage);
371
        $this->assertTrue($validator->validate('example.com'));
372
        $this->assertTrue($validator->validate('test.example.com'));
373
        $validator->labelNumberMin = 3;
374
        $this->assertFalse($validator->validate('example.com', $errorMessage));
375
        $this->assertEquals('the input value should consist of at least 3 labels separated by dots.', $errorMessage);
376
        $this->assertTrue($validator->validate('test.example.com'));
377
    }
378
379
    /**
380
     * @covers kdn\yii2\validators\DomainValidator::getDefaultErrorMessages
381
     * @covers kdn\yii2\validators\DomainValidator::getErrorMessage
382
     * @covers kdn\yii2\validators\DomainValidator::validateValue
383
     * @small
384
     */
385
    public function testLabelNumberMinWithEnabledIdn()
386
    {
387
        if (!function_exists('idn_to_ascii')) {
388
            $this->markTestSkipped('intl extension required.');
389
            return;
390
        }
391
392
        $this->validator->enableIDN = true;
393
        $this->testLabelNumberMin();
394
    }
395
396
    public static function invalidDomainProvider($testName)
397
    {
398
        if ($testName == 'testInvalidDomain') {
399
            $messageInvalidCharacter =
400
                'Each label of the input value can consist of only latin letters, numbers and hyphens.';
401
            $messageLabelStartEnd = 'Each label of the input value should start and end with latin letter or number.' .
402
                ' The rightmost label of the input value should start with latin letter.';
403
            $messageLabelTooLong = 'Each label of the input value should contain at most 63 characters.';
404
            $messageTooLong = 'the input value should contain at most 253 characters.';
405
        } else {
406
            $messageInvalidCharacter =
407
                'Each label of the input value can consist of only letters, numbers and hyphens.';
408
            $messageLabelStartEnd = 'Each label of the input value should start and end with letter or number.' .
409
                ' The rightmost label of the input value should start with letter.';
410
            $messageLabelTooLong = 'Label of the input value is too long.';
411
            $messageTooLong = 'the input value is too long.';
412
        }
413
        $messageLabelTooShort = 'Each label of the input value should contain at least 1 character.';
414
        $messageNotString = 'the input value must be a string.';
415
        $messageTooShort = 'the input value should contain at least 1 character.';
416
        return [
417
            'null' => [null, $messageNotString],
418
            'boolean' => [true, $messageNotString],
419
            'integer' => [1, $messageNotString],
420
            'float' => [1.2, $messageNotString],
421
            'array' => [[], $messageNotString],
422
            'object' => [new stdClass, $messageNotString],
423
424
            'domain name too long' => [str_repeat('a.', 126) . 'aa', $messageTooLong],
425
426
            'domain name too short' => ['', $messageTooShort],
427
428
            'first domain name label starts with hyphen' => ['-example.com', $messageLabelStartEnd],
429
            'first domain name label ends with hyphen' => ['example-.com', $messageLabelStartEnd],
430
            'last domain name label starts with hyphen' => ['example.-com', $messageLabelStartEnd],
431
            'last domain name label ends with hyphen' => ['example.com-', $messageLabelStartEnd],
432
433
            'IDN, first domain name label starts with hyphen' => ['-пример.испытание', $messageInvalidCharacter],
434
            'IDN, first domain name label ends with hyphen' => ['пример-.испытание', $messageInvalidCharacter],
435
            'IDN, last domain name label starts with hyphen' => ['пример.-испытание', $messageInvalidCharacter],
436
            'IDN, last domain name label ends with hyphen' => ['пример.испытание-', $messageInvalidCharacter],
437
438
            'IDN, HTTP, first domain name label starts with hyphen' => [
439
                'http://-пример.испытание/index.html',
440
                $messageInvalidCharacter,
441
            ],
442
            'IDN, HTTP, first domain name label ends with hyphen' => [
443
                'http://пример-.испытание/index.html',
444
                $messageInvalidCharacter,
445
            ],
446
            'IDN, HTTP, last domain name label starts with hyphen' => [
447
                'http://пример.-испытание/index.html',
448
                $messageInvalidCharacter,
449
            ],
450
            'IDN, HTTP, last domain name label ends with hyphen' => [
451
                'http://пример.испытание-/index.html',
452
                $messageInvalidCharacter,
453
            ],
454
455
            'last domain name label starts with number' => ['example.4om', $messageLabelStartEnd],
456
457
            'domain name label too long' => [str_repeat('a', 64), $messageLabelTooLong],
458
459
            'dot' => ['.', $messageLabelTooShort],
460
            'domain name starts with dot' => ['.example.com', $messageLabelTooShort],
461
            'domain name ends with two dots' => ['example.com..', $messageLabelTooShort],
462
            'domain name contains two dots in a row' => ['example..com', $messageLabelTooShort],
463
464
            'domain name contains underscore' => ['ex_ample.com', $messageInvalidCharacter],
465
            'domain name contains space' => ['ex ample.com', $messageInvalidCharacter],
466
            'domain name contains disallowed character' => ['a⒈com', $messageInvalidCharacter],
467
468
            'IDN, domain name too long' => [
469
                'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.' .
470
                'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.' .
471
                'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.' .
472
                'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.',
473
                $messageInvalidCharacter,
474
            ],
475
            'IDN, domain name label too long' => [
476
                'фффффффффффффффффффффффффффффффффффффффффффффффффффффффффs',
477
                $messageInvalidCharacter,
478
            ],
479
480
            'invalid url with valid domain name' => ['http//example.com/index.html', $messageInvalidCharacter],
481
            'IDN, invalid url with valid domain name' => ['http//пример.com/index.html', $messageInvalidCharacter],
482
        ];
483
    }
484
485
    /**
486
     * @param string $value
487
     * @param string $expectedErrorMessage
488
     * @covers       kdn\yii2\validators\DomainValidator::getDefaultErrorMessages
489
     * @covers       kdn\yii2\validators\DomainValidator::getErrorMessage
490
     * @covers       kdn\yii2\validators\DomainValidator::validateValue
491
     * @dataProvider invalidDomainProvider
492
     * @small
493
     */
494
    public function testInvalidDomain($value, $expectedErrorMessage)
495
    {
496
        $this->assertFalse($this->validator->validate($value, $errorMessage));
497
        $this->assertEquals($expectedErrorMessage, $errorMessage);
498
    }
499
500
    public static function invalidDomainWithEnabledIdnProvider()
501
    {
502
        $message = 'the input value is invalid.';
503
        $messageLabelStartEnd = 'Each label of the input value should start and end with letter or number.' .
504
            ' The rightmost label of the input value should start with letter.';
505
        $messageLabelTooLong = 'Label of the input value is too long.';
506
        $messageTooLong = 'the input value is too long.';
507
        return array_merge(
508
            static::invalidDomainProvider('testInvalidDomainWithEnabledIdn'),
509
            [
510
                /* todo it causes fatal error
1 ignored issue
show
Unused Code Comprehensibility introduced by
36% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
511
                'IDN, domain name too long, fatal' => [
512
                    'ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.ф.s.s.s.s',
513
                    $messageTooLong,
514
                ],
515
                //*/
516
                /* todo it causes fatal error
517
                'IDN, domain name too long, fatal' => [
518
                    'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.' .
519
                    'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.' .
520
                    'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.' .
521
                    'фффффффффффффффффффффффффффффффффффффффффффффффффффффффф.',
522
                    $messageTooLong,
523
                ],
524
                //*/
525
526
                'IDN, first domain name label starts with hyphen' => ['-пример.испытание', $messageLabelStartEnd],
527
                'IDN, first domain name label ends with hyphen' => ['пример-.испытание', $messageLabelStartEnd],
528
                'IDN, last domain name label starts with hyphen' => ['пример.-испытание', $messageLabelStartEnd],
529
                'IDN, last domain name label ends with hyphen' => ['пример.испытание-', $messageLabelStartEnd],
530
531
                'IDN, HTTP, first domain name label starts with hyphen' => [
532
                    'http://-пример.испытание/index.html',
533
                    $messageLabelStartEnd,
534
                ],
535
                'IDN, HTTP, first domain name label ends with hyphen' => [
536
                    'http://пример-.испытание/index.html',
537
                    $messageLabelStartEnd,
538
                ],
539
                'IDN, HTTP, last domain name label starts with hyphen' => [
540
                    'http://пример.-испытание/index.html',
541
                    $messageLabelStartEnd,
542
                ],
543
                'IDN, HTTP, last domain name label ends with hyphen' => [
544
                    'http://пример.испытание-/index.html',
545
                    $messageLabelStartEnd,
546
                ],
547
548
                // todo it causes empty array in "idn_to_ascii" $idnaInfo
549
                'IDN, domain name too long' => [
550
                    'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.' .
551
                    'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.' .
552
                    'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.' .
553
                    'ффффффффффффффффффффффффффффффффффффффффффффффффффффффффф.',
554
                    $messageTooLong,
555
                ],
556
                'IDN, domain name label too long' => [
557
                    'фффффффффффффффффффффффффффффффффффффффффффффффффффффффффs',
558
                    $messageLabelTooLong,
559
                ],
560
561
                'IDN, IDNA_ERROR_HYPHEN_3_4' => ['aa--a', $message],
562
                'IDN, IDNA_ERROR_LEADING_COMBINING_MARK' => [json_decode('"\u0308c"'), $message],
563
                'IDN, IDNA_ERROR_PUNYCODE' => ['xn--0', $message],
564
                'IDN, IDNA_ERROR_INVALID_ACE_LABEL' => ['xn--a', $message],
565
                'IDN, IDNA_ERROR_BIDI' => [json_decode('"0A.\\u05D0"'), $message],
566
            ]
567
        );
568
    }
569
570
    /**
571
     * @param string $value
572
     * @param string $expectedErrorMessage
573
     * @covers       kdn\yii2\validators\DomainValidator::getDefaultErrorMessages
574
     * @covers       kdn\yii2\validators\DomainValidator::getErrorMessage
575
     * @covers       kdn\yii2\validators\DomainValidator::validateValue
576
     * @dataProvider invalidDomainWithEnabledIdnProvider
577
     * @small
578
     */
579
    public function testInvalidDomainWithEnabledIdn($value, $expectedErrorMessage)
580
    {
581
        if (!function_exists('idn_to_ascii')) {
582
            $this->markTestSkipped('intl extension required.');
583
            return;
584
        }
585
586
        $this->validator->enableIDN = true;
587
        $this->testInvalidDomain($value, $expectedErrorMessage);
588
    }
589
590
    /**
591
     * @covers kdn\yii2\validators\DomainValidator::getErrorMessage
592
     * @covers kdn\yii2\validators\DomainValidator::validateValue
593
     * @small
594
     */
595
    public function testCustomErrorMessage()
596
    {
597
        $validator = $this->validator;
598
        $messageNotString = 'test';
599
        $validator->messageNotString = $messageNotString;
600
        $this->assertFalse($validator->validate(null, $errorMessage));
601
        $this->assertEquals($messageNotString, $errorMessage);
602
    }
603
604
    /**
605
     * @covers kdn\yii2\validators\DomainValidator::getDefaultErrorMessages
606
     * @covers kdn\yii2\validators\DomainValidator::getErrorMessage
607
     * @covers kdn\yii2\validators\DomainValidator::validateValue
608
     * @small
609
     */
610
    public function testSimpleErrorMessage()
611
    {
612
        $validator = $this->validator;
613
        $validator->simpleErrorMessage = true;
614
        $this->assertFalse($validator->validate('-', $errorMessage));
615
        $this->assertEquals('the input value is invalid.', $errorMessage);
616
    }
617
618
    /**
619
     * @covers kdn\yii2\validators\DomainValidator::getDefaultErrorMessages
620
     * @covers kdn\yii2\validators\DomainValidator::getErrorMessage
621
     * @covers kdn\yii2\validators\DomainValidator::validateValue
622
     * @small
623
     */
624
    public function testValidateAttributeAndI18n()
625
    {
626
        Yii::$app->language = 'ru-RU';
627
        $model = new ModelMock(['domain' => 'example']);
628
        $validator = $this->validator;
629
630
        $validator->validateAttribute($model, 'domain');
631
        $this->assertFalse($model->hasErrors('domain'));
632
633
        $validator->labelNumberMin = 2;
634
        $validator->validateAttribute($model, 'domain');
635
        $this->assertTrue($model->hasErrors('domain'));
636
        $this->assertEquals(
637
            'Значение «Доменное имя» должно состоять минимум из 2 меток, разделённых точкой.',
638
            $model->getFirstError('domain')
639
        );
640
641
        $model->clearErrors('domain');
642
643
        $validator->labelNumberMin = 21;
644
        $validator->validateAttribute($model, 'domain');
645
        $this->assertTrue($model->hasErrors('domain'));
646
        $this->assertEquals(
647
            'Значение «Доменное имя» должно состоять минимум из 21 метки, разделённых точками.',
648
            $model->getFirstError('domain')
649
        );
650
    }
651
652
    /**
653
     * Important: this test should be executed last, because it can remove function "idn_to_ascii".
654
     * @covers kdn\yii2\validators\DomainValidator::init
655
     * @expectedException \yii\base\InvalidConfigException
656
     * @expectedExceptionMessage In order to use IDN validation intl extension must be installed and enabled.
657
     * @small
658
     */
659
    public function testInitIdnIntlException()
660
    {
661
        if (!function_exists('runkit_function_remove') || !ini_get('runkit.internal_override')) {
662
            $this->markTestSkipped('runkit extension required. runkit.internal_override should be set to "On".');
663
            return;
664
        }
665
666
        runkit_function_remove('idn_to_ascii');
667
        new DomainValidator(['enableIDN' => true]);
668
    }
669
670
    /**
671
     * Add column to array.
672
     * @param array $array
673
     * @param mixed $value
674
     * @return array
675
     */
676
    protected static function arrayAddColumn($array, $value)
677
    {
678
        return array_map(
679
            function ($data) use ($value) {
680
                $data[] = $value;
681
                return $data;
682
            },
683
            $array
684
        );
685
    }
686
}
687