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 in5f47d994bcand accidentally reintroduced (unused) with440dfcf6d8, presumably due to a bad rebase. Bug: T32956 Change-Id: I041a320d05c9e5f30ac9cc9270ce82c4d19a957f
236 lines
6.2 KiB
PHP
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;
|
|
}
|
|
}
|