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