Passed
Push — master ( 9b342b...cbda31 )
by San
02:50
created

src/Context/RestContext.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace Behatch\Context;
4
5
use Behat\Mink\Exception\ExpectationException;
6
use Behatch\HttpCall\Request;
7
use Behat\Gherkin\Node\TableNode;
8
use Behat\Gherkin\Node\PyStringNode;
9
10
class RestContext extends BaseContext
11
{
12
    /**
13
     * @var Request
14
     */
15
    protected $request;
16
17
    public function __construct(Request $request)
18
    {
19
        $this->request = $request;
20
    }
21
22
    /**
23
     * Sends a HTTP request
24
     *
25
     * @Given I send a :method request to :url
26
     */
27
    public function iSendARequestTo($method, $url, PyStringNode $body = null, $files = [])
28
    {
29
        return $this->request->send(
30
            $method,
31
            $this->locatePath($url),
32
            [],
33
            $files,
34
            $body !== null ? $body->getRaw() : null
35
        );
36
    }
37
38
    /**
39
     * Sends a HTTP request with a some parameters
40
     *
41
     * @Given I send a :method request to :url with parameters:
42
     */
43
    public function iSendARequestToWithParameters($method, $url, TableNode $data)
44
    {
45
        $files = [];
46
        $parameters = [];
47
48
        foreach ($data->getHash() as $row) {
49
            if (!isset($row['key']) || !isset($row['value'])) {
50
                throw new \Exception("You must provide a 'key' and 'value' column in your table node.");
51
            }
52
53
            if (is_string($row['value']) && substr($row['value'], 0, 1) == '@') {
54
                $files[$row['key']] = rtrim($this->getMinkParameter('files_path'), DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.substr($row['value'],1);
55
            }
56
            else {
57
                $parameters[] = sprintf('%s=%s', $row['key'], $row['value']);
58
            }
59
        }
60
61
        parse_str(implode('&', $parameters), $parameters);
62
63
        return $this->request->send(
0 ignored issues
show
Documentation Bug introduced by
The method send does not exist on object<Behatch\HttpCall\Request>? Since you implemented __call, maybe consider adding a @method annotation.

If you implement __call and you know which methods are available, you can improve IDE auto-completion and static analysis by adding a @method annotation to the class.

This is often the case, when __call is implemented by a parent class and only the child class knows which methods exist:

class ParentClass {
    private $data = array();

    public function __call($method, array $args) {
        if (0 === strpos($method, 'get')) {
            return $this->data[strtolower(substr($method, 3))];
        }

        throw new \LogicException(sprintf('Unsupported method: %s', $method));
    }
}

/**
 * If this class knows which fields exist, you can specify the methods here:
 *
 * @method string getName()
 */
class SomeClass extends ParentClass { }
Loading history...
64
            $method,
65
            $this->locatePath($url),
66
            $parameters,
67
            $files
68
        );
69
    }
70
71
    /**
72
     * Sends a HTTP request with a body
73
     *
74
     * @Given I send a :method request to :url with body:
75
     */
76
    public function iSendARequestToWithBody($method, $url, PyStringNode $body)
77
    {
78
        return $this->iSendARequestTo($method, $url, $body);
79
    }
80
81
    /**
82
     * Checks, whether the response content is equal to given text
83
     *
84
     * @Then the response should be equal to
85
     * @Then the response should be equal to:
86
     */
87
    public function theResponseShouldBeEqualTo(PyStringNode $expected)
88
    {
89
        $expected = str_replace('\\"', '"', $expected);
90
        $actual   = $this->request->getContent();
91
        $message = "Actual response is '$actual', but expected '$expected'";
92
        $this->assertEquals($expected, $actual, $message);
93
    }
94
95
    /**
96
     * Checks, whether the response content is null or empty string
97
     *
98
     * @Then the response should be empty
99
     */
100
    public function theResponseShouldBeEmpty()
101
    {
102
        $actual = $this->request->getContent();
103
        $message = "The response of the current page is not empty, it is: $actual";
104
        $this->assertTrue(null === $actual || "" === $actual, $message);
105
    }
106
107
    /**
108
     * Checks, whether the header name is equal to given text
109
     *
110
     * @Then the header :name should be equal to :value
111
     */
112
    public function theHeaderShouldBeEqualTo($name, $value)
113
    {
114
        $actual = $this->request->getHttpHeader($name);
115
        $this->assertEquals(strtolower($value), strtolower($actual),
116
            "The header '$name' should be equal to '$value', but it is: '$actual'"
117
        );
118
    }
119
120
    /**
121
    * Checks, whether the header name is not equal to given text
122
    *
123
    * @Then the header :name should not be equal to :value
124
    */
125
    public function theHeaderShouldNotBeEqualTo($name, $value) {
126
        $actual = $this->getSession()->getResponseHeader($name);
127
        if (strtolower($value) == strtolower($actual)) {
128
            throw new ExpectationException(
129
                "The header '$name' is equal to '$actual'",
130
                $this->getSession()->getDriver()
131
            );
132
        }
133
    }
134
135
    public function theHeaderShouldBeContains($name, $value)
136
    {
137
        trigger_error(
138
            sprintf('The %s function is deprecated since version 3.1 and will be removed in 4.0. Use the %s::theHeaderShouldContain function instead.', __METHOD__, __CLASS__),
139
            E_USER_DEPRECATED
140
        );
141
        $this->theHeaderShouldContain($name, $value);
142
    }
143
144
    /**
145
     * Checks, whether the header name contains the given text
146
     *
147
     * @Then the header :name should contain :value
148
     */
149
    public function theHeaderShouldContain($name, $value)
150
    {
151
        $actual = $this->request->getHttpHeader($name);
152
        $this->assertContains($value, $actual,
153
            "The header '$name' should contain value '$value', but actual value is '$actual'"
154
        );
155
    }
156
157
    /**
158
     * Checks, whether the header name doesn't contain the given text
159
     *
160
     * @Then the header :name should not contain :value
161
     */
162
    public function theHeaderShouldNotContain($name, $value)
163
    {
164
        $this->assertNotContains($value, $this->request->getHttpHeader($name),
165
            "The header '$name' contains '$value'"
166
        );
167
    }
168
169
    /**
170
     * Checks, whether the header not exist
171
     *
172
     * @Then the header :name should not exist
173
     */
174
    public function theHeaderShouldNotExist($name)
175
    {
176
        $this->not(function () use($name) {
177
            $this->theHeaderShouldExist($name);
178
        }, "The header '$name' exists");
179
    }
180
181
    protected function theHeaderShouldExist($name)
182
    {
183
        return $this->request->getHttpHeader($name);
184
    }
185
186
   /**
187
     * Checks, that the response header expire is in the future
188
     *
189
     * @Then the response should expire in the future
190
     */
191
    public function theResponseShouldExpireInTheFuture()
192
    {
193
        $date = new \DateTime($this->request->getHttpRawHeader('Date')[0]);
194
        $expires = new \DateTime($this->request->getHttpRawHeader('Expires')[0]);
195
196
        $this->assertSame(1, $expires->diff($date)->invert,
197
            sprintf('The response doesn\'t expire in the future (%s)', $expires->format(DATE_ATOM))
198
        );
199
    }
200
201
    /**
202
     * Add an header element in a request
203
     *
204
     * @Then I add :name header equal to :value
205
     */
206
    public function iAddHeaderEqualTo($name, $value)
207
    {
208
        $this->request->setHttpHeader($name, $value);
209
    }
210
211
    /**
212
     * @Then the response should be encoded in :encoding
213
     */
214
    public function theResponseShouldBeEncodedIn($encoding)
215
    {
216
        $content = $this->request->getContent();
217
        if (!mb_check_encoding($content, $encoding)) {
218
            throw new \Exception("The response is not encoded in $encoding");
219
        }
220
221
        $this->theHeaderShouldContain('Content-Type', "charset=$encoding");
222
    }
223
224
    /**
225
     * @Then print last response headers
226
     */
227
    public function printLastResponseHeaders()
228
    {
229
        $text = '';
230
        $headers = $this->request->getHttpHeaders();
231
232
        foreach ($headers as $name => $value) {
233
            $text .= $name . ': '. $this->request->getHttpHeader($name) . "\n";
234
        }
235
        echo $text;
236
    }
237
238
239
    /**
240
     * @Then print the corresponding curl command
241
     */
242
    public function printTheCorrespondingCurlCommand()
243
    {
244
        $method = $this->request->getMethod();
245
        $url = $this->request->getUri();
246
247
        $headers = '';
248
        foreach ($this->request->getServer() as $name => $value) {
249
            if (substr($name, 0, 5) !== 'HTTP_' && $name !== 'HTTPS') {
250
                $headers .= " -H '$name: $value'";
251
            }
252
        }
253
254
        $data = '';
255
        $params = $this->request->getParameters();
256
        if (!empty($params)) {
257
            $query = http_build_query($params);
258
            $data = " --data '$query'" ;
259
        }
260
261
        echo "curl -X $method$data$headers '$url'";
262
    }
263
}
264