wiki.techinc.nl/tests/phpunit/unit/includes/Rest/Handler/PageHandlerTestTrait.php

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

247 lines
7.5 KiB
PHP
Raw Normal View History

<?php
namespace MediaWiki\Tests\Rest\Handler;
use File;
use FileRepo;
use MediaWiki\Config\ServiceOptions;
use MediaWiki\MainConfigNames;
use MediaWiki\MainConfigSchema;
Make ParsoidOutputAccess a wrapper over ParserOutputAccess * Updated ParserOutput to set Parsoid render ids that REST API functionality expects in ParserOutput objects. * CacheThresholdTime functionality no longer exists since it was implemented in ParsoidOutputAccess and ParserOutputAccess doesn't support it. This is tracked in T346765. * Enforce the constraint that uncacheable parses are only for fake or mutable revisions. Updated tests that violated this constraint to use 'getParseOutput' instead of calling the parse method directly. * Had to make some changes in ParsoidParser around use of preferredVariant passed to Parsoid. I also left some TODO comments for future fixes. T267067 is also relevant here. PARSOID-SPECIFIC OPTIONS: * logLinterData: linter data is always logged by default -- removed support to disable it. Linter extension handles stale lints properly and it is better to let it handle it rather than add special cases to the API. * offsetType: Moved this support to ParsoidHandler as a post-processing of byte-offset output. This eliminates the need to support this Parsoid-specific options in the ContentHandler hierarchies. * body_only / wrapSections: Handled this in HtmlOutputRendererHelper as a post-processing of regular output by removing sections and returning the body content only. This does result in some useless section-wrapping work with Parsoid, but the simplification is probably worth it. If in the future, we support Parsoid-specific options in the ContentHandler hierarchy, we could re-introduce this. But, in any case, this "fragment" flavor options is likely to get moved out of core into the VisualEditor extension code. DEPLOYMENT: * This patch changes the cache key by setting the useParsoid option in ParserOptions. The parent patch handles this to ensure we don't encounter a cold cache on deploy. TESTS: * Updated tests and mocks to reflect new reality. * Do we need any new tests? Bug: T332931 Change-Id: Ic9b7cc0fcf365e772b7d080d76a065e3fd585f80
2023-08-29 20:13:43 +00:00
use MediaWiki\Parser\Parsoid\ParsoidParser;
use MediaWiki\Parser\Parsoid\ParsoidParserFactory;
use MediaWiki\Rest\Handler\Helper\HtmlMessageOutputHelper;
use MediaWiki\Rest\Handler\Helper\HtmlOutputRendererHelper;
use MediaWiki\Rest\Handler\Helper\PageContentHelper;
use MediaWiki\Rest\Handler\Helper\PageRedirectHelper;
use MediaWiki\Rest\Handler\Helper\PageRestHelperFactory;
use MediaWiki\Rest\Handler\LanguageLinksHandler;
use MediaWiki\Rest\Handler\PageHistoryCountHandler;
use MediaWiki\Rest\Handler\PageHistoryHandler;
use MediaWiki\Rest\Handler\PageHTMLHandler;
use MediaWiki\Rest\Handler\PageSourceHandler;
use MediaWiki\Rest\RequestData;
use MediaWiki\Rest\RequestInterface;
use MediaWiki\Rest\ResponseFactory;
use MediaWiki\Rest\Router;
use PHPUnit\Framework\MockObject\MockObject;
use RepoGroup;
use WANObjectCache;
use Wikimedia\Parsoid\Parsoid;
/**
* A trait providing utility functions for testing Page Handler classes.
* This trait is intended to be used on subclasses of MediaWikiUnitTestCase
* or MediaWikiIntegrationTestCase.
*
* @stable to use
*/
trait PageHandlerTestTrait {
private function newRouterForPageHandler( $baseUrl, $rootPath = '' ): Router {
$router = $this->createNoOpMock( Router::class, [ 'getRoutePath', 'getRouteUrl' ] );
$router->method( 'getRoutePath' )
->willReturnCallback( static function (
string $route,
array $pathParams = [],
array $queryParams = []
) use ( $rootPath ) {
foreach ( $pathParams as $param => $value ) {
// NOTE: we use rawurlencode here, since execute() uses rawurldecode().
// Spaces in path params must be encoded to %20 (not +).
// Slashes must be encoded as %2F.
$route = str_replace( '{' . $param . '}', rawurlencode( (string)$value ), $route );
}
$url = $rootPath . $route;
return wfAppendQuery( $url, $queryParams );
} );
$router->method( 'getRouteUrl' )
->willReturnCallback( static function (
string $route,
array $pathParams = [],
array $queryParams = []
) use ( $baseUrl, $router ) {
return $baseUrl . $router->getRoutePath( $route, $pathParams, $queryParams );
} );
return $router;
}
/**
Make ParsoidOutputAccess a wrapper over ParserOutputAccess * Updated ParserOutput to set Parsoid render ids that REST API functionality expects in ParserOutput objects. * CacheThresholdTime functionality no longer exists since it was implemented in ParsoidOutputAccess and ParserOutputAccess doesn't support it. This is tracked in T346765. * Enforce the constraint that uncacheable parses are only for fake or mutable revisions. Updated tests that violated this constraint to use 'getParseOutput' instead of calling the parse method directly. * Had to make some changes in ParsoidParser around use of preferredVariant passed to Parsoid. I also left some TODO comments for future fixes. T267067 is also relevant here. PARSOID-SPECIFIC OPTIONS: * logLinterData: linter data is always logged by default -- removed support to disable it. Linter extension handles stale lints properly and it is better to let it handle it rather than add special cases to the API. * offsetType: Moved this support to ParsoidHandler as a post-processing of byte-offset output. This eliminates the need to support this Parsoid-specific options in the ContentHandler hierarchies. * body_only / wrapSections: Handled this in HtmlOutputRendererHelper as a post-processing of regular output by removing sections and returning the body content only. This does result in some useless section-wrapping work with Parsoid, but the simplification is probably worth it. If in the future, we support Parsoid-specific options in the ContentHandler hierarchy, we could re-introduce this. But, in any case, this "fragment" flavor options is likely to get moved out of core into the VisualEditor extension code. DEPLOYMENT: * This patch changes the cache key by setting the useParsoid option in ParserOptions. The parent patch handles this to ensure we don't encounter a cold cache on deploy. TESTS: * Updated tests and mocks to reflect new reality. * Do we need any new tests? Bug: T332931 Change-Id: Ic9b7cc0fcf365e772b7d080d76a065e3fd585f80
2023-08-29 20:13:43 +00:00
* @param Parsoid|MockObject $mockParsoid
*/
public function resetServicesWithMockedParsoid( $mockParsoid ): void {
$services = $this->getServiceContainer();
$parsoidParser = new ParsoidParser(
$mockParsoid,
$services->getParsoidPageConfigFactory(),
$services->getLanguageConverterFactory(),
$services->getParserFactory(),
$services->getGlobalIdGenerator()
);
// Create a mock Parsoid factory that returns the ParsoidParser object
// with the mocked Parsoid object.
$mockParsoidParserFactory = $this->createNoOpMock( ParsoidParserFactory::class, [ 'create' ] );
$mockParsoidParserFactory->method( 'create' )->willReturn( $parsoidParser );
$this->setService( 'ParsoidParserFactory', $mockParsoidParserFactory );
}
/**
* @return PageHTMLHandler
*/
Make ParsoidOutputAccess a wrapper over ParserOutputAccess * Updated ParserOutput to set Parsoid render ids that REST API functionality expects in ParserOutput objects. * CacheThresholdTime functionality no longer exists since it was implemented in ParsoidOutputAccess and ParserOutputAccess doesn't support it. This is tracked in T346765. * Enforce the constraint that uncacheable parses are only for fake or mutable revisions. Updated tests that violated this constraint to use 'getParseOutput' instead of calling the parse method directly. * Had to make some changes in ParsoidParser around use of preferredVariant passed to Parsoid. I also left some TODO comments for future fixes. T267067 is also relevant here. PARSOID-SPECIFIC OPTIONS: * logLinterData: linter data is always logged by default -- removed support to disable it. Linter extension handles stale lints properly and it is better to let it handle it rather than add special cases to the API. * offsetType: Moved this support to ParsoidHandler as a post-processing of byte-offset output. This eliminates the need to support this Parsoid-specific options in the ContentHandler hierarchies. * body_only / wrapSections: Handled this in HtmlOutputRendererHelper as a post-processing of regular output by removing sections and returning the body content only. This does result in some useless section-wrapping work with Parsoid, but the simplification is probably worth it. If in the future, we support Parsoid-specific options in the ContentHandler hierarchy, we could re-introduce this. But, in any case, this "fragment" flavor options is likely to get moved out of core into the VisualEditor extension code. DEPLOYMENT: * This patch changes the cache key by setting the useParsoid option in ParserOptions. The parent patch handles this to ensure we don't encounter a cold cache on deploy. TESTS: * Updated tests and mocks to reflect new reality. * Do we need any new tests? Bug: T332931 Change-Id: Ic9b7cc0fcf365e772b7d080d76a065e3fd585f80
2023-08-29 20:13:43 +00:00
public function newPageHtmlHandler( ?RequestInterface $request = null ) {
$services = $this->getServiceContainer();
$config = [
MainConfigNames::RightsUrl => 'https://example.com/rights',
MainConfigNames::RightsText => 'some rights',
MainConfigNames::ParsoidCacheConfig =>
MainConfigSchema::getDefaultValue( MainConfigNames::ParsoidCacheConfig )
];
$helperFactory = $this->createNoOpMock(
PageRestHelperFactory::class,
[ 'newPageContentHelper', 'newHtmlOutputRendererHelper', 'newHtmlMessageOutputHelper', 'newPageRedirectHelper' ]
);
$helperFactory->method( 'newPageContentHelper' )
->willReturn( new PageContentHelper(
new ServiceOptions( PageContentHelper::CONSTRUCTOR_OPTIONS, $config ),
$services->getRevisionLookup(),
$services->getTitleFormatter(),
$services->getPageStore()
) );
$parsoidOutputStash = $this->getParsoidOutputStash();
$helperFactory->method( 'newHtmlOutputRendererHelper' )
->willReturnCallback( static function ( $page, $parameters, $authority, $revision, $lenientRevHandling ) use ( $services, $parsoidOutputStash ) {
return new HtmlOutputRendererHelper(
$parsoidOutputStash,
$services->getStatsdDataFactory(),
$services->getParserOutputAccess(),
$services->getPageStore(),
$services->getRevisionLookup(),
$services->getRevisionRenderer(),
$services->getParsoidSiteConfig(),
$services->getHtmlTransformFactory(),
$services->getContentHandlerFactory(),
$services->getLanguageFactory(),
$page,
$parameters,
$authority,
$revision,
$lenientRevHandling
);
} );
$helperFactory->method( 'newHtmlMessageOutputHelper' )
->willReturnCallback( static function ( $page ) {
return new HtmlMessageOutputHelper( $page );
} );
$request ??= new RequestData( [] );
$responseFactory = new ResponseFactory( [] );
$helperFactory->method( 'newPageRedirectHelper' )
->willReturn(
new PageRedirectHelper(
$services->getRedirectStore(),
$services->getTitleFormatter(),
$responseFactory,
$this->newRouterForPageHandler( 'https://example.test/api' ),
'/test/{title}',
$request,
$services->getLanguageConverterFactory()
)
);
return new PageHTMLHandler(
$helperFactory
);
}
/**
* @return PageSourceHandler
*/
public function newPageSourceHandler() {
$services = $this->getServiceContainer();
return new PageSourceHandler(
$services->getTitleFormatter(),
$services->getPageRestHelperFactory()
);
}
public function newPageHistoryHandler() {
$services = $this->getServiceContainer();
return new PageHistoryHandler(
$services->getRevisionStore(),
$services->getNameTableStoreFactory(),
$services->getGroupPermissionsLookup(),
$services->getConnectionProvider(),
$services->getPageStore(),
$services->getTitleFormatter(),
$services->getPageRestHelperFactory()
);
}
public function newPageHistoryCountHandler() {
$services = $this->getServiceContainer();
return new PageHistoryCountHandler(
$services->getRevisionStore(),
$services->getNameTableStoreFactory(),
$services->getGroupPermissionsLookup(),
$services->getConnectionProvider(),
new WANObjectCache( [ 'cache' => $this->parserCacheBagOStuff, ] ),
$services->getPageStore(),
$services->getPageRestHelperFactory(),
$services->getTempUserConfig()
);
}
public function newLanguageLinksHandler() {
$services = $this->getServiceContainer();
return new LanguageLinksHandler(
$services->getConnectionProvider(),
$services->getLanguageNameUtils(),
$services->getTitleFormatter(),
$services->getTitleParser(),
$services->getPageStore(),
$services->getPageRestHelperFactory()
);
}
private function installMockFileRepo( string $fileName, ?string $redirectedFrom = null ): void {
$repo = $this->createNoOpMock(
FileRepo::class,
[]
);
$file = $this->createNoOpMock(
File::class,
[
'isLocal',
'exists',
'getRepo',
'getRedirected',
'getName',
]
);
$file->method( 'isLocal' )->willReturn( false );
$file->method( 'exists' )->willReturn( true );
$file->method( 'getRepo' )->willReturn( $repo );
$file->method( 'getRedirected' )->willReturn( $redirectedFrom );
$file->method( 'getName' )->willReturn( $fileName );
$repoGroup = $this->createNoOpMock(
RepoGroup::class,
[ 'findFile' ]
);
$repoGroup->expects( $this->atLeastOnce() )->method( 'findFile' )
->willReturn( $file );
$this->setService(
'RepoGroup',
$repoGroup
);
}
}