def test_mismatched_basket_owner(self): """ Verify the view returns an HTTP 400 status if the posted basket does not belong to the requesting user. """ basket = factories.BasketFactory() self.assert_basket_retrieval_error(basket.id) basket = factories.BasketFactory(owner=self.create_user()) self.assert_basket_retrieval_error(basket.id)
def test_transfers_vouchers_to_new_basket(self): baskets = [factories.BasketFactory(), factories.BasketFactory()] voucher = factories.VoucherFactory() baskets[0].vouchers.add(voucher) baskets[1].merge(baskets[0]) self.assertEqual(1, baskets[1].vouchers.all().count())
def test_moving_to_saved_basket_updates_existing(self): self.user = factories.UserFactory() product = factories.ProductFactory() basket = factories.BasketFactory(owner=self.user) basket.add_product(product) saved_basket = factories.BasketFactory(owner=self.user, status=Basket.SAVED) saved_basket.add_product(product) response = self.get(reverse('basket:summary')) formset = response.context['formset'] form = formset.forms[0] data = { formset.add_prefix('INITIAL_FORMS'): 1, formset.add_prefix('TOTAL_FORMS'): 1, formset.add_prefix('MIN_FORMS'): 0, formset.add_prefix('MAX_NUM_FORMS'): 1, form.add_prefix('id'): form.instance.pk, form.add_prefix('quantity'): form.initial['quantity'], form.add_prefix('save_for_later'): True, } response = self.post(reverse('basket:summary'), params=data) self.assertRedirects(response, reverse('basket:summary')) self.assertFalse(Basket.open.get(pk=basket.pk).lines.exists()) self.assertEqual(Basket.saved.get(pk=saved_basket.pk).lines.get( product=product).quantity, 2)
def setUp(self): super(AddSiteToBasketsBasketsCommandTests, self).setUp() self.site = Site.objects.create(domain='acme.fake') site = Site.objects.create(domain='test.fake') self.associated_baskets = [ factories.BasketFactory(site=site) for __ in range(0, 2) ] self.unassociated_baskets = [ factories.BasketFactory() for __ in range(0, 3) ]
def test_track_completed_discounted_order_with_offer(self): """ An event including a discount but no coupon should be sent to Segment""" with mock.patch( 'ecommerce.extensions.checkout.signals.track_segment_event' ) as mock_track: # Orders may be discounted by a fixed value offer_discount = 5 product = ProductFactory(categories=[], stockrecords__price_currency='USD') _range = factories.RangeFactory(products=[product], ) site_offer = factories.ConditionalOfferFactory( offer_type=ConditionalOffer.SITE, benefit=factories.BenefitFactory(range=_range, value=offer_discount), condition=factories.ConditionFactory(type=Condition.COVERAGE, value=1, range=_range)) basket = factories.BasketFactory(owner=self.user, site=self.site) basket.add_product(product) Applicator().apply_offers(basket, [site_offer]) order = factories.create_order(basket=basket, user=self.user) track_completed_order(None, order) properties = self._generate_event_properties(order) mock_track.assert_called_once_with(order.site, order.user, 'Order Completed', properties, traits=properties)
def test_get_applicable_lines(self): """ Assert that basket lines matching the range's discovery query are selected. """ basket = factories.BasketFactory(site=self.site, owner=self.user) entitlement_product = self.create_entitlement_product() course, seat = self.create_course_and_seat() no_certificate_product = factories.ProductFactory( stockrecords__price_currency='USD') basket.add_product(entitlement_product) basket.add_product(seat) applicable_lines = [(line.product.stockrecords.first().price_excl_tax, line) for line in basket.all_lines()] basket.add_product(no_certificate_product) self.mock_access_token_response() # Verify that the method raises an exception when it fails to reach the Discovery Service with self.assertRaises(Exception): self.benefit.get_applicable_lines(self.offer, basket) self.mock_catalog_query_contains_endpoint( course_run_ids=[], course_uuids=[entitlement_product.attr.UUID, course.id], absent_ids=[], query=self.benefit.range.catalog_query, discovery_api_url=self.site_configuration.discovery_api_url) self.assertEqual(self.benefit.get_applicable_lines(self.offer, basket), applicable_lines) # Verify that the API return value is cached httpretty.disable() self.assertEqual(self.benefit.get_applicable_lines(self.offer, basket), applicable_lines)
def test_is_single_use_range_condition_satisfied(self): """ Verify that the condition for a single use coupon is only satisfied by single-product baskets. """ valid_user_email = 'valid@{domain}'.format(domain=self.valid_sub_domain) basket = factories.BasketFactory(site=self.site, owner=factories.UserFactory(email=valid_user_email)) product1 = self.create_entitlement_product() product2 = self.create_entitlement_product() _range = factories.RangeFactory() _range.course_seat_types = ','.join(Range.ALLOWED_SEAT_TYPES) _range.catalog_query = 'uuid:*' benefit = factories.BenefitFactory(range=_range) offer = factories.ConditionalOfferFactory(benefit=benefit) offer.set_voucher( factories.VoucherFactory(usage='Single-use') ) self.mock_access_token_response() self.mock_catalog_query_contains_endpoint( course_run_ids=[], course_uuids=[product1.attr.UUID, product2.attr.UUID], absent_ids=[], query=benefit.range.catalog_query, discovery_api_url=self.site_configuration.discovery_api_url ) # Verify that each product individually satisfies the condition basket.add_product(product1) self.assertTrue(offer.is_condition_satisfied(basket)) basket.flush() basket.add_product(product2) self.assertTrue(offer.is_condition_satisfied(basket)) # Verify that the offer cannot be applied to a multi-product basket basket.add_product(product1) self.assertFalse(offer.is_condition_satisfied(basket))
def test_deactivate_user(self): """ Verify an SDN failure is logged. """ response = {'description': 'Bad dude.'} product1 = factories.ProductFactory( stockrecords__partner__short_code='first') product2 = factories.ProductFactory( stockrecords__partner__short_code='second') basket = factories.BasketFactory(owner=self.user, site=self.site_configuration.site) basket.add(product1) basket.add(product2) self.assertEqual(SDNCheckFailure.objects.count(), 0) with mock.patch.object(User, 'deactivate_account') as deactivate_account: deactivate_account.return_value = True self.sdn_validator.deactivate_user(basket, self.name, self.city, self.country, response) self.assertEqual(SDNCheckFailure.objects.count(), 1) sdn_object = SDNCheckFailure.objects.first() self.assertEqual(sdn_object.full_name, self.name) self.assertEqual(sdn_object.city, self.city) self.assertEqual(sdn_object.country, self.country) self.assertEqual(sdn_object.site, self.site_configuration.site) self.assertEqual(sdn_object.sdn_check_response, response) self.assertEqual(sdn_object.products.count(), basket.lines.count()) self.assertIn(product1, sdn_object.products.all()) self.assertIn(product2, sdn_object.products.all())
def create_order_with_billing_address(self): """ Creates an order object with a bit of extra information for HubSpot unit tests""" enrollment_code = Product.objects.get( product_class__name=ENROLLMENT_CODE_PRODUCT_CLASS_NAME) user = UserFactory() basket = factories.BasketFactory(owner=user, site=self.site) basket.add_product(enrollment_code, self.QUANTITY) # add organization and purchaser attributes manually to the basket for testing purposes basket_data = { 'organization': 'Dummy Business Client', PURCHASER_BEHALF_ATTRIBUTE: 'True' } basket_add_organization_attribute(basket, basket_data) # add some additional data the billing address to exercise some of the code paths in the unit we are testing billing_address = factories.BillingAddressFactory() billing_address.line2 = 'Suite 321' billing_address.line4 = "City" billing_address.state = "State" billing_address.country.name = "United States of America" # create new order adding in the additional billing address info return create_order(number=2, basket=basket, user=user, billing_address=billing_address)
def setUp(self): super(InvoiceManagementCommandTests, self).setUp() self.product = factories.ProductFactory(product_class=ProductClass.objects.get(name='Coupon')) client = Client.objects.create(username='******') self.basket = factories.BasketFactory(owner=client) self.basket.add_product(self.product, 1) self.order = factories.create_order(basket=self.basket)
def test_track_completed_discounted_order_with_voucher_with_offer(self): with mock.patch( 'ecommerce.extensions.checkout.signals.track_segment_event' ) as mock_track: # Orders may be discounted by a fixed value fixed_benefit = 5.00 offer_discount = 6 product = ProductFactory(categories=[], stockrecords__price_currency='USD') _range = factories.RangeFactory(products=[product], ) voucher, product = prepare_voucher(_range=_range, benefit_value=fixed_benefit, benefit_type=Benefit.FIXED) factories.ConditionalOfferFactory( offer_type=ConditionalOffer.SITE, benefit=factories.BenefitFactory(range=_range, value=offer_discount), condition=factories.ConditionFactory(type=Condition.COVERAGE, value=1, range=_range)) basket = factories.BasketFactory(owner=self.user, site=self.site) basket.add_product(product) basket.vouchers.add(voucher) Applicator().apply(basket, user=basket.owner, request=self.request) order = factories.create_order(basket=basket, user=self.user) track_completed_order(None, order) properties = self._generate_event_properties(order, voucher) mock_track.assert_called_once_with(order.site, order.user, 'Order Completed', properties, traits=properties)
def setUp(self): super(CouponFulfillmentModuleTest, self).setUp() coupon = self.create_coupon() user = factories.UserFactory() basket = factories.BasketFactory(owner=user, site=self.site) basket.add_product(coupon, 1) self.order = create_order(number=1, basket=basket, user=user)
def test_track_completed_discounted_order_with_voucher(self): """ An event including coupon information should be sent to Segment""" with mock.patch( 'ecommerce.extensions.checkout.signals.track_segment_event' ) as mock_track: # Orders may be discounted by percent percent_benefit = 66 product = ProductFactory(categories=[], stockrecords__price_currency='USD') _range = factories.RangeFactory(products=[product], ) voucher, product = prepare_voucher(_range=_range, benefit_value=percent_benefit) basket = factories.BasketFactory(owner=self.user, site=self.site) basket.add_product(product) basket.vouchers.add(voucher) Applicator().apply(basket, user=basket.owner, request=self.request) order = factories.create_order(basket=basket, user=self.user) track_completed_order(None, order) properties = self._generate_event_properties(order, voucher) mock_track.assert_called_once_with(order.site, order.user, 'Order Completed', properties, traits=properties)
def test_is_range_condition_satisfied(self): """ Verify that a basket satisfies a condition only when all of its products are in its range's catalog queryset. """ valid_user_email = 'valid@{domain}'.format( domain=self.valid_sub_domain) basket = factories.BasketFactory( site=self.site, owner=UserFactory(email=valid_user_email)) product = self.create_entitlement_product() another_product = self.create_entitlement_product() _range = factories.RangeFactory() _range.course_seat_types = ','.join(Range.ALLOWED_SEAT_TYPES) _range.catalog_query = 'uuid:{course_uuid}'.format( course_uuid=product.attr.UUID) benefit = factories.BenefitFactory(range=_range) offer = factories.ConditionalOfferFactory(benefit=benefit) self.mock_access_token_response() self.mock_catalog_query_contains_endpoint( course_run_ids=[], course_uuids=[product.attr.UUID], absent_ids=[another_product.attr.UUID], query=benefit.range.catalog_query, discovery_api_url=self.site_configuration.discovery_api_url) basket.add_product(product) self.assertTrue(offer.is_condition_satisfied(basket)) basket.add_product(another_product) self.assertFalse(offer.is_condition_satisfied(basket)) # Verify that API return values are cached httpretty.disable() self.assertFalse(offer.is_condition_satisfied(basket))
def setUp(self): super(InvoiceCommandTests, self).setUp() coupon_pc = factories.ProductClassFactory(name='Coupon') self.product = factories.ProductFactory(product_class=coupon_pc) self.basket = factories.BasketFactory() self.basket.add_product(self.product, 1) self.order = factories.create_order(basket=self.basket) self.invoice = Invoice.objects.create(order=self.order)
def apply_voucher(self, user, site, voucher): """ Apply the voucher to a basket. """ basket = factories.BasketFactory(owner=user, site=site) product = voucher.offers.first().benefit.range.all_products()[0] basket.add_product(product) basket.vouchers.add(voucher) Applicator().apply(basket, self.user) return basket
def setUp(self): super(JournalFulfillmentModuleTest, self).setUp() user = self.create_user(is_staff=True) self.client.login(username=user.username, password=self.password) basket = factories.BasketFactory(owner=user, site=self.site) basket.add_product(self.create_product(self.client), 1) self.order = create_order(number=1, basket=basket, user=user) self.lines = self.order.lines.all()
def test_create_refund_for_duplicate_orders_only(self, commit): """ Test that refund is generated for manual enrollment orders only if having some duplicate enrollments. """ orders = self.create_manual_order() filename = 'orders_file.txt' self.create_orders_file(orders, filename) # create duplicate order having course_entitlement product order_with_duplicate = orders[0] order_without_duplicate = orders[1] course_uuid = FAKER.uuid4() # pylint: disable=no-member order = Order.objects.get(number=order_with_duplicate['detail']) course_entitlement = create_or_update_course_entitlement( 'verified', 100, order.partner, course_uuid, 'Course Entitlement' ) basket = factories.BasketFactory(owner=order.user, site=order.site) basket.add_product(course_entitlement, 1) create_order(basket=basket, user=order.user) self.mock_access_token_response() self.mock_course_run_detail_endpoint( self.course, discovery_api_url=order.site.siteconfiguration.discovery_api_url, course_run_info={ 'course_uuid': course_uuid } ) self.assertFalse(Refund.objects.exists()) with LogCapture(LOGGER_NAME) as log_capture: params = ['create_refund_for_orders', '--order-numbers-file={}'.format(filename), '--refund-duplicate-only', '--sleep-time=0.5'] if not commit: params.append('--no-commit') call_command(*params) log_capture.check_present( (LOGGER_NAME, 'INFO', 'Sleeping for 0.5 second/seconds'), ) log_capture.check_present( ( LOGGER_NAME, 'ERROR', '[Ecommerce Order Refund]: Completed refund generation. 0 of 2 failed and 1 skipped.\n' 'Failed orders: \n' 'Skipped orders: {}\n'.format(order_without_duplicate['detail']), ), ) if commit: self.assertEqual(Refund.objects.count(), 1) refund = Refund.objects.get(order=order) self.assert_refund_matches_order(refund, order) order = Order.objects.get(number=order_without_duplicate['detail']) self.assertFalse(order.refunds.exists()) else: self.assertEqual(Refund.objects.count(), 0)
def create_basket_with_product(self): """ creates a basket for testing. """ product = self.course.create_or_update_seat('verified', True, 100) basket = factories.BasketFactory(owner=self.user, site=self.site) basket.add_product(product, 1) basket.freeze() return basket
def setUp(self): super(EnrollmentCodeFulfillmentModuleTests, self).setUp() course = CourseFactory(partner=self.partner) course.create_or_update_seat('verified', True, 50, create_enrollment_code=True) enrollment_code = Product.objects.get(product_class__name=ENROLLMENT_CODE_PRODUCT_CLASS_NAME) user = UserFactory() basket = factories.BasketFactory(owner=user, site=self.site) basket.add_product(enrollment_code, self.QUANTITY) self.order = create_order(number=1, basket=basket, user=user)
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)
def test_for_empty_price_excl_tax(self): basket = factories.BasketFactory() product_class = factories.ProductClassFactory(track_stock=False) product = factories.ProductFactory(product_class=product_class, stockrecords=[]) factories.StockRecordFactory.build(price_excl_tax=None, product=product) data = {'quantity': 1} form = forms.AddToBasketForm(basket=basket, product=product, data=data) self.assertFalse(form.is_valid()) self.assertEqual(form.errors['__all__'][0], 'unavailable')
def test_overflow_shipping_cost_scenario_handled_correctly(self): basket = factories.BasketFactory() product_attribute_value = factories.ProductAttributeValueFactory( value_float=2.5) basket.add_product(product_attribute_value.product) self.standard.bands.create(upper_limit=1, charge=D('1.00')) self.standard.bands.create(upper_limit=2, charge=D('2.00')) charge = self.standard.calculate(basket) self.assertEqual(D('1.00') + D('2.00'), charge.excl_tax)
def setUp(self): super(EnterpriseDiscountMixinTests, self).setUp() course = CourseFactory(id='edX/DemoX/Demo_Course', name='Demo Course', partner=self.partner) user = UserFactory() basket = factories.BasketFactory(owner=user, site=self.site) basket.add_product( course.create_or_update_seat('test-certificate-type', False, 100, None), 1) self.order = create_order(number=1, basket=basket, user=user)
def test_track_completed_coupon_order(self): """ Make sure we do not send GA events for Coupon orders """ with mock.patch('ecommerce.extensions.checkout.signals.track_segment_event') as mock_track: coupon = self.create_coupon() basket = factories.BasketFactory(owner=self.user, site=self.site) basket.add_product(coupon) order = factories.create_order(basket=basket, user=self.user) track_completed_order(None, order) assert not mock_track.called
def test_simple_shipping_cost_scenario_handled_correctly(self): basket = factories.BasketFactory() product_attribute_value = factories.ProductAttributeValueFactory( value_float=2.5) basket.add_product(product_attribute_value.product) expected_charge = D('3.00') self.standard.bands.create(upper_limit=3, charge=expected_charge) charge = self.standard.calculate(basket) self.assertEqual(expected_charge, charge.excl_tax)
def test_cannot_add_a_product_without_price(self): basket = factories.BasketFactory() product = factories.create_product(price=None) data = {'quantity': 1} form = forms.AddToBasketForm(basket=basket, product=product, data=data) self.assertFalse(form.is_valid()) self.assertEqual( form.errors['__all__'][0], 'This product cannot be added to the basket because a price ' 'could not be determined for it.', )
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)
def prepare_basket(self, price, bundle=False): """ Helper function that creates a basket and adds a product with set price to it. """ basket = factories.BasketFactory(owner=self.user, site=self.site) self.course_run.create_or_update_seat('verified', True, Decimal(price)) basket.add_product(self.course_run.seat_products[0]) self.assertEqual(basket.lines.count(), 1) self.assertEqual(basket.total_incl_tax, Decimal(price)) if bundle: BasketAttribute.objects.update_or_create( basket=basket, attribute_type=BasketAttributeType.objects.get(name='bundle_identifier'), value_text=self.bundle_attribute_value )
def setUp(self): super(DonationsFromCheckoutTestFulfillmentModuleTest, self).setUp() donation_class = ProductClass.objects.get( name=DONATIONS_FROM_CHECKOUT_TESTS_PRODUCT_TYPE_NAME, track_stock=False) donation = factories.create_product(product_class=donation_class, title='Test product') user = factories.UserFactory() basket = factories.BasketFactory(owner=user, site=self.site) factories.create_stockrecord(donation, num_in_stock=2, price_excl_tax=10) basket.add_product(donation, 1) self.order = create_order(number=1, basket=basket, user=user)