Completed
Push — master ( c0876f...8642a3 )
by Dominik
03:18
created

MailgunEventControllerTest::getEventDispatcher()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 0
1
<?php
2
namespace Azine\MailgunWebhooksBundle\Tests\Controller;
3
4
use Azine\MailgunWebhooksBundle\Tests\TestHelper;
5
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
6
use Symfony\Component\DomCrawler\Crawler;
7
use Symfony\Bundle\FrameworkBundle\Client;
8
use Symfony\Component\DependencyInjection\ContainerInterface;
9
use Azine\MailgunWebhooksBundle\Entity\MailgunEvent;
10
use Symfony\Component\EventDispatcher\EventDispatcher;
11
use Azine\MailgunWebhooksBundle\DependencyInjection\AzineMailgunWebhooksExtension;
12
use Doctrine\ORM\EntityManager;
13
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
14
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
15
16
class MailgunEventControllerTest extends WebTestCase
17
{
18
    public function testWebHookCreateAndEventDispatching()
19
    {
20
        $this->checkApplication();
21
22
        $client = static::createClient();
23
        $client->request("GET", "/");
24
25
        // create a subscriber to listen to create_events.
26
        $subscriberMock = $this->getMockBuilder("Azine\MailgunWebhooksBundle\Tests\EventSubscriberMock")->setMethods(array('handleCreate'))->getMock();
27
        $this->assertTrue($subscriberMock  instanceof EventSubscriberInterface);
28
        $this->getEventDispatcher()->addSubscriber($subscriberMock);
29
        $this->assertTrue($this->getEventDispatcher()->hasListeners(MailgunEvent::CREATE_EVENT));
30
31
//		dominik I would expect the method handleCreate to be called once, but for some reason it is not.
32
//		$subscriberMock->expects($this->once())->method("handleCreate");
33
34
        // get webhook url
35
        $url = $this->getRouter()->generate("mailgunevent_webhook", array(), UrlGeneratorInterface::ABSOLUTE_URL);
36
37
        $manager = $this->getEntityManager();
38
        $eventReop = $manager->getRepository("Azine\MailgunWebhooksBundle\Entity\MailgunEvent");
39
        $count = sizeof($eventReop->findAll());
40
41
        // post invalid data to the webhook-url and check the response & database
42
        $webhookdata = json_encode($this->getInvalidPostData());
43
        $crawler = $client->request("POST", $url, $this->getInvalidPostData());
44
45
        $this->assertEquals(401, $client->getResponse()->getStatusCode(), "Response-Code 401 expected for post-data with invalid signature: \n\n$webhookdata\n\n\n");
46
        $this->assertContains("Signature verification failed.", $crawler->text(), "Response expected.");
47
        $this->assertEquals($count, sizeof($eventReop->findAll()), "No new db entry for the webhook expected!");
48
49
        // post valid data to the webhook-url and check the response
50
        $webhookdata = json_encode($this->getValidPostData());
51
        $crawler = $client->request("POST", $url, $this->getValidPostData());
52
        $this->assertEquals(200, $client->getResponse()->getStatusCode(), "Response-Code 200 expected for '$url'.\n\n$webhookdata\n\n\n".$client->getResponse()->getContent());
53
        $this->assertContains("Thanx, for the info.", $crawler->text(), "Response expected.");
54
        $this->assertEquals($count + 1, sizeof($eventReop->findAll()), "One new db entry for the webhook expected!");
55
56
    }
57
58
    private function getValidPostData()
59
    {
60
        $postData = TestHelper::getPostDataWithoutSignature();
61
        $postData['signature'] = $this->getValidSignature($postData['token'], $postData['timestamp']);
62
63
        return $postData;
64
    }
65
66
    private function getInvalidPostData()
67
    {
68
        $postData = TestHelper::getPostDataWithoutSignature();
69
        $postData['signature'] = "invalid-signature";
70
71
        return $postData;
72
    }
73
74
    /**
75
     * @param string  $token
76
     * @param integer $timestamp
77
     */
78
    private function getValidSignature($token, $timestamp)
79
    {
80
        $key = $this->getContainer()->getParameter(AzineMailgunWebhooksExtension::PREFIX."_".AzineMailgunWebhooksExtension::API_KEY);
81
        $signature = hash_hmac("SHA256", $timestamp.$token, $key);
82
83
        return $signature;
84
    }
85
86
    public function testShowLog()
87
    {
88
        $this->checkApplication();
89
90
        // Create a new client to browse the application
91
        $client = static::createClient();
92
        $client->followRedirects();
93
94
        $manager = $this->getEntityManager();
95
        $eventReop = $manager->getRepository("Azine\MailgunWebhooksBundle\Entity\MailgunEvent");
96
97
        $apiKey = $this->getContainer()->getParameter(AzineMailgunWebhooksExtension::PREFIX."_".AzineMailgunWebhooksExtension::API_KEY);
98
99
        // make sure there is some data in the application
100
        if (sizeof($eventReop->findAll()) < 102) {
101
            TestHelper::addMailgunEvents($manager, 102, $apiKey);
102
        }
103
        $count = sizeof($eventReop->findAll());
104
105
        // view the list of events
106
        $pageSize = 25;
107
        $listUrl = substr($this->getRouter()->generate("mailgunevent_list", array('_locale' => "en", 'page' => 1, 'pageSize' => $pageSize, 'clear' => true)), 13);
108
        $crawler = $this->loginUserIfRequired($client, $listUrl);
109
        $this->assertEquals($pageSize+1, $crawler->filter(".eventsTable tr")->count(), "$pageSize Mailgun events (+1 header row) expected on this page ($listUrl)!");
110
111
        // view a single event
112
        $link = $crawler->filter(".eventsTable tr a:first-child")->first()->link();
113
        $posLastSlash = strrpos($link->getUri(), "/");
114
        $posOfIdStart = strrpos($link->getUri(), "/", -6) +1;
115
        $eventId = substr($link->getUri(), $posOfIdStart, $posLastSlash-$posOfIdStart);
116
        $crawler = $client->click($link);
117
        $this->assertEquals(200, $client->getResponse()->getStatusCode(), "Status 200 expected.");
118
        $this->assertEquals($eventId, $crawler->filter("td")->first()->text(), "Content of first td should be the eventId ($eventId)");
119
120
        // delete the event from show-page
121
        $link = $crawler->selectLink("delete")->link();
122
        $crawler = $client->click($link);
123
124
        // check that it is gone from the list
125
        $this->assertEquals(0, $crawler->filter("#event$eventId")->count(), "The deleted event should not be in the list anymore.");
126
127
        // delete the event from list-page
128
        $crawler = $client->followRedirect();
129
        $link = $crawler->filter(".eventsTable tr .deleteLink")->first()->link();
130
        $delUri = $link->getUri();
131
        $eventId = substr($delUri, strrpos($delUri, "/") + 1);
132
        $crawler = $client->click($link);
133
134
        // check that it is gone from the list
135
        $this->assertEquals(0, $crawler->filter("#event$eventId")->count(), "The deleted event should not be in the list anymore.");
136
137
        // filter the list for something
138
        $crawler = $client->followRedirect();
139
        $form = $crawler->selectButton("Filter")->form();
140
        $form['filter[eventType]']->select("delivered");
141
        $crawler = $client->submit($form);
142
        $this->assertEquals($crawler->filter(".eventsTable tr")->count() -1, $crawler->filter(".eventsTable a:contains('delivered')")->count(), "There should only be 'delivered' events in the list");
143
144
        // delete entry with xmlHttpRequest
145
        $eventToDelete = $eventReop->findOneBy(array());
146
        $ajaxUrl = $this->getRouter()->generate("mailgunevent_delete_ajax");
147
        $client->request("POST", $ajaxUrl, array('eventId' => $eventToDelete->getId()), array(), array('HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest'));
148
        $this->assertEquals('{"success":true}', $client->getResponse()->getContent(), "JSON response expcted.");
149
150
        // show/delete inexistent log entry
151
        $inexistentEventId = md5("123invalid");
152
        $url = $this->getRouter()->generate("mailgunevent_delete", array("eventId" => $inexistentEventId));
153
        $client->request("GET", $url);
154
        $this->assertEquals(404, $client->getResponse()->getStatusCode(), "404 expected for invalid eventId ($inexistentEventId).");
155
156
        $url = $this->getRouter()->generate("mailgunevent_show", array("id" => $inexistentEventId));
157
        $client->request("GET", $url);
158
        $this->assertEquals(404, $client->getResponse()->getStatusCode(), "404 expected.");
159
160
        // show inexistent page
161
        $maxPage = floor($count/$pageSize);
162
        $beyondListUrl = $this->getRouter()->generate("mailgunevent_list", array('_locale' => "en", 'page' => $maxPage + 1, 'pageSize' => $pageSize, 'clear' => true));
163
        $client->request("GET", $beyondListUrl);
164
        $crawler = $client->followRedirect();
165
        $this->assertEquals(2, $crawler->filter(".pagination .disabled:contains('Next')")->count(), "Expected to be on the last page => the next button should be disabled.");
166
167
    }
168
169
    /**
170
     * Load the url and login if required.
171
     * @param  string  $url
172
     * @param  string  $username
173
     * @param  Client  $client
174
     * @return Crawler $crawler of the page of the url or the page after the login
175
     */
176 View Code Duplication
    private function loginUserIfRequired(Client $client, $url, $username = "dominik", $password = "lkjlkjlkjlkj")
177
    {
178
        // try to get the url
179
        $client->followRedirects();
180
        $crawler = $client->request("GET", $url);
181
182
        $this->assertEquals(200, $client->getResponse()->getStatusCode(), "Status-Code 200 expected.");
183
184
        // if redirected to a login-page, login as admin-user
185
        if ($crawler->filter("input")->count() == 5 && $crawler->filter("#username")->count() == 1 && $crawler->filter("#password")->count() == 1 ) {
186
187
            // set the password of the admin
188
               $userProvider = $this->getContainer()->get('fos_user.user_provider.username_email');
189
            $user = $userProvider->loadUserByUsername($username);
190
            $user->setPlainPassword($password);
191
            $user->addRole("ROLE_ADMIN");
192
193
            $userManager = $this->getContainer()->get('fos_user.user_manager');
194
            $userManager->updateUser($user);
195
196
            $crawler = $crawler->filter("input[type='submit']");
197
            $form = $crawler->form();
198
            $form->get('_username')->setValue($username);
199
            $form->get('_password')->setValue($password);
200
            $crawler = $client->submit($form);
201
        }
202
203
        $this->assertEquals(200, $client->getResponse()->getStatusCode(),"Login failed.");
204
        $client->followRedirects(false);
205
206
        $this->assertStringEndsWith($url, $client->getRequest()->getUri(), "Login failed or not redirected to requested url: $url vs. ".$client->getRequest()->getUri());
207
208
        return $crawler;
209
    }
210
211
    /**
212
     * @var ContainerInterface
213
     */
214
    private $container;
215
216
    /**
217
     * Get the current container
218
     * @return \Symfony\Component\DependencyInjection\ContainerInterface
219
     */
220
    private function getContainer()
221
    {
222
        if ($this->container == null) {
223
            $this->container = static::$kernel->getContainer();
224
        }
225
226
        return $this->container;
227
    }
228
229
    /**
230
     * @return UrlGeneratorInterface
231
     */
232
    private function getRouter()
233
    {
234
        return $this->getContainer()->get('router');
235
    }
236
237
    /**
238
     * @return EntityManager
239
     */
240
    private function getEntityManager()
241
    {
242
        return $this->getContainer()->get('doctrine.orm.entity_manager');
243
    }
244
245
    /**
246
     * @return EventDispatcher
247
     */
248
    private function getEventDispatcher()
249
    {
250
        return $this->getContainer()->get("event_dispatcher");
251
    }
252
253
    /**
254
     * Check if the current setup is a full application.
255
     * If not, mark the test as skipped else continue.
256
     */
257
    private function checkApplication()
258
    {
259
        try {
260
            static::$kernel = static::createKernel(array());
261
        } catch (\RuntimeException $ex) {
262
            $this->markTestSkipped("There does not seem to be a full application available (e.g. running tests on travis.org). So this test is skipped.");
263
264
            return;
265
        }
266
    }
267
}
268