]> git.immae.eu Git - github/shaarli/Shaarli.git/blame - tests/api/controllers/links/GetLinksTest.php
New plugin hook: ability to add custom filters to Shaarli search engine
[github/shaarli/Shaarli.git] / tests / api / controllers / links / GetLinksTest.php
CommitLineData
c3b00963 1<?php
c3b00963
A
2namespace Shaarli\Api\Controllers;
3
fd1ddad9 4use malkusch\lock\mutex\NoMutex;
e26e2060
A
5use Shaarli\Bookmark\Bookmark;
6use Shaarli\Bookmark\BookmarkFileService;
dea72c71 7use Shaarli\Bookmark\LinkDB;
3c66e564 8use Shaarli\Config\ConfigManager;
e26e2060 9use Shaarli\History;
bcba6bd3 10use Shaarli\Plugin\PluginManager;
c3b00963
A
11use Slim\Container;
12use Slim\Http\Environment;
13use Slim\Http\Request;
14use Slim\Http\Response;
15
16/**
16e3d006 17 * Class GetLinksTest
c3b00963 18 *
16e3d006
A
19 * Test get Link list REST API service.
20 *
21 * @see http://shaarli.github.io/api-documentation/#links-links-collection-get
c3b00963
A
22 *
23 * @package Shaarli\Api\Controllers
24 */
a5a9cf23 25class GetLinksTest extends \Shaarli\TestCase
c3b00963
A
26{
27 /**
28 * @var string datastore to test write operations
29 */
30 protected static $testDatastore = 'sandbox/datastore.php';
31
32 /**
3c66e564 33 * @var ConfigManager instance
c3b00963
A
34 */
35 protected $conf;
36
37 /**
38 * @var \ReferenceLinkDB instance.
39 */
40 protected $refDB = null;
41
42 /**
43 * @var Container instance.
44 */
45 protected $container;
46
47 /**
48 * @var Links controller instance.
49 */
50 protected $controller;
51
52 /**
53 * Number of JSON field per link.
54 */
55 const NB_FIELDS_LINK = 9;
56
57 /**
e26e2060 58 * Before every test, instantiate a new Api with its config, plugins and bookmarks.
c3b00963 59 */
8f60e120 60 protected function setUp(): void
c3b00963 61 {
fd1ddad9 62 $mutex = new NoMutex();
3c66e564 63 $this->conf = new ConfigManager('tests/utils/config/configJson');
e26e2060 64 $this->conf->set('resource.datastore', self::$testDatastore);
c3b00963
A
65 $this->refDB = new \ReferenceLinkDB();
66 $this->refDB->write(self::$testDatastore);
e26e2060 67 $history = new History('sandbox/history.php');
c3b00963
A
68
69 $this->container = new Container();
70 $this->container['conf'] = $this->conf;
bcba6bd3
A
71 $pluginManager = new PluginManager($this->conf);
72 $this->container['db'] = new BookmarkFileService(
73 $this->conf,
74 $pluginManager,
75 $history,
76 $mutex,
77 true
78 );
813849e5 79 $this->container['history'] = null;
c3b00963
A
80
81 $this->controller = new Links($this->container);
82 }
83
84 /**
85 * After every test, remove the test datastore.
86 */
8f60e120 87 protected function tearDown(): void
c3b00963
A
88 {
89 @unlink(self::$testDatastore);
90 }
91
92 /**
e26e2060 93 * Test basic getLinks service: returns all bookmarks.
c3b00963
A
94 */
95 public function testGetLinks()
96 {
97 // Used by index_url().
98 $_SERVER['SERVER_NAME'] = 'domain.tld';
99 $_SERVER['SERVER_PORT'] = 80;
100 $_SERVER['SCRIPT_NAME'] = '/';
101
102 $env = Environment::mock([
103 'REQUEST_METHOD' => 'GET',
104 ]);
105 $request = Request::createFromEnvironment($env);
106
107 $response = $this->controller->getLinks($request, new Response());
108 $this->assertEquals(200, $response->getStatusCode());
109 $data = json_decode((string) $response->getBody(), true);
110 $this->assertEquals($this->refDB->countLinks(), count($data));
111
112 // Check order
4154c25b 113 $order = [10, 11, 41, 8, 6, 7, 0, 1, 9, 4, 42];
c3b00963
A
114 $cpt = 0;
115 foreach ($data as $link) {
116 $this->assertEquals(self::NB_FIELDS_LINK, count($link));
117 $this->assertEquals($order[$cpt++], $link['id']);
118 }
119
16e3d006 120 // Check first element fields
4154c25b 121 $first = $data[2];
f7f08cee 122 $this->assertEquals('http://domain.tld/shaare/WDWyig', $first['url']);
c3b00963
A
123 $this->assertEquals('WDWyig', $first['shorturl']);
124 $this->assertEquals('Link title: @website', $first['title']);
125 $this->assertEquals(
126 'Stallman has a beard and is part of the Free Software Foundation (or not). Seriously, read this. #hashtag',
127 $first['description']
128 );
129 $this->assertEquals('sTuff', $first['tags'][0]);
130 $this->assertEquals(false, $first['private']);
131 $this->assertEquals(
e26e2060 132 \DateTime::createFromFormat(Bookmark::LINK_DATE_FORMAT, '20150310_114651')->format(\DateTime::ATOM),
c3b00963
A
133 $first['created']
134 );
135 $this->assertEmpty($first['updated']);
136
137 // Multi tags
4154c25b 138 $link = $data[3];
c3b00963
A
139 $this->assertEquals(7, count($link['tags']));
140
141 // Update date
142 $this->assertEquals(
e26e2060 143 \DateTime::createFromFormat(Bookmark::LINK_DATE_FORMAT, '20160803_093033')->format(\DateTime::ATOM),
c3b00963
A
144 $link['updated']
145 );
146 }
147
148 /**
149 * Test getLinks service with offset and limit parameter:
150 * limit=1 and offset=1 should return only the second link, ID=8 (ordered by creation date DESC).
151 */
152 public function testGetLinksOffsetLimit()
153 {
154 $env = Environment::mock([
155 'REQUEST_METHOD' => 'GET',
4154c25b 156 'QUERY_STRING' => 'offset=3&limit=1'
c3b00963
A
157 ]);
158 $request = Request::createFromEnvironment($env);
159 $response = $this->controller->getLinks($request, new Response());
160 $this->assertEquals(200, $response->getStatusCode());
161 $data = json_decode((string) $response->getBody(), true);
162 $this->assertEquals(1, count($data));
163 $this->assertEquals(8, $data[0]['id']);
164 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
165 }
166
167 /**
168 * Test getLinks with limit=all (return all link).
169 */
170 public function testGetLinksLimitAll()
171 {
172 $env = Environment::mock([
173 'REQUEST_METHOD' => 'GET',
174 'QUERY_STRING' => 'limit=all'
175 ]);
176 $request = Request::createFromEnvironment($env);
177 $response = $this->controller->getLinks($request, new Response());
178 $this->assertEquals(200, $response->getStatusCode());
179 $data = json_decode((string) $response->getBody(), true);
180 $this->assertEquals($this->refDB->countLinks(), count($data));
181 // Check order
4154c25b 182 $order = [10, 11, 41, 8, 6, 7, 0, 1, 9, 4, 42];
c3b00963
A
183 $cpt = 0;
184 foreach ($data as $link) {
185 $this->assertEquals(self::NB_FIELDS_LINK, count($link));
186 $this->assertEquals($order[$cpt++], $link['id']);
187 }
188 }
189
190 /**
191 * Test getLinks service with offset and limit parameter:
192 * limit=1 and offset=1 should return only the second link, ID=8 (ordered by creation date DESC).
193 */
194 public function testGetLinksOffsetTooHigh()
195 {
196 $env = Environment::mock([
197 'REQUEST_METHOD' => 'GET',
198 'QUERY_STRING' => 'offset=100'
199 ]);
200 $request = Request::createFromEnvironment($env);
201 $response = $this->controller->getLinks($request, new Response());
202 $this->assertEquals(200, $response->getStatusCode());
203 $data = json_decode((string) $response->getBody(), true);
204 $this->assertEmpty(count($data));
205 }
206
207 /**
c37a6f82 208 * Test getLinks with visibility parameter set to all
c3b00963 209 */
c37a6f82 210 public function testGetLinksVisibilityAll()
c3b00963 211 {
c37a6f82
A
212 $env = Environment::mock(
213 [
214 'REQUEST_METHOD' => 'GET',
215 'QUERY_STRING' => 'visibility=all'
216 ]
217 );
c3b00963
A
218 $request = Request::createFromEnvironment($env);
219 $response = $this->controller->getLinks($request, new Response());
220 $this->assertEquals(200, $response->getStatusCode());
c37a6f82
A
221 $data = json_decode((string)$response->getBody(), true);
222 $this->assertEquals($this->refDB->countLinks(), count($data));
4154c25b
A
223 $this->assertEquals(10, $data[0]['id']);
224 $this->assertEquals(41, $data[2]['id']);
c3b00963 225 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
c37a6f82 226 }
c3b00963 227
c37a6f82
A
228 /**
229 * Test getLinks with visibility parameter set to private
230 */
231 public function testGetLinksVisibilityPrivate()
232 {
c3b00963
A
233 $env = Environment::mock([
234 'REQUEST_METHOD' => 'GET',
c37a6f82 235 'QUERY_STRING' => 'visibility=private'
c3b00963
A
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($this->refDB->countPrivateLinks(), count($data));
242 $this->assertEquals(6, $data[0]['id']);
243 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
244 }
245
246 /**
c37a6f82 247 * Test getLinks with visibility parameter set to public
c3b00963 248 */
c37a6f82 249 public function testGetLinksVisibilityPublic()
c3b00963
A
250 {
251 $env = Environment::mock(
252 [
253 'REQUEST_METHOD' => 'GET',
c37a6f82 254 'QUERY_STRING' => 'visibility=public'
c3b00963
A
255 ]
256 );
257 $request = Request::createFromEnvironment($env);
258 $response = $this->controller->getLinks($request, new Response());
259 $this->assertEquals(200, $response->getStatusCode());
260 $data = json_decode((string)$response->getBody(), true);
c37a6f82 261 $this->assertEquals($this->refDB->countPublicLinks(), count($data));
4154c25b
A
262 $this->assertEquals(10, $data[0]['id']);
263 $this->assertEquals(41, $data[2]['id']);
c3b00963
A
264 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
265 }
266
267 /**
268 * Test getLinks service with offset and limit parameter:
269 * limit=1 and offset=1 should return only the second link, ID=8 (ordered by creation date DESC).
270 */
271 public function testGetLinksSearchTerm()
272 {
273 // Only in description - 1 result
274 $env = Environment::mock([
275 'REQUEST_METHOD' => 'GET',
276 'QUERY_STRING' => 'searchterm=Tropical'
277 ]);
278 $request = Request::createFromEnvironment($env);
279 $response = $this->controller->getLinks($request, new Response());
280 $this->assertEquals(200, $response->getStatusCode());
281 $data = json_decode((string) $response->getBody(), true);
282 $this->assertEquals(1, count($data));
283 $this->assertEquals(1, $data[0]['id']);
284 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
285
286 // Only in tags - 1 result
287 $env = Environment::mock([
288 'REQUEST_METHOD' => 'GET',
289 'QUERY_STRING' => 'searchterm=tag3'
290 ]);
291 $request = Request::createFromEnvironment($env);
292 $response = $this->controller->getLinks($request, new Response());
293 $this->assertEquals(200, $response->getStatusCode());
294 $data = json_decode((string) $response->getBody(), true);
295 $this->assertEquals(1, count($data));
296 $this->assertEquals(0, $data[0]['id']);
297 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
298
299 // Multiple results (2)
300 $env = Environment::mock([
301 'REQUEST_METHOD' => 'GET',
302 'QUERY_STRING' => 'searchterm=stallman'
303 ]);
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]));
313
314 // Multiword - 2 results
315 $env = Environment::mock([
316 'REQUEST_METHOD' => 'GET',
317 'QUERY_STRING' => 'searchterm=stallman+software'
318 ]);
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]));
328
329 // URL encoding
330 $env = Environment::mock([
331 'REQUEST_METHOD' => 'GET',
332 'QUERY_STRING' => 'searchterm='. urlencode('@web')
333 ]);
334 $request = Request::createFromEnvironment($env);
335 $response = $this->controller->getLinks($request, new Response());
336 $this->assertEquals(200, $response->getStatusCode());
337 $data = json_decode((string) $response->getBody(), true);
338 $this->assertEquals(2, count($data));
339 $this->assertEquals(41, $data[0]['id']);
340 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
341 $this->assertEquals(8, $data[1]['id']);
342 $this->assertEquals(self::NB_FIELDS_LINK, count($data[1]));
343 }
344
345 public function testGetLinksSearchTermNoResult()
346 {
347 $env = Environment::mock([
348 'REQUEST_METHOD' => 'GET',
349 'QUERY_STRING' => 'searchterm=nope'
350 ]);
351 $request = Request::createFromEnvironment($env);
352 $response = $this->controller->getLinks($request, new Response());
353 $this->assertEquals(200, $response->getStatusCode());
354 $data = json_decode((string) $response->getBody(), true);
355 $this->assertEquals(0, count($data));
356 }
357
358 public function testGetLinksSearchTags()
359 {
360 // Single tag
361 $env = Environment::mock([
362 'REQUEST_METHOD' => 'GET',
363 'QUERY_STRING' => 'searchtags=dev',
364 ]);
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(2, count($data));
370 $this->assertEquals(0, $data[0]['id']);
371 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
372 $this->assertEquals(4, $data[1]['id']);
373 $this->assertEquals(self::NB_FIELDS_LINK, count($data[1]));
374
375 // Multitag + exclude
376 $env = Environment::mock([
377 'REQUEST_METHOD' => 'GET',
378 'QUERY_STRING' => 'searchtags=stuff+-gnu',
379 ]);
380 $request = Request::createFromEnvironment($env);
381 $response = $this->controller->getLinks($request, new Response());
382 $this->assertEquals(200, $response->getStatusCode());
383 $data = json_decode((string) $response->getBody(), true);
384 $this->assertEquals(1, count($data));
385 $this->assertEquals(41, $data[0]['id']);
386 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
341527ba
WE
387
388 // wildcard: placeholder at the start
389 $env = Environment::mock([
390 'REQUEST_METHOD' => 'GET',
391 'QUERY_STRING' => 'searchtags=*Tuff',
392 ]);
393 $request = Request::createFromEnvironment($env);
394 $response = $this->controller->getLinks($request, new Response());
395 $this->assertEquals(200, $response->getStatusCode());
396 $data = json_decode((string) $response->getBody(), true);
397 $this->assertEquals(2, count($data));
398 $this->assertEquals(41, $data[0]['id']);
399
400 // wildcard: placeholder at the end
401 $env = Environment::mock([
402 'REQUEST_METHOD' => 'GET',
403 'QUERY_STRING' => 'searchtags=c*',
404 ]);
405 $request = Request::createFromEnvironment($env);
406 $response = $this->controller->getLinks($request, new Response());
407 $this->assertEquals(200, $response->getStatusCode());
408 $data = json_decode((string) $response->getBody(), true);
f1a148ab 409 $this->assertEquals(5, count($data));
341527ba
WE
410 $this->assertEquals(6, $data[0]['id']);
411
412 // wildcard: placeholder at the middle
413 $env = Environment::mock([
414 'REQUEST_METHOD' => 'GET',
415 'QUERY_STRING' => 'searchtags=w*b',
416 ]);
417 $request = Request::createFromEnvironment($env);
418 $response = $this->controller->getLinks($request, new Response());
419 $this->assertEquals(200, $response->getStatusCode());
420 $data = json_decode((string) $response->getBody(), true);
421 $this->assertEquals(4, count($data));
422 $this->assertEquals(6, $data[0]['id']);
423
424 // wildcard: match all
425 $env = Environment::mock([
426 'REQUEST_METHOD' => 'GET',
427 'QUERY_STRING' => 'searchtags=*',
428 ]);
429 $request = Request::createFromEnvironment($env);
430 $response = $this->controller->getLinks($request, new Response());
431 $this->assertEquals(200, $response->getStatusCode());
432 $data = json_decode((string) $response->getBody(), true);
4154c25b
A
433 $this->assertEquals(\ReferenceLinkDB::$NB_LINKS_TOTAL, count($data));
434 $this->assertEquals(10, $data[0]['id']);
435 $this->assertEquals(41, $data[2]['id']);
341527ba
WE
436
437 // wildcard: optional ('*' does not need to expand)
438 $env = Environment::mock([
439 'REQUEST_METHOD' => 'GET',
440 'QUERY_STRING' => 'searchtags=*stuff*',
441 ]);
442 $request = Request::createFromEnvironment($env);
443 $response = $this->controller->getLinks($request, new Response());
444 $this->assertEquals(200, $response->getStatusCode());
445 $data = json_decode((string) $response->getBody(), true);
446 $this->assertEquals(2, count($data));
447 $this->assertEquals(41, $data[0]['id']);
448
449 // wildcard: exclusions
450 $env = Environment::mock([
451 'REQUEST_METHOD' => 'GET',
452 'QUERY_STRING' => 'searchtags=*a*+-*e*',
453 ]);
454 $request = Request::createFromEnvironment($env);
455 $response = $this->controller->getLinks($request, new Response());
456 $this->assertEquals(200, $response->getStatusCode());
457 $data = json_decode((string) $response->getBody(), true);
458 $this->assertEquals(1, count($data));
459 $this->assertEquals(41, $data[0]['id']); // finds '#hashtag' in descr.
460
461 // wildcard: exclude all
462 $env = Environment::mock([
463 'REQUEST_METHOD' => 'GET',
464 'QUERY_STRING' => 'searchtags=-*',
465 ]);
466 $request = Request::createFromEnvironment($env);
467 $response = $this->controller->getLinks($request, new Response());
468 $this->assertEquals(200, $response->getStatusCode());
469 $data = json_decode((string) $response->getBody(), true);
470 $this->assertEquals(0, count($data));
c3b00963
A
471 }
472
473 /**
474 * Test getLinks service with search tags+terms.
475 */
476 public function testGetLinksSearchTermsAndTags()
477 {
478 $env = Environment::mock([
479 'REQUEST_METHOD' => 'GET',
480 'QUERY_STRING' => 'searchterm=poke&searchtags=dev',
481 ]);
482 $request = Request::createFromEnvironment($env);
483 $response = $this->controller->getLinks($request, new Response());
484 $this->assertEquals(200, $response->getStatusCode());
485 $data = json_decode((string) $response->getBody(), true);
486 $this->assertEquals(1, count($data));
487 $this->assertEquals(0, $data[0]['id']);
488 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
489 }
490}