WatchAction::onSubmit return correct value, not always true
[lhc/web/wiklou.git] / tests / phpunit / includes / actions / WatchActionTest.php
1 <?php
2
3 /**
4 * @covers WatchAction
5 *
6 * @group Action
7 */
8 class WatchActionTest extends MediaWikiTestCase {
9
10 /**
11 * @var WatchAction
12 */
13 private $watchAction;
14
15 /**
16 * @var WikiPage
17 */
18 private $testWikiPage;
19
20 protected function setUp() {
21 parent::setUp();
22
23 $testTitle = Title::newFromText( 'UTTest' );
24 $this->testWikiPage = new WikiPage( $testTitle );
25 $testContext = new DerivativeContext( RequestContext::getMain() );
26 $testContext->setTitle( $testTitle );
27 $this->watchAction = new WatchAction( $this->testWikiPage, $testContext );
28 }
29
30 /**
31 * @throws MWException
32 */
33 protected function tearDown() {
34 parent::tearDown();
35
36 Hooks::clear( 'WatchArticle' );
37 Hooks::clear( 'UnwatchArticle' );
38 }
39
40 /**
41 * @covers WatchAction::getName()
42 */
43 public function testGetName() {
44 $this->assertEquals( 'watch', $this->watchAction->getName() );
45 }
46
47 /**
48 * @covers WatchAction::requiresUnblock()
49 */
50 public function testRequiresUnlock() {
51 $this->assertFalse( $this->watchAction->requiresUnblock() );
52 }
53
54 /**
55 * @covers WatchAction::doesWrites()
56 */
57 public function testDoesWrites() {
58 $this->assertTrue( $this->watchAction->doesWrites() );
59 }
60
61 /**
62 * @covers WatchAction::onSubmit()
63 * @covers WatchAction::doWatch()
64 */
65 public function testOnSubmit() {
66 /** @var Status $actual */
67 $actual = $this->watchAction->onSubmit( [] );
68
69 $this->assertTrue( $actual->isGood() );
70 }
71
72 /**
73 * @covers WatchAction::onSubmit()
74 * @covers WatchAction::doWatch()
75 */
76 public function testOnSubmitHookAborted() {
77 Hooks::register( 'WatchArticle', function () {
78 return false;
79 } );
80
81 /** @var Status $actual */
82 $actual = $this->watchAction->onSubmit( [] );
83
84 $this->assertInstanceOf( Status::class, $actual );
85 $this->assertTrue( $actual->hasMessage( 'hookaborted' ) );
86 }
87
88 /**
89 * @covers WatchAction::checkCanExecute()
90 */
91 public function testShowUserNotLoggedIn() {
92 $notLoggedInUser = new User();
93 $testContext = new DerivativeContext( $this->watchAction->getContext() );
94 $testContext->setUser( $notLoggedInUser );
95 $watchAction = new WatchAction( $this->testWikiPage, $testContext );
96 $this->setExpectedException( UserNotLoggedIn::class );
97
98 $watchAction->show();
99 }
100
101 /**
102 * @covers WatchAction::checkCanExecute()
103 */
104 public function testShowUserLoggedInNoException() {
105 $loggedInUser = $this->getMock( User::class );
106 $loggedInUser->method( 'isLoggedIn' )->willReturn( true );
107 $testContext = new DerivativeContext( $this->watchAction->getContext() );
108 $testContext->setUser( $loggedInUser );
109 $watchAction = new WatchAction( $this->testWikiPage, $testContext );
110
111 $exception = null;
112 try {
113 $watchAction->show();
114 } catch ( UserNotLoggedIn $e ) {
115 $exception = $e;
116 }
117 $this->assertNull( $exception,
118 'UserNotLoggedIn exception should not be thrown if user is logged in.' );
119 }
120
121 /**
122 * @covers WatchAction::onSuccess()
123 */
124 public function testOnSuccessMainNamespaceTitle() {
125 $testContext = $this->getMock(
126 DerivativeContext::class,
127 [ 'msg' ],
128 [ $this->watchAction->getContext() ]
129 );
130 $testOutput = new OutputPage( $testContext );
131 $testContext->setOutput( $testOutput );
132 $testContext->method( 'msg' )->willReturnCallback( function ( $msgKey ) {
133 return new RawMessage( $msgKey );
134 } );
135 $watchAction = new WatchAction( $this->testWikiPage, $testContext );
136
137 $watchAction->onSuccess();
138
139 $this->assertEquals( '<p>addedwatchtext
140 </p>', $testOutput->getHTML() );
141 }
142
143 /**
144 * @covers WatchAction::onSuccess()
145 */
146 public function testOnSuccessTalkPage() {
147 $testContext = $this->getMock(
148 DerivativeContext::class,
149 [],
150 [ $this->watchAction->getContext() ]
151 );
152 $testOutput = new OutputPage( $testContext );
153 $testContext->method( 'getOutput' )->willReturn( $testOutput );
154 $testContext->method( 'msg' )->willReturnCallback( function ( $msgKey ) {
155 return new RawMessage( $msgKey );
156 } );
157 $talkPageTitle = Title::newFromText( 'Talk:UTTest' );
158 $testContext->setTitle( $talkPageTitle );
159 $watchAction = new WatchAction( new WikiPage( $talkPageTitle ), $testContext );
160
161 $watchAction->onSuccess();
162
163 $this->assertEquals( '<p>addedwatchtext-talk
164 </p>', $testOutput->getHTML() );
165 }
166
167 /**
168 * @covers WatchAction::doWatch()
169 */
170 public function testDoWatchNoCheckRights() {
171 $notPermittedUser = $this->getMock( User::class );
172 $notPermittedUser->method( 'isAllowed' )->willReturn( false );
173
174 $actual = WatchAction::doWatch( $this->testWikiPage->getTitle(), $notPermittedUser, false );
175
176 $this->assertTrue( $actual->isGood() );
177 }
178
179 /**
180 * @covers WatchAction::doWatch()
181 */
182 public function testDoWatchUserNotPermittedStatusNotGood() {
183 $notPermittedUser = $this->getMock( User::class );
184 $notPermittedUser->method( 'isAllowed' )->willReturn( false );
185
186 $actual = WatchAction::doWatch( $this->testWikiPage->getTitle(), $notPermittedUser, true );
187
188 $this->assertFalse( $actual->isGood() );
189 }
190
191 /**
192 * @covers WatchAction::doWatch()
193 */
194 public function testDoWatchCallsUserAddWatch() {
195 $permittedUser = $this->getMock( User::class );
196 $permittedUser->method( 'isAllowed' )->willReturn( true );
197 $permittedUser->expects( $this->once() )
198 ->method( 'addWatch' )
199 ->with( $this->equalTo( $this->testWikiPage->getTitle() ), $this->equalTo( true ) );
200
201 $actual = WatchAction::doWatch( $this->testWikiPage->getTitle(), $permittedUser );
202
203 $this->assertTrue( $actual->isGood() );
204 }
205
206 /**
207 * @covers WatchAction::doUnWatch()
208 */
209 public function testDoUnWatchWithoutRights() {
210 $notPermittedUser = $this->getMock( User::class );
211 $notPermittedUser->method( 'isAllowed' )->willReturn( false );
212
213 $actual = WatchAction::doUnWatch( $this->testWikiPage->getTitle(), $notPermittedUser );
214
215 $this->assertFalse( $actual->isGood() );
216 }
217
218 /**
219 * @covers WatchAction::doUnWatch()
220 */
221 public function testDoUnWatchUserHookAborted() {
222 $permittedUser = $this->getMock( User::class );
223 $permittedUser->method( 'isAllowed' )->willReturn( true );
224 Hooks::register( 'UnwatchArticle', function () {
225 return false;
226 } );
227
228 $status = WatchAction::doUnWatch( $this->testWikiPage->getTitle(), $permittedUser );
229
230 $this->assertFalse( $status->isGood() );
231 $errors = $status->getErrors();
232 $this->assertEquals( 1, count( $errors ) );
233 $this->assertEquals( 'hookaborted', $errors[0]['message'] );
234 }
235
236 /**
237 * @covers WatchAction::doUnWatch()
238 */
239 public function testDoUnWatchCallsUserRemoveWatch() {
240 $permittedUser = $this->getMock( User::class );
241 $permittedUser->method( 'isAllowed' )->willReturn( true );
242 $permittedUser->expects( $this->once() )
243 ->method( 'removeWatch' )
244 ->with( $this->equalTo( $this->testWikiPage->getTitle() ) );
245
246 $actual = WatchAction::doUnWatch( $this->testWikiPage->getTitle(), $permittedUser );
247
248 $this->assertTrue( $actual->isGood() );
249 }
250
251 /**
252 * @covers WatchAction::getWatchToken()
253 */
254 public function testGetWatchTokenNormalizesToWatch() {
255 $user = $this->getMock( User::class );
256 $user->expects( $this->once() )
257 ->method( 'getEditToken' )
258 ->with( $this->equalTo( 'watch' ) );
259
260 WatchAction::getWatchToken( $this->watchAction->getTitle(), $user, 'INVALID_ACTION' );
261 }
262
263 /**
264 * @covers WatchAction::getWatchToken()
265 */
266 public function testGetWatchTokenProxiesUserGetEditToken() {
267 $user = $this->getMock( User::class );
268 $user->expects( $this->once() )->method( 'getEditToken' );
269
270 WatchAction::getWatchToken( $this->watchAction->getTitle(), $user );
271 }
272
273 /**
274 * @covers WatchAction::getUnwatchToken()
275 */
276 public function testGetUnwatchToken() {
277 $user = $this->getMock( User::class );
278 $user->expects( $this->once() )->method( 'getEditToken' );
279 $this->hideDeprecated( 'WatchAction::getUnwatchToken' );
280
281 WatchAction::getUnWatchToken( $this->watchAction->getTitle(), $user );
282 }
283
284 /**
285 * @covers WatchAction::doWatchOrUnwatch()
286 */
287 public function testDoWatchOrUnwatchUserNotLoggedIn() {
288 $user = $this->getLoggedInIsWatchedUser( false );
289 $user->expects( $this->never() )->method( 'removeWatch' );
290 $user->expects( $this->never() )->method( 'addWatch' );
291
292 $status = WatchAction::doWatchOrUnwatch( true, $this->watchAction->getTitle(), $user );
293
294 $this->assertTrue( $status->isGood() );
295 }
296
297 /**
298 * @covers WatchAction::doWatchOrUnwatch()
299 */
300 public function testDoWatchOrUnwatchSkipsIfAlreadyWatched() {
301 $user = $this->getLoggedInIsWatchedUser();
302 $user->expects( $this->never() )->method( 'removeWatch' );
303 $user->expects( $this->never() )->method( 'addWatch' );
304
305 $status = WatchAction::doWatchOrUnwatch( true, $this->watchAction->getTitle(), $user );
306
307 $this->assertTrue( $status->isGood() );
308 }
309
310 /**
311 * @covers WatchAction::doWatchOrUnwatch()
312 */
313 public function testDoWatchOrUnwatchSkipsIfAlreadyUnWatched() {
314 $user = $this->getLoggedInIsWatchedUser( true, false );
315 $user->expects( $this->never() )->method( 'removeWatch' );
316 $user->expects( $this->never() )->method( 'addWatch' );
317
318 $status = WatchAction::doWatchOrUnwatch( false, $this->watchAction->getTitle(), $user );
319
320 $this->assertTrue( $status->isGood() );
321 }
322
323 /**
324 * @covers WatchAction::doWatchOrUnwatch()
325 */
326 public function testDoWatchOrUnwatchWatchesIfWatch() {
327 $user = $this->getLoggedInIsWatchedUser( true, false );
328 $user->expects( $this->never() )->method( 'removeWatch' );
329 $user->expects( $this->once() )
330 ->method( 'addWatch' )
331 ->with( $this->equalTo( $this->testWikiPage->getTitle() ), $this->equalTo( false ) );
332
333 $status = WatchAction::doWatchOrUnwatch( true, $this->watchAction->getTitle(), $user );
334
335 $this->assertTrue( $status->isGood() );
336 }
337
338 /**
339 * @covers WatchAction::doWatchOrUnwatch()
340 */
341 public function testDoWatchOrUnwatchUnwatchesIfUnwatch() {
342 $user = $this->getLoggedInIsWatchedUser();
343 $user->method( 'isAllowed' )->willReturn( true );
344 $user->expects( $this->never() )->method( 'addWatch' );
345 $user->expects( $this->once() )
346 ->method( 'removeWatch' )
347 ->with( $this->equalTo( $this->testWikiPage->getTitle() ) );
348
349 $status = WatchAction::doWatchOrUnwatch( false, $this->watchAction->getTitle(), $user );
350
351 $this->assertTrue( $status->isGood() );
352 }
353
354 /**
355 * @param bool $isLoggedIn Whether the user should be "marked" as logged in
356 * @param bool $isWatched The value any call to isWatched should return
357 * @return PHPUnit_Framework_MockObject_MockObject
358 */
359 private function getLoggedInIsWatchedUser( $isLoggedIn = true, $isWatched = true ) {
360 $user = $this->getMock( User::class );
361 $user->method( 'isLoggedIn' )->willReturn( $isLoggedIn );
362 $user->method( 'isWatched' )->willReturn( $isWatched );
363
364 return $user;
365 }
366
367 }