aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests/api/controllers
diff options
context:
space:
mode:
authorArthurHoaro <arthur@hoa.ro>2018-07-28 11:07:55 +0200
committerArthurHoaro <arthur@hoa.ro>2018-07-28 11:07:55 +0200
commit83faedadff76c5bdca036f39f13943f63b27e164 (patch)
tree6f44cede16ec6a60f10b9699e211e0818f06d2c8 /tests/api/controllers
parent1d9eb22a3df85b67fe6652c0876cd7382c2fb525 (diff)
parent658988f3aeba7a5a938783249ccf2765251e5597 (diff)
downloadShaarli-83faedadff76c5bdca036f39f13943f63b27e164.tar.gz
Shaarli-83faedadff76c5bdca036f39f13943f63b27e164.tar.zst
Shaarli-83faedadff76c5bdca036f39f13943f63b27e164.zip
Merge tag 'v0.9.7' into stable
Release v0.9.7
Diffstat (limited to 'tests/api/controllers')
-rw-r--r--tests/api/controllers/DeleteLinkTest.php126
-rw-r--r--tests/api/controllers/GetLinkIdTest.php132
-rw-r--r--tests/api/controllers/GetLinksTest.php472
-rw-r--r--tests/api/controllers/HistoryTest.php216
-rw-r--r--tests/api/controllers/InfoTest.php115
-rw-r--r--tests/api/controllers/PostLinkTest.php216
-rw-r--r--tests/api/controllers/PutLinkTest.php222
7 files changed, 1499 insertions, 0 deletions
diff --git a/tests/api/controllers/DeleteLinkTest.php b/tests/api/controllers/DeleteLinkTest.php
new file mode 100644
index 00000000..7d797137
--- /dev/null
+++ b/tests/api/controllers/DeleteLinkTest.php
@@ -0,0 +1,126 @@
1<?php
2
3
4namespace Shaarli\Api\Controllers;
5
6use Shaarli\Config\ConfigManager;
7use Slim\Container;
8use Slim\Http\Environment;
9use Slim\Http\Request;
10use Slim\Http\Response;
11
12class DeleteLinkTest extends \PHPUnit_Framework_TestCase
13{
14 /**
15 * @var string datastore to test write operations
16 */
17 protected static $testDatastore = 'sandbox/datastore.php';
18
19 /**
20 * @var string datastore to test write operations
21 */
22 protected static $testHistory = 'sandbox/history.php';
23
24 /**
25 * @var ConfigManager instance
26 */
27 protected $conf;
28
29 /**
30 * @var \ReferenceLinkDB instance.
31 */
32 protected $refDB = null;
33
34 /**
35 * @var \LinkDB instance.
36 */
37 protected $linkDB;
38
39 /**
40 * @var \History instance.
41 */
42 protected $history;
43
44 /**
45 * @var Container instance.
46 */
47 protected $container;
48
49 /**
50 * @var Links controller instance.
51 */
52 protected $controller;
53
54 /**
55 * Before each test, instantiate a new Api with its config, plugins and links.
56 */
57 public function setUp()
58 {
59 $this->conf = new ConfigManager('tests/utils/config/configJson');
60 $this->refDB = new \ReferenceLinkDB();
61 $this->refDB->write(self::$testDatastore);
62 $this->linkDB = new \LinkDB(self::$testDatastore, true, false);
63 $refHistory = new \ReferenceHistory();
64 $refHistory->write(self::$testHistory);
65 $this->history = new \History(self::$testHistory);
66 $this->container = new Container();
67 $this->container['conf'] = $this->conf;
68 $this->container['db'] = $this->linkDB;
69 $this->container['history'] = $this->history;
70
71 $this->controller = new Links($this->container);
72 }
73
74 /**
75 * After each test, remove the test datastore.
76 */
77 public function tearDown()
78 {
79 @unlink(self::$testDatastore);
80 @unlink(self::$testHistory);
81 }
82
83 /**
84 * Test DELETE link endpoint: the link should be removed.
85 */
86 public function testDeleteLinkValid()
87 {
88 $id = '41';
89 $this->assertTrue(isset($this->linkDB[$id]));
90 $env = Environment::mock([
91 'REQUEST_METHOD' => 'DELETE',
92 ]);
93 $request = Request::createFromEnvironment($env);
94
95 $response = $this->controller->deleteLink($request, new Response(), ['id' => $id]);
96 $this->assertEquals(204, $response->getStatusCode());
97 $this->assertEmpty((string) $response->getBody());
98
99 $this->linkDB = new \LinkDB(self::$testDatastore, true, false);
100 $this->assertFalse(isset($this->linkDB[$id]));
101
102 $historyEntry = $this->history->getHistory()[0];
103 $this->assertEquals(\History::DELETED, $historyEntry['event']);
104 $this->assertTrue(
105 (new \DateTime())->add(\DateInterval::createFromDateString('-5 seconds')) < $historyEntry['datetime']
106 );
107 $this->assertEquals($id, $historyEntry['id']);
108 }
109
110 /**
111 * Test DELETE link endpoint: reach not existing ID.
112 *
113 * @expectedException Shaarli\Api\Exceptions\ApiLinkNotFoundException
114 */
115 public function testDeleteLink404()
116 {
117 $id = -1;
118 $this->assertFalse(isset($this->linkDB[$id]));
119 $env = Environment::mock([
120 'REQUEST_METHOD' => 'DELETE',
121 ]);
122 $request = Request::createFromEnvironment($env);
123
124 $this->controller->deleteLink($request, new Response(), ['id' => $id]);
125 }
126}
diff --git a/tests/api/controllers/GetLinkIdTest.php b/tests/api/controllers/GetLinkIdTest.php
new file mode 100644
index 00000000..57528d5a
--- /dev/null
+++ b/tests/api/controllers/GetLinkIdTest.php
@@ -0,0 +1,132 @@
1<?php
2
3namespace Shaarli\Api\Controllers;
4
5use Shaarli\Config\ConfigManager;
6
7use Slim\Container;
8use Slim\Http\Environment;
9use Slim\Http\Request;
10use Slim\Http\Response;
11
12/**
13 * Class GetLinkIdTest
14 *
15 * Test getLink by ID API service.
16 *
17 * @see http://shaarli.github.io/api-documentation/#links-link-get
18 *
19 * @package Shaarli\Api\Controllers
20 */
21class GetLinkIdTest extends \PHPUnit_Framework_TestCase
22{
23 /**
24 * @var string datastore to test write operations
25 */
26 protected static $testDatastore = 'sandbox/datastore.php';
27
28 /**
29 * @var ConfigManager instance
30 */
31 protected $conf;
32
33 /**
34 * @var \ReferenceLinkDB instance.
35 */
36 protected $refDB = null;
37
38 /**
39 * @var Container instance.
40 */
41 protected $container;
42
43 /**
44 * @var Links controller instance.
45 */
46 protected $controller;
47
48 /**
49 * Number of JSON fields per link.
50 */
51 const NB_FIELDS_LINK = 9;
52
53 /**
54 * Before each test, instantiate a new Api with its config, plugins and links.
55 */
56 public function setUp()
57 {
58 $this->conf = new ConfigManager('tests/utils/config/configJson');
59 $this->refDB = new \ReferenceLinkDB();
60 $this->refDB->write(self::$testDatastore);
61
62 $this->container = new Container();
63 $this->container['conf'] = $this->conf;
64 $this->container['db'] = new \LinkDB(self::$testDatastore, true, false);
65 $this->container['history'] = null;
66
67 $this->controller = new Links($this->container);
68 }
69
70 /**
71 * After each test, remove the test datastore.
72 */
73 public function tearDown()
74 {
75 @unlink(self::$testDatastore);
76 }
77
78 /**
79 * Test basic getLink service: return link ID=41.
80 */
81 public function testGetLinkId()
82 {
83 // Used by index_url().
84 $_SERVER['SERVER_NAME'] = 'domain.tld';
85 $_SERVER['SERVER_PORT'] = 80;
86 $_SERVER['SCRIPT_NAME'] = '/';
87
88 $id = 41;
89 $env = Environment::mock([
90 'REQUEST_METHOD' => 'GET',
91 ]);
92 $request = Request::createFromEnvironment($env);
93
94 $response = $this->controller->getLink($request, new Response(), ['id' => $id]);
95 $this->assertEquals(200, $response->getStatusCode());
96 $data = json_decode((string) $response->getBody(), true);
97 $this->assertEquals(self::NB_FIELDS_LINK, count($data));
98 $this->assertEquals($id, $data['id']);
99
100 // Check link elements
101 $this->assertEquals('http://domain.tld/?WDWyig', $data['url']);
102 $this->assertEquals('WDWyig', $data['shorturl']);
103 $this->assertEquals('Link title: @website', $data['title']);
104 $this->assertEquals(
105 'Stallman has a beard and is part of the Free Software Foundation (or not). Seriously, read this. #hashtag',
106 $data['description']
107 );
108 $this->assertEquals('sTuff', $data['tags'][0]);
109 $this->assertEquals(false, $data['private']);
110 $this->assertEquals(
111 \DateTime::createFromFormat(\LinkDB::LINK_DATE_FORMAT, '20150310_114651')->format(\DateTime::ATOM),
112 $data['created']
113 );
114 $this->assertEmpty($data['updated']);
115 }
116
117 /**
118 * Test basic getLink service: get non existent link => ApiLinkNotFoundException.
119 *
120 * @expectedException Shaarli\Api\Exceptions\ApiLinkNotFoundException
121 * @expectedExceptionMessage Link not found
122 */
123 public function testGetLink404()
124 {
125 $env = Environment::mock([
126 'REQUEST_METHOD' => 'GET',
127 ]);
128 $request = Request::createFromEnvironment($env);
129
130 $this->controller->getLink($request, new Response(), ['id' => -1]);
131 }
132}
diff --git a/tests/api/controllers/GetLinksTest.php b/tests/api/controllers/GetLinksTest.php
new file mode 100644
index 00000000..d22ed3bf
--- /dev/null
+++ b/tests/api/controllers/GetLinksTest.php
@@ -0,0 +1,472 @@
1<?php
2namespace Shaarli\Api\Controllers;
3
4use Shaarli\Config\ConfigManager;
5
6use Slim\Container;
7use Slim\Http\Environment;
8use Slim\Http\Request;
9use 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 */
20class 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 \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 = [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[0];
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(\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[1];
124 $this->assertEquals(7, count($link['tags']));
125
126 // Update date
127 $this->assertEquals(
128 \DateTime::createFromFormat(\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=1&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 = [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(41, $data[0]['id']);
209 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
210 }
211
212 /**
213 * Test getLinks with visibility parameter set to private
214 */
215 public function testGetLinksVisibilityPrivate()
216 {
217 $env = Environment::mock([
218 'REQUEST_METHOD' => 'GET',
219 'QUERY_STRING' => 'visibility=private'
220 ]);
221 $request = Request::createFromEnvironment($env);
222 $response = $this->controller->getLinks($request, new Response());
223 $this->assertEquals(200, $response->getStatusCode());
224 $data = json_decode((string) $response->getBody(), true);
225 $this->assertEquals($this->refDB->countPrivateLinks(), count($data));
226 $this->assertEquals(6, $data[0]['id']);
227 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
228 }
229
230 /**
231 * Test getLinks with visibility parameter set to public
232 */
233 public function testGetLinksVisibilityPublic()
234 {
235 $env = Environment::mock(
236 [
237 'REQUEST_METHOD' => 'GET',
238 'QUERY_STRING' => 'visibility=public'
239 ]
240 );
241 $request = Request::createFromEnvironment($env);
242 $response = $this->controller->getLinks($request, new Response());
243 $this->assertEquals(200, $response->getStatusCode());
244 $data = json_decode((string)$response->getBody(), true);
245 $this->assertEquals($this->refDB->countPublicLinks(), count($data));
246 $this->assertEquals(41, $data[0]['id']);
247 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
248 }
249
250 /**
251 * Test getLinks service with offset and limit parameter:
252 * limit=1 and offset=1 should return only the second link, ID=8 (ordered by creation date DESC).
253 */
254 public function testGetLinksSearchTerm()
255 {
256 // Only in description - 1 result
257 $env = Environment::mock([
258 'REQUEST_METHOD' => 'GET',
259 'QUERY_STRING' => 'searchterm=Tropical'
260 ]);
261 $request = Request::createFromEnvironment($env);
262 $response = $this->controller->getLinks($request, new Response());
263 $this->assertEquals(200, $response->getStatusCode());
264 $data = json_decode((string) $response->getBody(), true);
265 $this->assertEquals(1, count($data));
266 $this->assertEquals(1, $data[0]['id']);
267 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
268
269 // Only in tags - 1 result
270 $env = Environment::mock([
271 'REQUEST_METHOD' => 'GET',
272 'QUERY_STRING' => 'searchterm=tag3'
273 ]);
274 $request = Request::createFromEnvironment($env);
275 $response = $this->controller->getLinks($request, new Response());
276 $this->assertEquals(200, $response->getStatusCode());
277 $data = json_decode((string) $response->getBody(), true);
278 $this->assertEquals(1, count($data));
279 $this->assertEquals(0, $data[0]['id']);
280 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
281
282 // Multiple results (2)
283 $env = Environment::mock([
284 'REQUEST_METHOD' => 'GET',
285 'QUERY_STRING' => 'searchterm=stallman'
286 ]);
287 $request = Request::createFromEnvironment($env);
288 $response = $this->controller->getLinks($request, new Response());
289 $this->assertEquals(200, $response->getStatusCode());
290 $data = json_decode((string) $response->getBody(), true);
291 $this->assertEquals(2, count($data));
292 $this->assertEquals(41, $data[0]['id']);
293 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
294 $this->assertEquals(8, $data[1]['id']);
295 $this->assertEquals(self::NB_FIELDS_LINK, count($data[1]));
296
297 // Multiword - 2 results
298 $env = Environment::mock([
299 'REQUEST_METHOD' => 'GET',
300 'QUERY_STRING' => 'searchterm=stallman+software'
301 ]);
302 $request = Request::createFromEnvironment($env);
303 $response = $this->controller->getLinks($request, new Response());
304 $this->assertEquals(200, $response->getStatusCode());
305 $data = json_decode((string) $response->getBody(), true);
306 $this->assertEquals(2, count($data));
307 $this->assertEquals(41, $data[0]['id']);
308 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
309 $this->assertEquals(8, $data[1]['id']);
310 $this->assertEquals(self::NB_FIELDS_LINK, count($data[1]));
311
312 // URL encoding
313 $env = Environment::mock([
314 'REQUEST_METHOD' => 'GET',
315 'QUERY_STRING' => 'searchterm='. urlencode('@web')
316 ]);
317 $request = Request::createFromEnvironment($env);
318 $response = $this->controller->getLinks($request, new Response());
319 $this->assertEquals(200, $response->getStatusCode());
320 $data = json_decode((string) $response->getBody(), true);
321 $this->assertEquals(2, count($data));
322 $this->assertEquals(41, $data[0]['id']);
323 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
324 $this->assertEquals(8, $data[1]['id']);
325 $this->assertEquals(self::NB_FIELDS_LINK, count($data[1]));
326 }
327
328 public function testGetLinksSearchTermNoResult()
329 {
330 $env = Environment::mock([
331 'REQUEST_METHOD' => 'GET',
332 'QUERY_STRING' => 'searchterm=nope'
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(0, count($data));
339 }
340
341 public function testGetLinksSearchTags()
342 {
343 // Single tag
344 $env = Environment::mock([
345 'REQUEST_METHOD' => 'GET',
346 'QUERY_STRING' => 'searchtags=dev',
347 ]);
348 $request = Request::createFromEnvironment($env);
349 $response = $this->controller->getLinks($request, new Response());
350 $this->assertEquals(200, $response->getStatusCode());
351 $data = json_decode((string) $response->getBody(), true);
352 $this->assertEquals(2, count($data));
353 $this->assertEquals(0, $data[0]['id']);
354 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
355 $this->assertEquals(4, $data[1]['id']);
356 $this->assertEquals(self::NB_FIELDS_LINK, count($data[1]));
357
358 // Multitag + exclude
359 $env = Environment::mock([
360 'REQUEST_METHOD' => 'GET',
361 'QUERY_STRING' => 'searchtags=stuff+-gnu',
362 ]);
363 $request = Request::createFromEnvironment($env);
364 $response = $this->controller->getLinks($request, new Response());
365 $this->assertEquals(200, $response->getStatusCode());
366 $data = json_decode((string) $response->getBody(), true);
367 $this->assertEquals(1, count($data));
368 $this->assertEquals(41, $data[0]['id']);
369 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
370
371 // wildcard: placeholder at the start
372 $env = Environment::mock([
373 'REQUEST_METHOD' => 'GET',
374 'QUERY_STRING' => 'searchtags=*Tuff',
375 ]);
376 $request = Request::createFromEnvironment($env);
377 $response = $this->controller->getLinks($request, new Response());
378 $this->assertEquals(200, $response->getStatusCode());
379 $data = json_decode((string) $response->getBody(), true);
380 $this->assertEquals(2, count($data));
381 $this->assertEquals(41, $data[0]['id']);
382
383 // wildcard: placeholder at the end
384 $env = Environment::mock([
385 'REQUEST_METHOD' => 'GET',
386 'QUERY_STRING' => 'searchtags=c*',
387 ]);
388 $request = Request::createFromEnvironment($env);
389 $response = $this->controller->getLinks($request, new Response());
390 $this->assertEquals(200, $response->getStatusCode());
391 $data = json_decode((string) $response->getBody(), true);
392 $this->assertEquals(4, count($data));
393 $this->assertEquals(6, $data[0]['id']);
394
395 // wildcard: placeholder at the middle
396 $env = Environment::mock([
397 'REQUEST_METHOD' => 'GET',
398 'QUERY_STRING' => 'searchtags=w*b',
399 ]);
400 $request = Request::createFromEnvironment($env);
401 $response = $this->controller->getLinks($request, new Response());
402 $this->assertEquals(200, $response->getStatusCode());
403 $data = json_decode((string) $response->getBody(), true);
404 $this->assertEquals(4, count($data));
405 $this->assertEquals(6, $data[0]['id']);
406
407 // wildcard: match all
408 $env = Environment::mock([
409 'REQUEST_METHOD' => 'GET',
410 'QUERY_STRING' => 'searchtags=*',
411 ]);
412 $request = Request::createFromEnvironment($env);
413 $response = $this->controller->getLinks($request, new Response());
414 $this->assertEquals(200, $response->getStatusCode());
415 $data = json_decode((string) $response->getBody(), true);
416 $this->assertEquals(9, count($data));
417 $this->assertEquals(41, $data[0]['id']);
418
419 // wildcard: optional ('*' does not need to expand)
420 $env = Environment::mock([
421 'REQUEST_METHOD' => 'GET',
422 'QUERY_STRING' => 'searchtags=*stuff*',
423 ]);
424 $request = Request::createFromEnvironment($env);
425 $response = $this->controller->getLinks($request, new Response());
426 $this->assertEquals(200, $response->getStatusCode());
427 $data = json_decode((string) $response->getBody(), true);
428 $this->assertEquals(2, count($data));
429 $this->assertEquals(41, $data[0]['id']);
430
431 // wildcard: exclusions
432 $env = Environment::mock([
433 'REQUEST_METHOD' => 'GET',
434 'QUERY_STRING' => 'searchtags=*a*+-*e*',
435 ]);
436 $request = Request::createFromEnvironment($env);
437 $response = $this->controller->getLinks($request, new Response());
438 $this->assertEquals(200, $response->getStatusCode());
439 $data = json_decode((string) $response->getBody(), true);
440 $this->assertEquals(1, count($data));
441 $this->assertEquals(41, $data[0]['id']); // finds '#hashtag' in descr.
442
443 // wildcard: exclude all
444 $env = Environment::mock([
445 'REQUEST_METHOD' => 'GET',
446 'QUERY_STRING' => 'searchtags=-*',
447 ]);
448 $request = Request::createFromEnvironment($env);
449 $response = $this->controller->getLinks($request, new Response());
450 $this->assertEquals(200, $response->getStatusCode());
451 $data = json_decode((string) $response->getBody(), true);
452 $this->assertEquals(0, count($data));
453 }
454
455 /**
456 * Test getLinks service with search tags+terms.
457 */
458 public function testGetLinksSearchTermsAndTags()
459 {
460 $env = Environment::mock([
461 'REQUEST_METHOD' => 'GET',
462 'QUERY_STRING' => 'searchterm=poke&searchtags=dev',
463 ]);
464 $request = Request::createFromEnvironment($env);
465 $response = $this->controller->getLinks($request, new Response());
466 $this->assertEquals(200, $response->getStatusCode());
467 $data = json_decode((string) $response->getBody(), true);
468 $this->assertEquals(1, count($data));
469 $this->assertEquals(0, $data[0]['id']);
470 $this->assertEquals(self::NB_FIELDS_LINK, count($data[0]));
471 }
472}
diff --git a/tests/api/controllers/HistoryTest.php b/tests/api/controllers/HistoryTest.php
new file mode 100644
index 00000000..61046d97
--- /dev/null
+++ b/tests/api/controllers/HistoryTest.php
@@ -0,0 +1,216 @@
1<?php
2
3
4namespace Shaarli\Api\Controllers;
5
6
7use Shaarli\Config\ConfigManager;
8use Slim\Container;
9use Slim\Http\Environment;
10use Slim\Http\Request;
11use Slim\Http\Response;
12
13require_once 'tests/utils/ReferenceHistory.php';
14
15class HistoryTest extends \PHPUnit_Framework_TestCase
16{
17 /**
18 * @var string datastore to test write operations
19 */
20 protected static $testHistory = 'sandbox/history.php';
21
22 /**
23 * @var ConfigManager instance
24 */
25 protected $conf;
26
27 /**
28 * @var \ReferenceHistory instance.
29 */
30 protected $refHistory = null;
31
32 /**
33 * @var Container instance.
34 */
35 protected $container;
36
37 /**
38 * @var History controller instance.
39 */
40 protected $controller;
41
42 /**
43 * Before every test, instantiate a new Api with its config, plugins and links.
44 */
45 public function setUp()
46 {
47 $this->conf = new ConfigManager('tests/utils/config/configJson.json.php');
48 $this->refHistory = new \ReferenceHistory();
49 $this->refHistory->write(self::$testHistory);
50 $this->container = new Container();
51 $this->container['conf'] = $this->conf;
52 $this->container['db'] = true;
53 $this->container['history'] = new \History(self::$testHistory);
54
55 $this->controller = new History($this->container);
56 }
57
58 /**
59 * After every test, remove the test datastore.
60 */
61 public function tearDown()
62 {
63 @unlink(self::$testHistory);
64 }
65
66 /**
67 * Test /history service without parameter.
68 */
69 public function testGetHistory()
70 {
71 $env = Environment::mock([
72 'REQUEST_METHOD' => 'GET',
73 ]);
74 $request = Request::createFromEnvironment($env);
75
76 $response = $this->controller->getHistory($request, new Response());
77 $this->assertEquals(200, $response->getStatusCode());
78 $data = json_decode((string) $response->getBody(), true);
79
80 $this->assertEquals($this->refHistory->count(), count($data));
81
82 $this->assertEquals(\History::DELETED, $data[0]['event']);
83 $this->assertEquals(
84 \DateTime::createFromFormat('Ymd_His', '20170303_121216')->format(\DateTime::ATOM),
85 $data[0]['datetime']
86 );
87 $this->assertEquals(124, $data[0]['id']);
88
89 $this->assertEquals(\History::SETTINGS, $data[1]['event']);
90 $this->assertEquals(
91 \DateTime::createFromFormat('Ymd_His', '20170302_121215')->format(\DateTime::ATOM),
92 $data[1]['datetime']
93 );
94 $this->assertNull($data[1]['id']);
95
96 $this->assertEquals(\History::UPDATED, $data[2]['event']);
97 $this->assertEquals(
98 \DateTime::createFromFormat('Ymd_His', '20170301_121214')->format(\DateTime::ATOM),
99 $data[2]['datetime']
100 );
101 $this->assertEquals(123, $data[2]['id']);
102
103 $this->assertEquals(\History::CREATED, $data[3]['event']);
104 $this->assertEquals(
105 \DateTime::createFromFormat('Ymd_His', '20170201_121214')->format(\DateTime::ATOM),
106 $data[3]['datetime']
107 );
108 $this->assertEquals(124, $data[3]['id']);
109
110 $this->assertEquals(\History::CREATED, $data[4]['event']);
111 $this->assertEquals(
112 \DateTime::createFromFormat('Ymd_His', '20170101_121212')->format(\DateTime::ATOM),
113 $data[4]['datetime']
114 );
115 $this->assertEquals(123, $data[4]['id']);
116 }
117
118 /**
119 * Test /history service with limit parameter.
120 */
121 public function testGetHistoryLimit()
122 {
123 $env = Environment::mock([
124 'REQUEST_METHOD' => 'GET',
125 'QUERY_STRING' => 'limit=1'
126 ]);
127 $request = Request::createFromEnvironment($env);
128
129 $response = $this->controller->getHistory($request, new Response());
130 $this->assertEquals(200, $response->getStatusCode());
131 $data = json_decode((string) $response->getBody(), true);
132
133 $this->assertEquals(1, count($data));
134
135 $this->assertEquals(\History::DELETED, $data[0]['event']);
136 $this->assertEquals(
137 \DateTime::createFromFormat('Ymd_His', '20170303_121216')->format(\DateTime::ATOM),
138 $data[0]['datetime']
139 );
140 $this->assertEquals(124, $data[0]['id']);
141 }
142
143 /**
144 * Test /history service with offset parameter.
145 */
146 public function testGetHistoryOffset()
147 {
148 $env = Environment::mock([
149 'REQUEST_METHOD' => 'GET',
150 'QUERY_STRING' => 'offset=4'
151 ]);
152 $request = Request::createFromEnvironment($env);
153
154 $response = $this->controller->getHistory($request, new Response());
155 $this->assertEquals(200, $response->getStatusCode());
156 $data = json_decode((string) $response->getBody(), true);
157
158 $this->assertEquals(1, count($data));
159
160 $this->assertEquals(\History::CREATED, $data[0]['event']);
161 $this->assertEquals(
162 \DateTime::createFromFormat('Ymd_His', '20170101_121212')->format(\DateTime::ATOM),
163 $data[0]['datetime']
164 );
165 $this->assertEquals(123, $data[0]['id']);
166 }
167
168 /**
169 * Test /history service with since parameter.
170 */
171 public function testGetHistorySince()
172 {
173 $env = Environment::mock([
174 'REQUEST_METHOD' => 'GET',
175 'QUERY_STRING' => 'since=2017-03-03T00:00:00%2B00:00'
176 ]);
177 $request = Request::createFromEnvironment($env);
178
179 $response = $this->controller->getHistory($request, new Response());
180 $this->assertEquals(200, $response->getStatusCode());
181 $data = json_decode((string) $response->getBody(), true);
182
183 $this->assertEquals(1, count($data));
184
185 $this->assertEquals(\History::DELETED, $data[0]['event']);
186 $this->assertEquals(
187 \DateTime::createFromFormat('Ymd_His', '20170303_121216')->format(\DateTime::ATOM),
188 $data[0]['datetime']
189 );
190 $this->assertEquals(124, $data[0]['id']);
191 }
192
193 /**
194 * Test /history service with since parameter.
195 */
196 public function testGetHistorySinceOffsetLimit()
197 {
198 $env = Environment::mock([
199 'REQUEST_METHOD' => 'GET',
200 'QUERY_STRING' => 'since=2017-02-01T00:00:00%2B00:00&offset=1&limit=1'
201 ]);
202 $request = Request::createFromEnvironment($env);
203
204 $response = $this->controller->getHistory($request, new Response());
205 $this->assertEquals(200, $response->getStatusCode());
206 $data = json_decode((string) $response->getBody(), true);
207
208 $this->assertEquals(1, count($data));
209
210 $this->assertEquals(\History::SETTINGS, $data[0]['event']);
211 $this->assertEquals(
212 \DateTime::createFromFormat('Ymd_His', '20170302_121215')->format(\DateTime::ATOM),
213 $data[0]['datetime']
214 );
215 }
216}
diff --git a/tests/api/controllers/InfoTest.php b/tests/api/controllers/InfoTest.php
new file mode 100644
index 00000000..f7e63bfa
--- /dev/null
+++ b/tests/api/controllers/InfoTest.php
@@ -0,0 +1,115 @@
1<?php
2namespace Shaarli\Api\Controllers;
3
4use Shaarli\Config\ConfigManager;
5
6use Slim\Container;
7use Slim\Http\Environment;
8use Slim\Http\Request;
9use Slim\Http\Response;
10
11/**
12 * Class InfoTest
13 *
14 * Test REST API controller Info.
15 *
16 * @package Api\Controllers
17 */
18class InfoTest extends \PHPUnit_Framework_TestCase
19{
20 /**
21 * @var string datastore to test write operations
22 */
23 protected static $testDatastore = 'sandbox/datastore.php';
24
25 /**
26 * @var ConfigManager instance
27 */
28 protected $conf;
29
30 /**
31 * @var \ReferenceLinkDB instance.
32 */
33 protected $refDB = null;
34
35 /**
36 * @var Container instance.
37 */
38 protected $container;
39
40 /**
41 * @var Info controller instance.
42 */
43 protected $controller;
44
45 /**
46 * Before every test, instantiate a new Api with its config, plugins and links.
47 */
48 public function setUp()
49 {
50 $this->conf = new ConfigManager('tests/utils/config/configJson.json.php');
51 $this->refDB = new \ReferenceLinkDB();
52 $this->refDB->write(self::$testDatastore);
53
54 $this->container = new Container();
55 $this->container['conf'] = $this->conf;
56 $this->container['db'] = new \LinkDB(self::$testDatastore, true, false);
57 $this->container['history'] = null;
58
59 $this->controller = new Info($this->container);
60 }
61
62 /**
63 * After every test, remove the test datastore.
64 */
65 public function tearDown()
66 {
67 @unlink(self::$testDatastore);
68 }
69
70 /**
71 * Test /info service.
72 */
73 public function testGetInfo()
74 {
75 $env = Environment::mock([
76 'REQUEST_METHOD' => 'GET',
77 ]);
78 $request = Request::createFromEnvironment($env);
79
80 $response = $this->controller->getInfo($request, new Response());
81 $this->assertEquals(200, $response->getStatusCode());
82 $data = json_decode((string) $response->getBody(), true);
83
84 $this->assertEquals(\ReferenceLinkDB::$NB_LINKS_TOTAL, $data['global_counter']);
85 $this->assertEquals(2, $data['private_counter']);
86 $this->assertEquals('Shaarli', $data['settings']['title']);
87 $this->assertEquals('?', $data['settings']['header_link']);
88 $this->assertEquals('UTC', $data['settings']['timezone']);
89 $this->assertEquals(ConfigManager::$DEFAULT_PLUGINS, $data['settings']['enabled_plugins']);
90 $this->assertEquals(false, $data['settings']['default_private_links']);
91
92 $title = 'My links';
93 $headerLink = 'http://shaarli.tld';
94 $timezone = 'Europe/Paris';
95 $enabledPlugins = array('foo', 'bar');
96 $defaultPrivateLinks = true;
97 $this->conf->set('general.title', $title);
98 $this->conf->set('general.header_link', $headerLink);
99 $this->conf->set('general.timezone', $timezone);
100 $this->conf->set('general.enabled_plugins', $enabledPlugins);
101 $this->conf->set('privacy.default_private_links', $defaultPrivateLinks);
102
103 $response = $this->controller->getInfo($request, new Response());
104 $this->assertEquals(200, $response->getStatusCode());
105 $data = json_decode((string) $response->getBody(), true);
106
107 $this->assertEquals(\ReferenceLinkDB::$NB_LINKS_TOTAL, $data['global_counter']);
108 $this->assertEquals(2, $data['private_counter']);
109 $this->assertEquals($title, $data['settings']['title']);
110 $this->assertEquals($headerLink, $data['settings']['header_link']);
111 $this->assertEquals($timezone, $data['settings']['timezone']);
112 $this->assertEquals($enabledPlugins, $data['settings']['enabled_plugins']);
113 $this->assertEquals($defaultPrivateLinks, $data['settings']['default_private_links']);
114 }
115}
diff --git a/tests/api/controllers/PostLinkTest.php b/tests/api/controllers/PostLinkTest.php
new file mode 100644
index 00000000..31954e39
--- /dev/null
+++ b/tests/api/controllers/PostLinkTest.php
@@ -0,0 +1,216 @@
1<?php
2
3namespace Shaarli\Api\Controllers;
4
5
6use Shaarli\Config\ConfigManager;
7use Slim\Container;
8use Slim\Http\Environment;
9use Slim\Http\Request;
10use Slim\Http\Response;
11
12/**
13 * Class PostLinkTest
14 *
15 * Test POST Link REST API service.
16 *
17 * @package Shaarli\Api\Controllers
18 */
19class PostLinkTest 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 string datastore to test write operations
28 */
29 protected static $testHistory = 'sandbox/history.php';
30
31 /**
32 * @var ConfigManager instance
33 */
34 protected $conf;
35
36 /**
37 * @var \ReferenceLinkDB instance.
38 */
39 protected $refDB = null;
40
41 /**
42 * @var \History instance.
43 */
44 protected $history;
45
46 /**
47 * @var Container instance.
48 */
49 protected $container;
50
51 /**
52 * @var Links controller instance.
53 */
54 protected $controller;
55
56 /**
57 * Number of JSON field per link.
58 */
59 const NB_FIELDS_LINK = 9;
60
61 /**
62 * Before every test, instantiate a new Api with its config, plugins and links.
63 */
64 public function setUp()
65 {
66 $this->conf = new ConfigManager('tests/utils/config/configJson.json.php');
67 $this->refDB = new \ReferenceLinkDB();
68 $this->refDB->write(self::$testDatastore);
69
70 $refHistory = new \ReferenceHistory();
71 $refHistory->write(self::$testHistory);
72 $this->history = new \History(self::$testHistory);
73
74 $this->container = new Container();
75 $this->container['conf'] = $this->conf;
76 $this->container['db'] = new \LinkDB(self::$testDatastore, true, false);
77 $this->container['history'] = new \History(self::$testHistory);
78
79 $this->controller = new Links($this->container);
80
81 $mock = $this->getMock('\Slim\Router', ['relativePathFor']);
82 $mock->expects($this->any())
83 ->method('relativePathFor')
84 ->willReturn('api/v1/links/1');
85
86 // affect @property-read... seems to work
87 $this->controller->getCi()->router = $mock;
88
89 // Used by index_url().
90 $this->controller->getCi()['environment'] = [
91 'SERVER_NAME' => 'domain.tld',
92 'SERVER_PORT' => 80,
93 'SCRIPT_NAME' => '/',
94 ];
95 }
96
97 /**
98 * After every test, remove the test datastore.
99 */
100 public function tearDown()
101 {
102 @unlink(self::$testDatastore);
103 @unlink(self::$testHistory);
104 }
105
106 /**
107 * Test link creation without any field: creates a blank note.
108 */
109 public function testPostLinkMinimal()
110 {
111 $env = Environment::mock([
112 'REQUEST_METHOD' => 'POST',
113 ]);
114
115 $request = Request::createFromEnvironment($env);
116
117 $response = $this->controller->postLink($request, new Response());
118 $this->assertEquals(201, $response->getStatusCode());
119 $this->assertEquals('api/v1/links/1', $response->getHeader('Location')[0]);
120 $data = json_decode((string) $response->getBody(), true);
121 $this->assertEquals(self::NB_FIELDS_LINK, count($data));
122 $this->assertEquals(43, $data['id']);
123 $this->assertRegExp('/[\w-_]{6}/', $data['shorturl']);
124 $this->assertEquals('http://domain.tld/?' . $data['shorturl'], $data['url']);
125 $this->assertEquals('?' . $data['shorturl'], $data['title']);
126 $this->assertEquals('', $data['description']);
127 $this->assertEquals([], $data['tags']);
128 $this->assertEquals(false, $data['private']);
129 $this->assertTrue(new \DateTime('5 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['created']));
130 $this->assertEquals('', $data['updated']);
131
132 $historyEntry = $this->history->getHistory()[0];
133 $this->assertEquals(\History::CREATED, $historyEntry['event']);
134 $this->assertTrue(
135 (new \DateTime())->add(\DateInterval::createFromDateString('-5 seconds')) < $historyEntry['datetime']
136 );
137 $this->assertEquals(43, $historyEntry['id']);
138 }
139
140 /**
141 * Test link creation with all available fields.
142 */
143 public function testPostLinkFull()
144 {
145 $link = [
146 'url' => 'website.tld/test?foo=bar',
147 'title' => 'new entry',
148 'description' => 'shaare description',
149 'tags' => ['one', 'two'],
150 'private' => true,
151 ];
152 $env = Environment::mock([
153 'REQUEST_METHOD' => 'POST',
154 'CONTENT_TYPE' => 'application/json'
155 ]);
156
157 $request = Request::createFromEnvironment($env);
158 $request = $request->withParsedBody($link);
159 $response = $this->controller->postLink($request, new Response());
160
161 $this->assertEquals(201, $response->getStatusCode());
162 $this->assertEquals('api/v1/links/1', $response->getHeader('Location')[0]);
163 $data = json_decode((string) $response->getBody(), true);
164 $this->assertEquals(self::NB_FIELDS_LINK, count($data));
165 $this->assertEquals(43, $data['id']);
166 $this->assertRegExp('/[\w-_]{6}/', $data['shorturl']);
167 $this->assertEquals('http://' . $link['url'], $data['url']);
168 $this->assertEquals($link['title'], $data['title']);
169 $this->assertEquals($link['description'], $data['description']);
170 $this->assertEquals($link['tags'], $data['tags']);
171 $this->assertEquals(true, $data['private']);
172 $this->assertTrue(new \DateTime('2 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['created']));
173 $this->assertEquals('', $data['updated']);
174 }
175
176 /**
177 * Test link creation with an existing link (duplicate URL). Should return a 409 HTTP error and the existing link.
178 */
179 public function testPostLinkDuplicate()
180 {
181 $link = [
182 'url' => 'mediagoblin.org/',
183 'title' => 'new entry',
184 'description' => 'shaare description',
185 'tags' => ['one', 'two'],
186 'private' => true,
187 ];
188 $env = Environment::mock([
189 'REQUEST_METHOD' => 'POST',
190 'CONTENT_TYPE' => 'application/json'
191 ]);
192
193 $request = Request::createFromEnvironment($env);
194 $request = $request->withParsedBody($link);
195 $response = $this->controller->postLink($request, new Response());
196
197 $this->assertEquals(409, $response->getStatusCode());
198 $data = json_decode((string) $response->getBody(), true);
199 $this->assertEquals(self::NB_FIELDS_LINK, count($data));
200 $this->assertEquals(7, $data['id']);
201 $this->assertEquals('IuWvgA', $data['shorturl']);
202 $this->assertEquals('http://mediagoblin.org/', $data['url']);
203 $this->assertEquals('MediaGoblin', $data['title']);
204 $this->assertEquals('A free software media publishing platform #hashtagOther', $data['description']);
205 $this->assertEquals(['gnu', 'media', 'web', '.hidden', 'hashtag'], $data['tags']);
206 $this->assertEquals(false, $data['private']);
207 $this->assertEquals(
208 \DateTime::createFromFormat(\LinkDB::LINK_DATE_FORMAT, '20130614_184135'),
209 \DateTime::createFromFormat(\DateTime::ATOM, $data['created'])
210 );
211 $this->assertEquals(
212 \DateTime::createFromFormat(\LinkDB::LINK_DATE_FORMAT, '20130615_184230'),
213 \DateTime::createFromFormat(\DateTime::ATOM, $data['updated'])
214 );
215 }
216}
diff --git a/tests/api/controllers/PutLinkTest.php b/tests/api/controllers/PutLinkTest.php
new file mode 100644
index 00000000..8a562571
--- /dev/null
+++ b/tests/api/controllers/PutLinkTest.php
@@ -0,0 +1,222 @@
1<?php
2
3
4namespace Shaarli\Api\Controllers;
5
6
7use Shaarli\Config\ConfigManager;
8use Slim\Container;
9use Slim\Http\Environment;
10use Slim\Http\Request;
11use Slim\Http\Response;
12
13class PutLinkTest extends \PHPUnit_Framework_TestCase
14{
15 /**
16 * @var string datastore to test write operations
17 */
18 protected static $testDatastore = 'sandbox/datastore.php';
19
20 /**
21 * @var string datastore to test write operations
22 */
23 protected static $testHistory = 'sandbox/history.php';
24
25 /**
26 * @var ConfigManager instance
27 */
28 protected $conf;
29
30 /**
31 * @var \ReferenceLinkDB instance.
32 */
33 protected $refDB = null;
34
35 /**
36 * @var \History instance.
37 */
38 protected $history;
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 links.
57 */
58 public function setUp()
59 {
60 $this->conf = new ConfigManager('tests/utils/config/configJson.json.php');
61 $this->refDB = new \ReferenceLinkDB();
62 $this->refDB->write(self::$testDatastore);
63
64 $refHistory = new \ReferenceHistory();
65 $refHistory->write(self::$testHistory);
66 $this->history = new \History(self::$testHistory);
67
68 $this->container = new Container();
69 $this->container['conf'] = $this->conf;
70 $this->container['db'] = new \LinkDB(self::$testDatastore, true, false);
71 $this->container['history'] = new \History(self::$testHistory);
72
73 $this->controller = new Links($this->container);
74
75 // Used by index_url().
76 $this->controller->getCi()['environment'] = [
77 'SERVER_NAME' => 'domain.tld',
78 'SERVER_PORT' => 80,
79 'SCRIPT_NAME' => '/',
80 ];
81 }
82
83 /**
84 * After every test, remove the test datastore.
85 */
86 public function tearDown()
87 {
88 @unlink(self::$testDatastore);
89 @unlink(self::$testHistory);
90 }
91
92 /**
93 * Test link update without value: reset the link to default values
94 */
95 public function testPutLinkMinimal()
96 {
97 $env = Environment::mock([
98 'REQUEST_METHOD' => 'PUT',
99 ]);
100 $id = '41';
101 $request = Request::createFromEnvironment($env);
102
103 $response = $this->controller->putLink($request, new Response(), ['id' => $id]);
104 $this->assertEquals(200, $response->getStatusCode());
105 $data = json_decode((string) $response->getBody(), true);
106 $this->assertEquals(self::NB_FIELDS_LINK, count($data));
107 $this->assertEquals($id, $data['id']);
108 $this->assertEquals('WDWyig', $data['shorturl']);
109 $this->assertEquals('http://domain.tld/?WDWyig', $data['url']);
110 $this->assertEquals('?WDWyig', $data['title']);
111 $this->assertEquals('', $data['description']);
112 $this->assertEquals([], $data['tags']);
113 $this->assertEquals(false, $data['private']);
114 $this->assertEquals(
115 \DateTime::createFromFormat('Ymd_His', '20150310_114651'),
116 \DateTime::createFromFormat(\DateTime::ATOM, $data['created'])
117 );
118 $this->assertTrue(new \DateTime('5 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['updated']));
119
120 $historyEntry = $this->history->getHistory()[0];
121 $this->assertEquals(\History::UPDATED, $historyEntry['event']);
122 $this->assertTrue(
123 (new \DateTime())->add(\DateInterval::createFromDateString('-5 seconds')) < $historyEntry['datetime']
124 );
125 $this->assertEquals($id, $historyEntry['id']);
126 }
127
128 /**
129 * Test link update with new values
130 */
131 public function testPutLinkWithValues()
132 {
133 $env = Environment::mock([
134 'REQUEST_METHOD' => 'PUT',
135 'CONTENT_TYPE' => 'application/json'
136 ]);
137 $id = 41;
138 $update = [
139 'url' => 'http://somewhere.else',
140 'title' => 'Le Cid',
141 'description' => 'Percé jusques au fond du cœur [...]',
142 'tags' => ['corneille', 'rodrigue'],
143 'private' => true,
144 ];
145 $request = Request::createFromEnvironment($env);
146 $request = $request->withParsedBody($update);
147
148 $response = $this->controller->putLink($request, new Response(), ['id' => $id]);
149 $this->assertEquals(200, $response->getStatusCode());
150 $data = json_decode((string) $response->getBody(), true);
151 $this->assertEquals(self::NB_FIELDS_LINK, count($data));
152 $this->assertEquals($id, $data['id']);
153 $this->assertEquals('WDWyig', $data['shorturl']);
154 $this->assertEquals('http://somewhere.else', $data['url']);
155 $this->assertEquals('Le Cid', $data['title']);
156 $this->assertEquals('Percé jusques au fond du cœur [...]', $data['description']);
157 $this->assertEquals(['corneille', 'rodrigue'], $data['tags']);
158 $this->assertEquals(true, $data['private']);
159 $this->assertEquals(
160 \DateTime::createFromFormat('Ymd_His', '20150310_114651'),
161 \DateTime::createFromFormat(\DateTime::ATOM, $data['created'])
162 );
163 $this->assertTrue(new \DateTime('5 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['updated']));
164 }
165
166 /**
167 * Test link update with an existing URL: 409 Conflict with the existing link as body
168 */
169 public function testPutLinkDuplicate()
170 {
171 $link = [
172 'url' => 'mediagoblin.org/',
173 'title' => 'new entry',
174 'description' => 'shaare description',
175 'tags' => ['one', 'two'],
176 'private' => true,
177 ];
178 $env = Environment::mock([
179 'REQUEST_METHOD' => 'PUT',
180 'CONTENT_TYPE' => 'application/json'
181 ]);
182
183 $request = Request::createFromEnvironment($env);
184 $request = $request->withParsedBody($link);
185 $response = $this->controller->putLink($request, new Response(), ['id' => 41]);
186
187 $this->assertEquals(409, $response->getStatusCode());
188 $data = json_decode((string) $response->getBody(), true);
189 $this->assertEquals(self::NB_FIELDS_LINK, count($data));
190 $this->assertEquals(7, $data['id']);
191 $this->assertEquals('IuWvgA', $data['shorturl']);
192 $this->assertEquals('http://mediagoblin.org/', $data['url']);
193 $this->assertEquals('MediaGoblin', $data['title']);
194 $this->assertEquals('A free software media publishing platform #hashtagOther', $data['description']);
195 $this->assertEquals(['gnu', 'media', 'web', '.hidden', 'hashtag'], $data['tags']);
196 $this->assertEquals(false, $data['private']);
197 $this->assertEquals(
198 \DateTime::createFromFormat(\LinkDB::LINK_DATE_FORMAT, '20130614_184135'),
199 \DateTime::createFromFormat(\DateTime::ATOM, $data['created'])
200 );
201 $this->assertEquals(
202 \DateTime::createFromFormat(\LinkDB::LINK_DATE_FORMAT, '20130615_184230'),
203 \DateTime::createFromFormat(\DateTime::ATOM, $data['updated'])
204 );
205 }
206
207 /**
208 * Test link update on non existent link => ApiLinkNotFoundException.
209 *
210 * @expectedException Shaarli\Api\Exceptions\ApiLinkNotFoundException
211 * @expectedExceptionMessage Link not found
212 */
213 public function testGetLink404()
214 {
215 $env = Environment::mock([
216 'REQUEST_METHOD' => 'PUT',
217 ]);
218 $request = Request::createFromEnvironment($env);
219
220 $this->controller->putLink($request, new Response(), ['id' => -1]);
221 }
222}