createMock( ITextFormatter::class ); $formatter->method( 'format' )->willReturnCallback( function ( MessageValue $msg ) { return $msg->dump(); } ); /** @var ResponseFactory|MockObject $responseFactory */ $responseFactory = new ResponseFactory( [ 'qqx' => $formatter ] ); /** @var PermissionManager|MockObject $permissionManager */ $permissionManager = $this->createNoOpMock( PermissionManager::class, [ 'userCan', 'userHasRight' ] ); $permissionManager->method( 'userCan' )->willReturn( true ); $permissionManager->method( 'userHasRight' )->willReturn( true ); /** @var ServiceContainer|MockObject $serviceContainer */ $serviceContainer = $this->createNoOpMock( ServiceContainer::class ); $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 ); } ); $handler->init( $router, $request, $config, $responseFactory ); $handler->validate( $validator ); // Check conditional request headers $earlyResponse = $handler->checkPreconditions(); if ( $earlyResponse ) { return $earlyResponse; } $ret = $handler->execute(); $response = $ret instanceof Response ? $ret : $responseFactory->createFromReturnValue( $ret ); // Set Last-Modified and ETag headers in the response if available $handler->applyConditionalResponseHeaders( $response ); return $response; } /** * Executes the given Handler on the given request, parses the response body as JSON, * and returns the result. * * @param Handler $handler * @param RequestInterface $request * @param array $config * * @return array */ private function executeHandlerAndGetBodyData( Handler $handler, RequestInterface $request, $config = [] ) { $response = $this->executeHandler( $handler, $request, $config ); $this->assertTrue( $response->getStatusCode() >= 200 && $response->getStatusCode() < 300 ); $this->assertSame( 'application/json', $response->getHeaderLine( 'Content-Type' ) ); $data = json_decode( $response->getBody(), true ); $this->assertIsArray( $data, 'Body must be a JSON array' ); return $data; } /** * Executes the given Handler on the given request, and returns the HttpException thrown. * Fails if no HttpException is thrown. * * @param Handler $handler * @param RequestInterface $request * @param array $config * * @return HttpException */ private function executeHandlerAndGetHttpException( Handler $handler, RequestInterface $request, $config = [] ) { try { $this->executeHandler( $handler, $request, $config ); Assert::fail( 'Expected a HttpException to be thrown' ); } catch ( HttpException $ex ) { return $ex; } } /** * @param string $text * @param array $props Additional properties to set. Supported keys: * - id: int * - namespace: int * * @return Title|MockObject */ private function makeMockTitle( $text, array $props = [] ) { $id = $props['id'] ?? ++$this->pageIdCounter; $ns = $props['namespace'] ?? 0; $nsName = $ns ? "ns$ns:" : ''; $preText = $text; $text = preg_replace( '/^[\w ]*?:/', '', $text ); // If no namespace prefix was given, add one if needed. if ( $preText == $text && $ns ) { $preText = $nsName . $text; } /** @var Title|MockObject $title */ $title = $this->createMock( Title::class ); $title->method( 'getText' )->willReturn( str_replace( '_', ' ', $text ) ); $title->method( 'getDBkey' )->willReturn( str_replace( ' ', '_', $text ) ); $title->method( 'getPrefixedText' )->willReturn( str_replace( '_', ' ', $preText ) ); $title->method( 'getPrefixedDBkey' )->willReturn( str_replace( ' ', '_', $preText ) ); $title->method( 'getArticleID' )->willReturn( $id ); $title->method( 'getNamespace' )->willReturn( $props['namespace'] ?? 0 ); $title->method( 'exists' )->willReturn( $id > 0 ); $title->method( 'getTouched' )->willReturn( $id ? '20200101223344' : false ); return $title; } /** * @return PermissionManager|MockObject */ private function makeMockPermissionManager() { /** @var PermissionManager|MockObject $permissionManager */ $permissionManager = $this->createNoOpMock( PermissionManager::class, [ 'userCan' ] ); $permissionManager->method( 'userCan' ) ->willReturnCallback( function ( $action, User $user, LinkTarget $page ) { return !preg_match( '/Forbidden/', $page->getText() ); } ); return $permissionManager; } /** * @return MediaWikiTitleCodec */ private function makeMockTitleCodec() { /** @var Language|MockObject $language */ $language = $this->createNoOpMock( Language::class, [ 'ucfirst' ] ); $language->method( 'ucfirst' )->willReturnCallback( 'ucfirst' ); /** @var GenderCache|MockObject $genderCache */ $genderCache = $this->createNoOpMock( GenderCache::class ); /** @var InterwikiLookup|MockObject $interwikiLookup */ $interwikiLookup = $this->createNoOpMock( InterwikiLookup::class ); /** @var NamespaceInfo|MockObject $namespaceInfo */ $namespaceInfo = $this->createNoOpMock( NamespaceInfo::class, [ 'isCapitalized' ] ); $namespaceInfo->method( 'isCapitalized' )->willReturn( true ); $titleCodec = new MediaWikiTitleCodec( $language, $genderCache, [ 'en' ], $interwikiLookup, $namespaceInfo ); return $titleCodec; } }