We had several implementations of almost identical paging links: * PrevNextNavigationRenderer: The nicest one, somewhat recently added (4ca72763ec). Unfortunately it was also the least featureful: only supporting paging by numeric offset and not by index, and not able to generate "first"/"last" links. Also, I didn't realize that it exists when working on94553a1bcbandb95d208340, so it was missing those changes too. * IndexPager/ReverseChronologicalPager/AlphabeticPager: These have been here forever. The most featureful, but not configurable, so a large part of the implementation was copy-pasted in two classes. * SpecialWhatLinksHere: Through some accident of history, this one special page ended up with its own implementation??? They are all replaced to use the new PagerNavigationBuilder. It may be slightly too much, but I had fun writing it. Notable changes compared to PrevNextNavigationRenderer: * Adds <div class="mw-pager-navigation-bar"> wrapper around the navigation and <span class="…"> wrappers on inactive links * The current limit link is made inactive (like the "prev" link when on first page, etc.) Notable changes compared to ...Pager/...Pager/...Pager: * Does not generate useless tooltips that contain only the title of the page, can use custom tooltips * The current limit link is made inactive (like the "prev" link when on first page, etc.) * All links have query parameters in a consistent order: ?title= &... &dir= &offset= &limit= (some of them are optional) These changes affect many special pages and actions. I tested on: * Special:Contributions (ReverseChronologicalPager) * action=history (ReverseChronologicalPager) * Special:Categories (AlphabeticPager) * Special:WantedPages (PrevNextNavigationRenderer) * Special:Search (PrevNextNavigationRenderer) * Special:WhatLinksHere Bug: T308364 Change-Id: Ic75bd597b210e14612ca3aebb531b659897e8294
102 lines
3.4 KiB
PHP
102 lines
3.4 KiB
PHP
<?php
|
|
|
|
use MediaWiki\MainConfigNames;
|
|
use MediaWiki\Navigation\PrevNextNavigationRenderer;
|
|
use Wikimedia\TestingAccessWrapper;
|
|
|
|
/**
|
|
* @covers \MediaWiki\Navigation\PrevNextNavigationRenderer
|
|
*/
|
|
class PrevNextNavigationRendererTest extends MediaWikiIntegrationTestCase {
|
|
|
|
public function provideBuildPrevNextNavigation() {
|
|
yield [ 0, 20, false, false ];
|
|
yield [ 17, 20, false, false ];
|
|
yield [ 0, 17, false, false ];
|
|
yield [ 0, 20, true, 'Foo' ];
|
|
yield [ 17, 20, true, 'Föö_Bär' ];
|
|
}
|
|
|
|
/**
|
|
* @dataProvider provideBuildPrevNextNavigation
|
|
*/
|
|
public function testBuildPrevNextNavigation( $offset, $limit, $atEnd, $subPage ) {
|
|
$this->overrideConfigValue( MainConfigNames::LanguageCode, 'en' );
|
|
$this->setUserLang( 'qqx' ); // disable i18n
|
|
|
|
$prevNext = new PrevNextNavigationRenderer( RequestContext::getMain() );
|
|
$prevNext = TestingAccessWrapper::newFromObject( $prevNext );
|
|
|
|
$html = $prevNext->buildPrevNextNavigation(
|
|
SpecialPage::getTitleFor( 'Watchlist', $subPage ),
|
|
$offset,
|
|
$limit,
|
|
[ 'x' => 25 ],
|
|
$atEnd
|
|
);
|
|
|
|
$this->assertStringStartsWith( '<div class="mw-pager-navigation-bar">(viewprevnext:', $html );
|
|
|
|
preg_match_all( '!<(a|span).*?</(a|span)>!', $html, $m, PREG_PATTERN_ORDER );
|
|
$links = $m[0];
|
|
|
|
foreach ( $links as $a ) {
|
|
if ( str_starts_with( $a, '<a' ) ) {
|
|
if ( $subPage ) {
|
|
$this->assertStringContainsString( 'Special:Watchlist/' . wfUrlencode( $subPage ), $a );
|
|
} else {
|
|
$this->assertStringContainsString( 'Special:Watchlist', $a );
|
|
$this->assertStringNotContainsString( 'Special:Watchlist/', $a );
|
|
}
|
|
$this->assertStringContainsString( 'x=25', $a );
|
|
}
|
|
}
|
|
|
|
$i = 0;
|
|
|
|
// Check 'prev' link (or placeholder)
|
|
if ( $offset > 0 ) {
|
|
$this->assertStringContainsString(
|
|
'limit=' . $limit . '&offset=' . max( 0, $offset - $limit ) . '&',
|
|
$links[ $i ]
|
|
);
|
|
$this->assertStringContainsString( 'title="(prevn-title: ' . $limit . ')"', $links[$i] );
|
|
} else {
|
|
$this->assertStringContainsString( '<span', $links[$i] );
|
|
}
|
|
$this->assertStringContainsString( 'class="mw-prevlink"', $links[$i] );
|
|
$this->assertStringContainsString( '>(prevn: ' . $limit . ')<', $links[$i] );
|
|
$i += 1;
|
|
|
|
// Check 'next' link (or placeholder)
|
|
if ( !$atEnd ) {
|
|
$this->assertStringContainsString(
|
|
'limit=' . $limit . '&offset=' . ( $offset + $limit ) . '&',
|
|
$links[ $i ]
|
|
);
|
|
$this->assertStringContainsString( 'title="(nextn-title: ' . $limit . ')"', $links[$i] );
|
|
} else {
|
|
$this->assertStringContainsString( '<span', $links[$i] );
|
|
}
|
|
$this->assertStringContainsString( 'class="mw-nextlink"', $links[$i] );
|
|
$this->assertStringContainsString( '>(nextn: ' . $limit . ')<', $links[$i] );
|
|
$i += 1;
|
|
|
|
$this->assertCount( 7, $links );
|
|
|
|
if ( $limit !== 20 ) {
|
|
$this->assertStringContainsString( 'limit=20&offset=' . $offset, $links[$i] );
|
|
$this->assertStringContainsString( 'title="(shown-title: 20)"', $links[$i] );
|
|
} else {
|
|
$this->assertStringContainsString( '<span', $links[$i] );
|
|
}
|
|
$this->assertStringContainsString( 'class="mw-numlink"', $links[$i] );
|
|
$this->assertStringContainsString( '>20<', $links[$i] );
|
|
$i += 4;
|
|
|
|
$this->assertStringContainsString( 'limit=500&offset=' . $offset, $links[$i] );
|
|
$this->assertStringContainsString( 'title="(shown-title: 500)"', $links[$i] );
|
|
$this->assertStringContainsString( 'class="mw-numlink"', $links[$i] );
|
|
$this->assertStringContainsString( '>500<', $links[$i] );
|
|
}
|
|
}
|