3 class ResourceLoaderStartUpModuleTest
extends ResourceLoaderTestCase
{
5 protected static function expandPlaceholders( $text ) {
7 '{blankVer}' => self
::BLANK_VERSION
11 public function provideGetModuleRegistrations() {
14 'msg' => 'Empty registry',
17 mw.loader.addSource( {
18 "local": "/w/load.php"
20 mw.loader.register( [] );'
23 'msg' => 'Basic registry',
25 'test.blank' => [ 'class' => ResourceLoaderTestModule
::class ],
28 mw.loader.addSource( {
29 "local": "/w/load.php"
39 'msg' => 'Optimise the dependency tree (basic case)',
42 'class' => ResourceLoaderTestModule
::class,
43 'dependencies' => [ 'b', 'c', 'd' ],
46 'class' => ResourceLoaderTestModule
::class,
47 'dependencies' => [ 'c' ],
50 'class' => ResourceLoaderTestModule
::class,
54 'class' => ResourceLoaderTestModule
::class,
59 mw.loader.addSource( {
60 "local": "/w/load.php"
89 'msg' => 'Optimise the dependency tree (tolerate unknown deps)',
92 'class' => ResourceLoaderTestModule
::class,
93 'dependencies' => [ 'b', 'c', 'x' ]
96 'class' => ResourceLoaderTestModule
::class,
97 'dependencies' => [ 'c', 'x' ]
100 'class' => ResourceLoaderTestModule
::class,
105 mw.loader.addSource( {
106 "local": "/w/load.php"
108 mw.loader.register( [
132 // Regression test for T223402.
133 'msg' => 'Optimise the dependency tree (indirect circular dependency)',
136 'class' => ResourceLoaderTestModule
::class,
137 'dependencies' => [ 'middle1', 'util' ],
140 'class' => ResourceLoaderTestModule
::class,
141 'dependencies' => [ 'middle2', 'util' ],
144 'class' => ResourceLoaderTestModule
::class,
145 'dependencies' => [ 'bottom' ],
148 'class' => ResourceLoaderTestModule
::class,
149 'dependencies' => [ 'top' ],
152 'class' => ResourceLoaderTestModule
::class,
153 'dependencies' => [],
157 mw.loader.addSource( {
158 "local": "/w/load.php"
160 mw.loader.register( [
198 // Regression test for T223402.
199 'msg' => 'Optimise the dependency tree (direct circular dependency)',
202 'class' => ResourceLoaderTestModule
::class,
203 'dependencies' => [ 'util', 'top' ],
206 'class' => ResourceLoaderTestModule
::class,
207 'dependencies' => [],
211 mw.loader.addSource( {
212 "local": "/w/load.php"
214 mw.loader.register( [
230 'msg' => 'Version falls back gracefully if getVersionHash throws',
233 'factory' => function () {
234 $mock = $this->getMockBuilder( ResourceLoaderTestModule
::class )
235 ->setMethods( [ 'getVersionHash' ] )->getMock();
236 $mock->method( 'getVersionHash' )->will(
237 $this->throwException( new Exception
)
244 mw.loader.addSource( {
245 "local": "/w/load.php"
247 mw.loader.register( [
258 'msg' => 'Use version from getVersionHash',
261 'factory' => function () {
262 $mock = $this->getMockBuilder( ResourceLoaderTestModule
::class )
263 ->setMethods( [ 'getVersionHash' ] )->getMock();
264 $mock->method( 'getVersionHash' )->willReturn( '1234567' );
270 mw.loader.addSource( {
271 "local": "/w/load.php"
273 mw.loader.register( [
281 'msg' => 'Re-hash version from getVersionHash if too long',
284 'factory' => function () {
285 $mock = $this->getMockBuilder( ResourceLoaderTestModule
::class )
286 ->setMethods( [ 'getVersionHash' ] )->getMock();
287 $mock->method( 'getVersionHash' )->willReturn( '12345678' );
293 mw.loader.addSource( {
294 "local": "/w/load.php"
296 mw.loader.register( [
304 'msg' => 'Group signature',
306 'test.blank' => [ 'class' => ResourceLoaderTestModule
::class ],
307 'test.group.foo' => [
308 'class' => ResourceLoaderTestModule
::class,
311 'test.group.bar' => [
312 'class' => ResourceLoaderTestModule
::class,
317 mw.loader.addSource( {
318 "local": "/w/load.php"
320 mw.loader.register( [
340 'msg' => 'Different target (non-test should not be registered)',
342 'test.blank' => [ 'class' => ResourceLoaderTestModule
::class ],
343 'test.target.foo' => [
344 'class' => ResourceLoaderTestModule
::class,
345 'targets' => [ 'x-foo' ],
349 mw.loader.addSource( {
350 "local": "/w/load.php"
352 mw.loader.register( [
360 'msg' => 'Safemode disabled (default; register all modules)',
362 // Default origin: ORIGIN_CORE_SITEWIDE
363 'test.blank' => [ 'class' => ResourceLoaderTestModule
::class ],
364 'test.core-generated' => [
365 'class' => ResourceLoaderTestModule
::class,
366 'origin' => ResourceLoaderModule
::ORIGIN_CORE_INDIVIDUAL
369 'class' => ResourceLoaderTestModule
::class,
370 'origin' => ResourceLoaderModule
::ORIGIN_USER_SITEWIDE
373 'class' => ResourceLoaderTestModule
::class,
374 'origin' => ResourceLoaderModule
::ORIGIN_USER_INDIVIDUAL
378 mw.loader.addSource( {
379 "local": "/w/load.php"
381 mw.loader.register( [
387 "test.core-generated",
401 'msg' => 'Safemode enabled (filter modules with user/site origin)',
402 'extraQuery' => [ 'safemode' => '1' ],
404 // Default origin: ORIGIN_CORE_SITEWIDE
405 'test.blank' => [ 'class' => ResourceLoaderTestModule
::class ],
406 'test.core-generated' => [
407 'class' => ResourceLoaderTestModule
::class,
408 'origin' => ResourceLoaderModule
::ORIGIN_CORE_INDIVIDUAL
411 'class' => ResourceLoaderTestModule
::class,
412 'origin' => ResourceLoaderModule
::ORIGIN_USER_SITEWIDE
415 'class' => ResourceLoaderTestModule
::class,
416 'origin' => ResourceLoaderModule
::ORIGIN_USER_INDIVIDUAL
420 mw.loader.addSource( {
421 "local": "/w/load.php"
423 mw.loader.register( [
429 "test.core-generated",
435 'msg' => 'Foreign source',
438 'loadScript' => 'http://example.org/w/load.php',
439 'apiScript' => 'http://example.org/w/api.php',
444 'class' => ResourceLoaderTestModule
::class,
445 'source' => 'example'
449 mw.loader.addSource( {
450 "local": "/w/load.php",
451 "example": "http://example.org/w/load.php"
453 mw.loader.register( [
464 'msg' => 'Conditional dependency function',
466 'test.x.core' => [ 'class' => ResourceLoaderTestModule
::class ],
467 'test.x.polyfill' => [
468 'class' => ResourceLoaderTestModule
::class,
469 'skipFunction' => 'return true;'
471 'test.y.polyfill' => [
472 'class' => ResourceLoaderTestModule
::class,
481 'class' => ResourceLoaderTestModule
::class,
490 mw.loader.addSource( {
491 "local": "/w/load.php"
493 mw.loader.register( [
512 "return !!( window.JSON \u0026\u0026 JSON.parse \u0026\u0026 JSON.stringify);"
526 // This may seem like an edge case, but a plain MediaWiki core install
527 // with a few extensions installed is likely far more complex than this
528 // even, not to mention an install like Wikipedia.
529 // TODO: Make this even more realistic.
530 'msg' => 'Advanced (everything combined)',
533 'loadScript' => 'http://example.org/w/load.php',
534 'apiScript' => 'http://example.org/w/api.php',
538 'test.blank' => [ 'class' => ResourceLoaderTestModule
::class ],
539 'test.x.core' => [ 'class' => ResourceLoaderTestModule
::class ],
541 'class' => ResourceLoaderTestModule
::class,
547 'class' => ResourceLoaderTestModule
::class,
553 'class' => ResourceLoaderTestModule
::class,
560 'class' => ResourceLoaderTestModule
::class,
568 'test.group.foo.1' => [
569 'class' => ResourceLoaderTestModule
::class,
572 'test.group.foo.2' => [
573 'class' => ResourceLoaderTestModule
::class,
576 'test.group.bar.1' => [
577 'class' => ResourceLoaderTestModule
::class,
580 'test.group.bar.2' => [
581 'class' => ResourceLoaderTestModule
::class,
583 'source' => 'example',
585 'test.target.foo' => [
586 'class' => ResourceLoaderTestModule
::class,
587 'targets' => [ 'x-foo' ],
589 'test.target.bar' => [
590 'class' => ResourceLoaderTestModule
::class,
591 'source' => 'example',
592 'targets' => [ 'x-foo' ],
596 mw.loader.addSource( {
597 "local": "/w/load.php",
598 "example": "http://example.org/w/load.php"
600 mw.loader.register( [
670 * @dataProvider provideGetModuleRegistrations
671 * @covers ResourceLoaderStartUpModule
672 * @covers ResourceLoader::makeLoaderRegisterScript
674 public function testGetModuleRegistrations( $case ) {
675 $extraQuery = $case['extraQuery'] ??
[];
676 $context = $this->getResourceLoaderContext( $extraQuery );
677 $rl = $context->getResourceLoader();
678 if ( isset( $case['sources'] ) ) {
679 $rl->addSource( $case['sources'] );
681 $rl->register( $case['modules'] );
682 $module = new ResourceLoaderStartUpModule();
683 $out = ltrim( $case['out'], "\n" );
685 // Disable log from getModuleRegistrations via MWExceptionHandler
686 // for case where getVersionHash() is expected to throw.
687 $this->setLogger( 'exception', new Psr\Log\
NullLogger() );
690 self
::expandPlaceholders( $out ),
691 $module->getModuleRegistrations( $context ),
696 public static function provideRegistrations() {
699 'test.blank' => [ 'class' => ResourceLoaderTestModule
::class ],
701 'class' => ResourceLoaderTestModule
::class,
717 * @covers ResourceLoaderStartUpModule::getModuleRegistrations
718 * @dataProvider provideRegistrations
720 public function testRegistrationsMinified( $modules ) {
721 $this->setMwGlobals( 'wgResourceLoaderDebug', false );
723 $context = $this->getResourceLoaderContext();
724 $rl = $context->getResourceLoader();
725 $rl->register( $modules );
726 $module = new ResourceLoaderStartUpModule();
727 $out = 'mw.loader.addSource({"local":"/w/load.php"});' . "\n"
728 . 'mw.loader.register(['
729 . '["test.blank","{blankVer}"],'
730 . '["test.min","{blankVer}",[0],null,null,'
731 . '"return!!(window.JSON\u0026\u0026JSON.parse\u0026\u0026JSON.stringify);"'
735 self
::expandPlaceholders( $out ),
736 $module->getModuleRegistrations( $context ),
742 * @covers ResourceLoaderStartUpModule::getModuleRegistrations
743 * @dataProvider provideRegistrations
745 public function testRegistrationsUnminified( $modules ) {
746 $context = $this->getResourceLoaderContext();
747 $rl = $context->getResourceLoader();
748 $rl->register( $modules );
749 $module = new ResourceLoaderStartUpModule();
751 'mw.loader.addSource( {
752 "local": "/w/load.php"
754 mw.loader.register( [
767 "return !!( window.JSON \u0026\u0026 JSON.parse \u0026\u0026 JSON.stringify);"
772 self
::expandPlaceholders( $out ),
773 $module->getModuleRegistrations( $context ),
779 * @covers ResourceLoaderStartupModule::getDefinitionSummary
781 public function testGetVersionHash_varyConfig() {
782 $context = $this->getResourceLoaderContext();
784 $this->setMwGlobals( 'wgArticlePath', '/w1' );
785 $module = new ResourceLoaderStartupModule();
786 $version1 = $module->getVersionHash( $context );
787 $module = new ResourceLoaderStartupModule();
788 $version2 = $module->getVersionHash( $context );
790 $this->setMwGlobals( 'wgArticlePath', '/w3' );
791 $module = new ResourceLoaderStartupModule();
792 $version3 = $module->getVersionHash( $context );
797 'Deterministic version hash'
800 $this->assertNotEquals(
803 'Config change impacts version hash'
808 * @covers ResourceLoaderStartupModule
810 public function testGetVersionHash_varyModule() {
811 $context1 = $this->getResourceLoaderContext();
812 $rl1 = $context1->getResourceLoader();
814 'test.a' => [ 'class' => ResourceLoaderTestModule
::class ],
815 'test.b' => [ 'class' => ResourceLoaderTestModule
::class ],
817 $module = new ResourceLoaderStartupModule();
818 $version1 = $module->getVersionHash( $context1 );
820 $context2 = $this->getResourceLoaderContext();
821 $rl2 = $context2->getResourceLoader();
823 'test.b' => [ 'class' => ResourceLoaderTestModule
::class ],
824 'test.c' => [ 'class' => ResourceLoaderTestModule
::class ],
826 $module = new ResourceLoaderStartupModule();
827 $version2 = $module->getVersionHash( $context2 );
829 $context3 = $this->getResourceLoaderContext();
830 $rl3 = $context3->getResourceLoader();
832 'test.a' => [ 'class' => ResourceLoaderTestModule
::class ],
834 'class' => ResourceLoaderTestModule
::class,
835 'script' => 'different',
838 $module = new ResourceLoaderStartupModule();
839 $version3 = $module->getVersionHash( $context3 );
841 // Module name *is* significant (T201686)
842 $this->assertNotEquals(
845 'Module name is significant'
848 $this->assertNotEquals(
851 'Hash change of any module impacts startup hash'
856 * @covers ResourceLoaderStartupModule
858 public function testGetVersionHash_varyDeps() {
859 $context = $this->getResourceLoaderContext();
860 $rl = $context->getResourceLoader();
863 'class' => ResourceLoaderTestModule
::class,
864 'dependencies' => [ 'x', 'y' ],
867 $module = new ResourceLoaderStartupModule();
868 $version1 = $module->getVersionHash( $context );
870 $context = $this->getResourceLoaderContext();
871 $rl = $context->getResourceLoader();
874 'class' => ResourceLoaderTestModule
::class,
875 'dependencies' => [ 'x', 'z' ],
878 $module = new ResourceLoaderStartupModule();
879 $version2 = $module->getVersionHash( $context );
881 // Dependencies *are* significant (T201686)
882 $this->assertNotEquals(
885 'Dependencies are significant'