def test_prepare_basket_with_multiple_products(self): """ Verify a basket is returned and only contains a single product. """ product1 = ProductFactory(stockrecords__partner__short_code='test1') product2 = ProductFactory(stockrecords__partner__short_code='test2') basket = prepare_basket(self.request, product1) basket = prepare_basket(self.request, product2) self.assertIsNotNone(basket) self.assertEqual(basket.status, Basket.OPEN) self.assertEqual(basket.lines.count(), 1) self.assertEqual(basket.lines.first().product, product2) self.assertEqual(basket.product_quantity(product2), 1)
def test_course_entitlement_product(self): """Test if a course entitlement product is properly created.""" product_class, _ = ProductClass.objects.get_or_create( name=COURSE_ENTITLEMENT_PRODUCT_CLASS_NAME) product = ProductFactory(product_class=product_class) product.attr.course_key = 'foo-bar' product.attr.certificate_type = 'verified' product.attr.save() product.refresh_from_db() self.assertEqual(product.attr.course_key, 'foo-bar') self.assertEqual(product.attr.certificate_type, 'verified')
def test_is_duplicate_seat_attempt__seats(self): """ Verify we get a correct response for duplicate seat check (seats) """ product_type_seat, _ = ProductClass.objects.get_or_create(name='Seat') product1 = ProductFactory(stockrecords__partner__short_code='test1', product_class=product_type_seat) product2 = ProductFactory(stockrecords__partner__short_code='test2', product_class=product_type_seat) seat_basket = prepare_basket(self.request, [product1]) result_product1 = is_duplicate_seat_attempt(seat_basket, product1) result_product2 = is_duplicate_seat_attempt(seat_basket, product2) self.assertTrue(result_product1) self.assertFalse(result_product2)
def setUp(self): # Timestamp in the middle of the time window time_delta = (DEFAULT_START_DELTA_TIME + DEFAULT_END_DELTA_TIME) / 2 self.timestamp = datetime.datetime.now(pytz.utc) - datetime.timedelta(minutes=time_delta) self.payevent, __ = PaymentEventType.objects.get_or_create(name=PaymentEventTypeName.PAID) self.refundevent, __ = PaymentEventType.objects.get_or_create(name=PaymentEventTypeName.REFUNDED) self.seat_product_class, __ = ProductClass.objects.get_or_create(name=SEAT_PRODUCT_CLASS_NAME) self.order = OrderFactory(total_incl_tax=90, date_placed=self.timestamp) self.product = ProductFactory(product_class=self.seat_product_class, categories=None) self.line = OrderLineFactory(order=self.order, product=self.product, partner_sku='test_sku') self.line.save() self.product.save() self.order.save()
def test_wishlists_containing_product(self): p1 = ProductFactory() p2 = ProductFactory() user = UserFactory() wishlist1 = WishListFactory(owner=user) WishListFactory(owner=user) wishlist1.add(p1) containing_one = wishlists_containing_product(Wishlist.objects.all(), p1) self.assertEqual(len(containing_one), 1) self.assertEqual(containing_one[0], wishlist1) containing_none = wishlists_containing_product(Wishlist.objects.all(), p2) self.assertEqual(len(containing_none), 0)
def test_course_entitlement_product(self): """Test if a course entitlement product is properly created.""" product_class, _ = ProductClass.objects.get_or_create( name=COURSE_ENTITLEMENT_PRODUCT_CLASS_NAME) product = ProductFactory(product_class=product_class) product.attr.UUID = '8724c585-acb2-42ab-986e-bc0847ef122c' product.attr.certificate_type = 'verified' product.attr.id_verification_required = False product.attr.save() product.refresh_from_db() self.assertEqual(product.attr.UUID, '8724c585-acb2-42ab-986e-bc0847ef122c') self.assertEqual(product.attr.certificate_type, 'verified') self.assertEqual(product.attr.id_verification_required, False)
def test_prepare_basket_affiliate_cookie_lifecycle(self): """ Verify a basket is returned and referral captured. """ product = ProductFactory() affiliate_id = 'test_affiliate' self.request.COOKIES['affiliate_id'] = affiliate_id basket = prepare_basket(self.request, product) # test affiliate id from cookie saved in referral referral = Referral.objects.get(basket_id=basket.id) self.assertEqual(referral.affiliate_id, affiliate_id) # update cookie new_affiliate_id = 'new_affiliate' self.request.COOKIES['affiliate_id'] = new_affiliate_id basket = prepare_basket(self.request, product) # test new affiliate id saved referral = Referral.objects.get(basket_id=basket.id) self.assertEqual(referral.affiliate_id, new_affiliate_id) # expire cookie del self.request.COOKIES['affiliate_id'] basket = prepare_basket(self.request, product) # test referral record is deleted when no cookie set with self.assertRaises(Referral.DoesNotExist): Referral.objects.get(basket_id=basket.id)
def test_non_free_basket_order(self, __): """ Verify an error is raised for non-free basket. """ basket = create_basket(empty=True) basket.add_product(ProductFactory(stockrecords__price_excl_tax=10)) with self.assertRaises(BasketNotFreeError): EdxOrderPlacementMixin().place_free_order(basket)
def test_description(self): basket = BasketFactory() product = ProductFactory(title="A product") basket.add_product(product) line = basket.lines.first() self.assertEqual(line.description, "A product")
def test_prepare_basket_with_bundle_voucher(self): """ Test prepare_basket clears vouchers for a bundle """ product = ProductFactory(stockrecords__price_excl_tax=100) new_range = RangeFactory(products=[ product, ]) voucher, __ = prepare_voucher(_range=new_range, benefit_value=10) request = self.request basket = prepare_basket(request, [product], voucher) self.assertTrue(basket.vouchers.all()) request.GET = {'bundle': TEST_BUNDLE_ID} program_data = { 'marketing_slug': 'program-slug', 'title': 'program title', 'type_attrs': { 'slug': 'micromasters' } } with mock.patch('ecommerce.extensions.basket.utils.get_program', return_value=program_data): basket = prepare_basket(request, [product]) self.assertFalse(basket.vouchers.all())
def test_prepare_basket_applies_valid_voucher_argument(self): """ Tests that prepare_basket applies a valid voucher passed as an an argument, even when there is also a valid voucher already on the basket. """ product = ProductFactory(stockrecords__partner__short_code='test1', stockrecords__price_excl_tax=100) new_range = RangeFactory(products=[product]) new_voucher, __ = prepare_voucher(code='xyz', _range=new_range, benefit_value=10) existing_voucher, __ = prepare_voucher(code='test', _range=new_range, benefit_value=50) basket = BasketFactory(owner=self.request.user, site=self.request.site) basket.vouchers.add(existing_voucher) self.assertEqual(basket.vouchers.count(), 1) basket = prepare_basket(self.request, [product], new_voucher) self.assertIsNotNone(basket) self.assertEqual(basket.vouchers.count(), 1) self.assertEqual(basket.vouchers.first().code, 'XYZ') self.assertEqual(basket.total_discount, 10.00)
def test_success(self): product_price = 100 percentage_discount = 10 product = ProductFactory(stockrecords__price_excl_tax=product_price) voucher, product = prepare_voucher( _range=RangeFactory(products=[product]), benefit_value=percentage_discount) self.request.user = UserFactory() basket = prepare_basket(self.request, [product], voucher) ppr = PaymentProcessorResponse.objects.create(basket=basket, transaction_id='abc', processor_name='paypal') with mock.patch.object(Paypal, 'issue_credit') as mock_issue_credit: mock_issue_credit.return_value = None assert refund_basket_transactions(self.site, [basket.id]) == ( 1, 0, ) total = product_price * (100 - percentage_discount) / 100. mock_issue_credit.assert_called_once_with(basket.order_number, basket, ppr.transaction_id, total, basket.currency)
def test_prepare_basket_with_enterprise_catalog(self): """ Test `prepare_basket` with enterprise catalog. """ product = ProductFactory() request = self.request expected_enterprise_catalog_uuid = str(uuid4()) request.GET = {'catalog': expected_enterprise_catalog_uuid} basket = prepare_basket(request, [product]) # Verify that the enterprise catalog attribute exists for the basket # when basket is prepared with the value of provide catalog UUID enterprise_catalog_uuid = BasketAttribute.objects.get( basket=basket, attribute_type__name=ENTERPRISE_CATALOG_ATTRIBUTE_TYPE).value_text assert expected_enterprise_catalog_uuid == enterprise_catalog_uuid # Now verify that `prepare_basket` method removes the enterprise # catalog attribute if there is no `catalog` query parameter in url request.GET = {} basket = prepare_basket(request, [product]) # Verify that enterprise catalog attribute does not exists for a basket # when basket is prepared with the value of provided catalog UUID with self.assertRaises(BasketAttribute.DoesNotExist): BasketAttribute.objects.get( basket=basket, attribute_type__name=ENTERPRISE_CATALOG_ATTRIBUTE_TYPE)
def test_attribution_atomic_transaction(self): """ Verify that an IntegrityError raised while creating a referral does not prevent a basket from being created. """ self._setup_request_cookie() product = ProductFactory() existing_basket = Basket.get_basket(self.request.user, self.request.site) existing_referral = Referral(basket=existing_basket, site=self.request.site) # Let's save an existing referral object to force the duplication happen in database existing_referral.save() with transaction.atomic(): with mock.patch( 'ecommerce.extensions.basket.utils._referral_from_basket_site' ) as mock_get_referral: # Mock to return a duplicated referral object, so when saved, a DB integrity error is raised # Mocking with side_effect to raise IntegrityError will not roll back the DB transaction # We actually would handle the exception in the attribute_cookie_data method. # Only causing the true database conflict like what we are doing here, would cause the roll back mock_get_referral.return_value = Referral( basket=existing_basket, site=self.request.site) basket = prepare_basket(self.request, [product]) referral = Referral.objects.filter(basket=basket) self.assertEqual(len(referral), 1) self.assertIsNotNone(basket) self.assertTrue(basket.id > 0) self.assertEqual(basket.status, Basket.OPEN) self.assertEqual(basket.lines.count(), 1) self.assertEqual(basket.lines.first().product, product)
def test_prepare_basket_calls_attribution_method(self): """ Verify a basket is returned and referral method called. """ with mock.patch( 'ecommerce.extensions.basket.utils.attribute_cookie_data' ) as mock_attr_method: product = ProductFactory() basket = prepare_basket(self.request, [product]) mock_attr_method.assert_called_with(basket, self.request)
def test_is_duplicate_seat_attempt__enrollment_code(self): """ Verify we get a correct response for duplicate seat check (false for Enrollment code)""" enrollment_class = ProductClass.objects.create(name='Enrollment Code') enrollment_product = ProductFactory(stockrecords__partner__short_code='test3', product_class=enrollment_class) basket_with_enrollment_code = prepare_basket(self.request, [enrollment_product]) result_product3 = is_duplicate_seat_attempt(basket_with_enrollment_code, enrollment_product) self.assertFalse(result_product3)
def test_place_free_order(self, __): """ Verify an order is placed and the basket is submitted. """ basket = create_basket(empty=True) basket.add_product(ProductFactory(stockrecords__price_excl_tax=0)) order = EdxOrderPlacementMixin().place_free_order(basket) self.assertIsNotNone(order) self.assertEqual(basket.status, Basket.SUBMITTED)
def test_prepare_basket_raises_exception_for_purchased_product(self): """ Test prepare_basket raises AlreadyPlacedOrderException if the product is already purchased by user """ product = ProductFactory() with mock.patch.object(UserAlreadyPlacedOrder, 'user_already_placed_order', return_value=True): with self.assertRaises(AlreadyPlacedOrderException): prepare_basket(self.request, [product])
def test_prepare_basket_with_duplicate_seat(self): """ Verify a basket fixes the case where flush doesn't work and we attempt adding duplicate seat. """ with mock.patch('ecommerce.extensions.basket.utils.Basket.flush'): product_type_seat = ProductClass.objects.create(name='Seat') product1 = ProductFactory(stockrecords__partner__short_code='test1', product_class=product_type_seat) prepare_basket(self.request, [product1]) basket = prepare_basket(self.request, [product1]) # try to add a duplicate seat self.assertEqual(basket.product_quantity(product1), 1)
def test_available_with_offer(self): basket = BasketFactory() product1 = ProductFactory() product2 = ProductFactory() basket.add_product(product1, quantity=1) basket.add_product(product2, quantity=10) benefit = models.Benefit( type=models.Benefit.PERCENTAGE, value=10, max_affected_items=5, ) benefit.save() offer1 = ConditionalOfferFactory(name='offer1', benefit=benefit) lines = basket.all_lines() assert lines[0].consumer.available(offer1) == 1 assert lines[1].consumer.available(offer1) == 5
def test_coupon_product(self): """Test if a coupon product is properly created.""" coupon_product_class, _ = ProductClass.objects.get_or_create(name='coupon') coupon_product = ProductFactory( product_class=coupon_product_class, title='Test product' ) voucher = VoucherFactory(code='MYVOUCHER') voucherList = CouponVouchers.objects.create(coupon=coupon_product) voucherList.vouchers.add(voucher) coupon_product.attr.coupon_voucher = voucherList # clean() is an Oscar validation method for products self.assertIsNone(coupon_product.clean()) self.assertIsInstance(coupon_product, Product) self.assertEqual(coupon_product.title, 'Test product') self.assertEqual(coupon_product.attr.coupon_voucher.vouchers.count(), 1) self.assertEqual(coupon_product.attr.coupon_voucher.vouchers.first().code, 'MYVOUCHER')
def setUp(self): super(JournalProductUpdateSerializerTest, self).setUp() product_class = ProductClassFactory(name="Journal") self.product = ProductFactory(product_class=product_class, stockrecords=[], categories="") StockRecordFactory(partner_sku="unit02", product=self.product, partner=PartnerFactory(short_code="dummy-partner"))
def test_description_with_attributes(self): basket = BasketFactory() product = ProductFactory(title="A product") basket.add_product(product) line = basket.lines.first() BasketLineAttributeFactory( line=line, value='\u2603', option__name='with') self.assertEqual(line.description, "A product (with = '\u2603')")
def test_prepare_basket_without_voucher(self): """ Verify a basket is returned and does not contain a voucher. """ product = ProductFactory() basket = prepare_basket(self.request, [product]) self.assertIsNotNone(basket) self.assertEqual(basket.status, Basket.OPEN) self.assertEqual(basket.lines.count(), 1) self.assertEqual(basket.lines.first().product, product) self.assertFalse(basket.vouchers.all()) self.assertFalse(basket.applied_offers())
def setUp(self): super(StockRecordSerializerForUpdateTest, self).setUp() self.stock_record = StockRecordFactory( partner=PartnerFactory( short_code="dummy-partner" ), product=ProductFactory( categories="" ) )
def create_vouchers(self, partner=None, count=1): """Helper function that creates vouchers with a mocked coupon relation.""" vouchers = VoucherFactory.create_batch(count) partner = partner or self.partner coupon_vouchers = CouponVouchers.objects.create(coupon=ProductFactory( stockrecords__partner=partner)) for voucher in vouchers: voucher.offers.add(ConditionalOfferFactory()) coupon_vouchers.vouchers.add(voucher) return vouchers
def test_prepare_basket_attribute_delete(self): """ Test prepare_basket removes the bundle attribute for a basket when a user is purchasing a single course """ product = ProductFactory(categories=[], stockrecords__partner__short_code='second') request = self.request request.GET = {'bundle': TEST_BUNDLE_ID} program_data = { 'marketing_slug': 'program-slug', 'title': 'program title', 'type_attrs': { 'slug': 'micromasters' } } with mock.patch('ecommerce.extensions.basket.utils.get_program', return_value=program_data): basket = prepare_basket(request, [product]) # Verify that the bundle attribute exists for the basket when bundle is added to basket bundle_id = BasketAttribute.objects.get( basket=basket, attribute_type__name=BUNDLE).value_text self.assertEqual(bundle_id, TEST_BUNDLE_ID) # Verify that the attribute is deleted when a non-bundle product is added to the basket request.GET = {} with mock.patch( 'ecommerce.extensions.basket.models.track_segment_event' ) as mock_track: with mock.patch('ecommerce.extensions.basket.models.get_program', return_value=program_data): prepare_basket(request, [product]) properties = { 'bundle_id': TEST_BUNDLE_ID, 'marketing_slug': program_data['type_attrs']['slug'] + '/' + program_data['marketing_slug'], 'title': program_data['title'], 'total_price': basket.total_excl_tax, 'quantity': basket.lines.count(), } mock_track.assert_any_call( request.site, request.user, 'edx.bi.ecommerce.basket.bundle_removed', properties) with self.assertRaises(BasketAttribute.DoesNotExist): BasketAttribute.objects.get(basket=basket, attribute_type__name=BUNDLE) # Verify that no exception is raised when no basket attribute exists fitting the delete statement parameters prepare_basket(request, [product])
def test_coupon_product(self): """Test if a coupon product is properly created.""" coupon_product_class, _ = ProductClass.objects.get_or_create( name='coupon') coupon_product = ProductFactory(product_class=coupon_product_class, title='Test product') voucher = VoucherFactory(code='MYVOUCHER') voucherList = CouponVouchers.objects.create(coupon=coupon_product) voucherList.vouchers.add(voucher) coupon_product.attr.coupon_voucher = voucherList # clean() is an Oscar validation method for products self.assertIsNone(coupon_product.clean()) self.assertIsInstance(coupon_product, Product) self.assertEqual(coupon_product.title, 'Test product') self.assertEqual(coupon_product.attr.coupon_voucher.vouchers.count(), 1) self.assertEqual( coupon_product.attr.coupon_voucher.vouchers.first().code, 'MYVOUCHER')
def test_successful_response(self, product_title): """ Verify a successful response is returned. """ voucher = VoucherFactory() order = OrderFactory(user=self.user) product = ProductFactory(title=product_title, categories=[]) line = OrderLineFactory(order=order, product=product) order_line_vouchers = OrderLineVouchers.objects.create(line=line) order_line_vouchers.vouchers.add(voucher) response = self.client.get(reverse(self.path, args=[order.number])) self.assertEqual(response.status_code, 200) self.assertEqual(response['content-type'], 'text/csv')
def test_prepare_basket_with_bundle_voucher(self): """ Test prepare_basket clears vouchers for a bundle """ product = ProductFactory() voucher = VoucherFactory(code='FIRST') request = self.request basket = prepare_basket(request, [product], voucher) self.assertTrue(basket.vouchers.all()) request.GET = {'bundle': 'test_bundle'} basket = prepare_basket(request, [product]) self.assertFalse(basket.vouchers.all())
def test_voucher_offers_listing_product_found(self): """ Verify the endpoint returns offers data for single product range. """ self.mock_dynamic_catalog_course_runs_api() product = ProductFactory(stockrecords__price_excl_tax=100) new_range = RangeFactory(products=[ product, ]) voucher, __ = prepare_voucher(_range=new_range, benefit_value=10) request = self.prepare_offers_listing_request(voucher.code) response = self.endpointView(request) self.assertEqual(response.status_code, 200)