wiki.techinc.nl/tests/phpunit/ResourceLoaderTestCase.php
Timo Tijhof 64febce451 resourceloader: Improve wgResourceLoaderMaxage docs, minor clean up
The docs for wgResourceLoaderMaxage still described the "server"
and "client" subkeys, which have not existed since MW 1.35. This
was essentially a new configuration structure, add the `@since`
annotation to reflect this.

Clean up the ResourceLoader class and group together related class
members in a more logical way. Currently going for what I see various
other core components do:

* Constants: public, then private.
* Static: public, then private.
* Members: public (none), then ctor-assigned/injected stuff, then
  those with defaults that start as-is.

Make most protected members private, except for those intentionally
made protected for use in tests. This class is not meant to be
extended, is not marked as stable for that purpose, and Codesearch
shows no extensions that do so.

Remove unused internal '$testModuleNames' field. This was removed in
5f47d994bc and accidentally reintroduced (unused) with 440dfcf6d8,
presumably due to a bad rebase.

Bug: T32956
Change-Id: I041a320d05c9e5f30ac9cc9270ce82c4d19a957f
2022-01-06 18:52:45 +00:00

236 lines
6.2 KiB
PHP

<?php
use MediaWiki\MediaWikiServices;
use Psr\Log\LoggerInterface;
abstract class ResourceLoaderTestCase extends MediaWikiIntegrationTestCase {
// Version hash for a blank file module.
// Result of ResourceLoader::makeHash(), ResourceLoaderTestModule
// and ResourceLoaderFileModule::getDefinitionSummary().
public const BLANK_VERSION = '9p30q';
// Result of ResoureLoader::makeVersionQuery() for a blank file module.
// In other words, result of ResourceLoader::makeHash( BLANK_VERSION );
public const BLANK_COMBI = 'rbml8';
/**
* @param array|string $options Language code or options array
* - string 'lang' Language code
* - string 'dir' Language direction (ltr or rtl)
* - string 'modules' Pipe-separated list of module names
* - string|null 'only' "scripts" (unwrapped script), "styles" (stylesheet), or null
* (mw.loader.implement).
* @param ResourceLoader|null $rl
* @return ResourceLoaderContext
*/
protected function getResourceLoaderContext( $options = [], ResourceLoader $rl = null ) {
if ( is_string( $options ) ) {
// Back-compat for extension tests
$options = [ 'lang' => $options ];
}
$options += [
'debug' => 'true',
'lang' => 'en',
'dir' => 'ltr',
'skin' => 'fallback',
'modules' => 'startup',
'only' => 'scripts',
'safemode' => null,
];
$resourceLoader = $rl ?: new ResourceLoader( MediaWikiServices::getInstance()->getMainConfig() );
$request = new FauxRequest( [
'debug' => $options['debug'],
'lang' => $options['lang'],
'modules' => $options['modules'],
'only' => $options['only'],
'safemode' => $options['safemode'],
'skin' => $options['skin'],
'target' => 'phpunit',
] );
$ctx = $this->getMockBuilder( ResourceLoaderContext::class )
->setConstructorArgs( [ $resourceLoader, $request ] )
->onlyMethods( [ 'getDirection' ] )
->getMock();
$ctx->method( 'getDirection' )->willReturn( $options['dir'] );
return $ctx;
}
public static function getSettings() {
return [
// For ResourceLoader class
'ResourceLoaderDebug' => true,
'LoadScript' => '/w/load.php',
'EnableJavaScriptTest' => false,
// For ResourceLoader::respond() - TODO: Inject somehow T32956
'UseFileCache' => false,
// For ResourceLoaderModule
'ResourceLoaderValidateJS' => false,
// For ResourceLoaderWikiModule
'MaxRedirects' => 1,
// For ResourceLoaderSkinModule
'Logos' => false,
'Logo' => '/logo.png',
'ResourceBasePath' => '/w',
'ParserEnableLegacyMediaDOM' => true,
// For ResourceLoader::getSiteConfigSettings and ResourceLoaderStartUpModule
'Server' => 'https://example.org',
'ScriptPath' => '/w',
'Script' => '/w/index.php',
'ResourceLoaderEnableJSProfiler' => false,
];
}
public static function getMinimalConfig() {
return new HashConfig( self::getSettings() );
}
/**
* The annotation causes this to be called immediately before setUp()
* @before
*/
final protected function mediaWikiResourceLoaderSetUp(): void {
ResourceLoader::clearCache();
$globals = [];
foreach ( self::getSettings() as $key => $value ) {
$globals['wg' . $key] = $value;
}
$this->setMwGlobals( $globals );
}
}
/* Stubs */
class ResourceLoaderTestModule extends ResourceLoaderModule {
protected $messages = [];
protected $dependencies = [];
protected $group = null;
protected $source = 'local';
protected $script = '';
protected $styles = '';
protected $skipFunction = null;
protected $es6 = false;
protected $isRaw = false;
protected $isKnownEmpty = false;
protected $type = ResourceLoaderModule::LOAD_GENERAL;
protected $targets = [ 'phpunit' ];
protected $shouldEmbed = null;
protected $mayValidateScript = false;
public function __construct( $options = [] ) {
foreach ( $options as $key => $value ) {
$this->$key = $value;
}
}
public function getScript( ResourceLoaderContext $context ) {
if ( $this->mayValidateScript ) {
// This enables the validation check that replaces invalid
// scripts with a warning message.
// Based on $wgResourceLoaderValidateJS
return $this->validateScriptFile( 'input', $this->script );
} else {
return $this->script;
}
}
public function getStyles( ResourceLoaderContext $context ) {
return [ '' => $this->styles ];
}
public function getMessages() {
return $this->messages;
}
public function getDependencies( ResourceLoaderContext $context = null ) {
return $this->dependencies;
}
public function getGroup() {
return $this->group;
}
public function getSource() {
return $this->source;
}
public function getType() {
return $this->type;
}
public function getSkipFunction() {
return $this->skipFunction;
}
public function requiresES6() {
return $this->es6;
}
public function isRaw() {
return $this->isRaw;
}
public function isKnownEmpty( ResourceLoaderContext $context ) {
return $this->isKnownEmpty;
}
public function shouldEmbedModule( ResourceLoaderContext $context ) {
return $this->shouldEmbed ?? parent::shouldEmbedModule( $context );
}
public function enableModuleContentVersion() {
return true;
}
}
/**
* A more constrained and testable variant of ResourceLoaderFileModule.
*
* - Implements getLessVars() support.
* - Disables database persistance of discovered file dependencies.
*/
class ResourceLoaderFileTestModule extends ResourceLoaderFileModule {
protected $lessVars = [];
public function __construct( $options = [] ) {
if ( isset( $options['lessVars'] ) ) {
$this->lessVars = $options['lessVars'];
unset( $options['lessVars'] );
}
parent::__construct( $options );
}
public function getLessVars( ResourceLoaderContext $context ) {
return $this->lessVars;
}
/**
* @param ResourceLoaderContext $context
* @return array
*/
protected function getFileDependencies( ResourceLoaderContext $context ) {
// No-op
return [];
}
protected function saveFileDependencies( ResourceLoaderContext $context, $refs ) {
// No-op
}
}
class ResourceLoaderFileModuleTestingSubclass extends ResourceLoaderFileModule {
}
class EmptyResourceLoader extends ResourceLoader {
public function __construct( Config $config = null, LoggerInterface $logger = null ) {
parent::__construct( $config ?: ResourceLoaderTestCase::getMinimalConfig(), $logger );
}
public function getErrors() {
return $this->errors;
}
}