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