Merge "Removes old style rule"

This commit is contained in:
jenkins-bot 2023-03-10 20:52:42 +00:00 committed by Gerrit Code Review
commit 7932f6894d
15 changed files with 84 additions and 152 deletions

View file

@ -12,8 +12,8 @@ class VectorComponentPinnableHeader implements VectorComponent {
/** @var bool */
private $pinned;
/** @var string */
private $name;
/** @var string|null */
private $id;
/** @var string */
private $featureName;
/**
* @var bool
@ -28,9 +28,9 @@ class VectorComponentPinnableHeader implements VectorComponent {
/**
* @param MessageLocalizer $localizer
* @param bool $pinned
* @param string $name By convention, this should include the `vector-`
* @param string $id Pinnable element id, by convention this should include the `vector-`
* prefix e.g. `vector-page-tools` or `vector-toc`.
* @param string|null $featureName If set, pinned and unpinned states will
* @param string $featureName Pinned and unpinned states will
* persist for logged-in users by leveraging features.js to manage the user
* preference storage and the toggling of the body class. This name should NOT
* contain the "vector-" prefix.
@ -41,14 +41,14 @@ class VectorComponentPinnableHeader implements VectorComponent {
public function __construct(
MessageLocalizer $localizer,
bool $pinned,
string $name,
?string $featureName,
string $id,
string $featureName,
?bool $moveElement = true,
?string $labelTagName = 'div'
) {
$this->localizer = $localizer;
$this->pinned = $pinned;
$this->name = $name;
$this->id = $id;
$this->featureName = $featureName;
$this->moveElement = $moveElement;
$this->labelTagName = $labelTagName;
@ -61,19 +61,18 @@ class VectorComponentPinnableHeader implements VectorComponent {
$messageLocalizer = $this->localizer;
$data = [
'is-pinned' => $this->pinned,
'label' => $messageLocalizer->msg( $this->name . '-label' ),
'label' => $messageLocalizer->msg( $this->id . '-label' ),
'label-tag-name' => $this->labelTagName,
'pin-label' => $messageLocalizer->msg( 'vector-pin-element-label' ),
'unpin-label' => $messageLocalizer->msg( 'vector-unpin-element-label' ),
'data-name' => $this->name,
'data-pinnable-element-id' => $this->id,
'data-feature-name' => $this->featureName
];
if ( $this->moveElement ) {
// Assumes consistent naming standard for pinnable elements and their containers
$data = array_merge( $data, [
'data-pinnable-element-id' => $this->name,
'data-unpinned-container-id' => $this->name . '-unpinned-container',
'data-pinned-container-id' => $this->name . '-pinned-container',
'data-unpinned-container-id' => $this->id . '-unpinned-container',
'data-pinned-container-id' => $this->id . '-pinned-container',
] );
}
return $data;

View file

@ -1,12 +1,11 @@
<div
class="vector-pinnable-header {{data-name}}-pinnable-header vector-pinnable-header-{{#is-pinned}}pinned{{/is-pinned}}{{^is-pinned}}unpinned{{/is-pinned}}"
data-name="{{data-name}}"
class="vector-pinnable-header {{data-pinnable-element-id}}-pinnable-header vector-pinnable-header-{{#is-pinned}}pinned{{/is-pinned}}{{^is-pinned}}unpinned{{/is-pinned}}"
{{#data-feature-name}}data-feature-name="{{.}}"{{/data-feature-name}}
{{#data-pinnable-element-id}}data-pinnable-element-id="{{.}}"{{/data-pinnable-element-id}}
{{#data-pinned-container-id}}data-pinned-container-id="{{.}}"{{/data-pinned-container-id}}
{{#data-unpinned-container-id}}data-unpinned-container-id="{{.}}"{{/data-unpinned-container-id}}
>
<{{label-tag-name}} class="vector-pinnable-header-label">{{label}}</{{label-tag-name}}>
<button class="vector-pinnable-header-toggle-button vector-pinnable-header-pin-button" data-event-name="pinnable-header.{{data-name}}.pin">{{pin-label}}</button>
<button class="vector-pinnable-header-toggle-button vector-pinnable-header-unpin-button" data-event-name="pinnable-header.{{data-name}}.unpin">{{unpin-label}}</button>
<button class="vector-pinnable-header-toggle-button vector-pinnable-header-pin-button" data-event-name="pinnable-header.{{data-pinnable-element-id}}.pin">{{pin-label}}</button>
<button class="vector-pinnable-header-toggle-button vector-pinnable-header-unpin-button" data-event-name="pinnable-header.{{data-pinnable-element-id}}.unpin">{{unpin-label}}</button>
</div>

View file

@ -75,7 +75,22 @@ function toggle( name ) {
* @return {boolean}
*/
function isEnabled( name ) {
return document.documentElement.classList.contains( `vector-feature-${name}-enabled` );
return document.documentElement.classList.contains( getClass( name, true ) );
}
module.exports = { isEnabled, toggle, toggleDocClasses };
/**
* Get name of feature class.
*
* @param {string} name
* @param {boolean} featureEnabled
* @return {string}
*/
function getClass( name, featureEnabled ) {
if ( featureEnabled ) {
return `vector-feature-${name}-enabled`;
} else {
return `vector-feature-${name}-disabled`;
}
}
module.exports = { getClass, isEnabled, toggle, toggleDocClasses };

View file

@ -28,19 +28,13 @@ function disablePinningAtBreakpoint( header, e ) {
// Hide the button at lower resolutions.
header.hidden = e.matches;
// FIXME: Class toggling should be centralized instead of being
// handled here, in features.js and togglePinnableClasses().
if ( e.matches && savedPinnedState === true ) {
features.toggleDocClasses( featureName, false );
header.classList.remove( PINNED_HEADER_CLASS );
header.classList.add( UNPINNED_HEADER_CLASS );
movePinnableElement( pinnableElementId, unpinnedContainerId );
}
if ( !e.matches && savedPinnedState === true ) {
features.toggleDocClasses( featureName, true );
header.classList.add( PINNED_HEADER_CLASS );
header.classList.remove( UNPINNED_HEADER_CLASS );
movePinnableElement( pinnableElementId, pinnedContainerId );
}
}
@ -65,16 +59,12 @@ function setSavedPinnableState( header ) {
* @param {HTMLElement} header pinnable element
*/
function togglePinnableClasses( header ) {
const { featureName, name } = header.dataset;
const { featureName } = header.dataset;
if ( featureName ) {
// Leverage features.js to toggle the body classes and persist the state
// for logged-in users.
features.toggle( featureName );
} else {
// Toggle body classes, assumes default pinned classes are initialized serverside
document.body.classList.toggle( `${name}-pinned` );
document.body.classList.toggle( `${name}-unpinned` );
}
// Toggle pinned class
@ -139,10 +129,6 @@ function setFocusAfterToggle( pinnableElementId ) {
* @param {HTMLElement} header
*/
function bindPinnableToggleButtons( header ) {
if ( !header.dataset.name ) {
return;
}
const pinnableBreakpoint = window.matchMedia( '(max-width: 1000px)' );
const toggleButtons = header.querySelectorAll( '.vector-pinnable-header-toggle-button' );
@ -168,11 +154,11 @@ function bindPinnableToggleButtons( header ) {
* @return {boolean} Returns true if the element is pinned and false otherwise.
*/
function isPinned( header ) {
// In the future, consider delegating to `features.isEnabled()` if and when
// TOC (T316060, T325032) and all pinnable elements use the
// `vector-feature-{name}-pinned-enabled` naming convention for the body
// class.
return header.classList.contains( PINNED_HEADER_CLASS );
if ( !header.dataset.featureName ) {
return false;
} else {
return features.isEnabled( header.dataset.featureName );
}
}
/**

View file

@ -157,15 +157,13 @@
}
}
// - T314330 `.vector-toc-pinned #vector-toc-pinned-container`
// - T314330 `.vector-feature-toc-pinned-enabled #vector-toc-pinned-container`
// Prevent ToC from jumping when sticky header is enabled.
// - T289817 `.mw-sticky-header-element` provides an API for template developers
// to make their templates compatible with the Vector 2022 sticky header.
// @stable See the Integration notes for developers section at
// https://www.mediawiki.org/wiki/Reading/Web/Desktop_Improvements/Features/Sticky_Header
// - `.charts-stickyhead th` makes chart and table headers appear below the sticky header.
// FIXME: Remove the following line containing '.vector-toc-pinned #vector-toc-pinned-container' after line 169 has been in prod for a week.
.vector-toc-pinned #vector-toc-pinned-container,
&.vector-feature-toc-pinned-enabled #vector-toc-pinned-container,
&.vector-feature-page-tools-pinned-enabled .vector-page-tools-landmark,
.mw-sticky-header-element,

View file

@ -150,20 +150,8 @@
.client-js {
@media ( min-width: @min-width-desktop ) {
/**
* FIXME: Remove the following line containing '.vector-toc-unpinned' after line 157 has been in prod for a week.
*/
.vector-toc-unpinned.vector-sticky-header-visible .vector-sticky-header .vector-toc-landmark,
&.vector-feature-toc-pinned-disabled .vector-sticky-header-visible .vector-sticky-header .vector-toc-landmark,
/**
* FIXME: Remove the following line containing '.vector-toc-unpinned' after line 162 has been in prod for a week.
*/
.vector-toc-unpinned:not( .vector-sticky-header-visible ) .vector-page-titlebar .vector-toc-landmark,
&.vector-feature-toc-pinned-disabled body:not( .vector-sticky-header-visible ) .vector-page-titlebar .vector-toc-landmark,
/**
* FIXME: Remove the following line containing '.vector-toc-pinned' after line 167 has been in prod for a week.
*/
.vector-toc-pinned .mw-table-of-contents-container.vector-toc-landmark,
&.vector-feature-toc-pinned-enabled .mw-table-of-contents-container.vector-toc-landmark {
display: block;
}

View file

@ -112,10 +112,6 @@
.vector-feature-page-tools-disabled {
@{selector-sidebar-no-toc-sidebar-closed},
/**
* FIXME: Remove the following line containing '.vector-toc-unpinned' after line 117 has been in prod for a week.
*/
.vector-toc-unpinned @{selector-main-menu-closed},
&.vector-feature-toc-pinned-disabled @{selector-main-menu-closed} {
& ~ .mw-content-container {
grid-column: mainMenu / pageContent;
@ -129,10 +125,6 @@
// Horizontally center content when column start is empty (i.e. no pinned ToC or pinned main menu)
.vector-feature-page-tools-enabled {
&.vector-feature-main-menu-pinned-disabled .vector-sidebar-container-no-toc ~ .mw-content-container,
/**
* FIXME: Remove the following line containing '.vector-toc-unpinned' after line 134 has been in prod for a week.
*/
&.vector-feature-main-menu-pinned-disabled .vector-toc-unpinned .mw-content-container,
&.vector-feature-main-menu-pinned-disabled.vector-feature-toc-pinned-disabled .mw-content-container {
grid-column: mainMenu / pageContent;
margin-left: auto;

View file

@ -9,8 +9,6 @@
@media ( min-width: @min-width-desktop ) {
#mw-panel-toc {
// FIXME: Remove the following line containing '.vector-toc-pinned' after line 14 has been in prod for a week.
.vector-toc-pinned &,
.vector-feature-toc-pinned-enabled & {
// Support: Chrome
// Work around sticky-positioned layers disabling subpixel text rendering (T327460).
@ -21,15 +19,11 @@
contain: paint;
}
// FIXME: Remove the following line containing '.vector-toc-pinned' after line 26 has been in prod for a week.
.vector-feature-page-tools-disabled .vector-toc-pinned &,
.vector-feature-page-tools-disabled.vector-feature-toc-pinned-enabled & {
// Align the left edge of the TOC text with the main menu button icon.
margin-left: -27px;
}
// FIXME: Remove the following line containing '.vector-toc-pinned' after line 33 has been in prod for a week.
.vector-feature-page-tools-enabled .vector-toc-pinned &,
.vector-feature-page-tools-enabled.vector-feature-toc-pinned-enabled & {
// Align the left edge of the TOC text with the page container
margin-left: -@spacing-subsection-toggle;
@ -41,22 +35,16 @@
position: sticky;
top: 0;
// FIXME: Remove the following line containing '.vector-toc-pinned &' after line 46 has been in prod for a week.
.vector-toc-pinned &,
.vector-feature-toc-pinned-enabled & {
// Default spacing separating the sidebar TOC from the main menu.
margin-top: 1.5em;
}
// FIXME: Remove the following line containing '.vector-toc-pinned' after line 53 has been in prod for a week.
.vector-feature-page-tools-disabled .vector-toc-pinned @{selector-main-menu-closed} ~ .mw-table-of-contents-container &,
.vector-feature-page-tools-disabled.vector-feature-toc-pinned-enabled @{selector-main-menu-closed} ~ .mw-table-of-contents-container & {
// Needed to align TOC with bottom of title.
margin-top: @margin-top-pinned-toc;
}
// FIXME: Remove the following line containing '.vector-toc-pinned' after line 60 has been in prod for a week.
.vector-feature-page-tools-enabled.vector-feature-main-menu-pinned-disabled .vector-toc-pinned &,
.vector-feature-page-tools-enabled.vector-feature-main-menu-pinned-disabled.vector-feature-toc-pinned-enabled & {
// Align TOC with bottom of title when main menu is not pinned but the TOC is
margin-top: @margin-top-pinned-toc;

View file

@ -97,8 +97,6 @@ body:not( .vector-below-page-title ) #vector-page-titlebar-toc-label {
//
// TOC in page titlebar
//
// FIXME: Remove the following line containing '.vector-toc-unpinned' after line 102 has been in prod for a week.
.vector-toc-unpinned:not( .vector-sticky-header-visible ),
&.vector-feature-toc-pinned-disabled body:not( .vector-sticky-header-visible ) {
.vector-page-titlebar-toc {
.mixin-toc-unpinned();
@ -108,8 +106,6 @@ body:not( .vector-below-page-title ) #vector-page-titlebar-toc-label {
//
// TOC in page titlebar below page title
//
// FIXME: Remove the following line containing '.vector-toc-unpinned' after line 113 has been in prod for a week.
.vector-toc-unpinned:not( .vector-sticky-header-visible ).vector-below-page-title,
&.vector-feature-toc-pinned-disabled body:not( .vector-sticky-header-visible ).vector-below-page-title {
.vector-page-titlebar-toc {
.mixin-toc-below-page-title();
@ -119,8 +115,6 @@ body:not( .vector-below-page-title ) #vector-page-titlebar-toc-label {
//
// TOC in sticky header
//
// FIXME: Remove the following line containing '.vector-toc-unpinned' after line 124 has been in prod for a week.
.vector-toc-unpinned.vector-sticky-header-visible,
&.vector-feature-toc-pinned-disabled .vector-sticky-header-visible {
.vector-sticky-header-toc {
.mixin-toc-unpinned();

View file

@ -12,10 +12,10 @@ exports[`Pinnable header renders 1`] = `
</label>
<div class=\\"vector-menu-content\\">
<div id=\\"unpinned-container\\">
<div id=\\"pinnable-element\\"> <div class=\\"vector-pinnable-header simple-pinnable-header vector-pinnable-header-unpinned\\" data-name=\\"simple\\" data-pinnable-element-id=\\"pinnable-element\\">
<div id=\\"pinnable-element\\"> <div class=\\"vector-pinnable-header pinnable-element-pinnable-header vector-pinnable-header-unpinned\\" data-feature-name=\\"pinned\\" data-pinnable-element-id=\\"pinnable-element\\">
<div class=\\"vector-pinnable-header-label\\">simple pinnable element</div>
<button class=\\"vector-pinnable-header-toggle-button vector-pinnable-header-pin-button\\" data-event-name=\\"pinnable-header.simple.pin\\">pin</button>
<button class=\\"vector-pinnable-header-toggle-button vector-pinnable-header-unpin-button\\" data-event-name=\\"pinnable-header.simple.unpin\\">unpin</button>
<button class=\\"vector-pinnable-header-toggle-button vector-pinnable-header-pin-button\\" data-event-name=\\"pinnable-header.pinnable-element.pin\\">pin</button>
<button class=\\"vector-pinnable-header-toggle-button vector-pinnable-header-unpin-button\\" data-event-name=\\"pinnable-header.pinnable-element.unpin\\">unpin</button>
</div>
</div>
</div>

View file

@ -2,7 +2,7 @@
exports[`Table of contents reloadTableOfContents re-renders toc when wikipage.tableOfContents hook is fired with empty sections 1`] = `
"<div id=\\"vector-toc\\" class=\\"vector-toc vector-pinnable-element\\">
<div class=\\"vector-pinnable-header vector-toc-pinnable-header vector-pinnable-header-pinned\\" data-name=\\"vector-toc\\">
<div class=\\"vector-pinnable-header vector-toc-pinnable-header vector-pinnable-header-pinned\\" data-feature-name=\\"pinned\\" data-pinnable-element-id=\\"vector-toc\\">
<h2 class=\\"vector-pinnable-header-label\\">Contents</h2>
<button class=\\"vector-pinnable-header-toggle-button vector-pinnable-header-pin-button\\" data-event-name=\\"pinnable-header.vector-toc.pin\\">move to sidebar</button>
<button class=\\"vector-pinnable-header-toggle-button vector-pinnable-header-unpin-button\\" data-event-name=\\"pinnable-header.vector-toc.unpin\\">hide</button>
@ -63,13 +63,13 @@ exports[`Table of contents reloadTableOfContents re-renders toc when wikipage.ta
exports[`Table of contents reloadTableOfContents re-renders toc when wikipage.tableOfContents hook is fired with sections 1`] = `
"<div id=\\"vector-toc\\" class=\\"vector-toc vector-pinnable-element\\">
<div class=\\"vector-pinnable-header vector-toc-pinnable-header vector-pinnable-header-pinned\\" data-name=\\"vector-toc\\">
<div class=\\"vector-pinnable-header vector-toc-pinnable-header vector-pinnable-header-pinned\\" data-feature-name=\\"pinned\\" data-pinnable-element-id=\\"vector-toc\\">
<h2 class=\\"vector-pinnable-header-label\\">Contents</h2>
<button class=\\"vector-pinnable-header-toggle-button vector-pinnable-header-pin-button\\" data-event-name=\\"pinnable-header.vector-toc.pin\\">move to sidebar</button>
<button class=\\"vector-pinnable-header-toggle-button vector-pinnable-header-unpin-button\\" data-event-name=\\"pinnable-header.vector-toc.unpin\\">hide</button>
</div>
<ul class=\\"vector-toc-contents\\" id=\\"mw-panel-toc-list\\"><div id=\\"vector-toc\\" class=\\"vector-toc vector-pinnable-element\\">
<div class=\\"vector-pinnable-header vector-toc-pinnable-header vector-pinnable-header-pinned\\" data-name=\\"vector-toc\\">
<div class=\\"vector-pinnable-header vector-toc-pinnable-header vector-pinnable-header-pinned\\" data-feature-name=\\"pinned\\" data-pinnable-element-id=\\"vector-toc\\">
<h2 class=\\"vector-pinnable-header-label\\">Contents</h2>
<button class=\\"vector-pinnable-header-toggle-button vector-pinnable-header-pin-button\\" data-event-name=\\"pinnable-header.vector-toc.pin\\">move to sidebar</button>
<button class=\\"vector-pinnable-header-toggle-button vector-pinnable-header-unpin-button\\" data-event-name=\\"pinnable-header.vector-toc.unpin\\">hide</button>
@ -140,7 +140,7 @@ exports[`Table of contents reloadTableOfContents re-renders toc when wikipage.ta
exports[`Table of contents renders when \`vector-is-collapse-sections-enabled\` is false 1`] = `
"<div id=\\"vector-toc\\" class=\\"vector-toc vector-pinnable-element\\">
<div class=\\"vector-pinnable-header vector-toc-pinnable-header vector-pinnable-header-pinned\\" data-name=\\"vector-toc\\">
<div class=\\"vector-pinnable-header vector-toc-pinnable-header vector-pinnable-header-pinned\\" data-feature-name=\\"pinned\\" data-pinnable-element-id=\\"vector-toc\\">
<h2 class=\\"vector-pinnable-header-label\\">Contents</h2>
<button class=\\"vector-pinnable-header-toggle-button vector-pinnable-header-pin-button\\" data-event-name=\\"pinnable-header.vector-toc.pin\\">move to sidebar</button>
<button class=\\"vector-pinnable-header-toggle-button vector-pinnable-header-unpin-button\\" data-event-name=\\"pinnable-header.vector-toc.unpin\\">hide</button>
@ -201,7 +201,7 @@ exports[`Table of contents renders when \`vector-is-collapse-sections-enabled\`
exports[`Table of contents renders when \`vector-is-collapse-sections-enabled\` is true 1`] = `
"<div id=\\"vector-toc\\" class=\\"vector-toc vector-pinnable-element\\">
<div class=\\"vector-pinnable-header vector-toc-pinnable-header vector-pinnable-header-pinned\\" data-name=\\"vector-toc\\">
<div class=\\"vector-pinnable-header vector-toc-pinnable-header vector-pinnable-header-pinned\\" data-feature-name=\\"pinned\\" data-pinnable-element-id=\\"vector-toc\\">
<h2 class=\\"vector-pinnable-header-label\\">Contents</h2>
<button class=\\"vector-pinnable-header-toggle-button vector-pinnable-header-pin-button\\" data-event-name=\\"pinnable-header.vector-toc.pin\\">move to sidebar</button>
<button class=\\"vector-pinnable-header-toggle-button vector-pinnable-header-unpin-button\\" data-event-name=\\"pinnable-header.vector-toc.unpin\\">hide</button>

View file

@ -24,9 +24,18 @@ Object.defineProperty( window, 'matchMedia', {
} ) )
} );
// Mock functionality of features.js
let pinnedStatus = false;
features.toggle = jest.fn( () => {
pinnedStatus = !pinnedStatus;
} );
features.isEnabled = jest.fn( () => {
return pinnedStatus;
} );
const simpleData = {
'is-pinned': false,
'data-name': 'simple',
'data-feature-name': 'pinned',
'data-pinnable-element-id': 'pinnable-element',
label: 'simple pinnable element',
'label-tag-name': 'div',
@ -34,20 +43,14 @@ const simpleData = {
'unpin-label': 'unpin'
};
const movableData = {
'is-pinned': false,
'data-name': 'movable',
'data-pinnable-element-id': 'pinnable-element',
const movableData = { ...simpleData, ...{
'data-pinned-container-id': 'pinned-container',
'data-unpinned-container-id': 'unpinned-container',
label: 'moveable pinnable element',
'label-tag-name': 'div',
'pin-label': 'pin',
'unpin-label': 'unpin'
};
'data-unpinned-container-id': 'unpinned-container'
} };
// @ts-ignore
const initializeHTML = ( headerData ) => {
pinnedStatus = headerData[ 'is-pinned' ];
const pinnableHeaderHTML = mustache.render( pinnableHeaderTemplate, headerData );
const pinnableElementHTML = `<div id="pinnable-element"> ${ pinnableHeaderHTML } </div>`;
document.body.innerHTML = `
@ -66,20 +69,6 @@ const initializeHTML = ( headerData ) => {
</div>
</div>
`;
if ( headerData[ 'data-feature-name' ] ) {
// Return early if the persistent option is enabled as features.js will
// manage the body classes instead of pinnableElement.
return;
}
if ( headerData[ 'is-pinned' ] ) {
document.body.classList.add( `${headerData[ 'data-name' ]}-pinned` );
document.body.classList.remove( `${headerData[ 'data-name' ]}-unpinned` );
} else {
document.body.classList.remove( `${headerData[ 'data-name' ]}-pinned` );
document.body.classList.add( `${headerData[ 'data-name' ]}-unpinned` );
}
};
describe( 'Pinnable header', () => {
@ -88,27 +77,21 @@ describe( 'Pinnable header', () => {
expect( document.body.innerHTML ).toMatchSnapshot();
} );
test( 'updates pinnable classes when toggle is pressed', () => {
test( 'updates pinnable header classes when toggle is pressed', () => {
initializeHTML( simpleData );
pinnableElement.initPinnableElement();
const pinButton = /** @type {HTMLElement} */ ( document.querySelector( '.vector-pinnable-header-pin-button' ) );
const unpinButton = /** @type {HTMLElement} */ ( document.querySelector( '.vector-pinnable-header-unpin-button' ) );
const header = /** @type {HTMLElement} */ ( document.querySelector( `.${simpleData[ 'data-name' ]}-pinnable-header` ) );
const header = /** @type {HTMLElement} */ ( document.querySelector( `.${simpleData[ 'data-pinnable-element-id' ]}-pinnable-header` ) );
expect( header.classList.contains( pinnableElement.PINNED_HEADER_CLASS ) ).toBe( false );
expect( document.body.classList.contains( `${simpleData[ 'data-name' ]}-pinned` ) ).toBe( false );
expect( header.classList.contains( pinnableElement.UNPINNED_HEADER_CLASS ) ).toBe( true );
expect( document.body.classList.contains( `${simpleData[ 'data-name' ]}-unpinned` ) ).toBe( true );
pinButton.click();
expect( header.classList.contains( pinnableElement.PINNED_HEADER_CLASS ) ).toBe( true );
expect( document.body.classList.contains( `${simpleData[ 'data-name' ]}-pinned` ) ).toBe( true );
expect( header.classList.contains( pinnableElement.UNPINNED_HEADER_CLASS ) ).toBe( false );
expect( document.body.classList.contains( `${simpleData[ 'data-name' ]}-unpinned` ) ).toBe( false );
unpinButton.click();
expect( header.classList.contains( pinnableElement.PINNED_HEADER_CLASS ) ).toBe( false );
expect( document.body.classList.contains( `${simpleData[ 'data-name' ]}-pinned` ) ).toBe( false );
expect( header.classList.contains( pinnableElement.UNPINNED_HEADER_CLASS ) ).toBe( true );
expect( document.body.classList.contains( `${simpleData[ 'data-name' ]}-unpinned` ) ).toBe( true );
} );
test( 'doesnt move pinnable element when data attributes arent defined', () => {
@ -143,43 +126,33 @@ describe( 'Pinnable header', () => {
/* eslint-enable no-restricted-properties */
} );
test( 'calls features.js when data-feature-name is set', () => {
initializeHTML( {
...simpleData,
'data-name': 'vector-page-tools',
'data-feature-name': 'page-tools-pinned'
} );
pinnableElement.initPinnableElement();
const pinButton = /** @type {HTMLElement} */ ( document.querySelector( '.vector-pinnable-header-pin-button' ) );
const unpinButton = /** @type {HTMLElement} */ ( document.querySelector( '.vector-pinnable-header-unpin-button' ) );
pinButton.click();
expect( features.toggle ).toHaveBeenCalledTimes( 1 );
expect( features.toggle ).toHaveBeenCalledWith( 'page-tools-pinned' );
// @ts-ignore
features.toggle.mockClear();
unpinButton.click();
expect( features.toggle ).toHaveBeenCalledTimes( 1 );
expect( features.toggle ).toHaveBeenCalledWith( 'page-tools-pinned' );
} );
test( 'isPinned() returns whether the element is pinned or not', () => {
test( 'calls features.toggle() when toggle is pressed', () => {
initializeHTML( simpleData );
pinnableElement.initPinnableElement();
const pinButton = /** @type {HTMLElement} */ ( document.querySelector( '.vector-pinnable-header-pin-button' ) );
const unpinButton = /** @type {HTMLElement} */ ( document.querySelector( '.vector-pinnable-header-unpin-button' ) );
const header = /** @type {HTMLElement} */ ( document.querySelector( `.${simpleData[ 'data-name' ]}-pinnable-header` ) );
pinButton.click();
expect( features.toggle ).toHaveBeenCalledTimes( 1 );
expect( features.toggle ).toHaveBeenCalledWith( simpleData[ 'data-feature-name' ] );
expect( pinnableElement.isPinned( header ) ).toBe( true );
// @ts-ignore
features.toggle.mockClear();
unpinButton.click();
expect( features.toggle ).toHaveBeenCalledTimes( 1 );
expect( features.toggle ).toHaveBeenCalledWith( simpleData[ 'data-feature-name' ] );
} );
expect( pinnableElement.isPinned( header ) ).toBe( false );
test( 'isPinned() calls features.isEnabled()', () => {
initializeHTML( simpleData );
pinnableElement.initPinnableElement();
const header = /** @type {HTMLElement} */ ( document.querySelector( `.${simpleData[ 'data-pinnable-element-id' ]}-pinnable-header` ) );
// @ts-ignore
features.isEnabled.mockClear();
pinnableElement.isPinned( header );
expect( features.isEnabled ).toHaveBeenCalledTimes( 1 );
expect( features.isEnabled ).toHaveBeenCalledWith( simpleData[ 'data-feature-name' ] );
} );
test( 'setFocusAfterToggle() sets focus on appropriate element after pinnableElement is toggled', () => {

View file

@ -77,11 +77,12 @@ function render( templateProps = {} ) {
id: 'vector-toc',
'data-pinnable-header': {
'is-pinned': true,
'data-feature-name': 'pinned',
'data-pinnable-element-id': 'vector-toc',
label: 'Contents',
'label-tag-name': 'h2',
'pin-label': 'move to sidebar',
'unpin-label': 'hide',
'data-name': 'vector-toc'
'unpin-label': 'hide'
}
}, templateProps );

View file

@ -87,7 +87,6 @@ class VectorComponentPageToolsTest extends \MediaWikiUnitTestCase {
'label-tag-name' => 'div',
'pin-label' => 'vector-pin-element-label',
'unpin-label' => 'vector-unpin-element-label',
'data-name' => 'vector-page-tools',
'data-feature-name' => 'page-tools-pinned',
'data-pinnable-element-id' => 'vector-page-tools',
'data-unpinned-container-id' => 'vector-page-tools-unpinned-container',

View file

@ -113,7 +113,7 @@ class VectorComponentTableOfContentsTest extends \MediaWikiUnitTestCase {
'id' => 'vector-toc',
'data-pinnable-header' => [
'is-pinned' => true,
'data-name' => 'vector-toc',
'data-pinnable-element-id' => 'vector-toc',
'data-feature-name' => 'toc-pinned',
'label' => 'vector-toc-label',
'unpin-label' => 'vector-unpin-element-label',