MediaWiki  1.29.1
ApiOptionsTest.php
Go to the documentation of this file.
1 <?php
2 
11 
13  private $mUserMock;
15  private $mTested;
16  private $mSession;
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 
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 
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 }
ApiMain
This is the main API class, used for both external and internal processing.
Definition: ApiMain.php:45
$context
error also a ContextSource you ll probably need to make sure the header is varied on and they can depend only on the ResourceLoaderContext $context
Definition: hooks.txt:2612
FauxRequest
WebRequest clone which takes values from a provided array.
Definition: FauxRequest.php:33
Title\newFromText
static newFromText( $text, $defaultNamespace=NS_MAIN)
Create a new Title from text, such as what one would find in a link.
Definition: Title.php:265
ApiUsageException
Exception used to abort API execution with an error.
Definition: ApiUsageException.php:98
$request
error also a ContextSource you ll probably need to make sure the header is varied on $request
Definition: hooks.txt:2612
ApiOptionsTest\testReset
testReset()
Definition: ApiOptionsTest.php:206
MediaWikiTestCase\mergeMwGlobalArrayValue
mergeMwGlobalArrayValue( $name, $values)
Merges the given values into a MW global array variable.
Definition: MediaWikiTestCase.php:766
ApiOptionsTest\testSpecialOption
testSpecialOption()
Definition: ApiOptionsTest.php:380
$user
please add to it if you re going to add events to the MediaWiki code where normally authentication against an external auth plugin would be creating a account $user
Definition: hooks.txt:246
ApiOptionsTest\hookGetPreferences
hookGetPreferences( $user, &$preferences)
Definition: ApiOptionsTest.php:62
ApiOptionsTest\testResetKinds
testResetKinds()
Definition: ApiOptionsTest.php:224
ApiOptionsTest\setUp
setUp()
Definition: ApiOptionsTest.php:22
ApiOptionsTest\executeQuery
executeQuery( $request)
Definition: ApiOptionsTest.php:141
ApiOptionsTest\testUnknownOption
testUnknownOption()
Definition: ApiOptionsTest.php:403
ApiOptionsTest\getSampleRequest
getSampleRequest( $custom=[])
Definition: ApiOptionsTest.php:130
php
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
Definition: injection.txt:35
ApiOptionsTest\testNoChanges
testNoChanges()
Definition: ApiOptionsTest.php:185
DerivativeContext
An IContextSource implementation which will inherit context from another source but allow individual ...
Definition: DerivativeContext.php:31
ApiOptionsTest\$mTested
ApiOptions $mTested
Definition: ApiOptionsTest.php:15
ApiOptionsTest\$mContext
DerivativeContext $mContext
Definition: ApiOptionsTest.php:18
ApiOptionsTest\testUserjsOption
testUserjsOption()
Definition: ApiOptionsTest.php:426
ApiOptionsTest\$mSession
$mSession
Definition: ApiOptionsTest.php:16
ApiOptionsTest\testMultiSelect
testMultiSelect()
Definition: ApiOptionsTest.php:347
RequestContext
Group all the pieces relevant to the context of a request into one instance.
Definition: RequestContext.php:33
ApiOptionsTest\getOptionKinds
getOptionKinds(IContextSource $context, $options=null)
Definition: ApiOptionsTest.php:98
ApiOptions
API module that facilitates the changing of user's preferences.
Definition: ApiOptions.php:33
any
they could even be mouse clicks or menu items whatever suits your program You should also get your if any
Definition: COPYING.txt:326
$e
div flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException' returning false will NOT prevent logging $e
Definition: hooks.txt:2122
$value
$value
Definition: styleTest.css.php:45
ApiOptionsTest\testChange
testChange()
Definition: ApiOptionsTest.php:277
ApiOptionsTest\testNoToken
testNoToken()
ApiUsageException.
Definition: ApiOptionsTest.php:151
ApiOptionsTest\$mUserMock
PHPUnit_Framework_MockObject_MockObject $mUserMock
Definition: ApiOptionsTest.php:13
ApiOptionsTest\testOptionWithValue
testOptionWithValue()
Definition: ApiOptionsTest.php:242
MediaWikiLangTestCase
Base class that store and restore the Language objects.
Definition: MediaWikiLangTestCase.php:6
$response
this hook is for auditing only $response
Definition: hooks.txt:783
IContextSource
Interface for objects which can provide a MediaWiki context on request.
Definition: IContextSource.php:55
$args
if( $line===false) $args
Definition: cdb.php:63
ApiOptionsTest\testNoOptionname
testNoOptionname()
Definition: ApiOptionsTest.php:173
ApiTestCase\apiExceptionHasCode
static apiExceptionHasCode(ApiUsageException $ex, $code)
Definition: ApiTestCase.php:212
as
This document is intended to provide useful advice for parties seeking to redistribute MediaWiki to end users It s targeted particularly at maintainers for Linux since it s been observed that distribution packages of MediaWiki often break We ve consistently had to recommend that users seeking support use official tarballs instead of their distribution s and this often solves whatever problem the user is having It would be nice if this could such as
Definition: distributors.txt:9
ApiOptionsTest\testResetChangeOption
testResetChangeOption()
Definition: ApiOptionsTest.php:314
ApiOptionsTest
API Database medium.
Definition: ApiOptionsTest.php:10
$options
this hook is for auditing only RecentChangesLinked and Watchlist RecentChangesLinked and Watchlist Do not use this to implement individual filters if they are compatible with the ChangesListFilter and ChangesListFilterGroup structure use sub classes of those in conjunction with the ChangesListSpecialPageStructuredFilters hook This hook can be used to implement filters that do not implement that or custom behavior that is not an individual filter e g Watchlist and Watchlist you will want to construct new ChangesListBooleanFilter or ChangesListStringOptionsFilter objects When constructing you specify which group they belong to You can reuse existing or create your you must register them with $special registerFilterGroup removed from all revisions and log entries to which it was applied This gives extensions a chance to take it off their books as the deletion has already been partly carried out by this point or something similar the user will be unable to create the tag set and then return false from the hook function Ensure you consume the ChangeTagAfterDelete hook to carry out custom deletion actions as context called by AbstractContent::getParserOutput May be used to override the normal model specific rendering of page content as context as context $options
Definition: hooks.txt:1049
ApiOptionsTest\$Success
static $Success
Definition: ApiOptionsTest.php:20
ApiOptionsTest\testOptionResetValue
testOptionResetValue()
Definition: ApiOptionsTest.php:260
ApiOptionsTest\testAnon
testAnon()
Definition: ApiOptionsTest.php:157