AbstractResourceCest   A
last analyzed

Complexity

Total Complexity 26

Size/Duplication

Total Lines 359
Duplicated Lines 0 %

Test Coverage

Coverage 88.16%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 85
dl 0
loc 359
ccs 67
cts 76
cp 0.8816
rs 10
c 1
b 0
f 0
wmc 26

16 Methods

Rating   Name   Duplication   Size   Complexity  
A checkSuccessCreateResponse() 0 5 1
A checkResponse() 0 15 4
A authUser() 0 4 2
A internalDelete() 0 10 1
A checkSuccessViewResponse() 0 4 1
A checkSuccessIndexResponse() 0 5 1
A parseUrl() 0 9 2
A internalView() 0 12 1
A internalCreate() 0 16 1
A internalIndex() 0 13 1
A checkErrorResponse() 0 9 2
A internalUpdate() 0 16 2
A checkValidationResponse() 0 17 3
A __construct() 0 9 1
A selfLinkPath() 0 3 1
A checkSelfLink() 0 7 2
1
<?php
2
3
namespace roaresearch\yii2\roa\test;
4
5
use Codeception\{Example, Util\HttpCode, Verify\Verify};
6
use roaresearch\yii2\roa\urlRules\Resource as ResourceUrlRule;
7
use yii\web\UrlManager;
8
9
abstract class AbstractResourceCest
10
{
11
    /**
12
     * @var UrlManager url manager used to parse Route's for the services.
13
     */
14
    protected $urlManager;
15
16
    /**
17
     * Initializes the `$urlManager` object
18
     */
19
    public function __construct()
20
    {
21
        $this->urlManager = new UrlManager([
22
            'enablePrettyUrl' => true,
23
            'showScriptName' => false,
24
            'cache' => false,
25
            'rules' => [
26
                $this->getRoutePattern() . '/<id:\d+>'=> 'test/action',
27
                $this->getRoutePattern() => 'test/action',
28
            ],
29
        ]);
30
    }
31
32
    /**
33
     * Authenticates a user identified by 'authUser' index in the `$example`.
34
     *
35
     * @param Tester $I
36
     * @param Example $example data used for the testing. It uses the keys
37
     * - tokenName: (optional) string name of the token used to authenticate.
38
     */
39 15
    protected function authUser(Tester $I, Example $example)
40
    {
41 15
        if (!empty($example['tokenName'])) {
42
            $I->amAuthByToken($example['tokenName']);
43
        }
44
    }
45
46
    /**
47
     * Parses the Route for the test using `$urlManager` and `getRoutePattern()`
48
     *
49
     * @param Example $example data used for the testing. It uses the keys
50
     * - url: (optional) string if provided it will be used directly.
51
     * - urlParams: (optional) string[] GET params to parse the url rule with
52
     *   `getRoutePattern()`.
53
     * @return string the url which will be used for the service.
54
     */
55 15
    protected function parseUrl(Example $example): string
56
    {
57 15
        if (isset($example['url'])) {
58 6
            return $example['url'];
59
        }
60 10
        $params = $example['urlParams'] ?? [];
61 10
        $params[0] = 'test/action';
62
63 10
        return $this->urlManager->createUrl($params);
64
    }
65
66
    /**
67
     * Handles the internal logic when running a test on a collection resource.
68
     *
69
     * @param Tester $I
70
     * @param Example $example data used for the testing. It uses the keys
71
     * - tokenName: (optional) string name of the token used to authenticate.
72
     * - url: (optional) string if provided it will be used directly.
73
     * - urlParams: (optional) string[] GET params to parse the url rule with
74
     *   `getRoutePattern()`.
75
     * - headers: (optional) string[] pairs of header => value expected in the
76
     *   response.
77
     */
78 2
    protected function internalIndex(Tester $I, Example $example)
79
    {
80
        // Authenticates configured user.
81 2
        $this->authUser($I, $example);
82
83
        // Send request
84 2
        $I->sendGET($this->parseUrl($example));
0 ignored issues
show
Bug introduced by
The method sendGET() does not exist on roaresearch\yii2\roa\test\Tester. ( Ignorable by Annotation )

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

84
        $I->/** @scrutinizer ignore-call */ 
85
            sendGET($this->parseUrl($example));

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...
85
86
        // Checks the response has the required headers and body.
87 2
        $this->checkResponse([
88
            HttpCode::OK => 'checkSuccessIndexResponse',
89
            HttpCode::UNPROCESSABLE_ENTITY => 'checkValidationResponse',
90
        ], $I, $example);
91
    }
92
93
    /**
94
     * Handles the internal logic when running a test on a creating a record.
95
     *
96
     * @param Tester $I
97
     * @param Example $example data used for the testing. It uses the keys
98
     * - tokenName: (optional) string name of the token used to authenticate.
99
     * - url: (optional) string if provided it will be used directly.
100
     * - urlParams: (optional) string[] GET params to parse the url rule with
101
     *   `getRoutePattern()`.
102
     * - data: (optional) POST data sent on the request.
103
     * - headers: (optional) string[] pairs of header => value expected in the
104
     *   response.
105
     */
106 2
    protected function internalCreate(Tester $I, Example $example)
107
    {
108
        // Authenticates configured user.
109 2
        $this->authUser($I, $example);
110
111
        // Send request
112 2
        $I->sendPOST(
0 ignored issues
show
Bug introduced by
The method sendPOST() does not exist on roaresearch\yii2\roa\test\Tester. ( Ignorable by Annotation )

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

112
        $I->/** @scrutinizer ignore-call */ 
113
            sendPOST(

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...
113 2
            $this->parseUrl($example),
114 2
            $example['data'] ?? []
115
        );
116
117
        // Checks the response has the required headers and body.
118 2
        $this->checkResponse([
119
            HttpCode::CREATED => 'checkSuccessCreateResponse',
120
            HttpCode::UNPROCESSABLE_ENTITY => 'checkValidationResponse',
121
        ], $I, $example);
122
    }
123
124
    /**
125
     * Handles the internal logic when running a test on a record resource.
126
     *
127
     * @param Tester $I
128
     * @param Example $example data used for the testing. It uses the keys
129
     * - tokenName: (optional) string name of the token used to authenticate.
130
     * - url: string if provided it will be used directly.
131
     * - urlParams: string[] GET params to parse the url rule with
132
     *   `getRoutePattern()`.
133
     * - httpCode: integer expected Http Code response. If the httpCode is
134
     *   a key in `$responses` parameter then the method defined there will be
135
     *   used to analyze the response. Otherwise `checkErrorResponse()` will be
136
     *   used.
137
     * - error: string|string[] expected json being contained in the response.
138
     * - headers: (optional) string[] pairs of header => value expected in the
139
     *   response.
140
     */
141 2
    protected function internalView(Tester $I, Example $example)
142
    {
143
        // Authenticates configured user.
144 2
        $this->authUser($I, $example);
145
146
        // Send request
147 2
        $I->sendGET($this->parseUrl($example));
148
149
        // Checks the response has the required headers and body.
150 2
        $this->checkResponse([
151
            HttpCode::OK => 'checkSuccessViewResponse',
152
        ], $I, $example);
153
    }
154
155
    /**
156
     * Handles the internal logic when running a test on a updating a record.
157
     *
158
     * @param Tester $I
159
     * @param Example $example data used for the testing. It uses the keys
160
     * - tokenName: (optional) string name of the token used to authenticate.
161
     * - url: (optional) string if provided it will be used directly.
162
     * - urlParams: (optional) string[] GET params to parse the url rule with
163
     *   `getRoutePattern()`.
164
     * - data: (optional) POST data sent on the request.
165
     * - expected: (optional) expected in the JSON response body.
166
     * - headers: (optional) string[] pairs of header => value expected in the
167
     *   response.
168
     */
169 4
    protected function internalUpdate(Tester $I, Example $example)
170
    {
171
        // Authenticates configured user.
172 4
        $this->authUser($I, $example);
173
174
        // Send request
175 4
        $I->sendPATCH($this->parseUrl($example), $example['data']);
0 ignored issues
show
Bug introduced by
The method sendPATCH() does not exist on roaresearch\yii2\roa\test\Tester. ( Ignorable by Annotation )

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

175
        $I->/** @scrutinizer ignore-call */ 
176
            sendPATCH($this->parseUrl($example), $example['data']);

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...
176
177
        // Checks the response has the required headers and body.
178 4
        $this->checkResponse([
179
            HttpCode::OK => 'checkSuccessViewResponse',
180
            HttpCode::UNPROCESSABLE_ENTITY => 'checkValidationResponse',
181
        ], $I, $example);
182
183 4
        if (isset($example['expected'])) {
184
            $I->seeResponseContainsJson($example['expected']);
0 ignored issues
show
Bug introduced by
The method seeResponseContainsJson() does not exist on roaresearch\yii2\roa\test\Tester. ( Ignorable by Annotation )

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

184
            $I->/** @scrutinizer ignore-call */ 
185
                seeResponseContainsJson($example['expected']);

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...
185
        }
186
    }
187
188
    /**
189
     * Handles the internal logic when running a test on a updating a record.
190
     *
191
     * @param Tester $I
192
     * @param Example $example data used for the testing. It uses the keys
193
     * - tokenName: (optional) string name of the token used to authenticate.
194
     * - url: (optional) string if provided it will be used directly.
195
     * - urlParams: (optional) string[] GET params to parse the url rule with
196
     *   `getRoutePattern()`.
197
     * - httpCode: integer expected Http Code response.
198
     */
199 5
    protected function internalDelete(Tester $I, Example $example)
200
    {
201
        // Authenticates configured user.
202 5
        $this->authUser($I, $example);
203
204
        // Send request
205 5
        $I->sendDELETE($this->parseUrl($example));
0 ignored issues
show
Bug introduced by
The method sendDELETE() does not exist on roaresearch\yii2\roa\test\Tester. ( Ignorable by Annotation )

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

205
        $I->/** @scrutinizer ignore-call */ 
206
            sendDELETE($this->parseUrl($example));

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...
206
207
        // Check response code.
208 5
        $I->seeResponseCodeIs($example['httpCode']);
0 ignored issues
show
Bug introduced by
The method seeResponseCodeIs() does not exist on roaresearch\yii2\roa\test\Tester. ( Ignorable by Annotation )

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

208
        $I->/** @scrutinizer ignore-call */ 
209
            seeResponseCodeIs($example['httpCode']);

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...
209
    }
210
211
    /**
212
     * Checks the response Http code and the response based on the Http code and
213
     * a list of pairs 'httpCode' => 'responseMethod' provided in the
214
     * `$responses` parameter.
215
     *
216
     * If the Http Code in the response doesn't match any of the keys in
217
     * `$responses` then `checkErrorResponse` will be used instead.
218
     *
219
     * @param array $responses pairs of 'httpCode' => 'responseMethod' which
220
     * will determine how to check the response.
221
     * @param Tester $I
222
     * @param Example $example data used for the testing. It uses the keys
223
     * - httpCode: integer expected Http Code response. If the httpCode is
224
     *   a key in `$responses` parameter then the method defined there will be
225
     *   used to analyze the response. Otherwise `checkErrorResponse()` will be
226
     *   used.
227
     * - error: (optional) mixed expected json being contained in the response.
228
     * - headers: (optional) string[] pairs of header => value expected in the
229
     *   response.
230
     */
231 10
    protected function checkResponse(
232
        array $responses,
233
        Tester $I,
234
        Example $example
235
    ) {
236 10
        $I->seeResponseCodeIs($example['httpCode']);
237 10
        if (isset($responses[$example['httpCode']])) {
238 10
            $responseMethod = $responses[$example['httpCode']];
239 10
            $this->$responseMethod($I, $example);
240
        } else {
241 3
            $this->checkErrorResponse($I, $example);
242
        }
243 10
        if (isset($example['headers'])) {
244 2
            foreach ($example['headers'] as $header => $value) {
245 2
                $I->seeHttpHeader($header, (string)$value);
0 ignored issues
show
Bug introduced by
The method seeHttpHeader() does not exist on roaresearch\yii2\roa\test\Tester. ( Ignorable by Annotation )

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

245
                $I->/** @scrutinizer ignore-call */ 
246
                    seeHttpHeader($header, (string)$value);

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...
246
            }
247
        }
248
    }
249
250
    /**
251
     * Checks an expected success collection response.
252
     *
253
     * @param Tester $I
254
     * @param Example $example
255
     */
256 2
    protected function checkSuccessIndexResponse(Tester $I, Example $example)
257
    {
258 2
        $I->seeResponseMatchesJsonType($this->recordJsonType());
0 ignored issues
show
Bug introduced by
The method seeResponseMatchesJsonType() does not exist on roaresearch\yii2\roa\test\Tester. ( Ignorable by Annotation )

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

258
        $I->/** @scrutinizer ignore-call */ 
259
            seeResponseMatchesJsonType($this->recordJsonType());

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...
259 2
        $I->seeContentTypeHttpHeader();
260 2
        $I->seePaginationHttpHeaders();
261
    }
262
263
    /**
264
     * Checks an expected success record response.
265
     *
266
     * @param Tester $I
267
     * @param Example $example
268
     */
269 8
    protected function checkSuccessViewResponse(Tester $I, Example $example)
270
    {
271 8
        $I->seeResponseMatchesJsonType($this->recordJsonType());
272 8
        $I->seeContentTypeHttpHeader();
273
    }
274
275
    /**
276
     * Checks an expected success record creation response.
277
     *
278
     * @param Tester $I
279
     * @param Example $example
280
     */
281 2
    protected function checkSuccessCreateResponse(Tester $I, Example $example)
282
    {
283 2
        $this->checkSuccessViewResponse($I, $example);
284 2
        $I->seeHttpHeaderOnce('Location');
0 ignored issues
show
Bug introduced by
The method seeHttpHeaderOnce() does not exist on roaresearch\yii2\roa\test\Tester. ( Ignorable by Annotation )

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

284
        $I->/** @scrutinizer ignore-call */ 
285
            seeHttpHeaderOnce('Location');

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...
285 2
        $this->checkSelfLink($I, $I->grabHttpHeader('Location'));
0 ignored issues
show
Bug introduced by
The method grabHttpHeader() does not exist on roaresearch\yii2\roa\test\Tester. ( Ignorable by Annotation )

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

285
        $this->checkSelfLink($I, $I->/** @scrutinizer ignore-call */ grabHttpHeader('Location'));

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...
286
    }
287
288
    /**
289
     * Checks an expected response containing validation errors.
290
     *
291
     * @param Tester $I
292
     * @param Example $example data used for the testing. It uses the keys
293
     * - validationErrors: string[] (optional) pairs of field => message
294
     *   validation errors.
295
     */
296 5
    protected function checkValidationResponse(Tester $I, Example $example)
297
    {
298 5
        $I->seeResponseMatchesJsonType([
299
            'field' => 'string',
300
            'message' => 'string',
301
        ]);
302 5
        if (empty($example['validationErrors'])) {
303
            return;
304
        }
305 5
        $expected = [];
306 5
        foreach ($example['validationErrors'] as $field => $message) {
307 5
            $expected[] = [
308
                'field' => $field,
309
                'message' => $message,
310
            ];
311
        }
312 5
        $I->seeResponseContainsJson($expected);
313
    }
314
315
    /**
316
     * Checks an expected error response from user input.
317
     *
318
     * @param Tester $I
319
     * @param Example $example data used for the testing. It uses the keys
320
     * - error: (optional) mixed expected json being contained in the response.
321
     */
322 3
    protected function checkErrorResponse(Tester $I, Example $example)
323
    {
324 3
        $I->seeResponseMatchesJsonType([
325
            'name' => 'string',
326
            'message' => 'string',
327
            'code' => 'integer',
328
        ]);
329 3
        if (isset($example['error'])) {
330
            $I->seeResponseContainsJson($example['error']);
331
        }
332
    }
333
334
    /**
335
     * @param Tester $I
336
     * @param string $expected the expected self link.
337
     */
338 2
    protected function checkSelfLink(Tester $I, string $expected)
339
    {
340 2
        if ('' == $path = $this->selfLinkPath()) {
341
            return;
342
        }
343 2
        Verify::Array($I->grabDataFromResponseByJsonPath($path))
0 ignored issues
show
Bug introduced by
The method grabDataFromResponseByJsonPath() does not exist on roaresearch\yii2\roa\test\Tester. ( Ignorable by Annotation )

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

343
        Verify::Array($I->/** @scrutinizer ignore-call */ grabDataFromResponseByJsonPath($path))

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...
344 2
            ->contains($expected);
345
    }
346
347
    /**
348
     * @return string the path which will be used to obtain the self link of a
349
     * record. Return empty string to skip that check.
350
     */
351 2
    protected function selfLinkPath(): string
352
    {
353 2
        return '$._links.self.href';
354
    }
355
356
    /**
357
     * Expected Json Type for each resource.
358
     *
359
     * @return array
360
     * @see http://codeception.com/docs/modules/REST#seeResponseMatchesJsonType
361
     */
362
    abstract protected function recordJsonType(): array;
363
364
    /**
365
     * @return string route pattern to create the
366
     */
367
    abstract protected function getRoutePattern(): string;
368
}