commerce_shipping-8.x-2.0-rc2/tests/src/Kernel/ShipmentManagerTest.php
tests/src/Kernel/ShipmentManagerTest.php
<?php namespace Drupal\Tests\commerce_shipping\Kernel; use Drupal\commerce_order\Entity\Order; use Drupal\commerce_order\Entity\OrderItem; use Drupal\commerce_price\Price; use Drupal\commerce_promotion\Entity\Coupon; use Drupal\commerce_promotion\Entity\Promotion; use Drupal\commerce_shipping\Entity\Shipment; use Drupal\commerce_shipping\Entity\ShippingMethod; use Drupal\commerce_shipping\ShipmentItem; use Drupal\language\Entity\ConfigurableLanguage; use Drupal\physical\Weight; /** * Tests the shipment manager. * * @coversDefaultClass \Drupal\commerce_shipping\ShipmentManager * @group commerce_shipping */ class ShipmentManagerTest extends ShippingKernelTestBase { /** * The shipment manager. * * @var \Drupal\commerce_shipping\ShipmentManagerInterface */ protected $shipmentManager; /** * The sample order. * * @var \Drupal\commerce_order\Entity\OrderInterface */ protected $order; /** * The sample shipment. * * @var \Drupal\commerce_shipping\Entity\ShipmentInterface */ protected $shipment; /** * The sample shipping methods. * * @var \Drupal\commerce_shipping\Entity\ShippingMethodInterface[] */ protected $shippingMethods = []; /** * {@inheritdoc} */ protected static $modules = [ 'commerce_promotion', 'language', 'content_translation', ]; /** * {@inheritdoc} */ protected function setUp(): void { parent::setUp(); $this->installEntitySchema('commerce_promotion'); $this->installEntitySchema('commerce_promotion_coupon'); $this->installSchema('commerce_promotion', ['commerce_promotion_usage']); ConfigurableLanguage::createFromLangcode('fr')->save(); $this->container->get('content_translation.manager')->setEnabled('commerce_shipping_method', 'commerce_shipping_method', TRUE); $this->shipmentManager = $this->container->get('commerce_shipping.shipment_manager'); $order_item = OrderItem::create([ 'type' => 'test', 'quantity' => 1, 'unit_price' => new Price('12.00', 'USD'), ]); $order_item->save(); /** @var \Drupal\commerce_order\Entity\Order $order */ $order = Order::create([ 'type' => 'default', 'order_number' => '6', 'store_id' => $this->store->id(), 'state' => 'completed', 'order_items' => [$order_item], ]); $order->save(); $this->order = $order; $shipping_method = ShippingMethod::create([ 'stores' => $this->store->id(), 'name' => 'Example', 'plugin' => [ 'target_plugin_id' => 'flat_rate', 'target_plugin_configuration' => [ 'rate_label' => 'Standard shipping', 'rate_amount' => [ 'number' => '5', 'currency_code' => 'USD', ], ], ], 'status' => TRUE, 'weight' => 1, ]); $shipping_method->save(); $this->shippingMethods[] = $shipping_method; $another_shipping_method = ShippingMethod::create([ 'stores' => $this->store->id(), 'name' => 'Another shipping method', 'plugin' => [ 'target_plugin_id' => 'flat_rate', 'target_plugin_configuration' => [ 'rate_label' => 'Overnight shipping', 'rate_amount' => [ 'number' => '20', 'currency_code' => 'USD', ], ], ], 'status' => TRUE, 'weight' => 0, ]); $another_shipping_method->addTranslation('fr', [ 'name' => 'Another shipping method (FR)', 'plugin' => [ 'target_plugin_id' => 'flat_rate', 'target_plugin_configuration' => [ 'rate_label' => 'Le overnight shipping', 'rate_amount' => [ 'number' => '22', 'currency_code' => 'USD', ], ], ], ]); $another_shipping_method->save(); $this->shippingMethods[] = $another_shipping_method; $bad_shipping_method = ShippingMethod::create([ 'stores' => $this->store->id(), 'name' => $this->randomString(), 'status' => TRUE, 'plugin' => [ 'target_plugin_id' => 'exception_thrower', 'target_plugin_configuration' => [], ], ]); $bad_shipping_method->save(); $shipment = Shipment::create([ 'type' => 'default', 'order_id' => $order->id(), 'title' => 'Shipment', 'tracking_code' => 'ABC123', 'items' => [ new ShipmentItem([ 'order_item_id' => 1, 'title' => 'T-shirt (red, large)', 'quantity' => 2, 'weight' => new Weight('40', 'kg'), 'declared_value' => new Price('30', 'USD'), ]), ], 'amount' => new Price('5', 'USD'), 'state' => 'draft', ]); $shipment->save(); $this->shipment = $this->reloadEntity($shipment); } /** * Tests applying rates. * * @covers ::applyRate */ public function testApplyRate() { $rates = $this->shipmentManager->calculateRates($this->shipment); $this->assertCount(2, $rates); /** @var \Drupal\commerce_shipping\ShippingRate $second_rate */ $second_rate = end($rates); $this->shipmentManager->applyRate($this->shipment, $second_rate); $this->assertEquals($second_rate->getShippingMethodId(), $this->shipment->getShippingMethodId()); $this->assertEquals($second_rate->getService()->getId(), $this->shipment->getShippingService()); $this->assertEquals($second_rate->getOriginalAmount(), $this->shipment->getOriginalAmount()); $this->assertEquals($second_rate->getAmount(), $this->shipment->getAmount()); } /** * Tests calculating rates. * * @covers ::calculateRates */ public function testCalculateRates() { // Use the FR translation where available (e.g. $another_shipping_method). $this->container->get('language.default')->set(ConfigurableLanguage::createFromLangcode('fr')); $rates = $this->shipmentManager->calculateRates($this->shipment); $this->assertCount(2, $rates); $first_rate = reset($rates); $second_rate = end($rates); $this->assertArrayHasKey($first_rate->getId(), $rates); $this->assertEquals('2', $first_rate->getShippingMethodId()); $this->assertEquals('default', $first_rate->getService()->getId()); $this->assertEquals('Le overnight shipping', $first_rate->getService()->getLabel()); $this->assertEquals(new Price('22.00', 'USD'), $first_rate->getOriginalAmount()); $this->assertEquals(new Price('22.00', 'USD'), $first_rate->getAmount()); $this->assertArrayHasKey($second_rate->getId(), $rates); $this->assertEquals('1', $second_rate->getShippingMethodId()); $this->assertEquals('default', $second_rate->getService()->getId()); $this->assertEquals('Standard shipping', $second_rate->getService()->getLabel()); $this->assertEquals(new Price('5.00', 'USD'), $second_rate->getOriginalAmount()); $this->assertEquals(new Price('5.00', 'USD'), $second_rate->getAmount()); // Test rate altering. $this->shipment->setData('alter_rate', TRUE); $rates = $this->shipmentManager->calculateRates($this->shipment); $this->assertCount(2, $rates); $first_rate = reset($rates); $second_rate = end($rates); $this->assertArrayHasKey($first_rate->getId(), $rates); $this->assertEquals('2', $first_rate->getShippingMethodId()); $this->assertEquals('default', $first_rate->getService()->getId()); $this->assertEquals('Le overnight shipping', $first_rate->getService()->getLabel()); $this->assertEquals(new Price('22.00', 'USD'), $first_rate->getOriginalAmount()); $this->assertEquals(new Price('44.00', 'USD'), $first_rate->getAmount()); $this->assertArrayHasKey($second_rate->getId(), $rates); $this->assertEquals('1', $second_rate->getShippingMethodId()); $this->assertEquals('default', $second_rate->getService()->getId()); $this->assertEquals('Standard shipping', $second_rate->getService()->getLabel()); $this->assertEquals(new Price('5.00', 'USD'), $second_rate->getOriginalAmount()); $this->assertEquals(new Price('10.00', 'USD'), $second_rate->getAmount()); } /** * Tests the applying of display-inclusive promotions. * * @covers ::calculateRates */ public function testPromotions() { $first_promotion = Promotion::create([ 'name' => 'Promotion 1', 'order_types' => [$this->order->bundle()], 'stores' => [$this->store->id()], 'offer' => [ 'target_plugin_id' => 'shipment_fixed_amount_off', 'target_plugin_configuration' => [ 'display_inclusive' => TRUE, 'filter' => 'include', 'shipping_methods' => [ ['shipping_method' => $this->shippingMethods[0]->uuid()], ], 'amount' => [ 'number' => '1.00', 'currency_code' => 'USD', ], ], ], 'status' => TRUE, ]); $first_promotion->save(); $second_promotion = Promotion::create([ 'name' => 'Promotion 1', 'order_types' => [$this->order->bundle()], 'stores' => [$this->store->id()], 'offer' => [ 'target_plugin_id' => 'shipment_percentage_off', 'target_plugin_configuration' => [ 'display_inclusive' => TRUE, 'filter' => 'include', 'shipping_methods' => [ ['shipping_method' => $this->shippingMethods[1]->uuid()], ], 'percentage' => '0.5', ], ], 'status' => TRUE, ]); $second_promotion->save(); $coupon = Coupon::create([ 'promotion_id' => $second_promotion->id(), 'code' => '50% off shipping', 'status' => TRUE, ]); $coupon->save(); $this->order->set('coupons', [$coupon]); $this->order->setRefreshState(Order::REFRESH_SKIP); $this->order->save(); $rates = $this->shipmentManager->calculateRates($this->shipment); $this->assertCount(2, $rates); $first_rate = reset($rates); $second_rate = end($rates); // The first rate should be reduced by the 50% off coupon. $this->assertArrayHasKey($first_rate->getId(), $rates); $this->assertEquals('2', $first_rate->getShippingMethodId()); $this->assertEquals('default', $first_rate->getService()->getId()); $this->assertEquals('Overnight shipping', $first_rate->getService()->getLabel()); $this->assertEquals(new Price('20.00', 'USD'), $first_rate->getOriginalAmount()); $this->assertEquals(new Price('10.00', 'USD'), $first_rate->getAmount()); // The second rate should be reduced by the $1 off promotion. $this->assertArrayHasKey($second_rate->getId(), $rates); $this->assertEquals('1', $second_rate->getShippingMethodId()); $this->assertEquals('default', $second_rate->getService()->getId()); $this->assertEquals('Standard shipping', $second_rate->getService()->getLabel()); $this->assertEquals(new Price('5.00', 'USD'), $second_rate->getOriginalAmount()); $this->assertEquals(new Price('4.00', 'USD'), $second_rate->getAmount()); // Test applying a combination offer. $second_promotion->set('offer', [ 'target_plugin_id' => 'combination_offer', 'target_plugin_configuration' => [ 'offers' => [ [ 'target_plugin_id' => 'shipment_percentage_off', 'target_plugin_configuration' => [ 'display_inclusive' => TRUE, 'filter' => 'include', 'shipping_methods' => [ ['shipping_method' => $this->shippingMethods[1]->uuid()], ], 'percentage' => '0.2', ], ], ], ], ]); $second_promotion->save(); $rates = $this->shipmentManager->calculateRates($this->shipment); $this->assertCount(2, $rates); $first_rate = reset($rates); // The first rate should be reduced by the 20% off coupon. $this->assertArrayHasKey($first_rate->getId(), $rates); $this->assertEquals('2', $first_rate->getShippingMethodId()); $this->assertEquals('default', $first_rate->getService()->getId()); $this->assertEquals('Overnight shipping', $first_rate->getService()->getLabel()); $this->assertEquals(new Price('20.00', 'USD'), $first_rate->getOriginalAmount()); $this->assertEquals(new Price('16.00', 'USD'), $first_rate->getAmount()); } /** * Tests selecting the default rate. * * @covers ::selectDefaultRate */ public function testSelectDefaultRate() { $rates = $this->shipmentManager->calculateRates($this->shipment); // The selected rate should be the first one (as a fallback). $default_rate = $this->shipmentManager->selectDefaultRate($this->shipment, $rates); $this->assertEquals('2--default', $default_rate->getId()); // The selected rate should match the specified shipping method/service. $this->shipment->setShippingMethodId('1'); $this->shipment->setShippingService('default'); $default_rate = $this->shipmentManager->selectDefaultRate($this->shipment, $rates); $this->assertEquals('1--default', $default_rate->getId()); } }