def test_basket_offers_are_ordered(self): voucher = Voucher.objects.create( name="Test voucher", code="test", start_date=datetime.date.today(), end_date=datetime.date.today() + datetime.timedelta(days=12), ) voucher.offers = [ factories.create_offer(name="A", priority=0), factories.create_offer(name="B", priority=7), factories.create_offer(name="C", priority=5), factories.create_offer(name="D", priority=7), factories.create_offer(name="E", priority=1), ] basket = factories.create_basket() user = mock.Mock() # Apply voucher to basket basket.vouchers.add(voucher) offers = utils.Applicator().get_basket_offers(basket, user) ordered_names = [offer.name for offer in offers] self.assertEqual(["B", "D", "C", "E", "A"], ordered_names)
def test_for_multiple_offers_benefits_and_conditions_not_deleted(self): condition = factories.ConditionFactory() condition_id = condition.id benefit = factories.BenefitFactory() benefit_id = benefit.id offer1 = factories.create_offer( name='First test offer', condition=condition) offer2 = factories.create_offer( name='Second test offer', condition=condition, benefit=benefit) offer3 = factories.create_offer( name='Third test offer', benefit=benefit) offer1.delete() self.assertTrue( models.Condition.objects.filter(id=condition_id).exists()) offer2.delete() self.assertFalse( models.Condition.objects.filter(id=condition_id).exists()) self.assertTrue( models.Benefit.objects.filter(id=benefit_id).exists()) offer3.delete() self.assertFalse( models.Benefit.objects.filter(id=benefit_id).exists())
def test_for_multiple_offers_benefits_and_conditions_not_deleted(self): condition = factories.ConditionFactory() condition_id = condition.id benefit = factories.BenefitFactory() benefit_id = benefit.id offer1 = factories.create_offer(name='First test offer', condition=condition) offer2 = factories.create_offer(name='Second test offer', condition=condition, benefit=benefit) offer3 = factories.create_offer(name='Third test offer', benefit=benefit) offer1.delete() self.assertTrue( models.Condition.objects.filter(id=condition_id).exists()) offer2.delete() self.assertFalse( models.Condition.objects.filter(id=condition_id).exists()) self.assertTrue(models.Benefit.objects.filter(id=benefit_id).exists()) offer3.delete() self.assertFalse(models.Benefit.objects.filter(id=benefit_id).exists())
def test_basket_offers_are_ordered(self): voucher = Voucher.objects.create( name="Test voucher", code="test", usage=Voucher.MULTI_USE, start_datetime=timezone.now(), end_datetime=timezone.now() + datetime.timedelta(days=12)) voucher.offers.set([ factories.create_offer(name="A", priority=0), factories.create_offer(name="B", priority=7), factories.create_offer(name="C", priority=5), factories.create_offer(name="D", priority=7), factories.create_offer(name="E", priority=1), ]) basket = factories.create_basket() user = mock.Mock() # Apply voucher to basket basket.vouchers.add(voucher) offers = utils.Applicator().get_basket_offers(basket, user) ordered_names = [offer.name for offer in offers] self.assertEqual(["B", "D", "C", "E", "A"], ordered_names)
def test_includes_offers_in_date_range(self): now = timezone.now() start = now - datetime.timedelta(days=1) end = now + datetime.timedelta(days=1) factories.create_offer(start=start, end=end) filtered_offers = models.ConditionalOffer.active.all() self.assertEqual(1, len(filtered_offers))
def test_includes_offers_in_date_range(self): # Create offer that is available but with the wrong status now = datetime.datetime.now() start = now - datetime.timedelta(days=1) end = now + datetime.timedelta(days=1) factories.create_offer(start=start, end=end) filtered_offers = models.ConditionalOffer.active.all() self.assertEqual(1, len(filtered_offers))
def test_filters_out_offers_yet_to_start(self): # Create offer that is available but with the wrong status now = datetime.datetime.now() start = now + datetime.timedelta(days=1) end = now + datetime.timedelta(days=3) factories.create_offer(start=start, end=end) filtered_offers = models.ConditionalOffer.active.all() self.assertEqual(0, len(filtered_offers))
def test_site_offers_are_ordered(self): factories.create_offer(name="A", priority=0) factories.create_offer(name="B", priority=7) factories.create_offer(name="C", priority=5) factories.create_offer(name="D", priority=7) factories.create_offer(name="E", priority=1) offers = utils.Applicator().get_site_offers() ordered_names = [offer.name for offer in offers] self.assertEqual(["B", "D", "C", "E", "A"], ordered_names)
def setUp(self): self.basket = create_basket(empty=True) self.product = create_product(price=100) range = RangeFactory(products=[self.product]) condition = ConditionFactory(range=range, value=2) self.voucher = VoucherFactory() self.voucher.offers.add(create_offer(offer_type='Voucher', range=range, condition=condition))
def test_can_be_created_with_an_offer(self): offer = create_offer() order = create_order(number='100002') discount = OrderDiscount.objects.create(order=order, amount=D('10.00'), offer_id=offer.id) self.assertEqual(offer.id, discount.offer.id) self.assertEqual(offer.name, discount.offer_name)
def test_single_usage(self): user = AnonymousUser() basket = factories.create_basket() creator = OrderCreator() voucher = factories.VoucherFactory(usage=Voucher.SINGLE_USE) voucher.offers.add(factories.create_offer(offer_type='Voucher')) basket.vouchers.add(voucher) surcharges = SurchargeApplicator().get_applicable_surcharges(basket) place_order(creator, surcharges=surcharges, basket=basket, order_number='12346', user=user) assert voucher.applications.count() == 1 # Make sure the voucher usage is rechecked with pytest.raises(ValueError): place_order(creator, surcharges=surcharges, basket=basket, order_number='12347', user=user)
def test_jump_to_condition_step_for_existing_offer(self): offer = factories.create_offer() url = reverse('dashboard:offer-condition', kwargs={'pk': offer.id}) condition_page = self.get(url) self.assertFalse('range' in condition_page.errors) self.assertEqual(len(condition_page.errors), 0)
def apply_20percent_shipping_offer(self): """Shipping offer 20% off""" range = Range.objects.create(name="All products range", includes_all_products=True) benefit = Benefit.objects.create( range=range, type=Benefit.SHIPPING_PERCENTAGE, value=20) offer = factories.create_offer(range=range, benefit=benefit) Applicator().apply_offers(self.basket, [offer])
def test_can_change_offer_priority(self): offer = factories.create_offer() restrictions_page = self.get(reverse('dashboard:offer-restrictions', kwargs={'pk': offer.pk})) restrictions_page.form['priority'] = '12' restrictions_page.form.submit() offer.refresh_from_db() self.assertEqual(offer.priority, 12)
def test_can_be_created_with_an_offer_and_specified_offer_name(self): offer = create_offer(name="My offer") order = create_order(number='100002') discount = OrderDiscount.objects.create(order=order, amount=D('10.00'), offer_id=offer.id, offer_name="Your offer") self.assertEqual(offer.id, discount.offer.id) self.assertEqual("Your offer", discount.offer_name)
def test_can_update_an_existing_offer_save_directly(self): # see if we can save the offer directly without completing all # steps offer = factories.create_offer(name="Offer A") name_and_description_page = self.get( reverse('dashboard:offer-metadata', kwargs={'pk': offer.pk})) res = name_and_description_page.form.submit('save').follow() self.assertEqual(200, res.status_code)
def test_contains_offer_details_after_offer_is_deleted(self): offer = create_offer(name="Get 200% off") order = create_order(number="100002") discount = OrderDiscount.objects.create(order=order, amount=D("10.00"), offer_id=offer.id) offer.delete() self.assertTrue(discount.voucher is None) self.assertTrue(discount.offer is None) self.assertEquals(discount.description(), u"Get 200% off")
def setUp(self): super(TestPlacingOrderUsingAnOffer, self).setUp() offer = create_offer() self.add_product_to_basket() self.complete_shipping_address() self.complete_shipping_method() self.response = self.submit() # Reload offer self.offer = ConditionalOffer.objects.get(id=offer.id)
def setUp(self): self.basket = create_basket(empty=True) self.product = create_product(price=100) range = RangeFactory(products=[self.product]) condition = ConditionFactory(range=range, value=2) self.voucher = VoucherFactory() self.voucher.offers.add( create_offer(offer_type='Voucher', range=range, condition=condition))
def setUp(self): offer = create_offer() self.login() self.add_product_to_basket() self.complete_shipping_address() self.complete_shipping_method() self.response = self.submit() # Reload offer self.offer = ConditionalOffer.objects.get(id=offer.id)
def test_zero_charge_with_shipping_discount(self): offer = factories.create_offer(benefit=Benefit.objects.create( type=Benefit.SHIPPING_FIXED_PRICE, value=1), ) basket = factories.create_basket() Applicator().apply_offers(basket, [offer]) # Similar to test_zero_charge_discount(), # but now test how the repository deals with it. method = Repository().apply_shipping_offer(basket, self.standard, offer) self.assertEqual(D('0.00'), method.discount(basket))
def test_contains_offer_details_after_offer_is_deleted(self): offer = create_offer(name="Get 200% off") order = create_order(number='100002') discount = OrderDiscount.objects.create(order=order, amount=D('10.00'), offer_id=offer.id) offer.delete() self.assertTrue(discount.voucher is None) self.assertTrue(discount.offer is None) self.assertEqual(discount.description(), u'Get 200% off')
def test_can_update_an_existing_offer(self): factories.create_offer(name="Offer A") list_page = self.get(reverse('dashboard:offer-list')) detail_page = list_page.click('Offer A') metadata_page = detail_page.click(linkid="edit_metadata") metadata_form = metadata_page.form metadata_form['name'] = "Offer A+" benefit_page = metadata_form.submit().follow() benefit_form = benefit_page.form condition_page = benefit_form.submit().follow() condition_form = condition_page.form restrictions_page = condition_form.submit().follow() restrictions_page.form.submit() models.ConditionalOffer.objects.get(name="Offer A+")
def test_records_use(self): offer = factories.create_offer() self.add_product_to_basket() self.enter_shipping_address() self.place_order() # Reload offer offer = ConditionalOffer.objects.get(id=offer.id) self.assertEqual(1, offer.num_orders) self.assertEqual(1, offer.num_applications)
def test_can_suspend_an_offer(self): # Create an offer offer = factories.create_offer() self.assertFalse(offer.is_suspended) detail_page = self.get(reverse('dashboard:offer-detail', kwargs={'pk': offer.pk})) form = detail_page.forms['status_form'] form.submit('suspend') reloaded_offer = models.ConditionalOffer.objects.get(pk=offer.pk) self.assertTrue(reloaded_offer.is_suspended)
def test_can_suspend_an_offer(self): # Create an offer offer = factories.create_offer() self.assertFalse(offer.is_suspended) detail_page = self.get(reverse('dashboard:offer-detail', kwargs={'pk': offer.pk})) form = detail_page.forms['status_form'] form.submit('suspend') offer.refresh_from_db() self.assertTrue(offer.is_suspended)
def test_can_suspend_an_offer(self): # Create an offer offer = factories.create_offer() self.assertFalse(offer.is_suspended) detail_page = self.get( reverse('dashboard:offer-detail', kwargs={'pk': offer.pk})) form = detail_page.forms['status_form'] form.submit('suspend') offer.refresh_from_db() self.assertTrue(offer.is_suspended)
def test_can_suspend_an_offer(self): # Create an offer offer = factories.create_offer() self.assertFalse(offer.is_suspended) detail_page = self.get( reverse('dashboard:offer-detail', kwargs={'pk': offer.pk})) form = detail_page.forms['status_form'] form.submit('suspend') reloaded_offer = models.ConditionalOffer.objects.get(pk=offer.pk) self.assertTrue(reloaded_offer.is_suspended)
def test_expired_voucher(self): user = AnonymousUser() basket = factories.create_basket() creator = OrderCreator() voucher = factories.VoucherFactory(usage=Voucher.SINGLE_USE) voucher.offers.add(factories.create_offer(offer_type='Voucher')) basket.vouchers.add(voucher) voucher.end_datetime = timezone.now() - datetime.timedelta(days=100) voucher.save() place_order(creator, basket=basket, order_number='12346', user=user) assert voucher.applications.count() == 0
def test_custom_benefits_and_conditions_not_deleted(self): condition = custom.create_condition(BasketOwnerCalledBarry) condition_id = condition.id benefit = custom.create_benefit(CustomBenefitModel) benefit_id = benefit.id offer = factories.create_offer(benefit=benefit, condition=condition) offer.delete() self.assertTrue( models.Condition.objects.filter(id=condition_id).exists()) self.assertTrue(models.Benefit.objects.filter(id=benefit_id).exists())
def test_zero_charge_with_shipping_discount(self): offer = factories.create_offer( benefit=Benefit.objects.create( type=Benefit.SHIPPING_FIXED_PRICE, value=1), ) basket = factories.create_basket() Applicator().apply_offers(basket, [offer]) # Similar to test_zero_charge_discount(), # but now test how the repository deals with it. method = Repository().apply_shipping_offer( basket, self.standard, offer) self.assertEqual(D('0.00'), method.discount(basket))
def test_custom_benefits_and_conditions_not_deleted(self): condition = custom.create_condition(BasketOwnerCalledBarry) condition_id = condition.id benefit = custom.create_benefit(CustomBenefitModel) benefit_id = benefit.id offer = factories.create_offer(benefit=benefit, condition=condition) offer.delete() self.assertTrue( models.Condition.objects.filter(id=condition_id).exists()) self.assertTrue( models.Benefit.objects.filter(id=benefit_id).exists())
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) 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) 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_related_offer_deleted(self): # Voucher with offer name corresponding to it as used in the dashboard voucher_name = "Voucher" voucher = VoucherFactory(name=voucher_name, code="VOUCHER") voucher.offers.add( create_offer(name=_("Offer for voucher '%s'") % voucher_name, offer_type='Voucher', range=self.offer_range, condition=self.offer_condition)) voucher.delete() self.assertFalse( ConditionalOffer.objects.filter( name=_("Offer for voucher '%s'") % voucher_name, offer_type=ConditionalOffer.VOUCHER).exists())
def test_related_offer_different_name_not_deleted(self): # Voucher with offer named differently voucher = VoucherFactory(name="Voucher", code="VOUCHER") voucher.offers.add( create_offer(name="Different name test", offer_type='Voucher', range=self.offer_range, condition=self.offer_condition)) offer_ids = list(voucher.offers.all().values_list('pk', flat=True)) voucher.delete() count_offers = ConditionalOffer.objects.filter( id__in=offer_ids).count() assert len(offer_ids) == count_offers
def test_single_usage(self): user = AnonymousUser() basket = factories.create_basket() creator = OrderCreator() voucher = factories.VoucherFactory(usage=Voucher.SINGLE_USE) voucher.offers.add(factories.create_offer(offer_type='Voucher')) basket.vouchers.add(voucher) place_order(creator, basket=basket, order_number='12346', user=user) assert voucher.applications.count() == 1 # Make sure the voucher usage is rechecked with pytest.raises(ValueError): place_order(creator, basket=basket, order_number='12347', user=user)
def test_related_offer_different_type_not_deleted(self): # Voucher with offer not of type "Voucher" voucher_name = "Voucher" voucher = VoucherFactory(name=voucher_name, code="VOUCHER") voucher.offers.add( create_offer(name=_("Offer for voucher '%s'") % voucher_name, offer_type='Site', range=self.offer_range, condition=self.offer_condition)) offer_ids = list(voucher.offers.all().values_list('pk', flat=True)) voucher.delete() count_offers = ConditionalOffer.objects.filter( id__in=offer_ids).count() assert len(offer_ids) == count_offers
def test_multiple_related_offers_not_deleted(self): # Voucher with already used offer voucher_name = "Voucher 1" offer = create_offer(name=_("Offer for voucher '%s'") % voucher_name, offer_type='Voucher', range=self.offer_range, condition=self.offer_condition) voucher1 = VoucherFactory(name=voucher_name, code="VOUCHER1") voucher1.offers.add(offer) voucher2 = VoucherFactory(name="Voucher 2", code="VOUCHER2") voucher2.offers.add(offer) offer_ids = list(voucher1.offers.all().values_list('pk', flat=True)) voucher1.delete() count_offers = ConditionalOffer.objects.filter( id__in=offer_ids).count() assert len(offer_ids) == count_offers
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_offer_list_page(self): offer = factories.create_offer(name="Offer A") list_page = self.get(reverse('dashboard:offer-list')) form = list_page.forms[0] form['name'] = "I do not exist" res = form.submit() self.assertTrue("No offers found" in res.text) form['name'] = "Offer A" res = form.submit() self.assertFalse("No offers found" in res.text) form['is_active'] = True res = form.submit() self.assertFalse("No offers found" in res.text) yesterday = timezone.now() - timezone.timedelta(days=1) offer.end_datetime = yesterday offer.save() form['is_active'] = True res = form.submit() self.assertTrue("No offers found" in res.text)
def test_includes_offers_with_null_start_and_end_date(self): factories.create_offer(start=None, end=None) filtered_offers = models.ConditionalOffer.active.all() self.assertEqual(1, len(filtered_offers))
def test_filters_out_suspended_offers(self): # Create offer that is available but with the wrong status factories.create_offer( status=models.ConditionalOffer.SUSPENDED) filtered_offers = models.ConditionalOffer.active.all() self.assertEqual(0, len(filtered_offers))
def test_can_jump_to_intermediate_step_for_existing_offer(self): offer = factories.create_offer() url = reverse('dashboard:offer-condition', kwargs={'pk': offer.id}) self.assertEqual(200, self.get(url).status_code)