2 namespace Shaarli\Api\Controllers
;
4 use Shaarli\Bookmark\LinkDB
;
5 use Shaarli\Config\ConfigManager
;
7 use Slim\Http\Environment
;
9 use Slim\Http\Response
;
14 * Test get Link list REST API service.
16 * @see http://shaarli.github.io/api-documentation/#links-links-collection-get
18 * @package Shaarli\Api\Controllers
20 class GetLinksTest
extends \PHPUnit\Framework\TestCase
23 * @var string datastore to test write operations
25 protected static $testDatastore = 'sandbox/datastore.php';
28 * @var ConfigManager instance
33 * @var \ReferenceLinkDB instance.
35 protected $refDB = null;
38 * @var Container instance.
43 * @var Links controller instance.
45 protected $controller;
48 * Number of JSON field per link.
50 const NB_FIELDS_LINK
= 9;
53 * Before every test, instantiate a new Api with its config, plugins and links.
55 public function setUp()
57 $this->conf
= new ConfigManager('tests/utils/config/configJson');
58 $this->refDB
= new \
ReferenceLinkDB();
59 $this->refDB
->write(self
::$testDatastore);
61 $this->container
= new Container();
62 $this->container
['conf'] = $this->conf
;
63 $this->container
['db'] = new LinkDB(self
::$testDatastore, true, false);
64 $this->container
['history'] = null;
66 $this->controller
= new Links($this->container
);
70 * After every test, remove the test datastore.
72 public function tearDown()
74 @unlink(self
::$testDatastore);
78 * Test basic getLinks service: returns all links.
80 public function testGetLinks()
82 // Used by index_url().
83 $_SERVER['SERVER_NAME'] = 'domain.tld';
84 $_SERVER['SERVER_PORT'] = 80;
85 $_SERVER['SCRIPT_NAME'] = '/';
87 $env = Environment
::mock([
88 'REQUEST_METHOD' => 'GET',
90 $request = Request
::createFromEnvironment($env);
92 $response = $this->controller
->getLinks($request, new Response());
93 $this->assertEquals(200, $response->getStatusCode());
94 $data = json_decode((string) $response->getBody(), true);
95 $this->assertEquals($this->refDB
->countLinks(), count($data));
98 $order = [10, 11, 41, 8, 6, 7, 0, 1, 9, 4, 42];
100 foreach ($data as $link) {
101 $this->assertEquals(self
::NB_FIELDS_LINK
, count($link));
102 $this->assertEquals($order[$cpt++
], $link['id']);
105 // Check first element fields
107 $this->assertEquals('http://domain.tld/?WDWyig', $first['url']);
108 $this->assertEquals('WDWyig', $first['shorturl']);
109 $this->assertEquals('Link title: @website', $first['title']);
111 'Stallman has a beard and is part of the Free Software Foundation (or not). Seriously, read this. #hashtag',
112 $first['description']
114 $this->assertEquals('sTuff', $first['tags'][0]);
115 $this->assertEquals(false, $first['private']);
117 \DateTime
::createFromFormat(LinkDB
::LINK_DATE_FORMAT
, '20150310_114651')->format(\DateTime
::ATOM
),
120 $this->assertEmpty($first['updated']);
124 $this->assertEquals(7, count($link['tags']));
128 \DateTime
::createFromFormat(LinkDB
::LINK_DATE_FORMAT
, '20160803_093033')->format(\DateTime
::ATOM
),
134 * Test getLinks service with offset and limit parameter:
135 * limit=1 and offset=1 should return only the second link, ID=8 (ordered by creation date DESC).
137 public function testGetLinksOffsetLimit()
139 $env = Environment
::mock([
140 'REQUEST_METHOD' => 'GET',
141 'QUERY_STRING' => 'offset=3&limit=1'
143 $request = Request
::createFromEnvironment($env);
144 $response = $this->controller
->getLinks($request, new Response());
145 $this->assertEquals(200, $response->getStatusCode());
146 $data = json_decode((string) $response->getBody(), true);
147 $this->assertEquals(1, count($data));
148 $this->assertEquals(8, $data[0]['id']);
149 $this->assertEquals(self
::NB_FIELDS_LINK
, count($data[0]));
153 * Test getLinks with limit=all (return all link).
155 public function testGetLinksLimitAll()
157 $env = Environment
::mock([
158 'REQUEST_METHOD' => 'GET',
159 'QUERY_STRING' => 'limit=all'
161 $request = Request
::createFromEnvironment($env);
162 $response = $this->controller
->getLinks($request, new Response());
163 $this->assertEquals(200, $response->getStatusCode());
164 $data = json_decode((string) $response->getBody(), true);
165 $this->assertEquals($this->refDB
->countLinks(), count($data));
167 $order = [10, 11, 41, 8, 6, 7, 0, 1, 9, 4, 42];
169 foreach ($data as $link) {
170 $this->assertEquals(self
::NB_FIELDS_LINK
, count($link));
171 $this->assertEquals($order[$cpt++
], $link['id']);
176 * Test getLinks service with offset and limit parameter:
177 * limit=1 and offset=1 should return only the second link, ID=8 (ordered by creation date DESC).
179 public function testGetLinksOffsetTooHigh()
181 $env = Environment
::mock([
182 'REQUEST_METHOD' => 'GET',
183 'QUERY_STRING' => 'offset=100'
185 $request = Request
::createFromEnvironment($env);
186 $response = $this->controller
->getLinks($request, new Response());
187 $this->assertEquals(200, $response->getStatusCode());
188 $data = json_decode((string) $response->getBody(), true);
189 $this->assertEmpty(count($data));
193 * Test getLinks with visibility parameter set to all
195 public function testGetLinksVisibilityAll()
197 $env = Environment
::mock(
199 'REQUEST_METHOD' => 'GET',
200 'QUERY_STRING' => 'visibility=all'
203 $request = Request
::createFromEnvironment($env);
204 $response = $this->controller
->getLinks($request, new Response());
205 $this->assertEquals(200, $response->getStatusCode());
206 $data = json_decode((string)$response->getBody(), true);
207 $this->assertEquals($this->refDB
->countLinks(), count($data));
208 $this->assertEquals(10, $data[0]['id']);
209 $this->assertEquals(41, $data[2]['id']);
210 $this->assertEquals(self
::NB_FIELDS_LINK
, count($data[0]));
214 * Test getLinks with visibility parameter set to private
216 public function testGetLinksVisibilityPrivate()
218 $env = Environment
::mock([
219 'REQUEST_METHOD' => 'GET',
220 'QUERY_STRING' => 'visibility=private'
222 $request = Request
::createFromEnvironment($env);
223 $response = $this->controller
->getLinks($request, new Response());
224 $this->assertEquals(200, $response->getStatusCode());
225 $data = json_decode((string) $response->getBody(), true);
226 $this->assertEquals($this->refDB
->countPrivateLinks(), count($data));
227 $this->assertEquals(6, $data[0]['id']);
228 $this->assertEquals(self
::NB_FIELDS_LINK
, count($data[0]));
232 * Test getLinks with visibility parameter set to public
234 public function testGetLinksVisibilityPublic()
236 $env = Environment
::mock(
238 'REQUEST_METHOD' => 'GET',
239 'QUERY_STRING' => 'visibility=public'
242 $request = Request
::createFromEnvironment($env);
243 $response = $this->controller
->getLinks($request, new Response());
244 $this->assertEquals(200, $response->getStatusCode());
245 $data = json_decode((string)$response->getBody(), true);
246 $this->assertEquals($this->refDB
->countPublicLinks(), count($data));
247 $this->assertEquals(10, $data[0]['id']);
248 $this->assertEquals(41, $data[2]['id']);
249 $this->assertEquals(self
::NB_FIELDS_LINK
, count($data[0]));
253 * Test getLinks service with offset and limit parameter:
254 * limit=1 and offset=1 should return only the second link, ID=8 (ordered by creation date DESC).
256 public function testGetLinksSearchTerm()
258 // Only in description - 1 result
259 $env = Environment
::mock([
260 'REQUEST_METHOD' => 'GET',
261 'QUERY_STRING' => 'searchterm=Tropical'
263 $request = Request
::createFromEnvironment($env);
264 $response = $this->controller
->getLinks($request, new Response());
265 $this->assertEquals(200, $response->getStatusCode());
266 $data = json_decode((string) $response->getBody(), true);
267 $this->assertEquals(1, count($data));
268 $this->assertEquals(1, $data[0]['id']);
269 $this->assertEquals(self
::NB_FIELDS_LINK
, count($data[0]));
271 // Only in tags - 1 result
272 $env = Environment
::mock([
273 'REQUEST_METHOD' => 'GET',
274 'QUERY_STRING' => 'searchterm=tag3'
276 $request = Request
::createFromEnvironment($env);
277 $response = $this->controller
->getLinks($request, new Response());
278 $this->assertEquals(200, $response->getStatusCode());
279 $data = json_decode((string) $response->getBody(), true);
280 $this->assertEquals(1, count($data));
281 $this->assertEquals(0, $data[0]['id']);
282 $this->assertEquals(self
::NB_FIELDS_LINK
, count($data[0]));
284 // Multiple results (2)
285 $env = Environment
::mock([
286 'REQUEST_METHOD' => 'GET',
287 'QUERY_STRING' => 'searchterm=stallman'
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]));
299 // Multiword - 2 results
300 $env = Environment
::mock([
301 'REQUEST_METHOD' => 'GET',
302 'QUERY_STRING' => 'searchterm=stallman+software'
304 $request = Request
::createFromEnvironment($env);
305 $response = $this->controller
->getLinks($request, new Response());
306 $this->assertEquals(200, $response->getStatusCode());
307 $data = json_decode((string) $response->getBody(), true);
308 $this->assertEquals(2, count($data));
309 $this->assertEquals(41, $data[0]['id']);
310 $this->assertEquals(self
::NB_FIELDS_LINK
, count($data[0]));
311 $this->assertEquals(8, $data[1]['id']);
312 $this->assertEquals(self
::NB_FIELDS_LINK
, count($data[1]));
315 $env = Environment
::mock([
316 'REQUEST_METHOD' => 'GET',
317 'QUERY_STRING' => 'searchterm='. urlencode('@web')
319 $request = Request
::createFromEnvironment($env);
320 $response = $this->controller
->getLinks($request, new Response());
321 $this->assertEquals(200, $response->getStatusCode());
322 $data = json_decode((string) $response->getBody(), true);
323 $this->assertEquals(2, count($data));
324 $this->assertEquals(41, $data[0]['id']);
325 $this->assertEquals(self
::NB_FIELDS_LINK
, count($data[0]));
326 $this->assertEquals(8, $data[1]['id']);
327 $this->assertEquals(self
::NB_FIELDS_LINK
, count($data[1]));
330 public function testGetLinksSearchTermNoResult()
332 $env = Environment
::mock([
333 'REQUEST_METHOD' => 'GET',
334 'QUERY_STRING' => 'searchterm=nope'
336 $request = Request
::createFromEnvironment($env);
337 $response = $this->controller
->getLinks($request, new Response());
338 $this->assertEquals(200, $response->getStatusCode());
339 $data = json_decode((string) $response->getBody(), true);
340 $this->assertEquals(0, count($data));
343 public function testGetLinksSearchTags()
346 $env = Environment
::mock([
347 'REQUEST_METHOD' => 'GET',
348 'QUERY_STRING' => 'searchtags=dev',
350 $request = Request
::createFromEnvironment($env);
351 $response = $this->controller
->getLinks($request, new Response());
352 $this->assertEquals(200, $response->getStatusCode());
353 $data = json_decode((string) $response->getBody(), true);
354 $this->assertEquals(2, count($data));
355 $this->assertEquals(0, $data[0]['id']);
356 $this->assertEquals(self
::NB_FIELDS_LINK
, count($data[0]));
357 $this->assertEquals(4, $data[1]['id']);
358 $this->assertEquals(self
::NB_FIELDS_LINK
, count($data[1]));
360 // Multitag + exclude
361 $env = Environment
::mock([
362 'REQUEST_METHOD' => 'GET',
363 'QUERY_STRING' => 'searchtags=stuff+-gnu',
365 $request = Request
::createFromEnvironment($env);
366 $response = $this->controller
->getLinks($request, new Response());
367 $this->assertEquals(200, $response->getStatusCode());
368 $data = json_decode((string) $response->getBody(), true);
369 $this->assertEquals(1, count($data));
370 $this->assertEquals(41, $data[0]['id']);
371 $this->assertEquals(self
::NB_FIELDS_LINK
, count($data[0]));
373 // wildcard: placeholder at the start
374 $env = Environment
::mock([
375 'REQUEST_METHOD' => 'GET',
376 'QUERY_STRING' => 'searchtags=*Tuff',
378 $request = Request
::createFromEnvironment($env);
379 $response = $this->controller
->getLinks($request, new Response());
380 $this->assertEquals(200, $response->getStatusCode());
381 $data = json_decode((string) $response->getBody(), true);
382 $this->assertEquals(2, count($data));
383 $this->assertEquals(41, $data[0]['id']);
385 // wildcard: placeholder at the end
386 $env = Environment
::mock([
387 'REQUEST_METHOD' => 'GET',
388 'QUERY_STRING' => 'searchtags=c*',
390 $request = Request
::createFromEnvironment($env);
391 $response = $this->controller
->getLinks($request, new Response());
392 $this->assertEquals(200, $response->getStatusCode());
393 $data = json_decode((string) $response->getBody(), true);
394 $this->assertEquals(4, count($data));
395 $this->assertEquals(6, $data[0]['id']);
397 // wildcard: placeholder at the middle
398 $env = Environment
::mock([
399 'REQUEST_METHOD' => 'GET',
400 'QUERY_STRING' => 'searchtags=w*b',
402 $request = Request
::createFromEnvironment($env);
403 $response = $this->controller
->getLinks($request, new Response());
404 $this->assertEquals(200, $response->getStatusCode());
405 $data = json_decode((string) $response->getBody(), true);
406 $this->assertEquals(4, count($data));
407 $this->assertEquals(6, $data[0]['id']);
409 // wildcard: match all
410 $env = Environment
::mock([
411 'REQUEST_METHOD' => 'GET',
412 'QUERY_STRING' => 'searchtags=*',
414 $request = Request
::createFromEnvironment($env);
415 $response = $this->controller
->getLinks($request, new Response());
416 $this->assertEquals(200, $response->getStatusCode());
417 $data = json_decode((string) $response->getBody(), true);
418 $this->assertEquals(\ReferenceLinkDB
::$NB_LINKS_TOTAL, count($data));
419 $this->assertEquals(10, $data[0]['id']);
420 $this->assertEquals(41, $data[2]['id']);
422 // wildcard: optional ('*' does not need to expand)
423 $env = Environment
::mock([
424 'REQUEST_METHOD' => 'GET',
425 'QUERY_STRING' => 'searchtags=*stuff*',
427 $request = Request
::createFromEnvironment($env);
428 $response = $this->controller
->getLinks($request, new Response());
429 $this->assertEquals(200, $response->getStatusCode());
430 $data = json_decode((string) $response->getBody(), true);
431 $this->assertEquals(2, count($data));
432 $this->assertEquals(41, $data[0]['id']);
434 // wildcard: exclusions
435 $env = Environment
::mock([
436 'REQUEST_METHOD' => 'GET',
437 'QUERY_STRING' => 'searchtags=*a*+-*e*',
439 $request = Request
::createFromEnvironment($env);
440 $response = $this->controller
->getLinks($request, new Response());
441 $this->assertEquals(200, $response->getStatusCode());
442 $data = json_decode((string) $response->getBody(), true);
443 $this->assertEquals(1, count($data));
444 $this->assertEquals(41, $data[0]['id']); // finds '#hashtag' in descr.
446 // wildcard: exclude all
447 $env = Environment
::mock([
448 'REQUEST_METHOD' => 'GET',
449 'QUERY_STRING' => 'searchtags=-*',
451 $request = Request
::createFromEnvironment($env);
452 $response = $this->controller
->getLinks($request, new Response());
453 $this->assertEquals(200, $response->getStatusCode());
454 $data = json_decode((string) $response->getBody(), true);
455 $this->assertEquals(0, count($data));
459 * Test getLinks service with search tags+terms.
461 public function testGetLinksSearchTermsAndTags()
463 $env = Environment
::mock([
464 'REQUEST_METHOD' => 'GET',
465 'QUERY_STRING' => 'searchterm=poke&searchtags=dev',
467 $request = Request
::createFromEnvironment($env);
468 $response = $this->controller
->getLinks($request, new Response());
469 $this->assertEquals(200, $response->getStatusCode());
470 $data = json_decode((string) $response->getBody(), true);
471 $this->assertEquals(1, count($data));
472 $this->assertEquals(0, $data[0]['id']);
473 $this->assertEquals(self
::NB_FIELDS_LINK
, count($data[0]));