Ejemplo n.º 1
0
    def test_allocate_does_nothing_for_child_product(self):
        parent_product = factories.ProductFactory(
            structure='parent', product_class=self.product_class)
        child_product = factories.ProductFactory(
            parent=parent_product, product_class=None, structure='child')
        stockrecord = factories.create_stockrecord(
            child_product, price_excl_tax=D('10.00'), num_in_stock=10)

        self.assertFalse(stockrecord.can_track_allocations)
        stockrecord.allocate(5)
        self.assertEqual(stockrecord.num_allocated, None)
Ejemplo n.º 2
0
 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.refresh_from_db()
     self.assertEqual(list(product.attr.sizes),
                      [self.options[0], self.options[2]])
Ejemplo n.º 3
0
 def test_delete_multi_option_value(self):
     product = factories.ProductFactory()
     self.attr.save_value(product, [self.options[0], self.options[1]])
     # Now delete these values
     self.attr.save_value(product, None)
     product.refresh_from_db()
     self.assertFalse(hasattr(product.attr, 'sizes'))
Ejemplo n.º 4
0
    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)
            place_order(
                creator, 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
Ejemplo n.º 5
0
    def setUp(self):
        super().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
            elif attribute_type == ProductAttribute.MULTI_OPTION:
                option_group = factories.AttributeOptionGroupFactory()
                self.multi_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})
Ejemplo n.º 6
0
 def create_digital_product(self):
     product_class = factories.ProductClassFactory(requires_shipping=False,
                                                   track_stock=False)
     product = factories.ProductFactory(product_class=product_class)
     factories.StockRecordFactory(num_in_stock=None,
                                  price_excl_tax=D('12.00'),
                                  product=product)
     return product
Ejemplo n.º 7
0
    def test_works_for_child_product(self):
        parent = factories.ProductFactory(structure='parent', stockrecords=[])
        for x in range(3):
            variant = factories.ProductFactory(parent=parent,
                                               structure='child')

            detail_page = self.get(variant.get_absolute_url())
            form = detail_page.forms['add_to_basket_form']
            response = form.submit()

            self.assertIsRedirect(response)

        baskets = models.Basket.objects.all()
        self.assertEqual(1, len(baskets))

        basket = baskets[0]
        self.assertEqual(3, basket.num_items)
Ejemplo n.º 8
0
 def test_variant_images_fallback_to_parent(self):
     parent = factories.ProductFactory(structure='parent')
     variant = factories.create_product(parent=parent)
     factories.create_product_image(product=parent, caption='Parent Product Image')
     all_images = variant.get_all_images()
     self.assertEquals(all_images.count(), 1)
     product_image = all_images.first()
     self.assertEquals(product_image.caption, 'Parent Product Image')
Ejemplo n.º 9
0
    def test_allocate_does_nothing(self):
        product = factories.ProductFactory(product_class=self.product_class)
        stockrecord = factories.create_stockrecord(
            product, price_excl_tax=D('10.00'), num_in_stock=10)

        self.assertFalse(stockrecord.can_track_allocations)
        stockrecord.allocate(5)
        self.assertEqual(stockrecord.num_allocated, None)
Ejemplo n.º 10
0
    def test_redirects_customers_with_invalid_basket(self):
        # Add product to basket but then remove its stock so it is not
        # purchasable.
        product = factories.ProductFactory()
        self.add_product_to_basket(product)
        product.stockrecords.all().update(num_in_stock=0)

        response = self.get(reverse('checkout:index'))
        self.assertRedirectsTo(response, 'basket:summary')
Ejemplo n.º 11
0
 def add_product_to_basket(self, product=None):
     if product is None:
         product = factories.ProductFactory()
         factories.StockRecordFactory(num_in_stock=10,
                                      price_excl_tax=D('12.00'),
                                      product=product)
     detail_page = self.get(product.get_absolute_url())
     form = detail_page.forms['add_to_basket_form']
     form.submit()
Ejemplo n.º 12
0
 def test_availability_does_not_require_price(self):
     # regression test for https://github.com/izi-ecommerce/izi-core/issues/2664
     # The availability policy should be independent of price.
     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.assertTrue(info.availability.is_available_to_buy)
Ejemplo n.º 13
0
    def setUp(self):
        self.condition_product = factories.ProductFactory()
        condition_range = factories.RangeFactory()
        condition_range.add_product(self.condition_product)
        self.condition = models.CountCondition.objects.create(
            range=condition_range, type=models.Condition.COUNT, value=2)

        self.benefit_product = factories.ProductFactory()
        benefit_range = factories.RangeFactory()
        benefit_range.add_product(self.benefit_product)
        self.benefit = models.AbsoluteDiscountBenefit.objects.create(
            range=benefit_range, type=models.Benefit.FIXED, value=D('3.00'))

        self.offer = models.ConditionalOffer(id=1,
                                             condition=self.condition,
                                             benefit=self.benefit)
        self.basket = factories.create_basket(empty=True)

        self.applicator = Applicator()
Ejemplo n.º 14
0
    def test_works_for_standalone_product(self):
        product = factories.ProductFactory()

        detail_page = self.get(product.get_absolute_url())
        response = detail_page.forms['add_to_basket_form'].submit()

        self.assertIsRedirect(response)
        baskets = models.Basket.objects.all()
        self.assertEqual(1, len(baskets))

        basket = baskets[0]
        self.assertEqual(1, basket.num_items)
Ejemplo n.º 15
0
    def test_are_stock_allocations_available_track_stock_off(self):
        product_class = factories.ProductClassFactory(requires_shipping=False,
                                                      track_stock=False)
        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], [105]),
            True,
        )
Ejemplo n.º 16
0
    def test_product_update_form(self):
        self.product = factories.ProductFactory()
        url = reverse('dashboard:catalogue-product',
                      kwargs={'pk': self.product.id})

        page = self.get(url)
        product_form = page.form
        product_form['title'] = expected_title = 'Nice T-Shirt'
        page = product_form.submit()

        product = Product.objects.get(id=self.product.id)

        self.assertEqual(page.context['product'], self.product)
        self.assertEqual(product.title, expected_title)
Ejemplo n.º 17
0
    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())
Ejemplo n.º 18
0
    def test_cancel_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_allocated = stockrecord.num_allocated

        self.handler.cancel_stock_allocations(order)

        stockrecord.refresh_from_db()
        self.assertEqual(stockrecord.num_allocated, num_allocated - 5,
                         "Allocated stock should have decreased, but didn't.")
Ejemplo n.º 19
0
    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])
Ejemplo n.º 20
0
    def test_cancel_stock_allocations_track_stock_off(self):
        product_class = factories.ProductClassFactory(requires_shipping=False,
                                                      track_stock=False)
        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,
            "Allocated stock shouldn't have changed, but it did.")
Ejemplo n.º 21
0
    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
Ejemplo n.º 22
0
 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)
Ejemplo n.º 23
0
 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())
Ejemplo n.º 24
0
 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))