aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/Wallabag/AnnotationBundle/Controller/AnnotationControllerTest.php74
-rw-r--r--tests/Wallabag/AnnotationBundle/WallabagAnnotationTestCase.php2
-rw-r--r--tests/Wallabag/ApiBundle/Controller/DeveloperControllerTest.php57
-rw-r--r--tests/Wallabag/ApiBundle/Controller/EntryRestControllerTest.php592
-rw-r--r--tests/Wallabag/ApiBundle/Controller/TagRestControllerTest.php87
-rw-r--r--tests/Wallabag/ApiBundle/Controller/UserRestControllerTest.php185
-rw-r--r--tests/Wallabag/ApiBundle/Controller/WallabagRestControllerTest.php10
-rw-r--r--tests/Wallabag/ApiBundle/WallabagApiTestCase.php8
-rw-r--r--tests/Wallabag/CoreBundle/Command/CleanDuplicatesCommandTest.php108
-rw-r--r--tests/Wallabag/CoreBundle/Command/ExportCommandTest.php9
-rw-r--r--tests/Wallabag/CoreBundle/Command/InstallCommandTest.php187
-rw-r--r--tests/Wallabag/CoreBundle/Command/ListUserCommandTest.php75
-rw-r--r--tests/Wallabag/CoreBundle/Command/ReloadEntryCommandTest.php115
-rw-r--r--tests/Wallabag/CoreBundle/Command/ShowUserCommandTest.php93
-rw-r--r--tests/Wallabag/CoreBundle/Command/TagAllCommandTest.php7
-rw-r--r--tests/Wallabag/CoreBundle/Controller/ConfigControllerTest.php199
-rw-r--r--tests/Wallabag/CoreBundle/Controller/EntryControllerTest.php717
-rw-r--r--tests/Wallabag/CoreBundle/Controller/ExportControllerTest.php112
-rw-r--r--tests/Wallabag/CoreBundle/Controller/RssControllerTest.php91
-rw-r--r--tests/Wallabag/CoreBundle/Controller/SettingsControllerTest.php4
-rw-r--r--tests/Wallabag/CoreBundle/Controller/SiteCredentialControllerTest.php139
-rw-r--r--tests/Wallabag/CoreBundle/Controller/StaticControllerTest.php4
-rw-r--r--tests/Wallabag/CoreBundle/Controller/TagControllerTest.php95
-rw-r--r--tests/Wallabag/CoreBundle/Event/Listener/LocaleListenerTest.php28
-rw-r--r--tests/Wallabag/CoreBundle/Event/Listener/UserLocaleListenerTest.php4
-rw-r--r--tests/Wallabag/CoreBundle/Event/Subscriber/TablePrefixSubscriberTest.php18
-rw-r--r--tests/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilderTest.php119
-rw-r--r--tests/Wallabag/CoreBundle/Helper/ContentProxyTest.php463
-rw-r--r--tests/Wallabag/CoreBundle/Helper/CryptoProxyTest.php40
-rw-r--r--tests/Wallabag/CoreBundle/Helper/DownloadImagesTest.php89
-rw-r--r--tests/Wallabag/CoreBundle/Helper/RedirectTest.php34
-rw-r--r--tests/Wallabag/CoreBundle/Helper/RuleBasedTaggerTest.php29
-rw-r--r--tests/Wallabag/CoreBundle/Helper/TagsAssignerTest.php108
-rw-r--r--tests/Wallabag/CoreBundle/ParamConverter/UsernameRssTokenConverterTest.php4
-rw-r--r--tests/Wallabag/CoreBundle/Tools/UtilsTest.php2
-rw-r--r--tests/Wallabag/CoreBundle/Twig/WallabagExtensionTest.php6
-rw-r--r--tests/Wallabag/CoreBundle/WallabagCoreTestCase.php86
-rw-r--r--tests/Wallabag/CoreBundle/fixtures/image-no-content-type.jpgbin0 -> 354067 bytes
-rw-r--r--tests/Wallabag/ImportBundle/Command/ImportCommandTest.php36
-rw-r--r--tests/Wallabag/ImportBundle/Command/RedisWorkerCommandTest.php8
-rw-r--r--tests/Wallabag/ImportBundle/Consumer/AMQPEntryConsumerTest.php4
-rw-r--r--tests/Wallabag/ImportBundle/Consumer/RedisEntryConsumerTest.php2
-rw-r--r--tests/Wallabag/ImportBundle/Controller/ChromeControllerTest.php40
-rw-r--r--tests/Wallabag/ImportBundle/Controller/FirefoxControllerTest.php48
-rw-r--r--tests/Wallabag/ImportBundle/Controller/ImportControllerTest.php6
-rw-r--r--tests/Wallabag/ImportBundle/Controller/InstapaperControllerTest.php60
-rw-r--r--tests/Wallabag/ImportBundle/Controller/PinboardControllerTest.php48
-rw-r--r--tests/Wallabag/ImportBundle/Controller/PocketControllerTest.php24
-rw-r--r--tests/Wallabag/ImportBundle/Controller/ReadabilityControllerTest.php46
-rw-r--r--tests/Wallabag/ImportBundle/Controller/WallabagV1ControllerTest.php60
-rw-r--r--tests/Wallabag/ImportBundle/Controller/WallabagV2ControllerTest.php57
-rw-r--r--tests/Wallabag/ImportBundle/Import/ChromeImportTest.php111
-rw-r--r--tests/Wallabag/ImportBundle/Import/FirefoxImportTest.php111
-rw-r--r--tests/Wallabag/ImportBundle/Import/ImportChainTest.php2
-rw-r--r--tests/Wallabag/ImportBundle/Import/ImportCompilerPassTest.php2
-rw-r--r--tests/Wallabag/ImportBundle/Import/InstapaperImportTest.php138
-rw-r--r--tests/Wallabag/ImportBundle/Import/PocketImportTest.php148
-rw-r--r--tests/Wallabag/ImportBundle/Import/ReadabilityImportTest.php119
-rw-r--r--tests/Wallabag/ImportBundle/Import/WallabagV1ImportTest.php157
-rw-r--r--tests/Wallabag/ImportBundle/Import/WallabagV2ImportTest.php154
-rw-r--r--tests/Wallabag/ImportBundle/fixtures/instapaper-export.csv1
-rw-r--r--tests/Wallabag/ImportBundle/fixtures/pinboard_export4
-rw-r--r--tests/Wallabag/ImportBundle/fixtures/readability.json147
-rw-r--r--tests/Wallabag/ImportBundle/fixtures/wallabag-v1.json33
-rw-r--r--tests/Wallabag/ImportBundle/fixtures/wallabag-v2.json296
-rw-r--r--tests/Wallabag/UserBundle/Controller/ManageControllerTest.php46
-rw-r--r--tests/Wallabag/UserBundle/EventListener/AuthenticationFailureListenerTest.php66
-rw-r--r--tests/Wallabag/UserBundle/EventListener/CreateConfigListenerTest.php2
-rw-r--r--tests/Wallabag/UserBundle/Mailer/AuthCodeMailerTest.php4
69 files changed, 3826 insertions, 2154 deletions
diff --git a/tests/Wallabag/AnnotationBundle/Controller/AnnotationControllerTest.php b/tests/Wallabag/AnnotationBundle/Controller/AnnotationControllerTest.php
index 81f9e9ec..96474468 100644
--- a/tests/Wallabag/AnnotationBundle/Controller/AnnotationControllerTest.php
+++ b/tests/Wallabag/AnnotationBundle/Controller/AnnotationControllerTest.php
@@ -49,12 +49,12 @@ class AnnotationControllerTest extends WallabagAnnotationTestCase
49 $this->logInAs('admin'); 49 $this->logInAs('admin');
50 } 50 }
51 51
52 $this->client->request('GET', $prefixUrl.'/'.$entry->getId().'.json'); 52 $this->client->request('GET', $prefixUrl . '/' . $entry->getId() . '.json');
53 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 53 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
54 54
55 $content = json_decode($this->client->getResponse()->getContent(), true); 55 $content = json_decode($this->client->getResponse()->getContent(), true);
56 $this->assertGreaterThanOrEqual(1, $content['total']); 56 $this->assertGreaterThanOrEqual(1, $content['total']);
57 $this->assertEquals($annotation->getText(), $content['rows'][0]['text']); 57 $this->assertSame($annotation->getText(), $content['rows'][0]['text']);
58 58
59 // we need to re-fetch the annotation becase after the flush, it has been "detached" from the entity manager 59 // we need to re-fetch the annotation becase after the flush, it has been "detached" from the entity manager
60 $annotation = $em->getRepository('WallabagAnnotationBundle:Annotation')->findAnnotationById($annotation->getId()); 60 $annotation = $em->getRepository('WallabagAnnotationBundle:Annotation')->findAnnotationById($annotation->getId());
@@ -84,18 +84,20 @@ class AnnotationControllerTest extends WallabagAnnotationTestCase
84 $content = json_encode([ 84 $content = json_encode([
85 'text' => 'my annotation', 85 'text' => 'my annotation',
86 'quote' => 'my quote', 86 'quote' => 'my quote',
87 'ranges' => ['start' => '', 'startOffset' => 24, 'end' => '', 'endOffset' => 31], 87 'ranges' => [
88 ['start' => '', 'startOffset' => 24, 'end' => '', 'endOffset' => 31],
89 ],
88 ]); 90 ]);
89 $this->client->request('POST', $prefixUrl.'/'.$entry->getId().'.json', [], [], $headers, $content); 91 $this->client->request('POST', $prefixUrl . '/' . $entry->getId() . '.json', [], [], $headers, $content);
90 92
91 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 93 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
92 94
93 $content = json_decode($this->client->getResponse()->getContent(), true); 95 $content = json_decode($this->client->getResponse()->getContent(), true);
94 96
95 $this->assertEquals('Big boss', $content['user']); 97 $this->assertSame('Big boss', $content['user']);
96 $this->assertEquals('v1.0', $content['annotator_schema_version']); 98 $this->assertSame('v1.0', $content['annotator_schema_version']);
97 $this->assertEquals('my annotation', $content['text']); 99 $this->assertSame('my annotation', $content['text']);
98 $this->assertEquals('my quote', $content['quote']); 100 $this->assertSame('my quote', $content['quote']);
99 101
100 /** @var Annotation $annotation */ 102 /** @var Annotation $annotation */
101 $annotation = $this->client->getContainer() 103 $annotation = $this->client->getContainer()
@@ -103,7 +105,37 @@ class AnnotationControllerTest extends WallabagAnnotationTestCase
103 ->getRepository('WallabagAnnotationBundle:Annotation') 105 ->getRepository('WallabagAnnotationBundle:Annotation')
104 ->findLastAnnotationByPageId($entry->getId(), 1); 106 ->findLastAnnotationByPageId($entry->getId(), 1);
105 107
106 $this->assertEquals('my annotation', $annotation->getText()); 108 $this->assertSame('my annotation', $annotation->getText());
109 }
110
111 /**
112 * @dataProvider dataForEachAnnotations
113 */
114 public function testSetAnnotationWithQuoteTooLong($prefixUrl)
115 {
116 $em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
117
118 if ('annotations' === $prefixUrl) {
119 $this->logInAs('admin');
120 }
121
122 /** @var Entry $entry */
123 $entry = $em
124 ->getRepository('WallabagCoreBundle:Entry')
125 ->findOneByUsernameAndNotArchived('admin');
126
127 $longQuote = str_repeat('a', 10001);
128 $headers = ['CONTENT_TYPE' => 'application/json'];
129 $content = json_encode([
130 'text' => 'my annotation',
131 'quote' => $longQuote,
132 'ranges' => [
133 ['start' => '', 'startOffset' => 24, 'end' => '', 'endOffset' => 31],
134 ],
135 ]);
136 $this->client->request('POST', $prefixUrl . '/' . $entry->getId() . '.json', [], [], $headers, $content);
137
138 $this->assertSame(400, $this->client->getResponse()->getStatusCode());
107 } 139 }
108 140
109 /** 141 /**
@@ -134,21 +166,21 @@ class AnnotationControllerTest extends WallabagAnnotationTestCase
134 $content = json_encode([ 166 $content = json_encode([
135 'text' => 'a modified annotation', 167 'text' => 'a modified annotation',
136 ]); 168 ]);
137 $this->client->request('PUT', $prefixUrl.'/'.$annotation->getId().'.json', [], [], $headers, $content); 169 $this->client->request('PUT', $prefixUrl . '/' . $annotation->getId() . '.json', [], [], $headers, $content);
138 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 170 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
139 171
140 $content = json_decode($this->client->getResponse()->getContent(), true); 172 $content = json_decode($this->client->getResponse()->getContent(), true);
141 173
142 $this->assertEquals('Big boss', $content['user']); 174 $this->assertSame('Big boss', $content['user']);
143 $this->assertEquals('v1.0', $content['annotator_schema_version']); 175 $this->assertSame('v1.0', $content['annotator_schema_version']);
144 $this->assertEquals('a modified annotation', $content['text']); 176 $this->assertSame('a modified annotation', $content['text']);
145 $this->assertEquals('my quote', $content['quote']); 177 $this->assertSame('my quote', $content['quote']);
146 178
147 /** @var Annotation $annotationUpdated */ 179 /** @var Annotation $annotationUpdated */
148 $annotationUpdated = $em 180 $annotationUpdated = $em
149 ->getRepository('WallabagAnnotationBundle:Annotation') 181 ->getRepository('WallabagAnnotationBundle:Annotation')
150 ->findOneById($annotation->getId()); 182 ->findOneById($annotation->getId());
151 $this->assertEquals('a modified annotation', $annotationUpdated->getText()); 183 $this->assertSame('a modified annotation', $annotationUpdated->getText());
152 184
153 $em->remove($annotationUpdated); 185 $em->remove($annotationUpdated);
154 $em->flush(); 186 $em->flush();
@@ -186,12 +218,12 @@ class AnnotationControllerTest extends WallabagAnnotationTestCase
186 $content = json_encode([ 218 $content = json_encode([
187 'text' => 'a modified annotation', 219 'text' => 'a modified annotation',
188 ]); 220 ]);
189 $this->client->request('DELETE', $prefixUrl.'/'.$annotation->getId().'.json', [], [], $headers, $content); 221 $this->client->request('DELETE', $prefixUrl . '/' . $annotation->getId() . '.json', [], [], $headers, $content);
190 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 222 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
191 223
192 $content = json_decode($this->client->getResponse()->getContent(), true); 224 $content = json_decode($this->client->getResponse()->getContent(), true);
193 225
194 $this->assertEquals('This is my annotation /o/', $content['text']); 226 $this->assertSame('This is my annotation /o/', $content['text']);
195 227
196 $annotationDeleted = $em 228 $annotationDeleted = $em
197 ->getRepository('WallabagAnnotationBundle:Annotation') 229 ->getRepository('WallabagAnnotationBundle:Annotation')
diff --git a/tests/Wallabag/AnnotationBundle/WallabagAnnotationTestCase.php b/tests/Wallabag/AnnotationBundle/WallabagAnnotationTestCase.php
index ef3f1324..105e8add 100644
--- a/tests/Wallabag/AnnotationBundle/WallabagAnnotationTestCase.php
+++ b/tests/Wallabag/AnnotationBundle/WallabagAnnotationTestCase.php
@@ -52,7 +52,7 @@ abstract class WallabagAnnotationTestCase extends WebTestCase
52 $loginManager->logInUser($firewallName, $this->user); 52 $loginManager->logInUser($firewallName, $this->user);
53 53
54 // save the login token into the session and put it in a cookie 54 // save the login token into the session and put it in a cookie
55 $container->get('session')->set('_security_'.$firewallName, serialize($container->get('security.token_storage')->getToken())); 55 $container->get('session')->set('_security_' . $firewallName, serialize($container->get('security.token_storage')->getToken()));
56 $container->get('session')->save(); 56 $container->get('session')->save();
57 57
58 $session = $container->get('session'); 58 $session = $container->get('session');
diff --git a/tests/Wallabag/ApiBundle/Controller/DeveloperControllerTest.php b/tests/Wallabag/ApiBundle/Controller/DeveloperControllerTest.php
index 6659443b..e9e5ee3b 100644
--- a/tests/Wallabag/ApiBundle/Controller/DeveloperControllerTest.php
+++ b/tests/Wallabag/ApiBundle/Controller/DeveloperControllerTest.php
@@ -3,6 +3,7 @@
3namespace Tests\Wallabag\ApiBundle\Controller; 3namespace Tests\Wallabag\ApiBundle\Controller;
4 4
5use Tests\Wallabag\CoreBundle\WallabagCoreTestCase; 5use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
6use Wallabag\ApiBundle\Entity\Client;
6 7
7class DeveloperControllerTest extends WallabagCoreTestCase 8class DeveloperControllerTest extends WallabagCoreTestCase
8{ 9{
@@ -14,7 +15,7 @@ class DeveloperControllerTest extends WallabagCoreTestCase
14 $nbClients = $em->getRepository('WallabagApiBundle:Client')->findAll(); 15 $nbClients = $em->getRepository('WallabagApiBundle:Client')->findAll();
15 16
16 $crawler = $client->request('GET', '/developer/client/create'); 17 $crawler = $client->request('GET', '/developer/client/create');
17 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 18 $this->assertSame(200, $client->getResponse()->getStatusCode());
18 19
19 $form = $crawler->filter('button[type=submit]')->form(); 20 $form = $crawler->filter('button[type=submit]')->form();
20 21
@@ -24,7 +25,7 @@ class DeveloperControllerTest extends WallabagCoreTestCase
24 25
25 $crawler = $client->submit($form, $data); 26 $crawler = $client->submit($form, $data);
26 27
27 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 28 $this->assertSame(200, $client->getResponse()->getStatusCode());
28 29
29 $newNbClients = $em->getRepository('WallabagApiBundle:Client')->findAll(); 30 $newNbClients = $em->getRepository('WallabagApiBundle:Client')->findAll();
30 $this->assertGreaterThan(count($nbClients), count($newNbClients)); 31 $this->assertGreaterThan(count($nbClients), count($newNbClients));
@@ -33,14 +34,10 @@ class DeveloperControllerTest extends WallabagCoreTestCase
33 $this->assertContains('My app', $alert[0]); 34 $this->assertContains('My app', $alert[0]);
34 } 35 }
35 36
36 /**
37 * @depends testCreateClient
38 */
39 public function testCreateToken() 37 public function testCreateToken()
40 { 38 {
41 $client = $this->getClient(); 39 $client = $this->getClient();
42 $em = $client->getContainer()->get('doctrine.orm.entity_manager'); 40 $apiClient = $this->createApiClientForUser('admin');
43 $apiClient = $em->getRepository('WallabagApiBundle:Client')->findOneByName('My app');
44 41
45 $client->request('POST', '/oauth/v2/token', [ 42 $client->request('POST', '/oauth/v2/token', [
46 'grant_type' => 'password', 43 'grant_type' => 'password',
@@ -50,7 +47,7 @@ class DeveloperControllerTest extends WallabagCoreTestCase
50 'password' => 'mypassword', 47 'password' => 'mypassword',
51 ]); 48 ]);
52 49
53 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 50 $this->assertSame(200, $client->getResponse()->getStatusCode());
54 51
55 $data = json_decode($client->getResponse()->getContent(), true); 52 $data = json_decode($client->getResponse()->getContent(), true);
56 $this->assertArrayHasKey('access_token', $data); 53 $this->assertArrayHasKey('access_token', $data);
@@ -67,8 +64,8 @@ class DeveloperControllerTest extends WallabagCoreTestCase
67 $nbClients = $em->getRepository('WallabagApiBundle:Client')->findAll(); 64 $nbClients = $em->getRepository('WallabagApiBundle:Client')->findAll();
68 65
69 $crawler = $client->request('GET', '/developer'); 66 $crawler = $client->request('GET', '/developer');
70 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 67 $this->assertSame(200, $client->getResponse()->getStatusCode());
71 $this->assertEquals(count($nbClients), $crawler->filter('ul[class=collapsible] li')->count()); 68 $this->assertSame(count($nbClients), $crawler->filter('ul[class=collapsible] li')->count());
72 } 69 }
73 70
74 public function testDeveloperHowto() 71 public function testDeveloperHowto()
@@ -77,12 +74,13 @@ class DeveloperControllerTest extends WallabagCoreTestCase
77 $client = $this->getClient(); 74 $client = $this->getClient();
78 75
79 $crawler = $client->request('GET', '/developer/howto/first-app'); 76 $crawler = $client->request('GET', '/developer/howto/first-app');
80 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 77 $this->assertSame(200, $client->getResponse()->getStatusCode());
81 } 78 }
82 79
83 public function testRemoveClient() 80 public function testRemoveClient()
84 { 81 {
85 $client = $this->getClient(); 82 $client = $this->getClient();
83 $adminApiClient = $this->createApiClientForUser('admin');
86 $em = $client->getContainer()->get('doctrine.orm.entity_manager'); 84 $em = $client->getContainer()->get('doctrine.orm.entity_manager');
87 85
88 // Try to remove an admin's client with a wrong user 86 // Try to remove an admin's client with a wrong user
@@ -90,13 +88,9 @@ class DeveloperControllerTest extends WallabagCoreTestCase
90 $client->request('GET', '/developer'); 88 $client->request('GET', '/developer');
91 $this->assertContains('no_client', $client->getResponse()->getContent()); 89 $this->assertContains('no_client', $client->getResponse()->getContent());
92 90
93 // get an ID of a admin's client
94 $this->logInAs('admin');
95 $nbClients = $em->getRepository('WallabagApiBundle:Client')->findByUser($this->getLoggedInUserId());
96
97 $this->logInAs('bob'); 91 $this->logInAs('bob');
98 $client->request('GET', '/developer/client/delete/'.$nbClients[0]->getId()); 92 $client->request('GET', '/developer/client/delete/' . $adminApiClient->getId());
99 $this->assertEquals(403, $client->getResponse()->getStatusCode()); 93 $this->assertSame(403, $client->getResponse()->getStatusCode());
100 94
101 // Try to remove the admin's client with the good user 95 // Try to remove the admin's client with the good user
102 $this->logInAs('admin'); 96 $this->logInAs('admin');
@@ -109,9 +103,32 @@ class DeveloperControllerTest extends WallabagCoreTestCase
109 ; 103 ;
110 104
111 $client->click($link); 105 $client->click($link);
112 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 106 $this->assertSame(302, $client->getResponse()->getStatusCode());
107
108 $this->assertNull(
109 $em->getRepository('WallabagApiBundle:Client')->find($adminApiClient->getId()),
110 'The client should have been removed'
111 );
112 }
113 113
114 $newNbClients = $em->getRepository('WallabagApiBundle:Client')->findByUser($this->getLoggedInUserId()); 114 /**
115 $this->assertGreaterThan(count($newNbClients), count($nbClients)); 115 * @param string $username
116 * @param array $grantTypes
117 *
118 * @return Client
119 */
120 private function createApiClientForUser($username, $grantTypes = ['password'])
121 {
122 $client = $this->getClient();
123 $em = $client->getContainer()->get('doctrine.orm.entity_manager');
124 $userManager = $client->getContainer()->get('fos_user.user_manager');
125 $user = $userManager->findUserBy(['username' => $username]);
126 $apiClient = new Client($user);
127 $apiClient->setName('My app');
128 $apiClient->setAllowedGrantTypes($grantTypes);
129 $em->persist($apiClient);
130 $em->flush();
131
132 return $apiClient;
116 } 133 }
117} 134}
diff --git a/tests/Wallabag/ApiBundle/Controller/EntryRestControllerTest.php b/tests/Wallabag/ApiBundle/Controller/EntryRestControllerTest.php
index 0a65f9ce..2dc08be2 100644
--- a/tests/Wallabag/ApiBundle/Controller/EntryRestControllerTest.php
+++ b/tests/Wallabag/ApiBundle/Controller/EntryRestControllerTest.php
@@ -3,8 +3,10 @@
3namespace Tests\Wallabag\ApiBundle\Controller; 3namespace Tests\Wallabag\ApiBundle\Controller;
4 4
5use Tests\Wallabag\ApiBundle\WallabagApiTestCase; 5use Tests\Wallabag\ApiBundle\WallabagApiTestCase;
6use Wallabag\CoreBundle\Entity\Entry;
6use Wallabag\CoreBundle\Entity\Tag; 7use Wallabag\CoreBundle\Entity\Tag;
7use Wallabag\CoreBundle\Helper\ContentProxy; 8use Wallabag\CoreBundle\Helper\ContentProxy;
9use Wallabag\UserBundle\Entity\User;
8 10
9class EntryRestControllerTest extends WallabagApiTestCase 11class EntryRestControllerTest extends WallabagApiTestCase
10{ 12{
@@ -19,19 +21,19 @@ class EntryRestControllerTest extends WallabagApiTestCase
19 $this->markTestSkipped('No content found in db.'); 21 $this->markTestSkipped('No content found in db.');
20 } 22 }
21 23
22 $this->client->request('GET', '/api/entries/'.$entry->getId().'.json'); 24 $this->client->request('GET', '/api/entries/' . $entry->getId() . '.json');
23 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 25 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
24 26
25 $content = json_decode($this->client->getResponse()->getContent(), true); 27 $content = json_decode($this->client->getResponse()->getContent(), true);
26 28
27 $this->assertEquals($entry->getTitle(), $content['title']); 29 $this->assertSame($entry->getTitle(), $content['title']);
28 $this->assertEquals($entry->getUrl(), $content['url']); 30 $this->assertSame($entry->getUrl(), $content['url']);
29 $this->assertCount(count($entry->getTags()), $content['tags']); 31 $this->assertCount(count($entry->getTags()), $content['tags']);
30 $this->assertEquals($entry->getUserName(), $content['user_name']); 32 $this->assertSame($entry->getUserName(), $content['user_name']);
31 $this->assertEquals($entry->getUserEmail(), $content['user_email']); 33 $this->assertSame($entry->getUserEmail(), $content['user_email']);
32 $this->assertEquals($entry->getUserId(), $content['user_id']); 34 $this->assertSame($entry->getUserId(), $content['user_id']);
33 35
34 $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type')); 36 $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
35 } 37 }
36 38
37 public function testExportEntry() 39 public function testExportEntry()
@@ -45,39 +47,39 @@ class EntryRestControllerTest extends WallabagApiTestCase
45 $this->markTestSkipped('No content found in db.'); 47 $this->markTestSkipped('No content found in db.');
46 } 48 }
47 49
48 $this->client->request('GET', '/api/entries/'.$entry->getId().'/export.epub'); 50 $this->client->request('GET', '/api/entries/' . $entry->getId() . '/export.epub');
49 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 51 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
50 52
51 // epub format got the content type in the content 53 // epub format got the content type in the content
52 $this->assertContains('application/epub', $this->client->getResponse()->getContent()); 54 $this->assertContains('application/epub', $this->client->getResponse()->getContent());
53 $this->assertEquals('application/epub+zip', $this->client->getResponse()->headers->get('Content-Type')); 55 $this->assertSame('application/epub+zip', $this->client->getResponse()->headers->get('Content-Type'));
54 56
55 // re-auth client for mobi 57 // re-auth client for mobi
56 $client = $this->createAuthorizedClient(); 58 $client = $this->createAuthorizedClient();
57 $client->request('GET', '/api/entries/'.$entry->getId().'/export.mobi'); 59 $client->request('GET', '/api/entries/' . $entry->getId() . '/export.mobi');
58 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 60 $this->assertSame(200, $client->getResponse()->getStatusCode());
59 61
60 $this->assertEquals('application/x-mobipocket-ebook', $client->getResponse()->headers->get('Content-Type')); 62 $this->assertSame('application/x-mobipocket-ebook', $client->getResponse()->headers->get('Content-Type'));
61 63
62 // re-auth client for pdf 64 // re-auth client for pdf
63 $client = $this->createAuthorizedClient(); 65 $client = $this->createAuthorizedClient();
64 $client->request('GET', '/api/entries/'.$entry->getId().'/export.pdf'); 66 $client->request('GET', '/api/entries/' . $entry->getId() . '/export.pdf');
65 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 67 $this->assertSame(200, $client->getResponse()->getStatusCode());
66 68
67 $this->assertContains('PDF-', $client->getResponse()->getContent()); 69 $this->assertContains('PDF-', $client->getResponse()->getContent());
68 $this->assertEquals('application/pdf', $client->getResponse()->headers->get('Content-Type')); 70 $this->assertSame('application/pdf', $client->getResponse()->headers->get('Content-Type'));
69 71
70 // re-auth client for pdf 72 // re-auth client for pdf
71 $client = $this->createAuthorizedClient(); 73 $client = $this->createAuthorizedClient();
72 $client->request('GET', '/api/entries/'.$entry->getId().'/export.txt'); 74 $client->request('GET', '/api/entries/' . $entry->getId() . '/export.txt');
73 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 75 $this->assertSame(200, $client->getResponse()->getStatusCode());
74 76
75 $this->assertContains('text/plain', $client->getResponse()->headers->get('Content-Type')); 77 $this->assertContains('text/plain', $client->getResponse()->headers->get('Content-Type'));
76 78
77 // re-auth client for pdf 79 // re-auth client for pdf
78 $client = $this->createAuthorizedClient(); 80 $client = $this->createAuthorizedClient();
79 $client->request('GET', '/api/entries/'.$entry->getId().'/export.csv'); 81 $client->request('GET', '/api/entries/' . $entry->getId() . '/export.csv');
80 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 82 $this->assertSame(200, $client->getResponse()->getStatusCode());
81 83
82 $this->assertContains('application/csv', $client->getResponse()->headers->get('Content-Type')); 84 $this->assertContains('application/csv', $client->getResponse()->headers->get('Content-Type'));
83 } 85 }
@@ -93,26 +95,26 @@ class EntryRestControllerTest extends WallabagApiTestCase
93 $this->markTestSkipped('No content found in db.'); 95 $this->markTestSkipped('No content found in db.');
94 } 96 }
95 97
96 $this->client->request('GET', '/api/entries/'.$entry->getId().'.json'); 98 $this->client->request('GET', '/api/entries/' . $entry->getId() . '.json');
97 99
98 $this->assertEquals(403, $this->client->getResponse()->getStatusCode()); 100 $this->assertSame(403, $this->client->getResponse()->getStatusCode());
99 } 101 }
100 102
101 public function testGetEntries() 103 public function testGetEntries()
102 { 104 {
103 $this->client->request('GET', '/api/entries'); 105 $this->client->request('GET', '/api/entries');
104 106
105 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 107 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
106 108
107 $content = json_decode($this->client->getResponse()->getContent(), true); 109 $content = json_decode($this->client->getResponse()->getContent(), true);
108 110
109 $this->assertGreaterThanOrEqual(1, count($content)); 111 $this->assertGreaterThanOrEqual(1, count($content));
110 $this->assertNotEmpty($content['_embedded']['items']); 112 $this->assertNotEmpty($content['_embedded']['items']);
111 $this->assertGreaterThanOrEqual(1, $content['total']); 113 $this->assertGreaterThanOrEqual(1, $content['total']);
112 $this->assertEquals(1, $content['page']); 114 $this->assertSame(1, $content['page']);
113 $this->assertGreaterThanOrEqual(1, $content['pages']); 115 $this->assertGreaterThanOrEqual(1, $content['pages']);
114 116
115 $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type')); 117 $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
116 } 118 }
117 119
118 public function testGetEntriesWithFullOptions() 120 public function testGetEntriesWithFullOptions()
@@ -126,17 +128,18 @@ class EntryRestControllerTest extends WallabagApiTestCase
126 'perPage' => 2, 128 'perPage' => 2,
127 'tags' => 'foo', 129 'tags' => 'foo',
128 'since' => 1443274283, 130 'since' => 1443274283,
131 'public' => 0,
129 ]); 132 ]);
130 133
131 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 134 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
132 135
133 $content = json_decode($this->client->getResponse()->getContent(), true); 136 $content = json_decode($this->client->getResponse()->getContent(), true);
134 137
135 $this->assertGreaterThanOrEqual(1, count($content)); 138 $this->assertGreaterThanOrEqual(1, count($content));
136 $this->assertArrayHasKey('items', $content['_embedded']); 139 $this->assertArrayHasKey('items', $content['_embedded']);
137 $this->assertGreaterThanOrEqual(0, $content['total']); 140 $this->assertGreaterThanOrEqual(0, $content['total']);
138 $this->assertEquals(1, $content['page']); 141 $this->assertSame(1, $content['page']);
139 $this->assertEquals(2, $content['limit']); 142 $this->assertSame(2, $content['limit']);
140 $this->assertGreaterThanOrEqual(1, $content['pages']); 143 $this->assertGreaterThanOrEqual(1, $content['pages']);
141 144
142 $this->assertArrayHasKey('_links', $content); 145 $this->assertArrayHasKey('_links', $content);
@@ -152,9 +155,56 @@ class EntryRestControllerTest extends WallabagApiTestCase
152 $this->assertContains('order=asc', $content['_links'][$link]['href']); 155 $this->assertContains('order=asc', $content['_links'][$link]['href']);
153 $this->assertContains('tags=foo', $content['_links'][$link]['href']); 156 $this->assertContains('tags=foo', $content['_links'][$link]['href']);
154 $this->assertContains('since=1443274283', $content['_links'][$link]['href']); 157 $this->assertContains('since=1443274283', $content['_links'][$link]['href']);
158 $this->assertContains('public=0', $content['_links'][$link]['href']);
155 } 159 }
156 160
157 $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type')); 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'));
158 } 208 }
159 209
160 public function testGetEntriesOnPageTwo() 210 public function testGetEntriesOnPageTwo()
@@ -164,27 +214,27 @@ class EntryRestControllerTest extends WallabagApiTestCase
164 'perPage' => 2, 214 'perPage' => 2,
165 ]); 215 ]);
166 216
167 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 217 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
168 218
169 $content = json_decode($this->client->getResponse()->getContent(), true); 219 $content = json_decode($this->client->getResponse()->getContent(), true);
170 220
171 $this->assertGreaterThanOrEqual(0, $content['total']); 221 $this->assertGreaterThanOrEqual(0, $content['total']);
172 $this->assertEquals(2, $content['page']); 222 $this->assertSame(2, $content['page']);
173 $this->assertEquals(2, $content['limit']); 223 $this->assertSame(2, $content['limit']);
174 } 224 }
175 225
176 public function testGetStarredEntries() 226 public function testGetStarredEntries()
177 { 227 {
178 $this->client->request('GET', '/api/entries', ['starred' => 1, 'sort' => 'updated']); 228 $this->client->request('GET', '/api/entries', ['starred' => 1, 'sort' => 'updated']);
179 229
180 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 230 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
181 231
182 $content = json_decode($this->client->getResponse()->getContent(), true); 232 $content = json_decode($this->client->getResponse()->getContent(), true);
183 233
184 $this->assertGreaterThanOrEqual(1, count($content)); 234 $this->assertGreaterThanOrEqual(1, count($content));
185 $this->assertNotEmpty($content['_embedded']['items']); 235 $this->assertNotEmpty($content['_embedded']['items']);
186 $this->assertGreaterThanOrEqual(1, $content['total']); 236 $this->assertGreaterThanOrEqual(1, $content['total']);
187 $this->assertEquals(1, $content['page']); 237 $this->assertSame(1, $content['page']);
188 $this->assertGreaterThanOrEqual(1, $content['pages']); 238 $this->assertGreaterThanOrEqual(1, $content['pages']);
189 239
190 $this->assertArrayHasKey('_links', $content); 240 $this->assertArrayHasKey('_links', $content);
@@ -198,21 +248,21 @@ class EntryRestControllerTest extends WallabagApiTestCase
198 $this->assertContains('sort=updated', $content['_links'][$link]['href']); 248 $this->assertContains('sort=updated', $content['_links'][$link]['href']);
199 } 249 }
200 250
201 $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type')); 251 $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
202 } 252 }
203 253
204 public function testGetArchiveEntries() 254 public function testGetArchiveEntries()
205 { 255 {
206 $this->client->request('GET', '/api/entries', ['archive' => 1]); 256 $this->client->request('GET', '/api/entries', ['archive' => 1]);
207 257
208 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 258 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
209 259
210 $content = json_decode($this->client->getResponse()->getContent(), true); 260 $content = json_decode($this->client->getResponse()->getContent(), true);
211 261
212 $this->assertGreaterThanOrEqual(1, count($content)); 262 $this->assertGreaterThanOrEqual(1, count($content));
213 $this->assertNotEmpty($content['_embedded']['items']); 263 $this->assertNotEmpty($content['_embedded']['items']);
214 $this->assertGreaterThanOrEqual(1, $content['total']); 264 $this->assertGreaterThanOrEqual(1, $content['total']);
215 $this->assertEquals(1, $content['page']); 265 $this->assertSame(1, $content['page']);
216 $this->assertGreaterThanOrEqual(1, $content['pages']); 266 $this->assertGreaterThanOrEqual(1, $content['pages']);
217 267
218 $this->assertArrayHasKey('_links', $content); 268 $this->assertArrayHasKey('_links', $content);
@@ -225,21 +275,21 @@ class EntryRestControllerTest extends WallabagApiTestCase
225 $this->assertContains('archive=1', $content['_links'][$link]['href']); 275 $this->assertContains('archive=1', $content['_links'][$link]['href']);
226 } 276 }
227 277
228 $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type')); 278 $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
229 } 279 }
230 280
231 public function testGetTaggedEntries() 281 public function testGetTaggedEntries()
232 { 282 {
233 $this->client->request('GET', '/api/entries', ['tags' => 'foo,bar']); 283 $this->client->request('GET', '/api/entries', ['tags' => 'foo,bar']);
234 284
235 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 285 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
236 286
237 $content = json_decode($this->client->getResponse()->getContent(), true); 287 $content = json_decode($this->client->getResponse()->getContent(), true);
238 288
239 $this->assertGreaterThanOrEqual(1, count($content)); 289 $this->assertGreaterThanOrEqual(1, count($content));
240 $this->assertNotEmpty($content['_embedded']['items']); 290 $this->assertNotEmpty($content['_embedded']['items']);
241 $this->assertGreaterThanOrEqual(1, $content['total']); 291 $this->assertGreaterThanOrEqual(1, $content['total']);
242 $this->assertEquals(1, $content['page']); 292 $this->assertSame(1, $content['page']);
243 $this->assertGreaterThanOrEqual(1, $content['pages']); 293 $this->assertGreaterThanOrEqual(1, $content['pages']);
244 294
245 $this->assertArrayHasKey('_links', $content); 295 $this->assertArrayHasKey('_links', $content);
@@ -249,24 +299,24 @@ class EntryRestControllerTest extends WallabagApiTestCase
249 299
250 foreach (['self', 'first', 'last'] as $link) { 300 foreach (['self', 'first', 'last'] as $link) {
251 $this->assertArrayHasKey('href', $content['_links'][$link]); 301 $this->assertArrayHasKey('href', $content['_links'][$link]);
252 $this->assertContains('tags='.urlencode('foo,bar'), $content['_links'][$link]['href']); 302 $this->assertContains('tags=' . urlencode('foo,bar'), $content['_links'][$link]['href']);
253 } 303 }
254 304
255 $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type')); 305 $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
256 } 306 }
257 307
258 public function testGetDatedEntries() 308 public function testGetDatedEntries()
259 { 309 {
260 $this->client->request('GET', '/api/entries', ['since' => 1443274283]); 310 $this->client->request('GET', '/api/entries', ['since' => 1443274283]);
261 311
262 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 312 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
263 313
264 $content = json_decode($this->client->getResponse()->getContent(), true); 314 $content = json_decode($this->client->getResponse()->getContent(), true);
265 315
266 $this->assertGreaterThanOrEqual(1, count($content)); 316 $this->assertGreaterThanOrEqual(1, count($content));
267 $this->assertNotEmpty($content['_embedded']['items']); 317 $this->assertNotEmpty($content['_embedded']['items']);
268 $this->assertGreaterThanOrEqual(1, $content['total']); 318 $this->assertGreaterThanOrEqual(1, $content['total']);
269 $this->assertEquals(1, $content['page']); 319 $this->assertSame(1, $content['page']);
270 $this->assertGreaterThanOrEqual(1, $content['pages']); 320 $this->assertGreaterThanOrEqual(1, $content['pages']);
271 321
272 $this->assertArrayHasKey('_links', $content); 322 $this->assertArrayHasKey('_links', $content);
@@ -279,7 +329,7 @@ class EntryRestControllerTest extends WallabagApiTestCase
279 $this->assertContains('since=1443274283', $content['_links'][$link]['href']); 329 $this->assertContains('since=1443274283', $content['_links'][$link]['href']);
280 } 330 }
281 331
282 $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type')); 332 $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
283 } 333 }
284 334
285 public function testGetDatedSupEntries() 335 public function testGetDatedSupEntries()
@@ -287,15 +337,15 @@ class EntryRestControllerTest extends WallabagApiTestCase
287 $future = new \DateTime(date('Y-m-d H:i:s')); 337 $future = new \DateTime(date('Y-m-d H:i:s'));
288 $this->client->request('GET', '/api/entries', ['since' => $future->getTimestamp() + 1000]); 338 $this->client->request('GET', '/api/entries', ['since' => $future->getTimestamp() + 1000]);
289 339
290 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 340 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
291 341
292 $content = json_decode($this->client->getResponse()->getContent(), true); 342 $content = json_decode($this->client->getResponse()->getContent(), true);
293 343
294 $this->assertGreaterThanOrEqual(1, count($content)); 344 $this->assertGreaterThanOrEqual(1, count($content));
295 $this->assertEmpty($content['_embedded']['items']); 345 $this->assertEmpty($content['_embedded']['items']);
296 $this->assertEquals(0, $content['total']); 346 $this->assertSame(0, $content['total']);
297 $this->assertEquals(1, $content['page']); 347 $this->assertSame(1, $content['page']);
298 $this->assertEquals(1, $content['pages']); 348 $this->assertSame(1, $content['pages']);
299 349
300 $this->assertArrayHasKey('_links', $content); 350 $this->assertArrayHasKey('_links', $content);
301 $this->assertArrayHasKey('self', $content['_links']); 351 $this->assertArrayHasKey('self', $content['_links']);
@@ -304,10 +354,10 @@ class EntryRestControllerTest extends WallabagApiTestCase
304 354
305 foreach (['self', 'first', 'last'] as $link) { 355 foreach (['self', 'first', 'last'] as $link) {
306 $this->assertArrayHasKey('href', $content['_links'][$link]); 356 $this->assertArrayHasKey('href', $content['_links'][$link]);
307 $this->assertContains('since='.($future->getTimestamp() + 1000), $content['_links'][$link]['href']); 357 $this->assertContains('since=' . ($future->getTimestamp() + 1000), $content['_links'][$link]['href']);
308 } 358 }
309 359
310 $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type')); 360 $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
311 } 361 }
312 362
313 public function testDeleteEntry() 363 public function testDeleteEntry()
@@ -315,25 +365,25 @@ class EntryRestControllerTest extends WallabagApiTestCase
315 $entry = $this->client->getContainer() 365 $entry = $this->client->getContainer()
316 ->get('doctrine.orm.entity_manager') 366 ->get('doctrine.orm.entity_manager')
317 ->getRepository('WallabagCoreBundle:Entry') 367 ->getRepository('WallabagCoreBundle:Entry')
318 ->findOneByUser(1); 368 ->findOneByUser(1, ['id' => 'asc']);
319 369
320 if (!$entry) { 370 if (!$entry) {
321 $this->markTestSkipped('No content found in db.'); 371 $this->markTestSkipped('No content found in db.');
322 } 372 }
323 373
324 $this->client->request('DELETE', '/api/entries/'.$entry->getId().'.json'); 374 $this->client->request('DELETE', '/api/entries/' . $entry->getId() . '.json');
325 375
326 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 376 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
327 377
328 $content = json_decode($this->client->getResponse()->getContent(), true); 378 $content = json_decode($this->client->getResponse()->getContent(), true);
329 379
330 $this->assertEquals($entry->getTitle(), $content['title']); 380 $this->assertSame($entry->getTitle(), $content['title']);
331 $this->assertEquals($entry->getUrl(), $content['url']); 381 $this->assertSame($entry->getUrl(), $content['url']);
332 382
333 // We'll try to delete this entry again 383 // We'll try to delete this entry again
334 $this->client->request('DELETE', '/api/entries/'.$entry->getId().'.json'); 384 $this->client->request('DELETE', '/api/entries/' . $entry->getId() . '.json');
335 385
336 $this->assertEquals(404, $this->client->getResponse()->getStatusCode()); 386 $this->assertSame(404, $this->client->getResponse()->getStatusCode());
337 } 387 }
338 388
339 public function testPostEntry() 389 public function testPostEntry()
@@ -342,38 +392,60 @@ class EntryRestControllerTest extends WallabagApiTestCase
342 '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', 392 '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',
343 'tags' => 'google', 393 'tags' => 'google',
344 'title' => 'New title for my article', 394 'title' => 'New title for my article',
395 'content' => 'my content',
396 'language' => 'de',
397 'published_at' => '2016-09-08T11:55:58+0200',
398 'authors' => 'bob,helen',
399 'public' => 1,
345 ]); 400 ]);
346 401
347 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 402 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
348 403
349 $content = json_decode($this->client->getResponse()->getContent(), true); 404 $content = json_decode($this->client->getResponse()->getContent(), true);
350 405
351 $this->assertGreaterThan(0, $content['id']); 406 $this->assertGreaterThan(0, $content['id']);
352 $this->assertEquals('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']); 407 $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']);
353 $this->assertEquals(false, $content['is_archived']); 408 $this->assertSame(0, $content['is_archived']);
354 $this->assertEquals(false, $content['is_starred']); 409 $this->assertSame(0, $content['is_starred']);
355 $this->assertEquals('New title for my article', $content['title']); 410 $this->assertSame('New title for my article', $content['title']);
356 $this->assertEquals(1, $content['user_id']); 411 $this->assertSame(1, $content['user_id']);
357 $this->assertCount(1, $content['tags']); 412 $this->assertCount(2, $content['tags']);
413 $this->assertSame('my content', $content['content']);
414 $this->assertSame('de', $content['language']);
415 $this->assertSame('2016-09-08T11:55:58+0200', $content['published_at']);
416 $this->assertCount(2, $content['published_by']);
417 $this->assertContains('bob', $content['published_by']);
418 $this->assertContains('helen', $content['published_by']);
419 $this->assertTrue($content['is_public'], 'A public link has been generated for that entry');
358 } 420 }
359 421
360 public function testPostSameEntry() 422 public function testPostSameEntry()
361 { 423 {
424 $em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
425 $entry = new Entry($em->getReference(User::class, 1));
426 $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');
427 $entry->setArchived(true);
428 $entry->addTag((new Tag())->setLabel('google'));
429 $entry->addTag((new Tag())->setLabel('apple'));
430 $em->persist($entry);
431 $em->flush();
432 $em->clear();
433
362 $this->client->request('POST', '/api/entries.json', [ 434 $this->client->request('POST', '/api/entries.json', [
363 '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', 435 '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',
364 'archive' => '1', 436 'archive' => '1',
365 'tags' => 'google, apple', 437 'tags' => 'google, apple',
366 ]); 438 ]);
367 439
368 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 440 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
369 441
370 $content = json_decode($this->client->getResponse()->getContent(), true); 442 $content = json_decode($this->client->getResponse()->getContent(), true);
371 443
372 $this->assertGreaterThan(0, $content['id']); 444 $this->assertGreaterThan(0, $content['id']);
373 $this->assertEquals('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']); 445 $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']);
374 $this->assertEquals(true, $content['is_archived']); 446 $this->assertSame(1, $content['is_archived']);
375 $this->assertEquals(false, $content['is_starred']); 447 $this->assertSame(0, $content['is_starred']);
376 $this->assertCount(2, $content['tags']); 448 $this->assertCount(3, $content['tags']);
377 } 449 }
378 450
379 public function testPostEntryWhenFetchContentFails() 451 public function testPostEntryWhenFetchContentFails()
@@ -394,10 +466,10 @@ class EntryRestControllerTest extends WallabagApiTestCase
394 'url' => 'http://www.example.com/', 466 'url' => 'http://www.example.com/',
395 ]); 467 ]);
396 468
397 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 469 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
398 $content = json_decode($this->client->getResponse()->getContent(), true); 470 $content = json_decode($this->client->getResponse()->getContent(), true);
399 $this->assertGreaterThan(0, $content['id']); 471 $this->assertGreaterThan(0, $content['id']);
400 $this->assertEquals('http://www.example.com/', $content['url']); 472 $this->assertSame('http://www.example.com/', $content['url']);
401 } finally { 473 } finally {
402 // Remove the created entry to avoid side effects on other tests 474 // Remove the created entry to avoid side effects on other tests
403 if (isset($content['id'])) { 475 if (isset($content['id'])) {
@@ -417,15 +489,15 @@ class EntryRestControllerTest extends WallabagApiTestCase
417 'starred' => '1', 489 'starred' => '1',
418 ]); 490 ]);
419 491
420 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 492 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
421 493
422 $content = json_decode($this->client->getResponse()->getContent(), true); 494 $content = json_decode($this->client->getResponse()->getContent(), true);
423 495
424 $this->assertGreaterThan(0, $content['id']); 496 $this->assertGreaterThan(0, $content['id']);
425 $this->assertEquals('http://www.lemonde.fr/idees/article/2016/02/08/preserver-la-liberte-d-expression-sur-les-reseaux-sociaux_4861503_3232.html', $content['url']); 497 $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']);
426 $this->assertEquals(true, $content['is_archived']); 498 $this->assertSame(1, $content['is_archived']);
427 $this->assertEquals(true, $content['is_starred']); 499 $this->assertSame(1, $content['is_starred']);
428 $this->assertEquals(1, $content['user_id']); 500 $this->assertSame(1, $content['user_id']);
429 } 501 }
430 502
431 public function testPostArchivedAndStarredEntryWithoutQuotes() 503 public function testPostArchivedAndStarredEntryWithoutQuotes()
@@ -436,14 +508,14 @@ class EntryRestControllerTest extends WallabagApiTestCase
436 'starred' => 1, 508 'starred' => 1,
437 ]); 509 ]);
438 510
439 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 511 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
440 512
441 $content = json_decode($this->client->getResponse()->getContent(), true); 513 $content = json_decode($this->client->getResponse()->getContent(), true);
442 514
443 $this->assertGreaterThan(0, $content['id']); 515 $this->assertGreaterThan(0, $content['id']);
444 $this->assertEquals('http://www.lemonde.fr/idees/article/2016/02/08/preserver-la-liberte-d-expression-sur-les-reseaux-sociaux_4861503_3232.html', $content['url']); 516 $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']);
445 $this->assertEquals(false, $content['is_archived']); 517 $this->assertSame(0, $content['is_archived']);
446 $this->assertEquals(true, $content['is_starred']); 518 $this->assertSame(1, $content['is_starred']);
447 } 519 }
448 520
449 public function testPatchEntry() 521 public function testPatchEntry()
@@ -457,25 +529,35 @@ class EntryRestControllerTest extends WallabagApiTestCase
457 $this->markTestSkipped('No content found in db.'); 529 $this->markTestSkipped('No content found in db.');
458 } 530 }
459 531
460 // hydrate the tags relations 532 $this->client->request('PATCH', '/api/entries/' . $entry->getId() . '.json', [
461 $nbTags = count($entry->getTags());
462
463 $this->client->request('PATCH', '/api/entries/'.$entry->getId().'.json', [
464 'title' => 'New awesome title', 533 'title' => 'New awesome title',
465 'tags' => 'new tag '.uniqid(), 534 'tags' => 'new tag ' . uniqid(),
466 'starred' => '1', 535 'starred' => '1',
467 'archive' => '0', 536 'archive' => '0',
537 'language' => 'de_AT',
538 'preview_picture' => 'http://preview.io/picture.jpg',
539 'authors' => 'bob,sponge',
540 'content' => 'awesome',
541 'public' => 0,
542 'published_at' => 1488833381,
468 ]); 543 ]);
469 544
470 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 545 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
471 546
472 $content = json_decode($this->client->getResponse()->getContent(), true); 547 $content = json_decode($this->client->getResponse()->getContent(), true);
473 548
474 $this->assertEquals($entry->getId(), $content['id']); 549 $this->assertSame($entry->getId(), $content['id']);
475 $this->assertEquals($entry->getUrl(), $content['url']); 550 $this->assertSame($entry->getUrl(), $content['url']);
476 $this->assertEquals('New awesome title', $content['title']); 551 $this->assertSame('New awesome title', $content['title']);
477 $this->assertGreaterThan($nbTags, count($content['tags'])); 552 $this->assertGreaterThanOrEqual(1, count($content['tags']), 'We force only one tag');
478 $this->assertEquals(1, $content['user_id']); 553 $this->assertSame(1, $content['user_id']);
554 $this->assertSame('de_AT', $content['language']);
555 $this->assertSame('http://preview.io/picture.jpg', $content['preview_picture']);
556 $this->assertContains('sponge', $content['published_by']);
557 $this->assertContains('bob', $content['published_by']);
558 $this->assertSame('awesome', $content['content']);
559 $this->assertFalse($content['is_public'], 'Entry is no more shared');
560 $this->assertContains('2017-03-06', $content['published_at']);
479 } 561 }
480 562
481 public function testPatchEntryWithoutQuotes() 563 public function testPatchEntryWithoutQuotes()
@@ -489,24 +571,27 @@ class EntryRestControllerTest extends WallabagApiTestCase
489 $this->markTestSkipped('No content found in db.'); 571 $this->markTestSkipped('No content found in db.');
490 } 572 }
491 573
492 // hydrate the tags relations 574 $previousContent = $entry->getContent();
493 $nbTags = count($entry->getTags()); 575 $previousLanguage = $entry->getLanguage();
494 576
495 $this->client->request('PATCH', '/api/entries/'.$entry->getId().'.json', [ 577 $this->client->request('PATCH', '/api/entries/' . $entry->getId() . '.json', [
496 'title' => 'New awesome title', 578 'title' => 'New awesome title',
497 'tags' => 'new tag '.uniqid(), 579 'tags' => 'new tag ' . uniqid(),
498 'starred' => 1, 580 'starred' => 1,
499 'archive' => 0, 581 'archive' => 0,
582 'authors' => ['bob', 'sponge'],
500 ]); 583 ]);
501 584
502 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 585 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
503 586
504 $content = json_decode($this->client->getResponse()->getContent(), true); 587 $content = json_decode($this->client->getResponse()->getContent(), true);
505 588
506 $this->assertEquals($entry->getId(), $content['id']); 589 $this->assertSame($entry->getId(), $content['id']);
507 $this->assertEquals($entry->getUrl(), $content['url']); 590 $this->assertSame($entry->getUrl(), $content['url']);
508 $this->assertEquals('New awesome title', $content['title']); 591 $this->assertGreaterThanOrEqual(1, count($content['tags']), 'We force only one tag');
509 $this->assertGreaterThan($nbTags, count($content['tags'])); 592 $this->assertEmpty($content['published_by'], 'Authors were not saved because of an array instead of a string');
593 $this->assertSame($previousContent, $content['content'], 'Ensure content has not moved');
594 $this->assertSame($previousLanguage, $content['language'], 'Ensure language has not moved');
510 } 595 }
511 596
512 public function testGetTagsEntry() 597 public function testGetTagsEntry()
@@ -527,9 +612,9 @@ class EntryRestControllerTest extends WallabagApiTestCase
527 $tags[] = ['id' => $tag->getId(), 'label' => $tag->getLabel(), 'slug' => $tag->getSlug()]; 612 $tags[] = ['id' => $tag->getId(), 'label' => $tag->getLabel(), 'slug' => $tag->getSlug()];
528 } 613 }
529 614
530 $this->client->request('GET', '/api/entries/'.$entry->getId().'/tags'); 615 $this->client->request('GET', '/api/entries/' . $entry->getId() . '/tags');
531 616
532 $this->assertEquals(json_encode($tags, JSON_HEX_QUOT), $this->client->getResponse()->getContent()); 617 $this->assertSame(json_encode($tags, JSON_HEX_QUOT), $this->client->getResponse()->getContent());
533 } 618 }
534 619
535 public function testPostTagsOnEntry() 620 public function testPostTagsOnEntry()
@@ -547,14 +632,14 @@ class EntryRestControllerTest extends WallabagApiTestCase
547 632
548 $newTags = 'tag1,tag2,tag3'; 633 $newTags = 'tag1,tag2,tag3';
549 634
550 $this->client->request('POST', '/api/entries/'.$entry->getId().'/tags', ['tags' => $newTags]); 635 $this->client->request('POST', '/api/entries/' . $entry->getId() . '/tags', ['tags' => $newTags]);
551 636
552 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 637 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
553 638
554 $content = json_decode($this->client->getResponse()->getContent(), true); 639 $content = json_decode($this->client->getResponse()->getContent(), true);
555 640
556 $this->assertArrayHasKey('tags', $content); 641 $this->assertArrayHasKey('tags', $content);
557 $this->assertEquals($nbTags + 3, count($content['tags'])); 642 $this->assertSame($nbTags + 3, count($content['tags']));
558 643
559 $entryDB = $this->client->getContainer() 644 $entryDB = $this->client->getContainer()
560 ->get('doctrine.orm.entity_manager') 645 ->get('doctrine.orm.entity_manager')
@@ -587,14 +672,14 @@ class EntryRestControllerTest extends WallabagApiTestCase
587 $nbTags = count($entry->getTags()); 672 $nbTags = count($entry->getTags());
588 $tag = $entry->getTags()[0]; 673 $tag = $entry->getTags()[0];
589 674
590 $this->client->request('DELETE', '/api/entries/'.$entry->getId().'/tags/'.$tag->getId().'.json'); 675 $this->client->request('DELETE', '/api/entries/' . $entry->getId() . '/tags/' . $tag->getId() . '.json');
591 676
592 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 677 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
593 678
594 $content = json_decode($this->client->getResponse()->getContent(), true); 679 $content = json_decode($this->client->getResponse()->getContent(), true);
595 680
596 $this->assertArrayHasKey('tags', $content); 681 $this->assertArrayHasKey('tags', $content);
597 $this->assertEquals($nbTags - 1, count($content['tags'])); 682 $this->assertSame($nbTags - 1, count($content['tags']));
598 } 683 }
599 684
600 public function testSaveIsArchivedAfterPost() 685 public function testSaveIsArchivedAfterPost()
@@ -612,11 +697,11 @@ class EntryRestControllerTest extends WallabagApiTestCase
612 'url' => $entry->getUrl(), 697 'url' => $entry->getUrl(),
613 ]); 698 ]);
614 699
615 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 700 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
616 701
617 $content = json_decode($this->client->getResponse()->getContent(), true); 702 $content = json_decode($this->client->getResponse()->getContent(), true);
618 703
619 $this->assertEquals(true, $content['is_archived']); 704 $this->assertSame(1, $content['is_archived']);
620 } 705 }
621 706
622 public function testSaveIsStarredAfterPost() 707 public function testSaveIsStarredAfterPost()
@@ -634,11 +719,11 @@ class EntryRestControllerTest extends WallabagApiTestCase
634 'url' => $entry->getUrl(), 719 'url' => $entry->getUrl(),
635 ]); 720 ]);
636 721
637 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 722 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
638 723
639 $content = json_decode($this->client->getResponse()->getContent(), true); 724 $content = json_decode($this->client->getResponse()->getContent(), true);
640 725
641 $this->assertEquals(true, $content['is_starred']); 726 $this->assertSame(1, $content['is_starred']);
642 } 727 }
643 728
644 public function testSaveIsArchivedAfterPatch() 729 public function testSaveIsArchivedAfterPatch()
@@ -652,15 +737,18 @@ class EntryRestControllerTest extends WallabagApiTestCase
652 $this->markTestSkipped('No content found in db.'); 737 $this->markTestSkipped('No content found in db.');
653 } 738 }
654 739
655 $this->client->request('PATCH', '/api/entries/'.$entry->getId().'.json', [ 740 $previousTitle = $entry->getTitle();
656 'title' => $entry->getTitle().'++', 741
742 $this->client->request('PATCH', '/api/entries/' . $entry->getId() . '.json', [
743 'title' => $entry->getTitle() . '++',
657 ]); 744 ]);
658 745
659 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 746 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
660 747
661 $content = json_decode($this->client->getResponse()->getContent(), true); 748 $content = json_decode($this->client->getResponse()->getContent(), true);
662 749
663 $this->assertEquals(true, $content['is_archived']); 750 $this->assertSame(1, $content['is_archived']);
751 $this->assertSame($previousTitle . '++', $content['title']);
664 } 752 }
665 753
666 public function testSaveIsStarredAfterPatch() 754 public function testSaveIsStarredAfterPatch()
@@ -673,60 +761,93 @@ class EntryRestControllerTest extends WallabagApiTestCase
673 if (!$entry) { 761 if (!$entry) {
674 $this->markTestSkipped('No content found in db.'); 762 $this->markTestSkipped('No content found in db.');
675 } 763 }
676 $this->client->request('PATCH', '/api/entries/'.$entry->getId().'.json', [ 764 $this->client->request('PATCH', '/api/entries/' . $entry->getId() . '.json', [
677 'title' => $entry->getTitle().'++', 765 'title' => $entry->getTitle() . '++',
678 ]); 766 ]);
679 767
680 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 768 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
681 769
682 $content = json_decode($this->client->getResponse()->getContent(), true); 770 $content = json_decode($this->client->getResponse()->getContent(), true);
683 771
684 $this->assertEquals(true, $content['is_starred']); 772 $this->assertSame(1, $content['is_starred']);
773 }
774
775 public function dataForEntriesExistWithUrl()
776 {
777 return [
778 'with_id' => [
779 'url' => '/api/entries/exists?url=http://0.0.0.0/entry2&return_id=1',
780 'expectedValue' => 2,
781 ],
782 'without_id' => [
783 'url' => '/api/entries/exists?url=http://0.0.0.0/entry2',
784 'expectedValue' => true,
785 ],
786 ];
685 } 787 }
686 788
687 public function testGetEntriesExists() 789 /**
790 * @dataProvider dataForEntriesExistWithUrl
791 */
792 public function testGetEntriesExists($url, $expectedValue)
688 { 793 {
689 $this->client->request('GET', '/api/entries/exists?url=http://0.0.0.0/entry2'); 794 $this->client->request('GET', $url);
690 795
691 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 796 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
692 797
693 $content = json_decode($this->client->getResponse()->getContent(), true); 798 $content = json_decode($this->client->getResponse()->getContent(), true);
694 799
695 $this->assertEquals(true, $content['exists']); 800 $this->assertSame($expectedValue, $content['exists']);
696 } 801 }
697 802
698 public function testGetEntriesExistsWithManyUrls() 803 public function testGetEntriesExistsWithManyUrls()
699 { 804 {
700 $url1 = 'http://0.0.0.0/entry2'; 805 $url1 = 'http://0.0.0.0/entry2';
701 $url2 = 'http://0.0.0.0/entry10'; 806 $url2 = 'http://0.0.0.0/entry10';
702 $this->client->request('GET', '/api/entries/exists?urls[]='.$url1.'&urls[]='.$url2); 807 $this->client->request('GET', '/api/entries/exists?urls[]=' . $url1 . '&urls[]=' . $url2 . '&return_id=1');
703 808
704 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 809 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
705 810
706 $content = json_decode($this->client->getResponse()->getContent(), true); 811 $content = json_decode($this->client->getResponse()->getContent(), true);
707 812
708 $this->assertArrayHasKey($url1, $content); 813 $this->assertArrayHasKey($url1, $content);
709 $this->assertArrayHasKey($url2, $content); 814 $this->assertArrayHasKey($url2, $content);
710 $this->assertEquals(true, $content[$url1]); 815 $this->assertSame(2, $content[$url1]);
711 $this->assertEquals(false, $content[$url2]); 816 $this->assertNull($content[$url2]);
817 }
818
819 public function testGetEntriesExistsWithManyUrlsReturnBool()
820 {
821 $url1 = 'http://0.0.0.0/entry2';
822 $url2 = 'http://0.0.0.0/entry10';
823 $this->client->request('GET', '/api/entries/exists?urls[]=' . $url1 . '&urls[]=' . $url2);
824
825 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
826
827 $content = json_decode($this->client->getResponse()->getContent(), true);
828
829 $this->assertArrayHasKey($url1, $content);
830 $this->assertArrayHasKey($url2, $content);
831 $this->assertTrue($content[$url1]);
832 $this->assertFalse($content[$url2]);
712 } 833 }
713 834
714 public function testGetEntriesExistsWhichDoesNotExists() 835 public function testGetEntriesExistsWhichDoesNotExists()
715 { 836 {
716 $this->client->request('GET', '/api/entries/exists?url=http://google.com/entry2'); 837 $this->client->request('GET', '/api/entries/exists?url=http://google.com/entry2');
717 838
718 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 839 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
719 840
720 $content = json_decode($this->client->getResponse()->getContent(), true); 841 $content = json_decode($this->client->getResponse()->getContent(), true);
721 842
722 $this->assertEquals(false, $content['exists']); 843 $this->assertSame(false, $content['exists']);
723 } 844 }
724 845
725 public function testGetEntriesExistsWithNoUrl() 846 public function testGetEntriesExistsWithNoUrl()
726 { 847 {
727 $this->client->request('GET', '/api/entries/exists?url='); 848 $this->client->request('GET', '/api/entries/exists?url=');
728 849
729 $this->assertEquals(403, $this->client->getResponse()->getStatusCode()); 850 $this->assertSame(403, $this->client->getResponse()->getStatusCode());
730 } 851 }
731 852
732 public function testReloadEntryErrorWhileFetching() 853 public function testReloadEntryErrorWhileFetching()
@@ -739,8 +860,8 @@ class EntryRestControllerTest extends WallabagApiTestCase
739 $this->markTestSkipped('No content found in db.'); 860 $this->markTestSkipped('No content found in db.');
740 } 861 }
741 862
742 $this->client->request('PATCH', '/api/entries/'.$entry->getId().'/reload.json'); 863 $this->client->request('PATCH', '/api/entries/' . $entry->getId() . '/reload.json');
743 $this->assertEquals(304, $this->client->getResponse()->getStatusCode()); 864 $this->assertSame(304, $this->client->getResponse()->getStatusCode());
744 } 865 }
745 866
746 public function testReloadEntry() 867 public function testReloadEntry()
@@ -755,13 +876,208 @@ class EntryRestControllerTest extends WallabagApiTestCase
755 876
756 $this->setUp(); 877 $this->setUp();
757 878
758 $this->client->request('PATCH', '/api/entries/'.$json['id'].'/reload.json'); 879 $this->client->request('PATCH', '/api/entries/' . $json['id'] . '/reload.json');
759 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 880 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
760 881
761 $content = json_decode($this->client->getResponse()->getContent(), true); 882 $content = json_decode($this->client->getResponse()->getContent(), true);
762 883
763 $this->assertNotEmpty($content['title']); 884 $this->assertNotEmpty($content['title']);
764 885
765 $this->assertEquals('application/json', $this->client->getResponse()->headers->get('Content-Type')); 886 $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
887 }
888
889 public function testPostEntriesTagsListAction()
890 {
891 $entry = $this->client->getContainer()->get('doctrine.orm.entity_manager')
892 ->getRepository('WallabagCoreBundle:Entry')
893 ->findByUrlAndUserId('http://0.0.0.0/entry4', 1);
894
895 $tags = $entry->getTags();
896
897 $this->assertCount(2, $tags);
898
899 $list = [
900 [
901 'url' => 'http://0.0.0.0/entry4',
902 'tags' => 'new tag 1, new tag 2',
903 ],
904 ];
905
906 $this->client->request('POST', '/api/entries/tags/lists?list=' . json_encode($list));
907
908 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
909
910 $content = json_decode($this->client->getResponse()->getContent(), true);
911
912 $this->assertInternalType('int', $content[0]['entry']);
913 $this->assertSame('http://0.0.0.0/entry4', $content[0]['url']);
914
915 $entry = $this->client->getContainer()->get('doctrine.orm.entity_manager')
916 ->getRepository('WallabagCoreBundle:Entry')
917 ->findByUrlAndUserId('http://0.0.0.0/entry4', 1);
918
919 $tags = $entry->getTags();
920 $this->assertCount(4, $tags);
921 }
922
923 public function testPostEntriesTagsListActionNoList()
924 {
925 $this->client->request('POST', '/api/entries/tags/lists?list=' . json_encode([]));
926
927 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
928
929 $content = json_decode($this->client->getResponse()->getContent(), true);
930
931 $this->assertEmpty($content);
932 }
933
934 public function testDeleteEntriesTagsListAction()
935 {
936 $em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
937 $entry = new Entry($em->getReference(User::class, 1));
938 $entry->setUrl('http://0.0.0.0/test-entry');
939 $entry->addTag((new Tag())->setLabel('foo-tag'));
940 $entry->addTag((new Tag())->setLabel('bar-tag'));
941 $em->persist($entry);
942 $em->flush();
943
944 $em->clear();
945
946 $list = [
947 [
948 'url' => 'http://0.0.0.0/test-entry',
949 'tags' => 'foo-tag, bar-tag',
950 ],
951 ];
952
953 $this->client->request('DELETE', '/api/entries/tags/list?list=' . json_encode($list));
954 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
955
956 $entry = $em->getRepository('WallabagCoreBundle:Entry')->find($entry->getId());
957 $this->assertCount(0, $entry->getTags());
958 }
959
960 public function testDeleteEntriesTagsListActionNoList()
961 {
962 $this->client->request('DELETE', '/api/entries/tags/list?list=' . json_encode([]));
963
964 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
965
966 $content = json_decode($this->client->getResponse()->getContent(), true);
967
968 $this->assertEmpty($content);
969 }
970
971 public function testPostEntriesListAction()
972 {
973 $list = [
974 'http://www.lemonde.fr/musiques/article/2017/04/23/loin-de-la-politique-le-printemps-de-bourges-retombe-en-enfance_5115862_1654986.html',
975 'http://0.0.0.0/entry2',
976 ];
977
978 $this->client->request('POST', '/api/entries/lists?urls=' . json_encode($list));
979
980 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
981
982 $content = json_decode($this->client->getResponse()->getContent(), true);
983
984 $this->assertInternalType('int', $content[0]['entry']);
985 $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']);
986
987 $this->assertInternalType('int', $content[1]['entry']);
988 $this->assertSame('http://0.0.0.0/entry2', $content[1]['url']);
989 }
990
991 public function testPostEntriesListActionWithNoUrls()
992 {
993 $this->client->request('POST', '/api/entries/lists?urls=' . json_encode([]));
994
995 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
996
997 $content = json_decode($this->client->getResponse()->getContent(), true);
998
999 $this->assertEmpty($content);
1000 }
1001
1002 public function testDeleteEntriesListAction()
1003 {
1004 $em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
1005 $em->persist((new Entry($em->getReference(User::class, 1)))->setUrl('http://0.0.0.0/test-entry1'));
1006
1007 $em->flush();
1008 $em->clear();
1009 $list = [
1010 'http://0.0.0.0/test-entry1',
1011 'http://0.0.0.0/test-entry-not-exist',
1012 ];
1013
1014 $this->client->request('DELETE', '/api/entries/list?urls=' . json_encode($list));
1015
1016 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
1017
1018 $content = json_decode($this->client->getResponse()->getContent(), true);
1019
1020 $this->assertTrue($content[0]['entry']);
1021 $this->assertSame('http://0.0.0.0/test-entry1', $content[0]['url']);
1022
1023 $this->assertFalse($content[1]['entry']);
1024 $this->assertSame('http://0.0.0.0/test-entry-not-exist', $content[1]['url']);
1025 }
1026
1027 public function testDeleteEntriesListActionWithNoUrls()
1028 {
1029 $this->client->request('DELETE', '/api/entries/list?urls=' . json_encode([]));
1030
1031 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
1032
1033 $content = json_decode($this->client->getResponse()->getContent(), true);
1034
1035 $this->assertEmpty($content);
1036 }
1037
1038 public function testLimitBulkAction()
1039 {
1040 $list = [
1041 'http://0.0.0.0/entry1',
1042 'http://0.0.0.0/entry1',
1043 'http://0.0.0.0/entry1',
1044 'http://0.0.0.0/entry1',
1045 'http://0.0.0.0/entry1',
1046 'http://0.0.0.0/entry1',
1047 'http://0.0.0.0/entry1',
1048 'http://0.0.0.0/entry1',
1049 'http://0.0.0.0/entry1',
1050 'http://0.0.0.0/entry1',
1051 'http://0.0.0.0/entry1',
1052 ];
1053
1054 $this->client->request('POST', '/api/entries/lists?urls=' . json_encode($list));
1055
1056 $this->assertSame(400, $this->client->getResponse()->getStatusCode());
1057 $this->assertContains('API limit reached', $this->client->getResponse()->getContent());
1058 }
1059
1060 public function testRePostEntryAndReUsePublishedAt()
1061 {
1062 $em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
1063 $entry = new Entry($em->getReference(User::class, 1));
1064 $entry->setTitle('Antoine de Caunes : « Je veux avoir le droit de tâtonner »');
1065 $entry->setContent('hihi');
1066 $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');
1067 $entry->setPublishedAt(new \DateTime('2017-06-26T07:46:02+0200'));
1068 $em->persist($entry);
1069 $em->flush();
1070 $em->clear();
1071
1072 $this->client->request('POST', '/api/entries.json', [
1073 'url' => 'http://www.lemonde.fr/m-perso/article/2017/06/25/antoine-de-caunes-je-veux-avoir-le-droit-de-tatonner_5150728_4497916.html',
1074 ]);
1075
1076 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
1077
1078 $content = json_decode($this->client->getResponse()->getContent(), true);
1079
1080 $this->assertGreaterThan(0, $content['id']);
1081 $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']);
766 } 1082 }
767} 1083}
diff --git a/tests/Wallabag/ApiBundle/Controller/TagRestControllerTest.php b/tests/Wallabag/ApiBundle/Controller/TagRestControllerTest.php
index bde5251f..430e548d 100644
--- a/tests/Wallabag/ApiBundle/Controller/TagRestControllerTest.php
+++ b/tests/Wallabag/ApiBundle/Controller/TagRestControllerTest.php
@@ -11,7 +11,7 @@ class TagRestControllerTest extends WallabagApiTestCase
11 { 11 {
12 $this->client->request('GET', '/api/tags.json'); 12 $this->client->request('GET', '/api/tags.json');
13 13
14 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 14 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
15 15
16 $content = json_decode($this->client->getResponse()->getContent(), true); 16 $content = json_decode($this->client->getResponse()->getContent(), true);
17 17
@@ -22,39 +22,49 @@ class TagRestControllerTest extends WallabagApiTestCase
22 return end($content); 22 return end($content);
23 } 23 }
24 24
25 /** 25 public function testDeleteUserTag()
26 * @depends testGetUserTags
27 */
28 public function testDeleteUserTag($tag)
29 { 26 {
30 $tagName = $tag['label']; 27 $tagLabel = 'tagtest';
28 $tag = new Tag();
29 $tag->setLabel($tagLabel);
30
31 $em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
32 $em->persist($tag);
33 $em->flush();
34 $em->clear();
31 35
32 $this->client->request('DELETE', '/api/tags/'.$tag['id'].'.json'); 36 $this->client->request('DELETE', '/api/tags/' . $tag->getId() . '.json');
33 37
34 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 38 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
35 39
36 $content = json_decode($this->client->getResponse()->getContent(), true); 40 $content = json_decode($this->client->getResponse()->getContent(), true);
37 41
38 $this->assertArrayHasKey('label', $content); 42 $this->assertArrayHasKey('label', $content);
39 $this->assertEquals($tag['label'], $content['label']); 43 $this->assertSame($tag->getLabel(), $content['label']);
40 $this->assertEquals($tag['slug'], $content['slug']); 44 $this->assertSame($tag->getSlug(), $content['slug']);
41 45
42 $entries = $this->client->getContainer() 46 $entries = $em->getRepository('WallabagCoreBundle:Entry')
43 ->get('doctrine.orm.entity_manager') 47 ->findAllByTagId($this->user->getId(), $tag->getId());
44 ->getRepository('WallabagCoreBundle:Entry')
45 ->findAllByTagId($this->user->getId(), $tag['id']);
46 48
47 $this->assertCount(0, $entries); 49 $this->assertCount(0, $entries);
48 50
49 $tag = $this->client->getContainer() 51 $tag = $em->getRepository('WallabagCoreBundle:Tag')->findOneByLabel($tagLabel);
50 ->get('doctrine.orm.entity_manager')
51 ->getRepository('WallabagCoreBundle:Tag')
52 ->findOneByLabel($tagName);
53 52
54 $this->assertNull($tag, $tagName.' was removed because it begun an orphan tag'); 53 $this->assertNull($tag, $tagLabel . ' was removed because it begun an orphan tag');
55 } 54 }
56 55
57 public function testDeleteTagByLabel() 56 public function dataForDeletingTagByLabel()
57 {
58 return [
59 'by_query' => [true],
60 'by_body' => [false],
61 ];
62 }
63
64 /**
65 * @dataProvider dataForDeletingTagByLabel
66 */
67 public function testDeleteTagByLabel($useQueryString)
58 { 68 {
59 $em = $this->client->getContainer()->get('doctrine.orm.entity_manager'); 69 $em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
60 $entry = $this->client->getContainer() 70 $entry = $this->client->getContainer()
@@ -73,15 +83,19 @@ class TagRestControllerTest extends WallabagApiTestCase
73 $em->persist($entry); 83 $em->persist($entry);
74 $em->flush(); 84 $em->flush();
75 85
76 $this->client->request('DELETE', '/api/tag/label.json', ['tag' => $tag->getLabel()]); 86 if ($useQueryString) {
87 $this->client->request('DELETE', '/api/tag/label.json?tag=' . $tag->getLabel());
88 } else {
89 $this->client->request('DELETE', '/api/tag/label.json', ['tag' => $tag->getLabel()]);
90 }
77 91
78 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 92 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
79 93
80 $content = json_decode($this->client->getResponse()->getContent(), true); 94 $content = json_decode($this->client->getResponse()->getContent(), true);
81 95
82 $this->assertArrayHasKey('label', $content); 96 $this->assertArrayHasKey('label', $content);
83 $this->assertEquals($tag->getLabel(), $content['label']); 97 $this->assertSame($tag->getLabel(), $content['label']);
84 $this->assertEquals($tag->getSlug(), $content['slug']); 98 $this->assertSame($tag->getSlug(), $content['slug']);
85 99
86 $entries = $this->client->getContainer() 100 $entries = $this->client->getContainer()
87 ->get('doctrine.orm.entity_manager') 101 ->get('doctrine.orm.entity_manager')
@@ -95,10 +109,13 @@ class TagRestControllerTest extends WallabagApiTestCase
95 { 109 {
96 $this->client->request('DELETE', '/api/tag/label.json', ['tag' => 'does not exist']); 110 $this->client->request('DELETE', '/api/tag/label.json', ['tag' => 'does not exist']);
97 111
98 $this->assertEquals(404, $this->client->getResponse()->getStatusCode()); 112 $this->assertSame(404, $this->client->getResponse()->getStatusCode());
99 } 113 }
100 114
101 public function testDeleteTagsByLabel() 115 /**
116 * @dataProvider dataForDeletingTagByLabel
117 */
118 public function testDeleteTagsByLabel($useQueryString)
102 { 119 {
103 $em = $this->client->getContainer()->get('doctrine.orm.entity_manager'); 120 $em = $this->client->getContainer()->get('doctrine.orm.entity_manager');
104 $entry = $this->client->getContainer() 121 $entry = $this->client->getContainer()
@@ -122,21 +139,25 @@ class TagRestControllerTest extends WallabagApiTestCase
122 $em->persist($entry); 139 $em->persist($entry);
123 $em->flush(); 140 $em->flush();
124 141
125 $this->client->request('DELETE', '/api/tags/label.json', ['tags' => $tag->getLabel().','.$tag2->getLabel()]); 142 if ($useQueryString) {
143 $this->client->request('DELETE', '/api/tags/label.json?tags=' . $tag->getLabel() . ',' . $tag2->getLabel());
144 } else {
145 $this->client->request('DELETE', '/api/tags/label.json', ['tags' => $tag->getLabel() . ',' . $tag2->getLabel()]);
146 }
126 147
127 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 148 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
128 149
129 $content = json_decode($this->client->getResponse()->getContent(), true); 150 $content = json_decode($this->client->getResponse()->getContent(), true);
130 151
131 $this->assertCount(2, $content); 152 $this->assertCount(2, $content);
132 153
133 $this->assertArrayHasKey('label', $content[0]); 154 $this->assertArrayHasKey('label', $content[0]);
134 $this->assertEquals($tag->getLabel(), $content[0]['label']); 155 $this->assertSame($tag->getLabel(), $content[0]['label']);
135 $this->assertEquals($tag->getSlug(), $content[0]['slug']); 156 $this->assertSame($tag->getSlug(), $content[0]['slug']);
136 157
137 $this->assertArrayHasKey('label', $content[1]); 158 $this->assertArrayHasKey('label', $content[1]);
138 $this->assertEquals($tag2->getLabel(), $content[1]['label']); 159 $this->assertSame($tag2->getLabel(), $content[1]['label']);
139 $this->assertEquals($tag2->getSlug(), $content[1]['slug']); 160 $this->assertSame($tag2->getSlug(), $content[1]['slug']);
140 161
141 $entries = $this->client->getContainer() 162 $entries = $this->client->getContainer()
142 ->get('doctrine.orm.entity_manager') 163 ->get('doctrine.orm.entity_manager')
@@ -157,6 +178,6 @@ class TagRestControllerTest extends WallabagApiTestCase
157 { 178 {
158 $this->client->request('DELETE', '/api/tags/label.json', ['tags' => 'does not exist']); 179 $this->client->request('DELETE', '/api/tags/label.json', ['tags' => 'does not exist']);
159 180
160 $this->assertEquals(404, $this->client->getResponse()->getStatusCode()); 181 $this->assertSame(404, $this->client->getResponse()->getStatusCode());
161 } 182 }
162} 183}
diff --git a/tests/Wallabag/ApiBundle/Controller/UserRestControllerTest.php b/tests/Wallabag/ApiBundle/Controller/UserRestControllerTest.php
new file mode 100644
index 00000000..51fac2bd
--- /dev/null
+++ b/tests/Wallabag/ApiBundle/Controller/UserRestControllerTest.php
@@ -0,0 +1,185 @@
1<?php
2
3namespace Tests\Wallabag\ApiBundle\Controller;
4
5use Tests\Wallabag\ApiBundle\WallabagApiTestCase;
6
7class UserRestControllerTest extends WallabagApiTestCase
8{
9 public function testGetUser()
10 {
11 $this->client->request('GET', '/api/user.json');
12 $this->assertSame(200, $this->client->getResponse()->getStatusCode());
13
14 $content = json_decode($this->client->getResponse()->getContent(), true);
15
16 $this->assertArrayHasKey('id', $content);
17 $this->assertArrayHasKey('email', $content);
18 $this->assertArrayHasKey('name', $content);
19 $this->assertArrayHasKey('username', $content);
20 $this->assertArrayHasKey('created_at', $content);
21 $this->assertArrayHasKey('updated_at', $content);
22
23 $this->assertSame('bigboss@wallabag.org', $content['email']);
24 $this->assertSame('Big boss', $content['name']);
25 $this->assertSame('admin', $content['username']);
26
27 $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
28 }
29
30 public function testGetUserWithoutAuthentication()
31 {
32 $client = static::createClient();
33 $client->request('GET', '/api/user.json');
34 $this->assertSame(401, $client->getResponse()->getStatusCode());
35
36 $content = json_decode($client->getResponse()->getContent(), true);
37
38 $this->assertArrayHasKey('error', $content);
39 $this->assertArrayHasKey('error_description', $content);
40
41 $this->assertSame('access_denied', $content['error']);
42
43 $this->assertSame('application/json', $client->getResponse()->headers->get('Content-Type'));
44 }
45
46 public function testCreateNewUser()
47 {
48 $this->client->getContainer()->get('craue_config')->set('api_user_registration', 1);
49 $this->client->request('PUT', '/api/user.json', [
50 'username' => 'google',
51 'password' => 'googlegoogle',
52 'email' => 'wallabag@google.com',
53 ]);
54
55 $this->assertSame(201, $this->client->getResponse()->getStatusCode());
56
57 $content = json_decode($this->client->getResponse()->getContent(), true);
58
59 $this->assertArrayHasKey('id', $content);
60 $this->assertArrayHasKey('email', $content);
61 $this->assertArrayHasKey('username', $content);
62 $this->assertArrayHasKey('created_at', $content);
63 $this->assertArrayHasKey('updated_at', $content);
64 $this->assertArrayHasKey('default_client', $content);
65
66 $this->assertSame('wallabag@google.com', $content['email']);
67 $this->assertSame('google', $content['username']);
68
69 $this->assertArrayHasKey('client_secret', $content['default_client']);
70 $this->assertArrayHasKey('client_id', $content['default_client']);
71
72 $this->assertSame('Default client', $content['default_client']['name']);
73
74 $this->assertSame('application/json', $this->client->getResponse()->headers->get('Content-Type'));
75
76 $this->client->getContainer()->get('craue_config')->set('api_user_registration', 0);
77 }
78
79 public function testCreateNewUserWithoutAuthentication()
80 {
81 // create a new client instead of using $this->client to be sure client isn't authenticated
82 $client = static::createClient();
83 $client->getContainer()->get('craue_config')->set('api_user_registration', 1);
84 $client->request('PUT', '/api/user.json', [
85 'username' => 'google',
86 'password' => 'googlegoogle',
87 'email' => 'wallabag@google.com',
88 'client_name' => 'My client name !!',
89 ]);
90
91 $this->assertSame(201, $client->getResponse()->getStatusCode());
92
93 $content = json_decode($client->getResponse()->getContent(), true);
94
95 $this->assertArrayHasKey('id', $content);
96 $this->assertArrayHasKey('email', $content);
97 $this->assertArrayHasKey('username', $content);
98 $this->assertArrayHasKey('created_at', $content);
99 $this->assertArrayHasKey('updated_at', $content);
100 $this->assertArrayHasKey('default_client', $content);
101
102 $this->assertSame('wallabag@google.com', $content['email']);
103 $this->assertSame('google', $content['username']);
104
105 $this->assertArrayHasKey('client_secret', $content['default_client']);
106 $this->assertArrayHasKey('client_id', $content['default_client']);
107
108 $this->assertSame('My client name !!', $content['default_client']['name']);
109
110 $this->assertSame('application/json', $client->getResponse()->headers->get('Content-Type'));
111
112 $client->getContainer()->get('craue_config')->set('api_user_registration', 0);
113 }
114
115 public function testCreateNewUserWithExistingEmail()
116 {
117 $client = static::createClient();
118 $client->getContainer()->get('craue_config')->set('api_user_registration', 1);
119 $client->request('PUT', '/api/user.json', [
120 'username' => 'admin',
121 'password' => 'googlegoogle',
122 'email' => 'bigboss@wallabag.org',
123 ]);
124
125 $this->assertSame(400, $client->getResponse()->getStatusCode());
126
127 $content = json_decode($client->getResponse()->getContent(), true);
128
129 $this->assertArrayHasKey('error', $content);
130 $this->assertArrayHasKey('username', $content['error']);
131 $this->assertArrayHasKey('email', $content['error']);
132
133 // $this->assertEquals('fos_user.username.already_used', $content['error']['username'][0]);
134 // $this->assertEquals('fos_user.email.already_used', $content['error']['email'][0]);
135 // This shouldn't be translated ...
136 $this->assertSame('This value is already used.', $content['error']['username'][0]);
137 $this->assertSame('This value is already used.', $content['error']['email'][0]);
138
139 $this->assertSame('application/json', $client->getResponse()->headers->get('Content-Type'));
140
141 $client->getContainer()->get('craue_config')->set('api_user_registration', 0);
142 }
143
144 public function testCreateNewUserWithTooShortPassword()
145 {
146 $client = static::createClient();
147 $client->getContainer()->get('craue_config')->set('api_user_registration', 1);
148 $client->request('PUT', '/api/user.json', [
149 'username' => 'facebook',
150 'password' => 'face',
151 'email' => 'facebook@wallabag.org',
152 ]);
153
154 $this->assertSame(400, $client->getResponse()->getStatusCode());
155
156 $content = json_decode($client->getResponse()->getContent(), true);
157
158 $this->assertArrayHasKey('error', $content);
159 $this->assertArrayHasKey('password', $content['error']);
160
161 $this->assertSame('validator.password_too_short', $content['error']['password'][0]);
162
163 $this->assertSame('application/json', $client->getResponse()->headers->get('Content-Type'));
164
165 $client->getContainer()->get('craue_config')->set('api_user_registration', 0);
166 }
167
168 public function testCreateNewUserWhenRegistrationIsDisabled()
169 {
170 $client = static::createClient();
171 $client->request('PUT', '/api/user.json', [
172 'username' => 'facebook',
173 'password' => 'face',
174 'email' => 'facebook@wallabag.org',
175 ]);
176
177 $this->assertSame(403, $client->getResponse()->getStatusCode());
178
179 $content = json_decode($client->getResponse()->getContent(), true);
180
181 $this->assertArrayHasKey('error', $content);
182
183 $this->assertSame('application/json', $client->getResponse()->headers->get('Content-Type'));
184 }
185}
diff --git a/tests/Wallabag/ApiBundle/Controller/WallabagRestControllerTest.php b/tests/Wallabag/ApiBundle/Controller/WallabagRestControllerTest.php
index c87e58de..ac4d6cdc 100644
--- a/tests/Wallabag/ApiBundle/Controller/WallabagRestControllerTest.php
+++ b/tests/Wallabag/ApiBundle/Controller/WallabagRestControllerTest.php
@@ -8,12 +8,14 @@ class WallabagRestControllerTest extends WallabagApiTestCase
8{ 8{
9 public function testGetVersion() 9 public function testGetVersion()
10 { 10 {
11 $this->client->request('GET', '/api/version'); 11 // create a new client instead of using $this->client to be sure client isn't authenticated
12 $client = static::createClient();
13 $client->request('GET', '/api/version');
12 14
13 $this->assertEquals(200, $this->client->getResponse()->getStatusCode()); 15 $this->assertSame(200, $client->getResponse()->getStatusCode());
14 16
15 $content = json_decode($this->client->getResponse()->getContent(), true); 17 $content = json_decode($client->getResponse()->getContent(), true);
16 18
17 $this->assertEquals($this->client->getContainer()->getParameter('wallabag_core.version'), $content); 19 $this->assertSame($client->getContainer()->getParameter('wallabag_core.version'), $content);
18 } 20 }
19} 21}
diff --git a/tests/Wallabag/ApiBundle/WallabagApiTestCase.php b/tests/Wallabag/ApiBundle/WallabagApiTestCase.php
index cf9b3347..8a188e1c 100644
--- a/tests/Wallabag/ApiBundle/WallabagApiTestCase.php
+++ b/tests/Wallabag/ApiBundle/WallabagApiTestCase.php
@@ -8,7 +8,7 @@ use Symfony\Component\BrowserKit\Cookie;
8abstract class WallabagApiTestCase extends WebTestCase 8abstract class WallabagApiTestCase extends WebTestCase
9{ 9{
10 /** 10 /**
11 * @var Client 11 * @var \Symfony\Bundle\FrameworkBundle\Client
12 */ 12 */
13 protected $client = null; 13 protected $client = null;
14 14
@@ -23,7 +23,7 @@ abstract class WallabagApiTestCase extends WebTestCase
23 } 23 }
24 24
25 /** 25 /**
26 * @return Client 26 * @return \Symfony\Bundle\FrameworkBundle\Client
27 */ 27 */
28 protected function createAuthorizedClient() 28 protected function createAuthorizedClient()
29 { 29 {
@@ -37,10 +37,10 @@ abstract class WallabagApiTestCase extends WebTestCase
37 $firewallName = $container->getParameter('fos_user.firewall_name'); 37 $firewallName = $container->getParameter('fos_user.firewall_name');
38 38
39 $this->user = $userManager->findUserBy(['username' => 'admin']); 39 $this->user = $userManager->findUserBy(['username' => 'admin']);
40 $loginManager->loginUser($firewallName, $this->user); 40 $loginManager->logInUser($firewallName, $this->user);
41 41
42 // save the login token into the session and put it in a cookie 42 // save the login token into the session and put it in a cookie
43 $container->get('session')->set('_security_'.$firewallName, serialize($container->get('security.token_storage')->getToken())); 43 $container->get('session')->set('_security_' . $firewallName, serialize($container->get('security.token_storage')->getToken()));
44 $container->get('session')->save(); 44 $container->get('session')->save();
45 45
46 $session = $container->get('session'); 46 $session = $container->get('session');
diff --git a/tests/Wallabag/CoreBundle/Command/CleanDuplicatesCommandTest.php b/tests/Wallabag/CoreBundle/Command/CleanDuplicatesCommandTest.php
new file mode 100644
index 00000000..38e8dd07
--- /dev/null
+++ b/tests/Wallabag/CoreBundle/Command/CleanDuplicatesCommandTest.php
@@ -0,0 +1,108 @@
1<?php
2
3namespace Tests\Wallabag\CoreBundle\Command;
4
5use Symfony\Bundle\FrameworkBundle\Console\Application;
6use Symfony\Component\Console\Tester\CommandTester;
7use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
8use Wallabag\CoreBundle\Command\CleanDuplicatesCommand;
9use Wallabag\CoreBundle\Entity\Entry;
10
11class CleanDuplicatesCommandTest extends WallabagCoreTestCase
12{
13 public function testRunCleanDuplicates()
14 {
15 $application = new Application($this->getClient()->getKernel());
16 $application->add(new CleanDuplicatesCommand());
17
18 $command = $application->find('wallabag:clean-duplicates');
19
20 $tester = new CommandTester($command);
21 $tester->execute([
22 'command' => $command->getName(),
23 ]);
24
25 $this->assertContains('Cleaning through 3 user accounts', $tester->getDisplay());
26 $this->assertContains('Finished cleaning. 0 duplicates found in total', $tester->getDisplay());
27 }
28
29 public function testRunCleanDuplicatesCommandWithBadUsername()
30 {
31 $application = new Application($this->getClient()->getKernel());
32 $application->add(new CleanDuplicatesCommand());
33
34 $command = $application->find('wallabag:clean-duplicates');
35
36 $tester = new CommandTester($command);
37 $tester->execute([
38 'command' => $command->getName(),
39 'username' => 'unknown',
40 ]);
41
42 $this->assertContains('User "unknown" not found', $tester->getDisplay());
43 }
44
45 public function testRunCleanDuplicatesCommandForUser()
46 {
47 $application = new Application($this->getClient()->getKernel());
48 $application->add(new CleanDuplicatesCommand());
49
50 $command = $application->find('wallabag:clean-duplicates');
51
52 $tester = new CommandTester($command);
53 $tester->execute([
54 'command' => $command->getName(),
55 'username' => 'admin',
56 ]);
57
58 $this->assertContains('Cleaned 0 duplicates for user admin', $tester->getDisplay());
59 }
60
61 public function testDuplicate()
62 {
63 $url = 'http://www.lemonde.fr/sport/visuel/2017/05/05/rondelle-prison-blanchissage-comprendre-le-hockey-sur-glace_5122587_3242.html';
64 $client = $this->getClient();
65 $em = $client->getContainer()->get('doctrine.orm.entity_manager');
66
67 $this->logInAs('admin');
68
69 $nbEntries = $em->getRepository('WallabagCoreBundle:Entry')->findAllByUrlAndUserId($url, $this->getLoggedInUserId());
70 $this->assertCount(0, $nbEntries);
71
72 $user = $em->getRepository('WallabagUserBundle:User')->findOneById($this->getLoggedInUserId());
73
74 $entry1 = new Entry($user);
75 $entry1->setUrl($url);
76
77 $entry2 = new Entry($user);
78 $entry2->setUrl($url);
79
80 $em->persist($entry1);
81 $em->persist($entry2);
82
83 $em->flush();
84
85 $nbEntries = $em->getRepository('WallabagCoreBundle:Entry')->findAllByUrlAndUserId($url, $this->getLoggedInUserId());
86 $this->assertCount(2, $nbEntries);
87
88 $application = new Application($this->getClient()->getKernel());
89 $application->add(new CleanDuplicatesCommand());
90
91 $command = $application->find('wallabag:clean-duplicates');
92
93 $tester = new CommandTester($command);
94 $tester->execute([
95 'command' => $command->getName(),
96 'username' => 'admin',
97 ]);
98
99 $this->assertContains('Cleaned 1 duplicates for user admin', $tester->getDisplay());
100
101 $nbEntries = $em->getRepository('WallabagCoreBundle:Entry')->findAllByUrlAndUserId($url, $this->getLoggedInUserId());
102 $this->assertCount(1, $nbEntries);
103
104 $query = $em->createQuery('DELETE FROM Wallabag\CoreBundle\Entity\Entry e WHERE e.url = :url');
105 $query->setParameter('url', $url);
106 $query->execute();
107 }
108}
diff --git a/tests/Wallabag/CoreBundle/Command/ExportCommandTest.php b/tests/Wallabag/CoreBundle/Command/ExportCommandTest.php
index 6798c5d7..210b2ab6 100644
--- a/tests/Wallabag/CoreBundle/Command/ExportCommandTest.php
+++ b/tests/Wallabag/CoreBundle/Command/ExportCommandTest.php
@@ -4,13 +4,13 @@ namespace Tests\Wallabag\CoreBundle\Command;
4 4
5use Symfony\Bundle\FrameworkBundle\Console\Application; 5use Symfony\Bundle\FrameworkBundle\Console\Application;
6use Symfony\Component\Console\Tester\CommandTester; 6use Symfony\Component\Console\Tester\CommandTester;
7use Wallabag\CoreBundle\Command\ExportCommand;
8use Tests\Wallabag\CoreBundle\WallabagCoreTestCase; 7use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
8use Wallabag\CoreBundle\Command\ExportCommand;
9 9
10class ExportCommandTest extends WallabagCoreTestCase 10class ExportCommandTest extends WallabagCoreTestCase
11{ 11{
12 /** 12 /**
13 * @expectedException Symfony\Component\Console\Exception\RuntimeException 13 * @expectedException \Symfony\Component\Console\Exception\RuntimeException
14 * @expectedExceptionMessage Not enough arguments (missing: "username") 14 * @expectedExceptionMessage Not enough arguments (missing: "username")
15 */ 15 */
16 public function testExportCommandWithoutUsername() 16 public function testExportCommandWithoutUsername()
@@ -55,7 +55,8 @@ class ExportCommandTest extends WallabagCoreTestCase
55 'username' => 'admin', 55 'username' => 'admin',
56 ]); 56 ]);
57 57
58 $this->assertContains('Exporting 6 entrie(s) for user « admin »... Done', $tester->getDisplay()); 58 $this->assertContains('Exporting 5 entrie(s) for user admin...', $tester->getDisplay());
59 $this->assertContains('Done', $tester->getDisplay());
59 $this->assertFileExists('admin-export.json'); 60 $this->assertFileExists('admin-export.json');
60 } 61 }
61 62
@@ -70,7 +71,7 @@ class ExportCommandTest extends WallabagCoreTestCase
70 $tester->execute([ 71 $tester->execute([
71 'command' => $command->getName(), 72 'command' => $command->getName(),
72 'username' => 'admin', 73 'username' => 'admin',
73 'filepath' => 'specialexport.json' 74 'filepath' => 'specialexport.json',
74 ]); 75 ]);
75 76
76 $this->assertFileExists('specialexport.json'); 77 $this->assertFileExists('specialexport.json');
diff --git a/tests/Wallabag/CoreBundle/Command/InstallCommandTest.php b/tests/Wallabag/CoreBundle/Command/InstallCommandTest.php
index 1bfd41d5..f684a206 100644
--- a/tests/Wallabag/CoreBundle/Command/InstallCommandTest.php
+++ b/tests/Wallabag/CoreBundle/Command/InstallCommandTest.php
@@ -2,15 +2,18 @@
2 2
3namespace Tests\Wallabag\CoreBundle\Command; 3namespace Tests\Wallabag\CoreBundle\Command;
4 4
5use DAMA\DoctrineTestBundle\Doctrine\DBAL\StaticDriver;
5use Doctrine\Bundle\DoctrineBundle\Command\CreateDatabaseDoctrineCommand; 6use Doctrine\Bundle\DoctrineBundle\Command\CreateDatabaseDoctrineCommand;
6use Doctrine\Bundle\DoctrineBundle\Command\DropDatabaseDoctrineCommand; 7use Doctrine\Bundle\DoctrineBundle\Command\DropDatabaseDoctrineCommand;
8use Doctrine\DBAL\Platforms\PostgreSqlPlatform;
9use Doctrine\DBAL\Platforms\SqlitePlatform;
7use Symfony\Bundle\FrameworkBundle\Console\Application; 10use Symfony\Bundle\FrameworkBundle\Console\Application;
8use Symfony\Component\Console\Input\ArrayInput; 11use Symfony\Component\Console\Input\ArrayInput;
9use Symfony\Component\Console\Output\NullOutput; 12use Symfony\Component\Console\Output\NullOutput;
10use Symfony\Component\Console\Tester\CommandTester; 13use Symfony\Component\Console\Tester\CommandTester;
11use Wallabag\CoreBundle\Command\InstallCommand;
12use Tests\Wallabag\CoreBundle\Mock\InstallCommandMock; 14use Tests\Wallabag\CoreBundle\Mock\InstallCommandMock;
13use Tests\Wallabag\CoreBundle\WallabagCoreTestCase; 15use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
16use Wallabag\CoreBundle\Command\InstallCommand;
14 17
15class InstallCommandTest extends WallabagCoreTestCase 18class InstallCommandTest extends WallabagCoreTestCase
16{ 19{
@@ -18,7 +21,9 @@ class InstallCommandTest extends WallabagCoreTestCase
18 { 21 {
19 parent::setUp(); 22 parent::setUp();
20 23
21 if ($this->getClient()->getContainer()->get('doctrine')->getConnection()->getDriver() instanceof \Doctrine\DBAL\Driver\PDOPgSql\Driver) { 24 /** @var \Doctrine\DBAL\Connection $connection */
25 $connection = $this->getClient()->getContainer()->get('doctrine')->getConnection();
26 if ($connection->getDatabasePlatform() instanceof PostgreSqlPlatform) {
22 /* 27 /*
23 * LOG: statement: CREATE DATABASE "wallabag" 28 * LOG: statement: CREATE DATABASE "wallabag"
24 * ERROR: source database "template1" is being accessed by other users 29 * ERROR: source database "template1" is being accessed by other users
@@ -30,34 +35,44 @@ class InstallCommandTest extends WallabagCoreTestCase
30 */ 35 */
31 $this->markTestSkipped('PostgreSQL spotted: can\'t find a good way to drop current database, skipping.'); 36 $this->markTestSkipped('PostgreSQL spotted: can\'t find a good way to drop current database, skipping.');
32 } 37 }
33 }
34 38
35 /** 39 if ($connection->getDatabasePlatform() instanceof SqlitePlatform) {
36 * Ensure next tests will have a clean database. 40 // Environnement variable useful only for sqlite to avoid the error "attempt to write a readonly database"
37 */ 41 // We can't define always this environnement variable because pdo_mysql seems to use it
38 public static function tearDownAfterClass() 42 // and we have the error:
39 { 43 // SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax;
40 $application = new Application(static::$kernel); 44 // check the manual that corresponds to your MariaDB server version for the right syntax to use
41 $application->setAutoExit(false); 45 // near '/tmp/wallabag_testTYj1kp' at line 1
46 $databasePath = tempnam(sys_get_temp_dir(), 'wallabag_test');
47 putenv("TEST_DATABASE_PATH=$databasePath");
48
49 // The environnement has been changed, recreate the client in order to update connection
50 parent::setUp();
51 }
42 52
43 $application->run(new ArrayInput([ 53 // disable doctrine-test-bundle
44 'command' => 'doctrine:schema:drop', 54 StaticDriver::setKeepStaticConnections(false);
45 '--no-interaction' => true,
46 '--force' => true,
47 '--env' => 'test',
48 ]), new NullOutput());
49 55
50 $application->run(new ArrayInput([ 56 $this->resetDatabase($this->getClient());
51 'command' => 'doctrine:schema:create', 57 }
52 '--no-interaction' => true,
53 '--env' => 'test',
54 ]), new NullOutput());
55 58
56 $application->run(new ArrayInput([ 59 public function tearDown()
57 'command' => 'doctrine:fixtures:load', 60 {
58 '--no-interaction' => true, 61 $databasePath = getenv('TEST_DATABASE_PATH');
59 '--env' => 'test', 62 // Remove variable environnement
60 ]), new NullOutput()); 63 putenv('TEST_DATABASE_PATH');
64 if ($databasePath && file_exists($databasePath)) {
65 unlink($databasePath);
66 } else {
67 // Create a new client to avoid the error:
68 // Transaction commit failed because the transaction has been marked for rollback only.
69 $client = static::createClient();
70 $this->resetDatabase($client);
71 }
72
73 // enable doctrine-test-bundle
74 StaticDriver::setKeepStaticConnections(true);
75 parent::tearDown();
61 } 76 }
62 77
63 public function testRunInstallCommand() 78 public function testRunInstallCommand()
@@ -67,18 +82,14 @@ class InstallCommandTest extends WallabagCoreTestCase
67 82
68 $command = $application->find('wallabag:install'); 83 $command = $application->find('wallabag:install');
69 84
70 // We mock the QuestionHelper
71 $question = $this->getMockBuilder('Symfony\Component\Console\Helper\QuestionHelper')
72 ->disableOriginalConstructor()
73 ->getMock();
74 $question->expects($this->any())
75 ->method('ask')
76 ->will($this->returnValue('yes_'.uniqid('', true)));
77
78 // We override the standard helper with our mock
79 $command->getHelperSet()->set($question, 'question');
80
81 $tester = new CommandTester($command); 85 $tester = new CommandTester($command);
86 $tester->setInputs([
87 'y', // dropping database
88 'y', // create super admin
89 'username_' . uniqid('', true), // username
90 'password_' . uniqid('', true), // password
91 'email_' . uniqid('', true) . '@wallabag.it', // email
92 ]);
82 $tester->execute([ 93 $tester->execute([
83 'command' => $command->getName(), 94 'command' => $command->getName(),
84 ]); 95 ]);
@@ -87,6 +98,7 @@ class InstallCommandTest extends WallabagCoreTestCase
87 $this->assertContains('Setting up database.', $tester->getDisplay()); 98 $this->assertContains('Setting up database.', $tester->getDisplay());
88 $this->assertContains('Administration setup.', $tester->getDisplay()); 99 $this->assertContains('Administration setup.', $tester->getDisplay());
89 $this->assertContains('Config setup.', $tester->getDisplay()); 100 $this->assertContains('Config setup.', $tester->getDisplay());
101 $this->assertContains('Run migrations.', $tester->getDisplay());
90 } 102 }
91 103
92 public function testRunInstallCommandWithReset() 104 public function testRunInstallCommandWithReset()
@@ -96,18 +108,13 @@ class InstallCommandTest extends WallabagCoreTestCase
96 108
97 $command = $application->find('wallabag:install'); 109 $command = $application->find('wallabag:install');
98 110
99 // We mock the QuestionHelper
100 $question = $this->getMockBuilder('Symfony\Component\Console\Helper\QuestionHelper')
101 ->disableOriginalConstructor()
102 ->getMock();
103 $question->expects($this->any())
104 ->method('ask')
105 ->will($this->returnValue('yes_'.uniqid('', true)));
106
107 // We override the standard helper with our mock
108 $command->getHelperSet()->set($question, 'question');
109
110 $tester = new CommandTester($command); 111 $tester = new CommandTester($command);
112 $tester->setInputs([
113 'y', // create super admin
114 'username_' . uniqid('', true), // username
115 'password_' . uniqid('', true), // password
116 'email_' . uniqid('', true) . '@wallabag.it', // email
117 ]);
111 $tester->execute([ 118 $tester->execute([
112 'command' => $command->getName(), 119 'command' => $command->getName(),
113 '--reset' => true, 120 '--reset' => true,
@@ -115,19 +122,20 @@ class InstallCommandTest extends WallabagCoreTestCase
115 122
116 $this->assertContains('Checking system requirements.', $tester->getDisplay()); 123 $this->assertContains('Checking system requirements.', $tester->getDisplay());
117 $this->assertContains('Setting up database.', $tester->getDisplay()); 124 $this->assertContains('Setting up database.', $tester->getDisplay());
118 $this->assertContains('Droping database, creating database and schema, clearing the cache', $tester->getDisplay()); 125 $this->assertContains('Dropping database, creating database and schema, clearing the cache', $tester->getDisplay());
119 $this->assertContains('Administration setup.', $tester->getDisplay()); 126 $this->assertContains('Administration setup.', $tester->getDisplay());
120 $this->assertContains('Config setup.', $tester->getDisplay()); 127 $this->assertContains('Config setup.', $tester->getDisplay());
128 $this->assertContains('Run migrations.', $tester->getDisplay());
121 129
122 // we force to reset everything 130 // we force to reset everything
123 $this->assertContains('Droping database, creating database and schema, clearing the cache', $tester->getDisplay()); 131 $this->assertContains('Dropping database, creating database and schema, clearing the cache', $tester->getDisplay());
124 } 132 }
125 133
126 public function testRunInstallCommandWithDatabaseRemoved() 134 public function testRunInstallCommandWithDatabaseRemoved()
127 { 135 {
128 // skipped SQLite check when database is removed because while testing for the connection, 136 // skipped SQLite check when database is removed because while testing for the connection,
129 // the driver will create the file (so the database) before testing if database exist 137 // the driver will create the file (so the database) before testing if database exist
130 if ($this->getClient()->getContainer()->get('doctrine')->getConnection()->getDriver() instanceof \Doctrine\DBAL\Driver\PDOSqlite\Driver) { 138 if ($this->getClient()->getContainer()->get('doctrine')->getConnection()->getDatabasePlatform() instanceof \Doctrine\DBAL\Platforms\SqlitePlatform) {
131 $this->markTestSkipped('SQLite spotted: can\'t test with database removed.'); 139 $this->markTestSkipped('SQLite spotted: can\'t test with database removed.');
132 } 140 }
133 141
@@ -148,18 +156,13 @@ class InstallCommandTest extends WallabagCoreTestCase
148 156
149 $command = $application->find('wallabag:install'); 157 $command = $application->find('wallabag:install');
150 158
151 // We mock the QuestionHelper
152 $question = $this->getMockBuilder('Symfony\Component\Console\Helper\QuestionHelper')
153 ->disableOriginalConstructor()
154 ->getMock();
155 $question->expects($this->any())
156 ->method('ask')
157 ->will($this->returnValue('yes_'.uniqid('', true)));
158
159 // We override the standard helper with our mock
160 $command->getHelperSet()->set($question, 'question');
161
162 $tester = new CommandTester($command); 159 $tester = new CommandTester($command);
160 $tester->setInputs([
161 'y', // create super admin
162 'username_' . uniqid('', true), // username
163 'password_' . uniqid('', true), // password
164 'email_' . uniqid('', true) . '@wallabag.it', // email
165 ]);
163 $tester->execute([ 166 $tester->execute([
164 'command' => $command->getName(), 167 'command' => $command->getName(),
165 ]); 168 ]);
@@ -168,6 +171,7 @@ class InstallCommandTest extends WallabagCoreTestCase
168 $this->assertContains('Setting up database.', $tester->getDisplay()); 171 $this->assertContains('Setting up database.', $tester->getDisplay());
169 $this->assertContains('Administration setup.', $tester->getDisplay()); 172 $this->assertContains('Administration setup.', $tester->getDisplay());
170 $this->assertContains('Config setup.', $tester->getDisplay()); 173 $this->assertContains('Config setup.', $tester->getDisplay());
174 $this->assertContains('Run migrations.', $tester->getDisplay());
171 175
172 // the current database doesn't already exist 176 // the current database doesn't already exist
173 $this->assertContains('Creating database and schema, clearing the cache', $tester->getDisplay()); 177 $this->assertContains('Creating database and schema, clearing the cache', $tester->getDisplay());
@@ -180,23 +184,12 @@ class InstallCommandTest extends WallabagCoreTestCase
180 184
181 $command = $application->find('wallabag:install'); 185 $command = $application->find('wallabag:install');
182 186
183 // We mock the QuestionHelper
184 $question = $this->getMockBuilder('Symfony\Component\Console\Helper\QuestionHelper')
185 ->disableOriginalConstructor()
186 ->getMock();
187
188 $question->expects($this->exactly(3))
189 ->method('ask')
190 ->will($this->onConsecutiveCalls(
191 false, // don't want to reset the entire database
192 true, // do want to reset the schema
193 false // don't want to create a new user
194 ));
195
196 // We override the standard helper with our mock
197 $command->getHelperSet()->set($question, 'question');
198
199 $tester = new CommandTester($command); 187 $tester = new CommandTester($command);
188 $tester->setInputs([
189 'n', // don't want to reset the entire database
190 'y', // do want to reset the schema
191 'n', // don't want to create a new user
192 ]);
200 $tester->execute([ 193 $tester->execute([
201 'command' => $command->getName(), 194 'command' => $command->getName(),
202 ]); 195 ]);
@@ -205,8 +198,9 @@ class InstallCommandTest extends WallabagCoreTestCase
205 $this->assertContains('Setting up database.', $tester->getDisplay()); 198 $this->assertContains('Setting up database.', $tester->getDisplay());
206 $this->assertContains('Administration setup.', $tester->getDisplay()); 199 $this->assertContains('Administration setup.', $tester->getDisplay());
207 $this->assertContains('Config setup.', $tester->getDisplay()); 200 $this->assertContains('Config setup.', $tester->getDisplay());
201 $this->assertContains('Run migrations.', $tester->getDisplay());
208 202
209 $this->assertContains('Droping schema and creating schema', $tester->getDisplay()); 203 $this->assertContains('Dropping schema and creating schema', $tester->getDisplay());
210 } 204 }
211 205
212 public function testRunInstallCommandChooseNothing() 206 public function testRunInstallCommandChooseNothing()
@@ -235,22 +229,11 @@ class InstallCommandTest extends WallabagCoreTestCase
235 229
236 $command = $application->find('wallabag:install'); 230 $command = $application->find('wallabag:install');
237 231
238 // We mock the QuestionHelper
239 $question = $this->getMockBuilder('Symfony\Component\Console\Helper\QuestionHelper')
240 ->disableOriginalConstructor()
241 ->getMock();
242
243 $question->expects($this->exactly(2))
244 ->method('ask')
245 ->will($this->onConsecutiveCalls(
246 false, // don't want to reset the entire database
247 false // don't want to create a new user
248 ));
249
250 // We override the standard helper with our mock
251 $command->getHelperSet()->set($question, 'question');
252
253 $tester = new CommandTester($command); 232 $tester = new CommandTester($command);
233 $tester->setInputs([
234 'n', // don't want to reset the entire database
235 'n', // don't want to create a new user
236 ]);
254 $tester->execute([ 237 $tester->execute([
255 'command' => $command->getName(), 238 'command' => $command->getName(),
256 ]); 239 ]);
@@ -259,6 +242,7 @@ class InstallCommandTest extends WallabagCoreTestCase
259 $this->assertContains('Setting up database.', $tester->getDisplay()); 242 $this->assertContains('Setting up database.', $tester->getDisplay());
260 $this->assertContains('Administration setup.', $tester->getDisplay()); 243 $this->assertContains('Administration setup.', $tester->getDisplay());
261 $this->assertContains('Config setup.', $tester->getDisplay()); 244 $this->assertContains('Config setup.', $tester->getDisplay());
245 $this->assertContains('Run migrations.', $tester->getDisplay());
262 246
263 $this->assertContains('Creating schema', $tester->getDisplay()); 247 $this->assertContains('Creating schema', $tester->getDisplay());
264 } 248 }
@@ -270,26 +254,17 @@ class InstallCommandTest extends WallabagCoreTestCase
270 254
271 $command = $application->find('wallabag:install'); 255 $command = $application->find('wallabag:install');
272 256
273 // We mock the QuestionHelper
274 $question = $this->getMockBuilder('Symfony\Component\Console\Helper\QuestionHelper')
275 ->disableOriginalConstructor()
276 ->getMock();
277 $question->expects($this->any())
278 ->method('ask')
279 ->will($this->returnValue('yes_'.uniqid('', true)));
280
281 // We override the standard helper with our mock
282 $command->getHelperSet()->set($question, 'question');
283
284 $tester = new CommandTester($command); 257 $tester = new CommandTester($command);
285 $tester->execute([ 258 $tester->execute([
286 'command' => $command->getName(), 259 'command' => $command->getName(),
287 '--no-interaction' => true, 260 ], [
261 'interactive' => false,
288 ]); 262 ]);
289 263
290 $this->assertContains('Checking system requirements.', $tester->getDisplay()); 264 $this->assertContains('Checking system requirements.', $tester->getDisplay());
291 $this->assertContains('Setting up database.', $tester->getDisplay()); 265 $this->assertContains('Setting up database.', $tester->getDisplay());
292 $this->assertContains('Administration setup.', $tester->getDisplay()); 266 $this->assertContains('Administration setup.', $tester->getDisplay());
293 $this->assertContains('Config setup.', $tester->getDisplay()); 267 $this->assertContains('Config setup.', $tester->getDisplay());
268 $this->assertContains('Run migrations.', $tester->getDisplay());
294 } 269 }
295} 270}
diff --git a/tests/Wallabag/CoreBundle/Command/ListUserCommandTest.php b/tests/Wallabag/CoreBundle/Command/ListUserCommandTest.php
new file mode 100644
index 00000000..9068cf59
--- /dev/null
+++ b/tests/Wallabag/CoreBundle/Command/ListUserCommandTest.php
@@ -0,0 +1,75 @@
1<?php
2
3namespace Tests\Wallabag\CoreBundle\Command;
4
5use Symfony\Bundle\FrameworkBundle\Console\Application;
6use Symfony\Component\Console\Tester\CommandTester;
7use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
8use Wallabag\CoreBundle\Command\ListUserCommand;
9
10class ListUserCommandTest extends WallabagCoreTestCase
11{
12 public function testRunListUserCommand()
13 {
14 $application = new Application($this->getClient()->getKernel());
15 $application->add(new ListUserCommand());
16
17 $command = $application->find('wallabag:user:list');
18
19 $tester = new CommandTester($command);
20 $tester->execute([
21 'command' => $command->getName(),
22 ]);
23
24 $this->assertContains('3/3 user(s) displayed.', $tester->getDisplay());
25 }
26
27 public function testRunListUserCommandWithLimit()
28 {
29 $application = new Application($this->getClient()->getKernel());
30 $application->add(new ListUserCommand());
31
32 $command = $application->find('wallabag:user:list');
33
34 $tester = new CommandTester($command);
35 $tester->execute([
36 'command' => $command->getName(),
37 '--limit' => 2,
38 ]);
39
40 $this->assertContains('2/3 user(s) displayed.', $tester->getDisplay());
41 }
42
43 public function testRunListUserCommandWithSearch()
44 {
45 $application = new Application($this->getClient()->getKernel());
46 $application->add(new ListUserCommand());
47
48 $command = $application->find('wallabag:user:list');
49
50 $tester = new CommandTester($command);
51 $tester->execute([
52 'command' => $command->getName(),
53 'search' => 'boss',
54 ]);
55
56 $this->assertContains('1/3 (filtered) user(s) displayed.', $tester->getDisplay());
57 }
58
59 public function testRunListUserCommandWithSearchAndLimit()
60 {
61 $application = new Application($this->getClient()->getKernel());
62 $application->add(new ListUserCommand());
63
64 $command = $application->find('wallabag:user:list');
65
66 $tester = new CommandTester($command);
67 $tester->execute([
68 'command' => $command->getName(),
69 'search' => 'bo',
70 '--limit' => 1,
71 ]);
72
73 $this->assertContains('1/3 (filtered) user(s) displayed.', $tester->getDisplay());
74 }
75}
diff --git a/tests/Wallabag/CoreBundle/Command/ReloadEntryCommandTest.php b/tests/Wallabag/CoreBundle/Command/ReloadEntryCommandTest.php
new file mode 100644
index 00000000..63c068b4
--- /dev/null
+++ b/tests/Wallabag/CoreBundle/Command/ReloadEntryCommandTest.php
@@ -0,0 +1,115 @@
1<?php
2
3namespace Tests\Wallabag\CoreBundle\Command;
4
5use Symfony\Bundle\FrameworkBundle\Console\Application;
6use Symfony\Component\Console\Tester\CommandTester;
7use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
8use Wallabag\CoreBundle\Command\ReloadEntryCommand;
9use Wallabag\CoreBundle\Entity\Entry;
10
11class ReloadEntryCommandTest extends WallabagCoreTestCase
12{
13 public $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';
14
15 /**
16 * @var entry
17 */
18 public $adminEntry;
19
20 /**
21 * @var Entry
22 */
23 public $bobEntry;
24
25 public function setUp()
26 {
27 parent::setUp();
28
29 $userRepository = $this->getClient()->getContainer()->get('wallabag_user.user_repository');
30
31 $user = $userRepository->findOneByUserName('admin');
32 $this->adminEntry = new Entry($user);
33 $this->adminEntry->setUrl($this->url);
34 $this->adminEntry->setTitle('title foo');
35 $this->adminEntry->setContent('');
36 $this->getEntityManager()->persist($this->adminEntry);
37
38 $user = $userRepository->findOneByUserName('bob');
39 $this->bobEntry = new Entry($user);
40 $this->bobEntry->setUrl($this->url);
41 $this->bobEntry->setTitle('title foo');
42 $this->bobEntry->setContent('');
43 $this->getEntityManager()->persist($this->bobEntry);
44
45 $this->getEntityManager()->flush();
46 }
47
48 public function testRunReloadEntryCommand()
49 {
50 $application = new Application($this->getClient()->getKernel());
51 $application->add(new ReloadEntryCommand());
52
53 $command = $application->find('wallabag:entry:reload');
54 $tester = new CommandTester($command);
55 $tester->execute([
56 'command' => $command->getName(),
57 ], [
58 'interactive' => false,
59 ]);
60
61 $reloadedEntries = $this->getClient()
62 ->getContainer()
63 ->get('wallabag_core.entry_repository')
64 ->findById([$this->adminEntry->getId(), $this->bobEntry->getId()]);
65
66 foreach ($reloadedEntries as $reloadedEntry) {
67 $this->assertNotEmpty($reloadedEntry->getContent());
68 }
69
70 $this->assertContains('Done', $tester->getDisplay());
71 }
72
73 public function testRunReloadEntryWithUsernameCommand()
74 {
75 $application = new Application($this->getClient()->getKernel());
76 $application->add(new ReloadEntryCommand());
77
78 $command = $application->find('wallabag:entry:reload');
79 $tester = new CommandTester($command);
80 $tester->execute([
81 'command' => $command->getName(),
82 'username' => 'admin',
83 ], [
84 'interactive' => false,
85 ]);
86
87 $entryRepository = $this->getClient()->getContainer()->get('wallabag_core.entry_repository');
88
89 $reloadedAdminEntry = $entryRepository->find($this->adminEntry->getId());
90 $this->assertNotEmpty($reloadedAdminEntry->getContent());
91
92 $reloadedBobEntry = $entryRepository->find($this->bobEntry->getId());
93 $this->assertEmpty($reloadedBobEntry->getContent());
94
95 $this->assertContains('Done', $tester->getDisplay());
96 }
97
98 public function testRunReloadEntryWithoutEntryCommand()
99 {
100 $application = new Application($this->getClient()->getKernel());
101 $application->add(new ReloadEntryCommand());
102
103 $command = $application->find('wallabag:entry:reload');
104 $tester = new CommandTester($command);
105 $tester->execute([
106 'command' => $command->getName(),
107 'username' => 'empty',
108 ], [
109 'interactive' => false,
110 ]);
111
112 $this->assertContains('No entry to reload', $tester->getDisplay());
113 $this->assertNotContains('Done', $tester->getDisplay());
114 }
115}
diff --git a/tests/Wallabag/CoreBundle/Command/ShowUserCommandTest.php b/tests/Wallabag/CoreBundle/Command/ShowUserCommandTest.php
new file mode 100644
index 00000000..9b34f2a0
--- /dev/null
+++ b/tests/Wallabag/CoreBundle/Command/ShowUserCommandTest.php
@@ -0,0 +1,93 @@
1<?php
2
3namespace Tests\Wallabag\CoreBundle\Command;
4
5use Symfony\Bundle\FrameworkBundle\Console\Application;
6use Symfony\Component\Console\Tester\CommandTester;
7use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
8use Wallabag\CoreBundle\Command\ShowUserCommand;
9use Wallabag\UserBundle\Entity\User;
10
11class ShowUserCommandTest extends WallabagCoreTestCase
12{
13 /**
14 * @expectedException \Symfony\Component\Console\Exception\RuntimeException
15 * @expectedExceptionMessage Not enough arguments
16 */
17 public function testRunShowUserCommandWithoutUsername()
18 {
19 $application = new Application($this->getClient()->getKernel());
20 $application->add(new ShowUserCommand());
21
22 $command = $application->find('wallabag:user:show');
23
24 $tester = new CommandTester($command);
25 $tester->execute([
26 'command' => $command->getName(),
27 ]);
28 }
29
30 public function testRunShowUserCommandWithBadUsername()
31 {
32 $application = new Application($this->getClient()->getKernel());
33 $application->add(new ShowUserCommand());
34
35 $command = $application->find('wallabag:user:show');
36
37 $tester = new CommandTester($command);
38 $tester->execute([
39 'command' => $command->getName(),
40 'username' => 'unknown',
41 ]);
42
43 $this->assertContains('User "unknown" not found', $tester->getDisplay());
44 }
45
46 public function testRunShowUserCommandForUser()
47 {
48 $application = new Application($this->getClient()->getKernel());
49 $application->add(new ShowUserCommand());
50
51 $command = $application->find('wallabag:user:show');
52
53 $tester = new CommandTester($command);
54 $tester->execute([
55 'command' => $command->getName(),
56 'username' => 'admin',
57 ]);
58
59 $this->assertContains('Username: admin', $tester->getDisplay());
60 $this->assertContains('Email: bigboss@wallabag.org', $tester->getDisplay());
61 $this->assertContains('Display name: Big boss', $tester->getDisplay());
62 $this->assertContains('2FA activated: no', $tester->getDisplay());
63 }
64
65 public function testShowUser()
66 {
67 $client = $this->getClient();
68 $em = $client->getContainer()->get('doctrine.orm.entity_manager');
69
70 $this->logInAs('admin');
71
72 /** @var User $user */
73 $user = $em->getRepository('WallabagUserBundle:User')->findOneById($this->getLoggedInUserId());
74
75 $user->setName('Bug boss');
76 $em->persist($user);
77
78 $em->flush();
79
80 $application = new Application($this->getClient()->getKernel());
81 $application->add(new ShowUserCommand());
82
83 $command = $application->find('wallabag:user:show');
84
85 $tester = new CommandTester($command);
86 $tester->execute([
87 'command' => $command->getName(),
88 'username' => 'admin',
89 ]);
90
91 $this->assertContains('Display name: Bug boss', $tester->getDisplay());
92 }
93}
diff --git a/tests/Wallabag/CoreBundle/Command/TagAllCommandTest.php b/tests/Wallabag/CoreBundle/Command/TagAllCommandTest.php
index ec31708f..b1e56a10 100644
--- a/tests/Wallabag/CoreBundle/Command/TagAllCommandTest.php
+++ b/tests/Wallabag/CoreBundle/Command/TagAllCommandTest.php
@@ -4,13 +4,13 @@ namespace Tests\Wallabag\CoreBundle\Command;
4 4
5use Symfony\Bundle\FrameworkBundle\Console\Application; 5use Symfony\Bundle\FrameworkBundle\Console\Application;
6use Symfony\Component\Console\Tester\CommandTester; 6use Symfony\Component\Console\Tester\CommandTester;
7use Wallabag\CoreBundle\Command\TagAllCommand;
8use Tests\Wallabag\CoreBundle\WallabagCoreTestCase; 7use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
8use Wallabag\CoreBundle\Command\TagAllCommand;
9 9
10class TagAllCommandTest extends WallabagCoreTestCase 10class TagAllCommandTest extends WallabagCoreTestCase
11{ 11{
12 /** 12 /**
13 * @expectedException Symfony\Component\Console\Exception\RuntimeException 13 * @expectedException \Symfony\Component\Console\Exception\RuntimeException
14 * @expectedExceptionMessage Not enough arguments (missing: "username") 14 * @expectedExceptionMessage Not enough arguments (missing: "username")
15 */ 15 */
16 public function testRunTagAllCommandWithoutUsername() 16 public function testRunTagAllCommandWithoutUsername()
@@ -55,6 +55,7 @@ class TagAllCommandTest extends WallabagCoreTestCase
55 'username' => 'admin', 55 'username' => 'admin',
56 ]); 56 ]);
57 57
58 $this->assertContains('Tagging entries for user « admin »... Done', $tester->getDisplay()); 58 $this->assertContains('Tagging entries for user admin...', $tester->getDisplay());
59 $this->assertContains('Done', $tester->getDisplay());
59 } 60 }
60} 61}
diff --git a/tests/Wallabag/CoreBundle/Controller/ConfigControllerTest.php b/tests/Wallabag/CoreBundle/Controller/ConfigControllerTest.php
index beb0598a..e4bf0998 100644
--- a/tests/Wallabag/CoreBundle/Controller/ConfigControllerTest.php
+++ b/tests/Wallabag/CoreBundle/Controller/ConfigControllerTest.php
@@ -3,11 +3,11 @@
3namespace tests\Wallabag\CoreBundle\Controller; 3namespace tests\Wallabag\CoreBundle\Controller;
4 4
5use Tests\Wallabag\CoreBundle\WallabagCoreTestCase; 5use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
6use Wallabag\AnnotationBundle\Entity\Annotation;
6use Wallabag\CoreBundle\Entity\Config; 7use Wallabag\CoreBundle\Entity\Config;
7use Wallabag\UserBundle\Entity\User;
8use Wallabag\CoreBundle\Entity\Entry; 8use Wallabag\CoreBundle\Entity\Entry;
9use Wallabag\CoreBundle\Entity\Tag; 9use Wallabag\CoreBundle\Entity\Tag;
10use Wallabag\AnnotationBundle\Entity\Annotation; 10use Wallabag\UserBundle\Entity\User;
11 11
12class ConfigControllerTest extends WallabagCoreTestCase 12class ConfigControllerTest extends WallabagCoreTestCase
13{ 13{
@@ -17,7 +17,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
17 17
18 $client->request('GET', '/new'); 18 $client->request('GET', '/new');
19 19
20 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 20 $this->assertSame(302, $client->getResponse()->getStatusCode());
21 $this->assertContains('login', $client->getResponse()->headers->get('location')); 21 $this->assertContains('login', $client->getResponse()->headers->get('location'));
22 } 22 }
23 23
@@ -28,7 +28,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
28 28
29 $crawler = $client->request('GET', '/config'); 29 $crawler = $client->request('GET', '/config');
30 30
31 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 31 $this->assertSame(200, $client->getResponse()->getStatusCode());
32 32
33 $this->assertCount(1, $crawler->filter('button[id=config_save]')); 33 $this->assertCount(1, $crawler->filter('button[id=config_save]'));
34 $this->assertCount(1, $crawler->filter('button[id=change_passwd_save]')); 34 $this->assertCount(1, $crawler->filter('button[id=change_passwd_save]'));
@@ -43,7 +43,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
43 43
44 $crawler = $client->request('GET', '/config'); 44 $crawler = $client->request('GET', '/config');
45 45
46 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 46 $this->assertSame(200, $client->getResponse()->getStatusCode());
47 47
48 $form = $crawler->filter('button[id=config_save]')->form(); 48 $form = $crawler->filter('button[id=config_save]')->form();
49 49
@@ -57,7 +57,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
57 57
58 $client->submit($form, $data); 58 $client->submit($form, $data);
59 59
60 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 60 $this->assertSame(302, $client->getResponse()->getStatusCode());
61 61
62 $crawler = $client->followRedirect(); 62 $crawler = $client->followRedirect();
63 63
@@ -67,8 +67,17 @@ class ConfigControllerTest extends WallabagCoreTestCase
67 public function testChangeReadingSpeed() 67 public function testChangeReadingSpeed()
68 { 68 {
69 $this->logInAs('admin'); 69 $this->logInAs('admin');
70 $this->useTheme('baggy');
70 $client = $this->getClient(); 71 $client = $this->getClient();
71 72
73 $entry = new Entry($this->getLoggedInUser());
74 $entry->setUrl('http://0.0.0.0/test-entry1')
75 ->setReadingTime(22);
76 $this->getEntityManager()->persist($entry);
77
78 $this->getEntityManager()->flush();
79 $this->getEntityManager()->clear();
80
72 $crawler = $client->request('GET', '/unread/list'); 81 $crawler = $client->request('GET', '/unread/list');
73 $form = $crawler->filter('button[id=submit-filter]')->form(); 82 $form = $crawler->filter('button[id=submit-filter]')->form();
74 $dataFilters = [ 83 $dataFilters = [
@@ -122,13 +131,13 @@ class ConfigControllerTest extends WallabagCoreTestCase
122 131
123 $crawler = $client->request('GET', '/config'); 132 $crawler = $client->request('GET', '/config');
124 133
125 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 134 $this->assertSame(200, $client->getResponse()->getStatusCode());
126 135
127 $form = $crawler->filter('button[id=config_save]')->form(); 136 $form = $crawler->filter('button[id=config_save]')->form();
128 137
129 $crawler = $client->submit($form, $data); 138 $crawler = $client->submit($form, $data);
130 139
131 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 140 $this->assertSame(200, $client->getResponse()->getStatusCode());
132 141
133 $this->assertGreaterThan(1, $alert = $crawler->filter('body')->extract(['_text'])); 142 $this->assertGreaterThan(1, $alert = $crawler->filter('body')->extract(['_text']));
134 $this->assertContains('This value should not be blank', $alert[0]); 143 $this->assertContains('This value should not be blank', $alert[0]);
@@ -182,13 +191,13 @@ class ConfigControllerTest extends WallabagCoreTestCase
182 191
183 $crawler = $client->request('GET', '/config'); 192 $crawler = $client->request('GET', '/config');
184 193
185 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 194 $this->assertSame(200, $client->getResponse()->getStatusCode());
186 195
187 $form = $crawler->filter('button[id=change_passwd_save]')->form(); 196 $form = $crawler->filter('button[id=change_passwd_save]')->form();
188 197
189 $crawler = $client->submit($form, $data); 198 $crawler = $client->submit($form, $data);
190 199
191 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 200 $this->assertSame(200, $client->getResponse()->getStatusCode());
192 201
193 $this->assertGreaterThan(1, $alert = $crawler->filter('body')->extract(['_text'])); 202 $this->assertGreaterThan(1, $alert = $crawler->filter('body')->extract(['_text']));
194 $this->assertContains($expectedMessage, $alert[0]); 203 $this->assertContains($expectedMessage, $alert[0]);
@@ -201,7 +210,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
201 210
202 $crawler = $client->request('GET', '/config'); 211 $crawler = $client->request('GET', '/config');
203 212
204 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 213 $this->assertSame(200, $client->getResponse()->getStatusCode());
205 214
206 $form = $crawler->filter('button[id=change_passwd_save]')->form(); 215 $form = $crawler->filter('button[id=change_passwd_save]')->form();
207 216
@@ -213,7 +222,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
213 222
214 $client->submit($form, $data); 223 $client->submit($form, $data);
215 224
216 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 225 $this->assertSame(302, $client->getResponse()->getStatusCode());
217 226
218 $crawler = $client->followRedirect(); 227 $crawler = $client->followRedirect();
219 228
@@ -250,13 +259,13 @@ class ConfigControllerTest extends WallabagCoreTestCase
250 259
251 $crawler = $client->request('GET', '/config'); 260 $crawler = $client->request('GET', '/config');
252 261
253 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 262 $this->assertSame(200, $client->getResponse()->getStatusCode());
254 263
255 $form = $crawler->filter('button[id=update_user_save]')->form(); 264 $form = $crawler->filter('button[id=update_user_save]')->form();
256 265
257 $crawler = $client->submit($form, $data); 266 $crawler = $client->submit($form, $data);
258 267
259 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 268 $this->assertSame(200, $client->getResponse()->getStatusCode());
260 269
261 $this->assertGreaterThan(1, $alert = $crawler->filter('body')->extract(['_text'])); 270 $this->assertGreaterThan(1, $alert = $crawler->filter('body')->extract(['_text']));
262 $this->assertContains($expectedMessage, $alert[0]); 271 $this->assertContains($expectedMessage, $alert[0]);
@@ -269,7 +278,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
269 278
270 $crawler = $client->request('GET', '/config'); 279 $crawler = $client->request('GET', '/config');
271 280
272 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 281 $this->assertSame(200, $client->getResponse()->getStatusCode());
273 282
274 $form = $crawler->filter('button[id=update_user_save]')->form(); 283 $form = $crawler->filter('button[id=update_user_save]')->form();
275 284
@@ -280,7 +289,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
280 289
281 $client->submit($form, $data); 290 $client->submit($form, $data);
282 291
283 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 292 $this->assertSame(302, $client->getResponse()->getStatusCode());
284 293
285 $crawler = $client->followRedirect(); 294 $crawler = $client->followRedirect();
286 295
@@ -310,13 +319,13 @@ class ConfigControllerTest extends WallabagCoreTestCase
310 319
311 $crawler = $client->request('GET', '/config'); 320 $crawler = $client->request('GET', '/config');
312 321
313 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 322 $this->assertSame(200, $client->getResponse()->getStatusCode());
314 323
315 $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text'])); 324 $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
316 $this->assertContains('config.form_rss.no_token', $body[0]); 325 $this->assertContains('config.form_rss.no_token', $body[0]);
317 326
318 $client->request('GET', '/generate-token'); 327 $client->request('GET', '/generate-token');
319 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 328 $this->assertSame(302, $client->getResponse()->getStatusCode());
320 329
321 $crawler = $client->followRedirect(); 330 $crawler = $client->followRedirect();
322 331
@@ -337,7 +346,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
337 ['HTTP_X-Requested-With' => 'XMLHttpRequest'] 346 ['HTTP_X-Requested-With' => 'XMLHttpRequest']
338 ); 347 );
339 348
340 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 349 $this->assertSame(200, $client->getResponse()->getStatusCode());
341 $content = json_decode($client->getResponse()->getContent(), true); 350 $content = json_decode($client->getResponse()->getContent(), true);
342 $this->assertArrayHasKey('token', $content); 351 $this->assertArrayHasKey('token', $content);
343 } 352 }
@@ -349,7 +358,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
349 358
350 $crawler = $client->request('GET', '/config'); 359 $crawler = $client->request('GET', '/config');
351 360
352 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 361 $this->assertSame(200, $client->getResponse()->getStatusCode());
353 362
354 $form = $crawler->filter('button[id=rss_config_save]')->form(); 363 $form = $crawler->filter('button[id=rss_config_save]')->form();
355 364
@@ -359,7 +368,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
359 368
360 $client->submit($form, $data); 369 $client->submit($form, $data);
361 370
362 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 371 $this->assertSame(302, $client->getResponse()->getStatusCode());
363 372
364 $crawler = $client->followRedirect(); 373 $crawler = $client->followRedirect();
365 374
@@ -394,13 +403,13 @@ class ConfigControllerTest extends WallabagCoreTestCase
394 403
395 $crawler = $client->request('GET', '/config'); 404 $crawler = $client->request('GET', '/config');
396 405
397 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 406 $this->assertSame(200, $client->getResponse()->getStatusCode());
398 407
399 $form = $crawler->filter('button[id=rss_config_save]')->form(); 408 $form = $crawler->filter('button[id=rss_config_save]')->form();
400 409
401 $crawler = $client->submit($form, $data); 410 $crawler = $client->submit($form, $data);
402 411
403 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 412 $this->assertSame(200, $client->getResponse()->getStatusCode());
404 413
405 $this->assertGreaterThan(1, $alert = $crawler->filter('body')->extract(['_text'])); 414 $this->assertGreaterThan(1, $alert = $crawler->filter('body')->extract(['_text']));
406 $this->assertContains($expectedMessage, $alert[0]); 415 $this->assertContains($expectedMessage, $alert[0]);
@@ -409,11 +418,12 @@ class ConfigControllerTest extends WallabagCoreTestCase
409 public function testTaggingRuleCreation() 418 public function testTaggingRuleCreation()
410 { 419 {
411 $this->logInAs('admin'); 420 $this->logInAs('admin');
421 $this->useTheme('baggy');
412 $client = $this->getClient(); 422 $client = $this->getClient();
413 423
414 $crawler = $client->request('GET', '/config'); 424 $crawler = $client->request('GET', '/config');
415 425
416 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 426 $this->assertSame(200, $client->getResponse()->getStatusCode());
417 427
418 $form = $crawler->filter('button[id=tagging_rule_save]')->form(); 428 $form = $crawler->filter('button[id=tagging_rule_save]')->form();
419 429
@@ -424,7 +434,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
424 434
425 $client->submit($form, $data); 435 $client->submit($form, $data);
426 436
427 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 437 $this->assertSame(302, $client->getResponse()->getStatusCode());
428 438
429 $crawler = $client->followRedirect(); 439 $crawler = $client->followRedirect();
430 440
@@ -433,7 +443,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
433 $editLink = $crawler->filter('.mode_edit')->last()->link(); 443 $editLink = $crawler->filter('.mode_edit')->last()->link();
434 444
435 $crawler = $client->click($editLink); 445 $crawler = $client->click($editLink);
436 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 446 $this->assertSame(302, $client->getResponse()->getStatusCode());
437 $this->assertContains('?tagging-rule=', $client->getResponse()->headers->get('location')); 447 $this->assertContains('?tagging-rule=', $client->getResponse()->headers->get('location'));
438 448
439 $crawler = $client->followRedirect(); 449 $crawler = $client->followRedirect();
@@ -447,7 +457,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
447 457
448 $client->submit($form, $data); 458 $client->submit($form, $data);
449 459
450 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 460 $this->assertSame(302, $client->getResponse()->getStatusCode());
451 461
452 $crawler = $client->followRedirect(); 462 $crawler = $client->followRedirect();
453 463
@@ -458,7 +468,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
458 $deleteLink = $crawler->filter('.delete')->last()->link(); 468 $deleteLink = $crawler->filter('.delete')->last()->link();
459 469
460 $crawler = $client->click($deleteLink); 470 $crawler = $client->click($deleteLink);
461 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 471 $this->assertSame(302, $client->getResponse()->getStatusCode());
462 472
463 $crawler = $client->followRedirect(); 473 $crawler = $client->followRedirect();
464 $this->assertContains('flashes.config.notice.tagging_rules_deleted', $crawler->filter('body')->extract(['_text'])[0]); 474 $this->assertContains('flashes.config.notice.tagging_rules_deleted', $crawler->filter('body')->extract(['_text'])[0]);
@@ -500,13 +510,13 @@ class ConfigControllerTest extends WallabagCoreTestCase
500 510
501 $crawler = $client->request('GET', '/config'); 511 $crawler = $client->request('GET', '/config');
502 512
503 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 513 $this->assertSame(200, $client->getResponse()->getStatusCode());
504 514
505 $form = $crawler->filter('button[id=tagging_rule_save]')->form(); 515 $form = $crawler->filter('button[id=tagging_rule_save]')->form();
506 516
507 $crawler = $client->submit($form, $data); 517 $crawler = $client->submit($form, $data);
508 518
509 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 519 $this->assertSame(200, $client->getResponse()->getStatusCode());
510 520
511 $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text'])); 521 $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
512 522
@@ -522,7 +532,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
522 532
523 $crawler = $client->request('GET', '/config'); 533 $crawler = $client->request('GET', '/config');
524 534
525 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 535 $this->assertSame(200, $client->getResponse()->getStatusCode());
526 536
527 $form = $crawler->filter('button[id=tagging_rule_save]')->form(); 537 $form = $crawler->filter('button[id=tagging_rule_save]')->form();
528 538
@@ -531,7 +541,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
531 'tagging_rule[tags]' => 'cool tag', 541 'tagging_rule[tags]' => 'cool tag',
532 ]); 542 ]);
533 543
534 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 544 $this->assertSame(200, $client->getResponse()->getStatusCode());
535 545
536 $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text'])); 546 $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
537 547
@@ -547,9 +557,9 @@ class ConfigControllerTest extends WallabagCoreTestCase
547 ->getRepository('WallabagCoreBundle:TaggingRule') 557 ->getRepository('WallabagCoreBundle:TaggingRule')
548 ->findAll()[0]; 558 ->findAll()[0];
549 559
550 $crawler = $client->request('GET', '/tagging-rule/edit/'.$rule->getId()); 560 $crawler = $client->request('GET', '/tagging-rule/edit/' . $rule->getId());
551 561
552 $this->assertEquals(403, $client->getResponse()->getStatusCode()); 562 $this->assertSame(403, $client->getResponse()->getStatusCode());
553 $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text'])); 563 $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
554 $this->assertContains('You can not access this tagging rule', $body[0]); 564 $this->assertContains('You can not access this tagging rule', $body[0]);
555 } 565 }
@@ -563,9 +573,9 @@ class ConfigControllerTest extends WallabagCoreTestCase
563 ->getRepository('WallabagCoreBundle:TaggingRule') 573 ->getRepository('WallabagCoreBundle:TaggingRule')
564 ->findAll()[0]; 574 ->findAll()[0];
565 575
566 $crawler = $client->request('GET', '/tagging-rule/edit/'.$rule->getId()); 576 $crawler = $client->request('GET', '/tagging-rule/edit/' . $rule->getId());
567 577
568 $this->assertEquals(403, $client->getResponse()->getStatusCode()); 578 $this->assertSame(403, $client->getResponse()->getStatusCode());
569 $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text'])); 579 $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
570 $this->assertContains('You can not access this tagging rule', $body[0]); 580 $this->assertContains('You can not access this tagging rule', $body[0]);
571 } 581 }
@@ -581,7 +591,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
581 591
582 $crawler = $client->request('GET', '/config'); 592 $crawler = $client->request('GET', '/config');
583 593
584 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 594 $this->assertSame(200, $client->getResponse()->getStatusCode());
585 595
586 $form = $crawler->filter('button[id=change_passwd_save]')->form(); 596 $form = $crawler->filter('button[id=change_passwd_save]')->form();
587 597
@@ -593,7 +603,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
593 603
594 $client->submit($form, $data); 604 $client->submit($form, $data);
595 605
596 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 606 $this->assertSame(302, $client->getResponse()->getStatusCode());
597 $this->assertContains('flashes.config.notice.password_not_updated_demo', $client->getContainer()->get('session')->getFlashBag()->get('notice')[0]); 607 $this->assertContains('flashes.config.notice.password_not_updated_demo', $client->getContainer()->get('session')->getFlashBag()->get('notice')[0]);
598 608
599 $config->set('demo_mode_enabled', 0); 609 $config->set('demo_mode_enabled', 0);
@@ -632,7 +642,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
632 $this->assertNotContains('config.form_user.delete.button', $body[0]); 642 $this->assertNotContains('config.form_user.delete.button', $body[0]);
633 643
634 $client->request('GET', '/account/delete'); 644 $client->request('GET', '/account/delete');
635 $this->assertEquals(403, $client->getResponse()->getStatusCode()); 645 $this->assertSame(403, $client->getResponse()->getStatusCode());
636 646
637 $user = $em 647 $user = $em
638 ->getRepository('WallabagUserBundle:User') 648 ->getRepository('WallabagUserBundle:User')
@@ -682,7 +692,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
682 // that this entry is also deleted 692 // that this entry is also deleted
683 $crawler = $client->request('GET', '/new'); 693 $crawler = $client->request('GET', '/new');
684 694
685 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 695 $this->assertSame(200, $client->getResponse()->getStatusCode());
686 696
687 $form = $crawler->filter('form[name=entry]')->form(); 697 $form = $crawler->filter('form[name=entry]')->form();
688 $data = [ 698 $data = [
@@ -690,14 +700,14 @@ class ConfigControllerTest extends WallabagCoreTestCase
690 ]; 700 ];
691 701
692 $client->submit($form, $data); 702 $client->submit($form, $data);
693 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 703 $this->assertSame(302, $client->getResponse()->getStatusCode());
694 704
695 $crawler = $client->request('GET', '/config'); 705 $crawler = $client->request('GET', '/config');
696 706
697 $deleteLink = $crawler->filter('.delete-account')->last()->link(); 707 $deleteLink = $crawler->filter('.delete-account')->last()->link();
698 708
699 $client->click($deleteLink); 709 $client->click($deleteLink);
700 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 710 $this->assertSame(302, $client->getResponse()->getStatusCode());
701 711
702 $em = $client->getContainer()->get('doctrine.orm.entity_manager'); 712 $em = $client->getContainer()->get('doctrine.orm.entity_manager');
703 $user = $em 713 $user = $em
@@ -757,11 +767,11 @@ class ConfigControllerTest extends WallabagCoreTestCase
757 // reset annotations 767 // reset annotations
758 $crawler = $client->request('GET', '/config#set3'); 768 $crawler = $client->request('GET', '/config#set3');
759 769
760 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 770 $this->assertSame(200, $client->getResponse()->getStatusCode());
761 771
762 $crawler = $client->click($crawler->selectLink('config.reset.annotations')->link()); 772 $crawler = $client->click($crawler->selectLink('config.reset.annotations')->link());
763 773
764 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 774 $this->assertSame(302, $client->getResponse()->getStatusCode());
765 $this->assertContains('flashes.config.notice.annotations_reset', $client->getContainer()->get('session')->getFlashBag()->get('notice')[0]); 775 $this->assertContains('flashes.config.notice.annotations_reset', $client->getContainer()->get('session')->getFlashBag()->get('notice')[0]);
766 776
767 $annotationsReset = $em 777 $annotationsReset = $em
@@ -773,34 +783,110 @@ class ConfigControllerTest extends WallabagCoreTestCase
773 // reset tags 783 // reset tags
774 $crawler = $client->request('GET', '/config#set3'); 784 $crawler = $client->request('GET', '/config#set3');
775 785
776 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 786 $this->assertSame(200, $client->getResponse()->getStatusCode());
777 787
778 $crawler = $client->click($crawler->selectLink('config.reset.tags')->link()); 788 $crawler = $client->click($crawler->selectLink('config.reset.tags')->link());
779 789
780 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 790 $this->assertSame(302, $client->getResponse()->getStatusCode());
781 $this->assertContains('flashes.config.notice.tags_reset', $client->getContainer()->get('session')->getFlashBag()->get('notice')[0]); 791 $this->assertContains('flashes.config.notice.tags_reset', $client->getContainer()->get('session')->getFlashBag()->get('notice')[0]);
782 792
783 $tagReset = $em 793 $tagReset = $em
784 ->getRepository('WallabagCoreBundle:Tag') 794 ->getRepository('WallabagCoreBundle:Tag')
785 ->countAllTags($user->getId()); 795 ->countAllTags($user->getId());
786 796
787 $this->assertEquals(0, $tagReset, 'Tags were reset'); 797 $this->assertSame(0, $tagReset, 'Tags were reset');
788 798
789 // reset entries 799 // reset entries
790 $crawler = $client->request('GET', '/config#set3'); 800 $crawler = $client->request('GET', '/config#set3');
791 801
792 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 802 $this->assertSame(200, $client->getResponse()->getStatusCode());
793 803
794 $crawler = $client->click($crawler->selectLink('config.reset.entries')->link()); 804 $crawler = $client->click($crawler->selectLink('config.reset.entries')->link());
795 805
796 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 806 $this->assertSame(302, $client->getResponse()->getStatusCode());
797 $this->assertContains('flashes.config.notice.entries_reset', $client->getContainer()->get('session')->getFlashBag()->get('notice')[0]); 807 $this->assertContains('flashes.config.notice.entries_reset', $client->getContainer()->get('session')->getFlashBag()->get('notice')[0]);
798 808
799 $entryReset = $em 809 $entryReset = $em
800 ->getRepository('WallabagCoreBundle:Entry') 810 ->getRepository('WallabagCoreBundle:Entry')
801 ->countAllEntriesByUsername($user->getId()); 811 ->countAllEntriesByUser($user->getId());
812
813 $this->assertSame(0, $entryReset, 'Entries were reset');
814 }
815
816 public function testResetArchivedEntries()
817 {
818 $this->logInAs('empty');
819 $client = $this->getClient();
820
821 $em = $client->getContainer()->get('doctrine.orm.entity_manager');
802 822
803 $this->assertEquals(0, $entryReset, 'Entries were reset'); 823 $user = static::$kernel->getContainer()->get('security.token_storage')->getToken()->getUser();
824
825 $tag = new Tag();
826 $tag->setLabel('super');
827 $em->persist($tag);
828
829 $entry = new Entry($user);
830 $entry->setUrl('http://www.lemonde.fr/europe/article/2016/10/01/pour-le-psoe-chaque-election-s-est-transformee-en-une-agonie_5006476_3214.html');
831 $entry->setContent('Youhou');
832 $entry->setTitle('Youhou');
833 $entry->addTag($tag);
834 $em->persist($entry);
835
836 $annotation = new Annotation($user);
837 $annotation->setText('annotated');
838 $annotation->setQuote('annotated');
839 $annotation->setRanges([]);
840 $annotation->setEntry($entry);
841 $em->persist($annotation);
842
843 $tagArchived = new Tag();
844 $tagArchived->setLabel('super');
845 $em->persist($tagArchived);
846
847 $entryArchived = new Entry($user);
848 $entryArchived->setUrl('http://www.lemonde.fr/europe/article/2016/10/01/pour-le-psoe-chaque-election-s-est-transformee-en-une-agonie_5006476_3214.html');
849 $entryArchived->setContent('Youhou');
850 $entryArchived->setTitle('Youhou');
851 $entryArchived->addTag($tagArchived);
852 $entryArchived->setArchived(true);
853 $em->persist($entryArchived);
854
855 $annotationArchived = new Annotation($user);
856 $annotationArchived->setText('annotated');
857 $annotationArchived->setQuote('annotated');
858 $annotationArchived->setRanges([]);
859 $annotationArchived->setEntry($entryArchived);
860 $em->persist($annotationArchived);
861
862 $em->flush();
863
864 $crawler = $client->request('GET', '/config#set3');
865
866 $this->assertSame(200, $client->getResponse()->getStatusCode());
867
868 $crawler = $client->click($crawler->selectLink('config.reset.archived')->link());
869
870 $this->assertSame(302, $client->getResponse()->getStatusCode());
871 $this->assertContains('flashes.config.notice.archived_reset', $client->getContainer()->get('session')->getFlashBag()->get('notice')[0]);
872
873 $entryReset = $em
874 ->getRepository('WallabagCoreBundle:Entry')
875 ->countAllEntriesByUser($user->getId());
876
877 $this->assertSame(1, $entryReset, 'Entries were reset');
878
879 $tagReset = $em
880 ->getRepository('WallabagCoreBundle:Tag')
881 ->countAllTags($user->getId());
882
883 $this->assertSame(1, $tagReset, 'Tags were reset');
884
885 $annotationsReset = $em
886 ->getRepository('WallabagAnnotationBundle:Annotation')
887 ->findAnnotationsByPageId($annotationArchived->getId(), $user->getId());
888
889 $this->assertEmpty($annotationsReset, 'Annotations were reset');
804 } 890 }
805 891
806 public function testResetEntriesCascade() 892 public function testResetEntriesCascade()
@@ -834,24 +920,24 @@ class ConfigControllerTest extends WallabagCoreTestCase
834 920
835 $crawler = $client->request('GET', '/config#set3'); 921 $crawler = $client->request('GET', '/config#set3');
836 922
837 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 923 $this->assertSame(200, $client->getResponse()->getStatusCode());
838 924
839 $crawler = $client->click($crawler->selectLink('config.reset.entries')->link()); 925 $crawler = $client->click($crawler->selectLink('config.reset.entries')->link());
840 926
841 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 927 $this->assertSame(302, $client->getResponse()->getStatusCode());
842 $this->assertContains('flashes.config.notice.entries_reset', $client->getContainer()->get('session')->getFlashBag()->get('notice')[0]); 928 $this->assertContains('flashes.config.notice.entries_reset', $client->getContainer()->get('session')->getFlashBag()->get('notice')[0]);
843 929
844 $entryReset = $em 930 $entryReset = $em
845 ->getRepository('WallabagCoreBundle:Entry') 931 ->getRepository('WallabagCoreBundle:Entry')
846 ->countAllEntriesByUsername($user->getId()); 932 ->countAllEntriesByUser($user->getId());
847 933
848 $this->assertEquals(0, $entryReset, 'Entries were reset'); 934 $this->assertSame(0, $entryReset, 'Entries were reset');
849 935
850 $tagReset = $em 936 $tagReset = $em
851 ->getRepository('WallabagCoreBundle:Tag') 937 ->getRepository('WallabagCoreBundle:Tag')
852 ->countAllTags($user->getId()); 938 ->countAllTags($user->getId());
853 939
854 $this->assertEquals(0, $tagReset, 'Tags were reset'); 940 $this->assertSame(0, $tagReset, 'Tags were reset');
855 941
856 $annotationsReset = $em 942 $annotationsReset = $em
857 ->getRepository('WallabagAnnotationBundle:Annotation') 943 ->getRepository('WallabagAnnotationBundle:Annotation')
@@ -863,6 +949,7 @@ class ConfigControllerTest extends WallabagCoreTestCase
863 public function testSwitchViewMode() 949 public function testSwitchViewMode()
864 { 950 {
865 $this->logInAs('admin'); 951 $this->logInAs('admin');
952 $this->useTheme('baggy');
866 $client = $this->getClient(); 953 $client = $this->getClient();
867 954
868 $client->request('GET', '/unread/list'); 955 $client->request('GET', '/unread/list');
diff --git a/tests/Wallabag/CoreBundle/Controller/EntryControllerTest.php b/tests/Wallabag/CoreBundle/Controller/EntryControllerTest.php
index 7db4cf1f..33bfa71e 100644
--- a/tests/Wallabag/CoreBundle/Controller/EntryControllerTest.php
+++ b/tests/Wallabag/CoreBundle/Controller/EntryControllerTest.php
@@ -5,18 +5,35 @@ namespace Tests\Wallabag\CoreBundle\Controller;
5use Tests\Wallabag\CoreBundle\WallabagCoreTestCase; 5use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
6use Wallabag\CoreBundle\Entity\Config; 6use Wallabag\CoreBundle\Entity\Config;
7use Wallabag\CoreBundle\Entity\Entry; 7use Wallabag\CoreBundle\Entity\Entry;
8use Wallabag\CoreBundle\Entity\SiteCredential;
8 9
9class EntryControllerTest extends WallabagCoreTestCase 10class EntryControllerTest extends WallabagCoreTestCase
10{ 11{
12 public $downloadImagesEnabled = false;
11 public $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'; 13 public $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';
12 14
15 /**
16 * @after
17 *
18 * Ensure download_images_enabled is disabled after each script
19 */
20 public function tearDownImagesEnabled()
21 {
22 if ($this->downloadImagesEnabled) {
23 $client = static::createClient();
24 $client->getContainer()->get('craue_config')->set('download_images_enabled', 0);
25
26 $this->downloadImagesEnabled = false;
27 }
28 }
29
13 public function testLogin() 30 public function testLogin()
14 { 31 {
15 $client = $this->getClient(); 32 $client = $this->getClient();
16 33
17 $client->request('GET', '/new'); 34 $client->request('GET', '/new');
18 35
19 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 36 $this->assertSame(302, $client->getResponse()->getStatusCode());
20 $this->assertContains('login', $client->getResponse()->headers->get('location')); 37 $this->assertContains('login', $client->getResponse()->headers->get('location'));
21 } 38 }
22 39
@@ -26,16 +43,17 @@ class EntryControllerTest extends WallabagCoreTestCase
26 $client = $this->getClient(); 43 $client = $this->getClient();
27 44
28 $client->request('GET', '/unread/list'); 45 $client->request('GET', '/unread/list');
46 $this->assertSame(302, $client->getResponse()->getStatusCode());
29 $crawler = $client->followRedirect(); 47 $crawler = $client->followRedirect();
30 48
31 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 49 $this->assertSame(200, $client->getResponse()->getStatusCode());
32 $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text'])); 50 $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
33 $this->assertContains('quickstart.intro.title', $body[0]); 51 $this->assertContains('quickstart.intro.title', $body[0]);
34 52
35 // Test if quickstart is disabled when user has 1 entry 53 // Test if quickstart is disabled when user has 1 entry
36 $crawler = $client->request('GET', '/new'); 54 $crawler = $client->request('GET', '/new');
37 55
38 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 56 $this->assertSame(200, $client->getResponse()->getStatusCode());
39 57
40 $form = $crawler->filter('form[name=entry]')->form(); 58 $form = $crawler->filter('form[name=entry]')->form();
41 59
@@ -44,7 +62,7 @@ class EntryControllerTest extends WallabagCoreTestCase
44 ]; 62 ];
45 63
46 $client->submit($form, $data); 64 $client->submit($form, $data);
47 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 65 $this->assertSame(302, $client->getResponse()->getStatusCode());
48 $client->followRedirect(); 66 $client->followRedirect();
49 67
50 $crawler = $client->request('GET', '/unread/list'); 68 $crawler = $client->request('GET', '/unread/list');
@@ -55,11 +73,12 @@ class EntryControllerTest extends WallabagCoreTestCase
55 public function testGetNew() 73 public function testGetNew()
56 { 74 {
57 $this->logInAs('admin'); 75 $this->logInAs('admin');
76 $this->useTheme('baggy');
58 $client = $this->getClient(); 77 $client = $this->getClient();
59 78
60 $crawler = $client->request('GET', '/new'); 79 $crawler = $client->request('GET', '/new');
61 80
62 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 81 $this->assertSame(200, $client->getResponse()->getStatusCode());
63 82
64 $this->assertCount(1, $crawler->filter('input[type=url]')); 83 $this->assertCount(1, $crawler->filter('input[type=url]'));
65 $this->assertCount(1, $crawler->filter('form[name=entry]')); 84 $this->assertCount(1, $crawler->filter('form[name=entry]'));
@@ -68,6 +87,7 @@ class EntryControllerTest extends WallabagCoreTestCase
68 public function testPostNewViaBookmarklet() 87 public function testPostNewViaBookmarklet()
69 { 88 {
70 $this->logInAs('admin'); 89 $this->logInAs('admin');
90 $this->useTheme('baggy');
71 $client = $this->getClient(); 91 $client = $this->getClient();
72 92
73 $crawler = $client->request('GET', '/'); 93 $crawler = $client->request('GET', '/');
@@ -76,7 +96,7 @@ class EntryControllerTest extends WallabagCoreTestCase
76 96
77 // Good URL 97 // Good URL
78 $client->request('GET', '/bookmarklet', ['url' => $this->url]); 98 $client->request('GET', '/bookmarklet', ['url' => $this->url]);
79 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 99 $this->assertSame(302, $client->getResponse()->getStatusCode());
80 $client->followRedirect(); 100 $client->followRedirect();
81 $crawler = $client->request('GET', '/'); 101 $crawler = $client->request('GET', '/');
82 $this->assertCount(5, $crawler->filter('div[class=entry]')); 102 $this->assertCount(5, $crawler->filter('div[class=entry]'));
@@ -97,15 +117,15 @@ class EntryControllerTest extends WallabagCoreTestCase
97 117
98 $crawler = $client->request('GET', '/new'); 118 $crawler = $client->request('GET', '/new');
99 119
100 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 120 $this->assertSame(200, $client->getResponse()->getStatusCode());
101 121
102 $form = $crawler->filter('form[name=entry]')->form(); 122 $form = $crawler->filter('form[name=entry]')->form();
103 123
104 $crawler = $client->submit($form); 124 $crawler = $client->submit($form);
105 125
106 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 126 $this->assertSame(200, $client->getResponse()->getStatusCode());
107 $this->assertCount(1, $alert = $crawler->filter('form ul li')->extract(['_text'])); 127 $this->assertCount(1, $alert = $crawler->filter('form ul li')->extract(['_text']));
108 $this->assertEquals('This value should not be blank.', $alert[0]); 128 $this->assertSame('This value should not be blank.', $alert[0]);
109 } 129 }
110 130
111 /** 131 /**
@@ -118,7 +138,7 @@ class EntryControllerTest extends WallabagCoreTestCase
118 138
119 $crawler = $client->request('GET', '/new'); 139 $crawler = $client->request('GET', '/new');
120 140
121 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 141 $this->assertSame(200, $client->getResponse()->getStatusCode());
122 142
123 $form = $crawler->filter('form[name=entry]')->form(); 143 $form = $crawler->filter('form[name=entry]')->form();
124 144
@@ -128,26 +148,70 @@ class EntryControllerTest extends WallabagCoreTestCase
128 148
129 $client->submit($form, $data); 149 $client->submit($form, $data);
130 150
131 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 151 $this->assertSame(302, $client->getResponse()->getStatusCode());
132 152
133 $content = $client->getContainer() 153 $content = $client->getContainer()
134 ->get('doctrine.orm.entity_manager') 154 ->get('doctrine.orm.entity_manager')
135 ->getRepository('WallabagCoreBundle:Entry') 155 ->getRepository('WallabagCoreBundle:Entry')
136 ->findByUrlAndUserId($this->url, $this->getLoggedInUserId()); 156 ->findByUrlAndUserId($this->url, $this->getLoggedInUserId());
137 157
158 $author = $content->getPublishedBy();
159
138 $this->assertInstanceOf('Wallabag\CoreBundle\Entity\Entry', $content); 160 $this->assertInstanceOf('Wallabag\CoreBundle\Entity\Entry', $content);
139 $this->assertEquals($this->url, $content->getUrl()); 161 $this->assertSame($this->url, $content->getUrl());
140 $this->assertContains('Google', $content->getTitle()); 162 $this->assertContains('Google', $content->getTitle());
163 $this->assertSame('fr', $content->getLanguage());
164 $this->assertSame('2015-03-28 15:37:39', $content->getPublishedAt()->format('Y-m-d H:i:s'));
165 $this->assertSame('Morgane Tual', $author[0]);
166 $this->assertArrayHasKey('x-varnish1', $content->getHeaders());
167 }
168
169 public function testPostWithMultipleAuthors()
170 {
171 $url = 'http://www.liberation.fr/planete/2017/04/05/donald-trump-et-xi-jinping-tentative-de-flirt-en-floride_1560768';
172 $this->logInAs('admin');
173 $client = $this->getClient();
174
175 $crawler = $client->request('GET', '/new');
176
177 $this->assertSame(200, $client->getResponse()->getStatusCode());
178
179 $form = $crawler->filter('form[name=entry]')->form();
180
181 $data = [
182 'entry[url]' => $url,
183 ];
184
185 $client->submit($form, $data);
186
187 $this->assertSame(302, $client->getResponse()->getStatusCode());
188
189 $content = $client->getContainer()
190 ->get('doctrine.orm.entity_manager')
191 ->getRepository('WallabagCoreBundle:Entry')
192 ->findByUrlAndUserId($url, $this->getLoggedInUserId());
193
194 $authors = $content->getPublishedBy();
195 $this->assertSame('2017-04-05 19:26:13', $content->getPublishedAt()->format('Y-m-d H:i:s'));
196 $this->assertSame('fr', $content->getLanguage());
197 $this->assertSame('Raphaël Balenieri, correspondant à Pékin', $authors[0]);
198 $this->assertSame('Frédéric Autran, correspondant à New York', $authors[1]);
141 } 199 }
142 200
143 public function testPostNewOkUrlExist() 201 public function testPostNewOkUrlExist()
144 { 202 {
145 $this->logInAs('admin'); 203 $this->logInAs('admin');
204
205 $entry = new Entry($this->getLoggedInUser());
206 $entry->setUrl($this->url);
207 $this->getEntityManager()->persist($entry);
208 $this->getEntityManager()->flush();
209
146 $client = $this->getClient(); 210 $client = $this->getClient();
147 211
148 $crawler = $client->request('GET', '/new'); 212 $crawler = $client->request('GET', '/new');
149 213
150 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 214 $this->assertSame(200, $client->getResponse()->getStatusCode());
151 215
152 $form = $crawler->filter('form[name=entry]')->form(); 216 $form = $crawler->filter('form[name=entry]')->form();
153 217
@@ -157,7 +221,7 @@ class EntryControllerTest extends WallabagCoreTestCase
157 221
158 $client->submit($form, $data); 222 $client->submit($form, $data);
159 223
160 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 224 $this->assertSame(302, $client->getResponse()->getStatusCode());
161 $this->assertContains('/view/', $client->getResponse()->getTargetUrl()); 225 $this->assertContains('/view/', $client->getResponse()->getTargetUrl());
162 } 226 }
163 227
@@ -170,7 +234,7 @@ class EntryControllerTest extends WallabagCoreTestCase
170 234
171 $crawler = $client->request('GET', '/new'); 235 $crawler = $client->request('GET', '/new');
172 236
173 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 237 $this->assertSame(200, $client->getResponse()->getStatusCode());
174 238
175 $form = $crawler->filter('form[name=entry]')->form(); 239 $form = $crawler->filter('form[name=entry]')->form();
176 240
@@ -182,7 +246,7 @@ class EntryControllerTest extends WallabagCoreTestCase
182 246
183 $crawler = $client->request('GET', '/new'); 247 $crawler = $client->request('GET', '/new');
184 248
185 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 249 $this->assertSame(200, $client->getResponse()->getStatusCode());
186 250
187 $form = $crawler->filter('form[name=entry]')->form(); 251 $form = $crawler->filter('form[name=entry]')->form();
188 252
@@ -192,17 +256,8 @@ class EntryControllerTest extends WallabagCoreTestCase
192 256
193 $client->submit($form, $data); 257 $client->submit($form, $data);
194 258
195 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 259 $this->assertSame(302, $client->getResponse()->getStatusCode());
196 $this->assertContains('/view/', $client->getResponse()->getTargetUrl()); 260 $this->assertContains('/view/', $client->getResponse()->getTargetUrl());
197
198 $em = $client->getContainer()
199 ->get('doctrine.orm.entity_manager');
200 $entry = $em
201 ->getRepository('WallabagCoreBundle:Entry')
202 ->findOneByUrl(urldecode($url));
203
204 $em->remove($entry);
205 $em->flush();
206 } 261 }
207 262
208 /** 263 /**
@@ -215,7 +270,7 @@ class EntryControllerTest extends WallabagCoreTestCase
215 270
216 $crawler = $client->request('GET', '/new'); 271 $crawler = $client->request('GET', '/new');
217 272
218 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 273 $this->assertSame(200, $client->getResponse()->getStatusCode());
219 274
220 $form = $crawler->filter('form[name=entry]')->form(); 275 $form = $crawler->filter('form[name=entry]')->form();
221 276
@@ -225,7 +280,7 @@ class EntryControllerTest extends WallabagCoreTestCase
225 280
226 $client->submit($form, $data); 281 $client->submit($form, $data);
227 282
228 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 283 $this->assertSame(302, $client->getResponse()->getStatusCode());
229 $this->assertContains('/', $client->getResponse()->getTargetUrl()); 284 $this->assertContains('/', $client->getResponse()->getTargetUrl());
230 285
231 $em = $client->getContainer() 286 $em = $client->getContainer()
@@ -235,8 +290,9 @@ class EntryControllerTest extends WallabagCoreTestCase
235 ->findOneByUrl($url); 290 ->findOneByUrl($url);
236 $tags = $entry->getTags(); 291 $tags = $entry->getTags();
237 292
238 $this->assertCount(1, $tags); 293 $this->assertCount(2, $tags);
239 $this->assertEquals('wallabag', $tags[0]->getLabel()); 294 $this->assertContains('wallabag', $tags);
295 $this->assertSame('en', $entry->getLanguage());
240 296
241 $em->remove($entry); 297 $em->remove($entry);
242 $em->flush(); 298 $em->flush();
@@ -245,7 +301,7 @@ class EntryControllerTest extends WallabagCoreTestCase
245 // related https://github.com/wallabag/wallabag/issues/2121 301 // related https://github.com/wallabag/wallabag/issues/2121
246 $crawler = $client->request('GET', '/new'); 302 $crawler = $client->request('GET', '/new');
247 303
248 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 304 $this->assertSame(200, $client->getResponse()->getStatusCode());
249 305
250 $form = $crawler->filter('form[name=entry]')->form(); 306 $form = $crawler->filter('form[name=entry]')->form();
251 307
@@ -255,7 +311,7 @@ class EntryControllerTest extends WallabagCoreTestCase
255 311
256 $client->submit($form, $data); 312 $client->submit($form, $data);
257 313
258 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 314 $this->assertSame(302, $client->getResponse()->getStatusCode());
259 $this->assertContains('/', $client->getResponse()->getTargetUrl()); 315 $this->assertContains('/', $client->getResponse()->getTargetUrl());
260 316
261 $entry = $em 317 $entry = $em
@@ -264,8 +320,8 @@ class EntryControllerTest extends WallabagCoreTestCase
264 320
265 $tags = $entry->getTags(); 321 $tags = $entry->getTags();
266 322
267 $this->assertCount(1, $tags); 323 $this->assertCount(2, $tags);
268 $this->assertEquals('wallabag', $tags[0]->getLabel()); 324 $this->assertContains('wallabag', $tags);
269 325
270 $em->remove($entry); 326 $em->remove($entry);
271 $em->flush(); 327 $em->flush();
@@ -278,7 +334,7 @@ class EntryControllerTest extends WallabagCoreTestCase
278 334
279 $client->request('GET', '/archive/list'); 335 $client->request('GET', '/archive/list');
280 336
281 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 337 $this->assertSame(200, $client->getResponse()->getStatusCode());
282 } 338 }
283 339
284 public function testUntagged() 340 public function testUntagged()
@@ -288,7 +344,7 @@ class EntryControllerTest extends WallabagCoreTestCase
288 344
289 $client->request('GET', '/untagged/list'); 345 $client->request('GET', '/untagged/list');
290 346
291 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 347 $this->assertSame(200, $client->getResponse()->getStatusCode());
292 } 348 }
293 349
294 public function testStarred() 350 public function testStarred()
@@ -298,7 +354,7 @@ class EntryControllerTest extends WallabagCoreTestCase
298 354
299 $client->request('GET', '/starred/list'); 355 $client->request('GET', '/starred/list');
300 356
301 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 357 $this->assertSame(200, $client->getResponse()->getStatusCode());
302 } 358 }
303 359
304 public function testRangeException() 360 public function testRangeException()
@@ -308,33 +364,30 @@ class EntryControllerTest extends WallabagCoreTestCase
308 364
309 $client->request('GET', '/all/list/900'); 365 $client->request('GET', '/all/list/900');
310 366
311 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 367 $this->assertSame(302, $client->getResponse()->getStatusCode());
312 $this->assertEquals('/all/list', $client->getResponse()->getTargetUrl()); 368 $this->assertSame('/all/list', $client->getResponse()->getTargetUrl());
313 } 369 }
314 370
315 /**
316 * @depends testPostNewOk
317 */
318 public function testView() 371 public function testView()
319 { 372 {
320 $this->logInAs('admin'); 373 $this->logInAs('admin');
321 $client = $this->getClient(); 374 $client = $this->getClient();
322 375
323 $content = $client->getContainer() 376 $entry = new Entry($this->getLoggedInUser());
324 ->get('doctrine.orm.entity_manager') 377 $entry->setUrl('http://example.com/foo');
325 ->getRepository('WallabagCoreBundle:Entry') 378 $entry->setTitle('title foo');
326 ->findByUrlAndUserId($this->url, $this->getLoggedInUserId()); 379 $entry->setContent('foo bar baz');
380 $this->getEntityManager()->persist($entry);
381 $this->getEntityManager()->flush();
327 382
328 $crawler = $client->request('GET', '/view/'.$content->getId()); 383 $crawler = $client->request('GET', '/view/' . $entry->getId());
329 384
330 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 385 $this->assertSame(200, $client->getResponse()->getStatusCode());
331 $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text'])); 386 $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
332 $this->assertContains($content->getTitle(), $body[0]); 387 $this->assertContains($entry->getTitle(), $body[0]);
333 } 388 }
334 389
335 /** 390 /**
336 * @depends testPostNewOk
337 *
338 * This test will require an internet connection. 391 * This test will require an internet connection.
339 */ 392 */
340 public function testReload() 393 public function testReload()
@@ -342,65 +395,47 @@ class EntryControllerTest extends WallabagCoreTestCase
342 $this->logInAs('admin'); 395 $this->logInAs('admin');
343 $client = $this->getClient(); 396 $client = $this->getClient();
344 397
345 $em = $client->getContainer() 398 $entry = new Entry($this->getLoggedInUser());
346 ->get('doctrine.orm.entity_manager'); 399 $entry->setUrl($this->url);
347 400 $entry->setTitle('title foo');
348 $content = $em 401 $entry->setContent('');
349 ->getRepository('WallabagCoreBundle:Entry') 402 $this->getEntityManager()->persist($entry);
350 ->findByUrlAndUserId($this->url, $this->getLoggedInUserId()); 403 $this->getEntityManager()->flush();
351 404 $this->getEntityManager()->clear();
352 // empty content
353 $content->setContent('');
354 $em->persist($content);
355 $em->flush();
356 405
357 $client->request('GET', '/reload/'.$content->getId()); 406 $client->request('GET', '/reload/' . $entry->getId());
358 407
359 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 408 $this->assertSame(302, $client->getResponse()->getStatusCode());
360 409
361 $content = $em 410 $entry = $this->getEntityManager()
362 ->getRepository('WallabagCoreBundle:Entry') 411 ->getRepository('WallabagCoreBundle:Entry')
363 ->find($content->getId()); 412 ->find($entry->getId());
364 413
365 $this->assertNotEmpty($content->getContent()); 414 $this->assertNotEmpty($entry->getContent());
366 } 415 }
367 416
368 /**
369 * @depends testPostNewOk
370 */
371 public function testReloadWithFetchingFailed() 417 public function testReloadWithFetchingFailed()
372 { 418 {
373 $this->logInAs('admin'); 419 $this->logInAs('admin');
374 $client = $this->getClient(); 420 $client = $this->getClient();
375 421
376 $em = $client->getContainer() 422 $entry = new Entry($this->getLoggedInUser());
377 ->get('doctrine.orm.entity_manager'); 423 $entry->setUrl('http://0.0.0.0/failed.html');
424 $this->getEntityManager()->persist($entry);
425 $this->getEntityManager()->flush();
378 426
379 $content = $em 427 $client->request('GET', '/reload/' . $entry->getId());
380 ->getRepository('WallabagCoreBundle:Entry')
381 ->findByUrlAndUserId($this->url, $this->getLoggedInUserId());
382 428
383 // put a known failed url 429 $this->assertSame(302, $client->getResponse()->getStatusCode());
384 $content->setUrl('http://0.0.0.0/failed.html');
385 $em->persist($content);
386 $em->flush();
387
388 $client->request('GET', '/reload/'.$content->getId());
389
390 $this->assertEquals(302, $client->getResponse()->getStatusCode());
391 430
392 // force EntityManager to clear previous entity 431 // force EntityManager to clear previous entity
393 // otherwise, retrieve the same entity will retrieve change from the previous request :0 432 // otherwise, retrieve the same entity will retrieve change from the previous request :0
394 $em->clear(); 433 $this->getEntityManager()->clear();
395 $newContent = $em 434 $newContent = $this->getEntityManager()
396 ->getRepository('WallabagCoreBundle:Entry') 435 ->getRepository('WallabagCoreBundle:Entry')
397 ->find($content->getId()); 436 ->find($entry->getId());
398 437
399 $newContent->setUrl($this->url); 438 $this->assertNotSame($client->getContainer()->getParameter('wallabag_core.fetching_error_message'), $newContent->getContent());
400 $em->persist($newContent);
401 $em->flush();
402
403 $this->assertNotEquals($client->getContainer()->getParameter('wallabag_core.fetching_error_message'), $newContent->getContent());
404 } 439 }
405 440
406 public function testEdit() 441 public function testEdit()
@@ -408,14 +443,14 @@ class EntryControllerTest extends WallabagCoreTestCase
408 $this->logInAs('admin'); 443 $this->logInAs('admin');
409 $client = $this->getClient(); 444 $client = $this->getClient();
410 445
411 $content = $client->getContainer() 446 $entry = new Entry($this->getLoggedInUser());
412 ->get('doctrine.orm.entity_manager') 447 $entry->setUrl($this->url);
413 ->getRepository('WallabagCoreBundle:Entry') 448 $this->getEntityManager()->persist($entry);
414 ->findByUrlAndUserId($this->url, $this->getLoggedInUserId()); 449 $this->getEntityManager()->flush();
415 450
416 $crawler = $client->request('GET', '/edit/'.$content->getId()); 451 $crawler = $client->request('GET', '/edit/' . $entry->getId());
417 452
418 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 453 $this->assertSame(200, $client->getResponse()->getStatusCode());
419 454
420 $this->assertCount(1, $crawler->filter('input[id=entry_title]')); 455 $this->assertCount(1, $crawler->filter('input[id=entry_title]'));
421 $this->assertCount(1, $crawler->filter('button[id=entry_save]')); 456 $this->assertCount(1, $crawler->filter('button[id=entry_save]'));
@@ -426,14 +461,14 @@ class EntryControllerTest extends WallabagCoreTestCase
426 $this->logInAs('admin'); 461 $this->logInAs('admin');
427 $client = $this->getClient(); 462 $client = $this->getClient();
428 463
429 $content = $client->getContainer() 464 $entry = new Entry($this->getLoggedInUser());
430 ->get('doctrine.orm.entity_manager') 465 $entry->setUrl($this->url);
431 ->getRepository('WallabagCoreBundle:Entry') 466 $this->getEntityManager()->persist($entry);
432 ->findByUrlAndUserId($this->url, $this->getLoggedInUserId()); 467 $this->getEntityManager()->flush();
433 468
434 $crawler = $client->request('GET', '/edit/'.$content->getId()); 469 $crawler = $client->request('GET', '/edit/' . $entry->getId());
435 470
436 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 471 $this->assertSame(200, $client->getResponse()->getStatusCode());
437 472
438 $form = $crawler->filter('button[type=submit]')->form(); 473 $form = $crawler->filter('button[type=submit]')->form();
439 474
@@ -443,7 +478,7 @@ class EntryControllerTest extends WallabagCoreTestCase
443 478
444 $client->submit($form, $data); 479 $client->submit($form, $data);
445 480
446 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 481 $this->assertSame(302, $client->getResponse()->getStatusCode());
447 482
448 $crawler = $client->followRedirect(); 483 $crawler = $client->followRedirect();
449 484
@@ -456,21 +491,22 @@ class EntryControllerTest extends WallabagCoreTestCase
456 $this->logInAs('admin'); 491 $this->logInAs('admin');
457 $client = $this->getClient(); 492 $client = $this->getClient();
458 493
459 $content = $client->getContainer() 494 $entry = new Entry($this->getLoggedInUser());
460 ->get('doctrine.orm.entity_manager') 495 $entry->setUrl($this->url);
461 ->getRepository('WallabagCoreBundle:Entry') 496 $this->getEntityManager()->persist($entry);
462 ->findByUrlAndUserId($this->url, $this->getLoggedInUserId()); 497 $this->getEntityManager()->flush();
498 $this->getEntityManager()->clear();
463 499
464 $client->request('GET', '/archive/'.$content->getId()); 500 $client->request('GET', '/archive/' . $entry->getId());
465 501
466 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 502 $this->assertSame(302, $client->getResponse()->getStatusCode());
467 503
468 $res = $client->getContainer() 504 $res = $client->getContainer()
469 ->get('doctrine.orm.entity_manager') 505 ->get('doctrine.orm.entity_manager')
470 ->getRepository('WallabagCoreBundle:Entry') 506 ->getRepository('WallabagCoreBundle:Entry')
471 ->find($content->getId()); 507 ->find($entry->getId());
472 508
473 $this->assertEquals($res->isArchived(), true); 509 $this->assertSame(1, $res->isArchived());
474 } 510 }
475 511
476 public function testToggleStar() 512 public function testToggleStar()
@@ -478,21 +514,22 @@ class EntryControllerTest extends WallabagCoreTestCase
478 $this->logInAs('admin'); 514 $this->logInAs('admin');
479 $client = $this->getClient(); 515 $client = $this->getClient();
480 516
481 $content = $client->getContainer() 517 $entry = new Entry($this->getLoggedInUser());
482 ->get('doctrine.orm.entity_manager') 518 $entry->setUrl($this->url);
483 ->getRepository('WallabagCoreBundle:Entry') 519 $this->getEntityManager()->persist($entry);
484 ->findByUrlAndUserId($this->url, $this->getLoggedInUserId()); 520 $this->getEntityManager()->flush();
521 $this->getEntityManager()->clear();
485 522
486 $client->request('GET', '/star/'.$content->getId()); 523 $client->request('GET', '/star/' . $entry->getId());
487 524
488 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 525 $this->assertSame(302, $client->getResponse()->getStatusCode());
489 526
490 $res = $client->getContainer() 527 $res = $client->getContainer()
491 ->get('doctrine.orm.entity_manager') 528 ->get('doctrine.orm.entity_manager')
492 ->getRepository('WallabagCoreBundle:Entry') 529 ->getRepository('WallabagCoreBundle:Entry')
493 ->findOneById($content->getId()); 530 ->findOneById($entry->getId());
494 531
495 $this->assertEquals($res->isStarred(), true); 532 $this->assertSame(1, $res->isStarred());
496 } 533 }
497 534
498 public function testDelete() 535 public function testDelete()
@@ -500,18 +537,18 @@ class EntryControllerTest extends WallabagCoreTestCase
500 $this->logInAs('admin'); 537 $this->logInAs('admin');
501 $client = $this->getClient(); 538 $client = $this->getClient();
502 539
503 $content = $client->getContainer() 540 $entry = new Entry($this->getLoggedInUser());
504 ->get('doctrine.orm.entity_manager') 541 $entry->setUrl($this->url);
505 ->getRepository('WallabagCoreBundle:Entry') 542 $this->getEntityManager()->persist($entry);
506 ->findByUrlAndUserId($this->url, $this->getLoggedInUserId()); 543 $this->getEntityManager()->flush();
507 544
508 $client->request('GET', '/delete/'.$content->getId()); 545 $client->request('GET', '/delete/' . $entry->getId());
509 546
510 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 547 $this->assertSame(302, $client->getResponse()->getStatusCode());
511 548
512 $client->request('GET', '/delete/'.$content->getId()); 549 $client->request('GET', '/delete/' . $entry->getId());
513 550
514 $this->assertEquals(404, $client->getResponse()->getStatusCode()); 551 $this->assertSame(404, $client->getResponse()->getStatusCode());
515 } 552 }
516 553
517 /** 554 /**
@@ -547,14 +584,14 @@ class EntryControllerTest extends WallabagCoreTestCase
547 $em->persist($content); 584 $em->persist($content);
548 $em->flush(); 585 $em->flush();
549 586
550 $client->request('GET', '/view/'.$content->getId()); 587 $client->request('GET', '/view/' . $content->getId());
551 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 588 $this->assertSame(200, $client->getResponse()->getStatusCode());
552 589
553 $client->request('GET', '/delete/'.$content->getId()); 590 $client->request('GET', '/delete/' . $content->getId());
554 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 591 $this->assertSame(302, $client->getResponse()->getStatusCode());
555 592
556 $client->followRedirect(); 593 $client->followRedirect();
557 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 594 $this->assertSame(200, $client->getResponse()->getStatusCode());
558 } 595 }
559 596
560 public function testViewOtherUserEntry() 597 public function testViewOtherUserEntry()
@@ -567,15 +604,21 @@ class EntryControllerTest extends WallabagCoreTestCase
567 ->getRepository('WallabagCoreBundle:Entry') 604 ->getRepository('WallabagCoreBundle:Entry')
568 ->findOneByUsernameAndNotArchived('bob'); 605 ->findOneByUsernameAndNotArchived('bob');
569 606
570 $client->request('GET', '/view/'.$content->getId()); 607 $client->request('GET', '/view/' . $content->getId());
571 608
572 $this->assertEquals(403, $client->getResponse()->getStatusCode()); 609 $this->assertSame(403, $client->getResponse()->getStatusCode());
573 } 610 }
574 611
575 public function testFilterOnReadingTime() 612 public function testFilterOnReadingTime()
576 { 613 {
577 $this->logInAs('admin'); 614 $this->logInAs('admin');
615 $this->useTheme('baggy');
578 $client = $this->getClient(); 616 $client = $this->getClient();
617 $entry = new Entry($this->getLoggedInUser());
618 $entry->setUrl($this->url);
619 $entry->setReadingTime(22);
620 $this->getEntityManager()->persist($entry);
621 $this->getEntityManager()->flush();
579 622
580 $crawler = $client->request('GET', '/unread/list'); 623 $crawler = $client->request('GET', '/unread/list');
581 624
@@ -614,9 +657,20 @@ class EntryControllerTest extends WallabagCoreTestCase
614 public function testFilterOnReadingTimeOnlyUpper() 657 public function testFilterOnReadingTimeOnlyUpper()
615 { 658 {
616 $this->logInAs('admin'); 659 $this->logInAs('admin');
660 $this->useTheme('baggy');
617 $client = $this->getClient(); 661 $client = $this->getClient();
618 662
619 $crawler = $client->request('GET', '/unread/list'); 663 $crawler = $client->request('GET', '/all/list');
664 $this->assertCount(5, $crawler->filter('div[class=entry]'));
665
666 $entry = new Entry($this->getLoggedInUser());
667 $entry->setUrl($this->url);
668 $entry->setReadingTime(23);
669 $this->getEntityManager()->persist($entry);
670 $this->getEntityManager()->flush();
671
672 $crawler = $client->request('GET', '/all/list');
673 $this->assertCount(6, $crawler->filter('div[class=entry]'));
620 674
621 $form = $crawler->filter('button[id=submit-filter]')->form(); 675 $form = $crawler->filter('button[id=submit-filter]')->form();
622 676
@@ -626,12 +680,13 @@ class EntryControllerTest extends WallabagCoreTestCase
626 680
627 $crawler = $client->submit($form, $data); 681 $crawler = $client->submit($form, $data);
628 682
629 $this->assertCount(2, $crawler->filter('div[class=entry]')); 683 $this->assertCount(5, $crawler->filter('div[class=entry]'));
630 } 684 }
631 685
632 public function testFilterOnReadingTimeOnlyLower() 686 public function testFilterOnReadingTimeOnlyLower()
633 { 687 {
634 $this->logInAs('admin'); 688 $this->logInAs('admin');
689 $this->useTheme('baggy');
635 $client = $this->getClient(); 690 $client = $this->getClient();
636 691
637 $crawler = $client->request('GET', '/unread/list'); 692 $crawler = $client->request('GET', '/unread/list');
@@ -644,12 +699,22 @@ class EntryControllerTest extends WallabagCoreTestCase
644 699
645 $crawler = $client->submit($form, $data); 700 $crawler = $client->submit($form, $data);
646 701
647 $this->assertCount(4, $crawler->filter('div[class=entry]')); 702 $this->assertCount(0, $crawler->filter('div[class=entry]'));
703
704 $entry = new Entry($this->getLoggedInUser());
705 $entry->setUrl($this->url);
706 $entry->setReadingTime(23);
707 $this->getEntityManager()->persist($entry);
708 $this->getEntityManager()->flush();
709
710 $crawler = $client->submit($form, $data);
711 $this->assertCount(1, $crawler->filter('div[class=entry]'));
648 } 712 }
649 713
650 public function testFilterOnUnreadStatus() 714 public function testFilterOnUnreadStatus()
651 { 715 {
652 $this->logInAs('admin'); 716 $this->logInAs('admin');
717 $this->useTheme('baggy');
653 $client = $this->getClient(); 718 $client = $this->getClient();
654 719
655 $crawler = $client->request('GET', '/all/list'); 720 $crawler = $client->request('GET', '/all/list');
@@ -663,11 +728,22 @@ class EntryControllerTest extends WallabagCoreTestCase
663 $crawler = $client->submit($form, $data); 728 $crawler = $client->submit($form, $data);
664 729
665 $this->assertCount(4, $crawler->filter('div[class=entry]')); 730 $this->assertCount(4, $crawler->filter('div[class=entry]'));
731
732 $entry = new Entry($this->getLoggedInUser());
733 $entry->setUrl($this->url);
734 $entry->setArchived(false);
735 $this->getEntityManager()->persist($entry);
736 $this->getEntityManager()->flush();
737
738 $crawler = $client->submit($form, $data);
739
740 $this->assertCount(5, $crawler->filter('div[class=entry]'));
666 } 741 }
667 742
668 public function testFilterOnCreationDate() 743 public function testFilterOnCreationDate()
669 { 744 {
670 $this->logInAs('admin'); 745 $this->logInAs('admin');
746 $this->useTheme('baggy');
671 $client = $this->getClient(); 747 $client = $this->getClient();
672 748
673 $crawler = $client->request('GET', '/unread/list'); 749 $crawler = $client->request('GET', '/unread/list');
@@ -718,7 +794,7 @@ class EntryControllerTest extends WallabagCoreTestCase
718 794
719 $parameters = '?entry_filter%5BreadingTime%5D%5Bleft_number%5D=&entry_filter%5BreadingTime%5D%5Bright_number%5D='; 795 $parameters = '?entry_filter%5BreadingTime%5D%5Bleft_number%5D=&entry_filter%5BreadingTime%5D%5Bright_number%5D=';
720 796
721 $client->request('GET', 'unread/list'.$parameters); 797 $client->request('GET', 'unread/list' . $parameters);
722 798
723 $this->assertContains($parameters, $client->getResponse()->getContent()); 799 $this->assertContains($parameters, $client->getResponse()->getContent());
724 800
@@ -734,6 +810,7 @@ class EntryControllerTest extends WallabagCoreTestCase
734 public function testFilterOnDomainName() 810 public function testFilterOnDomainName()
735 { 811 {
736 $this->logInAs('admin'); 812 $this->logInAs('admin');
813 $this->useTheme('baggy');
737 $client = $this->getClient(); 814 $client = $this->getClient();
738 815
739 $crawler = $client->request('GET', '/unread/list'); 816 $crawler = $client->request('GET', '/unread/list');
@@ -766,6 +843,7 @@ class EntryControllerTest extends WallabagCoreTestCase
766 public function testFilterOnStatus() 843 public function testFilterOnStatus()
767 { 844 {
768 $this->logInAs('admin'); 845 $this->logInAs('admin');
846 $this->useTheme('baggy');
769 $client = $this->getClient(); 847 $client = $this->getClient();
770 848
771 $crawler = $client->request('GET', '/unread/list'); 849 $crawler = $client->request('GET', '/unread/list');
@@ -784,9 +862,24 @@ class EntryControllerTest extends WallabagCoreTestCase
784 $this->assertCount(1, $crawler->filter('div[class=entry]')); 862 $this->assertCount(1, $crawler->filter('div[class=entry]'));
785 } 863 }
786 864
865 public function testFilterOnIsPublic()
866 {
867 $this->logInAs('admin');
868 $this->useTheme('baggy');
869 $client = $this->getClient();
870
871 $crawler = $client->request('GET', '/unread/list');
872 $form = $crawler->filter('button[id=submit-filter]')->form();
873 $form['entry_filter[isPublic]']->tick();
874
875 $crawler = $client->submit($form);
876 $this->assertCount(0, $crawler->filter('div[class=entry]'));
877 }
878
787 public function testPreviewPictureFilter() 879 public function testPreviewPictureFilter()
788 { 880 {
789 $this->logInAs('admin'); 881 $this->logInAs('admin');
882 $this->useTheme('baggy');
790 $client = $this->getClient(); 883 $client = $this->getClient();
791 884
792 $crawler = $client->request('GET', '/unread/list'); 885 $crawler = $client->request('GET', '/unread/list');
@@ -800,8 +893,15 @@ class EntryControllerTest extends WallabagCoreTestCase
800 public function testFilterOnLanguage() 893 public function testFilterOnLanguage()
801 { 894 {
802 $this->logInAs('admin'); 895 $this->logInAs('admin');
896 $this->useTheme('baggy');
803 $client = $this->getClient(); 897 $client = $this->getClient();
804 898
899 $entry = new Entry($this->getLoggedInUser());
900 $entry->setUrl($this->url);
901 $entry->setLanguage('fr');
902 $this->getEntityManager()->persist($entry);
903 $this->getEntityManager()->flush();
904
805 $crawler = $client->request('GET', '/unread/list'); 905 $crawler = $client->request('GET', '/unread/list');
806 $form = $crawler->filter('button[id=submit-filter]')->form(); 906 $form = $crawler->filter('button[id=submit-filter]')->form();
807 $data = [ 907 $data = [
@@ -809,7 +909,7 @@ class EntryControllerTest extends WallabagCoreTestCase
809 ]; 909 ];
810 910
811 $crawler = $client->submit($form, $data); 911 $crawler = $client->submit($form, $data);
812 $this->assertCount(2, $crawler->filter('div[class=entry]')); 912 $this->assertCount(3, $crawler->filter('div[class=entry]'));
813 913
814 $form = $crawler->filter('button[id=submit-filter]')->form(); 914 $form = $crawler->filter('button[id=submit-filter]')->form();
815 $data = [ 915 $data = [
@@ -825,22 +925,26 @@ class EntryControllerTest extends WallabagCoreTestCase
825 $this->logInAs('admin'); 925 $this->logInAs('admin');
826 $client = $this->getClient(); 926 $client = $this->getClient();
827 927
828 $content = $client->getContainer() 928 // sharing is enabled
829 ->get('doctrine.orm.entity_manager') 929 $client->getContainer()->get('craue_config')->set('share_public', 1);
830 ->getRepository('WallabagCoreBundle:Entry') 930
831 ->findOneByUser($this->getLoggedInUserId()); 931 $content = new Entry($this->getLoggedInUser());
932 $content->setUrl($this->url);
933 $this->getEntityManager()->persist($content);
934 $this->getEntityManager()->flush();
935 $this->getEntityManager()->clear();
832 936
833 // no uid 937 // no uid
834 $client->request('GET', '/share/'.$content->getUid()); 938 $client->request('GET', '/share/' . $content->getUid());
835 $this->assertEquals(404, $client->getResponse()->getStatusCode()); 939 $this->assertSame(404, $client->getResponse()->getStatusCode());
836 940
837 // generating the uid 941 // generating the uid
838 $client->request('GET', '/share/'.$content->getId()); 942 $client->request('GET', '/share/' . $content->getId());
839 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 943 $this->assertSame(302, $client->getResponse()->getStatusCode());
840 944
841 // follow link with uid 945 // follow link with uid
842 $crawler = $client->followRedirect(); 946 $crawler = $client->followRedirect();
843 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 947 $this->assertSame(200, $client->getResponse()->getStatusCode());
844 $this->assertContains('max-age=25200', $client->getResponse()->headers->get('cache-control')); 948 $this->assertContains('max-age=25200', $client->getResponse()->headers->get('cache-control'));
845 $this->assertContains('public', $client->getResponse()->headers->get('cache-control')); 949 $this->assertContains('public', $client->getResponse()->headers->get('cache-control'));
846 $this->assertContains('s-maxage=25200', $client->getResponse()->headers->get('cache-control')); 950 $this->assertContains('s-maxage=25200', $client->getResponse()->headers->get('cache-control'));
@@ -852,23 +956,24 @@ class EntryControllerTest extends WallabagCoreTestCase
852 956
853 // sharing is now disabled 957 // sharing is now disabled
854 $client->getContainer()->get('craue_config')->set('share_public', 0); 958 $client->getContainer()->get('craue_config')->set('share_public', 0);
855 $client->request('GET', '/share/'.$content->getUid()); 959 $client->request('GET', '/share/' . $content->getUid());
856 $this->assertEquals(404, $client->getResponse()->getStatusCode()); 960 $this->assertSame(404, $client->getResponse()->getStatusCode());
857 961
858 $client->request('GET', '/view/'.$content->getId()); 962 $client->request('GET', '/view/' . $content->getId());
859 $this->assertContains('no-cache', $client->getResponse()->headers->get('cache-control')); 963 $this->assertContains('no-cache', $client->getResponse()->headers->get('cache-control'));
860 964
861 // removing the share 965 // removing the share
862 $client->request('GET', '/share/delete/'.$content->getId()); 966 $client->request('GET', '/share/delete/' . $content->getId());
863 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 967 $this->assertSame(302, $client->getResponse()->getStatusCode());
864 968
865 // share is now disable 969 // share is now disable
866 $client->request('GET', '/share/'.$content->getUid()); 970 $client->request('GET', '/share/' . $content->getUid());
867 $this->assertEquals(404, $client->getResponse()->getStatusCode()); 971 $this->assertSame(404, $client->getResponse()->getStatusCode());
868 } 972 }
869 973
870 public function testNewEntryWithDownloadImagesEnabled() 974 public function testNewEntryWithDownloadImagesEnabled()
871 { 975 {
976 $this->downloadImagesEnabled = true;
872 $this->logInAs('admin'); 977 $this->logInAs('admin');
873 $client = $this->getClient(); 978 $client = $this->getClient();
874 979
@@ -877,7 +982,7 @@ class EntryControllerTest extends WallabagCoreTestCase
877 982
878 $crawler = $client->request('GET', '/new'); 983 $crawler = $client->request('GET', '/new');
879 984
880 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 985 $this->assertSame(200, $client->getResponse()->getStatusCode());
881 986
882 $form = $crawler->filter('form[name=entry]')->form(); 987 $form = $crawler->filter('form[name=entry]')->form();
883 988
@@ -887,7 +992,7 @@ class EntryControllerTest extends WallabagCoreTestCase
887 992
888 $client->submit($form, $data); 993 $client->submit($form, $data);
889 994
890 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 995 $this->assertSame(302, $client->getResponse()->getStatusCode());
891 996
892 $em = $client->getContainer() 997 $em = $client->getContainer()
893 ->get('doctrine.orm.entity_manager'); 998 ->get('doctrine.orm.entity_manager');
@@ -897,9 +1002,10 @@ class EntryControllerTest extends WallabagCoreTestCase
897 ->findByUrlAndUserId($url, $this->getLoggedInUserId()); 1002 ->findByUrlAndUserId($url, $this->getLoggedInUserId());
898 1003
899 $this->assertInstanceOf('Wallabag\CoreBundle\Entity\Entry', $entry); 1004 $this->assertInstanceOf('Wallabag\CoreBundle\Entity\Entry', $entry);
900 $this->assertEquals($url, $entry->getUrl()); 1005 $this->assertSame($url, $entry->getUrl());
901 $this->assertContains('Perpignan', $entry->getTitle()); 1006 $this->assertContains('Perpignan', $entry->getTitle());
902 $this->assertContains('/d9bc0fcd.jpeg', $entry->getContent()); 1007 // instead of checking for the filename (which might change) check that the image is now local
1008 $this->assertContains($client->getContainer()->getParameter('domain_name') . '/assets/images/', $entry->getContent());
903 1009
904 $client->getContainer()->get('craue_config')->set('download_images_enabled', 0); 1010 $client->getContainer()->get('craue_config')->set('download_images_enabled', 0);
905 } 1011 }
@@ -909,20 +1015,35 @@ class EntryControllerTest extends WallabagCoreTestCase
909 */ 1015 */
910 public function testRemoveEntryWithDownloadImagesEnabled() 1016 public function testRemoveEntryWithDownloadImagesEnabled()
911 { 1017 {
1018 $this->downloadImagesEnabled = true;
912 $this->logInAs('admin'); 1019 $this->logInAs('admin');
913 $client = $this->getClient(); 1020 $client = $this->getClient();
914 1021
915 $url = 'http://www.20minutes.fr/montpellier/1952003-20161030-video-car-tombe-panne-rugbymen-perpignan-improvisent-melee-route'; 1022 $url = 'http://www.20minutes.fr/montpellier/1952003-20161030-video-car-tombe-panne-rugbymen-perpignan-improvisent-melee-route';
916 $client->getContainer()->get('craue_config')->set('download_images_enabled', 1); 1023 $client->getContainer()->get('craue_config')->set('download_images_enabled', 1);
917 1024
1025 $crawler = $client->request('GET', '/new');
1026
1027 $this->assertSame(200, $client->getResponse()->getStatusCode());
1028
1029 $form = $crawler->filter('form[name=entry]')->form();
1030
1031 $data = [
1032 'entry[url]' => $url,
1033 ];
1034
1035 $client->submit($form, $data);
1036
1037 $this->assertSame(302, $client->getResponse()->getStatusCode());
1038
918 $content = $client->getContainer() 1039 $content = $client->getContainer()
919 ->get('doctrine.orm.entity_manager') 1040 ->get('doctrine.orm.entity_manager')
920 ->getRepository('WallabagCoreBundle:Entry') 1041 ->getRepository('WallabagCoreBundle:Entry')
921 ->findByUrlAndUserId($url, $this->getLoggedInUserId()); 1042 ->findByUrlAndUserId($url, $this->getLoggedInUserId());
922 1043
923 $client->request('GET', '/delete/'.$content->getId()); 1044 $client->request('GET', '/delete/' . $content->getId());
924 1045
925 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 1046 $this->assertSame(302, $client->getResponse()->getStatusCode());
926 1047
927 $client->getContainer()->get('craue_config')->set('download_images_enabled', 0); 1048 $client->getContainer()->get('craue_config')->set('download_images_enabled', 0);
928 } 1049 }
@@ -932,31 +1053,22 @@ class EntryControllerTest extends WallabagCoreTestCase
932 $this->logInAs('empty'); 1053 $this->logInAs('empty');
933 $client = $this->getClient(); 1054 $client = $this->getClient();
934 1055
935 $em = $client->getContainer()->get('doctrine.orm.entity_manager');
936 $user = $em
937 ->getRepository('WallabagUserBundle:User')
938 ->find($this->getLoggedInUserId());
939
940 if (!$user) {
941 $this->markTestSkipped('No user found in db.');
942 }
943
944 // Redirect to homepage 1056 // Redirect to homepage
945 $config = $user->getConfig(); 1057 $config = $this->getLoggedInUser()->getConfig();
946 $config->setActionMarkAsRead(Config::REDIRECT_TO_HOMEPAGE); 1058 $config->setActionMarkAsRead(Config::REDIRECT_TO_HOMEPAGE);
947 $em->persist($config); 1059 $this->getEntityManager()->persist($config);
948 $em->flush();
949 1060
950 $content = $client->getContainer() 1061 $entry = new Entry($this->getLoggedInUser());
951 ->get('doctrine.orm.entity_manager') 1062 $entry->setUrl($this->url);
952 ->getRepository('WallabagCoreBundle:Entry') 1063 $this->getEntityManager()->persist($entry);
953 ->findByUrlAndUserId($this->url, $this->getLoggedInUserId()); 1064
1065 $this->getEntityManager()->flush();
954 1066
955 $client->request('GET', '/view/'.$content->getId()); 1067 $client->request('GET', '/view/' . $entry->getId());
956 $client->request('GET', '/archive/'.$content->getId()); 1068 $client->request('GET', '/archive/' . $entry->getId());
957 1069
958 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 1070 $this->assertSame(302, $client->getResponse()->getStatusCode());
959 $this->assertEquals('/', $client->getResponse()->headers->get('location')); 1071 $this->assertSame('/', $client->getResponse()->headers->get('location'));
960 } 1072 }
961 1073
962 public function testRedirectToCurrentPage() 1074 public function testRedirectToCurrentPage()
@@ -964,46 +1076,36 @@ class EntryControllerTest extends WallabagCoreTestCase
964 $this->logInAs('empty'); 1076 $this->logInAs('empty');
965 $client = $this->getClient(); 1077 $client = $this->getClient();
966 1078
967 $em = $client->getContainer()->get('doctrine.orm.entity_manager');
968 $user = $em
969 ->getRepository('WallabagUserBundle:User')
970 ->find($this->getLoggedInUserId());
971
972 if (!$user) {
973 $this->markTestSkipped('No user found in db.');
974 }
975
976 // Redirect to current page 1079 // Redirect to current page
977 $config = $user->getConfig(); 1080 $config = $this->getLoggedInUser()->getConfig();
978 $config->setActionMarkAsRead(Config::REDIRECT_TO_CURRENT_PAGE); 1081 $config->setActionMarkAsRead(Config::REDIRECT_TO_CURRENT_PAGE);
979 $em->persist($config); 1082 $this->getEntityManager()->persist($config);
980 $em->flush();
981 1083
982 $content = $client->getContainer() 1084 $entry = new Entry($this->getLoggedInUser());
983 ->get('doctrine.orm.entity_manager') 1085 $entry->setUrl($this->url);
984 ->getRepository('WallabagCoreBundle:Entry') 1086 $this->getEntityManager()->persist($entry);
985 ->findByUrlAndUserId($this->url, $this->getLoggedInUserId()); 1087
1088 $this->getEntityManager()->flush();
986 1089
987 $client->request('GET', '/view/'.$content->getId()); 1090 $client->request('GET', '/view/' . $entry->getId());
988 $client->request('GET', '/archive/'.$content->getId()); 1091 $client->request('GET', '/archive/' . $entry->getId());
989 1092
990 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 1093 $this->assertSame(302, $client->getResponse()->getStatusCode());
991 $this->assertContains('/view/'.$content->getId(), $client->getResponse()->headers->get('location')); 1094 $this->assertContains('/view/' . $entry->getId(), $client->getResponse()->headers->get('location'));
992 } 1095 }
993 1096
994 public function testFilterOnHttpStatus() 1097 public function testFilterOnHttpStatus()
995 { 1098 {
996 $this->logInAs('admin'); 1099 $this->logInAs('admin');
1100 $this->useTheme('baggy');
997 $client = $this->getClient(); 1101 $client = $this->getClient();
998 1102
999 $crawler = $client->request('GET', '/new'); 1103 $entry = new Entry($this->getLoggedInUser());
1000 $form = $crawler->filter('form[name=entry]')->form(); 1104 $entry->setUrl('http://www.lemonde.fr/incorrect-url/');
1105 $entry->setHttpStatus(404);
1106 $this->getEntityManager()->persist($entry);
1001 1107
1002 $data = [ 1108 $this->getEntityManager()->flush();
1003 'entry[url]' => 'http://www.lemonde.fr/incorrect-url/',
1004 ];
1005
1006 $client->submit($form, $data);
1007 1109
1008 $crawler = $client->request('GET', '/all/list'); 1110 $crawler = $client->request('GET', '/all/list');
1009 $form = $crawler->filter('button[id=submit-filter]')->form(); 1111 $form = $crawler->filter('button[id=submit-filter]')->form();
@@ -1016,14 +1118,17 @@ class EntryControllerTest extends WallabagCoreTestCase
1016 1118
1017 $this->assertCount(1, $crawler->filter('div[class=entry]')); 1119 $this->assertCount(1, $crawler->filter('div[class=entry]'));
1018 1120
1019 $crawler = $client->request('GET', '/new'); 1121 $entry = new Entry($this->getLoggedInUser());
1020 $form = $crawler->filter('form[name=entry]')->form(); 1122 $entry->setUrl($this->url);
1123 $entry->setHttpStatus(200);
1124 $this->getEntityManager()->persist($entry);
1021 1125
1022 $data = [ 1126 $entry = new Entry($this->getLoggedInUser());
1023 'entry[url]' => 'http://www.nextinpact.com/news/101235-wallabag-alternative-libre-a-pocket-creuse-petit-a-petit-son-nid.htm', 1127 $entry->setUrl('http://www.nextinpact.com/news/101235-wallabag-alternative-libre-a-pocket-creuse-petit-a-petit-son-nid.htm');
1024 ]; 1128 $entry->setHttpStatus(200);
1129 $this->getEntityManager()->persist($entry);
1025 1130
1026 $client->submit($form, $data); 1131 $this->getEntityManager()->flush();
1027 1132
1028 $crawler = $client->request('GET', '/all/list'); 1133 $crawler = $client->request('GET', '/all/list');
1029 $form = $crawler->filter('button[id=submit-filter]')->form(); 1134 $form = $crawler->filter('button[id=submit-filter]')->form();
@@ -1034,7 +1139,7 @@ class EntryControllerTest extends WallabagCoreTestCase
1034 1139
1035 $crawler = $client->submit($form, $data); 1140 $crawler = $client->submit($form, $data);
1036 1141
1037 $this->assertCount(1, $crawler->filter('div[class=entry]')); 1142 $this->assertCount(2, $crawler->filter('div[class=entry]'));
1038 1143
1039 $crawler = $client->request('GET', '/all/list'); 1144 $crawler = $client->request('GET', '/all/list');
1040 $form = $crawler->filter('button[id=submit-filter]')->form(); 1145 $form = $crawler->filter('button[id=submit-filter]')->form();
@@ -1045,14 +1150,21 @@ class EntryControllerTest extends WallabagCoreTestCase
1045 1150
1046 $crawler = $client->submit($form, $data); 1151 $crawler = $client->submit($form, $data);
1047 1152
1048 $this->assertCount(7, $crawler->filter('div[class=entry]')); 1153 $this->assertCount(8, $crawler->filter('div[class=entry]'));
1049 } 1154 }
1050 1155
1051 public function testSearch() 1156 public function testSearch()
1052 { 1157 {
1053 $this->logInAs('admin'); 1158 $this->logInAs('admin');
1159 $this->useTheme('baggy');
1054 $client = $this->getClient(); 1160 $client = $this->getClient();
1055 1161
1162 $entry = new Entry($this->getLoggedInUser());
1163 $entry->setUrl($this->url);
1164 $entry->setTitle('test');
1165 $this->getEntityManager()->persist($entry);
1166 $this->getEntityManager()->flush();
1167
1056 // Search on unread list 1168 // Search on unread list
1057 $crawler = $client->request('GET', '/unread/list'); 1169 $crawler = $client->request('GET', '/unread/list');
1058 1170
@@ -1063,35 +1175,37 @@ class EntryControllerTest extends WallabagCoreTestCase
1063 1175
1064 $crawler = $client->submit($form, $data); 1176 $crawler = $client->submit($form, $data);
1065 1177
1066 $this->assertCount(5, $crawler->filter('div[class=entry]')); 1178 $this->assertCount(4, $crawler->filter('div[class=entry]'));
1067 1179
1068 // Search on starred list 1180 // Search on starred list
1069 $crawler = $client->request('GET', '/starred/list'); 1181 $crawler = $client->request('GET', '/starred/list');
1070 1182
1183 $entry = new Entry($this->getLoggedInUser());
1184 $entry->setUrl('http://localhost/foo/bar');
1185 $entry->setTitle('testeur');
1186 $entry->setStarred(true);
1187 $this->getEntityManager()->persist($entry);
1188 $this->getEntityManager()->flush();
1189
1071 $form = $crawler->filter('form[name=search]')->form(); 1190 $form = $crawler->filter('form[name=search]')->form();
1072 $data = [ 1191 $data = [
1073 'search_entry[term]' => 'title', 1192 'search_entry[term]' => 'testeur',
1074 ]; 1193 ];
1075 1194
1076 $crawler = $client->submit($form, $data); 1195 $crawler = $client->submit($form, $data);
1077 1196
1078 $this->assertCount(1, $crawler->filter('div[class=entry]')); 1197 $this->assertCount(1, $crawler->filter('div[class=entry]'));
1079 1198
1080 // Added new article to test on archive list
1081 $crawler = $client->request('GET', '/new');
1082 $form = $crawler->filter('form[name=entry]')->form();
1083 $data = [
1084 'entry[url]' => $this->url,
1085 ];
1086 $client->submit($form, $data);
1087 $content = $client->getContainer()
1088 ->get('doctrine.orm.entity_manager')
1089 ->getRepository('WallabagCoreBundle:Entry')
1090 ->findByUrlAndUserId($this->url, $this->getLoggedInUserId());
1091 $client->request('GET', '/archive/'.$content->getId());
1092
1093 $crawler = $client->request('GET', '/archive/list'); 1199 $crawler = $client->request('GET', '/archive/list');
1094 1200
1201 // Added new article to test on archive list
1202 $entry = new Entry($this->getLoggedInUser());
1203 $entry->setUrl('http://0.0.0.0/foo/baz/qux');
1204 $entry->setTitle('Le manège');
1205 $entry->setArchived(true);
1206 $this->getEntityManager()->persist($entry);
1207 $this->getEntityManager()->flush();
1208
1095 $form = $crawler->filter('form[name=search]')->form(); 1209 $form = $crawler->filter('form[name=search]')->form();
1096 $data = [ 1210 $data = [
1097 'search_entry[term]' => 'manège', 1211 'search_entry[term]' => 'manège',
@@ -1100,7 +1214,7 @@ class EntryControllerTest extends WallabagCoreTestCase
1100 $crawler = $client->submit($form, $data); 1214 $crawler = $client->submit($form, $data);
1101 1215
1102 $this->assertCount(1, $crawler->filter('div[class=entry]')); 1216 $this->assertCount(1, $crawler->filter('div[class=entry]'));
1103 $client->request('GET', '/delete/'.$content->getId()); 1217 $client->request('GET', '/delete/' . $entry->getId());
1104 1218
1105 // test on list of all articles 1219 // test on list of all articles
1106 $crawler = $client->request('GET', '/all/list'); 1220 $crawler = $client->request('GET', '/all/list');
@@ -1115,6 +1229,13 @@ class EntryControllerTest extends WallabagCoreTestCase
1115 $this->assertCount(0, $crawler->filter('div[class=entry]')); 1229 $this->assertCount(0, $crawler->filter('div[class=entry]'));
1116 1230
1117 // test url search on list of all articles 1231 // test url search on list of all articles
1232 $entry = new Entry($this->getLoggedInUser());
1233 $entry->setUrl('http://domain/qux');
1234 $entry->setTitle('Le manège');
1235 $entry->setArchived(true);
1236 $this->getEntityManager()->persist($entry);
1237 $this->getEntityManager()->flush();
1238
1118 $crawler = $client->request('GET', '/all/list'); 1239 $crawler = $client->request('GET', '/all/list');
1119 1240
1120 $form = $crawler->filter('form[name=search]')->form(); 1241 $form = $crawler->filter('form[name=search]')->form();
@@ -1138,4 +1259,134 @@ class EntryControllerTest extends WallabagCoreTestCase
1138 1259
1139 $this->assertCount(1, $crawler->filter('div[class=entry]')); 1260 $this->assertCount(1, $crawler->filter('div[class=entry]'));
1140 } 1261 }
1262
1263 public function dataForLanguage()
1264 {
1265 return [
1266 'ru' => [
1267 'https://www.pravda.ru/world/09-06-2017/1337283-qatar-0/',
1268 'ru',
1269 ],
1270 'fr-FR' => [
1271 'http://www.zataz.com/90-des-dossiers-medicaux-des-coreens-du-sud-vendus-a-des-entreprises-privees/',
1272 'fr_FR',
1273 ],
1274 'de' => [
1275 'http://www.bild.de/politik/ausland/theresa-may/wahlbeben-grossbritannien-analyse-52108924.bild.html',
1276 'de',
1277 ],
1278 'it' => [
1279 'http://www.ansa.it/sito/notizie/mondo/europa/2017/06/08/voto-gb-seggi-aperti-misure-sicurezza-rafforzate_0cb71f7f-e23b-4d5f-95ca-bc12296419f0.html',
1280 'it',
1281 ],
1282 'zh_CN' => [
1283 'http://www.hao123.com/shequ?__noscript__-=1',
1284 'zh_CN',
1285 ],
1286 'de_AT' => [
1287 'https://buy.garmin.com/de-AT/AT/catalog/product/compareResult.ep?compareProduct=112885&compareProduct=36728',
1288 'de_AT',
1289 ],
1290 'ru_RU' => [
1291 'http://netler.ru/ikt/windows-error-reporting.htm',
1292 'ru_RU',
1293 ],
1294 'pt_BR' => [
1295 'http://precodoscombustiveis.com.br/postos/cidade/4121/pr/maringa',
1296 'pt_BR',
1297 ],
1298 'fucked_list_of_languages' => [
1299 'http://geocatalog.webservice-energy.org/geonetwork/srv/eng/main.home',
1300 null,
1301 ],
1302 'es-ES' => [
1303 'http://www.muylinux.com/2015/04/17/odf-reino-unido-microsoft-google/',
1304 'es_ES',
1305 ],
1306 ];
1307 }
1308
1309 /**
1310 * @dataProvider dataForLanguage
1311 */
1312 public function testLanguageValidation($url, $expectedLanguage)
1313 {
1314 $this->logInAs('admin');
1315 $client = $this->getClient();
1316
1317 $crawler = $client->request('GET', '/new');
1318
1319 $this->assertSame(200, $client->getResponse()->getStatusCode());
1320
1321 $form = $crawler->filter('form[name=entry]')->form();
1322
1323 $data = [
1324 'entry[url]' => $url,
1325 ];
1326
1327 $client->submit($form, $data);
1328
1329 $this->assertSame(302, $client->getResponse()->getStatusCode());
1330
1331 $content = $client->getContainer()
1332 ->get('doctrine.orm.entity_manager')
1333 ->getRepository('WallabagCoreBundle:Entry')
1334 ->findByUrlAndUserId($url, $this->getLoggedInUserId());
1335
1336 $this->assertInstanceOf('Wallabag\CoreBundle\Entity\Entry', $content);
1337 $this->assertSame($url, $content->getUrl());
1338 $this->assertSame($expectedLanguage, $content->getLanguage());
1339 }
1340
1341 /**
1342 * This test will require an internet connection.
1343 */
1344 public function testRestrictedArticle()
1345 {
1346 $url = 'http://www.monde-diplomatique.fr/2017/05/BONNET/57475';
1347 $this->logInAs('admin');
1348 $client = $this->getClient();
1349 $em = $client->getContainer()->get('doctrine.orm.entity_manager');
1350
1351 // enable restricted access
1352 $client->getContainer()->get('craue_config')->set('restricted_access', 1);
1353
1354 // create a new site_credential
1355 $user = $client->getContainer()->get('security.token_storage')->getToken()->getUser();
1356 $credential = new SiteCredential($user);
1357 $credential->setHost('monde-diplomatique.fr');
1358 $credential->setUsername($client->getContainer()->get('wallabag_core.helper.crypto_proxy')->crypt('foo'));
1359 $credential->setPassword($client->getContainer()->get('wallabag_core.helper.crypto_proxy')->crypt('bar'));
1360
1361 $em->persist($credential);
1362 $em->flush();
1363
1364 $crawler = $client->request('GET', '/new');
1365
1366 $this->assertSame(200, $client->getResponse()->getStatusCode());
1367
1368 $form = $crawler->filter('form[name=entry]')->form();
1369
1370 $data = [
1371 'entry[url]' => $url,
1372 ];
1373
1374 $client->submit($form, $data);
1375
1376 $this->assertSame(302, $client->getResponse()->getStatusCode());
1377
1378 $crawler = $client->followRedirect();
1379
1380 $this->assertSame(200, $client->getResponse()->getStatusCode());
1381 $this->assertContains('flashes.entry.notice.entry_saved', $crawler->filter('body')->extract(['_text'])[0]);
1382
1383 $content = $em
1384 ->getRepository('WallabagCoreBundle:Entry')
1385 ->findByUrlAndUserId($url, $this->getLoggedInUserId());
1386
1387 $this->assertInstanceOf('Wallabag\CoreBundle\Entity\Entry', $content);
1388 $this->assertSame('Crimes et réformes aux Philippines', $content->getTitle());
1389
1390 $client->getContainer()->get('craue_config')->set('restricted_access', 0);
1391 }
1141} 1392}
diff --git a/tests/Wallabag/CoreBundle/Controller/ExportControllerTest.php b/tests/Wallabag/CoreBundle/Controller/ExportControllerTest.php
index 32a18e26..3e216381 100644
--- a/tests/Wallabag/CoreBundle/Controller/ExportControllerTest.php
+++ b/tests/Wallabag/CoreBundle/Controller/ExportControllerTest.php
@@ -12,7 +12,7 @@ class ExportControllerTest extends WallabagCoreTestCase
12 12
13 $client->request('GET', '/export/unread.csv'); 13 $client->request('GET', '/export/unread.csv');
14 14
15 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 15 $this->assertSame(302, $client->getResponse()->getStatusCode());
16 $this->assertContains('login', $client->getResponse()->headers->get('location')); 16 $this->assertContains('login', $client->getResponse()->headers->get('location'));
17 } 17 }
18 18
@@ -23,7 +23,7 @@ class ExportControllerTest extends WallabagCoreTestCase
23 23
24 $client->request('GET', '/export/awesomeness.epub'); 24 $client->request('GET', '/export/awesomeness.epub');
25 25
26 $this->assertEquals(404, $client->getResponse()->getStatusCode()); 26 $this->assertSame(404, $client->getResponse()->getStatusCode());
27 } 27 }
28 28
29 public function testUnknownFormatExport() 29 public function testUnknownFormatExport()
@@ -33,7 +33,7 @@ class ExportControllerTest extends WallabagCoreTestCase
33 33
34 $client->request('GET', '/export/unread.xslx'); 34 $client->request('GET', '/export/unread.xslx');
35 35
36 $this->assertEquals(404, $client->getResponse()->getStatusCode()); 36 $this->assertSame(404, $client->getResponse()->getStatusCode());
37 } 37 }
38 38
39 public function testUnsupportedFormatExport() 39 public function testUnsupportedFormatExport()
@@ -42,15 +42,15 @@ class ExportControllerTest extends WallabagCoreTestCase
42 $client = $this->getClient(); 42 $client = $this->getClient();
43 43
44 $client->request('GET', '/export/unread.doc'); 44 $client->request('GET', '/export/unread.doc');
45 $this->assertEquals(404, $client->getResponse()->getStatusCode()); 45 $this->assertSame(404, $client->getResponse()->getStatusCode());
46 46
47 $content = $client->getContainer() 47 $content = $client->getContainer()
48 ->get('doctrine.orm.entity_manager') 48 ->get('doctrine.orm.entity_manager')
49 ->getRepository('WallabagCoreBundle:Entry') 49 ->getRepository('WallabagCoreBundle:Entry')
50 ->findOneByUsernameAndNotArchived('admin'); 50 ->findOneByUsernameAndNotArchived('admin');
51 51
52 $client->request('GET', '/export/'.$content->getId().'.doc'); 52 $client->request('GET', '/export/' . $content->getId() . '.doc');
53 $this->assertEquals(404, $client->getResponse()->getStatusCode()); 53 $this->assertSame(404, $client->getResponse()->getStatusCode());
54 } 54 }
55 55
56 public function testBadEntryId() 56 public function testBadEntryId()
@@ -60,7 +60,7 @@ class ExportControllerTest extends WallabagCoreTestCase
60 60
61 $client->request('GET', '/export/0.mobi'); 61 $client->request('GET', '/export/0.mobi');
62 62
63 $this->assertEquals(404, $client->getResponse()->getStatusCode()); 63 $this->assertSame(404, $client->getResponse()->getStatusCode());
64 } 64 }
65 65
66 public function testEpubExport() 66 public function testEpubExport()
@@ -72,12 +72,12 @@ class ExportControllerTest extends WallabagCoreTestCase
72 $crawler = $client->request('GET', '/export/archive.epub'); 72 $crawler = $client->request('GET', '/export/archive.epub');
73 ob_end_clean(); 73 ob_end_clean();
74 74
75 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 75 $this->assertSame(200, $client->getResponse()->getStatusCode());
76 76
77 $headers = $client->getResponse()->headers; 77 $headers = $client->getResponse()->headers;
78 $this->assertEquals('application/epub+zip', $headers->get('content-type')); 78 $this->assertSame('application/epub+zip', $headers->get('content-type'));
79 $this->assertEquals('attachment; filename="Archive articles.epub"', $headers->get('content-disposition')); 79 $this->assertSame('attachment; filename="Archive articles.epub"', $headers->get('content-disposition'));
80 $this->assertEquals('binary', $headers->get('content-transfer-encoding')); 80 $this->assertSame('binary', $headers->get('content-transfer-encoding'));
81 } 81 }
82 82
83 public function testMobiExport() 83 public function testMobiExport()
@@ -91,15 +91,15 @@ class ExportControllerTest extends WallabagCoreTestCase
91 ->findOneByUsernameAndNotArchived('admin'); 91 ->findOneByUsernameAndNotArchived('admin');
92 92
93 ob_start(); 93 ob_start();
94 $crawler = $client->request('GET', '/export/'.$content->getId().'.mobi'); 94 $crawler = $client->request('GET', '/export/' . $content->getId() . '.mobi');
95 ob_end_clean(); 95 ob_end_clean();
96 96
97 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 97 $this->assertSame(200, $client->getResponse()->getStatusCode());
98 98
99 $headers = $client->getResponse()->headers; 99 $headers = $client->getResponse()->headers;
100 $this->assertEquals('application/x-mobipocket-ebook', $headers->get('content-type')); 100 $this->assertSame('application/x-mobipocket-ebook', $headers->get('content-type'));
101 $this->assertEquals('attachment; filename="'.preg_replace('/[^A-Za-z0-9\-]/', '', $content->getTitle()).'.mobi"', $headers->get('content-disposition')); 101 $this->assertSame('attachment; filename="' . preg_replace('/[^A-Za-z0-9\-]/', '', $content->getTitle()) . '.mobi"', $headers->get('content-disposition'));
102 $this->assertEquals('binary', $headers->get('content-transfer-encoding')); 102 $this->assertSame('binary', $headers->get('content-transfer-encoding'));
103 } 103 }
104 104
105 public function testPdfExport() 105 public function testPdfExport()
@@ -111,23 +111,23 @@ class ExportControllerTest extends WallabagCoreTestCase
111 $crawler = $client->request('GET', '/export/all.pdf'); 111 $crawler = $client->request('GET', '/export/all.pdf');
112 ob_end_clean(); 112 ob_end_clean();
113 113
114 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 114 $this->assertSame(200, $client->getResponse()->getStatusCode());
115 115
116 $headers = $client->getResponse()->headers; 116 $headers = $client->getResponse()->headers;
117 $this->assertEquals('application/pdf', $headers->get('content-type')); 117 $this->assertSame('application/pdf', $headers->get('content-type'));
118 $this->assertEquals('attachment; filename="All articles.pdf"', $headers->get('content-disposition')); 118 $this->assertSame('attachment; filename="All articles.pdf"', $headers->get('content-disposition'));
119 $this->assertEquals('binary', $headers->get('content-transfer-encoding')); 119 $this->assertSame('binary', $headers->get('content-transfer-encoding'));
120 120
121 ob_start(); 121 ob_start();
122 $crawler = $client->request('GET', '/export/tag_entries.pdf?tag=foo-bar'); 122 $crawler = $client->request('GET', '/export/tag_entries.pdf?tag=foo-bar');
123 ob_end_clean(); 123 ob_end_clean();
124 124
125 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 125 $this->assertSame(200, $client->getResponse()->getStatusCode());
126 126
127 $headers = $client->getResponse()->headers; 127 $headers = $client->getResponse()->headers;
128 $this->assertEquals('application/pdf', $headers->get('content-type')); 128 $this->assertSame('application/pdf', $headers->get('content-type'));
129 $this->assertEquals('attachment; filename="Tag_entries articles.pdf"', $headers->get('content-disposition')); 129 $this->assertSame('attachment; filename="Tag_entries articles.pdf"', $headers->get('content-disposition'));
130 $this->assertEquals('binary', $headers->get('content-transfer-encoding')); 130 $this->assertSame('binary', $headers->get('content-transfer-encoding'));
131 } 131 }
132 132
133 public function testTxtExport() 133 public function testTxtExport()
@@ -139,12 +139,12 @@ class ExportControllerTest extends WallabagCoreTestCase
139 $crawler = $client->request('GET', '/export/all.txt'); 139 $crawler = $client->request('GET', '/export/all.txt');
140 ob_end_clean(); 140 ob_end_clean();
141 141
142 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 142 $this->assertSame(200, $client->getResponse()->getStatusCode());
143 143
144 $headers = $client->getResponse()->headers; 144 $headers = $client->getResponse()->headers;
145 $this->assertEquals('text/plain; charset=UTF-8', $headers->get('content-type')); 145 $this->assertSame('text/plain; charset=UTF-8', $headers->get('content-type'));
146 $this->assertEquals('attachment; filename="All articles.txt"', $headers->get('content-disposition')); 146 $this->assertSame('attachment; filename="All articles.txt"', $headers->get('content-disposition'));
147 $this->assertEquals('UTF-8', $headers->get('content-transfer-encoding')); 147 $this->assertSame('UTF-8', $headers->get('content-transfer-encoding'));
148 } 148 }
149 149
150 public function testCsvExport() 150 public function testCsvExport()
@@ -169,19 +169,19 @@ class ExportControllerTest extends WallabagCoreTestCase
169 $crawler = $client->request('GET', '/export/archive.csv'); 169 $crawler = $client->request('GET', '/export/archive.csv');
170 ob_end_clean(); 170 ob_end_clean();
171 171
172 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 172 $this->assertSame(200, $client->getResponse()->getStatusCode());
173 173
174 $headers = $client->getResponse()->headers; 174 $headers = $client->getResponse()->headers;
175 $this->assertEquals('application/csv', $headers->get('content-type')); 175 $this->assertSame('application/csv', $headers->get('content-type'));
176 $this->assertEquals('attachment; filename="Archive articles.csv"', $headers->get('content-disposition')); 176 $this->assertSame('attachment; filename="Archive articles.csv"', $headers->get('content-disposition'));
177 $this->assertEquals('UTF-8', $headers->get('content-transfer-encoding')); 177 $this->assertSame('UTF-8', $headers->get('content-transfer-encoding'));
178 178
179 $csv = str_getcsv($client->getResponse()->getContent(), "\n"); 179 $csv = str_getcsv($client->getResponse()->getContent(), "\n");
180 180
181 $this->assertGreaterThan(1, $csv); 181 $this->assertGreaterThan(1, $csv);
182 // +1 for title line 182 // +1 for title line
183 $this->assertEquals(count($contentInDB) + 1, count($csv)); 183 $this->assertSame(count($contentInDB) + 1, count($csv));
184 $this->assertEquals('Title;URL;Content;Tags;"MIME Type";Language;"Creation date"', $csv[0]); 184 $this->assertSame('Title;URL;Content;Tags;"MIME Type";Language;"Creation date"', $csv[0]);
185 $this->assertContains($contentInDB[0]['title'], $csv[1]); 185 $this->assertContains($contentInDB[0]['title'], $csv[1]);
186 $this->assertContains($contentInDB[0]['url'], $csv[1]); 186 $this->assertContains($contentInDB[0]['url'], $csv[1]);
187 $this->assertContains($contentInDB[0]['content'], $csv[1]); 187 $this->assertContains($contentInDB[0]['content'], $csv[1]);
@@ -189,11 +189,9 @@ class ExportControllerTest extends WallabagCoreTestCase
189 $this->assertContains($contentInDB[0]['language'], $csv[1]); 189 $this->assertContains($contentInDB[0]['language'], $csv[1]);
190 $this->assertContains($contentInDB[0]['createdAt']->format('d/m/Y h:i:s'), $csv[1]); 190 $this->assertContains($contentInDB[0]['createdAt']->format('d/m/Y h:i:s'), $csv[1]);
191 191
192 $expectedTag = [];
193 foreach ($contentInDB[0]['tags'] as $tag) { 192 foreach ($contentInDB[0]['tags'] as $tag) {
194 $expectedTag[] = $tag['label']; 193 $this->assertContains($tag['label'], $csv[1]);
195 } 194 }
196 $this->assertContains(implode(', ', $expectedTag), $csv[1]);
197 } 195 }
198 196
199 public function testJsonExport() 197 public function testJsonExport()
@@ -207,15 +205,15 @@ class ExportControllerTest extends WallabagCoreTestCase
207 ->findByUrlAndUserId('http://0.0.0.0/entry1', $this->getLoggedInUserId()); 205 ->findByUrlAndUserId('http://0.0.0.0/entry1', $this->getLoggedInUserId());
208 206
209 ob_start(); 207 ob_start();
210 $crawler = $client->request('GET', '/export/'.$contentInDB->getId().'.json'); 208 $crawler = $client->request('GET', '/export/' . $contentInDB->getId() . '.json');
211 ob_end_clean(); 209 ob_end_clean();
212 210
213 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 211 $this->assertSame(200, $client->getResponse()->getStatusCode());
214 212
215 $headers = $client->getResponse()->headers; 213 $headers = $client->getResponse()->headers;
216 $this->assertEquals('application/json', $headers->get('content-type')); 214 $this->assertSame('application/json', $headers->get('content-type'));
217 $this->assertEquals('attachment; filename="'.$contentInDB->getTitle().'.json"', $headers->get('content-disposition')); 215 $this->assertSame('attachment; filename="' . $contentInDB->getTitle() . '.json"', $headers->get('content-disposition'));
218 $this->assertEquals('UTF-8', $headers->get('content-transfer-encoding')); 216 $this->assertSame('UTF-8', $headers->get('content-transfer-encoding'));
219 217
220 $content = json_decode($client->getResponse()->getContent(), true); 218 $content = json_decode($client->getResponse()->getContent(), true);
221 $this->assertArrayHasKey('id', $content[0]); 219 $this->assertArrayHasKey('id', $content[0]);
@@ -232,16 +230,16 @@ class ExportControllerTest extends WallabagCoreTestCase
232 $this->assertArrayHasKey('created_at', $content[0]); 230 $this->assertArrayHasKey('created_at', $content[0]);
233 $this->assertArrayHasKey('updated_at', $content[0]); 231 $this->assertArrayHasKey('updated_at', $content[0]);
234 232
235 $this->assertEquals($contentInDB->isArchived(), $content[0]['is_archived']); 233 $this->assertSame((int) $contentInDB->isArchived(), $content[0]['is_archived']);
236 $this->assertEquals($contentInDB->isStarred(), $content[0]['is_starred']); 234 $this->assertSame((int) $contentInDB->isStarred(), $content[0]['is_starred']);
237 $this->assertEquals($contentInDB->getTitle(), $content[0]['title']); 235 $this->assertSame($contentInDB->getTitle(), $content[0]['title']);
238 $this->assertEquals($contentInDB->getUrl(), $content[0]['url']); 236 $this->assertSame($contentInDB->getUrl(), $content[0]['url']);
239 $this->assertEquals([['text' => 'This is my annotation /o/', 'quote' => 'content']], $content[0]['annotations']); 237 $this->assertSame([['text' => 'This is my annotation /o/', 'quote' => 'content']], $content[0]['annotations']);
240 $this->assertEquals($contentInDB->getMimetype(), $content[0]['mimetype']); 238 $this->assertSame($contentInDB->getMimetype(), $content[0]['mimetype']);
241 $this->assertEquals($contentInDB->getLanguage(), $content[0]['language']); 239 $this->assertSame($contentInDB->getLanguage(), $content[0]['language']);
242 $this->assertEquals($contentInDB->getReadingtime(), $content[0]['reading_time']); 240 $this->assertSame($contentInDB->getReadingtime(), $content[0]['reading_time']);
243 $this->assertEquals($contentInDB->getDomainname(), $content[0]['domain_name']); 241 $this->assertSame($contentInDB->getDomainname(), $content[0]['domain_name']);
244 $this->assertEquals(['foo bar', 'baz'], $content[0]['tags']); 242 $this->assertSame(['foo bar', 'baz'], $content[0]['tags']);
245 } 243 }
246 244
247 public function testXmlExport() 245 public function testXmlExport()
@@ -264,16 +262,16 @@ class ExportControllerTest extends WallabagCoreTestCase
264 $crawler = $client->request('GET', '/export/unread.xml'); 262 $crawler = $client->request('GET', '/export/unread.xml');
265 ob_end_clean(); 263 ob_end_clean();
266 264
267 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 265 $this->assertSame(200, $client->getResponse()->getStatusCode());
268 266
269 $headers = $client->getResponse()->headers; 267 $headers = $client->getResponse()->headers;
270 $this->assertEquals('application/xml', $headers->get('content-type')); 268 $this->assertSame('application/xml', $headers->get('content-type'));
271 $this->assertEquals('attachment; filename="Unread articles.xml"', $headers->get('content-disposition')); 269 $this->assertSame('attachment; filename="Unread articles.xml"', $headers->get('content-disposition'));
272 $this->assertEquals('UTF-8', $headers->get('content-transfer-encoding')); 270 $this->assertSame('UTF-8', $headers->get('content-transfer-encoding'));
273 271
274 $content = new \SimpleXMLElement($client->getResponse()->getContent()); 272 $content = new \SimpleXMLElement($client->getResponse()->getContent());
275 $this->assertGreaterThan(0, $content->count()); 273 $this->assertGreaterThan(0, $content->count());
276 $this->assertEquals(count($contentInDB), $content->count()); 274 $this->assertSame(count($contentInDB), $content->count());
277 $this->assertNotEmpty('id', (string) $content->entry[0]->id); 275 $this->assertNotEmpty('id', (string) $content->entry[0]->id);
278 $this->assertNotEmpty('title', (string) $content->entry[0]->title); 276 $this->assertNotEmpty('title', (string) $content->entry[0]->title);
279 $this->assertNotEmpty('url', (string) $content->entry[0]->url); 277 $this->assertNotEmpty('url', (string) $content->entry[0]->url);
diff --git a/tests/Wallabag/CoreBundle/Controller/RssControllerTest.php b/tests/Wallabag/CoreBundle/Controller/RssControllerTest.php
index 5a59654d..6167fe2d 100644
--- a/tests/Wallabag/CoreBundle/Controller/RssControllerTest.php
+++ b/tests/Wallabag/CoreBundle/Controller/RssControllerTest.php
@@ -6,7 +6,7 @@ use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
6 6
7class RssControllerTest extends WallabagCoreTestCase 7class RssControllerTest extends WallabagCoreTestCase
8{ 8{
9 public function validateDom($xml, $type, $nb = null) 9 public function validateDom($xml, $type, $urlPagination, $nb = null)
10 { 10 {
11 $doc = new \DOMDocument(); 11 $doc = new \DOMDocument();
12 $doc->loadXML($xml); 12 $doc->loadXML($xml);
@@ -16,36 +16,36 @@ class RssControllerTest extends WallabagCoreTestCase
16 if (null === $nb) { 16 if (null === $nb) {
17 $this->assertGreaterThan(0, $xpath->query('//item')->length); 17 $this->assertGreaterThan(0, $xpath->query('//item')->length);
18 } else { 18 } else {
19 $this->assertEquals($nb, $xpath->query('//item')->length); 19 $this->assertSame($nb, $xpath->query('//item')->length);
20 } 20 }
21 21
22 $this->assertEquals(1, $xpath->query('/rss')->length); 22 $this->assertSame(1, $xpath->query('/rss')->length);
23 $this->assertEquals(1, $xpath->query('/rss/channel')->length); 23 $this->assertSame(1, $xpath->query('/rss/channel')->length);
24 24
25 $this->assertEquals(1, $xpath->query('/rss/channel/title')->length); 25 $this->assertSame(1, $xpath->query('/rss/channel/title')->length);
26 $this->assertEquals('wallabag '.$type.' feed', $xpath->query('/rss/channel/title')->item(0)->nodeValue); 26 $this->assertSame('wallabag - ' . $type . ' feed', $xpath->query('/rss/channel/title')->item(0)->nodeValue);
27 27
28 $this->assertEquals(1, $xpath->query('/rss/channel/pubDate')->length); 28 $this->assertSame(1, $xpath->query('/rss/channel/pubDate')->length);
29 29
30 $this->assertEquals(1, $xpath->query('/rss/channel/generator')->length); 30 $this->assertSame(1, $xpath->query('/rss/channel/generator')->length);
31 $this->assertEquals('wallabag', $xpath->query('/rss/channel/generator')->item(0)->nodeValue); 31 $this->assertSame('wallabag', $xpath->query('/rss/channel/generator')->item(0)->nodeValue);
32 32
33 $this->assertEquals(1, $xpath->query('/rss/channel/description')->length); 33 $this->assertSame(1, $xpath->query('/rss/channel/description')->length);
34 $this->assertEquals('wallabag '.$type.' elements', $xpath->query('/rss/channel/description')->item(0)->nodeValue); 34 $this->assertSame('wallabag ' . $type . ' elements', $xpath->query('/rss/channel/description')->item(0)->nodeValue);
35 35
36 $this->assertEquals(1, $xpath->query('/rss/channel/link[@rel="self"]')->length); 36 $this->assertSame(1, $xpath->query('/rss/channel/link[@rel="self"]')->length);
37 $this->assertContains($type.'.xml', $xpath->query('/rss/channel/link[@rel="self"]')->item(0)->getAttribute('href')); 37 $this->assertContains($urlPagination . '.xml', $xpath->query('/rss/channel/link[@rel="self"]')->item(0)->getAttribute('href'));
38 38
39 $this->assertEquals(1, $xpath->query('/rss/channel/link[@rel="last"]')->length); 39 $this->assertSame(1, $xpath->query('/rss/channel/link[@rel="last"]')->length);
40 $this->assertContains($type.'.xml?page=', $xpath->query('/rss/channel/link[@rel="last"]')->item(0)->getAttribute('href')); 40 $this->assertContains($urlPagination . '.xml?page=', $xpath->query('/rss/channel/link[@rel="last"]')->item(0)->getAttribute('href'));
41 41
42 foreach ($xpath->query('//item') as $item) { 42 foreach ($xpath->query('//item') as $item) {
43 $this->assertEquals(1, $xpath->query('title', $item)->length); 43 $this->assertSame(1, $xpath->query('title', $item)->length);
44 $this->assertEquals(1, $xpath->query('source', $item)->length); 44 $this->assertSame(1, $xpath->query('source', $item)->length);
45 $this->assertEquals(1, $xpath->query('link', $item)->length); 45 $this->assertSame(1, $xpath->query('link', $item)->length);
46 $this->assertEquals(1, $xpath->query('guid', $item)->length); 46 $this->assertSame(1, $xpath->query('guid', $item)->length);
47 $this->assertEquals(1, $xpath->query('pubDate', $item)->length); 47 $this->assertSame(1, $xpath->query('pubDate', $item)->length);
48 $this->assertEquals(1, $xpath->query('description', $item)->length); 48 $this->assertSame(1, $xpath->query('description', $item)->length);
49 } 49 }
50 } 50 }
51 51
@@ -73,7 +73,7 @@ class RssControllerTest extends WallabagCoreTestCase
73 73
74 $client->request('GET', $url); 74 $client->request('GET', $url);
75 75
76 $this->assertEquals(404, $client->getResponse()->getStatusCode()); 76 $this->assertSame(404, $client->getResponse()->getStatusCode());
77 } 77 }
78 78
79 public function testUnread() 79 public function testUnread()
@@ -92,9 +92,9 @@ class RssControllerTest extends WallabagCoreTestCase
92 92
93 $client->request('GET', '/admin/SUPERTOKEN/unread.xml'); 93 $client->request('GET', '/admin/SUPERTOKEN/unread.xml');
94 94
95 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 95 $this->assertSame(200, $client->getResponse()->getStatusCode());
96 96
97 $this->validateDom($client->getResponse()->getContent(), 'unread', 2); 97 $this->validateDom($client->getResponse()->getContent(), 'unread', 'unread', 2);
98 } 98 }
99 99
100 public function testStarred() 100 public function testStarred()
@@ -114,9 +114,9 @@ class RssControllerTest extends WallabagCoreTestCase
114 $client = $this->getClient(); 114 $client = $this->getClient();
115 $client->request('GET', '/admin/SUPERTOKEN/starred.xml'); 115 $client->request('GET', '/admin/SUPERTOKEN/starred.xml');
116 116
117 $this->assertEquals(200, $client->getResponse()->getStatusCode(), 1); 117 $this->assertSame(200, $client->getResponse()->getStatusCode(), 1);
118 118
119 $this->validateDom($client->getResponse()->getContent(), 'starred'); 119 $this->validateDom($client->getResponse()->getContent(), 'starred', 'starred');
120 } 120 }
121 121
122 public function testArchives() 122 public function testArchives()
@@ -136,9 +136,9 @@ class RssControllerTest extends WallabagCoreTestCase
136 $client = $this->getClient(); 136 $client = $this->getClient();
137 $client->request('GET', '/admin/SUPERTOKEN/archive.xml'); 137 $client->request('GET', '/admin/SUPERTOKEN/archive.xml');
138 138
139 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 139 $this->assertSame(200, $client->getResponse()->getStatusCode());
140 140
141 $this->validateDom($client->getResponse()->getContent(), 'archive'); 141 $this->validateDom($client->getResponse()->getContent(), 'archive', 'archive');
142 } 142 }
143 143
144 public function testPagination() 144 public function testPagination()
@@ -158,14 +158,39 @@ class RssControllerTest extends WallabagCoreTestCase
158 $client = $this->getClient(); 158 $client = $this->getClient();
159 159
160 $client->request('GET', '/admin/SUPERTOKEN/unread.xml'); 160 $client->request('GET', '/admin/SUPERTOKEN/unread.xml');
161 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 161 $this->assertSame(200, $client->getResponse()->getStatusCode());
162 $this->validateDom($client->getResponse()->getContent(), 'unread'); 162 $this->validateDom($client->getResponse()->getContent(), 'unread', 'unread');
163 163
164 $client->request('GET', '/admin/SUPERTOKEN/unread.xml?page=2'); 164 $client->request('GET', '/admin/SUPERTOKEN/unread.xml?page=2');
165 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 165 $this->assertSame(200, $client->getResponse()->getStatusCode());
166 $this->validateDom($client->getResponse()->getContent(), 'unread'); 166 $this->validateDom($client->getResponse()->getContent(), 'unread', 'unread');
167 167
168 $client->request('GET', '/admin/SUPERTOKEN/unread.xml?page=3000'); 168 $client->request('GET', '/admin/SUPERTOKEN/unread.xml?page=3000');
169 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 169 $this->assertSame(302, $client->getResponse()->getStatusCode());
170 }
171
172 public function testTags()
173 {
174 $client = $this->getClient();
175 $em = $client->getContainer()->get('doctrine.orm.entity_manager');
176 $user = $em
177 ->getRepository('WallabagUserBundle:User')
178 ->findOneByUsername('admin');
179
180 $config = $user->getConfig();
181 $config->setRssToken('SUPERTOKEN');
182 $config->setRssLimit(null);
183 $em->persist($config);
184 $em->flush();
185
186 $client = $this->getClient();
187 $client->request('GET', '/admin/SUPERTOKEN/tags/foo-bar.xml');
188
189 $this->assertSame(200, $client->getResponse()->getStatusCode());
190
191 $this->validateDom($client->getResponse()->getContent(), 'tag (foo bar)', 'tags/foo-bar');
192
193 $client->request('GET', '/admin/SUPERTOKEN/tags/foo-bar.xml?page=3000');
194 $this->assertSame(302, $client->getResponse()->getStatusCode());
170 } 195 }
171} 196}
diff --git a/tests/Wallabag/CoreBundle/Controller/SettingsControllerTest.php b/tests/Wallabag/CoreBundle/Controller/SettingsControllerTest.php
index 9b8b5702..6005c0df 100644
--- a/tests/Wallabag/CoreBundle/Controller/SettingsControllerTest.php
+++ b/tests/Wallabag/CoreBundle/Controller/SettingsControllerTest.php
@@ -17,7 +17,7 @@ class SettingsControllerTest extends WallabagCoreTestCase
17 17
18 $crawler = $client->request('GET', '/settings'); 18 $crawler = $client->request('GET', '/settings');
19 19
20 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 20 $this->assertSame(200, $client->getResponse()->getStatusCode());
21 } 21 }
22 22
23 public function testSettingsWithNormalUser() 23 public function testSettingsWithNormalUser()
@@ -27,6 +27,6 @@ class SettingsControllerTest extends WallabagCoreTestCase
27 27
28 $crawler = $client->request('GET', '/settings'); 28 $crawler = $client->request('GET', '/settings');
29 29
30 $this->assertEquals(403, $client->getResponse()->getStatusCode()); 30 $this->assertSame(403, $client->getResponse()->getStatusCode());
31 } 31 }
32} 32}
diff --git a/tests/Wallabag/CoreBundle/Controller/SiteCredentialControllerTest.php b/tests/Wallabag/CoreBundle/Controller/SiteCredentialControllerTest.php
new file mode 100644
index 00000000..87ea2867
--- /dev/null
+++ b/tests/Wallabag/CoreBundle/Controller/SiteCredentialControllerTest.php
@@ -0,0 +1,139 @@
1<?php
2
3namespace Tests\Wallabag\CoreBundle\Controller;
4
5use Symfony\Bundle\FrameworkBundle\Client;
6use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
7use Wallabag\CoreBundle\Entity\SiteCredential;
8
9class SiteCredentialControllerTest extends WallabagCoreTestCase
10{
11 public function testListSiteCredential()
12 {
13 $this->logInAs('admin');
14 $client = $this->getClient();
15
16 $crawler = $client->request('GET', '/site-credentials/');
17
18 $this->assertSame(200, $client->getResponse()->getStatusCode());
19
20 $body = $crawler->filter('body')->extract(['_text'])[0];
21
22 $this->assertContains('site_credential.description', $body);
23 $this->assertContains('site_credential.list.create_new_one', $body);
24 }
25
26 public function testNewSiteCredential()
27 {
28 $this->logInAs('admin');
29 $client = $this->getClient();
30
31 $crawler = $client->request('GET', '/site-credentials/new');
32
33 $this->assertSame(200, $client->getResponse()->getStatusCode());
34
35 $body = $crawler->filter('body')->extract(['_text'])[0];
36
37 $this->assertContains('site_credential.new_site_credential', $body);
38 $this->assertContains('site_credential.form.back_to_list', $body);
39
40 $form = $crawler->filter('button[id=site_credential_save]')->form();
41
42 $data = [
43 'site_credential[host]' => 'google.io',
44 'site_credential[username]' => 'sergei',
45 'site_credential[password]' => 'microsoft',
46 ];
47
48 $client->submit($form, $data);
49
50 $this->assertSame(302, $client->getResponse()->getStatusCode());
51
52 $crawler = $client->followRedirect();
53
54 $this->assertContains('flashes.site_credential.notice.added', $crawler->filter('body')->extract(['_text'])[0]);
55 }
56
57 public function testEditSiteCredential()
58 {
59 $this->logInAs('admin');
60 $client = $this->getClient();
61
62 $credential = $this->createSiteCredential($client);
63
64 $crawler = $client->request('GET', '/site-credentials/' . $credential->getId() . '/edit');
65
66 $this->assertSame(200, $client->getResponse()->getStatusCode());
67
68 $body = $crawler->filter('body')->extract(['_text'])[0];
69
70 $this->assertContains('site_credential.edit_site_credential', $body);
71 $this->assertContains('site_credential.form.back_to_list', $body);
72
73 $form = $crawler->filter('button[id=site_credential_save]')->form();
74
75 $data = [
76 'site_credential[host]' => 'google.io',
77 'site_credential[username]' => 'larry',
78 'site_credential[password]' => 'microsoft',
79 ];
80
81 $client->submit($form, $data);
82
83 $this->assertSame(302, $client->getResponse()->getStatusCode());
84
85 $crawler = $client->followRedirect();
86
87 $this->assertContains('flashes.site_credential.notice.updated', $crawler->filter('body')->extract(['_text'])[0]);
88 }
89
90 public function testEditFromADifferentUserSiteCredential()
91 {
92 $this->logInAs('admin');
93 $client = $this->getClient();
94
95 $credential = $this->createSiteCredential($client);
96
97 $this->logInAs('bob');
98
99 $client->request('GET', '/site-credentials/' . $credential->getId() . '/edit');
100
101 $this->assertSame(403, $client->getResponse()->getStatusCode());
102 }
103
104 public function testDeleteSiteCredential()
105 {
106 $this->logInAs('admin');
107 $client = $this->getClient();
108
109 $credential = $this->createSiteCredential($client);
110
111 $crawler = $client->request('GET', '/site-credentials/' . $credential->getId() . '/edit');
112
113 $this->assertSame(200, $client->getResponse()->getStatusCode());
114
115 $deleteForm = $crawler->filter('body')->selectButton('site_credential.form.delete')->form();
116
117 $client->submit($deleteForm, []);
118
119 $this->assertSame(302, $client->getResponse()->getStatusCode());
120
121 $crawler = $client->followRedirect();
122
123 $this->assertContains('flashes.site_credential.notice.deleted', $crawler->filter('body')->extract(['_text'])[0]);
124 }
125
126 private function createSiteCredential(Client $client)
127 {
128 $credential = new SiteCredential($this->getLoggedInUser());
129 $credential->setHost('google.io');
130 $credential->setUsername('sergei');
131 $credential->setPassword('microsoft');
132
133 $em = $client->getContainer()->get('doctrine.orm.entity_manager');
134 $em->persist($credential);
135 $em->flush();
136
137 return $credential;
138 }
139}
diff --git a/tests/Wallabag/CoreBundle/Controller/StaticControllerTest.php b/tests/Wallabag/CoreBundle/Controller/StaticControllerTest.php
index 98a37b50..17847937 100644
--- a/tests/Wallabag/CoreBundle/Controller/StaticControllerTest.php
+++ b/tests/Wallabag/CoreBundle/Controller/StaticControllerTest.php
@@ -13,7 +13,7 @@ class StaticControllerTest extends WallabagCoreTestCase
13 13
14 $client->request('GET', '/about'); 14 $client->request('GET', '/about');
15 15
16 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 16 $this->assertSame(200, $client->getResponse()->getStatusCode());
17 } 17 }
18 18
19 public function testHowto() 19 public function testHowto()
@@ -23,6 +23,6 @@ class StaticControllerTest extends WallabagCoreTestCase
23 23
24 $client->request('GET', '/howto'); 24 $client->request('GET', '/howto');
25 25
26 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 26 $this->assertSame(200, $client->getResponse()->getStatusCode());
27 } 27 }
28} 28}
diff --git a/tests/Wallabag/CoreBundle/Controller/TagControllerTest.php b/tests/Wallabag/CoreBundle/Controller/TagControllerTest.php
index fa1a3539..be25a8b5 100644
--- a/tests/Wallabag/CoreBundle/Controller/TagControllerTest.php
+++ b/tests/Wallabag/CoreBundle/Controller/TagControllerTest.php
@@ -3,6 +3,7 @@
3namespace Tests\Wallabag\CoreBundle\Controller; 3namespace Tests\Wallabag\CoreBundle\Controller;
4 4
5use Tests\Wallabag\CoreBundle\WallabagCoreTestCase; 5use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
6use Wallabag\CoreBundle\Entity\Entry;
6use Wallabag\CoreBundle\Entity\Tag; 7use Wallabag\CoreBundle\Entity\Tag;
7 8
8class TagControllerTest extends WallabagCoreTestCase 9class TagControllerTest extends WallabagCoreTestCase
@@ -16,7 +17,7 @@ class TagControllerTest extends WallabagCoreTestCase
16 17
17 $client->request('GET', '/tag/list'); 18 $client->request('GET', '/tag/list');
18 19
19 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 20 $this->assertSame(200, $client->getResponse()->getStatusCode());
20 } 21 }
21 22
22 public function testAddTagToEntry() 23 public function testAddTagToEntry()
@@ -24,12 +25,13 @@ class TagControllerTest extends WallabagCoreTestCase
24 $this->logInAs('admin'); 25 $this->logInAs('admin');
25 $client = $this->getClient(); 26 $client = $this->getClient();
26 27
27 $entry = $client->getContainer() 28 $entry = new Entry($this->getLoggedInUser());
28 ->get('doctrine.orm.entity_manager') 29 $entry->setUrl('http://0.0.0.0/foo');
29 ->getRepository('WallabagCoreBundle:Entry') 30 $this->getEntityManager()->persist($entry);
30 ->findByUrlAndUserId('http://0.0.0.0/entry1', $this->getLoggedInUserId()); 31 $this->getEntityManager()->flush();
32 $this->getEntityManager()->clear();
31 33
32 $crawler = $client->request('GET', '/view/'.$entry->getId()); 34 $crawler = $client->request('GET', '/view/' . $entry->getId());
33 35
34 $form = $crawler->filter('form[name=tag]')->form(); 36 $form = $crawler->filter('form[name=tag]')->form();
35 37
@@ -38,26 +40,18 @@ class TagControllerTest extends WallabagCoreTestCase
38 ]; 40 ];
39 41
40 $client->submit($form, $data); 42 $client->submit($form, $data);
41 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 43 $this->assertSame(302, $client->getResponse()->getStatusCode());
42 44
43 // be sure to reload the entry 45 // be sure to reload the entry
44 $entry = $client->getContainer() 46 $entry = $this->getEntityManager()->getRepository(Entry::class)->find($entry->getId());
45 ->get('doctrine.orm.entity_manager') 47 $this->assertCount(1, $entry->getTags());
46 ->getRepository('WallabagCoreBundle:Entry')
47 ->findByUrlAndUserId('http://0.0.0.0/entry1', $this->getLoggedInUserId());
48
49 $this->assertEquals(3, count($entry->getTags()));
50 48
51 // tag already exists and already assigned 49 // tag already exists and already assigned
52 $client->submit($form, $data); 50 $client->submit($form, $data);
53 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 51 $this->assertSame(302, $client->getResponse()->getStatusCode());
54 52
55 $newEntry = $client->getContainer() 53 $entry = $this->getEntityManager()->getRepository(Entry::class)->find($entry->getId());
56 ->get('doctrine.orm.entity_manager') 54 $this->assertCount(1, $entry->getTags());
57 ->getRepository('WallabagCoreBundle:Entry')
58 ->find($entry->getId());
59
60 $this->assertEquals(3, count($newEntry->getTags()));
61 55
62 // tag already exists but still not assigned to this entry 56 // tag already exists but still not assigned to this entry
63 $data = [ 57 $data = [
@@ -65,14 +59,10 @@ class TagControllerTest extends WallabagCoreTestCase
65 ]; 59 ];
66 60
67 $client->submit($form, $data); 61 $client->submit($form, $data);
68 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 62 $this->assertSame(302, $client->getResponse()->getStatusCode());
69
70 $newEntry = $client->getContainer()
71 ->get('doctrine.orm.entity_manager')
72 ->getRepository('WallabagCoreBundle:Entry')
73 ->find($entry->getId());
74 63
75 $this->assertEquals(3, count($newEntry->getTags())); 64 $entry = $this->getEntityManager()->getRepository(Entry::class)->find($entry->getId());
65 $this->assertCount(2, $entry->getTags());
76 } 66 }
77 67
78 public function testAddMultipleTagToEntry() 68 public function testAddMultipleTagToEntry()
@@ -85,7 +75,7 @@ class TagControllerTest extends WallabagCoreTestCase
85 ->getRepository('WallabagCoreBundle:Entry') 75 ->getRepository('WallabagCoreBundle:Entry')
86 ->findByUrlAndUserId('http://0.0.0.0/entry2', $this->getLoggedInUserId()); 76 ->findByUrlAndUserId('http://0.0.0.0/entry2', $this->getLoggedInUserId());
87 77
88 $crawler = $client->request('GET', '/view/'.$entry->getId()); 78 $crawler = $client->request('GET', '/view/' . $entry->getId());
89 79
90 $form = $crawler->filter('form[name=tag]')->form(); 80 $form = $crawler->filter('form[name=tag]')->form();
91 81
@@ -94,7 +84,7 @@ class TagControllerTest extends WallabagCoreTestCase
94 ]; 84 ];
95 85
96 $client->submit($form, $data); 86 $client->submit($form, $data);
97 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 87 $this->assertSame(302, $client->getResponse()->getStatusCode());
98 88
99 $newEntry = $client->getContainer() 89 $newEntry = $client->getContainer()
100 ->get('doctrine.orm.entity_manager') 90 ->get('doctrine.orm.entity_manager')
@@ -107,8 +97,8 @@ class TagControllerTest extends WallabagCoreTestCase
107 } 97 }
108 98
109 $this->assertGreaterThanOrEqual(2, count($tags)); 99 $this->assertGreaterThanOrEqual(2, count($tags));
110 $this->assertNotFalse(array_search('foo2', $tags), 'Tag foo2 is assigned to the entry'); 100 $this->assertNotFalse(array_search('foo2', $tags, true), 'Tag foo2 is assigned to the entry');
111 $this->assertNotFalse(array_search('bar2', $tags), 'Tag bar2 is assigned to the entry'); 101 $this->assertNotFalse(array_search('bar2', $tags, true), 'Tag bar2 is assigned to the entry');
112 } 102 }
113 103
114 public function testRemoveTagFromEntry() 104 public function testRemoveTagFromEntry()
@@ -116,32 +106,37 @@ class TagControllerTest extends WallabagCoreTestCase
116 $this->logInAs('admin'); 106 $this->logInAs('admin');
117 $client = $this->getClient(); 107 $client = $this->getClient();
118 108
119 $entry = $client->getContainer() 109 $tag = new Tag();
120 ->get('doctrine.orm.entity_manager') 110 $tag->setLabel($this->tagName);
121 ->getRepository('WallabagCoreBundle:Entry') 111 $entry = new Entry($this->getLoggedInUser());
122 ->findByUrlAndUserId('http://0.0.0.0/entry1', $this->getLoggedInUserId()); 112 $entry->setUrl('http://0.0.0.0/foo');
123 113 $entry->addTag($tag);
124 $tag = $client->getContainer() 114 $this->getEntityManager()->persist($entry);
125 ->get('doctrine.orm.entity_manager') 115 $this->getEntityManager()->flush();
126 ->getRepository('WallabagCoreBundle:Tag') 116 $this->getEntityManager()->clear();
127 ->findOneByEntryAndTagLabel($entry, $this->tagName); 117
128 118 // We make a first request to set an history and test redirection after tag deletion
129 $client->request('GET', '/remove-tag/'.$entry->getId().'/'.$tag->getId()); 119 $client->request('GET', '/view/' . $entry->getId());
130 120 $entryUri = $client->getRequest()->getUri();
131 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 121 $client->request('GET', '/remove-tag/' . $entry->getId() . '/' . $tag->getId());
132 122
123 $this->assertSame(302, $client->getResponse()->getStatusCode());
124 $this->assertSame($entryUri, $client->getResponse()->getTargetUrl());
125
126 // re-retrieve the entry to be sure to get fresh data from database (mostly for tags)
127 $entry = $this->getEntityManager()->getRepository(Entry::class)->find($entry->getId());
133 $this->assertNotContains($this->tagName, $entry->getTags()); 128 $this->assertNotContains($this->tagName, $entry->getTags());
134 129
135 $client->request('GET', '/remove-tag/'.$entry->getId().'/'.$tag->getId()); 130 $client->request('GET', '/remove-tag/' . $entry->getId() . '/' . $tag->getId());
136 131
137 $this->assertEquals(404, $client->getResponse()->getStatusCode()); 132 $this->assertSame(404, $client->getResponse()->getStatusCode());
138 133
139 $tag = $client->getContainer() 134 $tag = $client->getContainer()
140 ->get('doctrine.orm.entity_manager') 135 ->get('doctrine.orm.entity_manager')
141 ->getRepository('WallabagCoreBundle:Tag') 136 ->getRepository('WallabagCoreBundle:Tag')
142 ->findOneByLabel($this->tagName); 137 ->findOneByLabel($this->tagName);
143 138
144 $this->assertNull($tag, $this->tagName.' was removed because it begun an orphan tag'); 139 $this->assertNull($tag, $this->tagName . ' was removed because it begun an orphan tag');
145 } 140 }
146 141
147 public function testShowEntriesForTagAction() 142 public function testShowEntriesForTagAction()
@@ -170,9 +165,9 @@ class TagControllerTest extends WallabagCoreTestCase
170 ->getRepository('WallabagCoreBundle:Tag') 165 ->getRepository('WallabagCoreBundle:Tag')
171 ->findOneByEntryAndTagLabel($entry, $this->tagName); 166 ->findOneByEntryAndTagLabel($entry, $this->tagName);
172 167
173 $crawler = $client->request('GET', '/tag/list/'.$tag->getSlug()); 168 $crawler = $client->request('GET', '/tag/list/' . $tag->getSlug());
174 169
175 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 170 $this->assertSame(200, $client->getResponse()->getStatusCode());
176 $this->assertCount(1, $crawler->filter('[id*="entry-"]')); 171 $this->assertCount(1, $crawler->filter('[id*="entry-"]'));
177 172
178 $entry->removeTag($tag); 173 $entry->removeTag($tag);
diff --git a/tests/Wallabag/CoreBundle/Event/Listener/LocaleListenerTest.php b/tests/Wallabag/CoreBundle/Event/Listener/LocaleListenerTest.php
index 84a54d3a..0dbd9f70 100644
--- a/tests/Wallabag/CoreBundle/Event/Listener/LocaleListenerTest.php
+++ b/tests/Wallabag/CoreBundle/Event/Listener/LocaleListenerTest.php
@@ -13,15 +13,6 @@ use Wallabag\CoreBundle\Event\Listener\LocaleListener;
13 13
14class LocaleListenerTest extends \PHPUnit_Framework_TestCase 14class LocaleListenerTest extends \PHPUnit_Framework_TestCase
15{ 15{
16 private function getEvent(Request $request)
17 {
18 $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')
19 ->disableOriginalConstructor()
20 ->getMock();
21
22 return new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST);
23 }
24
25 public function testWithoutSession() 16 public function testWithoutSession()
26 { 17 {
27 $request = Request::create('/'); 18 $request = Request::create('/');
@@ -30,7 +21,7 @@ class LocaleListenerTest extends \PHPUnit_Framework_TestCase
30 $event = $this->getEvent($request); 21 $event = $this->getEvent($request);
31 22
32 $listener->onKernelRequest($event); 23 $listener->onKernelRequest($event);
33 $this->assertEquals('en', $request->getLocale()); 24 $this->assertSame('en', $request->getLocale());
34 } 25 }
35 26
36 public function testWithPreviousSession() 27 public function testWithPreviousSession()
@@ -44,7 +35,7 @@ class LocaleListenerTest extends \PHPUnit_Framework_TestCase
44 $event = $this->getEvent($request); 35 $event = $this->getEvent($request);
45 36
46 $listener->onKernelRequest($event); 37 $listener->onKernelRequest($event);
47 $this->assertEquals('fr', $request->getLocale()); 38 $this->assertSame('fr', $request->getLocale());
48 } 39 }
49 40
50 public function testLocaleFromRequestAttribute() 41 public function testLocaleFromRequestAttribute()
@@ -59,8 +50,8 @@ class LocaleListenerTest extends \PHPUnit_Framework_TestCase
59 $event = $this->getEvent($request); 50 $event = $this->getEvent($request);
60 51
61 $listener->onKernelRequest($event); 52 $listener->onKernelRequest($event);
62 $this->assertEquals('en', $request->getLocale()); 53 $this->assertSame('en', $request->getLocale());
63 $this->assertEquals('es', $request->getSession()->get('_locale')); 54 $this->assertSame('es', $request->getSession()->get('_locale'));
64 } 55 }
65 56
66 public function testSubscribedEvents() 57 public function testSubscribedEvents()
@@ -81,6 +72,15 @@ class LocaleListenerTest extends \PHPUnit_Framework_TestCase
81 $event 72 $event
82 ); 73 );
83 74
84 $this->assertEquals('fr', $request->getLocale()); 75 $this->assertSame('fr', $request->getLocale());
76 }
77
78 private function getEvent(Request $request)
79 {
80 $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')
81 ->disableOriginalConstructor()
82 ->getMock();
83
84 return new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST);
85 } 85 }
86} 86}
diff --git a/tests/Wallabag/CoreBundle/Event/Listener/UserLocaleListenerTest.php b/tests/Wallabag/CoreBundle/Event/Listener/UserLocaleListenerTest.php
index 45aecc63..5ffe1ca6 100644
--- a/tests/Wallabag/CoreBundle/Event/Listener/UserLocaleListenerTest.php
+++ b/tests/Wallabag/CoreBundle/Event/Listener/UserLocaleListenerTest.php
@@ -32,7 +32,7 @@ class UserLocaleListenerTest extends \PHPUnit_Framework_TestCase
32 32
33 $listener->onInteractiveLogin($event); 33 $listener->onInteractiveLogin($event);
34 34
35 $this->assertEquals('fr', $session->get('_locale')); 35 $this->assertSame('fr', $session->get('_locale'));
36 } 36 }
37 37
38 public function testWithoutLanguage() 38 public function testWithoutLanguage()
@@ -53,6 +53,6 @@ class UserLocaleListenerTest extends \PHPUnit_Framework_TestCase
53 53
54 $listener->onInteractiveLogin($event); 54 $listener->onInteractiveLogin($event);
55 55
56 $this->assertEquals('', $session->get('_locale')); 56 $this->assertNull($session->get('_locale'));
57 } 57 }
58} 58}
diff --git a/tests/Wallabag/CoreBundle/Event/Subscriber/TablePrefixSubscriberTest.php b/tests/Wallabag/CoreBundle/Event/Subscriber/TablePrefixSubscriberTest.php
index b8cd0fad..64e3c6d9 100644
--- a/tests/Wallabag/CoreBundle/Event/Subscriber/TablePrefixSubscriberTest.php
+++ b/tests/Wallabag/CoreBundle/Event/Subscriber/TablePrefixSubscriberTest.php
@@ -46,12 +46,12 @@ class TablePrefixSubscriberTest extends \PHPUnit_Framework_TestCase
46 46
47 $metaDataEvent = new LoadClassMetadataEventArgs($metaClass, $em); 47 $metaDataEvent = new LoadClassMetadataEventArgs($metaClass, $em);
48 48
49 $this->assertEquals($tableNameExpected, $metaDataEvent->getClassMetadata()->getTableName()); 49 $this->assertSame($tableNameExpected, $metaDataEvent->getClassMetadata()->getTableName());
50 50
51 $subscriber->loadClassMetadata($metaDataEvent); 51 $subscriber->loadClassMetadata($metaDataEvent);
52 52
53 $this->assertEquals($finalTableName, $metaDataEvent->getClassMetadata()->getTableName()); 53 $this->assertSame($finalTableName, $metaDataEvent->getClassMetadata()->getTableName());
54 $this->assertEquals($finalTableNameQuoted, $metaDataEvent->getClassMetadata()->getQuotedTableName($platform)); 54 $this->assertSame($finalTableNameQuoted, $metaDataEvent->getClassMetadata()->getQuotedTableName($platform));
55 } 55 }
56 56
57 /** 57 /**
@@ -75,8 +75,8 @@ class TablePrefixSubscriberTest extends \PHPUnit_Framework_TestCase
75 75
76 $evm->dispatchEvent('loadClassMetadata', $metaDataEvent); 76 $evm->dispatchEvent('loadClassMetadata', $metaDataEvent);
77 77
78 $this->assertEquals($finalTableName, $metaDataEvent->getClassMetadata()->getTableName()); 78 $this->assertSame($finalTableName, $metaDataEvent->getClassMetadata()->getTableName());
79 $this->assertEquals($finalTableNameQuoted, $metaDataEvent->getClassMetadata()->getQuotedTableName($platform)); 79 $this->assertSame($finalTableNameQuoted, $metaDataEvent->getClassMetadata()->getQuotedTableName($platform));
80 } 80 }
81 81
82 public function testPrefixManyToMany() 82 public function testPrefixManyToMany()
@@ -103,12 +103,12 @@ class TablePrefixSubscriberTest extends \PHPUnit_Framework_TestCase
103 103
104 $metaDataEvent = new LoadClassMetadataEventArgs($metaClass, $em); 104 $metaDataEvent = new LoadClassMetadataEventArgs($metaClass, $em);
105 105
106 $this->assertEquals('entry', $metaDataEvent->getClassMetadata()->getTableName()); 106 $this->assertSame('entry', $metaDataEvent->getClassMetadata()->getTableName());
107 107
108 $subscriber->loadClassMetadata($metaDataEvent); 108 $subscriber->loadClassMetadata($metaDataEvent);
109 109
110 $this->assertEquals('yo_entry', $metaDataEvent->getClassMetadata()->getTableName()); 110 $this->assertSame('yo_entry', $metaDataEvent->getClassMetadata()->getTableName());
111 $this->assertEquals('yo_entry_tag', $metaDataEvent->getClassMetadata()->associationMappings['tags']['joinTable']['name']); 111 $this->assertSame('yo_entry_tag', $metaDataEvent->getClassMetadata()->associationMappings['tags']['joinTable']['name']);
112 $this->assertEquals('yo_entry', $metaDataEvent->getClassMetadata()->getQuotedTableName(new \Doctrine\DBAL\Platforms\MySqlPlatform())); 112 $this->assertSame('yo_entry', $metaDataEvent->getClassMetadata()->getQuotedTableName(new \Doctrine\DBAL\Platforms\MySqlPlatform()));
113 } 113 }
114} 114}
diff --git a/tests/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilderTest.php b/tests/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilderTest.php
index aee67259..5d6a29fe 100644
--- a/tests/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilderTest.php
+++ b/tests/Wallabag/CoreBundle/GuzzleSiteAuthenticator/GrabySiteConfigBuilderTest.php
@@ -2,12 +2,14 @@
2 2
3namespace Tests\Wallabag\CoreBundle\GuzzleSiteAuthenticator; 3namespace Tests\Wallabag\CoreBundle\GuzzleSiteAuthenticator;
4 4
5use BD\GuzzleSiteAuthenticator\SiteConfig\SiteConfig;
6use Graby\SiteConfig\SiteConfig as GrabySiteConfig; 5use Graby\SiteConfig\SiteConfig as GrabySiteConfig;
7use PHPUnit_Framework_TestCase; 6use Monolog\Handler\TestHandler;
7use Monolog\Logger;
8use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
9use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
8use Wallabag\CoreBundle\GuzzleSiteAuthenticator\GrabySiteConfigBuilder; 10use Wallabag\CoreBundle\GuzzleSiteAuthenticator\GrabySiteConfigBuilder;
9 11
10class GrabySiteConfigBuilderTest extends PHPUnit_Framework_TestCase 12class GrabySiteConfigBuilderTest extends \PHPUnit_Framework_TestCase
11{ 13{
12 /** @var \Wallabag\CoreBundle\GuzzleSiteAuthenticator\GrabySiteConfigBuilder */ 14 /** @var \Wallabag\CoreBundle\GuzzleSiteAuthenticator\GrabySiteConfigBuilder */
13 protected $builder; 15 protected $builder;
@@ -15,16 +17,16 @@ class GrabySiteConfigBuilderTest extends PHPUnit_Framework_TestCase
15 public function testBuildConfigExists() 17 public function testBuildConfigExists()
16 { 18 {
17 /* @var \Graby\SiteConfig\ConfigBuilder|\PHPUnit_Framework_MockObject_MockObject */ 19 /* @var \Graby\SiteConfig\ConfigBuilder|\PHPUnit_Framework_MockObject_MockObject */
18 $grabyConfigBuilderMock = $this->getMockBuilder('\Graby\SiteConfig\ConfigBuilder') 20 $grabyConfigBuilderMock = $this->getMockBuilder('Graby\SiteConfig\ConfigBuilder')
19 ->disableOriginalConstructor() 21 ->disableOriginalConstructor()
20 ->getMock(); 22 ->getMock();
21 23
22 $grabySiteConfig = new GrabySiteConfig(); 24 $grabySiteConfig = new GrabySiteConfig();
23 $grabySiteConfig->requires_login = true; 25 $grabySiteConfig->requires_login = true;
24 $grabySiteConfig->login_uri = 'http://example.com/login'; 26 $grabySiteConfig->login_uri = 'http://www.example.com/login';
25 $grabySiteConfig->login_username_field = 'login'; 27 $grabySiteConfig->login_username_field = 'login';
26 $grabySiteConfig->login_password_field = 'password'; 28 $grabySiteConfig->login_password_field = 'password';
27 $grabySiteConfig->login_extra_fields = ['field' => 'value']; 29 $grabySiteConfig->login_extra_fields = ['field=value'];
28 $grabySiteConfig->not_logged_in_xpath = '//div[@class="need-login"]'; 30 $grabySiteConfig->not_logged_in_xpath = '//div[@class="need-login"]';
29 31
30 $grabyConfigBuilderMock 32 $grabyConfigBuilderMock
@@ -32,27 +34,52 @@ class GrabySiteConfigBuilderTest extends PHPUnit_Framework_TestCase
32 ->with('example.com') 34 ->with('example.com')
33 ->will($this->returnValue($grabySiteConfig)); 35 ->will($this->returnValue($grabySiteConfig));
34 36
37 $logger = new Logger('foo');
38 $handler = new TestHandler();
39 $logger->pushHandler($handler);
40
41 $siteCrentialRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\SiteCredentialRepository')
42 ->disableOriginalConstructor()
43 ->getMock();
44 $siteCrentialRepo->expects($this->once())
45 ->method('findOneByHostAndUser')
46 ->with('example.com', 1)
47 ->willReturn(['username' => 'foo', 'password' => 'bar']);
48
49 $user = $this->getMockBuilder('Wallabag\UserBundle\Entity\User')
50 ->disableOriginalConstructor()
51 ->getMock();
52 $user->expects($this->once())
53 ->method('getId')
54 ->willReturn(1);
55
56 $token = new UsernamePasswordToken($user, 'pass', 'provider');
57
58 $tokenStorage = new TokenStorage();
59 $tokenStorage->setToken($token);
60
35 $this->builder = new GrabySiteConfigBuilder( 61 $this->builder = new GrabySiteConfigBuilder(
36 $grabyConfigBuilderMock, 62 $grabyConfigBuilderMock,
37 ['example.com' => ['username' => 'foo', 'password' => 'bar']] 63 $tokenStorage,
64 $siteCrentialRepo,
65 $logger
38 ); 66 );
39 67
40 $config = $this->builder->buildForHost('example.com'); 68 $config = $this->builder->buildForHost('www.example.com');
41 69
42 self::assertEquals( 70 $this->assertSame('example.com', $config->getHost());
43 new SiteConfig([ 71 $this->assertSame(true, $config->requiresLogin());
44 'host' => 'example.com', 72 $this->assertSame('http://www.example.com/login', $config->getLoginUri());
45 'requiresLogin' => true, 73 $this->assertSame('login', $config->getUsernameField());
46 'loginUri' => 'http://example.com/login', 74 $this->assertSame('password', $config->getPasswordField());
47 'usernameField' => 'login', 75 $this->assertSame(['field' => 'value'], $config->getExtraFields());
48 'passwordField' => 'password', 76 $this->assertSame('//div[@class="need-login"]', $config->getNotLoggedInXpath());
49 'extraFields' => ['field' => 'value'], 77 $this->assertSame('foo', $config->getUsername());
50 'notLoggedInXpath' => '//div[@class="need-login"]', 78 $this->assertSame('bar', $config->getPassword());
51 'username' => 'foo', 79
52 'password' => 'bar', 80 $records = $handler->getRecords();
53 ]), 81
54 $config 82 $this->assertCount(1, $records, 'One log was recorded');
55 );
56 } 83 }
57 84
58 public function testBuildConfigDoesntExist() 85 public function testBuildConfigDoesntExist()
@@ -67,19 +94,43 @@ class GrabySiteConfigBuilderTest extends PHPUnit_Framework_TestCase
67 ->with('unknown.com') 94 ->with('unknown.com')
68 ->will($this->returnValue(new GrabySiteConfig())); 95 ->will($this->returnValue(new GrabySiteConfig()));
69 96
70 $this->builder = new GrabySiteConfigBuilder($grabyConfigBuilderMock, []); 97 $logger = new Logger('foo');
98 $handler = new TestHandler();
99 $logger->pushHandler($handler);
71 100
72 $config = $this->builder->buildForHost('unknown.com'); 101 $siteCrentialRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\SiteCredentialRepository')
102 ->disableOriginalConstructor()
103 ->getMock();
104 $siteCrentialRepo->expects($this->once())
105 ->method('findOneByHostAndUser')
106 ->with('unknown.com', 1)
107 ->willReturn(null);
108
109 $user = $this->getMockBuilder('Wallabag\UserBundle\Entity\User')
110 ->disableOriginalConstructor()
111 ->getMock();
112 $user->expects($this->once())
113 ->method('getId')
114 ->willReturn(1);
115
116 $token = new UsernamePasswordToken($user, 'pass', 'provider');
117
118 $tokenStorage = new TokenStorage();
119 $tokenStorage->setToken($token);
73 120
74 self::assertEquals( 121 $this->builder = new GrabySiteConfigBuilder(
75 new SiteConfig([ 122 $grabyConfigBuilderMock,
76 'host' => 'unknown.com', 123 $tokenStorage,
77 'requiresLogin' => false, 124 $siteCrentialRepo,
78 'username' => null, 125 $logger
79 'password' => null,
80 'extraFields' => [],
81 ]),
82 $config
83 ); 126 );
127
128 $config = $this->builder->buildForHost('unknown.com');
129
130 $this->assertFalse($config);
131
132 $records = $handler->getRecords();
133
134 $this->assertCount(1, $records, 'One log was recorded');
84 } 135 }
85} 136}
diff --git a/tests/Wallabag/CoreBundle/Helper/ContentProxyTest.php b/tests/Wallabag/CoreBundle/Helper/ContentProxyTest.php
index 4f70ed0c..f94c2137 100644
--- a/tests/Wallabag/CoreBundle/Helper/ContentProxyTest.php
+++ b/tests/Wallabag/CoreBundle/Helper/ContentProxyTest.php
@@ -2,10 +2,17 @@
2 2
3namespace Tests\Wallabag\CoreBundle\Helper; 3namespace Tests\Wallabag\CoreBundle\Helper;
4 4
5use Graby\Graby;
6use Monolog\Handler\TestHandler;
7use Monolog\Logger;
5use Psr\Log\NullLogger; 8use Psr\Log\NullLogger;
6use Wallabag\CoreBundle\Helper\ContentProxy; 9use Symfony\Component\Validator\ConstraintViolation;
10use Symfony\Component\Validator\ConstraintViolationList;
11use Symfony\Component\Validator\Validator\RecursiveValidator;
7use Wallabag\CoreBundle\Entity\Entry; 12use Wallabag\CoreBundle\Entity\Entry;
8use Wallabag\CoreBundle\Entity\Tag; 13use Wallabag\CoreBundle\Entity\Tag;
14use Wallabag\CoreBundle\Helper\ContentProxy;
15use Wallabag\CoreBundle\Helper\RuleBasedTagger;
9use Wallabag\UserBundle\Entity\User; 16use Wallabag\UserBundle\Entity\User;
10 17
11class ContentProxyTest extends \PHPUnit_Framework_TestCase 18class ContentProxyTest extends \PHPUnit_Framework_TestCase
@@ -33,17 +40,18 @@ class ContentProxyTest extends \PHPUnit_Framework_TestCase
33 'language' => '', 40 'language' => '',
34 ]); 41 ]);
35 42
36 $proxy = new ContentProxy($graby, $tagger, $this->getTagRepositoryMock(), $this->getLogger(), $this->fetchingErrorMessage); 43 $proxy = new ContentProxy($graby, $tagger, $this->getValidator(), $this->getLogger(), $this->fetchingErrorMessage);
37 $entry = $proxy->updateEntry(new Entry(new User()), 'http://user@:80'); 44 $entry = new Entry(new User());
45 $proxy->updateEntry($entry, 'http://user@:80');
38 46
39 $this->assertEquals('http://user@:80', $entry->getUrl()); 47 $this->assertSame('http://user@:80', $entry->getUrl());
40 $this->assertEmpty($entry->getTitle()); 48 $this->assertEmpty($entry->getTitle());
41 $this->assertEquals($this->fetchingErrorMessage, $entry->getContent()); 49 $this->assertSame($this->fetchingErrorMessage, $entry->getContent());
42 $this->assertEmpty($entry->getPreviewPicture()); 50 $this->assertEmpty($entry->getPreviewPicture());
43 $this->assertEmpty($entry->getMimetype()); 51 $this->assertEmpty($entry->getMimetype());
44 $this->assertEmpty($entry->getLanguage()); 52 $this->assertEmpty($entry->getLanguage());
45 $this->assertEquals(0.0, $entry->getReadingTime()); 53 $this->assertSame(0.0, $entry->getReadingTime());
46 $this->assertEquals(false, $entry->getDomainName()); 54 $this->assertSame(null, $entry->getDomainName());
47 } 55 }
48 56
49 public function testWithEmptyContent() 57 public function testWithEmptyContent()
@@ -67,17 +75,18 @@ class ContentProxyTest extends \PHPUnit_Framework_TestCase
67 'language' => '', 75 'language' => '',
68 ]); 76 ]);
69 77
70 $proxy = new ContentProxy($graby, $tagger, $this->getTagRepositoryMock(), $this->getLogger(), $this->fetchingErrorMessage); 78 $proxy = new ContentProxy($graby, $tagger, $this->getValidator(), $this->getLogger(), $this->fetchingErrorMessage);
71 $entry = $proxy->updateEntry(new Entry(new User()), 'http://0.0.0.0'); 79 $entry = new Entry(new User());
80 $proxy->updateEntry($entry, 'http://0.0.0.0');
72 81
73 $this->assertEquals('http://0.0.0.0', $entry->getUrl()); 82 $this->assertSame('http://0.0.0.0', $entry->getUrl());
74 $this->assertEmpty($entry->getTitle()); 83 $this->assertEmpty($entry->getTitle());
75 $this->assertEquals($this->fetchingErrorMessage, $entry->getContent()); 84 $this->assertSame($this->fetchingErrorMessage, $entry->getContent());
76 $this->assertEmpty($entry->getPreviewPicture()); 85 $this->assertEmpty($entry->getPreviewPicture());
77 $this->assertEmpty($entry->getMimetype()); 86 $this->assertEmpty($entry->getMimetype());
78 $this->assertEmpty($entry->getLanguage()); 87 $this->assertEmpty($entry->getLanguage());
79 $this->assertEquals(0.0, $entry->getReadingTime()); 88 $this->assertSame(0.0, $entry->getReadingTime());
80 $this->assertEquals('0.0.0.0', $entry->getDomainName()); 89 $this->assertSame('0.0.0.0', $entry->getDomainName());
81 } 90 }
82 91
83 public function testWithEmptyContentButOG() 92 public function testWithEmptyContentButOG()
@@ -106,18 +115,19 @@ class ContentProxyTest extends \PHPUnit_Framework_TestCase
106 ], 115 ],
107 ]); 116 ]);
108 117
109 $proxy = new ContentProxy($graby, $tagger, $this->getTagRepositoryMock(), $this->getLogger(), $this->fetchingErrorMessage); 118 $proxy = new ContentProxy($graby, $tagger, $this->getValidator(), $this->getLogger(), $this->fetchingErrorMessage);
110 $entry = $proxy->updateEntry(new Entry(new User()), 'http://domain.io'); 119 $entry = new Entry(new User());
120 $proxy->updateEntry($entry, 'http://domain.io');
111 121
112 $this->assertEquals('http://domain.io', $entry->getUrl()); 122 $this->assertSame('http://domain.io', $entry->getUrl());
113 $this->assertEquals('my title', $entry->getTitle()); 123 $this->assertSame('my title', $entry->getTitle());
114 $this->assertEquals($this->fetchingErrorMessage . '<p><i>But we found a short description: </i></p>desc', $entry->getContent()); 124 $this->assertSame($this->fetchingErrorMessage . '<p><i>But we found a short description: </i></p>desc', $entry->getContent());
115 $this->assertEmpty($entry->getPreviewPicture()); 125 $this->assertEmpty($entry->getPreviewPicture());
116 $this->assertEmpty($entry->getLanguage()); 126 $this->assertEmpty($entry->getLanguage());
117 $this->assertEmpty($entry->getHttpStatus()); 127 $this->assertEmpty($entry->getHttpStatus());
118 $this->assertEmpty($entry->getMimetype()); 128 $this->assertEmpty($entry->getMimetype());
119 $this->assertEquals(0.0, $entry->getReadingTime()); 129 $this->assertSame(0.0, $entry->getReadingTime());
120 $this->assertEquals('domain.io', $entry->getDomainName()); 130 $this->assertSame('domain.io', $entry->getDomainName());
121 } 131 }
122 132
123 public function testWithContent() 133 public function testWithContent()
@@ -147,18 +157,19 @@ class ContentProxyTest extends \PHPUnit_Framework_TestCase
147 ], 157 ],
148 ]); 158 ]);
149 159
150 $proxy = new ContentProxy($graby, $tagger, $this->getTagRepositoryMock(), $this->getLogger(), $this->fetchingErrorMessage); 160 $proxy = new ContentProxy($graby, $tagger, $this->getValidator(), $this->getLogger(), $this->fetchingErrorMessage);
151 $entry = $proxy->updateEntry(new Entry(new User()), 'http://0.0.0.0'); 161 $entry = new Entry(new User());
162 $proxy->updateEntry($entry, 'http://0.0.0.0');
152 163
153 $this->assertEquals('http://1.1.1.1', $entry->getUrl()); 164 $this->assertSame('http://1.1.1.1', $entry->getUrl());
154 $this->assertEquals('this is my title', $entry->getTitle()); 165 $this->assertSame('this is my title', $entry->getTitle());
155 $this->assertContains('this is my content', $entry->getContent()); 166 $this->assertContains('this is my content', $entry->getContent());
156 $this->assertEquals('http://3.3.3.3/cover.jpg', $entry->getPreviewPicture()); 167 $this->assertSame('http://3.3.3.3/cover.jpg', $entry->getPreviewPicture());
157 $this->assertEquals('text/html', $entry->getMimetype()); 168 $this->assertSame('text/html', $entry->getMimetype());
158 $this->assertEquals('fr', $entry->getLanguage()); 169 $this->assertSame('fr', $entry->getLanguage());
159 $this->assertEquals('200', $entry->getHttpStatus()); 170 $this->assertSame('200', $entry->getHttpStatus());
160 $this->assertEquals(4.0, $entry->getReadingTime()); 171 $this->assertSame(4.0, $entry->getReadingTime());
161 $this->assertEquals('1.1.1.1', $entry->getDomainName()); 172 $this->assertSame('1.1.1.1', $entry->getDomainName());
162 } 173 }
163 174
164 public function testWithContentAndNoOgImage() 175 public function testWithContentAndNoOgImage()
@@ -184,205 +195,359 @@ class ContentProxyTest extends \PHPUnit_Framework_TestCase
184 'open_graph' => [ 195 'open_graph' => [
185 'og_title' => 'my OG title', 196 'og_title' => 'my OG title',
186 'og_description' => 'OG desc', 197 'og_description' => 'OG desc',
187 'og_image' => false, 198 'og_image' => null,
188 ], 199 ],
189 ]); 200 ]);
190 201
191 $proxy = new ContentProxy($graby, $tagger, $this->getTagRepositoryMock(), $this->getLogger(), $this->fetchingErrorMessage); 202 $proxy = new ContentProxy($graby, $tagger, $this->getValidator(), $this->getLogger(), $this->fetchingErrorMessage);
192 $entry = $proxy->updateEntry(new Entry(new User()), 'http://0.0.0.0'); 203 $entry = new Entry(new User());
204 $proxy->updateEntry($entry, 'http://0.0.0.0');
193 205
194 $this->assertEquals('http://1.1.1.1', $entry->getUrl()); 206 $this->assertSame('http://1.1.1.1', $entry->getUrl());
195 $this->assertEquals('this is my title', $entry->getTitle()); 207 $this->assertSame('this is my title', $entry->getTitle());
196 $this->assertContains('this is my content', $entry->getContent()); 208 $this->assertContains('this is my content', $entry->getContent());
197 $this->assertNull($entry->getPreviewPicture()); 209 $this->assertNull($entry->getPreviewPicture());
198 $this->assertEquals('text/html', $entry->getMimetype()); 210 $this->assertSame('text/html', $entry->getMimetype());
199 $this->assertEquals('fr', $entry->getLanguage()); 211 $this->assertSame('fr', $entry->getLanguage());
200 $this->assertEquals('200', $entry->getHttpStatus()); 212 $this->assertSame('200', $entry->getHttpStatus());
201 $this->assertEquals(4.0, $entry->getReadingTime()); 213 $this->assertSame(4.0, $entry->getReadingTime());
202 $this->assertEquals('1.1.1.1', $entry->getDomainName()); 214 $this->assertSame('1.1.1.1', $entry->getDomainName());
203 } 215 }
204 216
205 public function testWithForcedContent() 217 public function testWithContentAndBadLanguage()
206 { 218 {
207 $tagger = $this->getTaggerMock(); 219 $tagger = $this->getTaggerMock();
208 $tagger->expects($this->once()) 220 $tagger->expects($this->once())
209 ->method('tag'); 221 ->method('tag');
210 222
211 $graby = $this->getMockBuilder('Graby\Graby')->getMock(); 223 $validator = $this->getValidator();
212 224 $validator->expects($this->once())
213 $proxy = new ContentProxy($graby, $tagger, $this->getTagRepositoryMock(), $this->getLogger(), $this->fetchingErrorMessage); 225 ->method('validate')
214 $entry = $proxy->updateEntry(new Entry(new User()), 'http://0.0.0.0', [ 226 ->willReturn(new ConstraintViolationList([new ConstraintViolation('oops', 'oops', [], 'oops', 'language', 'dontexist')]));
215 'html' => str_repeat('this is my content', 325),
216 'title' => 'this is my title',
217 'url' => 'http://1.1.1.1',
218 'content_type' => 'text/html',
219 'language' => 'fr',
220 ]);
221
222 $this->assertEquals('http://1.1.1.1', $entry->getUrl());
223 $this->assertEquals('this is my title', $entry->getTitle());
224 $this->assertContains('this is my content', $entry->getContent());
225 $this->assertEquals('text/html', $entry->getMimetype());
226 $this->assertEquals('fr', $entry->getLanguage());
227 $this->assertEquals(4.0, $entry->getReadingTime());
228 $this->assertEquals('1.1.1.1', $entry->getDomainName());
229 }
230 227
231 public function testTaggerThrowException()
232 {
233 $graby = $this->getMockBuilder('Graby\Graby') 228 $graby = $this->getMockBuilder('Graby\Graby')
229 ->setMethods(['fetchContent'])
234 ->disableOriginalConstructor() 230 ->disableOriginalConstructor()
235 ->getMock(); 231 ->getMock();
236 232
237 $tagger = $this->getTaggerMock(); 233 $graby->expects($this->any())
238 $tagger->expects($this->once()) 234 ->method('fetchContent')
239 ->method('tag') 235 ->willReturn([
240 ->will($this->throwException(new \Exception())); 236 'html' => str_repeat('this is my content', 325),
241 237 'title' => 'this is my title',
242 $tagRepo = $this->getTagRepositoryMock(); 238 'url' => 'http://1.1.1.1',
243 $proxy = new ContentProxy($graby, $tagger, $tagRepo, $this->getLogger(), $this->fetchingErrorMessage); 239 'content_type' => 'text/html',
240 'language' => 'dontexist',
241 'status' => '200',
242 ]);
244 243
245 $entry = $proxy->updateEntry(new Entry(new User()), 'http://0.0.0.0', [ 244 $proxy = new ContentProxy($graby, $tagger, $validator, $this->getLogger(), $this->fetchingErrorMessage);
246 'html' => str_repeat('this is my content', 325), 245 $entry = new Entry(new User());
247 'title' => 'this is my title', 246 $proxy->updateEntry($entry, 'http://0.0.0.0');
248 'url' => 'http://1.1.1.1',
249 'content_type' => 'text/html',
250 'language' => 'fr',
251 ]);
252 247
253 $this->assertCount(0, $entry->getTags()); 248 $this->assertSame('http://1.1.1.1', $entry->getUrl());
249 $this->assertSame('this is my title', $entry->getTitle());
250 $this->assertContains('this is my content', $entry->getContent());
251 $this->assertSame('text/html', $entry->getMimetype());
252 $this->assertNull($entry->getLanguage());
253 $this->assertSame('200', $entry->getHttpStatus());
254 $this->assertSame(4.0, $entry->getReadingTime());
255 $this->assertSame('1.1.1.1', $entry->getDomainName());
254 } 256 }
255 257
256 public function testAssignTagsWithArrayAndExtraSpaces() 258 public function testWithContentAndBadOgImage()
257 { 259 {
260 $tagger = $this->getTaggerMock();
261 $tagger->expects($this->once())
262 ->method('tag');
263
264 $validator = $this->getValidator();
265 $validator->expects($this->exactly(2))
266 ->method('validate')
267 ->will($this->onConsecutiveCalls(
268 new ConstraintViolationList(),
269 new ConstraintViolationList([new ConstraintViolation('oops', 'oops', [], 'oops', 'url', 'https://')])
270 ));
271
258 $graby = $this->getMockBuilder('Graby\Graby') 272 $graby = $this->getMockBuilder('Graby\Graby')
273 ->setMethods(['fetchContent'])
259 ->disableOriginalConstructor() 274 ->disableOriginalConstructor()
260 ->getMock(); 275 ->getMock();
261 276
262 $tagRepo = $this->getTagRepositoryMock(); 277 $graby->expects($this->any())
263 $proxy = new ContentProxy($graby, $this->getTaggerMock(), $tagRepo, $this->getLogger(), $this->fetchingErrorMessage); 278 ->method('fetchContent')
279 ->willReturn([
280 'html' => str_repeat('this is my content', 325),
281 'title' => 'this is my title',
282 'url' => 'http://1.1.1.1',
283 'content_type' => 'text/html',
284 'language' => 'fr',
285 'status' => '200',
286 'open_graph' => [
287 'og_title' => 'my OG title',
288 'og_description' => 'OG desc',
289 'og_image' => 'https://',
290 ],
291 ]);
264 292
293 $proxy = new ContentProxy($graby, $tagger, $validator, $this->getLogger(), $this->fetchingErrorMessage);
265 $entry = new Entry(new User()); 294 $entry = new Entry(new User());
295 $proxy->updateEntry($entry, 'http://0.0.0.0');
266 296
267 $proxy->assignTagsToEntry($entry, [' tag1', 'tag2 ']); 297 $this->assertSame('http://1.1.1.1', $entry->getUrl());
268 298 $this->assertSame('this is my title', $entry->getTitle());
269 $this->assertCount(2, $entry->getTags()); 299 $this->assertContains('this is my content', $entry->getContent());
270 $this->assertEquals('tag1', $entry->getTags()[0]->getLabel()); 300 $this->assertNull($entry->getPreviewPicture());
271 $this->assertEquals('tag2', $entry->getTags()[1]->getLabel()); 301 $this->assertSame('text/html', $entry->getMimetype());
302 $this->assertSame('fr', $entry->getLanguage());
303 $this->assertSame('200', $entry->getHttpStatus());
304 $this->assertSame(4.0, $entry->getReadingTime());
305 $this->assertSame('1.1.1.1', $entry->getDomainName());
272 } 306 }
273 307
274 public function testAssignTagsWithString() 308 public function testWithForcedContent()
275 { 309 {
276 $graby = $this->getMockBuilder('Graby\Graby') 310 $tagger = $this->getTaggerMock();
277 ->disableOriginalConstructor() 311 $tagger->expects($this->once())
278 ->getMock(); 312 ->method('tag');
279
280 $tagRepo = $this->getTagRepositoryMock();
281 $proxy = new ContentProxy($graby, $this->getTaggerMock(), $tagRepo, $this->getLogger(), $this->fetchingErrorMessage);
282 313
314 $proxy = new ContentProxy((new Graby()), $tagger, $this->getValidator(), $this->getLogger(), $this->fetchingErrorMessage);
283 $entry = new Entry(new User()); 315 $entry = new Entry(new User());
316 $proxy->updateEntry(
317 $entry,
318 'http://0.0.0.0',
319 [
320 'html' => str_repeat('this is my content', 325),
321 'title' => 'this is my title',
322 'url' => 'http://1.1.1.1',
323 'content_type' => 'text/html',
324 'language' => 'fr',
325 'date' => '1395635872',
326 'authors' => ['Jeremy', 'Nico', 'Thomas'],
327 'all_headers' => [
328 'Cache-Control' => 'no-cache',
329 ],
330 ]
331 );
284 332
285 $proxy->assignTagsToEntry($entry, 'tag1, tag2'); 333 $this->assertSame('http://1.1.1.1', $entry->getUrl());
286 334 $this->assertSame('this is my title', $entry->getTitle());
287 $this->assertCount(2, $entry->getTags()); 335 $this->assertContains('this is my content', $entry->getContent());
288 $this->assertEquals('tag1', $entry->getTags()[0]->getLabel()); 336 $this->assertSame('text/html', $entry->getMimetype());
289 $this->assertEquals('tag2', $entry->getTags()[1]->getLabel()); 337 $this->assertSame('fr', $entry->getLanguage());
338 $this->assertSame(4.0, $entry->getReadingTime());
339 $this->assertSame('1.1.1.1', $entry->getDomainName());
340 $this->assertSame('24/03/2014', $entry->getPublishedAt()->format('d/m/Y'));
341 $this->assertContains('Jeremy', $entry->getPublishedBy());
342 $this->assertContains('Nico', $entry->getPublishedBy());
343 $this->assertContains('Thomas', $entry->getPublishedBy());
344 $this->assertContains('no-cache', $entry->getHeaders());
290 } 345 }
291 346
292 public function testAssignTagsWithEmptyArray() 347 public function testWithForcedContentAndDatetime()
293 { 348 {
294 $graby = $this->getMockBuilder('Graby\Graby') 349 $tagger = $this->getTaggerMock();
295 ->disableOriginalConstructor() 350 $tagger->expects($this->once())
296 ->getMock(); 351 ->method('tag');
297 352
298 $tagRepo = $this->getTagRepositoryMock(); 353 $logHandler = new TestHandler();
299 $proxy = new ContentProxy($graby, $this->getTaggerMock(), $tagRepo, $this->getLogger(), $this->fetchingErrorMessage); 354 $logger = new Logger('test', [$logHandler]);
300 355
356 $proxy = new ContentProxy((new Graby()), $tagger, $this->getValidator(), $logger, $this->fetchingErrorMessage);
301 $entry = new Entry(new User()); 357 $entry = new Entry(new User());
358 $proxy->updateEntry(
359 $entry,
360 'http://1.1.1.1',
361 [
362 'html' => str_repeat('this is my content', 325),
363 'title' => 'this is my title',
364 'url' => 'http://1.1.1.1',
365 'content_type' => 'text/html',
366 'language' => 'fr',
367 'date' => '2016-09-08T11:55:58+0200',
368 ]
369 );
302 370
303 $proxy->assignTagsToEntry($entry, []); 371 $this->assertSame('http://1.1.1.1', $entry->getUrl());
304 372 $this->assertSame('this is my title', $entry->getTitle());
305 $this->assertCount(0, $entry->getTags()); 373 $this->assertContains('this is my content', $entry->getContent());
374 $this->assertSame('text/html', $entry->getMimetype());
375 $this->assertSame('fr', $entry->getLanguage());
376 $this->assertSame(4.0, $entry->getReadingTime());
377 $this->assertSame('1.1.1.1', $entry->getDomainName());
378 $this->assertSame('08/09/2016', $entry->getPublishedAt()->format('d/m/Y'));
306 } 379 }
307 380
308 public function testAssignTagsWithEmptyString() 381 public function testWithForcedContentAndBadDate()
309 { 382 {
310 $graby = $this->getMockBuilder('Graby\Graby') 383 $tagger = $this->getTaggerMock();
311 ->disableOriginalConstructor() 384 $tagger->expects($this->once())
312 ->getMock(); 385 ->method('tag');
313 386
314 $tagRepo = $this->getTagRepositoryMock(); 387 $logger = new Logger('foo');
315 $proxy = new ContentProxy($graby, $this->getTaggerMock(), $tagRepo, $this->getLogger(), $this->fetchingErrorMessage); 388 $handler = new TestHandler();
389 $logger->pushHandler($handler);
316 390
391 $proxy = new ContentProxy((new Graby()), $tagger, $this->getValidator(), $logger, $this->fetchingErrorMessage);
317 $entry = new Entry(new User()); 392 $entry = new Entry(new User());
393 $proxy->updateEntry(
394 $entry,
395 'http://1.1.1.1',
396 [
397 'html' => str_repeat('this is my content', 325),
398 'title' => 'this is my title',
399 'url' => 'http://1.1.1.1',
400 'content_type' => 'text/html',
401 'language' => 'fr',
402 'date' => '01 02 2012',
403 ]
404 );
318 405
319 $proxy->assignTagsToEntry($entry, ''); 406 $this->assertSame('http://1.1.1.1', $entry->getUrl());
407 $this->assertSame('this is my title', $entry->getTitle());
408 $this->assertContains('this is my content', $entry->getContent());
409 $this->assertSame('text/html', $entry->getMimetype());
410 $this->assertSame('fr', $entry->getLanguage());
411 $this->assertSame(4.0, $entry->getReadingTime());
412 $this->assertSame('1.1.1.1', $entry->getDomainName());
413 $this->assertNull($entry->getPublishedAt());
320 414
321 $this->assertCount(0, $entry->getTags()); 415 $records = $handler->getRecords();
416
417 $this->assertCount(1, $records);
418 $this->assertContains('Error while defining date', $records[0]['message']);
322 } 419 }
323 420
324 public function testAssignTagsAlreadyAssigned() 421 public function testTaggerThrowException()
325 { 422 {
326 $graby = $this->getMockBuilder('Graby\Graby') 423 $tagger = $this->getTaggerMock();
327 ->disableOriginalConstructor() 424 $tagger->expects($this->once())
328 ->getMock(); 425 ->method('tag')
426 ->will($this->throwException(new \Exception()));
329 427
330 $tagRepo = $this->getTagRepositoryMock(); 428 $proxy = new ContentProxy((new Graby()), $tagger, $this->getValidator(), $this->getLogger(), $this->fetchingErrorMessage);
331 $proxy = new ContentProxy($graby, $this->getTaggerMock(), $tagRepo, $this->getLogger(), $this->fetchingErrorMessage); 429 $entry = new Entry(new User());
430 $proxy->updateEntry(
431 $entry,
432 'http://1.1.1.1',
433 [
434 'html' => str_repeat('this is my content', 325),
435 'title' => 'this is my title',
436 'url' => 'http://1.1.1.1',
437 'content_type' => 'text/html',
438 'language' => 'fr',
439 ]
440 );
332 441
333 $tagEntity = new Tag(); 442 $this->assertCount(0, $entry->getTags());
334 $tagEntity->setLabel('tag1'); 443 }
335 444
336 $entry = new Entry(new User()); 445 public function dataForCrazyHtml()
337 $entry->addTag($tagEntity); 446 {
447 return [
448 'script and comment' => [
449 '<strong>Script inside:</strong> <!--[if gte IE 4]><script>alert(\'lol\');</script><![endif]--><br />',
450 'lol',
451 ],
452 'script' => [
453 '<strong>Script inside:</strong><script>alert(\'lol\');</script>',
454 'script',
455 ],
456 ];
457 }
338 458
339 $proxy->assignTagsToEntry($entry, 'tag1, tag2'); 459 /**
460 * @dataProvider dataForCrazyHtml
461 */
462 public function testWithCrazyHtmlContent($html, $escapedString)
463 {
464 $tagger = $this->getTaggerMock();
465 $tagger->expects($this->once())
466 ->method('tag');
340 467
341 $this->assertCount(2, $entry->getTags()); 468 $proxy = new ContentProxy((new Graby()), $tagger, $this->getValidator(), $this->getLogger(), $this->fetchingErrorMessage);
342 $this->assertEquals('tag1', $entry->getTags()[0]->getLabel()); 469 $entry = new Entry(new User());
343 $this->assertEquals('tag2', $entry->getTags()[1]->getLabel()); 470 $proxy->updateEntry(
471 $entry,
472 'http://1.1.1.1',
473 [
474 'html' => $html,
475 'title' => 'this is my title',
476 'url' => 'http://1.1.1.1',
477 'content_type' => 'text/html',
478 'language' => 'fr',
479 'status' => '200',
480 'open_graph' => [
481 'og_title' => 'my OG title',
482 'og_description' => 'OG desc',
483 'og_image' => 'http://3.3.3.3/cover.jpg',
484 ],
485 ]
486 );
487
488 $this->assertSame('http://1.1.1.1', $entry->getUrl());
489 $this->assertSame('this is my title', $entry->getTitle());
490 $this->assertNotContains($escapedString, $entry->getContent());
491 $this->assertSame('http://3.3.3.3/cover.jpg', $entry->getPreviewPicture());
492 $this->assertSame('text/html', $entry->getMimetype());
493 $this->assertSame('fr', $entry->getLanguage());
494 $this->assertSame('200', $entry->getHttpStatus());
495 $this->assertSame('1.1.1.1', $entry->getDomainName());
344 } 496 }
345 497
346 public function testAssignTagsNotFlushed() 498 public function testWithImageAsContent()
347 { 499 {
500 $tagger = $this->getTaggerMock();
501 $tagger->expects($this->once())
502 ->method('tag');
503
348 $graby = $this->getMockBuilder('Graby\Graby') 504 $graby = $this->getMockBuilder('Graby\Graby')
505 ->setMethods(['fetchContent'])
349 ->disableOriginalConstructor() 506 ->disableOriginalConstructor()
350 ->getMock(); 507 ->getMock();
351 508
352 $tagRepo = $this->getTagRepositoryMock(); 509 $graby->expects($this->any())
353 $tagRepo->expects($this->never()) 510 ->method('fetchContent')
354 ->method('__call'); 511 ->willReturn([
355 512 'html' => '<p><img src="http://1.1.1.1/image.jpg" /></p>',
356 $proxy = new ContentProxy($graby, $this->getTaggerMock(), $tagRepo, $this->getLogger(), $this->fetchingErrorMessage); 513 'title' => 'this is my title',
357 514 'url' => 'http://1.1.1.1/image.jpg',
358 $tagEntity = new Tag(); 515 'content_type' => 'image/jpeg',
359 $tagEntity->setLabel('tag1'); 516 'status' => '200',
517 'open_graph' => [],
518 ]);
360 519
520 $proxy = new ContentProxy($graby, $tagger, $this->getValidator(), $this->getLogger(), $this->fetchingErrorMessage);
361 $entry = new Entry(new User()); 521 $entry = new Entry(new User());
362 522 $proxy->updateEntry($entry, 'http://0.0.0.0');
363 $proxy->assignTagsToEntry($entry, 'tag1', [$tagEntity]); 523
364 524 $this->assertSame('http://1.1.1.1/image.jpg', $entry->getUrl());
365 $this->assertCount(1, $entry->getTags()); 525 $this->assertSame('this is my title', $entry->getTitle());
366 $this->assertEquals('tag1', $entry->getTags()[0]->getLabel()); 526 $this->assertContains('http://1.1.1.1/image.jpg', $entry->getContent());
527 $this->assertSame('http://1.1.1.1/image.jpg', $entry->getPreviewPicture());
528 $this->assertSame('image/jpeg', $entry->getMimetype());
529 $this->assertSame('200', $entry->getHttpStatus());
530 $this->assertSame('1.1.1.1', $entry->getDomainName());
367 } 531 }
368 532
369 private function getTaggerMock() 533 private function getTaggerMock()
370 { 534 {
371 return $this->getMockBuilder('Wallabag\CoreBundle\Helper\RuleBasedTagger') 535 return $this->getMockBuilder(RuleBasedTagger::class)
372 ->setMethods(['tag']) 536 ->setMethods(['tag'])
373 ->disableOriginalConstructor() 537 ->disableOriginalConstructor()
374 ->getMock(); 538 ->getMock();
375 } 539 }
376 540
377 private function getTagRepositoryMock() 541 private function getLogger()
378 { 542 {
379 return $this->getMockBuilder('Wallabag\CoreBundle\Repository\TagRepository') 543 return new NullLogger();
380 ->disableOriginalConstructor()
381 ->getMock();
382 } 544 }
383 545
384 private function getLogger() 546 private function getValidator()
385 { 547 {
386 return new NullLogger(); 548 return $this->getMockBuilder(RecursiveValidator::class)
549 ->setMethods(['validate'])
550 ->disableOriginalConstructor()
551 ->getMock();
387 } 552 }
388} 553}
diff --git a/tests/Wallabag/CoreBundle/Helper/CryptoProxyTest.php b/tests/Wallabag/CoreBundle/Helper/CryptoProxyTest.php
new file mode 100644
index 00000000..782c29c3
--- /dev/null
+++ b/tests/Wallabag/CoreBundle/Helper/CryptoProxyTest.php
@@ -0,0 +1,40 @@
1<?php
2
3namespace Tests\Wallabag\CoreBundle\Helper;
4
5use Monolog\Handler\TestHandler;
6use Monolog\Logger;
7use Psr\Log\NullLogger;
8use Wallabag\CoreBundle\Helper\CryptoProxy;
9
10class CryptoProxyTest extends \PHPUnit_Framework_TestCase
11{
12 public function testCrypto()
13 {
14 $logHandler = new TestHandler();
15 $logger = new Logger('test', [$logHandler]);
16
17 $crypto = new CryptoProxy(sys_get_temp_dir() . '/' . uniqid('', true) . '.txt', $logger);
18 $crypted = $crypto->crypt('test');
19 $decrypted = $crypto->decrypt($crypted);
20
21 $this->assertSame('test', $decrypted);
22
23 $records = $logHandler->getRecords();
24 $this->assertCount(2, $records);
25 $this->assertContains('Crypto: crypting value', $records[0]['message']);
26 $this->assertContains('Crypto: decrypting value', $records[1]['message']);
27 }
28
29 /**
30 * @expectedException \RuntimeException
31 * @expectedExceptionMessage Decrypt fail
32 *
33 * @return [type] [description]
34 */
35 public function testDecryptBadValue()
36 {
37 $crypto = new CryptoProxy(sys_get_temp_dir() . '/' . uniqid('', true) . '.txt', new NullLogger());
38 $crypto->decrypt('badvalue');
39 }
40}
diff --git a/tests/Wallabag/CoreBundle/Helper/DownloadImagesTest.php b/tests/Wallabag/CoreBundle/Helper/DownloadImagesTest.php
index 85f12d87..c61f65d0 100644
--- a/tests/Wallabag/CoreBundle/Helper/DownloadImagesTest.php
+++ b/tests/Wallabag/CoreBundle/Helper/DownloadImagesTest.php
@@ -2,34 +2,52 @@
2 2
3namespace Tests\Wallabag\CoreBundle\Helper; 3namespace Tests\Wallabag\CoreBundle\Helper;
4 4
5use Wallabag\CoreBundle\Helper\DownloadImages;
6use Monolog\Logger;
7use Monolog\Handler\TestHandler;
8use GuzzleHttp\Client; 5use GuzzleHttp\Client;
9use GuzzleHttp\Subscriber\Mock;
10use GuzzleHttp\Message\Response; 6use GuzzleHttp\Message\Response;
11use GuzzleHttp\Stream\Stream; 7use GuzzleHttp\Stream\Stream;
8use GuzzleHttp\Subscriber\Mock;
9use Monolog\Handler\TestHandler;
10use Monolog\Logger;
11use Wallabag\CoreBundle\Helper\DownloadImages;
12 12
13class DownloadImagesTest extends \PHPUnit_Framework_TestCase 13class DownloadImagesTest extends \PHPUnit_Framework_TestCase
14{ 14{
15 public function testProcessHtml() 15 public function dataForSuccessImage()
16 {
17 return [
18 'imgur' => [
19 '<div><img src="http://i.imgur.com/T9qgcHc.jpg" /></div>',
20 'http://imgur.com/gallery/WxtWY',
21 ],
22 'image with &' => [
23 '<div><img src="https://i2.wp.com/www.tvaddons.ag/wp-content/uploads/2017/01/Screen-Shot-2017-01-07-at-10.17.40-PM.jpg?w=640&amp;ssl=1" /></div>',
24 'https://www.tvaddons.ag/realdebrid-kodi-jarvis/',
25 ],
26 ];
27 }
28
29 /**
30 * @dataProvider dataForSuccessImage
31 */
32 public function testProcessHtml($html, $url)
16 { 33 {
17 $client = new Client(); 34 $client = new Client();
18 35
19 $mock = new Mock([ 36 $mock = new Mock([
20 new Response(200, ['content-type' => 'image/png'], Stream::factory(file_get_contents(__DIR__.'/../fixtures/unnamed.png'))), 37 new Response(200, ['content-type' => 'image/png'], Stream::factory(file_get_contents(__DIR__ . '/../fixtures/unnamed.png'))),
21 ]); 38 ]);
22 39
23 $client->getEmitter()->attach($mock); 40 $client->getEmitter()->attach($mock);
24 41
25 $logHandler = new TestHandler(); 42 $logHandler = new TestHandler();
26 $logger = new Logger('test', array($logHandler)); 43 $logger = new Logger('test', [$logHandler]);
27 44
28 $download = new DownloadImages($client, sys_get_temp_dir().'/wallabag_test', 'http://wallabag.io/', $logger); 45 $download = new DownloadImages($client, sys_get_temp_dir() . '/wallabag_test', 'http://wallabag.io/', $logger);
29 46
30 $res = $download->processHtml(123, '<div><img src="http://i.imgur.com/T9qgcHc.jpg" /></div>', 'http://imgur.com/gallery/WxtWY'); 47 $res = $download->processHtml(123, $html, $url);
31 48
32 $this->assertContains('http://wallabag.io/assets/images/9/b/9b0ead26/c638b4c2.png', $res); 49 // this the base path of all image (since it's calculated using the entry id: 123)
50 $this->assertContains('http://wallabag.io/assets/images/9/b/9b0ead26/', $res);
33 } 51 }
34 52
35 public function testProcessHtmlWithBadImage() 53 public function testProcessHtmlWithBadImage()
@@ -43,9 +61,9 @@ class DownloadImagesTest extends \PHPUnit_Framework_TestCase
43 $client->getEmitter()->attach($mock); 61 $client->getEmitter()->attach($mock);
44 62
45 $logHandler = new TestHandler(); 63 $logHandler = new TestHandler();
46 $logger = new Logger('test', array($logHandler)); 64 $logger = new Logger('test', [$logHandler]);
47 65
48 $download = new DownloadImages($client, sys_get_temp_dir().'/wallabag_test', 'http://wallabag.io/', $logger); 66 $download = new DownloadImages($client, sys_get_temp_dir() . '/wallabag_test', 'http://wallabag.io/', $logger);
49 $res = $download->processHtml(123, '<div><img src="http://i.imgur.com/T9qgcHc.jpg" /></div>', 'http://imgur.com/gallery/WxtWY'); 67 $res = $download->processHtml(123, '<div><img src="http://i.imgur.com/T9qgcHc.jpg" /></div>', 'http://imgur.com/gallery/WxtWY');
50 68
51 $this->assertContains('http://i.imgur.com/T9qgcHc.jpg', $res, 'Image were not replace because of content-type'); 69 $this->assertContains('http://i.imgur.com/T9qgcHc.jpg', $res, 'Image were not replace because of content-type');
@@ -69,18 +87,18 @@ class DownloadImagesTest extends \PHPUnit_Framework_TestCase
69 $client = new Client(); 87 $client = new Client();
70 88
71 $mock = new Mock([ 89 $mock = new Mock([
72 new Response(200, ['content-type' => $header], Stream::factory(file_get_contents(__DIR__.'/../fixtures/unnamed.png'))), 90 new Response(200, ['content-type' => $header], Stream::factory(file_get_contents(__DIR__ . '/../fixtures/unnamed.png'))),
73 ]); 91 ]);
74 92
75 $client->getEmitter()->attach($mock); 93 $client->getEmitter()->attach($mock);
76 94
77 $logHandler = new TestHandler(); 95 $logHandler = new TestHandler();
78 $logger = new Logger('test', array($logHandler)); 96 $logger = new Logger('test', [$logHandler]);
79 97
80 $download = new DownloadImages($client, sys_get_temp_dir().'/wallabag_test', 'http://wallabag.io/', $logger); 98 $download = new DownloadImages($client, sys_get_temp_dir() . '/wallabag_test', 'http://wallabag.io/', $logger);
81 $res = $download->processSingleImage(123, 'T9qgcHc.jpg', 'http://imgur.com/gallery/WxtWY'); 99 $res = $download->processSingleImage(123, 'T9qgcHc.jpg', 'http://imgur.com/gallery/WxtWY');
82 100
83 $this->assertContains('/assets/images/9/b/9b0ead26/ebe60399.'.$extension, $res); 101 $this->assertContains('/assets/images/9/b/9b0ead26/ebe60399.' . $extension, $res);
84 } 102 }
85 103
86 public function testProcessSingleImageWithBadUrl() 104 public function testProcessSingleImageWithBadUrl()
@@ -94,9 +112,9 @@ class DownloadImagesTest extends \PHPUnit_Framework_TestCase
94 $client->getEmitter()->attach($mock); 112 $client->getEmitter()->attach($mock);
95 113
96 $logHandler = new TestHandler(); 114 $logHandler = new TestHandler();
97 $logger = new Logger('test', array($logHandler)); 115 $logger = new Logger('test', [$logHandler]);
98 116
99 $download = new DownloadImages($client, sys_get_temp_dir().'/wallabag_test', 'http://wallabag.io/', $logger); 117 $download = new DownloadImages($client, sys_get_temp_dir() . '/wallabag_test', 'http://wallabag.io/', $logger);
100 $res = $download->processSingleImage(123, 'T9qgcHc.jpg', 'http://imgur.com/gallery/WxtWY'); 118 $res = $download->processSingleImage(123, 'T9qgcHc.jpg', 'http://imgur.com/gallery/WxtWY');
101 119
102 $this->assertFalse($res, 'Image can not be found, so it will not be replaced'); 120 $this->assertFalse($res, 'Image can not be found, so it will not be replaced');
@@ -113,9 +131,9 @@ class DownloadImagesTest extends \PHPUnit_Framework_TestCase
113 $client->getEmitter()->attach($mock); 131 $client->getEmitter()->attach($mock);
114 132
115 $logHandler = new TestHandler(); 133 $logHandler = new TestHandler();
116 $logger = new Logger('test', array($logHandler)); 134 $logger = new Logger('test', [$logHandler]);
117 135
118 $download = new DownloadImages($client, sys_get_temp_dir().'/wallabag_test', 'http://wallabag.io/', $logger); 136 $download = new DownloadImages($client, sys_get_temp_dir() . '/wallabag_test', 'http://wallabag.io/', $logger);
119 $res = $download->processSingleImage(123, 'http://i.imgur.com/T9qgcHc.jpg', 'http://imgur.com/gallery/WxtWY'); 137 $res = $download->processSingleImage(123, 'http://i.imgur.com/T9qgcHc.jpg', 'http://imgur.com/gallery/WxtWY');
120 138
121 $this->assertFalse($res, 'Image can not be loaded, so it will not be replaced'); 139 $this->assertFalse($res, 'Image can not be loaded, so it will not be replaced');
@@ -126,17 +144,42 @@ class DownloadImagesTest extends \PHPUnit_Framework_TestCase
126 $client = new Client(); 144 $client = new Client();
127 145
128 $mock = new Mock([ 146 $mock = new Mock([
129 new Response(200, ['content-type' => 'image/png'], Stream::factory(file_get_contents(__DIR__.'/../fixtures/unnamed.png'))), 147 new Response(200, ['content-type' => 'image/png'], Stream::factory(file_get_contents(__DIR__ . '/../fixtures/unnamed.png'))),
130 ]); 148 ]);
131 149
132 $client->getEmitter()->attach($mock); 150 $client->getEmitter()->attach($mock);
133 151
134 $logHandler = new TestHandler(); 152 $logHandler = new TestHandler();
135 $logger = new Logger('test', array($logHandler)); 153 $logger = new Logger('test', [$logHandler]);
136 154
137 $download = new DownloadImages($client, sys_get_temp_dir().'/wallabag_test', 'http://wallabag.io/', $logger); 155 $download = new DownloadImages($client, sys_get_temp_dir() . '/wallabag_test', 'http://wallabag.io/', $logger);
138 $res = $download->processSingleImage(123, '/i.imgur.com/T9qgcHc.jpg', 'imgur.com/gallery/WxtWY'); 156 $res = $download->processSingleImage(123, '/i.imgur.com/T9qgcHc.jpg', 'imgur.com/gallery/WxtWY');
139 157
140 $this->assertFalse($res, 'Absolute image can not be determined, so it will not be replaced'); 158 $this->assertFalse($res, 'Absolute image can not be determined, so it will not be replaced');
141 } 159 }
160
161 public function testProcessRealImage()
162 {
163 $client = new Client();
164
165 $mock = new Mock([
166 new Response(200, ['content-type' => null], Stream::factory(file_get_contents(__DIR__ . '/../fixtures/image-no-content-type.jpg'))),
167 ]);
168
169 $client->getEmitter()->attach($mock);
170
171 $logHandler = new TestHandler();
172 $logger = new Logger('test', [$logHandler]);
173
174 $download = new DownloadImages($client, sys_get_temp_dir() . '/wallabag_test', 'http://wallabag.io/', $logger);
175
176 $res = $download->processSingleImage(
177 123,
178 'https://cdn.theconversation.com/files/157200/article/width926/gsj2rjp2-1487348607.jpg',
179 'https://theconversation.com/conversation-avec-gerald-bronner-ce-nest-pas-la-post-verite-qui-nous-menace-mais-lextension-de-notre-credulite-73089'
180 );
181
182 $this->assertContains('http://wallabag.io/assets/images/9/b/9b0ead26/', $res, 'Content-Type was empty but data is ok for an image');
183 $this->assertContains('DownloadImages: Checking extension (alternative)', $logHandler->getRecords()[3]['message']);
184 }
142} 185}
diff --git a/tests/Wallabag/CoreBundle/Helper/RedirectTest.php b/tests/Wallabag/CoreBundle/Helper/RedirectTest.php
index 0539f20a..7fd2ea2b 100644
--- a/tests/Wallabag/CoreBundle/Helper/RedirectTest.php
+++ b/tests/Wallabag/CoreBundle/Helper/RedirectTest.php
@@ -2,11 +2,11 @@
2 2
3namespace Tests\Wallabag\CoreBundle\Helper; 3namespace Tests\Wallabag\CoreBundle\Helper;
4 4
5use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
6use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
5use Wallabag\CoreBundle\Entity\Config; 7use Wallabag\CoreBundle\Entity\Config;
6use Wallabag\UserBundle\Entity\User;
7use Wallabag\CoreBundle\Helper\Redirect; 8use Wallabag\CoreBundle\Helper\Redirect;
8use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; 9use Wallabag\UserBundle\Entity\User;
9use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
10 10
11class RedirectTest extends \PHPUnit_Framework_TestCase 11class RedirectTest extends \PHPUnit_Framework_TestCase
12{ 12{
@@ -56,21 +56,21 @@ class RedirectTest extends \PHPUnit_Framework_TestCase
56 { 56 {
57 $redirectUrl = $this->redirect->to(null, 'fallback'); 57 $redirectUrl = $this->redirect->to(null, 'fallback');
58 58
59 $this->assertEquals('fallback', $redirectUrl); 59 $this->assertSame('fallback', $redirectUrl);
60 } 60 }
61 61
62 public function testRedirectToNullWithoutFallback() 62 public function testRedirectToNullWithoutFallback()
63 { 63 {
64 $redirectUrl = $this->redirect->to(null); 64 $redirectUrl = $this->redirect->to(null);
65 65
66 $this->assertEquals($this->routerMock->generate('homepage'), $redirectUrl); 66 $this->assertSame($this->routerMock->generate('homepage'), $redirectUrl);
67 } 67 }
68 68
69 public function testRedirectToValidUrl() 69 public function testRedirectToValidUrl()
70 { 70 {
71 $redirectUrl = $this->redirect->to('/unread/list'); 71 $redirectUrl = $this->redirect->to('/unread/list');
72 72
73 $this->assertEquals('/unread/list', $redirectUrl); 73 $this->assertSame('/unread/list', $redirectUrl);
74 } 74 }
75 75
76 public function testWithNotLoggedUser() 76 public function testWithNotLoggedUser()
@@ -78,7 +78,7 @@ class RedirectTest extends \PHPUnit_Framework_TestCase
78 $redirect = new Redirect($this->routerMock, new TokenStorage()); 78 $redirect = new Redirect($this->routerMock, new TokenStorage());
79 $redirectUrl = $redirect->to('/unread/list'); 79 $redirectUrl = $redirect->to('/unread/list');
80 80
81 $this->assertEquals('/unread/list', $redirectUrl); 81 $this->assertSame('/unread/list', $redirectUrl);
82 } 82 }
83 83
84 public function testUserForRedirectToHomepage() 84 public function testUserForRedirectToHomepage()
@@ -87,6 +87,24 @@ class RedirectTest extends \PHPUnit_Framework_TestCase
87 87
88 $redirectUrl = $this->redirect->to('/unread/list'); 88 $redirectUrl = $this->redirect->to('/unread/list');
89 89
90 $this->assertEquals($this->routerMock->generate('homepage'), $redirectUrl); 90 $this->assertSame($this->routerMock->generate('homepage'), $redirectUrl);
91 }
92
93 public function testUserForRedirectWithIgnoreActionMarkAsRead()
94 {
95 $this->token->getUser()->getConfig()->setActionMarkAsRead(Config::REDIRECT_TO_HOMEPAGE);
96
97 $redirectUrl = $this->redirect->to('/unread/list', '', true);
98
99 $this->assertSame('/unread/list', $redirectUrl);
100 }
101
102 public function testUserForRedirectNullWithFallbackWithIgnoreActionMarkAsRead()
103 {
104 $this->token->getUser()->getConfig()->setActionMarkAsRead(Config::REDIRECT_TO_HOMEPAGE);
105
106 $redirectUrl = $this->redirect->to(null, 'fallback', true);
107
108 $this->assertSame('fallback', $redirectUrl);
91 } 109 }
92} 110}
diff --git a/tests/Wallabag/CoreBundle/Helper/RuleBasedTaggerTest.php b/tests/Wallabag/CoreBundle/Helper/RuleBasedTaggerTest.php
index 17b08c2a..c31af680 100644
--- a/tests/Wallabag/CoreBundle/Helper/RuleBasedTaggerTest.php
+++ b/tests/Wallabag/CoreBundle/Helper/RuleBasedTaggerTest.php
@@ -2,6 +2,8 @@
2 2
3namespace Tests\Wallabag\CoreBundle\Helper; 3namespace Tests\Wallabag\CoreBundle\Helper;
4 4
5use Monolog\Handler\TestHandler;
6use Monolog\Logger;
5use Wallabag\CoreBundle\Entity\Config; 7use Wallabag\CoreBundle\Entity\Config;
6use Wallabag\CoreBundle\Entity\Entry; 8use Wallabag\CoreBundle\Entity\Entry;
7use Wallabag\CoreBundle\Entity\Tag; 9use Wallabag\CoreBundle\Entity\Tag;
@@ -15,14 +17,19 @@ class RuleBasedTaggerTest extends \PHPUnit_Framework_TestCase
15 private $tagRepository; 17 private $tagRepository;
16 private $entryRepository; 18 private $entryRepository;
17 private $tagger; 19 private $tagger;
20 private $logger;
21 private $handler;
18 22
19 public function setUp() 23 public function setUp()
20 { 24 {
21 $this->rulerz = $this->getRulerZMock(); 25 $this->rulerz = $this->getRulerZMock();
22 $this->tagRepository = $this->getTagRepositoryMock(); 26 $this->tagRepository = $this->getTagRepositoryMock();
23 $this->entryRepository = $this->getEntryRepositoryMock(); 27 $this->entryRepository = $this->getEntryRepositoryMock();
28 $this->logger = $this->getLogger();
29 $this->handler = new TestHandler();
30 $this->logger->pushHandler($this->handler);
24 31
25 $this->tagger = new RuleBasedTagger($this->rulerz, $this->tagRepository, $this->entryRepository); 32 $this->tagger = new RuleBasedTagger($this->rulerz, $this->tagRepository, $this->entryRepository, $this->logger);
26 } 33 }
27 34
28 public function testTagWithNoRule() 35 public function testTagWithNoRule()
@@ -32,6 +39,8 @@ class RuleBasedTaggerTest extends \PHPUnit_Framework_TestCase
32 $this->tagger->tag($entry); 39 $this->tagger->tag($entry);
33 40
34 $this->assertTrue($entry->getTags()->isEmpty()); 41 $this->assertTrue($entry->getTags()->isEmpty());
42 $records = $this->handler->getRecords();
43 $this->assertCount(0, $records);
35 } 44 }
36 45
37 public function testTagWithNoMatchingRule() 46 public function testTagWithNoMatchingRule()
@@ -49,6 +58,8 @@ class RuleBasedTaggerTest extends \PHPUnit_Framework_TestCase
49 $this->tagger->tag($entry); 58 $this->tagger->tag($entry);
50 59
51 $this->assertTrue($entry->getTags()->isEmpty()); 60 $this->assertTrue($entry->getTags()->isEmpty());
61 $records = $this->handler->getRecords();
62 $this->assertCount(0, $records);
52 } 63 }
53 64
54 public function testTagWithAMatchingRule() 65 public function testTagWithAMatchingRule()
@@ -70,6 +81,9 @@ class RuleBasedTaggerTest extends \PHPUnit_Framework_TestCase
70 $tags = $entry->getTags(); 81 $tags = $entry->getTags();
71 $this->assertSame('foo', $tags[0]->getLabel()); 82 $this->assertSame('foo', $tags[0]->getLabel());
72 $this->assertSame('bar', $tags[1]->getLabel()); 83 $this->assertSame('bar', $tags[1]->getLabel());
84
85 $records = $this->handler->getRecords();
86 $this->assertCount(1, $records);
73 } 87 }
74 88
75 public function testTagWithAMixOfMatchingRules() 89 public function testTagWithAMixOfMatchingRules()
@@ -90,6 +104,8 @@ class RuleBasedTaggerTest extends \PHPUnit_Framework_TestCase
90 104
91 $tags = $entry->getTags(); 105 $tags = $entry->getTags();
92 $this->assertSame('foo', $tags[0]->getLabel()); 106 $this->assertSame('foo', $tags[0]->getLabel());
107 $records = $this->handler->getRecords();
108 $this->assertCount(1, $records);
93 } 109 }
94 110
95 public function testWhenTheTagExists() 111 public function testWhenTheTagExists()
@@ -118,6 +134,8 @@ class RuleBasedTaggerTest extends \PHPUnit_Framework_TestCase
118 134
119 $tags = $entry->getTags(); 135 $tags = $entry->getTags();
120 $this->assertSame($tag, $tags[0]); 136 $this->assertSame($tag, $tags[0]);
137 $records = $this->handler->getRecords();
138 $this->assertCount(1, $records);
121 } 139 }
122 140
123 public function testSameTagWithDifferentfMatchingRules() 141 public function testSameTagWithDifferentfMatchingRules()
@@ -138,6 +156,8 @@ class RuleBasedTaggerTest extends \PHPUnit_Framework_TestCase
138 156
139 $tags = $entry->getTags(); 157 $tags = $entry->getTags();
140 $this->assertCount(1, $tags); 158 $this->assertCount(1, $tags);
159 $records = $this->handler->getRecords();
160 $this->assertCount(2, $records);
141 } 161 }
142 162
143 public function testTagAllEntriesForAUser() 163 public function testTagAllEntriesForAUser()
@@ -162,7 +182,7 @@ class RuleBasedTaggerTest extends \PHPUnit_Framework_TestCase
162 $tags = $entry->getTags(); 182 $tags = $entry->getTags();
163 183
164 $this->assertCount(1, $tags); 184 $this->assertCount(1, $tags);
165 $this->assertEquals('hey', $tags[0]->getLabel()); 185 $this->assertSame('hey', $tags[0]->getLabel());
166 } 186 }
167 } 187 }
168 188
@@ -209,4 +229,9 @@ class RuleBasedTaggerTest extends \PHPUnit_Framework_TestCase
209 ->disableOriginalConstructor() 229 ->disableOriginalConstructor()
210 ->getMock(); 230 ->getMock();
211 } 231 }
232
233 private function getLogger()
234 {
235 return new Logger('foo');
236 }
212} 237}
diff --git a/tests/Wallabag/CoreBundle/Helper/TagsAssignerTest.php b/tests/Wallabag/CoreBundle/Helper/TagsAssignerTest.php
new file mode 100644
index 00000000..475cd349
--- /dev/null
+++ b/tests/Wallabag/CoreBundle/Helper/TagsAssignerTest.php
@@ -0,0 +1,108 @@
1<?php
2
3namespace Tests\Wallabag\CoreBundle\Helper;
4
5use Wallabag\CoreBundle\Entity\Entry;
6use Wallabag\CoreBundle\Entity\Tag;
7use Wallabag\CoreBundle\Helper\TagsAssigner;
8use Wallabag\CoreBundle\Repository\TagRepository;
9use Wallabag\UserBundle\Entity\User;
10
11class TagsAssignerTest extends \PHPUnit_Framework_TestCase
12{
13 public function testAssignTagsWithArrayAndExtraSpaces()
14 {
15 $tagRepo = $this->getTagRepositoryMock();
16 $tagsAssigner = new TagsAssigner($tagRepo);
17
18 $entry = new Entry(new User());
19
20 $tagsAssigner->assignTagsToEntry($entry, [' tag1', 'tag2 ']);
21
22 $this->assertCount(2, $entry->getTags());
23 $this->assertSame('tag1', $entry->getTags()[0]->getLabel());
24 $this->assertSame('tag2', $entry->getTags()[1]->getLabel());
25 }
26
27 public function testAssignTagsWithString()
28 {
29 $tagRepo = $this->getTagRepositoryMock();
30 $tagsAssigner = new TagsAssigner($tagRepo);
31
32 $entry = new Entry(new User());
33
34 $tagsAssigner->assignTagsToEntry($entry, 'tag1, tag2');
35
36 $this->assertCount(2, $entry->getTags());
37 $this->assertSame('tag1', $entry->getTags()[0]->getLabel());
38 $this->assertSame('tag2', $entry->getTags()[1]->getLabel());
39 }
40
41 public function testAssignTagsWithEmptyArray()
42 {
43 $tagRepo = $this->getTagRepositoryMock();
44 $tagsAssigner = new TagsAssigner($tagRepo);
45
46 $entry = new Entry(new User());
47
48 $tagsAssigner->assignTagsToEntry($entry, []);
49
50 $this->assertCount(0, $entry->getTags());
51 }
52
53 public function testAssignTagsWithEmptyString()
54 {
55 $tagRepo = $this->getTagRepositoryMock();
56 $tagsAssigner = new TagsAssigner($tagRepo);
57
58 $entry = new Entry(new User());
59
60 $tagsAssigner->assignTagsToEntry($entry, '');
61
62 $this->assertCount(0, $entry->getTags());
63 }
64
65 public function testAssignTagsAlreadyAssigned()
66 {
67 $tagRepo = $this->getTagRepositoryMock();
68 $tagsAssigner = new TagsAssigner($tagRepo);
69
70 $tagEntity = new Tag();
71 $tagEntity->setLabel('tag1');
72
73 $entry = new Entry(new User());
74 $entry->addTag($tagEntity);
75
76 $tagsAssigner->assignTagsToEntry($entry, 'tag1, tag2');
77
78 $this->assertCount(2, $entry->getTags());
79 $this->assertSame('tag1', $entry->getTags()[0]->getLabel());
80 $this->assertSame('tag2', $entry->getTags()[1]->getLabel());
81 }
82
83 public function testAssignTagsNotFlushed()
84 {
85 $tagRepo = $this->getTagRepositoryMock();
86 $tagRepo->expects($this->never())
87 ->method('__call');
88
89 $tagsAssigner = new TagsAssigner($tagRepo);
90
91 $tagEntity = new Tag();
92 $tagEntity->setLabel('tag1');
93
94 $entry = new Entry(new User());
95
96 $tagsAssigner->assignTagsToEntry($entry, 'tag1', [$tagEntity]);
97
98 $this->assertCount(1, $entry->getTags());
99 $this->assertSame('tag1', $entry->getTags()[0]->getLabel());
100 }
101
102 private function getTagRepositoryMock()
103 {
104 return $this->getMockBuilder(TagRepository::class)
105 ->disableOriginalConstructor()
106 ->getMock();
107 }
108}
diff --git a/tests/Wallabag/CoreBundle/ParamConverter/UsernameRssTokenConverterTest.php b/tests/Wallabag/CoreBundle/ParamConverter/UsernameRssTokenConverterTest.php
index 2e6fccfb..74c645ef 100644
--- a/tests/Wallabag/CoreBundle/ParamConverter/UsernameRssTokenConverterTest.php
+++ b/tests/Wallabag/CoreBundle/ParamConverter/UsernameRssTokenConverterTest.php
@@ -136,7 +136,7 @@ class UsernameRssTokenConverterTest extends \PHPUnit_Framework_TestCase
136 } 136 }
137 137
138 /** 138 /**
139 * @expectedException Symfony\Component\HttpKernel\Exception\NotFoundHttpException 139 * @expectedException \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
140 * @expectedExceptionMessage User not found 140 * @expectedExceptionMessage User not found
141 */ 141 */
142 public function testApplyUserNotFound() 142 public function testApplyUserNotFound()
@@ -212,6 +212,6 @@ class UsernameRssTokenConverterTest extends \PHPUnit_Framework_TestCase
212 212
213 $converter->apply($request, $params); 213 $converter->apply($request, $params);
214 214
215 $this->assertEquals($user, $request->attributes->get('user')); 215 $this->assertSame($user, $request->attributes->get('user'));
216 } 216 }
217} 217}
diff --git a/tests/Wallabag/CoreBundle/Tools/UtilsTest.php b/tests/Wallabag/CoreBundle/Tools/UtilsTest.php
index 435c25ca..4521e485 100644
--- a/tests/Wallabag/CoreBundle/Tools/UtilsTest.php
+++ b/tests/Wallabag/CoreBundle/Tools/UtilsTest.php
@@ -18,7 +18,7 @@ class UtilsTest extends \PHPUnit_Framework_TestCase
18 public function examples() 18 public function examples()
19 { 19 {
20 $examples = []; 20 $examples = [];
21 $finder = (new Finder())->in(__DIR__.'/samples'); 21 $finder = (new Finder())->in(__DIR__ . '/samples');
22 foreach ($finder->getIterator() as $file) { 22 foreach ($finder->getIterator() as $file) {
23 $examples[] = [$file->getContents(), 1]; 23 $examples[] = [$file->getContents(), 1];
24 } 24 }
diff --git a/tests/Wallabag/CoreBundle/Twig/WallabagExtensionTest.php b/tests/Wallabag/CoreBundle/Twig/WallabagExtensionTest.php
index b1c8c946..ceec4b37 100644
--- a/tests/Wallabag/CoreBundle/Twig/WallabagExtensionTest.php
+++ b/tests/Wallabag/CoreBundle/Twig/WallabagExtensionTest.php
@@ -26,8 +26,8 @@ class WallabagExtensionTest extends \PHPUnit_Framework_TestCase
26 26
27 $extension = new WallabagExtension($entryRepository, $tagRepository, $tokenStorage, 0, $translator); 27 $extension = new WallabagExtension($entryRepository, $tagRepository, $tokenStorage, 0, $translator);
28 28
29 $this->assertEquals('lemonde.fr', $extension->removeWww('www.lemonde.fr')); 29 $this->assertSame('lemonde.fr', $extension->removeWww('www.lemonde.fr'));
30 $this->assertEquals('lemonde.fr', $extension->removeWww('lemonde.fr')); 30 $this->assertSame('lemonde.fr', $extension->removeWww('lemonde.fr'));
31 $this->assertEquals('gist.github.com', $extension->removeWww('gist.github.com')); 31 $this->assertSame('gist.github.com', $extension->removeWww('gist.github.com'));
32 } 32 }
33} 33}
diff --git a/tests/Wallabag/CoreBundle/WallabagCoreTestCase.php b/tests/Wallabag/CoreBundle/WallabagCoreTestCase.php
index 7bf4b43c..1eda5199 100644
--- a/tests/Wallabag/CoreBundle/WallabagCoreTestCase.php
+++ b/tests/Wallabag/CoreBundle/WallabagCoreTestCase.php
@@ -2,25 +2,72 @@
2 2
3namespace Tests\Wallabag\CoreBundle; 3namespace Tests\Wallabag\CoreBundle;
4 4
5use Symfony\Bundle\FrameworkBundle\Client;
6use Symfony\Bundle\FrameworkBundle\Console\Application;
5use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; 7use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
6use Symfony\Component\BrowserKit\Cookie; 8use Symfony\Component\BrowserKit\Cookie;
9use Symfony\Component\Console\Input\ArrayInput;
10use Symfony\Component\Console\Output\NullOutput;
11use Wallabag\CoreBundle\Entity\Config;
12use Wallabag\UserBundle\Entity\User;
7 13
8abstract class WallabagCoreTestCase extends WebTestCase 14abstract class WallabagCoreTestCase extends WebTestCase
9{ 15{
16 /**
17 * @var Client|null
18 */
10 private $client = null; 19 private $client = null;
11 20
21 public function setUp()
22 {
23 parent::setUp();
24
25 $this->client = static::createClient();
26 }
27
12 public function getClient() 28 public function getClient()
13 { 29 {
14 return $this->client; 30 return $this->client;
15 } 31 }
16 32
17 public function setUp() 33 public function resetDatabase(Client $client)
18 { 34 {
19 parent::setUp(); 35 $application = new Application($client->getKernel());
20 36 $application->setAutoExit(false);
37
38 $application->run(new ArrayInput([
39 'command' => 'doctrine:schema:drop',
40 '--no-interaction' => true,
41 '--force' => true,
42 '--env' => 'test',
43 ]), new NullOutput());
44
45 $application->run(new ArrayInput([
46 'command' => 'doctrine:schema:create',
47 '--no-interaction' => true,
48 '--env' => 'test',
49 ]), new NullOutput());
50
51 $application->run(new ArrayInput([
52 'command' => 'doctrine:fixtures:load',
53 '--no-interaction' => true,
54 '--env' => 'test',
55 ]), new NullOutput());
56
57 /*
58 * Recreate client to avoid error:
59 *
60 * [Doctrine\DBAL\ConnectionException]
61 * Transaction commit failed because the transaction has been marked for rollback only.
62 */
21 $this->client = static::createClient(); 63 $this->client = static::createClient();
22 } 64 }
23 65
66 public function getEntityManager()
67 {
68 return $this->client->getContainer()->get('doctrine.orm.entity_manager');
69 }
70
24 /** 71 /**
25 * Login a user without making a HTTP request. 72 * Login a user without making a HTTP request.
26 * If we make a HTTP request we lose ability to mock service in the container. 73 * If we make a HTTP request we lose ability to mock service in the container.
@@ -36,10 +83,10 @@ abstract class WallabagCoreTestCase extends WebTestCase
36 $loginManager = $container->get('fos_user.security.login_manager'); 83 $loginManager = $container->get('fos_user.security.login_manager');
37 $firewallName = $container->getParameter('fos_user.firewall_name'); 84 $firewallName = $container->getParameter('fos_user.firewall_name');
38 85
39 $user = $userManager->findUserBy(array('username' => $username)); 86 $user = $userManager->findUserBy(['username' => $username]);
40 $loginManager->loginUser($firewallName, $user); 87 $loginManager->logInUser($firewallName, $user);
41 88
42 $session->set('_security_'.$firewallName, serialize($container->get('security.token_storage')->getToken())); 89 $session->set('_security_' . $firewallName, serialize($container->get('security.token_storage')->getToken()));
43 $session->save(); 90 $session->save();
44 91
45 $cookie = new Cookie($session->getName(), $session->getId()); 92 $cookie = new Cookie($session->getName(), $session->getId());
@@ -65,23 +112,42 @@ abstract class WallabagCoreTestCase extends WebTestCase
65 } 112 }
66 113
67 /** 114 /**
68 * Return the user id of the logged in user. 115 * Return the user of the logged in user.
69 * You should be sure that you called `logInAs` before. 116 * You should be sure that you called `logInAs` before.
70 * 117 *
71 * @return int 118 * @return User
72 */ 119 */
73 public function getLoggedInUserId() 120 public function getLoggedInUser()
74 { 121 {
75 $token = static::$kernel->getContainer()->get('security.token_storage')->getToken(); 122 $token = static::$kernel->getContainer()->get('security.token_storage')->getToken();
76 123
77 if (null !== $token) { 124 if (null !== $token) {
78 return $token->getUser()->getId(); 125 return $token->getUser();
79 } 126 }
80 127
81 throw new \RuntimeException('No logged in User.'); 128 throw new \RuntimeException('No logged in User.');
82 } 129 }
83 130
84 /** 131 /**
132 * Return the user id of the logged in user.
133 * You should be sure that you called `logInAs` before.
134 *
135 * @return int
136 */
137 public function getLoggedInUserId()
138 {
139 return $this->getLoggedInUser()->getId();
140 }
141
142 public function useTheme($theme)
143 {
144 $config = $this->getEntityManager()->getRepository(Config::class)->findOneByUser($this->getLoggedInUser());
145 $config->setTheme($theme);
146 $this->getEntityManager()->persist($config);
147 $this->getEntityManager()->flush();
148 }
149
150 /**
85 * Check if Redis is installed. 151 * Check if Redis is installed.
86 * If not, mark test as skip. 152 * If not, mark test as skip.
87 */ 153 */
diff --git a/tests/Wallabag/CoreBundle/fixtures/image-no-content-type.jpg b/tests/Wallabag/CoreBundle/fixtures/image-no-content-type.jpg
new file mode 100644
index 00000000..0c60e952
--- /dev/null
+++ b/tests/Wallabag/CoreBundle/fixtures/image-no-content-type.jpg
Binary files differ
diff --git a/tests/Wallabag/ImportBundle/Command/ImportCommandTest.php b/tests/Wallabag/ImportBundle/Command/ImportCommandTest.php
index 7be1eb18..8bed180a 100644
--- a/tests/Wallabag/ImportBundle/Command/ImportCommandTest.php
+++ b/tests/Wallabag/ImportBundle/Command/ImportCommandTest.php
@@ -4,13 +4,13 @@ namespace Tests\Wallabag\ImportBundle\Command;
4 4
5use Symfony\Bundle\FrameworkBundle\Console\Application; 5use Symfony\Bundle\FrameworkBundle\Console\Application;
6use Symfony\Component\Console\Tester\CommandTester; 6use Symfony\Component\Console\Tester\CommandTester;
7use Wallabag\ImportBundle\Command\ImportCommand;
8use Tests\Wallabag\CoreBundle\WallabagCoreTestCase; 7use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
8use Wallabag\ImportBundle\Command\ImportCommand;
9 9
10class ImportCommandTest extends WallabagCoreTestCase 10class ImportCommandTest extends WallabagCoreTestCase
11{ 11{
12 /** 12 /**
13 * @expectedException Symfony\Component\Console\Exception\RuntimeException 13 * @expectedException \Symfony\Component\Console\Exception\RuntimeException
14 * @expectedExceptionMessage Not enough arguments 14 * @expectedExceptionMessage Not enough arguments
15 */ 15 */
16 public function testRunImportCommandWithoutArguments() 16 public function testRunImportCommandWithoutArguments()
@@ -27,7 +27,7 @@ class ImportCommandTest extends WallabagCoreTestCase
27 } 27 }
28 28
29 /** 29 /**
30 * @expectedException Symfony\Component\Config\Definition\Exception\Exception 30 * @expectedException \Symfony\Component\Config\Definition\Exception\Exception
31 * @expectedExceptionMessage not found 31 * @expectedExceptionMessage not found
32 */ 32 */
33 public function testRunImportCommandWithoutFilepath() 33 public function testRunImportCommandWithoutFilepath()
@@ -40,16 +40,15 @@ class ImportCommandTest extends WallabagCoreTestCase
40 $tester = new CommandTester($command); 40 $tester = new CommandTester($command);
41 $tester->execute([ 41 $tester->execute([
42 'command' => $command->getName(), 42 'command' => $command->getName(),
43 'userId' => 1, 43 'username' => 'admin',
44 'filepath' => 1, 44 'filepath' => 1,
45 ]); 45 ]);
46 } 46 }
47 47
48 /** 48 /**
49 * @expectedException Symfony\Component\Config\Definition\Exception\Exception 49 * @expectedException \Doctrine\ORM\NoResultException
50 * @expectedExceptionMessage User with id
51 */ 50 */
52 public function testRunImportCommandWithoutUserId() 51 public function testRunImportCommandWithWrongUsername()
53 { 52 {
54 $application = new Application($this->getClient()->getKernel()); 53 $application = new Application($this->getClient()->getKernel());
55 $application->add(new ImportCommand()); 54 $application->add(new ImportCommand());
@@ -59,7 +58,7 @@ class ImportCommandTest extends WallabagCoreTestCase
59 $tester = new CommandTester($command); 58 $tester = new CommandTester($command);
60 $tester->execute([ 59 $tester->execute([
61 'command' => $command->getName(), 60 'command' => $command->getName(),
62 'userId' => 0, 61 'username' => 'random',
63 'filepath' => './', 62 'filepath' => './',
64 ]); 63 ]);
65 } 64 }
@@ -74,12 +73,29 @@ class ImportCommandTest extends WallabagCoreTestCase
74 $tester = new CommandTester($command); 73 $tester = new CommandTester($command);
75 $tester->execute([ 74 $tester->execute([
76 'command' => $command->getName(), 75 'command' => $command->getName(),
77 'userId' => 1, 76 'username' => 'admin',
78 'filepath' => $application->getKernel()->getContainer()->getParameter('kernel.root_dir').'/../tests/Wallabag/ImportBundle/fixtures/wallabag-v2-read.json', 77 'filepath' => $application->getKernel()->getContainer()->getParameter('kernel.root_dir') . '/../tests/Wallabag/ImportBundle/fixtures/wallabag-v2-read.json',
79 '--importer' => 'v2', 78 '--importer' => 'v2',
80 ]); 79 ]);
81 80
82 $this->assertContains('imported', $tester->getDisplay()); 81 $this->assertContains('imported', $tester->getDisplay());
83 $this->assertContains('already saved', $tester->getDisplay()); 82 $this->assertContains('already saved', $tester->getDisplay());
84 } 83 }
84
85 public function testRunImportCommandWithUserId()
86 {
87 $application = new Application($this->getClient()->getKernel());
88 $application->add(new ImportCommand());
89
90 $command = $application->find('wallabag:import');
91
92 $tester = new CommandTester($command);
93 $tester->execute([
94 'command' => $command->getName(),
95 'username' => 1,
96 'filepath' => $application->getKernel()->getContainer()->getParameter('kernel.root_dir') . '/../tests/Wallabag/ImportBundle/fixtures/wallabag-v2-read.json',
97 '--useUserId' => true,
98 '--importer' => 'v2',
99 ]);
100 }
85} 101}
diff --git a/tests/Wallabag/ImportBundle/Command/RedisWorkerCommandTest.php b/tests/Wallabag/ImportBundle/Command/RedisWorkerCommandTest.php
index 74952847..af62550c 100644
--- a/tests/Wallabag/ImportBundle/Command/RedisWorkerCommandTest.php
+++ b/tests/Wallabag/ImportBundle/Command/RedisWorkerCommandTest.php
@@ -2,16 +2,16 @@
2 2
3namespace Tests\Wallabag\ImportBundle\Command; 3namespace Tests\Wallabag\ImportBundle\Command;
4 4
5use M6Web\Component\RedisMock\RedisMockFactory;
5use Symfony\Bundle\FrameworkBundle\Console\Application; 6use Symfony\Bundle\FrameworkBundle\Console\Application;
6use Symfony\Component\Console\Tester\CommandTester; 7use Symfony\Component\Console\Tester\CommandTester;
7use Wallabag\ImportBundle\Command\RedisWorkerCommand;
8use Tests\Wallabag\CoreBundle\WallabagCoreTestCase; 8use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
9use M6Web\Component\RedisMock\RedisMockFactory; 9use Wallabag\ImportBundle\Command\RedisWorkerCommand;
10 10
11class RedisWorkerCommandTest extends WallabagCoreTestCase 11class RedisWorkerCommandTest extends WallabagCoreTestCase
12{ 12{
13 /** 13 /**
14 * @expectedException Symfony\Component\Console\Exception\RuntimeException 14 * @expectedException \Symfony\Component\Console\Exception\RuntimeException
15 * @expectedExceptionMessage Not enough arguments (missing: "serviceName") 15 * @expectedExceptionMessage Not enough arguments (missing: "serviceName")
16 */ 16 */
17 public function testRunRedisWorkerCommandWithoutArguments() 17 public function testRunRedisWorkerCommandWithoutArguments()
@@ -28,7 +28,7 @@ class RedisWorkerCommandTest extends WallabagCoreTestCase
28 } 28 }
29 29
30 /** 30 /**
31 * @expectedException Symfony\Component\Config\Definition\Exception\Exception 31 * @expectedException \Symfony\Component\Config\Definition\Exception\Exception
32 * @expectedExceptionMessage No queue or consumer found for service name 32 * @expectedExceptionMessage No queue or consumer found for service name
33 */ 33 */
34 public function testRunRedisWorkerCommandWithBadService() 34 public function testRunRedisWorkerCommandWithBadService()
diff --git a/tests/Wallabag/ImportBundle/Consumer/AMQPEntryConsumerTest.php b/tests/Wallabag/ImportBundle/Consumer/AMQPEntryConsumerTest.php
index a989ec7f..52b98a0b 100644
--- a/tests/Wallabag/ImportBundle/Consumer/AMQPEntryConsumerTest.php
+++ b/tests/Wallabag/ImportBundle/Consumer/AMQPEntryConsumerTest.php
@@ -2,10 +2,10 @@
2 2
3namespace Tests\Wallabag\ImportBundle\Consumer\AMQP; 3namespace Tests\Wallabag\ImportBundle\Consumer\AMQP;
4 4
5use Wallabag\ImportBundle\Consumer\AMQPEntryConsumer;
6use PhpAmqpLib\Message\AMQPMessage; 5use PhpAmqpLib\Message\AMQPMessage;
7use Wallabag\UserBundle\Entity\User;
8use Wallabag\CoreBundle\Entity\Entry; 6use Wallabag\CoreBundle\Entity\Entry;
7use Wallabag\ImportBundle\Consumer\AMQPEntryConsumer;
8use Wallabag\UserBundle\Entity\User;
9 9
10class AMQPEntryConsumerTest extends \PHPUnit_Framework_TestCase 10class AMQPEntryConsumerTest extends \PHPUnit_Framework_TestCase
11{ 11{
diff --git a/tests/Wallabag/ImportBundle/Consumer/RedisEntryConsumerTest.php b/tests/Wallabag/ImportBundle/Consumer/RedisEntryConsumerTest.php
index 78bd83ba..9506ff63 100644
--- a/tests/Wallabag/ImportBundle/Consumer/RedisEntryConsumerTest.php
+++ b/tests/Wallabag/ImportBundle/Consumer/RedisEntryConsumerTest.php
@@ -2,9 +2,9 @@
2 2
3namespace Tests\Wallabag\ImportBundle\Consumer\AMQP; 3namespace Tests\Wallabag\ImportBundle\Consumer\AMQP;
4 4
5use Wallabag\CoreBundle\Entity\Entry;
5use Wallabag\ImportBundle\Consumer\RedisEntryConsumer; 6use Wallabag\ImportBundle\Consumer\RedisEntryConsumer;
6use Wallabag\UserBundle\Entity\User; 7use Wallabag\UserBundle\Entity\User;
7use Wallabag\CoreBundle\Entity\Entry;
8 8
9class RedisEntryConsumerTest extends \PHPUnit_Framework_TestCase 9class RedisEntryConsumerTest extends \PHPUnit_Framework_TestCase
10{ 10{
diff --git a/tests/Wallabag/ImportBundle/Controller/ChromeControllerTest.php b/tests/Wallabag/ImportBundle/Controller/ChromeControllerTest.php
index c1f82ea9..3873ccf4 100644
--- a/tests/Wallabag/ImportBundle/Controller/ChromeControllerTest.php
+++ b/tests/Wallabag/ImportBundle/Controller/ChromeControllerTest.php
@@ -2,8 +2,8 @@
2 2
3namespace Tests\Wallabag\ImportBundle\Controller; 3namespace Tests\Wallabag\ImportBundle\Controller;
4 4
5use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
6use Symfony\Component\HttpFoundation\File\UploadedFile; 5use Symfony\Component\HttpFoundation\File\UploadedFile;
6use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
7 7
8class ChromeControllerTest extends WallabagCoreTestCase 8class ChromeControllerTest extends WallabagCoreTestCase
9{ 9{
@@ -14,9 +14,9 @@ class ChromeControllerTest extends WallabagCoreTestCase
14 14
15 $crawler = $client->request('GET', '/import/chrome'); 15 $crawler = $client->request('GET', '/import/chrome');
16 16
17 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 17 $this->assertSame(200, $client->getResponse()->getStatusCode());
18 $this->assertEquals(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count()); 18 $this->assertSame(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
19 $this->assertEquals(1, $crawler->filter('input[type=file]')->count()); 19 $this->assertSame(1, $crawler->filter('input[type=file]')->count());
20 } 20 }
21 21
22 public function testImportChromeWithRabbitEnabled() 22 public function testImportChromeWithRabbitEnabled()
@@ -28,9 +28,9 @@ class ChromeControllerTest extends WallabagCoreTestCase
28 28
29 $crawler = $client->request('GET', '/import/chrome'); 29 $crawler = $client->request('GET', '/import/chrome');
30 30
31 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 31 $this->assertSame(200, $client->getResponse()->getStatusCode());
32 $this->assertEquals(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count()); 32 $this->assertSame(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
33 $this->assertEquals(1, $crawler->filter('input[type=file]')->count()); 33 $this->assertSame(1, $crawler->filter('input[type=file]')->count());
34 34
35 $client->getContainer()->get('craue_config')->set('import_with_rabbitmq', 0); 35 $client->getContainer()->get('craue_config')->set('import_with_rabbitmq', 0);
36 } 36 }
@@ -49,7 +49,7 @@ class ChromeControllerTest extends WallabagCoreTestCase
49 49
50 $client->submit($form, $data); 50 $client->submit($form, $data);
51 51
52 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 52 $this->assertSame(200, $client->getResponse()->getStatusCode());
53 } 53 }
54 54
55 public function testImportChromeWithRedisEnabled() 55 public function testImportChromeWithRedisEnabled()
@@ -61,13 +61,13 @@ class ChromeControllerTest extends WallabagCoreTestCase
61 61
62 $crawler = $client->request('GET', '/import/chrome'); 62 $crawler = $client->request('GET', '/import/chrome');
63 63
64 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 64 $this->assertSame(200, $client->getResponse()->getStatusCode());
65 $this->assertEquals(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count()); 65 $this->assertSame(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
66 $this->assertEquals(1, $crawler->filter('input[type=file]')->count()); 66 $this->assertSame(1, $crawler->filter('input[type=file]')->count());
67 67
68 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form(); 68 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
69 69
70 $file = new UploadedFile(__DIR__.'/../fixtures/chrome-bookmarks', 'Bookmarks'); 70 $file = new UploadedFile(__DIR__ . '/../fixtures/chrome-bookmarks', 'Bookmarks');
71 71
72 $data = [ 72 $data = [
73 'upload_import_file[file]' => $file, 73 'upload_import_file[file]' => $file,
@@ -75,7 +75,7 @@ class ChromeControllerTest extends WallabagCoreTestCase
75 75
76 $client->submit($form, $data); 76 $client->submit($form, $data);
77 77
78 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 78 $this->assertSame(302, $client->getResponse()->getStatusCode());
79 79
80 $crawler = $client->followRedirect(); 80 $crawler = $client->followRedirect();
81 81
@@ -95,7 +95,7 @@ class ChromeControllerTest extends WallabagCoreTestCase
95 $crawler = $client->request('GET', '/import/chrome'); 95 $crawler = $client->request('GET', '/import/chrome');
96 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form(); 96 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
97 97
98 $file = new UploadedFile(__DIR__.'/../fixtures/chrome-bookmarks', 'Bookmarks'); 98 $file = new UploadedFile(__DIR__ . '/../fixtures/chrome-bookmarks', 'Bookmarks');
99 99
100 $data = [ 100 $data = [
101 'upload_import_file[file]' => $file, 101 'upload_import_file[file]' => $file,
@@ -103,7 +103,7 @@ class ChromeControllerTest extends WallabagCoreTestCase
103 103
104 $client->submit($form, $data); 104 $client->submit($form, $data);
105 105
106 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 106 $this->assertSame(302, $client->getResponse()->getStatusCode());
107 107
108 $crawler = $client->followRedirect(); 108 $crawler = $client->followRedirect();
109 109
@@ -120,11 +120,11 @@ class ChromeControllerTest extends WallabagCoreTestCase
120 120
121 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://www.usinenouvelle.com is ok'); 121 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://www.usinenouvelle.com is ok');
122 $this->assertNotEmpty($content->getLanguage(), 'Language for http://www.usinenouvelle.com is ok'); 122 $this->assertNotEmpty($content->getLanguage(), 'Language for http://www.usinenouvelle.com is ok');
123 $this->assertEquals(0, count($content->getTags())); 123 $this->assertSame(1, count($content->getTags()));
124 124
125 $createdAt = $content->getCreatedAt(); 125 $createdAt = $content->getCreatedAt();
126 $this->assertEquals('2011', $createdAt->format('Y')); 126 $this->assertSame('2011', $createdAt->format('Y'));
127 $this->assertEquals('07', $createdAt->format('m')); 127 $this->assertSame('07', $createdAt->format('m'));
128 } 128 }
129 129
130 public function testImportWallabagWithEmptyFile() 130 public function testImportWallabagWithEmptyFile()
@@ -135,7 +135,7 @@ class ChromeControllerTest extends WallabagCoreTestCase
135 $crawler = $client->request('GET', '/import/chrome'); 135 $crawler = $client->request('GET', '/import/chrome');
136 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form(); 136 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
137 137
138 $file = new UploadedFile(__DIR__.'/../fixtures/test.txt', 'test.txt'); 138 $file = new UploadedFile(__DIR__ . '/../fixtures/test.txt', 'test.txt');
139 139
140 $data = [ 140 $data = [
141 'upload_import_file[file]' => $file, 141 'upload_import_file[file]' => $file,
@@ -143,7 +143,7 @@ class ChromeControllerTest extends WallabagCoreTestCase
143 143
144 $client->submit($form, $data); 144 $client->submit($form, $data);
145 145
146 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 146 $this->assertSame(302, $client->getResponse()->getStatusCode());
147 147
148 $crawler = $client->followRedirect(); 148 $crawler = $client->followRedirect();
149 149
diff --git a/tests/Wallabag/ImportBundle/Controller/FirefoxControllerTest.php b/tests/Wallabag/ImportBundle/Controller/FirefoxControllerTest.php
index 7557ea32..5e1260b1 100644
--- a/tests/Wallabag/ImportBundle/Controller/FirefoxControllerTest.php
+++ b/tests/Wallabag/ImportBundle/Controller/FirefoxControllerTest.php
@@ -2,8 +2,8 @@
2 2
3namespace Tests\Wallabag\ImportBundle\Controller; 3namespace Tests\Wallabag\ImportBundle\Controller;
4 4
5use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
6use Symfony\Component\HttpFoundation\File\UploadedFile; 5use Symfony\Component\HttpFoundation\File\UploadedFile;
6use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
7 7
8class FirefoxControllerTest extends WallabagCoreTestCase 8class FirefoxControllerTest extends WallabagCoreTestCase
9{ 9{
@@ -14,9 +14,9 @@ class FirefoxControllerTest extends WallabagCoreTestCase
14 14
15 $crawler = $client->request('GET', '/import/firefox'); 15 $crawler = $client->request('GET', '/import/firefox');
16 16
17 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 17 $this->assertSame(200, $client->getResponse()->getStatusCode());
18 $this->assertEquals(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count()); 18 $this->assertSame(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
19 $this->assertEquals(1, $crawler->filter('input[type=file]')->count()); 19 $this->assertSame(1, $crawler->filter('input[type=file]')->count());
20 } 20 }
21 21
22 public function testImportFirefoxWithRabbitEnabled() 22 public function testImportFirefoxWithRabbitEnabled()
@@ -28,9 +28,9 @@ class FirefoxControllerTest extends WallabagCoreTestCase
28 28
29 $crawler = $client->request('GET', '/import/firefox'); 29 $crawler = $client->request('GET', '/import/firefox');
30 30
31 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 31 $this->assertSame(200, $client->getResponse()->getStatusCode());
32 $this->assertEquals(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count()); 32 $this->assertSame(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
33 $this->assertEquals(1, $crawler->filter('input[type=file]')->count()); 33 $this->assertSame(1, $crawler->filter('input[type=file]')->count());
34 34
35 $client->getContainer()->get('craue_config')->set('import_with_rabbitmq', 0); 35 $client->getContainer()->get('craue_config')->set('import_with_rabbitmq', 0);
36 } 36 }
@@ -49,7 +49,7 @@ class FirefoxControllerTest extends WallabagCoreTestCase
49 49
50 $client->submit($form, $data); 50 $client->submit($form, $data);
51 51
52 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 52 $this->assertSame(200, $client->getResponse()->getStatusCode());
53 } 53 }
54 54
55 public function testImportFirefoxWithRedisEnabled() 55 public function testImportFirefoxWithRedisEnabled()
@@ -61,13 +61,13 @@ class FirefoxControllerTest extends WallabagCoreTestCase
61 61
62 $crawler = $client->request('GET', '/import/firefox'); 62 $crawler = $client->request('GET', '/import/firefox');
63 63
64 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 64 $this->assertSame(200, $client->getResponse()->getStatusCode());
65 $this->assertEquals(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count()); 65 $this->assertSame(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
66 $this->assertEquals(1, $crawler->filter('input[type=file]')->count()); 66 $this->assertSame(1, $crawler->filter('input[type=file]')->count());
67 67
68 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form(); 68 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
69 69
70 $file = new UploadedFile(__DIR__.'/../fixtures/firefox-bookmarks.json', 'Bookmarks'); 70 $file = new UploadedFile(__DIR__ . '/../fixtures/firefox-bookmarks.json', 'Bookmarks');
71 71
72 $data = [ 72 $data = [
73 'upload_import_file[file]' => $file, 73 'upload_import_file[file]' => $file,
@@ -75,7 +75,7 @@ class FirefoxControllerTest extends WallabagCoreTestCase
75 75
76 $client->submit($form, $data); 76 $client->submit($form, $data);
77 77
78 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 78 $this->assertSame(302, $client->getResponse()->getStatusCode());
79 79
80 $crawler = $client->followRedirect(); 80 $crawler = $client->followRedirect();
81 81
@@ -95,7 +95,7 @@ class FirefoxControllerTest extends WallabagCoreTestCase
95 $crawler = $client->request('GET', '/import/firefox'); 95 $crawler = $client->request('GET', '/import/firefox');
96 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form(); 96 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
97 97
98 $file = new UploadedFile(__DIR__.'/../fixtures/firefox-bookmarks.json', 'Bookmarks'); 98 $file = new UploadedFile(__DIR__ . '/../fixtures/firefox-bookmarks.json', 'Bookmarks');
99 99
100 $data = [ 100 $data = [
101 'upload_import_file[file]' => $file, 101 'upload_import_file[file]' => $file,
@@ -103,7 +103,7 @@ class FirefoxControllerTest extends WallabagCoreTestCase
103 103
104 $client->submit($form, $data); 104 $client->submit($form, $data);
105 105
106 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 106 $this->assertSame(302, $client->getResponse()->getStatusCode());
107 107
108 $crawler = $client->followRedirect(); 108 $crawler = $client->followRedirect();
109 109
@@ -121,23 +121,23 @@ class FirefoxControllerTest extends WallabagCoreTestCase
121 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for http://lexpansion.lexpress.fr is ok'); 121 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for http://lexpansion.lexpress.fr is ok');
122 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://lexpansion.lexpress.fr is ok'); 122 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://lexpansion.lexpress.fr is ok');
123 $this->assertNotEmpty($content->getLanguage(), 'Language for http://lexpansion.lexpress.fr is ok'); 123 $this->assertNotEmpty($content->getLanguage(), 'Language for http://lexpansion.lexpress.fr is ok');
124 $this->assertEquals(2, count($content->getTags())); 124 $this->assertSame(3, count($content->getTags()));
125 125
126 $content = $client->getContainer() 126 $content = $client->getContainer()
127 ->get('doctrine.orm.entity_manager') 127 ->get('doctrine.orm.entity_manager')
128 ->getRepository('WallabagCoreBundle:Entry') 128 ->getRepository('WallabagCoreBundle:Entry')
129 ->findByUrlAndUserId( 129 ->findByUrlAndUserId(
130 'http://stackoverflow.com/questions/15017163/parser-for-exported-bookmarks-html-file-of-google-chrome-and-mozilla-in-java', 130 'https://stackoverflow.com/questions/15017163/parser-for-exported-bookmarks-html-file-of-google-chrome-and-mozilla-in-java',
131 $this->getLoggedInUserId() 131 $this->getLoggedInUserId()
132 ); 132 );
133 133
134 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for http://stackoverflow.com is ok'); 134 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for https://stackoverflow.com is ok');
135 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://stackoverflow.com is ok'); 135 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for https://stackoverflow.com is ok');
136 $this->assertEmpty($content->getLanguage(), 'Language for http://stackoverflow.com is ok'); 136 $this->assertEmpty($content->getLanguage(), 'Language for https://stackoverflow.com is ok');
137 137
138 $createdAt = $content->getCreatedAt(); 138 $createdAt = $content->getCreatedAt();
139 $this->assertEquals('2013', $createdAt->format('Y')); 139 $this->assertSame('2013', $createdAt->format('Y'));
140 $this->assertEquals('12', $createdAt->format('m')); 140 $this->assertSame('12', $createdAt->format('m'));
141 } 141 }
142 142
143 public function testImportWallabagWithEmptyFile() 143 public function testImportWallabagWithEmptyFile()
@@ -148,7 +148,7 @@ class FirefoxControllerTest extends WallabagCoreTestCase
148 $crawler = $client->request('GET', '/import/firefox'); 148 $crawler = $client->request('GET', '/import/firefox');
149 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form(); 149 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
150 150
151 $file = new UploadedFile(__DIR__.'/../fixtures/test.txt', 'test.txt'); 151 $file = new UploadedFile(__DIR__ . '/../fixtures/test.txt', 'test.txt');
152 152
153 $data = [ 153 $data = [
154 'upload_import_file[file]' => $file, 154 'upload_import_file[file]' => $file,
@@ -156,7 +156,7 @@ class FirefoxControllerTest extends WallabagCoreTestCase
156 156
157 $client->submit($form, $data); 157 $client->submit($form, $data);
158 158
159 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 159 $this->assertSame(302, $client->getResponse()->getStatusCode());
160 160
161 $crawler = $client->followRedirect(); 161 $crawler = $client->followRedirect();
162 162
diff --git a/tests/Wallabag/ImportBundle/Controller/ImportControllerTest.php b/tests/Wallabag/ImportBundle/Controller/ImportControllerTest.php
index 5e57dcef..e1ec7c65 100644
--- a/tests/Wallabag/ImportBundle/Controller/ImportControllerTest.php
+++ b/tests/Wallabag/ImportBundle/Controller/ImportControllerTest.php
@@ -12,7 +12,7 @@ class ImportControllerTest extends WallabagCoreTestCase
12 12
13 $client->request('GET', '/import/'); 13 $client->request('GET', '/import/');
14 14
15 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 15 $this->assertSame(302, $client->getResponse()->getStatusCode());
16 $this->assertContains('login', $client->getResponse()->headers->get('location')); 16 $this->assertContains('login', $client->getResponse()->headers->get('location'));
17 } 17 }
18 18
@@ -23,7 +23,7 @@ class ImportControllerTest extends WallabagCoreTestCase
23 23
24 $crawler = $client->request('GET', '/import/'); 24 $crawler = $client->request('GET', '/import/');
25 25
26 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 26 $this->assertSame(200, $client->getResponse()->getStatusCode());
27 $this->assertEquals(8, $crawler->filter('blockquote')->count()); 27 $this->assertSame(8, $crawler->filter('blockquote')->count());
28 } 28 }
29} 29}
diff --git a/tests/Wallabag/ImportBundle/Controller/InstapaperControllerTest.php b/tests/Wallabag/ImportBundle/Controller/InstapaperControllerTest.php
index 3f6f2b9f..067cf3dc 100644
--- a/tests/Wallabag/ImportBundle/Controller/InstapaperControllerTest.php
+++ b/tests/Wallabag/ImportBundle/Controller/InstapaperControllerTest.php
@@ -2,8 +2,8 @@
2 2
3namespace Tests\Wallabag\ImportBundle\Controller; 3namespace Tests\Wallabag\ImportBundle\Controller;
4 4
5use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
6use Symfony\Component\HttpFoundation\File\UploadedFile; 5use Symfony\Component\HttpFoundation\File\UploadedFile;
6use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
7 7
8class InstapaperControllerTest extends WallabagCoreTestCase 8class InstapaperControllerTest extends WallabagCoreTestCase
9{ 9{
@@ -14,9 +14,9 @@ class InstapaperControllerTest extends WallabagCoreTestCase
14 14
15 $crawler = $client->request('GET', '/import/instapaper'); 15 $crawler = $client->request('GET', '/import/instapaper');
16 16
17 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 17 $this->assertSame(200, $client->getResponse()->getStatusCode());
18 $this->assertEquals(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count()); 18 $this->assertSame(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
19 $this->assertEquals(1, $crawler->filter('input[type=file]')->count()); 19 $this->assertSame(1, $crawler->filter('input[type=file]')->count());
20 } 20 }
21 21
22 public function testImportInstapaperWithRabbitEnabled() 22 public function testImportInstapaperWithRabbitEnabled()
@@ -28,9 +28,9 @@ class InstapaperControllerTest extends WallabagCoreTestCase
28 28
29 $crawler = $client->request('GET', '/import/instapaper'); 29 $crawler = $client->request('GET', '/import/instapaper');
30 30
31 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 31 $this->assertSame(200, $client->getResponse()->getStatusCode());
32 $this->assertEquals(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count()); 32 $this->assertSame(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
33 $this->assertEquals(1, $crawler->filter('input[type=file]')->count()); 33 $this->assertSame(1, $crawler->filter('input[type=file]')->count());
34 34
35 $client->getContainer()->get('craue_config')->set('import_with_rabbitmq', 0); 35 $client->getContainer()->get('craue_config')->set('import_with_rabbitmq', 0);
36 } 36 }
@@ -49,7 +49,7 @@ class InstapaperControllerTest extends WallabagCoreTestCase
49 49
50 $client->submit($form, $data); 50 $client->submit($form, $data);
51 51
52 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 52 $this->assertSame(200, $client->getResponse()->getStatusCode());
53 } 53 }
54 54
55 public function testImportInstapaperWithRedisEnabled() 55 public function testImportInstapaperWithRedisEnabled()
@@ -61,13 +61,13 @@ class InstapaperControllerTest extends WallabagCoreTestCase
61 61
62 $crawler = $client->request('GET', '/import/instapaper'); 62 $crawler = $client->request('GET', '/import/instapaper');
63 63
64 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 64 $this->assertSame(200, $client->getResponse()->getStatusCode());
65 $this->assertEquals(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count()); 65 $this->assertSame(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
66 $this->assertEquals(1, $crawler->filter('input[type=file]')->count()); 66 $this->assertSame(1, $crawler->filter('input[type=file]')->count());
67 67
68 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form(); 68 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
69 69
70 $file = new UploadedFile(__DIR__.'/../fixtures/instapaper-export.csv', 'instapaper.csv'); 70 $file = new UploadedFile(__DIR__ . '/../fixtures/instapaper-export.csv', 'instapaper.csv');
71 71
72 $data = [ 72 $data = [
73 'upload_import_file[file]' => $file, 73 'upload_import_file[file]' => $file,
@@ -75,7 +75,7 @@ class InstapaperControllerTest extends WallabagCoreTestCase
75 75
76 $client->submit($form, $data); 76 $client->submit($form, $data);
77 77
78 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 78 $this->assertSame(302, $client->getResponse()->getStatusCode());
79 79
80 $crawler = $client->followRedirect(); 80 $crawler = $client->followRedirect();
81 81
@@ -95,7 +95,7 @@ class InstapaperControllerTest extends WallabagCoreTestCase
95 $crawler = $client->request('GET', '/import/instapaper'); 95 $crawler = $client->request('GET', '/import/instapaper');
96 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form(); 96 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
97 97
98 $file = new UploadedFile(__DIR__.'/../fixtures/instapaper-export.csv', 'instapaper.csv'); 98 $file = new UploadedFile(__DIR__ . '/../fixtures/instapaper-export.csv', 'instapaper.csv');
99 99
100 $data = [ 100 $data = [
101 'upload_import_file[file]' => $file, 101 'upload_import_file[file]' => $file,
@@ -103,10 +103,13 @@ class InstapaperControllerTest extends WallabagCoreTestCase
103 103
104 $client->submit($form, $data); 104 $client->submit($form, $data);
105 105
106 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 106 $this->assertSame(302, $client->getResponse()->getStatusCode());
107 107
108 $crawler = $client->followRedirect(); 108 $crawler = $client->followRedirect();
109 109
110 $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
111 $this->assertContains('flashes.import.notice.summary', $body[0]);
112
110 $content = $client->getContainer() 113 $content = $client->getContainer()
111 ->get('doctrine.orm.entity_manager') 114 ->get('doctrine.orm.entity_manager')
112 ->getRepository('WallabagCoreBundle:Entry') 115 ->getRepository('WallabagCoreBundle:Entry')
@@ -115,14 +118,25 @@ class InstapaperControllerTest extends WallabagCoreTestCase
115 $this->getLoggedInUserId() 118 $this->getLoggedInUserId()
116 ); 119 );
117 120
118 $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
119 $this->assertContains('flashes.import.notice.summary', $body[0]);
120
121 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for http://www.liberation.fr is ok'); 121 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for http://www.liberation.fr is ok');
122 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://www.liberation.fr is ok'); 122 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://www.liberation.fr is ok');
123 $this->assertNotEmpty($content->getLanguage(), 'Language for http://www.liberation.fr is ok'); 123 $this->assertNotEmpty($content->getLanguage(), 'Language for http://www.liberation.fr is ok');
124 $this->assertEquals(0, count($content->getTags())); 124 $this->assertContains('foot', $content->getTags(), 'It includes the "foot" tag');
125 $this->assertSame(1, count($content->getTags()));
125 $this->assertInstanceOf(\DateTime::class, $content->getCreatedAt()); 126 $this->assertInstanceOf(\DateTime::class, $content->getCreatedAt());
127
128 $content = $client->getContainer()
129 ->get('doctrine.orm.entity_manager')
130 ->getRepository('WallabagCoreBundle:Entry')
131 ->findByUrlAndUserId(
132 'http://www.20minutes.fr/high-tech/2077615-20170531-dis-donc-donald-trump-quoi-exactement-covfefe',
133 $this->getLoggedInUserId()
134 );
135
136 $this->assertContains('foot', $content->getTags());
137 $this->assertContains('test_tag', $content->getTags());
138
139 $this->assertSame(2, count($content->getTags()));
126 } 140 }
127 141
128 public function testImportInstapaperWithFileAndMarkAllAsRead() 142 public function testImportInstapaperWithFileAndMarkAllAsRead()
@@ -133,7 +147,7 @@ class InstapaperControllerTest extends WallabagCoreTestCase
133 $crawler = $client->request('GET', '/import/instapaper'); 147 $crawler = $client->request('GET', '/import/instapaper');
134 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form(); 148 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
135 149
136 $file = new UploadedFile(__DIR__.'/../fixtures/instapaper-export.csv', 'instapaper-read.csv'); 150 $file = new UploadedFile(__DIR__ . '/../fixtures/instapaper-export.csv', 'instapaper-read.csv');
137 151
138 $data = [ 152 $data = [
139 'upload_import_file[file]' => $file, 153 'upload_import_file[file]' => $file,
@@ -142,7 +156,7 @@ class InstapaperControllerTest extends WallabagCoreTestCase
142 156
143 $client->submit($form, $data); 157 $client->submit($form, $data);
144 158
145 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 159 $this->assertSame(302, $client->getResponse()->getStatusCode());
146 160
147 $crawler = $client->followRedirect(); 161 $crawler = $client->followRedirect();
148 162
@@ -178,7 +192,7 @@ class InstapaperControllerTest extends WallabagCoreTestCase
178 $crawler = $client->request('GET', '/import/instapaper'); 192 $crawler = $client->request('GET', '/import/instapaper');
179 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form(); 193 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
180 194
181 $file = new UploadedFile(__DIR__.'/../fixtures/test.txt', 'test.txt'); 195 $file = new UploadedFile(__DIR__ . '/../fixtures/test.txt', 'test.txt');
182 196
183 $data = [ 197 $data = [
184 'upload_import_file[file]' => $file, 198 'upload_import_file[file]' => $file,
@@ -186,7 +200,7 @@ class InstapaperControllerTest extends WallabagCoreTestCase
186 200
187 $client->submit($form, $data); 201 $client->submit($form, $data);
188 202
189 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 203 $this->assertSame(302, $client->getResponse()->getStatusCode());
190 204
191 $crawler = $client->followRedirect(); 205 $crawler = $client->followRedirect();
192 206
diff --git a/tests/Wallabag/ImportBundle/Controller/PinboardControllerTest.php b/tests/Wallabag/ImportBundle/Controller/PinboardControllerTest.php
index 75a7e332..c307f96c 100644
--- a/tests/Wallabag/ImportBundle/Controller/PinboardControllerTest.php
+++ b/tests/Wallabag/ImportBundle/Controller/PinboardControllerTest.php
@@ -2,8 +2,8 @@
2 2
3namespace Tests\Wallabag\ImportBundle\Controller; 3namespace Tests\Wallabag\ImportBundle\Controller;
4 4
5use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
6use Symfony\Component\HttpFoundation\File\UploadedFile; 5use Symfony\Component\HttpFoundation\File\UploadedFile;
6use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
7 7
8class PinboardControllerTest extends WallabagCoreTestCase 8class PinboardControllerTest extends WallabagCoreTestCase
9{ 9{
@@ -14,9 +14,9 @@ class PinboardControllerTest extends WallabagCoreTestCase
14 14
15 $crawler = $client->request('GET', '/import/pinboard'); 15 $crawler = $client->request('GET', '/import/pinboard');
16 16
17 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 17 $this->assertSame(200, $client->getResponse()->getStatusCode());
18 $this->assertEquals(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count()); 18 $this->assertSame(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
19 $this->assertEquals(1, $crawler->filter('input[type=file]')->count()); 19 $this->assertSame(1, $crawler->filter('input[type=file]')->count());
20 } 20 }
21 21
22 public function testImportPinboardWithRabbitEnabled() 22 public function testImportPinboardWithRabbitEnabled()
@@ -28,9 +28,9 @@ class PinboardControllerTest extends WallabagCoreTestCase
28 28
29 $crawler = $client->request('GET', '/import/pinboard'); 29 $crawler = $client->request('GET', '/import/pinboard');
30 30
31 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 31 $this->assertSame(200, $client->getResponse()->getStatusCode());
32 $this->assertEquals(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count()); 32 $this->assertSame(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
33 $this->assertEquals(1, $crawler->filter('input[type=file]')->count()); 33 $this->assertSame(1, $crawler->filter('input[type=file]')->count());
34 34
35 $client->getContainer()->get('craue_config')->set('import_with_rabbitmq', 0); 35 $client->getContainer()->get('craue_config')->set('import_with_rabbitmq', 0);
36 } 36 }
@@ -49,7 +49,7 @@ class PinboardControllerTest extends WallabagCoreTestCase
49 49
50 $client->submit($form, $data); 50 $client->submit($form, $data);
51 51
52 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 52 $this->assertSame(200, $client->getResponse()->getStatusCode());
53 } 53 }
54 54
55 public function testImportPinboardWithRedisEnabled() 55 public function testImportPinboardWithRedisEnabled()
@@ -61,13 +61,13 @@ class PinboardControllerTest extends WallabagCoreTestCase
61 61
62 $crawler = $client->request('GET', '/import/pinboard'); 62 $crawler = $client->request('GET', '/import/pinboard');
63 63
64 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 64 $this->assertSame(200, $client->getResponse()->getStatusCode());
65 $this->assertEquals(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count()); 65 $this->assertSame(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
66 $this->assertEquals(1, $crawler->filter('input[type=file]')->count()); 66 $this->assertSame(1, $crawler->filter('input[type=file]')->count());
67 67
68 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form(); 68 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
69 69
70 $file = new UploadedFile(__DIR__.'/../fixtures/pinboard_export', 'pinboard.json'); 70 $file = new UploadedFile(__DIR__ . '/../fixtures/pinboard_export', 'pinboard.json');
71 71
72 $data = [ 72 $data = [
73 'upload_import_file[file]' => $file, 73 'upload_import_file[file]' => $file,
@@ -75,7 +75,7 @@ class PinboardControllerTest extends WallabagCoreTestCase
75 75
76 $client->submit($form, $data); 76 $client->submit($form, $data);
77 77
78 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 78 $this->assertSame(302, $client->getResponse()->getStatusCode());
79 79
80 $crawler = $client->followRedirect(); 80 $crawler = $client->followRedirect();
81 81
@@ -95,7 +95,7 @@ class PinboardControllerTest extends WallabagCoreTestCase
95 $crawler = $client->request('GET', '/import/pinboard'); 95 $crawler = $client->request('GET', '/import/pinboard');
96 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form(); 96 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
97 97
98 $file = new UploadedFile(__DIR__.'/../fixtures/pinboard_export', 'pinboard.json'); 98 $file = new UploadedFile(__DIR__ . '/../fixtures/pinboard_export', 'pinboard.json');
99 99
100 $data = [ 100 $data = [
101 'upload_import_file[file]' => $file, 101 'upload_import_file[file]' => $file,
@@ -103,7 +103,7 @@ class PinboardControllerTest extends WallabagCoreTestCase
103 103
104 $client->submit($form, $data); 104 $client->submit($form, $data);
105 105
106 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 106 $this->assertSame(302, $client->getResponse()->getStatusCode());
107 107
108 $crawler = $client->followRedirect(); 108 $crawler = $client->followRedirect();
109 109
@@ -121,9 +121,15 @@ class PinboardControllerTest extends WallabagCoreTestCase
121 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for https://ma.ttias.be is ok'); 121 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for https://ma.ttias.be is ok');
122 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for https://ma.ttias.be is ok'); 122 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for https://ma.ttias.be is ok');
123 $this->assertNotEmpty($content->getLanguage(), 'Language for https://ma.ttias.be is ok'); 123 $this->assertNotEmpty($content->getLanguage(), 'Language for https://ma.ttias.be is ok');
124 $this->assertEquals(2, count($content->getTags())); 124
125 $tags = $content->getTags();
126 $this->assertContains('foot', $tags, 'It includes the "foot" tag');
127 $this->assertContains('varnish', $tags, 'It includes the "varnish" tag');
128 $this->assertContains('PHP', $tags, 'It includes the "PHP" tag');
129 $this->assertSame(3, count($tags));
130
125 $this->assertInstanceOf(\DateTime::class, $content->getCreatedAt()); 131 $this->assertInstanceOf(\DateTime::class, $content->getCreatedAt());
126 $this->assertEquals('2016-10-26', $content->getCreatedAt()->format('Y-m-d')); 132 $this->assertSame('2016-10-26', $content->getCreatedAt()->format('Y-m-d'));
127 } 133 }
128 134
129 public function testImportPinboardWithFileAndMarkAllAsRead() 135 public function testImportPinboardWithFileAndMarkAllAsRead()
@@ -134,7 +140,7 @@ class PinboardControllerTest extends WallabagCoreTestCase
134 $crawler = $client->request('GET', '/import/pinboard'); 140 $crawler = $client->request('GET', '/import/pinboard');
135 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form(); 141 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
136 142
137 $file = new UploadedFile(__DIR__.'/../fixtures/pinboard_export', 'pinboard-read.json'); 143 $file = new UploadedFile(__DIR__ . '/../fixtures/pinboard_export', 'pinboard-read.json');
138 144
139 $data = [ 145 $data = [
140 'upload_import_file[file]' => $file, 146 'upload_import_file[file]' => $file,
@@ -143,7 +149,7 @@ class PinboardControllerTest extends WallabagCoreTestCase
143 149
144 $client->submit($form, $data); 150 $client->submit($form, $data);
145 151
146 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 152 $this->assertSame(302, $client->getResponse()->getStatusCode());
147 153
148 $crawler = $client->followRedirect(); 154 $crawler = $client->followRedirect();
149 155
@@ -179,7 +185,7 @@ class PinboardControllerTest extends WallabagCoreTestCase
179 $crawler = $client->request('GET', '/import/pinboard'); 185 $crawler = $client->request('GET', '/import/pinboard');
180 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form(); 186 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
181 187
182 $file = new UploadedFile(__DIR__.'/../fixtures/test.txt', 'test.txt'); 188 $file = new UploadedFile(__DIR__ . '/../fixtures/test.txt', 'test.txt');
183 189
184 $data = [ 190 $data = [
185 'upload_import_file[file]' => $file, 191 'upload_import_file[file]' => $file,
@@ -187,7 +193,7 @@ class PinboardControllerTest extends WallabagCoreTestCase
187 193
188 $client->submit($form, $data); 194 $client->submit($form, $data);
189 195
190 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 196 $this->assertSame(302, $client->getResponse()->getStatusCode());
191 197
192 $crawler = $client->followRedirect(); 198 $crawler = $client->followRedirect();
193 199
diff --git a/tests/Wallabag/ImportBundle/Controller/PocketControllerTest.php b/tests/Wallabag/ImportBundle/Controller/PocketControllerTest.php
index 7d6a300f..17ce1a2a 100644
--- a/tests/Wallabag/ImportBundle/Controller/PocketControllerTest.php
+++ b/tests/Wallabag/ImportBundle/Controller/PocketControllerTest.php
@@ -13,8 +13,8 @@ class PocketControllerTest extends WallabagCoreTestCase
13 13
14 $crawler = $client->request('GET', '/import/pocket'); 14 $crawler = $client->request('GET', '/import/pocket');
15 15
16 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 16 $this->assertSame(200, $client->getResponse()->getStatusCode());
17 $this->assertEquals(1, $crawler->filter('button[type=submit]')->count()); 17 $this->assertSame(1, $crawler->filter('button[type=submit]')->count());
18 } 18 }
19 19
20 public function testImportPocketWithRabbitEnabled() 20 public function testImportPocketWithRabbitEnabled()
@@ -26,8 +26,8 @@ class PocketControllerTest extends WallabagCoreTestCase
26 26
27 $crawler = $client->request('GET', '/import/pocket'); 27 $crawler = $client->request('GET', '/import/pocket');
28 28
29 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 29 $this->assertSame(200, $client->getResponse()->getStatusCode());
30 $this->assertEquals(1, $crawler->filter('button[type=submit]')->count()); 30 $this->assertSame(1, $crawler->filter('button[type=submit]')->count());
31 31
32 $client->getContainer()->get('craue_config')->set('import_with_rabbitmq', 0); 32 $client->getContainer()->get('craue_config')->set('import_with_rabbitmq', 0);
33 } 33 }
@@ -42,8 +42,8 @@ class PocketControllerTest extends WallabagCoreTestCase
42 42
43 $crawler = $client->request('GET', '/import/pocket'); 43 $crawler = $client->request('GET', '/import/pocket');
44 44
45 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 45 $this->assertSame(200, $client->getResponse()->getStatusCode());
46 $this->assertEquals(1, $crawler->filter('button[type=submit]')->count()); 46 $this->assertSame(1, $crawler->filter('button[type=submit]')->count());
47 47
48 $client->getContainer()->get('craue_config')->set('import_with_redis', 0); 48 $client->getContainer()->get('craue_config')->set('import_with_redis', 0);
49 } 49 }
@@ -55,7 +55,7 @@ class PocketControllerTest extends WallabagCoreTestCase
55 55
56 $client->request('GET', '/import/pocket/auth'); 56 $client->request('GET', '/import/pocket/auth');
57 57
58 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 58 $this->assertSame(302, $client->getResponse()->getStatusCode());
59 } 59 }
60 60
61 public function testImportPocketAuth() 61 public function testImportPocketAuth()
@@ -76,7 +76,7 @@ class PocketControllerTest extends WallabagCoreTestCase
76 76
77 $client->request('GET', '/import/pocket/auth'); 77 $client->request('GET', '/import/pocket/auth');
78 78
79 $this->assertEquals(301, $client->getResponse()->getStatusCode()); 79 $this->assertSame(301, $client->getResponse()->getStatusCode());
80 $this->assertContains('getpocket.com/auth/authorize', $client->getResponse()->headers->get('location')); 80 $this->assertContains('getpocket.com/auth/authorize', $client->getResponse()->headers->get('location'));
81 } 81 }
82 82
@@ -98,9 +98,9 @@ class PocketControllerTest extends WallabagCoreTestCase
98 98
99 $client->request('GET', '/import/pocket/callback'); 99 $client->request('GET', '/import/pocket/callback');
100 100
101 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 101 $this->assertSame(302, $client->getResponse()->getStatusCode());
102 $this->assertContains('/', $client->getResponse()->headers->get('location'), 'Import is ok, redirect to homepage'); 102 $this->assertContains('/', $client->getResponse()->headers->get('location'), 'Import is ok, redirect to homepage');
103 $this->assertEquals('flashes.import.notice.failed', $client->getContainer()->get('session')->getFlashBag()->peek('notice')[0]); 103 $this->assertSame('flashes.import.notice.failed', $client->getContainer()->get('session')->getFlashBag()->peek('notice')[0]);
104 } 104 }
105 105
106 public function testImportPocketCallback() 106 public function testImportPocketCallback()
@@ -132,8 +132,8 @@ class PocketControllerTest extends WallabagCoreTestCase
132 132
133 $client->request('GET', '/import/pocket/callback'); 133 $client->request('GET', '/import/pocket/callback');
134 134
135 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 135 $this->assertSame(302, $client->getResponse()->getStatusCode());
136 $this->assertContains('/', $client->getResponse()->headers->get('location'), 'Import is ok, redirect to homepage'); 136 $this->assertContains('/', $client->getResponse()->headers->get('location'), 'Import is ok, redirect to homepage');
137 $this->assertEquals('flashes.import.notice.summary', $client->getContainer()->get('session')->getFlashBag()->peek('notice')[0]); 137 $this->assertSame('flashes.import.notice.summary', $client->getContainer()->get('session')->getFlashBag()->peek('notice')[0]);
138 } 138 }
139} 139}
diff --git a/tests/Wallabag/ImportBundle/Controller/ReadabilityControllerTest.php b/tests/Wallabag/ImportBundle/Controller/ReadabilityControllerTest.php
index acb61ca1..e1915150 100644
--- a/tests/Wallabag/ImportBundle/Controller/ReadabilityControllerTest.php
+++ b/tests/Wallabag/ImportBundle/Controller/ReadabilityControllerTest.php
@@ -2,8 +2,8 @@
2 2
3namespace Tests\Wallabag\ImportBundle\Controller; 3namespace Tests\Wallabag\ImportBundle\Controller;
4 4
5use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
6use Symfony\Component\HttpFoundation\File\UploadedFile; 5use Symfony\Component\HttpFoundation\File\UploadedFile;
6use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
7 7
8class ReadabilityControllerTest extends WallabagCoreTestCase 8class ReadabilityControllerTest extends WallabagCoreTestCase
9{ 9{
@@ -14,9 +14,9 @@ class ReadabilityControllerTest extends WallabagCoreTestCase
14 14
15 $crawler = $client->request('GET', '/import/readability'); 15 $crawler = $client->request('GET', '/import/readability');
16 16
17 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 17 $this->assertSame(200, $client->getResponse()->getStatusCode());
18 $this->assertEquals(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count()); 18 $this->assertSame(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
19 $this->assertEquals(1, $crawler->filter('input[type=file]')->count()); 19 $this->assertSame(1, $crawler->filter('input[type=file]')->count());
20 } 20 }
21 21
22 public function testImportReadabilityWithRabbitEnabled() 22 public function testImportReadabilityWithRabbitEnabled()
@@ -28,9 +28,9 @@ class ReadabilityControllerTest extends WallabagCoreTestCase
28 28
29 $crawler = $client->request('GET', '/import/readability'); 29 $crawler = $client->request('GET', '/import/readability');
30 30
31 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 31 $this->assertSame(200, $client->getResponse()->getStatusCode());
32 $this->assertEquals(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count()); 32 $this->assertSame(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
33 $this->assertEquals(1, $crawler->filter('input[type=file]')->count()); 33 $this->assertSame(1, $crawler->filter('input[type=file]')->count());
34 34
35 $client->getContainer()->get('craue_config')->set('import_with_rabbitmq', 0); 35 $client->getContainer()->get('craue_config')->set('import_with_rabbitmq', 0);
36 } 36 }
@@ -49,7 +49,7 @@ class ReadabilityControllerTest extends WallabagCoreTestCase
49 49
50 $client->submit($form, $data); 50 $client->submit($form, $data);
51 51
52 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 52 $this->assertSame(200, $client->getResponse()->getStatusCode());
53 } 53 }
54 54
55 public function testImportReadabilityWithRedisEnabled() 55 public function testImportReadabilityWithRedisEnabled()
@@ -61,13 +61,13 @@ class ReadabilityControllerTest extends WallabagCoreTestCase
61 61
62 $crawler = $client->request('GET', '/import/readability'); 62 $crawler = $client->request('GET', '/import/readability');
63 63
64 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 64 $this->assertSame(200, $client->getResponse()->getStatusCode());
65 $this->assertEquals(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count()); 65 $this->assertSame(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
66 $this->assertEquals(1, $crawler->filter('input[type=file]')->count()); 66 $this->assertSame(1, $crawler->filter('input[type=file]')->count());
67 67
68 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form(); 68 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
69 69
70 $file = new UploadedFile(__DIR__.'/../fixtures/readability.json', 'readability.json'); 70 $file = new UploadedFile(__DIR__ . '/../fixtures/readability.json', 'readability.json');
71 71
72 $data = [ 72 $data = [
73 'upload_import_file[file]' => $file, 73 'upload_import_file[file]' => $file,
@@ -75,7 +75,7 @@ class ReadabilityControllerTest extends WallabagCoreTestCase
75 75
76 $client->submit($form, $data); 76 $client->submit($form, $data);
77 77
78 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 78 $this->assertSame(302, $client->getResponse()->getStatusCode());
79 79
80 $crawler = $client->followRedirect(); 80 $crawler = $client->followRedirect();
81 81
@@ -95,7 +95,7 @@ class ReadabilityControllerTest extends WallabagCoreTestCase
95 $crawler = $client->request('GET', '/import/readability'); 95 $crawler = $client->request('GET', '/import/readability');
96 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form(); 96 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
97 97
98 $file = new UploadedFile(__DIR__.'/../fixtures/readability.json', 'readability.json'); 98 $file = new UploadedFile(__DIR__ . '/../fixtures/readability.json', 'readability.json');
99 99
100 $data = [ 100 $data = [
101 'upload_import_file[file]' => $file, 101 'upload_import_file[file]' => $file,
@@ -103,7 +103,7 @@ class ReadabilityControllerTest extends WallabagCoreTestCase
103 103
104 $client->submit($form, $data); 104 $client->submit($form, $data);
105 105
106 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 106 $this->assertSame(302, $client->getResponse()->getStatusCode());
107 107
108 $crawler = $client->followRedirect(); 108 $crawler = $client->followRedirect();
109 109
@@ -121,9 +121,13 @@ class ReadabilityControllerTest extends WallabagCoreTestCase
121 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for http://www.zataz.com is ok'); 121 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for http://www.zataz.com is ok');
122 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://www.zataz.com is ok'); 122 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://www.zataz.com is ok');
123 $this->assertNotEmpty($content->getLanguage(), 'Language for http://www.zataz.com is ok'); 123 $this->assertNotEmpty($content->getLanguage(), 'Language for http://www.zataz.com is ok');
124 $this->assertEquals(0, count($content->getTags())); 124
125 $tags = $content->getTags();
126 $this->assertContains('foot', $tags, 'It includes the "foot" tag');
127 $this->assertSame(1, count($tags));
128
125 $this->assertInstanceOf(\DateTime::class, $content->getCreatedAt()); 129 $this->assertInstanceOf(\DateTime::class, $content->getCreatedAt());
126 $this->assertEquals('2016-09-08', $content->getCreatedAt()->format('Y-m-d')); 130 $this->assertSame('2016-09-08', $content->getCreatedAt()->format('Y-m-d'));
127 } 131 }
128 132
129 public function testImportReadabilityWithFileAndMarkAllAsRead() 133 public function testImportReadabilityWithFileAndMarkAllAsRead()
@@ -134,7 +138,7 @@ class ReadabilityControllerTest extends WallabagCoreTestCase
134 $crawler = $client->request('GET', '/import/readability'); 138 $crawler = $client->request('GET', '/import/readability');
135 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form(); 139 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
136 140
137 $file = new UploadedFile(__DIR__.'/../fixtures/readability-read.json', 'readability-read.json'); 141 $file = new UploadedFile(__DIR__ . '/../fixtures/readability-read.json', 'readability-read.json');
138 142
139 $data = [ 143 $data = [
140 'upload_import_file[file]' => $file, 144 'upload_import_file[file]' => $file,
@@ -143,7 +147,7 @@ class ReadabilityControllerTest extends WallabagCoreTestCase
143 147
144 $client->submit($form, $data); 148 $client->submit($form, $data);
145 149
146 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 150 $this->assertSame(302, $client->getResponse()->getStatusCode());
147 151
148 $crawler = $client->followRedirect(); 152 $crawler = $client->followRedirect();
149 153
@@ -179,7 +183,7 @@ class ReadabilityControllerTest extends WallabagCoreTestCase
179 $crawler = $client->request('GET', '/import/readability'); 183 $crawler = $client->request('GET', '/import/readability');
180 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form(); 184 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
181 185
182 $file = new UploadedFile(__DIR__.'/../fixtures/test.txt', 'test.txt'); 186 $file = new UploadedFile(__DIR__ . '/../fixtures/test.txt', 'test.txt');
183 187
184 $data = [ 188 $data = [
185 'upload_import_file[file]' => $file, 189 'upload_import_file[file]' => $file,
@@ -187,7 +191,7 @@ class ReadabilityControllerTest extends WallabagCoreTestCase
187 191
188 $client->submit($form, $data); 192 $client->submit($form, $data);
189 193
190 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 194 $this->assertSame(302, $client->getResponse()->getStatusCode());
191 195
192 $crawler = $client->followRedirect(); 196 $crawler = $client->followRedirect();
193 197
diff --git a/tests/Wallabag/ImportBundle/Controller/WallabagV1ControllerTest.php b/tests/Wallabag/ImportBundle/Controller/WallabagV1ControllerTest.php
index acc39997..25625c35 100644
--- a/tests/Wallabag/ImportBundle/Controller/WallabagV1ControllerTest.php
+++ b/tests/Wallabag/ImportBundle/Controller/WallabagV1ControllerTest.php
@@ -2,8 +2,8 @@
2 2
3namespace Tests\Wallabag\ImportBundle\Controller; 3namespace Tests\Wallabag\ImportBundle\Controller;
4 4
5use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
6use Symfony\Component\HttpFoundation\File\UploadedFile; 5use Symfony\Component\HttpFoundation\File\UploadedFile;
6use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
7 7
8class WallabagV1ControllerTest extends WallabagCoreTestCase 8class WallabagV1ControllerTest extends WallabagCoreTestCase
9{ 9{
@@ -14,9 +14,9 @@ class WallabagV1ControllerTest extends WallabagCoreTestCase
14 14
15 $crawler = $client->request('GET', '/import/wallabag-v1'); 15 $crawler = $client->request('GET', '/import/wallabag-v1');
16 16
17 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 17 $this->assertSame(200, $client->getResponse()->getStatusCode());
18 $this->assertEquals(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count()); 18 $this->assertSame(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
19 $this->assertEquals(1, $crawler->filter('input[type=file]')->count()); 19 $this->assertSame(1, $crawler->filter('input[type=file]')->count());
20 } 20 }
21 21
22 public function testImportWallabagWithRabbitEnabled() 22 public function testImportWallabagWithRabbitEnabled()
@@ -28,9 +28,9 @@ class WallabagV1ControllerTest extends WallabagCoreTestCase
28 28
29 $crawler = $client->request('GET', '/import/wallabag-v1'); 29 $crawler = $client->request('GET', '/import/wallabag-v1');
30 30
31 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 31 $this->assertSame(200, $client->getResponse()->getStatusCode());
32 $this->assertEquals(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count()); 32 $this->assertSame(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
33 $this->assertEquals(1, $crawler->filter('input[type=file]')->count()); 33 $this->assertSame(1, $crawler->filter('input[type=file]')->count());
34 34
35 $client->getContainer()->get('craue_config')->set('import_with_rabbitmq', 0); 35 $client->getContainer()->get('craue_config')->set('import_with_rabbitmq', 0);
36 } 36 }
@@ -49,7 +49,7 @@ class WallabagV1ControllerTest extends WallabagCoreTestCase
49 49
50 $client->submit($form, $data); 50 $client->submit($form, $data);
51 51
52 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 52 $this->assertSame(200, $client->getResponse()->getStatusCode());
53 } 53 }
54 54
55 public function testImportWallabagWithRedisEnabled() 55 public function testImportWallabagWithRedisEnabled()
@@ -62,13 +62,13 @@ class WallabagV1ControllerTest extends WallabagCoreTestCase
62 62
63 $crawler = $client->request('GET', '/import/wallabag-v1'); 63 $crawler = $client->request('GET', '/import/wallabag-v1');
64 64
65 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 65 $this->assertSame(200, $client->getResponse()->getStatusCode());
66 $this->assertEquals(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count()); 66 $this->assertSame(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
67 $this->assertEquals(1, $crawler->filter('input[type=file]')->count()); 67 $this->assertSame(1, $crawler->filter('input[type=file]')->count());
68 68
69 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form(); 69 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
70 70
71 $file = new UploadedFile(__DIR__.'/../fixtures/wallabag-v1.json', 'wallabag-v1.json'); 71 $file = new UploadedFile(__DIR__ . '/../fixtures/wallabag-v1.json', 'wallabag-v1.json');
72 72
73 $data = [ 73 $data = [
74 'upload_import_file[file]' => $file, 74 'upload_import_file[file]' => $file,
@@ -76,7 +76,7 @@ class WallabagV1ControllerTest extends WallabagCoreTestCase
76 76
77 $client->submit($form, $data); 77 $client->submit($form, $data);
78 78
79 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 79 $this->assertSame(302, $client->getResponse()->getStatusCode());
80 80
81 $crawler = $client->followRedirect(); 81 $crawler = $client->followRedirect();
82 82
@@ -96,7 +96,7 @@ class WallabagV1ControllerTest extends WallabagCoreTestCase
96 $crawler = $client->request('GET', '/import/wallabag-v1'); 96 $crawler = $client->request('GET', '/import/wallabag-v1');
97 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form(); 97 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
98 98
99 $file = new UploadedFile(__DIR__.'/../fixtures/wallabag-v1.json', 'wallabag-v1.json'); 99 $file = new UploadedFile(__DIR__ . '/../fixtures/wallabag-v1.json', 'wallabag-v1.json');
100 100
101 $data = [ 101 $data = [
102 'upload_import_file[file]' => $file, 102 'upload_import_file[file]' => $file,
@@ -104,7 +104,7 @@ class WallabagV1ControllerTest extends WallabagCoreTestCase
104 104
105 $client->submit($form, $data); 105 $client->submit($form, $data);
106 106
107 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 107 $this->assertSame(302, $client->getResponse()->getStatusCode());
108 108
109 $crawler = $client->followRedirect(); 109 $crawler = $client->followRedirect();
110 110
@@ -112,24 +112,22 @@ class WallabagV1ControllerTest extends WallabagCoreTestCase
112 ->get('doctrine.orm.entity_manager') 112 ->get('doctrine.orm.entity_manager')
113 ->getRepository('WallabagCoreBundle:Entry') 113 ->getRepository('WallabagCoreBundle:Entry')
114 ->findByUrlAndUserId( 114 ->findByUrlAndUserId(
115 'https://framablog.org/2014/02/05/framabag-service-libre-gratuit-interview-developpeur/', 115 'http://www.framablog.org/index.php/post/2014/02/05/Framabag-service-libre-gratuit-interview-developpeur',
116 $this->getLoggedInUserId() 116 $this->getLoggedInUserId()
117 ); 117 );
118 118
119 $tag = $client->getContainer()
120 ->get('doctrine.orm.entity_manager')
121 ->getRepository('WallabagCoreBundle:Tag')
122 ->findOneByLabel('Framabag');
123
124 $this->assertTrue($content->getTags()->contains($tag));
125
126 $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text'])); 119 $this->assertGreaterThan(1, $body = $crawler->filter('body')->extract(['_text']));
127 $this->assertContains('flashes.import.notice.summary', $body[0]); 120 $this->assertContains('flashes.import.notice.summary', $body[0]);
128 121
129 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for http://www.framablog.org is ok'); 122 $this->assertEmpty($content->getMimetype(), 'Mimetype for http://www.framablog.org is empty');
130 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://www.framablog.org is ok'); 123 $this->assertEmpty($content->getPreviewPicture(), 'Preview picture for http://www.framablog.org is empty');
131 $this->assertNotEmpty($content->getLanguage(), 'Language for http://www.framablog.org is ok'); 124 $this->assertEmpty($content->getLanguage(), 'Language for http://www.framablog.org is empty');
132 $this->assertEquals(1, count($content->getTags())); 125
126 $tags = $content->getTags();
127 $this->assertContains('foot', $tags, 'It includes the "foot" tag');
128 $this->assertContains('Framabag', $tags, 'It includes the "Framabag" tag');
129 $this->assertSame(2, count($tags));
130
133 $this->assertInstanceOf(\DateTime::class, $content->getCreatedAt()); 131 $this->assertInstanceOf(\DateTime::class, $content->getCreatedAt());
134 } 132 }
135 133
@@ -141,7 +139,7 @@ class WallabagV1ControllerTest extends WallabagCoreTestCase
141 $crawler = $client->request('GET', '/import/wallabag-v1'); 139 $crawler = $client->request('GET', '/import/wallabag-v1');
142 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form(); 140 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
143 141
144 $file = new UploadedFile(__DIR__.'/../fixtures/wallabag-v1-read.json', 'wallabag-v1-read.json'); 142 $file = new UploadedFile(__DIR__ . '/../fixtures/wallabag-v1-read.json', 'wallabag-v1-read.json');
145 143
146 $data = [ 144 $data = [
147 'upload_import_file[file]' => $file, 145 'upload_import_file[file]' => $file,
@@ -150,7 +148,7 @@ class WallabagV1ControllerTest extends WallabagCoreTestCase
150 148
151 $client->submit($form, $data); 149 $client->submit($form, $data);
152 150
153 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 151 $this->assertSame(302, $client->getResponse()->getStatusCode());
154 152
155 $crawler = $client->followRedirect(); 153 $crawler = $client->followRedirect();
156 154
@@ -186,7 +184,7 @@ class WallabagV1ControllerTest extends WallabagCoreTestCase
186 $crawler = $client->request('GET', '/import/wallabag-v1'); 184 $crawler = $client->request('GET', '/import/wallabag-v1');
187 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form(); 185 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
188 186
189 $file = new UploadedFile(__DIR__.'/../fixtures/test.txt', 'test.txt'); 187 $file = new UploadedFile(__DIR__ . '/../fixtures/test.txt', 'test.txt');
190 188
191 $data = [ 189 $data = [
192 'upload_import_file[file]' => $file, 190 'upload_import_file[file]' => $file,
@@ -194,7 +192,7 @@ class WallabagV1ControllerTest extends WallabagCoreTestCase
194 192
195 $client->submit($form, $data); 193 $client->submit($form, $data);
196 194
197 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 195 $this->assertSame(302, $client->getResponse()->getStatusCode());
198 196
199 $crawler = $client->followRedirect(); 197 $crawler = $client->followRedirect();
200 198
diff --git a/tests/Wallabag/ImportBundle/Controller/WallabagV2ControllerTest.php b/tests/Wallabag/ImportBundle/Controller/WallabagV2ControllerTest.php
index 26e2f40b..a94adcaf 100644
--- a/tests/Wallabag/ImportBundle/Controller/WallabagV2ControllerTest.php
+++ b/tests/Wallabag/ImportBundle/Controller/WallabagV2ControllerTest.php
@@ -2,8 +2,8 @@
2 2
3namespace Tests\Wallabag\ImportBundle\Controller; 3namespace Tests\Wallabag\ImportBundle\Controller;
4 4
5use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
6use Symfony\Component\HttpFoundation\File\UploadedFile; 5use Symfony\Component\HttpFoundation\File\UploadedFile;
6use Tests\Wallabag\CoreBundle\WallabagCoreTestCase;
7 7
8class WallabagV2ControllerTest extends WallabagCoreTestCase 8class WallabagV2ControllerTest extends WallabagCoreTestCase
9{ 9{
@@ -14,9 +14,9 @@ class WallabagV2ControllerTest extends WallabagCoreTestCase
14 14
15 $crawler = $client->request('GET', '/import/wallabag-v2'); 15 $crawler = $client->request('GET', '/import/wallabag-v2');
16 16
17 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 17 $this->assertSame(200, $client->getResponse()->getStatusCode());
18 $this->assertEquals(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count()); 18 $this->assertSame(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
19 $this->assertEquals(1, $crawler->filter('input[type=file]')->count()); 19 $this->assertSame(1, $crawler->filter('input[type=file]')->count());
20 } 20 }
21 21
22 public function testImportWallabagWithRabbitEnabled() 22 public function testImportWallabagWithRabbitEnabled()
@@ -28,9 +28,9 @@ class WallabagV2ControllerTest extends WallabagCoreTestCase
28 28
29 $crawler = $client->request('GET', '/import/wallabag-v2'); 29 $crawler = $client->request('GET', '/import/wallabag-v2');
30 30
31 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 31 $this->assertSame(200, $client->getResponse()->getStatusCode());
32 $this->assertEquals(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count()); 32 $this->assertSame(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
33 $this->assertEquals(1, $crawler->filter('input[type=file]')->count()); 33 $this->assertSame(1, $crawler->filter('input[type=file]')->count());
34 34
35 $client->getContainer()->get('craue_config')->set('import_with_rabbitmq', 0); 35 $client->getContainer()->get('craue_config')->set('import_with_rabbitmq', 0);
36 } 36 }
@@ -49,7 +49,7 @@ class WallabagV2ControllerTest extends WallabagCoreTestCase
49 49
50 $client->submit($form, $data); 50 $client->submit($form, $data);
51 51
52 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 52 $this->assertSame(200, $client->getResponse()->getStatusCode());
53 } 53 }
54 54
55 public function testImportWallabagWithRedisEnabled() 55 public function testImportWallabagWithRedisEnabled()
@@ -62,13 +62,13 @@ class WallabagV2ControllerTest extends WallabagCoreTestCase
62 62
63 $crawler = $client->request('GET', '/import/wallabag-v2'); 63 $crawler = $client->request('GET', '/import/wallabag-v2');
64 64
65 $this->assertEquals(200, $client->getResponse()->getStatusCode()); 65 $this->assertSame(200, $client->getResponse()->getStatusCode());
66 $this->assertEquals(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count()); 66 $this->assertSame(1, $crawler->filter('form[name=upload_import_file] > button[type=submit]')->count());
67 $this->assertEquals(1, $crawler->filter('input[type=file]')->count()); 67 $this->assertSame(1, $crawler->filter('input[type=file]')->count());
68 68
69 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form(); 69 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
70 70
71 $file = new UploadedFile(__DIR__.'/../fixtures/wallabag-v2.json', 'wallabag-v2.json'); 71 $file = new UploadedFile(__DIR__ . '/../fixtures/wallabag-v2.json', 'wallabag-v2.json');
72 72
73 $data = [ 73 $data = [
74 'upload_import_file[file]' => $file, 74 'upload_import_file[file]' => $file,
@@ -76,7 +76,7 @@ class WallabagV2ControllerTest extends WallabagCoreTestCase
76 76
77 $client->submit($form, $data); 77 $client->submit($form, $data);
78 78
79 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 79 $this->assertSame(302, $client->getResponse()->getStatusCode());
80 80
81 $crawler = $client->followRedirect(); 81 $crawler = $client->followRedirect();
82 82
@@ -96,7 +96,7 @@ class WallabagV2ControllerTest extends WallabagCoreTestCase
96 $crawler = $client->request('GET', '/import/wallabag-v2'); 96 $crawler = $client->request('GET', '/import/wallabag-v2');
97 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form(); 97 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
98 98
99 $file = new UploadedFile(__DIR__.'/../fixtures/wallabag-v2.json', 'wallabag-v2.json'); 99 $file = new UploadedFile(__DIR__ . '/../fixtures/wallabag-v2.json', 'wallabag-v2.json');
100 100
101 $data = [ 101 $data = [
102 'upload_import_file[file]' => $file, 102 'upload_import_file[file]' => $file,
@@ -104,7 +104,7 @@ class WallabagV2ControllerTest extends WallabagCoreTestCase
104 104
105 $client->submit($form, $data); 105 $client->submit($form, $data);
106 106
107 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 107 $this->assertSame(302, $client->getResponse()->getStatusCode());
108 108
109 $crawler = $client->followRedirect(); 109 $crawler = $client->followRedirect();
110 110
@@ -119,10 +119,14 @@ class WallabagV2ControllerTest extends WallabagCoreTestCase
119 $this->getLoggedInUserId() 119 $this->getLoggedInUserId()
120 ); 120 );
121 121
122 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for http://www.liberation.fr is ok'); 122 // empty because it wasn't re-imported
123 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for http://www.liberation.fr is ok'); 123 $this->assertEmpty($content->getMimetype(), 'Mimetype for http://www.liberation.fr is empty');
124 $this->assertNotEmpty($content->getLanguage(), 'Language for http://www.liberation.fr is ok'); 124 $this->assertEmpty($content->getPreviewPicture(), 'Preview picture for http://www.liberation.fr is empty');
125 $this->assertEquals(0, count($content->getTags())); 125 $this->assertEmpty($content->getLanguage(), 'Language for http://www.liberation.fr is empty');
126
127 $tags = $content->getTags();
128 $this->assertContains('foot', $tags, 'It includes the "foot" tag');
129 $this->assertSame(1, count($tags));
126 130
127 $content = $client->getContainer() 131 $content = $client->getContainer()
128 ->get('doctrine.orm.entity_manager') 132 ->get('doctrine.orm.entity_manager')
@@ -135,9 +139,16 @@ class WallabagV2ControllerTest extends WallabagCoreTestCase
135 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for https://www.mediapart.fr is ok'); 139 $this->assertNotEmpty($content->getMimetype(), 'Mimetype for https://www.mediapart.fr is ok');
136 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for https://www.mediapart.fr is ok'); 140 $this->assertNotEmpty($content->getPreviewPicture(), 'Preview picture for https://www.mediapart.fr is ok');
137 $this->assertNotEmpty($content->getLanguage(), 'Language for https://www.mediapart.fr is ok'); 141 $this->assertNotEmpty($content->getLanguage(), 'Language for https://www.mediapart.fr is ok');
138 $this->assertEquals(2, count($content->getTags())); 142
143 $tags = $content->getTags();
144 $this->assertContains('foot', $tags, 'It includes the "foot" tag');
145 $this->assertContains('mediapart', $tags, 'It includes the "mediapart" tag');
146 $this->assertContains('blog', $tags, 'It includes the "blog" tag');
147 $this->assertSame(3, count($tags));
148
139 $this->assertInstanceOf(\DateTime::class, $content->getCreatedAt()); 149 $this->assertInstanceOf(\DateTime::class, $content->getCreatedAt());
140 $this->assertEquals('2016-09-08', $content->getCreatedAt()->format('Y-m-d')); 150 $this->assertSame('2016-09-08', $content->getCreatedAt()->format('Y-m-d'));
151 $this->assertTrue($content->isStarred(), 'Entry is starred');
141 } 152 }
142 153
143 public function testImportWallabagWithEmptyFile() 154 public function testImportWallabagWithEmptyFile()
@@ -148,7 +159,7 @@ class WallabagV2ControllerTest extends WallabagCoreTestCase
148 $crawler = $client->request('GET', '/import/wallabag-v2'); 159 $crawler = $client->request('GET', '/import/wallabag-v2');
149 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form(); 160 $form = $crawler->filter('form[name=upload_import_file] > button[type=submit]')->form();
150 161
151 $file = new UploadedFile(__DIR__.'/../fixtures/test.txt', 'test.txt'); 162 $file = new UploadedFile(__DIR__ . '/../fixtures/test.txt', 'test.txt');
152 163
153 $data = [ 164 $data = [
154 'upload_import_file[file]' => $file, 165 'upload_import_file[file]' => $file,
@@ -156,7 +167,7 @@ class WallabagV2ControllerTest extends WallabagCoreTestCase
156 167
157 $client->submit($form, $data); 168 $client->submit($form, $data);
158 169
159 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 170 $this->assertSame(302, $client->getResponse()->getStatusCode());
160 171
161 $crawler = $client->followRedirect(); 172 $crawler = $client->followRedirect();
162 173
diff --git a/tests/Wallabag/ImportBundle/Import/ChromeImportTest.php b/tests/Wallabag/ImportBundle/Import/ChromeImportTest.php
index 6b3adda4..5559ac7e 100644
--- a/tests/Wallabag/ImportBundle/Import/ChromeImportTest.php
+++ b/tests/Wallabag/ImportBundle/Import/ChromeImportTest.php
@@ -2,14 +2,14 @@
2 2
3namespace Tests\Wallabag\ImportBundle\Import; 3namespace Tests\Wallabag\ImportBundle\Import;
4 4
5use Wallabag\ImportBundle\Import\ChromeImport; 5use M6Web\Component\RedisMock\RedisMockFactory;
6use Wallabag\UserBundle\Entity\User;
7use Wallabag\CoreBundle\Entity\Entry;
8use Wallabag\ImportBundle\Redis\Producer;
9use Monolog\Logger;
10use Monolog\Handler\TestHandler; 6use Monolog\Handler\TestHandler;
7use Monolog\Logger;
11use Simpleue\Queue\RedisQueue; 8use Simpleue\Queue\RedisQueue;
12use M6Web\Component\RedisMock\RedisMockFactory; 9use Wallabag\CoreBundle\Entity\Entry;
10use Wallabag\ImportBundle\Import\ChromeImport;
11use Wallabag\ImportBundle\Redis\Producer;
12use Wallabag\UserBundle\Entity\User;
13 13
14class ChromeImportTest extends \PHPUnit_Framework_TestCase 14class ChromeImportTest extends \PHPUnit_Framework_TestCase
15{ 15{
@@ -17,53 +17,21 @@ class ChromeImportTest extends \PHPUnit_Framework_TestCase
17 protected $em; 17 protected $em;
18 protected $logHandler; 18 protected $logHandler;
19 protected $contentProxy; 19 protected $contentProxy;
20 20 protected $tagsAssigner;
21 private function getChromeImport($unsetUser = false, $dispatched = 0)
22 {
23 $this->user = new User();
24
25 $this->em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
26 ->disableOriginalConstructor()
27 ->getMock();
28
29 $this->contentProxy = $this->getMockBuilder('Wallabag\CoreBundle\Helper\ContentProxy')
30 ->disableOriginalConstructor()
31 ->getMock();
32
33 $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcher')
34 ->disableOriginalConstructor()
35 ->getMock();
36
37 $dispatcher
38 ->expects($this->exactly($dispatched))
39 ->method('dispatch');
40
41 $wallabag = new ChromeImport($this->em, $this->contentProxy, $dispatcher);
42
43 $this->logHandler = new TestHandler();
44 $logger = new Logger('test', [$this->logHandler]);
45 $wallabag->setLogger($logger);
46
47 if (false === $unsetUser) {
48 $wallabag->setUser($this->user);
49 }
50
51 return $wallabag;
52 }
53 21
54 public function testInit() 22 public function testInit()
55 { 23 {
56 $chromeImport = $this->getChromeImport(); 24 $chromeImport = $this->getChromeImport();
57 25
58 $this->assertEquals('Chrome', $chromeImport->getName()); 26 $this->assertSame('Chrome', $chromeImport->getName());
59 $this->assertNotEmpty($chromeImport->getUrl()); 27 $this->assertNotEmpty($chromeImport->getUrl());
60 $this->assertEquals('import.chrome.description', $chromeImport->getDescription()); 28 $this->assertSame('import.chrome.description', $chromeImport->getDescription());
61 } 29 }
62 30
63 public function testImport() 31 public function testImport()
64 { 32 {
65 $chromeImport = $this->getChromeImport(false, 1); 33 $chromeImport = $this->getChromeImport(false, 1);
66 $chromeImport->setFilepath(__DIR__.'/../fixtures/chrome-bookmarks'); 34 $chromeImport->setFilepath(__DIR__ . '/../fixtures/chrome-bookmarks');
67 35
68 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository') 36 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
69 ->disableOriginalConstructor() 37 ->disableOriginalConstructor()
@@ -90,13 +58,13 @@ class ChromeImportTest extends \PHPUnit_Framework_TestCase
90 $res = $chromeImport->import(); 58 $res = $chromeImport->import();
91 59
92 $this->assertTrue($res); 60 $this->assertTrue($res);
93 $this->assertEquals(['skipped' => 0, 'imported' => 1, 'queued' => 0], $chromeImport->getSummary()); 61 $this->assertSame(['skipped' => 0, 'imported' => 1, 'queued' => 0], $chromeImport->getSummary());
94 } 62 }
95 63
96 public function testImportAndMarkAllAsRead() 64 public function testImportAndMarkAllAsRead()
97 { 65 {
98 $chromeImport = $this->getChromeImport(false, 1); 66 $chromeImport = $this->getChromeImport(false, 1);
99 $chromeImport->setFilepath(__DIR__.'/../fixtures/chrome-bookmarks'); 67 $chromeImport->setFilepath(__DIR__ . '/../fixtures/chrome-bookmarks');
100 68
101 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository') 69 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
102 ->disableOriginalConstructor() 70 ->disableOriginalConstructor()
@@ -128,13 +96,13 @@ class ChromeImportTest extends \PHPUnit_Framework_TestCase
128 96
129 $this->assertTrue($res); 97 $this->assertTrue($res);
130 98
131 $this->assertEquals(['skipped' => 0, 'imported' => 1, 'queued' => 0], $chromeImport->getSummary()); 99 $this->assertSame(['skipped' => 0, 'imported' => 1, 'queued' => 0], $chromeImport->getSummary());
132 } 100 }
133 101
134 public function testImportWithRabbit() 102 public function testImportWithRabbit()
135 { 103 {
136 $chromeImport = $this->getChromeImport(); 104 $chromeImport = $this->getChromeImport();
137 $chromeImport->setFilepath(__DIR__.'/../fixtures/chrome-bookmarks'); 105 $chromeImport->setFilepath(__DIR__ . '/../fixtures/chrome-bookmarks');
138 106
139 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository') 107 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
140 ->disableOriginalConstructor() 108 ->disableOriginalConstructor()
@@ -168,13 +136,13 @@ class ChromeImportTest extends \PHPUnit_Framework_TestCase
168 $res = $chromeImport->setMarkAsRead(true)->import(); 136 $res = $chromeImport->setMarkAsRead(true)->import();
169 137
170 $this->assertTrue($res); 138 $this->assertTrue($res);
171 $this->assertEquals(['skipped' => 0, 'imported' => 0, 'queued' => 1], $chromeImport->getSummary()); 139 $this->assertSame(['skipped' => 0, 'imported' => 0, 'queued' => 1], $chromeImport->getSummary());
172 } 140 }
173 141
174 public function testImportWithRedis() 142 public function testImportWithRedis()
175 { 143 {
176 $chromeImport = $this->getChromeImport(); 144 $chromeImport = $this->getChromeImport();
177 $chromeImport->setFilepath(__DIR__.'/../fixtures/chrome-bookmarks'); 145 $chromeImport->setFilepath(__DIR__ . '/../fixtures/chrome-bookmarks');
178 146
179 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository') 147 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
180 ->disableOriginalConstructor() 148 ->disableOriginalConstructor()
@@ -206,7 +174,7 @@ class ChromeImportTest extends \PHPUnit_Framework_TestCase
206 $res = $chromeImport->setMarkAsRead(true)->import(); 174 $res = $chromeImport->setMarkAsRead(true)->import();
207 175
208 $this->assertTrue($res); 176 $this->assertTrue($res);
209 $this->assertEquals(['skipped' => 0, 'imported' => 0, 'queued' => 1], $chromeImport->getSummary()); 177 $this->assertSame(['skipped' => 0, 'imported' => 0, 'queued' => 1], $chromeImport->getSummary());
210 178
211 $this->assertNotEmpty($redisMock->lpop('chrome')); 179 $this->assertNotEmpty($redisMock->lpop('chrome'));
212 } 180 }
@@ -214,7 +182,7 @@ class ChromeImportTest extends \PHPUnit_Framework_TestCase
214 public function testImportBadFile() 182 public function testImportBadFile()
215 { 183 {
216 $chromeImport = $this->getChromeImport(); 184 $chromeImport = $this->getChromeImport();
217 $chromeImport->setFilepath(__DIR__.'/../fixtures/wallabag-v1.jsonx'); 185 $chromeImport->setFilepath(__DIR__ . '/../fixtures/wallabag-v1.jsonx');
218 186
219 $res = $chromeImport->import(); 187 $res = $chromeImport->import();
220 188
@@ -222,13 +190,13 @@ class ChromeImportTest extends \PHPUnit_Framework_TestCase
222 190
223 $records = $this->logHandler->getRecords(); 191 $records = $this->logHandler->getRecords();
224 $this->assertContains('Wallabag Browser Import: unable to read file', $records[0]['message']); 192 $this->assertContains('Wallabag Browser Import: unable to read file', $records[0]['message']);
225 $this->assertEquals('ERROR', $records[0]['level_name']); 193 $this->assertSame('ERROR', $records[0]['level_name']);
226 } 194 }
227 195
228 public function testImportUserNotDefined() 196 public function testImportUserNotDefined()
229 { 197 {
230 $chromeImport = $this->getChromeImport(true); 198 $chromeImport = $this->getChromeImport(true);
231 $chromeImport->setFilepath(__DIR__.'/../fixtures/chrome-bookmarks'); 199 $chromeImport->setFilepath(__DIR__ . '/../fixtures/chrome-bookmarks');
232 200
233 $res = $chromeImport->import(); 201 $res = $chromeImport->import();
234 202
@@ -236,6 +204,43 @@ class ChromeImportTest extends \PHPUnit_Framework_TestCase
236 204
237 $records = $this->logHandler->getRecords(); 205 $records = $this->logHandler->getRecords();
238 $this->assertContains('Wallabag Browser Import: user is not defined', $records[0]['message']); 206 $this->assertContains('Wallabag Browser Import: user is not defined', $records[0]['message']);
239 $this->assertEquals('ERROR', $records[0]['level_name']); 207 $this->assertSame('ERROR', $records[0]['level_name']);
208 }
209
210 private function getChromeImport($unsetUser = false, $dispatched = 0)
211 {
212 $this->user = new User();
213
214 $this->em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
215 ->disableOriginalConstructor()
216 ->getMock();
217
218 $this->contentProxy = $this->getMockBuilder('Wallabag\CoreBundle\Helper\ContentProxy')
219 ->disableOriginalConstructor()
220 ->getMock();
221
222 $this->tagsAssigner = $this->getMockBuilder('Wallabag\CoreBundle\Helper\TagsAssigner')
223 ->disableOriginalConstructor()
224 ->getMock();
225
226 $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcher')
227 ->disableOriginalConstructor()
228 ->getMock();
229
230 $dispatcher
231 ->expects($this->exactly($dispatched))
232 ->method('dispatch');
233
234 $wallabag = new ChromeImport($this->em, $this->contentProxy, $this->tagsAssigner, $dispatcher);
235
236 $this->logHandler = new TestHandler();
237 $logger = new Logger('test', [$this->logHandler]);
238 $wallabag->setLogger($logger);
239
240 if (false === $unsetUser) {
241 $wallabag->setUser($this->user);
242 }
243
244 return $wallabag;
240 } 245 }
241} 246}
diff --git a/tests/Wallabag/ImportBundle/Import/FirefoxImportTest.php b/tests/Wallabag/ImportBundle/Import/FirefoxImportTest.php
index b516fbc5..a1783bfc 100644
--- a/tests/Wallabag/ImportBundle/Import/FirefoxImportTest.php
+++ b/tests/Wallabag/ImportBundle/Import/FirefoxImportTest.php
@@ -2,14 +2,14 @@
2 2
3namespace Tests\Wallabag\ImportBundle\Import; 3namespace Tests\Wallabag\ImportBundle\Import;
4 4
5use Wallabag\ImportBundle\Import\FirefoxImport; 5use M6Web\Component\RedisMock\RedisMockFactory;
6use Wallabag\UserBundle\Entity\User;
7use Wallabag\CoreBundle\Entity\Entry;
8use Wallabag\ImportBundle\Redis\Producer;
9use Monolog\Logger;
10use Monolog\Handler\TestHandler; 6use Monolog\Handler\TestHandler;
7use Monolog\Logger;
11use Simpleue\Queue\RedisQueue; 8use Simpleue\Queue\RedisQueue;
12use M6Web\Component\RedisMock\RedisMockFactory; 9use Wallabag\CoreBundle\Entity\Entry;
10use Wallabag\ImportBundle\Import\FirefoxImport;
11use Wallabag\ImportBundle\Redis\Producer;
12use Wallabag\UserBundle\Entity\User;
13 13
14class FirefoxImportTest extends \PHPUnit_Framework_TestCase 14class FirefoxImportTest extends \PHPUnit_Framework_TestCase
15{ 15{
@@ -17,53 +17,21 @@ class FirefoxImportTest extends \PHPUnit_Framework_TestCase
17 protected $em; 17 protected $em;
18 protected $logHandler; 18 protected $logHandler;
19 protected $contentProxy; 19 protected $contentProxy;
20 20 protected $tagsAssigner;
21 private function getFirefoxImport($unsetUser = false, $dispatched = 0)
22 {
23 $this->user = new User();
24
25 $this->em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
26 ->disableOriginalConstructor()
27 ->getMock();
28
29 $this->contentProxy = $this->getMockBuilder('Wallabag\CoreBundle\Helper\ContentProxy')
30 ->disableOriginalConstructor()
31 ->getMock();
32
33 $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcher')
34 ->disableOriginalConstructor()
35 ->getMock();
36
37 $dispatcher
38 ->expects($this->exactly($dispatched))
39 ->method('dispatch');
40
41 $wallabag = new FirefoxImport($this->em, $this->contentProxy, $dispatcher);
42
43 $this->logHandler = new TestHandler();
44 $logger = new Logger('test', [$this->logHandler]);
45 $wallabag->setLogger($logger);
46
47 if (false === $unsetUser) {
48 $wallabag->setUser($this->user);
49 }
50
51 return $wallabag;
52 }
53 21
54 public function testInit() 22 public function testInit()
55 { 23 {
56 $firefoxImport = $this->getFirefoxImport(); 24 $firefoxImport = $this->getFirefoxImport();
57 25
58 $this->assertEquals('Firefox', $firefoxImport->getName()); 26 $this->assertSame('Firefox', $firefoxImport->getName());
59 $this->assertNotEmpty($firefoxImport->getUrl()); 27 $this->assertNotEmpty($firefoxImport->getUrl());
60 $this->assertEquals('import.firefox.description', $firefoxImport->getDescription()); 28 $this->assertSame('import.firefox.description', $firefoxImport->getDescription());
61 } 29 }
62 30
63 public function testImport() 31 public function testImport()
64 { 32 {
65 $firefoxImport = $this->getFirefoxImport(false, 2); 33 $firefoxImport = $this->getFirefoxImport(false, 2);
66 $firefoxImport->setFilepath(__DIR__.'/../fixtures/firefox-bookmarks.json'); 34 $firefoxImport->setFilepath(__DIR__ . '/../fixtures/firefox-bookmarks.json');
67 35
68 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository') 36 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
69 ->disableOriginalConstructor() 37 ->disableOriginalConstructor()
@@ -90,13 +58,13 @@ class FirefoxImportTest extends \PHPUnit_Framework_TestCase
90 $res = $firefoxImport->import(); 58 $res = $firefoxImport->import();
91 59
92 $this->assertTrue($res); 60 $this->assertTrue($res);
93 $this->assertEquals(['skipped' => 0, 'imported' => 2, 'queued' => 0], $firefoxImport->getSummary()); 61 $this->assertSame(['skipped' => 0, 'imported' => 2, 'queued' => 0], $firefoxImport->getSummary());
94 } 62 }
95 63
96 public function testImportAndMarkAllAsRead() 64 public function testImportAndMarkAllAsRead()
97 { 65 {
98 $firefoxImport = $this->getFirefoxImport(false, 1); 66 $firefoxImport = $this->getFirefoxImport(false, 1);
99 $firefoxImport->setFilepath(__DIR__.'/../fixtures/firefox-bookmarks.json'); 67 $firefoxImport->setFilepath(__DIR__ . '/../fixtures/firefox-bookmarks.json');
100 68
101 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository') 69 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
102 ->disableOriginalConstructor() 70 ->disableOriginalConstructor()
@@ -128,13 +96,13 @@ class FirefoxImportTest extends \PHPUnit_Framework_TestCase
128 96
129 $this->assertTrue($res); 97 $this->assertTrue($res);
130 98
131 $this->assertEquals(['skipped' => 1, 'imported' => 1, 'queued' => 0], $firefoxImport->getSummary()); 99 $this->assertSame(['skipped' => 1, 'imported' => 1, 'queued' => 0], $firefoxImport->getSummary());
132 } 100 }
133 101
134 public function testImportWithRabbit() 102 public function testImportWithRabbit()
135 { 103 {
136 $firefoxImport = $this->getFirefoxImport(); 104 $firefoxImport = $this->getFirefoxImport();
137 $firefoxImport->setFilepath(__DIR__.'/../fixtures/firefox-bookmarks.json'); 105 $firefoxImport->setFilepath(__DIR__ . '/../fixtures/firefox-bookmarks.json');
138 106
139 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository') 107 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
140 ->disableOriginalConstructor() 108 ->disableOriginalConstructor()
@@ -168,13 +136,13 @@ class FirefoxImportTest extends \PHPUnit_Framework_TestCase
168 $res = $firefoxImport->setMarkAsRead(true)->import(); 136 $res = $firefoxImport->setMarkAsRead(true)->import();
169 137
170 $this->assertTrue($res); 138 $this->assertTrue($res);
171 $this->assertEquals(['skipped' => 0, 'imported' => 0, 'queued' => 1], $firefoxImport->getSummary()); 139 $this->assertSame(['skipped' => 0, 'imported' => 0, 'queued' => 1], $firefoxImport->getSummary());
172 } 140 }
173 141
174 public function testImportWithRedis() 142 public function testImportWithRedis()
175 { 143 {
176 $firefoxImport = $this->getFirefoxImport(); 144 $firefoxImport = $this->getFirefoxImport();
177 $firefoxImport->setFilepath(__DIR__.'/../fixtures/firefox-bookmarks.json'); 145 $firefoxImport->setFilepath(__DIR__ . '/../fixtures/firefox-bookmarks.json');
178 146
179 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository') 147 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
180 ->disableOriginalConstructor() 148 ->disableOriginalConstructor()
@@ -206,7 +174,7 @@ class FirefoxImportTest extends \PHPUnit_Framework_TestCase
206 $res = $firefoxImport->setMarkAsRead(true)->import(); 174 $res = $firefoxImport->setMarkAsRead(true)->import();
207 175
208 $this->assertTrue($res); 176 $this->assertTrue($res);
209 $this->assertEquals(['skipped' => 0, 'imported' => 0, 'queued' => 1], $firefoxImport->getSummary()); 177 $this->assertSame(['skipped' => 0, 'imported' => 0, 'queued' => 1], $firefoxImport->getSummary());
210 178
211 $this->assertNotEmpty($redisMock->lpop('firefox')); 179 $this->assertNotEmpty($redisMock->lpop('firefox'));
212 } 180 }
@@ -214,7 +182,7 @@ class FirefoxImportTest extends \PHPUnit_Framework_TestCase
214 public function testImportBadFile() 182 public function testImportBadFile()
215 { 183 {
216 $firefoxImport = $this->getFirefoxImport(); 184 $firefoxImport = $this->getFirefoxImport();
217 $firefoxImport->setFilepath(__DIR__.'/../fixtures/wallabag-v1.jsonx'); 185 $firefoxImport->setFilepath(__DIR__ . '/../fixtures/wallabag-v1.jsonx');
218 186
219 $res = $firefoxImport->import(); 187 $res = $firefoxImport->import();
220 188
@@ -222,13 +190,13 @@ class FirefoxImportTest extends \PHPUnit_Framework_TestCase
222 190
223 $records = $this->logHandler->getRecords(); 191 $records = $this->logHandler->getRecords();
224 $this->assertContains('Wallabag Browser Import: unable to read file', $records[0]['message']); 192 $this->assertContains('Wallabag Browser Import: unable to read file', $records[0]['message']);
225 $this->assertEquals('ERROR', $records[0]['level_name']); 193 $this->assertSame('ERROR', $records[0]['level_name']);
226 } 194 }
227 195
228 public function testImportUserNotDefined() 196 public function testImportUserNotDefined()
229 { 197 {
230 $firefoxImport = $this->getFirefoxImport(true); 198 $firefoxImport = $this->getFirefoxImport(true);
231 $firefoxImport->setFilepath(__DIR__.'/../fixtures/firefox-bookmarks.json'); 199 $firefoxImport->setFilepath(__DIR__ . '/../fixtures/firefox-bookmarks.json');
232 200
233 $res = $firefoxImport->import(); 201 $res = $firefoxImport->import();
234 202
@@ -236,6 +204,43 @@ class FirefoxImportTest extends \PHPUnit_Framework_TestCase
236 204
237 $records = $this->logHandler->getRecords(); 205 $records = $this->logHandler->getRecords();
238 $this->assertContains('Wallabag Browser Import: user is not defined', $records[0]['message']); 206 $this->assertContains('Wallabag Browser Import: user is not defined', $records[0]['message']);
239 $this->assertEquals('ERROR', $records[0]['level_name']); 207 $this->assertSame('ERROR', $records[0]['level_name']);
208 }
209
210 private function getFirefoxImport($unsetUser = false, $dispatched = 0)
211 {
212 $this->user = new User();
213
214 $this->em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
215 ->disableOriginalConstructor()
216 ->getMock();
217
218 $this->contentProxy = $this->getMockBuilder('Wallabag\CoreBundle\Helper\ContentProxy')
219 ->disableOriginalConstructor()
220 ->getMock();
221
222 $this->tagsAssigner = $this->getMockBuilder('Wallabag\CoreBundle\Helper\TagsAssigner')
223 ->disableOriginalConstructor()
224 ->getMock();
225
226 $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcher')
227 ->disableOriginalConstructor()
228 ->getMock();
229
230 $dispatcher
231 ->expects($this->exactly($dispatched))
232 ->method('dispatch');
233
234 $wallabag = new FirefoxImport($this->em, $this->contentProxy, $this->tagsAssigner, $dispatcher);
235
236 $this->logHandler = new TestHandler();
237 $logger = new Logger('test', [$this->logHandler]);
238 $wallabag->setLogger($logger);
239
240 if (false === $unsetUser) {
241 $wallabag->setUser($this->user);
242 }
243
244 return $wallabag;
240 } 245 }
241} 246}
diff --git a/tests/Wallabag/ImportBundle/Import/ImportChainTest.php b/tests/Wallabag/ImportBundle/Import/ImportChainTest.php
index 32568ce5..a9a9915e 100644
--- a/tests/Wallabag/ImportBundle/Import/ImportChainTest.php
+++ b/tests/Wallabag/ImportBundle/Import/ImportChainTest.php
@@ -16,6 +16,6 @@ class ImportChainTest extends \PHPUnit_Framework_TestCase
16 $importChain->addImport($import, 'alias'); 16 $importChain->addImport($import, 'alias');
17 17
18 $this->assertCount(1, $importChain->getAll()); 18 $this->assertCount(1, $importChain->getAll());
19 $this->assertEquals($import, $importChain->getAll()['alias']); 19 $this->assertSame($import, $importChain->getAll()['alias']);
20 } 20 }
21} 21}
diff --git a/tests/Wallabag/ImportBundle/Import/ImportCompilerPassTest.php b/tests/Wallabag/ImportBundle/Import/ImportCompilerPassTest.php
index 71a007a9..207054f4 100644
--- a/tests/Wallabag/ImportBundle/Import/ImportCompilerPassTest.php
+++ b/tests/Wallabag/ImportBundle/Import/ImportCompilerPassTest.php
@@ -36,7 +36,7 @@ class ImportCompilerPassTest extends \PHPUnit_Framework_TestCase
36 $this->assertTrue($definition->hasMethodCall('addImport')); 36 $this->assertTrue($definition->hasMethodCall('addImport'));
37 37
38 $calls = $definition->getMethodCalls(); 38 $calls = $definition->getMethodCalls();
39 $this->assertEquals('pocket', $calls[0][1][1]); 39 $this->assertSame('pocket', $calls[0][1][1]);
40 } 40 }
41 41
42 protected function process(ContainerBuilder $container) 42 protected function process(ContainerBuilder $container)
diff --git a/tests/Wallabag/ImportBundle/Import/InstapaperImportTest.php b/tests/Wallabag/ImportBundle/Import/InstapaperImportTest.php
index e262a808..274dc326 100644
--- a/tests/Wallabag/ImportBundle/Import/InstapaperImportTest.php
+++ b/tests/Wallabag/ImportBundle/Import/InstapaperImportTest.php
@@ -2,14 +2,14 @@
2 2
3namespace Tests\Wallabag\ImportBundle\Import; 3namespace Tests\Wallabag\ImportBundle\Import;
4 4
5use Wallabag\ImportBundle\Import\InstapaperImport; 5use M6Web\Component\RedisMock\RedisMockFactory;
6use Wallabag\UserBundle\Entity\User;
7use Wallabag\CoreBundle\Entity\Entry;
8use Wallabag\ImportBundle\Redis\Producer;
9use Monolog\Logger;
10use Monolog\Handler\TestHandler; 6use Monolog\Handler\TestHandler;
7use Monolog\Logger;
11use Simpleue\Queue\RedisQueue; 8use Simpleue\Queue\RedisQueue;
12use M6Web\Component\RedisMock\RedisMockFactory; 9use Wallabag\CoreBundle\Entity\Entry;
10use Wallabag\ImportBundle\Import\InstapaperImport;
11use Wallabag\ImportBundle\Redis\Producer;
12use Wallabag\UserBundle\Entity\User;
13 13
14class InstapaperImportTest extends \PHPUnit_Framework_TestCase 14class InstapaperImportTest extends \PHPUnit_Framework_TestCase
15{ 15{
@@ -17,59 +17,28 @@ class InstapaperImportTest extends \PHPUnit_Framework_TestCase
17 protected $em; 17 protected $em;
18 protected $logHandler; 18 protected $logHandler;
19 protected $contentProxy; 19 protected $contentProxy;
20 20 protected $tagsAssigner;
21 private function getInstapaperImport($unsetUser = false, $dispatched = 0) 21 protected $uow;
22 {
23 $this->user = new User();
24
25 $this->em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
26 ->disableOriginalConstructor()
27 ->getMock();
28
29 $this->contentProxy = $this->getMockBuilder('Wallabag\CoreBundle\Helper\ContentProxy')
30 ->disableOriginalConstructor()
31 ->getMock();
32
33 $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcher')
34 ->disableOriginalConstructor()
35 ->getMock();
36
37 $dispatcher
38 ->expects($this->exactly($dispatched))
39 ->method('dispatch');
40
41 $import = new InstapaperImport($this->em, $this->contentProxy, $dispatcher);
42
43 $this->logHandler = new TestHandler();
44 $logger = new Logger('test', [$this->logHandler]);
45 $import->setLogger($logger);
46
47 if (false === $unsetUser) {
48 $import->setUser($this->user);
49 }
50
51 return $import;
52 }
53 22
54 public function testInit() 23 public function testInit()
55 { 24 {
56 $instapaperImport = $this->getInstapaperImport(); 25 $instapaperImport = $this->getInstapaperImport();
57 26
58 $this->assertEquals('Instapaper', $instapaperImport->getName()); 27 $this->assertSame('Instapaper', $instapaperImport->getName());
59 $this->assertNotEmpty($instapaperImport->getUrl()); 28 $this->assertNotEmpty($instapaperImport->getUrl());
60 $this->assertEquals('import.instapaper.description', $instapaperImport->getDescription()); 29 $this->assertSame('import.instapaper.description', $instapaperImport->getDescription());
61 } 30 }
62 31
63 public function testImport() 32 public function testImport()
64 { 33 {
65 $instapaperImport = $this->getInstapaperImport(false, 3); 34 $instapaperImport = $this->getInstapaperImport(false, 4);
66 $instapaperImport->setFilepath(__DIR__.'/../fixtures/instapaper-export.csv'); 35 $instapaperImport->setFilepath(__DIR__ . '/../fixtures/instapaper-export.csv');
67 36
68 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository') 37 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
69 ->disableOriginalConstructor() 38 ->disableOriginalConstructor()
70 ->getMock(); 39 ->getMock();
71 40
72 $entryRepo->expects($this->exactly(3)) 41 $entryRepo->expects($this->exactly(4))
73 ->method('findByUrlAndUserId') 42 ->method('findByUrlAndUserId')
74 ->willReturn(false); 43 ->willReturn(false);
75 44
@@ -83,28 +52,28 @@ class InstapaperImportTest extends \PHPUnit_Framework_TestCase
83 ->getMock(); 52 ->getMock();
84 53
85 $this->contentProxy 54 $this->contentProxy
86 ->expects($this->exactly(3)) 55 ->expects($this->exactly(4))
87 ->method('updateEntry') 56 ->method('updateEntry')
88 ->willReturn($entry); 57 ->willReturn($entry);
89 58
90 $res = $instapaperImport->import(); 59 $res = $instapaperImport->import();
91 60
92 $this->assertTrue($res); 61 $this->assertTrue($res);
93 $this->assertEquals(['skipped' => 0, 'imported' => 3, 'queued' => 0], $instapaperImport->getSummary()); 62 $this->assertSame(['skipped' => 0, 'imported' => 4, 'queued' => 0], $instapaperImport->getSummary());
94 } 63 }
95 64
96 public function testImportAndMarkAllAsRead() 65 public function testImportAndMarkAllAsRead()
97 { 66 {
98 $instapaperImport = $this->getInstapaperImport(false, 1); 67 $instapaperImport = $this->getInstapaperImport(false, 1);
99 $instapaperImport->setFilepath(__DIR__.'/../fixtures/instapaper-export.csv'); 68 $instapaperImport->setFilepath(__DIR__ . '/../fixtures/instapaper-export.csv');
100 69
101 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository') 70 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
102 ->disableOriginalConstructor() 71 ->disableOriginalConstructor()
103 ->getMock(); 72 ->getMock();
104 73
105 $entryRepo->expects($this->exactly(3)) 74 $entryRepo->expects($this->exactly(4))
106 ->method('findByUrlAndUserId') 75 ->method('findByUrlAndUserId')
107 ->will($this->onConsecutiveCalls(false, true, true)); 76 ->will($this->onConsecutiveCalls(false, true, true, true));
108 77
109 $this->em 78 $this->em
110 ->expects($this->any()) 79 ->expects($this->any())
@@ -128,13 +97,13 @@ class InstapaperImportTest extends \PHPUnit_Framework_TestCase
128 97
129 $this->assertTrue($res); 98 $this->assertTrue($res);
130 99
131 $this->assertEquals(['skipped' => 2, 'imported' => 1, 'queued' => 0], $instapaperImport->getSummary()); 100 $this->assertSame(['skipped' => 3, 'imported' => 1, 'queued' => 0], $instapaperImport->getSummary());
132 } 101 }
133 102
134 public function testImportWithRabbit() 103 public function testImportWithRabbit()
135 { 104 {
136 $instapaperImport = $this->getInstapaperImport(); 105 $instapaperImport = $this->getInstapaperImport();
137 $instapaperImport->setFilepath(__DIR__.'/../fixtures/instapaper-export.csv'); 106 $instapaperImport->setFilepath(__DIR__ . '/../fixtures/instapaper-export.csv');
138 107
139 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository') 108 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
140 ->disableOriginalConstructor() 109 ->disableOriginalConstructor()
@@ -160,7 +129,7 @@ class InstapaperImportTest extends \PHPUnit_Framework_TestCase
160 ->getMock(); 129 ->getMock();
161 130
162 $producer 131 $producer
163 ->expects($this->exactly(3)) 132 ->expects($this->exactly(4))
164 ->method('publish'); 133 ->method('publish');
165 134
166 $instapaperImport->setProducer($producer); 135 $instapaperImport->setProducer($producer);
@@ -168,13 +137,13 @@ class InstapaperImportTest extends \PHPUnit_Framework_TestCase
168 $res = $instapaperImport->setMarkAsRead(true)->import(); 137 $res = $instapaperImport->setMarkAsRead(true)->import();
169 138
170 $this->assertTrue($res); 139 $this->assertTrue($res);
171 $this->assertEquals(['skipped' => 0, 'imported' => 0, 'queued' => 3], $instapaperImport->getSummary()); 140 $this->assertSame(['skipped' => 0, 'imported' => 0, 'queued' => 4], $instapaperImport->getSummary());
172 } 141 }
173 142
174 public function testImportWithRedis() 143 public function testImportWithRedis()
175 { 144 {
176 $instapaperImport = $this->getInstapaperImport(); 145 $instapaperImport = $this->getInstapaperImport();
177 $instapaperImport->setFilepath(__DIR__.'/../fixtures/instapaper-export.csv'); 146 $instapaperImport->setFilepath(__DIR__ . '/../fixtures/instapaper-export.csv');
178 147
179 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository') 148 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
180 ->disableOriginalConstructor() 149 ->disableOriginalConstructor()
@@ -206,7 +175,7 @@ class InstapaperImportTest extends \PHPUnit_Framework_TestCase
206 $res = $instapaperImport->setMarkAsRead(true)->import(); 175 $res = $instapaperImport->setMarkAsRead(true)->import();
207 176
208 $this->assertTrue($res); 177 $this->assertTrue($res);
209 $this->assertEquals(['skipped' => 0, 'imported' => 0, 'queued' => 3], $instapaperImport->getSummary()); 178 $this->assertSame(['skipped' => 0, 'imported' => 0, 'queued' => 4], $instapaperImport->getSummary());
210 179
211 $this->assertNotEmpty($redisMock->lpop('instapaper')); 180 $this->assertNotEmpty($redisMock->lpop('instapaper'));
212 } 181 }
@@ -214,7 +183,7 @@ class InstapaperImportTest extends \PHPUnit_Framework_TestCase
214 public function testImportBadFile() 183 public function testImportBadFile()
215 { 184 {
216 $instapaperImport = $this->getInstapaperImport(); 185 $instapaperImport = $this->getInstapaperImport();
217 $instapaperImport->setFilepath(__DIR__.'/../fixtures/wallabag-v1.jsonx'); 186 $instapaperImport->setFilepath(__DIR__ . '/../fixtures/wallabag-v1.jsonx');
218 187
219 $res = $instapaperImport->import(); 188 $res = $instapaperImport->import();
220 189
@@ -222,13 +191,13 @@ class InstapaperImportTest extends \PHPUnit_Framework_TestCase
222 191
223 $records = $this->logHandler->getRecords(); 192 $records = $this->logHandler->getRecords();
224 $this->assertContains('InstapaperImport: unable to read file', $records[0]['message']); 193 $this->assertContains('InstapaperImport: unable to read file', $records[0]['message']);
225 $this->assertEquals('ERROR', $records[0]['level_name']); 194 $this->assertSame('ERROR', $records[0]['level_name']);
226 } 195 }
227 196
228 public function testImportUserNotDefined() 197 public function testImportUserNotDefined()
229 { 198 {
230 $instapaperImport = $this->getInstapaperImport(true); 199 $instapaperImport = $this->getInstapaperImport(true);
231 $instapaperImport->setFilepath(__DIR__.'/../fixtures/instapaper-export.csv'); 200 $instapaperImport->setFilepath(__DIR__ . '/../fixtures/instapaper-export.csv');
232 201
233 $res = $instapaperImport->import(); 202 $res = $instapaperImport->import();
234 203
@@ -236,6 +205,57 @@ class InstapaperImportTest extends \PHPUnit_Framework_TestCase
236 205
237 $records = $this->logHandler->getRecords(); 206 $records = $this->logHandler->getRecords();
238 $this->assertContains('InstapaperImport: user is not defined', $records[0]['message']); 207 $this->assertContains('InstapaperImport: user is not defined', $records[0]['message']);
239 $this->assertEquals('ERROR', $records[0]['level_name']); 208 $this->assertSame('ERROR', $records[0]['level_name']);
209 }
210
211 private function getInstapaperImport($unsetUser = false, $dispatched = 0)
212 {
213 $this->user = new User();
214
215 $this->em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
216 ->disableOriginalConstructor()
217 ->getMock();
218
219 $this->uow = $this->getMockBuilder('Doctrine\ORM\UnitOfWork')
220 ->disableOriginalConstructor()
221 ->getMock();
222
223 $this->em
224 ->expects($this->any())
225 ->method('getUnitOfWork')
226 ->willReturn($this->uow);
227
228 $this->uow
229 ->expects($this->any())
230 ->method('getScheduledEntityInsertions')
231 ->willReturn([]);
232
233 $this->contentProxy = $this->getMockBuilder('Wallabag\CoreBundle\Helper\ContentProxy')
234 ->disableOriginalConstructor()
235 ->getMock();
236
237 $this->tagsAssigner = $this->getMockBuilder('Wallabag\CoreBundle\Helper\TagsAssigner')
238 ->disableOriginalConstructor()
239 ->getMock();
240
241 $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcher')
242 ->disableOriginalConstructor()
243 ->getMock();
244
245 $dispatcher
246 ->expects($this->exactly($dispatched))
247 ->method('dispatch');
248
249 $import = new InstapaperImport($this->em, $this->contentProxy, $this->tagsAssigner, $dispatcher);
250
251 $this->logHandler = new TestHandler();
252 $logger = new Logger('test', [$this->logHandler]);
253 $import->setLogger($logger);
254
255 if (false === $unsetUser) {
256 $import->setUser($this->user);
257 }
258
259 return $import;
240 } 260 }
241} 261}
diff --git a/tests/Wallabag/ImportBundle/Import/PocketImportTest.php b/tests/Wallabag/ImportBundle/Import/PocketImportTest.php
index 141ece36..fe59f867 100644
--- a/tests/Wallabag/ImportBundle/Import/PocketImportTest.php
+++ b/tests/Wallabag/ImportBundle/Import/PocketImportTest.php
@@ -2,19 +2,19 @@
2 2
3namespace Tests\Wallabag\ImportBundle\Import; 3namespace Tests\Wallabag\ImportBundle\Import;
4 4
5use Wallabag\UserBundle\Entity\User;
6use Wallabag\CoreBundle\Entity\Entry;
7use Wallabag\CoreBundle\Entity\Config;
8use Wallabag\ImportBundle\Import\PocketImport;
9use GuzzleHttp\Client; 5use GuzzleHttp\Client;
10use GuzzleHttp\Subscriber\Mock;
11use GuzzleHttp\Message\Response; 6use GuzzleHttp\Message\Response;
12use GuzzleHttp\Stream\Stream; 7use GuzzleHttp\Stream\Stream;
13use Wallabag\ImportBundle\Redis\Producer; 8use GuzzleHttp\Subscriber\Mock;
14use Monolog\Logger; 9use M6Web\Component\RedisMock\RedisMockFactory;
15use Monolog\Handler\TestHandler; 10use Monolog\Handler\TestHandler;
11use Monolog\Logger;
16use Simpleue\Queue\RedisQueue; 12use Simpleue\Queue\RedisQueue;
17use M6Web\Component\RedisMock\RedisMockFactory; 13use Wallabag\CoreBundle\Entity\Config;
14use Wallabag\CoreBundle\Entity\Entry;
15use Wallabag\ImportBundle\Import\PocketImport;
16use Wallabag\ImportBundle\Redis\Producer;
17use Wallabag\UserBundle\Entity\User;
18 18
19class PocketImportTest extends \PHPUnit_Framework_TestCase 19class PocketImportTest extends \PHPUnit_Framework_TestCase
20{ 20{
@@ -23,63 +23,16 @@ class PocketImportTest extends \PHPUnit_Framework_TestCase
23 protected $em; 23 protected $em;
24 protected $contentProxy; 24 protected $contentProxy;
25 protected $logHandler; 25 protected $logHandler;
26 26 protected $tagsAssigner;
27 private function getPocketImport($consumerKey = 'ConsumerKey', $dispatched = 0) 27 protected $uow;
28 {
29 $this->user = new User();
30
31 $config = new Config($this->user);
32 $config->setPocketConsumerKey('xxx');
33
34 $this->user->setConfig($config);
35
36 $this->contentProxy = $this->getMockBuilder('Wallabag\CoreBundle\Helper\ContentProxy')
37 ->disableOriginalConstructor()
38 ->getMock();
39
40 $this->em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
41 ->disableOriginalConstructor()
42 ->getMock();
43
44 $this->uow = $this->getMockBuilder('Doctrine\ORM\UnitOfWork')
45 ->disableOriginalConstructor()
46 ->getMock();
47
48 $this->em
49 ->expects($this->any())
50 ->method('getUnitOfWork')
51 ->willReturn($this->uow);
52
53 $this->uow
54 ->expects($this->any())
55 ->method('getScheduledEntityInsertions')
56 ->willReturn([]);
57
58 $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcher')
59 ->disableOriginalConstructor()
60 ->getMock();
61
62 $dispatcher
63 ->expects($this->exactly($dispatched))
64 ->method('dispatch');
65
66 $pocket = new PocketImport($this->em, $this->contentProxy, $dispatcher);
67 $pocket->setUser($this->user);
68
69 $this->logHandler = new TestHandler();
70 $logger = new Logger('test', [$this->logHandler]);
71 $pocket->setLogger($logger);
72
73 return $pocket;
74 }
75 28
76 public function testInit() 29 public function testInit()
77 { 30 {
78 $pocketImport = $this->getPocketImport(); 31 $pocketImport = $this->getPocketImport();
79 32
80 $this->assertEquals('Pocket', $pocketImport->getName()); 33 $this->assertSame('Pocket', $pocketImport->getName());
81 $this->assertNotEmpty($pocketImport->getUrl()); 34 $this->assertNotEmpty($pocketImport->getUrl());
82 $this->assertEquals('import.pocket.description', $pocketImport->getDescription()); 35 $this->assertSame('import.pocket.description', $pocketImport->getDescription());
83 } 36 }
84 37
85 public function testOAuthRequest() 38 public function testOAuthRequest()
@@ -97,7 +50,7 @@ class PocketImportTest extends \PHPUnit_Framework_TestCase
97 50
98 $code = $pocketImport->getRequestToken('http://0.0.0.0/redirect'); 51 $code = $pocketImport->getRequestToken('http://0.0.0.0/redirect');
99 52
100 $this->assertEquals('wunderbar_code', $code); 53 $this->assertSame('wunderbar_code', $code);
101 } 54 }
102 55
103 public function testOAuthRequestBadResponse() 56 public function testOAuthRequestBadResponse()
@@ -119,7 +72,7 @@ class PocketImportTest extends \PHPUnit_Framework_TestCase
119 72
120 $records = $this->logHandler->getRecords(); 73 $records = $this->logHandler->getRecords();
121 $this->assertContains('PocketImport: Failed to request token', $records[0]['message']); 74 $this->assertContains('PocketImport: Failed to request token', $records[0]['message']);
122 $this->assertEquals('ERROR', $records[0]['level_name']); 75 $this->assertSame('ERROR', $records[0]['level_name']);
123 } 76 }
124 77
125 public function testOAuthAuthorize() 78 public function testOAuthAuthorize()
@@ -138,7 +91,7 @@ class PocketImportTest extends \PHPUnit_Framework_TestCase
138 $res = $pocketImport->authorize('wunderbar_code'); 91 $res = $pocketImport->authorize('wunderbar_code');
139 92
140 $this->assertTrue($res); 93 $this->assertTrue($res);
141 $this->assertEquals('wunderbar_token', $pocketImport->getAccessToken()); 94 $this->assertSame('wunderbar_token', $pocketImport->getAccessToken());
142 } 95 }
143 96
144 public function testOAuthAuthorizeBadResponse() 97 public function testOAuthAuthorizeBadResponse()
@@ -160,7 +113,7 @@ class PocketImportTest extends \PHPUnit_Framework_TestCase
160 113
161 $records = $this->logHandler->getRecords(); 114 $records = $this->logHandler->getRecords();
162 $this->assertContains('PocketImport: Failed to authorize client', $records[0]['message']); 115 $this->assertContains('PocketImport: Failed to authorize client', $records[0]['message']);
163 $this->assertEquals('ERROR', $records[0]['level_name']); 116 $this->assertSame('ERROR', $records[0]['level_name']);
164 } 117 }
165 118
166 /** 119 /**
@@ -285,7 +238,7 @@ class PocketImportTest extends \PHPUnit_Framework_TestCase
285 $res = $pocketImport->import(); 238 $res = $pocketImport->import();
286 239
287 $this->assertTrue($res); 240 $this->assertTrue($res);
288 $this->assertEquals(['skipped' => 1, 'imported' => 1, 'queued' => 0], $pocketImport->getSummary()); 241 $this->assertSame(['skipped' => 1, 'imported' => 1, 'queued' => 0], $pocketImport->getSummary());
289 } 242 }
290 243
291 /** 244 /**
@@ -380,7 +333,7 @@ class PocketImportTest extends \PHPUnit_Framework_TestCase
380 $res = $pocketImport->setMarkAsRead(true)->import(); 333 $res = $pocketImport->setMarkAsRead(true)->import();
381 334
382 $this->assertTrue($res); 335 $this->assertTrue($res);
383 $this->assertEquals(['skipped' => 0, 'imported' => 2, 'queued' => 0], $pocketImport->getSummary()); 336 $this->assertSame(['skipped' => 0, 'imported' => 2, 'queued' => 0], $pocketImport->getSummary());
384 } 337 }
385 338
386 /** 339 /**
@@ -419,7 +372,7 @@ JSON;
419 { 372 {
420 "status": 1, 373 "status": 1,
421 "list": { 374 "list": {
422 "229279690": '.$body.' 375 "229279690": ' . $body . '
423 } 376 }
424 } 377 }
425 ')), 378 ')),
@@ -466,7 +419,7 @@ JSON;
466 $res = $pocketImport->setMarkAsRead(true)->import(); 419 $res = $pocketImport->setMarkAsRead(true)->import();
467 420
468 $this->assertTrue($res); 421 $this->assertTrue($res);
469 $this->assertEquals(['skipped' => 0, 'imported' => 0, 'queued' => 1], $pocketImport->getSummary()); 422 $this->assertSame(['skipped' => 0, 'imported' => 0, 'queued' => 1], $pocketImport->getSummary());
470 } 423 }
471 424
472 /** 425 /**
@@ -505,7 +458,7 @@ JSON;
505 { 458 {
506 "status": 1, 459 "status": 1,
507 "list": { 460 "list": {
508 "229279690": '.$body.' 461 "229279690": ' . $body . '
509 } 462 }
510 } 463 }
511 ')), 464 ')),
@@ -545,7 +498,7 @@ JSON;
545 $res = $pocketImport->setMarkAsRead(true)->import(); 498 $res = $pocketImport->setMarkAsRead(true)->import();
546 499
547 $this->assertTrue($res); 500 $this->assertTrue($res);
548 $this->assertEquals(['skipped' => 0, 'imported' => 0, 'queued' => 1], $pocketImport->getSummary()); 501 $this->assertSame(['skipped' => 0, 'imported' => 0, 'queued' => 1], $pocketImport->getSummary());
549 502
550 $this->assertNotEmpty($redisMock->lpop('pocket')); 503 $this->assertNotEmpty($redisMock->lpop('pocket'));
551 } 504 }
@@ -571,7 +524,7 @@ JSON;
571 524
572 $records = $this->logHandler->getRecords(); 525 $records = $this->logHandler->getRecords();
573 $this->assertContains('PocketImport: Failed to import', $records[0]['message']); 526 $this->assertContains('PocketImport: Failed to import', $records[0]['message']);
574 $this->assertEquals('ERROR', $records[0]['level_name']); 527 $this->assertSame('ERROR', $records[0]['level_name']);
575 } 528 }
576 529
577 public function testImportWithExceptionFromGraby() 530 public function testImportWithExceptionFromGraby()
@@ -624,6 +577,59 @@ JSON;
624 $res = $pocketImport->import(); 577 $res = $pocketImport->import();
625 578
626 $this->assertTrue($res); 579 $this->assertTrue($res);
627 $this->assertEquals(['skipped' => 0, 'imported' => 1, 'queued' => 0], $pocketImport->getSummary()); 580 $this->assertSame(['skipped' => 0, 'imported' => 1, 'queued' => 0], $pocketImport->getSummary());
581 }
582
583 private function getPocketImport($consumerKey = 'ConsumerKey', $dispatched = 0)
584 {
585 $this->user = new User();
586
587 $config = new Config($this->user);
588 $config->setPocketConsumerKey('xxx');
589
590 $this->user->setConfig($config);
591
592 $this->contentProxy = $this->getMockBuilder('Wallabag\CoreBundle\Helper\ContentProxy')
593 ->disableOriginalConstructor()
594 ->getMock();
595
596 $this->tagsAssigner = $this->getMockBuilder('Wallabag\CoreBundle\Helper\TagsAssigner')
597 ->disableOriginalConstructor()
598 ->getMock();
599
600 $this->em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
601 ->disableOriginalConstructor()
602 ->getMock();
603
604 $this->uow = $this->getMockBuilder('Doctrine\ORM\UnitOfWork')
605 ->disableOriginalConstructor()
606 ->getMock();
607
608 $this->em
609 ->expects($this->any())
610 ->method('getUnitOfWork')
611 ->willReturn($this->uow);
612
613 $this->uow
614 ->expects($this->any())
615 ->method('getScheduledEntityInsertions')
616 ->willReturn([]);
617
618 $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcher')
619 ->disableOriginalConstructor()
620 ->getMock();
621
622 $dispatcher
623 ->expects($this->exactly($dispatched))
624 ->method('dispatch');
625
626 $pocket = new PocketImport($this->em, $this->contentProxy, $this->tagsAssigner, $dispatcher);
627 $pocket->setUser($this->user);
628
629 $this->logHandler = new TestHandler();
630 $logger = new Logger('test', [$this->logHandler]);
631 $pocket->setLogger($logger);
632
633 return $pocket;
628 } 634 }
629} 635}
diff --git a/tests/Wallabag/ImportBundle/Import/ReadabilityImportTest.php b/tests/Wallabag/ImportBundle/Import/ReadabilityImportTest.php
index d1bbe648..1822cdaa 100644
--- a/tests/Wallabag/ImportBundle/Import/ReadabilityImportTest.php
+++ b/tests/Wallabag/ImportBundle/Import/ReadabilityImportTest.php
@@ -2,14 +2,14 @@
2 2
3namespace Tests\Wallabag\ImportBundle\Import; 3namespace Tests\Wallabag\ImportBundle\Import;
4 4
5use Wallabag\ImportBundle\Import\ReadabilityImport; 5use M6Web\Component\RedisMock\RedisMockFactory;
6use Wallabag\UserBundle\Entity\User;
7use Wallabag\CoreBundle\Entity\Entry;
8use Wallabag\ImportBundle\Redis\Producer;
9use Monolog\Logger;
10use Monolog\Handler\TestHandler; 6use Monolog\Handler\TestHandler;
7use Monolog\Logger;
11use Simpleue\Queue\RedisQueue; 8use Simpleue\Queue\RedisQueue;
12use M6Web\Component\RedisMock\RedisMockFactory; 9use Wallabag\CoreBundle\Entity\Entry;
10use Wallabag\ImportBundle\Import\ReadabilityImport;
11use Wallabag\ImportBundle\Redis\Producer;
12use Wallabag\UserBundle\Entity\User;
13 13
14class ReadabilityImportTest extends \PHPUnit_Framework_TestCase 14class ReadabilityImportTest extends \PHPUnit_Framework_TestCase
15{ 15{
@@ -17,59 +17,27 @@ class ReadabilityImportTest extends \PHPUnit_Framework_TestCase
17 protected $em; 17 protected $em;
18 protected $logHandler; 18 protected $logHandler;
19 protected $contentProxy; 19 protected $contentProxy;
20 20 protected $tagsAssigner;
21 private function getReadabilityImport($unsetUser = false, $dispatched = 0)
22 {
23 $this->user = new User();
24
25 $this->em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
26 ->disableOriginalConstructor()
27 ->getMock();
28
29 $this->contentProxy = $this->getMockBuilder('Wallabag\CoreBundle\Helper\ContentProxy')
30 ->disableOriginalConstructor()
31 ->getMock();
32
33 $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcher')
34 ->disableOriginalConstructor()
35 ->getMock();
36
37 $dispatcher
38 ->expects($this->exactly($dispatched))
39 ->method('dispatch');
40
41 $wallabag = new ReadabilityImport($this->em, $this->contentProxy, $dispatcher);
42
43 $this->logHandler = new TestHandler();
44 $logger = new Logger('test', [$this->logHandler]);
45 $wallabag->setLogger($logger);
46
47 if (false === $unsetUser) {
48 $wallabag->setUser($this->user);
49 }
50
51 return $wallabag;
52 }
53 21
54 public function testInit() 22 public function testInit()
55 { 23 {
56 $readabilityImport = $this->getReadabilityImport(); 24 $readabilityImport = $this->getReadabilityImport();
57 25
58 $this->assertEquals('Readability', $readabilityImport->getName()); 26 $this->assertSame('Readability', $readabilityImport->getName());
59 $this->assertNotEmpty($readabilityImport->getUrl()); 27 $this->assertNotEmpty($readabilityImport->getUrl());
60 $this->assertEquals('import.readability.description', $readabilityImport->getDescription()); 28 $this->assertSame('import.readability.description', $readabilityImport->getDescription());
61 } 29 }
62 30
63 public function testImport() 31 public function testImport()
64 { 32 {
65 $readabilityImport = $this->getReadabilityImport(false, 24); 33 $readabilityImport = $this->getReadabilityImport(false, 3);
66 $readabilityImport->setFilepath(__DIR__.'/../fixtures/readability.json'); 34 $readabilityImport->setFilepath(__DIR__ . '/../fixtures/readability.json');
67 35
68 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository') 36 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
69 ->disableOriginalConstructor() 37 ->disableOriginalConstructor()
70 ->getMock(); 38 ->getMock();
71 39
72 $entryRepo->expects($this->exactly(24)) 40 $entryRepo->expects($this->exactly(3))
73 ->method('findByUrlAndUserId') 41 ->method('findByUrlAndUserId')
74 ->willReturn(false); 42 ->willReturn(false);
75 43
@@ -83,20 +51,20 @@ class ReadabilityImportTest extends \PHPUnit_Framework_TestCase
83 ->getMock(); 51 ->getMock();
84 52
85 $this->contentProxy 53 $this->contentProxy
86 ->expects($this->exactly(24)) 54 ->expects($this->exactly(3))
87 ->method('updateEntry') 55 ->method('updateEntry')
88 ->willReturn($entry); 56 ->willReturn($entry);
89 57
90 $res = $readabilityImport->import(); 58 $res = $readabilityImport->import();
91 59
92 $this->assertTrue($res); 60 $this->assertTrue($res);
93 $this->assertEquals(['skipped' => 0, 'imported' => 24, 'queued' => 0], $readabilityImport->getSummary()); 61 $this->assertSame(['skipped' => 0, 'imported' => 3, 'queued' => 0], $readabilityImport->getSummary());
94 } 62 }
95 63
96 public function testImportAndMarkAllAsRead() 64 public function testImportAndMarkAllAsRead()
97 { 65 {
98 $readabilityImport = $this->getReadabilityImport(false, 1); 66 $readabilityImport = $this->getReadabilityImport(false, 1);
99 $readabilityImport->setFilepath(__DIR__.'/../fixtures/readability-read.json'); 67 $readabilityImport->setFilepath(__DIR__ . '/../fixtures/readability-read.json');
100 68
101 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository') 69 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
102 ->disableOriginalConstructor() 70 ->disableOriginalConstructor()
@@ -128,13 +96,13 @@ class ReadabilityImportTest extends \PHPUnit_Framework_TestCase
128 96
129 $this->assertTrue($res); 97 $this->assertTrue($res);
130 98
131 $this->assertEquals(['skipped' => 1, 'imported' => 1, 'queued' => 0], $readabilityImport->getSummary()); 99 $this->assertSame(['skipped' => 1, 'imported' => 1, 'queued' => 0], $readabilityImport->getSummary());
132 } 100 }
133 101
134 public function testImportWithRabbit() 102 public function testImportWithRabbit()
135 { 103 {
136 $readabilityImport = $this->getReadabilityImport(); 104 $readabilityImport = $this->getReadabilityImport();
137 $readabilityImport->setFilepath(__DIR__.'/../fixtures/readability.json'); 105 $readabilityImport->setFilepath(__DIR__ . '/../fixtures/readability.json');
138 106
139 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository') 107 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
140 ->disableOriginalConstructor() 108 ->disableOriginalConstructor()
@@ -160,7 +128,7 @@ class ReadabilityImportTest extends \PHPUnit_Framework_TestCase
160 ->getMock(); 128 ->getMock();
161 129
162 $producer 130 $producer
163 ->expects($this->exactly(24)) 131 ->expects($this->exactly(3))
164 ->method('publish'); 132 ->method('publish');
165 133
166 $readabilityImport->setProducer($producer); 134 $readabilityImport->setProducer($producer);
@@ -168,13 +136,13 @@ class ReadabilityImportTest extends \PHPUnit_Framework_TestCase
168 $res = $readabilityImport->setMarkAsRead(true)->import(); 136 $res = $readabilityImport->setMarkAsRead(true)->import();
169 137
170 $this->assertTrue($res); 138 $this->assertTrue($res);
171 $this->assertEquals(['skipped' => 0, 'imported' => 0, 'queued' => 24], $readabilityImport->getSummary()); 139 $this->assertSame(['skipped' => 0, 'imported' => 0, 'queued' => 3], $readabilityImport->getSummary());
172 } 140 }
173 141
174 public function testImportWithRedis() 142 public function testImportWithRedis()
175 { 143 {
176 $readabilityImport = $this->getReadabilityImport(); 144 $readabilityImport = $this->getReadabilityImport();
177 $readabilityImport->setFilepath(__DIR__.'/../fixtures/readability.json'); 145 $readabilityImport->setFilepath(__DIR__ . '/../fixtures/readability.json');
178 146
179 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository') 147 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
180 ->disableOriginalConstructor() 148 ->disableOriginalConstructor()
@@ -206,7 +174,7 @@ class ReadabilityImportTest extends \PHPUnit_Framework_TestCase
206 $res = $readabilityImport->setMarkAsRead(true)->import(); 174 $res = $readabilityImport->setMarkAsRead(true)->import();
207 175
208 $this->assertTrue($res); 176 $this->assertTrue($res);
209 $this->assertEquals(['skipped' => 0, 'imported' => 0, 'queued' => 24], $readabilityImport->getSummary()); 177 $this->assertSame(['skipped' => 0, 'imported' => 0, 'queued' => 3], $readabilityImport->getSummary());
210 178
211 $this->assertNotEmpty($redisMock->lpop('readability')); 179 $this->assertNotEmpty($redisMock->lpop('readability'));
212 } 180 }
@@ -214,7 +182,7 @@ class ReadabilityImportTest extends \PHPUnit_Framework_TestCase
214 public function testImportBadFile() 182 public function testImportBadFile()
215 { 183 {
216 $readabilityImport = $this->getReadabilityImport(); 184 $readabilityImport = $this->getReadabilityImport();
217 $readabilityImport->setFilepath(__DIR__.'/../fixtures/wallabag-v1.jsonx'); 185 $readabilityImport->setFilepath(__DIR__ . '/../fixtures/wallabag-v1.jsonx');
218 186
219 $res = $readabilityImport->import(); 187 $res = $readabilityImport->import();
220 188
@@ -222,13 +190,13 @@ class ReadabilityImportTest extends \PHPUnit_Framework_TestCase
222 190
223 $records = $this->logHandler->getRecords(); 191 $records = $this->logHandler->getRecords();
224 $this->assertContains('ReadabilityImport: unable to read file', $records[0]['message']); 192 $this->assertContains('ReadabilityImport: unable to read file', $records[0]['message']);
225 $this->assertEquals('ERROR', $records[0]['level_name']); 193 $this->assertSame('ERROR', $records[0]['level_name']);
226 } 194 }
227 195
228 public function testImportUserNotDefined() 196 public function testImportUserNotDefined()
229 { 197 {
230 $readabilityImport = $this->getReadabilityImport(true); 198 $readabilityImport = $this->getReadabilityImport(true);
231 $readabilityImport->setFilepath(__DIR__.'/../fixtures/readability.json'); 199 $readabilityImport->setFilepath(__DIR__ . '/../fixtures/readability.json');
232 200
233 $res = $readabilityImport->import(); 201 $res = $readabilityImport->import();
234 202
@@ -236,6 +204,43 @@ class ReadabilityImportTest extends \PHPUnit_Framework_TestCase
236 204
237 $records = $this->logHandler->getRecords(); 205 $records = $this->logHandler->getRecords();
238 $this->assertContains('ReadabilityImport: user is not defined', $records[0]['message']); 206 $this->assertContains('ReadabilityImport: user is not defined', $records[0]['message']);
239 $this->assertEquals('ERROR', $records[0]['level_name']); 207 $this->assertSame('ERROR', $records[0]['level_name']);
208 }
209
210 private function getReadabilityImport($unsetUser = false, $dispatched = 0)
211 {
212 $this->user = new User();
213
214 $this->em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
215 ->disableOriginalConstructor()
216 ->getMock();
217
218 $this->contentProxy = $this->getMockBuilder('Wallabag\CoreBundle\Helper\ContentProxy')
219 ->disableOriginalConstructor()
220 ->getMock();
221
222 $this->tagsAssigner = $this->getMockBuilder('Wallabag\CoreBundle\Helper\TagsAssigner')
223 ->disableOriginalConstructor()
224 ->getMock();
225
226 $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcher')
227 ->disableOriginalConstructor()
228 ->getMock();
229
230 $dispatcher
231 ->expects($this->exactly($dispatched))
232 ->method('dispatch');
233
234 $wallabag = new ReadabilityImport($this->em, $this->contentProxy, $this->tagsAssigner, $dispatcher);
235
236 $this->logHandler = new TestHandler();
237 $logger = new Logger('test', [$this->logHandler]);
238 $wallabag->setLogger($logger);
239
240 if (false === $unsetUser) {
241 $wallabag->setUser($this->user);
242 }
243
244 return $wallabag;
240 } 245 }
241} 246}
diff --git a/tests/Wallabag/ImportBundle/Import/WallabagV1ImportTest.php b/tests/Wallabag/ImportBundle/Import/WallabagV1ImportTest.php
index 4dbced60..822ad694 100644
--- a/tests/Wallabag/ImportBundle/Import/WallabagV1ImportTest.php
+++ b/tests/Wallabag/ImportBundle/Import/WallabagV1ImportTest.php
@@ -2,14 +2,14 @@
2 2
3namespace Tests\Wallabag\ImportBundle\Import; 3namespace Tests\Wallabag\ImportBundle\Import;
4 4
5use Wallabag\ImportBundle\Import\WallabagV1Import; 5use M6Web\Component\RedisMock\RedisMockFactory;
6use Wallabag\UserBundle\Entity\User;
7use Wallabag\CoreBundle\Entity\Entry;
8use Wallabag\ImportBundle\Redis\Producer;
9use Monolog\Logger;
10use Monolog\Handler\TestHandler; 6use Monolog\Handler\TestHandler;
7use Monolog\Logger;
11use Simpleue\Queue\RedisQueue; 8use Simpleue\Queue\RedisQueue;
12use M6Web\Component\RedisMock\RedisMockFactory; 9use Wallabag\CoreBundle\Entity\Entry;
10use Wallabag\ImportBundle\Import\WallabagV1Import;
11use Wallabag\ImportBundle\Redis\Producer;
12use Wallabag\UserBundle\Entity\User;
13 13
14class WallabagV1ImportTest extends \PHPUnit_Framework_TestCase 14class WallabagV1ImportTest extends \PHPUnit_Framework_TestCase
15{ 15{
@@ -17,73 +17,30 @@ class WallabagV1ImportTest extends \PHPUnit_Framework_TestCase
17 protected $em; 17 protected $em;
18 protected $logHandler; 18 protected $logHandler;
19 protected $contentProxy; 19 protected $contentProxy;
20 20 protected $tagsAssigner;
21 private function getWallabagV1Import($unsetUser = false, $dispatched = 0) 21 protected $uow;
22 { 22 protected $fetchingErrorMessageTitle = 'No title found';
23 $this->user = new User(); 23 protected $fetchingErrorMessage = 'wallabag can\'t retrieve contents for this article. Please <a href="http://doc.wallabag.org/en/master/user/errors_during_fetching.html#how-can-i-help-to-fix-that">troubleshoot this issue</a>.';
24
25 $this->em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
26 ->disableOriginalConstructor()
27 ->getMock();
28
29 $this->uow = $this->getMockBuilder('Doctrine\ORM\UnitOfWork')
30 ->disableOriginalConstructor()
31 ->getMock();
32
33 $this->em
34 ->expects($this->any())
35 ->method('getUnitOfWork')
36 ->willReturn($this->uow);
37
38 $this->uow
39 ->expects($this->any())
40 ->method('getScheduledEntityInsertions')
41 ->willReturn([]);
42
43 $this->contentProxy = $this->getMockBuilder('Wallabag\CoreBundle\Helper\ContentProxy')
44 ->disableOriginalConstructor()
45 ->getMock();
46
47 $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcher')
48 ->disableOriginalConstructor()
49 ->getMock();
50
51 $dispatcher
52 ->expects($this->exactly($dispatched))
53 ->method('dispatch');
54
55 $wallabag = new WallabagV1Import($this->em, $this->contentProxy, $dispatcher);
56
57 $this->logHandler = new TestHandler();
58 $logger = new Logger('test', [$this->logHandler]);
59 $wallabag->setLogger($logger);
60
61 if (false === $unsetUser) {
62 $wallabag->setUser($this->user);
63 }
64
65 return $wallabag;
66 }
67 24
68 public function testInit() 25 public function testInit()
69 { 26 {
70 $wallabagV1Import = $this->getWallabagV1Import(); 27 $wallabagV1Import = $this->getWallabagV1Import();
71 28
72 $this->assertEquals('wallabag v1', $wallabagV1Import->getName()); 29 $this->assertSame('wallabag v1', $wallabagV1Import->getName());
73 $this->assertNotEmpty($wallabagV1Import->getUrl()); 30 $this->assertNotEmpty($wallabagV1Import->getUrl());
74 $this->assertEquals('import.wallabag_v1.description', $wallabagV1Import->getDescription()); 31 $this->assertSame('import.wallabag_v1.description', $wallabagV1Import->getDescription());
75 } 32 }
76 33
77 public function testImport() 34 public function testImport()
78 { 35 {
79 $wallabagV1Import = $this->getWallabagV1Import(false, 3); 36 $wallabagV1Import = $this->getWallabagV1Import(false, 1);
80 $wallabagV1Import->setFilepath(__DIR__.'/../fixtures/wallabag-v1.json'); 37 $wallabagV1Import->setFilepath(__DIR__ . '/../fixtures/wallabag-v1.json');
81 38
82 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository') 39 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
83 ->disableOriginalConstructor() 40 ->disableOriginalConstructor()
84 ->getMock(); 41 ->getMock();
85 42
86 $entryRepo->expects($this->exactly(4)) 43 $entryRepo->expects($this->exactly(2))
87 ->method('findByUrlAndUserId') 44 ->method('findByUrlAndUserId')
88 ->will($this->onConsecutiveCalls(false, true, false, false)); 45 ->will($this->onConsecutiveCalls(false, true, false, false));
89 46
@@ -97,20 +54,20 @@ class WallabagV1ImportTest extends \PHPUnit_Framework_TestCase
97 ->getMock(); 54 ->getMock();
98 55
99 $this->contentProxy 56 $this->contentProxy
100 ->expects($this->exactly(3)) 57 ->expects($this->exactly(1))
101 ->method('updateEntry') 58 ->method('updateEntry')
102 ->willReturn($entry); 59 ->willReturn($entry);
103 60
104 $res = $wallabagV1Import->import(); 61 $res = $wallabagV1Import->import();
105 62
106 $this->assertTrue($res); 63 $this->assertTrue($res);
107 $this->assertEquals(['skipped' => 1, 'imported' => 3, 'queued' => 0], $wallabagV1Import->getSummary()); 64 $this->assertSame(['skipped' => 1, 'imported' => 1, 'queued' => 0], $wallabagV1Import->getSummary());
108 } 65 }
109 66
110 public function testImportAndMarkAllAsRead() 67 public function testImportAndMarkAllAsRead()
111 { 68 {
112 $wallabagV1Import = $this->getWallabagV1Import(false, 3); 69 $wallabagV1Import = $this->getWallabagV1Import(false, 3);
113 $wallabagV1Import->setFilepath(__DIR__.'/../fixtures/wallabag-v1-read.json'); 70 $wallabagV1Import->setFilepath(__DIR__ . '/../fixtures/wallabag-v1-read.json');
114 71
115 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository') 72 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
116 ->disableOriginalConstructor() 73 ->disableOriginalConstructor()
@@ -142,13 +99,13 @@ class WallabagV1ImportTest extends \PHPUnit_Framework_TestCase
142 99
143 $this->assertTrue($res); 100 $this->assertTrue($res);
144 101
145 $this->assertEquals(['skipped' => 0, 'imported' => 3, 'queued' => 0], $wallabagV1Import->getSummary()); 102 $this->assertSame(['skipped' => 0, 'imported' => 3, 'queued' => 0], $wallabagV1Import->getSummary());
146 } 103 }
147 104
148 public function testImportWithRabbit() 105 public function testImportWithRabbit()
149 { 106 {
150 $wallabagV1Import = $this->getWallabagV1Import(); 107 $wallabagV1Import = $this->getWallabagV1Import();
151 $wallabagV1Import->setFilepath(__DIR__.'/../fixtures/wallabag-v1.json'); 108 $wallabagV1Import->setFilepath(__DIR__ . '/../fixtures/wallabag-v1.json');
152 109
153 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository') 110 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
154 ->disableOriginalConstructor() 111 ->disableOriginalConstructor()
@@ -174,7 +131,7 @@ class WallabagV1ImportTest extends \PHPUnit_Framework_TestCase
174 ->getMock(); 131 ->getMock();
175 132
176 $producer 133 $producer
177 ->expects($this->exactly(4)) 134 ->expects($this->exactly(2))
178 ->method('publish'); 135 ->method('publish');
179 136
180 $wallabagV1Import->setProducer($producer); 137 $wallabagV1Import->setProducer($producer);
@@ -182,13 +139,13 @@ class WallabagV1ImportTest extends \PHPUnit_Framework_TestCase
182 $res = $wallabagV1Import->setMarkAsRead(true)->import(); 139 $res = $wallabagV1Import->setMarkAsRead(true)->import();
183 140
184 $this->assertTrue($res); 141 $this->assertTrue($res);
185 $this->assertEquals(['skipped' => 0, 'imported' => 0, 'queued' => 4], $wallabagV1Import->getSummary()); 142 $this->assertSame(['skipped' => 0, 'imported' => 0, 'queued' => 2], $wallabagV1Import->getSummary());
186 } 143 }
187 144
188 public function testImportWithRedis() 145 public function testImportWithRedis()
189 { 146 {
190 $wallabagV1Import = $this->getWallabagV1Import(); 147 $wallabagV1Import = $this->getWallabagV1Import();
191 $wallabagV1Import->setFilepath(__DIR__.'/../fixtures/wallabag-v1.json'); 148 $wallabagV1Import->setFilepath(__DIR__ . '/../fixtures/wallabag-v1.json');
192 149
193 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository') 150 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
194 ->disableOriginalConstructor() 151 ->disableOriginalConstructor()
@@ -220,7 +177,7 @@ class WallabagV1ImportTest extends \PHPUnit_Framework_TestCase
220 $res = $wallabagV1Import->setMarkAsRead(true)->import(); 177 $res = $wallabagV1Import->setMarkAsRead(true)->import();
221 178
222 $this->assertTrue($res); 179 $this->assertTrue($res);
223 $this->assertEquals(['skipped' => 0, 'imported' => 0, 'queued' => 4], $wallabagV1Import->getSummary()); 180 $this->assertSame(['skipped' => 0, 'imported' => 0, 'queued' => 2], $wallabagV1Import->getSummary());
224 181
225 $this->assertNotEmpty($redisMock->lpop('wallabag_v1')); 182 $this->assertNotEmpty($redisMock->lpop('wallabag_v1'));
226 } 183 }
@@ -228,7 +185,7 @@ class WallabagV1ImportTest extends \PHPUnit_Framework_TestCase
228 public function testImportBadFile() 185 public function testImportBadFile()
229 { 186 {
230 $wallabagV1Import = $this->getWallabagV1Import(); 187 $wallabagV1Import = $this->getWallabagV1Import();
231 $wallabagV1Import->setFilepath(__DIR__.'/../fixtures/wallabag-v1.jsonx'); 188 $wallabagV1Import->setFilepath(__DIR__ . '/../fixtures/wallabag-v1.jsonx');
232 189
233 $res = $wallabagV1Import->import(); 190 $res = $wallabagV1Import->import();
234 191
@@ -236,13 +193,13 @@ class WallabagV1ImportTest extends \PHPUnit_Framework_TestCase
236 193
237 $records = $this->logHandler->getRecords(); 194 $records = $this->logHandler->getRecords();
238 $this->assertContains('WallabagImport: unable to read file', $records[0]['message']); 195 $this->assertContains('WallabagImport: unable to read file', $records[0]['message']);
239 $this->assertEquals('ERROR', $records[0]['level_name']); 196 $this->assertSame('ERROR', $records[0]['level_name']);
240 } 197 }
241 198
242 public function testImportUserNotDefined() 199 public function testImportUserNotDefined()
243 { 200 {
244 $wallabagV1Import = $this->getWallabagV1Import(true); 201 $wallabagV1Import = $this->getWallabagV1Import(true);
245 $wallabagV1Import->setFilepath(__DIR__.'/../fixtures/wallabag-v1.json'); 202 $wallabagV1Import->setFilepath(__DIR__ . '/../fixtures/wallabag-v1.json');
246 203
247 $res = $wallabagV1Import->import(); 204 $res = $wallabagV1Import->import();
248 205
@@ -250,6 +207,64 @@ class WallabagV1ImportTest extends \PHPUnit_Framework_TestCase
250 207
251 $records = $this->logHandler->getRecords(); 208 $records = $this->logHandler->getRecords();
252 $this->assertContains('WallabagImport: user is not defined', $records[0]['message']); 209 $this->assertContains('WallabagImport: user is not defined', $records[0]['message']);
253 $this->assertEquals('ERROR', $records[0]['level_name']); 210 $this->assertSame('ERROR', $records[0]['level_name']);
211 }
212
213 private function getWallabagV1Import($unsetUser = false, $dispatched = 0)
214 {
215 $this->user = new User();
216
217 $this->em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
218 ->disableOriginalConstructor()
219 ->getMock();
220
221 $this->uow = $this->getMockBuilder('Doctrine\ORM\UnitOfWork')
222 ->disableOriginalConstructor()
223 ->getMock();
224
225 $this->em
226 ->expects($this->any())
227 ->method('getUnitOfWork')
228 ->willReturn($this->uow);
229
230 $this->uow
231 ->expects($this->any())
232 ->method('getScheduledEntityInsertions')
233 ->willReturn([]);
234
235 $this->contentProxy = $this->getMockBuilder('Wallabag\CoreBundle\Helper\ContentProxy')
236 ->disableOriginalConstructor()
237 ->getMock();
238
239 $this->tagsAssigner = $this->getMockBuilder('Wallabag\CoreBundle\Helper\TagsAssigner')
240 ->disableOriginalConstructor()
241 ->getMock();
242
243 $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcher')
244 ->disableOriginalConstructor()
245 ->getMock();
246
247 $dispatcher
248 ->expects($this->exactly($dispatched))
249 ->method('dispatch');
250
251 $wallabag = new WallabagV1Import(
252 $this->em,
253 $this->contentProxy,
254 $this->tagsAssigner,
255 $dispatcher,
256 $this->fetchingErrorMessageTitle,
257 $this->fetchingErrorMessage
258 );
259
260 $this->logHandler = new TestHandler();
261 $logger = new Logger('test', [$this->logHandler]);
262 $wallabag->setLogger($logger);
263
264 if (false === $unsetUser) {
265 $wallabag->setUser($this->user);
266 }
267
268 return $wallabag;
254 } 269 }
255} 270}
diff --git a/tests/Wallabag/ImportBundle/Import/WallabagV2ImportTest.php b/tests/Wallabag/ImportBundle/Import/WallabagV2ImportTest.php
index 0e50b8b2..fab50a45 100644
--- a/tests/Wallabag/ImportBundle/Import/WallabagV2ImportTest.php
+++ b/tests/Wallabag/ImportBundle/Import/WallabagV2ImportTest.php
@@ -2,14 +2,14 @@
2 2
3namespace Tests\Wallabag\ImportBundle\Import; 3namespace Tests\Wallabag\ImportBundle\Import;
4 4
5use Wallabag\ImportBundle\Import\WallabagV2Import; 5use M6Web\Component\RedisMock\RedisMockFactory;
6use Wallabag\UserBundle\Entity\User;
7use Wallabag\CoreBundle\Entity\Entry;
8use Wallabag\ImportBundle\Redis\Producer;
9use Monolog\Logger;
10use Monolog\Handler\TestHandler; 6use Monolog\Handler\TestHandler;
7use Monolog\Logger;
11use Simpleue\Queue\RedisQueue; 8use Simpleue\Queue\RedisQueue;
12use M6Web\Component\RedisMock\RedisMockFactory; 9use Wallabag\CoreBundle\Entity\Entry;
10use Wallabag\ImportBundle\Import\WallabagV2Import;
11use Wallabag\ImportBundle\Redis\Producer;
12use Wallabag\UserBundle\Entity\User;
13 13
14class WallabagV2ImportTest extends \PHPUnit_Framework_TestCase 14class WallabagV2ImportTest extends \PHPUnit_Framework_TestCase
15{ 15{
@@ -17,73 +17,28 @@ class WallabagV2ImportTest extends \PHPUnit_Framework_TestCase
17 protected $em; 17 protected $em;
18 protected $logHandler; 18 protected $logHandler;
19 protected $contentProxy; 19 protected $contentProxy;
20 20 protected $tagsAssigner;
21 private function getWallabagV2Import($unsetUser = false, $dispatched = 0) 21 protected $uow;
22 {
23 $this->user = new User();
24
25 $this->em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
26 ->disableOriginalConstructor()
27 ->getMock();
28
29 $this->uow = $this->getMockBuilder('Doctrine\ORM\UnitOfWork')
30 ->disableOriginalConstructor()
31 ->getMock();
32
33 $this->em
34 ->expects($this->any())
35 ->method('getUnitOfWork')
36 ->willReturn($this->uow);
37
38 $this->uow
39 ->expects($this->any())
40 ->method('getScheduledEntityInsertions')
41 ->willReturn([]);
42
43 $this->contentProxy = $this->getMockBuilder('Wallabag\CoreBundle\Helper\ContentProxy')
44 ->disableOriginalConstructor()
45 ->getMock();
46
47 $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcher')
48 ->disableOriginalConstructor()
49 ->getMock();
50
51 $dispatcher
52 ->expects($this->exactly($dispatched))
53 ->method('dispatch');
54
55 $wallabag = new WallabagV2Import($this->em, $this->contentProxy, $dispatcher);
56
57 $this->logHandler = new TestHandler();
58 $logger = new Logger('test', [$this->logHandler]);
59 $wallabag->setLogger($logger);
60
61 if (false === $unsetUser) {
62 $wallabag->setUser($this->user);
63 }
64
65 return $wallabag;
66 }
67 22
68 public function testInit() 23 public function testInit()
69 { 24 {
70 $wallabagV2Import = $this->getWallabagV2Import(); 25 $wallabagV2Import = $this->getWallabagV2Import();
71 26
72 $this->assertEquals('wallabag v2', $wallabagV2Import->getName()); 27 $this->assertSame('wallabag v2', $wallabagV2Import->getName());
73 $this->assertNotEmpty($wallabagV2Import->getUrl()); 28 $this->assertNotEmpty($wallabagV2Import->getUrl());
74 $this->assertEquals('import.wallabag_v2.description', $wallabagV2Import->getDescription()); 29 $this->assertSame('import.wallabag_v2.description', $wallabagV2Import->getDescription());
75 } 30 }
76 31
77 public function testImport() 32 public function testImport()
78 { 33 {
79 $wallabagV2Import = $this->getWallabagV2Import(false, 2); 34 $wallabagV2Import = $this->getWallabagV2Import(false, 2);
80 $wallabagV2Import->setFilepath(__DIR__.'/../fixtures/wallabag-v2.json'); 35 $wallabagV2Import->setFilepath(__DIR__ . '/../fixtures/wallabag-v2.json');
81 36
82 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository') 37 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
83 ->disableOriginalConstructor() 38 ->disableOriginalConstructor()
84 ->getMock(); 39 ->getMock();
85 40
86 $entryRepo->expects($this->exactly(24)) 41 $entryRepo->expects($this->exactly(6))
87 ->method('findByUrlAndUserId') 42 ->method('findByUrlAndUserId')
88 ->will($this->onConsecutiveCalls(false, true, false)); 43 ->will($this->onConsecutiveCalls(false, true, false));
89 44
@@ -100,13 +55,13 @@ class WallabagV2ImportTest extends \PHPUnit_Framework_TestCase
100 $res = $wallabagV2Import->import(); 55 $res = $wallabagV2Import->import();
101 56
102 $this->assertTrue($res); 57 $this->assertTrue($res);
103 $this->assertEquals(['skipped' => 22, 'imported' => 2, 'queued' => 0], $wallabagV2Import->getSummary()); 58 $this->assertSame(['skipped' => 4, 'imported' => 2, 'queued' => 0], $wallabagV2Import->getSummary());
104 } 59 }
105 60
106 public function testImportAndMarkAllAsRead() 61 public function testImportAndMarkAllAsRead()
107 { 62 {
108 $wallabagV2Import = $this->getWallabagV2Import(false, 2); 63 $wallabagV2Import = $this->getWallabagV2Import(false, 2);
109 $wallabagV2Import->setFilepath(__DIR__.'/../fixtures/wallabag-v2-read.json'); 64 $wallabagV2Import->setFilepath(__DIR__ . '/../fixtures/wallabag-v2-read.json');
110 65
111 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository') 66 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
112 ->disableOriginalConstructor() 67 ->disableOriginalConstructor()
@@ -138,13 +93,13 @@ class WallabagV2ImportTest extends \PHPUnit_Framework_TestCase
138 93
139 $this->assertTrue($res); 94 $this->assertTrue($res);
140 95
141 $this->assertEquals(['skipped' => 0, 'imported' => 2, 'queued' => 0], $wallabagV2Import->getSummary()); 96 $this->assertSame(['skipped' => 0, 'imported' => 2, 'queued' => 0], $wallabagV2Import->getSummary());
142 } 97 }
143 98
144 public function testImportWithRabbit() 99 public function testImportWithRabbit()
145 { 100 {
146 $wallabagV2Import = $this->getWallabagV2Import(); 101 $wallabagV2Import = $this->getWallabagV2Import();
147 $wallabagV2Import->setFilepath(__DIR__.'/../fixtures/wallabag-v2.json'); 102 $wallabagV2Import->setFilepath(__DIR__ . '/../fixtures/wallabag-v2.json');
148 103
149 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository') 104 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
150 ->disableOriginalConstructor() 105 ->disableOriginalConstructor()
@@ -166,7 +121,7 @@ class WallabagV2ImportTest extends \PHPUnit_Framework_TestCase
166 ->getMock(); 121 ->getMock();
167 122
168 $producer 123 $producer
169 ->expects($this->exactly(24)) 124 ->expects($this->exactly(6))
170 ->method('publish'); 125 ->method('publish');
171 126
172 $wallabagV2Import->setProducer($producer); 127 $wallabagV2Import->setProducer($producer);
@@ -174,13 +129,13 @@ class WallabagV2ImportTest extends \PHPUnit_Framework_TestCase
174 $res = $wallabagV2Import->setMarkAsRead(true)->import(); 129 $res = $wallabagV2Import->setMarkAsRead(true)->import();
175 130
176 $this->assertTrue($res); 131 $this->assertTrue($res);
177 $this->assertEquals(['skipped' => 0, 'imported' => 0, 'queued' => 24], $wallabagV2Import->getSummary()); 132 $this->assertSame(['skipped' => 0, 'imported' => 0, 'queued' => 6], $wallabagV2Import->getSummary());
178 } 133 }
179 134
180 public function testImportWithRedis() 135 public function testImportWithRedis()
181 { 136 {
182 $wallabagV2Import = $this->getWallabagV2Import(); 137 $wallabagV2Import = $this->getWallabagV2Import();
183 $wallabagV2Import->setFilepath(__DIR__.'/../fixtures/wallabag-v2.json'); 138 $wallabagV2Import->setFilepath(__DIR__ . '/../fixtures/wallabag-v2.json');
184 139
185 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository') 140 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
186 ->disableOriginalConstructor() 141 ->disableOriginalConstructor()
@@ -208,7 +163,7 @@ class WallabagV2ImportTest extends \PHPUnit_Framework_TestCase
208 $res = $wallabagV2Import->setMarkAsRead(true)->import(); 163 $res = $wallabagV2Import->setMarkAsRead(true)->import();
209 164
210 $this->assertTrue($res); 165 $this->assertTrue($res);
211 $this->assertEquals(['skipped' => 0, 'imported' => 0, 'queued' => 24], $wallabagV2Import->getSummary()); 166 $this->assertSame(['skipped' => 0, 'imported' => 0, 'queued' => 6], $wallabagV2Import->getSummary());
212 167
213 $this->assertNotEmpty($redisMock->lpop('wallabag_v2')); 168 $this->assertNotEmpty($redisMock->lpop('wallabag_v2'));
214 } 169 }
@@ -216,7 +171,7 @@ class WallabagV2ImportTest extends \PHPUnit_Framework_TestCase
216 public function testImportBadFile() 171 public function testImportBadFile()
217 { 172 {
218 $wallabagV1Import = $this->getWallabagV2Import(); 173 $wallabagV1Import = $this->getWallabagV2Import();
219 $wallabagV1Import->setFilepath(__DIR__.'/../fixtures/wallabag-v2.jsonx'); 174 $wallabagV1Import->setFilepath(__DIR__ . '/../fixtures/wallabag-v2.jsonx');
220 175
221 $res = $wallabagV1Import->import(); 176 $res = $wallabagV1Import->import();
222 177
@@ -224,13 +179,13 @@ class WallabagV2ImportTest extends \PHPUnit_Framework_TestCase
224 179
225 $records = $this->logHandler->getRecords(); 180 $records = $this->logHandler->getRecords();
226 $this->assertContains('WallabagImport: unable to read file', $records[0]['message']); 181 $this->assertContains('WallabagImport: unable to read file', $records[0]['message']);
227 $this->assertEquals('ERROR', $records[0]['level_name']); 182 $this->assertSame('ERROR', $records[0]['level_name']);
228 } 183 }
229 184
230 public function testImportUserNotDefined() 185 public function testImportUserNotDefined()
231 { 186 {
232 $wallabagV1Import = $this->getWallabagV2Import(true); 187 $wallabagV1Import = $this->getWallabagV2Import(true);
233 $wallabagV1Import->setFilepath(__DIR__.'/../fixtures/wallabag-v2.json'); 188 $wallabagV1Import->setFilepath(__DIR__ . '/../fixtures/wallabag-v2.json');
234 189
235 $res = $wallabagV1Import->import(); 190 $res = $wallabagV1Import->import();
236 191
@@ -238,30 +193,30 @@ class WallabagV2ImportTest extends \PHPUnit_Framework_TestCase
238 193
239 $records = $this->logHandler->getRecords(); 194 $records = $this->logHandler->getRecords();
240 $this->assertContains('WallabagImport: user is not defined', $records[0]['message']); 195 $this->assertContains('WallabagImport: user is not defined', $records[0]['message']);
241 $this->assertEquals('ERROR', $records[0]['level_name']); 196 $this->assertSame('ERROR', $records[0]['level_name']);
242 } 197 }
243 198
244 public function testImportEmptyFile() 199 public function testImportEmptyFile()
245 { 200 {
246 $wallabagV2Import = $this->getWallabagV2Import(); 201 $wallabagV2Import = $this->getWallabagV2Import();
247 $wallabagV2Import->setFilepath(__DIR__.'/../fixtures/wallabag-v2-empty.json'); 202 $wallabagV2Import->setFilepath(__DIR__ . '/../fixtures/wallabag-v2-empty.json');
248 203
249 $res = $wallabagV2Import->import(); 204 $res = $wallabagV2Import->import();
250 205
251 $this->assertFalse($res); 206 $this->assertFalse($res);
252 $this->assertEquals(['skipped' => 0, 'imported' => 0, 'queued' => 0], $wallabagV2Import->getSummary()); 207 $this->assertSame(['skipped' => 0, 'imported' => 0, 'queued' => 0], $wallabagV2Import->getSummary());
253 } 208 }
254 209
255 public function testImportWithExceptionFromGraby() 210 public function testImportWithExceptionFromGraby()
256 { 211 {
257 $wallabagV2Import = $this->getWallabagV2Import(false, 2); 212 $wallabagV2Import = $this->getWallabagV2Import(false, 2);
258 $wallabagV2Import->setFilepath(__DIR__.'/../fixtures/wallabag-v2.json'); 213 $wallabagV2Import->setFilepath(__DIR__ . '/../fixtures/wallabag-v2.json');
259 214
260 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository') 215 $entryRepo = $this->getMockBuilder('Wallabag\CoreBundle\Repository\EntryRepository')
261 ->disableOriginalConstructor() 216 ->disableOriginalConstructor()
262 ->getMock(); 217 ->getMock();
263 218
264 $entryRepo->expects($this->exactly(24)) 219 $entryRepo->expects($this->exactly(6))
265 ->method('findByUrlAndUserId') 220 ->method('findByUrlAndUserId')
266 ->will($this->onConsecutiveCalls(false, true, false)); 221 ->will($this->onConsecutiveCalls(false, true, false));
267 222
@@ -278,6 +233,57 @@ class WallabagV2ImportTest extends \PHPUnit_Framework_TestCase
278 $res = $wallabagV2Import->import(); 233 $res = $wallabagV2Import->import();
279 234
280 $this->assertTrue($res); 235 $this->assertTrue($res);
281 $this->assertEquals(['skipped' => 22, 'imported' => 2, 'queued' => 0], $wallabagV2Import->getSummary()); 236 $this->assertSame(['skipped' => 4, 'imported' => 2, 'queued' => 0], $wallabagV2Import->getSummary());
237 }
238
239 private function getWallabagV2Import($unsetUser = false, $dispatched = 0)
240 {
241 $this->user = new User();
242
243 $this->em = $this->getMockBuilder('Doctrine\ORM\EntityManager')
244 ->disableOriginalConstructor()
245 ->getMock();
246
247 $this->uow = $this->getMockBuilder('Doctrine\ORM\UnitOfWork')
248 ->disableOriginalConstructor()
249 ->getMock();
250
251 $this->em
252 ->expects($this->any())
253 ->method('getUnitOfWork')
254 ->willReturn($this->uow);
255
256 $this->uow
257 ->expects($this->any())
258 ->method('getScheduledEntityInsertions')
259 ->willReturn([]);
260
261 $this->contentProxy = $this->getMockBuilder('Wallabag\CoreBundle\Helper\ContentProxy')
262 ->disableOriginalConstructor()
263 ->getMock();
264
265 $this->tagsAssigner = $this->getMockBuilder('Wallabag\CoreBundle\Helper\TagsAssigner')
266 ->disableOriginalConstructor()
267 ->getMock();
268
269 $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcher')
270 ->disableOriginalConstructor()
271 ->getMock();
272
273 $dispatcher
274 ->expects($this->exactly($dispatched))
275 ->method('dispatch');
276
277 $wallabag = new WallabagV2Import($this->em, $this->contentProxy, $this->tagsAssigner, $dispatcher);
278
279 $this->logHandler = new TestHandler();
280 $logger = new Logger('test', [$this->logHandler]);
281 $wallabag->setLogger($logger);
282
283 if (false === $unsetUser) {
284 $wallabag->setUser($this->user);
285 }
286
287 return $wallabag;
282 } 288 }
283} 289}
diff --git a/tests/Wallabag/ImportBundle/fixtures/instapaper-export.csv b/tests/Wallabag/ImportBundle/fixtures/instapaper-export.csv
index 28a4c8e6..1a648f8a 100644
--- a/tests/Wallabag/ImportBundle/fixtures/instapaper-export.csv
+++ b/tests/Wallabag/ImportBundle/fixtures/instapaper-export.csv
@@ -2,3 +2,4 @@ URL,Title,Selection,Folder
2http://www.liberation.fr/societe/2012/12/06/baumettes-un-tour-en-cellule_865551,Baumettes : un tour en cellule,,Unread 2http://www.liberation.fr/societe/2012/12/06/baumettes-un-tour-en-cellule_865551,Baumettes : un tour en cellule,,Unread
3https://redditblog.com/2016/09/20/amp-and-reactredux/,AMP and React+Redux: Why Not?,,Archive 3https://redditblog.com/2016/09/20/amp-and-reactredux/,AMP and React+Redux: Why Not?,,Archive
4https://medium.com/@the_minh/why-foursquare-swarm-is-still-my-favourite-social-network-e38228493e6c,Why Foursquare / Swarm is still my favourite social network,,Starred 4https://medium.com/@the_minh/why-foursquare-swarm-is-still-my-favourite-social-network-e38228493e6c,Why Foursquare / Swarm is still my favourite social network,,Starred
5http://www.20minutes.fr/high-tech/2077615-20170531-dis-donc-donald-trump-quoi-exactement-covfefe,"Dis donc Donald Trump, c'est quoi exactement «covfefe»?",,test_tag
diff --git a/tests/Wallabag/ImportBundle/fixtures/pinboard_export b/tests/Wallabag/ImportBundle/fixtures/pinboard_export
index 2dd744d3..b5f653e7 100644
--- a/tests/Wallabag/ImportBundle/fixtures/pinboard_export
+++ b/tests/Wallabag/ImportBundle/fixtures/pinboard_export
@@ -1,5 +1,3 @@
1[{"href":"https:\/\/developers.google.com\/web\/updates\/2016\/07\/infinite-scroller","description":"Complexities of an Infinite Scroller","extended":"TL;DR: Re-use your DOM elements and remove the ones that are far away from the viewport. Use placeholders to account for delayed data","meta":"21ff61c6f648901168f9e6119f53df7d","hash":"e69b65724cca1c585b446d4c47865d76","time":"2016-10-31T15:57:56Z","shared":"yes","toread":"no","tags":"infinite dom performance scroll"}, 1[{"href":"https:\/\/developers.google.com\/web\/updates\/2016\/07\/infinite-scroller","description":"Complexities of an Infinite Scroller","extended":"TL;DR: Re-use your DOM elements and remove the ones that are far away from the viewport. Use placeholders to account for delayed data","meta":"21ff61c6f648901168f9e6119f53df7d","hash":"e69b65724cca1c585b446d4c47865d76","time":"2016-10-31T15:57:56Z","shared":"yes","toread":"no","tags":"infinite dom performance scroll"},
2{"href":"https:\/\/ma.ttias.be\/varnish-explained\/","description":"Varnish (explained) for PHP developers","extended":"A few months ago, I gave a presentation at LaraconEU in Amsterdam titled \"Varnish for PHP developers\". The generic title of that presentation is actually Varnish Explained and this is a write-up of that presentation, the video and the slides.","meta":"d32ad9fac2ed29da4aec12c562e9afb1","hash":"21dd6bdda8ad62666a2c9e79f6e80f98","time":"2016-10-26T06:43:03Z","shared":"yes","toread":"no","tags":"varnish PHP"}, 2{"href":"https:\/\/ma.ttias.be\/varnish-explained\/","description":"Varnish (explained) for PHP developers","extended":"A few months ago, I gave a presentation at LaraconEU in Amsterdam titled \"Varnish for PHP developers\". The generic title of that presentation is actually Varnish Explained and this is a write-up of that presentation, the video and the slides.","meta":"d32ad9fac2ed29da4aec12c562e9afb1","hash":"21dd6bdda8ad62666a2c9e79f6e80f98","time":"2016-10-26T06:43:03Z","shared":"yes","toread":"no","tags":"varnish PHP"},
3{"href":"https:\/\/ilia.ws\/files\/nginx_torontophpug.pdf","description":"Nginx Tricks for PHP Developers","extended":"","meta":"9adbb5c4ca6760e335b920800d88c70a","hash":"0189bb08f8bd0122c6544bed4624c546","time":"2016-10-05T07:11:27Z","shared":"yes","toread":"no","tags":"nginx PHP best_practice"}, 3{"href":"https:\/\/ilia.ws\/files\/nginx_torontophpug.pdf","description":"Nginx Tricks for PHP Developers","extended":"","meta":"9adbb5c4ca6760e335b920800d88c70a","hash":"0189bb08f8bd0122c6544bed4624c546","time":"2016-10-05T07:11:27Z","shared":"yes","toread":"no","tags":"nginx PHP best_practice"}]
4{"href":"https:\/\/jolicode.com\/blog\/starting-a-mobile-application-with-react-native","description":"Starting a mobile application with React Native","extended":"While preparing our next React Native training, I learnt a lot on the library and discovered an amazing community with a lot of packages.","meta":"bd140bd3e53e3a0b4cb08cdaf64bcbfc","hash":"015fa10cd97f56186420555e52cfab62","time":"2016-09-23T10:58:20Z","shared":"yes","toread":"no","tags":"react-native"},
5{"href":"http:\/\/open.blogs.nytimes.com\/2016\/08\/29\/testing-varnish-using-varnishtest\/","description":"Testing Varnish Using Varnishtest","extended":"Varnish ships with the ability to test using the testing tool varnishtest. Varnishtest gives you the ability to write VCL tests you can run on the command line or as part of your build process.","meta":"ca2752a07adea4bab52cd19e8fdbf356","hash":"d3e642cc1274d10e4c12ee31f5dde736","time":"2016-08-30T09:33:24Z","shared":"yes","toread":"no","tags":"varnish test vcl"}]
diff --git a/tests/Wallabag/ImportBundle/fixtures/readability.json b/tests/Wallabag/ImportBundle/fixtures/readability.json
index 32f6fa53..b9fd570d 100644
--- a/tests/Wallabag/ImportBundle/fixtures/readability.json
+++ b/tests/Wallabag/ImportBundle/fixtures/readability.json
@@ -11,13 +11,6 @@
11 "archive": false 11 "archive": false
12 }, 12 },
13 { 13 {
14 "article__title": "Réfugiés: l'UE va créer 100 000 places d'accueil dans les Balkans",
15 "article__url": "http://www.liberation.fr/planete/2015/10/26/refugies-l-ue-va-creer-100-000-places-d-accueil-dans-les-balkans_1408867",
16 "archive": false,
17 "date_added": "2016-09-08T11:55:58+0200",
18 "favorite": false
19 },
20 {
21 "article__title": "No title found", 14 "article__title": "No title found",
22 "article__url": "http://news.nationalgeographic.com/2016/02/160211-albatrosses-mothers-babies-animals-science/&sf20739758=1", 15 "article__url": "http://news.nationalgeographic.com/2016/02/160211-albatrosses-mothers-babies-animals-science/&sf20739758=1",
23 "archive": false, 16 "archive": false,
@@ -28,148 +21,8 @@
28 "archive": 0, 21 "archive": 0,
29 "date_added": "2016-09-08T11:55:58+0200", 22 "date_added": "2016-09-08T11:55:58+0200",
30 "favorite": 0, 23 "favorite": 0,
31 "article__title": "Échecs",
32 "article__url": "https://fr.wikipedia.org/wiki/Échecs"
33 },
34 {
35 "archive": 0,
36 "date_added": "2016-09-08T11:55:58+0200",
37 "favorite": 0,
38 "article__title": "90% des dossiers médicaux des Coréens du sud vendus à des entreprises privées - ZATAZ", 24 "article__title": "90% des dossiers médicaux des Coréens du sud vendus à des entreprises privées - ZATAZ",
39 "article__url": "http://www.zataz.com/90-des-dossiers-medicaux-des-coreens-du-sud-vendus-a-des-entreprises-privees/" 25 "article__url": "http://www.zataz.com/90-des-dossiers-medicaux-des-coreens-du-sud-vendus-a-des-entreprises-privees/"
40 },
41 {
42 "archive": 0,
43 "date_added": "2016-09-08T11:55:58+0200",
44 "favorite": 0,
45 "article__title": "Mass Surveillance As Art",
46 "article__url": "https://www.nationaljournal.com/s/73311/mass-surveillance-art"
47 },
48 {
49 "archive": 0,
50 "date_added": "2016-09-08T11:55:58+0200",
51 "favorite": 0,
52 "article__title": "What David Cameron did to the pig, his party is now doing to the country",
53 "article__url": "http://www.newstatesman.com/2015/09/what-david-cameron-did-pig-his-party-now-doing-country"
54 },
55 {
56 "archive": 1,
57 "date_added": "2016-09-08T11:55:58+0200",
58 "favorite": 0,
59 "article__title": "CLICK HERE to support 2016 CES Winner, Revolutionary Auto-Tracking Robot",
60 "article__url": "https://www.indiegogo.com/projects/2016-ces-winner-revolutionary-auto-tracking-robot"
61 },
62 {
63 "archive": 0,
64 "date_added": "2016-09-08T11:55:58+0200",
65 "favorite": 1,
66 "article__title": "No title found",
67 "article__url": "http://carnetdevol.shost.ca/wordpress/aide-memoire-sur-les-commandes-associees-a-systemd/"
68 },
69 {
70 "archive": 1,
71 "date_added": "2016-09-08T11:55:58+0200",
72 "favorite": 0,
73 "article__title": "Présentation d'Arduino - Tuto Arduino - Le blog d'Eskimon",
74 "article__url": "http://eskimon.fr/73-arduino-101-presentation"
75 },
76 {
77 "archive": 1,
78 "date_added": "2016-09-08T11:55:58+0200",
79 "favorite": 0,
80 "article__title": "Lenovo ThinkPad X1 Carbon Ultrabook Review",
81 "article__url": "http://www.notebookcheck.net/Lenovo-ThinkPad-X1-Carbon-Ultrabook-Review.138033.0.html"
82 },
83 {
84 "archive": 0,
85 "date_added": "2016-09-08T11:55:58+0200",
86 "favorite": 0,
87 "article__title": "Visitons le Château de Landsberg !",
88 "article__url": "http://autour-du-mont-sainte-odile.overblog.com/2016/01/visitons-le-chateau-de-landsberg.html"
89 },
90 {
91 "archive": 1,
92 "date_added": "2016-09-08T11:55:58+0200",
93 "favorite": 0,
94 "article__title": "Contrer les stéréotypes par les livres : “C'est dès l'enfance qu'ils se construisent”",
95 "article__url": "https://www.actualitte.com/article/monde-edition/contrer-les-stereotypes-par-les-livres-c-est-des-l-enfance-qu-ils-se-construisent/64058"
96 },
97 {
98 "archive": 1,
99 "date_added": "2016-09-08T11:55:58+0200",
100 "favorite": 0,
101 "article__title": "[ROM][6.0.1][Layers][N5] TipsyOS official builds {UBER TCs}",
102 "article__url": "http://forum.xda-developers.com/google-nexus-5/development/rom-tipsyos-official-builds-uber-tcs-t3325989"
103 },
104 {
105 "archive": 0,
106 "date_added": "2016-09-08T11:55:58+0200",
107 "favorite": 0,
108 "article__title": "Top 15 Podcasts All Web Developers Should Follow - Envato Tuts+ Code Article",
109 "article__url": "http://code.tutsplus.com/articles/top-15-podcasts-all-web-developers-should-follow--net-14461"
110 },
111 {
112 "archive": 1,
113 "date_added": "2016-09-08T11:55:58+0200",
114 "favorite": 0,
115 "article__title": "University of Mississippi",
116 "article__url": "http://olemiss.edu"
117 },
118 {
119 "archive": 1,
120 "date_added": "2016-09-08T11:55:58+0200",
121 "favorite": 0,
122 "article__title": "FinnChristiansen.de Jetzt Dank Let’s Encrypt Per HTTPS Erreichbar",
123 "article__url": "https://www.finnchristiansen.de/2015/12/06/finnchristiansen-de-jetzt-dank-lets-encrypt-per-https-erreichbar/"
124 },
125 {
126 "archive": 1,
127 "date_added": "2016-09-08T11:55:58+0200",
128 "favorite": 0,
129 "article__title": "Le développeur et l'ingénierie logicielle",
130 "article__url": "http://wemucs.com/le-developpeur-et-lingenierie-logicielle/"
131 },
132 {
133 "archive": 1,
134 "date_added": "2016-09-08T11:55:58+0200",
135 "favorite": 0,
136 "article__title": "The Role of Methylation in Gene Expression",
137 "article__url": "http://www.nature.com/scitable/topicpage/the-role-of-methylation-in-gene-expression-1070"
138 },
139 {
140 "archive": 1,
141 "date_added": "2016-09-08T11:55:58+0200",
142 "favorite": 0,
143 "article__title": "E-Mail-Adresse kostenlos, FreeMail, De-Mail & Nachrichten",
144 "article__url": "http://web.de"
145 },
146 {
147 "archive": 1,
148 "date_added": "2016-09-08T11:55:58+0200",
149 "favorite": 0,
150 "article__title": "OpenSSH Server on Arch Linux | DominicM test",
151 "article__url": "http://dominicm.com/openssh-server-arch-linux/"
152 },
153 {
154 "archive": 1,
155 "date_added": "2016-09-08T11:55:58+0200",
156 "favorite": 0,
157 "article__title": "Site Moved | Site Help",
158 "article__url": "http://g1.com/help/sitemoved.asp"
159 },
160 {
161 "archive": 1,
162 "date_added": "2016-09-08T11:55:58+0200",
163 "favorite": 0,
164 "article__title": "#Maroc : le stylo anti-pédophiles EAGLE d’AMESYS est moins bien configuré que les faux-lowers Twitter du roi Mohammed VI",
165 "article__url": "https://reflets.info/maroc-le-stylo-anti-pedophiles-eagle-damesys-est-moins-bien-configure-que-les-faux-lowers-twitter-du-roi-mohammed-vi/"
166 },
167 {
168 "archive": 1,
169 "date_added": "2016-09-08T11:55:58+0200",
170 "favorite": 0,
171 "article__title": "Simple Cloud Infrastructure for Developers",
172 "article__url": "https://www.digitalocean.com/"
173 } 26 }
174 ], 27 ],
175 "recommendations": [] 28 "recommendations": []
diff --git a/tests/Wallabag/ImportBundle/fixtures/wallabag-v1.json b/tests/Wallabag/ImportBundle/fixtures/wallabag-v1.json
index f298469f..28270ec4 100644
--- a/tests/Wallabag/ImportBundle/fixtures/wallabag-v1.json
+++ b/tests/Wallabag/ImportBundle/fixtures/wallabag-v1.json
@@ -32,38 +32,5 @@
32 "content": "<span class=\"name\">README.md</span><p>wallabag is a self hostable application allowing you to not miss any content anymore. Click, save, read it when you can. It extracts content so that you can read it when you have time.</p>\n<p>More informations on our website: <a href=\"http://wallabag.org\">wallabag.org</a></p>\n<h2><a class=\"anchor\" href=\"https://github.com/wallabag/wallabag#license\"></a>License</h2>\n<p>Copyright © 2010-2014 Nicolas Lœuillet <a href=\"mailto:nicolas@loeuillet.org\">nicolas@loeuillet.org</a> This work is free. You can redistribute it and/or modify it under the terms of the Do What The Fuck You Want To Public License, Version 2, as published by Sam Hocevar. See the COPYING file for more details.</p>\n", 32 "content": "<span class=\"name\">README.md</span><p>wallabag is a self hostable application allowing you to not miss any content anymore. Click, save, read it when you can. It extracts content so that you can read it when you have time.</p>\n<p>More informations on our website: <a href=\"http://wallabag.org\">wallabag.org</a></p>\n<h2><a class=\"anchor\" href=\"https://github.com/wallabag/wallabag#license\"></a>License</h2>\n<p>Copyright © 2010-2014 Nicolas Lœuillet <a href=\"mailto:nicolas@loeuillet.org\">nicolas@loeuillet.org</a> This work is free. You can redistribute it and/or modify it under the terms of the Do What The Fuck You Want To Public License, Version 2, as published by Sam Hocevar. See the COPYING file for more details.</p>\n",
33 "user_id": "1", 33 "user_id": "1",
34 "tags":"" 34 "tags":""
35 },
36 {
37 "0": "3",
38 "1": "a self hostable application for saving web pages | wallabag",
39 "2": "https://www.wallabag.org/",
40 "3": "1",
41 "4": "0",
42 "5": "\n<div class=\"row\">\n<div class=\"col-lg-8 col-md-12 col-xs-12 col-sm-12\">\n<p>wallabag (formerly poche) is a <strong>self hostable application for saving web pages</strong>. Unlike other services, wallabag is free (as in freedom) and open source.</p>\n</div>\n\n</div>\n<div class=\"row\">\n<div class=\"col-lg-8 col-md-12 col-xs-12 col-sm-12\">\n<p>With this application you will not miss content anymore. <strong>Click, save, read it when you want</strong>. It saves the content you select so that you can read it when you have time.</p>\n</div>\n\n</div>\n<div class=\"row\">\n<div class=\"col-lg-6 col-md-12 col-xs-12 col-sm-12\">\n<h2>How it works</h2>\n<p>Thanks to the bookmarklet or <a title=\"Downloads\" href=\"http://www.wallabag.org/downloads/\">third-party applications</a>, you save an article in your wallabag to read it later. Then, when you open your wallabag, <strong>you can comfortably read your articles</strong>.</p>\n<h2>How to use wallabag</h2>\n<p>There are two ways to use wallabag: you can <a href=\"http://www.wallabag.org/frequently-asked-questions/#How_can_I_install_wallabag_and_what_are_the_requirements\">install it</a> on your web server or you can <a href=\"http://app.inthepoche.com\">create an account</a> at Framabag (we install and upgrade wallabag for you).</p>\n</div>\n\n</div>\n",
43 "6": "1",
44 "id": "3",
45 "title": "a self hostable application for saving web pages | wallabag",
46 "url": "https://www.wallabag.org/",
47 "is_read": "1",
48 "is_fav": "0",
49 "content": "\n<div class=\"row\">\n<div class=\"col-lg-8 col-md-12 col-xs-12 col-sm-12\">\n<p>wallabag (formerly poche) is a <strong>self hostable application for saving web pages</strong>. Unlike other services, wallabag is free (as in freedom) and open source.</p>\n</div>\n\n</div>\n<div class=\"row\">\n<div class=\"col-lg-8 col-md-12 col-xs-12 col-sm-12\">\n<p>With this application you will not miss content anymore. <strong>Click, save, read it when you want</strong>. It saves the content you select so that you can read it when you have time.</p>\n</div>\n\n</div>\n<div class=\"row\">\n<div class=\"col-lg-6 col-md-12 col-xs-12 col-sm-12\">\n<h2>How it works</h2>\n<p>Thanks to the bookmarklet or <a title=\"Downloads\" href=\"http://www.wallabag.org/downloads/\">third-party applications</a>, you save an article in your wallabag to read it later. Then, when you open your wallabag, <strong>you can comfortably read your articles</strong>.</p>\n<h2>How to use wallabag</h2>\n<p>There are two ways to use wallabag: you can <a href=\"http://www.wallabag.org/frequently-asked-questions/#How_can_I_install_wallabag_and_what_are_the_requirements\">install it</a> on your web server or you can <a href=\"http://app.inthepoche.com\">create an account</a> at Framabag (we install and upgrade wallabag for you).</p>\n</div>\n\n</div>\n",
50 "user_id": "1"
51 },
52 {
53 "0": "4",
54 "1": "Sans titre",
55 "2": "http:\/\/www.konradlischka.info\/2016\/01\/blog\/wie-ein-deutsches-start-up-mit-wagniskapital-die-marktluecke-fuer-lokalen-digitaljournalismus-schliessen-will\/",
56 "3": "0",
57 "4": "0",
58 "5": "[unable to retrieve full-text content]",
59 "6": "1",
60 "id": "4",
61 "title": "Sans titre",
62 "url": "http:\/\/www.konradlischka.info\/2016\/01\/blog\/wie-ein-deutsches-start-up-mit-wagniskapital-die-marktluecke-fuer-lokalen-digitaljournalismus-schliessen-will\/",
63 "is_read": "0",
64 "is_fav": "0",
65 "content": "[unable to retrieve full-text content]",
66 "user_id": "1",
67 "tags": ""
68 } 35 }
69] 36]
diff --git a/tests/Wallabag/ImportBundle/fixtures/wallabag-v2.json b/tests/Wallabag/ImportBundle/fixtures/wallabag-v2.json
index efa8faf2..0e30d95b 100644
--- a/tests/Wallabag/ImportBundle/fixtures/wallabag-v2.json
+++ b/tests/Wallabag/ImportBundle/fixtures/wallabag-v2.json
@@ -6,7 +6,7 @@
6 "is_archived": false, 6 "is_archived": false,
7 "created_at": "2016-09-08T11:55:58+0200", 7 "created_at": "2016-09-08T11:55:58+0200",
8 "updated_at": "2016-09-08T11:57:16+0200", 8 "updated_at": "2016-09-08T11:57:16+0200",
9 "is_starred": false, 9 "is_starred": true,
10 "content": "<div alt=\"li\">Édition <a href=\"https://blogs.mediapart.fr/edition/camedia-0\">CAMédia</a>\n<h3 class=\"title\"><a href=\"https://blogs.mediapart.fr/edition/camedia/article/180116/deux-nouvelles-editions-pour-debattre-dans-le-club-sur-la-laicite-et-sur-la-democratie\">Deux nouvelles éditions pour débattre dans le club sur la laïcité et sur la démocratie</a></h3>\n<p>18 janv. 2016 | Par </p>\n<p>CAMédia après un échange sur « l'éthique du débat » a lancé deux discussions , l'une sur le thème de la laïcité, l'autre ( encore en cours) sur celui de la démocratie. Nous sommes heureux de pouvoir signaler la création de deux nouvelles éditions participatives sur ces thèmes. Nous vous invitons à les lire et à participer à leurs débats.</p>\n</div><div alt=\"li\">\n<h3 class=\"title\"><a href=\"https://blogs.mediapart.fr/lucile-longre/blog/170116/de-limportance-de-rever-eloge-du-merveilleux\">De l'importance de rêver, éloge du merveilleux</a></h3>\n<p>17 janv. 2016 | Par </p>\n<p>Je parlerai ici des rêves comme moteur de vie, de ces rêves qui vous rattachent et vous font espérer à ce qu’il y a de plus humain dans l’homme, même au milieu de la plus noire des détresses.</p>\n</div><div alt=\"li\">\n<h3 class=\"title\"><a href=\"https://blogs.mediapart.fr/barbara-romagnan/blog/180116/fins-dune-toute-puissance\">Fin(s) d'une toute-puissance</a></h3>\n<p>18 janv. 2016 | Par </p>\n<p>En ce début d’année, je recommande la lecture du dernier ouvrage de Guillaume Duval, La France ne sera jamais plus une grande puissance ? Tant mieux !</p>\n</div><div alt=\"li\">\n<h3 class=\"title\"><a href=\"https://blogs.mediapart.fr/jean-pierre-thibaudat/blog/170116/l-allier-departement-de-destruction-massive-du-tissu-culturel\">L’Allier, département de destruction massive du tissu culturel</a></h3>\n<p>18 janv. 2016 | Par </p>\n<p>Les temps sont durs pour les petites structures, les associations culturelles qui, de bourgades en villages, travaillent au cœur des régions. Leurs subventions sont souvent revues à la baisse. Le département de l’Allier les a carrément supprimées. Pour favoriser « l’événementiel ».</p>\n</div><div alt=\"li\">Édition <a href=\"https://blogs.mediapart.fr/edition/les-invites-de-mediapart\">Les invités de Mediapart</a>\n<h3 class=\"title\"><a href=\"https://blogs.mediapart.fr/edition/les-invites-de-mediapart/article/180116/la-democratie-deja-attaquee-par-la-cooperation-reglementaire-transatlantiqu\">La démocratie déjà attaquée par la coopération réglementaire transatlantique</a></h3>\n<p>18 janv. 2016 | Par </p>\n<p>Lora Verheecke et David Lundy travaillent pour Corporate Europe Observatory, une ONG basée à Bruxelles qui enquête sur le pouvoir des lobbies des grandes entreprises sur la politique de l’Union européenne. Ils révèlent que depuis 25 ans le projet de « coopération réglementaire » mené par l’Union européenne et les États-Unis a été dominé par les grandes entreprises. ET que le TTIP cherche à entériner ce projet.</p>\n</div><div alt=\"li\">\n<h3 class=\"title\"><a href=\"https://blogs.mediapart.fr/jacqueline-derens/blog/180116/2016-une-annee-test-pour-jacob-zuma-et-son-gouvernement\">2016, une année test pour Jacob Zuma et son gouvernement</a></h3>\n<p>18 janv. 2016 | Par </p>\n<p>Les turbulences de l’an passé ont toutes les chances de continuer à troubler le climat politique et social de l’Afrique du Sud en 2016. La situation exige des changements profonds dans la conduite des affaires du pays. Jacob Zuma tout en admettant la nécessité de ces changements, est-il l’homme de la situation ? Son gouvernement répondra-t-il aux attentes des citoyens sud-africains ?</p>\n</div><div alt=\"li\">\n<h3 class=\"title\"><a href=\"https://blogs.mediapart.fr/marie-cosnay/blog/140116/un-mal-fou-janvier-2016\">Un mal fou (janvier 2016)</a></h3>\n<p>14 janv. 2016 | Par </p>\n<p>J’ai une fringale d’aventure, d’aventures à venir. J’ai la fringale de la fringale des aventures et soudain, rupture. Je n’y arrive plus, tout est bloqué, tout empêché. Faut dire que depuis un an environ, tout est devenu plus compliqué. Ecrire va de moins en moins de soi.</p>\n</div><div alt=\"li\">\n<h3 class=\"title\"><a href=\"https://blogs.mediapart.fr/jean-pierre-veran/blog/170116/redoublement-le-changement-bas-bruit\">Redoublement : le changement à bas bruit ?</a></h3>\n<p>17 janv. 2016 | Par </p>\n<p>S’il est une caractéristique de la forme scolaire française bien établie dans la culture des personnels, des élèves et des parents, c’est bien le redoublement, censé sanctionner des résultats insuffisants pour envisager le passage dans la classe supérieure. Or, en ce domaine, l’évolution est nette.</p>\n</div><div alt=\"li\">\n<h3 class=\"title\"><a href=\"https://blogs.mediapart.fr/michel-de-pracontal/blog/160116/samedi-sciences-196-des-chasseurs-de-mammouths-en-arctique-il-y-45-000-ans\">Samedi-sciences (196): des chasseurs de mammouths en Arctique il y a 45 000 ans</a></h3>\n<p>16 janv. 2016 | Par <a href=\"https://blogs.mediapart.fr/michel-de-pracontal\" class=\"journalist\">Michel de Pracontal</a></p>\n<p>Les restes d’un mammouth retrouvés en Arctique sibérien, datés de 45 000 ans, portent les traces de blessures infligées par des chasseurs humains. Les scientifiques pensaient jusqu’ici que notre espèce ne s’était pas aventurée dans cette région glaciale il y a plus de 30 000 ou 35 0000 ans. En réalité, des hommes ont réussi à survivre en Arctique au moins 10 000 ans plus tôt que l’on croyait.</p>\n</div><div alt=\"li\">\n<h3 class=\"title\"><a href=\"https://blogs.mediapart.fr/alain-zolty/blog/140116/de-la-democratie-du-citoyen-et-de-lethique\">De la démocratie, du citoyen et de l'éthique</a></h3>\n<p>14 janv. 2016 | Par </p>\n<p>Trois ouvrages sont parus au Seuil, qui font état de la nécessité d’intégrer le citoyen dans la gouvernance de la nation. Non pas à titre consultatif mais doté d’un pouvoir délibératif pour constituer une contre-force face aux clans politico-financiers qui dominent la vie publique.</p>\n</div>", 10 "content": "<div alt=\"li\">Édition <a href=\"https://blogs.mediapart.fr/edition/camedia-0\">CAMédia</a>\n<h3 class=\"title\"><a href=\"https://blogs.mediapart.fr/edition/camedia/article/180116/deux-nouvelles-editions-pour-debattre-dans-le-club-sur-la-laicite-et-sur-la-democratie\">Deux nouvelles éditions pour débattre dans le club sur la laïcité et sur la démocratie</a></h3>\n<p>18 janv. 2016 | Par </p>\n<p>CAMédia après un échange sur « l'éthique du débat » a lancé deux discussions , l'une sur le thème de la laïcité, l'autre ( encore en cours) sur celui de la démocratie. Nous sommes heureux de pouvoir signaler la création de deux nouvelles éditions participatives sur ces thèmes. Nous vous invitons à les lire et à participer à leurs débats.</p>\n</div><div alt=\"li\">\n<h3 class=\"title\"><a href=\"https://blogs.mediapart.fr/lucile-longre/blog/170116/de-limportance-de-rever-eloge-du-merveilleux\">De l'importance de rêver, éloge du merveilleux</a></h3>\n<p>17 janv. 2016 | Par </p>\n<p>Je parlerai ici des rêves comme moteur de vie, de ces rêves qui vous rattachent et vous font espérer à ce qu’il y a de plus humain dans l’homme, même au milieu de la plus noire des détresses.</p>\n</div><div alt=\"li\">\n<h3 class=\"title\"><a href=\"https://blogs.mediapart.fr/barbara-romagnan/blog/180116/fins-dune-toute-puissance\">Fin(s) d'une toute-puissance</a></h3>\n<p>18 janv. 2016 | Par </p>\n<p>En ce début d’année, je recommande la lecture du dernier ouvrage de Guillaume Duval, La France ne sera jamais plus une grande puissance ? Tant mieux !</p>\n</div><div alt=\"li\">\n<h3 class=\"title\"><a href=\"https://blogs.mediapart.fr/jean-pierre-thibaudat/blog/170116/l-allier-departement-de-destruction-massive-du-tissu-culturel\">L’Allier, département de destruction massive du tissu culturel</a></h3>\n<p>18 janv. 2016 | Par </p>\n<p>Les temps sont durs pour les petites structures, les associations culturelles qui, de bourgades en villages, travaillent au cœur des régions. Leurs subventions sont souvent revues à la baisse. Le département de l’Allier les a carrément supprimées. Pour favoriser « l’événementiel ».</p>\n</div><div alt=\"li\">Édition <a href=\"https://blogs.mediapart.fr/edition/les-invites-de-mediapart\">Les invités de Mediapart</a>\n<h3 class=\"title\"><a href=\"https://blogs.mediapart.fr/edition/les-invites-de-mediapart/article/180116/la-democratie-deja-attaquee-par-la-cooperation-reglementaire-transatlantiqu\">La démocratie déjà attaquée par la coopération réglementaire transatlantique</a></h3>\n<p>18 janv. 2016 | Par </p>\n<p>Lora Verheecke et David Lundy travaillent pour Corporate Europe Observatory, une ONG basée à Bruxelles qui enquête sur le pouvoir des lobbies des grandes entreprises sur la politique de l’Union européenne. Ils révèlent que depuis 25 ans le projet de « coopération réglementaire » mené par l’Union européenne et les États-Unis a été dominé par les grandes entreprises. ET que le TTIP cherche à entériner ce projet.</p>\n</div><div alt=\"li\">\n<h3 class=\"title\"><a href=\"https://blogs.mediapart.fr/jacqueline-derens/blog/180116/2016-une-annee-test-pour-jacob-zuma-et-son-gouvernement\">2016, une année test pour Jacob Zuma et son gouvernement</a></h3>\n<p>18 janv. 2016 | Par </p>\n<p>Les turbulences de l’an passé ont toutes les chances de continuer à troubler le climat politique et social de l’Afrique du Sud en 2016. La situation exige des changements profonds dans la conduite des affaires du pays. Jacob Zuma tout en admettant la nécessité de ces changements, est-il l’homme de la situation ? Son gouvernement répondra-t-il aux attentes des citoyens sud-africains ?</p>\n</div><div alt=\"li\">\n<h3 class=\"title\"><a href=\"https://blogs.mediapart.fr/marie-cosnay/blog/140116/un-mal-fou-janvier-2016\">Un mal fou (janvier 2016)</a></h3>\n<p>14 janv. 2016 | Par </p>\n<p>J’ai une fringale d’aventure, d’aventures à venir. J’ai la fringale de la fringale des aventures et soudain, rupture. Je n’y arrive plus, tout est bloqué, tout empêché. Faut dire que depuis un an environ, tout est devenu plus compliqué. Ecrire va de moins en moins de soi.</p>\n</div><div alt=\"li\">\n<h3 class=\"title\"><a href=\"https://blogs.mediapart.fr/jean-pierre-veran/blog/170116/redoublement-le-changement-bas-bruit\">Redoublement : le changement à bas bruit ?</a></h3>\n<p>17 janv. 2016 | Par </p>\n<p>S’il est une caractéristique de la forme scolaire française bien établie dans la culture des personnels, des élèves et des parents, c’est bien le redoublement, censé sanctionner des résultats insuffisants pour envisager le passage dans la classe supérieure. Or, en ce domaine, l’évolution est nette.</p>\n</div><div alt=\"li\">\n<h3 class=\"title\"><a href=\"https://blogs.mediapart.fr/michel-de-pracontal/blog/160116/samedi-sciences-196-des-chasseurs-de-mammouths-en-arctique-il-y-45-000-ans\">Samedi-sciences (196): des chasseurs de mammouths en Arctique il y a 45 000 ans</a></h3>\n<p>16 janv. 2016 | Par <a href=\"https://blogs.mediapart.fr/michel-de-pracontal\" class=\"journalist\">Michel de Pracontal</a></p>\n<p>Les restes d’un mammouth retrouvés en Arctique sibérien, datés de 45 000 ans, portent les traces de blessures infligées par des chasseurs humains. Les scientifiques pensaient jusqu’ici que notre espèce ne s’était pas aventurée dans cette région glaciale il y a plus de 30 000 ou 35 0000 ans. En réalité, des hommes ont réussi à survivre en Arctique au moins 10 000 ans plus tôt que l’on croyait.</p>\n</div><div alt=\"li\">\n<h3 class=\"title\"><a href=\"https://blogs.mediapart.fr/alain-zolty/blog/140116/de-la-democratie-du-citoyen-et-de-lethique\">De la démocratie, du citoyen et de l'éthique</a></h3>\n<p>14 janv. 2016 | Par </p>\n<p>Trois ouvrages sont parus au Seuil, qui font état de la nécessité d’intégrer le citoyen dans la gouvernance de la nation. Non pas à titre consultatif mais doté d’un pouvoir délibératif pour constituer une contre-force face aux clans politico-financiers qui dominent la vie publique.</p>\n</div>",
11 "mimetype": "text/html", 11 "mimetype": "text/html",
12 "language": "fr", 12 "language": "fr",
@@ -96,299 +96,5 @@
96 "domain_name": "www.nationaljournal.com", 96 "domain_name": "www.nationaljournal.com",
97 "preview_picture": "https://www.nationaljournal.com/media/media/2015/09/17/06Julian-Assange.jpg", 97 "preview_picture": "https://www.nationaljournal.com/media/media/2015/09/17/06Julian-Assange.jpg",
98 "tags": [] 98 "tags": []
99 },
100 {
101 "is_archived": 0,
102 "created_at": "2016-09-08T11:55:58+0200",
103 "updated_at": "2016-09-08T11:57:16+0200",
104 "is_starred": 0,
105 "id": 605,
106 "title": "What David Cameron did to the pig, his party is now doing to the country",
107 "url": "http://www.newstatesman.com/2015/09/what-david-cameron-did-pig-his-party-now-doing-country",
108 "content": "<p>Whatever you do, don’t think about David Cameron and a dead pig. I know, I know it’s like trying not to think of an elephant, but the fact is that the allegations that the Prime Minister may have put a 'private part of his anatomy\" into a dead pig's mouth as part of an initiation ritual for an elite drinking society at Oxford University are actually a very serious matter, and it’s all about corruption and the nature of elected power, and it would help if we could all just calm down for a second and stop giggling. Don’t think I don’t see you at the back there.</p>\n<p>You know, I feel for David Cameron today, I really do. Politicians’ private sex lives should never be used against them - unless their particular proclivities implicate them in gross hypocrisy or they have harmed another human being. If the rumours are true, it’s unlikely that the pig in question was hurt by the Prime Minister’s ministrations, given that it was already missing its limbs and torso.</p>\n<p>Sniggering aside, this is unlikely to hurt David Cameron in the long run. He’s not looking for re-election, and besides, everyone knows posh people get up to weird sex stuff. Weird sex stuff is as British as weak tea and racism. When I was at Oxford, it was an open secret that the posh kids had naughty parties, and, of course, so did the rest of us - the difference was the much lower budget, and the fact that the posh kids didn’t seem to enjoy it as much as we did. It all seemed to be more about getting on than getting off. You didn’t shag or not shag the pig’s face because that was what you were into, you did it because you had your eye on a safe seat in Dorset in 20 years’ time and you needed to make the right friends.</p>\n<p>There is a reason that David Cameron is allowed to hold office when everyone assumes he spent the 1980s taking drugs and getting up to weird things with his Eton mates, but Jeremy Corbyn is considered unelectable because he didn’t sing the national anthem last week. Cameron is part of a select group of people to whom different rules apply, and he knows it, and his friends know it, and the tabloids know it, and the whole cosy British political machine knows it. This is why Corbyn will spend the next five years being savaged for having a slightly rumpled tie by the same newspapers that reported on the dead pig allegations under the title \"the making of an extraordinary Prime Minister\".</p>\n<p>The thing that's really horrifying about what has already been dubbed the 'Hameron' scandal is that it demonstrates what entitlement of this kind actually means, and how embarrassing it all is. There are people out there who can spend their early twenties in close proximity to cocaine and popping their peckers in offal and not even consider for a second that there might be anyone better placed to run the country. These are people who know the rules don’t apply to them, who know they can do whatever they want and still end up in charge. </p>\n<p>I don't honestly care whether or not David Cameron shagged a dead pig. I've been to enough house parties in Bethnal Green that this sort of thing doesn't shock me. Come back to me when there’s video evidence of Cameron dressed in a leather gimp-suit tanned from the flayed skins of the former shadow cabinet, leaping into an entire Shropshire field full of pigs and screaming that his name is Legion. Then we’ll talk. There are a lot of things that David Cameron has definitely done that I do find disgusting, though. Taking away benefits from sick and disabled people, pricing poor kids out of higher education, and forcing millions of families to rely on food banks. That, to me, is shocking and grotesque. I don't give a damn about what he did or didn’t do to that pig, and whether there was mood-lighting involved. </p>\n<p>But the fact is that a lot of people do, and they're precisely the sort of people whose votes Cameron has relied on to shore up the power he clearly feels is his by right, might and various dodgy initiation rituals involving sex workers, smashing up pubs and knobbing bits of meat. Cameron clearly believes those people are there to be manipulated, and that’s the reason this story actually matters, beyond the immediate risk that a handful of pearl-clutchers in the Home Counties might splutter themselves to death. </p>\n<p>I was explaining all this to an American friend who asked, not unreasonably, why I'd spent all morning scrolling through Twitter and cackling like a toddler with a nerf gun. I did my best to describe seriously what had happened, and my friend, who does not follow British politics, asked me, 'so this guy, was he elected or appointed?'</p>\n<p>The answer, of course, is both. David Cameron is not just prime minister because a quarter of the country voted for him. That's not how power works in Britain, or anywhere, and it's moments like this that show it plainly, which is why we're all vaguely embarrassed today. Cameron's route to the office he clearly believes himself born to began much earlier, possibly even on a balmy Oxford night, just Dave, a dead pig and a select group of wide-eyed, gurning future business leaders, all whooping and cheering.</p>\n<p>It would surely have been a moment more important to Cameron's career than any number of photoshoots with builders in Totnes. Power and money are accessed through the back door, or, as it may be, the pig's mouth, and as with any kink, the eroticism isn't about the act, but about what the act symbolises. It's about humiliation, about control, about power play. What might the young swain have been thinking as he unzipped? What went through his head? If you ask me, I'll bet he was thinking: <em>Soon. Someday soon, I will do this to the whole bloody country.</em></p>\n",
109 "annotations": [],
110 "mimetype": "text/html",
111 "language": "en",
112 "reading_time": 5,
113 "domain_name": "www.newstatesman.com",
114 "preview_picture": "http://www.newstatesman.com/sites/default/files/styles/thumb_730/public/blogs_2015/09/gettyimages-464604046.jpg?itok=EaABrZda",
115 "tags": []
116 },
117 {
118 "is_archived": 1,
119 "created_at": "2016-09-08T11:55:58+0200",
120 "updated_at": "2016-09-08T11:57:16+0200",
121 "is_starred": 0,
122 "id": 604,
123 "title": "CLICK HERE to support 2016 CES Winner, Revolutionary Auto-Tracking Robot",
124 "url": "https://www.indiegogo.com/projects/2016-ces-winner-revolutionary-auto-tracking-robot",
125 "content": "<div class=\"visible-xs visible-sm\" readability=\"8\">\n<div class=\"row\" readability=\"12\">\n<section class=\"col-sm-8\" readability=\"8\"><p>Sign Up for Inspiration</p>\n<p>Private, secure, spam-free</p>\n</section><section class=\"col-sm-4 i-top-lined-mobile-only\"><p>Follow us</p>\n </section></div>\n<div class=\"row\" readability=\"9\">\n<section class=\"col-sm-8 i-top-lined\" readability=\"5\"><p>About Indiegogo</p>\n</section><section class=\"col-sm-4 i-top-lined\"><div class=\"row\">\n<p>Language</p>\n</div>\n</section></div>\n</div>\n<div class=\"visible-md visible-lg\" readability=\"13\">\n<section class=\"row\" readability=\"4\"><div class=\"col-md-3\">\n<p>Campaigning</p>\n </div>\n<div class=\"col-md-3\">\n<p>Contributing</p>\n </div>\n<div class=\"col-md-6\" readability=\"13\">\n<p>Sign Up for Inspiration</p>\n<p>Private, secure, spam-free</p>\n</div>\n</section><section class=\"row\"><div class=\"col-md-3\">\n<p>About Indiegogo</p>\n </div>\n<div class=\"col-md-4\">\n<p>Follow us</p>\n</div>\n<div class=\"col-md-2\">\n<p>Language</p>\n</div>\n</section></div>\n<section class=\"i-top-lined\" readability=\"1\">\n</section>",
126 "annotations": [],
127 "mimetype": "text/html",
128 "reading_time": 0,
129 "domain_name": "www.indiegogo.com",
130 "preview_picture": "https://c1.iggcdn.com/indiegogo-media-prod-cld/image/upload/c_fill,f_auto,h_630,w_1200/v1447395263/d6ckex9ynild6ica1xdk.jpg",
131 "tags": []
132 },
133 {
134 "is_archived": 0,
135 "created_at": "2016-09-08T11:55:58+0200",
136 "updated_at": "2016-09-08T11:57:16+0200",
137 "is_starred": 1,
138 "id": 603,
139 "title": "No title found",
140 "url": "http://carnetdevol.shost.ca/wordpress/aide-memoire-sur-les-commandes-associees-a-systemd/",
141 "content": "wallabag can't retrieve contents for this article. Please report this issue to us.",
142 "annotations": [],
143 "mimetype": "text/html",
144 "reading_time": 0,
145 "domain_name": "carnetdevol.shost.ca",
146 "tags": []
147 },
148 {
149 "is_archived": 1,
150 "created_at": "2016-09-08T11:55:58+0200",
151 "updated_at": "2016-09-08T11:57:16+0200",
152 "is_starred": 0,
153 "id": 602,
154 "title": "Présentation d'Arduino - Tuto Arduino - Le blog d'Eskimon",
155 "url": "http://eskimon.fr/73-arduino-101-presentation",
156 "content": "<div class=\"chapitre\" id=\"457282\">\n<p class=\"introduction\">Comment faire de l’électronique en utilisant un langage de programmation ? La réponse, c’est le projet Arduino qui l’apporte. Vous allez le voir, celui-ci a été conçu pour être accessible à tous par sa simplicité. Mais il peut également être d’usage professionnel, tant les possibilités d’applications sont nombreuses.</p>\n<div class=\"sommaire\"><strong class=\"tgros\">Sommaire</strong>\n<ul><li><a href=\"http://eskimon.fr/73-arduino-101-presentation#457704\">Qu’est-ce que c’est ?</a></li>\n<li><a href=\"http://eskimon.fr/73-arduino-101-presentation#769345\">Pourquoi choisir Arduino ?</a></li>\n<li><a href=\"http://eskimon.fr/73-arduino-101-presentation#458252\">Les cartes Arduino</a></li>\n<li><a href=\"http://eskimon.fr/73-arduino-101-presentation#629075\">Liste d’achat</a></li>\n</ul></div>\n<div class=\"sideSommaire blocwrapper\"><ins class=\"adsbygoogle c1\" data-ad-client=\"ca-pub-2080155902357792\" data-ad-slot=\"1103196807\"/></div>\n<div class=\"sousparties\">\n<div class=\"souspartie\" id=\"457704\">\n<h2>Qu’est-ce que c’est ?</h2>\n<div class=\"texte\">Une équipe de développeurs composée de <em>Massimo Banzi, David Cuartielles, Tom Igoe, Gianluca Martino, David Mellis et Nicholas Zambetti</em> a imaginé un projet répondant au doux nom de <strong>Arduino</strong> et mettant en œuvre une petite carte électronique programmable et un logiciel multiplateforme, qui puisse être accessible à tout un chacun dans le but de créer facilement des systèmes électroniques. Étant donné qu’il y a des débutants parmi nous, commençons par voir un peu le vocabulaire commun propre au domaine de l’électronique et de l’informatique.\n<h3>Une carte électronique</h3>\n<p>Une <strong>carte électronique</strong> est un support plan, flexible ou rigide, généralement composé d’<a href=\"http://fr.wikipedia.org/wiki/Poly%C3%A9poxyde\">epoxy</a> ou de fibre de verre. Elle possède des pistes électriques disposées sur une, deux ou plusieurs couches (en surface et/ou en interne) qui permettent la mise en relation électrique des composants électroniques. Chaque piste relie tel composant à tel autre, de façon à créer un système électronique qui fonctionne et qui réalise les opérations demandées.</p>\n<div class=\"centre\"><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/422585.png\"/><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/422584.png\"/><br/><em>Exemples de cartes électroniques</em></div>\n<p>Évidemment, tous les composants d’une carte électronique ne sont pas forcément reliés entre eux. Le câblage des composants suit un plan spécifique à chaque carte électronique, qui se nomme le <strong>schéma électronique</strong>.</p>\n<div class=\"centre\"><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/422580.png\"/><br/><em>Exemple de schéma électronique – carte Arduino Uno</em></div>\n<p>Enfin, avant de passer à la réalisation d’un carte électronique, il est nécessaire de transformer le schéma électronique en un <strong>schéma de câblage</strong>, appelé <strong>typon</strong>.</p>\n<div class=\"centre\"><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/422582.png\"/><br/><em>Exemple de typon – carte Arduino</em></div>\n<p class=\"question\">Une fois que l’on a une carte électronique, on fait quoi avec ?</p>\n<p>Eh bien une fois que la carte électronique est faite, nous n’avons plus qu’à la tester et l’utiliser ! Dans notre cas, avec Arduino, nous n’aurons pas à fabriquer la carte et encore moins à la concevoir. Elle existe, elle est déjà prête à l’emploi et nous n’avons plus qu’à l’utiliser. Et pour cela, vous allez devoir apprendre comment l’utiliser, ce que je vais vous montrer dans ce tutoriel.</p>\n<h3>Programmable ?</h3>\n<p>J’ai parlé de <strong>carte électronique programmable</strong> au début de ce chapitre. Mais savez-vous ce que c’est exactement ? Non pas vraiment. Alors voyons ensemble de quoi il s’agit. La carte Arduino est une carte électronique qui ne sait rien faire sans qu’on lui dise quoi faire. Pourquoi ? Eh bien c’est du au fait qu’elle est <strong>programmable</strong>. Cela signifie qu’elle a besoin d’un <strong>programme</strong> pour fonctionner.</p>\n<h4>Un programme</h4>\n<p>Un programme est une liste d’instructions qui est exécuté par un système. Par exemple votre navigateur internet, avec lequel vous lisez probablement ce cours, est un programme. On peut analogiquement faire référence à une liste de course :</p>\n<div class=\"gauche\"><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/422587.png\"/></div>\n<p>Chaque élément de cette liste est une <strong>instruction</strong> qui vous dis : « Va chercher le lait » ou « Va chercher le pain », etc. Dans un programme le fonctionnement est similaire :</p>\n<ul><li>Attendre que l’utilisateur rentre un site internet à consulter</li>\n<li>Rechercher sur internet la page demandée</li>\n<li>Afficher le résultat</li>\n</ul><p>Tel pourrait être le fonctionnement de votre navigateur internet. Il va attendre que vous lui demandiez quelque chose pour aller le chercher et ensuite vous le montrer. Eh bien, tout aussi simplement que ces deux cas, une carte électronique programmable suit une liste d’instructions pour effectuer les opérations demandées par le programme.</p>\n<p class=\"question\">Et on les trouves où ces programmes ? Comment on fait pour le mettre dans la carte ? o_O</p>\n<p>Des programmes, on peut en trouver de partout. Mais restons concentré sur Arduino. Le programme que nous allons mettre dans la carte Arduino, c’est nous qui allons le réaliser. Oui, vous avez bien lu. Nous allons programmer cette carte Arduino. Bien sûr, ce ne sera pas aussi simple qu’une liste de course, mais rassurez-vous cependant car nous allons réussir quand même ! Je vous montrerais comment y parvenir, puisque avant tout c’est un des objectifs de ce tutoriel. Voici un exemple de programme : <img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/422588.png\"/> Vous le voyez comme moi, il s’agit de plusieurs lignes de texte, chacune étant une instruction. Ce langage ressemble à un véritable baragouin et ne semble vouloir <em>à priori</em> rien dire du tout… Et pourtant, c’est ce que nous saurons faire dans quelques temps ! Car nous apprendrons le <strong>langage informatique</strong> utilisé pour programmer la carte Arduino. Je ne m’attarde pas sur les détails, nous aurons amplement le temps de revenir sur le sujet plus tard. Pour répondre à la deuxième question, nous allons avoir besoin d’un logiciel…</p>\n<h3>Et un logiciel ?</h3>\n<p>Bon, je ne vais pas vous faire le détail de ce qu’est un logiciel, vous savez sans aucun doute de quoi il s’agit. Ce n’est autre qu’un programme informatique exécuté sur un ordinateur. Oui, pour programmer la carte Arduino, nous allons utiliser un programme ! En fait, il va s’agir d’un <strong>compilateur</strong>. Alors qu’est-ce que c’est exactement ?</p>\n<h4>Un compilateur</h4>\n<p>En informatique, ce terme désigne un logiciel qui est capable de traduire un langage informatique, ou plutôt un programme utilisant un langage informatique, vers un langage plus approprié afin que la machine qui va le lire puisse le comprendre. C’est un peu comme si le patron anglais d’une firme Chinoise donnait des instructions en anglais à un de ses ouvriers chinois. L’ouvrier ne pourrait comprendre ce qu’il doit faire. Pour cela, il a besoin que l’on traduise ce que lui dit son patron. C’est le rôle du <strong>traducteur</strong>. Le compilateur va donc traduire les instructions du programme précédent, écrites en langage texte, vers un langage dit « machine ». Ce langage utilise uniquement des 0 et des 1. Nous verrons plus tard pourquoi. Cela pourrait être imagé de la façon suivante :</p>\n<div class=\"centre\"><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/422590.png\"/></div>\n<p>Donc, pour traduire le langage texte vers le langage machine (avec des 0 et des 1), nous aurons besoin de ce fameux compilateur. Et pas n’importe lequel, il faut celui qui soit capable de traduire le langage texte Arduino vers le langage machine Arduino. Et oui, sinon rien ne va fonctionner. Si vous mettez un traducteur Français vers Allemand entre notre patron anglais et son ouvrier chinois, ça ne fonctionnera pas mieux que s’ils discutaient directement. Vous comprenez ?</p>\n<p class=\"question\">Et pourquoi on doit utiliser un traducteur, on peut pas simplement apprendre le langage machine directement ?</p>\n<p>Comment dire… non ! Non parce que le langage machine est quasiment impossible à utiliser tel quel. Par exemple, comme il est composé de 0 et de 1, si je vous montre ça : « 0001011100111010101000111 », vous serez incapable, tout comme moi, de dire ce que cela signifie ! Et même si je vous dis que la suite « 01000001 » correspond à la lettre « A », je vous donne bien du courage pour coder rien qu’une phrase ! 😛 Bref, oubliez cette idée. C’est quand même plus facile d’utiliser des mots anglais (car oui nous allons être obligé de faire un peu d’anglais pour programmer, mais rien de bien compliqué rassure-vous) que des suites de 0 et de 1. Vous ne croyez pas ?</p>\n<h4>Envoyer le programme dans la carte</h4>\n<p>Là, je ne vais pas vous dire grand chose car c’est l’environnement de développement qui va gérer tout ça. Nous n’aurons qu’à apprendre comment utiliser ce dernier et il se débrouillera tout seul pour envoyer le programme dans la carte. Nah ! Nous n’aurons donc qu’à créer le programme sans nous soucier du reste.</p>\n</div>\n</div>\n<div class=\"souspartie\" id=\"769345\">\n<h2>Pourquoi choisir Arduino ?</h2>\n<div class=\"texte\">\n<h3>Que va-t-on faire avec ?</h3>\n<p>Avec Arduino, nous allons commencer par apprendre à programmer puis à utiliser des composants électroniques. Au final, nous saurons créer des systèmes électroniques plus ou moins complexes. Mais ce n’est pas tout…</p>\n<h4>D’abord, Arduino c’est…</h4>\n<p>… une carte électronique programmable et un logiciel gratuit :</p>\n<div class=\"centre\"><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/307927.png\"/></div>\n<h4>Mais aussi</h4>\n<p>– Un prix dérisoire étant donné l’étendue des applications possibles. On comptera 20 euros pour la carte que l’on va utiliser dans le cours. Le logiciel est fournit gratuitement ! – Une compatibilité sous toutes les plateformes, à savoir : Windows, Linux et Mac OS. – Une communauté ultra développée ! Des milliers de forums d’entre-aide, de présentations de projets, de propositions de programmes et de bibliothèques, … – Un site en anglais <a href=\"http://www.arduino.cc/\">arduino.cc</a> et un autre en français <a href=\"http://www.arduino.cc/\">arduino.cc</a> où vous trouverez tout de la référence Arduino, le matériel, des exemples d’utilisations, de l’aide pour débuter, des explications sur le logiciel et le matériel, etc. – Une liberté quasi absolue. Elle constitue en elle même deux choses :</p>\n<ul><li>Le logiciel : gratuit et open source, développé en Java, dont la simplicité d’utilisation relève du savoir cliquer sur la souris</li>\n<li>Le matériel : cartes électroniques dont les schémas sont en libre circulation sur internet</li>\n</ul><p class=\"attention\">Cette liberté a une condition : le nom « Arduino » ne doit être employé que pour les cartes « officielles ». En somme, vous ne pouvez pas fabriquer votre propre carte sur le modèle Arduino et lui assigner le nom « Arduino ».</p>\n<h4>Et enfin, les applications possibles</h4>\n<p>Voici une liste non exhaustive des applications possible réalisées grâce à Arduino :</p>\n<ul><li>contrôler des appareils domestiques</li>\n<li>donner une « intelligence » à un robot</li>\n<li>réaliser des jeux de lumières</li>\n<li>permettre à un ordinateur de communiquer avec une carte électronique et différents capteurs</li>\n<li>télécommander un appareil mobile (modélisme)</li>\n<li>etc.</li>\n</ul><p>Il y a tellement d’autres infinités d’utilisations, vous pouvez simplement chercher sur votre moteur de recherche préféré ou sur Youtube le mot « Arduino » pour découvrir les milliers de projets réalisés avec !</p>\n<h4>Arduino dans ce tutoriel</h4>\n<p>Je vais quand même rappeler les principaux objectifs de ce cours. Nous allons avant tout découvrir Arduino dans son ensemble et apprendre à l’utiliser. Dans un premier temps, il s’agira de vous présenter ce qu’est Arduino, comment cela fonctionne globalement, pour ensuite entrer un peu plus dans le détail. Nous allons alors apprendre à utiliser le langage Arduino pour pouvoir créer des programmes très simple pour débuter. Nous enchainerons ensuite avec les différentes fonctionnalités de la carte et ferons de petits TP qui vous permettront d’assimiler chaque notion abordée. Dès lors que vous serez plutôt à l’aise avec toutes les bases, nous nous rapprocherons de l’utilisation de composants électroniques plus ou moins complexes et finirons par un plus « gros » TP alliant la programmation et l’électronique. De quoi vous mettre de l’eau à la bouche ! 😛</p>\n<h3>Arduino à l’école ?</h3>\n<p>Pédagogiquement, Arduino a aussi pas mal d’atout. En effet, ses créateurs ont d’abord pensé ce projet pour qu’il soit facile d’accès. Il permet ainsi une très bonne approche de nombreux domaines et ainsi d’apprendre plein de choses assez simplement.</p>\n<h4>Des exemples</h4>\n<p>Voici quelques exemples d’utilisation possible :</p>\n<ul><li>Simuler le fonctionnement des portes logiques</li>\n<li>Permettre l’utilisation de différents capteurs</li>\n<li>Mettre en œuvre et faciliter la compréhension d’un réseau informatique</li>\n<li>Se servir d’Arduino pour créer des maquettes animées montrant le fonctionnement des collisions entres les plaques de la croute terrestre, par exemple <img src=\"http://eskimon.fr/wp-includes/images/smilies/mrgreen.png\" alt=\":mrgreen:\" class=\"wp-smiley c2\"/></li>\n<li>Donner un exemple concret d’utilisation des matrices avec un clavier alphanumérique 16 touches ou plus</li>\n<li>Être la base pour des élèves ayant un TPE à faire pour le BAC</li>\n<li>…</li>\n</ul><p>De plus, énormément de ressources et tutoriels (mais souvent en anglais) se trouvent sur internet, ce qui offre un autonomie particulière à l’apprenant.</p>\n<h4>Des outils existant !</h4>\n<p>Enfin, pour terminer de vous convaincre d’utiliser Arduino pour découvrir le monde merveilleux de l’embarqué, il existe différents outils qui puissent être utilisé avec Arduino. Je vais en citer deux qui me semble être les principaux : <a href=\"http://blog.ardublock.com/\">Ardublock</a> est un outil qui se greffe au logiciel Arduino et qui permet de programmer avec des blocs. Chaque bloc est une instruction. On peut aisément faire des programmes avec cet outil et mêmes des plutôt complexes. Cela permet par exemple de se concentrer sur ce que l’on doit faire avec Arduino et non se concentrer sur Arduino pour ensuite ce que l’on doit comprendre avec. Citons entre autre la simulation de porte logique : plutôt créer des programmes rapidement sans connaitre le langage pour comprendre plus facilement comment fonctionne une porte logique. Et ce n’est qu’un exemple. Car cela permet aussi de permettre à de jeunes enfants de commencer à programmer sans de trop grandes complications.</p>\n<div class=\"centre\"><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/422596.png\"/><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/422595.png\"/><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/422597.png\"/><br/><em>Exemple de programmes réalisés avec Ardublock</em></div>\n<p><a href=\"http://processing.org/\">Processing</a> est une autre plateforme en lien avec Arduino. Là il n’y a pas de matériel, uniquement un logiciel. Il permet entre autre de créer des interfaces graphiques avec un langage de programmation très similaire à celui d’Arduino. Par contre, cela demande un niveau un peu plus élevé pour pouvoir l’utiliser, même si cela reste simple dans l’ensemble.</p>\n<div class=\"centre\"><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/422599.png\"/><br/><em>Voilà un exemple de ce que j’avais réalisé avec Processing pour faire communiquer mon ordinateur avec ma carte Arduino</em></div>\n<p>J’espère avoir été assez convaincant afin que vous franchissiez le pas et ayez du plaisir à apprendre ! <img src=\"http://eskimon.fr/wp-includes/images/smilies/simple-smile.png\" alt=\":)\" class=\"wp-smiley c2\"/></p>\n</div>\n</div>\n<div class=\"souspartie\" id=\"458252\">\n<h2>Les cartes Arduino</h2>\n<div class=\"texte\">Le matériel que j’ai choisi d’utiliser tout au long de ce cours n’a pas un prix excessif et, je l’ai dit, tourne aux alentours de 25 € TTC. Il existe plusieurs magasins en lignes et en boutiques qui vendent des cartes Arduino. Je vais vous en donner quelques-uns, mais avant, il va falloir différencier certaines choses.\n<h4>Les fabricants</h4>\n<p>Le projet Arduino est libre et les schémas des cartes circulent librement sur internet. D’où la mise en garde que je vais faire : il se peut qu’un illustre inconnu fabrique lui même ses cartes Arduino. Cela n’a rien de mal en soi, s’il veut les commercialiser, il peut. Mais s’il est malhonnête, il peut vous vendre un produit défectueux. Bien sûr, tout le monde ne cherchera pas à vous arnaquer. Mais la prudence est de rigueur. Faites donc attention où vous achetez vos cartes.</p>\n<h4>Les types de cartes</h4>\n<div class=\"floatDroite\"><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/422602.gif\"/></div>\n<p>Il y a trois types de cartes :</p>\n<ul><li>Lesdites « officielles » qui sont fabriquées en Italie par le fabricant officiel : <em>Smart Projects</em></li>\n<li>Lesdits « compatibles » qui ne sont pas fabriqués par <em>Smart Projects</em>, mais qui sont totalement compatibles avec les Arduino officielles.</li>\n<li>Les « autres » fabriquées par diverse entreprise et commercialisées sous un nom différent (Freeduino, Seeduino, Femtoduino, …).</li>\n</ul><h4>Les différentes cartes</h4>\n<p>Des cartes Arduino il en existe beaucoup ! Voyons celles qui nous intéressent… <strong>La carte <em>Uno</em> et <em>Duemilanove</em></strong> Nous choisirons d’utiliser la carte portant le nom de « Uno » ou « Duemilanove ». Ces deux versions sont presque identiques.</p>\n<div class=\"centre\"><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/422601.png\"/><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/422600.gif\"/><br/><em>Carte Arduino « Duemilavove » et « Uno » avec laquelle nous allons travailler</em></div>\n<p><strong>La carte <em>Mega</em></strong> La carte Arduino Mega est une autre carte qui offre toutes les fonctionnalités de la carte précédente, mais avec des fonctionnalités supplémentaires. On retrouve notamment un nombre d’entrées et de sorties plus important ainsi que plusieurs liaisons séries. Bien sûr, le prix est plus élevé : &gt; 40 € !</p>\n<div class=\"centre\"><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/422586.png\"/><br/><em>Carte Arduino « Mega »</em></div>\n<p><strong>Les autres cartes</strong> Il existe encore beaucoup d’autres cartes, je vous laisse vous débrouiller pour trouver celle qui conviendra à vos projets. Cela dit, je vous conseil dans un premier temps d’utiliser la carte Arduino Uno ou Duemilanove d’une part car elle vous sera largement suffisante pour débuter et d’autre part car c’est avec celle-ci que nous présentons le cours.</p>\n<h4>Où acheter ?</h4>\n<p>Il existe sur le net une multitude de magasins qui proposent des cartes Arduino. Pour consulter la liste de ces magasins, rien de plus simple, il suffit de vous rendre sur le forum dédié :</p>\n<div class=\"centre\"><a href=\"http://fr.openclassrooms.com/forum/sujet/les-meilleures-boutiques-d-electronique-90967\"><strong>Les meilleurs boutiques d’électronique</strong></a> Cliquez-ici</div>\n<p class=\"question\">J’ai vu des cartes officielles « édition SMD/CMS ». Ca à l’air bien aussi, c’est quoi la différence ? Je peux m’en servir ?</p>\n<p>Il n’y a pas de différence ! enfin presque… « SMD » signifie <strong>Surface Mount Device</strong>, en français on appelle ça des « CMS » pour <strong>Composants Montés en Surface</strong>. Ces composants sont soudés directement sur le cuivre de la carte, il ne la traverse pas comme les autres. Pour les cartes Arduino, on retrouve le composant principal en édition SMD dans ces cartes. La carte est donc la même, aucune différence pour le tuto. Les composants sont les mêmes, seule l’allure « physique » est différente. Par exemple, ci-dessus la « Mega » est en SMD et la Uno est « classique ».</p>\n</div>\n</div>\n<div class=\"souspartie\" id=\"629075\">\n<h2>Liste d’achat</h2>\n<div class=\"texte\">Tout au long du cours, nous allons utiliser du matériel en supplément de la carte. Rassurez-vous le prix est bien moindre. Je vous donne cette liste, cela vous évitera d’acheter en plusieurs fois. Vous allez devoir me croire sur parole sur leur intérêt. Nous découvrirons comment chaque composant fonctionne et comment les utiliser tout au long du tutoriel. <img src=\"http://eskimon.fr/wp-includes/images/smilies/simple-smile.png\" alt=\":)\" class=\"wp-smiley c2\"/><p class=\"attention\">Attention, cette liste ne contient que les composants en quantités minimales strictes. Libre à vous de prendre plus de LED et de résistances par exemple (au cas où vous en perdriez ou détruisiez…). Pour ce qui est des prix, j’ai regardé sur différents sites grands publics (donc pas Farnell par exemple), ils peuvent donc paraître plus élevé que la normale dans la mesure où ces sites amortissent moins sur des ventes à des clients fidèles qui prennent tout en grande quantité…</p>\n<p>Avant que j’oublie, quatres éléments n’apparaitront pas dans la liste et sont indispensables :</p>\n<table><tbody><tr><th>Une Arduino Uno ou Duemilanove</th>\n<th>Un câble USB A mâle/B mâle</th>\n</tr><tr><td><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/369652.gif\"/></td>\n<td><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/422603.png\"/></td>\n</tr></tbody></table><table><tbody><tr><th>Une BreadBoard (plaque d’essai)</th>\n<th>Un lot de fils pour brancher le tout !</th>\n</tr><tr><td><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/369653.jpg\"/></td>\n<td><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/369661.png\"/></td>\n</tr></tbody></table><h3>Liste Globale</h3>\n<p>Voici donc la liste du matériel nécessaire pour suivre le cours. Libre à vous de tout acheter ou non.</p>\n<div class=\"erreur\">Liste incomplète, le tutoriel n’est pas terminé ! Mais elle suffit pour suivre les chapitres en ligne.</div>\n<table><tbody><tr><th>Désignation</th>\n<th>Quantité</th>\n<th>Photo</th>\n<th>Description</th>\n</tr><tr><td>LED rouge</td>\n<td>7</td>\n<td rowspan=\"3\"><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/369662.png\"/></td>\n<td rowspan=\"3\">Ce composant est une sorte de lampe un peu spécial. Nous nous en servirons principalement pour faire de la signalisation.</td>\n</tr><tr><td>LED verte</td>\n<td>3</td>\n</tr><tr><td>LED jaune (ou orange)</td>\n<td>2</td>\n</tr><tr><td>Résistance (entre 220 et 470 Ohm)</td>\n<td>10</td>\n<td rowspan=\"3\"><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/369663.png\"/></td>\n<td rowspan=\"3\">La résistance est un composant de base qui s’oppose au passage du courant. On s’en sert pour limiter des courants maximums mais aussi pour d’autres choses.</td>\n</tr><tr><td>Résistance (entre 2.2 et 4.7 kOhm)</td>\n<td>2</td>\n</tr><tr><td>Résistance (10 kOhm)</td>\n<td>2</td>\n</tr><tr><td>Bouton Poussoir</td>\n<td>2</td>\n<td><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/369665.jpg\"/></td>\n<td>Un bouton poussoir sert à faire passer le courant lorsqu’on appuie dessus ou au contraire garder le circuit « éteint » lorsqu’il est relâché.</td>\n</tr><tr><td>Transistor (2N2222 ou BC547)</td>\n<td>2</td>\n<td><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/369664.png\"/></td>\n<td>Le transistor sert à plein de chose. Il peut être utilisé pour faire de l’amplification (de courant ou de tension) mais aussi comme un interrupteur commandé électriquement.</td>\n</tr><tr><td>Afficheur 7 segments (anode commune)</td>\n<td>2</td>\n<td><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/345467.png\"/></td>\n<td>Un afficheur 7 segments est un ensemble de LEDs (cf. ci-dessus) disposées géométriquement pour afficher des chiffres.</td>\n</tr><tr><td>Décodeur BCD (CD4543BE)</td>\n<td>1</td>\n<td><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/369667.png\"/></td>\n<td>Le décodeur BCD (Binaire Codé Décimal) permet piloter des afficheurs 7 segments en limitant le nombre de fils de données (4 au lieu de 7).</td>\n</tr><tr><td>Condensateur (10nF/5V ou plus)</td>\n<td>2</td>\n<td><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/369673.jpg\"/></td>\n<td>Le condensateur est un composant de base. Il sert à plein de chose. On peut se le représenter comme un petit réservoir à électricité.</td>\n</tr><tr><td>Condensateur (1000µF 15V ou plus</td>\n<td>1</td>\n<td><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/370226.png\"/></td>\n<td>Celui-ci est un plus gros réservoir que le précédent</td>\n</tr><tr><td>Potentiomètre linéaire (10 kOhm)</td>\n<td>1</td>\n<td><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/369668.png\"/></td>\n<td>Le potentiomètre est une résistance que l’on peut faire varier manuellement.</td>\n</tr><tr><td>LED RVB</td>\n<td>1</td>\n<td><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/369672.jpg\"/></td>\n<td>Une LED RVB (Rouge Vert Bleu) est une LED permettant de mélanger les couleurs de bases pour en créer d’autres.</td>\n</tr><tr><td>Écran LCD alphanumérique</td>\n<td>1</td>\n<td><img alt=\"\" src=\"http://eskimon.fr/wp-content/uploads/tuto/385800.jpg\"/></td>\n<td>L’écran LCD alphanumérique permet d’afficher des caractères tels que les chiffres et les lettres. Il va apporter de l’interactivité à vos projets les plus fous !</td>\n</tr></tbody></table><h3>Les revendeurs</h3>\n<p>Je vous ai déjà donné le lien, vous pourrez trouver ces composants chez les revendeurs listés dans ce sujet du forum :</p>\n<div class=\"centre\"><a href=\"http://fr.openclassrooms.com/forum/sujet/les-meilleures-boutiques-d-electronique-90967\"><strong>Les meilleurs boutiques d’électronique</strong></a> Cliquez-ici</div>\n<h3>Les kits</h3>\n<p>Enfin, il existe des kits tout prêts chez certains revendeurs. Nous n’en conseillerons aucun pour plusieurs raisons. Tout d’abord, pour ne pas faire trop de publicité et rester conforme avec la charte du site. Ensuite, car il est difficile de trouver un kit « complet ». Ils ont tous des avantages et des inconvénients mais aucun (au moment de la publication de ces lignes) ne propose absolument tous les composants que nous allons utiliser. Nous ne voulons donc pas que vous reveniez vous plaindre sur les forums car nous vous aurions fait dépenser votre argent inutilement !</p>\n<div class=\"erreur\">Cela étant dit, merci de <strong>ne pas nous spammer de MP</strong> pour que l’on donne notre avis sur tel ou tel kit ! Usez des forums pour cela, il y a toujours quelqu’un qui sera là pour vous aider. Et puis nous n’avons pas les moyens de tous les acheter et tester leur qualité !</div>\n</div>\n</div>\n</div>\n<div class=\"conclusion\"/>\n</div>\n\n\n",
157 "annotations": [],
158 "mimetype": "text/html",
159 "language": "fr-FR",
160 "reading_time": 17,
161 "domain_name": "eskimon.fr",
162 "preview_picture": "http://eskimon.fr/wp-content/uploads/tuto/385800.jpg",
163 "tags": []
164 },
165 {
166 "is_archived": 1,
167 "created_at": "2016-09-08T11:55:58+0200",
168 "updated_at": "2016-09-08T11:57:16+0200",
169 "is_starred": 0,
170 "id": 543,
171 "title": "Lenovo ThinkPad X1 Carbon Ultrabook Review",
172 "url": "http://www.notebookcheck.net/Lenovo-ThinkPad-X1-Carbon-Ultrabook-Review.138033.0.html",
173 "content": "<p class=\"align-justify\">The Lenovo X1 Carbon 3rd Gen is <strong>a beautiful machine</strong>. Much like the <a href=\"http://www.notebookcheck.net/Dell-XPS-13-9343-Touchscreen-Ultrabook-Review.135817.0.html\" target=\"_self\" class=\"internal-link\">Dell XPS 13</a> took the initiative to cram a 13-inch screen into an 11-inch form factor, the X1 Carbon sports dimensions that are more comparable to a typical 13-inch machine—and that includes its <strong>weight and thinness</strong>, both of which are <strong>indisputably manageable</strong>. It’s also <strong>practically designed</strong>; the <strong>matte black surfaces</strong> that comprise the majority of the case are minimalist and attractive, but they’re simultaneously haptically comfortable, with an <strong>unmistakably cool metal feel</strong> and a comfortable fit for use on both lap and desk. The case also feels fairly solid, though the incidence of flex and relative lack of torsion resistance in some regards gave us pause.</p>\n<p class=\"align-justify\">Perhaps more exciting, however, is <strong>what has improved over the <a href=\"http://www.notebookcheck.net/Review-Update-Lenovo-ThinkPad-X1-Carbon-Touch-20A7-002DGE-Ultrabook.113926.0.html\" target=\"_self\" class=\"internal-link\">X1 Carbon 2nd Gen</a></strong>. Criticism of the <a href=\"http://www.notebookcheck.net/Review-Update-Lenovo-ThinkPad-X1-Carbon-Touch-20A7-002DGE-Ultrabook.113926.0.html\" target=\"_self\" class=\"internal-link\">2nd Gen</a>’s radical (and arguably illogical) keyboard design and polarizing full-depression clickpad scared away many prospective buyers—as such fearlessly progressive and experimental design decisions generally don’t fit well with the business market, where practicality rules supreme. The Gen 3 wholeheartedly acknowledges these complaints and implements a complete reversal of those decisions. As a result, <strong>the keyboard</strong>—immediately familiar and accessible—<strong>is one of the absolute best we have ever used on an Ultrabook</strong>. Meanwhile, the <strong>three classic top-mounted physical buttons for use with the Trackpoint have returned</strong>, and the <strong>touchpad</strong> itself <strong>ditches the controversial full-click design</strong> in favor of a far more comfortable (and, in our judgment, reliable) clickpad approach. The end result is that the X1 Carbon Gen 3 <strong>features some of the best input devices we’ve tested on an Ultrabook</strong>.</p>\n<p class=\"align-justify\">What about performance? <strong>CPU performance differences between the <a href=\"http://www.notebookcheck.net/Review-Update-Lenovo-ThinkPad-X1-Carbon-Touch-20A7-002DGE-Ultrabook.113926.0.html\" target=\"_self\" class=\"internal-link\">2nd Gen</a> and 3rd Gen</strong> X1 Carbon models <strong>were essentially nil</strong> in our testing—for all intents and purposes, the machines are identical in this regard. However in GPU testing, we witnessed a notable speed boost—in some cases up to 19% better. As compared with other modern notebooks of its class, apart from some multi-core synthetic performance hiccups, <strong>the X1 Carbon 3rd Gen holds its own, both in terms of CPU/GPU and general system performance</strong>. The only final niggle here is the Samsung PM851 SSD, whose write speeds are conspicuously capped at around 250 MB/s.</p>\n<p class=\"align-justify\">While the leap to a Broadwell chipset and slightly larger battery seemed sure to promise improved <strong>battery runtimes</strong>, we were surprised to find throughout our testing that <strong>there wasn’t much of a difference at all</strong>. Our classic Wi-Fi Surfing Test produced a result <strong>only slightly better than that of the <a href=\"http://www.notebookcheck.net/Review-Update-Lenovo-ThinkPad-X1-Carbon-Touch-20A7-002DGE-Ultrabook.113926.0.html\" target=\"_self\" class=\"internal-link\">2nd Gen</a></strong>, and the revised Wi-Fi test we just recently implemented—which is more broad and aggressive and arguably closer to actual real-world usage patterns—recorded under five hours before the machine shut down. That’s hardly an impressive number on one hand given the 50 Wh battery and supposed enhanced efficiency, though it’s still likely to get most users through a typical trip unplugged, especially if more restrictive power savings options are employed. If longer battery life is a priority, we’d suggest taking a look instead at the <a href=\"http://www.notebookcheck.net/Dell-XPS-13-9343-Touchscreen-Ultrabook-Review.135817.0.html\" target=\"_self\" class=\"internal-link\">Dell XPS 13-9343</a> or the <a href=\"http://www.notebookcheck.net/Apple-MacBook-Air-13-MD761D-B-2014-06-Notebook-Review-Update.119805.0.html\" target=\"_self\" class=\"internal-link\">MacBook Air 13</a>.</p>\n<p class=\"align-justify\">Rounding out the list of considerations is an <strong>underwhelming screen</strong>, at least in terms of brightness, contrast, and color saturation—though we do most certainly appreciate the <strong>anti-glare display filter</strong> for both its diffusion of reflections and relative ease of cleaning. The X1 Carbon Gen 3 is also <strong>invariably cool and quiet</strong>, clearly favoring comfort over top-end performance (as we discovered during our stress testing of the device).</p>\n<p class=\"align-justify\">Summing up, the X1 Carbon Gen 3 is <strong>indisputably superior to its predecessor</strong>. Although some of these improvements come in the form of better GPU performance, cooler temperatures, and lower average system noise levels, the vast majority of them center on the thankful retreat from the experimental (and finicky) input devices of the Gen 2 design and back to sanity. This isn’t just a return to form, either; to reiterate, by our judgment, they are some of the best input devices on any Ultrabook we’ve tested to date. But in spite of this self-improvement, <strong>how does the X1 Carbon compare with its modern competitors</strong>? In truth, though it’s a compelling option, <strong>it’s lost some ground since our last encounter</strong>. While notebooks such as the <a href=\"http://www.notebookcheck.net/Apple-MacBook-Air-13-MD761D-B-2014-06-Notebook-Review-Update.119805.0.html\" target=\"_self\" class=\"internal-link\">MacBook Air 13</a> and (especially) the <a href=\"http://www.notebookcheck.net/Dell-XPS-13-9343-Touchscreen-Ultrabook-Review.135817.0.html\" target=\"_self\" class=\"internal-link\">Dell XPS 13-9343</a> have sprinted forward with such massive improvements in portability, battery life, and LCD quality, the X1 Carbon 3rd Gen has only marginally improved, mostly regaining footing it’s lost elsewhere. It’s <strong>still a strong contender</strong>, and it’s <strong>certainly the best Carbon to date</strong>, but especially at a <strong>pricey $1,574</strong>, we fear that its inability to innovate further may relegate it to the shadows of these more aggressive contenders.</p>\n",
174 "annotations": [],
175 "mimetype": "text/html",
176 "language": "en",
177 "reading_time": 3,
178 "domain_name": "www.notebookcheck.net",
179 "preview_picture": "http://www.notebookcheck.net/fileadmin/Notebooks/Lenovo/ThinkPad_X1_Carbon_2015/x12015.jpg",
180 "tags": []
181 },
182 {
183 "is_archived": 0,
184 "created_at": "2016-09-08T11:55:58+0200",
185 "updated_at": "2016-09-08T11:57:16+0200",
186 "is_starred": 0,
187 "id": 541,
188 "title": "Visitons le Château de Landsberg !",
189 "url": "http://autour-du-mont-sainte-odile.overblog.com/2016/01/visitons-le-chateau-de-landsberg.html",
190 "content": "<p class=\"c1\">Situé au dessus de Heiligenstein et de Barr, à mi-hauteur de la montée vers plateau de la Bloss, le château de Landsberg est un but de promenade apprécié des randonneurs et des amateurs de vieilles pierres. Posé sur un éperon de granite, visible de loin, la forteresse médiévale domine fièrement la plaine d’Alsace.</p>\n<p class=\"c1\"><img alt=\"Visitons le Château de Landsberg !\" class=\"ob-cell ob-img ob-media c2\" src=\"http://img.over-blog-kiwi.com/0/28/39/78/20160128/ob_e68986_2.jpg\"/></p>\n<h3>Le château primitif</h3>\n<p class=\"c1\">Fin du onzième siècle, <strong><a href=\"http://autour-du-mont-sainte-odile.overblog.com/2014/01/l%E2%80%99assassinat-de-philippe-de-souabe.html\">Philippe de Souabe et Otton de Brunswick</a></strong> se disputent le trône impérial. Philippe, tenant des Hohenstaufen, veut conforter la puissance des couvents du <strong>Mont Sainte Odile.</strong> Il s’appuie sur un de ses représentants pour construire une nouvelle forteresse sur le Mont. <strong>Conrad de Vinhege</strong> érige le château de Landsberg dont sa famille prendra bientôt le nom. Nous sommes en 1197-1198. Le burg est construit sur les terres de l’<strong>abbaye de Niedermunster</strong>, le Couvent du Bas du Mont Sainte Odile. Un acte est signé de l’Abbesse <strong>Edelinde</strong>, il est daté du 23 juin 1200, il confirme la cession du terrain au chevalier Conrad.<br/>Nous avons publié le <a href=\"http://autour-du-mont-sainte-odile.overblog.com/2015/01/edelinde-et-le-chateau-de-landsberg.html\"><strong>texte de l’abbesse Edelinde</strong></a>, l’an passé. (cliquez sur le lien)<br/>Ce premier château n’avait pas l’importance des ruines que nous pouvons admirer aujourd’hui. Il ne comportait qu’un donjon et un corps de logis, complété par une basse-cour. Commençons la visite des ruines par cette partie. Le <strong>donjon</strong> est construit sur un carré de dix mètres de côté. Puissant, placé en diagonale par rapport au corps de logis, il formait bouclier pour défendre celui-ci du côté de la plaine, au nord-est. En levant la tête, le visiteur découvre l’accès : une porte haute, qui était accessible par un pont volant à partir de l’étage du logis seigneurial. Tout en haut du donjon, on distingue encore les corbeaux qui portaient les hourds. Les hourds, constructions de bois, ancêtres des mâchicoulis, permettaient aux défenseurs de surplomber les assaillants du château.<br/><img alt=\"Visitons le Château de Landsberg !\" class=\"ob-cell ob-img ob-media c3\" src=\"http://img.over-blog-kiwi.com/0/28/39/78/20160128/ob_d6d5c7_litho.jpg\"/>Le <strong>logis seigneurial</strong> comportait un rez-de-chaussée dédié à l’usage domestique : cuisines, citerne, salle des gardes. Ces pièces basses n’étaient éclairées que par quelques meurtrières. Le premier étage était l’habitation de Conrad et de ses successeurs : la façade nord-est est largement éclairée par quatre <strong>baies géminées</strong> en plein-cintre. Les fenêtres doubles sont séparées par de fines colonnes et surmontées d’élégants occuli. Au sud-est, deux doubles baies et un <strong>magnifique oriel</strong> agrémentent la façade. Situé sur le coté de la porte du château, cet élément de décor est le plus frappant du site du Landsberg, un genre d’échauguette semi-cylindrique, portée par un cul de lampe conique. Nous serions là dans la chapelle castrale du Landsberg. Coté extérieur, deux petites sculptures ornent la base de l’oriel : une fleur de lys et un petit personnage accroupi. A l’intérieur, une frise d’arceaux délimite les petites fenêtres du chœur de la chapelle. L’une d’elles a la forme d’une croix. Admirez la finesse des dessins du chapiteau de la colonne toujours en place au droite de l’oriel !<br/>Le château de Landsberg est situé à la limite géologique des grès, prédominants au nord, et des granites d’Andlau, côté sud. Les bases et les assises de la forteresse sont en granite, roche dure extraite du fossé creusé au nord, par les carriers du moyen âge. Les parties hautes sont en grès rose du Maennelstein, plus facile à travailler.</p>\n<h3 class=\"c4\">Le château neuf</h3>\n<p class=\"c1\">Ce premier château était, somme toute, de dimensions modestes. Quelques dizaines d’ années plus tard, preuve de l’importance des couvents du Mont Sainte Odile et signe de la puissance croissante de la famille de Landsberg, le site fut agrandi de façon conséquente. Nous sommes alors en 1240-1250.<br/>L’extension se fait au nord-ouest. Les deux tours rondes et l’imposante courtine délimitent l’emprise du Château Neuf. A l’origine, cette nouvelle enceinte était détachée du vieux burg, les deux sites ne furent rattachés que postérieurement. Les <strong>tours circulaires</strong> mesurent environ sept mètres de diamètre. Leur sommet portaient des créneaux. Un <strong>chemin de ronde</strong> surmontait la courtine : il était garni de hourds et traversait les deux tours. Archères et bretèches sont toutes orientées au nord, côté montagne, là où le risque d’attaque était le plus grand.<br/>Deux corps de logis se partageaient le site. Au sud, le bâtiment ne comportait qu’un seul étage, éclairé au sud-ouest par des fenêtres à banquettes, aujourd’hui murées. Le deuxième bâtiment, côté nord, fut construit plus tard. Composé de deux étages, il communiquait directement avec la tour nord.<br/>L’ensemble a connu plusieurs remaniements au cours des siècles.</p>\n<p class=\"c1\"><img alt=\"Visitons le Château de Landsberg !\" class=\"ob-cell ob-img ob-media c5\" src=\"http://img.over-blog-kiwi.com/0/28/39/78/20160128/ob_0861df_11.jpg\"/></p>\n<h3 class=\"c4\">Les extensions du XVème et du XVIème siècles</h3>\n<p class=\"c1\">L’apparition des <strong>armes à feu</strong> modifie l’art de la guerre. La géométrie des châteaux doit s’adapter aux armes nouvelles : résister aux boulets et accueillir couleuvrines et canons. Tous les châteaux des Vosges n’ont pas connu cette évolution, certains, trop solitaires, trop isolés, ont été abandonnés dés cette époque. Au Landsberg, les seigneurs ont respecté le vieux burg dans sa forme initiale, mais ils l’ont adapté tout d’abord en renforçant ses murs, puis en l’entourant de nouvelles murailles. Au nord, le château neuf se voit délaissé, ses nombreuses ouvertures extérieures sont murées, à part les archères, bien entendu. Ses courtines sont prolongées pour assurer la continuité avec celles du vieux burg. Un <strong>puissant bastion</strong> est construit au sud-est. Les armes nouvelles sont mises en place : couleuvrines, poivrière portant une canonnière protégée par des vastes vantaux. Ainsi, un vaste glacis s’étend devant la forteresse. C’est en faisant le tour du château dans les fossés que le promeneur se rendra le mieux compte de la force de la place et de son adaptation aux débuts de l’artillerie.<br/><img alt=\"Visitons le Château de Landsberg !\" class=\"ob-cell ob-img ob-media c6\" src=\"http://img.over-blog-kiwi.com/0/28/39/78/20160128/ob_57b020_plan-schematique.png\"/>Quelques temps, le château est passé des Landsberg au Comte Palatin, avant de revenir à la famille qui resta maître des lieux jusqu’à la Révolution.<br/>On ne trouve guère de textes relatant l’histoire du château de Landsberg dans les temps troublés que connut l’Alsace. Lors de la <strong>Guerre du Bundschuh</strong>, les paysans révoltés s’étaient installés dans la prévôté de Truttenhausen, toute proche. Cependant, rien ne dit que les Rustauds aient attaqué le château. Lors de la <strong>Guerre de Trente Ans</strong>, il semble que les troupes de Mansfeld, puis les Suédois se soient plutôt attaqués aux riches villes de la plaine, comme Obernai, oubliant les forteresses de montagne, déjà devenues inutiles. Cependant, le château est décrit comme ruiné au milieu du XVIIème siècle.<br/>Depuis longtemps, les Landsberg avaient délaissé le burg de leurs ancêtres pour lui préférer leur <strong>résidence de Niedernai</strong>, située en plaine. Le château fut confié à des gardes, puis servit de ferme. Aujourd’hui, les ruines du Landsberg sont une propriété privée. Merci à vous de respecter le site.</p>\n<p class=\"c1\">Dans la basse cour du château fleurit au printemps, l’<strong>éranthe d’hiver</strong>. Sa floraison ne dure que quelques jours. Cette petite fleur jaune est rare sous nos climats. De son nom latin ‘Eranthis hyemalis’, l’éranthe est originaire d’Italie ou de Turquie. La légende nous dit qu’elle aurait été rapportée des croisades par un sire de Landsberg. Elle serait un remède à la mélancolie.</p>\n<h3 class=\"c4\">Promenade et accès au château de Landsberg<img alt=\"Visitons le Château de Landsberg !\" class=\"ob-cell ob-img ob-media c7\" src=\"http://img.over-blog-kiwi.com/0/28/39/78/20160128/ob_902c3e_org.jpg\"/></h3>\n<p class=\"c1\">Les automobilistes pourront garer leur véhicule sur le petit parking situé à l’ouest d’Heiligenstein. Ils gagneront Truttenhausen sur la petite route à travers prés. Un sentier du Club Vosgien ( disque bleu ) monte vers les ruines.<br/>Les marcheurs préfèreront effectuer une boucle à partir de Saint-Jacques, par exemple. Saint-Jacques, Kapellenhausfelsen, Ameisenberg, Landsberg ( balisage : triangle bleu ) avec un retour sur Saint-Jacques par le sentier sans dénivelé ( rectangle : bicolore rouge et blanc).<br/>A moins qu’ils ne préfèrent rechercher les pierres sculptées du <a href=\"http://autour-du-mont-sainte-odile.overblog.com/des-chameaux-en-alsace\"><strong>Chemin des Chameaux</strong></a>. (cliquez sur le lien ), ou découvrir la <a href=\"http://autour-du-mont-sainte-odile.overblog.com/2015/07/la-chapelle-de-frere-leon-pres-de-barr.html\"><strong>Chapelle du Frère Léon</strong></a> dans la vallée de la Kirneck.</p>\n<h3 class=\"c4\">Illustrations</h3>\n<ul><li class=\"c8\">Photographies du château de Landsberg ( BrR, FrP et PiP)</li>\n<li class=\"c8\">Schéma des ruines ( PiP)</li>\n<li class=\"c8\">L’Orgueil, Herrade de landsberg, Hortus Deliciarum</li>\n<li class=\"c8\">Les Ruines du Landsberg, aquarelle de Osterwald, 1873</li>\n</ul>\n",
191 "annotations": [],
192 "mimetype": "text/html",
193 "language": "fr",
194 "reading_time": 7,
195 "domain_name": "autour-du-mont-sainte-odile.overblog.com",
196 "preview_picture": "http://img.over-blog-kiwi.com/0/28/39/78/20160128/ob_68f59d_12.jpg",
197 "tags": []
198 },
199 {
200 "is_archived": 1,
201 "created_at": "2016-09-08T11:55:58+0200",
202 "updated_at": "2016-09-08T11:57:16+0200",
203 "is_starred": 0,
204 "id": 454,
205 "title": "Contrer les stéréotypes par les livres : “C'est dès l'enfance qu'ils se construisent”",
206 "url": "https://www.actualitte.com/article/monde-edition/contrer-les-stereotypes-par-les-livres-c-est-des-l-enfance-qu-ils-se-construisent/64058",
207 "content": "<br/><h2><strong>Même dans l'espace jeunesse d'un immense salon littéraire, difficile de passer à côté du livre de coloriage féministe — et fier de l'être — de la maison d'édition Goater. Cette structure atypique, adossée à un bar de Rennes, Le Papier-Timbré, propose des titres tout aussi uniques, de ces livres que l'on devine importants avant même de les ouvrir. </strong></h2>\n\n<p class=\"c3\"><img alt=\"Livre Paris 2016\" src=\"https://farm2.staticflickr.com/1650/25284788384_ea234db7b9_z.jpg\" class=\"c2\"/></p>\n<p class=\"c3\">Judikael et Jean-Marie Goater (ActuaLitté, CC BY SA 2.0)</p>\n\n\n<p class=\"p1\">Le Papier-Timbré et les éditions Goater avancent main dans la main, dans une même structure, depuis 2009. En plus de la licence IV, permis de publier : « <em>On est très occupé par les soirées étudiantes et festives, mais on développe en plus des projets autour des livres qui, parfois, émergent d'ailleurs avec la clientèle. C'est surtout un motif supplémentaire pour se retrouver et partager des moments de convivialité, partager des goûts, des envies, de la littérature, des essais et de la jeunesse</em> », explique Jean-Marie Goater.</p>\n<p class=\"p1\"> </p>\n<p class=\"p1\">En plus de la production maison, le café-librairie propose celle de maisons soeurs : les éditions de juillet, L'Oeuf, les Éditions Pontcerq, essentiellement des petits éditeurs de Rennes et de la Bretagne. La maison est diffusée et distribuée en Bretagne par Coop Breizh, diffusé par Hobo Diffusion, distribué par Makassar pour la France (comme <a href=\"https://www.actualitte.com/article/monde-edition/avec-les-editions-prairial-le-surrealisme-nrv-est-de-retour/64055\">les éditions surréalistes Prairial</a>). Les tirages vont de 500 exemplaires à 3000 sauf exceptions et coéditions comme <em>Détachez vos ceintures</em>, projet collectif des éditions du Kyste contre l'aéroport de Notre-Dame-des-Landes, ou <em>Galette-saucisse, je t’aime !</em> de Benjamin Keltz, avec les Éditions du coin de la rue.</p>\n<p class=\"p1\"> </p>\n<p class=\"p1\"><em>Mon premier cahier de coloriage féministe !</em> sera en librairie d'ici quelques jours, et la maison Goater y croit dur comme fer : « <em>Nous avons commencé par traduire et adapter</em> C'est quoi ton genre ?<em>, un livre écrit par Jacinta Bunnell et publié par l'éditeur anarchiste américain PM Press</em> », explique Jean-Marie Goater. Dans les pages du livre, on croise des monstres qui aiment les petits sacs à main et les chaussures, des princesses qui ne suivent pas vraiment le dress code, ou des enfants en fauteuil roulant, encore rares dans les livres jeunesse.</p>\n<p class=\"p1\"> </p>\n<p class=\"p1 c3\"><img alt=\"Livre Paris 2016\" src=\"https://farm2.staticflickr.com/1628/25822534701_142d157b15_z.jpg\" class=\"c2\"/></p>\n<p class=\"p1 c3\">(ActuaLitté, CC BY SA 2.0)</p>\n<p class=\"p1 c3\"> </p>\n<p class=\"p1\"> </p>\n<p class=\"p1\">Après cette publication, la maison a souhaité développer un projet en France, en réunissant 16 dessinatrices dont 4 dessinateurs pour leur proposer d'expliquer le féminisme aux enfants, à travers un dessin. « <em>Le livre aborde la vie à l'école, les habillements, les métiers, le sport, mais aussi les quelques femmes féministes importantes de l'histoire... Ça reste ludique et sans prétention encyclopédique sur le féminisme, mais il est plus simple d'aborder le sujet avec un support comme celui-ci à la maison, à l'école ou au centre de loisirs.</em> » Comme le précédent, l'ouvrage présente d'une nouvelle manière les situations traditionnelles des livres de coloriage ou jeunesse.</p>\n<p class=\"p1\"> </p>\n<h3 class=\"p1\"><strong>Des ressources rares, des besoins importants</strong></h3>\n<p class=\"p1\"> </p>\n<p class=\"p1\">Pas la peine d'insister pour que Jean-Marie Goater partage son avis : « <em>La production majoritaire est quand même très caricaturale et stéréotypée, cependant on remarque depuis quelques années des éditeurs intéressants qui essaient de bousculer un peu ces stéréotypes comme La Ville Brûle, ou encore l'édition LGBT qui commence à arriver avec Des ailes sur un tracteur qui a publié un cahier de coloriage avec Sophie Labelle, plutôt sur les questions trans.</em> »</p>\n<p class=\"p1\"> </p>\n<p class=\"p1\">Contrairement à ce que les détracteurs des livres jeunesse atypiques prétendent (<a href=\"https://www.actualitte.com/recherche?q=tous+a+poil+cope\">coucou, Jean-François Copé</a>), lutter contre les stéréotypes n'a rien d'une guerre de civilisation ou autre affabulation du genre. Il s'agit simplement de montrer que chacun doit être fier de ce qu'il est, respecter ce que l'autre est, et ne pas chercher l'assentiment des uns ou des autres. « <em>Fuck the world</em> », comme dirait 2Pac... « <em>Se poser ces questions est indispensable, il faut qu'il y ait ce débat : les enfants ne sont pas si naïfs que ça, ils ont besoin de se poser ce genre de questions.</em> »</p>\n<p class=\"p1\"> </p>\n<p class=\"p1 c3\"><img alt=\"Livre Paris 2016\" src=\"https://farm2.staticflickr.com/1554/25284764604_1d8b3e9a0a_z.jpg\" class=\"c2\"/></p>\n<p class=\"p1 c3\">(ActuaLitté, CC BY SA 2.0)</p>\n<p class=\"p1\"> </p>\n<p class=\"p1\"> </p>\n<p class=\"p1\">Judikael, venu aider son père, acquiesce : il a répondu à l'appel à dessins et proposé une activité dans le cahier de coloriage féministe. « <em>Ce genre de ressources pour enfant est important, parce que c'est dès l'enfance que se construisent certains préjugés, certains stéréotypes qui restent ensuite. Quand on voit que 90 % des personnes présentes dans les manuels scolaires sont des hommes par exemple, ce genre d'ouvrages permet à certaines personnes de se reconnaître davantage dans certains rôles, qu'on ne leur attribue pas forcément de base.</em> »</p>\n<p class=\"p1\"> </p>\n<p class=\"p1\">Là est la lutte, résumée par Judikael : « <em>On parle souvent de</em> “déconstruire” <em>dans le féminisme, les préjugés ou autre, ces livres peuvent permettre d'éviter de les construire.</em> » En Terminale L, Judikael confirme que les préjugés sont toujours présents, forcément surtout en sport ou vis-à-vis de « <em>la filière homme</em> » (comprendre, la filière scientifique) et de « <em>la filière femme </em>» (comprendre, la filière littéraire). Si l'histoire du féminisme est désormais abordée en classe, certains sujets restent touchy : le journal du lycée s'est vu censurer un article sur la culture du viol, et la ségrégation hommes-femmes, « <em>au prétexte que c'était trop hard, que les lycéens n'allaient pas comprendre </em>»...</p>\n<p class=\"p1\"> </p>\n<h3 class=\"p1\"><strong>« <em>L'édition, c'est un milieu qui est quand même très hypocrite</em> »</strong></h3>\n<p class=\"p1\"> </p>\n<p class=\"p1\">À votre avis, comment réagit l'éditeur de <em>Mon premier cahier de coloriage féministe</em> lorsqu'on lui parle des différences entre les salaires <a href=\"https://www.actualitte.com/article/monde-edition/l-inegalite-entre-hommes-et-femmes-persiste-dans-le-monde-du-livre/63891\">des hommes et des femmes dans l'édition</a>, ou dans les aides attribuées par le CNL ? Sans langue de bois : « <em>C'est pas trop surprenant malheureusement, parce que c'est à l'image des autres professions. En tant que bar-maison d'édition, de toute façon, je ne rentre pas dans la case du CNL, je me tourne plutôt vers la région</em> », explique Jean-Marie Goater.</p>\n<p class=\"p1\"> </p>\n<p class=\"p1\">Haut les coeurs : « <em>C'est pas grave, je m'en passe très bien. L'édition, c'est un milieu qui a quand même une grande dimension d'hypocrisie sur pas mal d'aspects, on le voit sur certaines pratiques... Il y a des cons dans ce métier-là comme dans d'autres métiers, mais je pense que ce serait bien de faire le ménage, comme à Angoulême, c'est quand même criant. Dans certains secteurs du livre, la majorité des lecteurs sont des lectrices, très clairement, ce serait quand même la moindre des choses qu'il n'y ait pas des inégalités de ce type qui existent dans le monde de l'édition.</em> »</p>\n<p class=\"p1\"> </p>\n<p class=\"p1 c3\"><img alt=\"Livre Paris 2016\" src=\"https://farm2.staticflickr.com/1672/25796714772_315ae8c648_z.jpg\" class=\"c2\"/></p>\n<p class=\"p1 c3\">Un album jeunesse bilingue français-langue des signes (ActuaLitté, CC BY SA 2.0)</p>\n<p class=\"p1\"> </p>\n<p class=\"p1\"> </p>\n<p class=\"p1\">Même sans aide du CNL, les éditions Goater produisent de quoi lire : <em>Les Joyeux Punks</em>, un album à compter, mais aussi une collection d'albums bilingues français-langue des signes, des livres en breton, dont une traduction du <em>Persepolis</em> de Marjane Satrapi. Pour les amateurs de polar, Goater noir, une collection de 14 titres qui a notamment fait revivre <em>Le Soviet</em>, la série culte des années 89-90 d'abord publiée chez Fleuve Noir et Série Noire. Pour les amateurs des écrits du Colonel Durruti, un inédit est prévu pour le mois d'octobre prochain.</p>\n<p class=\"p1\"> </p>\n<p class=\"p1\">Perdez-vous sans hésiter dans le catalogue de la maison, qui propose aussi de la littérature blanche \"classique\", des essais sur l'écologie et le convivialisme ou la convivialité, l'écologie sociale, et l'Histoire, surtout XXe.</p>\n\n<br/>",
208 "annotations": [],
209 "mimetype": "text/html",
210 "language": "en",
211 "reading_time": 6,
212 "domain_name": "www.actualitte.com",
213 "preview_picture": "//cdn.actualitte.com/images/facebook/25284788384-ea234db7b9-z-56eeff88c23a0.jpg",
214 "tags": []
215 },
216 {
217 "is_archived": 1,
218 "created_at": "2016-09-08T11:55:58+0200",
219 "updated_at": "2016-09-08T11:57:16+0200",
220 "is_starred": 0,
221 "id": 99,
222 "title": "[ROM][6.0.1][Layers][N5] TipsyOS official builds {UBER TCs}",
223 "url": "http://forum.xda-developers.com/google-nexus-5/development/rom-tipsyos-official-builds-uber-tcs-t3325989",
224 "content": "<div class=\"post-text post-first-post\" id=\"post_message_65589573\" readability=\"82\">\n<div class=\"c16\" readability=\"51\"><img src=\"http://imagizer.imageshack.us/v2/640x480q90/673/zEwXs9.png\" border=\"0\" alt=\"\" title=\"\"/><p><span>*Welcome to Tipsy OS*</span></p>\n<div class=\"c16\"><img src=\"http://imagizer.imageshack.us/v2/1024x768q90/922/uy7Jf6.png\" border=\"0\" alt=\"\" title=\"\"/></div>\n<br/><span>This is something Martin Coulon (@martinusbe) started in his 'free' time when waiting for GZR Validus or Tesla builds and having some drinks.<br/>He just started with a slim base; on lp and early mm, and now using <a href=\"https://github.com/AOSPB\" target=\"_blank\" rel=\"nofollow\"><strong class=\"c17\"><span>AOSPB</span></strong></a> as a base (wich Martin is also a part of)....then added what we thought useful.<br/>It grew up to be a fully functional Rom<br/>The main goal is to keep it AOSPB/Slim based and will not add any cm features unless AOSPB/Slim does.<br/></span>\n<p>TipsyOS is Black and Yellow default themed, we don't like white UI, so it may look a bit weird on light switch,<br/>but heh! use layers to suit it your needs =)</p>\n<p>We are a team wich is constantly learning and ...drinking because both gets along so well hahaha <img src=\"http://forum.xda-cdn.com/images/smilies/laugh.gif\" border=\"0\" alt=\"\" title=\"Laugh\" class=\"inlineimg\"/></p>\n<p>Just report the bugs and request features, we'll see what we can do!.......</p>\n<p><strong>And don't get it twisted</strong>, its not because we're Tipsy that this project is not a serious one, try it and feel speed and stability <img src=\"http://forum.xda-cdn.com/images/smilies/tongue.gif\" border=\"0\" alt=\"\" title=\"Stick Out Tongue\" class=\"inlineimg\"/></p>\n<p>My builds are compiled with UBER toolchains 4.9 on both rom and kernel code.<br/>We can go over with 5.2/3, 6 ...but to be really honest, 4.9 is the most battery friendly in my opinion, and is still super smooth and snappy!</p>\n<p>Im using a cm device tree base a bit modified...<br/>This rom includes a custom kernel, cm was my base, and i have decided to go a bit wild and cherry-picked up <em>some</em> stuff from:<br/>Francisco Franco, Chet Kener, Faux123, Flar2, Hellsgod and some others<br/>So a <strong class=\"c17\">huge thanks</strong> for them and their AWESOME open sources work!<br/>I will continue to work on this kernel because its fun <img src=\"http://forum.xda-cdn.com/images/smilies/laugh.gif\" border=\"0\" alt=\"\" title=\"Laugh\" class=\"inlineimg\"/></p>\n<div class=\"c16\" readability=\"8\"><img src=\"http://imagizer.imageshack.us/v2/1024x768q90/923/nPeHiF.png\" border=\"0\" alt=\"\" title=\"\"/><p><strong><em><span>For cool wallpapers, test builds, requests; join us on our community!</span></em></strong></p>\n</div>\n<strong class=\"c17\"><span><a href=\"https://plus.google.com/u/0/communities/114022867167626892613\" target=\"_blank\" rel=\"nofollow\"><span>Google+ Community</span></a></span></strong>\n<div class=\"c16\"><strong class=\"c17\"><span>Features:</span></strong>\n<div class=\"c20\">\n<p>Code:</p>\n<pre class=\"alt2 c19\" dir=\"ltr\">\nWe slowly adding only what we need, we don't want a 1236544547 features rom...\n\"The Tavern\":\nPower menu customisations\nToasts/ListView/System animations\nBattery bar\nLCD Density\nGesture Anywhere\nExpanded Desktop\nStatus bar customisations\nAosp Recents and OmniSwitch \nBuilt in:\nDashboard (settings) columns selector\nDashboard lines remover\nSlim Navbar customisation\nVolume steps\nNotification led changer\nHeadsUp switch\nKernel Adiutor app\nLayers manager app\nLayers backup/restore app\nAdaway\nNova launcher\nViper4Android\nES Manager\nSnapCam\nChangelog generator in about phone menu....\nand prolly some other stuff that i can't remember but heh,\n just flash dat sh#t to figure out by yourself =)\n</pre></div>\n</div>\n<p><span><br/><span class=\"c12\">Installation Instructions</span><br/></span></p>\n<p><span>1. Make sure you have a working recovery and a nandroid backup</span></p>\n<p><span>2. Download the ROM.</span></p>\n<p><span>3. Reboot to recovery.</span></p>\n<p><span>4.Wipe everything! system/data/cache partitions (except internal storage indeed!)</span></p>\n<p><span>7. Flash the ROM.</span></p>\n<p><span><em>Optional- Flash 6.x GApps.</em></span></p>\n<p><span>8. Reboot and feel Tipsy!</span></p>\n<p><strong class=\"c17\"><span>Download:</span></strong></p>\n<p><span><a href=\"https://www.androidfilehost.com/?w=files&amp;flid=48392\" target=\"_blank\" rel=\"nofollow\"><strong class=\"c17\"><span>Tipsy HammerHead downloads folder</span></strong></a></span></p>\n<p><span>STAY TIPSY <img src=\"http://forum.xda-cdn.com/images/smilies/wink.gif\" border=\"0\" alt=\"\" title=\"Wink\" class=\"inlineimg\"/><img src=\"http://forum.xda-cdn.com/images/smilies/laugh.gif\" border=\"0\" alt=\"\" title=\"Laugh\" class=\"inlineimg\"/></span><br/><img src=\"http://imageshack.com/a/img924/6871/q1zjrl.gif\" border=\"0\" alt=\"\" title=\"\"/></p>\n<p><span><strong>TipsyOs, a ROM for Nexus 5 aka Hammerhead</strong></span></p>\n</div>\n<br/><strong class=\"c17\"><span>Kernel features:</span></strong><br/>Kexec patch for multirom support, intelliplug, hellsactive governor, extra io schedulers, intellithermal v2, etc etc and growing, just check commits on history on the link below\n<p><strong class=\"c17\"><span>Known bugs:</span></strong><br/>quick tiles may be a bit messy while re arranging them....<br/>u tell me then.</p>\n<p><span>don't even think to report a bug with:</span><br/>a dirty flashed rom,<br/>xposed frameworks installed,<br/>all of your apps installed, if u have a bug, clean flash the build, (flash the gapps if needed) and reproduce your bug without any data restore.<br/>BRING BACK LOGCAT or u will be simply ignored....</p>\n<p><strong class=\"c17\">Contributors</strong><br/><a href=\"http://forum.xda-developers.com/member.php?u=4139665\" target=\"_blank\">martinusbe</a><br/>@<a href=\"http://forum.xda-developers.com/member.php?u=5265704\" target=\"_blank\">Alx31</a><br/><strong>ROM OS Version:</strong> 6.0.1 Marshmallow<br/><strong>ROM Kernel:</strong> Linux 3.4.x<br/><strong>Based On:</strong> AOSPB</p>\n<p><strong class=\"c17\">Version Information</strong><br/><strong>Status:</strong> Stable<br/><strong>Created</strong> 2016_29_02</p>\n<p><strong class=\"c17\">Credits:</strong><br/>AOSPB/Slim team for an amazing base, Google, CyanogenMod for device trees and some other repos, Dirty Unicorns/CrDroid/AICP and other roms with their open sources i may have forgotten...</p>\n<p><strong class=\"c17\">Rom code:</strong> <a class=\"c21\" href=\"https://github.com/TipsyOs\" target=\"_blank\" rel=\"nofollow\">https://github.com/TipsyOs</a><br/><strong class=\"c17\">Device:</strong> <a class=\"c21\" href=\"https://github.com/TipsyOs-Devices/device_lge_hammerhead/commits/6.0\" target=\"_blank\" rel=\"nofollow\">Hammerhead commits history</a><br/><strong class=\"c17\">Kernel code:</strong> <a class=\"c21\" href=\"https://github.com/TipsyOs-Devices/kernel_lge_hammerhead/commits/6.0\" target=\"_blank\" rel=\"nofollow\">Kernel commits history</a><br/><strong class=\"c17\">My github:</strong> <a class=\"c21\" href=\"https://github.com/Alx31\" target=\"_blank\" rel=\"nofollow\">https://github.com/Alx31</a></p>\n<p><img src=\"http://imagizer.imageshack.us/v2/640x480q90/901/JGwVTy.png\" border=\"0\" alt=\"\" title=\"\"/></p>\n</div><p>Last edited by Alx31; 29th February 2016 at 10:48 PM.</p>",
225 "annotations": [],
226 "mimetype": "text/html",
227 "language": "en",
228 "reading_time": 3,
229 "domain_name": "forum.xda-developers.com",
230 "preview_picture": "http://cdn3.xda-developers.com/images/xda-facebook-default.jpg",
231 "tags": []
232 },
233 {
234 "is_archived": 0,
235 "created_at": "2016-09-08T11:55:58+0200",
236 "updated_at": "2016-09-08T11:57:16+0200",
237 "is_starred": 0,
238 "id": 98,
239 "title": "Top 15 Podcasts All Web Developers Should Follow - Envato Tuts+ Code Article",
240 "url": "http://code.tutsplus.com/articles/top-15-podcasts-all-web-developers-should-follow--net-14461",
241 "content": "<p>As web developers, we’re always trying to get better at what we do. One of the best ways to do that is to listen to what other developers have to share. And even if you’re not learning, it’s still fun to hear what other devs are talking about. Today, I’ll share 15 podcasts that you should definitely check out.</p>\n<hr/>\n<div class=\"tutorial_image\"><img src=\"https://cdn.tutsplus.com/net/uploads/legacy/793_podcasts/yahootheater.png\" data-original-url=\"http://nettuts.s3.amazonaws.com/793_podcasts/yahootheater.png\"/></div>\n<p>It seems that as often as a few times a month, Yahoo! brings in developers on the cutting edge of web technology to keep their employees up to date. For the benefit of the rest of us, these talks are recorded and published. You’ll find well-known devs like Douglas Crockford and NNicolas Zakas, and talks on everything from performance and accessibility to JavaScript and the DOM.</p>\n<ul><li><a href=\"http://itunes.apple.com/us/podcast/yui-theater/id263846173\">iTunes Feed</a></li>\n<li><a href=\"http://feeds.yuiblog.com/yuiblog/yui-theater\">RSS Feed</a></li>\n</ul><hr/>\n<div class=\"tutorial_image\"><img src=\"https://cdn.tutsplus.com/net/uploads/legacy/793_podcasts/devshow.png\" data-original-url=\"http://nettuts.s3.amazonaws.com/793_podcasts/devshow.png\"/></div>\n<p>This may be my favourite show from this list. The Dev Show, hosted weekly by Dan Benjamin and Jason Seifer, will give you a carefully curated set of development-related links (usually with a web dev slant) to enjoy. As an added bonus, you can <a href=\"http://live.5by5.tv\">watch the show live</a> on Tuesdays at 1pm EST.</p>\n<ul><li><a href=\"http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=352611845\">iTunes Feed (Audio)</a></li>\n<li><a href=\"http://feeds.feedburner.com/thedevshow\">RSS Feed (Audio)</a></li>\n<li><a href=\"http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=374004076\">iTunes Feed (Video)</a></li>\n<li><a href=\"http://feeds.feedburner.com/devshowvideo\">RSS Feed (Video)</a></li>\n<li><a href=\"http://twitter.com/devshow\">Twitter</a></li>\n</ul><hr/>\n<div class=\"tutorial_image\"><img src=\"https://cdn.tutsplus.com/net/uploads/legacy/793_podcasts/changelog.png\" data-original-url=\"http://nettuts.s3.amazonaws.com/793_podcasts/changelog.png\"/></div>\n<p>The tagline for the Changelog says it all: “Open Source moves fast. Keep up.” This podcast, and the accompanying blog, is all about keeping you updated with the latest in Open Source Technology. It’s hosted by Adam Stacoviak and Wynn Netherland, and seems to be the official Github podcast.</p>\n<ul><li><a href=\"http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=341623264&amp;subMediaType=Audio\">iTunes Feed</a></li>\n<li><a href=\"http://feeds.feedburner.com/thechangelog\">RSS Feed</a></li>\n<li><a href=\"http://twitter.com/changelogshow\">Twitter</a></li>\n</ul><hr/>\n<div class=\"tutorial_image\"><img src=\"https://cdn.tutsplus.com/net/uploads/legacy/793_podcasts/jquerypodcast.png\" data-original-url=\"http://nettuts.s3.amazonaws.com/793_podcasts/jquerypodcast.png\"/></div>\n<p>If you’re familiar with jQuery (and you probably are), you know there’s a podcast to go with it. Each week, hosts Ralph Whitbeck and Rey Bango bring you the latest in jQuery news, as well as great interviews with important people in the jQuery community. You can listen in to the jQuery wisdom of people like Remy Sharp, Yehuda Katz, Cody Lindley, and our own Jeffrey Way, among so many others.</p>\n<ul><li><a href=\"http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=339835419\">iTunes Feed</a></li>\n<li><a href=\"http://feeds.feedburner.com/jQueryPodcastShowNotes\">RSS Feed</a></li>\n<li><a href=\"http://www.twitter.com/jquerypodcast\">Twitter</a></li>\n</ul><hr/>\n<div class=\"tutorial_image\"><img src=\"https://cdn.tutsplus.com/net/uploads/legacy/793_podcasts/sitepoint.png\" data-original-url=\"http://nettuts.s3.amazonaws.com/793_podcasts/sitepoint.png\"/></div>\n<p>Sitepoint is a great resource for anyone interesting in technology, design, and even business. Books, courses, forums, blogs, articles, they’ve got it all. Of course, there’s a podcast too: check it out to find out what’s going on in the web industry.</p>\n<ul><li><a href=\"http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=296180681&amp;s=143441\">iTunes Feed</a></li>\n<li><a href=\"http://www.sitepoint.com/blogs/?feed=podcast\">RSS Feed</a></li>\n</ul><hr/>\n<div class=\"tutorial_image\"><img src=\"https://cdn.tutsplus.com/net/uploads/legacy/793_podcasts/webpulp.png\" data-original-url=\"http://nettuts.s3.amazonaws.com/793_podcasts/webpulp.png\"/></div>\n<p>According to the site, WebPulp is “a podcast about technology that powers the web.” In each podcast, host Josh Owens interviews someone from behind the scenes of a well-known webapp; you’ll find out what hardware and software it takes to run apps like the 37signals apps, or GitHub.</p>\n<ul><li><a href=\"http://itunes.apple.com/us/podcast/webpulp-tv/id371328694\">iTunes Feed</a></li>\n<li><a href=\"http://webpulp.tv/rss\">RSS Feed</a></li>\n<li><a href=\"http://twitter.com/webpulptv\">Twitter</a></li>\n</ul><hr/>\n<div class=\"tutorial_image\"><img src=\"https://cdn.tutsplus.com/net/uploads/legacy/793_podcasts/wordpresspodcast.png\" data-original-url=\"http://nettuts.s3.amazonaws.com/793_podcasts/wordpresspodcast.png\"/></div>\n<p>It’s pretty apparent that both Nettuts+ readers and writers are big fans of WordPress. If you can’t get enough WordPress goodness, you’ll probably want to sign up for the WordPress Podcast, “a weekly podcast with news, interviews and plugin tips.” There’s a bonus here: one of the most recent interviewees was none other than Collis Ta’eed, CEO of Envato.</p>\n<ul><li><a href=\"http://itunes.apple.com/us/podcast/wordpress-community-podcast/id164651619\">iTunes Feed</a></li>\n<li><a href=\"http://wp-community.org/feed/\">RSS Feed</a></li>\n<li><a href=\"http://twitter.com/wppodcast\">Twitter</a></li>\n</ul><hr/>\n<div class=\"tutorial_image\"><img src=\"https://cdn.tutsplus.com/net/uploads/legacy/793_podcasts/eepodcast.png\" data-original-url=\"http://nettuts.s3.amazonaws.com/793_podcasts/eepodcast.png\"/></div>\n<p>If you’re a user of Ellis Lab’s Expression Engine, you’ll enjoy the EE Podcast (Ellis Lab is the company behind CodeIgniter; in fact, EE is build completely on CI). Each week, Ryan Irelan and Lea Alcantara will fill in you on a certain aspect of of EE deveopment.</p>\n<ul><li><a href=\"http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=334063423\">iTunes Feed</a></li>\n<li><a href=\"http://feeds.feedburner.com/eepodcast\">RSS Feed</a></li>\n<li><a href=\"http://twitter.com/eepodcast\">Twitter</a></li>\n</ul><hr/>\n<div class=\"tutorial_image\"><img src=\"https://cdn.tutsplus.com/net/uploads/legacy/793_podcasts/csstricks.png\" data-original-url=\"http://nettuts.s3.amazonaws.com/793_podcasts/csstricks.png\"/></div>\n<p>If you’re a web developer, you’re probably pretty familiar with Chris Coyier’s website <a href=\"http://www.css-tricks.com\">CSS Tricks</a>. Besides his excellent articles, Chris occasionally puts out a screencast every few weeks. With his relaxed style, you’ll learn about a random—but always practical—part of web development in each episode.</p>\n<ul><li><a href=\"http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=273881728\">iTunes Feed</a></li>\n<li><a href=\"http://feeds.feedburner.com/CSS-Tricks-Screencasts\">RSS Feed</a></li>\n</ul><hr/>\n<div class=\"tutorial_image\"><img src=\"https://cdn.tutsplus.com/net/uploads/legacy/793_podcasts/bigwebshow.png\" data-original-url=\"http://nettuts.s3.amazonaws.com/793_podcasts/bigwebshow.png\"/></div>\n<p>Hosted by Jeffrey Zeldman and Dan Benjamin, the Big Web Show “features special guests and topics like web publishing, art direction, content strategy, typography, web technology, and more. It’s everything web that matters.” You’ll listen to interviews in which famous web personalities like Eric Meyer, Jason Fried, Nicole Sullivan, Ethan Marcotte, and other professionals you should know open their minds and let you learn from the best. You can <a href=\"http://5by5.tv/bigwebshow\">catch this show live</a> on Thursdays a 1PM EST. Just like the Dev Show and the EE Podcast, the Big Web Show is part of Dan Benjamin’s incredible <a href=\"http://5by5.tv\">5by5 podcast network</a>.</p>\n<ul><li><a href=\"http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=370445683\">iTunes Feed (Audio)</a></li>\n<li><a href=\"http://feeds.feedburner.com/bigwebshow\">RSS Feed (Audio)</a></li>\n<li><a href=\"http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=374004085\">iTunes Feed (Video)</a></li>\n<li><a href=\"http://feeds.feedburner.com/bigwebshowvideo\">RSS Feed (Video)</a></li>\n<li><a href=\"http://twitter.com/bigwebshow\">Twitter</a></li>\n</ul><hr/>\n<div class=\"tutorial_image\"><img src=\"https://cdn.tutsplus.com/net/uploads/legacy/793_podcasts/thinkvitamin.png\" data-original-url=\"http://nettuts.s3.amazonaws.com/793_podcasts/thinkvitamin.png\"/></div>\n<p>You may be familiar with Carsonified, the company behind many web dev / design training initiatives (including the Future of Web Design and Future of Web Apps confernces). On Think Vitamin, Carsonified’s “blog about the web”, you can catch Think Vitamin Radio, “a bi-weekly chat about web design, development, and entrepreneurship.”</p>\n<ul><li><a href=\"http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=351340191\">iTunes Feed</a></li>\n<li><a href=\"http://feeds.feedburner.com/thinkvitaminradio\">RSS Feed</a></li>\n</ul><hr/>\n<div class=\"tutorial_image\"><img src=\"https://cdn.tutsplus.com/net/uploads/legacy/793_podcasts/userability.png\" data-original-url=\"http://nettuts.s3.amazonaws.com/793_podcasts/userability.png\"/></div>\n<p>User Interface Engineering “is a leading research, training, and consulting firm specializing in web site and product usability.” You can take advantage of some of the free usability training they offer in their podcast, the Userability Podcast.</p>\n<ul><li><a href=\"http://itunes.apple.com/podcast/uie-brain-sparks/id119728465\">iTunes Feed</a></li>\n</ul><hr/>\n<div class=\"tutorial_image\"><img src=\"https://cdn.tutsplus.com/net/uploads/legacy/793_podcasts/jqueryfordesigners.png\" data-original-url=\"http://nettuts.s3.amazonaws.com/793_podcasts/jqueryfordesigners.png\"/></div>\n<p>This is a great resource for any beginner (and even intermediate) jQuery developers. In each episode, Remy Sharp will explain how to create an popular web effect using jQuery. You’ll learn how to build pop-up bubbles, sliding headers, and simple tabs.</p>\n<ul><li><a href=\"http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewPodcast?id=281057468\">iTunes Feed</a></li>\n</ul><hr/>\n<div class=\"tutorial_image\"><img src=\"https://cdn.tutsplus.com/net/uploads/legacy/793_podcasts/nettuts.png\" data-original-url=\"http://nettuts.s3.amazonaws.com/793_podcasts/nettuts.png\"/></div>\n<p>Of course, Nettuts+ publishes screencasts, too! For your convenience, you can get these in an iTunes feed, or subscribe to them on YouTube.</p>\n<ul><li><a href=\"http://itunes.apple.com/podcast/nettuts/id291173544?i=60856588\">iTunes Feed</a></li>\n<li><a href=\"http://www.youtube.com/user/nettutsplus\">Youtube Profile</a></li>\n</ul><hr/>\n<div class=\"tutorial_image\"><img src=\"https://cdn.tutsplus.com/net/uploads/legacy/793_podcasts/huffduffer.png\" data-original-url=\"http://nettuts.s3.amazonaws.com/793_podcasts/huffduffer.png\"/></div>\n<p>HuffDuffer is a site created by Jeremy Keith; it allows you to easily create your own podcasts. From the tag cloud above, you can see that a lot of the content being collected is related to web development. Check it out!</p>\n<hr/>\n<p>I’m sure most developers listen to the occasional podcast. Have I missed your favourite podcast? Let us all know in the comments!</p>\n",
242 "annotations": [],
243 "mimetype": "text/html",
244 "reading_time": 4,
245 "domain_name": "code.tutsplus.com",
246 "preview_picture": "https://cdn.tutsplus.com/net/uploads/legacy/793_podcasts/preview.jpg",
247 "tags": []
248 },
249 {
250 "is_archived": 1,
251 "created_at": "2016-09-08T11:55:58+0200",
252 "updated_at": "2016-09-08T11:57:16+0200",
253 "is_starred": 0,
254 "id": 97,
255 "title": "University of Mississippi",
256 "url": "http://olemiss.edu",
257 "content": "<header readability=\"1\">\n<section class=\"hero\">\n</section></header><div class=\"pushdown\">\n<div id=\"academics-push\" class=\"push main c2\" readability=\"21\">\n<hr/><h4>UNIVERSITY OF MISSISSIPPI SCHOOLS AND COLLEGES</h4>\n<hr/><p>The Schools of Nursing and Pharmacy operate on both the Oxford and Jackson campuses. The Schools of Dentistry, Health Related Professionals and Medicine, and the Health Sciences Graduate School, are based in Jackson only. (Additional healthcare programs are available through the School of Applied Sciences on the Oxford campus.) Other than these exceptions, the schools above are on the Oxford campus.</p>\n</div>\n</div>\n<section id=\"herophoto\" readability=\"3\"><p><a href=\"http://www.olemiss.edu/emergency/\"><strong>Public Service Announcement</strong>: UM Health Center Seeing Increase in Flu Cases MORE INFO</a></p>\n<div class=\"flexslider page\">\n<ul class=\"slides\"><li class=\"quad3\">\n<figure><img alt=\"\" src=\"http://olemiss.edu/www.olemiss.edu/_images/hero2/2016-03-02_20_23_23CTG_0268-AC.jpg\"/><figcaption readability=\"2\"><h5>Hotty Toddy</h5>\n<p>Martavious Newby celebrates with fans after Ole Miss' 86-78 win over Mississippi State.</p>\n</figcaption></figure></li>\n<li class=\"quad3\">\n<figure><img alt=\"\" src=\"http://olemiss.edu/www.olemiss.edu/_images/hero2/2016-03-02_20_23_23CTG_0268-AB.jpg\"/><figcaption readability=\"6\"><h5>Moody's Amazing Night</h5>\n<p>Stefan Moody celebrates at the end of Ole Miss' 86-78 win over Mississippi State. Moody finished his final game at The Pavilion on Senior Night with a career-high 43 points.</p>\n</figcaption></figure></li>\n<li class=\"quad2\">\n<figure><img alt=\"\" src=\"http://olemiss.edu/www.olemiss.edu/_images/hero2/2016-03-01_16_29_53CTG_0266-D.jpg\"/><figcaption readability=\"4\"><h5>Career Expo</h5>\n<p>Students talk to prospective employers during an all-majors career fair held at The Inn at Ole Miss.</p>\n</figcaption></figure></li>\n<li class=\"quad2\">\n<figure><img alt=\"\" src=\"http://olemiss.edu/www.olemiss.edu/_images/hero2/2016-03-01_15_50_57SKB_2725-AAweb.jpg\"/><figcaption readability=\"8\"><h5>Choir Rehearsal</h5>\n<p>Members of the University of Mississippi Concert Singers prepare for a performance at the American Choral Directors Association convention March 10 in Chattanooga, Tenn.</p>\n</figcaption></figure></li>\n<li class=\"quad3\">\n<figure><img alt=\"\" src=\"http://olemiss.edu/www.olemiss.edu/_images/hero2/2016-02-29_15_05_23Dental-White-Coat-2016_13web.jpg\"/><figcaption readability=\"6\"><h5>Dentist's Pledge</h5>\n<p>Kendra Clark (right) and other students in the UMMC School of Dentistry Class of 2018 recite the Dentist's Pledge at the American College of Dentists White Coat Ceremony held Feb. 26 in Jackson.</p>\n</figcaption></figure></li>\n</ul><div class=\"weather\">\n<p>45°</p>\n<p>Oxford, MS</p>\n</div>\n</div>\n</section>\n<div id=\"newsannouncements\" readability=\"31\">\n<section id=\"news\"><a href=\"http://news.olemiss.edu\" class=\"link2all\">ALL NEWS</a>\n<h2>Latest News</h2>\n<article>\n<h3>UM Honors 150 Students with Who's Who Distinction</h3>\n</article><article>\n<h3>UM Lazarus Project Attracts International Collaborations</h3>\n</article><article>\n<h3>Schedule Set for BancorpSouth Rebel Road Trip</h3>\n</article></section><section id=\"announcements\"><a href=\"http://olemiss.edu/newsevents/announcements.html\" class=\"link2all\">ALL ANNOUNCEMENTS</a>\n<h2>Announcements</h2>\n<ul><li readability=\"1\">\n<h3><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=rebeccac-300-2R6EhILE.html\">Conferences — Oxford Conference for the Book</a></h3>\n<p><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=rebeccac-300-2R6EhILE.html\">Celebrating the written word.</a></p>\n</li>\n<li readability=\"3\">\n<h3><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=rmwhitti-300-6zip0xir.html\">Lectures — William Winter Institute Keynote Address</a></h3>\n<p><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=rmwhitti-300-6zip0xir.html\">Dr. Susan Neiman will provide the keynote address, 'Learning from the Germans: What Can They Teach Us about Racial Reconciliation'</a></p>\n</li>\n<li readability=\"4\">\n<h3><a href=\"http://olemiss.edu/#\">Campus News — Conversation with Dr. Susan Neiman</a></h3>\n<p><a href=\"http://olemiss.edu/#\">Dr. Neiman will speak with campus activists on memory and iconography on Thursday, March 3 at the William Winter Institute in Lamar Hall</a></p>\n</li>\n<li readability=\"6\">\n<h3><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=nicwea-300-pxgOJp5E.pdf\">Class News — Watercolor In London Meeting THIS Thursday!</a></h3>\n<p><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=nicwea-300-pxgOJp5E.pdf\">Summer Study Abroad Watercolor in London meeting THIS THURSDAY, March 3rd, Noon, Meek 110. Don't miss out and BRING A FRIEND!</a></p>\n</li>\n<li readability=\"5\">\n<h3><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=mlong-300-nGVc0sVA.html\">Lectures — Porter L. Fortune, Jr. History Symposium</a></h3>\n<p><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=mlong-300-nGVc0sVA.html\">Dr. Robert Karl, of Princeton University, will present the Keynote Address at the 2016 Porter L. Fortune, Jr. History Symposium.</a></p>\n</li>\n<li readability=\"3\">\n<h3><a href=\"http://goo.gl/forms/MCxDZ1E3tZ\">Green Initiative — ASB Seeks Input on Bicycle Issues</a></h3>\n<p><a href=\"http://goo.gl/forms/MCxDZ1E3tZ\">ASB is working on resolutions to improve the bike community on campus! Let us know what you think by taking this quick survey-new link.</a></p>\n</li>\n<li readability=\"2\">\n<h3><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=jamunson-300-PkJPHikV.pdf\">Academics — Breakfast For Dinner? It Is At Lenoir Dining!</a></h3>\n<p><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=jamunson-300-PkJPHikV.pdf\">It's breakfast for dinner this week at Lenoir Dining. Make your reservations online at lenoirdining.com or by calling 662-915-1863.</a></p>\n</li>\n<li readability=\"2\">\n<h3><a href=\"http://olemiss.edu/#\">Invitation — Tallahatchie Toastmasters Meeting</a></h3>\n<p><a href=\"http://olemiss.edu/#\">Anyone interested in improving their communication and leadership skills are welcome to attend the meeting. Guests are always welcome!</a></p>\n</li>\n<li readability=\"4\">\n<h3><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=cekalu-300-pukIwGmb.html\">Invitation — Oxford Writers Featured at Overby Center</a></h3>\n<p><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=cekalu-300-pukIwGmb.html\">The extraordinary literary community in Oxford will be the subject of a panel discussion at the Overby Center, followed by a reception.</a></p>\n</li>\n<li readability=\"1\">\n<h3><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=rebeccac-300-hWem8ZK1.html\">Conferences — Oxford Conference for the Book</a></h3>\n<p><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=rebeccac-300-hWem8ZK1.html\">Celebrating the written word.</a></p>\n</li>\n<li readability=\"6\">\n<h3><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=mlong-300-XkqfHOm8.html\">Brown Bag — Croft Professor Lecture Series: Dr. Joshua First</a></h3>\n<p><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=mlong-300-XkqfHOm8.html\">Dr. Joshua First, Croft Asst. Prof. of History, will speak on 'Ukraine's Revolution and Documentary Nationalism'; Fri., March 4; Croft 107.</a></p>\n</li>\n<li readability=\"5\">\n<h3><a href=\"http://olemiss.edu/#\">Campus News — Lunch and Learn with Dr. Susan Neiman</a></h3>\n<p><a href=\"http://olemiss.edu/#\">Dr. Susan Neiman and UM students will discuss her book, Moral Clarity, during a lunch and learn at the William Winter Institute.</a></p>\n</li>\n<li readability=\"2\">\n<h3><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=jrbreela-300-sk5TCBl9.pdf\">Arts and Culture — Colloquium: Thalberg in the American South</a></h3>\n<p><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=jrbreela-300-sk5TCBl9.pdf\">This colloquium will be taught by Dr. Ian Hominick in room 136 (Small Ensemble Room) on Friday at 4 o'clock.</a></p>\n</li>\n<li>\n<h3><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=kcozart-300-aSL2Edda.pdf\">Conferences — 2016 Isom Student Gender Conference</a></h3>\n<p><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=kcozart-300-aSL2Edda.pdf\">'Undoing the Norms'</a></p>\n</li>\n<li readability=\"1\">\n<h3><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=ikaufman-300-dsdTiMuB.html\">Invitation — 'El Cafe' de los Lunes' Meets this Monday</a></h3>\n<p><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=ikaufman-300-dsdTiMuB.html\">Come practice your Spanish with us in a relaxed setting. Join us every Monday.</a></p>\n</li>\n<li readability=\"3\">\n<h3><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=jharris-300-uAfBgf3h.html\">UM Memo — UM Faculty/Staff Appeals Committee</a></h3>\n<p><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=jharris-300-uAfBgf3h.html\">Location: Mississippi Small Business Development Center Boardroom, 122 Jeanette Phillips Drive. See details for map.</a></p>\n</li>\n<li readability=\"3\">\n<h3><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=blair-300-5fkNFdmA.pdf\">Study Abroad — Scholarships for Study Abroad in China!</a></h3>\n<p><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=blair-300-5fkNFdmA.pdf\">UM has received two generous Chinese Government Scholarships for study in China during AY 2016/17. See Study Abroad for more info!</a></p>\n</li>\n<li readability=\"1\">\n<h3><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=jharris-300-M98IbaPW.html\">Invitation — How to Develop a Business Plan (Oxford)</a></h3>\n<p><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=jharris-300-M98IbaPW.html\">This seminar is designed to assist in preparing a business plan.</a></p>\n</li>\n<li readability=\"2\">\n<h3><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=mdennis-300-soCfN09J.pdf\">Library — Citation Management Workshop</a></h3>\n<p><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=mdennis-300-soCfN09J.pdf\">Join Buffy Choinski in Room 106E to learn more about using RefWorks and other tools to make your bibliographies easier!</a></p>\n</li>\n<li readability=\"1\">\n<h3><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=rebeccac-300-efSwrORQ.html\">Brown Bag — 'Collaboration'</a></h3>\n<p><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=rebeccac-300-efSwrORQ.html\">Brown Bag Lecture with Ann Fisher-Wirth and Maude Schuyler Clay.</a></p>\n</li>\n<li readability=\"3\">\n<h3><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=tbbaker-300-DeTNJicl.html\">Campus News — Register for Ole Miss Big Event 2016</a></h3>\n<p><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=tbbaker-300-DeTNJicl.html\">Sign up to be a part of the largest day of community service in the state of Mississippi! Registration is open on myOleMiss until 3/21.</a></p>\n</li>\n<li readability=\"3\">\n<h3><a href=\"http://technews.olemiss.edu/online-timesheets-now-required-eligible-um-employees/\">TECHNews — Online Timesheets Required - Eligible UM Employees</a></h3>\n<p><a href=\"http://technews.olemiss.edu/online-timesheets-now-required-eligible-um-employees/\">Beginning in early March,all eligible employees will be REQUIRED to record their time using the ESS Timesheet application within myOleMiss.</a></p>\n</li>\n<li readability=\"3\">\n<h3><a href=\"http://green.olemiss.edu/propose-a-project/\">Green Initiative — Green Fund Proposals Due March 23</a></h3>\n<p><a href=\"http://green.olemiss.edu/propose-a-project/\">Students, faculty &amp; staff - Receive funding for your sustainability project! Green Fund proposals are due March 23.</a></p>\n</li>\n<li readability=\"4\">\n<h3><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=dawiley-300-xvEUewt4.html\">IT Alert — Some IT Services Unavailable March 14</a></h3>\n<p><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=dawiley-300-xvEUewt4.html\">System upgrades are scheduled to begin 12 a.m. on Monday, March 14. Some IT services will be unavailable until this work is completed.</a></p>\n</li>\n<li readability=\"3\">\n<h3><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=whamilton-300-vNtM6yzN.html\">Parking and Transportation — New Road Construction Near Rebel Drive Water Tower</a></h3>\n<p><a href=\"https://secure1.olemiss.edu/tools/ViewUserFile.jsp?filename=whamilton-300-vNtM6yzN.html\">Starting in March, a new road will be constructed as Phase I of the North Residential Parking Garage project.</a></p>\n</li>\n</ul></section></div>\n<hr/><hr/><section id=\"sports\" class=\"c7\"><a href=\"http://www.olemisssports.com\" class=\"link2all\">olemisssports.com</a>\n<h2>UM Athletics</h2>\n<div class=\"games\">\n<div class=\"game\">\n<h3>Men's Basketball</h3>\n<div class=\"team win\"><img src=\"http://web6.olemiss.edu/mercury/sports/10431523.olemiss.png\" alt=\"team logo\"/> Ole Miss 86</div>\n<div class=\"team\"><img src=\"http://web6.olemiss.edu/mercury/sports/10164724.msst.png\" alt=\"team logo\"/> Miss. St. 78</div>\n<p>Wednesday, Mar. 2</p>\n</div>\n<div class=\"game\">\n<h3>Men's Baseball</h3>\n<div class=\"team win\"><img src=\"http://web6.olemiss.edu/mercury/sports/10431523.olemiss.png\" alt=\"team logo\"/> Ole Miss 9</div>\n<div class=\"team\"><img src=\"http://web6.olemiss.edu/mercury/sports/10166676.memphis.png\" alt=\"team logo\"/> Memphis 7</div>\n<p>Wednesday, Mar. 2</p>\n</div>\n<div class=\"game\">\n<h3>Women's Basketball</h3>\n<div class=\"team\"><img src=\"http://web6.olemiss.edu/mercury/sports/10431523.olemiss.png\" alt=\"team logo\"/> Ole Miss 59</div>\n<div class=\"team win\"><img src=\"http://web6.olemiss.edu/mercury/sports/10166693.vanderbilt.png\" alt=\"team logo\"/> Vanderbilt 74</div>\n<p>Wednesday, Mar. 2</p>\n</div>\n</div>\n</section><footer/>\n",
258 "annotations": [],
259 "mimetype": "text/html",
260 "language": "en",
261 "reading_time": 4,
262 "domain_name": "olemiss.edu",
263 "tags": []
264 },
265 {
266 "is_archived": 1,
267 "created_at": "2016-09-08T11:55:58+0200",
268 "updated_at": "2016-09-08T11:57:16+0200",
269 "is_starred": 0,
270 "id": 96,
271 "title": "FinnChristiansen.de Jetzt Dank Let’s Encrypt Per HTTPS Erreichbar",
272 "url": "https://www.finnchristiansen.de/2015/12/06/finnchristiansen-de-jetzt-dank-lets-encrypt-per-https-erreichbar/",
273 "content": "<div class=\"entry-content-thumbnail\"><img width=\"750\" height=\"179\" src=\"https://www.finnchristiansen.de/wp-content/uploads/2015/12/letsencrypt-1024x245.png\" class=\"attachment-large size-large wp-post-image\" alt=\"letsencrypt\" srcset=\"https://www.finnchristiansen.de/wp-content/uploads/2015/12/letsencrypt-300x72.png 300w, https://www.finnchristiansen.de/wp-content/uploads/2015/12/letsencrypt-1024x245.png 1024w, https://www.finnchristiansen.de/wp-content/uploads/2015/12/letsencrypt.png 1025w\" sizes=\"(max-width: 750px) 100vw, 750px\"/></div><div class=\"entry-content\">\n<p>Wenn ich in meinen FeedReader blicke, tauchen dort viele Beiträge zu <a href=\"https://letsencrypt.org/\" target=\"_blank\">Let’s Encrypt</a> auf. <a href=\"https://letsencrypt.org/2015/12/03/entering-public-beta.html\" target=\"_blank\">Seit Donnerstag befindet sich Let’s Encrypt in der offenen Beta Phase</a> und nun kann jeder ohne vorherige Freischaltung die kostenlosen SSL Zertifikate beantragen. Das habe ich natürlich auch getan.<br/></p>\n<p>Viele meiner Seiten oder Dienste waren zwar auch schon vorher SSL-verschlüsselt erreichbar, aber meistens habe ich dafür selbstsignierte Zertifkate bzw. eine selbstsignierte Certificate Authority verwendet. Für meine ownCloud Installation hatte ich mir sogar mal ein Zertifikat gekauft, da auch andere die Cloud nutzen und ich so ohne große Erklärungen ownCloud Links versenden konnte.</p>\n<p>Zur Verwendung von Let’s Encrypt brauche ich nicht mehr viel sagen, das haben schon <a href=\"https://thomas-leister.de/internet/lets-encrypt-zertifikate-im-manual-mode-abholen/\" target=\"_blank\">Thomas Leister</a>, <a href=\"http://linuxundich.de/gnu-linux/ssl-zertifikat-lets-encrypt-synology-nas/\" target=\"_blank\">Christoph Langner</a> oder andere getan. <a href=\"https://tuxproject.de/blog/2015/12/virtualisierungswahn/\" target=\"_blank\">Auch Kritik wird geäußert</a>, da der Let’s Encrypt Client verhältnismäßig aufgebläht ist und das Erstellen eines CSRs (Zertifikatsantrag) schon ewig mit openssl auf der Konsole bestens funktioniert. Let’s Encrypt möchte diesen Prozess aber vereinfachen und sogar die Installation des Zertifikates vereinfachen und sogar automatisieren.</p>\n<p>Ich habe meine Zertifikate mit Let’s Encrypt mit meinem Arch Linux Desktop im „Manual Mode“ erstellt und per Hand auf die Server verteilt. Das ist mir lieber, als dass ich die Software auf jeden Server installiere. Handarbeit ist eh notwendig, da ich <a href=\"https://www.finnchristiansen.de/2015/08/27/tlsa-records-fuer-dane-erstellen/\" target=\"_blank\">DANE</a> einsetze und die Records eh anpassen musste.</p>\n<p>Leider können nur Zertifikate für 10 Subdomains / Host-Records einer Domain beantragt werden. Das habe ich für die 10 wichtigsten getan, die übrigen 15 kann ich hoffentlich bald nachholen. Bisher gibt es eine entsprechende Fehlermeldung, falls man versucht, mehr Zertifikate zu beantragen:</p>\n<div id=\"crayon-56d87312178e8166484796\" class=\"crayon-syntax crayon-theme-classic crayon-font-monaco crayon-os-pc print-yes notranslate c6\" data-settings=\" minimize scroll-mouseover\">\n<div class=\"crayon-toolbar crayon-tools c1\" data-settings=\" mouseover overlay hide delay\">\n<div class=\"crayon-button crayon-nums-button crayon-button-icon\" title=\"Zeilennummern\"/>\n<div class=\"crayon-button crayon-plain-button crayon-button-icon\" title=\"Unformatierte Code-Ansicht\"/>\n<div class=\"crayon-button crayon-wrap-button crayon-button-icon\" title=\"Zeilenumbruch umschalten\"/>\n<div class=\"crayon-button crayon-expand-button crayon-button-icon\" title=\"Code aufklappen\"/>\n<div class=\"crayon-button crayon-copy-button crayon-button-icon\" title=\"Copy\"/>\n<div class=\"crayon-button crayon-popup-button crayon-button-icon\" title=\"Code in einem neuen Fenster anzeigen\"/>\n</div>\n<div class=\"crayon-info c2\"/>\n<div class=\"crayon-plain-wrap\">\n<textarea wrap=\"soft\" class=\"crayon-plain print-no c3\" data-settings=\"dblclick\" readonly=\"readonly\">\nError: urn:acme:error:rateLimited :: There were too many requests of a given type :: Error creating new cert :: Too many certificates already issued for: finnchristiansen.de\n</textarea></div>\n<div class=\"crayon-main\">\n<table class=\"crayon-table\"><tr class=\"crayon-row\"><td class=\"crayon-nums\" data-settings=\"show\">\n<div class=\"crayon-nums-content crayon-num c4\">1</div>\n</td>\n<td class=\"crayon-code\">\n<div class=\"crayon-pre crayon-line c5\">Error: urn:acme:error:rateLimited :: There were too many requests of a given type :: Error creating new cert :: Too many certificates already issued for: finnchristiansen.de</div>\n</td>\n</tr></table></div>\n</div>\n<p>Die Zertifikate sind 90 Tage gültig, so dass ich mir eine Erinnerung im Kalender hinterlegt habe, damit ich die Zertifikate erneuern kann. Bis dahin: Viel Spaß beim Erstellen und Einbauen der Zertifikate.</p>\n<p><em>Beitragsbild-Quelle: <a href=\"https://letsencrypt.org/\" target=\"_blank\">LetsEncrypt.org</a> – <a href=\"http://creativecommons.org/licenses/by/3.0/\">Creative Commons Attribution 3.0 License</a>.</em></p>\n</div>",
274 "annotations": [],
275 "mimetype": "text/html",
276 "language": "de-DE",
277 "reading_time": 1,
278 "domain_name": "www.finnchristiansen.de",
279 "tags": []
280 },
281 {
282 "is_archived": 1,
283 "created_at": "2016-09-08T11:55:58+0200",
284 "updated_at": "2016-09-08T11:57:16+0200",
285 "is_starred": 0,
286 "id": 82,
287 "title": "Le développeur et l'ingénierie logicielle",
288 "url": "http://wemucs.com/le-developpeur-et-lingenierie-logicielle/",
289 "content": "<p><strong>Etre un développeur, ce n'est pas juste pisser du code. Non. L'architecture de l'applicatif est bien plus importante et la conception fera la différence entre un bon et mauvais développeur.</strong></p><p>Julien Dollon a tout résumé en un seul tweet :<br/></p>\n<p>Alors, voyons un peu ce qui paraît essentiel pour progresser dans le développement et l'ingénierie logicielle plus généralement.</p>\n<h2 id=\"lesbases\">Les bases</h2>\n<p>Peu importe votre âge, que vous ayez fait de longues études dans une école prestigieuse ou non : vous devez maîtriser vos bases. J'entends par là :</p>\n<ul><li>Savoir développer sans framework ni librairie</li>\n<li>Connaitre la programmation orientée objet</li>\n<li>Etre à l'aise avec une base de données</li>\n<li>Avoir des notions de réseau</li>\n<li>S'intéresser au hardware</li>\n</ul><p>Oui, parce que si vous maîtrisez vos bases, vous comprendrez que tous les langages manipulent des données qui passent leur temps à transiter entre unités de calcul et de stockage.</p>\n<p><strong>Un bon développeur doit pouvoir changer de plateforme ou de langage très rapidement</strong>, s’imprégner d’une nouvelle base de données ou même d’un nouveau protocole en très peu de temps. A chaque fois, ce n'est que question de logique et d'implémentation.</p>\n<h2 id=\"lacuriosit\">La curiosité</h2>\n<p>L'intégrisme mène au côté obscur. Et puis, vous risquez de finir votre carrière à bosser sur des projets fait en ASP 2.0 ou en PHP 4. Chacun son truc mais ce qui fait la beauté du monde, c'est <strong>la diversité</strong>.</p>\n<p>Il est vraiment important d'être à l'aise avec un environnement et un langage. Vous coderez plus vite et vous contournerez les pièges. De l'autre côté, être ouvert sera votre plus grande force. Le PHP ou le Java ne sont pas les seuls : vous pourriez être surpris par la simplicité et la rapidité de Python et du Go, ou même des outils Unix/Linux codés en C.</p>\n<p>Si vous avez un peu de temps, n'hésitez pas à vous amusez à développer de tous petits applicatifs pour découvrir un nouveau langage. Après tout, les histoires d'amour sont souvent inattendues !</p>\n<h2 id=\"ladettetechnique\">La dette technique</h2>\n<p>On entre un peu plus dans le vif du sujet. Maîtriser ses bases, c'est bien. Connaître plusieurs langages et être à l'aise avec des frameworks, c'est mieux. Imaginer un logiciel pour qu'il soit encore en prod dans 10 ans, c'est la réussite !</p>\n<h4 id=\"projetscourtsetabsencedemaintenance\">Projets courts et absence de maintenance</h4>\n<p>Un certain nombre de développeurs bossent sur des projets assez courts (entre 3 mois et 1 an) sans en assumer la maintenance. Au final, c'est soit un autre développeur qui reprendra les spaghettis pour le debugger ou essayer d'y ajouter une fonctionnalité.</p>\n<p>Alors ça peut être super cool :</p>\n<ul><li>on peut changer souvent de techno / librairies / frameworks</li>\n<li>on peut sortir du concret très vite</li>\n<li>on peut plus facilement contribuer à l'open source avec de nouveaux projets</li>\n</ul><p>Mais vous allez inévitablement contribuer à la plus grande frustration du développeur : reprendre du code qui a plusieurs années écrit par quelqu'un d'autre… Au final, soit vous ferez un hack, soit vous ferez une librairie à part sur un patron de conception différent, <strong>augmentant la dette technique</strong>.</p>\n<p><img src=\"http://wemucs.com/content/images/2016/02/65748811.jpg\" alt=\"Shitty code\"/></p>\n<h4 id=\"projetslongsetddis\">Projets longs et dédiés</h4>\n<p>De l'autre côté, si vous travaillez chez un éditeur ou un \"client final\", vous aurez sans doute l'opportunité de travailler sur des projets qui resteront en production durant des années, voir des dizaines d'années. Et là, la vision que vous allez avoir est quelque peu différente.</p>\n<p>Je ne vais pas revenir sur ce qu'est la dette technique. <a href=\"http://blog.dollon.net/la-dette-technique/\">Julien l'a très bien décrit dans son article</a>, que je vous invite à lire à la suite.</p>\n<p>Ne pas créer de dette technique involontaire et contrôler la volontaire, ce sera votre plus grande mission. Et pour cela, pas de magie : c'est <strong>l'expérience</strong> qui parlera. Les vieux ne sont pas tous des cons et ils vous donneront souvent de précieux conseils !<br/>La plus grande réussite, c'est de pouvoir ajouter des fonctionnalités dans 10 ans à votre projet en suivant la même conception de départ avec toutes les briques déjà en place.</p>\n<p>Quelques petites remarques en vrac :</p>\n<ul><li>Bien nommer ses variables, fonctions et classes : elles doivent s'auto-décrire sans commentaire, représenter la réalité sans confusion</li>\n<li>La POO, ce n'est pas automatique : le fonctionnel permet de découpler plus facilement les briques</li>\n<li>Les micro-services, c'est bien, mais il faut faire attention de ne pas devoir gérer 50 bases de projets différents</li>\n<li>Les tests unitaires et fonctionnels sont aussi importants que l'implémentation</li>\n<li>Les librairies externes, oui, mais elles ne doivent pas devenir un poids si elles deviennent trop couplées à votre projet</li>\n<li>Et j'en passe !</li>\n</ul><h2 id=\"rflectionvsttebaisse\">Réflection vs tête baissée</h2>\n<p>Dans une vie de développeur, on rencontre à la fois des projets simples, répétitifs et un peu bateau. Ce qui nous motive réellement, ce sont les <strong>défis complexes</strong> à résoudre et heureusement, on en rencontre très souvent.</p>\n<p>Démarrer à coder tout de suite, c'est foncer tête baissée et créer des fondations fragiles. Au final, vous commencez à poser des briques pour construire votre maison sans en avoir dessiné le plan précis.</p>\n<ul><li>Comprenez les besoins métiers, et mettez-vous à la place des utilisateurs. Passez beaucoup de temps avec eux pour tout expliciter et les avertir de ce que vous pourrez et ne pourrez pas faire</li>\n<li>Faites une étude sur l'architecture et les technologies possibles : prenez un papier, un crayon et représentez-les</li>\n<li>Soyez impartial de votre décision : mettez les points positifs en regard des négatifs pour chaque possibilité</li>\n<li>Demandez d'autres avis que le votre en organisant des brainstorming. <strong>C'est en équipe que l'on avance le plus</strong>, vous mettrez sans doute en évidence des points que vous aviez oublié et il faut savoir reconnaitre que vous n'aviez pas la meilleure solution !</li>\n</ul><h2 id=\"seremettreenquestion\">Se remettre en question</h2>\n<p>Il ne faut pas seulement avoir l'impression de faire du bon travail, il est important de s'en assurer. La définition d'un \"bon\" travail va varier énormément en fonction des contextes et en fonction des attentes. Cependant, au fur et à mesure de l'avancé de vos projets, <strong>faites un point sur ce que vous venez de créer</strong> : mettez en avant les points forts avec en perspective les parties faibles.</p>\n<p><img src=\"http://wemucs.com/content/images/2016/02/continuous-improvement-cycle.gif\" alt=\"Continuous Improvement Cycle\"/></p>\n<p>Il est évident qu'avec le recul, après mise en production et sans doute les premiers bugs ou comportements non voulus, ou même simplement la difficulté de faire évoluer vos outils, vous pourrez réellement voir ce qui a cloché et comment l'éviter à l'avenir. C'est ça le travail d'un développeur et d'un ingénieur en général : aller de l'avant en étant lucide sur le passé.</p>\n<p>Oh, et surtout <strong>pas de vanité</strong>. Utilisez des métriques qui veulent vraiment dire quelque chose, n'essayez pas de cacher la vilaine classe FileUtils qui devient un cauchemar : il faut savoir être sincère dans ces moments là.</p>\n<h2 id=\"enrsum\">En résumé…</h2>\n<p>Il faut de tout pour faire un monde ! Si vous préférez changer de projets tous les 4 matins, être à l'affut de toutes les nouveautés, alors restez comme vous êtes et soyez des précurseurs !</p>\n<p>A l'inverse, si vous désirez vraiment entrer dans de la conception logicielle, la pure et dure, alors je vous conseille fortement de travailler sur des projets au long court. Cela ne vous empêchera pas de vous éclatez, mais vous allez pouvoir vraiment réfléchir à ce qu'est un bon logiciel et ce qui ne l'est pas.</p>\n<p>Et puis, si vous le pouvez, <strong>bossez avec des pointures</strong> dans le domaine. Apprenez sur le tas avec des séniors qui ont des années de dev dans les baskets. Ils seront sans doute de précieux conseils, même si votre première Pull Request aura sans doute 3 commentaires par ligne !</p>\n<p><img src=\"http://wemucs.com/content/images/2016/02/57772588.jpg\" alt=\"Self merged\"/></p>\n",
290 "annotations": [],
291 "mimetype": "text/html",
292 "reading_time": 6,
293 "domain_name": "wemucs.com",
294 "tags": []
295 },
296 {
297 "is_archived": 1,
298 "created_at": "2016-09-08T11:55:58+0200",
299 "updated_at": "2016-09-08T11:57:16+0200",
300 "is_starred": 0,
301 "id": 78,
302 "title": "The Role of Methylation in Gene Expression",
303 "url": "http://www.nature.com/scitable/topicpage/the-role-of-methylation-in-gene-expression-1070",
304 "content": "<p>Today, researchers know that DNA methylation occurs at the cytosine bases of eukaryotic DNA, which are converted to 5-methylcytosine by DNA methyltransferase (DNMT) enzymes. The altered cytosine residues are usually immediately adjacent to a guanine nucleotide, resulting in two methylated cytosine residues sitting diagonally to each other on opposing DNA strands. Different members of the DNMT family of enzymes act either as <em>de novo</em> DNMTs, putting the initial pattern of methyl groups in place on a DNA sequence, or as maintenance DNMTs, copying the methylation from an existing DNA strand to its new partner after replication. Methylation can be observed by staining cells with an immunofluorescently labeled antibody for 5-methylcytosine. In mammals, methylation is found sparsely but globally, distributed in definite CpG sequences throughout the entire genome, with the exception of CpG islands, or certain stretches (approximately 1 kilobase in length) where high CpG contents are found. The methylation of these sequences can lead to inappropriate gene silencing, such as the <a href=\"http://www.nature.com/scitable/topicpage/Tumor-Suppressor-TS-Genes-and-the-Two-887\" onclick=\"return isUDV('/topicpage/Tumor-Suppressor-TS-Genes-and-the-Two-887');\" title=\"silencing of tumor suppressor genes in cancer cells\">silencing of tumor suppressor genes in cancer cells</a>.</p>\n<p>Currently, the mechanism by which <em>de novo</em> DNMT enzymes are directed to the sites that they are meant to silence is not well understood. However, researchers have determined that some of these DNMTs are part of <a href=\"http://www.nature.com/scitable/topicpage/Chromatin-Remodeling-in-Eukaryotes-1082\" onclick=\"return isUDV('/topicpage/Chromatin-Remodeling-in-Eukaryotes-1082');\" title=\"chromatin-remodeling complexes\">chromatin-remodeling complexes</a> and serve to complete the remodeling process by performing on-the-spot DNA methylation to lock the closed shape of the chromatin in place.</p>\n<p>The roles and targets of DNA methylation vary among the kingdoms of organisms. As previously noted, among Animalia, mammals tend to have fairly globally distributed CpG methylation patterns. On the other hand, invertebrate animals generally have a \"mosaic\" pattern of methylation, where regions of heavily methylated DNA are interspersed with nonmethylated regions. The global pattern of methylation in mammals makes it difficult to determine whether methylation is targeted to certain gene sequences or is a default state, but the CpG islands tend to be near transcription start sites, indicating that there is a recognition system in place.</p>\n<p>Plantae are the most highly methylated eukaryotes, with up to 50% of their cytosine residues exhibiting methylation. Interestingly, in Fungi, only repetitive DNA sequences are methylated, and in some species, methylation is absent altogether, or it occurs on the DNA of <a href=\"http://www.nature.com/scitable/topicpage/Transposons-or-Jumping-Genes-Not-Junk-DNA-1211\" onclick=\"return isUDV('/topicpage/Transposons-or-Jumping-Genes-Not-Junk-DNA-1211');\" title=\"Transposons\">transposable elements</a> in the genome. The mechanism by which the transposons are recognized and methylated appears to involve <a href=\"http://www.nature.com/scitable/topicpage/Small-Non-coding-RNA-and-Gene-Expression-1078\" onclick=\"return isUDV('/topicpage/Small-Non-coding-RNA-and-Gene-Expression-1078');\" title=\"siRNA\">small interfering RNA</a> (siRNA). The whole silencing mechanism invoking DNMTs could be a way for these organisms to defend themselves against viral infections, which could generate transposon-like sequences. Such sequences can do less harm to the organism if they are prevented from being expressed, although replicating them can still be a burden (Suzuki &amp; Bird, 2008). In other fungi, such as fission yeast, siRNA is involved in gene silencing, but the targets include structural sequences of the chromosomes, such as the centromeric DNA and the telomeric repeats at the chromosome ends. </p>\n",
305 "annotations": [],
306 "mimetype": "text/html",
307 "language": "en",
308 "reading_time": 2,
309 "domain_name": "www.nature.com",
310 "tags": []
311 },
312 {
313 "is_archived": 1,
314 "created_at": "2016-09-08T11:55:58+0200",
315 "updated_at": "2016-09-08T11:57:16+0200",
316 "is_starred": 0,
317 "id": 53,
318 "title": "E-Mail-Adresse kostenlos, FreeMail, De-Mail & Nachrichten",
319 "url": "http://web.de",
320 "content": "<div class=\"r2\">\n<div class=\"slider-container slider\" data-active-slide=\"1\">\n<div class=\"teaser-content\" data-slide-id=\"1\" readability=\"12\">\nNPD setzt auf Verzögerungen\n<p>Rechtsextremisten kämpfen vor Verfassungsgericht um ihr Überleben.</p>\n</div>\n<div class=\"teaser-content\" data-slide-id=\"3\" readability=\"8\">\n<a href=\"http://web.de/magazine/politik/frank-buschmann-schockiert-menschen-geschrieben-31389104\" data-teaser-id=\"31389104\" data-teaser-type=\"DEFAULT\">Schockiert über den Hass</a>\n<p>Kommentator Frank Buschmann spricht über Reaktionen auf sein Merkel-Lob.</p>\n</div>\n</div>\n</div>\n<div class=\"r1\">\n<div class=\"slider-container slider\" data-active-slide=\"1\">\n<div class=\"teaser-content\" data-slide-id=\"2\" readability=\"11\">\nSchlägerei nach One-Night-Stand</div>\n<div class=\"teaser-content\" data-slide-id=\"3\" readability=\"11\">\nPartei \"Die Rechte\" sorgt für Eklat</div>\n<div class=\"teaser-content\" data-slide-id=\"4\" readability=\"11\">\nScheibe vereist? Das hilft!</div>\n</div>\n<ul class=\"news-list\"><li class=\"first active\"><a href=\"http://web.de/magazine/wissen/deutscher-weltenbummler-mumifiziert-yacht-gefunden-31382634\" data-teaser-id=\"31382634\" data-teaser-type=\"DEFAULT\" data-reco-teaser=\"1\"><img src=\"http://i1.web.de/image/734/31382734,pd=3,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Yacht\" width=\"72\" height=\"54\"/></a> Die Yacht des deutschen Weltenbummlers Manfred Fritz Bajorat wurde vor der philippinischen Küste gefunden.</li>\n<li><a href=\"http://web.de/magazine/panorama/one-night-stand-endet-unschoenem-ausgang-31384014\" data-teaser-id=\"31384014\" data-teaser-type=\"DEFAULT\" data-reco-teaser=\"1\"><img src=\"http://i1.web.de/image/078/31384078,pd=3,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"One-Night-Stand\" width=\"72\" height=\"54\"/></a> Ein One-Night-Stand zweier Teenager endet anders als geplant.</li>\n<li><a href=\"http://web.de/magazine/politik/plakat-partei-rechte-haengen-plakate-31384064\" data-teaser-id=\"31384064\" data-teaser-type=\"DEFAULT\" data-reco-teaser=\"1\"><img src=\"http://i2.web.de/image/088/31384088,pd=3,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"\" width=\"72\" height=\"54\"/></a> Das Landeskriminalamt in Sachsen-Anhalt prüft den Verdacht der Volksverhetzung wegen eines Wahlplakats der Partei \"Die Rechte\". (Symbolbild)</li>\n<li class=\"last\"><a href=\"http://www.auto-service.de/videos/76198-scheibe-vereist-hilft.html\" data-teaser-id=\"31384058\" data-teaser-type=\"AUTOSERVICE\" target=\"_blank\" data-reco-teaser=\"1\"><img src=\"http://i1.web.de/image/054/31384054,pd=3,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Life Hack Eiskratzen\" width=\"72\" height=\"54\"/></a> Life Hack Eiskratzen</li>\n</ul></div>\n<div class=\"r1\">\n<div class=\"r1 news-content teaser-content\" readability=\"8\">\n<a href=\"http://web.de/magazine/sport/fussball/bundesliga/fc-bayern-pep-guardiola-wagt-experimente-31385492\" data-teaser-id=\"31385492\" data-teaser-type=\"DEFAULT\" data-reco-teaser=\"1\">Spieler leiden unter Pep</a>\n<p>Guardiola hat Angst vor dem Scheitern und opfert für den Erfolg einiges.</p>\n</div>\n</div>\n<div class=\"r1\">\n<div class=\"slider-container slider\" data-active-slide=\"1\">\n<div class=\"teaser-content\" data-slide-id=\"1\">\n<a href=\"http://www.auto-service.de/news/76208-consumer-reports-besten-automarken-welt.html\" data-teaser-id=\"31383558\" data-teaser-type=\"AUTOSERVICE\" target=\"_blank\">Die besten Automarken der Welt</a></div>\n<div class=\"teaser-content\" data-slide-id=\"2\" readability=\"12\">\nHeidi, zieh das wieder aus!</div>\n<div class=\"teaser-content\" data-slide-id=\"3\" readability=\"11\">\nDie besten Gebrauchten 2016</div>\n<div class=\"teaser-content\" data-slide-id=\"4\" readability=\"11\">\nOscars: Kate feiert mit ihrem Leo</div>\n</div>\n<ul class=\"news-list\"><li class=\"first active\"><a href=\"http://www.auto-service.de/news/76208-consumer-reports-besten-automarken-welt.html\" data-teaser-id=\"31383558\" data-teaser-type=\"AUTOSERVICE\" target=\"_blank\"><img src=\"http://i2.web.de/image/554/31383554,pd=3,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Consumer Reports: Das sind die zehn besten Automarken der Welt!\" width=\"72\" height=\"54\"/></a> Consumer Reports: Das sind die zehn besten Automarken der Welt!</li>\n<li><a href=\"http://web.de/magazine/unterhaltung/tv-film/oscar/oscar-2016-tops-flops-oscar-roben-31382576\" data-teaser-id=\"31382576\" data-teaser-type=\"SLIDESHOW\"><img src=\"http://i0.web.de/image/552/31383552,pd=3,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Heidi Klum (l.) Flop, Charlize Theron Top!\" width=\"72\" height=\"54\"/></a> So nahe beieinander liegen manchmal die Tops und Flops auf dem Roten Teppich: Heidi Klum (l.) Flop, Charlize Theron Top!</li>\n<li><a href=\"http://www.auto-service.de/news/76134-gebrauchtwagenreport-2016-besten-gebrauchten-deutschland.html\" data-teaser-id=\"31379186\" data-teaser-type=\"AUTOSERVICE\" target=\"_blank\"><img src=\"http://i1.web.de/image/182/31379182,pd=4,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Gebrauchtwagenreport 2016: Das sind die besten Gebrauchten in Deutschland\" width=\"72\" height=\"54\"/></a> Gebrauchtwagenreport 2016: Das sind die besten Gebrauchten in Deutschland</li>\n<li class=\"last\"><a href=\"http://web.de/magazine/unterhaltung/tv-film/oscar/oscars-2016-schoensten-bilder-oscar-nacht-31382570\" data-teaser-id=\"31382570\" data-teaser-type=\"SLIDESHOW\"><img src=\"http://i1.web.de/image/776/31382776,pd=2,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Kate Winslet, Leonardo DiCaprio, Oscars 2016\" width=\"72\" height=\"54\"/></a> Kate Winslet feiert mit Leonardo DiCaprio.</li>\n</ul></div>\n<div class=\"r1\">\n<div class=\"slider-container slider\" data-active-slide=\"1\">\n<div class=\"service-content slide-lotto\" data-slide-id=\"1\" readability=\"36\">WEB.DE Lottoservice\n<div class=\"next-draw\" readability=\"7\">Jackpothöhe am Mittwoch, 02.03.16\n<div class=\"next-draw-content\">\n<p class=\"jackpot\">1</p>\n<a href=\"http://lotto.web.de/webshop/product/lottonormal/?partnerId=0WEHOMDISP&amp;advertisementId=0HPMODU000000000JACKPOTHO000LO000000000000\"><img src=\"http://img.ui-portal.de/homepage/img/webde/bg/lotto_button.png\" height=\"22\" width=\"104\" alt=\"Lotto spielen\"/></a> Chance 1:140 Mio.</div>\n</div>\n<div class=\"last-draw\" readability=\"7\">Ziehung vom Samstag, 27.02.16\n<div class=\"winning-numbers\">\n<ol class=\"numbers\"><li>7</li>\n<li>10</li>\n<li>15</li>\n<li>25</li>\n<li>37</li>\n<li>49</li>\n</ol>\nSZ\n<ol class=\"numbers\"><li>7</li>\n</ol></div>\n</div>\nAb 18 Jahren. Suchtgefahr. Hilfe bei www.bzga.de.</div>\n<div class=\"service-content slide-eurojackpot\" data-slide-id=\"2\" readability=\"36\">WEB.DE Lottoservice\n<div class=\"next-draw\" readability=\"7\">Jackpothöhe am Freitag, 04.03.16\n<div class=\"next-draw-content\">\n<p class=\"jackpot\">40</p>\n<a href=\"http://lotto.web.de/webshop/product/eurojackpot/?partnerId=0WEHOM0HOM&amp;advertisementId=0HPMODU000000000EUROJACKPO000EJ000000000000\"><img src=\"http://img.ui-portal.de/homepage/img/webde/bg/eurojackpot_button.png\" height=\"22\" width=\"104\" alt=\"Jetzt spielen\"/></a> Chance 1:95 Mio.</div>\n</div>\n<div class=\"last-draw\" readability=\"7\">Ziehung vom Freitag, 26.02.16\n<div class=\"winning-numbers\">\n<ol class=\"numbers\"><li>9</li>\n<li>11</li>\n<li>19</li>\n<li>42</li>\n<li>45</li>\n</ol>\nEZ\n<ol class=\"numbers\"><li>7</li>\n<li>10</li>\n</ol></div>\n</div>\nAb 18 Jahren. Suchtgefahr. Hilfe bei www.bzga.de.</div>\n</div>\n</div>\n<div class=\"r1 service-content\">Top 5 Artikel\n<a href=\"http://web.de/magazine/news/\">Weitere Nachrichten</a></div>\n<div class=\"r1 service-content\"><a href=\"http://web.de/magazine/unterhaltung/lifestyle/horoskop/\">Horoskop</a>\n</div>\n<div class=\"r2\">\n<div class=\"r1 news-content\"><a href=\"http://web.de/magazine/auto/\">Auto-Service</a>\n<div class=\"teaser-content\" readability=\"8\">\n<a href=\"http://www.auto-service.de/news/genfer-autosalon/76288-panne-audi-show-moderatorin-weichselbraun-bleibt-auto-stehen.html\" data-teaser-id=\"31388878\" data-teaser-type=\"AUTOSERVICE\" target=\"_blank\">Auto-Panne bei Audi-Show</a>\n<p>Moderatorin Mirjam Weichselbraun bleibt in Genf auf der Bühne stehen.</p>\n</div>\n</div>\n<div class=\"r1 news-content teaser-content\" readability=\"8\">\n<a href=\"http://www.auto-service.de/news/genfer-autosalon/76268-bugatti-chiron-uebersportwagen-unfassbaren-1500-ps-vorgestellt.html\" data-teaser-id=\"31385222\" data-teaser-type=\"AUTOSERVICE\" target=\"_blank\">1.500 Bugatti-PS - Wahnsinn!</a>\n<p>Der neue \"Chiron\" feiert auf dem Autosalon in Genf seine Premiere.</p>\n</div>\n<div class=\"r1 news-content teaser-content\" readability=\"7\">\n<a href=\"http://www.auto-service.de/news/genfer-autosalon/76276-mercedes-c-klasse-cabrio-open-air-spass-367-ps.html\" data-teaser-id=\"31385422\" data-teaser-type=\"AUTOSERVICE\" target=\"_blank\">Premiere für die offene C-Klasse</a>\n<p>Das brandneue Mercedes C-Klasse Cabrio rollt nach Genf.</p>\n</div>\n</div>\n<div class=\"r1\">\n<div class=\"slider-container slider\" data-active-slide=\"1\">\n<div class=\"teaser-content\" data-slide-id=\"2\" readability=\"11\">\nRiskante Havarie in der Antarktis</div>\n<div class=\"teaser-content\" data-slide-id=\"3\" readability=\"11\">\nSchnee sorgt für viele Unfälle</div>\n<div class=\"teaser-content\" data-slide-id=\"4\" readability=\"11\">\nExplosion auf Kraftwerksgelände</div>\n</div>\n<ul class=\"news-list\"><li class=\"first active\"><a href=\"http://web.de/magazine/politik/fluechtlingskrise-in-europa/dschungel-calais-zerstoerung-fluechtlingslager-gestattet-31377034\" data-teaser-id=\"31377034\" data-teaser-type=\"VIDEO\"><img src=\"http://i2.web.de/image/032/31377032,pd=1,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Zerstörung von Flüchtlingslager bei Calais gestattet\" width=\"72\" height=\"54\"/></a> Frankreichs Innenminister Bernard Cazeneuve begrüßte die Entscheidung und versprach Hilfe.</li>\n<li><a href=\"http://web.de/magazine/panorama/havarie-antarktis-31375668\" data-teaser-id=\"31375668\" data-teaser-type=\"VIDEO\"><img src=\"http://i1.web.de/image/666/31375666,pd=1,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Havarie in der Antarktis\" width=\"72\" height=\"54\"/></a> Der australische Eisbrecher Aurora Australis ist auf dem Weg zu einer Forschungsstation auf Grund gelaufen. Wegen schwieriger Witterungsbedingungen blieb das Ausmaß des dabei entstandenen Schadens zunächst unklar.</li>\n<li><a href=\"http://web.de/magazine/politik/winter-fruehling-schnee-eis-sorgen-unfaelle-31375364\" data-teaser-id=\"31375364\" data-teaser-type=\"VIDEO\"><img src=\"http://i0.web.de/image/362/31375362,pd=1,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Winter zum Frühling: Schnee und Eis sorgen für Unfälle\" width=\"72\" height=\"54\"/></a> Zum meteorologischen Frühlingsbeginn Anfang März stehen die Zeichen auf Schnee. Nach Auskunft der Wetterexperten ist mit einem Temperaturabfall und Glätte zu rechnen. Im Erzgebirge hatten die Autofahrer schon seit Wochenbeginn zu kämpfen.</li>\n<li class=\"last\"><a href=\"http://web.de/magazine/panorama/medien-explosion-britischem-kraftwerksgelaende-31371758\" data-teaser-id=\"31371758\" data-teaser-type=\"VIDEO\"><img src=\"http://i0.web.de/image/756/31371756,pd=1,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Laut Medien Explosion auf britischem Kraftwerksgelände\" width=\"72\" height=\"54\"/></a> Es soll westlich von London Opfer gegeben haben.</li>\n</ul></div>\n<p><a href=\"http://route.web.de/\">Routenplaner</a> Der richtige Weg <a href=\"http://web.de/magazine/video/\">Video</a> Die besten Clips <a href=\"http://tv.web.de\">Fernsehprogramm</a> Die besten Serien, Filme und Sport-Events auf einen Blick <a href=\"https://millionenklick.web.de/#C0101041109010101\" target=\"_blank\">MillionenKlick</a> Jetzt mitmachen!</p>\n<p><a href=\"http://web.de/magazine/unicef/\">Unicef</a> Helfen Sie jetzt! <a href=\"http://www.auto-service.de/staumelder/\" target=\"_blank\">Staumelder</a> Gute Fahrt! <a href=\"http://web.de/magazine/reise/ferientermine/\">Schulferien</a> Urlaub planen <a href=\"http://web.de/magazine/unterhaltung/comic/\">Comics</a> Witzig, witzig</p>\n<div class=\"r1\">\n<div class=\"slider-container slider\" data-active-slide=\"1\">\n<div class=\"teaser-content\" data-slide-id=\"2\" readability=\"12\">\nVerschollen, aber überlebt</div>\n<div class=\"teaser-content\" data-slide-id=\"3\" readability=\"11\">\nKorallenriffe sterben im Pazifik</div>\n<div class=\"teaser-content\" data-slide-id=\"4\" readability=\"12\">\nWer hier eine Stunde bleibt, ist tot</div>\n</div>\n<ul class=\"news-list\"><li class=\"first active\"><a href=\"http://web.de/magazine/digital/laendern-selfie-toten-31341552\" data-teaser-id=\"31341552\" data-teaser-type=\"DEFAULT\"><img src=\"http://i2.web.de/image/578/31341578,pd=3,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Selfie\" width=\"72\" height=\"54\"/></a> Um sich selbst spektakulär in Szene zu setzen, verhalten sich vor allem junge Menschen extrem.</li>\n<li><a href=\"http://web.de/magazine/wissen/robinson-crusoe-verschollenen-ueberlebt-31322746\" data-teaser-id=\"31322746\" data-teaser-type=\"DEFAULT\"><img src=\"http://i2.web.de/image/428/31332428,pd=4,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Jose Salvador Alvarenga \" width=\"72\" height=\"54\"/></a> Jose Salvador Alvarenga verschwand im November 2012 und tauchte im Januar 2014 wieder auf.</li>\n<li><a href=\"http://web.de/magazine/wissen/satellitenbilder-weltall-9077788\" data-teaser-id=\"9077788\" data-teaser-type=\"SLIDESHOW\"><img src=\"http://i1.web.de/image/762/31375762,pd=4,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Fatu Huku Pazifik El Nino\" width=\"72\" height=\"54\"/></a> El Niño, die ungewöhnlichen Strömungen im Pazifischen Ozean, bedroht die Korallenriffe. Die Korallen werden durch die Strömungen ausgebleicht. Es wird befürchtet, dass dieses Jahr Riffe weltweit bedroht sind. Das Bild zeigt die Pazifik-Insel Fatu Huku und wurde vom europäischen Satelliten Sentinel-2 aufgenommen. Es dient zur Überprüfung der Korallen-Schäden.</li>\n<li class=\"last\"><a href=\"http://web.de/magazine/wissen/mystery/karatschai-see-russland-gefaehrlichste-ort-welt-31327140\" data-teaser-id=\"31327140\" data-teaser-type=\"DEFAULT\"><img src=\"http://i1.web.de/image/546/31327546,pd=5,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Mystery\" width=\"72\" height=\"54\"/></a> Der Karatschai-See in Russland gilt als gefährlichster Ort der Welt.</li>\n</ul></div>\n<div class=\"r1 service-content\">WEB.DE Produkte\n<a href=\"https://produkte.web.de/#.hp.int.produktebox\">Weitere Produkte</a></div>\n<div class=\"r1\">\n<div class=\"slider-container slider\" data-active-slide=\"1\">\n<div class=\"teaser-content\" data-slide-id=\"2\">\nDe-Mail</div>\n<div class=\"teaser-content\" data-slide-id=\"3\">\nMail App</div>\n<div class=\"teaser-content\" data-slide-id=\"4\">\nBrowser</div>\n</div>\n<ul class=\"news-list\"><li class=\"first active\"><a href=\"https://produkte.web.de/mailcheck/#.hp.int.produktebox\" data-teaser-id=\"30017408\" data-teaser-type=\"DEFAULT\"><img src=\"http://i2.web.de/image/402/30017402,pd=17,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"\" width=\"72\" height=\"54\"/></a> WEB.DE Mailcheck</li>\n<li><a href=\"https://produkte.web.de/de-mail/#.hp.int.produktebox\" data-teaser-id=\"30017424\" data-teaser-type=\"DEFAULT\"><img src=\"http://i2.web.de/image/420/30017420,pd=17,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"\" width=\"72\" height=\"54\"/></a></li>\n<li><a href=\"https://produkte.web.de/freemail_mobile_startseite/mail-app/#.hp.int.produktebox\" data-teaser-id=\"30017430\" data-teaser-type=\"DEFAULT\"><img src=\"http://i1.web.de/image/428/30017428,pd=17,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Mobile Apps\" width=\"72\" height=\"54\"/></a></li>\n<li class=\"last\"><a href=\"https://produkte.web.de/browser/#.hp.int.produktebox\" data-teaser-id=\"30017436\" data-teaser-type=\"DEFAULT\"><img src=\"http://i1.web.de/image/434/30017434,pd=17,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Audible\" width=\"72\" height=\"54\"/></a></li>\n</ul></div>\n<div class=\"r1\">\n<div class=\"slider-container slider\" data-active-slide=\"1\">\n<div class=\"teaser-content\" data-slide-id=\"2\" readability=\"11\">\nDie Missen und ihre sexy Tattoos</div>\n<div class=\"teaser-content\" data-slide-id=\"3\" readability=\"11\">\nSo lief die Wahl der Miss Germany</div>\n<div class=\"teaser-content\" data-slide-id=\"4\" readability=\"11\">\nMissen-Shooting am Strand</div>\n</div>\n<ul class=\"news-list\"><li class=\"first active\"><a href=\"http://web.de/magazine/unterhaltung/lifestyle/miss-internet/schoen-miss-germany-2016-lena-broeder-31367418\" data-teaser-id=\"31367418\" data-teaser-type=\"SLIDESHOW\"><img src=\"http://i0.web.de/image/294/31368294,pd=6,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Lena Bröder Miss Germany 2016\" width=\"72\" height=\"54\"/></a> Lena Bröder (M.) und ihre beiden Stellvertreterinnen Francesca Orru (l.) und Katharina Schubert (r.) nach der Wahl zur Miss Germany 2016.</li>\n<li><a href=\"http://web.de/magazine/unterhaltung/lifestyle/miss-internet/miss-germany-2016-missen-sexy-tattoos-31341074\" data-teaser-id=\"31341074\" data-teaser-type=\"SLIDESHOW\"><img src=\"http://i2.web.de/image/014/31341014,pd=3,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Missen Tattoos Noten\" width=\"72\" height=\"54\"/></a> In diesem Tattoo steckt so einiges: Im \"L\" beim Wort Liebe hat sich ein Unendlichkeitszeichen versteckt, die Blumen erinnern aber daran, dass auch die Liebe welken kann. Und die Noten sind ein kurzer Ausschnitt aus dem Soundtrack von \"Die fabelhafte Welt der Amelie\". Große Körperkunst.</li>\n<li><a href=\"http://web.de/magazine/unterhaltung/lifestyle/miss-internet/miss-germany-2016-religionslehrerin-schoenste-deutschlands-31365694\" data-teaser-id=\"31365694\" data-teaser-type=\"SLIDESHOW\"><img src=\"http://i2.web.de/image/686/31365686,pd=4,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Olga Hoffmann und Lena Bröder\" width=\"72\" height=\"54\"/></a> Die Krone bekommt die frischgebackene Miss Germany von ihrer Vorgängerin Olga Hoffmann aufgesetzt.</li>\n<li class=\"last\"><a href=\"http://web.de/magazine/unterhaltung/lifestyle/miss-internet/miss-germany-2016-missen-shooting-strand-31333712\" data-teaser-id=\"31333712\" data-teaser-type=\"SLIDESHOW\"><img src=\"http://i1.web.de/image/672/31333672,pd=6,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Missen am Strand\" width=\"72\" height=\"54\"/></a> Sieht ein bisschen so aus, als gäbe es da etwas umsonst. Schuhe vielleicht?</li>\n</ul></div>\n<div class=\"r1\">\n<div class=\"slider-container slider\" data-active-slide=\"1\">\n<div class=\"teaser-content\" data-slide-id=\"2\" readability=\"11\">\nExklusiver Clip: \"Eddie the Eagle\"</div>\n<div class=\"teaser-content\" data-slide-id=\"3\" readability=\"11\">\nExklusiver Clip: \"Spotlight\"</div>\n<div class=\"teaser-content\" data-slide-id=\"4\" readability=\"11\">\nEinblick in den Film \"Zoomania\"</div>\n</div>\n<ul class=\"news-list\"><li class=\"first active\"><a href=\"http://web.de/magazine/unterhaltung/tv-film/aktuelle-kinotrailer/exklusiv-trailer-angry-birds-film-31371008\" data-teaser-id=\"31371008\" data-teaser-type=\"VIDEO\"><img src=\"http://i0.web.de/image/006/31371006,pd=2,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"AngryBirds2\" width=\"72\" height=\"54\"/></a> AngryBirds2</li>\n<li><a href=\"http://web.de/magazine/unterhaltung/tv-film/aktuelle-kinotrailer/exklusiver-clip-eddie-the-eagle-31367488\" data-teaser-id=\"31367488\" data-teaser-type=\"VIDEO\"><img src=\"http://i2.web.de/image/486/31367486,pd=2,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"EddieEagleClip\" width=\"72\" height=\"54\"/></a> EddieEagleClip</li>\n<li><a href=\"http://web.de/magazine/unterhaltung/tv-film/aktuelle-kinotrailer/exklusiver-clip-spotlight-31361458\" data-teaser-id=\"31361458\" data-teaser-type=\"VIDEO\"><img src=\"http://i2.web.de/image/456/31361456,pd=2,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"SpotlightClip\" width=\"72\" height=\"54\"/></a> SpotlightClip</li>\n<li class=\"last\"><a href=\"http://web.de/magazine/unterhaltung/tv-film/aktuelle-kinotrailer/exklusiver-clip-zoomania-31359474\" data-teaser-id=\"31359474\" data-teaser-type=\"VIDEO\"><img src=\"http://i1.web.de/image/472/31359472,pd=2,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"ZoomaniaClip\" width=\"72\" height=\"54\"/></a> ZoomaniaClip</li>\n</ul></div>\n<div class=\"r1\">\n<div class=\"slider-container slider\" data-active-slide=\"1\">\n<div class=\"teaser-content\" data-slide-id=\"2\" readability=\"11\">\nPlötzlich Mutter: Ist das möglich?</div>\n<div class=\"teaser-content\" data-slide-id=\"3\" readability=\"11\">\nTödliche Geißel der Menschheit</div>\n<div class=\"teaser-content\" data-slide-id=\"4\" readability=\"11\">\nMuss ich zur Krebsvorsorge?</div>\n</div>\n<ul class=\"news-list\"><li class=\"first active\"><a href=\"http://web.de/magazine/gesundheit/500-kalorien-31356692\" data-teaser-id=\"31356692\" data-teaser-type=\"VIDEO\"><img src=\"http://i0.web.de/image/548/31357548,pd=3,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"\" width=\"72\" height=\"54\"/></a></li>\n<li><a href=\"http://web.de/magazine/gesundheit/gntm-kandidatin-saskia-unbemerkt-schwanger-moeglich-31332426\" data-teaser-id=\"31332426\" data-teaser-type=\"DEFAULT\"><img src=\"http://i2.web.de/image/830/31332830,pd=3,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Geburt Kind OP\" width=\"72\" height=\"54\"/></a> Normalerweise sendet der Körper während einer Schwangerschaft viele Zeichen. Doch nicht immer werden diese von der werdenden Mutter wahrgenommen. (Symbolbild)</li>\n<li><a href=\"http://web.de/magazine/gesundheit/krebs-unbesiegbare-geissel-menschheit-31291766\" data-teaser-id=\"31291766\" data-teaser-type=\"DEFAULT\"><img src=\"http://i2.web.de/image/422/31311422,pd=4,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Krebs, Patient, Krankenhaus\" width=\"72\" height=\"54\"/></a> Krebs rafft immer mehr Menschen dahin.</li>\n<li class=\"last\"><a href=\"http://web.de/magazine/gesundheit/krebs-fruehzeitig-erkennen-vorsorgeuntersuchungen-brauche-31298136\" data-teaser-id=\"31298136\" data-teaser-type=\"DEFAULT\"><img src=\"http://i2.web.de/image/298/31330298,pd=3,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Mammographie-Screening\" width=\"72\" height=\"54\"/></a> Das Mammographie-Screening wird Frauen ab 50 alle zwei Jahre empfohlen. Das Verfahren an sich kann jedoch ebenfalls Tumore entstehen lassen.</li>\n</ul></div>\n<div class=\"r1\">\n<div class=\"slider-container slider\" data-active-slide=\"1\">\n<div class=\"teaser-content\" data-slide-id=\"2\" readability=\"11\">\n\"Bachelorette\" macht Schluss ...</div>\n<div class=\"teaser-content\" data-slide-id=\"3\" readability=\"12\">\nWas, die sind verwandt?</div>\n<div class=\"teaser-content\" data-slide-id=\"4\" readability=\"11\">\nZiemlich dick im Geschäft</div>\n</div>\n<ul class=\"news-list\"><li class=\"first active\"><a href=\"http://web.de/magazine/unterhaltung/stars/liebesnews-woche-liebt-trennt-31363836\" data-teaser-id=\"31363836\" data-teaser-type=\"SLIDESHOW\"><img src=\"http://i2.web.de/image/270/31379270,pd=4,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Jenny Elvers, Steffen von der Beeck\" width=\"72\" height=\"54\"/></a> Jenny Elvers im Glück: Ein ganzes Jahr lang konnten sie und ihr Freund Steffen von der Beeck das Geheimnis für sich behalten. Nun verriet Jenny auf ihrem Facebook-Profil, dass sie und Steffen schon seit über einem Jahr verlobt sind. Der Dschungelcamp-Kandidatin schien es lieber zu sein, selbst mit der schönen Botschaft an die Öffentlichkeit zu gehen. So ist sie den Medien zuvorgekommen.</li>\n<li><a href=\"http://web.de/magazine/unterhaltung/tv-film/bachelorette/bachelorette-alisa-patrick-zusammenziehen-31365706\" data-teaser-id=\"31365706\" data-teaser-type=\"VIDEO\"><img src=\"http://i2.web.de/image/704/31365704,pd=3,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Bachelorette_Paar_zieht_zusammen\" width=\"72\" height=\"54\"/></a> Bachelorette_Paar_zieht_zusammen</li>\n<li><a href=\"http://web.de/magazine/unterhaltung/stars/stars-verwandt-haetten-sies-gewusst-30222388\" data-teaser-id=\"30222388\" data-teaser-type=\"SLIDESHOW\"><img src=\"http://i1.web.de/image/970/31362970,pd=5,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Melissa McCarthy Jenny McCarthy\" width=\"72\" height=\"54\"/></a> Dass es sich bei Ulknudel Melissa McCarthy (l.) und Ex-Playmate Jenny McCarthy um Cousinen handelt, ist trotz des Nachnamens nur schwer vorstellbar.</li>\n<li class=\"last\"><a href=\"http://web.de/magazine/unterhaltung/stars/stars-dick-geschaeft-31361072\" data-teaser-id=\"31361072\" data-teaser-type=\"SLIDESHOW\"><img src=\"http://i0.web.de/image/460/31361460,pd=7,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Kevin James und Beth Ditto\" width=\"72\" height=\"54\"/></a> Kevin James und Beth Ditto sind \"dick im Geschäft\".</li>\n</ul></div>\n<div class=\"r1\">\n<div class=\"slider-container slider\" data-active-slide=\"1\">\n<div class=\"teaser-content\" data-slide-id=\"2\" readability=\"11\">\nEine Million Kinder in akuter Gefahr</div>\n<div class=\"teaser-content\" data-slide-id=\"3\" readability=\"11\">\nNächstenliebe als Geschenk</div>\n<div class=\"teaser-content\" data-slide-id=\"4\" readability=\"11\">\nUnsere Stiftung feiert Jubiläum</div>\n</div>\n<ul class=\"news-list\"><li class=\"first active\"><a href=\"http://web.de/magazine/unicef/gewinnspiel-aktion-geschenkte-tag-treffen-mats-hummels-31362846\" data-teaser-id=\"31362846\" data-teaser-type=\"DEFAULT\"><img src=\"http://i0.web.de/image/858/31362858,pd=6,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"UNICEF, United Internet for UNICEF, Mats Hummels, Gewinnspiel\" width=\"72\" height=\"54\"/></a> Anlässlich der Aktion \"Der geschenkte Tag\": Gewinnen Sie ein Treffen mit Mats Hummels.</li>\n<li><a href=\"http://web.de/magazine/unicef/unicef-million-kinder-ost-suedafrika-schwer-unterernaehrt-31356858\" data-teaser-id=\"31356858\" data-teaser-type=\"DEFAULT\"><img src=\"http://i0.web.de/image/286/31358286,pd=2,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"Mangelernährung, UNICEF\" width=\"72\" height=\"54\"/></a> Laut UNICEF sind knapp eine Million Kinder in Afrika schwer unterernährt.</li>\n<li><a href=\"http://web.de/magazine/unicef/valentinstag-2016-naechstenliebe-schoenste-geschenk-31347082\" data-teaser-id=\"31347082\" data-teaser-type=\"DEFAULT\"><img src=\"http://i2.web.de/image/080/31347080,pd=1,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"UNICEF, United Internet for UNICEF\" width=\"72\" height=\"54\"/></a> Zum Valentinstag wollen wir auch an diejenigen denken, denen es nicht so gut geht.</li>\n<li class=\"last\"><a href=\"http://web.de/magazine/unicef/united-internet-unicef-feiert-jubilaeum-unterstuetzer-31192220\" data-teaser-id=\"31192220\" data-teaser-type=\"DEFAULT\"><img src=\"http://i1.web.de/image/234/31192234,pd=7,h=54,mxh=600,mxw=800,w=72.jpg\" alt=\"UNICEF, United Internet for UNICEF\" width=\"72\" height=\"54\"/></a> Die Stiftung United Internet for UNICEF sagt DANKE.</li>\n</ul></div>\n",
321 "annotations": [],
322 "mimetype": "text/html",
323 "language": "de",
324 "reading_time": 4,
325 "domain_name": "web.de",
326 "tags": []
327 },
328 {
329 "is_archived": 1,
330 "created_at": "2016-09-08T11:55:58+0200",
331 "updated_at": "2016-09-08T11:57:16+0200",
332 "is_starred": 0,
333 "id": 48,
334 "title": "OpenSSH Server on Arch Linux | DominicM test",
335 "url": "http://dominicm.com/openssh-server-arch-linux/",
336 "content": "<p><a href=\"http://dominicm.com/openssh-server-arch-linux/\"><img class=\"aligncenter wp-image-2354 size-medium\" title=\"OpenSSH Server on Arch Linux\" src=\"http://dominicm.com/wp-content/uploads/2016/01/ssh-arch-linux-450x450.png\" alt=\"OpenSSH Server on Arch Linux\" width=\"450\" height=\"450\" srcset=\"http://dominicm.com/wp-content/uploads/2016/01/ssh-arch-linux-150x150.png 150w, http://dominicm.com/wp-content/uploads/2016/01/ssh-arch-linux-450x450.png 450w, http://dominicm.com/wp-content/uploads/2016/01/ssh-arch-linux-768x768.png 768w, http://dominicm.com/wp-content/uploads/2016/01/ssh-arch-linux-1024x1024.png 1024w, http://dominicm.com/wp-content/uploads/2016/01/ssh-arch-linux-60x60.png 60w, http://dominicm.com/wp-content/uploads/2016/01/ssh-arch-linux.png 1200w\" sizes=\"(max-width: 450px) 100vw, 450px\"/></a></p>\n<p>OpenSSH allows powerful and convenient way to remotely access remote systems. However it creates a possible security weakness which is one reason it is not installed by default. With proper configuration it can be secured and allows the administration of headless servers servers or other devices.</p>\n\n<h2>Install OpenSSH</h2>\n<p>Install from the official repository.</p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\">\nsudo pacman -S openssh\n</pre>\n\n<h2>Configure OpenSSH</h2>\n<p>Open the configuration file.</p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\">\nsudo nano /etc/ssh/sshd_config\n</pre>\n\n<p>Uncomment and or modify the desired lines in the configuration file and save.</p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\">\nAllowUsers user1 user2\nAllowGroups group1 group2\nPermitRootLogin no\nPort 22\n</pre>\n<p>Only certain users can be allowed to login by listing them after <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">AllowUsers</code>. Analogously <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">AllowGroups</code> option allows users in listed groups to login. Root login can be controlled with <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">PermitRootLogin</code> option, <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">yes</code> to allow, <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">no</code> to disallow and <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">without-password</code> to allow only with public key authentication. This should be set to <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">no</code> in almost always for security purposes. Root access can still be gained with the use of <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">sudo</code> or <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">su</code> commands.</p>\n<p>Default <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">Port</code> is set to <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">22</code> which can make it easier for automated bots to attempt to login. In practice changing the default SSH port does not improve security but can reduce attempted logins which can fill the logs with errors. Using ports above <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">1024</code> can actually be detrimental to security as ports below <code class=\"EnlighterJSRAW\" data-enlighter-language=\"generic\">1024</code> are restricted to root access while ports above can be listened to by non-root users.</p>\n\n<p>For improved security and convenience it is also recommended to configure password-less SSH logins. Optionally also configure print Screenfetch on SSH login.</p>\n\n<h2>Run OpenSSH</h2>\n<p>SSH can be started as a daemon with sshd however this is not recommended in most cases. It is better to start SSH on demand. When a socket service is started it will listen for incoming connections and will only then start the daemon process.</p>\n\n<p>Start the socket service.</p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\">\nsudo systemctl start sshd.socket\n</pre>\n\n<p>Enable the socket service to run on boot.</p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"shell\">\nsudo systemctl enable sshd.socket\n</pre>\n",
337 "annotations": [],
338 "mimetype": "text/html",
339 "language": "en-GB",
340 "reading_time": 1,
341 "domain_name": "dominicm.com",
342 "preview_picture": "http://dominicm.com/wp-content/uploads/2016/01/ssh-arch-linux.png",
343 "tags": []
344 },
345 {
346 "is_archived": 1,
347 "created_at": "2016-09-08T11:55:58+0200",
348 "updated_at": "2016-09-08T11:57:16+0200",
349 "is_starred": 0,
350 "id": 39,
351 "title": "Site Moved | Site Help",
352 "url": "http://g1.com/help/sitemoved.asp",
353 "content": "<ul id=\"breadcrumbs\"><li class=\"level1\"><a href=\"http://g1.com/\" rel=\"home\">Home</a></li>\n<li><a href=\"http://g1.com/Support/\">Support</a></li>\n<li><a href=\"http://g1.com/Help/\">Site Help</a></li>\n<li id=\"lastItem\">Site Moved</li>\n</ul>\n<p>The Group 1 Software website has been discontinued and has been replaced by the Pitney Bowes Software website. For support of your Group 1 Software product, visit <a href=\"http://www.g1.com/Support/\" title=\"Group 1 Support website\">http://www.g1.com/Support/</a>. For information about our products, please visit <a href=\"http://www.pb.com/software\" title=\"Pitney Bowes Software website\">http://www.pb.com/software</a>.</p>\n<ul id=\"altPage\"><li><a href=\"http://g1.com/Help/TellAFriend.asp\" class=\"envelope\">Tell a Friend</a></li>\n</ul>\n",
354 "annotations": [],
355 "mimetype": "text/html",
356 "language": "en",
357 "reading_time": 0,
358 "domain_name": "g1.com",
359 "tags": []
360 },
361 {
362 "is_archived": 1,
363 "created_at": "2016-09-08T11:55:58+0200",
364 "updated_at": "2016-09-08T11:57:16+0200",
365 "is_starred": 0,
366 "id": 38,
367 "title": "#Maroc : le stylo anti-pédophiles EAGLE d’AMESYS est moins bien configuré que les faux-lowers Twitter du roi Mohammed VI",
368 "url": "https://reflets.info/maroc-le-stylo-anti-pedophiles-eagle-damesys-est-moins-bien-configure-que-les-faux-lowers-twitter-du-roi-mohammed-vi/",
369 "content": "<p><a href=\"http://reflets.info/wp-content/uploads/2013/08/pedobear.jpg\" data-rel=\"lightbox-0\" title=\"\"><img class=\"size-medium wp-image-26091 alignright\" alt=\"pedobear\" src=\"http://reflets.info/wp-content/uploads/2013/08/pedobear-350x301.jpg\" width=\"350\" height=\"301\" srcset=\"https://reflets.info/wp-content/uploads/2013/08/pedobear-350x301.jpg 350w, https://reflets.info/wp-content/uploads/2013/08/pedobear-550x473.jpg 550w, https://reflets.info/wp-content/uploads/2013/08/pedobear.jpg 610w\" sizes=\"(max-width: 350px) 100vw, 350px\"/></a>Le EAGLE déployé par Amesys / Bull au Maroc n’y aura rien fait. Quand la justice attrape un pédo-criminel, ce dernier trouve le moyen de se faire gracier. On peut au bas mot parler d’un sérieux dysfonctionnement de l’institution judiciaire et se demander quel genre de bug qui a pu provoquer ce malaise. En attendant, les bots Twitter de Sa Majesté sont bien présents pour tenter de récupérer la boulette. Mais comme d’habitude dans ce genre de cas, c’est tellement mal fait que ça se voit beaucoup.</p>\n<h3 class=\"c3\">Previously in PopCorn</h3>\n<p class=\"c4\">Deux millions d’euros rien qu’en disques durs, des mois de déploiement. Cet EAGLE béta testé par Kadhafi sur sa population est maintenant en production au Maroc. Evidemment Amesys / Bull contribue toujours activement (mais <a title=\"Advanced Middle East Systems, le Amesys nouveau est de retour en Libye\" href=\"http://reflets.info/advanced-middle-east-systems-le-amesys-nouveau-est-de-retour-en-libye/\">plus sous pavillon français</a> depuis un sombre <a title=\"Bull vend Eagle… à un actionnaire de Crescendo, qui est l’actionnaire principal de… Bull\" href=\"http://reflets.info/bull-vend-eagle-a-un-actionnaire-de-crescendo-qui-est-lactionnaire-principal-de-bull/\">tour de passe passe</a>) au paramétrage et à la formation des autorités marocaines pour mettre sur écoute l’ensemble de la population marocaine. Popcorn c’est le petit nom du projet du EAGLE marocain, nous vous en avions déjà assez largement parlé. L’amitié franco-marocaine c’est une bien belle histoire : ses accords de coopération policière, sa lutte contre les pédophiles et les narco trafiquants, et évidemment, la mise sur écoute téléphonique de ses 32 millions d’habitants et l’interception des communications de ses 1,5 millions d’accès Internet et de ses 14 millions d’internautes…</p>\n<p class=\"c4\">Il faut dire qu’EAGLE partait avec de sérieux avantages sur la concurrence, les technologies de BULL ont déjà fait leur preuve en Libye (projet CANDY), au Qatar (projet FINGER), au GABON (projet CROCO) ainsi que dans d’autres pays ou l’amitié bilatérale se traduit également à grand renfort de cyber-matraques.</p>\n<h3 class=\"c3\">Le stylo traqueur de pédophiles</h3>\n<p class=\"c4\">Quand on demandait à Amesys pourquoi et comment Abdallah al Senousi, un terroriste notoire, s’était vu confier un outil comme Eagle en Libye pour surveiller l’ensemble de sa population, la réponse de Bruno Samtmann, directeur commercial d’Amesys, se faisait rassurante, pour lui, <a href=\"http://reflets.info/amesys-la-justice-et-la-morale/\" target=\"_blank\">Amesys avait fourni à Kadhafi un stylo traqueur de pédophiles, de narco trafiquants et terroristes</a>… ça ne s’invente pas. C’est exactement ce même genre de stylo qu’Amesys a fournit aux autorités marocaines qui a donc en toute logique placé l’ensemble de la population du pays sous écoute.</p>\n<iframe src=\"http://player.vimeo.com/video/41977398?title=0&amp;byline=0&amp;portrait=0&amp;color=ffffff\" height=\"400\" width=\"500\" allowfullscreen=\"\" frameborder=\"0\"> </iframe>\n<p class=\"c5\"><a href=\"http://vimeo.com/41977398\" data-rel=\"lightbox-video-0\">Traqué – documentaire de Paul Moreira – Canal+</a> from <a href=\"http://vimeo.com/fhimtcom\">fhimt.com</a> on <a href=\"https://vimeo.com\">Vimeo</a>.</p>\n<p class=\"c4\">Manque de bol, pour une fois que le Maroc arrête un pédophile, voilà que le roi le gracie ! Mais à quoi peut bien servir cet Eagle au juste s’il ne permet même pas aux autorités marocaines de conserver en prison des pédophiles qu’ils ont déjà arrêté, condamné et mis en prison ?</p>\n<h3>Un plugin Eagle à bots Twitter ?</h3>\n<p class=\"c4\">Pour désamorcer la contestation au sujet du Daniel Gate sur les réseaux sociaux, les matraques ne sont pas encore parfaitement au point. Configurer un Eagle, c’est un peu long voyez vous. On utilise donc, tout naturellement, une armée de bots, des faux comptes Twitter pour twitter et retweeter la propagande de Sa Majesté. L’<a href=\"https://fr.lakome.com/index.php/maroc/1234-twitter-les-robots-de-sa-majeste\" target=\"_blank\">excellent site d’information Lakome nous explique la supercherie dans le détail</a>.</p>\n<p class=\"c5\"><a href=\"http://reflets.info/wp-content/uploads/2013/08/tweeter-robot-m6-total.jpg\" data-rel=\"lightbox-1\" title=\"\"><img class=\"aligncenter size-large wp-image-26093\" alt=\"tweeter robot m6 total\" src=\"http://reflets.info/wp-content/uploads/2013/08/tweeter-robot-m6-total-550x386.jpg\" width=\"550\" height=\"386\" srcset=\"https://reflets.info/wp-content/uploads/2013/08/tweeter-robot-m6-total-350x246.jpg 350w, https://reflets.info/wp-content/uploads/2013/08/tweeter-robot-m6-total-550x386.jpg 550w, https://reflets.info/wp-content/uploads/2013/08/tweeter-robot-m6-total.jpg 579w\" sizes=\"(max-width: 550px) 100vw, 550px\"/></a></p>\n<p class=\"c4\">Pour parfaire l’attirail autoritariste et adapter son produit aux challenges de demain, nous suggérons donc à Amesys, si ce n’est déjà fait, un plugin Eagle pour créer des bots à tweeter des âneries de manière grossière, ce afin d’éviter aux contribuables marocains d’avoir à payer grassement des agences de communication pour ce genre de propagande ridicule.</p>\n<p class=\"c5\"><a href=\"http://reflets.info/wp-content/uploads/2013/08/tweeter-robot10-liste.jpg\" data-rel=\"lightbox-2\" title=\"\"><img class=\"aligncenter size-large wp-image-26092\" alt=\"tweeter robot10 liste\" src=\"http://reflets.info/wp-content/uploads/2013/08/tweeter-robot10-liste-550x503.jpg\" width=\"550\" height=\"503\" srcset=\"https://reflets.info/wp-content/uploads/2013/08/tweeter-robot10-liste-350x320.jpg 350w, https://reflets.info/wp-content/uploads/2013/08/tweeter-robot10-liste-550x503.jpg 550w, https://reflets.info/wp-content/uploads/2013/08/tweeter-robot10-liste.jpg 573w\" sizes=\"(max-width: 550px) 100vw, 550px\"/></a></p>\n",
370 "annotations": [],
371 "mimetype": "text/html",
372 "language": "fr-FR",
373 "reading_time": 3,
374 "domain_name": "reflets.info",
375 "preview_picture": "http://reflets.info/wp-content/uploads/2013/08/tweeter-robot10-liste-550x503.jpg",
376 "tags": []
377 },
378 {
379 "is_archived": 1,
380 "created_at": "2016-09-08T11:55:58+0200",
381 "updated_at": "2016-09-08T11:57:16+0200",
382 "is_starred": 0,
383 "id": 3,
384 "title": "Simple Cloud Infrastructure for Developers",
385 "url": "https://www.digitalocean.com/",
386 "content": "<div class=\"wrapper-full\">\n<div class=\"container lighter-grey wrap-content\">\n<h3>Simple to Set Up. Flexible to Scale.</h3>\n<ul id=\"simple-setup\"><li readability=\"1\"><img src=\"https://www.digitalocean.com/assets/images/join/deploy-with-ease-ccf9cdee.svg\" alt=\"Deploy with Ease\"/><h4>Easy to Deploy</h4>\n<p>Spin up a Droplet complete with full root access in just a few clicks from our Control Panel.</p>\n</li>\n<li readability=\"3\"><img src=\"https://www.digitalocean.com/assets/images/join/build-to-scale-4d39297b.svg\" alt=\"Build to Scale\"/><h4>Built to Scale</h4>\n<p>Scale your applications with our API and Floating IPs. As you grow, manage your apps with team accounts.</p>\n</li>\n<li readability=\"3\"><img src=\"https://www.digitalocean.com/assets/images/join/select-location-e2a393dc.svg\" alt=\"Select Location\"/><h4>Reliable and Available</h4>\n<p>Select from datacenter regions around the world based on latency, or deploy across regions for redundancy.</p>\n</li>\n</ul></div>\n<div class=\"hide-group container wrap-content\" readability=\"32\">\n<h3 class=\"hasSub\">Straightforward Pricing</h3>\n<ul class=\"pricing-chart\"><li readability=\"2\">\n<p>5/mo $0.007/hour</p>\n<p>512MB / 1 cpu 20GB SSD Disk 1TB Transfer</p>\n</li>\n<li readability=\"2\">\n<p>10/mo $0.015/hour</p>\n<p>1GB / 1 cpu 30GB SSD Disk 2TB Transfer</p>\n</li>\n<li readability=\"2\">\n<p>20/mo $0.03/hour</p>\nMOST POPULAR PLAN\n<p>2GB / 2 cpu 40GB SSD Disk 3TB Transfer</p>\n</li>\n<li readability=\"2\">\n<p>40/mo $0.06/hour</p>\n<p>4GB / 2 cpu 60GB SSD Disk 4TB Transfer</p>\n</li>\n<li readability=\"2\">\n<p>80/mo $0.119/hour</p>\n<p>8GB / 4 cpu 80GB SSD Disk 5TB Transfer</p>\n</li>\n</ul><a href=\"https://cloud.digitalocean.com/registrations/new\" class=\"Button--blue\">Get Started</a></div>\n<div class=\"container wrap-content\" id=\"teams-on-do\" readability=\"29\">\n<h4 class=\"caps\">Teams on DigitalOcean</h4>\n<img class=\"case-study\" src=\"https://www.digitalocean.com/assets/images/ghost-676798cc.svg\"/><p>Blog publishing platform Ghost scaled to support one million customers.</p>\n<a href=\"https://www.digitalocean.com/customers/ghost/\" class=\"Button Button--blue\">Learn how they did it</a> <img class=\"teams-on-do\" src=\"https://www.digitalocean.com/assets/images/companies-944c4b3b.svg\"/></div>\n<div class=\"container wrap-content\" id=\"sales-cta\" readability=\"32\">\n<h3>Scaling or Migrating? Let's talk.</h3>\n<p>Our team is ready to answer your questions and help you get up and running.</p>\n<a class=\"Button Button--white\" href=\"https://www.digitalocean.com/company/contact/sales/\">Get in touch</a></div>\n</div>\n",
387 "annotations": [],
388 "mimetype": "text/html",
389 "reading_time": 0,
390 "domain_name": "www.digitalocean.com",
391 "preview_picture": "https://www.digitalocean.com/assets/images/logo-3b02463b.jpg",
392 "tags": []
393 } 99 }
394] 100]
diff --git a/tests/Wallabag/UserBundle/Controller/ManageControllerTest.php b/tests/Wallabag/UserBundle/Controller/ManageControllerTest.php
index 4faddfc4..adc2cf09 100644
--- a/tests/Wallabag/UserBundle/Controller/ManageControllerTest.php
+++ b/tests/Wallabag/UserBundle/Controller/ManageControllerTest.php
@@ -10,9 +10,9 @@ class ManageControllerTest extends WallabagCoreTestCase
10 { 10 {
11 $client = $this->getClient(); 11 $client = $this->getClient();
12 12
13 $client->request('GET', '/users/'); 13 $client->request('GET', '/users/list');
14 14
15 $this->assertEquals(302, $client->getResponse()->getStatusCode()); 15 $this->assertSame(302, $client->getResponse()->getStatusCode());
16 $this->assertContains('login', $client->getResponse()->headers->get('location')); 16 $this->assertContains('login', $client->getResponse()->headers->get('location'));
17 } 17 }
18 18
@@ -22,21 +22,21 @@ class ManageControllerTest extends WallabagCoreTestCase
22 $client = $this->getClient(); 22 $client = $this->getClient();
23 23
24 // Create a new user in the database 24 // Create a new user in the database
25 $crawler = $client->request('GET', '/users/'); 25 $crawler = $client->request('GET', '/users/list');
26 $this->assertEquals(200, $client->getResponse()->getStatusCode(), 'Unexpected HTTP status code for GET /users/'); 26 $this->assertSame(200, $client->getResponse()->getStatusCode(), 'Unexpected HTTP status code for GET /users/');
27 $crawler = $client->click($crawler->selectLink('user.list.create_new_one')->link()); 27 $crawler = $client->click($crawler->selectLink('user.list.create_new_one')->link());
28 28
29 // Fill in the form and submit it 29 // Fill in the form and submit it
30 $form = $crawler->selectButton('user.form.save')->form(array( 30 $form = $crawler->selectButton('user.form.save')->form([
31 'new_user[username]' => 'test_user', 31 'new_user[username]' => 'test_user',
32 'new_user[email]' => 'test@test.io', 32 'new_user[email]' => 'test@test.io',
33 'new_user[plainPassword][first]' => 'test', 33 'new_user[plainPassword][first]' => 'testtest',
34 'new_user[plainPassword][second]' => 'test', 34 'new_user[plainPassword][second]' => 'testtest',
35 )); 35 ]);
36 36
37 $client->submit($form); 37 $client->submit($form);
38 $client->followRedirect(); 38 $client->followRedirect();
39 $crawler = $client->request('GET', '/users/'); 39 $crawler = $client->request('GET', '/users/list');
40 40
41 // Check data in the show view 41 // Check data in the show view
42 $this->assertGreaterThan(0, $crawler->filter('td:contains("test_user")')->count(), 'Missing element td:contains("test_user")'); 42 $this->assertGreaterThan(0, $crawler->filter('td:contains("test_user")')->count(), 'Missing element td:contains("test_user")');
@@ -44,12 +44,12 @@ class ManageControllerTest extends WallabagCoreTestCase
44 // Edit the user 44 // Edit the user
45 $crawler = $client->click($crawler->selectLink('user.list.edit_action')->last()->link()); 45 $crawler = $client->click($crawler->selectLink('user.list.edit_action')->last()->link());
46 46
47 $form = $crawler->selectButton('user.form.save')->form(array( 47 $form = $crawler->selectButton('user.form.save')->form([
48 'user[name]' => 'Foo User', 48 'user[name]' => 'Foo User',
49 'user[username]' => 'test_user', 49 'user[username]' => 'test_user',
50 'user[email]' => 'test@test.io', 50 'user[email]' => 'test@test.io',
51 'user[enabled]' => true, 51 'user[enabled]' => true,
52 )); 52 ]);
53 53
54 $client->submit($form); 54 $client->submit($form);
55 $crawler = $client->followRedirect(); 55 $crawler = $client->followRedirect();
@@ -57,7 +57,7 @@ class ManageControllerTest extends WallabagCoreTestCase
57 // Check the element contains an attribute with value equals "Foo User" 57 // Check the element contains an attribute with value equals "Foo User"
58 $this->assertGreaterThan(0, $crawler->filter('[value="Foo User"]')->count(), 'Missing element [value="Foo User"]'); 58 $this->assertGreaterThan(0, $crawler->filter('[value="Foo User"]')->count(), 'Missing element [value="Foo User"]');
59 59
60 $crawler = $client->request('GET', '/users/'); 60 $crawler = $client->request('GET', '/users/list');
61 $crawler = $client->click($crawler->selectLink('user.list.edit_action')->last()->link()); 61 $crawler = $client->click($crawler->selectLink('user.list.edit_action')->last()->link());
62 62
63 // Delete the user 63 // Delete the user
@@ -73,9 +73,27 @@ class ManageControllerTest extends WallabagCoreTestCase
73 $this->logInAs('admin'); 73 $this->logInAs('admin');
74 $client = $this->getClient(); 74 $client = $this->getClient();
75 75
76 $crawler = $client->request('GET', '/users/'.$this->getLoggedInUserId().'/edit'); 76 $crawler = $client->request('GET', '/users/' . $this->getLoggedInUserId() . '/edit');
77 $disabled = $crawler->selectButton('user.form.delete')->extract('disabled'); 77 $disabled = $crawler->selectButton('user.form.delete')->extract('disabled');
78 78
79 $this->assertEquals('disabled', $disabled[0]); 79 $this->assertSame('disabled', $disabled[0]);
80 }
81
82 public function testUserSearch()
83 {
84 $this->logInAs('admin');
85 $client = $this->getClient();
86
87 // Search on unread list
88 $crawler = $client->request('GET', '/users/list');
89
90 $form = $crawler->filter('form[name=search_users]')->form();
91 $data = [
92 'search_user[term]' => 'admin',
93 ];
94
95 $crawler = $client->submit($form, $data);
96
97 $this->assertCount(2, $crawler->filter('tr')); // 1 result + table header
80 } 98 }
81} 99}
diff --git a/tests/Wallabag/UserBundle/EventListener/AuthenticationFailureListenerTest.php b/tests/Wallabag/UserBundle/EventListener/AuthenticationFailureListenerTest.php
new file mode 100644
index 00000000..9e33cdca
--- /dev/null
+++ b/tests/Wallabag/UserBundle/EventListener/AuthenticationFailureListenerTest.php
@@ -0,0 +1,66 @@
1<?php
2
3namespace Tests\Wallabag\UserBundle\EventListener;
4
5use Monolog\Handler\TestHandler;
6use Monolog\Logger;
7use Symfony\Component\EventDispatcher\EventDispatcher;
8use Symfony\Component\HttpFoundation\Request;
9use Symfony\Component\HttpFoundation\RequestStack;
10use Symfony\Component\Security\Core\AuthenticationEvents;
11use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent;
12use Wallabag\UserBundle\EventListener\AuthenticationFailureListener;
13
14class AuthenticationFailureListenerTest extends \PHPUnit_Framework_TestCase
15{
16 private $requestStack;
17 private $logHandler;
18 private $listener;
19 private $dispatcher;
20
21 protected function setUp()
22 {
23 $request = Request::create('/');
24 $request->request->set('_username', 'admin');
25
26 $this->requestStack = new RequestStack();
27 $this->requestStack->push($request);
28
29 $this->logHandler = new TestHandler();
30 $logger = new Logger('test', [$this->logHandler]);
31
32 $this->listener = new AuthenticationFailureListener(
33 $this->requestStack,
34 $logger
35 );
36
37 $this->dispatcher = new EventDispatcher();
38 $this->dispatcher->addSubscriber($this->listener);
39 }
40
41 public function testOnAuthenticationFailure()
42 {
43 $token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')
44 ->disableOriginalConstructor()
45 ->getMock();
46
47 $exception = $this->getMockBuilder('Symfony\Component\Security\Core\Exception\AuthenticationException')
48 ->disableOriginalConstructor()
49 ->getMock();
50
51 $event = new AuthenticationFailureEvent(
52 $token,
53 $exception
54 );
55
56 $this->dispatcher->dispatch(
57 AuthenticationEvents::AUTHENTICATION_FAILURE,
58 $event
59 );
60
61 $records = $this->logHandler->getRecords();
62
63 $this->assertCount(1, $records);
64 $this->assertSame('Authentication failure for user "admin", from IP "127.0.0.1", with UA: "Symfony/3.X".', $records[0]['message']);
65 }
66}
diff --git a/tests/Wallabag/UserBundle/EventListener/CreateConfigListenerTest.php b/tests/Wallabag/UserBundle/EventListener/CreateConfigListenerTest.php
index 01796ded..e5a145b8 100644
--- a/tests/Wallabag/UserBundle/EventListener/CreateConfigListenerTest.php
+++ b/tests/Wallabag/UserBundle/EventListener/CreateConfigListenerTest.php
@@ -8,8 +8,8 @@ use Symfony\Component\EventDispatcher\EventDispatcher;
8use Symfony\Component\HttpFoundation\Request; 8use Symfony\Component\HttpFoundation\Request;
9use Symfony\Component\HttpFoundation\Response; 9use Symfony\Component\HttpFoundation\Response;
10use Wallabag\CoreBundle\Entity\Config; 10use Wallabag\CoreBundle\Entity\Config;
11use Wallabag\UserBundle\EventListener\CreateConfigListener;
12use Wallabag\UserBundle\Entity\User; 11use Wallabag\UserBundle\Entity\User;
12use Wallabag\UserBundle\EventListener\CreateConfigListener;
13 13
14class CreateConfigListenerTest extends \PHPUnit_Framework_TestCase 14class CreateConfigListenerTest extends \PHPUnit_Framework_TestCase
15{ 15{
diff --git a/tests/Wallabag/UserBundle/Mailer/AuthCodeMailerTest.php b/tests/Wallabag/UserBundle/Mailer/AuthCodeMailerTest.php
index 21412da6..7381ccf1 100644
--- a/tests/Wallabag/UserBundle/Mailer/AuthCodeMailerTest.php
+++ b/tests/Wallabag/UserBundle/Mailer/AuthCodeMailerTest.php
@@ -68,8 +68,8 @@ TWIG;
68 68
69 $msg = $this->spool->getMessages()[0]; 69 $msg = $this->spool->getMessages()[0];
70 $this->assertArrayHasKey('test@wallabag.io', $msg->getTo()); 70 $this->assertArrayHasKey('test@wallabag.io', $msg->getTo());
71 $this->assertEquals(['nobody@test.io' => 'wallabag test'], $msg->getFrom()); 71 $this->assertSame(['nobody@test.io' => 'wallabag test'], $msg->getFrom());
72 $this->assertEquals('subject', $msg->getSubject()); 72 $this->assertSame('subject', $msg->getSubject());
73 $this->assertContains('text body http://0.0.0.0/support', $msg->toString()); 73 $this->assertContains('text body http://0.0.0.0/support', $msg->toString());
74 $this->assertContains('html body 666666', $msg->toString()); 74 $this->assertContains('html body 666666', $msg->toString());
75 } 75 }