4 * This file is part of the Goutte package.
6 * (c) Fabien Potencier <fabien@symfony.com>
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
12 namespace Goutte\Tests;
15 use GuzzleHttp\Client as GuzzleClient;
16 use GuzzleHttp\Exception\RequestException;
17 use GuzzleHttp\Handler\MockHandler;
18 use GuzzleHttp\HandlerStack;
19 use GuzzleHttp\Psr7\Response as GuzzleResponse;
20 use GuzzleHttp\Middleware;
21 use PHPUnit\Framework\TestCase;
22 use Symfony\Component\BrowserKit\Cookie;
27 * @author Michael Dowling <michael@guzzlephp.org>
28 * @author Charles Sarrazin <charles@sarraz.in>
30 class ClientTest extends TestCase
33 /** @var MockHandler */
36 protected function getGuzzle(array $responses = [])
38 if (empty($responses)) {
39 $responses = [new GuzzleResponse(200, [], '<html><body><p>Hi</p></body></html>')];
41 $this->mock = new MockHandler($responses);
42 $handlerStack = HandlerStack::create($this->mock);
44 $handlerStack->push(Middleware::history($this->history));
45 $guzzle = new GuzzleClient(array('redirect.disable' => true, 'base_uri' => '', 'handler' => $handlerStack));
50 public function testCreatesDefaultClient()
52 $client = new Client();
53 $this->assertInstanceOf('GuzzleHttp\\ClientInterface', $client->getClient());
56 public function testUsesCustomClient()
58 $guzzle = new GuzzleClient();
59 $client = new Client();
60 $this->assertSame($client, $client->setClient($guzzle));
61 $this->assertSame($guzzle, $client->getClient());
64 public function testUsesCustomHeaders()
66 $guzzle = $this->getGuzzle();
67 $client = new Client();
68 $client->setClient($guzzle);
69 $client->setHeader('X-Test', 'test');
70 $client->request('GET', 'http://www.example.com/');
71 $this->assertEquals('test', end($this->history)['request']->getHeaderLine('X-Test'));
74 public function testCustomUserAgent()
76 $guzzle = $this->getGuzzle();
77 $client = new Client();
78 $client->setClient($guzzle);
79 $client->setHeader('User-Agent', 'foo');
80 $client->request('GET', 'http://www.example.com/');
81 $this->assertEquals('foo', end($this->history)['request']->getHeaderLine('User-Agent'));
84 public function testUsesAuth()
86 $guzzle = $this->getGuzzle();
87 $client = new Client();
88 $client->setClient($guzzle);
89 $client->setAuth('me', '**');
90 $client->request('GET', 'http://www.example.com/');
91 $request = end($this->history)['request'];
92 $this->assertEquals('Basic bWU6Kio=', $request->getHeaderLine('Authorization'));
95 public function testResetsAuth()
97 $guzzle = $this->getGuzzle();
98 $client = new Client();
99 $client->setClient($guzzle);
100 $client->setAuth('me', '**');
101 $client->resetAuth();
102 $client->request('GET', 'http://www.example.com/');
103 $request = end($this->history)['request'];
104 $this->assertEquals('', $request->getHeaderLine('authorization'));
107 public function testUsesCookies()
109 $guzzle = $this->getGuzzle();
110 $client = new Client();
111 $client->setClient($guzzle);
112 $client->getCookieJar()->set(new Cookie('test', '123'));
113 $client->request('GET', 'http://www.example.com/');
114 $request = end($this->history)['request'];
115 $this->assertEquals('test=123', $request->getHeaderLine('Cookie'));
118 public function testUsesCookiesWithCustomPort()
120 $guzzle = $this->getGuzzle();
121 $client = new Client();
122 $client->setClient($guzzle);
123 $client->getCookieJar()->set(new Cookie('test', '123'));
124 $client->request('GET', 'http://www.example.com:8000/');
125 $request = end($this->history)['request'];
126 $this->assertEquals('test=123', $request->getHeaderLine('Cookie'));
129 public function testUsesPostFiles()
131 $guzzle = $this->getGuzzle();
132 $client = new Client();
133 $client->setClient($guzzle);
136 'name' => 'test.txt',
137 'tmp_name' => __DIR__.'/fixtures.txt',
141 $client->request('POST', 'http://www.example.com/', array(), $files);
142 $request = end($this->history)['request'];
144 $stream = $request->getBody();
145 $boundary = $stream->getBoundary();
147 "--$boundary\r\nContent-Disposition: form-data; name=\"test\"; filename=\"test.txt\"\r\nContent-Length: 4\r\n"
148 ."Content-Type: text/plain\r\n\r\nfoo\n\r\n--$boundary--\r\n",
149 $stream->getContents()
153 public function testUsesPostNamedFiles()
155 $guzzle = $this->getGuzzle();
156 $client = new Client();
157 $client->setClient($guzzle);
159 'test' => __DIR__.'/fixtures.txt',
162 $client->request('POST', 'http://www.example.com/', array(), $files);
163 $request = end($this->history)['request'];
165 $stream = $request->getBody();
166 $boundary = $stream->getBoundary();
168 "--$boundary\r\nContent-Disposition: form-data; name=\"test\"; filename=\"fixtures.txt\"\r\nContent-Length: 4\r\n"
169 ."Content-Type: text/plain\r\n\r\nfoo\n\r\n--$boundary--\r\n",
170 $stream->getContents()
174 public function testUsesPostFilesNestedFields()
176 $guzzle = $this->getGuzzle();
177 $client = new Client();
178 $client->setClient($guzzle);
182 'name' => 'test.txt',
183 'tmp_name' => __DIR__.'/fixtures.txt',
188 $client->request('POST', 'http://www.example.com/', array(), $files);
189 $request = end($this->history)['request'];
191 $stream = $request->getBody();
192 $boundary = $stream->getBoundary();
194 "--$boundary\r\nContent-Disposition: form-data; name=\"form[test]\"; filename=\"test.txt\"\r\nContent-Length: 4\r\n"
195 ."Content-Type: text/plain\r\n\r\nfoo\n\r\n--$boundary--\r\n",
196 $stream->getContents()
200 public function testPostFormWithFiles()
202 $guzzle = $this->getGuzzle();
203 $client = new Client();
204 $client->setClient($guzzle);
206 'test' => __DIR__.'/fixtures.txt',
212 $client->request('POST', 'http://www.example.com/', $params, $files);
213 $request = end($this->history)['request'];
215 $stream = $request->getBody();
216 $boundary = $stream->getBoundary();
218 "--$boundary\r\nContent-Disposition: form-data; name=\"foo\"\r\nContent-Length: 3\r\n"
220 ."--$boundary\r\nContent-Disposition: form-data; name=\"test\"; filename=\"fixtures.txt\"\r\nContent-Length: 4\r\n"
221 ."Content-Type: text/plain\r\n\r\nfoo\n\r\n--$boundary--\r\n",
222 $stream->getContents());
225 public function testPostEmbeddedFormWithFiles()
227 $guzzle = $this->getGuzzle();
228 $client = new Client();
229 $client->setClient($guzzle);
231 'test' => __DIR__.'/fixtures.txt',
239 $client->request('POST', 'http://www.example.com/', $params, $files);
240 $request = end($this->history)['request'];
242 $stream = $request->getBody();
243 $boundary = $stream->getBoundary();
245 "--$boundary\r\nContent-Disposition: form-data; name=\"foo[bar]\"\r\nContent-Length: 3\r\n"
247 ."--$boundary\r\nContent-Disposition: form-data; name=\"test\"; filename=\"fixtures.txt\"\r\nContent-Length: 4\r\n"
248 ."Content-Type: text/plain\r\n\r\nfoo\n\r\n--$boundary--\r\n",
249 $stream->getContents());
252 public function testUsesPostFilesOnClientSide()
254 $guzzle = $this->getGuzzle();
255 $client = new Client();
256 $client->setClient($guzzle);
258 'test' => __DIR__.'/fixtures.txt',
261 $client->request('POST', 'http://www.example.com/', array(), $files);
262 $request = end($this->history)['request'];
264 $stream = $request->getBody();
265 $boundary = $stream->getBoundary();
267 "--$boundary\r\nContent-Disposition: form-data; name=\"test\"; filename=\"fixtures.txt\"\r\nContent-Length: 4\r\n"
268 ."Content-Type: text/plain\r\n\r\nfoo\n\r\n--$boundary--\r\n",
269 $stream->getContents()
273 public function testUsesPostFilesUploadError()
275 $guzzle = $this->getGuzzle();
276 $client = new Client();
277 $client->setClient($guzzle);
288 $client->request('POST', 'http://www.example.com/', array(), $files);
289 $request = end($this->history)['request'];
290 $stream = $request->getBody();
291 $boundary = $stream->getBoundary();
293 $this->assertEquals("--$boundary--\r\n", $stream->getContents());
296 public function testCreatesResponse()
298 $guzzle = $this->getGuzzle();
299 $client = new Client();
300 $client->setClient($guzzle);
301 $crawler = $client->request('GET', 'http://www.example.com/');
302 $this->assertEquals('Hi', $crawler->filter('p')->text());
305 public function testHandlesRedirectsCorrectly()
307 $guzzle = $this->getGuzzle([
308 new GuzzleResponse(301, array(
309 'Location' => 'http://www.example.com/',
311 new GuzzleResponse(200, [], '<html><body><p>Test</p></body></html>'),
314 $client = new Client();
315 $client->setClient($guzzle);
317 $crawler = $client->request('GET', 'http://www.example.com/');
318 $this->assertEquals('Test', $crawler->filter('p')->text());
320 // Ensure that two requests were sent
321 $this->assertEquals(2, count($this->history));
324 public function testConvertsGuzzleHeadersToArrays()
326 $guzzle = $this->getGuzzle([
327 new GuzzleResponse(200, array(
328 'Date' => 'Tue, 04 Jun 2013 13:22:41 GMT',
332 $client = new Client();
333 $client->setClient($guzzle);
334 $client->request('GET', 'http://www.example.com/');
335 $response = $client->getResponse();
336 $headers = $response->getHeaders();
338 $this->assertInternalType('array', array_shift($headers), 'Header not converted from Guzzle\Http\Message\Header to array');
342 * @expectedException \GuzzleHttp\Exception\RequestException
344 public function testNullResponseException()
346 $guzzle = $this->getGuzzle([
347 new RequestException('', $this->getMockBuilder('Psr\Http\Message\RequestInterface')->getMock()),
349 $client = new Client();
350 $client->setClient($guzzle);
351 $client->request('GET', 'http://www.example.com/');
352 $client->getResponse();
355 public function testHttps()
357 $guzzle = $this->getGuzzle([
358 new GuzzleResponse(200, [], '<html><body><p>Test</p></body></html>'),
361 $client = new Client();
362 $client->setClient($guzzle);
363 $crawler = $client->request('GET', 'https://www.example.com/');
364 $this->assertEquals('Test', $crawler->filter('p')->text());
367 public function testCustomUserAgentConstructor()
369 $guzzle = $this->getGuzzle();
370 $client = new Client([
371 'HTTP_HOST' => '1.2.3.4',
372 'HTTP_USER_AGENT' => 'SomeHost',
374 $client->setClient($guzzle);
375 $client->request('GET', 'http://www.example.com/');
376 $this->assertEquals('SomeHost', end($this->history)['request']->getHeaderLine('User-Agent'));
379 public function testResetHeaders()
381 $client = new Client();
382 $client->setHeader('X-Test', 'test');
384 $reflectionProperty = new \ReflectionProperty('Goutte\Client', 'headers');
385 $reflectionProperty->setAccessible(true);
386 $this->assertEquals(array('x-test' => 'test'), $reflectionProperty->getValue($client));
388 $client->resetHeaders();
389 $this->assertEquals([], $reflectionProperty->getValue($client));
392 public function testRestart()
394 $client = new Client();
395 $client->setHeader('X-Test', 'test');
396 $client->setAuth('foo', 'bar');
398 $headersReflectionProperty = new \ReflectionProperty('Goutte\Client', 'headers');
399 $headersReflectionProperty->setAccessible(true);
400 $this->assertEquals(array('x-test' => 'test'), $headersReflectionProperty->getValue($client));
402 $authReflectionProperty = new \ReflectionProperty('Goutte\Client', 'auth');
403 $authReflectionProperty->setAccessible(true);
404 $this->assertEquals(array('foo', 'bar', 'basic'), $authReflectionProperty->getValue($client));
407 $this->assertEquals([], $headersReflectionProperty->getValue($client));
408 $this->assertNull($authReflectionProperty->getValue($client));