Completed
Push — signal_search_issues ( 5556b2...f328ba )
by André
63:06 queued 07:22
created

RestContext::assertStatusCode()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 21
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 5
eloc 14
nc 3
nop 1
dl 0
loc 21
rs 8.7624
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * File containing the RestContext for RestBundle.
5
 *
6
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
7
 * @license For full copyright and license information view LICENSE file distributed with this source code.
8
 *
9
 * @version //autogentag//
10
 */
11
namespace eZ\Bundle\EzPublishRestBundle\Features\Context;
12
13
use Behat\Mink\Mink;
14
use Behat\MinkExtension\Context\MinkAwareContext;
15
use eZ\Publish\Core\REST\Client\Values\ErrorMessage;
16
use EzSystems\BehatBundle\Context\Api\Context;
17
use EzSystems\BehatBundle\Helper\Gherkin as GherkinHelper;
18
use eZ\Publish\Core\Base\Exceptions\InvalidArgumentException;
19
use Behat\Gherkin\Node\TableNode;
20
use PHPUnit_Framework_Assert as Assertion;
21
22
/**
23
 * RestContext is the core of the REST testing
24
 *   All SubContext (traits), helpers are loaded here
25
 *   Settings and client initializations is done here
26
 *   Also it contains all REST generic actions.
27
 */
28
class RestContext extends Context implements MinkAwareContext
29
{
30
    use SubContext\EzRest;
31
    use SubContext\Authentication;
32
    use SubContext\ContentTypeGroup;
33
    use SubContext\Exception;
34
    use SubContext\Views;
35
    use SubContext\User;
36
37
    const AUTHTYPE_BASICHTTP = 'http_basic';
38
    const AUTHTYPE_SESSION = 'session';
39
40
    const DEFAULT_URL = 'http://localhost/';
41
    const DEFAULT_DRIVER = 'GuzzleDriver';
42
    const DEFAULT_BODY_TYPE = 'json';
43
44
    const DEFAULT_AUTH_TYPE = self::AUTHTYPE_SESSION;
45
46
    /**
47
     * Rest driver for all requests and responses.
48
     *
49
     * @var \eZ\Bundle\EzPublishRestBundle\Features\Context\RestClient\DriverInterface
50
     */
51
    protected $restDriver;
52
53
    /**
54
     * @var string
55
     */
56
    private $url;
57
58
    /**
59
     * @var string
60
     */
61
    private $driver;
62
63
    /**
64
     * @var \Behat\Mink\Mink
65
     */
66
    private $mink;
67
68
    /**
69
     * @var array
70
     */
71
    private $minkParameters;
72
73
    /**
74
     * Initialize class.
75
     *
76
     * @param string $url    Base URL for REST calls
0 ignored issues
show
Bug introduced by
There is no parameter named $url. 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...
77
     * @param string $driver REST Driver to be used
78
     * @param string $json
0 ignored issues
show
Bug introduced by
There is no parameter named $json. 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...
79
     */
80
    public function __construct(
81
        $driver = self::DEFAULT_DRIVER,
82
        $type = self::DEFAULT_BODY_TYPE,
83
        $authType = self::DEFAULT_AUTH_TYPE
84
    ) {
85
        $this->driver = $driver;
86
        $this->restBodyType = $type;
87
        $this->authType = $authType;
88
89
        $this->setRestDriver($this->driver);
90
    }
91
92
    private function setUrl($url)
93
    {
94
        $this->url = $url;
95
        if (isset($this->restDriver)) {
96
            $this->restDriver->setHost($this->url);
97
        }
98
    }
99
100
    /**
101
     * Sets Mink instance.
102
     *
103
     * @param Mink $mink Mink session manager
104
     */
105
    public function setMink(Mink $mink)
106
    {
107
        $this->mink = $mink;
108
    }
109
110
    /**
111
     * Sets parameters provided for Mink.
112
     * While at it, take the base_url, and use it to build the one for the REST driver.
113
     *
114
     * @param array $parameters
115
     */
116
    public function setMinkParameters(array $parameters)
117
    {
118
        $this->minkParameters = $parameters;
119
        $this->setUrl($parameters['base_url'] . '/api/ezp/v2/');
120
    }
121
122
    /**
123
     * @BeforeScenario
124
     */
125
    private function resetDriver()
0 ignored issues
show
Unused Code introduced by
This method is not used, and could be removed.
Loading history...
126
    {
127
        $this->setRestDriver($this->driver, $this->url);
128
    }
129
130
    /**
131
     * Create and set the REST driver to be used.
132
     *
133
     * @param string $restDriver REST driver class name
134
     */
135
    private function setRestDriver($restDriver)
136
    {
137
        $namespace = '\\' . __NAMESPACE__ .  '\\RestClient\\';
138
        $driver = $namespace . $restDriver;
139
        $parent = $namespace . 'DriverInterface';
140
141
        if (
142
            empty($restDriver)
143
            || !class_exists($driver)
144
            || !is_subclass_of($driver, $parent)
0 ignored issues
show
Bug introduced by
Due to PHP Bug #53727, is_subclass_of might return inconsistent results on some PHP versions if $parent can be an interface. If so, you could instead use ReflectionClass::implementsInterface.
Loading history...
145
        ) {
146
            throw new InvalidArgumentException('rest driver', $driver);
147
        }
148
149
        // create a new REST Driver
150
        $this->restDriver = new $driver();
151
        if (isset($this->url)) {
152
            $this->restDriver->setHost($this->url);
153
        }
154
    }
155
156
    /**
157
     * @When I create a :type request to :resource (url)
158
     */
159
    public function createRequest($type, $resource)
160
    {
161
        $this->restDriver->setMethod($type);
162
        $this->restDriver->setResource(
163
            $this->changeMappedValuesOnUrl($resource)
164
        );
165
        $this->responseObject = null;
166
    }
167
168
    /**
169
     * @When I send a :type request to :resource (url)
170
     */
171
    public function createAndSendRequest($type, $resource)
172
    {
173
        $this->createRequest($type, $resource);
174
        $this->restDriver->send();
175
    }
176
177
    /**
178
     * @When I set :header header with :value (value)
179
     */
180
    public function setHeader($header, $value)
181
    {
182
        $this->restDriver->setHeader($header, $value);
183
    }
184
185
    /**
186
     * @When I set headers:
187
     */
188
    public function setHeaders(TableNode $table)
189
    {
190
        $headers = GherkinHelper::convertTableToArrayOfData($table);
191
192
        foreach ($headers as $header => $value) {
0 ignored issues
show
Bug introduced by
The expression $headers of type false|array is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
193
            $this->iAddHeaderWithValue($header, $value);
194
        }
195
    }
196
197
    /**
198
     * @When I send the request
199
     */
200
    public function sendRequest()
201
    {
202
        $requestObject = $this->getRequestObject();
203
        if (!empty($requestObject)) {
204
            $this->addObjectToRequestBody(
205
                $requestObject,
206
                $this->restBodyType
207
            );
208
        }
209
        $this->restDriver->send();
210
    }
211
212
    /**
213
     * @Then response status code is :code
214
     */
215
    public function assertStatusCode($code)
216
    {
217
        $exceptionMessage = '';
218
        if ($code != $this->restDriver->getStatusCode() && $code >= 200 && $code < 400) {
219
            $errorMessage = $this->getResponseObject();
220
            if ($errorMessage instanceof ErrorMessage) {
221
                $exceptionMessage = <<< EOF
222
223
Exception ({$errorMessage->code}): {$errorMessage->description}
224
225
{$errorMessage->trace}
226
EOF;
227
            }
228
        }
229
230
        Assertion::assertEquals(
231
            $code,
232
            $this->restDriver->getStatusCode(),
233
            "Expected status code '$code' found '{$this->restDriver->getStatusCode()}'$exceptionMessage"
234
        );
235
    }
236
237
    /**
238
     * @Then response status message is :message
239
     */
240
    public function assertStatusMessage($message)
241
    {
242
        Assertion::assertEquals(
243
            strtolower($message),
244
            strtolower($this->restDriver->getStatusMessage()),
245
            "Expected status message '$message' found '{$this->restDriver->getStatusMessage()}'"
246
        );
247
    }
248
249
    /**
250
     * @Then response header :header exist
251
     */
252
    public function existResponseHeader($header)
253
    {
254
        Assertion::assertNotNull(
255
            $this->restDriver->getHeader($header),
256
            "Expected '$header' header not found"
257
        );
258
    }
259
260
    /**
261
     * @Then response header :header don't exist
262
     */
263
    public function dontExistResponseHeader($header)
264
    {
265
        Assertion::assertNull(
266
            $this->restDriver->getHeader($header),
267
            "Unexpected '$header' header found with '{$this->restDriver->getHeader($header)}' value"
268
        );
269
    }
270
271
    /**
272
     * @Then response header :header have :value (value)
273
     */
274
    public function assertHeaderHaveValue($header, $value)
275
    {
276
        Assertion::assertEquals(
277
            $value,
278
            $this->restDriver->getResponseHeader($header),
0 ignored issues
show
Bug introduced by
The method getResponseHeader() does not seem to exist on object<eZ\Bundle\EzPubli...Client\DriverInterface>.

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...
279
            "Expected '$header' header with '$value' found it with '{$this->restDriver->getHeader($header)}' value"
280
        );
281
    }
282
283
    /**
284
     * @Then response header :header don't have :value (value)
285
     */
286
    public function assertHeaderDontHaveValue($header, $value)
287
    {
288
        Assertion::assertNotEquals(
289
            $value,
290
            $this->restDriver->getResponseHeader($header),
0 ignored issues
show
Bug introduced by
The method getResponseHeader() does not seem to exist on object<eZ\Bundle\EzPubli...Client\DriverInterface>.

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...
291
            "Unexpected '$header' header found with '{$this->restDriver->getHeader($header)}' value"
292
        );
293
    }
294
295
    /**
296
     * @Then response body has :value (value)
297
     */
298
    public function responseBodyHasValue($value)
299
    {
300
        Assertion::assertEquals(
301
            $value,
302
            $this->restDriver->getBody(),
303
            "Expected body isn't equal to the actual one."
304
            . "\nExpected: "
305
            . print_r($value, true)
306
            . "\nActual: "
307
            . print_r($this->restDriver->getBody(), true)
308
        );
309
    }
310
}
311