diff options
Diffstat (limited to 'www/wiki/tests/phpunit/includes/linkeddata/PageDataRequestHandlerTest.php')
-rw-r--r-- | www/wiki/tests/phpunit/includes/linkeddata/PageDataRequestHandlerTest.php | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/www/wiki/tests/phpunit/includes/linkeddata/PageDataRequestHandlerTest.php b/www/wiki/tests/phpunit/includes/linkeddata/PageDataRequestHandlerTest.php new file mode 100644 index 00000000..ad0c3d1e --- /dev/null +++ b/www/wiki/tests/phpunit/includes/linkeddata/PageDataRequestHandlerTest.php @@ -0,0 +1,284 @@ +<?php + +/** + * @covers PageDataRequestHandler + * @group PageData + */ +class PageDataRequestHandlerTest extends \MediaWikiTestCase { + + /** + * @var Title + */ + private $interfaceTitle; + + /** + * @var int + */ + private $obLevel; + + protected function setUp() { + parent::setUp(); + + $this->interfaceTitle = Title::newFromText( "Special:PageDataRequestHandlerTest" ); + + $this->obLevel = ob_get_level(); + } + + protected function tearDown() { + $obLevel = ob_get_level(); + + while ( ob_get_level() > $this->obLevel ) { + ob_end_clean(); + } + + if ( $obLevel !== $this->obLevel ) { + $this->fail( "Test changed output buffer level: was {$this->obLevel}" . + "before test, but $obLevel after test." + ); + } + + parent::tearDown(); + } + + /** + * @return PageDataRequestHandler + */ + protected function newHandler() { + return new PageDataRequestHandler( 'json' ); + } + + /** + * @param array $params + * @param string[] $headers + * + * @return OutputPage + */ + protected function makeOutputPage( array $params, array $headers ) { + // construct request + $request = new FauxRequest( $params ); + $request->response()->header( 'Status: 200 OK', true, 200 ); // init/reset + + foreach ( $headers as $name => $value ) { + $request->setHeader( strtoupper( $name ), $value ); + } + + // construct Context and OutputPage + $context = new DerivativeContext( RequestContext::getMain() ); + $context->setRequest( $request ); + + $output = new OutputPage( $context ); + $output->setTitle( $this->interfaceTitle ); + $context->setOutput( $output ); + + return $output; + } + + public function handleRequestProvider() { + $cases = []; + + $cases[] = [ '', [], [], '!!', 400 ]; + + $cases[] = [ '', [ 'target' => 'Helsinki' ], [], '!!', 303, [ 'Location' => '!.+!' ] ]; + + $subpageCases = []; + foreach ( $cases as $c ) { + $case = $c; + $case[0] = 'main/'; + + if ( isset( $case[1]['target'] ) ) { + $case[0] .= $case[1]['target']; + unset( $case[1]['target'] ); + } + + $subpageCases[] = $case; + } + + $cases = array_merge( $cases, $subpageCases ); + + $cases[] = [ + '', + [ 'target' => 'Helsinki' ], + [ 'Accept' => 'text/HTML' ], + '!!', + 303, + [ 'Location' => '!Helsinki$!' ] + ]; + + $cases[] = [ + '', + [ + 'target' => 'Helsinki', + 'revision' => '4242', + ], + [ 'Accept' => 'text/HTML' ], + '!!', + 303, + [ 'Location' => '!Helsinki(\?|&)oldid=4242!' ] + ]; + + $cases[] = [ + '/Helsinki', + [], + [], + '!!', + 303, + [ 'Location' => '!Helsinki&action=raw!' ] + ]; + + // #31: /Q5 with "Accept: text/foobar" triggers a 406 + $cases[] = [ + 'main/Helsinki', + [], + [ 'Accept' => 'text/foobar' ], + '!!', + 406, + [], + ]; + + $cases[] = [ + 'main/Helsinki', + [], + [ 'Accept' => 'text/HTML' ], + '!!', + 303, + [ 'Location' => '!Helsinki$!' ] + ]; + + $cases[] = [ + '/Helsinki', + [], + [ 'Accept' => 'text/HTML' ], + '!!', + 303, + [ 'Location' => '!Helsinki$!' ] + ]; + + $cases[] = [ + 'main/AC/DC', + [], + [ 'Accept' => 'text/HTML' ], + '!!', + 303, + [ 'Location' => '!AC/DC$!' ] + ]; + + return $cases; + } + + /** + * @dataProvider handleRequestProvider + * + * @param string $subpage The subpage to request (or '') + * @param array $params Request parameters + * @param array $headers Request headers + * @param string $expectedOutput Regex to match the output against. + * @param int $expectedStatusCode Expected HTTP status code. + * @param string[] $expectedHeaders Expected HTTP response headers. + */ + public function testHandleRequest( + $subpage, + array $params, + array $headers, + $expectedOutput, + $expectedStatusCode = 200, + array $expectedHeaders = [] + ) { + $output = $this->makeOutputPage( $params, $headers ); + $request = $output->getRequest(); + + /* @var FauxResponse $response */ + $response = $request->response(); + + // construct handler + $handler = $this->newHandler(); + + try { + ob_start(); + $handler->handleRequest( $subpage, $request, $output ); + + if ( $output->getRedirect() !== '' ) { + // hack to apply redirect to web response + $output->output(); + } + + $text = ob_get_contents(); + ob_end_clean(); + + $this->assertEquals( $expectedStatusCode, $response->getStatusCode(), 'status code' ); + $this->assertRegExp( $expectedOutput, $text, 'output' ); + + foreach ( $expectedHeaders as $name => $exp ) { + $value = $response->getHeader( $name ); + $this->assertNotNull( $value, "header: $name" ); + $this->assertInternalType( 'string', $value, "header: $name" ); + $this->assertRegExp( $exp, $value, "header: $name" ); + } + } catch ( HttpError $e ) { + ob_end_clean(); + $this->assertEquals( $expectedStatusCode, $e->getStatusCode(), 'status code' ); + $this->assertRegExp( $expectedOutput, $e->getHTML(), 'error output' ); + } + + // We always set "Access-Control-Allow-Origin: *" + $this->assertSame( '*', $response->getHeader( 'Access-Control-Allow-Origin' ) ); + } + + public function provideHttpContentNegotiation() { + $helsinki = Title::newFromText( 'Helsinki' ); + return [ + 'Accept Header of HTML' => [ + $helsinki, + [ 'ACCEPT' => 'text/html' ], // headers + 'Helsinki' + ], + 'Accept Header without weights' => [ + $helsinki, + [ 'ACCEPT' => '*/*, text/html, text/x-wiki' ], + 'Helsinki&action=raw' + ], + 'Accept Header with weights' => [ + $helsinki, + [ 'ACCEPT' => 'text/*; q=0.5, text/json; q=0.7, application/rdf+xml; q=0.8' ], + 'Helsinki&action=raw' + ], + 'Accept Header accepting evertyhing and HTML' => [ + $helsinki, + [ 'ACCEPT' => 'text/html, */*' ], + 'Helsinki&action=raw' + ], + 'No Accept Header' => [ + $helsinki, + [], + 'Helsinki&action=raw' + ], + ]; + } + + /** + * @dataProvider provideHttpContentNegotiation + * + * @param Title $title + * @param array $headers Request headers + * @param string $expectedRedirectSuffix Expected suffix of the HTTP Location header. + * + * @throws HttpError + */ + public function testHttpContentNegotiation( + Title $title, + array $headers, + $expectedRedirectSuffix + ) { + /* @var FauxResponse $response */ + $output = $this->makeOutputPage( [], $headers ); + $request = $output->getRequest(); + + $handler = $this->newHandler(); + $handler->httpContentNegotiation( $request, $output, $title ); + + $this->assertStringEndsWith( + $expectedRedirectSuffix, + $output->getRedirect(), + 'redirect target' + ); + } +} |