Issues (36)

tests/Helpers/IComparerTester.php (2 issues)

1
<?php
2
3
/**
4
 * PHP: Nelson Martell Library file
5
 *
6
 * Copyright © 2016-2021 Nelson Martell (http://nelson6e65.github.io)
7
 *
8
 * Licensed under The MIT License (MIT)
9
 * For full copyright and license information, please see the LICENSE
10
 * Redistributions of files must retain the above copyright notice.
11
 *
12
 * @copyright 2016-2021 Nelson Martell
13
 * @link      http://nelson6e65.github.io/php_nml/
14
 * @since     0.6.0
15
 * @license   http://www.opensource.org/licenses/mit-license.php The MIT License (MIT)
16
 * */
17
18
declare(strict_types=1);
19
20
namespace NelsonMartell\Test\Helpers;
21
22
use ReflectionClass;
23
use NelsonMartell\Extensions\Text;
24
use NelsonMartell\IComparer;
25
use PHPUnit\Framework\TestCase;
26
27
/**
28
 * Test helper for classes implementing ``NelsonMartell\IComparable`` interface.
29
 *
30
 * Note: Classes using this trait MUST use ConstructorMethodTester and ExporterPlugin traits too.
31
 *
32
 * @author Nelson Martell <[email protected]>
33
 * @since  0.6.0
34
 * */
35
trait IComparerTester
36
{
37
    /**
38
     * @return string
39
     *
40
     * @see ConstructorMethodTester
41
     */
42
    abstract public function getTargetClassName(): string;
43
44
    /**
45
     * @param mixed $obj
46
     * @param int   $depth
47
     * @param bool  $short
48
     *
49
     * @return string
50
     *
51
     * @see ExporterPlugin
52
     */
53
    abstract public static function export($obj, int $depth = 2, bool $short = false): string;
54
55
    /**
56
     * Datasets for ``testCompareMethod(integer|null $expected, mixed $left, mixed $right)``.
57
     *
58
     * @return array
59
     */
60
    abstract public function compareMethodArgumentsProvider(): array;
61
62
    /**
63
     * Datasets for ``testCanUseCompareMethodInArraySorting(integer|null $expected, mixed $left, mixed $right)``.
64
     *
65
     * Must provide an array of sorted items.
66
     *
67
     * @return array
68
     */
69
    abstract public function compareMethodArraysProvider(): array;
70
71
72
    /**
73
     * @testdox Can compare relative position of objects of different type
74
     * @dataProvider compareMethodArgumentsProvider
75
     *
76
     * @param int|null $expected
77
     * @param mixed $left
78
     * @param mixed $right
79
     */
80
    public function testCompareMethod($expected, $left, $right): void
81
    {
82
        $class  = $this->getTargetClassName();
83
        $actual = $class::compare($left, $right);
84
85
        $message = Text::format(
86
            '{class}::{method}({left}, {right}); // Returned: {actual}',
87
            [
88
                'class'  => $class,
89
                'method' => 'compare',
90
                'left'   => static::export($left),
91
                'right'  => static::export($right),
92
                'actual' => static::export($actual),
93
            ]
94
        );
95
96
        /** @var TestCase $this */
97
        if ($expected === 0) {
98
            $this->assertIsInt($actual, $message);
99
            $this->assertEquals(0, $actual, $message);
100
        } else {
101
            if ($expected === null) {
102
                $this->assertNull($actual, $message);
103
            } else {
104
                $major = $minor = 0;
105
106
                if ($expected < 0) {
107
                    $minor = $actual;
108
                } else {
109
                    $major = $actual;
110
                }
111
112
                $this->assertIsInt($actual, $message);
113
                $this->assertGreaterThan($minor, $major, $message);
114
                $this->assertLessThan($major, $minor, $message);
115
            }
116
        }
117
    }
118
119
120
    /**
121
     * @testdox Provides comparison function to array sorting
122
     * @dataProvider compareMethodArraysProvider
123
     *
124
     * @param array $expected
125
     */
126
    public function testCanUseCompareMethodInArraySorting(array $expected): void
127
    {
128
        $actual = $expected;
129
130
        @shuffle($actual);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for shuffle(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

130
        /** @scrutinizer ignore-unhandled */ @shuffle($actual);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
131
132
        $message = Text::format(
133
            'usort({actual}, [{class}, {method}]);',
134
            [
135
                'class'  => $this->getTargetClassName(),
136
                'method' => 'compare',
137
                'actual' => static::export($actual),
138
            ]
139
        );
140
141
        @usort($actual, [$this->getTargetClassName(), 'compare']);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition for usort(). This can introduce security issues, and is generally not recommended. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unhandled  annotation

141
        /** @scrutinizer ignore-unhandled */ @usort($actual, [$this->getTargetClassName(), 'compare']);

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
142
143
        /** @var TestCase $this */
144
        $this->assertEquals($expected, $actual, $message);
145
    }
146
147
    /**
148
     * @testdox Is compliant with ``NelsonMartell\IComparer`` interface
149
     * @depends testCanUseCompareMethodInArraySorting
150
     */
151
    public function testIsCompliantWithIComparerIterface(): void
152
    {
153
        $className = $this->getTargetClassName();
154
155
        $message = Text::format(
156
            '"{0}" do not implements "{1}" interface.',
157
            $className,
158
            IComparer::class
159
        );
160
161
        $reflectionClass = new ReflectionClass($className);
162
163
        /** @var TestCase $this */
164
        $this->assertContains(IComparer::class, $reflectionClass->getInterfaceNames(), $message);
165
    }
166
}
167