This reverts commit e08ea8ccb9.
Reason for revert: Breaks Phan in extensions, and as far as I’m aware,
this change isn’t urgently needed for anything, so the simplest fix is
to revert it again for now. After PHP 7.4 it should be safer to try this
again (we hopefully won’t need the two “hack” classes by then).
Bug: T308443
Change-Id: Iff3318cbf97a67f821f78e60da62a583f63e389e
304 lines
8.3 KiB
PHP
304 lines
8.3 KiB
PHP
<?php
|
|
|
|
class ResourceLoaderModuleTest extends ResourceLoaderTestCase {
|
|
|
|
/**
|
|
* @covers ResourceLoaderModule::getVersionHash
|
|
*/
|
|
public function testGetVersionHash() {
|
|
$context = $this->getResourceLoaderContext( [ 'debug' => 'false' ] );
|
|
|
|
$baseParams = [
|
|
'scripts' => [ 'foo.js', 'bar.js' ],
|
|
'dependencies' => [ 'jquery', 'mediawiki' ],
|
|
'messages' => [ 'hello', 'world' ],
|
|
];
|
|
|
|
$module = new ResourceLoaderFileModule( $baseParams );
|
|
$version = json_encode( $module->getVersionHash( $context ) );
|
|
|
|
// Exactly the same
|
|
$module = new ResourceLoaderFileModule( $baseParams );
|
|
$this->assertEquals(
|
|
$version,
|
|
json_encode( $module->getVersionHash( $context ) ),
|
|
'Instance is insignificant'
|
|
);
|
|
|
|
// Re-order dependencies
|
|
$module = new ResourceLoaderFileModule( [
|
|
'dependencies' => [ 'mediawiki', 'jquery' ],
|
|
] + $baseParams );
|
|
$this->assertEquals(
|
|
$version,
|
|
json_encode( $module->getVersionHash( $context ) ),
|
|
'Order of dependencies is insignificant'
|
|
);
|
|
|
|
// Re-order messages
|
|
$module = new ResourceLoaderFileModule( [
|
|
'messages' => [ 'world', 'hello' ],
|
|
] + $baseParams );
|
|
$this->assertEquals(
|
|
$version,
|
|
json_encode( $module->getVersionHash( $context ) ),
|
|
'Order of messages is insignificant'
|
|
);
|
|
|
|
// Re-order scripts
|
|
$module = new ResourceLoaderFileModule( [
|
|
'scripts' => [ 'bar.js', 'foo.js' ],
|
|
] + $baseParams );
|
|
$this->assertNotEquals(
|
|
$version,
|
|
json_encode( $module->getVersionHash( $context ) ),
|
|
'Order of scripts is significant'
|
|
);
|
|
|
|
// Subclass
|
|
$module = new ResourceLoaderFileModuleTestingSubclass( $baseParams );
|
|
$this->assertNotEquals(
|
|
$version,
|
|
json_encode( $module->getVersionHash( $context ) ),
|
|
'Class is significant'
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @covers ResourceLoaderModule::getVersionHash
|
|
*/
|
|
public function testGetVersionHash_debug() {
|
|
$module = new ResourceLoaderTestModule( [ 'script' => 'foo();' ] );
|
|
$context = $this->getResourceLoaderContext( [ 'debug' => 'true' ] );
|
|
$this->assertSame( '', $module->getVersionHash( $context ) );
|
|
}
|
|
|
|
/**
|
|
* @covers ResourceLoaderModule::getVersionHash
|
|
*/
|
|
public function testGetVersionHash_length() {
|
|
$context = $this->getResourceLoaderContext( [ 'debug' => 'false' ] );
|
|
$module = new ResourceLoaderTestModule( [
|
|
'script' => 'foo();'
|
|
] );
|
|
$version = $module->getVersionHash( $context );
|
|
$this->assertSame( ResourceLoader::HASH_LENGTH, strlen( $version ), 'Hash length' );
|
|
}
|
|
|
|
/**
|
|
* @covers ResourceLoaderModule::getVersionHash
|
|
*/
|
|
public function testGetVersionHash_parentDefinition() {
|
|
$context = $this->getResourceLoaderContext( [ 'debug' => 'false' ] );
|
|
$module = $this->getMockBuilder( ResourceLoaderModule::class )
|
|
->onlyMethods( [ 'getDefinitionSummary' ] )->getMock();
|
|
$module->method( 'getDefinitionSummary' )->willReturn( [ 'a' => 'summary' ] );
|
|
|
|
$this->expectException( LogicException::class );
|
|
$this->expectExceptionMessage( 'must call parent' );
|
|
$module->getVersionHash( $context );
|
|
}
|
|
|
|
/**
|
|
* @covers ResourceLoaderModule::getScriptURLsForDebug
|
|
* @covers ResourceLoader
|
|
* @covers ResourceLoaderModule::getScriptURLsForDebug
|
|
*/
|
|
public function testGetURLsForDebug() {
|
|
$module = new ResourceLoaderTestModule( [
|
|
'script' => 'foo();',
|
|
'styles' => '.foo { color: blue; }',
|
|
] );
|
|
$context = $this->getResourceLoaderContext( [ 'debug' => 'true' ] );
|
|
$module->setConfig( $context->getResourceLoader()->getConfig() );
|
|
|
|
$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'
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @covers ResourceLoaderModule::validateScriptFile
|
|
*/
|
|
public function testValidateScriptFile() {
|
|
$this->setMwGlobals( 'wgResourceLoaderValidateJS', 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
|
|
* @covers ResourceLoaderModule::buildContent
|
|
*/
|
|
public function testBuildContentScripts( $raw, $build, $message = '' ) {
|
|
$context = $this->getResourceLoaderContext();
|
|
$module = new ResourceLoaderTestModule( [
|
|
'script' => $raw
|
|
] );
|
|
$this->assertEquals( $raw, $module->getScript( $context ), 'Raw script' );
|
|
$this->assertEquals(
|
|
$build,
|
|
$module->getModuleContent( $context )[ 'scripts' ],
|
|
$message
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @covers ResourceLoaderModule::getRelativePaths
|
|
* @covers ResourceLoaderModule::expandRelativePaths
|
|
*/
|
|
public function testPlaceholderize() {
|
|
$getRelativePaths = new ReflectionMethod( ResourceLoaderModule::class, 'getRelativePaths' );
|
|
$getRelativePaths->setAccessible( true );
|
|
$expandRelativePaths = new ReflectionMethod( ResourceLoaderModule::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'
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @covers ResourceLoaderModule::getHeaders
|
|
* @covers ResourceLoaderModule::getPreloadLinks
|
|
*/
|
|
public function testGetHeaders() {
|
|
$context = $this->getResourceLoaderContext();
|
|
|
|
$module = new ResourceLoaderTestModule();
|
|
$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' ],
|
|
] );
|
|
$this->assertSame(
|
|
[
|
|
'Link: <https://example.org/script.js>;rel=preload;as=script,' .
|
|
'</example.png>;rel=preload;as=image'
|
|
],
|
|
$module->getHeaders( $context ),
|
|
'Preload two resources'
|
|
);
|
|
}
|
|
}
|