469 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			PHP
		
	
	
		
			Executable File
		
	
	
			
		
		
	
	
			469 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			PHP
		
	
	
		
			Executable File
		
	
	
<?php
 | 
						|
/**
 | 
						|
 * Copyright © Magento, Inc. All rights reserved.
 | 
						|
 * See COPYING.txt for license details.
 | 
						|
 */
 | 
						|
declare(strict_types=1);
 | 
						|
 | 
						|
namespace Magento\Ups\Model;
 | 
						|
 | 
						|
use Magento\Framework\App\Config\ReinitableConfigInterface;
 | 
						|
use Magento\Framework\DataObject;
 | 
						|
use Magento\Framework\HTTP\AsyncClient\HttpException;
 | 
						|
use Magento\Framework\HTTP\AsyncClient\HttpResponseDeferredInterface;
 | 
						|
use Magento\Framework\HTTP\AsyncClient\Response;
 | 
						|
use Magento\Framework\HTTP\AsyncClientInterface;
 | 
						|
use Magento\Quote\Model\Quote\Address\RateRequest;
 | 
						|
use Magento\Quote\Model\Quote\Address\RateRequestFactory;
 | 
						|
use Magento\Quote\Model\Quote\Address\RateResult\Error;
 | 
						|
use Magento\Shipping\Model\Shipment\Request;
 | 
						|
use Magento\TestFramework\Helper\Bootstrap;
 | 
						|
use Magento\TestFramework\HTTP\AsyncClientInterfaceMock;
 | 
						|
use PHPUnit\Framework\MockObject\MockObject;
 | 
						|
use PHPUnit\Framework\TestCase;
 | 
						|
use Psr\Log\LoggerInterface;
 | 
						|
 | 
						|
/**
 | 
						|
 * Integration tests for Carrier model class
 | 
						|
 *
 | 
						|
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 | 
						|
 */
 | 
						|
class CarrierTest extends TestCase
 | 
						|
{
 | 
						|
    /**
 | 
						|
     * @var Carrier
 | 
						|
     */
 | 
						|
    private $carrier;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var AsyncClientInterfaceMock
 | 
						|
     */
 | 
						|
    private $httpClient;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var ReinitableConfigInterface
 | 
						|
     */
 | 
						|
    private $config;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var LoggerInterface|MockObject
 | 
						|
     */
 | 
						|
    private $loggerMock;
 | 
						|
 | 
						|
    /**
 | 
						|
     * @var string[]
 | 
						|
     */
 | 
						|
    private $logs = [];
 | 
						|
 | 
						|
    /**
 | 
						|
     * @inheritDoc
 | 
						|
     */
 | 
						|
    protected function setUp(): void
 | 
						|
    {
 | 
						|
        $this->httpClient = Bootstrap::getObjectManager()->get(AsyncClientInterface::class);
 | 
						|
        $this->config = Bootstrap::getObjectManager()->get(ReinitableConfigInterface::class);
 | 
						|
        $this->logs = [];
 | 
						|
        $this->loggerMock = $this->getMockForAbstractClass(LoggerInterface::class);
 | 
						|
        $this->loggerMock->method('debug')
 | 
						|
            ->willReturnCallback(
 | 
						|
                function (string $message) {
 | 
						|
                    $this->logs[] = $message;
 | 
						|
                }
 | 
						|
            );
 | 
						|
        $this->carrier = Bootstrap::getObjectManager()->create(Carrier::class, ['logger' => $this->loggerMock]);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public function testGetShipAcceptUrl()
 | 
						|
    {
 | 
						|
        $this->assertEquals('https://wwwcie.ups.com/ups.app/xml/ShipAccept', $this->carrier->getShipAcceptUrl());
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Test ship accept url for live site
 | 
						|
     *
 | 
						|
     * @magentoConfigFixture current_store carriers/ups/is_account_live 1
 | 
						|
     */
 | 
						|
    public function testGetShipAcceptUrlLive()
 | 
						|
    {
 | 
						|
        $this->assertEquals('https://onlinetools.ups.com/ups.app/xml/ShipAccept', $this->carrier->getShipAcceptUrl());
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @return void
 | 
						|
     */
 | 
						|
    public function testGetShipConfirmUrl()
 | 
						|
    {
 | 
						|
        $this->assertEquals('https://wwwcie.ups.com/ups.app/xml/ShipConfirm', $this->carrier->getShipConfirmUrl());
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Test ship accept url for live site
 | 
						|
     *
 | 
						|
     * @magentoConfigFixture current_store carriers/ups/is_account_live 1
 | 
						|
     */
 | 
						|
    public function testGetShipConfirmUrlLive()
 | 
						|
    {
 | 
						|
        $this->assertEquals(
 | 
						|
            'https://onlinetools.ups.com/ups.app/xml/ShipConfirm',
 | 
						|
            $this->carrier->getShipConfirmUrl()
 | 
						|
        );
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Collect rates for UPS Ground method.
 | 
						|
     *
 | 
						|
     * @magentoConfigFixture current_store carriers/ups/active 1
 | 
						|
     * @magentoConfigFixture current_store carriers/ups/type UPS_XML
 | 
						|
     * @magentoConfigFixture current_store carriers/ups/allowed_methods 03
 | 
						|
     * @magentoConfigFixture current_store carriers/ups/free_method 03
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/shipper_number 12345
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/origin_shipment Shipments Originating in the United States
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/username user
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/password pass
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/access_license_number acn
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/debug 1
 | 
						|
     * @magentoConfigFixture default_store currency/options/allow USD,EUR
 | 
						|
     * @magentoConfigFixture default_store currency/options/base USD
 | 
						|
     */
 | 
						|
    public function testCollectFreeRates()
 | 
						|
    {
 | 
						|
        $request = Bootstrap::getObjectManager()->create(
 | 
						|
            RateRequest::class,
 | 
						|
            [
 | 
						|
                'data' => [
 | 
						|
                    'dest_country' => 'US',
 | 
						|
                    'dest_postal' => '90001',
 | 
						|
                    'package_weight' => '1',
 | 
						|
                    'package_qty' => '1',
 | 
						|
                    'free_method_weight' => '5',
 | 
						|
                    'product' => '11',
 | 
						|
                    'action' => 'Rate',
 | 
						|
                    'unit_measure' => 'KGS',
 | 
						|
                    'free_shipping' => '1',
 | 
						|
                    'base_currency' => new DataObject(['code' => 'USD'])
 | 
						|
                ]
 | 
						|
            ]
 | 
						|
        );
 | 
						|
        //phpcs:disable Magento2.Functions.DiscouragedFunction
 | 
						|
        $this->httpClient->nextResponses(
 | 
						|
            [
 | 
						|
                new Response(
 | 
						|
                    200,
 | 
						|
                    [],
 | 
						|
                    file_get_contents(__DIR__ . "/../_files/ups_rates_response_option9.xml")
 | 
						|
                )
 | 
						|
            ]
 | 
						|
        );
 | 
						|
 | 
						|
        $rates = $this->carrier->collectRates($request)->getAllRates();
 | 
						|
        $this->assertEquals('19.19', $rates[0]->getPrice());
 | 
						|
        $this->assertEquals('03', $rates[0]->getMethod());
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Test processing rates response.
 | 
						|
     *
 | 
						|
     * @param int $negotiable
 | 
						|
     * @param int $tax
 | 
						|
     * @param int $responseId
 | 
						|
     * @param string $method
 | 
						|
     * @param float $price
 | 
						|
     * @return void
 | 
						|
     * @dataProvider collectRatesDataProvider
 | 
						|
     * @magentoConfigFixture default_store shipping/origin/country_id GB
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/type UPS_XML
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/active 1
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/shipper_number 12345
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/origin_shipment Shipments Originating in the European Union
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/username user
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/password pass
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/access_license_number acn
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/debug 1
 | 
						|
     * @magentoConfigFixture default_store currency/options/allow GBP,USD,EUR
 | 
						|
     * @magentoConfigFixture default_store currency/options/base GBP
 | 
						|
     */
 | 
						|
    public function testCollectRates(int $negotiable, int $tax, int $responseId, string $method, float $price): void
 | 
						|
    {
 | 
						|
        $request = Bootstrap::getObjectManager()->create(
 | 
						|
            RateRequest::class,
 | 
						|
            [
 | 
						|
                'data' => [
 | 
						|
                    'dest_country' => 'GB',
 | 
						|
                    'dest_postal' => '01104',
 | 
						|
                    'product' => '11',
 | 
						|
                    'action' => 'Rate',
 | 
						|
                    'unit_measure' => 'KGS',
 | 
						|
                    'base_currency' => new DataObject(['code' => 'GBP'])
 | 
						|
                ]
 | 
						|
            ]
 | 
						|
        );
 | 
						|
        //phpcs:disable Magento2.Functions.DiscouragedFunction
 | 
						|
        $this->httpClient->nextResponses(
 | 
						|
            [
 | 
						|
                new Response(
 | 
						|
                    200,
 | 
						|
                    [],
 | 
						|
                    file_get_contents(__DIR__ . "/../_files/ups_rates_response_option$responseId.xml")
 | 
						|
                )
 | 
						|
            ]
 | 
						|
        );
 | 
						|
        //phpcs:enable Magento2.Functions.DiscouragedFunction
 | 
						|
        $this->config->setValue('carriers/ups/negotiated_active', $negotiable, 'store');
 | 
						|
        $this->config->setValue('carriers/ups/include_taxes', $tax, 'store');
 | 
						|
        $this->config->setValue('carriers/ups/allowed_methods', $method, 'store');
 | 
						|
 | 
						|
        $rates = $this->carrier->collectRates($request)->getAllRates();
 | 
						|
        $this->assertEquals($price, $rates[0]->getPrice());
 | 
						|
        $this->assertEquals($method, $rates[0]->getMethod());
 | 
						|
 | 
						|
        $requestFound = false;
 | 
						|
        foreach ($this->logs as $log) {
 | 
						|
            if (mb_stripos($log, 'RatingServiceSelectionRequest') &&
 | 
						|
                mb_stripos($log, 'RatingServiceSelectionResponse')
 | 
						|
            ) {
 | 
						|
                $requestFound = true;
 | 
						|
                break;
 | 
						|
            }
 | 
						|
        }
 | 
						|
        $this->assertTrue($requestFound);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Test collect rates function without any allowed methods set.
 | 
						|
     *
 | 
						|
     * @return void
 | 
						|
     * @magentoConfigFixture default_store shipping/origin/country_id GB
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/type UPS_XML
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/active 1
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/shipper_number 12345
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/origin_shipment Shipments Originating in the European Union
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/username user
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/password pass
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/access_license_number acn
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/debug 1
 | 
						|
     * @magentoConfigFixture default_store currency/options/allow GBP,USD,EUR
 | 
						|
     * @magentoConfigFixture default_store currency/options/base GBP
 | 
						|
     */
 | 
						|
    public function testCollectRatesWithoutAnyAllowedMethods(): void
 | 
						|
    {
 | 
						|
        $request = Bootstrap::getObjectManager()->create(
 | 
						|
            RateRequest::class,
 | 
						|
            [
 | 
						|
                'data' => [
 | 
						|
                    'dest_country' => 'GB',
 | 
						|
                    'dest_postal' => '01104',
 | 
						|
                    'product' => '11',
 | 
						|
                    'action' => 'Rate',
 | 
						|
                    'unit_measure' => 'KGS',
 | 
						|
                    'base_currency' => new DataObject(['code' => 'GBP'])
 | 
						|
                ]
 | 
						|
            ]
 | 
						|
        );
 | 
						|
        $this->config->setValue('carriers/ups/allowed_methods', '', 'store');
 | 
						|
        $rates = $this->carrier->collectRates($request)->getAllRates();
 | 
						|
        $this->assertInstanceOf(Error::class, current($rates));
 | 
						|
        $this->assertEquals(current($rates)['carrier_title'], $this->carrier->getConfigData('title'));
 | 
						|
        $this->assertEquals(current($rates)['error_message'], $this->carrier->getConfigData('specificerrmsg'));
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Get list of rates variations
 | 
						|
     *
 | 
						|
     * @return array
 | 
						|
     */
 | 
						|
    public function collectRatesDataProvider()
 | 
						|
    {
 | 
						|
        return [
 | 
						|
            [0, 0, 1, '11', 6.45 ],
 | 
						|
            [0, 0, 2, '65', 29.59 ],
 | 
						|
            [0, 1, 3, '11', 7.74 ],
 | 
						|
            [0, 1, 4, '65', 29.59 ],
 | 
						|
            [1, 0, 5, '11', 9.35 ],
 | 
						|
            [1, 0, 6, '65', 41.61 ],
 | 
						|
            [1, 1, 7, '11', 11.22 ],
 | 
						|
            [1, 1, 8, '65', 41.61 ],
 | 
						|
        ];
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Test shipping a package.
 | 
						|
     *
 | 
						|
     *
 | 
						|
     * @magentoConfigFixture default_store shipping/origin/country_id GB
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/type UPS_XML
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/active 1
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/shipper_number 12345
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/origin_shipment Shipments Originating in the European Union
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/username user
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/password pass
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/access_license_number acn
 | 
						|
     * @magentoConfigFixture default_store currency/options/allow GBP,USD,EUR
 | 
						|
     * @magentoConfigFixture default_store currency/options/base GBP
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/min_package_weight 2
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/debug 1
 | 
						|
     */
 | 
						|
    public function testRequestToShipment(): void
 | 
						|
    {
 | 
						|
        //phpcs:disable Magento2.Functions.DiscouragedFunction
 | 
						|
        $expectedShipmentRequest = file_get_contents(__DIR__ . '/../_files/ShipmentConfirmRequest.xml');
 | 
						|
        $shipmentResponse = file_get_contents(__DIR__ . '/../_files/ShipmentConfirmResponse.xml');
 | 
						|
        $acceptResponse = file_get_contents(__DIR__ . '/../_files/ShipmentAcceptResponse.xml');
 | 
						|
        //phpcs:enable Magento2.Functions.DiscouragedFunction
 | 
						|
        $this->httpClient->nextResponses(
 | 
						|
            [
 | 
						|
                new Response(200, [], $shipmentResponse),
 | 
						|
                new Response(200, [], $acceptResponse)
 | 
						|
            ]
 | 
						|
        );
 | 
						|
        $this->httpClient->clearRequests();
 | 
						|
 | 
						|
        $request = new Request(
 | 
						|
            [
 | 
						|
                'packages' => [
 | 
						|
                    'package' => [
 | 
						|
                        'params' => [
 | 
						|
                            'width' => '3',
 | 
						|
                            'length' => '3',
 | 
						|
                            'height' => '3',
 | 
						|
                            'dimension_units' => 'INCH',
 | 
						|
                            'weight_units' => 'POUND',
 | 
						|
                            'weight' => '0.454000000001',
 | 
						|
                            'customs_value' => '10.00',
 | 
						|
                            'container' => 'Small Express Box',
 | 
						|
                        ],
 | 
						|
                        'items' => [
 | 
						|
                            'item1' => [
 | 
						|
                                'name' => 'item_name',
 | 
						|
                            ],
 | 
						|
                        ],
 | 
						|
                    ],
 | 
						|
                    'package2' => [
 | 
						|
                        'params' => [
 | 
						|
                            'width' => '4',
 | 
						|
                            'length' => '4',
 | 
						|
                            'height' => '4',
 | 
						|
                            'dimension_units' => 'INCH',
 | 
						|
                            'weight_units' => 'POUND',
 | 
						|
                            'weight' => '0.55',
 | 
						|
                            'customs_value' => '20.00',
 | 
						|
                            'container' => 'Large Express Box',
 | 
						|
                            'delivery_confirmation' => 0,
 | 
						|
                        ],
 | 
						|
                        'items' => [
 | 
						|
                            'item2' => [
 | 
						|
                                'name' => 'item2_name',
 | 
						|
                            ],
 | 
						|
                        ],
 | 
						|
                    ],
 | 
						|
                ]
 | 
						|
            ]
 | 
						|
        );
 | 
						|
        $request->setRecipientAddressCountryCode('UK');
 | 
						|
 | 
						|
        $result = $this->carrier->requestToShipment($request);
 | 
						|
 | 
						|
        $requests = $this->httpClient->getRequests();
 | 
						|
        $this->assertNotEmpty($requests);
 | 
						|
        $shipmentRequest = $this->extractShipmentRequest($requests[0]->getBody());
 | 
						|
        $this->assertEquals(
 | 
						|
            $this->formatXml($expectedShipmentRequest),
 | 
						|
            $this->formatXml($shipmentRequest)
 | 
						|
        );
 | 
						|
 | 
						|
        $this->assertEmpty($result->getErrors());
 | 
						|
        $this->assertNotEmpty($result->getInfo());
 | 
						|
        $this->assertEquals(
 | 
						|
            '1Z207W886698856557',
 | 
						|
            $result->getInfo()[0]['tracking_number'],
 | 
						|
            'Tracking Number must match.'
 | 
						|
        );
 | 
						|
        $this->assertEquals(
 | 
						|
            '2V467W886398839541',
 | 
						|
            $result->getInfo()[1]['tracking_number'],
 | 
						|
            'Tracking Number must match.'
 | 
						|
        );
 | 
						|
        $this->httpClient->clearRequests();
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Test get carriers rates if has HttpException.
 | 
						|
     *
 | 
						|
     * @magentoConfigFixture default_store shipping/origin/country_id GB
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/type UPS_XML
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/active 1
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/shipper_number 12345
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/origin_shipment Shipments Originating in the European Union
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/username user
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/password pass
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/access_license_number acn
 | 
						|
     * @magentoConfigFixture default_store carriers/ups/debug 1
 | 
						|
     * @magentoConfigFixture default_store currency/options/allow GBP,USD,EUR
 | 
						|
     * @magentoConfigFixture default_store currency/options/base GBP
 | 
						|
     */
 | 
						|
    public function testGetRatesWithHttpException(): void
 | 
						|
    {
 | 
						|
        $deferredResponse = $this->getMockBuilder(HttpResponseDeferredInterface::class)
 | 
						|
            ->onlyMethods(['get'])
 | 
						|
            ->getMockForAbstractClass();
 | 
						|
        $exception = new HttpException('Exception message');
 | 
						|
        $deferredResponse->method('get')->willThrowException($exception);
 | 
						|
        $this->httpClient->setDeferredResponseMock($deferredResponse);
 | 
						|
        $request = Bootstrap::getObjectManager()->create(
 | 
						|
            RateRequest::class,
 | 
						|
            [
 | 
						|
                'data' => [
 | 
						|
                    'dest_country' => 'GB',
 | 
						|
                    'dest_postal' => '01105',
 | 
						|
                    'product' => '11',
 | 
						|
                    'action' => 'Rate',
 | 
						|
                    'unit_measure' => 'KGS',
 | 
						|
                    'base_currency' => new DataObject(['code' => 'GBP'])
 | 
						|
                ]
 | 
						|
            ]
 | 
						|
        );
 | 
						|
        $resultRate = $this->carrier->collectRates($request)->getAllRates()[0];
 | 
						|
        $error = Bootstrap::getObjectManager()->get(Error::class);
 | 
						|
        $error->setCarrier('ups');
 | 
						|
        $error->setCarrierTitle($this->carrier->getConfigData('title'));
 | 
						|
        $error->setErrorMessage($this->carrier->getConfigData('specificerrmsg'));
 | 
						|
 | 
						|
        $this->assertEquals($error, $resultRate);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Extracts shipment request.
 | 
						|
     *
 | 
						|
     * @param string $requestBody
 | 
						|
     * @return string
 | 
						|
     */
 | 
						|
    private function extractShipmentRequest(string $requestBody): string
 | 
						|
    {
 | 
						|
        $resultXml = '';
 | 
						|
        $pattern = '%(<\?xml version="1.0"\?>\n<ShipmentConfirmRequest)(.*)$%im';
 | 
						|
        if (preg_match($pattern, $requestBody, $result)) {
 | 
						|
            $resultXml = array_shift($result);
 | 
						|
        }
 | 
						|
 | 
						|
        return $resultXml;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Format XML string.
 | 
						|
     *
 | 
						|
     * @param string $xmlString
 | 
						|
     * @return string
 | 
						|
     */
 | 
						|
    private function formatXml(string $xmlString): string
 | 
						|
    {
 | 
						|
        $xmlDocument = new \DOMDocument('1.0');
 | 
						|
        $xmlDocument->preserveWhiteSpace = false;
 | 
						|
        $xmlDocument->formatOutput = true;
 | 
						|
        $xmlDocument->loadXML($xmlString);
 | 
						|
 | 
						|
        return $xmlDocument->saveXML();
 | 
						|
    }
 | 
						|
}
 |