When the 'watchlistunwatchlinks' preference option is enabled, this adds a '×' link to each entry of the watchlist that unwatches the page of that entry. When clicked, it changes into a '+' which can be used to re-watch the page (effectively undoing the earlier unwatch). When a page is unwatched, its entries and the entries of its associated talk page (or vice versa) become translucent and are struck through. Without JS, '×'/'+' link to action=(un)watch for the relevant page. In addition, ChangesList classes have been modified to allow a prefixer that adds a prefix to each line (used in this case to put the unwatch link) and to add HTML data attributes to reliably determine the target page of each entry. Unit tests have been updated accordingly. Bug: T2424 Change-Id: I450b2901413d7e75c11de2a446829fdbb22d31e1
189 lines
4 KiB
PHP
189 lines
4 KiB
PHP
<?php
|
|
|
|
use Wikimedia\TestingAccessWrapper;
|
|
|
|
/**
|
|
* @author Addshore
|
|
*
|
|
* @group Database
|
|
*
|
|
* @covers SpecialWatchlist
|
|
*/
|
|
class SpecialWatchlistTest extends SpecialPageTestBase {
|
|
public function setUp() {
|
|
parent::setUp();
|
|
|
|
$this->setTemporaryHook(
|
|
'ChangesListSpecialPageFilters',
|
|
null
|
|
);
|
|
|
|
$this->setTemporaryHook(
|
|
'SpecialWatchlistQuery',
|
|
null
|
|
);
|
|
|
|
$this->setTemporaryHook(
|
|
'ChangesListSpecialPageQuery',
|
|
null
|
|
);
|
|
|
|
$this->setMwGlobals(
|
|
'wgDefaultUserOptions',
|
|
[
|
|
'extendwatchlist' => 1,
|
|
'watchlistdays' => 3.0,
|
|
'watchlisthideanons' => 0,
|
|
'watchlisthidebots' => 0,
|
|
'watchlisthideliu' => 0,
|
|
'watchlisthideminor' => 0,
|
|
'watchlisthideown' => 0,
|
|
'watchlisthidepatrolled' => 0,
|
|
'watchlisthidecategorization' => 1,
|
|
'watchlistreloadautomatically' => 0,
|
|
'watchlistunwatchlinks' => 0,
|
|
]
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Returns a new instance of the special page under test.
|
|
*
|
|
* @return SpecialPage
|
|
*/
|
|
protected function newSpecialPage() {
|
|
return new SpecialWatchlist();
|
|
}
|
|
|
|
public function testNotLoggedIn_throwsException() {
|
|
$this->setExpectedException( 'UserNotLoggedIn' );
|
|
$this->executeSpecialPage();
|
|
}
|
|
|
|
public function testUserWithNoWatchedItems_displaysNoWatchlistMessage() {
|
|
$user = new TestUser( __METHOD__ );
|
|
list( $html, ) = $this->executeSpecialPage( '', null, 'qqx', $user->getUser() );
|
|
$this->assertContains( '(nowatchlist)', $html );
|
|
}
|
|
|
|
/**
|
|
* @dataProvider provideFetchOptionsFromRequest
|
|
*/
|
|
public function testFetchOptionsFromRequest( $expectedValues, $preferences, $inputParams ) {
|
|
$page = TestingAccessWrapper::newFromObject(
|
|
$this->newSpecialPage()
|
|
);
|
|
|
|
$context = new DerivativeContext( $page->getContext() );
|
|
|
|
$fauxRequest = new FauxRequest( $inputParams, /* $wasPosted= */ false );
|
|
$user = $this->getTestUser()->getUser();
|
|
|
|
foreach ( $preferences as $key => $value ) {
|
|
$user->setOption( $key, $value );
|
|
}
|
|
|
|
$context->setRequest( $fauxRequest );
|
|
$context->setUser( $user );
|
|
$page->setContext( $context );
|
|
|
|
$page->registerFilters();
|
|
$formOptions = $page->getDefaultOptions();
|
|
$page->fetchOptionsFromRequest( $formOptions );
|
|
|
|
$this->assertArrayEquals(
|
|
$expectedValues,
|
|
$formOptions->getAllValues(),
|
|
/* $ordered= */ false,
|
|
/* $named= */ true
|
|
);
|
|
}
|
|
|
|
public function provideFetchOptionsFromRequest() {
|
|
// $defaults and $allFalse are just to make the expected values below
|
|
// shorter by hiding the background.
|
|
|
|
$page = TestingAccessWrapper::newFromObject(
|
|
$this->newSpecialPage()
|
|
);
|
|
|
|
$this->setTemporaryHook(
|
|
'ChangesListSpecialPageFilters',
|
|
null
|
|
);
|
|
|
|
$page->registerFilters();
|
|
|
|
// Does not consider $preferences, just wiki's defaults
|
|
$wikiDefaults = $page->getDefaultOptions()->getAllValues();
|
|
|
|
$allFalse = $wikiDefaults;
|
|
|
|
foreach ( $allFalse as $key => &$value ) {
|
|
if ( $value === true ) {
|
|
$value = false;
|
|
}
|
|
}
|
|
|
|
// This is not exposed on the form (only in preferences) so it
|
|
// respects the preference.
|
|
$allFalse['extended'] = true;
|
|
|
|
return [
|
|
[
|
|
[
|
|
'hideminor' => true,
|
|
] + $wikiDefaults,
|
|
[],
|
|
[
|
|
'hideMinor' => 1,
|
|
],
|
|
],
|
|
|
|
[
|
|
[
|
|
// First two same as prefs
|
|
'hideminor' => true,
|
|
'hidebots' => false,
|
|
|
|
// Second two overriden
|
|
'hideanons' => false,
|
|
'hideliu' => true,
|
|
] + $wikiDefaults,
|
|
[
|
|
'watchlisthideminor' => 1,
|
|
'watchlisthidebots' => 0,
|
|
|
|
'watchlisthideanons' => 1,
|
|
'watchlisthideliu' => 0,
|
|
],
|
|
[
|
|
'hideanons' => 0,
|
|
'hideliu' => 1,
|
|
],
|
|
],
|
|
|
|
// Defaults/preferences for form elements are entirely ignored for
|
|
// action=submit and omitted elements become false
|
|
[
|
|
[
|
|
'hideminor' => false,
|
|
'hidebots' => true,
|
|
'hideanons' => false,
|
|
'hideliu' => true,
|
|
] + $allFalse,
|
|
[
|
|
'watchlisthideminor' => 0,
|
|
'watchlisthidebots' => 1,
|
|
'watchlisthideanons' => 1,
|
|
'watchlisthideliu' => 0,
|
|
],
|
|
[
|
|
'hidebots' => 1,
|
|
'hideliu' => 1,
|
|
'action' => 'submit',
|
|
],
|
|
],
|
|
];
|
|
}
|
|
}
|