]> git.immae.eu Git - github/shaarli/Shaarli.git/blame - tests/api/controllers/links/PostLinkTest.php
New plugin hook: ability to add custom filters to Shaarli search engine
[github/shaarli/Shaarli.git] / tests / api / controllers / links / PostLinkTest.php
CommitLineData
68016e37
A
1<?php
2
3namespace Shaarli\Api\Controllers;
4
fd1ddad9 5use malkusch\lock\mutex\NoMutex;
e26e2060
A
6use Shaarli\Bookmark\Bookmark;
7use Shaarli\Bookmark\BookmarkFileService;
68016e37 8use Shaarli\Config\ConfigManager;
dea72c71 9use Shaarli\History;
bcba6bd3 10use Shaarli\Plugin\PluginManager;
a5a9cf23 11use Shaarli\TestCase;
68016e37
A
12use Slim\Container;
13use Slim\Http\Environment;
14use Slim\Http\Request;
15use Slim\Http\Response;
5617dcf9 16use Slim\Router;
68016e37
A
17
18/**
19 * Class PostLinkTest
20 *
21 * Test POST Link REST API service.
22 *
23 * @package Shaarli\Api\Controllers
24 */
5617dcf9 25class PostLinkTest extends TestCase
68016e37
A
26{
27 /**
28 * @var string datastore to test write operations
29 */
30 protected static $testDatastore = 'sandbox/datastore.php';
31
813849e5
A
32 /**
33 * @var string datastore to test write operations
34 */
35 protected static $testHistory = 'sandbox/history.php';
36
68016e37
A
37 /**
38 * @var ConfigManager instance
39 */
40 protected $conf;
41
42 /**
43 * @var \ReferenceLinkDB instance.
44 */
45 protected $refDB = null;
46
e26e2060
A
47 /**
48 * @var BookmarkFileService instance.
49 */
50 protected $bookmarkService;
51
813849e5 52 /**
dea72c71 53 * @var HistoryController instance.
813849e5
A
54 */
55 protected $history;
56
68016e37
A
57 /**
58 * @var Container instance.
59 */
60 protected $container;
61
62 /**
63 * @var Links controller instance.
64 */
65 protected $controller;
66
67 /**
68 * Number of JSON field per link.
69 */
70 const NB_FIELDS_LINK = 9;
71
72 /**
e26e2060 73 * Before every test, instantiate a new Api with its config, plugins and bookmarks.
68016e37 74 */
8f60e120 75 protected function setUp(): void
68016e37 76 {
fd1ddad9 77 $mutex = new NoMutex();
e26e2060
A
78 $this->conf = new ConfigManager('tests/utils/config/configJson');
79 $this->conf->set('resource.datastore', self::$testDatastore);
68016e37
A
80 $this->refDB = new \ReferenceLinkDB();
81 $this->refDB->write(self::$testDatastore);
813849e5
A
82 $refHistory = new \ReferenceHistory();
83 $refHistory->write(self::$testHistory);
dea72c71 84 $this->history = new History(self::$testHistory);
bcba6bd3
A
85 $pluginManager = new PluginManager($this->conf);
86 $this->bookmarkService = new BookmarkFileService(
87 $this->conf,
88 $pluginManager,
89 $this->history,
90 $mutex,
91 true
92 );
68016e37
A
93 $this->container = new Container();
94 $this->container['conf'] = $this->conf;
e26e2060
A
95 $this->container['db'] = $this->bookmarkService;
96 $this->container['history'] = $this->history;
68016e37
A
97
98 $this->controller = new Links($this->container);
99
5617dcf9 100 $mock = $this->createMock(Router::class);
68016e37 101 $mock->expects($this->any())
b37ca790
LC
102 ->method('pathFor')
103 ->willReturn('/api/v1/bookmarks/1');
68016e37
A
104
105 // affect @property-read... seems to work
106 $this->controller->getCi()->router = $mock;
107
108 // Used by index_url().
109 $this->controller->getCi()['environment'] = [
110 'SERVER_NAME' => 'domain.tld',
111 'SERVER_PORT' => 80,
112 'SCRIPT_NAME' => '/',
113 ];
114 }
115
116 /**
117 * After every test, remove the test datastore.
118 */
8f60e120 119 protected function tearDown(): void
68016e37
A
120 {
121 @unlink(self::$testDatastore);
813849e5 122 @unlink(self::$testHistory);
68016e37
A
123 }
124
125 /**
126 * Test link creation without any field: creates a blank note.
127 */
128 public function testPostLinkMinimal()
129 {
130 $env = Environment::mock([
131 'REQUEST_METHOD' => 'POST',
132 ]);
133
134 $request = Request::createFromEnvironment($env);
135
136 $response = $this->controller->postLink($request, new Response());
137 $this->assertEquals(201, $response->getStatusCode());
b37ca790 138 $this->assertEquals('/api/v1/bookmarks/1', $response->getHeader('Location')[0]);
68016e37
A
139 $data = json_decode((string) $response->getBody(), true);
140 $this->assertEquals(self::NB_FIELDS_LINK, count($data));
141 $this->assertEquals(43, $data['id']);
a43e7842 142 $this->assertRegExp('/[\w_-]{6}/', $data['shorturl']);
301c7ab1
A
143 $this->assertEquals('http://domain.tld/shaare/' . $data['shorturl'], $data['url']);
144 $this->assertEquals('/shaare/' . $data['shorturl'], $data['title']);
68016e37
A
145 $this->assertEquals('', $data['description']);
146 $this->assertEquals([], $data['tags']);
e26e2060 147 $this->assertEquals(true, $data['private']);
9d9f6d75
V
148 $this->assertTrue(
149 new \DateTime('5 seconds ago') < \DateTime::createFromFormat(\DateTime::ATOM, $data['created'])
150 );
68016e37 151 $this->assertEquals('', $data['updated']);
813849e5
A
152
153 $historyEntry = $this->history->getHistory()[0];
dea72c71 154 $this->assertEquals(History::CREATED, $historyEntry['event']);
813849e5
A
155 $this->assertTrue(
156 (new \DateTime())->add(\DateInterval::createFromDateString('-5 seconds')) < $historyEntry['datetime']
157 );
158 $this->assertEquals(43, $historyEntry['id']);
68016e37
A
159 }
160
161 /**
162 * Test link creation with all available fields.
163 */
164 public function testPostLinkFull()
165 {
166 $link = [
167 'url' => 'website.tld/test?foo=bar',
168 'title' => 'new entry',
169 'description' => 'shaare description',
170 'tags' => ['one', 'two'],
171 'private' => true,
b06fc28a
A
172 'created' => '2015-05-05T12:30:00+03:00',
173 'updated' => '2016-06-05T14:32:10+03:00',
68016e37
A
174 ];
175 $env = Environment::mock([
176 'REQUEST_METHOD' => 'POST',
177 'CONTENT_TYPE' => 'application/json'
178 ]);
179
180 $request = Request::createFromEnvironment($env);
181 $request = $request->withParsedBody($link);
182 $response = $this->controller->postLink($request, new Response());
183
184 $this->assertEquals(201, $response->getStatusCode());
b37ca790 185 $this->assertEquals('/api/v1/bookmarks/1', $response->getHeader('Location')[0]);
68016e37
A
186 $data = json_decode((string) $response->getBody(), true);
187 $this->assertEquals(self::NB_FIELDS_LINK, count($data));
188 $this->assertEquals(43, $data['id']);
a43e7842 189 $this->assertRegExp('/[\w_-]{6}/', $data['shorturl']);
68016e37
A
190 $this->assertEquals('http://' . $link['url'], $data['url']);
191 $this->assertEquals($link['title'], $data['title']);
192 $this->assertEquals($link['description'], $data['description']);
193 $this->assertEquals($link['tags'], $data['tags']);
194 $this->assertEquals(true, $data['private']);
b06fc28a
A
195 $this->assertSame($link['created'], $data['created']);
196 $this->assertSame($link['updated'], $data['updated']);
68016e37
A
197 }
198
199 /**
200 * Test link creation with an existing link (duplicate URL). Should return a 409 HTTP error and the existing link.
201 */
202 public function testPostLinkDuplicate()
203 {
204 $link = [
205 'url' => 'mediagoblin.org/',
206 'title' => 'new entry',
207 'description' => 'shaare description',
208 'tags' => ['one', 'two'],
209 'private' => true,
210 ];
211 $env = Environment::mock([
212 'REQUEST_METHOD' => 'POST',
213 'CONTENT_TYPE' => 'application/json'
214 ]);
215
216 $request = Request::createFromEnvironment($env);
217 $request = $request->withParsedBody($link);
218 $response = $this->controller->postLink($request, new Response());
219
220 $this->assertEquals(409, $response->getStatusCode());
221 $data = json_decode((string) $response->getBody(), true);
222 $this->assertEquals(self::NB_FIELDS_LINK, count($data));
223 $this->assertEquals(7, $data['id']);
224 $this->assertEquals('IuWvgA', $data['shorturl']);
225 $this->assertEquals('http://mediagoblin.org/', $data['url']);
226 $this->assertEquals('MediaGoblin', $data['title']);
227 $this->assertEquals('A free software media publishing platform #hashtagOther', $data['description']);
228 $this->assertEquals(['gnu', 'media', 'web', '.hidden', 'hashtag'], $data['tags']);
229 $this->assertEquals(false, $data['private']);
230 $this->assertEquals(
e26e2060 231 \DateTime::createFromFormat(Bookmark::LINK_DATE_FORMAT, '20130614_184135'),
68016e37
A
232 \DateTime::createFromFormat(\DateTime::ATOM, $data['created'])
233 );
234 $this->assertEquals(
e26e2060 235 \DateTime::createFromFormat(Bookmark::LINK_DATE_FORMAT, '20130615_184230'),
68016e37
A
236 \DateTime::createFromFormat(\DateTime::ATOM, $data['updated'])
237 );
238 }
0640c1a6
A
239
240 /**
241 * Test link creation with a tag string provided
242 */
243 public function testPostLinkWithTagString(): void
244 {
245 $link = [
246 'tags' => 'one two',
247 ];
248 $env = Environment::mock([
249 'REQUEST_METHOD' => 'POST',
250 'CONTENT_TYPE' => 'application/json'
251 ]);
252
253 $request = Request::createFromEnvironment($env);
254 $request = $request->withParsedBody($link);
255 $response = $this->controller->postLink($request, new Response());
256
257 $this->assertEquals(201, $response->getStatusCode());
258 $this->assertEquals('/api/v1/bookmarks/1', $response->getHeader('Location')[0]);
259 $data = json_decode((string) $response->getBody(), true);
260 $this->assertEquals(self::NB_FIELDS_LINK, count($data));
261 $this->assertEquals(['one', 'two'], $data['tags']);
262 }
263
264 /**
265 * Test link creation with a tag string provided
266 */
267 public function testPostLinkWithTagString2(): void
268 {
269 $link = [
270 'tags' => ['one two'],
271 ];
272 $env = Environment::mock([
273 'REQUEST_METHOD' => 'POST',
274 'CONTENT_TYPE' => 'application/json'
275 ]);
276
277 $request = Request::createFromEnvironment($env);
278 $request = $request->withParsedBody($link);
279 $response = $this->controller->postLink($request, new Response());
280
281 $this->assertEquals(201, $response->getStatusCode());
282 $this->assertEquals('/api/v1/bookmarks/1', $response->getHeader('Location')[0]);
283 $data = json_decode((string) $response->getBody(), true);
284 $this->assertEquals(self::NB_FIELDS_LINK, count($data));
285 $this->assertEquals(['one', 'two'], $data['tags']);
286 }
68016e37 287}