Refactor user links functions in Hooks.php to increase test coverage

Change-Id: I8fbf5cdf111dbb1ec06e5e74056ffdef77f77f22
This commit is contained in:
bwang 2022-03-04 14:24:10 -06:00 committed by Jdlrobson
parent 749217f782
commit 2511e35837
2 changed files with 131 additions and 67 deletions

View file

@ -260,6 +260,43 @@ class Hooks {
}
}
/**
* Updates personal navigation menu (user links) overflow items for modern Vector
* including 'notification', 'user-interface-preferences', 'user-page', 'vector-user-menu-overflow'
*
* @param array &$content_navigation
*/
private static function updateUserLinksOverflowItems( &$content_navigation ) {
// Upgrade preferences, notifications, and watchlist to icon buttons
// for extensions that have opted in.
if ( isset( $content_navigation['notifications'] ) ) {
self::updateMenuItems( $content_navigation, 'notifications' );
}
if ( isset( $content_navigation['user-interface-preferences']['uls'] ) ) {
$content_navigation['user-interface-preferences']['uls'] += [
'collapsible' => true,
];
self::updateMenuItems( $content_navigation, 'user-interface-preferences' );
}
if ( isset( $content_navigation['user-page']['userpage'] ) ) {
$content_navigation['user-page']['userpage'] = array_merge( $content_navigation['user-page']['userpage'], [
'button' => true,
'collapsible' => true,
'icon' => null,
] );
self::updateMenuItems( $content_navigation, 'user-page' );
}
if ( isset( $content_navigation['vector-user-menu-overflow']['watchlist'] ) ) {
$content_navigation['vector-user-menu-overflow']['watchlist'] += [
'button' => true,
'collapsible' => true,
'text-hidden' => true,
'id' => 'pt-watchlist-2',
];
self::updateMenuItems( $content_navigation, 'vector-user-menu-overflow' );
}
}
/**
* Updates personal navigation menu (user links) for modern Vector wherein user page, create account and login links
* are removed from the dropdown to be handled separately. In legacy Vector, the custom "user-page" bucket is
@ -267,30 +304,24 @@ class Hooks {
*
* @param SkinTemplate $sk
* @param array &$content_navigation
* @suppress PhanTypeArraySuspiciousNullable False positives
*/
private static function updateUserLinksItems( $sk, &$content_navigation ) {
$hasUserMenu = $content_navigation['user-menu'] ?? false;
if ( $hasUserMenu ) {
self::updateUserLinksDropdownItems( $sk, $content_navigation );
}
// ULS and user page links are hidden at lower resolutions.
if ( $content_navigation['user-interface-preferences'] ) {
self::makeMenuItemCollapsible(
$content_navigation['user-interface-preferences']['uls']
);
}
if ( $content_navigation['user-page'] ) {
self::makeMenuItemCollapsible(
$content_navigation['user-page']['userpage']
);
$skinName = $sk->getSkinName();
if ( self::isSkinVersionLegacy( $skinName ) ) {
// Remove user page from personal toolbar since it will be inside the personal menu for logged-in
// users in legacy Vector.
unset( $content_navigation['user-page'] );
} else {
if ( isset( $content_navigation['user-menu']['watchlist'] ) ) {
// Copy watchlist data into 'vector-user-menu-overflow'
$content_navigation['vector-user-menu-overflow'] = [
'watchlist' => $content_navigation['user-menu']['watchlist']
];
// Style the user page link as mw-ui-button.
self::addListItemClass(
$content_navigation['user-page']['userpage'],
[ 'mw-ui-button', 'mw-ui-quiet' ],
true
);
self::updateUserLinksDropdownItems( $sk, $content_navigation );
}
self::updateUserLinksOverflowItems( $content_navigation );
}
}
@ -340,15 +371,19 @@ class Hooks {
}
if ( $hasButton ) {
$item['link-class'][] = 'mw-ui-button mw-ui-quiet';
self::addListItemClass( $item, [ 'mw-ui-button', 'mw-ui-quiet' ], true );
}
if ( $icon ) {
if ( $hideText ) {
$item['link-class'][] = 'mw-ui-icon mw-ui-icon-element'
. ' mw-ui-icon-wikimedia-' . $icon
$iconElementClasses = [ 'mw-ui-icon', 'mw-ui-icon-element',
// Some extensions declare icons without the wikimedia- prefix. e.g. Echo
. ' mw-ui-icon-' . $icon;
'mw-ui-icon-' . $icon,
// FIXME: Some icon names are prefixed with `wikimedia-`.
// We should seek to remove all these instances.
'mw-ui-icon-wikimedia-' . $icon
];
self::addListItemClass( $item, $iconElementClasses, true );
} else {
$item['link-html'] = self::makeIcon( $icon );
}
@ -379,45 +414,7 @@ class Hooks {
self::updateActionsMenu( $content_navigation );
}
// watchlist item is not present if not logged in.
$wlItem = $content_navigation['user-menu']['watchlist'] ?? null;
if ( $wlItem !== null ) {
$content_navigation['vector-user-menu-overflow'] = [
'watchlist' => $wlItem + [
'button' => true,
'collapsible' => true,
'text-hidden' => true,
'id' => 'pt-watchlist-2',
],
];
self::updateMenuItems( $content_navigation, 'vector-user-menu-overflow' );
}
if ( isset( $content_navigation['user-menu'] ) ) {
if ( self::isSkinVersionLegacy( $skinName ) ) {
// Remove user page from personal toolbar since it will be inside the personal menu for logged-in
// users in legacy Vector.
unset( $content_navigation['user-page'] );
} else {
// For modern Vector, rearrange some links in the personal toolbar.
self::updateUserLinksItems( $sk, $content_navigation );
}
}
if ( !self::isSkinVersionLegacy( $skinName ) ) {
// Upgrade preferences and notifications to icon buttons
// for extensions that have opted in.
if ( isset( $content_navigation['user-interface-preferences'] ) ) {
self::updateMenuItems(
$content_navigation, 'user-interface-preferences'
);
}
if ( isset( $content_navigation['notifications'] ) ) {
self::updateMenuItems(
$content_navigation, 'notifications'
);
}
}
self::updateUserLinksItems( $sk, $content_navigation );
}
}

View file

@ -20,6 +20,7 @@ use Vector\FeatureManagement\FeatureManager;
use Vector\Hooks;
use Vector\HTMLForm\Fields\HTMLLegacySkinVersionField;
use Vector\SkinVector;
use Vector\SkinVector22;
/**
* Integration tests for Vector Hooks.
@ -579,7 +580,7 @@ class VectorHooksTest extends MediaWikiIntegrationTestCase {
'updateUserLinksDropdownItems'
);
$updateUserLinksDropdownItems->setAccessible( true );
$skin = new SkinVector( [ 'name' => 'vector' ] );
$skin = new SkinVector22( [ 'name' => 'vector-2022' ] );
// Anon user
$skin->getUser()->setId( '1' );
$contentAnon = [
@ -609,16 +610,82 @@ class VectorHooksTest extends MediaWikiIntegrationTestCase {
'User page link in user links dropdown requires collapsible class'
);
$this->assertContains( 'mw-ui-icon-before', $contentRegistered['user-menu']['userpage']['link-class'],
'User page link in user links dropdown requires icon classes'
'User page link in user links dropdown requires before icon classes'
);
$this->assertContains( 'user-links-collapsible-item', $contentRegistered['user-menu']['watchlist']['class'],
'Watchlist link in user links dropdown requires collapsible class'
);
$this->assertContains( 'mw-ui-icon-before', $contentRegistered['user-menu']['watchlist']['link-class'],
'Watchlist link in user links dropdown requires icon classes'
'Watchlist link in user links dropdown requires before icon classes'
);
$this->assertFalse( isset( $contentRegistered['user-menu']['logout'] ),
'Logout link in user links dropdown is not set'
);
}
/**
* @covers ::updateUserLinksOverflowItems
*/
public function testUpdateUserLinksOverflowItems() {
$updateUserLinksOverflowItems = new ReflectionMethod(
Hooks::class,
'updateUserLinksOverflowItems'
);
$updateUserLinksOverflowItems->setAccessible( true );
$content = [
'notifications' => [
'alert' => [ 'class' => [], 'icon' => 'alert' ],
],
'user-interface-preferences' => [
'uls' => [ 'class' => [], 'icon' => 'uls' ],
],
'user-page' => [
'userpage' => [ 'class' => [], 'icon' => 'userpage' ],
],
'vector-user-menu-overflow' => [
'watchlist' => [ 'class' => [], 'icon' => 'watchlist' ],
],
];
$updateUserLinksOverflowItems->invokeArgs( null, [ &$content ] );
$this->assertContains( 'user-links-collapsible-item',
$content['user-interface-preferences']['uls']['class'],
'ULS link in user links overflow requires collapsible class'
);
$this->assertContains( 'user-links-collapsible-item',
$content['user-page']['userpage']['class'],
'User page link in user links overflow requires collapsible class'
);
$this->assertContains( 'mw-ui-button',
$content['user-page']['userpage']['link-class'],
'User page link in user links overflow requires button classes'
);
$this->assertContains( 'mw-ui-quiet',
$content['user-page']['userpage']['link-class'],
'User page link in user links overflow requires quiet button classes'
);
$this->assertNotContains( 'mw-ui-icon',
$content['user-page']['userpage']['class'],
'User page link in user links overflow does not have icon classes'
);
$this->assertContains( 'user-links-collapsible-item',
$content['vector-user-menu-overflow']['watchlist']['class'],
'Watchlist link in user links overflow requires collapsible class'
);
$this->assertContains( 'mw-ui-button',
$content['vector-user-menu-overflow']['watchlist']['link-class'],
'Watchlist link in user links overflow requires button classes'
);
$this->assertContains( 'mw-ui-quiet',
$content['vector-user-menu-overflow']['watchlist']['link-class'],
'Watchlist link in user links overflow requires quiet button classes'
);
$this->assertContains( 'mw-ui-icon-element',
$content['vector-user-menu-overflow']['watchlist']['link-class'],
'Watchlist link in user links overflow hides text'
);
$this->assertTrue(
$content['vector-user-menu-overflow']['watchlist']['id'] === 'pt-watchlist-2',
'Watchlist link in user links has unique id'
);
}
}