Reset all logging tables together
[lhc/web/wiklou.git] / tests / phpunit / includes / preferences / DefaultPreferencesFactoryTest.php
1 <?php
2
3 use MediaWiki\Auth\AuthManager;
4 use MediaWiki\MediaWikiServices;
5 use MediaWiki\Preferences\DefaultPreferencesFactory;
6 use Wikimedia\TestingAccessWrapper;
7
8 /**
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 * http://www.gnu.org/copyleft/gpl.html
23 *
24 * @file
25 */
26
27 /**
28 * @group Preferences
29 */
30 class DefaultPreferencesFactoryTest extends \MediaWikiTestCase {
31 use TestAllServiceOptionsUsed;
32
33 /** @var IContextSource */
34 protected $context;
35
36 /** @var Config */
37 protected $config;
38
39 public function setUp() {
40 parent::setUp();
41 $this->context = new RequestContext();
42 $this->context->setTitle( Title::newFromText( self::class ) );
43
44 $services = MediaWikiServices::getInstance();
45
46 $this->setMwGlobals( 'wgParser', $services->getParserFactory()->create() );
47 $this->config = $services->getMainConfig();
48 }
49
50 /**
51 * Get a basic PreferencesFactory for testing with.
52 * @return DefaultPreferencesFactory
53 */
54 protected function getPreferencesFactory() {
55 $mockNsInfo = $this->createMock( NamespaceInfo::class );
56 $mockNsInfo->method( 'getValidNamespaces' )->willReturn( [
57 NS_MAIN, NS_TALK, NS_USER, NS_USER_TALK
58 ] );
59 $mockNsInfo->expects( $this->never() )
60 ->method( $this->anythingBut( 'getValidNamespaces', '__destruct' ) );
61
62 return new DefaultPreferencesFactory(
63 new LoggedServiceOptions( self::$serviceOptionsAccessLog,
64 DefaultPreferencesFactory::$constructorOptions, $this->config ),
65 new Language(),
66 AuthManager::singleton(),
67 MediaWikiServices::getInstance()->getLinkRenderer(),
68 $mockNsInfo
69 );
70 }
71
72 /**
73 * @covers MediaWiki\Preferences\DefaultPreferencesFactory::getForm()
74 */
75 public function testGetForm() {
76 $this->setTemporaryHook( 'GetPreferences', null );
77
78 $testUser = $this->getTestUser();
79 $form = $this->getPreferencesFactory()->getForm( $testUser->getUser(), $this->context );
80 $this->assertInstanceOf( PreferencesFormOOUI::class, $form );
81 $this->assertCount( 5, $form->getPreferenceSections() );
82 }
83
84 /**
85 * CSS classes for emailauthentication preference field when there's no email.
86 * @see https://phabricator.wikimedia.org/T36302
87 * @covers MediaWiki\Preferences\DefaultPreferencesFactory::profilePreferences()
88 * @dataProvider emailAuthenticationProvider
89 */
90 public function testEmailAuthentication( $user, $cssClass ) {
91 $prefs = $this->getPreferencesFactory()->getFormDescriptor( $user, $this->context );
92 $this->assertArrayHasKey( 'cssclass', $prefs['emailauthentication'] );
93 $this->assertEquals( $cssClass, $prefs['emailauthentication']['cssclass'] );
94 }
95
96 /**
97 * @covers MediaWiki\Preferences\DefaultPreferencesFactory::renderingPreferences()
98 */
99 public function testShowRollbackConfIsHiddenForUsersWithoutRollbackRights() {
100 $userMock = $this->getMockBuilder( User::class )
101 ->disableOriginalConstructor()
102 ->getMock();
103 $userMock->method( 'isAllowed' )
104 ->willReturn( false );
105 $userMock->method( 'getEffectiveGroups' )
106 ->willReturn( [] );
107 $userMock->method( 'getGroupMemberships' )
108 ->willReturn( [] );
109 $userMock->method( 'getOptions' )
110 ->willReturn( [ 'test' => 'yes' ] );
111
112 $prefs = $this->getPreferencesFactory()->getFormDescriptor( $userMock, $this->context );
113 $this->assertArrayNotHasKey( 'showrollbackconfirmation', $prefs );
114 }
115
116 /**
117 * @covers MediaWiki\Preferences\DefaultPreferencesFactory::renderingPreferences()
118 */
119 public function testShowRollbackConfIsShownForUsersWithRollbackRights() {
120 $userMock = $this->getMockBuilder( User::class )
121 ->disableOriginalConstructor()
122 ->getMock();
123 $userMock->method( 'isAllowed' )
124 ->willReturn( true );
125 $userMock->method( 'getEffectiveGroups' )
126 ->willReturn( [] );
127 $userMock->method( 'getGroupMemberships' )
128 ->willReturn( [] );
129 $userMock->method( 'getOptions' )
130 ->willReturn( [ 'test' => 'yes' ] );
131
132 $prefs = $this->getPreferencesFactory()->getFormDescriptor( $userMock, $this->context );
133 $this->assertArrayHasKey( 'showrollbackconfirmation', $prefs );
134 $this->assertEquals(
135 'rendering/advancedrendering',
136 $prefs['showrollbackconfirmation']['section']
137 );
138 }
139
140 public function emailAuthenticationProvider() {
141 $userNoEmail = new User;
142 $userEmailUnauthed = new User;
143 $userEmailUnauthed->setEmail( 'noauth@example.org' );
144 $userEmailAuthed = new User;
145 $userEmailAuthed->setEmail( 'noauth@example.org' );
146 $userEmailAuthed->setEmailAuthenticationTimestamp( wfTimestamp() );
147 return [
148 [ $userNoEmail, 'mw-email-none' ],
149 [ $userEmailUnauthed, 'mw-email-not-authenticated' ],
150 [ $userEmailAuthed, 'mw-email-authenticated' ],
151 ];
152 }
153
154 /**
155 * Test that PreferencesFormPreSave hook has correct data:
156 * - user Object is passed
157 * - oldUserOptions contains previous user options (before save)
158 * - formData and User object have set up new properties
159 *
160 * @see https://phabricator.wikimedia.org/T169365
161 * @covers MediaWiki\Preferences\DefaultPreferencesFactory::submitForm()
162 */
163 public function testPreferencesFormPreSaveHookHasCorrectData() {
164 $oldOptions = [
165 'test' => 'abc',
166 'option' => 'old'
167 ];
168 $newOptions = [
169 'test' => 'abc',
170 'option' => 'new'
171 ];
172 $configMock = new HashConfig( [
173 'HiddenPrefs' => []
174 ] );
175 $form = $this->getMockBuilder( PreferencesFormOOUI::class )
176 ->disableOriginalConstructor()
177 ->getMock();
178
179 $userMock = $this->getMockBuilder( User::class )
180 ->disableOriginalConstructor()
181 ->getMock();
182 $userMock->method( 'getOptions' )
183 ->willReturn( $oldOptions );
184 $userMock->method( 'isAllowedAny' )
185 ->willReturn( true );
186 $userMock->method( 'isAllowed' )
187 ->willReturn( true );
188
189 $userMock->expects( $this->exactly( 2 ) )
190 ->method( 'setOption' )
191 ->withConsecutive(
192 [ $this->equalTo( 'test' ), $this->equalTo( $newOptions[ 'test' ] ) ],
193 [ $this->equalTo( 'option' ), $this->equalTo( $newOptions[ 'option' ] ) ]
194 );
195
196 $form->expects( $this->any() )
197 ->method( 'getModifiedUser' )
198 ->willReturn( $userMock );
199
200 $form->expects( $this->any() )
201 ->method( 'getContext' )
202 ->willReturn( $this->context );
203
204 $form->expects( $this->any() )
205 ->method( 'getConfig' )
206 ->willReturn( $configMock );
207
208 $this->setTemporaryHook( 'PreferencesFormPreSave',
209 function ( $formData, $form, $user, &$result, $oldUserOptions )
210 use ( $newOptions, $oldOptions, $userMock ) {
211 $this->assertSame( $userMock, $user );
212 foreach ( $newOptions as $option => $value ) {
213 $this->assertSame( $value, $formData[ $option ] );
214 }
215 foreach ( $oldOptions as $option => $value ) {
216 $this->assertSame( $value, $oldUserOptions[ $option ] );
217 }
218 $this->assertEquals( true, $result );
219 }
220 );
221
222 /** @var DefaultPreferencesFactory $factory */
223 $factory = TestingAccessWrapper::newFromObject( $this->getPreferencesFactory() );
224 $factory->saveFormData( $newOptions, $form, [] );
225 }
226
227 /**
228 * The rclimit preference should accept non-integer input and filter it to become an integer.
229 *
230 * @covers \MediaWiki\Preferences\DefaultPreferencesFactory::saveFormData
231 */
232 public function testIntvalFilter() {
233 // Test a string with leading zeros (i.e. not octal) and spaces.
234 $this->context->getRequest()->setVal( 'wprclimit', ' 0012 ' );
235 $user = new User;
236 $form = $this->getPreferencesFactory()->getForm( $user, $this->context );
237 $form->show();
238 $form->trySubmit();
239 $this->assertEquals( 12, $user->getOption( 'rclimit' ) );
240 }
241
242 /**
243 * @coversNothing
244 */
245 public function testAllServiceOptionsUsed() {
246 $this->assertAllServiceOptionsUsed( [ 'EnotifMinorEdits', 'EnotifRevealEditorAddress' ] );
247 }
248 }