Exemplo n.º 1
0
    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=u'\u2603',
                                   option__name='with')
        self.assertEqual(line.description, u"A product (with = '\u2603')")
Exemplo n.º 2
0
 def setUp(self):
     self.applicator = Applicator()
     self.basket = BasketFactory()
     rng = RangeFactory(includes_all_products=True)
     self.condition = ConditionFactory(
         range=rng, type=ConditionFactory._meta.model.VALUE,
         value=D('100'), proxy_class=None)
     self.benefit = BenefitFactory(
         range=rng, type=BenefitFactory._meta.model.FIXED,
         value=D('10'))
Exemplo n.º 3
0
 def test_basket_lines_queryset_is_ordered(self):
     # This is needed to make sure a formset is not performing the query
     # again with an order_by clause (losing all calculated discounts)
     basket = BasketFactory()
     product = ProductFactory(title="A product")
     another_product = ProductFactory(title="Another product")
     basket.add_product(product)
     basket.add_product(another_product)
     queryset = basket.all_lines()
     self.assertTrue(queryset.ordered)
Exemplo n.º 4
0
 def test_is_satisfied_free_basket(self):
     """ Ensure the basket returns False if the basket total is zero. """
     offer = factories.ProgramOfferFactory(partner=self.partner,
                                           condition=self.condition)
     basket = BasketFactory(site=self.site, owner=UserFactory())
     test_product = factories.ProductFactory(
         stockrecords__price_excl_tax=0,
         stockrecords__partner__short_code='test')
     basket.add_product(test_product)
     self.assertFalse(self.condition.is_satisfied(offer, basket))
Exemplo n.º 5
0
    def test_is_satisfied_with_exception_for_programs(self, value):
        """ The method should return False if there is an exception when trying to get program details. """
        offer = factories.ProgramOfferFactory(partner=self.partner,
                                              condition=self.condition)
        basket = BasketFactory(site=self.site, owner=UserFactory())
        basket.add_product(self.test_product)

        with mock.patch('ecommerce.programs.conditions.get_program',
                        side_effect=value):
            self.assertFalse(self.condition.is_satisfied(offer, basket))
Exemplo n.º 6
0
 def test_get_basket_cache(self):
     """ Verify subsequent calls to the method utilize the middleware's memoization/caching. """
     # pylint: disable=protected-access
     self.request.user = self.create_user()
     basket = BasketFactory(owner=self.request.user, site=self.site)
     self.assertIsNone(self.request._basket_cache)
     self.middleware.get_basket(self.request)
     self.assertEqual(self.request._basket_cache, basket)
     self.assertEqual(self.middleware.get_basket(self.request),
                      self.request._basket_cache)
Exemplo n.º 7
0
    def test_is_satisfied_with_enrollments(self):
        """ The condition should be satisfied if one valid course run from each course is in either the
        basket or the user's enrolled courses and the site has enabled partial program offers. """
        offer = factories.ProgramOfferFactory(partner=self.partner,
                                              condition=self.condition)
        basket = BasketFactory(site=self.site, owner=UserFactory())
        program = self.mock_program_detail_endpoint(
            self.condition.program_uuid,
            self.site_configuration.discovery_api_url)

        # Extract one verified seat for each course
        verified_seats = []
        for course in program['courses']:
            course_run = Course.objects.get(id=course['course_runs'][0]['key'])
            for seat in course_run.seat_products:
                if seat.attr.id_verification_required:
                    verified_seats.append(seat)

        # Add verified enrollments for the first two program courses to the mock user data
        enrollments = [{
            'mode': 'verified',
            'course_details': {
                'course_id': program['courses'][0]['course_runs'][0]['key']
            }
        }, {
            'mode': 'verified',
            'course_details': {
                'course_id': program['courses'][1]['course_runs'][0]['key']
            }
        }]
        self.mock_user_data(basket.owner.username, owned_products=enrollments)

        # If the user has not added all of the remaining courses in the program to their basket,
        # the condition should not be satisfied
        basket.flush()
        for seat in verified_seats[2:len(verified_seats) - 1]:
            basket.add_product(seat)
        self.assertFalse(self.condition.is_satisfied(offer, basket))

        # When all courses in the program that the user is not already enrolled in are in their basket
        # and the site allows partial program completion, the condition should be satisfied
        basket.add_product(verified_seats[-1])
        self.assertTrue(self.condition.is_satisfied(offer, basket))

        # If the site does not allow partial program completion and the user does not have all of the program
        # courses in their basket, the condition should not be satisfied
        basket.site.siteconfiguration.enable_partial_program = False
        self.assertFalse(self.condition.is_satisfied(offer, basket))

        # Verify the user enrollments are cached
        basket.site.siteconfiguration.enable_partial_program = True
        httpretty.disable()
        with mock.patch('ecommerce.programs.conditions.get_program',
                        return_value=program):
            self.assertTrue(self.condition.is_satisfied(offer, basket))
Exemplo n.º 8
0
 def setUp(self):
     super(DynamicConditionTests, self).setUp()
     self.condition = Condition.objects.get(
         proxy_class=
         'ecommerce.extensions.offer.dynamic_conditional_offer.DynamicDiscountCondition'
     ).proxy()
     self.offer = ConditionalOffer.objects.get(
         name='dynamic_conditional_offer')
     self.basket = BasketFactory(site=self.site, owner=self.create_user())
     self.seat_product_class, __ = ProductClass.objects.get_or_create(
         name=SEAT_PRODUCT_CLASS_NAME)
Exemplo n.º 9
0
 def test_is_satisfied_wrong_enterprise(self):
     """ Ensure the condition returns false if the learner is associated with a different EnterpriseCustomer. """
     offer = factories.EnterpriseOfferFactory(partner=self.partner,
                                              condition=self.condition)
     basket = BasketFactory(site=self.site, owner=self.user)
     basket.add_product(self.course_run.seat_products[0])
     self.mock_enterprise_learner_api(
         learner_id=self.user.id,
         course_run_id=self.course_run.id,
     )
     self.assertFalse(self.condition.is_satisfied(offer, basket))
Exemplo n.º 10
0
    def _create_order(self, price, mode='verified'):
        seat = self.course.create_or_update_seat(mode, False, price, None)

        basket = BasketFactory(owner=self.user, site=self.site)
        basket.add_product(seat, 1)
        order = create_order(number=1,
                             basket=basket,
                             user=self.user,
                             site=self.site)
        order.total_excl_tax = price
        return seat, order
Exemplo n.º 11
0
    def test_is_satisfied_false_for_invalid_enterprise_catalog(self, invalid_enterprise_catalog_uuid):
        """
        Ensure the condition returns false if provided enterprise catalog UUID is invalid.
        """
        offer = factories.EnterpriseOfferFactory(partner=self.partner, condition=self.condition)

        basket = BasketFactory(site=self.site, owner=self.user)
        basket.strategy.request = self.request
        basket.strategy.request.GET = {'catalog': invalid_enterprise_catalog_uuid}
        self._check_condition_is_satisfied(offer, basket, is_satisfied=False)
        assert invalid_enterprise_catalog_uuid != offer.condition.enterprise_customer_catalog_uuid
Exemplo n.º 12
0
    def test_order_number_from_basket_id(self):
        """ Verify the method returns an order number determined using the basket's ID, and the specified partner. """
        basket = BasketFactory()
        acme = PartnerFactory(name='ACME')

        for partner in (
                self.partner,
                acme,
        ):
            self.assertEqual(
                self.generator.order_number_from_basket_id(partner, basket.id),
                '{}-{}'.format(partner.short_code.upper(), 100000 + basket.id))
Exemplo n.º 13
0
 def test_apply_voucher_on_basket_and_check_discount_with_valid_voucher(self):
     """
     Tests apply_voucher_on_basket_and_check_discount when called with valid voucher
     applies voucher and returns the correct values.
     """
     basket = BasketFactory(owner=self.request.user, site=self.request.site)
     voucher, product = prepare_voucher()
     basket.add_product(product, 1)
     applied, msg = apply_voucher_on_basket_and_check_discount(voucher, self.request, basket)
     self.assertEqual(applied, True)
     self.assertIsNotNone(basket.applied_offers())
     self.assertEqual(msg, "Coupon code '{code}' added to basket.".format(code=voucher.code))
Exemplo n.º 14
0
 def test_is_satisfied_true_for_enterprise_catalog_in_get_request(self):
     """
     Ensure that condition returns true for valid enterprise catalog uuid in GET request.
     """
     offer = factories.EnterpriseOfferFactory(partner=self.partner,
                                              condition=self.condition)
     enterprise_catalog_uuid = str(
         self.condition.enterprise_customer_catalog_uuid)
     basket = BasketFactory(site=self.site, owner=self.user)
     basket.strategy.request = self.request
     basket.strategy.request.GET = {'catalog': enterprise_catalog_uuid}
     self._check_condition_is_satisfied(offer, basket, is_satisfied=True)
Exemplo n.º 15
0
    def test_is_satisfied_with_entitlements(self):
        """
        The condition should be satisfied if, for each course in the program, their is either an entitlement sku in the
        basket or the user already has an entitlement for the course and the site has enabled partial program offers.
        """
        offer = factories.ProgramOfferFactory(partner=self.partner, condition=self.condition)
        basket = BasketFactory(site=self.site, owner=UserFactory())
        program = self.mock_program_detail_endpoint(
            self.condition.program_uuid, self.site_configuration.discovery_api_url
        )
        entitlements_response = {
            "count": 0, "num_pages": 1, "current_page": 1, "results": [
                {'mode': 'verified', 'course_uuid': '268afbfc-cc1e-415b-a5d8-c58d955bcfc3'},
                {'mode': 'verified', 'course_uuid': '268afbfc-cc1e-415b-a5d8-c58d955bcfc4'}
            ], "next": None, "start": 0, "previous": None
        }

        # Extract one verified seat for each course
        verified_entitlements = []
        course_uuids = {course['uuid'] for course in program['courses']}
        for parent_entitlement in Product.objects.filter(
                product_class__name=COURSE_ENTITLEMENT_PRODUCT_CLASS_NAME, structure=Product.PARENT
        ):
            for entitlement in Product.objects.filter(parent=parent_entitlement):
                if entitlement.attr.UUID in course_uuids and entitlement.attr.certificate_type == 'verified':
                    verified_entitlements.append(entitlement)

        self.mock_user_data(basket.owner.username, mocked_api='entitlements', owned_products=entitlements_response)
        self.mock_user_data(basket.owner.username)
        # If the user has not added all of the remaining courses in program to their basket,
        # the condition should not be satisfied
        basket.flush()
        for entitlement in verified_entitlements[2:len(verified_entitlements) - 1]:
            basket.add_product(entitlement)
        self.assertFalse(self.condition.is_satisfied(offer, basket))

        # When all courses in the program that the user is not already enrolled in are in their basket
        # and the site allows partial program completion, the condition should be satisfied
        basket.add_product(verified_entitlements[-1])
        self.assertTrue(self.condition.is_satisfied(offer, basket))

        # If the site does not allow partial program completion and the user does not have all of the program
        # courses in their basket, the condition should not be satisfied
        basket.site.siteconfiguration.enable_partial_program = False
        self.assertFalse(self.condition.is_satisfied(offer, basket))

        # Verify the user enrollments are cached
        basket.site.siteconfiguration.enable_partial_program = True
        httpretty.disable()
        with mock.patch('ecommerce.programs.conditions.get_program',
                        return_value=program):
            self.assertTrue(self.condition.is_satisfied(offer, basket))
Exemplo n.º 16
0
    def test_unsupported_product_class(self, mock_log_error, mock_update_course_enrollment):
        """ Verify Sailthru is not contacted for non-seat products. """
        coupon = self.create_coupon()
        basket = BasketFactory(owner=self.user, site=self.site)
        basket.add_product(coupon, 1)
        process_basket_addition(None, request=self.request, user=self.user, product=coupon, basket=basket)
        self.assertFalse(mock_update_course_enrollment.called)
        self.assertFalse(mock_log_error.called)

        order = create_order(number=1, basket=basket, user=self.user)
        process_checkout_complete(None, order=order, request=None)
        self.assertFalse(mock_update_course_enrollment.called)
        self.assertFalse(mock_log_error.called)
Exemplo n.º 17
0
    def test_is_satisfied_when_no_code_assignments_exists(self, num_orders, redemptions_available, mock_request):
        """
        Ensure that condition returns expected result when code has no assignments.
        """
        mock_request.return_value = self.request
        enterprise_offer = factories.EnterpriseOfferFactory()
        voucher = factories.VoucherFactory(usage=Voucher.SINGLE_USE, code='AAA', num_orders=num_orders)
        voucher.offers.add(enterprise_offer)

        basket = BasketFactory(site=self.site, owner=UserFactory(email='*****@*****.**'))
        basket.vouchers.add(voucher)

        assert self.condition.is_satisfied(enterprise_offer, basket) == redemptions_available
Exemplo n.º 18
0
 def test_apply_voucher_on_basket_and_check_discount_with_invalid_product(self):
     """
     Tests apply_voucher_on_basket_and_check_discount when called with invalid product
     does not apply voucher and returns the correct values.
     """
     basket = BasketFactory(owner=self.request.user, site=self.request.site)
     product = ProductFactory(stockrecords__partner__short_code='test1', stockrecords__price_excl_tax=0)
     voucher, __ = prepare_voucher(_range=RangeFactory(products=[product]))
     basket.add_product(product, 1)
     applied, msg = apply_voucher_on_basket_and_check_discount(voucher, self.request, basket)
     self.assertEqual(applied, False)
     self.assertEqual(basket.applied_offers(), {})
     self.assertEqual(msg, 'Basket does not qualify for coupon code {code}.'.format(code=voucher.code))
Exemplo n.º 19
0
 def test_is_satisfied_no_course_product(self):
     """ Ensure the condition returns false if the basket contains a product not associated with a course run. """
     offer = factories.EnterpriseOfferFactory(partner=self.partner,
                                              condition=self.condition)
     basket = BasketFactory(site=self.site, owner=self.user)
     basket.add_product(self.test_product)
     self.mock_enterprise_learner_api(
         learner_id=self.user.id,
         enterprise_customer_uuid=str(
             self.condition.enterprise_customer_uuid),
         course_run_id=self.course_run.id,
     )
     self.assertFalse(self.condition.is_satisfied(offer, basket))
Exemplo n.º 20
0
 def test_is_satisfied_true_for_enterprise_catalog_in_basket_attribute(
         self):
     """
     Ensure that condition returns true for valid enterprise catalog uuid in basket attribute.
     """
     offer = factories.EnterpriseOfferFactory(partner=self.partner,
                                              condition=self.condition)
     enterprise_catalog_uuid = str(
         self.condition.enterprise_customer_catalog_uuid)
     basket = BasketFactory(site=self.site, owner=self.user)
     request_data = {'catalog': enterprise_catalog_uuid}
     basket_add_enterprise_catalog_attribute(basket, request_data)
     self._check_condition_is_satisfied(offer, basket, is_satisfied=True)
Exemplo n.º 21
0
    def test_is_satisfied_no_enrollments(self):
        """ The method should return True if the basket contains one course run seat corresponding to each
        course in the program. """
        offer = factories.ProgramOfferFactory(partner=self.partner,
                                              condition=self.condition)
        basket = BasketFactory(site=self.site, owner=UserFactory())
        program = self.mock_program_detail_endpoint(
            self.condition.program_uuid,
            self.site_configuration.discovery_api_url)

        # Extract one audit and one verified seat for each course
        audit_seats = []
        verified_seats = []

        for course in program['courses']:
            course_run = Course.objects.get(id=course['course_runs'][0]['key'])
            for seat in course_run.seat_products:
                if seat.attr.id_verification_required:
                    verified_seats.append(seat)
                else:
                    audit_seats.append(seat)

        self.mock_user_data(basket.owner.username)
        # Empty baskets should never be satisfied
        basket.flush()
        self.assertTrue(basket.is_empty)
        self.assertFalse(self.condition.is_satisfied(offer, basket))

        # Adding seats of all the courses with the wrong seat type should NOT satisfy the condition.
        basket.flush()
        for seat in audit_seats:
            basket.add_product(seat)
        self.assertFalse(self.condition.is_satisfied(offer, basket))

        # All courses must be represented in the basket.
        # NOTE: We add all but the first verified seat to ensure complete branch coverage of the method.
        basket.flush()
        for verified_seat in verified_seats[1:len(verified_seats)]:
            basket.add_product(verified_seat)
        self.assertFalse(self.condition.is_satisfied(offer, basket))

        # The condition should be satisfied if one valid course run from each course is in the basket.
        basket.add_product(verified_seats[0])
        self.assertTrue(self.condition.is_satisfied(offer, basket))

        # If the user is enrolled with the wrong seat type for courses missing from their basket that are
        # needed for the program, the condition should NOT be satisfied
        basket.flush()
        for verified_seat in verified_seats[1:len(verified_seats)]:
            basket.add_product(verified_seat)
        self.assertFalse(self.condition.is_satisfied(offer, basket))
Exemplo n.º 22
0
    def setUp(self):
        super(EnterpriseAPITests, self).setUp()
        self.course_run = CourseFactory()
        self.learner = self.create_user(is_staff=True)
        self.client.login(username=self.learner.username, password=self.password)

        # Enable enterprise functionality
        toggle_switch(settings.ENABLE_ENTERPRISE_ON_RUNTIME_SWITCH, True)

        self.request.user = self.learner
        self.request.site = self.site
        self.request.strategy = DefaultStrategy()

        self.basket = BasketFactory(site=self.site, owner=self.learner, strategy=self.request.strategy)
Exemplo n.º 23
0
    def test_post_valid(self):
        basket = BasketFactory()
        voucher = VoucherFactory(num_basket_additions=5)
        basket.vouchers.add(voucher)

        data = {'code': voucher.code}
        request = RequestFactory().post('/', data=data, basket=basket)

        view = views.VoucherRemoveView.as_view()
        response = view(request, pk=voucher.pk)
        self.assertEqual(response.status_code, 302)

        voucher = voucher.__class__.objects.get(pk=voucher.pk)
        self.assertEqual(voucher.num_basket_additions, 4)
Exemplo n.º 24
0
 def test_apply_voucher_on_basket_and_check_discount_with_multiple_vouchers(self):
     """
     Tests apply_voucher_on_basket_and_check_discount when called with a basket already
     containing a valid voucher it only checks the new voucher.
     """
     basket = BasketFactory(owner=self.request.user, site=self.request.site)
     product = ProductFactory(stockrecords__partner__short_code='test1', stockrecords__price_excl_tax=10)
     invalid_voucher, __ = prepare_voucher(code='TEST1')
     valid_voucher, __ = prepare_voucher(code='TEST2', _range=RangeFactory(products=[product]))
     basket.add_product(product, 1)
     basket.vouchers.add(valid_voucher)
     applied, msg = apply_voucher_on_basket_and_check_discount(invalid_voucher, self.request, basket)
     self.assertEqual(applied, False)
     self.assertEqual(msg, 'Basket does not qualify for coupon code {code}.'.format(code=invalid_voucher.code))
Exemplo n.º 25
0
    def test_voucher_errors(self):
        """ Test data when voucher error happen"""
        basket = BasketFactory(site=self.site)
        voucher, product = prepare_voucher(code='test101')
        basket.vouchers.add(voucher)
        basket.add_product(product)

        with mock.patch('ecommerce.extensions.api.serializers.VoucherSerializer', side_effect=ValueError):
            response = self.client.get(self.path, HTTP_AUTHORIZATION=self.token)
            self.assertIsNone(response.json()['results'][0]['vouchers'])

        with mock.patch('ecommerce.extensions.api.serializers.VoucherSerializer', side_effect=AttributeError):
            response = self.client.get(self.path, HTTP_AUTHORIZATION=self.token)
            self.assertIsNone(response.json()['results'][0]['vouchers'])
Exemplo n.º 26
0
    def test_only_works_for_staff_users(self):
        """ Test view only return results when accessed by staff. """
        basket = BasketFactory(site=self.site)
        response = self.client.get(self.path, HTTP_AUTHORIZATION=self.token)

        self.assertEqual(response.status_code, 200)
        content = response.json()
        self.assertEqual(content['count'], 1)
        self.assertEqual(content['results'][0]['id'], basket.id)

        other_user = self.create_user()
        self.client.login(username=other_user.username, password=self.password)
        response = self.client.get(self.path)
        self.assertEqual(response.status_code, 403)
Exemplo n.º 27
0
    def test_prepare_basket_removes_existing_basket_invalid_range_voucher(self):
        """
        Tests that prepare_basket removes an existing basket voucher that is not
        valid for the product and used to purchase that product.
        """
        product = ProductFactory(stockrecords__partner__short_code='xyz', stockrecords__price_excl_tax=100)
        invalid_range_voucher, __ = prepare_voucher()
        basket = BasketFactory(owner=self.request.user, site=self.request.site)

        basket.vouchers.add(invalid_range_voucher)
        basket = prepare_basket(self.request, [product])

        self.assertIsNotNone(basket)
        self.assertEqual(basket.lines.first().product, product)
        self.assertEqual(basket.vouchers.count(), 0)
Exemplo n.º 28
0
    def test_order_number_for_basket_without_site(self):
        """ Verify the order number is linked to the default site, if the basket has no associated site. """
        site_configuration = SiteConfigurationFactory(site__domain='acme.fake',
                                                      partner__name='ACME')
        site = site_configuration.site
        partner = site_configuration.partner
        basket = BasketFactory(site=None)

        request = RequestFactory().get('')
        request.session = None
        request.site = site

        with mock.patch('ecommerce.extensions.order.utils.get_current_request',
                        mock.Mock(return_value=request)):
            self.assert_order_number_matches_basket(basket, partner)
Exemplo n.º 29
0
    def test_post_valid(self):
        basket = BasketFactory()
        voucher = VoucherFactory()
        self.assertTrue(voucher.is_active())

        data = {
            'code': voucher.code
        }
        request = RequestFactory().post('/', data=data, basket=basket)

        view = views.VoucherAddView.as_view()
        response = view(request)
        self.assertEqual(response.status_code, 302)

        voucher = voucher.__class__.objects.get(pk=voucher.pk)
        self.assertEqual(voucher.num_basket_additions, 1, msg=self._get_voucher_message(request))
Exemplo n.º 30
0
 def test_is_satisfied_true(self):
     """ Ensure the condition returns true if all basket requirements are met. """
     offer = factories.EnterpriseOfferFactory(partner=self.partner, condition=self.condition)
     basket = BasketFactory(site=self.site, owner=self.user)
     basket.add_product(self.course_run.seat_products[0])
     self.mock_enterprise_learner_api(
         learner_id=self.user.id,
         enterprise_customer_uuid=str(self.condition.enterprise_customer_uuid),
         course_run_id=self.course_run.id,
     )
     self.mock_catalog_contains_course_runs(
         [self.course_run.id],
         self.condition.enterprise_customer_uuid,
         enterprise_customer_catalog_uuid=self.condition.enterprise_customer_catalog_uuid,
     )
     self.assertTrue(self.condition.is_satisfied(offer, basket))