Passed
Pull Request — master (#306)
by Tobias
02:05
created

FunctionalTest::testFormPostWithRequestBuilder()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 23
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 16
nc 2
nop 2
dl 0
loc 23
rs 9.0856
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Buzz\Test\Unit\Client;
6
7
use Buzz\Browser;
8
use Buzz\Client\BuzzClientInterface;
9
use Buzz\Client\Curl;
10
use Buzz\Client\FileGetContents;
11
use Buzz\Client\MultiCurl;
12
use Buzz\Exception\ClientException;
13
use Buzz\Message\FormRequestBuilder;
14
use Nyholm\Psr7\Request;
15
use PHPUnit\Framework\TestCase;
16
use Psr\Http\Message\RequestInterface;
17
use Psr\Http\Message\ResponseInterface;
18
19
class FunctionalTest extends TestCase
20
{
21
    protected function setUp()
22
    {
23
        if (!isset($_SERVER['BUZZ_TEST_SERVER']) || empty($_SERVER['BUZZ_TEST_SERVER'])) {
24
            $this->markTestSkipped('The test server is not configured.');
25
        }
26
    }
27
28
    /**
29
     * @dataProvider provideClientAndMethod
30
     */
31
    public function testRequestMethods($client, $method, $async)
32
    {
33
        $request = new Request($method, $_SERVER['BUZZ_TEST_SERVER'], [], 'test');
34
        $response = $this->send($client, $request, $async);
35
36
        $data = json_decode($response->getBody()->__toString(), true);
37
38
        $this->assertEquals($method, $data['SERVER']['REQUEST_METHOD']);
39
    }
40
41
    /**
42
     * @dataProvider provideClient
43
     */
44
    public function testGetContentType($client, $async)
45
    {
46
        $request = new Request('GET', $_SERVER['BUZZ_TEST_SERVER']);
47
        $response = $this->send($client, $request, $async);
48
49
        $data = json_decode($response->getBody()->__toString(), true);
50
        $this->assertArrayHasKey('SERVER', $data, $response->getBody()->__toString());
51
52
        $this->assertArrayNotHasKey('CONTENT_TYPE', $data['SERVER']);
53
    }
54
55
    /**
56
     * @dataProvider provideClient
57
     */
58
    public function testFormPost($client, $async)
59
    {
60
        $request = new Request(
61
            'POST',
62
            $_SERVER['BUZZ_TEST_SERVER'],
63
            ['Content-Type' => 'application/x-www-form-urlencoded'],
64
            http_build_query(['company[name]' => 'Google'])
65
        );
66
        $response = $this->send($client, $request, $async);
67
68
        $data = json_decode($response->getBody()->__toString(), true);
69
70
        $this->assertStringStartsWith('application/x-www-form-urlencoded', $data['SERVER']['CONTENT_TYPE']);
71
        $this->assertEquals('Google', $data['POST']['company']['name']);
72
    }
73
74
    /**
75
     * @dataProvider provideClient
76
     */
77
    public function testFormPostWithRequestBuilder($client, $async)
78
    {
79
        if ($async) {
80
            $this->markTestSkipped('Skipping for async requests');
81
        }
82
83
        $builder = new FormRequestBuilder();
84
        $builder->addField('company[name]', 'Google');
85
        $builder->addFile('image', __DIR__.'/../../Resources/image.png', 'image/png', 'filename.png');
86
        $browser = new Browser($client);
87
        $response = $browser->submitForm($_SERVER['BUZZ_TEST_SERVER'], $builder->build());
88
89
        $this->assertNotEmpty($response->getBody()->__toString(), 'Response from server should not be empty');
90
91
        $data = json_decode($response->getBody()->__toString(), true);
92
        $this->assertInternalType('array', $data, $response->getBody()->__toString());
93
        $this->assertArrayHasKey('SERVER', $data);
94
95
        $this->assertStringStartsWith('multipart/form-data', $data['SERVER']['CONTENT_TYPE']);
96
        $this->assertEquals('Google', $data['POST']['company']['name']);
97
        $this->assertEquals('filename.png', $data['FILES']['image']['name']);
98
        $this->assertEquals('image/png', $data['FILES']['image']['type']);
99
        $this->assertEquals(39618, $data['FILES']['image']['size']);
100
    }
101
102
    /**
103
     * @dataProvider provideClient
104
     */
105
    public function testFormPostWithLargeRequestBody($client, $async)
106
    {
107
        if ($async) {
108
            $this->markTestSkipped('Skipping for async requests');
109
        }
110
111
        $browser = new Browser($client);
112
        $response = $browser->submitForm($_SERVER['BUZZ_TEST_SERVER'], [
113
            'image' => [
114
                'path' => __DIR__.'/../../Resources/large.png',
115
                'filename' => 'filename.png',
116
                'contentType' => 'image/png',
117
            ],
118
        ]);
119
120
        $this->assertNotEmpty($response->getBody()->__toString(), 'Response from server should not be empty');
121
122
        $data = json_decode($response->getBody()->__toString(), true);
123
        $this->assertInternalType('array', $data, $response->getBody()->__toString());
124
        $this->assertArrayHasKey('SERVER', $data);
125
126
        $this->assertStringStartsWith('multipart/form-data', $data['SERVER']['CONTENT_TYPE']);
127
        $this->assertGreaterThan(39618, $data['FILES']['image']['size']);
128
    }
129
130
    public function testMultiCurlExecutesRequestsConcurently()
131
    {
132
        $client = new MultiCurl(['timeout' => 30]);
133
134
        $calls = [];
135
        $callback = function (RequestInterface $request, ResponseInterface $response = null, ClientException $exception = null) use (&$calls) {
136
            $calls[] = func_get_args();
137
        };
138
139
        for ($i = 3; $i > 0; --$i) {
140
            $request = new Request('GET', $_SERVER['BUZZ_TEST_SERVER'].'?delay='.$i);
141
            $client->sendAsyncRequest($request, ['callback' => $callback]);
142
        }
143
144
        $client->flush();
145
        $this->assertCount(3, $calls);
146
147
        foreach ($calls as $i => $call) {
148
            /** @var ResponseInterface $response */
149
            $response = $call[1];
150
            $body = $response->getBody()->__toString();
151
            $array = json_decode($body, true);
152
            // Make sure the order is correct
153
            $this->assertEquals($i + 1, $array['GET']['delay']);
154
        }
155
    }
156
157
    public function provideClient()
158
    {
159
        return [
160
            [new Curl(), false],
161
            [new FileGetContents(), false],
162
            [new MultiCurl(), false],
163
            [new MultiCurl(), true],
164
        ];
165
    }
166
167
    public function provideClientAndMethod()
168
    {
169
        // HEAD is intentionally omitted
170
        // http://stackoverflow.com/questions/2603104/does-mod-php-honor-head-requests-properly
171
172
        $methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'];
173
        $clients = $this->provideClient();
174
175
        foreach ($clients as $client) {
176
            foreach ($methods as $method) {
177
                yield [$client[0], $method, $client[1]];
178
            }
179
        }
180
    }
181
182
    private function send(BuzzClientInterface $client, RequestInterface $request, bool $async): ResponseInterface
183
    {
184
        if (!$async) {
185
            return $client->sendRequest($request);
186
        }
187
188
        $newResponse = null;
189
        $client->sendAsyncRequest($request, ['callback' => function (RequestInterface $request, ResponseInterface $response = null, ClientException $exception = null) use (&$newResponse) {
0 ignored issues
show
Unused Code introduced by
The parameter $exception is not used and could be removed. ( Ignorable by Annotation )

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

189
        $client->sendAsyncRequest($request, ['callback' => function (RequestInterface $request, ResponseInterface $response = null, /** @scrutinizer ignore-unused */ ClientException $exception = null) use (&$newResponse) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Bug introduced by
The method sendAsyncRequest() does not exist on Buzz\Client\BuzzClientInterface. It seems like you code against a sub-type of Buzz\Client\BuzzClientInterface such as Buzz\Client\MultiCurl. ( Ignorable by Annotation )

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

189
        $client->/** @scrutinizer ignore-call */ 
190
                 sendAsyncRequest($request, ['callback' => function (RequestInterface $request, ResponseInterface $response = null, ClientException $exception = null) use (&$newResponse) {
Loading history...
190
            $newResponse = $response;
191
        }]);
192
193
        $client->flush();
0 ignored issues
show
Bug introduced by
The method flush() does not exist on Buzz\Client\BuzzClientInterface. It seems like you code against a sub-type of Buzz\Client\BuzzClientInterface such as Buzz\Client\MultiCurl. ( Ignorable by Annotation )

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

193
        $client->/** @scrutinizer ignore-call */ 
194
                 flush();
Loading history...
194
195
        return $newResponse;
196
    }
197
}
198