Completed
Push — master ( ca4b0a...c0876f )
by Dominik
16:11
created

MailgunEventControllerTest::getValidSignature()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 4
Bugs 0 Features 3
Metric Value
c 4
b 0
f 3
dl 0
loc 7
rs 9.4285
cc 1
eloc 4
nc 1
nop 2
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
    public function testShowLog()
75
    {
76
        $this->checkApplication();
77
78
        // Create a new client to browse the application
79
        $client = static::createClient();
80
        $client->followRedirects();
81
82
        $manager = $this->getEntityManager();
83
        $eventReop = $manager->getRepository("Azine\MailgunWebhooksBundle\Entity\MailgunEvent");
84
85
        $apiKey = $this->getContainer()->getParameter(AzineMailgunWebhooksExtension::PREFIX."_".AzineMailgunWebhooksExtension::API_KEY);
86
87
        // make sure there is some data in the application
88
        if (sizeof($eventReop->findAll()) < 102) {
89
            TestHelper::addMailgunEvents($manager, 102, $apiKey);
90
        }
91
        $count = sizeof($eventReop->findAll());
92
93
        // view the list of events
94
        $pageSize = 25;
95
        $listUrl = substr($this->getRouter()->generate("mailgunevent_list", array('_locale' => "en", 'page' => 1, 'pageSize' => $pageSize, 'clear' => true)), 13);
96
        $crawler = $this->loginUserIfRequired($client, $listUrl);
97
        $this->assertEquals($pageSize+1, $crawler->filter(".eventsTable tr")->count(), "$pageSize Mailgun events (+1 header row) expected on this page ($listUrl)!");
98
99
        // view a single event
100
        $link = $crawler->filter(".eventsTable tr a:first-child")->first()->link();
101
        $posLastSlash = strrpos($link->getUri(), "/");
102
        $posOfIdStart = strrpos($link->getUri(), "/", -6) +1;
103
        $eventId = substr($link->getUri(), $posOfIdStart, $posLastSlash-$posOfIdStart);
104
        $crawler = $client->click($link);
105
        $this->assertEquals(200, $client->getResponse()->getStatusCode(), "Status 200 expected.");
106
        $this->assertEquals($eventId, $crawler->filter("td")->first()->text(), "Content of first td should be the eventId ($eventId)");
107
108
        // delete the event from show-page
109
        $link = $crawler->selectLink("delete")->link();
110
        $crawler = $client->click($link);
111
112
        // check that it is gone from the list
113
        $this->assertEquals(0, $crawler->filter("#event$eventId")->count(), "The deleted event should not be in the list anymore.");
114
115
        // delete the event from list-page
116
        $crawler = $client->followRedirect();
117
        $link = $crawler->filter(".eventsTable tr .deleteLink")->first()->link();
118
        $delUri = $link->getUri();
119
        $eventId = substr($delUri, strrpos($delUri, "/") + 1);
120
        $crawler = $client->click($link);
121
122
        // check that it is gone from the list
123
        $this->assertEquals(0, $crawler->filter("#event$eventId")->count(), "The deleted event should not be in the list anymore.");
124
125
        // filter the list for something
126
        $crawler = $client->followRedirect();
127
        $form = $crawler->selectButton("Filter")->form();
128
        $form['filter[eventType]']->select("delivered");
129
        $crawler = $client->submit($form);
130
        $this->assertEquals($crawler->filter(".eventsTable tr")->count() -1, $crawler->filter(".eventsTable a:contains('delivered')")->count(), "There should only be 'delivered' events in the list");
131
132
        // delete entry with xmlHttpRequest
133
        $eventToDelete = $eventReop->findOneBy(array());
134
        $ajaxUrl = $this->getRouter()->generate("mailgunevent_delete_ajax");
135
        $client->request("POST", $ajaxUrl, array('eventId' => $eventToDelete->getId()), array(), array('HTTP_X_REQUESTED_WITH' => 'XMLHttpRequest'));
136
        $this->assertEquals('{"success":true}', $client->getResponse()->getContent(), "JSON response expcted.");
137
138
        // show/delete inexistent log entry
139
        $inexistentEventId = md5("123invalid");
140
        $url = $this->getRouter()->generate("mailgunevent_delete", array("eventId" => $inexistentEventId));
141
        $client->request("GET", $url);
142
        $this->assertEquals(404, $client->getResponse()->getStatusCode(), "404 expected for invalid eventId ($inexistentEventId).");
143
144
        $url = $this->getRouter()->generate("mailgunevent_show", array("id" => $inexistentEventId));
145
        $client->request("GET", $url);
146
        $this->assertEquals(404, $client->getResponse()->getStatusCode(), "404 expected.");
147
148
        // show inexistent page
149
        $maxPage = floor($count/$pageSize);
150
        $beyondListUrl = $this->getRouter()->generate("mailgunevent_list", array('_locale' => "en", 'page' => $maxPage + 1, 'pageSize' => $pageSize, 'clear' => true));
151
        $client->request("GET", $beyondListUrl);
152
        $crawler = $client->followRedirect();
153
        $this->assertEquals(2, $crawler->filter(".pagination .disabled:contains('Next')")->count(), "Expected to be on the last page => the next button should be disabled.");
154
155
    }
156
157
    /**
158
     * Load the url and login if required.
159
     * @param  string  $url
160
     * @param  string  $username
161
     * @param  Client  $client
162
     * @return Crawler $crawler of the page of the url or the page after the login
163
     */
164 View Code Duplication
    private function loginUserIfRequired(Client $client, $url, $username = "dominik", $password = "lkjlkjlkjlkj")
165
    {
166
        // try to get the url
167
        $client->followRedirects();
168
        $crawler = $client->request("GET", $url);
169
170
        $this->assertEquals(200, $client->getResponse()->getStatusCode(), "Status-Code 200 expected.");
171
172
        // if redirected to a login-page, login as admin-user
173
        if ($crawler->filter("input")->count() == 5 && $crawler->filter("#username")->count() == 1 && $crawler->filter("#password")->count() == 1 ) {
174
175
            // set the password of the admin
176
               $userProvider = $this->getContainer()->get('fos_user.user_provider.username_email');
177
            $user = $userProvider->loadUserByUsername($username);
178
            $user->setPlainPassword($password);
179
            $user->addRole("ROLE_ADMIN");
180
181
            $userManager = $this->getContainer()->get('fos_user.user_manager');
182
            $userManager->updateUser($user);
183
184
            $crawler = $crawler->filter("input[type='submit']");
185
            $form = $crawler->form();
186
            $form->get('_username')->setValue($username);
187
            $form->get('_password')->setValue($password);
188
            $crawler = $client->submit($form);
189
        }
190
191
        $this->assertEquals(200, $client->getResponse()->getStatusCode(),"Login failed.");
192
        $client->followRedirects(false);
193
194
        $this->assertStringEndsWith($url, $client->getRequest()->getUri(), "Login failed or not redirected to requested url: $url vs. ".$client->getRequest()->getUri());
195
196
        return $crawler;
197
    }
198
199
    /**
200
     * @var ContainerInterface
201
     */
202
    private $container;
203
204
    /**
205
     * Get the current container
206
     * @return \Symfony\Component\DependencyInjection\ContainerInterface
207
     */
208
    private function getContainer()
209
    {
210
        if ($this->container == null) {
211
            $this->container = static::$kernel->getContainer();
212
        }
213
214
        return $this->container;
215
    }
216
217
    /**
218
     * @return UrlGeneratorInterface
219
     */
220
    private function getRouter()
221
    {
222
        return $this->getContainer()->get('router');
223
    }
224
225
    /**
226
     * @return EntityManager
227
     */
228
    private function getEntityManager()
229
    {
230
        return $this->getContainer()->get('doctrine.orm.entity_manager');
231
    }
232
233
    /**
234
     * @return EventDispatcher
235
     */
236
    private function getEventDispatcher()
237
    {
238
        return $this->getContainer()->get("event_dispatcher");
239
    }
240
241
    /**
242
     * Check if the current setup is a full application.
243
     * If not, mark the test as skipped else continue.
244
     */
245
    private function checkApplication()
246
    {
247
        try {
248
            static::$kernel = static::createKernel(array());
249
        } catch (\RuntimeException $ex) {
250
            $this->markTestSkipped("There does not seem to be a full application available (e.g. running tests on travis.org). So this test is skipped.");
251
252
            return;
253
        }
254
    }
255
}
256