linkeddata: Simplity PageDataRequestHandler test setup
[lhc/web/wiklou.git] / tests / phpunit / includes / linkeddata / PageDataRequestHandlerTest.php
1 <?php
2
3 /**
4 * @covers PageDataRequestHandler
5 * @group PageData
6 */
7 class PageDataRequestHandlerTest extends \MediaWikiLangTestCase {
8
9 /**
10 * @var Title
11 */
12 private $interfaceTitle;
13
14 /**
15 * @var int
16 */
17 private $obLevel;
18
19 protected function setUp() {
20 parent::setUp();
21
22 $this->interfaceTitle = Title::newFromText( __CLASS__ );
23 $this->obLevel = ob_get_level();
24
25 $this->setMwGlobals( 'wgArticlePath', '/wiki/$1' );
26 }
27
28 protected function tearDown() {
29 $obLevel = ob_get_level();
30
31 while ( ob_get_level() > $this->obLevel ) {
32 ob_end_clean();
33 }
34
35 if ( $obLevel !== $this->obLevel ) {
36 $this->fail( "Test changed output buffer level: was {$this->obLevel}" .
37 "before test, but $obLevel after test."
38 );
39 }
40
41 parent::tearDown();
42 }
43
44 /**
45 * @return PageDataRequestHandler
46 */
47 protected function newHandler() {
48 return new PageDataRequestHandler();
49 }
50
51 /**
52 * @param array $params
53 * @param string[] $headers
54 *
55 * @return OutputPage
56 */
57 protected function makeOutputPage( array $params, array $headers ) {
58 // construct request
59 $request = new FauxRequest( $params );
60 $request->response()->header( 'Status: 200 OK', true, 200 ); // init/reset
61
62 foreach ( $headers as $name => $value ) {
63 $request->setHeader( strtoupper( $name ), $value );
64 }
65
66 // construct Context and OutputPage
67 $context = new DerivativeContext( RequestContext::getMain() );
68 $context->setRequest( $request );
69
70 $output = new OutputPage( $context );
71 $output->setTitle( $this->interfaceTitle );
72 $context->setOutput( $output );
73
74 return $output;
75 }
76
77 public function handleRequestProvider() {
78 $cases = [];
79
80 $cases[] = [ '', [], [], 'Invalid title', 400 ];
81
82 $cases[] = [
83 '',
84 [ 'target' => 'Helsinki' ],
85 [],
86 '',
87 303,
88 [ 'Location' => '?title=Helsinki&action=raw' ]
89 ];
90
91 $subpageCases = [];
92 foreach ( $cases as $c ) {
93 $case = $c;
94 $case[0] = 'main/';
95
96 if ( isset( $case[1]['target'] ) ) {
97 $case[0] .= $case[1]['target'];
98 unset( $case[1]['target'] );
99 }
100
101 $subpageCases[] = $case;
102 }
103
104 $cases = array_merge( $cases, $subpageCases );
105
106 $cases[] = [
107 '',
108 [ 'target' => 'Helsinki' ],
109 [ 'Accept' => 'text/HTML' ],
110 '',
111 303,
112 [ 'Location' => '/wiki/Helsinki' ]
113 ];
114
115 $cases[] = [
116 '',
117 [
118 'target' => 'Helsinki',
119 'revision' => '4242',
120 ],
121 [ 'Accept' => 'text/HTML' ],
122 '',
123 303,
124 [ 'Location' => '?title=Helsinki&oldid=4242' ]
125 ];
126
127 $cases[] = [
128 '/Helsinki',
129 [],
130 [],
131 '',
132 303,
133 [ 'Location' => '?title=Helsinki&action=raw' ]
134 ];
135
136 // #31: /Q5 with "Accept: text/foobar" triggers a 406
137 $cases[] = [
138 'main/Helsinki',
139 [],
140 [ 'Accept' => 'text/foobar' ],
141 'No matching format found',
142 406,
143 ];
144
145 $cases[] = [
146 'no slash',
147 [],
148 [ 'Accept' => 'text/HTML' ],
149 'Invalid title',
150 400,
151 ];
152
153 $cases[] = [
154 'main',
155 [],
156 [ 'Accept' => 'text/HTML' ],
157 'Invalid title',
158 400,
159 ];
160
161 $cases[] = [
162 'xyz/Helsinki',
163 [],
164 [ 'Accept' => 'text/HTML' ],
165 'Invalid title',
166 400,
167 ];
168
169 $cases[] = [
170 'main/Helsinki',
171 [],
172 [ 'Accept' => 'text/HTML' ],
173 '',
174 303,
175 [ 'Location' => '/wiki/Helsinki' ]
176 ];
177
178 $cases[] = [
179 '/Helsinki',
180 [],
181 [ 'Accept' => 'text/HTML' ],
182 '',
183 303,
184 [ 'Location' => '/wiki/Helsinki' ]
185 ];
186
187 $cases[] = [
188 'main/AC/DC',
189 [],
190 [ 'Accept' => 'text/HTML' ],
191 '',
192 303,
193 [ 'Location' => '/wiki/AC/DC' ]
194 ];
195
196 return $cases;
197 }
198
199 /**
200 * @dataProvider handleRequestProvider
201 *
202 * @param string $subpage The subpage to request (or '')
203 * @param array $params Request parameters
204 * @param array $headers Request headers
205 * @param string $expectedOutput
206 * @param int $expectedStatusCode Expected HTTP status code.
207 * @param string[] $expectedHeaders Expected HTTP response headers.
208 */
209 public function testHandleRequest(
210 $subpage,
211 array $params,
212 array $headers,
213 $expectedOutput = '',
214 $expectedStatusCode = 200,
215 array $expectedHeaders = []
216 ) {
217 $output = $this->makeOutputPage( $params, $headers );
218 $request = $output->getRequest();
219
220 /* @var FauxResponse $response */
221 $response = $request->response();
222
223 // construct handler
224 $handler = $this->newHandler();
225
226 try {
227 ob_start();
228 $handler->handleRequest( $subpage, $request, $output );
229
230 if ( $output->getRedirect() !== '' ) {
231 // hack to apply redirect to web response
232 $output->output();
233 }
234
235 $text = ob_get_clean();
236
237 $this->assertEquals( $expectedStatusCode, $response->getStatusCode(), 'status code' );
238 $this->assertSame( $expectedOutput, $text, 'output' );
239
240 foreach ( $expectedHeaders as $name => $exp ) {
241 $value = $response->getHeader( $name );
242 $this->assertNotNull( $value, "header: $name" );
243 $this->assertInternalType( 'string', $value, "header: $name" );
244 $this->assertStringEndsWith( $exp, $value, "header: $name" );
245 }
246 } catch ( HttpError $e ) {
247 ob_end_clean();
248 $this->assertEquals( $expectedStatusCode, $e->getStatusCode(), 'status code' );
249 $this->assertContains( $expectedOutput, $e->getHTML(), 'error output' );
250 }
251
252 // We always set "Access-Control-Allow-Origin: *"
253 $this->assertSame( '*', $response->getHeader( 'Access-Control-Allow-Origin' ) );
254 }
255
256 public function provideHttpContentNegotiation() {
257 $helsinki = Title::newFromText( 'Helsinki' );
258 return [
259 'Accept Header of HTML' => [
260 $helsinki,
261 [ 'ACCEPT' => 'text/html' ], // headers
262 'Helsinki'
263 ],
264 'Accept Header without weights' => [
265 $helsinki,
266 [ 'ACCEPT' => '*/*, text/html, text/x-wiki' ],
267 'Helsinki&action=raw'
268 ],
269 'Accept Header with weights' => [
270 $helsinki,
271 [ 'ACCEPT' => 'text/*; q=0.5, text/json; q=0.7, application/rdf+xml; q=0.8' ],
272 'Helsinki&action=raw'
273 ],
274 'Accept Header accepting evertyhing and HTML' => [
275 $helsinki,
276 [ 'ACCEPT' => 'text/html, */*' ],
277 'Helsinki&action=raw'
278 ],
279 'No Accept Header' => [
280 $helsinki,
281 [],
282 'Helsinki&action=raw'
283 ],
284 ];
285 }
286
287 /**
288 * @dataProvider provideHttpContentNegotiation
289 *
290 * @param Title $title
291 * @param array $headers Request headers
292 * @param string $expectedRedirectSuffix Expected suffix of the HTTP Location header.
293 *
294 * @throws HttpError
295 */
296 public function testHttpContentNegotiation(
297 Title $title,
298 array $headers,
299 $expectedRedirectSuffix
300 ) {
301 /* @var FauxResponse $response */
302 $output = $this->makeOutputPage( [], $headers );
303 $request = $output->getRequest();
304
305 $handler = $this->newHandler();
306 $handler->httpContentNegotiation( $request, $output, $title );
307
308 $this->assertStringEndsWith(
309 $expectedRedirectSuffix,
310 $output->getRedirect(),
311 'redirect target'
312 );
313 }
314 }