]> git.immae.eu Git - github/shaarli/Shaarli.git/blob - tests/api/controllers/links/GetLinksTest.php
namespacing: \Shaarli\Bookmark\LinkDB
[github/shaarli/Shaarli.git] / tests / api / controllers / links / GetLinksTest.php
1 <?php
2 namespace Shaarli\Api\Controllers;
3
4 use Shaarli\Config\ConfigManager;
5
6 use Slim\Container;
7 use Slim\Http\Environment;
8 use Slim\Http\Request;
9 use Slim\Http\Response;
10
11 /**
12 * Class GetLinksTest
13 *
14 * Test get Link list REST API service.
15 *
16 * @see http://shaarli.github.io/api-documentation/#links-links-collection-get
17 *
18 * @package Shaarli\Api\Controllers
19 */
20 class GetLinksTest extends \PHPUnit_Framework_TestCase
21 {
22 /**
23 * @var string datastore to test write operations
24 */
25 protected static $testDatastore = 'sandbox/datastore.php';
26
27 /**
28 * @var ConfigManager instance
29 */
30 protected $conf;
31
32 /**
33 * @var \ReferenceLinkDB instance.
34 */
35 protected $refDB = null;
36
37 /**
38 * @var Container instance.
39 */
40 protected $container;
41
42 /**
43 * @var Links controller instance.
44 */
45 protected $controller;
46
47 /**
48 * Number of JSON field per link.
49 */
50 const NB_FIELDS_LINK = 9;
51
52 /**
53 * Before every test, instantiate a new Api with its config, plugins and links.
54 */
55 public function setUp()
56 {
57 $this->conf = new ConfigManager('tests/utils/config/configJson');
58 $this->refDB = new \ReferenceLinkDB();
59 $this->refDB->write(self::$testDatastore);
60
61 $this->container = new Container();
62 $this->container['conf'] = $this->conf;
63 $this->container['db'] = new \Shaarli\Bookmark\LinkDB(self::$testDatastore, true, false);
64 $this->container['history'] = null;
65
66 $this->controller = new Links($this->container);
67 }
68
69 /**
70 * After every test, remove the test datastore.
71 */
72 public function tearDown()
73 {
74 @unlink(self::$testDatastore);
75 }
76
77 /**
78 * Test basic getLinks service: returns all links.
79 */
80 public function testGetLinks()
81 {
82 // Used by index_url().
83 $_SERVER['SERVER_NAME'] = 'domain.tld';
84 $_SERVER['SERVER_PORT'] = 80;
85 $_SERVER['SCRIPT_NAME'] = '/';
86
87 $env = Environment::mock([
88 'REQUEST_METHOD' => 'GET',
89 ]);
90 $request = Request::createFromEnvironment($env);
91
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));
96
97 // Check order
98 $order = [10, 11, 41, 8, 6, 7, 0, 1, 9, 4, 42];
99 $cpt = 0;
100 foreach ($data as $link) {
101 $this->assertEquals(self::NB_FIELDS_LINK, count($link));
102 $this->assertEquals($order[$cpt++], $link['id']);
103 }
104
105 // Check first element fields
106 $first = $data[2];
107 $this->assertEquals('http://domain.tld/?WDWyig', $first['url']);
108 $this->assertEquals('WDWyig', $first['shorturl']);
109 $this->assertEquals('Link title: @website', $first['title']);
110 $this->assertEquals(
111 'Stallman has a beard and is part of the Free Software Foundation (or not). Seriously, read this. #hashtag',
112 $first['description']
113 );
114 $this->assertEquals('sTuff', $first['tags'][0]);
115 $this->assertEquals(false, $first['private']);
116 $this->assertEquals(
117 \DateTime::createFromFormat(\Shaarli\Bookmark\LinkDB::LINK_DATE_FORMAT, '20150310_114651')->format(\DateTime::ATOM),
118 $first['created']
119 );
120 $this->assertEmpty($first['updated']);
121
122 // Multi tags
123 $link = $data[3];
124 $this->assertEquals(7, count($link['tags']));
125
126 // Update date
127 $this->assertEquals(
128 \DateTime::createFromFormat(\Shaarli\Bookmark\LinkDB::LINK_DATE_FORMAT, '20160803_093033')->format(\DateTime::ATOM),
129 $link['updated']
130 );
131 }
132
133 /**
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).
136 */
137 public function testGetLinksOffsetLimit()
138 {
139 $env = Environment::mock([
140 'REQUEST_METHOD' => 'GET',
141 'QUERY_STRING' => 'offset=3&limit=1'
142 ]);
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]));
150 }
151
152 /**
153 * Test getLinks with limit=all (return all link).
154 */
155 public function testGetLinksLimitAll()
156 {
157 $env = Environment::mock([
158 'REQUEST_METHOD' => 'GET',
159 'QUERY_STRING' => 'limit=all'
160 ]);
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));
166 // Check order
167 $order = [10, 11, 41, 8, 6, 7, 0, 1, 9, 4, 42];
168 $cpt = 0;
169 foreach ($data as $link) {
170 $this->assertEquals(self::NB_FIELDS_LINK, count($link));
171 $this->assertEquals($order[$cpt++], $link['id']);
172 }
173 }
174
175 /**
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).
178 */
179 public function testGetLinksOffsetTooHigh()
180 {
181 $env = Environment::mock([
182 'REQUEST_METHOD' => 'GET',
183 'QUERY_STRING' => 'offset=100'
184 ]);
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));
190 }
191
192 /**
193 * Test getLinks with visibility parameter set to all
194 */
195 public function testGetLinksVisibilityAll()
196 {
197 $env = Environment::mock(
198 [
199 'REQUEST_METHOD' => 'GET',
200 'QUERY_STRING' => 'visibility=all'
201 ]
202 );
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]));
211 }
212
213 /**
214 * Test getLinks with visibility parameter set to private
215 */
216 public function testGetLinksVisibilityPrivate()
217 {
218 $env = Environment::mock([
219 'REQUEST_METHOD' => 'GET',
220 'QUERY_STRING' => 'visibility=private'
221 ]);
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]));
229 }
230
231 /**
232 * Test getLinks with visibility parameter set to public
233 */
234 public function testGetLinksVisibilityPublic()
235 {
236 $env = Environment::mock(
237 [
238 'REQUEST_METHOD' => 'GET',
239 'QUERY_STRING' => 'visibility=public'
240 ]
241 );
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]));
250 }
251
252 /**
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).
255 */
256 public function testGetLinksSearchTerm()
257 {
258 // Only in description - 1 result
259 $env = Environment::mock([
260 'REQUEST_METHOD' => 'GET',
261 'QUERY_STRING' => 'searchterm=Tropical'
262 ]);
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]));
270
271 // Only in tags - 1 result
272 $env = Environment::mock([
273 'REQUEST_METHOD' => 'GET',
274 'QUERY_STRING' => 'searchterm=tag3'
275 ]);
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]));
283
284 // Multiple results (2)
285 $env = Environment::mock([
286 'REQUEST_METHOD' => 'GET',
287 'QUERY_STRING' => 'searchterm=stallman'
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 // Multiword - 2 results
300 $env = Environment::mock([
301 'REQUEST_METHOD' => 'GET',
302 'QUERY_STRING' => 'searchterm=stallman+software'
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 // URL encoding
315 $env = Environment::mock([
316 'REQUEST_METHOD' => 'GET',
317 'QUERY_STRING' => 'searchterm='. urlencode('@web')
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
330 public function testGetLinksSearchTermNoResult()
331 {
332 $env = Environment::mock([
333 'REQUEST_METHOD' => 'GET',
334 'QUERY_STRING' => 'searchterm=nope'
335 ]);
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));
341 }
342
343 public function testGetLinksSearchTags()
344 {
345 // Single tag
346 $env = Environment::mock([
347 'REQUEST_METHOD' => 'GET',
348 'QUERY_STRING' => 'searchtags=dev',
349 ]);
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]));
359
360 // Multitag + exclude
361 $env = Environment::mock([
362 'REQUEST_METHOD' => 'GET',
363 'QUERY_STRING' => 'searchtags=stuff+-gnu',
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(1, count($data));
370 $this->assertEquals(41, $data[0]['id']);
371 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
372
373 // wildcard: placeholder at the start
374 $env = Environment::mock([
375 'REQUEST_METHOD' => 'GET',
376 'QUERY_STRING' => 'searchtags=*Tuff',
377 ]);
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']);
384
385 // wildcard: placeholder at the end
386 $env = Environment::mock([
387 'REQUEST_METHOD' => 'GET',
388 'QUERY_STRING' => 'searchtags=c*',
389 ]);
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']);
396
397 // wildcard: placeholder at the middle
398 $env = Environment::mock([
399 'REQUEST_METHOD' => 'GET',
400 'QUERY_STRING' => 'searchtags=w*b',
401 ]);
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']);
408
409 // wildcard: match all
410 $env = Environment::mock([
411 'REQUEST_METHOD' => 'GET',
412 'QUERY_STRING' => 'searchtags=*',
413 ]);
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']);
421
422 // wildcard: optional ('*' does not need to expand)
423 $env = Environment::mock([
424 'REQUEST_METHOD' => 'GET',
425 'QUERY_STRING' => 'searchtags=*stuff*',
426 ]);
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']);
433
434 // wildcard: exclusions
435 $env = Environment::mock([
436 'REQUEST_METHOD' => 'GET',
437 'QUERY_STRING' => 'searchtags=*a*+-*e*',
438 ]);
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.
445
446 // wildcard: exclude all
447 $env = Environment::mock([
448 'REQUEST_METHOD' => 'GET',
449 'QUERY_STRING' => 'searchtags=-*',
450 ]);
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));
456 }
457
458 /**
459 * Test getLinks service with search tags+terms.
460 */
461 public function testGetLinksSearchTermsAndTags()
462 {
463 $env = Environment::mock([
464 'REQUEST_METHOD' => 'GET',
465 'QUERY_STRING' => 'searchterm=poke&searchtags=dev',
466 ]);
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]));
474 }
475 }