<?php
use Wikimedia\TestingAccessWrapper;
+use MediaWiki\MediaWikiServices;
class ResourceLoaderTest extends ResourceLoaderTestCase {
/**
* Ensure the ResourceLoaderRegisterModules hook is called.
- *
- * @covers ResourceLoader::__construct
+ * @coversNothing
*/
- public function testConstructRegistrationHook() {
- $resourceLoaderRegisterModulesHook = false;
+ public function testServiceWiring() {
+ $this->overrideMwServices();
+ $ranHook = 0;
$this->setMwGlobals( 'wgHooks', [
'ResourceLoaderRegisterModules' => [
- function ( &$resourceLoader ) use ( &$resourceLoaderRegisterModulesHook ) {
- $resourceLoaderRegisterModulesHook = true;
+ function ( &$resourceLoader ) use ( &$ranHook ) {
+ $ranHook++;
}
]
] );
- $unused = new ResourceLoader();
- $this->assertTrue(
- $resourceLoaderRegisterModulesHook,
- 'Hook ResourceLoaderRegisterModules called'
- );
+ MediaWikiServices::getInstance()->getResourceLoader();
+
+ $this->assertSame( 1, $ranHook, 'Hook was called' );
+ }
+
+ public static function provideInvalidModuleName() {
+ return [
+ 'name with 300 chars' => [ str_repeat( 'x', 300 ) ],
+ 'name with bang' => [ 'this!that' ],
+ 'name with comma' => [ 'this,that' ],
+ 'name with pipe' => [ 'this|that' ],
+ ];
+ }
+
+ public static function provideValidModuleName() {
+ return [
+ 'empty string' => [ '' ],
+ 'simple name' => [ 'this.and-that2' ],
+ 'name with 100 chars' => [ str_repeat( 'x', 100 ) ],
+ 'name with hash' => [ 'this#that' ],
+ 'name with slash' => [ 'this/that' ],
+ 'name with at' => [ 'this@that' ],
+ ];
}
/**
- * @covers ResourceLoader::register
- * @covers ResourceLoader::getModule
+ * @dataProvider provideInvalidModuleName
+ * @covers ResourceLoader
*/
- public function testRegisterValidObject() {
- $module = new ResourceLoaderTestModule();
- $resourceLoader = new EmptyResourceLoader();
- $resourceLoader->register( 'test', $module );
- $this->assertEquals( $module, $resourceLoader->getModule( 'test' ) );
+ public function testIsValidModuleName_invalid( $name ) {
+ $this->assertFalse( ResourceLoader::isValidModuleName( $name ) );
+ }
+
+ /**
+ * @dataProvider provideValidModuleName
+ * @covers ResourceLoader
+ */
+ public function testIsValidModuleName_valid( $name ) {
+ $this->assertTrue( ResourceLoader::isValidModuleName( $name ) );
}
/**
* @covers ResourceLoader::getModule
*/
public function testRegisterValidArray() {
- $module = new ResourceLoaderTestModule();
$resourceLoader = new EmptyResourceLoader();
// Covers case of register() setting $rl->moduleInfos,
// but $rl->modules lazy-populated by getModule()
- $resourceLoader->register( 'test', [ 'object' => $module ] );
- $this->assertEquals( $module, $resourceLoader->getModule( 'test' ) );
+ $resourceLoader->register( 'test', [ 'class' => ResourceLoaderTestModule::class ] );
+ $this->assertInstanceOf(
+ ResourceLoaderTestModule::class,
+ $resourceLoader->getModule( 'test' )
+ );
}
/**
* @covers ResourceLoader::register
+ * @group medium
*/
public function testRegisterEmptyString() {
- $module = new ResourceLoaderTestModule();
$resourceLoader = new EmptyResourceLoader();
- $resourceLoader->register( '', $module );
- $this->assertEquals( $module, $resourceLoader->getModule( '' ) );
+ $resourceLoader->register( '', [ 'class' => ResourceLoaderTestModule::class ] );
+ $this->assertInstanceOf(
+ ResourceLoaderTestModule::class,
+ $resourceLoader->getModule( '' )
+ );
}
/**
* @covers ResourceLoader::register
+ * @group medium
*/
public function testRegisterInvalidName() {
$resourceLoader = new EmptyResourceLoader();
$this->setExpectedException( MWException::class, "name 'test!invalid' is invalid" );
- $resourceLoader->register( 'test!invalid', new ResourceLoaderTestModule() );
+ $resourceLoader->register( 'test!invalid', [] );
}
/**
->method( 'warning' );
$resourceLoader = new EmptyResourceLoader( null, $logger );
- $module1 = new ResourceLoaderTestModule();
- $module2 = new ResourceLoaderTestModule();
- $resourceLoader->register( 'test', $module1 );
- $resourceLoader->register( 'test', $module2 );
- $this->assertSame( $module2, $resourceLoader->getModule( 'test' ) );
+ $resourceLoader->register( 'test', [ 'class' => ResourceLoaderSkinModule::class ] );
+ $resourceLoader->register( 'test', [ 'class' => ResourceLoaderStartUpModule::class ] );
+ $this->assertInstanceOf(
+ ResourceLoaderStartUpModule::class,
+ $resourceLoader->getModule( 'test' ),
+ 'last one wins'
+ );
}
/**
public function testGetModuleNames() {
// Use an empty one so that core and extension modules don't get in.
$resourceLoader = new EmptyResourceLoader();
- $resourceLoader->register( 'test.foo', new ResourceLoaderTestModule() );
- $resourceLoader->register( 'test.bar', new ResourceLoaderTestModule() );
+ $resourceLoader->register( 'test.foo', [] );
+ $resourceLoader->register( 'test.bar', [] );
$this->assertEquals(
- [ 'test.foo', 'test.bar' ],
+ [ 'startup', 'test.foo', 'test.bar' ],
$resourceLoader->getModuleNames()
);
}
public function provideTestIsFileModule() {
- $fileModuleObj = $this->getMockBuilder( ResourceLoaderFileModule::class )
- ->disableOriginalConstructor()
- ->getMock();
+ $fileModuleObj = $this->createMock( ResourceLoaderFileModule::class );
return [
- 'object' => [ false,
- new ResourceLoaderTestModule()
+ 'factory ignored' => [ false,
+ [
+ 'factory' => function () {
+ return new ResourceLoaderTestModule();
+ }
+ ]
],
- 'FileModule object' => [ false,
- $fileModuleObj
+ 'factory ignored (actual FileModule)' => [ false,
+ [
+ 'factory' => function () use ( $fileModuleObj ) {
+ return $fileModuleObj;
+ }
+ ]
],
'simple empty' => [ true,
[]
'simple scripts' => [ true,
[ 'scripts' => 'example.js' ]
],
- 'simple scripts, raw and targets' => [ true, [
+ 'simple scripts with targets' => [ true, [
'scripts' => [ 'a.js', 'b.js' ],
- 'raw' => true,
'targets' => [ 'desktop', 'mobile' ],
] ],
'FileModule' => [ true,
*/
public function testIsModuleRegistered() {
$rl = new EmptyResourceLoader();
- $rl->register( 'test', new ResourceLoaderTestModule() );
+ $rl->register( 'test', [] );
$this->assertTrue( $rl->isModuleRegistered( 'test' ) );
$this->assertFalse( $rl->isModuleRegistered( 'test.unknown' ) );
}
* @covers ResourceLoader::getSources
*/
public function testAddSource( $name, $info, $expected ) {
- $rl = new ResourceLoader;
+ $rl = new EmptyResourceLoader;
$rl->addSource( $name, $info );
if ( is_array( $expected ) ) {
foreach ( $expected as $source ) {
* @covers ResourceLoader::addSource
*/
public function testAddSourceDupe() {
- $rl = new ResourceLoader;
+ $rl = new EmptyResourceLoader;
$this->setExpectedException(
MWException::class, 'ResourceLoader duplicate source addition error'
);
* @covers ResourceLoader::addSource
*/
public function testAddSourceInvalid() {
- $rl = new ResourceLoader;
+ $rl = new EmptyResourceLoader;
$this->setExpectedException( MWException::class, 'with no "loadScript" key' );
$rl->addSource( 'foo', [ 'x' => 'https://example.org/w/load.php' ] );
}
* @covers ResourceLoader::getLoadScript
*/
public function testGetLoadScript() {
- $rl = new ResourceLoader();
+ $rl = new EmptyResourceLoader();
$sources = self::fakeSources();
$rl->addSource( $sources );
foreach ( [ 'examplewiki', 'example2wiki' ] as $name ) {
// Disable log from outputErrorAndLog
->setMethods( [ 'outputErrorAndLog' ] )->getMock();
$rl->register( [
- 'foo' => self::getSimpleModuleMock(),
- 'ferry' => self::getFailFerryMock(),
- 'bar' => self::getSimpleModuleMock(),
+ 'foo' => [ 'class' => ResourceLoaderTestModule::class ],
+ 'ferry' => [
+ 'factory' => function () {
+ return self::getFailFerryMock();
+ }
+ ],
+ 'bar' => [ 'class' => ResourceLoaderTestModule::class ],
] );
$context = $this->getResourceLoaderContext( [], $rl );
$modules = array_map( function ( $script ) {
return self::getSimpleModuleMock( $script );
}, $scripts );
- $rl->register( $modules );
$context = $this->getResourceLoaderContext(
[
'bar' => self::getSimpleModuleMock( 'bar();' ),
];
$rl = new EmptyResourceLoader();
- $rl->register( $modules );
$context = $this->getResourceLoaderContext(
[
'modules' => 'foo|ferry|bar',
'bar' => self::getSimpleStyleModuleMock( '.bar{}' ),
];
$rl = new EmptyResourceLoader();
- $rl->register( $modules );
$context = $this->getResourceLoaderContext(
[
'modules' => 'foo|ferry|bar',
* @covers ResourceLoader::makeModuleResponse
*/
public function testMakeModuleResponseStartupError() {
- $rl = new EmptyResourceLoader();
+ // This is an integration test that uses a lot of MediaWiki state,
+ // provide the full Config object here.
+ $rl = new EmptyResourceLoader( MediaWikiServices::getInstance()->getMainConfig() );
$rl->register( [
- 'foo' => self::getSimpleModuleMock( 'foo();' ),
- 'ferry' => self::getFailFerryMock(),
- 'bar' => self::getSimpleModuleMock( 'bar();' ),
- 'startup' => [ 'class' => ResourceLoaderStartUpModule::class ],
+ 'foo' => [ 'factory' => function () {
+ return self::getSimpleModuleMock( 'foo();' );
+ } ],
+ 'ferry' => [ 'factory' => function () {
+ return self::getFailFerryMock();
+ } ],
+ 'bar' => [ 'factory' => function () {
+ return self::getSimpleModuleMock( 'bar();' );
+ } ],
] );
$context = $this->getResourceLoaderContext(
[
);
$this->assertEquals(
- [ 'foo', 'ferry', 'bar', 'startup' ],
+ [ 'startup', 'foo', 'ferry', 'bar' ],
$rl->getModuleNames(),
'getModuleNames'
);
] );
$rl = new EmptyResourceLoader();
- $rl->register( [
- 'foo' => $module,
- ] );
$context = $this->getResourceLoaderContext(
[ 'modules' => 'foo', 'only' => 'scripts' ],
$rl
);
- $modules = [ 'foo' => $rl->getModule( 'foo' ) ];
+ $modules = [ 'foo' => $module ];
$response = $rl->makeModuleResponse( $context, $modules );
$extraHeaders = TestingAccessWrapper::newFromObject( $rl )->extraHeaders;
] );
$rl = new EmptyResourceLoader();
- $rl->register( [ 'foo' => $foo, 'bar' => $bar ] );
$context = $this->getResourceLoaderContext(
[ 'modules' => 'foo|bar', 'only' => 'scripts' ],
$rl
);
- $modules = [ 'foo' => $rl->getModule( 'foo' ), 'bar' => $rl->getModule( 'bar' ) ];
+ $modules = [ 'foo' => $foo, 'bar' => $bar ];
$response = $rl->makeModuleResponse( $context, $modules );
$extraHeaders = TestingAccessWrapper::newFromObject( $rl )->extraHeaders;
$this->assertEquals(
'makeModuleResponse',
] )
->getMock();
- $rl->register( 'test', $module );
+ $rl->register( 'test', [
+ 'factory' => function () use ( $module ) {
+ return $module;
+ }
+ ] );
$context = $this->getResourceLoaderContext(
[ 'modules' => 'test', 'only' => null ],
$rl
'sendResponseHeaders',
] )
->getMock();
- $rl->register( 'test', $module );
+ $rl->register( 'test', [
+ 'factory' => function () use ( $module ) {
+ return $module;
+ }
+ ] );
$context = $this->getResourceLoaderContext( [ 'modules' => 'test' ], $rl );
// Disable logging from outputErrorAndLog
$this->setLogger( 'exception', new Psr\Log\NullLogger() );