mirror of
https://gerrit.wikimedia.org/r/mediawiki/skins/Vector.git
synced 2024-11-24 15:53:46 +00:00
Merge "Add Jest tests for TOC before/after edit"
This commit is contained in:
commit
b590555126
|
@ -29,10 +29,10 @@ module.exports = {
|
||||||
// An object that configures minimum threshold enforcement for coverage results
|
// An object that configures minimum threshold enforcement for coverage results
|
||||||
coverageThreshold: {
|
coverageThreshold: {
|
||||||
global: {
|
global: {
|
||||||
branches: 14,
|
branches: 25,
|
||||||
functions: 24,
|
functions: 29,
|
||||||
lines: 22,
|
lines: 32,
|
||||||
statements: 22
|
statements: 33
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,82 @@
|
||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`Table of contents re-rendering re-renders toc when wikipage.tableOfContents hook is fired with empty sections 1`] = `
|
||||||
|
"<nav id=\\"mw-panel-toc\\" class=\\"sidebar-toc\\" role=\\"navigation\\" aria-labelledby=\\"sidebar-toc-label\\" data-event-name=\\"ui.sidebar-toc\\"></nav>
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Table of contents re-rendering re-renders toc when wikipage.tableOfContents hook is fired with sections 1`] = `
|
||||||
|
"<nav id=\\"mw-panel-toc\\" class=\\"sidebar-toc\\" role=\\"navigation\\" aria-labelledby=\\"sidebar-toc-label\\" data-event-name=\\"ui.sidebar-toc\\"><nav id=\\"mw-panel-toc\\" class=\\"sidebar-toc\\" role=\\"navigation\\" aria-labelledby=\\"sidebar-toc-label\\" data-event-name=\\"ui.sidebar-toc\\">
|
||||||
|
<div id=\\"sidebar-toc-label\\" class=\\"sidebar-toc-header\\">
|
||||||
|
<p class=\\"sidebar-toc-title\\">
|
||||||
|
Contents
|
||||||
|
<button class=\\"vector-toc-uncollapse-button\\">move to sidebar</button>
|
||||||
|
<button class=\\"vector-toc-collapse-button\\">hide</button>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<ul class=\\"sidebar-toc-contents\\" id=\\"mw-panel-toc-list\\">
|
||||||
|
<li id=\\"toc-mw-content-text\\" class=\\"sidebar-toc-list-item sidebar-toc-level-1\\">
|
||||||
|
<a href=\\"#top-page\\" class=\\"sidebar-toc-link\\">
|
||||||
|
<div class=\\"sidebar-toc-text\\">Beginning</div>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
<li id=\\"toc-foo\\" class=\\"sidebar-toc-list-item sidebar-toc-level-1 sidebar-toc-list-item-expanded\\">
|
||||||
|
<a class=\\"sidebar-toc-link\\" href=\\"#foo\\">
|
||||||
|
<div class=\\"sidebar-toc-text\\">
|
||||||
|
<span class=\\"sidebar-toc-numb\\">1</span>foo</div>
|
||||||
|
</a>
|
||||||
|
<ul id=\\"toc-foo-sublist\\" class=\\"sidebar-toc-list\\">
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li id=\\"toc-bar\\" class=\\"sidebar-toc-list-item sidebar-toc-level-1 sidebar-toc-list-item-expanded\\">
|
||||||
|
<a class=\\"sidebar-toc-link\\" href=\\"#bar\\">
|
||||||
|
<div class=\\"sidebar-toc-text\\">
|
||||||
|
<span class=\\"sidebar-toc-numb\\">2</span>bar</div>
|
||||||
|
</a>
|
||||||
|
<button aria-controls=\\"toc-bar-sublist\\" class=\\"mw-ui-icon mw-ui-icon-wikimedia-expand mw-ui-icon-small sidebar-toc-toggle\\" aria-expanded=\\"true\\">
|
||||||
|
Toggle bar subsection
|
||||||
|
</button>
|
||||||
|
<ul id=\\"toc-bar-sublist\\" class=\\"sidebar-toc-list\\">
|
||||||
|
<li id=\\"toc-baz\\" class=\\"sidebar-toc-list-item sidebar-toc-level-2\\">
|
||||||
|
<a class=\\"sidebar-toc-link\\" href=\\"#baz\\">
|
||||||
|
<div class=\\"sidebar-toc-text\\">
|
||||||
|
<span class=\\"sidebar-toc-numb\\">2.1</span>baz</div>
|
||||||
|
</a>
|
||||||
|
<ul id=\\"toc-baz-sublist\\" class=\\"sidebar-toc-list\\">
|
||||||
|
<li id=\\"toc-qux\\" class=\\"sidebar-toc-list-item sidebar-toc-level-3\\">
|
||||||
|
<a class=\\"sidebar-toc-link\\" href=\\"#qux\\">
|
||||||
|
<div class=\\"sidebar-toc-text\\">
|
||||||
|
<span class=\\"sidebar-toc-numb\\">2.1.1</span>qux</div>
|
||||||
|
</a>
|
||||||
|
<ul id=\\"toc-qux-sublist\\" class=\\"sidebar-toc-list\\">
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li id=\\"toc-quux\\" class=\\"sidebar-toc-list-item sidebar-toc-level-1 sidebar-toc-list-item-expanded\\">
|
||||||
|
<a class=\\"sidebar-toc-link\\" href=\\"#quux\\">
|
||||||
|
<div class=\\"sidebar-toc-text\\">
|
||||||
|
<span class=\\"sidebar-toc-numb\\">3</span>quux</div>
|
||||||
|
</a>
|
||||||
|
<ul id=\\"toc-quux-sublist\\" class=\\"sidebar-toc-list\\">
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<li id=\\"toc-bat\\" class=\\"sidebar-toc-list-item sidebar-toc-level-1 sidebar-toc-list-item-expanded\\">
|
||||||
|
<a class=\\"sidebar-toc-link\\" href=\\"#bat\\">
|
||||||
|
<div class=\\"sidebar-toc-text\\">
|
||||||
|
<span class=\\"sidebar-toc-numb\\">4</span>bat</div>
|
||||||
|
</a>
|
||||||
|
<ul id=\\"toc-bat-sublist\\" class=\\"sidebar-toc-list\\">
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</nav>
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`Table of contents renders when \`vector-is-collapse-sections-enabled\` is false 1`] = `
|
exports[`Table of contents renders when \`vector-is-collapse-sections-enabled\` is false 1`] = `
|
||||||
"<nav id=\\"mw-panel-toc\\" class=\\"sidebar-toc\\" role=\\"navigation\\" aria-labelledby=\\"sidebar-toc-label\\" data-event-name=\\"ui.sidebar-toc\\">
|
"<nav id=\\"mw-panel-toc\\" class=\\"sidebar-toc\\" role=\\"navigation\\" aria-labelledby=\\"sidebar-toc-label\\" data-event-name=\\"ui.sidebar-toc\\">
|
||||||
<div id=\\"sidebar-toc-label\\" class=\\"sidebar-toc-header\\">
|
<div id=\\"sidebar-toc-label\\" class=\\"sidebar-toc-header\\">
|
||||||
|
|
|
@ -13,6 +13,51 @@ const onHeadingClick = jest.fn();
|
||||||
const onToggleClick = jest.fn();
|
const onToggleClick = jest.fn();
|
||||||
const onToggleCollapse = jest.fn();
|
const onToggleCollapse = jest.fn();
|
||||||
|
|
||||||
|
const SECTIONS = [
|
||||||
|
{
|
||||||
|
toclevel: 1,
|
||||||
|
number: '1',
|
||||||
|
line: 'foo',
|
||||||
|
anchor: 'foo',
|
||||||
|
'is-top-level-section': true,
|
||||||
|
'is-parent-section': false,
|
||||||
|
'array-sections': null
|
||||||
|
}, {
|
||||||
|
toclevel: 1,
|
||||||
|
number: '2',
|
||||||
|
line: 'bar',
|
||||||
|
anchor: 'bar',
|
||||||
|
'is-top-level-section': true,
|
||||||
|
'is-parent-section': true,
|
||||||
|
'vector-button-label': 'Toggle bar subsection',
|
||||||
|
'array-sections': [ {
|
||||||
|
toclevel: 2,
|
||||||
|
number: '2.1',
|
||||||
|
line: 'baz',
|
||||||
|
anchor: 'baz',
|
||||||
|
'is-top-level-section': false,
|
||||||
|
'is-parent-section': true,
|
||||||
|
'array-sections': [ {
|
||||||
|
toclevel: 3,
|
||||||
|
number: '2.1.1',
|
||||||
|
line: 'qux',
|
||||||
|
anchor: 'qux',
|
||||||
|
'is-top-level-section': false,
|
||||||
|
'is-parent-section': false,
|
||||||
|
'array-sections': null
|
||||||
|
} ]
|
||||||
|
} ]
|
||||||
|
}, {
|
||||||
|
toclevel: 1,
|
||||||
|
number: '3',
|
||||||
|
line: 'quux',
|
||||||
|
anchor: 'quux',
|
||||||
|
'is-top-level-section': true,
|
||||||
|
'is-parent-section': false,
|
||||||
|
'array-sections': null
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {Object} templateProps
|
* @param {Object} templateProps
|
||||||
* @return {string}
|
* @return {string}
|
||||||
|
@ -23,48 +68,7 @@ function render( templateProps = {} ) {
|
||||||
'msg-vector-toc-beginning': 'Beginning',
|
'msg-vector-toc-beginning': 'Beginning',
|
||||||
'msg-vector-toc-heading': 'Contents',
|
'msg-vector-toc-heading': 'Contents',
|
||||||
'vector-is-collapse-sections-enabled': false,
|
'vector-is-collapse-sections-enabled': false,
|
||||||
'array-sections': [ {
|
'array-sections': SECTIONS
|
||||||
toclevel: 1,
|
|
||||||
number: '1',
|
|
||||||
line: 'foo',
|
|
||||||
anchor: 'foo',
|
|
||||||
'is-top-level-section': true,
|
|
||||||
'is-parent-section': false,
|
|
||||||
'array-sections': null
|
|
||||||
}, {
|
|
||||||
toclevel: 1,
|
|
||||||
number: '2',
|
|
||||||
line: 'bar',
|
|
||||||
anchor: 'bar',
|
|
||||||
'is-top-level-section': true,
|
|
||||||
'is-parent-section': true,
|
|
||||||
'vector-button-label': 'Toggle bar subsection',
|
|
||||||
'array-sections': [ {
|
|
||||||
toclevel: 2,
|
|
||||||
number: '2.1',
|
|
||||||
line: 'baz',
|
|
||||||
anchor: 'baz',
|
|
||||||
'is-top-level-section': false,
|
|
||||||
'is-parent-section': true,
|
|
||||||
'array-sections': [ {
|
|
||||||
toclevel: 3,
|
|
||||||
number: '2.1.1',
|
|
||||||
line: 'qux',
|
|
||||||
anchor: 'qux',
|
|
||||||
'is-top-level-section': false,
|
|
||||||
'is-parent-section': false,
|
|
||||||
'array-sections': null
|
|
||||||
} ]
|
|
||||||
} ]
|
|
||||||
}, {
|
|
||||||
toclevel: 1,
|
|
||||||
number: '3',
|
|
||||||
line: 'quux',
|
|
||||||
anchor: 'quux',
|
|
||||||
'is-top-level-section': true,
|
|
||||||
'is-parent-section': false,
|
|
||||||
'array-sections': null
|
|
||||||
} ]
|
|
||||||
}, templateProps );
|
}, templateProps );
|
||||||
|
|
||||||
return mustache.render( tableOfContentsTemplate, templateData, {
|
return mustache.render( tableOfContentsTemplate, templateData, {
|
||||||
|
@ -215,4 +219,142 @@ describe( 'Table of contents', () => {
|
||||||
expect( toggleButton.getAttribute( 'aria-expanded' ) ).toEqual( 'true' );
|
expect( toggleButton.getAttribute( 'aria-expanded' ) ).toEqual( 'true' );
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
describe( 're-rendering', () => {
|
||||||
|
const mockMwHook = () => {
|
||||||
|
/** @type {Function} */
|
||||||
|
let callback;
|
||||||
|
// @ts-ignore
|
||||||
|
jest.spyOn( mw, 'hook' ).mockImplementation( () => {
|
||||||
|
|
||||||
|
return {
|
||||||
|
add: function ( fn ) {
|
||||||
|
callback = fn;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
fire: ( data ) => {
|
||||||
|
if ( callback ) {
|
||||||
|
callback( data );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} );
|
||||||
|
};
|
||||||
|
|
||||||
|
afterEach( () => {
|
||||||
|
jest.restoreAllMocks();
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'listens to wikipage.tableOfContents hook when mounted', () => {
|
||||||
|
const spy = jest.spyOn( mw, 'hook' );
|
||||||
|
mount();
|
||||||
|
expect( spy ).toHaveBeenCalledWith( 'wikipage.tableOfContents' );
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 're-renders toc when wikipage.tableOfContents hook is fired with empty sections', () => {
|
||||||
|
mockMwHook();
|
||||||
|
mount();
|
||||||
|
|
||||||
|
mw.hook( 'wikipage.tableOfContents' ).fire( [] );
|
||||||
|
|
||||||
|
expect( document.body.innerHTML ).toMatchSnapshot();
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 're-renders toc when wikipage.tableOfContents hook is fired with sections', async () => {
|
||||||
|
mockMwHook();
|
||||||
|
// @ts-ignore
|
||||||
|
// eslint-disable-next-line compat/compat
|
||||||
|
jest.spyOn( mw.loader, 'using' ).mockImplementation( () => Promise.resolve() );
|
||||||
|
// @ts-ignore
|
||||||
|
mw.template.getCompiler = () => {};
|
||||||
|
jest.spyOn( mw, 'message' ).mockImplementation( ( msg ) => {
|
||||||
|
const msgFactory = ( /** @type {string} */ text ) => {
|
||||||
|
return {
|
||||||
|
parse: () => '',
|
||||||
|
plain: () => '',
|
||||||
|
escaped: () => '',
|
||||||
|
exists: () => true,
|
||||||
|
text: () => text
|
||||||
|
};
|
||||||
|
};
|
||||||
|
switch ( msg ) {
|
||||||
|
case 'vector-toc-heading':
|
||||||
|
return msgFactory( 'Contents' );
|
||||||
|
case 'vector-toc-toggle-position-sidebar':
|
||||||
|
return msgFactory( 'move to sidebar' );
|
||||||
|
case 'vector-toc-toggle-position-title':
|
||||||
|
return msgFactory( 'hide' );
|
||||||
|
case 'vector-toc-beginning':
|
||||||
|
return msgFactory( 'Beginning' );
|
||||||
|
default:
|
||||||
|
return msgFactory( '' );
|
||||||
|
}
|
||||||
|
|
||||||
|
} );
|
||||||
|
// @ts-ignore
|
||||||
|
jest.spyOn( mw.template, 'getCompiler' ).mockImplementation( () => {
|
||||||
|
return {
|
||||||
|
compile: () => {
|
||||||
|
return {
|
||||||
|
render: ( /** @type {Object} */ data ) => {
|
||||||
|
return {
|
||||||
|
html: () => {
|
||||||
|
return render( data );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} );
|
||||||
|
|
||||||
|
const toc = mount();
|
||||||
|
|
||||||
|
const toggleButton = /** @type {HTMLElement} */ ( barSection.querySelector( `.${toc.TOGGLE_CLASS}` ) );
|
||||||
|
// Collapse section.
|
||||||
|
toc.toggleExpandSection( 'toc-bar' );
|
||||||
|
expect( toggleButton.getAttribute( 'aria-expanded' ) ).toEqual( 'false' );
|
||||||
|
|
||||||
|
// wikipage.tableOfContents includes the nested sections in the top level
|
||||||
|
// of the array.
|
||||||
|
mw.hook( 'wikipage.tableOfContents' ).fire( [
|
||||||
|
// foo
|
||||||
|
SECTIONS[ 0 ],
|
||||||
|
// bar
|
||||||
|
SECTIONS[ 1 ],
|
||||||
|
// baz
|
||||||
|
// @ts-ignore
|
||||||
|
SECTIONS[ 1 ][ 'array-sections' ][ 0 ],
|
||||||
|
// qux
|
||||||
|
// @ts-ignore
|
||||||
|
SECTIONS[ 1 ][ 'array-sections' ][ 0 ][ 'array-sections' ][ 0 ],
|
||||||
|
// quux
|
||||||
|
SECTIONS[ 2 ],
|
||||||
|
// Add new section to see how the re-render performs.
|
||||||
|
{
|
||||||
|
toclevel: 1,
|
||||||
|
number: '4',
|
||||||
|
line: 'bat',
|
||||||
|
anchor: 'bat',
|
||||||
|
'is-top-level-section': true,
|
||||||
|
'is-parent-section': false,
|
||||||
|
'array-sections': null
|
||||||
|
}
|
||||||
|
] );
|
||||||
|
|
||||||
|
// Wait until the mw.loader.using promise has resolved so that we can
|
||||||
|
// check the DOM after it has been updated.
|
||||||
|
// eslint-disable-next-line compat/compat
|
||||||
|
await Promise.resolve();
|
||||||
|
|
||||||
|
const newToggleButton = /** @type {HTMLElement} */ ( document.querySelector( `#toc-bar .${toc.TOGGLE_CLASS}` ) );
|
||||||
|
expect( newToggleButton ).not.toBeNull();
|
||||||
|
// Check that the sections render in their expanded form.
|
||||||
|
expect( newToggleButton.getAttribute( 'aria-expanded' ) ).toEqual( 'true' );
|
||||||
|
|
||||||
|
// Verify newly rendered TOC html matches the expected html.
|
||||||
|
expect( document.body.innerHTML ).toMatchSnapshot();
|
||||||
|
} );
|
||||||
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
Loading…
Reference in a new issue