From 5965f6fc0a08a04c8dda3da3ae562c983bcc0079 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Szab=C3=B3?= Date: Mon, 6 Jan 2025 15:18:27 +0100 Subject: specials: Support temporary account filtering on Special:BlockList Why: - Special:BlockList currently supports excluding blocks targeting IP addresses or registered users, but not temporary accounts. - To preserve feature parity when temporary accounts are enabled, it should also allow excluding blocks that are targeting temporary accounts. What: - Add a new filtering option to exclude blocks targeting temporary accounts on Special:BlockList. This is only displayed if temporary accounts are a known concept on the local wiki. - Have the existing "Hide account blocks" checkbox exclude named users only if temporary accounts are a known concept on the local wiki, and show a different label if so. Bug: T380266 Change-Id: I63ada264c0da406c728ac54fcbe0b6621f1e9250 --- .../includes/specials/SpecialBlockListTest.php | 172 +++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 tests/phpunit/integration/includes/specials/SpecialBlockListTest.php (limited to 'tests/phpunit/integration/includes') diff --git a/tests/phpunit/integration/includes/specials/SpecialBlockListTest.php b/tests/phpunit/integration/includes/specials/SpecialBlockListTest.php new file mode 100644 index 000000000000..f597bbd01681 --- /dev/null +++ b/tests/phpunit/integration/includes/specials/SpecialBlockListTest.php @@ -0,0 +1,172 @@ +getServiceContainer()->getSpecialPageFactory()->getPage( 'BlockList' ); + } + + private function makeTestBlock( UserIdentity $target ): void { + $status = $this->getServiceContainer() + ->getBlockUserFactory() + ->newBlockUser( + $target, + $this->getTestSysop()->getAuthority(), + 'infinity' + ) + ->placeBlock(); + + $this->assertStatusGood( $status, "Failed to place block for {$target->getName()}" ); + } + + public function addDBDataOnce() { + $this->enableAutoCreateTempUser(); + + $req = new FauxRequest(); + $tempUser = $this->getServiceContainer() + ->getTempUserCreator() + ->create( null, $req ) + ->getUser(); + + $namedUser = $this->getTestUser()->getUser(); + + self::$blockedTempUserName = $tempUser->getName(); + self::$blockedUserName = $namedUser->getName(); + + $this->makeTestBlock( $tempUser ); + + $this->makeTestBlock( $this->getTestUser()->getUser() ); + + $this->makeTestBlock( + $this->getServiceContainer()->getUserFactory()->newAnonymous( self::TEST_BLOCKED_IP ) + ); + } + + /** + * @dataProvider provideTargetTypes + */ + public function testShouldAllowFilteringBlocksByTargetType( + ?string $targetType, + callable $expectedBlockTargetNamesProvider, + bool $tempAccountsKnown = true + ): void { + $this->disableAutoCreateTempUser( [ + 'known' => $tempAccountsKnown, + ] ); + + $queryParams = $targetType ? [ 'wpOptions' => [ $targetType ] ] : []; + $req = new FauxRequest( $queryParams ); + + [ $html ] = $this->executeSpecialPage( '', $req ); + + $doc = ( new HtmlFormatter( HtmlFormatter::wrapHTML( $html ) ) )->getDoc(); + $targetUserNames = []; + foreach ( DOMCompat::querySelectorAll( $doc, '.TablePager_col_target > .mw-userlink' ) as $targetUser ) { + $targetUserNames[] = $targetUser->textContent; + } + + $this->assertSame( + $expectedBlockTargetNamesProvider(), + $targetUserNames + ); + } + + public static function provideTargetTypes(): iterable { + yield 'no target type, temp accounts known' => [ + null, + static fn () => [ self::TEST_BLOCKED_IP, self::$blockedUserName, self::$blockedTempUserName ] + ]; + yield 'named user blocks excluded, temp accounts known' => [ + 'userblocks', + static fn () => [ self::TEST_BLOCKED_IP, self::$blockedTempUserName ] + ]; + yield 'IP blocks excluded, temp accounts known' => [ + 'addressblocks', + static fn () => [ self::$blockedUserName, self::$blockedTempUserName ] + ]; + yield 'temp user blocks excluded, temp accounts known' => [ + 'tempuserblocks', + static fn () => [ self::TEST_BLOCKED_IP, self::$blockedUserName ] + ]; + + yield 'no target type, temp accounts not known' => [ + null, + static fn () => [ self::TEST_BLOCKED_IP, self::$blockedUserName, self::$blockedTempUserName ], + false + ]; + yield 'user blocks excluded, temp accounts not known' => [ + 'userblocks', + static fn () => [ self::TEST_BLOCKED_IP ], + false + ]; + yield 'IP blocks excluded, temp accounts not known' => [ + 'addressblocks', + static fn () => [ self::$blockedUserName, self::$blockedTempUserName ], + false + ]; + } + + public function testShouldAdaptFilterOptionsWhenTemporaryAccountsAreKnown(): void { + $this->disableAutoCreateTempUser( [ + 'known' => true, + ] ); + + [ $html ] = $this->executeSpecialPage(); + + $doc = ( new HtmlFormatter( HtmlFormatter::wrapHTML( $html ) ) )->getDoc(); + + $accountBlocksFilter = DOMCompat::querySelector( $doc, 'input[name="wpOptions[]"][value="userblocks"]' ); + $accountBlocksLabel = DOMCompat::querySelector( + $doc, "label[for=\"{$accountBlocksFilter->getAttribute( 'id' )}\"]" + ); + + $this->assertSame( + '(blocklist-nameduserblocks)', + $accountBlocksLabel->textContent + ); + $this->assertNotNull( + DOMCompat::querySelector( $doc, 'input[name="wpOptions[]"][value="tempuserblocks"]' ), + 'Temporary accounts filter checkbox should be present' + ); + } + + public function testShouldNotShowTemporaryAccountsFilterCheckboxWhenTemporaryAccountsAreNotKnown(): void { + $this->disableAutoCreateTempUser(); + + [ $html ] = $this->executeSpecialPage(); + + $doc = ( new HtmlFormatter( HtmlFormatter::wrapHTML( $html ) ) )->getDoc(); + + $accountBlocksFilter = DOMCompat::querySelector( $doc, 'input[name="wpOptions[]"][value="userblocks"]' ); + $accountBlocksLabel = DOMCompat::querySelector( + $doc, "label[for=\"{$accountBlocksFilter->getAttribute( 'id' )}\"]" + ); + + $this->assertSame( + '(blocklist-userblocks)', + $accountBlocksLabel->textContent + ); + $this->assertNull( + DOMCompat::querySelector( $doc, 'input[name="wpOptions[]"][value="tempuserblocks"]' ), + 'Temporary accounts filter checkbox should not be present' + ); + } +} -- cgit v1.2.3