From f1b666aeecf4593c53099cd671944703b4a8356a Mon Sep 17 00:00:00 2001 From: Edie Lemoine Date: Fri, 15 Nov 2024 12:48:01 +0100 Subject: [PATCH] test: add more webhook tests --- tests/Bootstrap/MockLogger.php | 12 +- .../App/Webhook/PdkWebhookManagerTest.php | 103 ++++++++++++++---- 2 files changed, 91 insertions(+), 24 deletions(-) diff --git a/tests/Bootstrap/MockLogger.php b/tests/Bootstrap/MockLogger.php index 7227a5da1..4dccedd85 100644 --- a/tests/Bootstrap/MockLogger.php +++ b/tests/Bootstrap/MockLogger.php @@ -80,10 +80,20 @@ public function getLogFiles(): array } /** + * @param null|string $level + * * @return array */ - public function getLogs(): array + public function getLogs(string $level = null): array { + if ($level) { + $byLevel = array_filter($this->logs, static function (array $log) use ($level) { + return $log['level'] === $level; + }); + + return array_values($byLevel); + } + return $this->logs; } diff --git a/tests/Unit/App/Webhook/PdkWebhookManagerTest.php b/tests/Unit/App/Webhook/PdkWebhookManagerTest.php index 387a4f91e..78cb846f6 100644 --- a/tests/Unit/App/Webhook/PdkWebhookManagerTest.php +++ b/tests/Unit/App/Webhook/PdkWebhookManagerTest.php @@ -18,6 +18,7 @@ use MyParcelNL\Pdk\Base\Support\Arr; use MyParcelNL\Pdk\Facade\Pdk; use MyParcelNL\Pdk\Tests\Uses\UsesMockEachCron; +use MyParcelNL\Pdk\Tests\Uses\UsesMockEachLogger; use MyParcelNL\Pdk\Tests\Uses\UsesMockPdkInstance; use MyParcelNL\Pdk\Webhook\Collection\WebhookSubscriptionCollection; use MyParcelNL\Pdk\Webhook\Model\WebhookSubscription; @@ -27,23 +28,19 @@ uses()->group('webhook'); -usesShared(new UsesMockPdkInstance(), new UsesMockEachCron()); - -it('dispatches and executes webhooks', function (string $hook, string $calledClass, bool $useHeader) { - /** @var \MyParcelNL\Pdk\App\Webhook\Contract\PdkWebhooksRepositoryInterface $repository */ - $repository = Pdk::get(PdkWebhooksRepositoryInterface::class); - /** @var \MyParcelNL\Pdk\Tests\Bootstrap\MockPdkWebhookManager $webhookManager */ - $webhookManager = Pdk::get(PdkWebhookManagerInterface::class); - /** @var \MyParcelNL\Pdk\Tests\Bootstrap\MockCronService $cronService */ - $cronService = Pdk::get(CronServiceInterface::class); - - $repository->storeHashedUrl('https://example.com/hashed-url'); - $repository->store(new WebhookSubscriptionCollection([['hook' => $hook, 'url' => $repository->getHashedUrl()]])); - - $time = time(); - - $request = Request::create( - $repository->getHashedUrl(), +usesShared(new UsesMockPdkInstance(), new UsesMockEachCron(), new UsesMockEachLogger()); + +/** + * @param string $url + * @param string $hook + * @param bool $useHeader + * + * @return \Symfony\Component\HttpFoundation\Request + */ +function createWebhookRequest(string $url, string $hook, bool $useHeader = false): Request +{ + return Request::create( + $url, Request::METHOD_POST, [], [], @@ -57,16 +54,42 @@ ], ]) ); +} - $response = $webhookManager->call($request); +function sendWebhook(string $hook, bool $useHeader = false): Response +{ + /** @var \MyParcelNL\Pdk\App\Webhook\Contract\PdkWebhooksRepositoryInterface $webhooksRepository */ + $webhooksRepository = Pdk::get(PdkWebhooksRepositoryInterface::class); + /** @var \MyParcelNL\Pdk\Tests\Bootstrap\MockPdkWebhookManager $webhookManager */ + $webhookManager = Pdk::get(PdkWebhookManagerInterface::class); + + $subscriptions = new WebhookSubscriptionCollection([ + [ + 'hook' => $hook, + 'url' => $webhooksRepository->getHashedUrl(), + ], + ]); + + $webhooksRepository->storeHashedUrl('https://example.com/hashed-url'); + $webhooksRepository->store($subscriptions); + + return $webhookManager->call(createWebhookRequest($webhooksRepository->getHashedUrl(), $hook, $useHeader)); +} + +it('dispatches and executes webhooks', function (string $hook, string $calledClass, bool $useHeader) { + /** @var \MyParcelNL\Pdk\Tests\Bootstrap\MockPdkWebhookManager $webhookManager */ + $webhookManager = Pdk::get(PdkWebhookManagerInterface::class); + /** @var \MyParcelNL\Pdk\Tests\Bootstrap\MockCronService $cronService */ + $cronService = Pdk::get(CronServiceInterface::class); + + $time = time(); + $response = sendWebhook($hook, $useHeader); $scheduled = $cronService->getScheduledTasks(); $timestamp = $scheduled->first()['timestamp']; expect($response->getStatusCode()) ->toBe(Response::HTTP_ACCEPTED) - ->and($request->headers->get('x-myparcel-hook')) - ->toBe($hook) ->and($response->getStatusCode()) ->toBe(Response::HTTP_ACCEPTED) ->and($scheduled->all()) @@ -77,9 +100,7 @@ ->and($timestamp) ->toBeLessThanOrEqual($time + 10) ->and($scheduled->first()['callback']) - ->toBe([$webhookManager, 'processWebhook']) - ->and($scheduled->first()['args']) - ->toBe([$request]); + ->toBe([$webhookManager, 'processWebhook']); $cronService->executeScheduledTask(); @@ -130,3 +151,39 @@ 'no header' => [false], 'header' => [true], ]); + +it('throws error if webhook is not found', function () { + /** @var \MyParcelNL\Pdk\App\Webhook\Contract\PdkWebhooksRepositoryInterface $repository */ + $repository = Pdk::get(PdkWebhooksRepositoryInterface::class); + /** @var \MyParcelNL\Pdk\Tests\Bootstrap\MockPdkWebhookManager $webhookManager */ + $webhookManager = Pdk::get(PdkWebhookManagerInterface::class); + + $repository->storeHashedUrl('https://example.com/hashed-url'); + + $request = createWebhookRequest($repository->getHashedUrl(), 'unknown'); + + $response = $webhookManager->call($request); + + expect($response->getStatusCode())->toBe(Response::HTTP_ACCEPTED); +}); + +it('does nothing if webhook is called with invalid context', function () { + /** @var \MyParcelNL\Pdk\App\Webhook\Contract\PdkWebhooksRepositoryInterface $repository */ + $repository = Pdk::get(PdkWebhooksRepositoryInterface::class); + /** @var \MyParcelNL\Pdk\Tests\Bootstrap\MockPdkWebhookManager $webhookManager */ + $webhookManager = Pdk::get(PdkWebhookManagerInterface::class); + /** @var \MyParcelNL\Pdk\Tests\Bootstrap\MockCronService $cronService */ + $cronService = Pdk::get(CronServiceInterface::class); + + $repository->storeHashedUrl('https://example.com/hashed-url'); + + $request = createWebhookRequest($repository->getHashedUrl(), 'unknown'); + $response = $webhookManager->call($request, 'invalid_context'); + + $scheduledTasks = $cronService->getScheduledTasks(); + + expect($response->getStatusCode()) + ->toBe(Response::HTTP_ACCEPTED) + ->and($scheduledTasks) + ->toBeEmpty(); +});