From af96510455bcde92092e850ef8f7909b6c1e3399 Mon Sep 17 00:00:00 2001 From: Morne Alberts Date: Fri, 22 May 2026 10:40:09 +0200 Subject: [PATCH 1/2] Restore per-component vector-fix module loading `AbstractComponent::augmentParserOutput()` used to load each component's per-skin module variants by calling `getModulesFor()` with a hard-coded `'vector'` skin name, which the JSON registry treats as "always include the vector entry alongside the default". That published the `modal.vector-fix` and `popover.vector-fix` CSS to every skin's output, hiding the `.modal-backdrop` element on Vector-family chromes that would otherwise overlay the page. MediaWiki 1.43's ParserOutputAccess lifecycle change broke that publication path: the modules attached via the augment hook no longer reach the OutputPage. The earlier sparse-loading patch in `HooksHandler::onParserAfterParse` (5.2.3) routed the default modules through `ParserAfterParse` instead, but its foreach didn't pass any skin argument, so the per-skin entries stopped loading on every skin. Users on Vector, Vector 2022, MonoBook, and Timeless all end up with the BS4 modal backdrop covering the page once a modal opens. Pass the same hard-coded `'vector'` into the post-parse foreach so the registry returns the per-skin variants exactly as it did pre-1.43. The redesign of this path (route by active skin name, audit per-skin requirements) belongs in the next major release. Co-Authored-By: Claude Opus 4.7 --- src/HooksHandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/HooksHandler.php b/src/HooksHandler.php index 7ff5bac..91fbef5 100644 --- a/src/HooksHandler.php +++ b/src/HooksHandler.php @@ -226,7 +226,7 @@ public function onParserAfterParse( $parser, &$text, $stripState ): bool { if ( !$this->getComponentLibrary()->isRegistered( $activeComponent ) ) { continue; } - foreach ( $this->getComponentLibrary()->getModulesFor( $activeComponent ) as $module ) { + foreach ( $this->getComponentLibrary()->getModulesFor( $activeComponent, 'vector' ) as $module ) { $parser->getOutput()->addModuleStyles( [ $module ] ); $parser->getOutput()->addModules( [ $module ] ); } From c0ac01b8d6180a7701d6b7835134eacb28b678d0 Mon Sep 17 00:00:00 2001 From: Morne Alberts Date: Fri, 22 May 2026 10:40:09 +0200 Subject: [PATCH 2/2] Drop heavy mock-based test for the post-parse module loader Per the reviewer comment at https://github.com/oetterer/BootstrapComponents/pull/80#pullrequestreview-4341362729 the test pinned a single argument literal through deep mocks of every collaborator on `HooksHandler`, coupling to call signatures rather than behaviour. Integration verification on the running rig covers the regression more reliably. Co-Authored-By: Claude Opus 4.7 --- tests/phpunit/Unit/HooksHandlerTest.php | 47 ------------------------- 1 file changed, 47 deletions(-) diff --git a/tests/phpunit/Unit/HooksHandlerTest.php b/tests/phpunit/Unit/HooksHandlerTest.php index 3d9867e..18aa2fb 100644 --- a/tests/phpunit/Unit/HooksHandlerTest.php +++ b/tests/phpunit/Unit/HooksHandlerTest.php @@ -6,8 +6,6 @@ use MediaWiki\Extension\BootstrapComponents\ComponentLibrary; use MediaWiki\Extension\BootstrapComponents\HooksHandler; use MediaWiki\Extension\BootstrapComponents\NestingController; -use Parser; -use ParserOutput; use PHPUnit\Framework\TestCase; /** @@ -75,49 +73,4 @@ public function testOnOutputPageParserOutput() { $this->assertTrue( true ); } - public function testOnParserAfterParseLoadsActiveComponentScriptsAndStyles() { - $loadedStyles = []; - $loadedModules = []; - - $parserOutput = $this->createMock( ParserOutput::class ); - $parserOutput->method( 'addModuleStyles' ) - ->willReturnCallback( function ( $m ) use ( &$loadedStyles ) { - $loadedStyles = array_merge( $loadedStyles, (array)$m ); - } ); - $parserOutput->method( 'addModules' ) - ->willReturnCallback( function ( $m ) use ( &$loadedModules ) { - $loadedModules = array_merge( $loadedModules, (array)$m ); - } ); - - $parser = $this->createMock( Parser::class ); - $parser->method( 'getOutput' )->willReturn( $parserOutput ); - - $service = $this->createMock( BootstrapComponentsService::class ); - $service->method( 'getNameOfActiveSkin' )->willReturn( 'vector' ); - $service->method( 'getActiveComponents' )->willReturn( [ 'tooltip', 'popover' ] ); - - $library = $this->createMock( ComponentLibrary::class ); - $library->method( 'isRegistered' )->willReturn( true ); - $library->method( 'getModulesFor' ) - ->willReturnCallback( function ( $name ) { - return [ 'ext.bootstrapComponents.' . $name . '.fix' ]; - } ); - - $handler = new HooksHandler( - $service, - $library, - $this->createMock( NestingController::class ) - ); - - $text = ''; - $handler->onParserAfterParse( $parser, $text, null ); - - // Per-component fix modules must reach BOTH addModuleStyles and addModules - // (style-only modules treat addModules as a no-op; modules with a scripts - // entry get their JS init via that call). - $this->assertContains( 'ext.bootstrapComponents.tooltip.fix', $loadedStyles ); - $this->assertContains( 'ext.bootstrapComponents.popover.fix', $loadedStyles ); - $this->assertContains( 'ext.bootstrapComponents.tooltip.fix', $loadedModules ); - $this->assertContains( 'ext.bootstrapComponents.popover.fix', $loadedModules ); - } }