mirror of
https://gerrit.wikimedia.org/r/mediawiki/skins/Vector.git
synced 2024-11-17 20:52:14 +00:00
3dffee277c
Append mw-ui-icon classes to list item not list link This allows us to apply a custom padding separate from the icon. Note due to a bug in how core handles personal user items, this will result in the icons temporarily disappearing for several items until If399dfff9bbdd3b03b2ca702face3ec5164bef11 is resolved. This is okay given the user menu is currently feature flagged. Bug: T191021 Change-Id: I766aeb4d1bb36cebd0d80ad43ced940dbea96477
383 lines
9.5 KiB
PHP
383 lines
9.5 KiB
PHP
<?php
|
|
/*
|
|
* @file
|
|
* @ingroup skins
|
|
*/
|
|
|
|
use Vector\Constants;
|
|
use Vector\FeatureManagement\FeatureManager;
|
|
use Vector\Hooks;
|
|
use Vector\HTMLForm\Fields\HTMLLegacySkinVersionField;
|
|
|
|
/**
|
|
* Integration tests for Vector Hooks.
|
|
*
|
|
* @group Vector
|
|
* @coversDefaultClass \Vector\Hooks
|
|
*/
|
|
class VectorHooksTest extends MediaWikiIntegrationTestCase {
|
|
|
|
private const SKIN_PREFS_SECTION = 'rendering/skin/skin-prefs';
|
|
|
|
/**
|
|
* @param bool $excludeMainPage
|
|
* @param array $excludeNamespaces
|
|
* @param array $include
|
|
* @param array $querystring
|
|
* @return array
|
|
*/
|
|
private static function makeMaxWidthConfig(
|
|
$excludeMainPage,
|
|
$excludeNamespaces = [],
|
|
$include = [],
|
|
$querystring = []
|
|
) {
|
|
return [
|
|
'exclude' => [
|
|
'mainpage' => $excludeMainPage,
|
|
'namespaces' => $excludeNamespaces,
|
|
'querystring' => $querystring,
|
|
],
|
|
'include' => $include
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @covers ::shouldDisableMaxWidth
|
|
*/
|
|
public function providerShouldDisableMaxWidth() {
|
|
$excludeTalkFooConfig = self::makeMaxWidthConfig(
|
|
false,
|
|
[ NS_TALK ],
|
|
[ 'Talk:Foo' ],
|
|
[]
|
|
);
|
|
|
|
return [
|
|
[
|
|
'No options, nothing disables max width',
|
|
[],
|
|
Title::makeTitle( NS_MAIN, 'Foo' ),
|
|
[],
|
|
false
|
|
],
|
|
[
|
|
'Main page disables max width if exclude.mainpage set',
|
|
self::makeMaxWidthConfig( true ),
|
|
Title::newMainPage(),
|
|
[],
|
|
true
|
|
],
|
|
[
|
|
'Namespaces can be excluded',
|
|
self::makeMaxWidthConfig( false, [ NS_CATEGORY ] ),
|
|
Title::makeTitle( NS_CATEGORY, 'Category' ),
|
|
[],
|
|
true
|
|
],
|
|
[
|
|
'Namespaces are included if not excluded',
|
|
self::makeMaxWidthConfig( false, [ NS_CATEGORY ] ),
|
|
Title::makeTitle( NS_SPECIAL, 'SpecialPages' ),
|
|
[],
|
|
false
|
|
],
|
|
[
|
|
'More than one namespace can be included',
|
|
self::makeMaxWidthConfig( false, [ NS_CATEGORY, NS_SPECIAL ] ),
|
|
Title::makeTitle( NS_SPECIAL, 'Specialpages' ),
|
|
[],
|
|
true
|
|
],
|
|
[
|
|
'Can be disabled on history page',
|
|
self::makeMaxWidthConfig(
|
|
false,
|
|
[
|
|
/* no namespaces excluded */
|
|
],
|
|
[
|
|
/* no includes */
|
|
],
|
|
[ 'action' => 'history' ]
|
|
),
|
|
Title::makeTitle( NS_MAIN, 'History page' ),
|
|
[ 'action' => 'history' ],
|
|
true
|
|
],
|
|
[
|
|
'Include can override exclusions',
|
|
self::makeMaxWidthConfig(
|
|
false,
|
|
[ NS_CATEGORY, NS_SPECIAL ],
|
|
[ 'Special:Specialpages' ],
|
|
[ 'action' => 'history' ]
|
|
),
|
|
Title::makeTitle( NS_SPECIAL, 'Specialpages' ),
|
|
[ 'action' => 'history' ],
|
|
false
|
|
],
|
|
[
|
|
'Max width can be disabled on talk pages',
|
|
$excludeTalkFooConfig,
|
|
Title::makeTitle( NS_TALK, 'A talk page' ),
|
|
[],
|
|
true
|
|
],
|
|
[
|
|
'includes can be used to override any page in a disabled namespace',
|
|
$excludeTalkFooConfig,
|
|
Title::makeTitle( NS_TALK, 'Foo' ),
|
|
[],
|
|
false
|
|
],
|
|
[
|
|
'Excludes/includes are based on root title so should apply to subpages',
|
|
$excludeTalkFooConfig,
|
|
Title::makeTitle( NS_TALK, 'Foo/subpage' ),
|
|
[],
|
|
false
|
|
]
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @covers ::shouldDisableMaxWidth
|
|
* @dataProvider providerShouldDisableMaxWidth
|
|
*/
|
|
public function testShouldDisableMaxWidth(
|
|
$msg,
|
|
$options,
|
|
$title,
|
|
$requestValues,
|
|
$shouldDisableMaxWidth
|
|
) {
|
|
$this->assertSame(
|
|
$shouldDisableMaxWidth,
|
|
Hooks::shouldDisableMaxWidth( $options, $title, $requestValues ),
|
|
$msg
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @covers ::onGetPreferences
|
|
*/
|
|
public function testOnGetPreferencesShowPreferencesDisabled() {
|
|
$config = new HashConfig( [
|
|
'VectorShowSkinPreferences' => false,
|
|
] );
|
|
$this->setService( 'Vector.Config', $config );
|
|
|
|
$prefs = [];
|
|
Hooks::onGetPreferences( $this->getTestUser()->getUser(), $prefs );
|
|
$this->assertSame( [], $prefs, 'No preferences are added.' );
|
|
}
|
|
|
|
private function setFeatureLatestSkinVersionIsEnabled( $isEnabled ) {
|
|
$featureManager = new FeatureManager();
|
|
$featureManager->registerSimpleRequirement( Constants::REQUIREMENT_LATEST_SKIN_VERSION, $isEnabled );
|
|
$featureManager->registerFeature( Constants::FEATURE_LATEST_SKIN, [
|
|
Constants::REQUIREMENT_LATEST_SKIN_VERSION
|
|
] );
|
|
|
|
$this->setService( Constants::SERVICE_FEATURE_MANAGER, $featureManager );
|
|
}
|
|
|
|
/**
|
|
* @covers ::onGetPreferences
|
|
*/
|
|
public function testOnGetPreferencesShowPreferencesEnabledSkinSectionFoundLegacy() {
|
|
$isLegacy = true;
|
|
$this->setFeatureLatestSkinVersionIsEnabled( !$isLegacy );
|
|
|
|
$prefs = [
|
|
'foo' => [],
|
|
'skin' => [],
|
|
'bar' => []
|
|
];
|
|
Hooks::onGetPreferences( $this->getTestUser()->getUser(), $prefs );
|
|
$this->assertEquals(
|
|
[
|
|
'foo' => [],
|
|
'skin' => [],
|
|
'VectorSkinVersion' => [
|
|
'class' => HTMLLegacySkinVersionField::class,
|
|
'label-message' => 'prefs-vector-enable-vector-1-label',
|
|
'help-message' => 'prefs-vector-enable-vector-1-help',
|
|
'section' => self::SKIN_PREFS_SECTION,
|
|
'default' => $isLegacy,
|
|
'hide-if' => [ '!==', 'wpskin', Constants::SKIN_NAME ]
|
|
],
|
|
'VectorSidebarVisible' => [
|
|
'type' => 'api',
|
|
'default' => true
|
|
],
|
|
'bar' => [],
|
|
],
|
|
$prefs,
|
|
'Preferences are inserted directly after skin.'
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @covers ::onGetPreferences
|
|
*/
|
|
public function testOnGetPreferencesShowPreferencesEnabledSkinSectionMissingLegacy() {
|
|
$isLegacy = false;
|
|
$this->setFeatureLatestSkinVersionIsEnabled( !$isLegacy );
|
|
|
|
$prefs = [
|
|
'foo' => [],
|
|
'bar' => []
|
|
];
|
|
Hooks::onGetPreferences( $this->getTestUser()->getUser(), $prefs );
|
|
$this->assertEquals(
|
|
[
|
|
'foo' => [],
|
|
'bar' => [],
|
|
'VectorSkinVersion' => [
|
|
'class' => HTMLLegacySkinVersionField::class,
|
|
'label-message' => 'prefs-vector-enable-vector-1-label',
|
|
'help-message' => 'prefs-vector-enable-vector-1-help',
|
|
'section' => self::SKIN_PREFS_SECTION,
|
|
'default' => $isLegacy,
|
|
'hide-if' => [ '!==', 'wpskin', Constants::SKIN_NAME ]
|
|
],
|
|
'VectorSidebarVisible' => [
|
|
'type' => 'api',
|
|
'default' => true
|
|
],
|
|
],
|
|
$prefs,
|
|
'Preferences are appended.'
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @covers ::onPreferencesFormPreSave
|
|
*/
|
|
public function testOnPreferencesFormPreSaveVectorEnabledLegacyNewPreference() {
|
|
$formData = [
|
|
'skin' => 'vector',
|
|
'VectorSkinVersion' => Constants::SKIN_VERSION_LEGACY,
|
|
];
|
|
$form = $this->createMock( HTMLForm::class );
|
|
$user = $this->createMock( User::class );
|
|
$user->expects( $this->never() )
|
|
->method( 'setOption' );
|
|
$result = true;
|
|
$oldPreferences = [];
|
|
|
|
Hooks::onPreferencesFormPreSave( $formData, $form, $user, $result, $oldPreferences );
|
|
}
|
|
|
|
/**
|
|
* @covers ::onPreferencesFormPreSave
|
|
*/
|
|
public function testOnPreferencesFormPreSaveVectorDisabledNoOldPreference() {
|
|
$formData = [
|
|
'VectorSkinVersion' => Constants::SKIN_VERSION_LATEST,
|
|
];
|
|
$form = $this->createMock( HTMLForm::class );
|
|
$user = $this->createMock( User::class );
|
|
$user->expects( $this->never() )
|
|
->method( 'setOption' );
|
|
$result = true;
|
|
$oldPreferences = [];
|
|
|
|
Hooks::onPreferencesFormPreSave( $formData, $form, $user, $result, $oldPreferences );
|
|
}
|
|
|
|
/**
|
|
* @covers ::onPreferencesFormPreSave
|
|
*/
|
|
public function testOnPreferencesFormPreSaveVectorDisabledOldPreference() {
|
|
$formData = [
|
|
'VectorSkinVersion' => Constants::SKIN_VERSION_LATEST,
|
|
];
|
|
$form = $this->createMock( HTMLForm::class );
|
|
$user = $this->createMock( User::class );
|
|
$user->expects( $this->once() )
|
|
->method( 'setOption' )
|
|
->with( 'VectorSkinVersion', 'old' );
|
|
$result = true;
|
|
$oldPreferences = [
|
|
'VectorSkinVersion' => 'old',
|
|
];
|
|
|
|
Hooks::onPreferencesFormPreSave( $formData, $form, $user, $result, $oldPreferences );
|
|
}
|
|
|
|
/**
|
|
* @covers ::onLocalUserCreated
|
|
*/
|
|
public function testOnLocalUserCreatedLegacy() {
|
|
$config = new HashConfig( [
|
|
'VectorDefaultSkinVersionForNewAccounts' => Constants::SKIN_VERSION_LEGACY,
|
|
] );
|
|
$this->setService( 'Vector.Config', $config );
|
|
|
|
$user = $this->createMock( User::class );
|
|
$user->expects( $this->once() )
|
|
->method( 'setOption' )
|
|
->with( 'VectorSkinVersion', Constants::SKIN_VERSION_LEGACY );
|
|
$isAutoCreated = false;
|
|
Hooks::onLocalUserCreated( $user, $isAutoCreated );
|
|
}
|
|
|
|
/**
|
|
* @covers ::onLocalUserCreated
|
|
*/
|
|
public function testOnLocalUserCreatedLatest() {
|
|
$config = new HashConfig( [
|
|
'VectorDefaultSkinVersionForNewAccounts' => Constants::SKIN_VERSION_LATEST,
|
|
] );
|
|
$this->setService( 'Vector.Config', $config );
|
|
|
|
$user = $this->createMock( User::class );
|
|
$user->expects( $this->once() )
|
|
->method( 'setOption' )
|
|
->with( 'VectorSkinVersion', Constants::SKIN_VERSION_LATEST );
|
|
$isAutoCreated = false;
|
|
Hooks::onLocalUserCreated( $user, $isAutoCreated );
|
|
}
|
|
|
|
/**
|
|
* @covers ::onSkinTemplateNavigation
|
|
*/
|
|
public function testOnSkinTemplateNavigation() {
|
|
$this->setMwGlobals( [
|
|
'wgVectorUseIconWatch' => true
|
|
] );
|
|
$skin = new SkinVector( [ 'name' => 'vector' ] );
|
|
$skin->getContext()->setTitle( Title::newFromText( 'Foo' ) );
|
|
$contentNavWatch = [
|
|
'actions' => [
|
|
'watch' => [ 'class' => 'watch' ],
|
|
]
|
|
];
|
|
$contentNavUnWatch = [
|
|
'actions' => [
|
|
'move' => [ 'class' => 'move' ],
|
|
'unwatch' => [],
|
|
],
|
|
];
|
|
|
|
Hooks::onSkinTemplateNavigation( $skin, $contentNavUnWatch );
|
|
Hooks::onSkinTemplateNavigation( $skin, $contentNavWatch );
|
|
|
|
$this->assertTrue(
|
|
in_array( 'icon', $contentNavWatch['views']['watch']['class'] ) !== false,
|
|
'Watch list items require an "icon" class'
|
|
);
|
|
$this->assertTrue(
|
|
in_array( 'icon', $contentNavUnWatch['views']['unwatch']['class'] ) !== false,
|
|
'Unwatch list items require an "icon" class'
|
|
);
|
|
$this->assertFalse(
|
|
strpos( $contentNavUnWatch['actions']['move']['class'], 'icon' ) !== false,
|
|
'List item other than watch or unwatch should not have an "icon" class'
|
|
);
|
|
}
|
|
}
|