REST: Testable EntryPoint

* Split EntryPoint into a static main() and a non-static execute()
* Add tests for execute()

Change-Id: I025356b04ddc5a16494f98c446d785d6bb05ab10
This commit is contained in:
Tim Starling 2019-06-05 09:59:57 +10:00
parent f1c11c2c49
commit 4e0e36397c
5 changed files with 134 additions and 13 deletions

View file

@ -6,8 +6,16 @@ use ExtensionRegistry;
use MediaWiki\MediaWikiServices;
use RequestContext;
use Title;
use WebResponse;
class EntryPoint {
/** @var RequestInterface */
private $request;
/** @var WebResponse */
private $webResponse;
/** @var Router */
private $router;
public static function main() {
// URL safety checks
global $wgRequest;
@ -21,8 +29,8 @@ class EntryPoint {
RequestContext::getMain()->setTitle( $wgTitle );
$services = MediaWikiServices::getInstance();
$conf = $services->getMainConfig();
$request = new RequestFromGlobals( [
'cookiePrefix' => $conf->get( 'CookiePrefix' )
] );
@ -36,20 +44,35 @@ class EntryPoint {
new ResponseFactory
);
$response = $router->execute( $request );
$entryPoint = new self(
$request,
$wgRequest->response(),
$router );
$entryPoint->execute();
}
$webResponse = $wgRequest->response();
$webResponse->header(
public function __construct( RequestInterface $request, WebResponse $webResponse,
Router $router
) {
$this->request = $request;
$this->webResponse = $webResponse;
$this->router = $router;
}
public function execute() {
$response = $this->router->execute( $this->request );
$this->webResponse->header(
'HTTP/' . $response->getProtocolVersion() . ' ' .
$response->getStatusCode() . ' ' .
$response->getReasonPhrase() );
foreach ( $response->getRawHeaderLines() as $line ) {
$webResponse->header( $line );
$this->webResponse->header( $line );
}
foreach ( $response->getCookies() as $cookie ) {
$webResponse->setCookie(
$this->webResponse->setCookie(
$cookie['name'],
$cookie['value'],
$cookie['expiry'],

View file

@ -0,0 +1,90 @@
<?php
namespace MediaWiki\Tests\Rest;
use EmptyBagOStuff;
use GuzzleHttp\Psr7\Uri;
use GuzzleHttp\Psr7\Stream;
use MediaWiki\Rest\Handler;
use MediaWikiTestCase;
use MediaWiki\Rest\EntryPoint;
use MediaWiki\Rest\RequestData;
use MediaWiki\Rest\ResponseFactory;
use MediaWiki\Rest\Router;
use WebResponse;
/**
* @covers \MediaWiki\Rest\EntryPoint
* @covers \MediaWiki\Rest\Router
*/
class EntryPointTest extends MediaWikiTestCase {
private static $mockHandler;
private function createRouter() {
return new Router(
[ __DIR__ . '/testRoutes.json' ],
[],
'/rest',
new EmptyBagOStuff(),
new ResponseFactory() );
}
private function createWebResponse() {
return $this->getMockBuilder( WebResponse::class )
->setMethods( [ 'header' ] )
->getMock();
}
public static function mockHandlerHeader() {
return new class extends Handler {
public function execute() {
$response = $this->getResponseFactory()->create();
$response->setHeader( 'Foo', 'Bar' );
return $response;
}
};
}
public function testHeader() {
$webResponse = $this->createWebResponse();
$webResponse->expects( $this->any() )
->method( 'header' )
->withConsecutive(
[ 'HTTP/1.1 200 OK', true, null ],
[ 'Foo: Bar', true, null ]
);
$entryPoint = new EntryPoint(
new RequestData( [ 'uri' => new Uri( '/rest/mock/EntryPoint/header' ) ] ),
$webResponse,
$this->createRouter() );
$entryPoint->execute();
$this->assertTrue( true );
}
public static function mockHandlerBodyRewind() {
return new class extends Handler {
public function execute() {
$response = $this->getResponseFactory()->create();
$stream = new Stream( fopen( 'php://memory', 'w+' ) );
$stream->write( 'hello' );
$response->setBody( $stream );
return $response;
}
};
}
/**
* Make sure EntryPoint rewinds a seekable body stream before reading.
*/
public function testBodyRewind() {
$entryPoint = new EntryPoint(
new RequestData( [ 'uri' => new Uri( '/rest/mock/EntryPoint/bodyRewind' ) ] ),
$this->createWebResponse(),
$this->createRouter() );
ob_start();
$entryPoint->execute();
$this->assertSame( 'hello', ob_get_clean() );
}
}

View file

@ -49,7 +49,7 @@ class HelloHandlerTest extends MediaWikiTestCase {
/** @dataProvider provideTestViaRouter */
public function testViaRouter( $requestInfo, $responseInfo ) {
$router = new Router(
[ __DIR__ . '/testRoutes.json' ],
[ __DIR__ . '/../testRoutes.json' ],
[],
'/rest',
new EmptyBagOStuff(),

View file

@ -1,6 +0,0 @@
[
{
"path": "/user/{name}/hello",
"class": "MediaWiki\\Rest\\Handler\\HelloHandler"
}
]

View file

@ -0,0 +1,14 @@
[
{
"path": "/user/{name}/hello",
"class": "MediaWiki\\Rest\\Handler\\HelloHandler"
},
{
"path": "/mock/EntryPoint/header",
"factory": "MediaWiki\\Tests\\Rest\\EntryPointTest::mockHandlerHeader"
},
{
"path": "/mock/EntryPoint/bodyRewind",
"factory": "MediaWiki\\Tests\\Rest\\EntryPointTest::mockHandlerBodyRewind"
}
]