text: from decimal import Decimal as D
  
  from django.test import TestCase
  from django.contrib.auth.models import User
  
  from oscar.apps.shipping.methods import Free, FixedPrice
  from oscar.apps.shipping.models import OrderAndItemCharges, WeightBased
  from oscar.apps.shipping.repository import Repository
  from oscar.apps.shipping import Scales
  from oscar.apps.basket.models import Basket
  from oscar_testsupport.factories import create_product
  from oscar_testsupport.decorators import dataProvider
  
  
  class FreeTest(TestCase):
  
      def setUp(self):
          self.method = Free()
  
      def test_shipping_is_free_for_empty_basket(self):
          basket = Basket()
          self.method.set_basket(basket)
          self.assertEquals(D('0.00'), self.method.basket_charge_incl_tax())
          self.assertEquals(D('0.00'), self.method.basket_charge_excl_tax())
  
      def test_shipping_is_free_for_nonempty_basket(self):
          basket = Basket()
          basket.add_product(create_product())
          self.method.set_basket(basket)
          self.assertEquals(D('0.00'), self.method.basket_charge_incl_tax())
          self.assertEquals(D('0.00'), self.method.basket_charge_excl_tax())
  
  
  class FixedPriceTest(TestCase):
  
      def test_fixed_price_shipping_charges_for_empty_basket(self):
          method = FixedPrice(D('10.00'), D('10.00'))
          basket = Basket()
          method.set_basket(basket)
          self.assertEquals(D('10.00'), method.basket_charge_incl_tax())
          self.assertEquals(D('10.00'), method.basket_charge_excl_tax())
  
      def test_fixed_price_shipping_assumes_no_tax(self):
          method = FixedPrice(D('10.00'))
          basket = Basket()
          method.set_basket(basket)
          self.assertEquals(D('10.00'), method.basket_charge_excl_tax())
  
      shipping_values = lambda: [('1.00',),
                                 ('5.00',),
                                 ('10.00',),
                                 ('12.00',)]
  
      @dataProvider(shipping_values)
      def test_different_values(self, value):
          method = FixedPrice(D(value))
          basket = Basket()
          method.set_basket(basket)
          self.assertEquals(D(value), method.basket_charge_excl_tax())
  
  
  class OrderAndItemChargesTests(TestCase):
  
      def setUp(self):
          self.method = OrderAndItemCharges(price_per_order=D('5.00'), price_per_item=D('1.00'))
          self.basket = Basket.objects.create()
          self.method.set_basket(self.basket)
  
      def test_order_level_charge_for_empty_basket(self):
          self.assertEquals(D('5.00'), self.method.basket_charge_incl_tax())
  
      def test_single_item_basket(self):
          p = create_product()
          self.basket.add_product(p)
          self.assertEquals(D('5.00') + D('1.00'), self.method.basket_charge_incl_tax())
  
      def test_multi_item_basket(self):
          p = create_product()
          self.basket.add_product(p, 7)
          self.assertEquals(D('5.00') + 7*D('1.00'), self.method.basket_charge_incl_tax())
  
  
  class ZeroFreeThresholdTest(TestCase):
  
      def setUp(self):
          self.method = OrderAndItemCharges(price_per_order=D('10.00'), free_shipping_threshold=D('0.00'))
          self.basket = Basket.objects.create()
          self.method.set_basket(self.basket)
  
      def test_free_shipping_with_empty_basket(self):
          self.assertEquals(D('0.00'), self.method.basket_charge_incl_tax())
  
      def test_free_shipping_with_nonempty_basket(self):
          p = create_product(D('5.00'))
          self.basket.add_product(p)
          self.assertEquals(D('0.00'), self.method.basket_charge_incl_tax())
  
  
  class NonZeroFreeThresholdTest(TestCase):
  
      def setUp(self):
          self.method = OrderAndItemCharges(price_per_order=D('10.00'), free_shipping_threshold=D('20.00'))
          self.basket = Basket.objects.create()
          self.method.set_basket(self.basket)
  
      def test_basket_below_threshold(self):
          p = create_product(D('5.00'))
          self.basket.add_product(p)
          self.assertEquals(D('10.00'), self.method.basket_charge_incl_tax())
  
      def test_basket_on_threshold(self):
          p = create_product(D('5.00'))
          self.basket.add_product(p, 4)
          self.assertEquals(D('0.00'), self.method.basket_charge_incl_tax())
  
      def test_basket_above_threshold(self):
          p = create_product(D('5.00'))
          self.basket.add_product(p, 8)
          self.assertEquals(D('0.00'), self.method.basket_charge_incl_tax())
  
  
  class ScalesTests(TestCase):
  
      def test_simple_weight_calculation(self):
          scales = Scales(attribute_code='weight')
          p = create_product(attributes={'weight': 1})
          self.assertEqual(1, scales.weigh_product(p))
  
      def test_default_weight_is_used_when_attribute_is_missing(self):
          scales = Scales(attribute_code='weight', default_weight=0.5)
          p = create_product()
          self.assertEqual(0.5, scales.weigh_product(p))
  
      def test_exception_is_raised_when_attribute_is_missing(self):
          scales = Scales(attribute_code='weight')
          p = create_product()
          with self.assertRaises(ValueError):
              scales.weigh_product(p)
  
      def test_weight_calculation_of_empty_basket(self):
          basket = Basket()
  
          scales = Scales(attribute_code='weight')
          self.assertEquals(0, scales.weigh_basket(basket))
  
      def test_weight_calculation_of_basket(self):
          basket = Basket()
          basket.add_product(create_product(attributes={'weight': 1}))
          basket.add_product(create_product(attributes={'weight': 2}))
  
          scales = Scales(attribute_code='weight')
          self.assertEquals(1+2, scales.weigh_basket(basket))
  
      def test_weight_calculation_of_basket_with_line_quantity(self):
          basket = Basket()
          basket.add_product(create_product(attributes={'weight': 1}), quantity=3)
          basket.add_product(create_product(attributes={'weight': 2}), quantity=4)
  
          scales = Scales(attribute_code='weight')
          self.assertEquals(1*3+2*4, scales.weigh_basket(basket))
  
  
  class WeightBasedMethodTests(TestCase):
  
      def setUp(self):
          self.standard = WeightBased.objects.create(name='Standard')
          self.express = WeightBased.objects.create(name='Express')
  
      def tearDown(self):
          self.standard.delete()
          self.express.delete()
  
      def test_get_band_for_lower_weight(self):
          band = self.standard.bands.create(upper_limit=1, charge=D('4.00'))
          fetched_band = self.standard.get_band_for_weight(0.5)
          self.assertEqual(band.id, fetched_band.id)
  
      def test_get_band_for_higher_weight(self):
          band = self.standard.bands.create(upper_limit=1, charge=D('4.00'))
          fetched_band = self.standard.get_band_for_weight(1.5)
          self.assertIsNone(fetched_band)
  
      def test_get_band_for_matching_weight(self):
          band = self.standard.bands.create(upper_limit=1, charge=D('4.00'))
          fetched_band = self.standard.get_band_for_weight(1)
          self.assertEqual(band.id, fetched_band.id)
  
      def test_weight_to_is_upper_bound(self):
          band = self.standard.bands.create(upper_limit=1, charge=D('4.00'))
          self.assertEqual(1, band.weight_to)
  
      def test_weight_from_for_single_band(self):
          band = self.standard.bands.create(upper_limit=1, charge=D('4.00'))
          self.assertEqual(0, band.weight_from)
  
      def test_weight_from_for_multiple_bands(self):
          self.standard.bands.create(upper_limit=1, charge=D('4.00'))
          band = self.standard.objects.create(upper_limit=2, charge=D('8.00'))
          self.assertEqual(1, band.weight_from)
  
      def test_weight_from_for_multiple_bands(self):
          self.standard.bands.create(upper_limit=1, charge=D('4.00'))
          band = self.express.bands.create(upper_limit=2, charge=D('8.00'))
          self.assertEqual(0, band.weight_from)
  
      def test_get_band_for_series_of_bands(self):
          self.standard.bands.create(upper_limit=1, charge=D('4.00'))
          self.standard.bands.create(upper_limit=2, charge=D('8.00'))
          self.standard.bands.create(upper_limit=3, charge=D('12.00'))
          self.assertEqual(D('4.00'), self.standard.get_band_for_weight(0.5).charge)
          self.assertEqual(D('8.00'), self.standard.get_band_for_weight(1.5).charge)
          self.assertEqual(D('12.00'), self.standard.get_band_for_weight(2.5).charge)
  
      def test_get_band_for_series_of_bands_from_different_methods(self):
          self.express.bands.create(upper_limit=2, charge=D('8.00'))
          self.standard.bands.create(upper_limit=1, charge=D('4.00'))
          self.standard.bands.create(upper_limit=3, charge=D('12.00'))
          self.assertEqual(D('12.00'), self.standard.get_band_for_weight(2.5).charge)
  
      def test_for_smoke_with_basket_charge(self):
          basket = Basket()
          self.standard.set_basket(basket)
          charge = self.standard.basket_charge_incl_tax()
          self.assertEqual(D('0.00'), charge)
  
  
  class RepositoryTests(TestCase):
  
      def setUp(self):
          self.repo = Repository()
  
      def test_default_method_is_free(self):
          user, basket = User(), Basket()
          methods = self.repo.get_shipping_methods(user, basket)
          self.assertEqual(1, len(methods))
          self.assertTrue(isinstance(methods[0], Free))
  
  