testWikiPage = new WikiPage( $testTitle ); $testContext = new DerivativeContext( RequestContext::getMain() ); $testContext->setTitle( $testTitle ); $this->watchAction = new WatchAction( $this->testWikiPage, $testContext ); } /** * @throws MWException */ protected function tearDown() { parent::tearDown(); Hooks::clear( 'WatchArticle' ); Hooks::clear( 'UnwatchArticle' ); } /** * @covers WatchAction::getName() */ public function testGetName() { $this->assertEquals( 'watch', $this->watchAction->getName() ); } /** * @covers WatchAction::requiresUnblock() */ public function testRequiresUnlock() { $this->assertFalse( $this->watchAction->requiresUnblock() ); } /** * @covers WatchAction::doesWrites() */ public function testDoesWrites() { $this->assertTrue( $this->watchAction->doesWrites() ); } /** * @covers WatchAction::onSubmit() * @covers WatchAction::doWatch() */ public function testOnSubmit() { /** @var Status $actual */ $actual = $this->watchAction->onSubmit( [] ); $this->assertTrue( $actual->isGood() ); } /** * @covers WatchAction::onSubmit() * @covers WatchAction::doWatch() */ public function testOnSubmitHookAborted() { Hooks::register( 'WatchArticle', function () { return false; } ); /** @var Status $actual */ $actual = $this->watchAction->onSubmit( [] ); $this->assertInstanceOf( Status::class, $actual ); $this->assertTrue( $actual->hasMessage( 'hookaborted' ) ); } /** * @covers WatchAction::checkCanExecute() */ public function testShowUserNotLoggedIn() { $notLoggedInUser = new User(); $testContext = new DerivativeContext( $this->watchAction->getContext() ); $testContext->setUser( $notLoggedInUser ); $watchAction = new WatchAction( $this->testWikiPage, $testContext ); $this->setExpectedException( UserNotLoggedIn::class ); $watchAction->show(); } /** * @covers WatchAction::checkCanExecute() */ public function testShowUserLoggedInNoException() { $loggedInUser = $this->getMock( User::class ); $loggedInUser->method( 'isLoggedIn' )->willReturn( true ); $testContext = new DerivativeContext( $this->watchAction->getContext() ); $testContext->setUser( $loggedInUser ); $watchAction = new WatchAction( $this->testWikiPage, $testContext ); $exception = null; try { $watchAction->show(); } catch ( UserNotLoggedIn $e ) { $exception = $e; } $this->assertNull( $exception, 'UserNotLoggedIn exception should not be thrown if user is logged in.' ); } /** * @covers WatchAction::onSuccess() */ public function testOnSuccessMainNamespaceTitle() { $testContext = $this->getMock( DerivativeContext::class, [ 'msg' ], [ $this->watchAction->getContext() ] ); $testOutput = new OutputPage( $testContext ); $testContext->setOutput( $testOutput ); $testContext->method( 'msg' )->willReturnCallback( function ( $msgKey ) { return new RawMessage( $msgKey ); } ); $watchAction = new WatchAction( $this->testWikiPage, $testContext ); $watchAction->onSuccess(); $this->assertEquals( '

addedwatchtext

', $testOutput->getHTML() ); } /** * @covers WatchAction::onSuccess() */ public function testOnSuccessTalkPage() { $testContext = $this->getMock( DerivativeContext::class, [], [ $this->watchAction->getContext() ] ); $testOutput = new OutputPage( $testContext ); $testContext->method( 'getOutput' )->willReturn( $testOutput ); $testContext->method( 'msg' )->willReturnCallback( function ( $msgKey ) { return new RawMessage( $msgKey ); } ); $talkPageTitle = Title::newFromText( 'Talk:UTTest' ); $testContext->setTitle( $talkPageTitle ); $watchAction = new WatchAction( new WikiPage( $talkPageTitle ), $testContext ); $watchAction->onSuccess(); $this->assertEquals( '

addedwatchtext-talk

', $testOutput->getHTML() ); } /** * @covers WatchAction::doWatch() */ public function testDoWatchNoCheckRights() { $notPermittedUser = $this->getMock( User::class ); $notPermittedUser->method( 'isAllowed' )->willReturn( false ); $actual = WatchAction::doWatch( $this->testWikiPage->getTitle(), $notPermittedUser, false ); $this->assertTrue( $actual->isGood() ); } /** * @covers WatchAction::doWatch() */ public function testDoWatchUserNotPermittedStatusNotGood() { $notPermittedUser = $this->getMock( User::class ); $notPermittedUser->method( 'isAllowed' )->willReturn( false ); $actual = WatchAction::doWatch( $this->testWikiPage->getTitle(), $notPermittedUser, true ); $this->assertFalse( $actual->isGood() ); } /** * @covers WatchAction::doWatch() */ public function testDoWatchCallsUserAddWatch() { $permittedUser = $this->getMock( User::class ); $permittedUser->method( 'isAllowed' )->willReturn( true ); $permittedUser->expects( $this->once() ) ->method( 'addWatch' ) ->with( $this->equalTo( $this->testWikiPage->getTitle() ), $this->equalTo( true ) ); $actual = WatchAction::doWatch( $this->testWikiPage->getTitle(), $permittedUser ); $this->assertTrue( $actual->isGood() ); } /** * @covers WatchAction::doUnWatch() */ public function testDoUnWatchWithoutRights() { $notPermittedUser = $this->getMock( User::class ); $notPermittedUser->method( 'isAllowed' )->willReturn( false ); $actual = WatchAction::doUnWatch( $this->testWikiPage->getTitle(), $notPermittedUser ); $this->assertFalse( $actual->isGood() ); } /** * @covers WatchAction::doUnWatch() */ public function testDoUnWatchUserHookAborted() { $permittedUser = $this->getMock( User::class ); $permittedUser->method( 'isAllowed' )->willReturn( true ); Hooks::register( 'UnwatchArticle', function () { return false; } ); $status = WatchAction::doUnWatch( $this->testWikiPage->getTitle(), $permittedUser ); $this->assertFalse( $status->isGood() ); $errors = $status->getErrors(); $this->assertEquals( 1, count( $errors ) ); $this->assertEquals( 'hookaborted', $errors[0]['message'] ); } /** * @covers WatchAction::doUnWatch() */ public function testDoUnWatchCallsUserRemoveWatch() { $permittedUser = $this->getMock( User::class ); $permittedUser->method( 'isAllowed' )->willReturn( true ); $permittedUser->expects( $this->once() ) ->method( 'removeWatch' ) ->with( $this->equalTo( $this->testWikiPage->getTitle() ) ); $actual = WatchAction::doUnWatch( $this->testWikiPage->getTitle(), $permittedUser ); $this->assertTrue( $actual->isGood() ); } /** * @covers WatchAction::getWatchToken() */ public function testGetWatchTokenNormalizesToWatch() { $user = $this->getMock( User::class ); $user->expects( $this->once() ) ->method( 'getEditToken' ) ->with( $this->equalTo( 'watch' ) ); WatchAction::getWatchToken( $this->watchAction->getTitle(), $user, 'INVALID_ACTION' ); } /** * @covers WatchAction::getWatchToken() */ public function testGetWatchTokenProxiesUserGetEditToken() { $user = $this->getMock( User::class ); $user->expects( $this->once() )->method( 'getEditToken' ); WatchAction::getWatchToken( $this->watchAction->getTitle(), $user ); } /** * @covers WatchAction::doWatchOrUnwatch() */ public function testDoWatchOrUnwatchUserNotLoggedIn() { $user = $this->getLoggedInIsWatchedUser( false ); $user->expects( $this->never() )->method( 'removeWatch' ); $user->expects( $this->never() )->method( 'addWatch' ); $status = WatchAction::doWatchOrUnwatch( true, $this->watchAction->getTitle(), $user ); $this->assertTrue( $status->isGood() ); } /** * @covers WatchAction::doWatchOrUnwatch() */ public function testDoWatchOrUnwatchSkipsIfAlreadyWatched() { $user = $this->getLoggedInIsWatchedUser(); $user->expects( $this->never() )->method( 'removeWatch' ); $user->expects( $this->never() )->method( 'addWatch' ); $status = WatchAction::doWatchOrUnwatch( true, $this->watchAction->getTitle(), $user ); $this->assertTrue( $status->isGood() ); } /** * @covers WatchAction::doWatchOrUnwatch() */ public function testDoWatchOrUnwatchSkipsIfAlreadyUnWatched() { $user = $this->getLoggedInIsWatchedUser( true, false ); $user->expects( $this->never() )->method( 'removeWatch' ); $user->expects( $this->never() )->method( 'addWatch' ); $status = WatchAction::doWatchOrUnwatch( false, $this->watchAction->getTitle(), $user ); $this->assertTrue( $status->isGood() ); } /** * @covers WatchAction::doWatchOrUnwatch() */ public function testDoWatchOrUnwatchWatchesIfWatch() { $user = $this->getLoggedInIsWatchedUser( true, false ); $user->expects( $this->never() )->method( 'removeWatch' ); $user->expects( $this->once() ) ->method( 'addWatch' ) ->with( $this->equalTo( $this->testWikiPage->getTitle() ), $this->equalTo( false ) ); $status = WatchAction::doWatchOrUnwatch( true, $this->watchAction->getTitle(), $user ); $this->assertTrue( $status->isGood() ); } /** * @covers WatchAction::doWatchOrUnwatch() */ public function testDoWatchOrUnwatchUnwatchesIfUnwatch() { $user = $this->getLoggedInIsWatchedUser(); $user->method( 'isAllowed' )->willReturn( true ); $user->expects( $this->never() )->method( 'addWatch' ); $user->expects( $this->once() ) ->method( 'removeWatch' ) ->with( $this->equalTo( $this->testWikiPage->getTitle() ) ); $status = WatchAction::doWatchOrUnwatch( false, $this->watchAction->getTitle(), $user ); $this->assertTrue( $status->isGood() ); } /** * @param bool $isLoggedIn Whether the user should be "marked" as logged in * @param bool $isWatched The value any call to isWatched should return * @return PHPUnit_Framework_MockObject_MockObject */ private function getLoggedInIsWatchedUser( $isLoggedIn = true, $isWatched = true ) { $user = $this->getMock( User::class ); $user->method( 'isLoggedIn' )->willReturn( $isLoggedIn ); $user->method( 'isWatched' )->willReturn( $isWatched ); return $user; } }