"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "tests/phpunit/includes/resourceloader/ResourceLoaderTest.php" between
mediawiki-1.31.1.tar.gz and mediawiki-1.32.0.tar.gz

About: MediaWiki is a wiki engine (the collaborative editing software that runs for e.g. Wikipedia, the free encyclopedia).

ResourceLoaderTest.php  (mediawiki-1.31.1):ResourceLoaderTest.php  (mediawiki-1.32.0)
<?php <?php
use Wikimedia\TestingAccessWrapper; use Wikimedia\TestingAccessWrapper;
class ResourceLoaderTest extends ResourceLoaderTestCase { class ResourceLoaderTest extends ResourceLoaderTestCase {
protected function setUp() { protected function setUp() {
parent::setUp(); parent::setUp();
$this->setMwGlobals( [ $this->setMwGlobals( [
'wgResourceLoaderLESSImportPaths' => [
dirname( dirname( __DIR__ ) ) . '/data/less/commo
n',
],
'wgResourceLoaderLESSVars' => [
'foo' => '2px',
'Foo' => '#eeeeee',
'bar' => 5,
],
// Clear ResourceLoaderGetConfigVars hooks (called by Sta
rtupModule)
// to avoid notices during testMakeModuleResponse for mis
sing
// wgResourceLoaderLESSVars keys in extension hooks.
'wgHooks' => [],
'wgShowExceptionDetails' => true, 'wgShowExceptionDetails' => true,
] ); ] );
} }
/** /**
* Ensure the ResourceLoaderRegisterModules hook is called. * Ensure the ResourceLoaderRegisterModules hook is called.
* *
* @covers ResourceLoader::__construct * @covers ResourceLoader::__construct
*/ */
public function testConstructRegistrationHook() { public function testConstructRegistrationHook() {
skipping to change at line 103 skipping to change at line 91
/** /**
* @covers ResourceLoader::register * @covers ResourceLoader::register
*/ */
public function testRegisterInvalidType() { public function testRegisterInvalidType() {
$resourceLoader = new EmptyResourceLoader(); $resourceLoader = new EmptyResourceLoader();
$this->setExpectedException( MWException::class, 'ResourceLoader module info type error' ); $this->setExpectedException( MWException::class, 'ResourceLoader module info type error' );
$resourceLoader->register( 'test', new stdClass() ); $resourceLoader->register( 'test', new stdClass() );
} }
/** /**
* @covers ResourceLoader::register
*/
public function testRegisterDuplicate() {
$logger = $this->getMockBuilder( Psr\Log\LoggerInterface::class )
->getMock();
$logger->expects( $this->once() )
->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' )
);
}
/**
* @covers ResourceLoader::getModuleNames * @covers ResourceLoader::getModuleNames
*/ */
public function testGetModuleNames() { public function testGetModuleNames() {
// Use an empty one so that core and extension modules don't get in. // Use an empty one so that core and extension modules don't get in.
$resourceLoader = new EmptyResourceLoader(); $resourceLoader = new EmptyResourceLoader();
$resourceLoader->register( 'test.foo', new ResourceLoaderTestModu le() ); $resourceLoader->register( 'test.foo', new ResourceLoaderTestModu le() );
$resourceLoader->register( 'test.bar', new ResourceLoaderTestModu le() ); $resourceLoader->register( 'test.bar', new ResourceLoaderTestModu le() );
$this->assertEquals( $this->assertEquals(
[ 'test.foo', 'test.bar' ], [ 'test.foo', 'test.bar' ],
$resourceLoader->getModuleNames() $resourceLoader->getModuleNames()
skipping to change at line 237 skipping to change at line 241
$rl = new EmptyResourceLoader(); $rl = new EmptyResourceLoader();
$rl->register( 'test', [] ); $rl->register( 'test', [] );
$this->assertInstanceOf( $this->assertInstanceOf(
ResourceLoaderFileModule::class, ResourceLoaderFileModule::class,
$rl->getModule( 'test' ), $rl->getModule( 'test' ),
'Array-style module registrations default to FileModule' 'Array-style module registrations default to FileModule'
); );
} }
/** /**
* @covers ResourceLoaderFileModule::compileLessFile * @covers ResourceLoader::getLessCompiler
*/ */
public function testLessFileCompilation() { public function testLessImportDirs() {
$context = $this->getResourceLoaderContext(); $rl = new EmptyResourceLoader();
$basePath = __DIR__ . '/../../data/less/module'; $lc = $rl->getLessCompiler( [ 'foo' => '2px', 'Foo' => '#eeeeee'
$module = new ResourceLoaderFileModule( [ ] );
'localBasePath' => $basePath, $basePath = dirname( dirname( __DIR__ ) ) . '/data/less';
'styles' => [ 'styles.less' ], $lc->SetImportDirs( [
"$basePath/common" => '',
] ); ] );
$module->setName( 'test.less' ); $css = $lc->parseFile( "$basePath/module/use-import-dir.less" )->
$styles = $module->getStyles( $context ); getCss();
$this->assertStringEqualsFile( $basePath . '/styles.css', $styles $this->assertStringEqualsFile( "$basePath/module/styles.css", $cs
['all'] ); s );
} }
public static function providePackedModules() { public static function providePackedModules() {
return [ return [
[ [
'Example from makePackedModulesString doc comment ', 'Example from makePackedModulesString doc comment ',
[ 'foo.bar', 'foo.baz', 'bar.baz', 'bar.quux' ], [ 'foo.bar', 'foo.baz', 'bar.baz', 'bar.quux' ],
'foo.bar,baz|bar.baz,quux', 'foo.bar,baz|bar.baz,quux',
], ],
[ [
skipping to change at line 499 skipping to change at line 502
"1234567" "1234567"
] ]
] );', ] );',
ResourceLoader::makeLoaderRegisterScript( [ ResourceLoader::makeLoaderRegisterScript( [
[ 'test.name', '1234567' ], [ 'test.name', '1234567' ],
] ), ] ),
'Nested array parameter' 'Nested array parameter'
); );
$this->assertEquals( $this->assertEquals(
'mw.loader.register( "test.name", "1234567" );', 'mw.loader.register( [
ResourceLoader::makeLoaderRegisterScript( [
'test.name', "test.foo",
'1234567' "100"
), ],
'Variadic parameters' [
"test.bar",
"200",
[
"test.unknown"
]
],
[
"test.baz",
"300",
[
3,
0
]
],
[
"test.quux",
"400",
[],
null,
null,
"return true;"
]
] );',
ResourceLoader::makeLoaderRegisterScript( [
[ 'test.foo', '100' , [], null, null ],
[ 'test.bar', '200', [ 'test.unknown' ], null ],
[ 'test.baz', '300', [ 'test.quux', 'test.foo' ],
null ],
[ 'test.quux', '400', [], null, null, 'return tru
e;' ],
] ),
'Compact dependency indexes'
); );
} }
/** /**
* @covers ResourceLoader::makeLoaderSourcesScript * @covers ResourceLoader::makeLoaderSourcesScript
*/ */
public function testMakeLoaderSourcesScript() { public function testMakeLoaderSourcesScript() {
$this->assertEquals( $this->assertEquals(
'mw.loader.addSource( "local", "/w/load.php" );', 'mw.loader.addSource( {
"local": "/w/load.php"
} );',
ResourceLoader::makeLoaderSourcesScript( 'local', '/w/loa d.php' ) ResourceLoader::makeLoaderSourcesScript( 'local', '/w/loa d.php' )
); );
$this->assertEquals( $this->assertEquals(
'mw.loader.addSource( { 'mw.loader.addSource( {
"local": "/w/load.php" "local": "/w/load.php"
} );', } );',
ResourceLoader::makeLoaderSourcesScript( [ 'local' => '/w /load.php' ] ) ResourceLoader::makeLoaderSourcesScript( [ 'local' => '/w /load.php' ] )
); );
$this->assertEquals( $this->assertEquals(
'mw.loader.addSource( { 'mw.loader.addSource( {
skipping to change at line 571 skipping to change at line 606
} }
try { try {
$rl->getLoadScript( 'thiswasneverreigstered' ); $rl->getLoadScript( 'thiswasneverreigstered' );
$this->assertTrue( false, 'ResourceLoader::getLoadScript should have thrown an exception' ); $this->assertTrue( false, 'ResourceLoader::getLoadScript should have thrown an exception' );
} catch ( MWException $e ) { } catch ( MWException $e ) {
$this->assertTrue( true ); $this->assertTrue( true );
} }
} }
protected function getFailFerryMock() { protected function getFailFerryMock( $getter = 'getScript' ) {
$mock = $this->getMockBuilder( ResourceLoaderTestModule::class ) $mock = $this->getMockBuilder( ResourceLoaderTestModule::class )
->setMethods( [ 'getScript' ] ) ->setMethods( [ $getter ] )
->getMock(); ->getMock();
$mock->method( 'getScript' )->will( $this->throwException( $mock->method( $getter )->will( $this->throwException(
new Exception( 'Ferry not found' ) new Exception( 'Ferry not found' )
) ); ) );
return $mock; return $mock;
} }
protected function getSimpleModuleMock( $script = '' ) { protected function getSimpleModuleMock( $script = '' ) {
$mock = $this->getMockBuilder( ResourceLoaderTestModule::class ) $mock = $this->getMockBuilder( ResourceLoaderTestModule::class )
->setMethods( [ 'getScript' ] ) ->setMethods( [ 'getScript' ] )
->getMock(); ->getMock();
$mock->method( 'getScript' )->willReturn( $script ); $mock->method( 'getScript' )->willReturn( $script );
return $mock; return $mock;
} }
protected function getSimpleStyleModuleMock( $styles = '' ) {
$mock = $this->getMockBuilder( ResourceLoaderTestModule::class )
->setMethods( [ 'getStyles' ] )
->getMock();
$mock->method( 'getStyles' )->willReturn( [ '' => $styles ] );
return $mock;
}
/** /**
* @covers ResourceLoader::getCombinedVersion * @covers ResourceLoader::getCombinedVersion
*/ */
public function testGetCombinedVersion() { public function testGetCombinedVersion() {
$rl = $this->getMockBuilder( EmptyResourceLoader::class ) $rl = $this->getMockBuilder( EmptyResourceLoader::class )
// Disable log from outputErrorAndLog // Disable log from outputErrorAndLog
->setMethods( [ 'outputErrorAndLog' ] )->getMock(); ->setMethods( [ 'outputErrorAndLog' ] )->getMock();
$rl->register( [ $rl->register( [
'foo' => self::getSimpleModuleMock(), 'foo' => self::getSimpleModuleMock(),
'ferry' => self::getFailFerryMock(), 'ferry' => self::getFailFerryMock(),
skipping to change at line 705 skipping to change at line 748
], ],
$rl $rl
); );
$response = $rl->makeModuleResponse( $context, $modules ); $response = $rl->makeModuleResponse( $context, $modules );
$this->assertSame( [], $rl->getErrors(), 'Errors' ); $this->assertSame( [], $rl->getErrors(), 'Errors' );
$this->assertEquals( $expected, $response, $message ?: 'Response' ); $this->assertEquals( $expected, $response, $message ?: 'Response' );
} }
/** /**
* @covers ResourceLoader::makeModuleResponse
*/
public function testMakeModuleResponseEmpty() {
$rl = new EmptyResourceLoader();
$context = $this->getResourceLoaderContext(
[ 'modules' => '', 'only' => 'scripts' ],
$rl
);
$response = $rl->makeModuleResponse( $context, [] );
$this->assertSame( [], $rl->getErrors(), 'Errors' );
$this->assertRegExp( '/^\/\*.+no modules were requested.+\*\/$/ms
', $response );
}
/**
* Verify that when building module content in a load.php response, * Verify that when building module content in a load.php response,
* an exception from one module will not break script output from * an exception from one module will not break script output from
* other modules. * other modules.
* *
* @covers ResourceLoader::makeModuleResponse * @covers ResourceLoader::makeModuleResponse
*/ */
public function testMakeModuleResponseError() { public function testMakeModuleResponseError() {
$modules = [ $modules = [
'foo' => self::getSimpleModuleMock( 'foo();' ), 'foo' => self::getSimpleModuleMock( 'foo();' ),
'ferry' => self::getFailFerryMock(), 'ferry' => self::getFailFerryMock(),
skipping to change at line 746 skipping to change at line 804
"foo();\nbar();\n" . 'mw.loader.state( { "foo();\nbar();\n" . 'mw.loader.state( {
"ferry": "error", "ferry": "error",
"foo": "ready", "foo": "ready",
"bar": "ready" "bar": "ready"
} );', } );',
$response $response
); );
} }
/** /**
* Verify that exceptions in PHP for one module will not break others
* (stylesheet response).
*
* @covers ResourceLoader::makeModuleResponse
*/
public function testMakeModuleResponseErrorCSS() {
$modules = [
'foo' => self::getSimpleStyleModuleMock( '.foo{}' ),
'ferry' => self::getFailFerryMock( 'getStyles' ),
'bar' => self::getSimpleStyleModuleMock( '.bar{}' ),
];
$rl = new EmptyResourceLoader();
$rl->register( $modules );
$context = $this->getResourceLoaderContext(
[
'modules' => 'foo|ferry|bar',
'only' => 'styles',
'debug' => 'false',
],
$rl
);
// Disable log from makeModuleResponse via outputErrorAndLog
$this->setLogger( 'exception', new Psr\Log\NullLogger() );
$response = $rl->makeModuleResponse( $context, $modules );
$errors = $rl->getErrors();
$this->assertCount( 2, $errors );
$this->assertRegExp( '/Ferry not found/', $errors[0] );
$this->assertRegExp( '/Problem.+"ferry":\s*"error"/ms', $errors[1
] );
$this->assertEquals(
'.foo{}.bar{}',
$response
);
}
/**
* Verify that when building the startup module response, * Verify that when building the startup module response,
* an exception from one module class will not break the entire * an exception from one module class will not break the entire
* startup module response. See T152266. * startup module response. See T152266.
* *
* @covers ResourceLoader::makeModuleResponse * @covers ResourceLoader::makeModuleResponse
*/ */
public function testMakeModuleResponseStartupError() { public function testMakeModuleResponseStartupError() {
$rl = new EmptyResourceLoader(); $rl = new EmptyResourceLoader();
$rl->register( [ $rl->register( [
'foo' => self::getSimpleModuleMock( 'foo();' ), 'foo' => self::getSimpleModuleMock( 'foo();' ),
skipping to change at line 784 skipping to change at line 879
// Disable log from makeModuleResponse via outputErrorAndLog // Disable log from makeModuleResponse via outputErrorAndLog
$this->setLogger( 'exception', new Psr\Log\NullLogger() ); $this->setLogger( 'exception', new Psr\Log\NullLogger() );
$modules = [ 'startup' => $rl->getModule( 'startup' ) ]; $modules = [ 'startup' => $rl->getModule( 'startup' ) ];
$response = $rl->makeModuleResponse( $context, $modules ); $response = $rl->makeModuleResponse( $context, $modules );
$errors = $rl->getErrors(); $errors = $rl->getErrors();
$this->assertRegExp( '/Ferry not found/', $errors[0] ); $this->assertRegExp( '/Ferry not found/', $errors[0] );
$this->assertCount( 1, $errors ); $this->assertCount( 1, $errors );
$this->assertRegExp( $this->assertRegExp(
'/isCompatible.*function startUp/s', '/isCompatible.*window\.RLQ/s',
$response, $response,
'startup response undisrupted (T152266)' 'startup response undisrupted (T152266)'
); );
$this->assertRegExp( $this->assertRegExp(
'/register\([^)]+"ferry",\s*""/s', '/register\([^)]+"ferry",\s*""/s',
$response, $response,
'startup response registers broken module' 'startup response registers broken module'
); );
$this->assertRegExp( $this->assertRegExp(
'/state\([^)]+"ferry":\s*"error"/s', '/state\([^)]+"ferry":\s*"error"/s',
skipping to change at line 878 skipping to change at line 973
'Link: </example.png>;rel=preload;as=image,</exam ple.jpg>;rel=preload;as=image' 'Link: </example.png>;rel=preload;as=image,</exam ple.jpg>;rel=preload;as=image'
], ],
$extraHeaders, $extraHeaders,
'Extra headers' 'Extra headers'
); );
} }
/** /**
* @covers ResourceLoader::respond * @covers ResourceLoader::respond
*/ */
public function testRespond() { public function testRespondEmpty() {
$rl = $this->getMockBuilder( EmptyResourceLoader::class ) $rl = $this->getMockBuilder( EmptyResourceLoader::class )
->setMethods( [ ->setMethods( [
'tryRespondNotModified', 'tryRespondNotModified',
'sendResponseHeaders', 'sendResponseHeaders',
'measureResponseTime', 'measureResponseTime',
] ) ] )
->getMock(); ->getMock();
$context = $this->getResourceLoaderContext( [ 'modules' => '' ], $rl ); $context = $this->getResourceLoaderContext( [ 'modules' => '' ], $rl );
$rl->expects( $this->once() )->method( 'measureResponseTime' ); $rl->expects( $this->once() )->method( 'measureResponseTime' );
$this->expectOutputRegex( '/no modules were requested/' ); $this->expectOutputRegex( '/no modules were requested/' );
$rl->respond( $context ); $rl->respond( $context );
} }
/** /**
* @covers ResourceLoader::respond
*/
public function testRespondSimple() {
$module = new ResourceLoaderTestModule( [ 'script' => 'foo();' ]
);
$rl = $this->getMockBuilder( EmptyResourceLoader::class )
->setMethods( [
'measureResponseTime',
'tryRespondNotModified',
'sendResponseHeaders',
'makeModuleResponse',
] )
->getMock();
$rl->register( 'test', $module );
$context = $this->getResourceLoaderContext(
[ 'modules' => 'test', 'only' => null ],
$rl
);
$rl->expects( $this->once() )->method( 'makeModuleResponse' )
->with( $context, [ 'test' => $module ] )
->willReturn( 'implement_foo;' );
$this->expectOutputRegex( '/^implement_foo;/' );
$rl->respond( $context );
}
/**
* @covers ResourceLoader::respond
*/
public function testRespondInternalFailures() {
$module = new ResourceLoaderTestModule( [ 'script' => 'foo();' ]
);
$rl = $this->getMockBuilder( EmptyResourceLoader::class )
->setMethods( [
'measureResponseTime',
'preloadModuleInfo',
'getCombinedVersion',
'tryRespondNotModified',
'makeModuleResponse',
'sendResponseHeaders',
] )
->getMock();
$rl->register( 'test', $module );
$context = $this->getResourceLoaderContext( [ 'modules' => 'test'
], $rl );
// Disable logging from outputErrorAndLog
$this->setLogger( 'exception', new Psr\Log\NullLogger() );
$rl->expects( $this->once() )->method( 'preloadModuleInfo' )
->willThrowException( new Exception( 'Preload error' ) );
$rl->expects( $this->once() )->method( 'getCombinedVersion' )
->willThrowException( new Exception( 'Version error' ) );
$rl->expects( $this->once() )->method( 'makeModuleResponse' )
->with( $context, [ 'test' => $module ] )
->willReturn( 'foo;' );
// Internal errors should be caught and logged without affecting
module output
$this->expectOutputRegex( '/^\/\*.+Preload error.+Version error.+
\*\/.*foo;/ms' );
$rl->respond( $context );
}
/**
* @covers ResourceLoader::measureResponseTime * @covers ResourceLoader::measureResponseTime
*/ */
public function testMeasureResponseTime() { public function testMeasureResponseTime() {
$stats = $this->getMockBuilder( NullStatsdDataFactory::class ) $stats = $this->getMockBuilder( NullStatsdDataFactory::class )
->setMethods( [ 'timing' ] )->getMock(); ->setMethods( [ 'timing' ] )->getMock();
$this->setService( 'StatsdDataFactory', $stats ); $this->setService( 'StatsdDataFactory', $stats );
$stats->expects( $this->once() )->method( 'timing' ) $stats->expects( $this->once() )->method( 'timing' )
->with( 'resourceloader.responseTime', $this->anything() ); ->with( 'resourceloader.responseTime', $this->anything() );
 End of changes. 16 change blocks. 
38 lines changed or deleted 203 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)