Hello World

'; protected function setUp(): void { parent::setUp(); // Clean up these tables after each test $this->tablesUsed = [ 'page', 'revision', 'comment', 'text', 'content' ]; } /** * Checks whether Parsoid extension is installed and skips the test if it's not. */ private function checkParsoidInstalled() { if ( !ExtensionRegistry::getInstance()->isLoaded( 'Parsoid' ) ) { $this->markTestSkipped( 'Skip test, since parsoid is not configured' ); } } /** * @param BagOStuff|null $cache * @param Parsoid|MockObject|null $parsoid * @return PageHTMLHandler * @throws Exception */ private function newHandler( BagOStuff $cache = null, Parsoid $parsoid = null ): PageHTMLHandler { $handler = new PageHTMLHandler( new HashConfig( [ 'RightsUrl' => 'https://example.com/rights', 'RightsText' => 'some rights', ] ), $this->getServiceContainer()->getPermissionManager(), $this->getServiceContainer()->getRevisionLookup(), $this->getServiceContainer()->getTitleFormatter(), $this->getServiceContainer()->getTitleFactory(), new ParserCacheFactory( $cache ?: new EmptyBagOStuff(), "1234567", $this->createHookContainer(), new JsonCodec(), new NullStatsdDataFactory(), new NullLogger() ), $this->getServiceContainer()->getWikiPageFactory() ); if ( $parsoid !== null ) { $wrapper = TestingAccessWrapper::newFromObject( $handler ); $wrapper->parsoid = $parsoid; } return $handler; } public function testExecuteBare() { $page = $this->getExistingTestPage( 'HtmlEndpointTestPage/with/slashes' ); $request = new RequestData( [ 'pathParams' => [ 'title' => $page->getTitle()->getPrefixedText() ] ] ); $htmlUrl = 'https://wiki.example.com/rest/v1/page/HtmlEndpointTestPage%2Fwith%2Fslashes/html'; $handler = $this->newHandler(); $config = [ 'format' => 'bare' ]; $data = $this->executeHandlerAndGetBodyData( $handler, $request, $config ); $this->assertResponseData( $page, $data ); $this->assertSame( $htmlUrl, $data['html_url'] ); } public function testExecuteWithHtml() { $this->checkParsoidInstalled(); $page = $this->getExistingTestPage( 'HtmlEndpointTestPage/with/slashes' ); $this->assertTrue( $this->editPage( $page, self::WIKITEXT )->isGood(), 'Sanity: edited a page' ); $request = new RequestData( [ 'pathParams' => [ 'title' => $page->getTitle()->getPrefixedText() ] ] ); $handler = $this->newHandler(); $data = $this->executeHandlerAndGetBodyData( $handler, $request, [ 'format' => 'with_html' ] ); $this->assertResponseData( $page, $data ); $this->assertStringContainsString( '', $data['html'] ); $this->assertStringContainsString( 'assertStringContainsString( self::HTML, $data['html'] ); } public function testExecuteHtmlOnly() { $this->checkParsoidInstalled(); $page = $this->getExistingTestPage( 'HtmlEndpointTestPage/with/slashes' ); $this->assertTrue( $this->editPage( $page, self::WIKITEXT )->isGood(), 'Sanity: edited a page' ); $request = new RequestData( [ 'pathParams' => [ 'title' => $page->getTitle()->getPrefixedText() ] ] ); $handler = $this->newHandler(); $response = $this->executeHandler( $handler, $request, [ 'format' => 'html' ] ); $htmlResponse = (string)$response->getBody(); $this->assertStringContainsString( '', $htmlResponse ); $this->assertStringContainsString( 'assertStringContainsString( self::HTML, $htmlResponse ); } public function testHtmlIsCached() { $this->checkParsoidInstalled(); $page = $this->getExistingTestPage( 'HtmlEndpointTestPage/with/slashes' ); $request = new RequestData( [ 'pathParams' => [ 'title' => $page->getTitle()->getPrefixedText() ] ] ); $cache = new HashBagOStuff(); $parsoid = $this->createNoOpMock( Parsoid::class, [ 'wikitext2html' ] ); $parsoid->expects( $this->once() ) ->method( 'wikitext2html' ) ->willReturn( new PageBundle( 'mocked HTML', null, null, '1.0' ) ); $handler = $this->newHandler( $cache, $parsoid ); $response = $this->executeHandler( $handler, $request, [ 'format' => 'html' ] ); $htmlResponse = (string)$response->getBody(); $this->assertStringContainsString( 'mocked HTML', $htmlResponse ); // check that we can run the test again and ensure that the parse is only run once $handler = $this->newHandler( $cache, $parsoid ); $response = $this->executeHandler( $handler, $request, [ 'format' => 'html' ] ); $htmlResponse = (string)$response->getBody(); $this->assertStringContainsString( 'mocked HTML', $htmlResponse ); } public function testEtagLastModified() { $this->checkParsoidInstalled(); $time = time(); MWTimestamp::setFakeTime( $time ); $page = $this->getExistingTestPage( 'HtmlEndpointTestPage/with/slashes' ); $request = new RequestData( [ 'pathParams' => [ 'title' => $page->getTitle()->getPrefixedText() ] ] ); $cache = new HashBagOStuff(); // First, test it works if nothing was cached yet. // Make some time pass since page was created: MWTimestamp::setFakeTime( $time + 10 ); $handler = $this->newHandler( $cache ); $response = $this->executeHandler( $handler, $request, [ 'format' => 'html' ] ); $this->assertArrayHasKey( 'ETag', $response->getHeaders() ); $etag = $response->getHeaderLine( 'ETag' ); $this->assertArrayHasKey( 'Last-Modified', $response->getHeaders() ); $this->assertSame( MWTimestamp::convert( TS_RFC2822, $time ), $response->getHeaderLine( 'Last-Modified' ) ); // Now, test that headers work when getting from cache too. $handler = $this->newHandler( $cache ); $response = $this->executeHandler( $handler, $request, [ 'format' => 'html' ] ); $this->assertArrayHasKey( 'ETag', $response->getHeaders() ); $this->assertNotSame( $etag, $response->getHeaderLine( 'ETag' ) ); $etag = $response->getHeaderLine( 'ETag' ); $this->assertArrayHasKey( 'Last-Modified', $response->getHeaders() ); $this->assertSame( MWTimestamp::convert( TS_RFC2822, $time + 10 ), $response->getHeaderLine( 'Last-Modified' ) ); // Now, expire the cache $time += 1000; MWTimestamp::setFakeTime( $time ); $this->assertTrue( $page->getTitle()->invalidateCache( MWTimestamp::convert( TS_MW, $time ) ), 'Sanity: can invalidate cache' ); DeferredUpdates::doUpdates(); $handler = $this->newHandler( $cache ); $response = $this->executeHandler( $handler, $request, [ 'format' => 'html' ] ); $this->assertArrayHasKey( 'ETag', $response->getHeaders() ); $this->assertNotSame( $etag, $response->getHeaderLine( 'ETag' ) ); $this->assertArrayHasKey( 'Last-Modified', $response->getHeaders() ); $this->assertSame( MWTimestamp::convert( TS_RFC2822, $time ), $response->getHeaderLine( 'Last-Modified' ) ); } public function provideHandlesParsoidError() { yield 'ClientError' => [ new ClientError( 'TEST_TEST' ), new LocalizedHttpException( new MessageValue( 'rest-html-backend-error' ), 400, [ 'reason' => 'TEST_TEST' ] ) ]; yield 'ResourceLimitExceededException' => [ new ResourceLimitExceededException( 'TEST_TEST' ), new LocalizedHttpException( new MessageValue( 'rest-resource-limit-exceeded' ), 413, [ 'reason' => 'TEST_TEST' ] ) ]; } /** * @dataProvider provideHandlesParsoidError * @param Exception $parsoidException * @param Exception $expectedException */ public function testHandlesParsoidError( Exception $parsoidException, Exception $expectedException ) { $this->checkParsoidInstalled(); $page = $this->getExistingTestPage( 'HtmlEndpointTestPage/with/slashes' ); $request = new RequestData( [ 'pathParams' => [ 'title' => $page->getTitle()->getPrefixedText() ] ] ); $parsoid = $this->createNoOpMock( Parsoid::class, [ 'wikitext2html' ] ); $parsoid->expects( $this->once() ) ->method( 'wikitext2html' ) ->willThrowException( $parsoidException ); $handler = $this->newHandler( null, $parsoid ); $this->expectExceptionObject( $expectedException ); $this->executeHandler( $handler, $request, [ 'format' => 'html' ] ); } public function testExecute_missingparam() { $request = new RequestData(); $this->expectExceptionObject( new LocalizedHttpException( new MessageValue( "paramvalidator-missingparam", [ 'title' ] ), 400 ) ); $handler = $this->newHandler(); $this->executeHandler( $handler, $request ); } public function testExecute_error() { $request = new RequestData( [ 'pathParams' => [ 'title' => 'DoesNotExist8237456assda1234' ] ] ); $this->expectExceptionObject( new LocalizedHttpException( new MessageValue( "rest-nonexistent-title", [ 'testing' ] ), 404 ) ); $handler = $this->newHandler(); $this->executeHandler( $handler, $request ); } /** * @param WikiPage $page * @param array $data */ private function assertResponseData( WikiPage $page, array $data ): void { $this->assertSame( $page->getId(), $data['id'] ); $this->assertSame( $page->getTitle()->getPrefixedDBkey(), $data['key'] ); $this->assertSame( $page->getTitle()->getPrefixedText(), $data['title'] ); $this->assertSame( $page->getLatest(), $data['latest']['id'] ); $this->assertSame( wfTimestampOrNull( TS_ISO_8601, $page->getTimestamp() ), $data['latest']['timestamp'] ); $this->assertSame( CONTENT_MODEL_WIKITEXT, $data['content_model'] ); $this->assertSame( 'https://example.com/rights', $data['license']['url'] ); $this->assertSame( 'some rights', $data['license']['title'] ); } }