Most notably this gets rid of all regular expressions and replaces them with straight string comparisons. This is mostly done for readability, but also makes the test more independend from the setup of the server that is running the test. Change-Id: I8c34cf1756c8e6c126b95b3eda163561d53186b9
314 lines
6.5 KiB
PHP
314 lines
6.5 KiB
PHP
<?php
|
|
|
|
/**
|
|
* @covers PageDataRequestHandler
|
|
* @group PageData
|
|
*/
|
|
class PageDataRequestHandlerTest extends \MediaWikiLangTestCase {
|
|
|
|
/**
|
|
* @var Title
|
|
*/
|
|
private $interfaceTitle;
|
|
|
|
/**
|
|
* @var int
|
|
*/
|
|
private $obLevel;
|
|
|
|
protected function setUp() {
|
|
parent::setUp();
|
|
|
|
$this->interfaceTitle = Title::newFromText( __CLASS__ );
|
|
$this->obLevel = ob_get_level();
|
|
|
|
$this->setMwGlobals( 'wgArticlePath', '/wiki/$1' );
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
/**
|
|
* @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[] = [ '', [], [], 'Invalid title', 400 ];
|
|
|
|
$cases[] = [
|
|
'',
|
|
[ 'target' => 'Helsinki' ],
|
|
[],
|
|
'',
|
|
303,
|
|
[ 'Location' => '?title=Helsinki&action=raw' ]
|
|
];
|
|
|
|
$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' => '/wiki/Helsinki' ]
|
|
];
|
|
|
|
$cases[] = [
|
|
'',
|
|
[
|
|
'target' => 'Helsinki',
|
|
'revision' => '4242',
|
|
],
|
|
[ 'Accept' => 'text/HTML' ],
|
|
'',
|
|
303,
|
|
[ 'Location' => '?title=Helsinki&oldid=4242' ]
|
|
];
|
|
|
|
$cases[] = [
|
|
'/Helsinki',
|
|
[],
|
|
[],
|
|
'',
|
|
303,
|
|
[ 'Location' => '?title=Helsinki&action=raw' ]
|
|
];
|
|
|
|
// #31: /Q5 with "Accept: text/foobar" triggers a 406
|
|
$cases[] = [
|
|
'main/Helsinki',
|
|
[],
|
|
[ 'Accept' => 'text/foobar' ],
|
|
'No matching format found',
|
|
406,
|
|
];
|
|
|
|
$cases[] = [
|
|
'no slash',
|
|
[],
|
|
[ 'Accept' => 'text/HTML' ],
|
|
'Invalid title',
|
|
400,
|
|
];
|
|
|
|
$cases[] = [
|
|
'main',
|
|
[],
|
|
[ 'Accept' => 'text/HTML' ],
|
|
'Invalid title',
|
|
400,
|
|
];
|
|
|
|
$cases[] = [
|
|
'xyz/Helsinki',
|
|
[],
|
|
[ 'Accept' => 'text/HTML' ],
|
|
'Invalid title',
|
|
400,
|
|
];
|
|
|
|
$cases[] = [
|
|
'main/Helsinki',
|
|
[],
|
|
[ 'Accept' => 'text/HTML' ],
|
|
'',
|
|
303,
|
|
[ 'Location' => '/wiki/Helsinki' ]
|
|
];
|
|
|
|
$cases[] = [
|
|
'/Helsinki',
|
|
[],
|
|
[ 'Accept' => 'text/HTML' ],
|
|
'',
|
|
303,
|
|
[ 'Location' => '/wiki/Helsinki' ]
|
|
];
|
|
|
|
$cases[] = [
|
|
'main/AC/DC',
|
|
[],
|
|
[ 'Accept' => 'text/HTML' ],
|
|
'',
|
|
303,
|
|
[ 'Location' => '/wiki/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
|
|
* @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_clean();
|
|
|
|
$this->assertEquals( $expectedStatusCode, $response->getStatusCode(), 'status code' );
|
|
$this->assertSame( $expectedOutput, $text, 'output' );
|
|
|
|
foreach ( $expectedHeaders as $name => $exp ) {
|
|
$value = $response->getHeader( $name );
|
|
$this->assertNotNull( $value, "header: $name" );
|
|
$this->assertInternalType( 'string', $value, "header: $name" );
|
|
$this->assertStringEndsWith( $exp, $value, "header: $name" );
|
|
}
|
|
} catch ( HttpError $e ) {
|
|
ob_end_clean();
|
|
$this->assertEquals( $expectedStatusCode, $e->getStatusCode(), 'status code' );
|
|
$this->assertContains( $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'
|
|
);
|
|
}
|
|
}
|