diff --git a/Test/Unit/Helper/WebhookTest.php b/Test/Unit/Helper/WebhookTest.php index b94d27f3a..fc832031d 100644 --- a/Test/Unit/Helper/WebhookTest.php +++ b/Test/Unit/Helper/WebhookTest.php @@ -18,6 +18,8 @@ use Adyen\Payment\Helper\Webhook\WebhookHandlerFactory; use Adyen\Payment\Logger\AdyenLogger; use ReflectionMethod; +use Adyen\Payment\Exception\AdyenWebhookException; + class WebhookTest extends AbstractAdyenTestCase { @@ -40,7 +42,7 @@ public function testProcessNotificationWithInvalidMerchantReference() public function testProcessNotificationWithOrderNotFound() { - $merchantReference = 'TestMerchant'; // Replace with a merchant reference that does not exist + $merchantReference = 'TestMerchant'; $notification = $this->createMock(Notification::class); $notification->method('getMerchantReference')->willReturn($merchantReference); @@ -53,7 +55,6 @@ public function testProcessNotificationWithOrderNotFound() $result = $webhookHandler->processNotification($notification); - // Assertions for the unsuccessful processing $this->assertFalse($result); } @@ -74,7 +75,6 @@ public function testProcessNotificationForInvalidDataException() $notification->method('getPspreference')->willReturn('ABCD1234GHJK5678'); $notification->method('getPaymentMethod')->willReturn('ADYEN_CC'); - // Mocking Order and other dependencies $payment = $this->createMock(Payment::class); $order = $this->createMock(Order::class); $order->method('getState')->willReturn(Order::STATE_NEW); @@ -93,10 +93,8 @@ public function testProcessNotificationForInvalidDataException() $logger = $this->createMock(AdyenLogger::class); $logger->method('getOrderContext')->with($order); - // Mock the WebhookHandlerFactory and WebhookHandler $webhookHandlerFactory = $this->createMock(WebhookHandlerFactory::class); - // Partially mock the Webhook class $webhookHandler = $this->getMockBuilder(Webhook::class) ->setConstructorArgs([ $this->createMock(Data::class), @@ -126,7 +124,6 @@ public function testProcessNotificationForInvalidDataException() public function testAddNotificationDetailsHistoryComment() { - // Mock necessary dependencies $orderMock = $this->getMockBuilder(Order::class) ->disableOriginalConstructor() ->getMock(); @@ -144,19 +141,15 @@ public function testAddNotificationDetailsHistoryComment() public function testGetTransitionState() { - // Mock necessary dependencies $notificationMock = $this->getMockBuilder(Notification::class) ->disableOriginalConstructor() ->getMock(); - // Create an instance of your class $webhook = $this->createWebhook(null, null, null, null, null, null, null, null, null); - // Use reflection to make the private method accessible $method = new ReflectionMethod(Webhook::class, 'getTransitionState'); $method->setAccessible(true); - // Set up expectations for the mocked objects $notificationMock->expects($this->once()) ->method('getEventCode') ->willReturn('AUTHORISATION'); @@ -167,10 +160,8 @@ public function testGetTransitionState() $orderState = Order::STATE_NEW; - // Call the private method $result = $method->invokeArgs($webhook, [$notificationMock, $orderState]); - // Assertions based on your logic $this->assertNotEquals( 'STATE_NEW', $result, @@ -205,7 +196,6 @@ public function testUpdateAdyenAttributes() $orderRepositoryMock = $this->createMock(OrderRepository::class); $orderRepositoryMock->method('get')->willReturn($orderMock); - // Create an instance of your class $webhook = $this->createWebhook( null, $serializerMock, @@ -218,7 +208,6 @@ public function testUpdateAdyenAttributes() $orderRepositoryMock ); - // Set up expectations for the mocked objects $notificationMock->expects($this->once()) ->method('getEventCode') ->willReturn(Notification::AUTHORISATION); @@ -264,7 +253,6 @@ public function testProcessNotificationWithSuccess() $orderHelper = $this->createMock(OrderHelper::class); $orderHelper->method('getOrderByIncrementId')->willReturn($order); - // Create a mock for the payment $payment = $this->createMock(Payment::class); $mockWebhookHandlerFactory = $this->createMock(WebhookHandlerFactory::class); $webhookHandlerInterface = $this->createMock(WebhookHandlerInterface::class); @@ -291,6 +279,280 @@ public function testProcessNotificationWithSuccess() $this->assertTrue($result); } + public function testProcessNotificationWithAdyenWebhookException() + { + $notification = $this->createMock(Notification::class); + $notification->method('getMerchantReference')->willReturn('TestMerchant'); + $notification->method('getEventCode')->willReturn('AUTHORISATION : FALSE'); + $notification->method('getEntityId')->willReturn('1234'); + $notification->method('getPspreference')->willReturn('ABCD1234GHJK5678'); + $notification->method('getPaymentMethod')->willReturn('ADYEN_CC'); + + $payment = $this->createMock(Payment::class); + $order = $this->createMock(Order::class); + $order->method('getState')->willReturn(Order::STATE_NEW); + $order->method('getIncrementId')->willReturn(123); + $order->method('getId')->willReturn(123); + $order->method('getStatus')->willReturn('processing'); + $order->method('getPayment')->willReturn($payment); + + $orderHelper = $this->createMock(OrderHelper::class); + $orderHelper->method('getOrderByIncrementId')->willReturn($order); + + $payment->expects($this->once()) + ->method('setAdditionalInformation') + ->with('payment_method', $notification->getPaymentMethod()); + + $webhookHandlerInterfaceMock = $this->createMock(WebhookHandlerInterface::class); + $webhookHandlerInterfaceMock->method('handleWebhook')->willThrowException(new AdyenWebhookException( + new \Magento\Framework\Phrase("Test Adyen webhook exception" + ))); + + $webhookHandlerFactory = $this->createMock(WebhookHandlerFactory::class); + $webhookHandlerFactory->method('create') + ->willReturn($webhookHandlerInterfaceMock); + + $logger = $this->createMock(AdyenLogger::class); + $logger->method('getOrderContext')->with($order); + + $webhookHandler = $this->getMockBuilder(Webhook::class) + ->setConstructorArgs([ + $this->createMock(Data::class), + $this->createMock(SerializerInterface::class), + $this->createMock(TimezoneInterface::class), + $this->createMock(ConfigHelper::class), + $this->createMock(ChargedCurrency::class), + $logger, + $webhookHandlerFactory, + $orderHelper, + $this->createMock(OrderRepository::class) + ]) + ->onlyMethods([ + 'updateNotification', + 'addNotificationDetailsHistoryComment', + 'updateAdyenAttributes', + 'getCurrentState', + 'getTransitionState', + 'handleNotificationError' + ]) + ->getMock(); + + $result = $webhookHandler->processNotification($notification); + + $this->assertFalse($result); + } + + public function testProcessNotificationWithGeneralException() + { + $notification = $this->createMock(Notification::class); + $notification->method('getMerchantReference')->willReturn('TestMerchant'); + $notification->method('getEventCode')->willReturn('AUTHORISATION : FALSE'); + $notification->method('getEntityId')->willReturn('1234'); + $notification->method('getPspreference')->willReturn('ABCD1234GHJK5678'); + $notification->method('getPaymentMethod')->willReturn('ADYEN_CC'); + + $payment = $this->createMock(Payment::class); + $order = $this->createMock(Order::class); + $order->method('getState')->willReturn(Order::STATE_NEW); + $order->method('getIncrementId')->willReturn(123); + $order->method('getId')->willReturn(123); + $order->method('getStatus')->willReturn('processing'); + $order->method('getPayment')->willReturn($payment); + + $orderHelper = $this->createMock(OrderHelper::class); + $orderHelper->method('getOrderByIncrementId')->willReturn($order); + + $payment->expects($this->once()) + ->method('setAdditionalInformation') + ->with('payment_method', $notification->getPaymentMethod()); + + $webhookHandlerInterfaceMock = $this->createMock(WebhookHandlerInterface::class); + $webhookHandlerInterfaceMock->method('handleWebhook')->willThrowException(new \Exception( + new \Magento\Framework\Phrase("Test generic exception" + ))); + + $webhookHandlerFactory = $this->createMock(WebhookHandlerFactory::class); + $webhookHandlerFactory->method('create') + ->willReturn($webhookHandlerInterfaceMock); + + $logger = $this->createMock(AdyenLogger::class); + $logger->method('getOrderContext')->with($order); + + $webhookHandler = $this->getMockBuilder(Webhook::class) + ->setConstructorArgs([ + $this->createMock(Data::class), + $this->createMock(SerializerInterface::class), + $this->createMock(TimezoneInterface::class), + $this->createMock(ConfigHelper::class), + $this->createMock(ChargedCurrency::class), + $logger, + $webhookHandlerFactory, + $orderHelper, + $this->createMock(OrderRepository::class) + ]) + ->onlyMethods([ + 'updateNotification', + 'addNotificationDetailsHistoryComment', + 'updateAdyenAttributes', + 'getCurrentState', + 'getTransitionState', + 'handleNotificationError' + ]) + ->getMock(); + + $result = $webhookHandler->processNotification($notification); + + $this->assertFalse($result); + } + + public function testAddNotificationDetailsHistoryCommentWithFullRefund() + { + $orderMock = $this->getMockBuilder(Order::class) + ->disableOriginalConstructor() + ->getMock(); + $notificationMock = $this->getMockBuilder(Notification::class) + ->disableOriginalConstructor() + ->getMock(); + + $orderAmountCurrencyObject = new class { + public function getAmount() { + return 100; + } + public function getCurrencyCode() { + return 'EUR'; + } + }; + + $chargedCurrencyMock = $this->createMock(ChargedCurrency::class); + $chargedCurrencyMock->method('getOrderAmountCurrency') + ->willReturn($orderAmountCurrencyObject); + + $adyenHelperMock = $this->createMock(Data::class); + $adyenHelperMock->method('formatAmount') + ->willReturn(100); + + $webhook = $this->createWebhook( + $adyenHelperMock, + null, + null, + null, + $chargedCurrencyMock, + null, + null, + null, + null + ); + + $notificationMock->method('getEventCode') + ->willReturn(Notification::REFUND); + $notificationMock->method('getAmountValue') + ->willReturn(100); + $notificationMock->method('isSuccessful') + ->willReturn(true); + + $orderMock->expects($this->once()) + ->method('setData') + ->with( + 'adyen_notification_event_code', + $this->stringContains('REFUND : TRUE') + ); + + $reflection = new \ReflectionClass(get_class($webhook)); + $method = $reflection->getMethod('addNotificationDetailsHistoryComment'); + $method->setAccessible(true); + + $result = $method->invokeArgs($webhook, [$orderMock, $notificationMock]); + + $this->assertInstanceOf(Order::class, $result); + } + + public function testAddNotificationDetailsHistoryCommentWithPendingEventCode() + { + $orderMock = $this->getMockBuilder(Order::class) + ->disableOriginalConstructor() + ->getMock(); + $notificationMock = $this->getMockBuilder(Notification::class) + ->disableOriginalConstructor() + ->getMock(); + $configHelperMock = $this->createMock(ConfigHelper::class); + $adyenHelperMock = $this->createMock(Data::class); + $chargedCurrencyMock = $this->createMock(ChargedCurrency::class); + + $webhook = $this->createWebhook( + $adyenHelperMock, + null, + null, + $configHelperMock, + $chargedCurrencyMock, + null, + null, + null, + null + ); + + $notificationMock->method('getEventCode') + ->willReturn(Notification::PENDING); + $notificationMock->method('getPspreference') + ->willReturn('some_psp_reference'); + $orderMock->method('getStoreId') + ->willReturn(1); + + $configHelperMock->method('getConfigData') + ->with('pending_status', 'adyen_abstract', 1) + ->willReturn('pending_status_value'); + + $reflection = new \ReflectionClass(get_class($webhook)); + $method = $reflection->getMethod('addNotificationDetailsHistoryComment'); + $method->setAccessible(true); + + $orderMock->expects($this->once()) + ->method('addStatusHistoryComment') + ->with( + $this->anything(), + 'pending_status_value' + ); + + $result = $method->invokeArgs($webhook, [$orderMock, $notificationMock]); + + $this->assertInstanceOf(Order::class, $result); + } + + public function testUpdateOrderPaymentWithAdyenAttributes() + { + $paymentMock = $this->getMockBuilder(Order\Payment::class) + ->disableOriginalConstructor() + ->getMock(); + $notificationMock = $this->getMockBuilder(Notification::class) + ->disableOriginalConstructor() + ->getMock(); + + $webhook = $this->createWebhook(null,null,null,null,null,null,null,null,null); + + $additionalData = [ + 'avsResult' => 'avs_result_value', + 'cvcResult' => 'cvc_result_value', + ]; + + $notificationMock->method('getPspreference')->willReturn('pspReference'); + $notificationMock->method('getReason')->willReturn('card summary reason'); + + $reflection = new \ReflectionClass(get_class($webhook)); + $method = $reflection->getMethod('updateOrderPaymentWithAdyenAttributes'); + $method->setAccessible(true); + + $paymentMock->expects($this->exactly(4)) + ->method('setAdditionalInformation') + ->withConsecutive( + ['adyen_avs_result', 'avs_result_value'], + ['adyen_cvc_result', 'cvc_result_value'], + ['pspReference', 'pspReference'], + ['adyen_ratepay_descriptor', $this->anything()] + ); + + $method->invokeArgs($webhook, [$paymentMock, $notificationMock, $additionalData]); + } + + protected function createWebhook( $mockAdyenHelper = null, $mockSerializer = null,