3 namespace MediaWiki\Tests\Maintenance
;
5 use MediaWiki\MainConfigNames
;
6 use MediaWiki\Revision\SlotRecord
;
7 use MediaWiki\Title\Title
;
8 use MediaWiki\User\CentralId\CentralIdLookup
;
16 class RenameUserTest
extends MaintenanceBaseTestCase
{
17 public function getMaintenanceClass() {
18 return RenameUser
::class;
21 /** @dataProvider provideExecuteForFatalError */
22 public function testExecuteForFatalError( $oldName, $newName, $options, $expectedOutputRegex ) {
23 $this->maintenance
->setArg( 'old-name', $oldName );
24 $this->maintenance
->setArg( 'new-name', $newName );
25 foreach ( $options as $name => $value ) {
26 $this->maintenance
->setOption( $name, $value );
28 $this->expectCallToFatalError();
29 $this->expectOutputRegex( $expectedOutputRegex );
30 $this->maintenance
->execute();
33 public static function provideExecuteForFatalError() {
35 'Invalid old name' => [ 'Template:Testing#test', 'abc', [], '/The specified old username is invalid/' ],
36 'Non-existing old name' => [ 'Non-existing-test-user123', 'abc', [], '/The user does not exist/' ],
40 /** @dataProvider provideExecuteForFatalErrorWithValidOldName */
41 public function testExecuteForFatalErrorWithValidOldName( $newName, $options, $expectedOutputRegex ) {
42 $oldName = $this->getMutableTestUser()->getUserIdentity()->getName();
43 $this->testExecuteForFatalError( $oldName, $newName, $options, $expectedOutputRegex );
44 // Check that the old username has not been renamed, as the script should have failed to perform the rename.
45 $this->newSelectQueryBuilder()
46 ->select( 'COUNT(*)' )
48 ->where( [ 'actor_name' => $oldName ] )
49 ->assertFieldValue( 1 );
52 public static function provideExecuteForFatalErrorWithValidOldName() {
54 'Invalid new name' => [ 'Template:Test#testing', [], '/The specified new username is invalid/' ],
55 'Performer does not exist' => [
56 'Abc', [ 'performer' => 'Non-existing-test-user' ], '/Performer does not exist/',
61 public function testExecuteWhenNewNameIsAlreadyTaken() {
62 $newName = $this->getMutableTestUser()->getUserIdentity();
63 $this->testExecuteForFatalErrorWithValidOldName( $newName, [], '/New username must be free/' );
66 public function testExecuteWhenUserIsAttachedToNonLocalProvider() {
67 // Set the CentralIdLookup as a mock CentralIdLookup which always returns true from ::isAttached.
68 $this->overrideConfigValue( MainConfigNames
::CentralIdLookupProviders
, [
69 'renameUserTestProvider' => [
70 'factory' => function () {
71 $mockCentralIdLookup = $this->createMock( CentralIdLookup
::class );
72 $mockCentralIdLookup->method( 'isAttached' )
74 return $mockCentralIdLookup;
78 $this->overrideConfigValue( MainConfigNames
::CentralIdLookupProvider
, 'renameUserTestProvider' );
79 // Run the maintenance script and expect an error.
80 $this->testExecuteForFatalErrorWithValidOldName(
81 $this->getTestUser()->getUserIdentity()->getName(), [], '/The user is globally attached/'
85 public function testExecuteWithoutPageMoves() {
86 // Get one testing user, and create a user talk and user page for that user
87 $testUser = $this->getMutableTestUser( [], 'Abc' );
88 $testUser->getUser()->addToDatabase();
89 $userPageBeforeRename = $testUser->getUser()->getUserPage();
90 $this->editPage( $userPageBeforeRename, 'user testing1234' );
91 $userTalkPageBeforeRename = $userPageBeforeRename->getTalkPageIfDefined();
92 $this->editPage( $userTalkPageBeforeRename, 'usertalk testing1234' );
93 $testUserIdentity = $testUser->getUserIdentity();
94 // Run the maintenance script
95 $this->maintenance
->setArg( 'old-name', $testUserIdentity->getName() );
96 $this->maintenance
->setArg( 'new-name', 'Abcdef-user' );
97 $this->maintenance
->setOption( 'skip-page-moves', true );
98 $this->maintenance
->execute();
99 // Check that the output of the script is as expected
100 $this->expectOutputRegex(
101 '/' . preg_quote( $testUserIdentity->getName(), '/' ) . ' was successfully renamed to Abcdef-user/'
103 // Check that the rename actually occurred
104 $this->newSelectQueryBuilder()
105 ->select( 'user_name' )
107 ->where( [ 'user_id' => $testUserIdentity->getId() ] )
108 ->assertFieldValue( 'Abcdef-user' );
109 // Check that the user page and user talk page were not moved.
110 $userPageContent = $this->getServiceContainer()->getRevisionLookup()
111 ->getRevisionByTitle( $userPageBeforeRename )
112 ->getContent( SlotRecord
::MAIN
)->getWikitextForTransclusion();
113 $this->assertSame( 'user testing1234', $userPageContent );
114 $userTalkPageContent = $this->getServiceContainer()->getRevisionLookup()
115 ->getRevisionByTitle( $userTalkPageBeforeRename )
116 ->getContent( SlotRecord
::MAIN
)->getWikitextForTransclusion();
117 $this->assertSame( 'usertalk testing1234', $userTalkPageContent );
118 $this->assertFalse( Title
::newFromText( 'abcdef-user', NS_USER
)->exists() );
119 $this->assertFalse( Title
::newFromText( 'abcdef-user', NS_USER_TALK
)->exists() );
122 public function testExecuteWithPageMoves() {
123 // Get one testing user, and create a user talk and user page for that user
124 $testUser = $this->getMutableTestUser( [], 'Abc' );
125 $testUser->getUser()->addToDatabase();
126 $this->editPage( $testUser->getUser()->getUserPage(), 'user testing1234' );
127 $userTalkPageBeforeRename = $testUser->getUser()->getUserPage()->getTalkPageIfDefined();
128 $this->editPage( $userTalkPageBeforeRename, 'usertalk testing1234' );
129 $this->editPage( Title
::newFromText( $userTalkPageBeforeRename->getPrefixedText() . '/test' ), 'usertalk subpage' );
130 $testUserIdentity = $testUser->getUserIdentity();
131 // Run the maintenance script
132 $this->maintenance
->setArg( 'old-name', $testUserIdentity->getName() );
133 $this->maintenance
->setArg( 'new-name', 'Abcdef-user' );
134 $this->maintenance
->execute();
135 // Check that the output of the script is as expected
136 $this->expectOutputRegex(
137 '/' . preg_quote( $testUserIdentity->getName(), '/' ) . ' was successfully renamed to Abcdef-user/'
139 // Check that the rename actually occurred
140 $this->newSelectQueryBuilder()
141 ->select( 'user_name' )
143 ->where( [ 'user_id' => $testUserIdentity->getId() ] )
144 ->assertFieldValue( 'Abcdef-user' );
145 // Check that the user page, user talk page, and user talk subpage were actually moved.
146 $expectedPageContent = [
147 'user testing1234' => Title
::newFromText( 'abcdef-user', NS_USER
),
148 'usertalk testing1234' => Title
::newFromText( 'abcdef-user', NS_USER_TALK
),
149 'usertalk subpage' => Title
::newFromText( 'abcdef-user/test', NS_USER_TALK
),
151 foreach ( $expectedPageContent as $expectedContent => $title ) {
152 $userPageContent = $this->getServiceContainer()->getRevisionLookup()
153 ->getRevisionByTitle( $title )
154 ->getContent( SlotRecord
::MAIN
)->getWikitextForTransclusion();
155 $this->assertSame( $expectedContent, $userPageContent );