Merge "Type hint against LinkTarget in WatchedItemStore"
[lhc/web/wiklou.git] / tests / phpunit / includes / api / ApiQueryWatchlistRawIntegrationTest.php
1 <?php
2
3 use MediaWiki\MediaWikiServices;
4
5 /**
6 * @group API
7 * @group Database
8 * @group medium
9 *
10 * @covers ApiQueryWatchlistRaw
11 */
12 class ApiQueryWatchlistRawIntegrationTest extends ApiTestCase {
13
14 protected function setUp() {
15 parent::setUp();
16 self::$users['ApiQueryWatchlistRawIntegrationTestUser']
17 = $this->getMutableTestUser();
18 self::$users['ApiQueryWatchlistRawIntegrationTestUser2']
19 = $this->getMutableTestUser();
20 }
21
22 private function getLoggedInTestUser() {
23 return self::$users['ApiQueryWatchlistRawIntegrationTestUser']->getUser();
24 }
25
26 private function getNotLoggedInTestUser() {
27 return self::$users['ApiQueryWatchlistRawIntegrationTestUser2']->getUser();
28 }
29
30 private function getWatchedItemStore() {
31 return MediaWikiServices::getInstance()->getWatchedItemStore();
32 }
33
34 private function doListWatchlistRawRequest( array $params = [] ) {
35 return $this->doApiRequest( array_merge(
36 [ 'action' => 'query', 'list' => 'watchlistraw' ],
37 $params
38 ), null, false, $this->getLoggedInTestUser() );
39 }
40
41 private function doGeneratorWatchlistRawRequest( array $params = [] ) {
42 return $this->doApiRequest( array_merge(
43 [ 'action' => 'query', 'generator' => 'watchlistraw' ],
44 $params
45 ), null, false, $this->getLoggedInTestUser() );
46 }
47
48 private function getItemsFromApiResponse( array $response ) {
49 return $response[0]['watchlistraw'];
50 }
51
52 public function testListWatchlistRaw_returnsWatchedItems() {
53 $store = $this->getWatchedItemStore();
54 $store->addWatch(
55 $this->getLoggedInTestUser(),
56 new TitleValue( 0, 'ApiQueryWatchlistRawIntegrationTestPage' )
57 );
58
59 $result = $this->doListWatchlistRawRequest();
60
61 $this->assertArrayHasKey( 'watchlistraw', $result[0] );
62
63 $this->assertEquals(
64 [
65 [
66 'ns' => 0,
67 'title' => 'ApiQueryWatchlistRawIntegrationTestPage',
68 ],
69 ],
70 $this->getItemsFromApiResponse( $result )
71 );
72 }
73
74 public function testPropChanged_addsNotificationTimestamp() {
75 $target = new TitleValue( 0, 'ApiQueryWatchlistRawIntegrationTestPage' );
76 $otherUser = $this->getNotLoggedInTestUser();
77
78 $store = $this->getWatchedItemStore();
79
80 $store->addWatch( $this->getLoggedInTestUser(), $target );
81 $store->updateNotificationTimestamp(
82 $otherUser,
83 $target,
84 '20151212010101'
85 );
86
87 $result = $this->doListWatchlistRawRequest( [ 'wrprop' => 'changed' ] );
88
89 $this->assertEquals(
90 [
91 [
92 'ns' => 0,
93 'title' => 'ApiQueryWatchlistRawIntegrationTestPage',
94 'changed' => '2015-12-12T01:01:01Z',
95 ],
96 ],
97 $this->getItemsFromApiResponse( $result )
98 );
99 }
100
101 public function testNamespaceParam() {
102 $store = $this->getWatchedItemStore();
103
104 $store->addWatchBatchForUser( $this->getLoggedInTestUser(), [
105 new TitleValue( 0, 'ApiQueryWatchlistRawIntegrationTestPage' ),
106 new TitleValue( 1, 'ApiQueryWatchlistRawIntegrationTestPage' ),
107 ] );
108
109 $result = $this->doListWatchlistRawRequest( [ 'wrnamespace' => '0' ] );
110
111 $this->assertEquals(
112 [
113 [
114 'ns' => 0,
115 'title' => 'ApiQueryWatchlistRawIntegrationTestPage',
116 ],
117 ],
118 $this->getItemsFromApiResponse( $result )
119 );
120 }
121
122 public function testShowChangedParams() {
123 $subjectTarget = new TitleValue( 0, 'ApiQueryWatchlistRawIntegrationTestPage' );
124 $talkTarget = new TitleValue( 1, 'ApiQueryWatchlistRawIntegrationTestPage' );
125 $otherUser = $this->getNotLoggedInTestUser();
126
127 $store = $this->getWatchedItemStore();
128
129 $store->addWatchBatchForUser( $this->getLoggedInTestUser(), [
130 $subjectTarget,
131 $talkTarget,
132 ] );
133 $store->updateNotificationTimestamp(
134 $otherUser,
135 $subjectTarget,
136 '20151212010101'
137 );
138
139 $resultChanged = $this->doListWatchlistRawRequest(
140 [ 'wrprop' => 'changed', 'wrshow' => WatchedItemQueryService::FILTER_CHANGED ]
141 );
142 $resultNotChanged = $this->doListWatchlistRawRequest(
143 [ 'wrprop' => 'changed', 'wrshow' => WatchedItemQueryService::FILTER_NOT_CHANGED ]
144 );
145
146 $this->assertEquals(
147 [
148 [
149 'ns' => 0,
150 'title' => 'ApiQueryWatchlistRawIntegrationTestPage',
151 'changed' => '2015-12-12T01:01:01Z',
152 ],
153 ],
154 $this->getItemsFromApiResponse( $resultChanged )
155 );
156
157 $this->assertEquals(
158 [
159 [
160 'ns' => 1,
161 'title' => 'Talk:ApiQueryWatchlistRawIntegrationTestPage',
162 ],
163 ],
164 $this->getItemsFromApiResponse( $resultNotChanged )
165 );
166 }
167
168 public function testLimitParam() {
169 $store = $this->getWatchedItemStore();
170
171 $store->addWatchBatchForUser( $this->getLoggedInTestUser(), [
172 new TitleValue( 0, 'ApiQueryWatchlistRawIntegrationTestPage1' ),
173 new TitleValue( 1, 'ApiQueryWatchlistRawIntegrationTestPage1' ),
174 new TitleValue( 0, 'ApiQueryWatchlistRawIntegrationTestPage2' ),
175 ] );
176
177 $resultWithoutLimit = $this->doListWatchlistRawRequest();
178 $resultWithLimit = $this->doListWatchlistRawRequest( [ 'wrlimit' => 2 ] );
179
180 $this->assertEquals(
181 [
182 [
183 'ns' => 0,
184 'title' => 'ApiQueryWatchlistRawIntegrationTestPage1',
185 ],
186 [
187 'ns' => 0,
188 'title' => 'ApiQueryWatchlistRawIntegrationTestPage2',
189 ],
190 [
191 'ns' => 1,
192 'title' => 'Talk:ApiQueryWatchlistRawIntegrationTestPage1',
193 ],
194 ],
195 $this->getItemsFromApiResponse( $resultWithoutLimit )
196 );
197 $this->assertEquals(
198 [
199 [
200 'ns' => 0,
201 'title' => 'ApiQueryWatchlistRawIntegrationTestPage1',
202 ],
203 [
204 'ns' => 0,
205 'title' => 'ApiQueryWatchlistRawIntegrationTestPage2',
206 ],
207 ],
208 $this->getItemsFromApiResponse( $resultWithLimit )
209 );
210
211 $this->assertArrayNotHasKey( 'continue', $resultWithoutLimit[0] );
212 $this->assertArrayHasKey( 'continue', $resultWithLimit[0] );
213 $this->assertArrayHasKey( 'wrcontinue', $resultWithLimit[0]['continue'] );
214 }
215
216 public function testDirParams() {
217 $store = $this->getWatchedItemStore();
218
219 $store->addWatchBatchForUser( $this->getLoggedInTestUser(), [
220 new TitleValue( 0, 'ApiQueryWatchlistRawIntegrationTestPage1' ),
221 new TitleValue( 1, 'ApiQueryWatchlistRawIntegrationTestPage1' ),
222 new TitleValue( 0, 'ApiQueryWatchlistRawIntegrationTestPage2' ),
223 ] );
224
225 $resultDirAsc = $this->doListWatchlistRawRequest( [ 'wrdir' => 'ascending' ] );
226 $resultDirDesc = $this->doListWatchlistRawRequest( [ 'wrdir' => 'descending' ] );
227
228 $this->assertEquals(
229 [
230 [
231 'ns' => 0,
232 'title' => 'ApiQueryWatchlistRawIntegrationTestPage1',
233 ],
234 [
235 'ns' => 0,
236 'title' => 'ApiQueryWatchlistRawIntegrationTestPage2',
237 ],
238 [
239 'ns' => 1,
240 'title' => 'Talk:ApiQueryWatchlistRawIntegrationTestPage1',
241 ],
242 ],
243 $this->getItemsFromApiResponse( $resultDirAsc )
244 );
245
246 $this->assertEquals(
247 [
248 [
249 'ns' => 1,
250 'title' => 'Talk:ApiQueryWatchlistRawIntegrationTestPage1',
251 ],
252 [
253 'ns' => 0,
254 'title' => 'ApiQueryWatchlistRawIntegrationTestPage2',
255 ],
256 [
257 'ns' => 0,
258 'title' => 'ApiQueryWatchlistRawIntegrationTestPage1',
259 ],
260 ],
261 $this->getItemsFromApiResponse( $resultDirDesc )
262 );
263 }
264
265 public function testAscendingIsDefaultOrder() {
266 $store = $this->getWatchedItemStore();
267
268 $store->addWatchBatchForUser( $this->getLoggedInTestUser(), [
269 new TitleValue( 0, 'ApiQueryWatchlistRawIntegrationTestPage1' ),
270 new TitleValue( 1, 'ApiQueryWatchlistRawIntegrationTestPage1' ),
271 new TitleValue( 0, 'ApiQueryWatchlistRawIntegrationTestPage2' ),
272 ] );
273
274 $resultNoDir = $this->doListWatchlistRawRequest();
275 $resultAscDir = $this->doListWatchlistRawRequest( [ 'wrdir' => 'ascending' ] );
276
277 $this->assertEquals(
278 $this->getItemsFromApiResponse( $resultNoDir ),
279 $this->getItemsFromApiResponse( $resultAscDir )
280 );
281 }
282
283 public function testFromTitleParam() {
284 $store = $this->getWatchedItemStore();
285
286 $store->addWatchBatchForUser( $this->getLoggedInTestUser(), [
287 new TitleValue( 0, 'ApiQueryWatchlistRawIntegrationTestPage1' ),
288 new TitleValue( 0, 'ApiQueryWatchlistRawIntegrationTestPage2' ),
289 new TitleValue( 0, 'ApiQueryWatchlistRawIntegrationTestPage3' ),
290 ] );
291
292 $result = $this->doListWatchlistRawRequest( [
293 'wrfromtitle' => 'ApiQueryWatchlistRawIntegrationTestPage2',
294 ] );
295
296 $this->assertEquals(
297 [
298 [
299 'ns' => 0,
300 'title' => 'ApiQueryWatchlistRawIntegrationTestPage2',
301 ],
302 [
303 'ns' => 0,
304 'title' => 'ApiQueryWatchlistRawIntegrationTestPage3',
305 ],
306 ],
307 $this->getItemsFromApiResponse( $result )
308 );
309 }
310
311 public function testToTitleParam() {
312 $store = $this->getWatchedItemStore();
313
314 $store->addWatchBatchForUser( $this->getLoggedInTestUser(), [
315 new TitleValue( 0, 'ApiQueryWatchlistRawIntegrationTestPage1' ),
316 new TitleValue( 0, 'ApiQueryWatchlistRawIntegrationTestPage2' ),
317 new TitleValue( 0, 'ApiQueryWatchlistRawIntegrationTestPage3' ),
318 ] );
319
320 $result = $this->doListWatchlistRawRequest( [
321 'wrtotitle' => 'ApiQueryWatchlistRawIntegrationTestPage2',
322 ] );
323
324 $this->assertEquals(
325 [
326 [
327 'ns' => 0,
328 'title' => 'ApiQueryWatchlistRawIntegrationTestPage1',
329 ],
330 [
331 'ns' => 0,
332 'title' => 'ApiQueryWatchlistRawIntegrationTestPage2',
333 ],
334 ],
335 $this->getItemsFromApiResponse( $result )
336 );
337 }
338
339 public function testContinueParam() {
340 $store = $this->getWatchedItemStore();
341
342 $store->addWatchBatchForUser( $this->getLoggedInTestUser(), [
343 new TitleValue( 0, 'ApiQueryWatchlistRawIntegrationTestPage1' ),
344 new TitleValue( 0, 'ApiQueryWatchlistRawIntegrationTestPage2' ),
345 new TitleValue( 0, 'ApiQueryWatchlistRawIntegrationTestPage3' ),
346 ] );
347
348 $firstResult = $this->doListWatchlistRawRequest( [ 'wrlimit' => 2 ] );
349 $continuationParam = $firstResult[0]['continue']['wrcontinue'];
350
351 $this->assertEquals( '0|ApiQueryWatchlistRawIntegrationTestPage3', $continuationParam );
352
353 $continuedResult = $this->doListWatchlistRawRequest( [ 'wrcontinue' => $continuationParam ] );
354
355 $this->assertEquals(
356 [
357 [
358 'ns' => 0,
359 'title' => 'ApiQueryWatchlistRawIntegrationTestPage3',
360 ]
361 ],
362 $this->getItemsFromApiResponse( $continuedResult )
363 );
364 }
365
366 public function fromTitleToTitleContinueComboProvider() {
367 return [
368 [
369 [
370 'wrfromtitle' => 'ApiQueryWatchlistRawIntegrationTestPage1',
371 'wrtotitle' => 'ApiQueryWatchlistRawIntegrationTestPage2',
372 ],
373 [
374 [ 'ns' => 0, 'title' => 'ApiQueryWatchlistRawIntegrationTestPage1' ],
375 [ 'ns' => 0, 'title' => 'ApiQueryWatchlistRawIntegrationTestPage2' ],
376 ],
377 ],
378 [
379 [
380 'wrfromtitle' => 'ApiQueryWatchlistRawIntegrationTestPage1',
381 'wrcontinue' => '0|ApiQueryWatchlistRawIntegrationTestPage3',
382 ],
383 [
384 [ 'ns' => 0, 'title' => 'ApiQueryWatchlistRawIntegrationTestPage3' ],
385 ],
386 ],
387 [
388 [
389 'wrtotitle' => 'ApiQueryWatchlistRawIntegrationTestPage3',
390 'wrcontinue' => '0|ApiQueryWatchlistRawIntegrationTestPage2',
391 ],
392 [
393 [ 'ns' => 0, 'title' => 'ApiQueryWatchlistRawIntegrationTestPage2' ],
394 [ 'ns' => 0, 'title' => 'ApiQueryWatchlistRawIntegrationTestPage3' ],
395 ],
396 ],
397 [
398 [
399 'wrfromtitle' => 'ApiQueryWatchlistRawIntegrationTestPage1',
400 'wrtotitle' => 'ApiQueryWatchlistRawIntegrationTestPage3',
401 'wrcontinue' => '0|ApiQueryWatchlistRawIntegrationTestPage3',
402 ],
403 [
404 [ 'ns' => 0, 'title' => 'ApiQueryWatchlistRawIntegrationTestPage3' ],
405 ],
406 ],
407 ];
408 }
409
410 /**
411 * @dataProvider fromTitleToTitleContinueComboProvider
412 */
413 public function testFromTitleToTitleContinueCombo( array $params, array $expectedItems ) {
414 $store = $this->getWatchedItemStore();
415
416 $store->addWatchBatchForUser( $this->getLoggedInTestUser(), [
417 new TitleValue( 0, 'ApiQueryWatchlistRawIntegrationTestPage1' ),
418 new TitleValue( 0, 'ApiQueryWatchlistRawIntegrationTestPage2' ),
419 new TitleValue( 0, 'ApiQueryWatchlistRawIntegrationTestPage3' ),
420 ] );
421
422 $result = $this->doListWatchlistRawRequest( $params );
423
424 $this->assertEquals( $expectedItems, $this->getItemsFromApiResponse( $result ) );
425 }
426
427 public function fromTitleToTitleContinueSelfContradictoryComboProvider() {
428 return [
429 [
430 [
431 'wrfromtitle' => 'ApiQueryWatchlistRawIntegrationTestPage2',
432 'wrtotitle' => 'ApiQueryWatchlistRawIntegrationTestPage1',
433 ]
434 ],
435 [
436 [
437 'wrfromtitle' => 'ApiQueryWatchlistRawIntegrationTestPage1',
438 'wrtotitle' => 'ApiQueryWatchlistRawIntegrationTestPage2',
439 'wrdir' => 'descending',
440 ]
441 ],
442 [
443 [
444 'wrtotitle' => 'ApiQueryWatchlistRawIntegrationTestPage1',
445 'wrcontinue' => '0|ApiQueryWatchlistRawIntegrationTestPage2',
446 ]
447 ],
448 ];
449 }
450
451 /**
452 * @dataProvider fromTitleToTitleContinueSelfContradictoryComboProvider
453 */
454 public function testFromTitleToTitleContinueSelfContradictoryCombo( array $params ) {
455 $store = $this->getWatchedItemStore();
456
457 $store->addWatchBatchForUser( $this->getLoggedInTestUser(), [
458 new TitleValue( 0, 'ApiQueryWatchlistRawIntegrationTestPage1' ),
459 new TitleValue( 0, 'ApiQueryWatchlistRawIntegrationTestPage2' ),
460 ] );
461
462 $result = $this->doListWatchlistRawRequest( $params );
463
464 $this->assertEmpty( $this->getItemsFromApiResponse( $result ) );
465 $this->assertArrayNotHasKey( 'continue', $result[0] );
466 }
467
468 public function testOwnerAndTokenParams() {
469 $otherUser = $this->getNotLoggedInTestUser();
470 $otherUser->setOption( 'watchlisttoken', '1234567890' );
471 $otherUser->saveSettings();
472
473 $store = $this->getWatchedItemStore();
474 $store->addWatchBatchForUser( $otherUser, [
475 new TitleValue( 0, 'ApiQueryWatchlistRawIntegrationTestPage1' ),
476 new TitleValue( 1, 'ApiQueryWatchlistRawIntegrationTestPage1' ),
477 ] );
478
479 MediaWikiServices::getInstance()->getMainWANObjectCache()->clearProcessCache();
480 $result = $this->doListWatchlistRawRequest( [
481 'wrowner' => $otherUser->getName(),
482 'wrtoken' => '1234567890',
483 ] );
484
485 $this->assertEquals(
486 [
487 [
488 'ns' => 0,
489 'title' => 'ApiQueryWatchlistRawIntegrationTestPage1',
490 ],
491 [
492 'ns' => 1,
493 'title' => 'Talk:ApiQueryWatchlistRawIntegrationTestPage1',
494 ],
495 ],
496 $this->getItemsFromApiResponse( $result )
497 );
498 }
499
500 public function testOwnerAndTokenParams_wrongToken() {
501 $otherUser = $this->getNotLoggedInTestUser();
502 $otherUser->setOption( 'watchlisttoken', '1234567890' );
503 $otherUser->saveSettings();
504
505 $this->setExpectedException( ApiUsageException::class, 'Incorrect watchlist token provided' );
506
507 $this->doListWatchlistRawRequest( [
508 'wrowner' => $otherUser->getName(),
509 'wrtoken' => 'wrong-token',
510 ] );
511 }
512
513 public function testOwnerAndTokenParams_userHasNoWatchlistToken() {
514 $this->setExpectedException( ApiUsageException::class, 'Incorrect watchlist token provided' );
515
516 $this->doListWatchlistRawRequest( [
517 'wrowner' => $this->getNotLoggedInTestUser()->getName(),
518 'wrtoken' => 'some-watchlist-token',
519 ] );
520 }
521
522 public function testGeneratorWatchlistRawPropInfo_returnsWatchedItems() {
523 $store = $this->getWatchedItemStore();
524 $store->addWatch(
525 $this->getLoggedInTestUser(),
526 new TitleValue( 0, 'ApiQueryWatchlistRawIntegrationTestPage' )
527 );
528
529 $result = $this->doGeneratorWatchlistRawRequest( [ 'prop' => 'info' ] );
530
531 $this->assertArrayHasKey( 'query', $result[0] );
532 $this->assertArrayHasKey( 'pages', $result[0]['query'] );
533 $this->assertCount( 1, $result[0]['query']['pages'] );
534
535 // $result[0]['query']['pages'] uses page ids as keys
536 $item = array_values( $result[0]['query']['pages'] )[0];
537
538 $this->assertEquals( 0, $item['ns'] );
539 $this->assertEquals( 'ApiQueryWatchlistRawIntegrationTestPage', $item['title'] );
540 }
541
542 }