ApiQueryWatchlistRawIntegrationTest.php 15 KB

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