wiki.techinc.nl/tests/phpunit/includes/ResourceLoader/ModuleTest.php
Timo Tijhof 11f729301b ResourceLoader: Hoist and simplify @covers in test cases
I consider it busywork to maintain this, for no tangible benefit.
Limiting the credited coverage to a class is limiting enough to
exclude unintended coverage from reports. Especially as this
helps ensure tracking coverage correctly for implementation details
such as helper methods and internal methods that do not warrant
their own test as that would defeat the purpose of tests exercising
the contract and demonstrating good usage.

Change-Id: Icf865f15cbd86585bbc02fc4943a960efb40c0eb
2022-08-23 23:59:17 +00:00

307 lines
8.3 KiB
PHP

<?php
namespace MediaWiki\Tests\ResourceLoader;
use LogicException;
use MediaWiki\MainConfigNames;
use MediaWiki\ResourceLoader\FileModule;
use MediaWiki\ResourceLoader\Module;
use MediaWiki\ResourceLoader\ResourceLoader;
use ReflectionMethod;
use ResourceLoaderFileModuleTestingSubclass;
use ResourceLoaderTestCase;
use ResourceLoaderTestModule;
/**
* @covers \MediaWiki\ResourceLoader\Module
*/
class ModuleTest extends ResourceLoaderTestCase {
public function testGetVersionHash() {
$context = $this->getResourceLoaderContext( [ 'debug' => 'false' ] );
$baseParams = [
'scripts' => [ 'foo.js', 'bar.js' ],
'dependencies' => [ 'jquery', 'mediawiki' ],
'messages' => [ 'hello', 'world' ],
];
$module = new FileModule( $baseParams );
$module->setName( "" );
$version = json_encode( $module->getVersionHash( $context ) );
// Exactly the same
$module = new FileModule( $baseParams );
$module->setName( "" );
$this->assertEquals(
$version,
json_encode( $module->getVersionHash( $context ) ),
'Instance is insignificant'
);
// Re-order dependencies
$module = new FileModule( [
'dependencies' => [ 'mediawiki', 'jquery' ],
] + $baseParams );
$module->setName( "" );
$this->assertEquals(
$version,
json_encode( $module->getVersionHash( $context ) ),
'Order of dependencies is insignificant'
);
// Re-order messages
$module = new FileModule( [
'messages' => [ 'world', 'hello' ],
] + $baseParams );
$module->setName( "" );
$this->assertEquals(
$version,
json_encode( $module->getVersionHash( $context ) ),
'Order of messages is insignificant'
);
// Re-order scripts
$module = new FileModule( [
'scripts' => [ 'bar.js', 'foo.js' ],
] + $baseParams );
$module->setName( "" );
$this->assertNotEquals(
$version,
json_encode( $module->getVersionHash( $context ) ),
'Order of scripts is significant'
);
// Subclass
$module = new ResourceLoaderFileModuleTestingSubclass( $baseParams );
$module->setName( "" );
$this->assertNotEquals(
$version,
json_encode( $module->getVersionHash( $context ) ),
'Class is significant'
);
}
public function testGetVersionHash_debug() {
$module = new ResourceLoaderTestModule( [ 'script' => 'foo();' ] );
$module->setName( "" );
$context = $this->getResourceLoaderContext( [ 'debug' => 'true' ] );
$this->assertSame( '', $module->getVersionHash( $context ) );
}
public function testGetVersionHash_length() {
$context = $this->getResourceLoaderContext( [ 'debug' => 'false' ] );
$module = new ResourceLoaderTestModule( [
'script' => 'foo();'
] );
$module->setName( "" );
$version = $module->getVersionHash( $context );
$this->assertSame( ResourceLoader::HASH_LENGTH, strlen( $version ), 'Hash length' );
}
public function testGetVersionHash_parentDefinition() {
$context = $this->getResourceLoaderContext( [ 'debug' => 'false' ] );
$module = $this->getMockBuilder( Module::class )
->onlyMethods( [ 'getDefinitionSummary' ] )->getMock();
$module->method( 'getDefinitionSummary' )->willReturn( [ 'a' => 'summary' ] );
$module->setName( "" );
$this->expectException( LogicException::class );
$this->expectExceptionMessage( 'must call parent' );
$module->getVersionHash( $context );
}
/**
* @covers \MediaWiki\ResourceLoader\Module
* @covers \MediaWiki\ResourceLoader\ResourceLoader
*/
public function testGetURLsForDebug() {
$module = new ResourceLoaderTestModule( [
'script' => 'foo();',
'styles' => '.foo { color: blue; }',
] );
$context = $this->getResourceLoaderContext( [ 'debug' => 'true' ] );
$module->setConfig( $context->getResourceLoader()->getConfig() );
$module->setName( "" );
$this->assertEquals(
[
'https://example.org/w/load.php?debug=1&lang=en&modules=&only=scripts'
],
$module->getScriptURLsForDebug( $context ),
'script urls debug=true'
);
$this->assertEquals(
[ 'all' => [
'/w/load.php?debug=1&lang=en&modules=&only=styles'
] ],
$module->getStyleURLsForDebug( $context ),
'style urls debug=true'
);
$context = $this->getResourceLoaderContext( [ 'debug' => '2' ] );
$this->assertEquals(
[
'https://example.org/w/load.php?debug=2&lang=en&modules=&only=scripts'
],
$module->getScriptURLsForDebug( $context ),
'script urls debug=2'
);
$this->assertEquals(
[ 'all' => [
'/w/load.php?debug=2&lang=en&modules=&only=styles'
] ],
$module->getStyleURLsForDebug( $context ),
'style urls debug=2'
);
}
public function testValidateScriptFile() {
$this->overrideConfigValue( MainConfigNames::ResourceLoaderValidateJS, true );
$context = $this->getResourceLoaderContext();
$module = new ResourceLoaderTestModule( [
'mayValidateScript' => true,
'script' => "var a = 'this is';\n {\ninvalid"
] );
$module->setConfig( $context->getResourceLoader()->getConfig() );
$this->assertEquals(
'mw.log.error(' .
'"JavaScript parse error (scripts need to be valid ECMAScript 5): ' .
'Parse error: Unexpected token; token } expected in file \'input\' on line 3"' .
');',
$module->getScript( $context ),
'Replace invalid syntax with error logging'
);
$module = new ResourceLoaderTestModule( [
'script' => "\n'valid';"
] );
$this->assertEquals(
"\n'valid';",
$module->getScript( $context ),
'Leave valid scripts as-is'
);
}
public static function provideBuildContentScripts() {
return [
[
"mw.foo()",
"mw.foo()\n",
],
[
"mw.foo();",
"mw.foo();\n",
],
[
"mw.foo();\n",
"mw.foo();\n",
],
[
"mw.foo()\n",
"mw.foo()\n",
],
[
"mw.foo()\n// mw.bar();",
"mw.foo()\n// mw.bar();\n",
],
[
"mw.foo()\n// mw.bar()",
"mw.foo()\n// mw.bar()\n",
],
[
"mw.foo()// mw.bar();",
"mw.foo()// mw.bar();\n",
],
];
}
/**
* @dataProvider provideBuildContentScripts
*/
public function testBuildContentScripts( $raw, $build, $message = '' ) {
$context = $this->getResourceLoaderContext();
$module = new ResourceLoaderTestModule( [
'script' => $raw
] );
$module->setName( "" );
$this->assertEquals( $raw, $module->getScript( $context ), 'Raw script' );
$this->assertEquals(
$build,
$module->getModuleContent( $context )[ 'scripts' ],
$message
);
}
public function testPlaceholderize() {
$getRelativePaths = new ReflectionMethod( Module::class, 'getRelativePaths' );
$getRelativePaths->setAccessible( true );
$expandRelativePaths = new ReflectionMethod( Module::class, 'expandRelativePaths' );
$expandRelativePaths->setAccessible( true );
$this->setMwGlobals( [
'IP' => '/srv/example/mediawiki/core',
] );
$raw = [
'/srv/example/mediawiki/core/resources/foo.js',
'/srv/example/mediawiki/core/extensions/Example/modules/bar.js',
'/srv/example/mediawiki/skins/Example/baz.css',
'/srv/example/mediawiki/skins/Example/images/quux.png',
];
$canonical = [
'resources/foo.js',
'extensions/Example/modules/bar.js',
'../skins/Example/baz.css',
'../skins/Example/images/quux.png',
];
$this->assertEquals(
$canonical,
$getRelativePaths->invoke( null, $raw ),
'Insert placeholders'
);
$this->assertEquals(
$raw,
$expandRelativePaths->invoke( null, $canonical ),
'Substitute placeholders'
);
}
public function testGetHeaders() {
$context = $this->getResourceLoaderContext();
$module = new ResourceLoaderTestModule();
$module->setName( "" );
$this->assertSame( [], $module->getHeaders( $context ), 'Default' );
$module = $this->getMockBuilder( ResourceLoaderTestModule::class )
->onlyMethods( [ 'getPreloadLinks' ] )->getMock();
$module->method( 'getPreloadLinks' )->willReturn( [
'https://example.org/script.js' => [ 'as' => 'script' ],
] );
$this->assertSame(
[
'Link: <https://example.org/script.js>;rel=preload;as=script'
],
$module->getHeaders( $context ),
'Preload one resource'
);
$module = $this->getMockBuilder( ResourceLoaderTestModule::class )
->onlyMethods( [ 'getPreloadLinks' ] )->getMock();
$module->method( 'getPreloadLinks' )->willReturn( [
'https://example.org/script.js' => [ 'as' => 'script' ],
'/example.png' => [ 'as' => 'image' ],
] );
$module->setName( "" );
$this->assertSame(
[
'Link: <https://example.org/script.js>;rel=preload;as=script,' .
'</example.png>;rel=preload;as=image'
],
$module->getHeaders( $context ),
'Preload two resources'
);
}
}