def test_checks_if_purchase_is_permitted(self): basket = factories.BasketFactory() product = factories.ProductFactory() # Build a 4-level mock monster so we can force the return value of # whether the product is available to buy. This is a serious code smell # and needs to be remedied. info = mock.Mock() info.availability = mock.Mock() info.availability.is_purchase_permitted = mock.Mock( return_value=(False, "Not on your nelly!")) basket.strategy.fetch_for_product = mock.Mock(return_value=info) data = {'quantity': 1} form = forms.AddToBasketForm(basket=basket, product=product, data=data) self.assertFalse(form.is_valid()) self.assertEqual('Not on your nelly!', form.errors['__all__'][0])
def _create_coupon_product_with_attributes(self, note='note', notify_email=None): """Helper method that creates a coupon product with note and notify_email attributes.""" coupon_product = factories.ProductFactory( title=self.COUPON_PRODUCT_TITLE, product_class=self.coupon_product_class, categories=[]) voucher = factories.VoucherFactory() coupon_vouchers = CouponVouchers.objects.create(coupon=coupon_product) coupon_vouchers.vouchers.add(voucher) coupon_product.attr.coupon_vouchers = coupon_vouchers coupon_product.attr.note = note if notify_email: coupon_product.attr.notify_email = notify_email coupon_product.save() return coupon_product
def test_voucher_single_usage(self): user = AnonymousUser() creator = OrderCreator() product = factories.ProductFactory() voucher = factories.VoucherFactory(usage=Voucher.SINGLE_USE) voucher.offers.add(factories.create_offer(offer_type='Voucher')) # Make the order creator a bit more slow too reliable trigger # concurrency issues org_create_order_model = OrderCreator.create_order_model def new_create_order_model(*args, **kwargs): time.sleep(0.5) return org_create_order_model(creator, *args, **kwargs) creator.create_order_model = new_create_order_model org_record_voucher_usage = OrderCreator.record_voucher_usage def record_voucher_usage(*args, **kwargs): time.sleep(0.5) return org_record_voucher_usage(creator, *args, **kwargs) creator.record_voucher_usage = record_voucher_usage # Start 5 threads to place an order concurrently def worker(): order_number = threading.current_thread().name basket = factories.BasketFactory() basket.add_product(product) basket.vouchers.add(voucher) place_order(creator, basket=basket, order_number=order_number, user=user) exceptions = run_concurrently(worker, num_threads=5) voucher.refresh_from_db() assert all(isinstance(x, ValueError) for x in exceptions), exceptions assert len(exceptions) == 4 assert voucher.applications.count() == 1 assert Order.objects.count() == 1
def test_cancel_stock_allocations_track_stock_on(self): product_class = factories.ProductClassFactory(requires_shipping=False, track_stock=True) product = factories.ProductFactory(product_class=product_class) basket = factories.create_basket(empty=True) add_product(basket, D('10.00'), 5, product=product) order = factories.create_order(basket=basket) stockrecord = product.stockrecords.get() num_allocated = stockrecord.num_allocated lines = order.lines.all() self.handler.cancel_stock_allocations( order, lines, [line.quantity for line in lines]) stockrecord.refresh_from_db() self.assertEqual(stockrecord.num_allocated, num_allocated - 5, "Allocated stock should have decreased, but didn't.")
def test_mixed_currency_baskets_are_not_permitted(self): # Ensure basket is one currency basket = mock.Mock() basket.currency = 'GBP' basket.num_items = 1 # Ensure new product has different currency info = mock.Mock() info.price.currency = 'EUR' basket.strategy.fetch_for_product = mock.Mock( return_value=info) product = factories.ProductFactory() data = {'quantity': 1} form = forms.AddToBasketForm( basket=basket, product=product, data=data) self.assertFalse(form.is_valid())
def test_consume_stock_allocations_without_line_arguments(self): product_class = factories.ProductClassFactory(requires_shipping=False, track_stock=True) product = factories.ProductFactory(product_class=product_class) basket = factories.create_basket(empty=True) add_product(basket, D('10.00'), 5, product=product) order = factories.create_order(basket=basket) stockrecord = product.stockrecords.get() num_in_stock = stockrecord.num_in_stock num_allocated = stockrecord.num_allocated self.handler.consume_stock_allocations(order) stockrecord.refresh_from_db() self.assertEqual(stockrecord.num_allocated, num_allocated - 5, "Allocated stock should have decreased, but didn't.") self.assertEqual(stockrecord.num_in_stock, num_in_stock - 5, "Stock should have decreased, but didn't.")
def test_attributes_initialised_before_write(self): # Regression test for https://github.com/django-oscar/django-oscar/issues/3258 product_class = factories.ProductClassFactory() product_class.attributes.create(name='a1', code='a1', required=True) product_class.attributes.create(name='a2', code='a2', required=False) product_class.attributes.create(name='a3', code='a3', required=True) product = factories.ProductFactory(product_class=product_class) product.attr.a1 = "v1" product.attr.a3 = "v3" product.attr.save() product = Product.objects.get(pk=product.pk) product.attr.a1 = "v2" product.attr.a3 = "v6" product.attr.save() product = Product.objects.get(pk=product.pk) assert product.attr.a1 == "v2" assert product.attr.a3 == "v6"
def test_voucher_not_valid_for_bundle(self): """ Verify correct error message is returned when voucher is used against a bundle. """ self.mock_access_token_response() self.mock_account_api(self.request, self.user.username, data={'is_active': True}) voucher, product = prepare_voucher(code=COUPON_CODE, benefit_value=0) new_product = factories.ProductFactory( categories=[], stockrecords__partner__short_code='second') self.basket.add_product(product) self.basket.add_product(new_product) BasketAttributeType.objects.get_or_create(name=BUNDLE) BasketAttribute.objects.update_or_create( basket=self.basket, attribute_type=BasketAttributeType.objects.get(name=BUNDLE), value_text='test_bundle') self.assert_form_valid_message( "Coupon code '{code}' is not valid for this basket.".format( code=voucher.code))
def test_are_stock_allocations_available(self): product_class = factories.ProductClassFactory(requires_shipping=False, track_stock=True) product = factories.ProductFactory(product_class=product_class) basket = factories.create_basket(empty=True) add_product(basket, D('10.00'), 5, product=product) order = factories.create_order(basket=basket) line = order.lines.get() self.assertEqual( self.handler.are_stock_allocations_available([line], [line.quantity]), True, ) self.assertEqual( self.handler.are_stock_allocations_available([line], [105]), False, )
def setUp(self): super(TestProductClass, self).setUp() self.pclass = ProductClassFactory(name='T-Shirts', slug='tshirts') for attribute_type, __ in ProductAttribute.TYPE_CHOICES: values = { 'type': attribute_type, 'code': attribute_type, 'product_class': self.pclass, 'name': attribute_type, } if attribute_type == ProductAttribute.OPTION: option_group = factories.AttributeOptionGroupFactory() self.option = factories.AttributeOptionFactory( group=option_group) values['option_group'] = option_group ProductAttributeFactory(**values) self.product = factories.ProductFactory(product_class=self.pclass) self.url = reverse('dashboard:catalogue-product', kwargs={'pk': self.product.id})
def test_single_usage(self): user = AnonymousUser() creator = OrderCreator() product = factories.ProductFactory(stockrecords__num_in_stock=1000) # Make the order creator a bit more slow too reliable trigger # concurrency issues org_create_order_model = OrderCreator.create_order_model def new_create_order_model(*args, **kwargs): time.sleep(0.5) return org_create_order_model(creator, *args, **kwargs) creator.create_order_model = new_create_order_model # Start 5 threads to place an order concurrently def worker(): order_number = threading.current_thread().name basket = factories.BasketFactory() basket.add_product(product) surcharges = SurchargeApplicator().get_applicable_surcharges( basket) place_order(creator, surcharges=surcharges, basket=basket, order_number=order_number, user=user) exceptions = run_concurrently(worker, num_threads=5) assert all(isinstance(x, ValueError) for x in exceptions), exceptions assert len(exceptions) == 0 assert Order.objects.count() == 5 stockrecord = product.stockrecords.first() assert stockrecord.num_allocated == 5
def _create_program_with_courses_and_offer(self): offer = ProgramOfferFactory( site=self.site, partner=self.site.siteconfiguration.partner, benefit=PercentageDiscountBenefitWithoutRangeFactory(value=20)) program_uuid = offer.condition.program_uuid program_data = self.mock_program_detail_endpoint( program_uuid, self.site_configuration.discovery_api_url) self.mock_user_data(self.user.username) sku_list = [] products = [] for course in program_data['courses']: sku_list.append(course['entitlements'][0]['sku']) for sku in sku_list: products.append( factories.ProductFactory( stockrecords__partner=self.partner, stockrecords__price_excl_tax=Decimal('10.00'), stockrecords__partner_sku=sku, )) return products, program_uuid
def test_validates_that_child_products_dont_need_a_title(self): parent = factories.ProductFactory(product_class=self.product_class, structure='parent') form = self.submit({'structure': 'child'}, parent=parent) self.assertTrue(form.is_valid())
def setUp(self): product_class = factories.ProductClassFactory( requires_shipping=False, track_stock=False) self.product = factories.ProductFactory(product_class=product_class) self.stockrecord = factories.create_stockrecord( self.product, price_excl_tax=D('10.00'), num_in_stock=10)
def setUp(self): super(InvoiceManagementCommandExceptionsTest, self).setUp() self.product = factories.ProductFactory(product_class=ProductClass.objects.get(name='Coupon')) self.basket = factories.BasketFactory() self.basket.add_product(self.product, 1) self.basket.submit()
def setUp(self): super().setUp() self.basket = factories.create_basket(empty=True) # Create range and add one product to it. rng = factories.RangeFactory(name='All products', includes_all_products=True) self.product = factories.ProductFactory() rng.add_product(self.product) # Create offer #1. condition1 = factories.ConditionFactory( range=rng, type=factories.ConditionFactory._meta.model.COUNT, value=D('2'), ) benefit1 = factories.BenefitFactory( range=rng, type=factories.BenefitFactory._meta.model.MULTIBUY, value=None, ) self.offer1 = factories.ConditionalOfferFactory( condition=condition1, benefit=benefit1, slug='offer-1', start_datetime=now(), name='Test offer #1', priority=1, ) # Create offer #2. condition2 = factories.ConditionFactory( range=rng, type=factories.ConditionFactory._meta.model.VALUE, value=D('1.99'), ) benefit2 = factories.BenefitFactory( range=rng, type=factories.BenefitFactory._meta.model.MULTIBUY, value=None, ) self.offer2 = factories.ConditionalOfferFactory( condition=condition2, benefit=benefit2, slug='offer-2', start_datetime=now(), name='Test offer #2', ) # Create offer #3. condition3 = factories.ConditionFactory( range=rng, type=factories.ConditionFactory._meta.model.COVERAGE, value=1, ) benefit3 = factories.BenefitFactory( range=rng, type=factories.BenefitFactory._meta.model.MULTIBUY, value=None, ) self.offer3 = factories.ConditionalOfferFactory( condition=condition3, benefit=benefit3, slug='offer-3', start_datetime=now(), name='Test offer #3', ) # Prepare `BasketView` to use `get_upsell_messages` method in tests. self.view = BasketView() self.view.request = RequestFactory().get(reverse('basket:summary')) self.view.request.user = factories.UserFactory() self.view.args = [] self.view.kwargs = {}
def test_pricing_policy_unavailable_if_no_price_excl_tax(self): product = factories.ProductFactory(stockrecords=[]) factories.StockRecordFactory(price_excl_tax=None, product=product) info = strategy.US().fetch_for_product(product) self.assertFalse(info.price.exists)
def test_product_with_empty_price(self): product_class = factories.ProductClassFactory(track_stock=False) product = factories.ProductFactory(product_class=product_class, stockrecords=[]) factories.StockRecordFactory(price_excl_tax=None, product=product) info = self.strategy.fetch_for_product(product) self.assertFalse(info.availability.is_available_to_buy)
def test_save_multi_option_value(self): product = factories.ProductFactory() # We'll save two out of the three available options self.attr.save_value(product, [self.options[0], self.options[2]]) product = Product.objects.get(pk=product.pk) self.assertEqual(list(product.attr.sizes), [self.options[0], self.options[2]])
def test_option_value_as_text(self): product = factories.ProductFactory() option_2 = self.options[1] self.attr.save_value(product, option_2) attr_val = product.attribute_values.get(attribute=self.attr) assert attr_val.value_as_text == str(option_2)
def setUp(self): super().setUp() self.basket = factories.create_basket(empty=True) # Create range and add one product to it. rng = factories.RangeFactory(name='All products', includes_all_products=True) self.product = factories.ProductFactory() rng.add_product(self.product) # Create offer #1. condition1 = factories.ConditionFactory( range=rng, type=factories.ConditionFactory._meta.model.COUNT, value=D('2'), ) benefit1 = factories.BenefitFactory( range=rng, type=factories.BenefitFactory._meta.model.MULTIBUY, value=None, ) self.offer1 = factories.ConditionalOfferFactory( condition=condition1, benefit=benefit1, slug='offer-1', start_datetime=now(), name='Test offer #1', priority=1, ) # Create offer #2. condition2 = factories.ConditionFactory( range=rng, type=factories.ConditionFactory._meta.model.COUNT, value=D('1'), ) benefit2 = factories.BenefitFactory( range=rng, type=factories.BenefitFactory._meta.model.PERCENTAGE, value=D('5'), ) self.offer2 = factories.ConditionalOfferFactory( condition=condition2, benefit=benefit2, slug='offer-2', start_datetime=now(), name='Test offer #2', ) # Create offer #3. condition3 = factories.ConditionFactory( range=rng, type=factories.ConditionFactory._meta.model.COUNT, value=D('1'), ) benefit3 = factories.BenefitFactory( range=rng, type=factories.BenefitFactory._meta.model.MULTIBUY, value=None, ) self.offer3 = factories.ConditionalOfferFactory( condition=condition3, benefit=benefit3, slug='offer-3', start_datetime=now(), name='Test offer #3', exclusive=False, ) # Create offer #4. condition4 = factories.ConditionFactory( range=rng, type=factories.ConditionFactory._meta.model.COUNT, value=D('1'), ) benefit4 = factories.BenefitFactory( range=rng, type=factories.BenefitFactory._meta.model.MULTIBUY, value=None, ) self.offer4 = factories.ConditionalOfferFactory( condition=condition4, benefit=benefit4, slug='offer-4', start_datetime=now(), name='Test offer #4', exclusive=False, priority=3, )
def test_multi_option_value_as_text(self): product = factories.ProductFactory() self.attr.save_value(product, self.options) attr_val = product.attribute_values.get(attribute=self.attr) self.assertEqual(attr_val.value_as_text, ", ".join(o.option for o in self.options))
def setUp(self): super().setUp() self.product = factories.ProductFactory() self.url = reverse('dashboard:catalogue-product', kwargs={'pk': self.product.id})