From 179d402344f80f2bdf8ec1e31128819c71991bc5 Mon Sep 17 00:00:00 2001 From: WMDE-Fisch Date: Fri, 19 Apr 2024 09:42:41 +0200 Subject: [PATCH] Add ReferencePreviews config checks to Cite extension PHP classes and test are somewhat copies from the Popups codebase. Some refactoring was applied. More could be done. Not to sure if this should happen more in follow ups though. Could also reduce the complexity of checks on the JS side. Most of these things can only change on page load. The only dynamic part left is the anon user setting managed by the Popups extension. Note, that I needed to add a new PHP config for here although the other still exists and is needed in the Popups extension. This will change, when the user settings code also moves. I guess it's okay for now though. Both settings default to true and are not overridden in the config repos. Also needed to add the Gadget extension as phan dependency. Bug: T362771 Depends-On: Ia028c41f8aaa1c522dfc7c372e1ce51e40933a5e Change-Id: Ie6e8bc706235724494036c7f0d873f5c996c46e6 --- .phan/config.php | 14 ++ extension.json | 16 +- modules/ext.cite.referencePreviews/index.js | 5 +- .../isReferencePreviewsEnabled.js | 14 +- .../setUserConfigFlags.js | 29 --- src/Hooks/CiteHooks.php | 21 +- .../ReferencePreviewsContext.php | 52 +++++ .../ReferencePreviewsGadgetsIntegration.php | 70 +++++++ .../ReferencePreviewsContextTest.php | 92 +++++++++ ...eferencePreviewsGadgetsIntegrationTest.php | 183 ++++++++++++++++++ .../isReferencePreviewsEnabled.test.js | 121 +----------- .../setUserConfigFlags.test.js | 51 ----- 12 files changed, 449 insertions(+), 219 deletions(-) delete mode 100644 modules/ext.cite.referencePreviews/setUserConfigFlags.js create mode 100644 src/ReferencePreviews/ReferencePreviewsContext.php create mode 100644 src/ReferencePreviews/ReferencePreviewsGadgetsIntegration.php create mode 100644 tests/phpunit/integration/ReferencePreviews/ReferencePreviewsContextTest.php create mode 100644 tests/phpunit/integration/ReferencePreviews/ReferencePreviewsGadgetsIntegrationTest.php delete mode 100644 tests/qunit/ext.cite.referencePreviews/setUserConfigFlags.test.js diff --git a/.phan/config.php b/.phan/config.php index 66e9f1c67..5e0fef8b3 100644 --- a/.phan/config.php +++ b/.phan/config.php @@ -2,6 +2,20 @@ $cfg = require __DIR__ . '/../vendor/mediawiki/mediawiki-phan-config/src/config.php'; +$cfg['directory_list'] = array_merge( + $cfg['directory_list'], + [ + '../../extensions/Gadgets', + ] +); + +$cfg['exclude_analysis_directory_list'] = array_merge( + $cfg['exclude_analysis_directory_list'], + [ + '../../extensions/Gadgets', + ] +); + /** * Quick implementation of a recursive directory list. * @param string $dir The directory to list diff --git a/extension.json b/extension.json index cafd31e50..26c8d2c0c 100644 --- a/extension.json +++ b/extension.json @@ -31,6 +31,7 @@ "ParserCloned": "parser", "ParserFirstCallInit": "parser", "EditPage::showEditForm:initial": "main", + "MakeGlobalVariablesScript": "main", "ResourceLoaderGetConfigVars": "main", "ResourceLoaderRegisterModules": "main" }, @@ -251,8 +252,7 @@ "tests/qunit/ve-cite/ve.ui.MWWikitextStringTransferHandler.test.js", "tests/qunit/ext.cite.referencePreviews/createReferenceGateway.test.js", "tests/qunit/ext.cite.referencePreviews/isReferencePreviewsEnabled.test.js", - "tests/qunit/ext.cite.referencePreviews/renderer.test.js", - "tests/qunit/ext.cite.referencePreviews/setUserConfigFlags.test.js" + "tests/qunit/ext.cite.referencePreviews/renderer.test.js" ], "dependencies": [ "ext.cite.visualEditor", @@ -299,6 +299,18 @@ "description": "If long lists with more than 10 references should behave responsive by default and be displayed in two or more columns. This can also be toggled individually with to enable and to disable it.", "public": true, "value": true + }, + "CiteReferencePreviews": { + "description": "Feature flag to enable or disable the popups provided by the Popups extension for tags.", + "value": true + }, + "CiteReferencePreviewsConflictingNavPopupsGadgetName": { + "description": "@var string: Name of a gadget that would cause duplicate reference preview popups. Should usually be identical to wgPopupsConflictingNavPopupsGadgetName in the Popups extension.", + "value": "Navigation_popups" + }, + "CiteReferencePreviewsConflictingRefTooltipsGadgetName": { + "description": "@var string: Name of a gadget that would cause duplicate reference preview popups. Known conflicting gadgets include \"ReferenceTooltips\", \"CiteTooltip\" alias \"RefTooltip\", \"ReferencePopups\", and \"tooltipRef\" (see T274353).", + "value": "ReferenceTooltips" } }, "AutoloadNamespaces": { diff --git a/modules/ext.cite.referencePreviews/index.js b/modules/ext.cite.referencePreviews/index.js index 6c55331ff..7b2fbc109 100644 --- a/modules/ext.cite.referencePreviews/index.js +++ b/modules/ext.cite.referencePreviews/index.js @@ -3,9 +3,7 @@ const { initReferencePreviewsInstrumentation, LOGGING_SCHEMA } = require( './ref const createReferenceGateway = require( './createReferenceGateway.js' ); const renderFn = require( './createReferencePreview.js' ); const { TYPE_REFERENCE, FETCH_DELAY_REFERENCE_TYPE } = require( './constants.js' ); -const setUserConfigFlags = require( './setUserConfigFlags.js' ); -setUserConfigFlags( mw.config ); const referencePreviewsState = isReferencePreviewsEnabled( mw.user, mw.popups.isEnabled, @@ -40,7 +38,6 @@ if ( typeof QUnit !== 'undefined' ) { module.exports = { private: { createReferenceGateway: require( './createReferenceGateway.js' ), createReferencePreview: require( './createReferencePreview.js' ), - isReferencePreviewsEnabled: require( './isReferencePreviewsEnabled.js' ), - setUserConfigFlags: require( './setUserConfigFlags.js' ) + isReferencePreviewsEnabled: require( './isReferencePreviewsEnabled.js' ) } }; } diff --git a/modules/ext.cite.referencePreviews/isReferencePreviewsEnabled.js b/modules/ext.cite.referencePreviews/isReferencePreviewsEnabled.js index fdfedb96a..41a1ea1a5 100644 --- a/modules/ext.cite.referencePreviews/isReferencePreviewsEnabled.js +++ b/modules/ext.cite.referencePreviews/isReferencePreviewsEnabled.js @@ -15,27 +15,15 @@ const { TYPE_REFERENCE } = require( './constants.js' ); * @return {boolean|null} Null when there is no way the popup type can be enabled at run-time. */ function isReferencePreviewsEnabled( user, isPreviewTypeEnabled, config ) { - // TODO: This and the final `mw.user.options` check are currently redundant. Only this here - // should be removed when the wgCiteReferencePreviews feature flag is not needed any more. if ( !config.get( 'wgCiteReferencePreviews' ) ) { return null; } - // T265872: Unavailable when in conflict with (one of the) reference tooltips gadgets. - if ( config.get( 'wgCiteReferencePreviewsConflictsWithRefTooltipsGadget' ) || - config.get( 'wgPopupsConflictsWithNavPopupGadget' ) || - // T243822: Temporarily disabled in the mobile skin - config.get( 'skin' ) === 'minerva' - ) { - return null; - } - if ( user.isAnon() ) { return isPreviewTypeEnabled( TYPE_REFERENCE ); } - // Registered users never can enable popup types at run-time. - return user.options.get( 'popups-reference-previews' ) === '1' ? true : null; + return true; } module.exports = isReferencePreviewsEnabled; diff --git a/modules/ext.cite.referencePreviews/setUserConfigFlags.js b/modules/ext.cite.referencePreviews/setUserConfigFlags.js deleted file mode 100644 index 7001f19ce..000000000 --- a/modules/ext.cite.referencePreviews/setUserConfigFlags.js +++ /dev/null @@ -1,29 +0,0 @@ -/** - * @module setUserConfigFlags - */ - -/** - * Same as in includes/PopupsContext.php - */ -const REF_TOOLTIPS_ENABLED = 2, - REFERENCE_PREVIEWS_ENABLED = 4; - -/** - * Decodes the bitmask that represents preferences to the related config options. - * - * @param {mw.Map} config - */ -module.exports = function setUserConfigFlags( config ) { - const popupsFlags = parseInt( config.get( 'wgPopupsFlags' ), 10 ); - - /* eslint-disable no-bitwise */ - config.set( - 'wgCiteReferencePreviewsConflictsWithRefTooltipsGadget', - !!( popupsFlags & REF_TOOLTIPS_ENABLED ) - ); - config.set( - 'wgCiteReferencePreviews', - !!( popupsFlags & REFERENCE_PREVIEWS_ENABLED ) - ); - /* eslint-enable no-bitwise */ -}; diff --git a/src/Hooks/CiteHooks.php b/src/Hooks/CiteHooks.php index 676d675cd..ac2c9fe99 100644 --- a/src/Hooks/CiteHooks.php +++ b/src/Hooks/CiteHooks.php @@ -7,11 +7,13 @@ namespace Cite\Hooks; use ApiQuerySiteinfo; +use Cite\ReferencePreviews\ReferencePreviewsContext; use ExtensionRegistry; use MediaWiki\Api\Hook\APIQuerySiteInfoGeneralInfoHook; use MediaWiki\Config\Config; use MediaWiki\EditPage\EditPage; use MediaWiki\Hook\EditPage__showEditForm_initialHook; +use MediaWiki\Output\Hook\MakeGlobalVariablesScriptHook; use MediaWiki\Output\OutputPage; use MediaWiki\ResourceLoader\Hook\ResourceLoaderGetConfigVarsHook; use MediaWiki\ResourceLoader\Hook\ResourceLoaderRegisterModulesHook; @@ -26,6 +28,7 @@ use MediaWiki\User\Options\UserOptionsLookup; */ class CiteHooks implements ContentHandlerDefaultModelForHook, + MakeGlobalVariablesScriptHook, ResourceLoaderGetConfigVarsHook, ResourceLoaderRegisterModulesHook, APIQuerySiteInfoGeneralInfoHook, @@ -58,6 +61,21 @@ class CiteHooks implements } } + /** + * @param array &$vars + * @param OutputPage $out + */ + public function onMakeGlobalVariablesScript( &$vars, $out ): void { + $referencePreviewsContext = new ReferencePreviewsContext( + $out->getConfig(), + $this->userOptionsLookup + ); + $vars['wgCiteReferencePreviews'] = $referencePreviewsContext->isReferencePreviewsEnabled( + $out->getUser(), + $out->getSkin() + ); + } + /** * Adds extra variables to the global config * @param array &$vars `[ variable name => value ]` @@ -92,8 +110,7 @@ class CiteHooks implements 'createReferenceGateway.js', 'createReferencePreview.js', 'isReferencePreviewsEnabled.js', - 'referencePreviewsInstrumentation.js', - 'setUserConfigFlags.js' + 'referencePreviewsInstrumentation.js' ] ] ] ); diff --git a/src/ReferencePreviews/ReferencePreviewsContext.php b/src/ReferencePreviews/ReferencePreviewsContext.php new file mode 100644 index 000000000..8fe26a1bf --- /dev/null +++ b/src/ReferencePreviews/ReferencePreviewsContext.php @@ -0,0 +1,52 @@ +gadgetsIntegration = new ReferencePreviewsGadgetsIntegration( $config ); + $this->userOptionsLookup = $userOptionsLookup; + + $this->config = $config; + } + + /** + * User preference key to enable/disable Reference Previews. Named + * "mwe-popups-referencePreviews-enabled" in localStorage for anonymous users. + */ + public const REFERENCE_PREVIEWS_PREFERENCE_NAME = 'popups-reference-previews'; + + public function isReferencePreviewsEnabled( User $user, Skin $skin ): bool { + if ( + // T243822: Temporarily disabled in the mobile skin + $skin->getSkinName() === 'minerva' || + !$this->config->get( 'CiteReferencePreviews' ) || + $this->gadgetsIntegration->isRefToolTipsGadgetEnabled( $user ) || + $this->gadgetsIntegration->isNavPopupsGadgetEnabled( $user ) + ) { + return false; + } + + return !$user->isNamed() || $this->userOptionsLookup->getBoolOption( + $user, self::REFERENCE_PREVIEWS_PREFERENCE_NAME + ); + } +} diff --git a/src/ReferencePreviews/ReferencePreviewsGadgetsIntegration.php b/src/ReferencePreviews/ReferencePreviewsGadgetsIntegration.php new file mode 100644 index 000000000..48b7cf379 --- /dev/null +++ b/src/ReferencePreviews/ReferencePreviewsGadgetsIntegration.php @@ -0,0 +1,70 @@ +navPopupsGadgetName = $this->sanitizeGadgetName( + $config->get( self::CONFIG_NAVIGATION_POPUPS_NAME ) ); + $this->refTooltipsGadgetName = $this->sanitizeGadgetName( + $config->get( self::CONFIG_REFERENCE_TOOLTIPS_NAME ) ); + + try { + $this->gadgetRepo = MediaWikiServices::getInstance()->getService( 'GadgetsRepo' ); + } catch ( NoSuchServiceException $e ) { + $this->gadgetRepo = null; + } + } + + private function sanitizeGadgetName( string $gadgetName ): string { + return str_replace( ' ', '_', trim( $gadgetName ) ); + } + + private function isGadgetEnabled( UserIdentity $user, string $gadgetName ): bool { + if ( $this->gadgetRepo ) { + if ( in_array( $gadgetName, $this->gadgetRepo->getGadgetIds() ) ) { + try { + return $this->gadgetRepo->getGadget( $gadgetName ) + ->isEnabled( $user ); + } catch ( InvalidArgumentException $e ) { + return false; + } + } + } + return false; + } + + public function isNavPopupsGadgetEnabled( User $user ): bool { + return $this->isGadgetEnabled( $user, $this->navPopupsGadgetName ); + } + + public function isRefTooltipsGadgetEnabled( User $user ): bool { + return $this->isGadgetEnabled( $user, $this->refTooltipsGadgetName ); + } + +} diff --git a/tests/phpunit/integration/ReferencePreviews/ReferencePreviewsContextTest.php b/tests/phpunit/integration/ReferencePreviews/ReferencePreviewsContextTest.php new file mode 100644 index 000000000..f2ae9d621 --- /dev/null +++ b/tests/phpunit/integration/ReferencePreviews/ReferencePreviewsContextTest.php @@ -0,0 +1,92 @@ + $setting, + 'CiteReferencePreviewsConflictingNavPopupsGadgetName' => '', + 'CiteReferencePreviewsConflictingRefTooltipsGadgetName' => '', + ] ); + $userOptLookup = $this->createNoOpMock( UserOptionsLookup::class ); + + $context = new ReferencePreviewsContext( $config, $userOptLookup ); + + $user = $this->createMock( User::class ); + $user->method( 'isNamed' )->willReturn( false ); + + $skin = $this->createMock( Skin::class ); + $skin->method( 'getSkinName' )->willReturn( $skinName ); + + $this->assertSame( $expected, + $context->isReferencePreviewsEnabled( $user, $skin ), + ( $expected ? 'A' : 'No' ) . ' module is sent to the user.' ); + } + + public static function provideIsReferencePreviewsEnabled_requirements() { + yield [ true, 'minerva', false ]; + yield [ false, 'minerva', false ]; + yield [ true, 'vector', true ]; + yield [ false, 'vector', false ]; + } + + /** + * Tests #shouldSendModuleToUser when the user is logged in and the reference previews feature + * is disabled. + * + * @covers ::isReferencePreviewsEnabled + * @dataProvider provideIsReferencePreviewsEnabled_userOptions + */ + public function testIsReferencePreviewsEnabled_userOptions( bool $isNamed, bool $option, bool $expected ) { + $user = $this->createMock( User::class ); + $user->method( 'isNamed' )->willReturn( $isNamed ); + + $userOptLookup = $this->createMock( UserOptionsLookup::class ); + $userOptLookup->method( 'getBoolOption' ) + ->with( $user, ReferencePreviewsContext::REFERENCE_PREVIEWS_PREFERENCE_NAME ) + ->willReturn( $option ); + + $config = new HashConfig( [ + 'CiteReferencePreviews' => true, + 'CiteReferencePreviewsConflictingNavPopupsGadgetName' => '', + 'CiteReferencePreviewsConflictingRefTooltipsGadgetName' => '', + ] ); + + $context = new ReferencePreviewsContext( $config, $userOptLookup ); + + $skin = $this->createMock( Skin::class ); + + $this->assertSame( $expected, + $context->isReferencePreviewsEnabled( $user, $skin ), + ( $expected ? 'A' : 'No' ) . ' module is sent to the user.' ); + } + + public static function provideIsReferencePreviewsEnabled_userOptions() { + yield [ true, true, true ]; + yield [ true, false, false ]; + yield [ false, false, true ]; + yield [ false, true, true ]; + } + +} diff --git a/tests/phpunit/integration/ReferencePreviews/ReferencePreviewsGadgetsIntegrationTest.php b/tests/phpunit/integration/ReferencePreviews/ReferencePreviewsGadgetsIntegrationTest.php new file mode 100644 index 000000000..dad6a2b9a --- /dev/null +++ b/tests/phpunit/integration/ReferencePreviews/ReferencePreviewsGadgetsIntegrationTest.php @@ -0,0 +1,183 @@ +createMock( Config::class ); + $mock->expects( $this->atLeastOnce() ) + ->method( 'get' ) + ->willReturnMap( [ + [ ReferencePreviewsGadgetsIntegration::CONFIG_NAVIGATION_POPUPS_NAME, self::NAV_POPUPS_GADGET_NAME ], + [ ReferencePreviewsGadgetsIntegration::CONFIG_REFERENCE_TOOLTIPS_NAME, self::NAV_POPUPS_GADGET_NAME ], + ] ); + return $mock; + } + + /** + * @covers ::isNavPopupsGadgetEnabled + * @covers ::__construct + * @covers ::sanitizeGadgetName + */ + public function testConflictsWithNavPopupsGadgetIfGadgetsExtensionIsNotLoaded() { + $user = $this->createMock( User::class ); + $integration = new ReferencePreviewsGadgetsIntegration( $this->getConfigMock() ); + $this->assertFalse( + $integration->isNavPopupsGadgetEnabled( $user ), + 'No conflict is identified.' ); + } + + /** + * @covers ::isNavPopupsGadgetEnabled + */ + public function testConflictsWithNavPopupsGadgetIfGadgetNotExists() { + $user = $this->createMock( User::class ); + + $gadgetRepoMock = $this->createMock( GadgetRepo::class ); + $gadgetRepoMock->expects( $this->once() ) + ->method( 'getGadgetIds' ) + ->willReturn( [] ); + + $this->executeConflictsWithNavPopupsGadgetSafeCheck( $user, $this->getConfigMock(), + $gadgetRepoMock, self::GADGET_DISABLED ); + } + + /** + * @covers ::isNavPopupsGadgetEnabled + */ + public function testConflictsWithNavPopupsGadgetIfGadgetExists() { + $user = $this->createMock( User::class ); + + $gadgetMock = $this->createMock( Gadget::class ); + $gadgetMock->expects( $this->once() ) + ->method( 'isEnabled' ) + ->with( $user ) + ->willReturn( self::GADGET_ENABLED ); + + $gadgetRepoMock = $this->createMock( GadgetRepo::class ); + $gadgetRepoMock->expects( $this->once() ) + ->method( 'getGadgetIds' ) + ->willReturn( [ self::NAV_POPUPS_GADGET_NAME ] ); + $gadgetRepoMock->expects( $this->once() ) + ->method( 'getGadget' ) + ->with( self::NAV_POPUPS_GADGET_NAME ) + ->willReturn( $gadgetMock ); + + $this->executeConflictsWithNavPopupsGadgetSafeCheck( $user, $this->getConfigMock(), + $gadgetRepoMock, self::GADGET_ENABLED ); + } + + /** + * Test the edge case when GadgetsRepo::getGadget throws an exception + * @covers ::isNavPopupsGadgetEnabled + */ + public function testConflictsWithNavPopupsGadgetWhenGadgetNotExists() { + $user = $this->createMock( User::class ); + + $gadgetRepoMock = $this->createMock( GadgetRepo::class ); + $gadgetRepoMock->expects( $this->once() ) + ->method( 'getGadgetIds' ) + ->willReturn( [ self::NAV_POPUPS_GADGET_NAME ] ); + $gadgetRepoMock->expects( $this->once() ) + ->method( 'getGadget' ) + ->with( self::NAV_POPUPS_GADGET_NAME ) + ->willThrowException( new InvalidArgumentException() ); + + $this->executeConflictsWithNavPopupsGadgetSafeCheck( $user, $this->getConfigMock(), + $gadgetRepoMock, self::GADGET_DISABLED ); + } + + /** + * @covers ::sanitizeGadgetName + * @dataProvider provideGadgetNamesWithSanitizedVersion + */ + public function testConflictsWithNavPopupsGadgetNameSanitization( $name, $sanitized ) { + $user = $this->createMock( User::class ); + + $configMock = $this->createMock( Config::class ); + $configMock->expects( $this->atLeastOnce() ) + ->method( 'get' ) + ->willReturnMap( [ + [ ReferencePreviewsGadgetsIntegration::CONFIG_NAVIGATION_POPUPS_NAME, $name ], + [ ReferencePreviewsGadgetsIntegration::CONFIG_REFERENCE_TOOLTIPS_NAME, $name ] + ] ); + + $gadgetMock = $this->createMock( Gadget::class ); + $gadgetMock->expects( $this->once() ) + ->method( 'isEnabled' ) + ->willReturn( self::GADGET_ENABLED ); + + $gadgetRepoMock = $this->createMock( GadgetRepo::class ); + $gadgetRepoMock->expects( $this->once() ) + ->method( 'getGadgetIds' ) + ->willReturn( [ $sanitized ] ); + $gadgetRepoMock->expects( $this->once() ) + ->method( 'getGadget' ) + ->with( $sanitized ) + ->willReturn( $gadgetMock ); + + $this->executeConflictsWithNavPopupsGadgetSafeCheck( $user, $configMock, $gadgetRepoMock, + self::GADGET_ENABLED ); + } + + public static function provideGadgetNamesWithSanitizedVersion() { + return [ + [ ' Popups ', 'Popups' ], + [ 'Navigation_popups-API', 'Navigation_popups-API' ], + [ 'Navigation popups ', 'Navigation_popups' ] + ]; + } + + /** + * Execute test and restore GadgetRepo + * + * @param User $user + * @param Config $config + * @param GadgetRepo $repoMock + * @param bool $expected + */ + private function executeConflictsWithNavPopupsGadgetSafeCheck( + User $user, + Config $config, + GadgetRepo $repoMock, + $expected + ) { + $this->setService( 'GadgetsRepo', $repoMock ); + + $integration = new ReferencePreviewsGadgetsIntegration( $config ); + $this->assertSame( $expected, + $integration->isNavPopupsGadgetEnabled( $user ), + ( $expected ? 'A' : 'No' ) . ' conflict is identified.' ); + } +} diff --git a/tests/qunit/ext.cite.referencePreviews/isReferencePreviewsEnabled.test.js b/tests/qunit/ext.cite.referencePreviews/isReferencePreviewsEnabled.test.js index c4a0e6398..0d20296f6 100644 --- a/tests/qunit/ext.cite.referencePreviews/isReferencePreviewsEnabled.test.js +++ b/tests/qunit/ext.cite.referencePreviews/isReferencePreviewsEnabled.test.js @@ -24,109 +24,28 @@ const options = { get: () => '1' }; QUnit.module : QUnit.module.skip )( 'ext.cite.referencePreviews#isReferencePreviewsEnabled' ); -QUnit.test( 'all relevant combinations of flags', ( assert ) => { +QUnit.test( 'relevant combinations of anonymous flags', ( assert ) => { [ { testCase: 'enabled for an anonymous user', wgCiteReferencePreviews: true, - wgCiteReferencePreviewsConflictsWithRefTooltipsGadget: false, - isMobile: false, isAnon: true, enabledByAnon: true, - enabledByRegistered: false, expected: true }, { testCase: 'turned off via the feature flag (anonymous user)', wgCiteReferencePreviews: false, - wgCiteReferencePreviewsConflictsWithRefTooltipsGadget: false, - isMobile: false, isAnon: true, enabledByAnon: true, - enabledByRegistered: true, - expected: null - }, - { - testCase: 'not available because of a conflicting gadget (anonymous user)', - wgCiteReferencePreviews: true, - wgCiteReferencePreviewsConflictsWithRefTooltipsGadget: true, - isMobile: false, - isAnon: true, - enabledByAnon: true, - enabledByRegistered: true, - expected: null - }, - { - testCase: 'not available in the mobile skin (anonymous user)', - wgCiteReferencePreviews: true, - wgCiteReferencePreviewsConflictsWithRefTooltipsGadget: false, - isMobile: true, - isAnon: true, - enabledByAnon: true, - enabledByRegistered: true, expected: null }, { testCase: 'manually disabled by the anonymous user', wgCiteReferencePreviews: true, - wgCiteReferencePreviewsConflictsWithRefTooltipsGadget: false, - isMobile: false, isAnon: true, enabledByAnon: false, - enabledByRegistered: true, expected: false - }, - { - testCase: 'enabled for a registered user', - wgCiteReferencePreviews: true, - wgCiteReferencePreviewsConflictsWithRefTooltipsGadget: false, - isMobile: false, - isAnon: false, - enabledByAnon: false, - enabledByRegistered: true, - expected: true - }, - { - testCase: 'turned off via the feature flag (registered user)', - wgCiteReferencePreviews: false, - wgCiteReferencePreviewsConflictsWithRefTooltipsGadget: false, - isMobile: false, - isAnon: false, - enabledByAnon: true, - enabledByRegistered: true, - expected: null - }, - { - testCase: 'not available because of a conflicting gadget (registered user)', - wgCiteReferencePreviews: true, - wgCiteReferencePreviewsConflictsWithRefTooltipsGadget: true, - isMobile: false, - isAnon: false, - enabledByAnon: true, - enabledByRegistered: true, - expected: null - }, - { - testCase: 'not available in the mobile skin (registered user)', - wgCiteReferencePreviews: true, - wgCiteReferencePreviewsConflictsWithRefTooltipsGadget: false, - isMobile: true, - isAnon: false, - enabledByAnon: true, - enabledByRegistered: true, - expected: null - }, - { - // TODO: This combination will make much more sense when the server-side - // wgCiteReferencePreviews flag doesn't include the user's setting any more - testCase: 'manually disabled by the registered user', - wgCiteReferencePreviews: true, - wgCiteReferencePreviewsConflictsWithRefTooltipsGadget: false, - isMobile: false, - isAnon: false, - enabledByAnon: true, - enabledByRegistered: false, - expected: null } ].forEach( ( data ) => { const user = { @@ -142,9 +61,8 @@ QUnit.test( 'all relevant combinations of flags', ( assert ) => { } return data.enabledByAnon; }, - config = { - get: ( key ) => key === 'skin' && data.isMobile ? 'minerva' : data[ key ] - }; + config = new Map(); + config.set( 'wgCiteReferencePreviews', data.wgCiteReferencePreviews ); if ( data.isAnon ) { user.options.get = () => assert.true( false, 'not expected to be called 2' ); @@ -166,7 +84,6 @@ QUnit.test( 'it should display reference previews when conditions are fulfilled' config = new Map(); config.set( 'wgCiteReferencePreviews', true ); - config.set( 'wgCiteReferencePreviewsConflictsWithRefTooltipsGadget', false ); assert.true( require( 'ext.cite.referencePreviews' ).private.isReferencePreviewsEnabled( user, userSettings, config ), @@ -174,44 +91,12 @@ QUnit.test( 'it should display reference previews when conditions are fulfilled' ); } ); -QUnit.test( 'it should handle the conflict with the Reference Tooltips Gadget', ( assert ) => { - const user = createStubUser( false ), - userSettings = createStubUserSettings( false ), - config = new Map(); - - config.set( 'wgCiteReferencePreviews', true ); - config.set( 'wgCiteReferencePreviewsConflictsWithRefTooltipsGadget', true ); - - assert.strictEqual( - require( 'ext.cite.referencePreviews' ).private.isReferencePreviewsEnabled( user, userSettings, config ), - null, - 'Reference Previews is disabled.' - ); -} ); - QUnit.test( 'it should not be enabled when the global is disabling it', ( assert ) => { const user = createStubUser( false ), userSettings = createStubUserSettings( false ), config = new Map(); config.set( 'wgCiteReferencePreviews', false ); - config.set( 'wgCiteReferencePreviewsConflictsWithRefTooltipsGadget', false ); - - assert.strictEqual( - require( 'ext.cite.referencePreviews' ).private.isReferencePreviewsEnabled( user, userSettings, config ), - null, - 'Reference Previews is disabled.' - ); -} ); - -QUnit.test( 'it should not be enabled when minerva skin used', ( assert ) => { - const user = createStubUser( false ), - userSettings = createStubUserSettings( false ), - config = new Map(); - - config.set( 'wgCiteReferencePreviews', true ); - config.set( 'wgCiteReferencePreviewsConflictsWithRefTooltipsGadget', false ); - config.set( 'skin', 'minerva' ); assert.strictEqual( require( 'ext.cite.referencePreviews' ).private.isReferencePreviewsEnabled( user, userSettings, config ), diff --git a/tests/qunit/ext.cite.referencePreviews/setUserConfigFlags.test.js b/tests/qunit/ext.cite.referencePreviews/setUserConfigFlags.test.js deleted file mode 100644 index 6a0324602..000000000 --- a/tests/qunit/ext.cite.referencePreviews/setUserConfigFlags.test.js +++ /dev/null @@ -1,51 +0,0 @@ -( mw.loader.getModuleNames().indexOf( 'ext.popups.main' ) !== -1 ? - QUnit.module : - QUnit.module.skip )( 'ext.cite.referencePreviews#setUserConfigFlags' ); - -QUnit.test( 'reference preview config settings are successfully set from bitmask', ( assert ) => { - const config = new Map(); - - config.set( 'wgPopupsFlags', '7' ); - require( 'ext.cite.referencePreviews' ).private.setUserConfigFlags( config ); - - assert.deepEqual( - [ - config.get( 'wgCiteReferencePreviewsConflictsWithRefTooltipsGadget' ), - config.get( 'wgCiteReferencePreviews' ) - ], - [ true, true ] - ); - - config.set( 'wgPopupsFlags', '2' ); - require( 'ext.cite.referencePreviews' ).private.setUserConfigFlags( config ); - - assert.deepEqual( - [ - config.get( 'wgCiteReferencePreviewsConflictsWithRefTooltipsGadget' ), - config.get( 'wgCiteReferencePreviews' ) - ], - [ true, false ] - ); - - config.set( 'wgPopupsFlags', '5' ); - require( 'ext.cite.referencePreviews' ).private.setUserConfigFlags( config ); - - assert.deepEqual( - [ - config.get( 'wgCiteReferencePreviewsConflictsWithRefTooltipsGadget' ), - config.get( 'wgCiteReferencePreviews' ) - ], - [ false, true ] - ); - - config.set( 'wgPopupsFlags', '0' ); - require( 'ext.cite.referencePreviews' ).private.setUserConfigFlags( config ); - - assert.deepEqual( - [ - config.get( 'wgCiteReferencePreviewsConflictsWithRefTooltipsGadget' ), - config.get( 'wgCiteReferencePreviews' ) - ], - [ false, false ] - ); -} );