Completed
Push — master ( 9c45fe...2e51e7 )
by
unknown
29:13 queued 13:18
created

FieldTypeTest::getSettingsSchemaExpectation()

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
nc 1
dl 0
loc 1
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
5
 * @license For full copyright and license information view LICENSE file distributed with this source code.
6
 */
7
namespace eZ\Publish\SPI\FieldType\Tests;
8
9
use PHPUnit\Framework\TestCase;
10
use Exception;
11
use eZ\Publish\API\Repository\Values\ContentType\FieldDefinition as APIFieldDefinition;
12
use eZ\Publish\SPI\FieldType\Value as SPIValue;
13
use eZ\Publish\SPI\FieldType\ValidationError;
14
use eZ\Publish\SPI\FieldType\FieldType;
15
16
abstract class FieldTypeTest extends TestCase
17
{
18
    /**
19
     * Generic cache for the getFieldTypeUnderTest() method.
20
     *
21
     * @var \eZ\Publish\SPI\FieldType\FieldType
22
     */
23
    private $fieldTypeUnderTest;
24
25
    /**
26
     * Returns the identifier of the field type under test.
27
     *
28
     * @return string
29
     */
30
    abstract protected function provideFieldTypeIdentifier();
31
32
    /**
33
     * Returns the field type under test.
34
     *
35
     * This method is used by all test cases to retrieve the field type under
36
     * test. Just create the FieldType instance using mocks from the provided
37
     * get*Mock() methods and/or custom get*Mock() implementations. You MUST
38
     * NOT take care for test case wide caching of the field type, just return
39
     * a new instance from this method!
40
     *
41
     * @return FieldType
42
     */
43
    abstract protected function createFieldTypeUnderTest();
44
45
    /**
46
     * Returns the validator configuration schema expected from the field type.
47
     *
48
     * @return array
49
     */
50
    abstract protected function getValidatorConfigurationSchemaExpectation();
51
52
    /**
53
     * Returns the settings schema expected from the field type.
54
     *
55
     * @return array
56
     */
57
    abstract protected function getSettingsSchemaExpectation();
58
59
    /**
60
     * Returns the empty value expected from the field type.
61
     *
62
     * @return mixed
63
     */
64
    abstract protected function getEmptyValueExpectation();
65
66
    /**
67
     * Data provider for invalid input to acceptValue().
68
     *
69
     * Returns an array of data provider sets with 2 arguments: 1. The invalid
70
     * input to acceptValue(), 2. The expected exception type as a string. For
71
     * example:
72
     *
73
     * <code>
74
     *  return array(
75
     *      array(
76
     *          new \stdClass(),
77
     *          'eZ\\Publish\\Core\\Base\\Exceptions\\InvalidArgumentException',
78
     *      ),
79
     *      array(
80
     *          array(),
81
     *          'eZ\\Publish\\Core\\Base\\Exceptions\\InvalidArgumentException',
82
     *      ),
83
     *      // ...
84
     *  );
85
     * </code>
86
     *
87
     * @return array
88
     */
89
    abstract public function provideInvalidInputForAcceptValue();
90
91
    /**
92
     * Data provider for valid input to acceptValue().
93
     *
94
     * Returns an array of data provider sets with 2 arguments: 1. The valid
95
     * input to acceptValue(), 2. The expected return value from acceptValue().
96
     * For example:
97
     *
98
     * <code>
99
     *  return array(
100
     *      array(
101
     *          null,
102
     *          null
103
     *      ),
104
     *      array(
105
     *          __FILE__,
106
     *          new BinaryFileValue( array(
107
     *              'path' => __FILE__,
108
     *              'fileName' => basename( __FILE__ ),
109
     *              'fileSize' => filesize( __FILE__ ),
110
     *              'downloadCount' => 0,
111
     *              'mimeType' => 'text/plain',
112
     *          ) )
113
     *      ),
114
     *      // ...
115
     *  );
116
     * </code>
117
     *
118
     * @return array
119
     */
120
    abstract public function provideValidInputForAcceptValue();
121
122
    /**
123
     * Provide input for the toHash() method.
124
     *
125
     * Returns an array of data provider sets with 2 arguments: 1. The valid
126
     * input to toHash(), 2. The expected return value from toHash().
127
     * For example:
128
     *
129
     * <code>
130
     *  return array(
131
     *      array(
132
     *          null,
133
     *          null
134
     *      ),
135
     *      array(
136
     *          new BinaryFileValue( array(
137
     *              'path' => 'some/file/here',
138
     *              'fileName' => 'sindelfingen.jpg',
139
     *              'fileSize' => 2342,
140
     *              'downloadCount' => 0,
141
     *              'mimeType' => 'image/jpeg',
142
     *          ) ),
143
     *          array(
144
     *              'path' => 'some/file/here',
145
     *              'fileName' => 'sindelfingen.jpg',
146
     *              'fileSize' => 2342,
147
     *              'downloadCount' => 0,
148
     *              'mimeType' => 'image/jpeg',
149
     *          )
150
     *      ),
151
     *      // ...
152
     *  );
153
     * </code>
154
     *
155
     * @return array
156
     */
157
    abstract public function provideInputForToHash();
158
159
    /**
160
     * Provide input to fromHash() method.
161
     *
162
     * Returns an array of data provider sets with 2 arguments: 1. The valid
163
     * input to fromHash(), 2. The expected return value from fromHash().
164
     * For example:
165
     *
166
     * <code>
167
     *  return array(
168
     *      array(
169
     *          null,
170
     *          null
171
     *      ),
172
     *      array(
173
     *          array(
174
     *              'path' => 'some/file/here',
175
     *              'fileName' => 'sindelfingen.jpg',
176
     *              'fileSize' => 2342,
177
     *              'downloadCount' => 0,
178
     *              'mimeType' => 'image/jpeg',
179
     *          ),
180
     *          new BinaryFileValue( array(
181
     *              'path' => 'some/file/here',
182
     *              'fileName' => 'sindelfingen.jpg',
183
     *              'fileSize' => 2342,
184
     *              'downloadCount' => 0,
185
     *              'mimeType' => 'image/jpeg',
186
     *          ) )
187
     *      ),
188
     *      // ...
189
     *  );
190
     * </code>
191
     *
192
     * @return array
193
     */
194
    abstract public function provideInputForFromHash();
195
196
    /**
197
     * Provides data for the getName() test.
198
     *
199
     * @return array
200
     */
201
    abstract public function provideDataForGetName(): array;
202
203
    /**
204
     * Provide data sets with field settings which are considered valid by the
205
     * {@link validateFieldSettings()} method.
206
     *
207
     * ATTENTION: This is a default implementation, which must be overwritten
208
     * if a FieldType supports field settings!
209
     *
210
     * Returns an array of data provider sets with a single argument: A valid
211
     * set of field settings.
212
     * For example:
213
     *
214
     * <code>
215
     *  return array(
216
     *      array(
217
     *          array(),
218
     *      ),
219
     *      array(
220
     *          array( 'rows' => 2 )
221
     *      ),
222
     *      // ...
223
     *  );
224
     * </code>
225
     *
226
     * @return array
227
     */
228
    public function provideValidFieldSettings()
229
    {
230
        return [
231
            [
232
                [],
233
            ],
234
        ];
235
    }
236
237
    /**
238
     * Provide data sets with field settings which are considered invalid by the
239
     * {@link validateFieldSettings()} method. The method must return a
240
     * non-empty array of validation error when receiving such field settings.
241
     *
242
     * ATTENTION: This is a default implementation, which must be overwritten
243
     * if a FieldType supports field settings!
244
     *
245
     * Returns an array of data provider sets with a single argument: A valid
246
     * set of field settings.
247
     * For example:
248
     *
249
     * <code>
250
     *  return array(
251
     *      array(
252
     *          true,
253
     *      ),
254
     *      array(
255
     *          array( 'nonExistentKey' => 2 )
256
     *      ),
257
     *      // ...
258
     *  );
259
     * </code>
260
     *
261
     * @return array
262
     */
263
    public function provideInValidFieldSettings()
264
    {
265
        return [
266
            [
267
                ['nonempty'],
268
            ],
269
        ];
270
    }
271
272
    /**
273
     * Provide data sets with validator configurations which are considered
274
     * valid by the {@link validateValidatorConfiguration()} method.
275
     *
276
     * ATTENTION: This is a default implementation, which must be overwritten
277
     * if a FieldType supports validators!
278
     *
279
     * Returns an array of data provider sets with a single argument: A valid
280
     * set of validator configurations.
281
     *
282
     * For example:
283
     *
284
     * <code>
285
     *  return array(
286
     *      array(
287
     *          array(),
288
     *      ),
289
     *      array(
290
     *          array(
291
     *              'IntegerValueValidator' => array(
292
     *                  'minIntegerValue' => 0,
293
     *                  'maxIntegerValue' => 23,
294
     *              )
295
     *          )
296
     *      ),
297
     *      // ...
298
     *  );
299
     * </code>
300
     *
301
     * @return array
302
     */
303
    public function provideValidValidatorConfiguration()
304
    {
305
        return [
306
            [
307
                [],
308
            ],
309
        ];
310
    }
311
312
    /**
313
     * Provide data sets with validator configurations which are considered
314
     * invalid by the {@link validateValidatorConfiguration()} method. The
315
     * method must return a non-empty array of valiation errors when receiving
316
     * one of the provided values.
317
     *
318
     * ATTENTION: This is a default implementation, which must be overwritten
319
     * if a FieldType supports validators!
320
     *
321
     * Returns an array of data provider sets with a single argument: A valid
322
     * set of validator configurations.
323
     *
324
     * For example:
325
     *
326
     * <code>
327
     *  return array(
328
     *      array(
329
     *          array(
330
     *              'NonExistentValidator' => array(),
331
     *          ),
332
     *      ),
333
     *      array(
334
     *          array(
335
     *              // Typos
336
     *              'InTEgervALUeVALIdator' => array(
337
     *                  'minIntegerValue' => 0,
338
     *                  'maxIntegerValue' => 23,
339
     *              )
340
     *          )
341
     *      ),
342
     *      array(
343
     *          array(
344
     *              'IntegerValueValidator' => array(
345
     *                  // Incorrect value types
346
     *                  'minIntegerValue' => true,
347
     *                  'maxIntegerValue' => false,
348
     *              )
349
     *          )
350
     *      ),
351
     *      // ...
352
     *  );
353
     * </code>
354
     *
355
     * @return array
356
     */
357
    public function provideInvalidValidatorConfiguration()
358
    {
359
        return [
360
            [
361
                [
362
                    'NonExistentValidator' => [],
363
                ],
364
            ],
365
        ];
366
    }
367
368
    /**
369
     * Provides data sets with validator configuration and/or field settings and
370
     * field value which are considered valid by the {@link validate()} method.
371
     *
372
     * ATTENTION: This is a default implementation, which must be overwritten if
373
     * a FieldType supports validation!
374
     *
375
     * For example:
376
     *
377
     * <code>
378
     *  return array(
379
     *      array(
380
     *          array(
381
     *              "validatorConfiguration" => array(
382
     *                  "StringLengthValidator" => array(
383
     *                      "minStringLength" => 2,
384
     *                      "maxStringLength" => 10,
385
     *                  ),
386
     *              ),
387
     *          ),
388
     *          new TextLineValue( "lalalala" ),
389
     *      ),
390
     *      array(
391
     *          array(
392
     *              "fieldSettings" => array(
393
     *                  'isMultiple' => true
394
     *              ),
395
     *          ),
396
     *          new CountryValue(
397
     *              array(
398
     *                  "BE" => array(
399
     *                      "Name" => "Belgium",
400
     *                      "Alpha2" => "BE",
401
     *                      "Alpha3" => "BEL",
402
     *                      "IDC" => 32,
403
     *                  ),
404
     *              ),
405
     *          ),
406
     *      ),
407
     *      // ...
408
     *  );
409
     * </code>
410
     *
411
     * @return array
412
     */
413
    public function provideValidDataForValidate()
414
    {
415
        return [
416
            [
417
                [],
418
                $this->createMock(SPIValue::class),
419
            ],
420
        ];
421
    }
422
423
    /**
424
     * Provides data sets with validator configuration and/or field settings,
425
     * field value and corresponding validation errors returned by
426
     * the {@link validate()} method.
427
     *
428
     * ATTENTION: This is a default implementation, which must be overwritten
429
     * if a FieldType supports validation!
430
     *
431
     * For example:
432
     *
433
     * <code>
434
     *  return array(
435
     *      array(
436
     *          array(
437
     *              "validatorConfiguration" => array(
438
     *                  "IntegerValueValidator" => array(
439
     *                      "minIntegerValue" => 5,
440
     *                      "maxIntegerValue" => 10
441
     *                  ),
442
     *              ),
443
     *          ),
444
     *          new IntegerValue( 3 ),
445
     *          array(
446
     *              new ValidationError(
447
     *                  "The value can not be lower than %size%.",
448
     *                  null,
449
     *                  array(
450
     *                      "%size%" => 5
451
     *                  ),
452
     *              ),
453
     *          ),
454
     *      ),
455
     *      array(
456
     *          array(
457
     *              "fieldSettings" => array(
458
     *                  "isMultiple" => false
459
     *              ),
460
     *          ),
461
     *          new CountryValue(
462
     *              "BE" => array(
463
     *                  "Name" => "Belgium",
464
     *                  "Alpha2" => "BE",
465
     *                  "Alpha3" => "BEL",
466
     *                  "IDC" => 32,
467
     *              ),
468
     *              "FR" => array(
469
     *                  "Name" => "France",
470
     *                  "Alpha2" => "FR",
471
     *                  "Alpha3" => "FRA",
472
     *                  "IDC" => 33,
473
     *              ),
474
     *          )
475
     *      ),
476
     *      array(
477
     *          new ValidationError(
478
     *              "Field definition does not allow multiple countries to be selected."
479
     *          ),
480
     *      ),
481
     *      // ...
482
     *  );
483
     * </code>
484
     *
485
     * @return array
486
     */
487
    public function provideInvalidDataForValidate()
488
    {
489
        return [
490
            [
491
                [],
492
                $this->createMock(SPIValue::class),
493
                [],
494
            ],
495
        ];
496
    }
497
498
    /**
499
     * Retrieves a test wide cached version of the field type under test.
500
     *
501
     * Uses {@link createFieldTypeUnderTest()} to create the instance
502
     * initially.
503
     *
504
     * @return \eZ\Publish\SPI\FieldType\FieldType
505
     */
506
    protected function getFieldTypeUnderTest()
507
    {
508
        if (!isset($this->fieldTypeUnderTest)) {
509
            $this->fieldTypeUnderTest = $this->createFieldTypeUnderTest();
510
        }
511
512
        return $this->fieldTypeUnderTest;
513
    }
514
515
    public function testGetFieldTypeIdentifier()
516
    {
517
        self::assertSame(
518
            $this->provideFieldTypeIdentifier(),
519
            $this->getFieldTypeUnderTest()->getFieldTypeIdentifier()
520
        );
521
    }
522
523
    /**
524
     * @dataProvider provideDataForGetName
525
     */
526 View Code Duplication
    public function testGetName(SPIValue $value, array $fieldSettings = [], string $languageCode = 'en_GB', string $expected)
527
    {
528
        $fieldDefinitionMock = $this->getFieldDefinitionMock($fieldSettings);
529
530
        self::assertSame(
531
            $expected,
532
            $this->getFieldTypeUnderTest()->getName($value, $fieldDefinitionMock, $languageCode)
0 ignored issues
show
Bug introduced by
It seems like $fieldDefinitionMock defined by $this->getFieldDefinitionMock($fieldSettings) on line 528 can also be of type object<PHPUnit\Framework\MockObject\MockObject>; however, eZ\Publish\SPI\FieldType\FieldType::getName() does only seem to accept object<eZ\Publish\API\Re...ntType\FieldDefinition>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
533
        );
534
    }
535
536
    public function testValidatorConfigurationSchema()
537
    {
538
        $fieldType = $this->getFieldTypeUnderTest();
539
540
        self::assertSame(
541
            $this->getValidatorConfigurationSchemaExpectation(),
542
            $fieldType->getValidatorConfigurationSchema(),
543
            'Validator configuration schema not returned correctly.'
544
        );
545
    }
546
547
    public function testSettingsSchema()
548
    {
549
        $fieldType = $this->getFieldTypeUnderTest();
550
551
        self::assertSame(
552
            $this->getSettingsSchemaExpectation(),
553
            $fieldType->getSettingsSchema(),
554
            'Settings schema not returned correctly.'
555
        );
556
    }
557
558
    public function testEmptyValue()
559
    {
560
        $fieldType = $this->getFieldTypeUnderTest();
561
562
        $this->assertEquals(
563
            $this->getEmptyValueExpectation(),
564
            $fieldType->getEmptyValue()
565
        );
566
    }
567
568
    /**
569
     * @param mixed $inputValue
570
     * @param mixed $expectedOutputValue
571
     *
572
     * @dataProvider provideValidInputForAcceptValue
573
     */
574
    public function testAcceptValue($inputValue, $expectedOutputValue)
575
    {
576
        $fieldType = $this->getFieldTypeUnderTest();
577
578
        $outputValue = $fieldType->acceptValue($inputValue);
579
580
        $this->assertEquals(
581
            $expectedOutputValue,
582
            $outputValue,
583
            'acceptValue() did not convert properly.'
584
        );
585
    }
586
587
    /**
588
     * Tests that default empty value is unchanged by acceptValue() method.
589
     */
590
    public function testAcceptGetEmptyValue()
591
    {
592
        $fieldType = $this->getFieldTypeUnderTest();
593
        $emptyValue = $fieldType->getEmptyValue();
594
595
        $acceptedEmptyValue = $fieldType->acceptValue($emptyValue);
596
597
        $this->assertEquals(
598
            $emptyValue,
599
            $acceptedEmptyValue,
600
            'acceptValue() did not convert properly.'
601
        );
602
    }
603
604
    /**
605
     * @param mixed $inputValue
606
     * @param \Exception $expectedException
607
     *
608
     * @dataProvider provideInvalidInputForAcceptValue
609
     */
610
    public function testAcceptValueFailsOnInvalidValues($inputValue, $expectedException)
611
    {
612
        $fieldType = $this->getFieldTypeUnderTest();
613
614
        try {
615
            $fieldType->acceptValue($inputValue);
616
            $this->fail(
617
                sprintf(
618
                    'Expected exception of type "%s" not thrown on incorrect input to acceptValue().',
619
                    $expectedException
620
                )
621
            );
622
        } catch (Exception $e) {
623
            if ($e instanceof \PHPUnit_Framework_Exception
0 ignored issues
show
Bug introduced by
The class PHPUnit_Framework_Exception does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
624
                 || $e instanceof \PHPUnit_Framework_Error
0 ignored issues
show
Bug introduced by
The class PHPUnit_Framework_Error does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
625
                 || $e instanceof \PHPUnit_Framework_AssertionFailedError) {
0 ignored issues
show
Bug introduced by
The class PHPUnit_Framework_AssertionFailedError does not exist. Did you forget a USE statement, or did you not list all dependencies?

This error could be the result of:

1. Missing dependencies

PHP Analyzer uses your composer.json file (if available) to determine the dependencies of your project and to determine all the available classes and functions. It expects the composer.json to be in the root folder of your repository.

Are you sure this class is defined by one of your dependencies, or did you maybe not list a dependency in either the require or require-dev section?

2. Missing use statement

PHP does not complain about undefined classes in ìnstanceof checks. For example, the following PHP code will work perfectly fine:

if ($x instanceof DoesNotExist) {
    // Do something.
}

If you have not tested against this specific condition, such errors might go unnoticed.

Loading history...
626
                throw $e;
627
            }
628
629
            $this->assertInstanceOf(
630
                $expectedException,
631
                $e
632
            );
633
        }
634
    }
635
636
    /**
637
     * @param mixed $inputValue
638
     * @param array $expectedResult
639
     *
640
     * @dataProvider provideInputForToHash
641
     */
642 View Code Duplication
    public function testToHash($inputValue, $expectedResult)
643
    {
644
        $fieldType = $this->getFieldTypeUnderTest();
645
646
        $actualResult = $fieldType->toHash($inputValue);
647
648
        $this->assertIsValidHashValue($actualResult);
649
650
        if (is_object($expectedResult) || is_array($expectedResult)) {
651
            $this->assertEquals(
652
                $expectedResult,
653
                $actualResult,
654
                'toHash() method did not create expected result.'
655
            );
656
        } else {
657
            $this->assertSame(
658
                $expectedResult,
659
                $actualResult,
660
                'toHash() method did not create expected result.'
661
            );
662
        }
663
    }
664
665
    /**
666
     * @param mixed $inputValue
0 ignored issues
show
Bug introduced by
There is no parameter named $inputValue. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
667
     * @param array $expectedResult
668
     *
669
     * @dataProvider provideInputForFromHash
670
     */
671 View Code Duplication
    public function testFromHash($inputHash, $expectedResult)
672
    {
673
        $this->assertIsValidHashValue($inputHash);
674
675
        $fieldType = $this->getFieldTypeUnderTest();
676
677
        $actualResult = $fieldType->fromHash($inputHash);
678
679
        if (is_object($expectedResult) || is_array($expectedResult)) {
680
            $this->assertEquals(
681
                $expectedResult,
682
                $actualResult,
683
                'fromHash() method did not create expected result.'
684
            );
685
        } else {
686
            $this->assertSame(
687
                $expectedResult,
688
                $actualResult,
689
                'fromHash() method did not create expected result.'
690
            );
691
        }
692
    }
693
694
    public function testEmptyValueIsEmpty()
695
    {
696
        $fieldType = $this->getFieldTypeUnderTest();
697
698
        $this->assertTrue(
699
            $fieldType->isEmptyValue($fieldType->getEmptyValue())
700
        );
701
    }
702
703
    /**
704
     * @param mixed $inputSettings
705
     *
706
     * @dataProvider provideValidFieldSettings
707
     */
708
    public function testValidateFieldSettingsValid($inputSettings)
709
    {
710
        $fieldType = $this->getFieldTypeUnderTest();
711
712
        $validationResult = $fieldType->validateFieldSettings($inputSettings);
713
714
        $this->assertIsArray($validationResult,
715
            'The method validateFieldSettings() must return an array.'
716
        );
717
        $this->assertEquals(
718
            [],
719
            $validationResult,
720
            'validateFieldSettings() did not consider the input settings valid.'
721
        );
722
    }
723
724
    /**
725
     * @param mixed $inputSettings
726
     *
727
     * @dataProvider provideInvalidFieldSettings
728
     */
729 View Code Duplication
    public function testValidateFieldSettingsInvalid($inputSettings)
730
    {
731
        $fieldType = $this->getFieldTypeUnderTest();
732
733
        $validationResult = $fieldType->validateFieldSettings($inputSettings);
734
735
        $this->assertIsArray($validationResult,
736
            'The method validateFieldSettings() must return an array.'
737
        );
738
739
        $this->assertNotEquals(
740
            [],
741
            $validationResult,
742
            'validateFieldSettings() did consider the input settings valid, which should be invalid.'
743
        );
744
745
        foreach ($validationResult as $actualResultElement) {
746
            $this->assertInstanceOf(
747
                ValidationError::class,
748
                $actualResultElement,
749
                'Validation result of incorrect type.'
750
            );
751
        }
752
    }
753
754
    /**
755
     * @param mixed $inputConfiguration
756
     *
757
     * @dataProvider provideValidValidatorConfiguration
758
     */
759
    public function testValidateValidatorConfigurationValid($inputConfiguration)
760
    {
761
        $fieldType = $this->getFieldTypeUnderTest();
762
763
        $validationResult = $fieldType->validateValidatorConfiguration($inputConfiguration);
764
765
        $this->assertIsArray($validationResult,
766
            'The method validateValidatorConfiguration() must return an array.'
767
        );
768
        $this->assertEquals(
769
            [],
770
            $validationResult,
771
            'validateValidatorConfiguration() did not consider the input configuration valid.'
772
        );
773
    }
774
775
    /**
776
     * @param mixed $inputConfiguration
777
     *
778
     * @dataProvider provideInvalidValidatorConfiguration
779
     */
780 View Code Duplication
    public function testValidateValidatorConfigurationInvalid($inputConfiguration)
781
    {
782
        $fieldType = $this->getFieldTypeUnderTest();
783
784
        $validationResult = $fieldType->validateValidatorConfiguration($inputConfiguration);
785
786
        $this->assertIsArray($validationResult,
787
            'The method validateValidatorConfiguration() must return an array.'
788
        );
789
790
        $this->assertNotEquals(
791
            [],
792
            $validationResult,
793
            'validateValidatorConfiguration() did consider the input settings valid, which should be invalid.'
794
        );
795
796
        foreach ($validationResult as $actualResultElement) {
797
            $this->assertInstanceOf(
798
                ValidationError::class,
799
                $actualResultElement,
800
                'Validation result of incorrect type.'
801
            );
802
        }
803
    }
804
805
    /**
806
     * @param mixed $inputConfiguration
0 ignored issues
show
Bug introduced by
There is no parameter named $inputConfiguration. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
807
     *
808
     * @dataProvider provideValidFieldSettings
809
     */
810
    public function testFieldSettingsToHash($inputSettings)
811
    {
812
        $fieldType = $this->getFieldTypeUnderTest();
813
814
        $hash = $fieldType->fieldSettingsToHash($inputSettings);
815
816
        $this->assertIsValidHashValue($hash);
817
    }
818
819
    /**
820
     * @param mixed $inputConfiguration
821
     *
822
     * @dataProvider provideValidValidatorConfiguration
823
     */
824
    public function testValidatorConfigurationToHash($inputConfiguration)
825
    {
826
        $fieldType = $this->getFieldTypeUnderTest();
827
828
        $hash = $fieldType->validatorConfigurationToHash($inputConfiguration);
829
830
        $this->assertIsValidHashValue($hash);
831
    }
832
833
    /**
834
     * @param mixed $inputConfiguration
0 ignored issues
show
Bug introduced by
There is no parameter named $inputConfiguration. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
835
     *
836
     * @dataProvider provideValidFieldSettings
837
     */
838
    public function testFieldSettingsFromHash($inputSettings)
839
    {
840
        $fieldType = $this->getFieldTypeUnderTest();
841
842
        $hash = $fieldType->fieldSettingsToHash($inputSettings);
843
        $restoredSettings = $fieldType->fieldSettingsFromHash($hash);
844
845
        $this->assertEquals($inputSettings, $restoredSettings);
846
    }
847
848
    /**
849
     * @param mixed $inputConfiguration
850
     *
851
     * @dataProvider provideValidValidatorConfiguration
852
     */
853
    public function testValidatorConfigurationFromHash($inputConfiguration)
854
    {
855
        $fieldType = $this->getFieldTypeUnderTest();
856
857
        $hash = $fieldType->validatorConfigurationToHash($inputConfiguration);
858
        $restoredConfiguration = $fieldType->validatorConfigurationFromHash($hash);
859
860
        $this->assertEquals($inputConfiguration, $restoredConfiguration);
861
    }
862
863
    /**
864
     * Asserts that the given $actualHash complies to the rules for hashes.
865
     *
866
     * @param mixed $actualHash
867
     * @param array $keyChain
868
     */
869
    protected function assertIsValidHashValue($actualHash, $keyChain = [])
870
    {
871
        switch ($actualHashType = gettype($actualHash)) {
872
            case 'boolean':
873
            case 'integer':
874
            case 'double':
875
            case 'string':
876
            case 'NULL':
877
                // All valid, just return
878
                return;
879
880
            case 'array':
881
                foreach ($actualHash as $key => $childHash) {
882
                    $this->assertIsValidHashValue(
883
                        $childHash,
884
                        array_merge($keyChain, [$key])
885
                    );
886
                }
887
888
                return;
889
890
            case 'resource':
891
            case 'object':
892
                $this->fail(
893
                    sprintf(
894
                        'Value for $hash[%s] is of invalid type "%s".',
895
                        implode('][', $keyChain),
896
                        $actualHashType
897
                    )
898
                );
899
        }
900
    }
901
902
    /**
903
     * @dataProvider provideValidDataForValidate
904
     */
905
    public function testValidateValid($fieldDefinitionData, $value)
906
    {
907
        $validationErrors = $this->doValidate($fieldDefinitionData, $value);
908
909
        $this->assertIsArray($validationErrors);
910
        $this->assertEmpty($validationErrors, "Got value:\n" . var_export($validationErrors, true));
911
    }
912
913
    /**
914
     * @dataProvider provideInvalidDataForValidate
915
     */
916
    public function testValidateInvalid($fieldDefinitionData, $value, $errors)
917
    {
918
        $validationErrors = $this->doValidate($fieldDefinitionData, $value);
919
920
        $this->assertIsArray($validationErrors);
921
        $this->assertEquals($errors, $validationErrors);
922
    }
923
924
    protected function doValidate($fieldDefinitionData, $value)
925
    {
926
        $fieldType = $this->getFieldTypeUnderTest();
927
928
        /** @var \eZ\Publish\API\Repository\Values\ContentType\FieldDefinition|\PHPUnit\Framework\MockObject\MockObject $fieldDefinitionMock */
929
        $fieldDefinitionMock = $this->createMock(APIFieldDefinition::class);
930
931
        foreach ($fieldDefinitionData as $method => $data) {
932
            if ($method === 'validatorConfiguration') {
933
                $fieldDefinitionMock
934
                    ->expects($this->any())
935
                    ->method('getValidatorConfiguration')
936
                    ->will($this->returnValue($data));
937
            }
938
939
            if ($method === 'fieldSettings') {
940
                $fieldDefinitionMock
941
                    ->expects($this->any())
942
                    ->method('getFieldSettings')
943
                    ->will($this->returnValue($data));
944
            }
945
        }
946
947
        $validationErrors = $fieldType->validate($fieldDefinitionMock, $value);
0 ignored issues
show
Bug introduced by
It seems like $fieldDefinitionMock defined by $this->createMock(\eZ\Pu...FieldDefinition::class) on line 929 can also be of type object<PHPUnit\Framework\MockObject\MockObject>; however, eZ\Publish\SPI\FieldType\FieldType::validate() does only seem to accept object<eZ\Publish\API\Re...ntType\FieldDefinition>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
948
949
        return $validationErrors;
950
    }
951
952
    /**
953
     * @return \eZ\Publish\API\Repository\Values\ContentType\FieldDefinition|\PHPUnit\Framework\MockObject\MockObject
954
     */
955
    protected function getFieldDefinitionMock(array $fieldSettings)
956
    {
957
        /** @var |\PHPUnit\Framework\MockObject\MockObject $fieldDefinitionMock */
0 ignored issues
show
Documentation introduced by
The doc-type |\PHPUnit\Framework\MockObject\MockObject could not be parsed: Unknown type name "|" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
958
        $fieldDefinitionMock = $this->createMock(APIFieldDefinition::class);
959
        $fieldDefinitionMock
0 ignored issues
show
Bug introduced by
The method method() does not seem to exist on object<PHPUnit\Framework\MockObject\MockObject>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
960
            ->method('getFieldSettings')
961
            ->willReturn($fieldSettings);
962
963
        return $fieldDefinitionMock;
964
    }
965
966
    // @todo: More test methods …
967
}
968