Skip to content

Commit

Permalink
fix: fix webhooks
Browse files Browse the repository at this point in the history
  • Loading branch information
EdieLemoine committed Nov 8, 2023
1 parent 412ab5c commit 920d2fd
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 26 deletions.
15 changes: 1 addition & 14 deletions src/App/Webhook/Hook/AbstractHook.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,7 @@ public function handle(Request $request): void
*/
public function validate(Request $request): bool
{
return $this->eventMatches($request, $this->getHookEvent());
}

/**
* @param \Symfony\Component\HttpFoundation\Request $request
* @param string $hook
*
* @return bool
*/
protected function eventMatches(Request $request, string $hook): bool
{
$content = $this->getHookBody($request);

return $request->headers->get('x-myparcel-hook') === $hook && $content['event'] === $hook;
return true;
}

/**
Expand Down
18 changes: 15 additions & 3 deletions src/App/Webhook/PdkWebhookManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,27 @@ public function processWebhook(Request $request): void
continue;
}

$hook->handle($request);

Logger::debug('Webhook processed', $logContext);
$this->handleHook($hook, $request, $logContext);
} catch (Throwable $exception) {
Logger::error('Webhook failed', $logContext);
}
}
}

/**
* @param \MyParcelNL\Pdk\App\Webhook\Contract\HookInterface $hook
* @param \Symfony\Component\HttpFoundation\Request $request
* @param array $logContext
*
* @return void
*/
protected function handleHook(HookInterface $hook, Request $request, array $logContext): void
{
$hook->handle($request);

Logger::debug('Webhook processed', $logContext);
}

/**
* @param string $event
*
Expand Down
2 changes: 2 additions & 0 deletions tests/Bootstrap/MockPdkConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
use MyParcelNL\Pdk\App\Order\Contract\PdkProductRepositoryInterface;
use MyParcelNL\Pdk\App\ShippingMethod\Contract\PdkShippingMethodRepositoryInterface;
use MyParcelNL\Pdk\App\Tax\Contract\TaxServiceInterface;
use MyParcelNL\Pdk\App\Webhook\Contract\PdkWebhookManagerInterface;
use MyParcelNL\Pdk\App\Webhook\Contract\PdkWebhookServiceInterface;
use MyParcelNL\Pdk\App\Webhook\Contract\PdkWebhooksRepositoryInterface;
use MyParcelNL\Pdk\Base\Concern\PdkInterface;
Expand Down Expand Up @@ -93,6 +94,7 @@ private static function getDefaultConfig(): array
PdkOrderRepositoryInterface::class => get(MockPdkOrderRepository::class),
PdkProductRepositoryInterface::class => get(MockPdkProductRepository::class),
PdkShippingMethodRepositoryInterface::class => get(MockPdkShippingMethodRepository::class),
PdkWebhookManagerInterface::class => get(MockPdkWebhookManager::class),
PdkWebhookServiceInterface::class => get(MockPdkWebhookService::class),
PdkWebhooksRepositoryInterface::class => get(MockPdkWebhooksRepository::class),
SettingsRepositoryInterface::class => get(MockSettingsRepository::class),
Expand Down
35 changes: 35 additions & 0 deletions tests/Bootstrap/MockPdkWebhookManager.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<?php

declare(strict_types=1);

namespace MyParcelNL\Pdk\Tests\Bootstrap;

use MyParcelNL\Pdk\App\Webhook\Contract\HookInterface;
use MyParcelNL\Pdk\App\Webhook\PdkWebhookManager;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Contracts\Service\ResetInterface;

final class MockPdkWebhookManager extends PdkWebhookManager implements ResetInterface
{
protected $calledHooks = [];

/**
* @return array
*/
public function getCalledHooks(): array
{
return $this->calledHooks;
}

public function reset(): void
{
$this->calledHooks = [];
}

protected function handleHook(HookInterface $hook, Request $request, array $logContext): void
{
$this->calledHooks[] = $hook;

parent::handleHook($hook, $request, $logContext);
}
}
1 change: 1 addition & 0 deletions tests/Bootstrap/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ protected function getResetServices(): array
MockMemoryCacheStorage::class,
MockOrderStatusService::class,
MockPdkActionsService::class,
MockPdkWebhookManager::class,
MockPdkWebhooksRepository::class,
SharedFactoryState::class,
];
Expand Down
68 changes: 59 additions & 9 deletions tests/Unit/App/Webhook/PdkWebhookManagerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,15 @@

use MyParcelNL\Pdk\App\Webhook\Contract\PdkWebhookManagerInterface;
use MyParcelNL\Pdk\App\Webhook\Contract\PdkWebhooksRepositoryInterface;
use MyParcelNL\Pdk\App\Webhook\Hook\OrderStatusChangeWebhook;
use MyParcelNL\Pdk\App\Webhook\Hook\ShipmentLabelCreatedWebhook;
use MyParcelNL\Pdk\App\Webhook\Hook\ShipmentStatusChangeWebhook;
use MyParcelNL\Pdk\App\Webhook\Hook\ShopCarrierAccessibilityUpdatedWebhook;
use MyParcelNL\Pdk\App\Webhook\Hook\ShopCarrierConfigurationUpdatedWebhook;
use MyParcelNL\Pdk\App\Webhook\Hook\ShopUpdatedWebhook;
use MyParcelNL\Pdk\App\Webhook\Hook\SubscriptionCreatedOrUpdatedWebhook;
use MyParcelNL\Pdk\Base\Contract\CronServiceInterface;
use MyParcelNL\Pdk\Base\Support\Arr;
use MyParcelNL\Pdk\Facade\Pdk;
use MyParcelNL\Pdk\Tests\Uses\UsesMockEachCron;
use MyParcelNL\Pdk\Tests\Uses\UsesMockPdkInstance;
Expand All @@ -21,10 +29,10 @@

usesShared(new UsesMockPdkInstance(), new UsesMockEachCron());

it('dispatches and executes webhooks with myparcel header', function (string $hook, bool $hasHeader) {
/** @var PdkWebhooksRepositoryInterface $repository */
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 PdkWebhookManagerInterface $webhookManager */
/** @var \MyParcelNL\Pdk\Tests\Bootstrap\MockPdkWebhookManager $webhookManager */
$webhookManager = Pdk::get(PdkWebhookManagerInterface::class);
/** @var \MyParcelNL\Pdk\Tests\Bootstrap\MockCronService $cronService */
$cronService = Pdk::get(CronServiceInterface::class);
Expand All @@ -40,11 +48,11 @@
[],
[],
[],
$hasHeader ? ['HTTP_X_MYPARCEL_HOOK' => $hook] : [],
['HTTP_X_MYPARCEL_HOOK' => $hook],
json_encode([
'data' => [
'hooks' => [
['event' => $hook],
$useHeader ? [] : ['event' => $hook],
],
],
])
Expand All @@ -58,9 +66,7 @@
expect($response->getStatusCode())
->toBe(Response::HTTP_ACCEPTED)
->and($request->headers->get('x-myparcel-hook'))
->toBe($hasHeader ? $hook : null)
->and($request->getContent())
->toEqual('{"data":{"hooks":[{"event":"' . $hook . '"}]}}')
->toBe($hook)
->and($response->getStatusCode())
->toBe(Response::HTTP_ACCEPTED)
->and($scheduled->all())
Expand All @@ -74,8 +80,52 @@
->toBe([$webhookManager, 'processWebhook'])
->and($scheduled->first()['args'])
->toBe([$request]);

$cronService->executeScheduledTask();

$calledHooks = $webhookManager->getCalledHooks();

expect($calledHooks)
->toHaveLength(1)
->and(Arr::first($calledHooks))
->toBeInstanceOf($calledClass);
})
->with(WebhookSubscription::ALL)
->with([
WebhookSubscription::SHIPMENT_STATUS_CHANGE => [
WebhookSubscription::SHIPMENT_STATUS_CHANGE,
ShipmentStatusChangeWebhook::class,
],

WebhookSubscription::SHIPMENT_LABEL_CREATED => [
WebhookSubscription::SHIPMENT_LABEL_CREATED,
ShipmentLabelCreatedWebhook::class,
],

WebhookSubscription::ORDER_STATUS_CHANGE => [
WebhookSubscription::ORDER_STATUS_CHANGE,
OrderStatusChangeWebhook::class,
],

WebhookSubscription::SHOP_UPDATED => [
WebhookSubscription::SHOP_UPDATED,
ShopUpdatedWebhook::class,
],

WebhookSubscription::SHOP_CARRIER_ACCESSIBILITY_UPDATED => [
WebhookSubscription::SHOP_CARRIER_ACCESSIBILITY_UPDATED,
ShopCarrierAccessibilityUpdatedWebhook::class,
],

WebhookSubscription::SHOP_CARRIER_CONFIGURATION_UPDATED => [
WebhookSubscription::SHOP_CARRIER_CONFIGURATION_UPDATED,
ShopCarrierConfigurationUpdatedWebhook::class,
],

WebhookSubscription::SUBSCRIPTION_CREATED_OR_UPDATED => [
WebhookSubscription::SUBSCRIPTION_CREATED_OR_UPDATED,
SubscriptionCreatedOrUpdatedWebhook::class,
],
])
->with([
'no header' => [false],
'header' => [true],
Expand Down

0 comments on commit 920d2fd

Please sign in to comment.