4 namespace Shaarli\Api\Controllers
;
6 use malkusch\lock\mutex\NoMutex
;
7 use Shaarli\Bookmark\Bookmark
;
8 use Shaarli\Bookmark\BookmarkFileService
;
9 use Shaarli\Config\ConfigManager
;
12 use Slim\Http\Environment
;
13 use Slim\Http\Request
;
14 use Slim\Http\Response
;
16 class PutLinkTest
extends \Shaarli\TestCase
19 * @var string datastore to test write operations
21 protected static $testDatastore = 'sandbox/datastore.php';
24 * @var string datastore to test write operations
26 protected static $testHistory = 'sandbox/history.php';
29 * @var ConfigManager instance
34 * @var \ReferenceLinkDB instance.
36 protected $refDB = null;
39 * @var BookmarkFileService instance.
41 protected $bookmarkService;
44 * @var HistoryController instance.
49 * @var Container instance.
54 * @var Links controller instance.
56 protected $controller;
59 * Number of JSON field per link.
61 const NB_FIELDS_LINK
= 9;
64 * Before every test, instantiate a new Api with its config, plugins and bookmarks.
66 protected function setUp(): void
68 $mutex = new NoMutex();
69 $this->conf
= new ConfigManager('tests/utils/config/configJson');
70 $this->conf
->set('resource.datastore', self
::$testDatastore);
71 $this->refDB
= new \
ReferenceLinkDB();
72 $this->refDB
->write(self
::$testDatastore);
73 $refHistory = new \
ReferenceHistory();
74 $refHistory->write(self
::$testHistory);
75 $this->history
= new History(self
::$testHistory);
76 $this->bookmarkService
= new BookmarkFileService($this->conf
, $this->history
, $mutex, true);
78 $this->container
= new Container();
79 $this->container
['conf'] = $this->conf
;
80 $this->container
['db'] = $this->bookmarkService
;
81 $this->container
['history'] = $this->history
;
83 $this->controller
= new Links($this->container
);
85 // Used by index_url().
86 $this->controller
->getCi()['environment'] = [
87 'SERVER_NAME' => 'domain.tld',
94 * After every test, remove the test datastore.
96 protected function tearDown(): void
98 @unlink(self
::$testDatastore);
99 @unlink(self
::$testHistory);
103 * Test link update without value: reset the link to default values
105 public function testPutLinkMinimal()
107 $env = Environment
::mock([
108 'REQUEST_METHOD' => 'PUT',
111 $request = Request
::createFromEnvironment($env);
113 $response = $this->controller
->putLink($request, new Response(), ['id' => $id]);
114 $this->assertEquals(200, $response->getStatusCode());
115 $data = json_decode((string) $response->getBody(), true);
116 $this->assertEquals(self
::NB_FIELDS_LINK
, count($data));
117 $this->assertEquals($id, $data['id']);
118 $this->assertEquals('WDWyig', $data['shorturl']);
119 $this->assertEquals('http://domain.tld/shaare/WDWyig', $data['url']);
120 $this->assertEquals('/shaare/WDWyig', $data['title']);
121 $this->assertEquals('', $data['description']);
122 $this->assertEquals([], $data['tags']);
123 $this->assertEquals(true, $data['private']);
125 \DateTime
::createFromFormat('Ymd_His', '20150310_114651'),
126 \DateTime
::createFromFormat(\DateTime
::ATOM
, $data['created'])
129 new \
DateTime('5 seconds ago') < \DateTime
::createFromFormat(\DateTime
::ATOM
, $data['updated'])
132 $historyEntry = $this->history
->getHistory()[0];
133 $this->assertEquals(History
::UPDATED
, $historyEntry['event']);
135 (new \
DateTime())->add(\DateInterval
::createFromDateString('-5 seconds')) < $historyEntry['datetime']
137 $this->assertEquals($id, $historyEntry['id']);
141 * Test link update with new values
143 public function testPutLinkWithValues()
145 $env = Environment
::mock([
146 'REQUEST_METHOD' => 'PUT',
147 'CONTENT_TYPE' => 'application/json'
151 'url' => 'http://somewhere.else',
153 'description' => 'Percé jusques au fond du cœur [...]',
154 'tags' => ['corneille', 'rodrigue'],
157 $request = Request
::createFromEnvironment($env);
158 $request = $request->withParsedBody($update);
160 $response = $this->controller
->putLink($request, new Response(), ['id' => $id]);
161 $this->assertEquals(200, $response->getStatusCode());
162 $data = json_decode((string) $response->getBody(), true);
163 $this->assertEquals(self
::NB_FIELDS_LINK
, count($data));
164 $this->assertEquals($id, $data['id']);
165 $this->assertEquals('WDWyig', $data['shorturl']);
166 $this->assertEquals('http://somewhere.else', $data['url']);
167 $this->assertEquals('Le Cid', $data['title']);
168 $this->assertEquals('Percé jusques au fond du cœur [...]', $data['description']);
169 $this->assertEquals(['corneille', 'rodrigue'], $data['tags']);
170 $this->assertEquals(true, $data['private']);
172 \DateTime
::createFromFormat('Ymd_His', '20150310_114651'),
173 \DateTime
::createFromFormat(\DateTime
::ATOM
, $data['created'])
176 new \
DateTime('5 seconds ago') < \DateTime
::createFromFormat(\DateTime
::ATOM
, $data['updated'])
181 * Test link update with an existing URL: 409 Conflict with the existing link as body
183 public function testPutLinkDuplicate()
186 'url' => 'mediagoblin.org/',
187 'title' => 'new entry',
188 'description' => 'shaare description',
189 'tags' => ['one', 'two'],
192 $env = Environment
::mock([
193 'REQUEST_METHOD' => 'PUT',
194 'CONTENT_TYPE' => 'application/json'
197 $request = Request
::createFromEnvironment($env);
198 $request = $request->withParsedBody($link);
199 $response = $this->controller
->putLink($request, new Response(), ['id' => 41]);
201 $this->assertEquals(409, $response->getStatusCode());
202 $data = json_decode((string) $response->getBody(), true);
203 $this->assertEquals(self
::NB_FIELDS_LINK
, count($data));
204 $this->assertEquals(7, $data['id']);
205 $this->assertEquals('IuWvgA', $data['shorturl']);
206 $this->assertEquals('http://mediagoblin.org/', $data['url']);
207 $this->assertEquals('MediaGoblin', $data['title']);
208 $this->assertEquals('A free software media publishing platform #hashtagOther', $data['description']);
209 $this->assertEquals(['gnu', 'media', 'web', '.hidden', 'hashtag'], $data['tags']);
210 $this->assertEquals(false, $data['private']);
212 \DateTime
::createFromFormat(Bookmark
::LINK_DATE_FORMAT
, '20130614_184135'),
213 \DateTime
::createFromFormat(\DateTime
::ATOM
, $data['created'])
216 \DateTime
::createFromFormat(Bookmark
::LINK_DATE_FORMAT
, '20130615_184230'),
217 \DateTime
::createFromFormat(\DateTime
::ATOM
, $data['updated'])
222 * Test link update on non existent link => ApiLinkNotFoundException.
224 public function testGetLink404()
226 $this->expectException(\Shaarli\Api\Exceptions\ApiLinkNotFoundException
::class);
227 $this->expectExceptionMessage('Link not found');
229 $env = Environment
::mock([
230 'REQUEST_METHOD' => 'PUT',
232 $request = Request
::createFromEnvironment($env);
234 $this->controller
->putLink($request, new Response(), ['id' => -1]);
238 * Test link creation with a tag string provided
240 public function testPutLinkWithTagString(): void
246 $env = Environment
::mock([
247 'REQUEST_METHOD' => 'PUT',
248 'CONTENT_TYPE' => 'application/json'
251 $request = Request
::createFromEnvironment($env);
252 $request = $request->withParsedBody($link);
253 $response = $this->controller
->putLink($request, new Response(), ['id' => $id]);
255 $this->assertEquals(200, $response->getStatusCode());
256 $data = json_decode((string) $response->getBody(), true);
257 $this->assertEquals(self
::NB_FIELDS_LINK
, count($data));
258 $this->assertEquals(['one', 'two'], $data['tags']);
262 * Test link creation with a tag string provided
264 public function testPutLinkWithTagString2(): void
267 'tags' => ['one two'],
270 $env = Environment
::mock([
271 'REQUEST_METHOD' => 'PUT',
272 'CONTENT_TYPE' => 'application/json'
275 $request = Request
::createFromEnvironment($env);
276 $request = $request->withParsedBody($link);
277 $response = $this->controller
->putLink($request, new Response(), ['id' => $id]);
279 $this->assertEquals(200, $response->getStatusCode());
280 $data = json_decode((string) $response->getBody(), true);
281 $this->assertEquals(self
::NB_FIELDS_LINK
, count($data));
282 $this->assertEquals(['one', 'two'], $data['tags']);