]> git.immae.eu Git - github/wallabag/wallabag.git/blob - tests/Wallabag/ApiBundle/Controller/EntryRestControllerTest.php
CS
[github/wallabag/wallabag.git] / tests / Wallabag / ApiBundle / Controller / EntryRestControllerTest.php
1 <?php
2
3 namespace Tests\Wallabag\ApiBundle\Controller;
4
5 use Tests\Wallabag\ApiBundle\WallabagApiTestCase;
6 use Wallabag\CoreBundle\Entity\Entry;
7 use Wallabag\CoreBundle\Entity\Tag;
8 use Wallabag\CoreBundle\Helper\ContentProxy;
9 use Wallabag\UserBundle\Entity\User;
10
11 class EntryRestControllerTest extends WallabagApiTestCase
12 {
13 public function testGetOneEntry()
14 {
15 $entry = $this->client->getContainer()
16 ->get('doctrine.orm.entity_manager')
17 ->getRepository('WallabagCoreBundle:Entry')
18 ->findOneBy(['user' => 1, 'isArchived' => false]);
19
20 if (!$entry) {
21 $this->markTestSkipped('No content found in db.');
22 }
23
24 $this->client->request('GET', '/api/entries/' . $entry->getId() . '.json');
25 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
26
27 $content = json_decode($this->client->getResponse()->getContent(), true);
28
29 $this->assertSame($entry->getTitle(), $content['title']);
30 $this->assertSame($entry->getUrl(), $content['url']);
31 $this->assertCount(count($entry->getTags()), $content['tags']);
32 $this->assertSame($entry->getUserName(), $content['user_name']);
33 $this->assertSame($entry->getUserEmail(), $content['user_email']);
34 $this->assertSame($entry->getUserId(), $content['user_id']);
35
36 $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
37 }
38
39 public function testExportEntry()
40 {
41 $entry = $this->client->getContainer()
42 ->get('doctrine.orm.entity_manager')
43 ->getRepository('WallabagCoreBundle:Entry')
44 ->findOneBy(['user' => 1, 'isArchived' => false]);
45
46 if (!$entry) {
47 $this->markTestSkipped('No content found in db.');
48 }
49
50 $this->client->request('GET', '/api/entries/' . $entry->getId() . '/export.epub');
51 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
52
53 // epub format got the content type in the content
54 $this->assertContains('application/epub', $this->client->getResponse()->getContent());
55 $this->assertSame('application/epub+zip', $this->client->getResponse()->headers->get('Content-Type'));
56
57 // re-auth client for mobi
58 $client = $this->createAuthorizedClient();
59 $client->request('GET', '/api/entries/' . $entry->getId() . '/export.mobi');
60 $this->assertSame(200, $client->getResponse()->getStatusCode());
61
62 $this->assertSame('application/x-mobipocket-ebook', $client->getResponse()->headers->get('Content-Type'));
63
64 // re-auth client for pdf
65 $client = $this->createAuthorizedClient();
66 $client->request('GET', '/api/entries/' . $entry->getId() . '/export.pdf');
67 $this->assertSame(200, $client->getResponse()->getStatusCode());
68
69 $this->assertContains('PDF-', $client->getResponse()->getContent());
70 $this->assertSame('application/pdf', $client->getResponse()->headers->get('Content-Type'));
71
72 // re-auth client for pdf
73 $client = $this->createAuthorizedClient();
74 $client->request('GET', '/api/entries/' . $entry->getId() . '/export.txt');
75 $this->assertSame(200, $client->getResponse()->getStatusCode());
76
77 $this->assertContains('text/plain', $client->getResponse()->headers->get('Content-Type'));
78
79 // re-auth client for pdf
80 $client = $this->createAuthorizedClient();
81 $client->request('GET', '/api/entries/' . $entry->getId() . '/export.csv');
82 $this->assertSame(200, $client->getResponse()->getStatusCode());
83
84 $this->assertContains('application/csv', $client->getResponse()->headers->get('Content-Type'));
85 }
86
87 public function testGetOneEntryWrongUser()
88 {
89 $entry = $this->client->getContainer()
90 ->get('doctrine.orm.entity_manager')
91 ->getRepository('WallabagCoreBundle:Entry')
92 ->findOneBy(['user' => 2, 'isArchived' => false]);
93
94 if (!$entry) {
95 $this->markTestSkipped('No content found in db.');
96 }
97
98 $this->client->request('GET', '/api/entries/' . $entry->getId() . '.json');
99
100 $this->assertSame(403, $this->client->getResponse()->getStatusCode());
101 }
102
103 public function testGetEntries()
104 {
105 $this->client->request('GET', '/api/entries');
106
107 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
108
109 $content = json_decode($this->client->getResponse()->getContent(), true);
110
111 $this->assertGreaterThanOrEqual(1, count($content));
112 $this->assertNotEmpty($content['_embedded']['items']);
113 $this->assertGreaterThanOrEqual(1, $content['total']);
114 $this->assertSame(1, $content['page']);
115 $this->assertGreaterThanOrEqual(1, $content['pages']);
116
117 $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
118 }
119
120 public function testGetEntriesWithFullOptions()
121 {
122 $this->client->request('GET', '/api/entries', [
123 'archive' => 1,
124 'starred' => 1,
125 'sort' => 'updated',
126 'order' => 'asc',
127 'page' => 1,
128 'perPage' => 2,
129 'tags' => 'foo',
130 'since' => 1443274283,
131 'public' => 0,
132 ]);
133
134 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
135
136 $content = json_decode($this->client->getResponse()->getContent(), true);
137
138 $this->assertGreaterThanOrEqual(1, count($content));
139 $this->assertArrayHasKey('items', $content['_embedded']);
140 $this->assertGreaterThanOrEqual(0, $content['total']);
141 $this->assertSame(1, $content['page']);
142 $this->assertSame(2, $content['limit']);
143 $this->assertGreaterThanOrEqual(1, $content['pages']);
144
145 $this->assertArrayHasKey('_links', $content);
146 $this->assertArrayHasKey('self', $content['_links']);
147 $this->assertArrayHasKey('first', $content['_links']);
148 $this->assertArrayHasKey('last', $content['_links']);
149
150 foreach (['self', 'first', 'last'] as $link) {
151 $this->assertArrayHasKey('href', $content['_links'][$link]);
152 $this->assertContains('archive=1', $content['_links'][$link]['href']);
153 $this->assertContains('starred=1', $content['_links'][$link]['href']);
154 $this->assertContains('sort=updated', $content['_links'][$link]['href']);
155 $this->assertContains('order=asc', $content['_links'][$link]['href']);
156 $this->assertContains('tags=foo', $content['_links'][$link]['href']);
157 $this->assertContains('since=1443274283', $content['_links'][$link]['href']);
158 $this->assertContains('public=0', $content['_links'][$link]['href']);
159 }
160
161 $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
162 }
163
164 public function testGetEntriesPublicOnly()
165 {
166 $entry = $this->client->getContainer()
167 ->get('doctrine.orm.entity_manager')
168 ->getRepository('WallabagCoreBundle:Entry')
169 ->findOneByUser(1);
170
171 if (!$entry) {
172 $this->markTestSkipped('No content found in db.');
173 }
174
175 // generate at least one public entry
176 $entry->generateUid();
177
178 $em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
179 $em->persist($entry);
180 $em->flush();
181
182 $this->client->request('GET', '/api/entries', [
183 'public' => 1,
184 ]);
185
186 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
187
188 $content = json_decode($this->client->getResponse()->getContent(), true);
189
190 $this->assertGreaterThanOrEqual(1, count($content));
191 $this->assertArrayHasKey('items', $content['_embedded']);
192 $this->assertGreaterThanOrEqual(1, $content['total']);
193 $this->assertSame(1, $content['page']);
194 $this->assertSame(30, $content['limit']);
195 $this->assertGreaterThanOrEqual(1, $content['pages']);
196
197 $this->assertArrayHasKey('_links', $content);
198 $this->assertArrayHasKey('self', $content['_links']);
199 $this->assertArrayHasKey('first', $content['_links']);
200 $this->assertArrayHasKey('last', $content['_links']);
201
202 foreach (['self', 'first', 'last'] as $link) {
203 $this->assertArrayHasKey('href', $content['_links'][$link]);
204 $this->assertContains('public=1', $content['_links'][$link]['href']);
205 }
206
207 $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
208 }
209
210 public function testGetEntriesOnPageTwo()
211 {
212 $this->client->request('GET', '/api/entries', [
213 'page' => 2,
214 'perPage' => 2,
215 ]);
216
217 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
218
219 $content = json_decode($this->client->getResponse()->getContent(), true);
220
221 $this->assertGreaterThanOrEqual(0, $content['total']);
222 $this->assertSame(2, $content['page']);
223 $this->assertSame(2, $content['limit']);
224 }
225
226 public function testGetStarredEntries()
227 {
228 $this->client->request('GET', '/api/entries', ['starred' => 1, 'sort' => 'updated']);
229
230 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
231
232 $content = json_decode($this->client->getResponse()->getContent(), true);
233
234 $this->assertGreaterThanOrEqual(1, count($content));
235 $this->assertNotEmpty($content['_embedded']['items']);
236 $this->assertGreaterThanOrEqual(1, $content['total']);
237 $this->assertSame(1, $content['page']);
238 $this->assertGreaterThanOrEqual(1, $content['pages']);
239
240 $this->assertArrayHasKey('_links', $content);
241 $this->assertArrayHasKey('self', $content['_links']);
242 $this->assertArrayHasKey('first', $content['_links']);
243 $this->assertArrayHasKey('last', $content['_links']);
244
245 foreach (['self', 'first', 'last'] as $link) {
246 $this->assertArrayHasKey('href', $content['_links'][$link]);
247 $this->assertContains('starred=1', $content['_links'][$link]['href']);
248 $this->assertContains('sort=updated', $content['_links'][$link]['href']);
249 }
250
251 $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
252 }
253
254 public function testGetArchiveEntries()
255 {
256 $this->client->request('GET', '/api/entries', ['archive' => 1]);
257
258 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
259
260 $content = json_decode($this->client->getResponse()->getContent(), true);
261
262 $this->assertGreaterThanOrEqual(1, count($content));
263 $this->assertNotEmpty($content['_embedded']['items']);
264 $this->assertGreaterThanOrEqual(1, $content['total']);
265 $this->assertSame(1, $content['page']);
266 $this->assertGreaterThanOrEqual(1, $content['pages']);
267
268 $this->assertArrayHasKey('_links', $content);
269 $this->assertArrayHasKey('self', $content['_links']);
270 $this->assertArrayHasKey('first', $content['_links']);
271 $this->assertArrayHasKey('last', $content['_links']);
272
273 foreach (['self', 'first', 'last'] as $link) {
274 $this->assertArrayHasKey('href', $content['_links'][$link]);
275 $this->assertContains('archive=1', $content['_links'][$link]['href']);
276 }
277
278 $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
279 }
280
281 public function testGetTaggedEntries()
282 {
283 $this->client->request('GET', '/api/entries', ['tags' => 'foo,bar']);
284
285 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
286
287 $content = json_decode($this->client->getResponse()->getContent(), true);
288
289 $this->assertGreaterThanOrEqual(1, count($content));
290 $this->assertNotEmpty($content['_embedded']['items']);
291 $this->assertGreaterThanOrEqual(1, $content['total']);
292 $this->assertSame(1, $content['page']);
293 $this->assertGreaterThanOrEqual(1, $content['pages']);
294
295 $this->assertContains('foo', array_column($content['_embedded']['items'][0]['tags'], 'label'), 'Entries tags should have "foo" tag');
296 $this->assertContains('bar', array_column($content['_embedded']['items'][0]['tags'], 'label'), 'Entries tags should have "bar" tag');
297
298 $this->assertArrayHasKey('_links', $content);
299 $this->assertArrayHasKey('self', $content['_links']);
300 $this->assertArrayHasKey('first', $content['_links']);
301 $this->assertArrayHasKey('last', $content['_links']);
302
303 foreach (['self', 'first', 'last'] as $link) {
304 $this->assertArrayHasKey('href', $content['_links'][$link]);
305 $this->assertContains('tags=' . urlencode('foo,bar'), $content['_links'][$link]['href']);
306 }
307
308 $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
309 }
310
311 public function testGetTaggedEntriesWithBadParams()
312 {
313 $this->client->request('GET', '/api/entries', ['tags' => ['foo', 'bar']]);
314
315 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
316 }
317
318 public function testGetDatedEntries()
319 {
320 $this->client->request('GET', '/api/entries', ['since' => 1443274283]);
321
322 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
323
324 $content = json_decode($this->client->getResponse()->getContent(), true);
325
326 $this->assertGreaterThanOrEqual(1, count($content));
327 $this->assertNotEmpty($content['_embedded']['items']);
328 $this->assertGreaterThanOrEqual(1, $content['total']);
329 $this->assertSame(1, $content['page']);
330 $this->assertGreaterThanOrEqual(1, $content['pages']);
331
332 $this->assertArrayHasKey('_links', $content);
333 $this->assertArrayHasKey('self', $content['_links']);
334 $this->assertArrayHasKey('first', $content['_links']);
335 $this->assertArrayHasKey('last', $content['_links']);
336
337 foreach (['self', 'first', 'last'] as $link) {
338 $this->assertArrayHasKey('href', $content['_links'][$link]);
339 $this->assertContains('since=1443274283', $content['_links'][$link]['href']);
340 }
341
342 $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
343 }
344
345 public function testGetDatedSupEntries()
346 {
347 $future = new \DateTime(date('Y-m-d H:i:s'));
348 $this->client->request('GET', '/api/entries', ['since' => $future->getTimestamp() + 1000]);
349
350 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
351
352 $content = json_decode($this->client->getResponse()->getContent(), true);
353
354 $this->assertGreaterThanOrEqual(1, count($content));
355 $this->assertEmpty($content['_embedded']['items']);
356 $this->assertSame(0, $content['total']);
357 $this->assertSame(1, $content['page']);
358 $this->assertSame(1, $content['pages']);
359
360 $this->assertArrayHasKey('_links', $content);
361 $this->assertArrayHasKey('self', $content['_links']);
362 $this->assertArrayHasKey('first', $content['_links']);
363 $this->assertArrayHasKey('last', $content['_links']);
364
365 foreach (['self', 'first', 'last'] as $link) {
366 $this->assertArrayHasKey('href', $content['_links'][$link]);
367 $this->assertContains('since=' . ($future->getTimestamp() + 1000), $content['_links'][$link]['href']);
368 }
369
370 $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
371 }
372
373 public function testDeleteEntry()
374 {
375 $entry = $this->client->getContainer()
376 ->get('doctrine.orm.entity_manager')
377 ->getRepository('WallabagCoreBundle:Entry')
378 ->findOneByUser(1, ['id' => 'asc']);
379
380 if (!$entry) {
381 $this->markTestSkipped('No content found in db.');
382 }
383
384 $this->client->request('DELETE', '/api/entries/' . $entry->getId() . '.json');
385
386 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
387
388 $content = json_decode($this->client->getResponse()->getContent(), true);
389
390 $this->assertSame($entry->getTitle(), $content['title']);
391 $this->assertSame($entry->getUrl(), $content['url']);
392
393 // We'll try to delete this entry again
394 $this->client->request('DELETE', '/api/entries/' . $entry->getId() . '.json');
395
396 $this->assertSame(404, $this->client->getResponse()->getStatusCode());
397 }
398
399 public function testPostEntry()
400 {
401 $this->client->request('POST', '/api/entries.json', [
402 'url' => 'http://www.lemonde.fr/pixels/article/2015/03/28/plongee-dans-l-univers-d-ingress-le-jeu-de-google-aux-frontieres-du-reel_4601155_4408996.html',
403 'tags' => 'google',
404 'title' => 'New title for my article',
405 'content' => 'my content',
406 'language' => 'de',
407 'published_at' => '2016-09-08T11:55:58+0200',
408 'authors' => 'bob,helen',
409 'public' => 1,
410 ]);
411
412 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
413
414 $content = json_decode($this->client->getResponse()->getContent(), true);
415
416 $this->assertGreaterThan(0, $content['id']);
417 $this->assertSame('http://www.lemonde.fr/pixels/article/2015/03/28/plongee-dans-l-univers-d-ingress-le-jeu-de-google-aux-frontieres-du-reel_4601155_4408996.html', $content['url']);
418 $this->assertSame(0, $content['is_archived']);
419 $this->assertSame(0, $content['is_starred']);
420 $this->assertNull($content['starred_at']);
421 $this->assertSame('New title for my article', $content['title']);
422 $this->assertSame(1, $content['user_id']);
423 $this->assertCount(2, $content['tags']);
424 $this->assertSame('my content', $content['content']);
425 $this->assertSame('de', $content['language']);
426 $this->assertSame('2016-09-08T11:55:58+0200', $content['published_at']);
427 $this->assertCount(2, $content['published_by']);
428 $this->assertContains('bob', $content['published_by']);
429 $this->assertContains('helen', $content['published_by']);
430 $this->assertTrue($content['is_public'], 'A public link has been generated for that entry');
431 }
432
433 public function testPostSameEntry()
434 {
435 $em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
436 $entry = new Entry($em->getReference(User::class, 1));
437 $entry->setUrl('http://www.lemonde.fr/pixels/article/2015/03/28/plongee-dans-l-univers-d-ingress-le-jeu-de-google-aux-frontieres-du-reel_4601155_4408996.html');
438 $entry->setArchived(true);
439 $entry->addTag((new Tag())->setLabel('google'));
440 $entry->addTag((new Tag())->setLabel('apple'));
441 $em->persist($entry);
442 $em->flush();
443 $em->clear();
444
445 $this->client->request('POST', '/api/entries.json', [
446 'url' => 'http://www.lemonde.fr/pixels/article/2015/03/28/plongee-dans-l-univers-d-ingress-le-jeu-de-google-aux-frontieres-du-reel_4601155_4408996.html',
447 'archive' => '1',
448 'tags' => 'google, apple',
449 ]);
450
451 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
452
453 $content = json_decode($this->client->getResponse()->getContent(), true);
454
455 $this->assertGreaterThan(0, $content['id']);
456 $this->assertSame('http://www.lemonde.fr/pixels/article/2015/03/28/plongee-dans-l-univers-d-ingress-le-jeu-de-google-aux-frontieres-du-reel_4601155_4408996.html', $content['url']);
457 $this->assertSame(1, $content['is_archived']);
458 $this->assertSame(0, $content['is_starred']);
459 $this->assertCount(3, $content['tags']);
460 }
461
462 public function testPostEntryWhenFetchContentFails()
463 {
464 /** @var \Symfony\Component\DependencyInjection\Container $container */
465 $container = $this->client->getContainer();
466 $contentProxy = $this->getMockBuilder(ContentProxy::class)
467 ->disableOriginalConstructor()
468 ->setMethods(['updateEntry'])
469 ->getMock();
470 $contentProxy->expects($this->any())
471 ->method('updateEntry')
472 ->willThrowException(new \Exception('Test Fetch content fails'));
473 $container->set('wallabag_core.content_proxy', $contentProxy);
474
475 try {
476 $this->client->request('POST', '/api/entries.json', [
477 'url' => 'http://www.example.com/',
478 ]);
479
480 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
481 $content = json_decode($this->client->getResponse()->getContent(), true);
482 $this->assertGreaterThan(0, $content['id']);
483 $this->assertSame('http://www.example.com/', $content['url']);
484 } finally {
485 // Remove the created entry to avoid side effects on other tests
486 if (isset($content['id'])) {
487 $em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
488 $entry = $em->getReference('WallabagCoreBundle:Entry', $content['id']);
489 $em->remove($entry);
490 $em->flush();
491 }
492 }
493 }
494
495 public function testPostArchivedAndStarredEntry()
496 {
497 $now = new \DateTime();
498 $this->client->request('POST', '/api/entries.json', [
499 'url' => 'http://www.lemonde.fr/idees/article/2016/02/08/preserver-la-liberte-d-expression-sur-les-reseaux-sociaux_4861503_3232.html',
500 'archive' => '1',
501 'starred' => '1',
502 ]);
503
504 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
505
506 $content = json_decode($this->client->getResponse()->getContent(), true);
507
508 $this->assertGreaterThan(0, $content['id']);
509 $this->assertSame('http://www.lemonde.fr/idees/article/2016/02/08/preserver-la-liberte-d-expression-sur-les-reseaux-sociaux_4861503_3232.html', $content['url']);
510 $this->assertSame(1, $content['is_archived']);
511 $this->assertSame(1, $content['is_starred']);
512 $this->assertGreaterThanOrEqual($now->getTimestamp(), (new \DateTime($content['starred_at']))->getTimestamp());
513 $this->assertSame(1, $content['user_id']);
514 }
515
516 public function testPostArchivedAndStarredEntryWithoutQuotes()
517 {
518 $this->client->request('POST', '/api/entries.json', [
519 'url' => 'http://www.lemonde.fr/idees/article/2016/02/08/preserver-la-liberte-d-expression-sur-les-reseaux-sociaux_4861503_3232.html',
520 'archive' => 0,
521 'starred' => 1,
522 ]);
523
524 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
525
526 $content = json_decode($this->client->getResponse()->getContent(), true);
527
528 $this->assertGreaterThan(0, $content['id']);
529 $this->assertSame('http://www.lemonde.fr/idees/article/2016/02/08/preserver-la-liberte-d-expression-sur-les-reseaux-sociaux_4861503_3232.html', $content['url']);
530 $this->assertSame(0, $content['is_archived']);
531 $this->assertSame(1, $content['is_starred']);
532 }
533
534 public function testPatchEntry()
535 {
536 $entry = $this->client->getContainer()
537 ->get('doctrine.orm.entity_manager')
538 ->getRepository('WallabagCoreBundle:Entry')
539 ->findOneByUser(1);
540
541 if (!$entry) {
542 $this->markTestSkipped('No content found in db.');
543 }
544
545 $this->client->request('PATCH', '/api/entries/' . $entry->getId() . '.json', [
546 'title' => 'New awesome title',
547 'tags' => 'new tag ' . uniqid(),
548 'starred' => '1',
549 'archive' => '0',
550 'language' => 'de_AT',
551 'preview_picture' => 'http://preview.io/picture.jpg',
552 'authors' => 'bob,sponge',
553 'content' => 'awesome',
554 'public' => 0,
555 'published_at' => 1488833381,
556 ]);
557
558 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
559
560 $content = json_decode($this->client->getResponse()->getContent(), true);
561
562 $this->assertSame($entry->getId(), $content['id']);
563 $this->assertSame($entry->getUrl(), $content['url']);
564 $this->assertSame('New awesome title', $content['title']);
565 $this->assertGreaterThanOrEqual(1, count($content['tags']), 'We force only one tag');
566 $this->assertSame(1, $content['user_id']);
567 $this->assertSame('de_AT', $content['language']);
568 $this->assertSame('http://preview.io/picture.jpg', $content['preview_picture']);
569 $this->assertContains('sponge', $content['published_by']);
570 $this->assertContains('bob', $content['published_by']);
571 $this->assertSame('awesome', $content['content']);
572 $this->assertFalse($content['is_public'], 'Entry is no more shared');
573 $this->assertContains('2017-03-06', $content['published_at']);
574 }
575
576 public function testPatchEntryWithoutQuotes()
577 {
578 $entry = $this->client->getContainer()
579 ->get('doctrine.orm.entity_manager')
580 ->getRepository('WallabagCoreBundle:Entry')
581 ->findOneByUser(1);
582
583 if (!$entry) {
584 $this->markTestSkipped('No content found in db.');
585 }
586
587 $previousContent = $entry->getContent();
588 $previousLanguage = $entry->getLanguage();
589
590 $this->client->request('PATCH', '/api/entries/' . $entry->getId() . '.json', [
591 'title' => 'New awesome title',
592 'tags' => 'new tag ' . uniqid(),
593 'starred' => 1,
594 'archive' => 0,
595 'authors' => ['bob', 'sponge'],
596 ]);
597
598 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
599
600 $content = json_decode($this->client->getResponse()->getContent(), true);
601
602 $this->assertSame($entry->getId(), $content['id']);
603 $this->assertSame($entry->getUrl(), $content['url']);
604 $this->assertGreaterThanOrEqual(1, count($content['tags']), 'We force only one tag');
605 $this->assertEmpty($content['published_by'], 'Authors were not saved because of an array instead of a string');
606 $this->assertSame($previousContent, $content['content'], 'Ensure content has not moved');
607 $this->assertSame($previousLanguage, $content['language'], 'Ensure language has not moved');
608 }
609
610 public function testGetTagsEntry()
611 {
612 $entry = $this->client->getContainer()
613 ->get('doctrine.orm.entity_manager')
614 ->getRepository('WallabagCoreBundle:Entry')
615 ->findOneWithTags($this->user->getId());
616
617 $entry = $entry[0];
618
619 if (!$entry) {
620 $this->markTestSkipped('No content found in db.');
621 }
622
623 $tags = [];
624 foreach ($entry->getTags() as $tag) {
625 $tags[] = ['id' => $tag->getId(), 'label' => $tag->getLabel(), 'slug' => $tag->getSlug()];
626 }
627
628 $this->client->request('GET', '/api/entries/' . $entry->getId() . '/tags');
629
630 $this->assertSame(json_encode($tags, JSON_HEX_QUOT), $this->client->getResponse()->getContent());
631 }
632
633 public function testPostTagsOnEntry()
634 {
635 $entry = $this->client->getContainer()
636 ->get('doctrine.orm.entity_manager')
637 ->getRepository('WallabagCoreBundle:Entry')
638 ->findOneByUser(1);
639
640 if (!$entry) {
641 $this->markTestSkipped('No content found in db.');
642 }
643
644 $nbTags = count($entry->getTags());
645
646 $newTags = 'tag1,tag2,tag3';
647
648 $this->client->request('POST', '/api/entries/' . $entry->getId() . '/tags', ['tags' => $newTags]);
649
650 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
651
652 $content = json_decode($this->client->getResponse()->getContent(), true);
653
654 $this->assertArrayHasKey('tags', $content);
655 $this->assertSame($nbTags + 3, count($content['tags']));
656
657 $entryDB = $this->client->getContainer()
658 ->get('doctrine.orm.entity_manager')
659 ->getRepository('WallabagCoreBundle:Entry')
660 ->find($entry->getId());
661
662 $tagsInDB = [];
663 foreach ($entryDB->getTags()->toArray() as $tag) {
664 $tagsInDB[$tag->getId()] = $tag->getLabel();
665 }
666
667 foreach (explode(',', $newTags) as $tag) {
668 $this->assertContains($tag, $tagsInDB);
669 }
670 }
671
672 public function testDeleteOneTagEntry()
673 {
674 $entry = $this->client->getContainer()
675 ->get('doctrine.orm.entity_manager')
676 ->getRepository('WallabagCoreBundle:Entry')
677 ->findOneWithTags($this->user->getId());
678 $entry = $entry[0];
679
680 if (!$entry) {
681 $this->markTestSkipped('No content found in db.');
682 }
683
684 // hydrate the tags relations
685 $nbTags = count($entry->getTags());
686 $tag = $entry->getTags()[0];
687
688 $this->client->request('DELETE', '/api/entries/' . $entry->getId() . '/tags/' . $tag->getId() . '.json');
689
690 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
691
692 $content = json_decode($this->client->getResponse()->getContent(), true);
693
694 $this->assertArrayHasKey('tags', $content);
695 $this->assertSame($nbTags - 1, count($content['tags']));
696 }
697
698 public function testSaveIsArchivedAfterPost()
699 {
700 $entry = $this->client->getContainer()
701 ->get('doctrine.orm.entity_manager')
702 ->getRepository('WallabagCoreBundle:Entry')
703 ->findOneBy(['user' => 1, 'isArchived' => true]);
704
705 if (!$entry) {
706 $this->markTestSkipped('No content found in db.');
707 }
708
709 $this->client->request('POST', '/api/entries.json', [
710 'url' => $entry->getUrl(),
711 ]);
712
713 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
714
715 $content = json_decode($this->client->getResponse()->getContent(), true);
716
717 $this->assertSame(1, $content['is_archived']);
718 }
719
720 public function testSaveIsStarredAfterPost()
721 {
722 $entry = $this->client->getContainer()
723 ->get('doctrine.orm.entity_manager')
724 ->getRepository('WallabagCoreBundle:Entry')
725 ->findOneBy(['user' => 1, 'isStarred' => true]);
726
727 if (!$entry) {
728 $this->markTestSkipped('No content found in db.');
729 }
730
731 $this->client->request('POST', '/api/entries.json', [
732 'url' => $entry->getUrl(),
733 ]);
734
735 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
736
737 $content = json_decode($this->client->getResponse()->getContent(), true);
738
739 $this->assertSame(1, $content['is_starred']);
740 }
741
742 public function testSaveIsArchivedAfterPatch()
743 {
744 $entry = $this->client->getContainer()
745 ->get('doctrine.orm.entity_manager')
746 ->getRepository('WallabagCoreBundle:Entry')
747 ->findOneBy(['user' => 1, 'isArchived' => true]);
748
749 if (!$entry) {
750 $this->markTestSkipped('No content found in db.');
751 }
752
753 $previousTitle = $entry->getTitle();
754
755 $this->client->request('PATCH', '/api/entries/' . $entry->getId() . '.json', [
756 'title' => $entry->getTitle() . '++',
757 ]);
758
759 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
760
761 $content = json_decode($this->client->getResponse()->getContent(), true);
762
763 $this->assertSame(1, $content['is_archived']);
764 $this->assertSame($previousTitle . '++', $content['title']);
765 }
766
767 public function testSaveIsStarredAfterPatch()
768 {
769 $now = new \DateTime();
770 $entry = $this->client->getContainer()
771 ->get('doctrine.orm.entity_manager')
772 ->getRepository('WallabagCoreBundle:Entry')
773 ->findOneBy(['user' => 1, 'isStarred' => true]);
774
775 if (!$entry) {
776 $this->markTestSkipped('No content found in db.');
777 }
778 $this->client->request('PATCH', '/api/entries/' . $entry->getId() . '.json', [
779 'title' => $entry->getTitle() . '++',
780 ]);
781
782 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
783
784 $content = json_decode($this->client->getResponse()->getContent(), true);
785
786 $this->assertSame(1, $content['is_starred']);
787 $this->assertGreaterThanOrEqual($now->getTimestamp(), (new \DateTime($content['starred_at']))->getTimestamp());
788 }
789
790 public function dataForEntriesExistWithUrl()
791 {
792 return [
793 'with_id' => [
794 'url' => '/api/entries/exists?url=http://0.0.0.0/entry2&return_id=1',
795 'expectedValue' => 2,
796 ],
797 'without_id' => [
798 'url' => '/api/entries/exists?url=http://0.0.0.0/entry2',
799 'expectedValue' => true,
800 ],
801 ];
802 }
803
804 /**
805 * @dataProvider dataForEntriesExistWithUrl
806 */
807 public function testGetEntriesExists($url, $expectedValue)
808 {
809 $this->client->request('GET', $url);
810
811 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
812
813 $content = json_decode($this->client->getResponse()->getContent(), true);
814
815 $this->assertSame($expectedValue, $content['exists']);
816 }
817
818 public function testGetEntriesExistsWithManyUrls()
819 {
820 $url1 = 'http://0.0.0.0/entry2';
821 $url2 = 'http://0.0.0.0/entry10';
822 $this->client->request('GET', '/api/entries/exists?urls[]=' . $url1 . '&urls[]=' . $url2 . '&return_id=1');
823
824 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
825
826 $content = json_decode($this->client->getResponse()->getContent(), true);
827
828 $this->assertArrayHasKey($url1, $content);
829 $this->assertArrayHasKey($url2, $content);
830 $this->assertSame(2, $content[$url1]);
831 $this->assertNull($content[$url2]);
832 }
833
834 public function testGetEntriesExistsWithManyUrlsReturnBool()
835 {
836 $url1 = 'http://0.0.0.0/entry2';
837 $url2 = 'http://0.0.0.0/entry10';
838 $this->client->request('GET', '/api/entries/exists?urls[]=' . $url1 . '&urls[]=' . $url2);
839
840 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
841
842 $content = json_decode($this->client->getResponse()->getContent(), true);
843
844 $this->assertArrayHasKey($url1, $content);
845 $this->assertArrayHasKey($url2, $content);
846 $this->assertTrue($content[$url1]);
847 $this->assertFalse($content[$url2]);
848 }
849
850 public function testGetEntriesExistsWhichDoesNotExists()
851 {
852 $this->client->request('GET', '/api/entries/exists?url=http://google.com/entry2');
853
854 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
855
856 $content = json_decode($this->client->getResponse()->getContent(), true);
857
858 $this->assertSame(false, $content['exists']);
859 }
860
861 public function testGetEntriesExistsWithNoUrl()
862 {
863 $this->client->request('GET', '/api/entries/exists?url=');
864
865 $this->assertSame(403, $this->client->getResponse()->getStatusCode());
866 }
867
868 public function testReloadEntryErrorWhileFetching()
869 {
870 $entry = $this->client->getContainer()->get('doctrine.orm.entity_manager')
871 ->getRepository('WallabagCoreBundle:Entry')
872 ->findByUrlAndUserId('http://0.0.0.0/entry4', 1);
873
874 if (!$entry) {
875 $this->markTestSkipped('No content found in db.');
876 }
877
878 $this->client->request('PATCH', '/api/entries/' . $entry->getId() . '/reload.json');
879 $this->assertSame(304, $this->client->getResponse()->getStatusCode());
880 }
881
882 public function testReloadEntry()
883 {
884 $this->client->request('POST', '/api/entries.json', [
885 'url' => 'http://www.lemonde.fr/pixels/article/2015/03/28/plongee-dans-l-univers-d-ingress-le-jeu-de-google-aux-frontieres-du-reel_4601155_4408996.html',
886 'archive' => '1',
887 'tags' => 'google, apple',
888 ]);
889
890 $json = json_decode($this->client->getResponse()->getContent(), true);
891
892 $this->setUp();
893
894 $this->client->request('PATCH', '/api/entries/' . $json['id'] . '/reload.json');
895 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
896
897 $content = json_decode($this->client->getResponse()->getContent(), true);
898
899 $this->assertNotEmpty($content['title']);
900
901 $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
902 }
903
904 public function testPostEntriesTagsListAction()
905 {
906 $entry = $this->client->getContainer()->get('doctrine.orm.entity_manager')
907 ->getRepository('WallabagCoreBundle:Entry')
908 ->findByUrlAndUserId('http://0.0.0.0/entry4', 1);
909
910 $tags = $entry->getTags();
911
912 $this->assertCount(2, $tags);
913
914 $list = [
915 [
916 'url' => 'http://0.0.0.0/entry4',
917 'tags' => 'new tag 1, new tag 2',
918 ],
919 ];
920
921 $this->client->request('POST', '/api/entries/tags/lists?list=' . json_encode($list));
922
923 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
924
925 $content = json_decode($this->client->getResponse()->getContent(), true);
926
927 $this->assertInternalType('int', $content[0]['entry']);
928 $this->assertSame('http://0.0.0.0/entry4', $content[0]['url']);
929
930 $entry = $this->client->getContainer()->get('doctrine.orm.entity_manager')
931 ->getRepository('WallabagCoreBundle:Entry')
932 ->findByUrlAndUserId('http://0.0.0.0/entry4', 1);
933
934 $tags = $entry->getTags();
935 $this->assertCount(4, $tags);
936 }
937
938 public function testPostEntriesTagsListActionNoList()
939 {
940 $this->client->request('POST', '/api/entries/tags/lists?list=' . json_encode([]));
941
942 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
943
944 $content = json_decode($this->client->getResponse()->getContent(), true);
945
946 $this->assertEmpty($content);
947 }
948
949 public function testDeleteEntriesTagsListAction()
950 {
951 $em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
952 $entry = new Entry($em->getReference(User::class, 1));
953 $entry->setUrl('http://0.0.0.0/test-entry');
954 $entry->addTag((new Tag())->setLabel('foo-tag'));
955 $entry->addTag((new Tag())->setLabel('bar-tag'));
956 $em->persist($entry);
957 $em->flush();
958
959 $em->clear();
960
961 $list = [
962 [
963 'url' => 'http://0.0.0.0/test-entry',
964 'tags' => 'foo-tag, bar-tag',
965 ],
966 ];
967
968 $this->client->request('DELETE', '/api/entries/tags/list?list=' . json_encode($list));
969 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
970
971 $entry = $em->getRepository('WallabagCoreBundle:Entry')->find($entry->getId());
972 $this->assertCount(0, $entry->getTags());
973 }
974
975 public function testDeleteEntriesTagsListActionNoList()
976 {
977 $this->client->request('DELETE', '/api/entries/tags/list?list=' . json_encode([]));
978
979 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
980
981 $content = json_decode($this->client->getResponse()->getContent(), true);
982
983 $this->assertEmpty($content);
984 }
985
986 public function testPostEntriesListAction()
987 {
988 $list = [
989 'http://www.lemonde.fr/musiques/article/2017/04/23/loin-de-la-politique-le-printemps-de-bourges-retombe-en-enfance_5115862_1654986.html',
990 'http://0.0.0.0/entry2',
991 ];
992
993 $this->client->request('POST', '/api/entries/lists?urls=' . json_encode($list));
994
995 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
996
997 $content = json_decode($this->client->getResponse()->getContent(), true);
998
999 $this->assertInternalType('int', $content[0]['entry']);
1000 $this->assertSame('http://www.lemonde.fr/musiques/article/2017/04/23/loin-de-la-politique-le-printemps-de-bourges-retombe-en-enfance_5115862_1654986.html', $content[0]['url']);
1001
1002 $this->assertInternalType('int', $content[1]['entry']);
1003 $this->assertSame('http://0.0.0.0/entry2', $content[1]['url']);
1004 }
1005
1006 public function testPostEntriesListActionWithNoUrls()
1007 {
1008 $this->client->request('POST', '/api/entries/lists?urls=' . json_encode([]));
1009
1010 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
1011
1012 $content = json_decode($this->client->getResponse()->getContent(), true);
1013
1014 $this->assertEmpty($content);
1015 }
1016
1017 public function testDeleteEntriesListAction()
1018 {
1019 $em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
1020 $em->persist((new Entry($em->getReference(User::class, 1)))->setUrl('http://0.0.0.0/test-entry1'));
1021
1022 $em->flush();
1023 $em->clear();
1024 $list = [
1025 'http://0.0.0.0/test-entry1',
1026 'http://0.0.0.0/test-entry-not-exist',
1027 ];
1028
1029 $this->client->request('DELETE', '/api/entries/list?urls=' . json_encode($list));
1030
1031 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
1032
1033 $content = json_decode($this->client->getResponse()->getContent(), true);
1034
1035 $this->assertTrue($content[0]['entry']);
1036 $this->assertSame('http://0.0.0.0/test-entry1', $content[0]['url']);
1037
1038 $this->assertFalse($content[1]['entry']);
1039 $this->assertSame('http://0.0.0.0/test-entry-not-exist', $content[1]['url']);
1040 }
1041
1042 public function testDeleteEntriesListActionWithNoUrls()
1043 {
1044 $this->client->request('DELETE', '/api/entries/list?urls=' . json_encode([]));
1045
1046 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
1047
1048 $content = json_decode($this->client->getResponse()->getContent(), true);
1049
1050 $this->assertEmpty($content);
1051 }
1052
1053 public function testLimitBulkAction()
1054 {
1055 $list = [
1056 'http://0.0.0.0/entry1',
1057 'http://0.0.0.0/entry1',
1058 'http://0.0.0.0/entry1',
1059 'http://0.0.0.0/entry1',
1060 'http://0.0.0.0/entry1',
1061 'http://0.0.0.0/entry1',
1062 'http://0.0.0.0/entry1',
1063 'http://0.0.0.0/entry1',
1064 'http://0.0.0.0/entry1',
1065 'http://0.0.0.0/entry1',
1066 'http://0.0.0.0/entry1',
1067 ];
1068
1069 $this->client->request('POST', '/api/entries/lists?urls=' . json_encode($list));
1070
1071 $this->assertSame(400, $this->client->getResponse()->getStatusCode());
1072 $this->assertContains('API limit reached', $this->client->getResponse()->getContent());
1073 }
1074
1075 public function testRePostEntryAndReUsePublishedAt()
1076 {
1077 $em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
1078 $entry = new Entry($em->getReference(User::class, 1));
1079 $entry->setTitle('Antoine de Caunes : « Je veux avoir le droit de tâtonner »');
1080 $entry->setContent('hihi');
1081 $entry->setUrl('http://www.lemonde.fr/m-perso/article/2017/06/25/antoine-de-caunes-je-veux-avoir-le-droit-de-tatonner_5150728_4497916.html');
1082 $entry->setPublishedAt(new \DateTime('2017-06-26T07:46:02+0200'));
1083 $em->persist($entry);
1084 $em->flush();
1085 $em->clear();
1086
1087 $this->client->request('POST', '/api/entries.json', [
1088 'url' => 'http://www.lemonde.fr/m-perso/article/2017/06/25/antoine-de-caunes-je-veux-avoir-le-droit-de-tatonner_5150728_4497916.html',
1089 ]);
1090
1091 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
1092
1093 $content = json_decode($this->client->getResponse()->getContent(), true);
1094
1095 $this->assertGreaterThan(0, $content['id']);
1096 $this->assertSame('http://www.lemonde.fr/m-perso/article/2017/06/25/antoine-de-caunes-je-veux-avoir-le-droit-de-tatonner_5150728_4497916.html', $content['url']);
1097 }
1098 }