MediaWiki
REL1_23
|
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 = false; 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 if ( $this->mOldGetPreferencesHooks !== false ) { 00065 $wgHooks['GetPreferences'] = $this->mOldGetPreferencesHooks; 00066 $this->mOldGetPreferencesHooks = false; 00067 } 00068 00069 parent::tearDown(); 00070 } 00071 00072 public function hookGetPreferences( $user, &$preferences ) { 00073 $preferences = array(); 00074 00075 foreach ( array( 'name', 'willBeNull', 'willBeEmpty', 'willBeHappy' ) as $k ) { 00076 $preferences[$k] = array( 00077 'type' => 'text', 00078 'section' => 'test', 00079 'label' => ' ', 00080 ); 00081 } 00082 00083 $preferences['testmultiselect'] = array( 00084 'type' => 'multiselect', 00085 'options' => array( 00086 'Test' => array( 00087 '<span dir="auto">Some HTML here for option 1</span>' => 'opt1', 00088 '<span dir="auto">Some HTML here for option 2</span>' => 'opt2', 00089 '<span dir="auto">Some HTML here for option 3</span>' => 'opt3', 00090 '<span dir="auto">Some HTML here for option 4</span>' => 'opt4', 00091 ), 00092 ), 00093 'section' => 'test', 00094 'label' => ' ', 00095 'prefix' => 'testmultiselect-', 00096 'default' => array(), 00097 ); 00098 00099 return true; 00100 } 00101 00108 public function getOptionKinds( IContextSource $context, $options = null ) { 00109 // Match with above. 00110 $kinds = array( 00111 'name' => 'registered', 00112 'willBeNull' => 'registered', 00113 'willBeEmpty' => 'registered', 00114 'willBeHappy' => 'registered', 00115 'testmultiselect-opt1' => 'registered-multiselect', 00116 'testmultiselect-opt2' => 'registered-multiselect', 00117 'testmultiselect-opt3' => 'registered-multiselect', 00118 'testmultiselect-opt4' => 'registered-multiselect', 00119 'special' => 'special', 00120 ); 00121 00122 if ( $options === null ) { 00123 return $kinds; 00124 } 00125 00126 $mapping = array(); 00127 foreach ( $options as $key => $value ) { 00128 if ( isset( $kinds[$key] ) ) { 00129 $mapping[$key] = $kinds[$key]; 00130 } elseif ( substr( $key, 0, 7 ) === 'userjs-' ) { 00131 $mapping[$key] = 'userjs'; 00132 } else { 00133 $mapping[$key] = 'unused'; 00134 } 00135 } 00136 00137 return $mapping; 00138 } 00139 00140 private function getSampleRequest( $custom = array() ) { 00141 $request = array( 00142 'token' => '123ABC', 00143 'change' => null, 00144 'optionname' => null, 00145 'optionvalue' => null, 00146 ); 00147 00148 return array_merge( $request, $custom ); 00149 } 00150 00151 private function executeQuery( $request ) { 00152 $this->mContext->setRequest( new FauxRequest( $request, true, $this->mSession ) ); 00153 $this->mTested->execute(); 00154 00155 return $this->mTested->getResult()->getData(); 00156 } 00157 00161 public function testNoToken() { 00162 $request = $this->getSampleRequest( array( 'token' => null ) ); 00163 00164 $this->executeQuery( $request ); 00165 } 00166 00167 public function testAnon() { 00168 $this->mUserMock->expects( $this->once() ) 00169 ->method( 'isAnon' ) 00170 ->will( $this->returnValue( true ) ); 00171 00172 try { 00173 $request = $this->getSampleRequest(); 00174 00175 $this->executeQuery( $request ); 00176 } catch ( UsageException $e ) { 00177 $this->assertEquals( 'notloggedin', $e->getCodeString() ); 00178 $this->assertEquals( 'Anonymous users cannot change preferences', $e->getMessage() ); 00179 00180 return; 00181 } 00182 $this->fail( "UsageException was not thrown" ); 00183 } 00184 00185 public function testNoOptionname() { 00186 try { 00187 $request = $this->getSampleRequest( array( 'optionvalue' => '1' ) ); 00188 00189 $this->executeQuery( $request ); 00190 } catch ( UsageException $e ) { 00191 $this->assertEquals( 'nooptionname', $e->getCodeString() ); 00192 $this->assertEquals( 'The optionname parameter must be set', $e->getMessage() ); 00193 00194 return; 00195 } 00196 $this->fail( "UsageException was not thrown" ); 00197 } 00198 00199 public function testNoChanges() { 00200 $this->mUserMock->expects( $this->never() ) 00201 ->method( 'resetOptions' ); 00202 00203 $this->mUserMock->expects( $this->never() ) 00204 ->method( 'setOption' ); 00205 00206 $this->mUserMock->expects( $this->never() ) 00207 ->method( 'saveSettings' ); 00208 00209 try { 00210 $request = $this->getSampleRequest(); 00211 00212 $this->executeQuery( $request ); 00213 } catch ( UsageException $e ) { 00214 $this->assertEquals( 'nochanges', $e->getCodeString() ); 00215 $this->assertEquals( 'No changes were requested', $e->getMessage() ); 00216 00217 return; 00218 } 00219 $this->fail( "UsageException was not thrown" ); 00220 } 00221 00222 public function testReset() { 00223 $this->mUserMock->expects( $this->once() ) 00224 ->method( 'resetOptions' ) 00225 ->with( $this->equalTo( array( 'all' ) ) ); 00226 00227 $this->mUserMock->expects( $this->never() ) 00228 ->method( 'setOption' ); 00229 00230 $this->mUserMock->expects( $this->once() ) 00231 ->method( 'saveSettings' ); 00232 00233 $request = $this->getSampleRequest( array( 'reset' => '' ) ); 00234 00235 $response = $this->executeQuery( $request ); 00236 00237 $this->assertEquals( self::$Success, $response ); 00238 } 00239 00240 public function testResetKinds() { 00241 $this->mUserMock->expects( $this->once() ) 00242 ->method( 'resetOptions' ) 00243 ->with( $this->equalTo( array( 'registered' ) ) ); 00244 00245 $this->mUserMock->expects( $this->never() ) 00246 ->method( 'setOption' ); 00247 00248 $this->mUserMock->expects( $this->once() ) 00249 ->method( 'saveSettings' ); 00250 00251 $request = $this->getSampleRequest( array( 'reset' => '', 'resetkinds' => 'registered' ) ); 00252 00253 $response = $this->executeQuery( $request ); 00254 00255 $this->assertEquals( self::$Success, $response ); 00256 } 00257 00258 public function testOptionWithValue() { 00259 $this->mUserMock->expects( $this->never() ) 00260 ->method( 'resetOptions' ); 00261 00262 $this->mUserMock->expects( $this->once() ) 00263 ->method( 'setOption' ) 00264 ->with( $this->equalTo( 'name' ), $this->equalTo( 'value' ) ); 00265 00266 $this->mUserMock->expects( $this->once() ) 00267 ->method( 'saveSettings' ); 00268 00269 $request = $this->getSampleRequest( array( 'optionname' => 'name', 'optionvalue' => 'value' ) ); 00270 00271 $response = $this->executeQuery( $request ); 00272 00273 $this->assertEquals( self::$Success, $response ); 00274 } 00275 00276 public function testOptionResetValue() { 00277 $this->mUserMock->expects( $this->never() ) 00278 ->method( 'resetOptions' ); 00279 00280 $this->mUserMock->expects( $this->once() ) 00281 ->method( 'setOption' ) 00282 ->with( $this->equalTo( 'name' ), $this->identicalTo( null ) ); 00283 00284 $this->mUserMock->expects( $this->once() ) 00285 ->method( 'saveSettings' ); 00286 00287 $request = $this->getSampleRequest( array( 'optionname' => 'name' ) ); 00288 $response = $this->executeQuery( $request ); 00289 00290 $this->assertEquals( self::$Success, $response ); 00291 } 00292 00293 public function testChange() { 00294 $this->mUserMock->expects( $this->never() ) 00295 ->method( 'resetOptions' ); 00296 00297 $this->mUserMock->expects( $this->at( 2 ) ) 00298 ->method( 'getOptions' ); 00299 00300 $this->mUserMock->expects( $this->at( 4 ) ) 00301 ->method( 'setOption' ) 00302 ->with( $this->equalTo( 'willBeNull' ), $this->identicalTo( null ) ); 00303 00304 $this->mUserMock->expects( $this->at( 5 ) ) 00305 ->method( 'getOptions' ); 00306 00307 $this->mUserMock->expects( $this->at( 6 ) ) 00308 ->method( 'setOption' ) 00309 ->with( $this->equalTo( 'willBeEmpty' ), $this->equalTo( '' ) ); 00310 00311 $this->mUserMock->expects( $this->at( 7 ) ) 00312 ->method( 'getOptions' ); 00313 00314 $this->mUserMock->expects( $this->at( 8 ) ) 00315 ->method( 'setOption' ) 00316 ->with( $this->equalTo( 'willBeHappy' ), $this->equalTo( 'Happy' ) ); 00317 00318 $this->mUserMock->expects( $this->once() ) 00319 ->method( 'saveSettings' ); 00320 00321 $request = $this->getSampleRequest( array( 'change' => 'willBeNull|willBeEmpty=|willBeHappy=Happy' ) ); 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|testmultiselect-opt3=|testmultiselect-opt4=0' 00386 ) ); 00387 00388 $response = $this->executeQuery( $request ); 00389 00390 $this->assertEquals( self::$Success, $response ); 00391 } 00392 00393 public function testSpecialOption() { 00394 $this->mUserMock->expects( $this->never() ) 00395 ->method( 'resetOptions' ); 00396 00397 $this->mUserMock->expects( $this->never() ) 00398 ->method( 'saveSettings' ); 00399 00400 $request = $this->getSampleRequest( array( 00401 'change' => 'special=1' 00402 ) ); 00403 00404 $response = $this->executeQuery( $request ); 00405 00406 $this->assertEquals( array( 00407 'options' => 'success', 00408 'warnings' => array( 00409 'options' => array( 00410 '*' => "Validation error for 'special': cannot be set by this module" 00411 ) 00412 ) 00413 ), $response ); 00414 } 00415 00416 public function testUnknownOption() { 00417 $this->mUserMock->expects( $this->never() ) 00418 ->method( 'resetOptions' ); 00419 00420 $this->mUserMock->expects( $this->never() ) 00421 ->method( 'saveSettings' ); 00422 00423 $request = $this->getSampleRequest( array( 00424 'change' => 'unknownOption=1' 00425 ) ); 00426 00427 $response = $this->executeQuery( $request ); 00428 00429 $this->assertEquals( array( 00430 'options' => 'success', 00431 'warnings' => array( 00432 'options' => array( 00433 '*' => "Validation error for 'unknownOption': not a valid preference" 00434 ) 00435 ) 00436 ), $response ); 00437 } 00438 00439 public function testUserjsOption() { 00440 $this->mUserMock->expects( $this->never() ) 00441 ->method( 'resetOptions' ); 00442 00443 $this->mUserMock->expects( $this->at( 3 ) ) 00444 ->method( 'setOption' ) 00445 ->with( $this->equalTo( 'userjs-option' ), $this->equalTo( '1' ) ); 00446 00447 $this->mUserMock->expects( $this->once() ) 00448 ->method( 'saveSettings' ); 00449 00450 $request = $this->getSampleRequest( array( 00451 'change' => 'userjs-option=1' 00452 ) ); 00453 00454 $response = $this->executeQuery( $request ); 00455 00456 $this->assertEquals( self::$Success, $response ); 00457 } 00458 }