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