LinksTest.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393
  1. <?php
  2. namespace Shaarli\Api\Controllers;
  3. use Slim\Container;
  4. use Slim\Http\Environment;
  5. use Slim\Http\Request;
  6. use Slim\Http\Response;
  7. /**
  8. * Class LinksTest
  9. *
  10. * Test Links REST API services.
  11. * Note that api call results are tightly related to data contained in ReferenceLinkDB.
  12. *
  13. * @package Shaarli\Api\Controllers
  14. */
  15. class LinksTest extends \PHPUnit_Framework_TestCase
  16. {
  17. /**
  18. * @var string datastore to test write operations
  19. */
  20. protected static $testDatastore = 'sandbox/datastore.php';
  21. /**
  22. * @var \ConfigManager instance
  23. */
  24. protected $conf;
  25. /**
  26. * @var \ReferenceLinkDB instance.
  27. */
  28. protected $refDB = null;
  29. /**
  30. * @var Container instance.
  31. */
  32. protected $container;
  33. /**
  34. * @var Links controller instance.
  35. */
  36. protected $controller;
  37. /**
  38. * Number of JSON field per link.
  39. */
  40. const NB_FIELDS_LINK = 9;
  41. /**
  42. * Before every test, instantiate a new Api with its config, plugins and links.
  43. */
  44. public function setUp()
  45. {
  46. $this->conf = new \ConfigManager('tests/utils/config/configJson.json.php');
  47. $this->refDB = new \ReferenceLinkDB();
  48. $this->refDB->write(self::$testDatastore);
  49. $this->container = new Container();
  50. $this->container['conf'] = $this->conf;
  51. $this->container['db'] = new \LinkDB(self::$testDatastore, true, false);
  52. $this->controller = new Links($this->container);
  53. }
  54. /**
  55. * After every test, remove the test datastore.
  56. */
  57. public function tearDown()
  58. {
  59. @unlink(self::$testDatastore);
  60. }
  61. /**
  62. * Test basic getLinks service: returns all links.
  63. */
  64. public function testGetLinks()
  65. {
  66. // Used by index_url().
  67. $_SERVER['SERVER_NAME'] = 'domain.tld';
  68. $_SERVER['SERVER_PORT'] = 80;
  69. $_SERVER['SCRIPT_NAME'] = '/';
  70. $env = Environment::mock([
  71. 'REQUEST_METHOD' => 'GET',
  72. ]);
  73. $request = Request::createFromEnvironment($env);
  74. $response = $this->controller->getLinks($request, new Response());
  75. $this->assertEquals(200, $response->getStatusCode());
  76. $data = json_decode((string) $response->getBody(), true);
  77. $this->assertEquals($this->refDB->countLinks(), count($data));
  78. // Check order
  79. $order = [41, 8, 6, 7, 0, 1, 4, 42];
  80. $cpt = 0;
  81. foreach ($data as $link) {
  82. $this->assertEquals(self::NB_FIELDS_LINK, count($link));
  83. $this->assertEquals($order[$cpt++], $link['id']);
  84. }
  85. // Check first element fields\
  86. $first = $data[0];
  87. $this->assertEquals('http://domain.tld/?WDWyig', $first['url']);
  88. $this->assertEquals('WDWyig', $first['shorturl']);
  89. $this->assertEquals('Link title: @website', $first['title']);
  90. $this->assertEquals(
  91. 'Stallman has a beard and is part of the Free Software Foundation (or not). Seriously, read this. #hashtag',
  92. $first['description']
  93. );
  94. $this->assertEquals('sTuff', $first['tags'][0]);
  95. $this->assertEquals(false, $first['private']);
  96. $this->assertEquals(
  97. \DateTime::createFromFormat(\LinkDB::LINK_DATE_FORMAT, '20150310_114651')->format(\DateTime::ATOM),
  98. $first['created']
  99. );
  100. $this->assertEmpty($first['updated']);
  101. // Multi tags
  102. $link = $data[1];
  103. $this->assertEquals(7, count($link['tags']));
  104. // Update date
  105. $this->assertEquals(
  106. \DateTime::createFromFormat(\LinkDB::LINK_DATE_FORMAT, '20160803_093033')->format(\DateTime::ATOM),
  107. $link['updated']
  108. );
  109. }
  110. /**
  111. * Test getLinks service with offset and limit parameter:
  112. * limit=1 and offset=1 should return only the second link, ID=8 (ordered by creation date DESC).
  113. */
  114. public function testGetLinksOffsetLimit()
  115. {
  116. $env = Environment::mock([
  117. 'REQUEST_METHOD' => 'GET',
  118. 'QUERY_STRING' => 'offset=1&limit=1'
  119. ]);
  120. $request = Request::createFromEnvironment($env);
  121. $response = $this->controller->getLinks($request, new Response());
  122. $this->assertEquals(200, $response->getStatusCode());
  123. $data = json_decode((string) $response->getBody(), true);
  124. $this->assertEquals(1, count($data));
  125. $this->assertEquals(8, $data[0]['id']);
  126. $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
  127. }
  128. /**
  129. * Test getLinks with limit=all (return all link).
  130. */
  131. public function testGetLinksLimitAll()
  132. {
  133. $env = Environment::mock([
  134. 'REQUEST_METHOD' => 'GET',
  135. 'QUERY_STRING' => 'limit=all'
  136. ]);
  137. $request = Request::createFromEnvironment($env);
  138. $response = $this->controller->getLinks($request, new Response());
  139. $this->assertEquals(200, $response->getStatusCode());
  140. $data = json_decode((string) $response->getBody(), true);
  141. $this->assertEquals($this->refDB->countLinks(), count($data));
  142. // Check order
  143. $order = [41, 8, 6, 7, 0, 1, 4, 42];
  144. $cpt = 0;
  145. foreach ($data as $link) {
  146. $this->assertEquals(self::NB_FIELDS_LINK, count($link));
  147. $this->assertEquals($order[$cpt++], $link['id']);
  148. }
  149. }
  150. /**
  151. * Test getLinks service with offset and limit parameter:
  152. * limit=1 and offset=1 should return only the second link, ID=8 (ordered by creation date DESC).
  153. */
  154. public function testGetLinksOffsetTooHigh()
  155. {
  156. $env = Environment::mock([
  157. 'REQUEST_METHOD' => 'GET',
  158. 'QUERY_STRING' => 'offset=100'
  159. ]);
  160. $request = Request::createFromEnvironment($env);
  161. $response = $this->controller->getLinks($request, new Response());
  162. $this->assertEquals(200, $response->getStatusCode());
  163. $data = json_decode((string) $response->getBody(), true);
  164. $this->assertEmpty(count($data));
  165. }
  166. /**
  167. * Test getLinks with private attribute to 1 or true.
  168. */
  169. public function testGetLinksPrivate()
  170. {
  171. $env = Environment::mock([
  172. 'REQUEST_METHOD' => 'GET',
  173. 'QUERY_STRING' => 'private=true'
  174. ]);
  175. $request = Request::createFromEnvironment($env);
  176. $response = $this->controller->getLinks($request, new Response());
  177. $this->assertEquals(200, $response->getStatusCode());
  178. $data = json_decode((string) $response->getBody(), true);
  179. $this->assertEquals($this->refDB->countPrivateLinks(), count($data));
  180. $this->assertEquals(6, $data[0]['id']);
  181. $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
  182. $env = Environment::mock([
  183. 'REQUEST_METHOD' => 'GET',
  184. 'QUERY_STRING' => 'private=1'
  185. ]);
  186. $request = Request::createFromEnvironment($env);
  187. $response = $this->controller->getLinks($request, new Response());
  188. $this->assertEquals(200, $response->getStatusCode());
  189. $data = json_decode((string) $response->getBody(), true);
  190. $this->assertEquals($this->refDB->countPrivateLinks(), count($data));
  191. $this->assertEquals(6, $data[0]['id']);
  192. $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
  193. }
  194. /**
  195. * Test getLinks with private attribute to false or 0
  196. */
  197. public function testGetLinksNotPrivate()
  198. {
  199. $env = Environment::mock(
  200. [
  201. 'REQUEST_METHOD' => 'GET',
  202. 'QUERY_STRING' => 'private=0'
  203. ]
  204. );
  205. $request = Request::createFromEnvironment($env);
  206. $response = $this->controller->getLinks($request, new Response());
  207. $this->assertEquals(200, $response->getStatusCode());
  208. $data = json_decode((string)$response->getBody(), true);
  209. $this->assertEquals($this->refDB->countLinks(), count($data));
  210. $this->assertEquals(41, $data[0]['id']);
  211. $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
  212. $env = Environment::mock(
  213. [
  214. 'REQUEST_METHOD' => 'GET',
  215. 'QUERY_STRING' => 'private=false'
  216. ]
  217. );
  218. $request = Request::createFromEnvironment($env);
  219. $response = $this->controller->getLinks($request, new Response());
  220. $this->assertEquals(200, $response->getStatusCode());
  221. $data = json_decode((string)$response->getBody(), true);
  222. $this->assertEquals($this->refDB->countLinks(), count($data));
  223. $this->assertEquals(41, $data[0]['id']);
  224. $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
  225. }
  226. /**
  227. * Test getLinks service with offset and limit parameter:
  228. * limit=1 and offset=1 should return only the second link, ID=8 (ordered by creation date DESC).
  229. */
  230. public function testGetLinksSearchTerm()
  231. {
  232. // Only in description - 1 result
  233. $env = Environment::mock([
  234. 'REQUEST_METHOD' => 'GET',
  235. 'QUERY_STRING' => 'searchterm=Tropical'
  236. ]);
  237. $request = Request::createFromEnvironment($env);
  238. $response = $this->controller->getLinks($request, new Response());
  239. $this->assertEquals(200, $response->getStatusCode());
  240. $data = json_decode((string) $response->getBody(), true);
  241. $this->assertEquals(1, count($data));
  242. $this->assertEquals(1, $data[0]['id']);
  243. $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
  244. // Only in tags - 1 result
  245. $env = Environment::mock([
  246. 'REQUEST_METHOD' => 'GET',
  247. 'QUERY_STRING' => 'searchterm=tag3'
  248. ]);
  249. $request = Request::createFromEnvironment($env);
  250. $response = $this->controller->getLinks($request, new Response());
  251. $this->assertEquals(200, $response->getStatusCode());
  252. $data = json_decode((string) $response->getBody(), true);
  253. $this->assertEquals(1, count($data));
  254. $this->assertEquals(0, $data[0]['id']);
  255. $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
  256. // Multiple results (2)
  257. $env = Environment::mock([
  258. 'REQUEST_METHOD' => 'GET',
  259. 'QUERY_STRING' => 'searchterm=stallman'
  260. ]);
  261. $request = Request::createFromEnvironment($env);
  262. $response = $this->controller->getLinks($request, new Response());
  263. $this->assertEquals(200, $response->getStatusCode());
  264. $data = json_decode((string) $response->getBody(), true);
  265. $this->assertEquals(2, count($data));
  266. $this->assertEquals(41, $data[0]['id']);
  267. $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
  268. $this->assertEquals(8, $data[1]['id']);
  269. $this->assertEquals(self::NB_FIELDS_LINK, count($data[1]));
  270. // Multiword - 2 results
  271. $env = Environment::mock([
  272. 'REQUEST_METHOD' => 'GET',
  273. 'QUERY_STRING' => 'searchterm=stallman+software'
  274. ]);
  275. $request = Request::createFromEnvironment($env);
  276. $response = $this->controller->getLinks($request, new Response());
  277. $this->assertEquals(200, $response->getStatusCode());
  278. $data = json_decode((string) $response->getBody(), true);
  279. $this->assertEquals(2, count($data));
  280. $this->assertEquals(41, $data[0]['id']);
  281. $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
  282. $this->assertEquals(8, $data[1]['id']);
  283. $this->assertEquals(self::NB_FIELDS_LINK, count($data[1]));
  284. // URL encoding
  285. $env = Environment::mock([
  286. 'REQUEST_METHOD' => 'GET',
  287. 'QUERY_STRING' => 'searchterm='. urlencode('@web')
  288. ]);
  289. $request = Request::createFromEnvironment($env);
  290. $response = $this->controller->getLinks($request, new Response());
  291. $this->assertEquals(200, $response->getStatusCode());
  292. $data = json_decode((string) $response->getBody(), true);
  293. $this->assertEquals(2, count($data));
  294. $this->assertEquals(41, $data[0]['id']);
  295. $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
  296. $this->assertEquals(8, $data[1]['id']);
  297. $this->assertEquals(self::NB_FIELDS_LINK, count($data[1]));
  298. }
  299. public function testGetLinksSearchTermNoResult()
  300. {
  301. $env = Environment::mock([
  302. 'REQUEST_METHOD' => 'GET',
  303. 'QUERY_STRING' => 'searchterm=nope'
  304. ]);
  305. $request = Request::createFromEnvironment($env);
  306. $response = $this->controller->getLinks($request, new Response());
  307. $this->assertEquals(200, $response->getStatusCode());
  308. $data = json_decode((string) $response->getBody(), true);
  309. $this->assertEquals(0, count($data));
  310. }
  311. public function testGetLinksSearchTags()
  312. {
  313. // Single tag
  314. $env = Environment::mock([
  315. 'REQUEST_METHOD' => 'GET',
  316. 'QUERY_STRING' => 'searchtags=dev',
  317. ]);
  318. $request = Request::createFromEnvironment($env);
  319. $response = $this->controller->getLinks($request, new Response());
  320. $this->assertEquals(200, $response->getStatusCode());
  321. $data = json_decode((string) $response->getBody(), true);
  322. $this->assertEquals(2, count($data));
  323. $this->assertEquals(0, $data[0]['id']);
  324. $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
  325. $this->assertEquals(4, $data[1]['id']);
  326. $this->assertEquals(self::NB_FIELDS_LINK, count($data[1]));
  327. // Multitag + exclude
  328. $env = Environment::mock([
  329. 'REQUEST_METHOD' => 'GET',
  330. 'QUERY_STRING' => 'searchtags=stuff+-gnu',
  331. ]);
  332. $request = Request::createFromEnvironment($env);
  333. $response = $this->controller->getLinks($request, new Response());
  334. $this->assertEquals(200, $response->getStatusCode());
  335. $data = json_decode((string) $response->getBody(), true);
  336. $this->assertEquals(1, count($data));
  337. $this->assertEquals(41, $data[0]['id']);
  338. $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
  339. }
  340. /**
  341. * Test getLinks service with search tags+terms.
  342. */
  343. public function testGetLinksSearchTermsAndTags()
  344. {
  345. $env = Environment::mock([
  346. 'REQUEST_METHOD' => 'GET',
  347. 'QUERY_STRING' => 'searchterm=poke&searchtags=dev',
  348. ]);
  349. $request = Request::createFromEnvironment($env);
  350. $response = $this->controller->getLinks($request, new Response());
  351. $this->assertEquals(200, $response->getStatusCode());
  352. $data = json_decode((string) $response->getBody(), true);
  353. $this->assertEquals(1, count($data));
  354. $this->assertEquals(0, $data[0]['id']);
  355. $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
  356. }
  357. }