def test_flush_with_product_is_not_tracked_for_temporary_basket_calculation( self): """ Verify the method does NOT fire 'Product Removed' Segment for temporary basket calculation """ basket = self._create_basket_with_product() RequestCache.set(TEMPORARY_BASKET_CACHE_KEY, True) with mock.patch.object(Client, 'track') as mock_track: basket.flush() mock_track.assert_not_called()
def test_get_cached_response_force_django_cache_miss(self, mock_cache_get): RequestCache.set(SHOULD_FORCE_CACHE_MISS_KEY, True) mock_cache_get.return_value = EXPECTED_VALUE cached_response = TieredCache.get_cached_response(TEST_KEY) self.assertTrue(cached_response.is_miss) cached_response = RequestCache.get_cached_response(TEST_KEY) self.assertTrue( cached_response.is_miss, 'Forced Django cache miss should not cache value in request cache.' )
def test_delete(self): RequestCache.set(TEST_KEY, EXPECTED_VALUE) RequestCache.set(TEST_KEY_2, EXPECTED_VALUE) RequestCache.delete(TEST_KEY) cached_response = RequestCache.get_cached_response(TEST_KEY) self.assertTrue(cached_response.is_miss) cached_response = RequestCache.get_cached_response(TEST_KEY_2) self.assertTrue(cached_response.is_hit) self.assertEqual(cached_response.value, EXPECTED_VALUE)
def test_add_product_not_tracked_for_temporary_basket_calculation(self): """ Verify the method does NOT fire Product Added analytic event when a product is added to the basket """ course = CourseFactory() basket = create_basket(empty=True) seat = course.create_or_update_seat('verified', True, 100, self.partner) RequestCache.set(TEMPORARY_BASKET_CACHE_KEY, True) with mock.patch( 'ecommerce.extensions.basket.models.track_segment_event' ) as mock_track: basket.add_product(seat) properties = translate_basket_line_for_segment( basket.lines.first()) properties['cart_id'] = basket.id mock_track.assert_not_called()
def get(self, request): # pylint: disable=too-many-statements """ Calculate basket totals given a list of sku's Create a temporary basket add the sku's and apply an optional voucher code. Then calculate the total price less discounts. If a voucher code is not provided apply a voucher in the Enterprise entitlements available to the user. Query Params: sku (string): A list of sku(s) to calculate code (string): Optional voucher code to apply to the basket. username (string): Optional username of a user for which to calculate the basket. Returns: JSON: { 'total_incl_tax_excl_discounts': basket.total_incl_tax_excl_discounts, 'total_incl_tax': basket.total_incl_tax, 'currency': basket.currency } """ RequestCache.set(TEMPORARY_BASKET_CACHE_KEY, True) # TODO: LEARNER 5463 partner = get_partner_for_site(request) skus = request.GET.getlist('sku') if not skus: return HttpResponseBadRequest(_('No SKUs provided.')) skus.sort() code = request.GET.get('code', None) try: voucher = Voucher.objects.get(code=code) if code else None except Voucher.DoesNotExist: voucher = None products = Product.objects.filter(stockrecords__partner=partner, stockrecords__partner_sku__in=skus) if not products: return HttpResponseBadRequest( _('Products with SKU(s) [{skus}] do not exist.').format( skus=', '.join(skus))) # If there is only one product apply an Enterprise entitlement voucher if not voucher and len(products) == 1: voucher = get_entitlement_voucher(request, products[0]) basket_owner = request.user requested_username = request.GET.get('username', default='') is_anonymous = request.GET.get('is_anonymous', 'false').lower() == 'true' use_default_basket = is_anonymous # validate query parameters if requested_username and is_anonymous: return HttpResponseBadRequest( _('Provide username or is_anonymous query param, but not both') ) elif not requested_username and not is_anonymous: logger.warning( "Request to Basket Calculate must supply either username or is_anonymous query" " param. Requesting user=%s. Future versions of this API will treat this " "WARNING as an ERROR and raise an exception.", basket_owner.username) requested_username = request.user.username # If a username is passed in, validate that the user has staff access or is the same user. if requested_username: if basket_owner.username.lower() == requested_username.lower(): pass elif basket_owner.is_staff: try: basket_owner = User.objects.get( username=requested_username) except User.DoesNotExist: # This case represents a user who is logged in to marketing, but # doesn't yet have an account in ecommerce. These users have # never purchased before. use_default_basket = True else: return HttpResponseForbidden('Unauthorized user credentials') if basket_owner.username == self.MARKETING_USER and not use_default_basket: # For legacy requests that predate is_anonymous parameter, we will calculate # an anonymous basket if the calculated user is the marketing user. # TODO: LEARNER-5057: Remove this special case for the marketing user # once logs show no more requests with no parameters (see above). use_default_basket = True if use_default_basket: basket_owner = None cache_key = None if use_default_basket: # For an anonymous user we can directly get the cached price, because # there can't be any enrollments or entitlements. cache_key = get_cache_key(site_comain=request.site, resource_name='calculate', skus=skus) cached_response = TieredCache.get_cached_response(cache_key) if cached_response.is_hit: return Response(cached_response.value) if waffle.flag_is_active( request, "disable_calculate_temporary_basket_atomic_transaction"): response = self._calculate_temporary_basket( basket_owner, request, products, voucher, skus, code) else: response = self._calculate_temporary_basket_atomic( basket_owner, request, products, voucher, skus, code) if response and use_default_basket: TieredCache.set_all_tiers( cache_key, response, settings.ANONYMOUS_BASKET_CALCULATE_CACHE_TIMEOUT) return Response(response)
def test_get_cached_response_request_cache_hit(self): RequestCache.set(TEST_KEY, EXPECTED_VALUE) cached_response = TieredCache.get_cached_response(TEST_KEY) self.assertTrue(cached_response.is_hit) self.assertEqual(cached_response.value, EXPECTED_VALUE)
def test_clear(self): RequestCache.set(TEST_KEY, EXPECTED_VALUE) RequestCache.clear() cached_response = RequestCache.get_cached_response(TEST_KEY) self.assertTrue(cached_response.is_miss)
def test_get_cached_response_hit_with_cached_none(self): RequestCache.set(TEST_KEY, None) cached_response = RequestCache.get_cached_response(TEST_KEY) self.assertFalse(cached_response.is_miss) self.assertEqual(cached_response.value, None)
def test_get_cached_response_hit(self): RequestCache.set(TEST_KEY, EXPECTED_VALUE) cached_response = RequestCache.get_cached_response(TEST_KEY) self.assertFalse(cached_response.is_miss) self.assertEqual(cached_response.value, EXPECTED_VALUE)
def _dirty_request_cache(): """ Dirties the request cache to ensure it is cleared later. """ RequestCache.set(TEST_KEY, EXPECTED_VALUE)