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