diff options
author | ArthurHoaro <arthur@hoa.ro> | 2016-12-22 14:36:45 +0100 |
---|---|---|
committer | ArthurHoaro <arthur@hoa.ro> | 2017-01-15 13:55:22 +0100 |
commit | c3b00963fe22479e87998c82bc83827a54c8d972 (patch) | |
tree | 4c3f47697f8e58e2c60aa94bdcb506c770e4bd5e /tests | |
parent | fc11ab2f290a3712b766d78fdbcd354625a35d0a (diff) | |
download | Shaarli-c3b00963fe22479e87998c82bc83827a54c8d972.tar.gz Shaarli-c3b00963fe22479e87998c82bc83827a54c8d972.tar.zst Shaarli-c3b00963fe22479e87998c82bc83827a54c8d972.zip |
REST API: implement getLinks service
See http://shaarli.github.io/api-documentation/#links-links-collection-get
Diffstat (limited to 'tests')
-rw-r--r-- | tests/api/ApiUtilsTest.php | 65 | ||||
-rw-r--r-- | tests/api/controllers/LinksTest.php | 393 |
2 files changed, 458 insertions, 0 deletions
diff --git a/tests/api/ApiUtilsTest.php b/tests/api/ApiUtilsTest.php index 10da1459..516ee686 100644 --- a/tests/api/ApiUtilsTest.php +++ b/tests/api/ApiUtilsTest.php | |||
@@ -203,4 +203,69 @@ class ApiUtilsTest extends \PHPUnit_Framework_TestCase | |||
203 | $token = $this->generateCustomJwtToken('{"JSON":1}', '{"iat":' . (time() + 60) . '}', 'secret'); | 203 | $token = $this->generateCustomJwtToken('{"JSON":1}', '{"iat":' . (time() + 60) . '}', 'secret'); |
204 | ApiUtils::validateJwtToken($token, 'secret'); | 204 | ApiUtils::validateJwtToken($token, 'secret'); |
205 | } | 205 | } |
206 | |||
207 | /** | ||
208 | * Test formatLink() with a link using all useful fields. | ||
209 | */ | ||
210 | public function testFormatLinkComplete() | ||
211 | { | ||
212 | $indexUrl = 'https://domain.tld/sub/'; | ||
213 | $link = [ | ||
214 | 'id' => 12, | ||
215 | 'url' => 'http://lol.lol', | ||
216 | 'shorturl' => 'abc', | ||
217 | 'title' => 'Important Title', | ||
218 | 'description' => 'It is very lol<tag>' . PHP_EOL . 'new line', | ||
219 | 'tags' => 'blip .blop ', | ||
220 | 'private' => '1', | ||
221 | 'created' => \DateTime::createFromFormat('Ymd_His', '20170107_160102'), | ||
222 | 'updated' => \DateTime::createFromFormat('Ymd_His', '20170107_160612'), | ||
223 | ]; | ||
224 | |||
225 | $expected = [ | ||
226 | 'id' => 12, | ||
227 | 'url' => 'http://lol.lol', | ||
228 | 'shorturl' => 'abc', | ||
229 | 'title' => 'Important Title', | ||
230 | 'description' => 'It is very lol<tag>' . PHP_EOL . 'new line', | ||
231 | 'tags' => ['blip', '.blop'], | ||
232 | 'private' => true, | ||
233 | 'created' => '2017-01-07T16:01:02+00:00', | ||
234 | 'updated' => '2017-01-07T16:06:12+00:00', | ||
235 | ]; | ||
236 | |||
237 | $this->assertEquals($expected, ApiUtils::formatLink($link, $indexUrl)); | ||
238 | } | ||
239 | |||
240 | /** | ||
241 | * Test formatLink() with only minimal fields filled, and internal link. | ||
242 | */ | ||
243 | public function testFormatLinkMinimalNote() | ||
244 | { | ||
245 | $indexUrl = 'https://domain.tld/sub/'; | ||
246 | $link = [ | ||
247 | 'id' => 12, | ||
248 | 'url' => '?abc', | ||
249 | 'shorturl' => 'abc', | ||
250 | 'title' => 'Note', | ||
251 | 'description' => '', | ||
252 | 'tags' => '', | ||
253 | 'private' => '', | ||
254 | 'created' => \DateTime::createFromFormat('Ymd_His', '20170107_160102'), | ||
255 | ]; | ||
256 | |||
257 | $expected = [ | ||
258 | 'id' => 12, | ||
259 | 'url' => 'https://domain.tld/sub/?abc', | ||
260 | 'shorturl' => 'abc', | ||
261 | 'title' => 'Note', | ||
262 | 'description' => '', | ||
263 | 'tags' => [], | ||
264 | 'private' => false, | ||
265 | 'created' => '2017-01-07T16:01:02+00:00', | ||
266 | 'updated' => '', | ||
267 | ]; | ||
268 | |||
269 | $this->assertEquals($expected, ApiUtils::formatLink($link, $indexUrl)); | ||
270 | } | ||
206 | } | 271 | } |
diff --git a/tests/api/controllers/LinksTest.php b/tests/api/controllers/LinksTest.php new file mode 100644 index 00000000..4ead26b9 --- /dev/null +++ b/tests/api/controllers/LinksTest.php | |||
@@ -0,0 +1,393 @@ | |||
1 | <?php | ||
2 | |||
3 | namespace Shaarli\Api\Controllers; | ||
4 | |||
5 | |||
6 | use Slim\Container; | ||
7 | use Slim\Http\Environment; | ||
8 | use Slim\Http\Request; | ||
9 | use Slim\Http\Response; | ||
10 | |||
11 | /** | ||
12 | * Class LinksTest | ||
13 | * | ||
14 | * Test Links REST API services. | ||
15 | * Note that api call results are tightly related to data contained in ReferenceLinkDB. | ||
16 | * | ||
17 | * @package Shaarli\Api\Controllers | ||
18 | */ | ||
19 | class LinksTest extends \PHPUnit_Framework_TestCase | ||
20 | { | ||
21 | /** | ||
22 | * @var string datastore to test write operations | ||
23 | */ | ||
24 | protected static $testDatastore = 'sandbox/datastore.php'; | ||
25 | |||
26 | /** | ||
27 | * @var \ConfigManager instance | ||
28 | */ | ||
29 | protected $conf; | ||
30 | |||
31 | /** | ||
32 | * @var \ReferenceLinkDB instance. | ||
33 | */ | ||
34 | protected $refDB = null; | ||
35 | |||
36 | /** | ||
37 | * @var Container instance. | ||
38 | */ | ||
39 | protected $container; | ||
40 | |||
41 | /** | ||
42 | * @var Links controller instance. | ||
43 | */ | ||
44 | protected $controller; | ||
45 | |||
46 | /** | ||
47 | * Number of JSON field per link. | ||
48 | */ | ||
49 | const NB_FIELDS_LINK = 9; | ||
50 | |||
51 | /** | ||
52 | * Before every test, instantiate a new Api with its config, plugins and links. | ||
53 | */ | ||
54 | public function setUp() | ||
55 | { | ||
56 | $this->conf = new \ConfigManager('tests/utils/config/configJson.json.php'); | ||
57 | $this->refDB = new \ReferenceLinkDB(); | ||
58 | $this->refDB->write(self::$testDatastore); | ||
59 | |||
60 | $this->container = new Container(); | ||
61 | $this->container['conf'] = $this->conf; | ||
62 | $this->container['db'] = new \LinkDB(self::$testDatastore, true, false); | ||
63 | |||
64 | $this->controller = new Links($this->container); | ||
65 | } | ||
66 | |||
67 | /** | ||
68 | * After every test, remove the test datastore. | ||
69 | */ | ||
70 | public function tearDown() | ||
71 | { | ||
72 | @unlink(self::$testDatastore); | ||
73 | } | ||
74 | |||
75 | /** | ||
76 | * Test basic getLinks service: returns all links. | ||
77 | */ | ||
78 | public function testGetLinks() | ||
79 | { | ||
80 | // Used by index_url(). | ||
81 | $_SERVER['SERVER_NAME'] = 'domain.tld'; | ||
82 | $_SERVER['SERVER_PORT'] = 80; | ||
83 | $_SERVER['SCRIPT_NAME'] = '/'; | ||
84 | |||
85 | $env = Environment::mock([ | ||
86 | 'REQUEST_METHOD' => 'GET', | ||
87 | ]); | ||
88 | $request = Request::createFromEnvironment($env); | ||
89 | |||
90 | $response = $this->controller->getLinks($request, new Response()); | ||
91 | $this->assertEquals(200, $response->getStatusCode()); | ||
92 | $data = json_decode((string) $response->getBody(), true); | ||
93 | $this->assertEquals($this->refDB->countLinks(), count($data)); | ||
94 | |||
95 | // Check order | ||
96 | $order = [41, 8, 6, 7, 0, 1, 4, 42]; | ||
97 | $cpt = 0; | ||
98 | foreach ($data as $link) { | ||
99 | $this->assertEquals(self::NB_FIELDS_LINK, count($link)); | ||
100 | $this->assertEquals($order[$cpt++], $link['id']); | ||
101 | } | ||
102 | |||
103 | // Check first element fields\ | ||
104 | $first = $data[0]; | ||
105 | $this->assertEquals('http://domain.tld/?WDWyig', $first['url']); | ||
106 | $this->assertEquals('WDWyig', $first['shorturl']); | ||
107 | $this->assertEquals('Link title: @website', $first['title']); | ||
108 | $this->assertEquals( | ||
109 | 'Stallman has a beard and is part of the Free Software Foundation (or not). Seriously, read this. #hashtag', | ||
110 | $first['description'] | ||
111 | ); | ||
112 | $this->assertEquals('sTuff', $first['tags'][0]); | ||
113 | $this->assertEquals(false, $first['private']); | ||
114 | $this->assertEquals( | ||
115 | \DateTime::createFromFormat(\LinkDB::LINK_DATE_FORMAT, '20150310_114651')->format(\DateTime::ATOM), | ||
116 | $first['created'] | ||
117 | ); | ||
118 | $this->assertEmpty($first['updated']); | ||
119 | |||
120 | // Multi tags | ||
121 | $link = $data[1]; | ||
122 | $this->assertEquals(7, count($link['tags'])); | ||
123 | |||
124 | // Update date | ||
125 | $this->assertEquals( | ||
126 | \DateTime::createFromFormat(\LinkDB::LINK_DATE_FORMAT, '20160803_093033')->format(\DateTime::ATOM), | ||
127 | $link['updated'] | ||
128 | ); | ||
129 | } | ||
130 | |||
131 | /** | ||
132 | * Test getLinks service with offset and limit parameter: | ||
133 | * limit=1 and offset=1 should return only the second link, ID=8 (ordered by creation date DESC). | ||
134 | */ | ||
135 | public function testGetLinksOffsetLimit() | ||
136 | { | ||
137 | $env = Environment::mock([ | ||
138 | 'REQUEST_METHOD' => 'GET', | ||
139 | 'QUERY_STRING' => 'offset=1&limit=1' | ||
140 | ]); | ||
141 | $request = Request::createFromEnvironment($env); | ||
142 | $response = $this->controller->getLinks($request, new Response()); | ||
143 | $this->assertEquals(200, $response->getStatusCode()); | ||
144 | $data = json_decode((string) $response->getBody(), true); | ||
145 | $this->assertEquals(1, count($data)); | ||
146 | $this->assertEquals(8, $data[0]['id']); | ||
147 | $this->assertEquals(self::NB_FIELDS_LINK, count($data[0])); | ||
148 | } | ||
149 | |||
150 | /** | ||
151 | * Test getLinks with limit=all (return all link). | ||
152 | */ | ||
153 | public function testGetLinksLimitAll() | ||
154 | { | ||
155 | $env = Environment::mock([ | ||
156 | 'REQUEST_METHOD' => 'GET', | ||
157 | 'QUERY_STRING' => 'limit=all' | ||
158 | ]); | ||
159 | $request = Request::createFromEnvironment($env); | ||
160 | $response = $this->controller->getLinks($request, new Response()); | ||
161 | $this->assertEquals(200, $response->getStatusCode()); | ||
162 | $data = json_decode((string) $response->getBody(), true); | ||
163 | $this->assertEquals($this->refDB->countLinks(), count($data)); | ||
164 | // Check order | ||
165 | $order = [41, 8, 6, 7, 0, 1, 4, 42]; | ||
166 | $cpt = 0; | ||
167 | foreach ($data as $link) { | ||
168 | $this->assertEquals(self::NB_FIELDS_LINK, count($link)); | ||
169 | $this->assertEquals($order[$cpt++], $link['id']); | ||
170 | } | ||
171 | } | ||
172 | |||
173 | /** | ||
174 | * Test getLinks service with offset and limit parameter: | ||
175 | * limit=1 and offset=1 should return only the second link, ID=8 (ordered by creation date DESC). | ||
176 | */ | ||
177 | public function testGetLinksOffsetTooHigh() | ||
178 | { | ||
179 | $env = Environment::mock([ | ||
180 | 'REQUEST_METHOD' => 'GET', | ||
181 | 'QUERY_STRING' => 'offset=100' | ||
182 | ]); | ||
183 | $request = Request::createFromEnvironment($env); | ||
184 | $response = $this->controller->getLinks($request, new Response()); | ||
185 | $this->assertEquals(200, $response->getStatusCode()); | ||
186 | $data = json_decode((string) $response->getBody(), true); | ||
187 | $this->assertEmpty(count($data)); | ||
188 | } | ||
189 | |||
190 | /** | ||
191 | * Test getLinks with private attribute to 1 or true. | ||
192 | */ | ||
193 | public function testGetLinksPrivate() | ||
194 | { | ||
195 | $env = Environment::mock([ | ||
196 | 'REQUEST_METHOD' => 'GET', | ||
197 | 'QUERY_STRING' => 'private=true' | ||
198 | ]); | ||
199 | $request = Request::createFromEnvironment($env); | ||
200 | $response = $this->controller->getLinks($request, new Response()); | ||
201 | $this->assertEquals(200, $response->getStatusCode()); | ||
202 | $data = json_decode((string) $response->getBody(), true); | ||
203 | $this->assertEquals($this->refDB->countPrivateLinks(), count($data)); | ||
204 | $this->assertEquals(6, $data[0]['id']); | ||
205 | $this->assertEquals(self::NB_FIELDS_LINK, count($data[0])); | ||
206 | |||
207 | $env = Environment::mock([ | ||
208 | 'REQUEST_METHOD' => 'GET', | ||
209 | 'QUERY_STRING' => 'private=1' | ||
210 | ]); | ||
211 | $request = Request::createFromEnvironment($env); | ||
212 | $response = $this->controller->getLinks($request, new Response()); | ||
213 | $this->assertEquals(200, $response->getStatusCode()); | ||
214 | $data = json_decode((string) $response->getBody(), true); | ||
215 | $this->assertEquals($this->refDB->countPrivateLinks(), count($data)); | ||
216 | $this->assertEquals(6, $data[0]['id']); | ||
217 | $this->assertEquals(self::NB_FIELDS_LINK, count($data[0])); | ||
218 | } | ||
219 | |||
220 | /** | ||
221 | * Test getLinks with private attribute to false or 0 | ||
222 | */ | ||
223 | public function testGetLinksNotPrivate() | ||
224 | { | ||
225 | $env = Environment::mock( | ||
226 | [ | ||
227 | 'REQUEST_METHOD' => 'GET', | ||
228 | 'QUERY_STRING' => 'private=0' | ||
229 | ] | ||
230 | ); | ||
231 | $request = Request::createFromEnvironment($env); | ||
232 | $response = $this->controller->getLinks($request, new Response()); | ||
233 | $this->assertEquals(200, $response->getStatusCode()); | ||
234 | $data = json_decode((string)$response->getBody(), true); | ||
235 | $this->assertEquals($this->refDB->countLinks(), count($data)); | ||
236 | $this->assertEquals(41, $data[0]['id']); | ||
237 | $this->assertEquals(self::NB_FIELDS_LINK, count($data[0])); | ||
238 | |||
239 | $env = Environment::mock( | ||
240 | [ | ||
241 | 'REQUEST_METHOD' => 'GET', | ||
242 | 'QUERY_STRING' => 'private=false' | ||
243 | ] | ||
244 | ); | ||
245 | $request = Request::createFromEnvironment($env); | ||
246 | $response = $this->controller->getLinks($request, new Response()); | ||
247 | $this->assertEquals(200, $response->getStatusCode()); | ||
248 | $data = json_decode((string)$response->getBody(), true); | ||
249 | $this->assertEquals($this->refDB->countLinks(), count($data)); | ||
250 | $this->assertEquals(41, $data[0]['id']); | ||
251 | $this->assertEquals(self::NB_FIELDS_LINK, count($data[0])); | ||
252 | } | ||
253 | |||
254 | /** | ||
255 | * Test getLinks service with offset and limit parameter: | ||
256 | * limit=1 and offset=1 should return only the second link, ID=8 (ordered by creation date DESC). | ||
257 | */ | ||
258 | public function testGetLinksSearchTerm() | ||
259 | { | ||
260 | // Only in description - 1 result | ||
261 | $env = Environment::mock([ | ||
262 | 'REQUEST_METHOD' => 'GET', | ||
263 | 'QUERY_STRING' => 'searchterm=Tropical' | ||
264 | ]); | ||
265 | $request = Request::createFromEnvironment($env); | ||
266 | $response = $this->controller->getLinks($request, new Response()); | ||
267 | $this->assertEquals(200, $response->getStatusCode()); | ||
268 | $data = json_decode((string) $response->getBody(), true); | ||
269 | $this->assertEquals(1, count($data)); | ||
270 | $this->assertEquals(1, $data[0]['id']); | ||
271 | $this->assertEquals(self::NB_FIELDS_LINK, count($data[0])); | ||
272 | |||
273 | // Only in tags - 1 result | ||
274 | $env = Environment::mock([ | ||
275 | 'REQUEST_METHOD' => 'GET', | ||
276 | 'QUERY_STRING' => 'searchterm=tag3' | ||
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(0, $data[0]['id']); | ||
284 | $this->assertEquals(self::NB_FIELDS_LINK, count($data[0])); | ||
285 | |||
286 | // Multiple results (2) | ||
287 | $env = Environment::mock([ | ||
288 | 'REQUEST_METHOD' => 'GET', | ||
289 | 'QUERY_STRING' => 'searchterm=stallman' | ||
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(2, count($data)); | ||
296 | $this->assertEquals(41, $data[0]['id']); | ||
297 | $this->assertEquals(self::NB_FIELDS_LINK, count($data[0])); | ||
298 | $this->assertEquals(8, $data[1]['id']); | ||
299 | $this->assertEquals(self::NB_FIELDS_LINK, count($data[1])); | ||
300 | |||
301 | // Multiword - 2 results | ||
302 | $env = Environment::mock([ | ||
303 | 'REQUEST_METHOD' => 'GET', | ||
304 | 'QUERY_STRING' => 'searchterm=stallman+software' | ||
305 | ]); | ||
306 | $request = Request::createFromEnvironment($env); | ||
307 | $response = $this->controller->getLinks($request, new Response()); | ||
308 | $this->assertEquals(200, $response->getStatusCode()); | ||
309 | $data = json_decode((string) $response->getBody(), true); | ||
310 | $this->assertEquals(2, count($data)); | ||
311 | $this->assertEquals(41, $data[0]['id']); | ||
312 | $this->assertEquals(self::NB_FIELDS_LINK, count($data[0])); | ||
313 | $this->assertEquals(8, $data[1]['id']); | ||
314 | $this->assertEquals(self::NB_FIELDS_LINK, count($data[1])); | ||
315 | |||
316 | // URL encoding | ||
317 | $env = Environment::mock([ | ||
318 | 'REQUEST_METHOD' => 'GET', | ||
319 | 'QUERY_STRING' => 'searchterm='. urlencode('@web') | ||
320 | ]); | ||
321 | $request = Request::createFromEnvironment($env); | ||
322 | $response = $this->controller->getLinks($request, new Response()); | ||
323 | $this->assertEquals(200, $response->getStatusCode()); | ||
324 | $data = json_decode((string) $response->getBody(), true); | ||
325 | $this->assertEquals(2, count($data)); | ||
326 | $this->assertEquals(41, $data[0]['id']); | ||
327 | $this->assertEquals(self::NB_FIELDS_LINK, count($data[0])); | ||
328 | $this->assertEquals(8, $data[1]['id']); | ||
329 | $this->assertEquals(self::NB_FIELDS_LINK, count($data[1])); | ||
330 | } | ||
331 | |||
332 | public function testGetLinksSearchTermNoResult() | ||
333 | { | ||
334 | $env = Environment::mock([ | ||
335 | 'REQUEST_METHOD' => 'GET', | ||
336 | 'QUERY_STRING' => 'searchterm=nope' | ||
337 | ]); | ||
338 | $request = Request::createFromEnvironment($env); | ||
339 | $response = $this->controller->getLinks($request, new Response()); | ||
340 | $this->assertEquals(200, $response->getStatusCode()); | ||
341 | $data = json_decode((string) $response->getBody(), true); | ||
342 | $this->assertEquals(0, count($data)); | ||
343 | } | ||
344 | |||
345 | public function testGetLinksSearchTags() | ||
346 | { | ||
347 | // Single tag | ||
348 | $env = Environment::mock([ | ||
349 | 'REQUEST_METHOD' => 'GET', | ||
350 | 'QUERY_STRING' => 'searchtags=dev', | ||
351 | ]); | ||
352 | $request = Request::createFromEnvironment($env); | ||
353 | $response = $this->controller->getLinks($request, new Response()); | ||
354 | $this->assertEquals(200, $response->getStatusCode()); | ||
355 | $data = json_decode((string) $response->getBody(), true); | ||
356 | $this->assertEquals(2, count($data)); | ||
357 | $this->assertEquals(0, $data[0]['id']); | ||
358 | $this->assertEquals(self::NB_FIELDS_LINK, count($data[0])); | ||
359 | $this->assertEquals(4, $data[1]['id']); | ||
360 | $this->assertEquals(self::NB_FIELDS_LINK, count($data[1])); | ||
361 | |||
362 | // Multitag + exclude | ||
363 | $env = Environment::mock([ | ||
364 | 'REQUEST_METHOD' => 'GET', | ||
365 | 'QUERY_STRING' => 'searchtags=stuff+-gnu', | ||
366 | ]); | ||
367 | $request = Request::createFromEnvironment($env); | ||
368 | $response = $this->controller->getLinks($request, new Response()); | ||
369 | $this->assertEquals(200, $response->getStatusCode()); | ||
370 | $data = json_decode((string) $response->getBody(), true); | ||
371 | $this->assertEquals(1, count($data)); | ||
372 | $this->assertEquals(41, $data[0]['id']); | ||
373 | $this->assertEquals(self::NB_FIELDS_LINK, count($data[0])); | ||
374 | } | ||
375 | |||
376 | /** | ||
377 | * Test getLinks service with search tags+terms. | ||
378 | */ | ||
379 | public function testGetLinksSearchTermsAndTags() | ||
380 | { | ||
381 | $env = Environment::mock([ | ||
382 | 'REQUEST_METHOD' => 'GET', | ||
383 | 'QUERY_STRING' => 'searchterm=poke&searchtags=dev', | ||
384 | ]); | ||
385 | $request = Request::createFromEnvironment($env); | ||
386 | $response = $this->controller->getLinks($request, new Response()); | ||
387 | $this->assertEquals(200, $response->getStatusCode()); | ||
388 | $data = json_decode((string) $response->getBody(), true); | ||
389 | $this->assertEquals(1, count($data)); | ||
390 | $this->assertEquals(0, $data[0]['id']); | ||
391 | $this->assertEquals(self::NB_FIELDS_LINK, count($data[0])); | ||
392 | } | ||
393 | } | ||