]> scripts.mit.edu Git - autoinstallsdev/mediawiki.git/blob - tests/phpunit/includes/api/ApiOptionsTest.php
MediaWiki 1.30.2
[autoinstallsdev/mediawiki.git] / tests / phpunit / includes / api / ApiOptionsTest.php
1 <?php
2
3 /**
4  * @group API
5  * @group Database
6  * @group medium
7  *
8  * @covers ApiOptions
9  */
10 class ApiOptionsTest extends MediaWikiLangTestCase {
11
12         /** @var PHPUnit_Framework_MockObject_MockObject */
13         private $mUserMock;
14         /** @var ApiOptions */
15         private $mTested;
16         private $mSession;
17         /** @var DerivativeContext */
18         private $mContext;
19
20         private static $Success = [ 'options' => 'success' ];
21
22         protected function setUp() {
23                 parent::setUp();
24
25                 $this->mUserMock = $this->getMockBuilder( 'User' )
26                         ->disableOriginalConstructor()
27                         ->getMock();
28
29                 // Set up groups and rights
30                 $this->mUserMock->expects( $this->any() )
31                         ->method( 'getEffectiveGroups' )->will( $this->returnValue( [ '*', 'user' ] ) );
32                 $this->mUserMock->expects( $this->any() )
33                         ->method( 'isAllowedAny' )->will( $this->returnValue( true ) );
34
35                 // Set up callback for User::getOptionKinds
36                 $this->mUserMock->expects( $this->any() )
37                         ->method( 'getOptionKinds' )->will( $this->returnCallback( [ $this, 'getOptionKinds' ] ) );
38
39                 // No actual DB data
40                 $this->mUserMock->expects( $this->any() )
41                         ->method( 'getInstanceForUpdate' )->will( $this->returnValue( $this->mUserMock ) );
42
43                 // Create a new context
44                 $this->mContext = new DerivativeContext( new RequestContext() );
45                 $this->mContext->getContext()->setTitle( Title::newFromText( 'Test' ) );
46                 $this->mContext->setUser( $this->mUserMock );
47
48                 $main = new ApiMain( $this->mContext );
49
50                 // Empty session
51                 $this->mSession = [];
52
53                 $this->mTested = new ApiOptions( $main, 'options' );
54
55                 $this->mergeMwGlobalArrayValue( 'wgHooks', [
56                         'GetPreferences' => [
57                                 [ $this, 'hookGetPreferences' ]
58                         ]
59                 ] );
60         }
61
62         public function hookGetPreferences( $user, &$preferences ) {
63                 $preferences = [];
64
65                 foreach ( [ 'name', 'willBeNull', 'willBeEmpty', 'willBeHappy' ] as $k ) {
66                         $preferences[$k] = [
67                                 'type' => 'text',
68                                 'section' => 'test',
69                                 'label' => '&#160;',
70                         ];
71                 }
72
73                 $preferences['testmultiselect'] = [
74                         'type' => 'multiselect',
75                         'options' => [
76                                 'Test' => [
77                                         '<span dir="auto">Some HTML here for option 1</span>' => 'opt1',
78                                         '<span dir="auto">Some HTML here for option 2</span>' => 'opt2',
79                                         '<span dir="auto">Some HTML here for option 3</span>' => 'opt3',
80                                         '<span dir="auto">Some HTML here for option 4</span>' => 'opt4',
81                                 ],
82                         ],
83                         'section' => 'test',
84                         'label' => '&#160;',
85                         'prefix' => 'testmultiselect-',
86                         'default' => [],
87                 ];
88
89                 return true;
90         }
91
92         /**
93          * @param IContextSource $context
94          * @param array|null $options
95          *
96          * @return array
97          */
98         public function getOptionKinds( IContextSource $context, $options = null ) {
99                 // Match with above.
100                 $kinds = [
101                         'name' => 'registered',
102                         'willBeNull' => 'registered',
103                         'willBeEmpty' => 'registered',
104                         'willBeHappy' => 'registered',
105                         'testmultiselect-opt1' => 'registered-multiselect',
106                         'testmultiselect-opt2' => 'registered-multiselect',
107                         'testmultiselect-opt3' => 'registered-multiselect',
108                         'testmultiselect-opt4' => 'registered-multiselect',
109                         'special' => 'special',
110                 ];
111
112                 if ( $options === null ) {
113                         return $kinds;
114                 }
115
116                 $mapping = [];
117                 foreach ( $options as $key => $value ) {
118                         if ( isset( $kinds[$key] ) ) {
119                                 $mapping[$key] = $kinds[$key];
120                         } elseif ( substr( $key, 0, 7 ) === 'userjs-' ) {
121                                 $mapping[$key] = 'userjs';
122                         } else {
123                                 $mapping[$key] = 'unused';
124                         }
125                 }
126
127                 return $mapping;
128         }
129
130         private function getSampleRequest( $custom = [] ) {
131                 $request = [
132                         'token' => '123ABC',
133                         'change' => null,
134                         'optionname' => null,
135                         'optionvalue' => null,
136                 ];
137
138                 return array_merge( $request, $custom );
139         }
140
141         private function executeQuery( $request ) {
142                 $this->mContext->setRequest( new FauxRequest( $request, true, $this->mSession ) );
143                 $this->mTested->execute();
144
145                 return $this->mTested->getResult()->getResultData( null, [ 'Strip' => 'all' ] );
146         }
147
148         /**
149          * @expectedException ApiUsageException
150          */
151         public function testNoToken() {
152                 $request = $this->getSampleRequest( [ 'token' => null ] );
153
154                 $this->executeQuery( $request );
155         }
156
157         public function testAnon() {
158                 $this->mUserMock->expects( $this->once() )
159                         ->method( 'isAnon' )
160                         ->will( $this->returnValue( true ) );
161
162                 try {
163                         $request = $this->getSampleRequest();
164
165                         $this->executeQuery( $request );
166                 } catch ( ApiUsageException $e ) {
167                         $this->assertTrue( ApiTestCase::apiExceptionHasCode( $e, 'notloggedin' ) );
168                         return;
169                 }
170                 $this->fail( "ApiUsageException was not thrown" );
171         }
172
173         public function testNoOptionname() {
174                 try {
175                         $request = $this->getSampleRequest( [ 'optionvalue' => '1' ] );
176
177                         $this->executeQuery( $request );
178                 } catch ( ApiUsageException $e ) {
179                         $this->assertTrue( ApiTestCase::apiExceptionHasCode( $e, 'nooptionname' ) );
180                         return;
181                 }
182                 $this->fail( "ApiUsageException was not thrown" );
183         }
184
185         public function testNoChanges() {
186                 $this->mUserMock->expects( $this->never() )
187                         ->method( 'resetOptions' );
188
189                 $this->mUserMock->expects( $this->never() )
190                         ->method( 'setOption' );
191
192                 $this->mUserMock->expects( $this->never() )
193                         ->method( 'saveSettings' );
194
195                 try {
196                         $request = $this->getSampleRequest();
197
198                         $this->executeQuery( $request );
199                 } catch ( ApiUsageException $e ) {
200                         $this->assertTrue( ApiTestCase::apiExceptionHasCode( $e, 'nochanges' ) );
201                         return;
202                 }
203                 $this->fail( "ApiUsageException was not thrown" );
204         }
205
206         public function testReset() {
207                 $this->mUserMock->expects( $this->once() )
208                         ->method( 'resetOptions' )
209                         ->with( $this->equalTo( [ 'all' ] ) );
210
211                 $this->mUserMock->expects( $this->never() )
212                         ->method( 'setOption' );
213
214                 $this->mUserMock->expects( $this->once() )
215                         ->method( 'saveSettings' );
216
217                 $request = $this->getSampleRequest( [ 'reset' => '' ] );
218
219                 $response = $this->executeQuery( $request );
220
221                 $this->assertEquals( self::$Success, $response );
222         }
223
224         public function testResetKinds() {
225                 $this->mUserMock->expects( $this->once() )
226                         ->method( 'resetOptions' )
227                         ->with( $this->equalTo( [ 'registered' ] ) );
228
229                 $this->mUserMock->expects( $this->never() )
230                         ->method( 'setOption' );
231
232                 $this->mUserMock->expects( $this->once() )
233                         ->method( 'saveSettings' );
234
235                 $request = $this->getSampleRequest( [ 'reset' => '', 'resetkinds' => 'registered' ] );
236
237                 $response = $this->executeQuery( $request );
238
239                 $this->assertEquals( self::$Success, $response );
240         }
241
242         public function testOptionWithValue() {
243                 $this->mUserMock->expects( $this->never() )
244                         ->method( 'resetOptions' );
245
246                 $this->mUserMock->expects( $this->once() )
247                         ->method( 'setOption' )
248                         ->with( $this->equalTo( 'name' ), $this->equalTo( 'value' ) );
249
250                 $this->mUserMock->expects( $this->once() )
251                         ->method( 'saveSettings' );
252
253                 $request = $this->getSampleRequest( [ 'optionname' => 'name', 'optionvalue' => 'value' ] );
254
255                 $response = $this->executeQuery( $request );
256
257                 $this->assertEquals( self::$Success, $response );
258         }
259
260         public function testOptionResetValue() {
261                 $this->mUserMock->expects( $this->never() )
262                         ->method( 'resetOptions' );
263
264                 $this->mUserMock->expects( $this->once() )
265                         ->method( 'setOption' )
266                         ->with( $this->equalTo( 'name' ), $this->identicalTo( null ) );
267
268                 $this->mUserMock->expects( $this->once() )
269                         ->method( 'saveSettings' );
270
271                 $request = $this->getSampleRequest( [ 'optionname' => 'name' ] );
272                 $response = $this->executeQuery( $request );
273
274                 $this->assertEquals( self::$Success, $response );
275         }
276
277         public function testChange() {
278                 $this->mUserMock->expects( $this->never() )
279                         ->method( 'resetOptions' );
280
281                 $this->mUserMock->expects( $this->at( 2 ) )
282                         ->method( 'getOptions' );
283
284                 $this->mUserMock->expects( $this->at( 5 ) )
285                         ->method( 'setOption' )
286                         ->with( $this->equalTo( 'willBeNull' ), $this->identicalTo( null ) );
287
288                 $this->mUserMock->expects( $this->at( 6 ) )
289                         ->method( 'getOptions' );
290
291                 $this->mUserMock->expects( $this->at( 7 ) )
292                         ->method( 'setOption' )
293                         ->with( $this->equalTo( 'willBeEmpty' ), $this->equalTo( '' ) );
294
295                 $this->mUserMock->expects( $this->at( 8 ) )
296                         ->method( 'getOptions' );
297
298                 $this->mUserMock->expects( $this->at( 9 ) )
299                         ->method( 'setOption' )
300                         ->with( $this->equalTo( 'willBeHappy' ), $this->equalTo( 'Happy' ) );
301
302                 $this->mUserMock->expects( $this->once() )
303                         ->method( 'saveSettings' );
304
305                 $request = $this->getSampleRequest( [
306                         'change' => 'willBeNull|willBeEmpty=|willBeHappy=Happy'
307                 ] );
308
309                 $response = $this->executeQuery( $request );
310
311                 $this->assertEquals( self::$Success, $response );
312         }
313
314         public function testResetChangeOption() {
315                 $this->mUserMock->expects( $this->once() )
316                         ->method( 'resetOptions' );
317
318                 $this->mUserMock->expects( $this->at( 5 ) )
319                         ->method( 'getOptions' );
320
321                 $this->mUserMock->expects( $this->at( 6 ) )
322                         ->method( 'setOption' )
323                         ->with( $this->equalTo( 'willBeHappy' ), $this->equalTo( 'Happy' ) );
324
325                 $this->mUserMock->expects( $this->at( 7 ) )
326                         ->method( 'getOptions' );
327
328                 $this->mUserMock->expects( $this->at( 8 ) )
329                         ->method( 'setOption' )
330                         ->with( $this->equalTo( 'name' ), $this->equalTo( 'value' ) );
331
332                 $this->mUserMock->expects( $this->once() )
333                         ->method( 'saveSettings' );
334
335                 $args = [
336                         'reset' => '',
337                         'change' => 'willBeHappy=Happy',
338                         'optionname' => 'name',
339                         'optionvalue' => 'value'
340                 ];
341
342                 $response = $this->executeQuery( $this->getSampleRequest( $args ) );
343
344                 $this->assertEquals( self::$Success, $response );
345         }
346
347         public function testMultiSelect() {
348                 $this->mUserMock->expects( $this->never() )
349                         ->method( 'resetOptions' );
350
351                 $this->mUserMock->expects( $this->at( 4 ) )
352                         ->method( 'setOption' )
353                         ->with( $this->equalTo( 'testmultiselect-opt1' ), $this->identicalTo( true ) );
354
355                 $this->mUserMock->expects( $this->at( 5 ) )
356                         ->method( 'setOption' )
357                         ->with( $this->equalTo( 'testmultiselect-opt2' ), $this->identicalTo( null ) );
358
359                 $this->mUserMock->expects( $this->at( 6 ) )
360                         ->method( 'setOption' )
361                         ->with( $this->equalTo( 'testmultiselect-opt3' ), $this->identicalTo( false ) );
362
363                 $this->mUserMock->expects( $this->at( 7 ) )
364                         ->method( 'setOption' )
365                         ->with( $this->equalTo( 'testmultiselect-opt4' ), $this->identicalTo( false ) );
366
367                 $this->mUserMock->expects( $this->once() )
368                         ->method( 'saveSettings' );
369
370                 $request = $this->getSampleRequest( [
371                         'change' => 'testmultiselect-opt1=1|testmultiselect-opt2|'
372                                 . 'testmultiselect-opt3=|testmultiselect-opt4=0'
373                 ] );
374
375                 $response = $this->executeQuery( $request );
376
377                 $this->assertEquals( self::$Success, $response );
378         }
379
380         public function testSpecialOption() {
381                 $this->mUserMock->expects( $this->never() )
382                         ->method( 'resetOptions' );
383
384                 $this->mUserMock->expects( $this->never() )
385                         ->method( 'saveSettings' );
386
387                 $request = $this->getSampleRequest( [
388                         'change' => 'special=1'
389                 ] );
390
391                 $response = $this->executeQuery( $request );
392
393                 $this->assertEquals( [
394                         'options' => 'success',
395                         'warnings' => [
396                                 'options' => [
397                                         'warnings' => "Validation error for \"special\": cannot be set by this module."
398                                 ]
399                         ]
400                 ], $response );
401         }
402
403         public function testUnknownOption() {
404                 $this->mUserMock->expects( $this->never() )
405                         ->method( 'resetOptions' );
406
407                 $this->mUserMock->expects( $this->never() )
408                         ->method( 'saveSettings' );
409
410                 $request = $this->getSampleRequest( [
411                         'change' => 'unknownOption=1'
412                 ] );
413
414                 $response = $this->executeQuery( $request );
415
416                 $this->assertEquals( [
417                         'options' => 'success',
418                         'warnings' => [
419                                 'options' => [
420                                         'warnings' => "Validation error for \"unknownOption\": not a valid preference."
421                                 ]
422                         ]
423                 ], $response );
424         }
425
426         public function testUserjsOption() {
427                 $this->mUserMock->expects( $this->never() )
428                         ->method( 'resetOptions' );
429
430                 $this->mUserMock->expects( $this->once() )
431                         ->method( 'setOption' )
432                         ->with( $this->equalTo( 'userjs-option' ), $this->equalTo( '1' ) );
433
434                 $this->mUserMock->expects( $this->once() )
435                         ->method( 'saveSettings' );
436
437                 $request = $this->getSampleRequest( [
438                         'change' => 'userjs-option=1'
439                 ] );
440
441                 $response = $this->executeQuery( $request );
442
443                 $this->assertEquals( self::$Success, $response );
444         }
445 }