Failed Conditions
Pull Request — master (#8)
by
unknown
01:56
created

ArrayAssertsTrait::isNumeric()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 5
nc 2
nop 1
1
<?php
2
3
namespace Chadicus;
4
5
/**
6
 * Trait for adding asserts for arrays
7
 */
8
trait ArrayAssertsTrait
9
{
10
    /**
11
     * Asserts the given $actual array is the same as the $expected array disregarding index order
12
     *
13
     * @param array       $expected The expected array.
14
     * @param mixed       $actual   The actual array.
15
     * @param string|null $prefix   Prefix to use with error messages. Useful for nested arrays.
16
     *
17
     * @return void
18
     */
19
    public function assertSameArray(array $expected, $actual, $prefix = null)
20
    {
21
        //assert that the actual value is an array
22
        $this->assertInternalType('array', $actual, '$actual was not an array');
23
24
        $expectedKeys = array_keys($expected);
25
        $actualKeys = array_keys($actual);
26
27
        //find any keys in the expected array that are not present in the actual array
28
        $missingExpectedKeys = array_diff($expectedKeys, $actualKeys);
29
        $this->assertCount(
30
            0,
31
            $missingExpectedKeys,
32
            sprintf(
33
                '$actual array is missing %d keys: %s',
34
                count($missingExpectedKeys),
35
                implode(', ', $missingExpectedKeys)
36
            )
37
        );
38
39
        //find any keys in the actual array that are not expected in the expected array
40
        $unexpectedKeys = array_diff($actualKeys, $expectedKeys);
41
        $this->assertCount(
42
            0,
43
            $unexpectedKeys,
44
            sprintf(
45
                '$actual array contains %d unexpected keys: %s',
46
                count($unexpectedKeys),
47
                implode(', ', $unexpectedKeys)
48
            )
49
        );
50
51
        //Assert all values are the same value and type.
52
        //Recursively call assertSameArray on array values
53
        foreach ($expected as $key => $value) {
54
            //If a sub array is indexed numerically we just want to ensure all the values are present and not their keys.
55
            if (is_array($value) && self::isNumeric($value)) {
56
                $difference = array_diff($value, $actual[$key]);
57
                $this->assertSame(count($difference), 0);
58
                continue;
59
            }
60
61
            if (is_array($value)) {
62
                $this->assertSameArray($value, $actual[$key], "{$prefix}{$key}.");
63
                continue;
64
            }
65
66
            $this->assertSame(
67
                $value,
68
                $actual[$key],
69
                sprintf(
70
                    "{$prefix}{$key} value is not correct expected %s\nfound %s",
71
                    var_export($value, 1),
72
                    var_export($actual[$key], 1)
73
                )
74
            );
75
        }
76
    }
77
78
    /**
79
     * Determines if an array is a numerically indexed array i.e. an array with numeric and sequential keys.
80
     *
81
     * @param array $subject The array to check if indexed.
82
     *
83
     * @return boolean
84
     */
85
    private function isNumeric(array $subject)
86
    {
87
        $nonNumericKeyCount = count(array_filter(array_keys($subject), 'is_string'));
88
        if ($nonNumericKeyCount > 0) {
89
            return false;
90
        }
91
92
        //If the array keys are from 0 to N they are sequential and therefore numerically indexed.
93
        return array_keys($subject) === range(0, count($subject) -1);
94
    }
95
96
    /**
97
     * Asserts the number of elements of an array, Countable or Traversable.
98
     *
99
     * Ensures this method must be provided by classes using this trait.
100
     *
101
     * @param integer $expectedCount The expected number of items in $haystack.
102
     * @param mixed   $haystack      The array, countable or traversable object containing items.
103
     * @param string  $message       Optional error message to give upon failure.
104
     *
105
     * @return void
106
     */
107
    abstract public function assertCount($expectedCount, $haystack, $message = '');
108
109
    /**
110
     * Asserts that a variable is of a given type.
111
     *
112
     * Ensures this method must be provided by classes using this trait.
113
     *
114
     * @param string $expected The expected internal type.
115
     * @param mixed  $actual   The variable to verify.
116
     * @param string $message  Optional error message to give upon failure.
117
     *
118
     * @return void
119
     */
120
    abstract public function assertInternalType($expected, $actual, $message = '');
121
122
    /**
123
     * Asserts that two variables have the same type and value. Used on objects, it asserts that two variables reference
124
     * the same object.
125
     *
126
     * Ensures this method must be provided by classes using this trait.
127
     *
128
     * @param string $expected The expected value.
129
     * @param mixed  $actual   The actual value.
130
     * @param string $message  Optional error message to give upon failure.
131
     *
132
     * @return void
133
     */
134
    abstract public function assertSame($expected, $actual, $message = '');
135
}
136