wiki.techinc.nl/tests/phpunit/includes/resourceloader/ResourceLoaderTest.php
Timo Tijhof 3cf2f18bb8 resourceloader: Omit empty parameters from mw.loader.implement calls
Follows-up ebeb29723, 1f393b6da, 0e719ce23.

Also:
* Add tests for ResourceLoader::makeLoaderImplementScript().
* Apply ResourceLoader::trimArray to makeLoaderImplementScript (new in c0c221bf).

This commit changes the load.php response to omit empty parameters.

These parameters were required until recently. The client has been
updated (1f393b6da and 0e719ce23) to make these optional, thus supporting
both the old server format and the change this commit makes

Clients with a tab open from before 0e719ce23 are naturally not
compatible with load.php responses from after this commit. Ensure
this is deployed several days after 0e719ce23 to reduce race
conditions of this nature.

(This is a re-submitted version of 4ce0c0da4)

Bug: T88879
Change-Id: I9e998261ee9b0b745e3339bc3493755c0cb04b6a
2015-04-03 07:20:51 +01:00

318 lines
8.4 KiB
PHP

<?php
class ResourceLoaderTest extends ResourceLoaderTestCase {
protected function setUp() {
parent::setUp();
$this->setMwGlobals( array(
'wgResourceLoaderLESSFunctions' => array(
'test-sum' => function ( $frame, $less ) {
$sum = 0;
foreach ( $frame[2] as $arg ) {
$sum += (int)$arg[1];
}
return $sum;
},
),
'wgResourceLoaderLESSImportPaths' => array(
dirname( dirname( __DIR__ ) ) . '/data/less/common',
),
'wgResourceLoaderLESSVars' => array(
'foo' => '2px',
'Foo' => '#eeeeee',
'bar' => 5,
),
) );
}
public static function provideValidModules() {
return array(
array( 'TEST.validModule1', new ResourceLoaderTestModule() ),
);
}
/**
* Ensures that the ResourceLoaderRegisterModules hook is called when a new
* ResourceLoader object is constructed.
* @covers ResourceLoader::__construct
*/
public function testCreatingNewResourceLoaderCallsRegistrationHook() {
$resourceLoaderRegisterModulesHook = false;
$this->setMwGlobals( 'wgHooks', array(
'ResourceLoaderRegisterModules' => array(
function ( &$resourceLoader ) use ( &$resourceLoaderRegisterModulesHook ) {
$resourceLoaderRegisterModulesHook = true;
}
)
) );
$resourceLoader = new ResourceLoader();
$this->assertTrue(
$resourceLoaderRegisterModulesHook,
'Hook ResourceLoaderRegisterModules called'
);
return $resourceLoader;
}
/**
* @dataProvider provideValidModules
* @depends testCreatingNewResourceLoaderCallsRegistrationHook
* @covers ResourceLoader::register
* @covers ResourceLoader::getModule
*/
public function testRegisteredValidModulesAreAccessible(
$name, ResourceLoaderModule $module, ResourceLoader $resourceLoader
) {
$resourceLoader->register( $name, $module );
$this->assertEquals( $module, $resourceLoader->getModule( $name ) );
}
/**
* @covers ResourceLoaderFileModule::compileLessFile
*/
public function testLessFileCompilation() {
$context = $this->getResourceLoaderContext();
$basePath = __DIR__ . '/../../data/less/module';
$module = new ResourceLoaderFileModule( array(
'localBasePath' => $basePath,
'styles' => array( 'styles.less' ),
) );
$module->setName( 'test.less' );
$styles = $module->getStyles( $context );
$this->assertStringEqualsFile( $basePath . '/styles.css', $styles['all'] );
}
/**
* Strip @noflip annotations from CSS code.
* @param string $css
* @return string
*/
private static function stripNoflip( $css ) {
return str_replace( '/*@noflip*/ ', '', $css );
}
/**
* @dataProvider providePackedModules
* @covers ResourceLoader::makePackedModulesString
*/
public function testMakePackedModulesString( $desc, $modules, $packed ) {
$this->assertEquals( $packed, ResourceLoader::makePackedModulesString( $modules ), $desc );
}
/**
* @dataProvider providePackedModules
* @covers ResourceLoaderContext::expandModuleNames
*/
public function testexpandModuleNames( $desc, $modules, $packed ) {
$this->assertEquals( $modules, ResourceLoaderContext::expandModuleNames( $packed ), $desc );
}
public static function providePackedModules() {
return array(
array(
'Example from makePackedModulesString doc comment',
array( 'foo.bar', 'foo.baz', 'bar.baz', 'bar.quux' ),
'foo.bar,baz|bar.baz,quux',
),
array(
'Example from expandModuleNames doc comment',
array( 'jquery.foo', 'jquery.bar', 'jquery.ui.baz', 'jquery.ui.quux' ),
'jquery.foo,bar|jquery.ui.baz,quux',
),
array(
'Regression fixed in r88706 with dotless names',
array( 'foo', 'bar', 'baz' ),
'foo,bar,baz',
),
array(
'Prefixless modules after a prefixed module',
array( 'single.module', 'foobar', 'foobaz' ),
'single.module|foobar,foobaz',
),
);
}
public static function provideAddSource() {
return array(
array( 'examplewiki', '//example.org/w/load.php', 'examplewiki' ),
array( 'example2wiki', array( 'loadScript' => '//example.com/w/load.php' ), 'example2wiki' ),
array(
array( 'foowiki' => '//foo.org/w/load.php', 'bazwiki' => '//baz.org/w/load.php' ),
null,
array( 'foowiki', 'bazwiki' )
),
array(
array( 'foowiki' => '//foo.org/w/load.php' ),
null,
false,
),
);
}
/**
* @dataProvider provideAddSource
* @covers ResourceLoader::addSource
* @covers ResourceLoader::getSources
*/
public function testAddSource( $name, $info, $expected ) {
$rl = new ResourceLoader;
if ( $expected === false ) {
$this->setExpectedException( 'MWException', 'ResourceLoader duplicate source addition error' );
$rl->addSource( $name, $info );
}
$rl->addSource( $name, $info );
if ( is_array( $expected ) ) {
foreach ( $expected as $source ) {
$this->assertArrayHasKey( $source, $rl->getSources() );
}
} else {
$this->assertArrayHasKey( $expected, $rl->getSources() );
}
}
public static function fakeSources() {
return array(
'examplewiki' => array(
'loadScript' => '//example.org/w/load.php',
'apiScript' => '//example.org/w/api.php',
),
'example2wiki' => array(
'loadScript' => '//example.com/w/load.php',
'apiScript' => '//example.com/w/api.php',
),
);
}
public static function provideLoaderImplement() {
return array(
array( array(
'title' => 'Implement scripts, styles and messages',
'name' => 'test.example',
'scripts' => 'mw.example();',
'styles' => array( 'css' => array( '.mw-example {}' ) ),
'messages' => array( 'example' => '' ),
'templates' => array(),
'expected' => 'mw.loader.implement( "test.example", function ( $, jQuery ) {
mw.example();
}, {
"css": [
".mw-example {}"
]
}, {
"example": ""
} );',
) ),
array( array(
'title' => 'Implement scripts',
'name' => 'test.example',
'scripts' => 'mw.example();',
'styles' => array(),
'messages' => new XmlJsCode( '{}' ),
'templates' => array(),
'title' => 'scripts, styles and messags',
'expected' => 'mw.loader.implement( "test.example", function ( $, jQuery ) {
mw.example();
} );',
) ),
array( array(
'title' => 'Implement styles',
'name' => 'test.example',
'scripts' => array(),
'styles' => array( 'css' => array( '.mw-example {}' ) ),
'messages' => new XmlJsCode( '{}' ),
'templates' => array(),
'expected' => 'mw.loader.implement( "test.example", [], {
"css": [
".mw-example {}"
]
} );',
) ),
array( array(
'title' => 'Implement scripts and messages',
'name' => 'test.example',
'scripts' => 'mw.example();',
'styles' => array(),
'messages' => array( 'example' => '' ),
'templates' => array(),
'expected' => 'mw.loader.implement( "test.example", function ( $, jQuery ) {
mw.example();
}, {}, {
"example": ""
} );',
) ),
array( array(
'title' => 'Implement scripts and templates',
'name' => 'test.example',
'scripts' => 'mw.example();',
'styles' => array(),
'messages' => new XmlJsCode( '{}' ),
'templates' => array( 'example.html' => '' ),
'expected' => 'mw.loader.implement( "test.example", function ( $, jQuery ) {
mw.example();
}, {}, {}, {
"example.html": ""
} );',
) ),
);
}
/**
* @dataProvider provideLoaderImplement
* @covers ResourceLoader::makeLoaderImplementScript
*/
public function testMakeLoaderImplementScript( $case ) {
$this->assertEquals(
$case['expected'],
ResourceLoader::makeLoaderImplementScript(
$case['name'],
$case['scripts'],
$case['styles'],
$case['messages'],
$case['templates']
)
);
}
/**
* @covers ResourceLoader::getLoadScript
*/
public function testGetLoadScript() {
$this->setMwGlobals( 'wgResourceLoaderSources', array() );
$rl = new ResourceLoader();
$sources = self::fakeSources();
$rl->addSource( $sources );
foreach ( array( 'examplewiki', 'example2wiki' ) as $name ) {
$this->assertEquals( $rl->getLoadScript( $name ), $sources[$name]['loadScript'] );
}
try {
$rl->getLoadScript( 'thiswasneverreigstered' );
$this->assertTrue( false, 'ResourceLoader::getLoadScript should have thrown an exception' );
} catch ( MWException $e ) {
$this->assertTrue( true );
}
}
/**
* @covers ResourceLoader::isModuleRegistered
*/
public function testIsModuleRegistered() {
$rl = new ResourceLoader();
$rl->register( 'test.module', new ResourceLoaderTestModule() );
$this->assertTrue( $rl->isModuleRegistered( 'test.module' ) );
$this->assertFalse( $rl->isModuleRegistered( 'test.modulenotregistered' ) );
}
}