MediaWiki  REL1_24
ApiOptionsTest.php
Go to the documentation of this file.
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' => '&#160;',
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' => '&#160;',
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 }