MediaWiki
REL1_24
|
00001 <?php 00002 00010 class ApiOptionsTest extends MediaWikiLangTestCase { 00011 00013 private $mUserMock; 00015 private $mTested; 00016 private $mSession; 00018 private $mContext; 00019 00020 private $mOldGetPreferencesHooks; 00021 00022 private static $Success = array( 'options' => 'success' ); 00023 00024 protected function setUp() { 00025 parent::setUp(); 00026 00027 $this->mUserMock = $this->getMockBuilder( 'User' ) 00028 ->disableOriginalConstructor() 00029 ->getMock(); 00030 00031 // Set up groups and rights 00032 $this->mUserMock->expects( $this->any() ) 00033 ->method( 'getEffectiveGroups' )->will( $this->returnValue( array( '*', 'user' ) ) ); 00034 $this->mUserMock->expects( $this->any() ) 00035 ->method( 'isAllowed' )->will( $this->returnValue( true ) ); 00036 00037 // Set up callback for User::getOptionKinds 00038 $this->mUserMock->expects( $this->any() ) 00039 ->method( 'getOptionKinds' )->will( $this->returnCallback( array( $this, 'getOptionKinds' ) ) ); 00040 00041 // Create a new context 00042 $this->mContext = new DerivativeContext( new RequestContext() ); 00043 $this->mContext->getContext()->setTitle( Title::newFromText( 'Test' ) ); 00044 $this->mContext->setUser( $this->mUserMock ); 00045 00046 $main = new ApiMain( $this->mContext ); 00047 00048 // Empty session 00049 $this->mSession = array(); 00050 00051 $this->mTested = new ApiOptions( $main, 'options' ); 00052 00053 global $wgHooks; 00054 if ( !isset( $wgHooks['GetPreferences'] ) ) { 00055 $wgHooks['GetPreferences'] = array(); 00056 } 00057 $this->mOldGetPreferencesHooks = $wgHooks['GetPreferences']; 00058 $wgHooks['GetPreferences'][] = array( $this, 'hookGetPreferences' ); 00059 } 00060 00061 protected function tearDown() { 00062 global $wgHooks; 00063 00064 $wgHooks['GetPreferences'] = $this->mOldGetPreferencesHooks; 00065 $this->mOldGetPreferencesHooks = false; 00066 00067 parent::tearDown(); 00068 } 00069 00070 public function hookGetPreferences( $user, &$preferences ) { 00071 $preferences = array(); 00072 00073 foreach ( array( 'name', 'willBeNull', 'willBeEmpty', 'willBeHappy' ) as $k ) { 00074 $preferences[$k] = array( 00075 'type' => 'text', 00076 'section' => 'test', 00077 'label' => ' ', 00078 ); 00079 } 00080 00081 $preferences['testmultiselect'] = array( 00082 'type' => 'multiselect', 00083 'options' => array( 00084 'Test' => array( 00085 '<span dir="auto">Some HTML here for option 1</span>' => 'opt1', 00086 '<span dir="auto">Some HTML here for option 2</span>' => 'opt2', 00087 '<span dir="auto">Some HTML here for option 3</span>' => 'opt3', 00088 '<span dir="auto">Some HTML here for option 4</span>' => 'opt4', 00089 ), 00090 ), 00091 'section' => 'test', 00092 'label' => ' ', 00093 'prefix' => 'testmultiselect-', 00094 'default' => array(), 00095 ); 00096 00097 return true; 00098 } 00099 00106 public function getOptionKinds( IContextSource $context, $options = null ) { 00107 // Match with above. 00108 $kinds = array( 00109 'name' => 'registered', 00110 'willBeNull' => 'registered', 00111 'willBeEmpty' => 'registered', 00112 'willBeHappy' => 'registered', 00113 'testmultiselect-opt1' => 'registered-multiselect', 00114 'testmultiselect-opt2' => 'registered-multiselect', 00115 'testmultiselect-opt3' => 'registered-multiselect', 00116 'testmultiselect-opt4' => 'registered-multiselect', 00117 'special' => 'special', 00118 ); 00119 00120 if ( $options === null ) { 00121 return $kinds; 00122 } 00123 00124 $mapping = array(); 00125 foreach ( $options as $key => $value ) { 00126 if ( isset( $kinds[$key] ) ) { 00127 $mapping[$key] = $kinds[$key]; 00128 } elseif ( substr( $key, 0, 7 ) === 'userjs-' ) { 00129 $mapping[$key] = 'userjs'; 00130 } else { 00131 $mapping[$key] = 'unused'; 00132 } 00133 } 00134 00135 return $mapping; 00136 } 00137 00138 private function getSampleRequest( $custom = array() ) { 00139 $request = array( 00140 'token' => '123ABC', 00141 'change' => null, 00142 'optionname' => null, 00143 'optionvalue' => null, 00144 ); 00145 00146 return array_merge( $request, $custom ); 00147 } 00148 00149 private function executeQuery( $request ) { 00150 $this->mContext->setRequest( new FauxRequest( $request, true, $this->mSession ) ); 00151 $this->mTested->execute(); 00152 00153 return $this->mTested->getResult()->getData(); 00154 } 00155 00159 public function testNoToken() { 00160 $request = $this->getSampleRequest( array( 'token' => null ) ); 00161 00162 $this->executeQuery( $request ); 00163 } 00164 00165 public function testAnon() { 00166 $this->mUserMock->expects( $this->once() ) 00167 ->method( 'isAnon' ) 00168 ->will( $this->returnValue( true ) ); 00169 00170 try { 00171 $request = $this->getSampleRequest(); 00172 00173 $this->executeQuery( $request ); 00174 } catch ( UsageException $e ) { 00175 $this->assertEquals( 'notloggedin', $e->getCodeString() ); 00176 $this->assertEquals( 'Anonymous users cannot change preferences', $e->getMessage() ); 00177 00178 return; 00179 } 00180 $this->fail( "UsageException was not thrown" ); 00181 } 00182 00183 public function testNoOptionname() { 00184 try { 00185 $request = $this->getSampleRequest( array( 'optionvalue' => '1' ) ); 00186 00187 $this->executeQuery( $request ); 00188 } catch ( UsageException $e ) { 00189 $this->assertEquals( 'nooptionname', $e->getCodeString() ); 00190 $this->assertEquals( 'The optionname parameter must be set', $e->getMessage() ); 00191 00192 return; 00193 } 00194 $this->fail( "UsageException was not thrown" ); 00195 } 00196 00197 public function testNoChanges() { 00198 $this->mUserMock->expects( $this->never() ) 00199 ->method( 'resetOptions' ); 00200 00201 $this->mUserMock->expects( $this->never() ) 00202 ->method( 'setOption' ); 00203 00204 $this->mUserMock->expects( $this->never() ) 00205 ->method( 'saveSettings' ); 00206 00207 try { 00208 $request = $this->getSampleRequest(); 00209 00210 $this->executeQuery( $request ); 00211 } catch ( UsageException $e ) { 00212 $this->assertEquals( 'nochanges', $e->getCodeString() ); 00213 $this->assertEquals( 'No changes were requested', $e->getMessage() ); 00214 00215 return; 00216 } 00217 $this->fail( "UsageException was not thrown" ); 00218 } 00219 00220 public function testReset() { 00221 $this->mUserMock->expects( $this->once() ) 00222 ->method( 'resetOptions' ) 00223 ->with( $this->equalTo( array( 'all' ) ) ); 00224 00225 $this->mUserMock->expects( $this->never() ) 00226 ->method( 'setOption' ); 00227 00228 $this->mUserMock->expects( $this->once() ) 00229 ->method( 'saveSettings' ); 00230 00231 $request = $this->getSampleRequest( array( 'reset' => '' ) ); 00232 00233 $response = $this->executeQuery( $request ); 00234 00235 $this->assertEquals( self::$Success, $response ); 00236 } 00237 00238 public function testResetKinds() { 00239 $this->mUserMock->expects( $this->once() ) 00240 ->method( 'resetOptions' ) 00241 ->with( $this->equalTo( array( 'registered' ) ) ); 00242 00243 $this->mUserMock->expects( $this->never() ) 00244 ->method( 'setOption' ); 00245 00246 $this->mUserMock->expects( $this->once() ) 00247 ->method( 'saveSettings' ); 00248 00249 $request = $this->getSampleRequest( array( 'reset' => '', 'resetkinds' => 'registered' ) ); 00250 00251 $response = $this->executeQuery( $request ); 00252 00253 $this->assertEquals( self::$Success, $response ); 00254 } 00255 00256 public function testOptionWithValue() { 00257 $this->mUserMock->expects( $this->never() ) 00258 ->method( 'resetOptions' ); 00259 00260 $this->mUserMock->expects( $this->once() ) 00261 ->method( 'setOption' ) 00262 ->with( $this->equalTo( 'name' ), $this->equalTo( 'value' ) ); 00263 00264 $this->mUserMock->expects( $this->once() ) 00265 ->method( 'saveSettings' ); 00266 00267 $request = $this->getSampleRequest( array( 'optionname' => 'name', 'optionvalue' => 'value' ) ); 00268 00269 $response = $this->executeQuery( $request ); 00270 00271 $this->assertEquals( self::$Success, $response ); 00272 } 00273 00274 public function testOptionResetValue() { 00275 $this->mUserMock->expects( $this->never() ) 00276 ->method( 'resetOptions' ); 00277 00278 $this->mUserMock->expects( $this->once() ) 00279 ->method( 'setOption' ) 00280 ->with( $this->equalTo( 'name' ), $this->identicalTo( null ) ); 00281 00282 $this->mUserMock->expects( $this->once() ) 00283 ->method( 'saveSettings' ); 00284 00285 $request = $this->getSampleRequest( array( 'optionname' => 'name' ) ); 00286 $response = $this->executeQuery( $request ); 00287 00288 $this->assertEquals( self::$Success, $response ); 00289 } 00290 00291 public function testChange() { 00292 $this->mUserMock->expects( $this->never() ) 00293 ->method( 'resetOptions' ); 00294 00295 $this->mUserMock->expects( $this->at( 2 ) ) 00296 ->method( 'getOptions' ); 00297 00298 $this->mUserMock->expects( $this->at( 4 ) ) 00299 ->method( 'setOption' ) 00300 ->with( $this->equalTo( 'willBeNull' ), $this->identicalTo( null ) ); 00301 00302 $this->mUserMock->expects( $this->at( 5 ) ) 00303 ->method( 'getOptions' ); 00304 00305 $this->mUserMock->expects( $this->at( 6 ) ) 00306 ->method( 'setOption' ) 00307 ->with( $this->equalTo( 'willBeEmpty' ), $this->equalTo( '' ) ); 00308 00309 $this->mUserMock->expects( $this->at( 7 ) ) 00310 ->method( 'getOptions' ); 00311 00312 $this->mUserMock->expects( $this->at( 8 ) ) 00313 ->method( 'setOption' ) 00314 ->with( $this->equalTo( 'willBeHappy' ), $this->equalTo( 'Happy' ) ); 00315 00316 $this->mUserMock->expects( $this->once() ) 00317 ->method( 'saveSettings' ); 00318 00319 $request = $this->getSampleRequest( array( 00320 'change' => 'willBeNull|willBeEmpty=|willBeHappy=Happy' 00321 ) ); 00322 00323 $response = $this->executeQuery( $request ); 00324 00325 $this->assertEquals( self::$Success, $response ); 00326 } 00327 00328 public function testResetChangeOption() { 00329 $this->mUserMock->expects( $this->once() ) 00330 ->method( 'resetOptions' ); 00331 00332 $this->mUserMock->expects( $this->at( 4 ) ) 00333 ->method( 'getOptions' ); 00334 00335 $this->mUserMock->expects( $this->at( 5 ) ) 00336 ->method( 'setOption' ) 00337 ->with( $this->equalTo( 'willBeHappy' ), $this->equalTo( 'Happy' ) ); 00338 00339 $this->mUserMock->expects( $this->at( 6 ) ) 00340 ->method( 'getOptions' ); 00341 00342 $this->mUserMock->expects( $this->at( 7 ) ) 00343 ->method( 'setOption' ) 00344 ->with( $this->equalTo( 'name' ), $this->equalTo( 'value' ) ); 00345 00346 $this->mUserMock->expects( $this->once() ) 00347 ->method( 'saveSettings' ); 00348 00349 $args = array( 00350 'reset' => '', 00351 'change' => 'willBeHappy=Happy', 00352 'optionname' => 'name', 00353 'optionvalue' => 'value' 00354 ); 00355 00356 $response = $this->executeQuery( $this->getSampleRequest( $args ) ); 00357 00358 $this->assertEquals( self::$Success, $response ); 00359 } 00360 00361 public function testMultiSelect() { 00362 $this->mUserMock->expects( $this->never() ) 00363 ->method( 'resetOptions' ); 00364 00365 $this->mUserMock->expects( $this->at( 3 ) ) 00366 ->method( 'setOption' ) 00367 ->with( $this->equalTo( 'testmultiselect-opt1' ), $this->identicalTo( true ) ); 00368 00369 $this->mUserMock->expects( $this->at( 4 ) ) 00370 ->method( 'setOption' ) 00371 ->with( $this->equalTo( 'testmultiselect-opt2' ), $this->identicalTo( null ) ); 00372 00373 $this->mUserMock->expects( $this->at( 5 ) ) 00374 ->method( 'setOption' ) 00375 ->with( $this->equalTo( 'testmultiselect-opt3' ), $this->identicalTo( false ) ); 00376 00377 $this->mUserMock->expects( $this->at( 6 ) ) 00378 ->method( 'setOption' ) 00379 ->with( $this->equalTo( 'testmultiselect-opt4' ), $this->identicalTo( false ) ); 00380 00381 $this->mUserMock->expects( $this->once() ) 00382 ->method( 'saveSettings' ); 00383 00384 $request = $this->getSampleRequest( array( 00385 'change' => 'testmultiselect-opt1=1|testmultiselect-opt2|' 00386 . 'testmultiselect-opt3=|testmultiselect-opt4=0' 00387 ) ); 00388 00389 $response = $this->executeQuery( $request ); 00390 00391 $this->assertEquals( self::$Success, $response ); 00392 } 00393 00394 public function testSpecialOption() { 00395 $this->mUserMock->expects( $this->never() ) 00396 ->method( 'resetOptions' ); 00397 00398 $this->mUserMock->expects( $this->never() ) 00399 ->method( 'saveSettings' ); 00400 00401 $request = $this->getSampleRequest( array( 00402 'change' => 'special=1' 00403 ) ); 00404 00405 $response = $this->executeQuery( $request ); 00406 00407 $this->assertEquals( array( 00408 'options' => 'success', 00409 'warnings' => array( 00410 'options' => array( 00411 '*' => "Validation error for 'special': cannot be set by this module" 00412 ) 00413 ) 00414 ), $response ); 00415 } 00416 00417 public function testUnknownOption() { 00418 $this->mUserMock->expects( $this->never() ) 00419 ->method( 'resetOptions' ); 00420 00421 $this->mUserMock->expects( $this->never() ) 00422 ->method( 'saveSettings' ); 00423 00424 $request = $this->getSampleRequest( array( 00425 'change' => 'unknownOption=1' 00426 ) ); 00427 00428 $response = $this->executeQuery( $request ); 00429 00430 $this->assertEquals( array( 00431 'options' => 'success', 00432 'warnings' => array( 00433 'options' => array( 00434 '*' => "Validation error for 'unknownOption': not a valid preference" 00435 ) 00436 ) 00437 ), $response ); 00438 } 00439 00440 public function testUserjsOption() { 00441 $this->mUserMock->expects( $this->never() ) 00442 ->method( 'resetOptions' ); 00443 00444 $this->mUserMock->expects( $this->at( 3 ) ) 00445 ->method( 'setOption' ) 00446 ->with( $this->equalTo( 'userjs-option' ), $this->equalTo( '1' ) ); 00447 00448 $this->mUserMock->expects( $this->once() ) 00449 ->method( 'saveSettings' ); 00450 00451 $request = $this->getSampleRequest( array( 00452 'change' => 'userjs-option=1' 00453 ) ); 00454 00455 $response = $this->executeQuery( $request ); 00456 00457 $this->assertEquals( self::$Success, $response ); 00458 } 00459 }