aboutsummaryrefslogtreecommitdiffstats
path: root/tests/phpunit
diff options
context:
space:
mode:
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>2020-05-26 10:53:00 +0000
committerGerrit Code Review <gerrit@wikimedia.org>2020-05-26 10:53:00 +0000
commit9d1bd65aa27a234079fe4959fa13cb0daf5a22a5 (patch)
tree9762c2cef5869cfd9bd4dc261f5192462f5944c0 /tests/phpunit
parent4602f8db2dcc486ead043a9b882c9dc1ff35343f (diff)
parentad6879e6b64affc8f40121ec53c29fb4474e4adc (diff)
downloadmediawikicore-9d1bd65aa27a234079fe4959fa13cb0daf5a22a5.tar.gz
mediawikicore-9d1bd65aa27a234079fe4959fa13cb0daf5a22a5.zip
Merge "REST Handler: add unit tests for base class"
Diffstat (limited to 'tests/phpunit')
-rw-r--r--tests/phpunit/unit/includes/Rest/Handler/HandlerTest.php235
-rw-r--r--tests/phpunit/unit/includes/Rest/Handler/HandlerTestTrait.php47
2 files changed, 269 insertions, 13 deletions
diff --git a/tests/phpunit/unit/includes/Rest/Handler/HandlerTest.php b/tests/phpunit/unit/includes/Rest/Handler/HandlerTest.php
new file mode 100644
index 000000000000..4847ef9209c4
--- /dev/null
+++ b/tests/phpunit/unit/includes/Rest/Handler/HandlerTest.php
@@ -0,0 +1,235 @@
+<?php
+
+namespace MediaWiki\Tests\Rest\Handler;
+
+use MediaWiki\Rest\ConditionalHeaderUtil;
+use MediaWiki\Rest\Handler;
+use MediaWiki\Rest\LocalizedHttpException;
+use MediaWiki\Rest\RequestData;
+use MediaWiki\Rest\ResponseFactory;
+use MediaWiki\Rest\ResponseInterface;
+use MediaWiki\Rest\Router;
+use MediaWiki\Rest\Validator\BodyValidator;
+use MediaWiki\Rest\Validator\Validator;
+use PHPUnit\Framework\MockObject\MockObject;
+use Wikimedia\ParamValidator\ParamValidator;
+use Wikimedia\TestingAccessWrapper;
+
+/**
+ * @covers \MediaWiki\Rest\Handler\SearchHandler
+ */
+class HandlerTest extends \MediaWikiUnitTestCase {
+
+ use HandlerTestTrait;
+
+ /**
+ * @param string[] $methods
+ *
+ * @return Handler|MockObject
+ */
+ private function newHandler( $methods = [] ) {
+ $methods = array_merge( $methods, [ 'execute' ] );
+ /** @var Handler|MockObject $handler */
+ $handler = $this->getMockBuilder( Handler::class )
+ ->onlyMethods( $methods )
+ ->getMock();
+ $handler->method( 'execute' )->willReturn( (object)[] );
+
+ return $handler;
+ }
+
+ public function testGetRouter() {
+ $handler = $this->newHandler();
+ $this->initHandler( $handler, new RequestData() );
+
+ $handler = TestingAccessWrapper::newFromObject( $handler );
+ $this->assertInstanceOf( Router::class, $handler->getRouter() );
+ }
+
+ public function testGetResponseFactory() {
+ $handler = $this->newHandler();
+ $this->initHandler( $handler, new RequestData() );
+
+ $this->assertInstanceOf( ResponseFactory::class, $handler->getResponseFactory() );
+ }
+
+ public function testGetConditionalHeaderUtil() {
+ $handler = $this->newHandler();
+ $this->initHandler( $handler, new RequestData() );
+
+ $handler = TestingAccessWrapper::newFromObject( $handler );
+ $this->assertInstanceOf( ConditionalHeaderUtil::class, $handler->getConditionalHeaderUtil() );
+ }
+
+ public function provideCheckPreconditions() {
+ yield 'no status' => [ null ];
+ yield 'a status' => [ 444 ];
+ }
+
+ /**
+ * @dataProvider provideCheckPreconditions
+ */
+ public function testCheckPreconditions( $status ) {
+ $request = new RequestData();
+
+ $util = $this->createNoOpMock( ConditionalHeaderUtil::class, [ 'checkPreconditions' ] );
+ $util->method( 'checkPreconditions' )->with( $request )->willReturn( $status );
+
+ $handler = $this->newHandler( [ 'getConditionalHeaderUtil' ] );
+ $handler->method( 'getConditionalHeaderUtil' )->willReturn( $util );
+
+ $this->initHandler( $handler, $request );
+ $resp = $handler->checkPreconditions();
+
+ $responseStatus = $resp ? $resp->getStatusCode() : null;
+ $this->assertSame( $status, $responseStatus );
+ }
+
+ public function testApplyConditionalResponseHeaders() {
+ $util = $this->createNoOpMock( ConditionalHeaderUtil::class, [ 'applyResponseHeaders' ] );
+ $util->method( 'applyResponseHeaders' )->willReturnCallback(
+ function ( ResponseInterface $response ) {
+ $response->setHeader( 'Testing', 'foo' );
+ }
+ );
+
+ $handler = $this->newHandler( [ 'getConditionalHeaderUtil' ] );
+ $handler->method( 'getConditionalHeaderUtil' )->willReturn( $util );
+
+ $this->initHandler( $handler, new RequestData() );
+ $response = $handler->getResponseFactory()->create();
+ $handler->applyConditionalResponseHeaders( $response );
+
+ $this->assertSame( 'foo', $response->getHeaderLine( 'Testing' ) );
+ }
+
+ public function provideValidate() {
+ yield 'empty' => [ [], new RequestData(), [] ];
+
+ yield 'parameter' => [
+ [
+ 'foo' => [
+ ParamValidator::PARAM_TYPE => 'string',
+ ParamValidator::PARAM_REQUIRED => true,
+ Handler::PARAM_SOURCE => 'query',
+ ]
+ ],
+ new RequestData( [ 'queryParams' => [ 'foo' => 'kittens' ] ] ),
+ [ 'foo' => 'kittens' ]
+ ];
+ }
+
+ /**
+ * @dataProvider provideValidate
+ */
+ public function testValidate( $paramSettings, $request, $expected ) {
+ $handler = $this->newHandler( [ 'getParamSettings' ] );
+ $handler->method( 'getParamSettings' )->willReturn( $paramSettings );
+
+ $this->initHandler( $handler, $request );
+ $this->validateHandler( $handler );
+
+ $params = $handler->getValidatedParams();
+ $this->assertSame( $expected, $params );
+ }
+
+ public function provideValidate_invalid() {
+ $paramSettings = [
+ 'foo' => [
+ ParamValidator::PARAM_TYPE => 'string',
+ ParamValidator::PARAM_REQUIRED => true,
+ Handler::PARAM_SOURCE => 'query',
+ ]
+ ];
+
+ $request = new RequestData( [ 'queryParams' => [ 'bar' => 'kittens' ] ] );
+
+ $handler = $this->newHandler( [ 'getParamSettings' ] );
+ $handler->method( 'getParamSettings' )->willReturn( $paramSettings );
+
+ try {
+ $this->initHandler( $handler, $request );
+ $this->validateHandler( $handler );
+ $this->fail( 'Expected LocalizedHttpException' );
+ } catch ( LocalizedHttpException $ex ) {
+ $this->assertSame( 'paramvalidator-missingparam', $ex->getMessageValue()->getKey() );
+ }
+ }
+
+ public function testGetValidatedBody() {
+ $validator = $this->createMock( Validator::class );
+ $validator->method( 'validateBody' )->willReturn( 'VALIDATED BODY' );
+
+ $handler = $this->newHandler();
+ $this->initHandler( $handler, new RequestData() );
+ $handler->validate( $validator );
+
+ $body = $handler->getValidatedBody();
+ $this->assertSame( 'VALIDATED BODY', $body );
+ }
+
+ public function testGetRequest() {
+ $handler = $this->newHandler();
+ $request = new RequestData();
+ $this->initHandler( $handler, $request );
+
+ $this->assertSame( $request, $handler->getRequest() );
+ }
+
+ public function testGetConfig() {
+ $handler = $this->newHandler();
+ $config = [ 'foo' => 'bar' ];
+ $this->initHandler( $handler, new RequestData(), $config );
+
+ $this->assertSame( $config, $handler->getConfig() );
+ }
+
+ public function testGetBodyValidator() {
+ $handler = $this->newHandler();
+ $this->assertInstanceOf(
+ BodyValidator::class,
+ $handler->getBodyValidator( 'unknown/unknown' )
+ );
+ }
+
+ public function testThatGetParamSettingsReturnsNothingPerDefault() {
+ $handler = $this->newHandler();
+ $this->assertSame( [], $handler->getParamSettings() );
+ }
+
+ public function testThatGetLastModifiedReturnsNullPerDefault() {
+ $handler = $this->newHandler();
+
+ $handler = TestingAccessWrapper::newFromObject( $handler );
+ $this->assertNull( $handler->getLastModified() );
+ }
+
+ public function testThatGetETagReturnsNullPerDefault() {
+ $handler = $this->newHandler();
+
+ $handler = TestingAccessWrapper::newFromObject( $handler );
+ $this->assertNull( $handler->getETag() );
+ }
+
+ public function testThatHasRepresentationReturnsNullPerDefault() {
+ $handler = $this->newHandler();
+
+ $handler = TestingAccessWrapper::newFromObject( $handler );
+ $this->assertNull( $handler->hasRepresentation() );
+ }
+
+ public function testThatNeedsReadAccessReturnsTruePerDefault() {
+ $handler = $this->newHandler();
+
+ $handler = TestingAccessWrapper::newFromObject( $handler );
+ $this->assertTrue( $handler->needsReadAccess() );
+ }
+
+ public function testThatNeedsWriteAccessReturnsTruePerDefault() {
+ $handler = $this->newHandler();
+
+ $handler = TestingAccessWrapper::newFromObject( $handler );
+ $this->assertTrue( $handler->needsWriteAccess() );
+ }
+
+}
diff --git a/tests/phpunit/unit/includes/Rest/Handler/HandlerTestTrait.php b/tests/phpunit/unit/includes/Rest/Handler/HandlerTestTrait.php
index 16ad9411cd82..46d288f3afd4 100644
--- a/tests/phpunit/unit/includes/Rest/Handler/HandlerTestTrait.php
+++ b/tests/phpunit/unit/includes/Rest/Handler/HandlerTestTrait.php
@@ -52,15 +52,13 @@ trait HandlerTestTrait {
abstract protected function createMock( $originalClassName ): MockObject;
/**
- * Executes the given Handler on the given request.
+ * Calls init() on the Handler, supplying a mock Router and ResponseFactory.
*
* @param Handler $handler
* @param RequestInterface $request
* @param array $config
- *
- * @return ResponseInterface
*/
- private function executeHandler( Handler $handler, RequestInterface $request, $config = [] ) {
+ private function initHandler( Handler $handler, RequestInterface $request, $config = [] ) {
$formatter = $this->createMock( ITextFormatter::class );
$formatter->method( 'format' )->willReturnCallback( function ( MessageValue $msg ) {
return $msg->dump();
@@ -69,6 +67,21 @@ trait HandlerTestTrait {
/** @var ResponseFactory|MockObject $responseFactory */
$responseFactory = new ResponseFactory( [ 'qqx' => $formatter ] );
+ /** @var Router|MockObject $router */
+ $router = $this->createNoOpMock( Router::class, [ 'getRouteUrl' ] );
+ $router->method( 'getRouteUrl' )->willReturnCallback( function ( $route, $query = [] ) {
+ return wfAppendQuery( 'https://wiki.example.com/rest' . $route, $query );
+ } );
+
+ $handler->init( $router, $request, $config, $responseFactory );
+ }
+
+ /**
+ * Calls validate() on the Handler, with an appropriate Validator supplied.
+ *
+ * @param Handler $handler
+ */
+ private function validateHandler( Handler $handler ) {
/** @var PermissionManager|MockObject $permissionManager */
$permissionManager = $this->createNoOpMock(
PermissionManager::class, [ 'userCan', 'userHasRight' ]
@@ -81,16 +94,24 @@ trait HandlerTestTrait {
$objectFactory = new ObjectFactory( $serviceContainer );
$user = new UserIdentityValue( 0, 'Fake User', 0 );
- $validator = new Validator( $objectFactory, $permissionManager, $request, $user );
-
- /** @var Router|MockObject $router */
- $router = $this->createNoOpMock( Router::class, [ 'getRouteUrl' ] );
- $router->method( 'getRouteUrl' )->willReturnCallback( function ( $route, $query = [] ) {
- return wfAppendQuery( 'https://wiki.example.com/rest' . $route, $query );
- } );
+ $validator =
+ new Validator( $objectFactory, $permissionManager, $handler->getRequest(), $user );
- $handler->init( $router, $request, $config, $responseFactory );
$handler->validate( $validator );
+ }
+
+ /**
+ * Executes the given Handler on the given request.
+ *
+ * @param Handler $handler
+ * @param RequestInterface $request
+ * @param array $config
+ *
+ * @return ResponseInterface
+ */
+ private function executeHandler( Handler $handler, RequestInterface $request, $config = [] ) {
+ $this->initHandler( $handler, $request, $config );
+ $this->validateHandler( $handler );
// Check conditional request headers
$earlyResponse = $handler->checkPreconditions();
@@ -101,7 +122,7 @@ trait HandlerTestTrait {
$ret = $handler->execute();
$response = $ret instanceof Response ? $ret
- : $responseFactory->createFromReturnValue( $ret );
+ : $handler->getResponseFactory()->createFromReturnValue( $ret );
// Set Last-Modified and ETag headers in the response if available
$handler->applyConditionalResponseHeaders( $response );