Completed
Push — master ( 7700d1...23cd67 )
by Mahmoud
03:21
created

GeneralTestsHelpersTrait::responseToArray()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 12
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 6
nc 4
nop 1
1
<?php
2
3
namespace App\Port\Test\PHPUnit\Traits;
4
5
use App;
6
use Artisan;
7
use Dingo\Api\Http\Response as DingoAPIResponse;
8
use Illuminate\Http\Response;
9
use Illuminate\Http\UploadedFile;
10
use Illuminate\Support\Arr as LaravelArr;
11
use Illuminate\Support\Facades\Config;
12
use Illuminate\Support\Str as LaravelStr;
13
use Mockery;
14
use Symfony\Component\Debug\Exception\UndefinedMethodException;
15
use Vinkla\Hashids\Facades\Hashids;
16
17
/**
18
 * Class GeneralTestsHelpersTrait
19
 *
20
 * General Tests helpers for making HTTP calls, formatting response, Mocking services and more..
21
 *
22
 * @author  Mahmoud Zalt  <[email protected]>
23
 */
24
trait GeneralTestsHelpersTrait
25
{
26
27
    // ---[ HTTP CALLS ]------------------------------------------------------------------------------------------------
28
29
    /**
30
     * @param        $endpoint
31
     * @param string $verb
32
     * @param array  $data
33
     * @param bool   $protected
34
     * @param array  $headers
35
     *
36
     * @return  mixed
37
     * @throws \Symfony\Component\Debug\Exception\UndefinedMethodException
38
     */
39
    public function apiCall($endpoint, $verb = 'get', array $data = [], $protected = true, array $headers = [])
40
    {
41
        // if endpoint is protected (requires token to access it's functionality)
42
        if ($protected && !array_has($headers, 'Authorization')) {
43
            // append the token to the header
44
            $headers['Authorization'] = 'Bearer ' . $this->getLoggedInTestingUserToken();
0 ignored issues
show
Bug introduced by
It seems like getLoggedInTestingUserToken() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
45
        }
46
47
        switch ($verb) {
48
            case 'get':
49
                $endpoint = $data ? $endpoint . '?' . http_build_query($data) : $endpoint;
50
                $response = $this->get($endpoint, $headers)->response;
0 ignored issues
show
Bug introduced by
It seems like get() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
51
                break;
52
            case 'post':
53
            case 'put':
54
            case 'patch':
55
            case 'delete':
56
                $response = $this->{$verb}($endpoint, $data, $headers)->response;
57
                break;
58
            case 'json:post':
59
                $response = $this->json('post', $endpoint, $data, $headers)->response;
0 ignored issues
show
Bug introduced by
It seems like json() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
60
                break;
61
            default:
62
                throw new UndefinedMethodException('Undefined HTTP Verb (' . $verb . ').');
0 ignored issues
show
Bug introduced by
The call to UndefinedMethodException::__construct() misses a required argument $previous.

This check looks for function calls that miss required arguments.

Loading history...
63
        }
64
65
        return $response;
66
    }
67
68
    /**
69
     * Inject the ID in the Endpoint URI
70
     *
71
     * Example: you give it ('users/{id}/stores', 100) it returns 'users/100/stores'
72
     *
73
     * @param        $endpoint
74
     * @param        $id
75
     * @param bool   $skipEncoding
76
     * @param string $replace
77
     *
78
     * @return  mixed
79
     */
80
    public function injectEndpointId($endpoint, $id, $skipEncoding = false, $replace = '{id}')
81
    {
82
        // In case Hash ID is enabled it will encode the ID first
83
        if (Config::get('hello.hash-id')) {
84
85
            if (!$skipEncoding) {
86
                $id = Hashids::encode($id);
87
            }
88
        }
89
90
        return str_replace($replace, $id, $endpoint);
91
    }
92
93
    // ---[ RESPONSE MODIFIERS ]----------------------------------------------------------------------------------------
94
95
    /**
96
     * get response object, get the string content from it and convert it to an std object
97
     * making it easier to read
98
     *
99
     * @param $response
100
     *
101
     * @return  mixed
102
     */
103
    public function getResponseObject(Response $response)
104
    {
105
        return json_decode($response->getContent());
106
    }
107
108
    /**
109
     * @param $response
110
     *
111
     * @return  mixed
112
     */
113
    private function responseToArray($response)
114
    {
115
        if ($response instanceof \Illuminate\Http\Response) {
116
            $response = json_decode($response->getContent(), true);
117
        }
118
119
        if (array_key_exists('data', $response)) {
120
            $response = $response['data'];
121
        }
122
123
        return $response;
124
    }
125
126
    /**
127
     * Format the given key and value into a JSON string for expectation checks.
128
     *
129
     * @param string $key
130
     * @param mixed  $value
131
     *
132
     * @return string
133
     */
134
    private function formatToKeyValueToString($key, $value)
135
    {
136
        $expected = json_encode([$key => $value]);
137
138
        if (LaravelStr::startsWith($expected, '{')) {
139
            $expected = substr($expected, 1);
140
        }
141
142
        if (LaravelStr::endsWith($expected, '}')) {
143
            $expected = substr($expected, 0, -1);
144
        }
145
146
        return $expected;
147
    }
148
149
    // ---[ UPLOADER'S ]------------------------------------------------------------------------------------------------
150
151
    /**
152
     * @param        $fileName
153
     * @param        $stubDirPath
154
     * @param string $mimeType
155
     * @param null   $size
156
     *
157
     * @return  \Illuminate\Http\UploadedFile
158
     */
159
    public function getTestingFile($fileName, $stubDirPath, $mimeType = 'text/plain', $size = null)
160
    {
161
        $file = $stubDirPath . $fileName;
162
163
        return new UploadedFile($file, $fileName, $mimeType, $size, null, true); // null = null | $testMode = true
0 ignored issues
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...
164
    }
165
166
    /**
167
     * @param        $imageName
168
     * @param        $stubDirPath
169
     * @param string $mimeType
170
     * @param null   $size
171
     *
172
     * @return  \Illuminate\Http\UploadedFile
173
     */
174
    public function getTestingImage($imageName, $stubDirPath, $mimeType = 'image/jpeg', $size = null)
175
    {
176
        return $this->getTestingFile($imageName, $stubDirPath, $mimeType, $size);
177
    }
178
179
    // ---[ CUSTOM ASSERTIONS ]-----------------------------------------------------------------------------------------
180
181
    /**
182
     * @param \Dingo\Api\Http\Response $response
183
     * @param array                    $messages
184
     */
185
    public function assertValidationErrorContain(DingoAPIResponse $response, array $messages)
186
    {
187
        $arrayResponse = json_decode($response->getContent());
188
189
        foreach ($messages as $key => $value) {
190
            $this->assertEquals($arrayResponse->errors->{$key}[0], $value);
0 ignored issues
show
Bug introduced by
It seems like assertEquals() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
191
        }
192
    }
193
194
    /**
195
     * @param $keys
196
     * @param $response
197
     */
198
    public function assertResponseContainKeys($keys, $response)
199
    {
200
        if (!is_array($keys)) {
201
            $keys = (array)$keys;
202
        }
203
204
        foreach ($keys as $key) {
205
            $this->assertTrue(array_key_exists($key, $this->responseToArray($response)));
0 ignored issues
show
Bug introduced by
It seems like assertTrue() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
206
        }
207
    }
208
209
    /**
210
     * @param $values
211
     * @param $response
212
     */
213
    public function assertResponseContainValues($values, $response)
214
    {
215
        if (!is_array($values)) {
216
            $values = (array)$values;
217
        }
218
219
        foreach ($values as $value) {
220
            $this->assertTrue(in_array($value, $this->responseToArray($response)));
0 ignored issues
show
Bug introduced by
It seems like assertTrue() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
221
        }
222
    }
223
224
    /**
225
     * @param $data
226
     * @param $response
227
     */
228
    public function assertResponseContainKeyValue($data, $response)
229
    {
230
        $response = json_encode(LaravelArr::sortRecursive(
231
            (array)$this->responseToArray($response)
232
        ));
233
234
        foreach (LaravelArr::sortRecursive($data) as $key => $value) {
235
            $expected = $this->formatToExpectedJson($key, $value);
0 ignored issues
show
Bug introduced by
It seems like formatToExpectedJson() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
236
            $this->assertTrue(LaravelStr::contains($response, $expected),
0 ignored issues
show
Bug introduced by
It seems like assertTrue() must be provided by classes using this trait. How about adding it as abstract method to this trait?

This check looks for methods that are used by a trait but not required by it.

To illustrate, let’s look at the following code example

trait Idable {
    public function equalIds(Idable $other) {
        return $this->getId() === $other->getId();
    }
}

The trait Idable provides a method equalsId that in turn relies on the method getId(). If this method does not exist on a class mixing in this trait, the method will fail.

Adding the getId() as an abstract method to the trait will make sure it is available.

Loading history...
237
                "The JSON fragment [ {$expected} ] does not exist in the response [ {$response} ].");
238
        }
239
    }
240
241
    // ---[ MOCKING ]---------------------------------------------------------------------------------------------------
242
243
    /**
244
     * Mocking helper
245
     *
246
     * @param $class
247
     *
248
     * @return  \Mockery\MockInterface
249
     */
250
    public function mock($class)
251
    {
252
        $mock = Mockery::mock($class);
253
        App::instance($class, $mock);
254
255
        return $mock;
256
    }
257
258
}
259