Merge "tests: Add unit tests for OutputPage::transformResourcePath"
[lhc/web/wiklou.git] / tests / integration / includes / http / MWHttpRequestTestCase.php
1 <?php
2
3 class MWHttpRequestTestCase extends PHPUnit_Framework_TestCase {
4 protected static $httpEngine;
5 protected $oldHttpEngine;
6
7 public function setUp() {
8 parent::setUp();
9 $this->oldHttpEngine = Http::$httpEngine;
10 Http::$httpEngine = static::$httpEngine;
11
12 try {
13 $request = MWHttpRequest::factory( 'null:' );
14 } catch ( DomainException $e ) {
15 $this->markTestSkipped( static::$httpEngine . ' engine not supported' );
16 }
17
18 if ( static::$httpEngine === 'php' ) {
19 $this->assertInstanceOf( PhpHttpRequest::class, $request );
20 } else {
21 $this->assertInstanceOf( CurlHttpRequest::class, $request );
22 }
23 }
24
25 public function tearDown() {
26 parent::tearDown();
27 Http::$httpEngine = $this->oldHttpEngine;
28 }
29
30 // --------------------
31
32 public function testIsRedirect() {
33 $request = MWHttpRequest::factory( 'http://httpbin.org/get' );
34 $status = $request->execute();
35 $this->assertTrue( $status->isGood() );
36 $this->assertFalse( $request->isRedirect() );
37
38 $request = MWHttpRequest::factory( 'http://httpbin.org/redirect/1' );
39 $status = $request->execute();
40 $this->assertTrue( $status->isGood() );
41 $this->assertTrue( $request->isRedirect() );
42 }
43
44 public function testgetFinalUrl() {
45 $request = MWHttpRequest::factory( 'http://httpbin.org/redirect/3' );
46 if ( !$request->canFollowRedirects() ) {
47 $this->markTestSkipped( 'cannot follow redirects' );
48 }
49 $status = $request->execute();
50 $this->assertTrue( $status->isGood() );
51 $this->assertNotSame( 'http://httpbin.org/get', $request->getFinalUrl() );
52
53 $request = MWHttpRequest::factory( 'http://httpbin.org/redirect/3', [ 'followRedirects'
54 => true ] );
55 $status = $request->execute();
56 $this->assertTrue( $status->isGood() );
57 $this->assertSame( 'http://httpbin.org/get', $request->getFinalUrl() );
58 $this->assertResponseFieldValue( 'url', 'http://httpbin.org/get', $request );
59
60 $request = MWHttpRequest::factory( 'http://httpbin.org/redirect/3', [ 'followRedirects'
61 => true ] );
62 $status = $request->execute();
63 $this->assertTrue( $status->isGood() );
64 $this->assertSame( 'http://httpbin.org/get', $request->getFinalUrl() );
65 $this->assertResponseFieldValue( 'url', 'http://httpbin.org/get', $request );
66
67 if ( static::$httpEngine === 'curl' ) {
68 $this->markTestIncomplete( 'maxRedirects seems to be ignored by CurlHttpRequest' );
69 return;
70 }
71
72 $request = MWHttpRequest::factory( 'http://httpbin.org/redirect/3', [ 'followRedirects'
73 => true, 'maxRedirects' => 1 ] );
74 $status = $request->execute();
75 $this->assertTrue( $status->isGood() );
76 $this->assertNotSame( 'http://httpbin.org/get', $request->getFinalUrl() );
77 }
78
79 public function testSetCookie() {
80 $request = MWHttpRequest::factory( 'http://httpbin.org/cookies' );
81 $request->setCookie( 'foo', 'bar' );
82 $request->setCookie( 'foo2', 'bar2', [ 'domain' => 'example.com' ] );
83 $status = $request->execute();
84 $this->assertTrue( $status->isGood() );
85 $this->assertResponseFieldValue( 'cookies', [ 'foo' => 'bar' ], $request );
86 }
87
88 public function testSetCookieJar() {
89 $request = MWHttpRequest::factory( 'http://httpbin.org/cookies' );
90 $cookieJar = new CookieJar();
91 $cookieJar->setCookie( 'foo', 'bar', [ 'domain' => 'httpbin.org' ] );
92 $cookieJar->setCookie( 'foo2', 'bar2', [ 'domain' => 'example.com' ] );
93 $request->setCookieJar( $cookieJar );
94 $status = $request->execute();
95 $this->assertTrue( $status->isGood() );
96 $this->assertResponseFieldValue( 'cookies', [ 'foo' => 'bar' ], $request );
97
98 $request = MWHttpRequest::factory( 'http://httpbin.org/cookies/set?foo=bar' );
99 $cookieJar = new CookieJar();
100 $request->setCookieJar( $cookieJar );
101 $status = $request->execute();
102 $this->assertTrue( $status->isGood() );
103 $this->assertHasCookie( 'foo', 'bar', $request->getCookieJar() );
104
105 $this->markTestIncomplete( 'CookieJar does not handle deletion' );
106 return;
107
108 $request = MWHttpRequest::factory( 'http://httpbin.org/cookies/delete?foo' );
109 $cookieJar = new CookieJar();
110 $cookieJar->setCookie( 'foo', 'bar', [ 'domain' => 'httpbin.org' ] );
111 $cookieJar->setCookie( 'foo2', 'bar2', [ 'domain' => 'httpbin.org' ] );
112 $request->setCookieJar( $cookieJar );
113 $status = $request->execute();
114 $this->assertTrue( $status->isGood() );
115 $this->assertNotHasCookie( 'foo', $request->getCookieJar() );
116 $this->assertHasCookie( 'foo2', 'bar2', $request->getCookieJar() );
117 }
118
119 public function testGetResponseHeaders() {
120 $request = MWHttpRequest::factory( 'http://httpbin.org/response-headers?Foo=bar' );
121 $status = $request->execute();
122 $this->assertTrue( $status->isGood() );
123 $headers = array_change_key_case( $request->getResponseHeaders(), CASE_LOWER );
124 $this->assertArrayHasKey( 'foo', $headers );
125 $this->assertSame( $request->getResponseHeader( 'Foo' ), 'bar' );
126 }
127
128 public function testSetHeader() {
129 $request = MWHttpRequest::factory( 'http://httpbin.org/headers' );
130 $request->setHeader( 'Foo', 'bar' );
131 $status = $request->execute();
132 $this->assertTrue( $status->isGood() );
133 $this->assertResponseFieldValue( [ 'headers', 'Foo' ], 'bar', $request );
134 }
135
136 public function testGetStatus() {
137 $request = MWHttpRequest::factory( 'http://httpbin.org/status/418' );
138 $status = $request->execute();
139 $this->assertFalse( $status->isOK() );
140 $this->assertSame( $request->getStatus(), 418 );
141 }
142
143 public function testSetUserAgent() {
144 $request = MWHttpRequest::factory( 'http://httpbin.org/user-agent' );
145 $request->setUserAgent( 'foo' );
146 $status = $request->execute();
147 $this->assertTrue( $status->isGood() );
148 $this->assertResponseFieldValue( 'user-agent', 'foo', $request );
149 }
150
151 public function testSetData() {
152 $request = MWHttpRequest::factory( 'http://httpbin.org/post', [ 'method' => 'POST' ] );
153 $request->setData( [ 'foo' => 'bar', 'foo2' => 'bar2' ] );
154 $status = $request->execute();
155 $this->assertTrue( $status->isGood() );
156 $this->assertResponseFieldValue( 'form', [ 'foo' => 'bar', 'foo2' => 'bar2' ], $request );
157 }
158
159 public function testSetCallback() {
160 if ( static::$httpEngine === 'php' ) {
161 $this->markTestIncomplete( 'PhpHttpRequest does not use setCallback()' );
162 return;
163 }
164
165 $request = MWHttpRequest::factory( 'http://httpbin.org/ip' );
166 $data = '';
167 $request->setCallback( function ( $fh, $content ) use ( &$data ) {
168 $data .= $content;
169 return strlen( $content );
170 } );
171 $status = $request->execute();
172 $this->assertTrue( $status->isGood() );
173 $data = json_decode( $data, true );
174 $this->assertInternalType( 'array', $data );
175 $this->assertArrayHasKey( 'origin', $data );
176 }
177
178 public function testBasicAuthentication() {
179 $request = MWHttpRequest::factory( 'http://httpbin.org/basic-auth/user/pass', [
180 'username' => 'user',
181 'password' => 'pass',
182 ] );
183 $status = $request->execute();
184 $this->assertTrue( $status->isGood() );
185 $this->assertResponseFieldValue( 'authenticated', true, $request );
186
187 $request = MWHttpRequest::factory( 'http://httpbin.org/basic-auth/user/pass', [
188 'username' => 'user',
189 'password' => 'wrongpass',
190 ] );
191 $status = $request->execute();
192 $this->assertFalse( $status->isOK() );
193 $this->assertSame( 401, $request->getStatus() );
194 }
195
196 // --------------------
197
198 /**
199 * Verifies that the request was successful, returned valid JSON and the given field of that
200 * JSON data is as expected.
201 * @param string|string[] $key Path to the data in the response object
202 * @param mixed $expectedValue
203 * @param MWHttpRequest $response
204 */
205 protected function assertResponseFieldValue( $key, $expectedValue, MWHttpRequest $response ) {
206 $this->assertSame( 200, $response->getStatus(), 'response status is not 200' );
207 $data = json_decode( $response->getContent(), true );
208 $this->assertInternalType( 'array', $data, 'response is not JSON' );
209 $keyPath = '';
210 foreach ( (array)$key as $keySegment ) {
211 $keyPath .= ( $keyPath ? '.' : '' ) . $keySegment;
212 $this->assertArrayHasKey( $keySegment, $data, $keyPath . ' not found' );
213 $data = $data[$keySegment];
214 }
215 $this->assertSame( $expectedValue, $data );
216 }
217
218 /**
219 * Asserts that the cookie jar has the given cookie with the given value.
220 * @param string $expectedName Cookie name
221 * @param string $expectedValue Cookie value
222 * @param CookieJar $cookieJar
223 */
224 protected function assertHasCookie( $expectedName, $expectedValue, CookieJar $cookieJar ) {
225 $cookieJar = TestingAccessWrapper::newFromObject( $cookieJar );
226 $cookies = array_change_key_case( $cookieJar->cookie, CASE_LOWER );
227 $this->assertArrayHasKey( strtolower( $expectedName ), $cookies );
228 $cookie = TestingAccessWrapper::newFromObject(
229 $cookies[strtolower( $expectedName )] );
230 $this->assertSame( $expectedValue, $cookie->value );
231 }
232
233 /**
234 * Asserts that the cookie jar does not have the given cookie.
235 * @param string $expectedName Cookie name
236 * @param CookieJar $cookieJar
237 */
238 protected function assertNotHasCookie( $name, CookieJar $cookieJar ) {
239 $cookieJar = TestingAccessWrapper::newFromObject( $cookieJar );
240 $this->assertArrayNotHasKey( strtolower( $name ),
241 array_change_key_case( $cookieJar->cookie, CASE_LOWER ) );
242 }
243 }