Beispiel #1
0
 def test_proper_code(self):
     """ Verify that proper information is returned when a valid code is provided. """
     _range = self.prepare_course_information()
     prepare_voucher(code=COUPON_CODE, _range=_range)
     response = self.client.get(self.path_with_code)
     self.assertEqual(response.context['course']['name'], _('Test course'))
     self.assertEqual(response.context['code'], COUPON_CODE)
Beispiel #2
0
 def test_no_product(self):
     """ Verify an error is returned for voucher with no product. """
     no_product_range = RangeFactory()
     prepare_voucher(code='NOPRODUCT', _range=no_product_range)
     url = self.path + '?code={}'.format('NOPRODUCT')
     response = self.client.get(url)
     self.assertEqual(response.context['error'], _('The voucher is not applicable to your current basket.'))
Beispiel #3
0
    def test_expired_voucher(self):
        """ Verify proper response is returned for expired vouchers. """
        start_datetime = now() - datetime.timedelta(days=20)
        end_datetime = now() - datetime.timedelta(days=10)
        prepare_voucher(code='EXPIRED', start_datetime=start_datetime, end_datetime=end_datetime)

        url = self.path + '?code={}'.format('EXPIRED')
        response = self.client.get(url)
        self.assertEqual(response.context['error'], _('This coupon code has expired.'))
Beispiel #4
0
    def prepare_url_for_credit_seat(self, code='CREDIT'):
        """Helper method for creating a credit seat and construct the URL to its offer landing page.
        Returns:
            URL to its offer landing page.
        """
        __, credit_seat = self.create_course_and_seat(seat_type='credit')
        # Make sure to always pair `course_seat_types` and `catalog_query` parameters because
        # if one of them is missing it could result in a SEGFAULT error when running tests
        # with migrations enabled.
        _range = RangeFactory(products=[credit_seat, ], course_seat_types='credit', catalog_query='*:*')
        prepare_voucher(code=code, _range=_range)

        url = '{path}?code={code}'.format(path=self.path, code=code)
        return url
    def test_get_offers_for_single_course_voucher(self):
        """ Verify that the course offers data is returned for a single course voucher. """
        course, seat = self.create_course_and_seat()
        new_range = RangeFactory(products=[seat, ])
        voucher, __ = prepare_voucher(_range=new_range, benefit_value=10)
        voucher, products = get_voucher_and_products_from_code(voucher.code)
        benefit = voucher.offers.first().benefit
        request = self.prepare_offers_listing_request(voucher.code)
        self.mock_course_api_response(course=course)
        offers = VoucherViewSet().get_offers(products=products, request=request, voucher=voucher)
        first_offer = offers[0]

        self.assertEqual(len(offers), 1)
        self.assertDictEqual(first_offer, {
            'benefit': {
                'type': benefit.type,
                'value': benefit.value
            },
            'contains_verified': True,
            'course_start_date': '2013-02-05T05:00:00Z',
            'id': course.id,
            'image_url': get_lms_url('/asset-v1:test+test+test+type@asset+block@images_course_image.jpg'),
            'organization': CourseKey.from_string(course.id).org,
            'seat_type': course.type,
            'stockrecords': serializers.StockRecordSerializer(seat.stockrecords.first()).data,
            'title': course.name,
            'voucher_end_date': voucher.end_datetime
        })
Beispiel #6
0
    def test_get_offers_for_single_course_voucher(self):
        """ Verify that the course offers data is returned for a single course voucher. """
        course, seat = self.create_course_and_seat()
        new_range = RangeFactory(products=[seat, ])
        voucher, __ = prepare_voucher(_range=new_range, benefit_value=10)
        benefit = voucher.offers.first().benefit
        request = self.prepare_offers_listing_request(voucher.code)
        self.mock_dynamic_catalog_single_course_runs_api(course)
        offers = VoucherViewSet().get_offers(request=request, voucher=voucher)['results']
        first_offer = offers[0]

        self.assertEqual(len(offers), 1)
        self.assertDictEqual(first_offer, {
            'benefit': {
                'type': benefit.type,
                'value': benefit.value
            },
            'contains_verified': True,
            'course_start_date': '2013-02-05T05:00:00Z',
            'id': course.id,
            'image_url': '/path/to/image.jpg',
            'multiple_credit_providers': False,
            'organization': CourseKey.from_string(course.id).org,
            'credit_provider_price': None,
            'seat_type': course.type,
            'stockrecords': serializers.StockRecordSerializer(seat.stockrecords.first()).data,
            'title': course.name,
            'voucher_end_date': voucher.end_datetime,
        })
Beispiel #7
0
 def test_valid_voucher(self):
     """ Verify voucher_is_valid() assess that the voucher is valid. """
     voucher, product = prepare_voucher(code=COUPON_CODE)
     request = RequestFactory().request()
     valid, msg = voucher_is_valid(voucher=voucher, products=[product], request=request)
     self.assertTrue(valid)
     self.assertEquals(msg, '')
Beispiel #8
0
 def test_once_per_customer_voucher(self):
     """ Verify the coupon is valid for anonymous users. """
     voucher, product = prepare_voucher(usage=Voucher.ONCE_PER_CUSTOMER)
     request = RequestFactory().request()
     valid, msg = voucher_is_valid(voucher=voucher, products=[product], request=request)
     self.assertTrue(valid)
     self.assertEqual(msg, '')
    def test_get_offers_for_multiple_courses_voucher(self):
        """ Verify that the course offers data is returned for a multiple courses voucher. """
        course, seat = self.create_course_and_seat()
        self.mock_dynamic_catalog_course_runs_api(query='*:*', course_run=course)
        new_range, __ = Range.objects.get_or_create(catalog_query='*:*')
        new_range.add_product(seat)
        voucher, __ = prepare_voucher(_range=new_range, benefit_value=10)
        voucher, products = get_voucher_and_products_from_code(voucher.code)
        benefit = voucher.offers.first().benefit
        request = self.prepare_offers_listing_request(voucher.code)
        offers = VoucherViewSet().get_offers(products=products, request=request, voucher=voucher)
        first_offer = offers[0]

        self.assertEqual(len(offers), 1)
        self.assertDictEqual(first_offer, {
            'benefit': {
                'type': benefit.type,
                'value': benefit.value
            },
            'contains_verified': False,
            'course_start_date': '2016-05-01T00:00:00Z',
            'id': course.id,
            'image_url': 'path/to/the/course/image',
            'organization': CourseKey.from_string(course.id).org,
            'seat_type': course.type,
            'stockrecords': serializers.StockRecordSerializer(seat.stockrecords.first()).data,
            'title': course.name,
            'voucher_end_date': voucher.end_datetime
        })
Beispiel #10
0
    def test_provider_fields(self, benefit_type, discount):
        code = 'TEST'
        seat = self.course.create_or_update_seat(
            'credit', True, self.price, self.partner, self.provider, credit_hours=self.credit_hours
        )
        new_range = RangeFactory(products=[seat, ])
        prepare_voucher(code=code, _range=new_range, benefit_value=100, benefit_type=benefit_type)
        self._mock_eligibility_api(body=self.eligibilities)
        self._mock_providers_api(body=self.provider_data)

        response = self.client.get('{}?code={}'.format(self.path, code))
        self.assertEqual(response.status_code, 200)
        provider_info = response.context['providers'][0]

        self.assertEqual(provider_info['new_price'], '0.00')
        self.assertEqual(provider_info['discount'], discount)
Beispiel #11
0
 def test_expired_voucher(self):
     """ Verify voucher_is_valid() assess that the voucher has expired. """
     future_datetime = now() + datetime.timedelta(days=10)
     voucher, product = prepare_voucher(code=COUPON_CODE, start_datetime=future_datetime)
     valid, msg = voucher_is_valid(voucher=voucher, product=product, request=None)
     self.assertFalse(valid)
     self.assertEqual(msg, _('Coupon expired'))
Beispiel #12
0
    def test_course_information_error(self):
        """ Verify a response is returned when course information is not accessable. """
        course = CourseFactory()
        seat = course.create_or_update_seat('verified', True, 50, self.partner)
        _range = RangeFactory(products=[seat, ])
        prepare_voucher(code=COUPON_CODE, _range=_range)

        course_url = get_lms_url('api/courses/v1/courses/{}/'.format(course.id))
        httpretty.register_uri(httpretty.GET, course_url, status=404, content_type=CONTENT_TYPE)

        response = self.client.get(self.path_with_code)
        response_text = (
            'Could not get course information. '
            '[Client Error 404: http://127.0.0.1:8000/api/courses/v1/courses/{}/]'
        ).format(course.id)
        self.assertEqual(response.context['error'], _(response_text))
Beispiel #13
0
 def test_voucher_unavailable_to_buy(self):
     """ Verify that False is returned for unavialable products. """
     request = RequestFactory().request()
     voucher, product = prepare_voucher(code=COUPON_CODE)
     product.expires = pytz.utc.localize(datetime.datetime.min)
     valid, __ = voucher_is_valid(voucher=voucher, products=[product], request=request)
     self.assertFalse(valid)
Beispiel #14
0
 def test_used_voucher(self):
     """ Verify voucher_is_valid() assess that the voucher is unavailable. """
     voucher, product = prepare_voucher(code=COUPON_CODE)
     user = self.create_user()
     order = OrderFactory()
     VoucherApplication.objects.create(voucher=voucher, user=user, order=order)
     error_msg = _('This coupon has already been used')
     self.assert_error_messages(voucher, product, user, error_msg)
Beispiel #15
0
 def test_future_voucher(self):
     """ Verify voucher_is_valid() assess that the voucher has not started yet. """
     start_datetime = now() + datetime.timedelta(days=10)
     end_datetime = now() + datetime.timedelta(days=20)
     voucher, product = prepare_voucher(code=COUPON_CODE, start_datetime=start_datetime, end_datetime=end_datetime)
     valid, msg = voucher_is_valid(voucher=voucher, products=[product], request=None)
     self.assertFalse(valid)
     self.assertEqual(msg, _('This coupon code is not yet valid.'))
Beispiel #16
0
 def test_omitting_unavailable_voucher(self):
     """ Verify if there are more than one product, that availability check is omitted. """
     request = RequestFactory().request()
     voucher, product = prepare_voucher(code=COUPON_CODE)
     product.expires = pytz.utc.localize(datetime.datetime.min)
     __, seat = self.create_course_and_seat()
     valid, __ = voucher_is_valid(voucher=voucher, products=[product, seat], request=request)
     self.assertTrue(valid)
Beispiel #17
0
 def test_expired_voucher(self):
     """ Verify an error is returned for expired coupon. """
     start_datetime = now() - datetime.timedelta(days=20)
     end_datetime = now() - datetime.timedelta(days=10)
     code = 'INVALID'
     __, product = prepare_voucher(code=code, start_datetime=start_datetime, end_datetime=end_datetime)
     url = self.redeem_url + '?code={}&sku={}'.format(code, StockRecord.objects.get(product=product).partner_sku)
     response = self.client.get(url)
     self.assertEqual(response.context['error'], _('This coupon code has expired.'))
Beispiel #18
0
 def test_used_voucher(self):
     """ Verify voucher_is_valid() assess that the voucher is unavailable. """
     voucher, product = prepare_voucher(code=COUPON_CODE)
     order = OrderFactory()
     user = self.create_user()
     VoucherApplication.objects.create(voucher=voucher, user=user, order=order)
     request = RequestFactory().request()
     valid, msg = voucher_is_valid(voucher=voucher, product=product, request=request)
     self.assertFalse(valid)
     self.assertEqual(msg, _('This coupon has already been used'))
Beispiel #19
0
    def test_get_voucher_and_products_from_code(self):
        """ Verify that get_voucher_and_products_from_code() returns products and voucher. """
        original_voucher, original_product = prepare_voucher(code=COUPON_CODE)
        voucher, products = get_voucher_and_products_from_code(code=COUPON_CODE)

        self.assertIsNotNone(voucher)
        self.assertEqual(voucher, original_voucher)
        self.assertEqual(voucher.code, COUPON_CODE)
        self.assertEqual(len(products), 1)
        self.assertEqual(products[0], original_product)
    def test_voucher_offers_listing_product_found(self):
        """ Verify the endpoint returns offers data for single product range. """
        course, seat = self.create_course_and_seat()
        self.mock_course_api_response(course=course)

        new_range = RangeFactory(products=[seat, ])
        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)
Beispiel #21
0
    def prepare_get_offers_response(self, quantity=1, seat_type='verified', seats=None):
        """Helper method for creating response the voucher offers endpoint.

        Args:
            quantity (int): Number of course runs

        Returns:
            The products, request and vouchers created.
        """
        course_run_info = {
            'count': quantity,
            'next': 'path/to/the/next/page',
            'results': []
        }
        products = []
        new_range, __ = Range.objects.get_or_create(catalog_query='*:*', course_seat_types=seat_type)
        if seats:
            for seat in seats:
                course_run_info['results'].append({
                    'image': {
                        'src': 'path/to/the/course/image'
                    },
                    'key': seat.course_id,
                    'start': '2016-05-01T00:00:00Z',
                    'title': seat.title,
                    'enrollment_end': None
                })
                new_range.add_product(seat)
        else:
            for _ in range(quantity):
                course, seat = self.create_course_and_seat(seat_type=seat_type)
                course_run_info['results'].append({
                    'image': {
                        'src': 'path/to/the/course/image'
                    },
                    'key': course.id,
                    'start': '2016-05-01T00:00:00Z',
                    'title': course.name,
                    'enrollment_end': None
                })
                new_range.add_product(seat)
                products.append(seat)

        self.mock_dynamic_catalog_course_runs_api(query='*:*', course_run_info=course_run_info)
        voucher, __ = prepare_voucher(_range=new_range)

        factory = APIRequestFactory()
        request = factory.get('/?code={}&page_size=6'.format(voucher.code))
        request.site = self.site
        request.user = self.user
        request.strategy = DefaultStrategy()

        return products, request, voucher
Beispiel #22
0
    def test_voucher_offers_listing_catalog_query(self):
        """ Verify the endpoint returns offers data for single product range. """
        course, seat = self.create_course_and_seat()
        self.mock_dynamic_catalog_course_runs_api(query='*:*', course_run=course)
        new_range, __ = Range.objects.get_or_create(catalog_query='*:*', course_seat_types='verified')
        new_range.add_product(seat)
        voucher, __ = prepare_voucher(_range=new_range)
        request = self.prepare_offers_listing_request(voucher.code)
        response = self.endpointView(request)

        self.assertEqual(response.status_code, 200)
        self.assertGreater(len(response.data), 0)
    def test_get_offers_object_not_found(self):
        """ Verify the endpoint returns status 404 Not Found when product Course or Stock Record is not found """
        __, seat = self.create_course_and_seat()
        new_range = RangeFactory(products=[seat, ])
        voucher, __ = prepare_voucher(_range=new_range)

        with mock.patch(
            'ecommerce.extensions.api.v2.views.vouchers.VoucherViewSet.get_offers',
            mock.Mock(side_effect=Http404)
        ):
            request = self.prepare_offers_listing_request(voucher.code)
            response = self.endpointView(request)

            self.assertEqual(response.status_code, 404)
    def test_voucher_offers_listing_api_exception_caught(self, exception):
        """ Verify the endpoint returns status 400 Bad Request when ConnectionError occurs """
        __, seat = self.create_course_and_seat()
        new_range = RangeFactory(products=[seat, ])
        voucher, __ = prepare_voucher(_range=new_range, benefit_value=10)

        with mock.patch(
            'ecommerce.extensions.api.v2.views.vouchers.VoucherViewSet.get_offers',
            mock.Mock(side_effect=exception)
        ):
            request = self.prepare_offers_listing_request(voucher.code)
            response = self.endpointView(request)

            self.assertEqual(response.status_code, 400)
    def test_voucher_offers_listing_api_exception_caught(self, exception):
        """ Verify the endpoint returns status 400 Bad Request when ConnectionError occurs """
        __, seat = self.create_course_and_seat()
        new_range = RangeFactory(products=[
            seat,
        ])
        voucher, __ = prepare_voucher(_range=new_range, benefit_value=10)

        with mock.patch(
                'ecommerce.extensions.api.v2.views.vouchers.VoucherViewSet.get_offers',
                mock.Mock(side_effect=exception)):
            request = self.prepare_offers_listing_request(voucher.code)
            response = self.endpointView(request)

            self.assertEqual(response.status_code, 400)
Beispiel #26
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)
Beispiel #27
0
 def test_voucher_used_error_msg(self):
     """ Verify correct error message is returned when voucher has been used (Single use). """
     self.mock_access_token_response()
     self.mock_account_api(self.request,
                           self.user.username,
                           data={'is_active': True})
     voucher, product = prepare_voucher(code=COUPON_CODE)
     self.basket.add_product(product)
     order = factories.OrderFactory()
     VoucherApplication.objects.create(voucher=voucher,
                                       user=self.user,
                                       order=order)
     self.assert_form_valid_message(
         "Coupon code '{code}' has already been redeemed.".format(
             code=COUPON_CODE))
Beispiel #28
0
    def test_voucher_offers_listing_catalog_query(self):
        """ Verify the endpoint returns offers data for single product range. """
        self.mock_access_token_response()
        course, seat = self.create_course_and_seat()
        self.mock_course_runs_endpoint(
            self.site_configuration.discovery_api_url, query='*:*', course_run=course
        )
        new_range, __ = Range.objects.get_or_create(catalog_query='*:*', course_seat_types='verified')
        new_range.add_product(seat)
        voucher, __ = prepare_voucher(_range=new_range)
        request = self.prepare_offers_listing_request(voucher.code)
        response = self.endpointView(request)

        self.assertEqual(response.status_code, 200)
        self.assertGreater(len(response.data), 0)
Beispiel #29
0
    def test_get_offers_object_not_found(self):
        """ Verify the endpoint returns status 404 Not Found when product Course or Stock Record is not found """
        __, seat = self.create_course_and_seat()
        new_range = RangeFactory(products=[
            seat,
        ])
        voucher, __ = prepare_voucher(_range=new_range)

        with mock.patch(
                'ecommerce.extensions.api.v2.views.vouchers.VoucherViewSet.get_offers',
                mock.Mock(side_effect=Http404)):
            request = self.prepare_offers_listing_request(voucher.code)
            response = self.endpointView(request)

            self.assertEqual(response.status_code, 404)
Beispiel #30
0
    def test_voucher_offers_listing_for_a_single_course_voucher(self):
        """ Verify the endpoint returns offers data when a single product is in voucher range. """
        course, seat = self.create_course_and_seat()
        self.mock_dynamic_catalog_single_course_runs_api(course)
        new_range = RangeFactory(products=[seat, ])
        new_range.catalog = Catalog.objects.create(partner=self.partner)
        new_range.catalog.stock_records.add(StockRecord.objects.get(product=seat))
        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)

        new_range.remove_product(seat)
        response = self.endpointView(request)
        self.assertEqual(response.status_code, 404)
Beispiel #31
0
    def test_basket_calculate_fixed_coupon(self):
        """ Verify successful basket calculation for a fixed price voucher """
        discount = 5
        voucher, _ = prepare_voucher(_range=self.range, benefit_type=Benefit.FIXED, benefit_value=discount)

        response = self.client.get(self.url + '&code={code}'.format(code=voucher.code))

        expected = {
            'total_incl_tax_excl_discounts': self.product_total,
            'total_incl_tax': self.product_total - discount,
            'currency': 'GBP'
        }

        self.assertEqual(response.status_code, 200)
        self.assertEqual(response.data, expected)
Beispiel #32
0
    def test_set_enterprise_cookie(self):
        """
        Validate that a cookie is set with UUID of the enterprise customer
        associated with the voucher of given code.
        """
        enterprise_customer_uuid = uuid.uuid4()
        voucher, __ = prepare_voucher(
            enterprise_customer=enterprise_customer_uuid)
        request = RequestFactory().get('/', data={'code': voucher.code})
        request.site = self.site
        response = decorators.set_enterprise_cookie(self._mock_view)(request)

        cookie = response.cookies[settings.ENTERPRISE_CUSTOMER_COOKIE_NAME]
        self.assertEqual(str(enterprise_customer_uuid), cookie.value)
        self.assertEqual(60, cookie.get('max-age'))
Beispiel #33
0
    def test_voucher_offers_listing_for_a_single_course_voucher(self):
        """ Verify the endpoint returns offers data when a single product is in voucher range. """
        course, seat = self.create_course_and_seat()
        self.mock_dynamic_catalog_single_course_runs_api(course)
        new_range = RangeFactory(products=[seat, ])
        new_range.catalog = Catalog.objects.create(partner=self.partner)
        new_range.catalog.stock_records.add(StockRecord.objects.get(product=seat))
        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)

        new_range.remove_product(seat)
        response = self.endpointView(request)
        self.assertEqual(response.status_code, 404)
Beispiel #34
0
 def test_voucher_not_valid_for_bundle(self):
     """ Verify correct error message is returned when voucher is used against a bundle. """
     self.mock_access_token_response()
     self.mock_account_api(self.request, self.user.username, data={'is_active': True})
     voucher, product = prepare_voucher(code=COUPON_CODE, benefit_value=0)
     new_product = factories.ProductFactory(categories=[], stockrecords__partner__short_code='second')
     self.basket.add_product(product)
     self.basket.add_product(new_product)
     BasketAttributeType.objects.get_or_create(name=BUNDLE)
     BasketAttribute.objects.update_or_create(
         basket=self.basket,
         attribute_type=BasketAttributeType.objects.get(name=BUNDLE),
         value_text='test_bundle'
     )
     self.assert_form_valid_message("Coupon code '{code}' is not valid for this basket.".format(code=voucher.code))
    def test_get_offers_for_single_course_voucher(self):
        """ Verify that the course offers data is returned for a single course voucher. """
        self.mock_access_token_response()
        course, seat = self.create_course_and_seat()
        new_range = RangeFactory(products=[
            seat,
        ])
        voucher, __ = prepare_voucher(_range=new_range, benefit_value=10)
        benefit = voucher.offers.first().benefit
        request = self.prepare_offers_listing_request(voucher.code)
        self.mock_course_run_detail_endpoint(
            course,
            discovery_api_url=self.site_configuration.discovery_api_url)
        offers = VoucherViewSet().get_offers(request=request,
                                             voucher=voucher)['results']
        first_offer = offers[0]

        self.assertEqual(len(offers), 1)
        self.assertDictEqual(
            first_offer, {
                'benefit': {
                    'type': get_benefit_type(benefit),
                    'value': benefit.value
                },
                'contains_verified':
                True,
                'course_start_date':
                '2013-02-05T05:00:00Z',
                'id':
                course.id,
                'image_url':
                '/path/to/image.jpg',
                'multiple_credit_providers':
                False,
                'organization':
                CourseKey.from_string(course.id).org,
                'credit_provider_price':
                None,
                'seat_type':
                course.type,
                'stockrecords':
                serializers.StockRecordSerializer(
                    seat.stockrecords.first()).data,
                'title':
                course.name,
                'voucher_end_date':
                voucher.end_datetime,
            })
Beispiel #36
0
 def test_get_offers_for_multiple_courses_voucher(self):
     """ Verify that the course offers data is returned for a multiple courses voucher. """
     self.mock_access_token_response()
     course, seat = self.create_course_and_seat()
     self.mock_course_runs_endpoint(
         self.site_configuration.discovery_api_url,
         query='*:*',
         course_run=course)
     new_range, __ = Range.objects.get_or_create(
         catalog_query='*:*', course_seat_types='verified')
     new_range.add_product(seat)
     voucher, __ = prepare_voucher(_range=new_range, benefit_value=10)
     benefit = voucher.offers.first().benefit
     request = self.prepare_offers_listing_request(voucher.code)
     offers = VoucherViewSet().get_offers(request=request,
                                          voucher=voucher)['results']
     first_offer = offers[0]
     self.assertEqual(len(offers), 1)
     self.assertDictEqual(
         first_offer, {
             'benefit': {
                 'type': get_benefit_type(benefit),
                 'value': benefit.value
             },
             'contains_verified':
             True,
             'course_start_date':
             '2016-05-01T00:00:00Z',
             'id':
             course.id,
             'image_url':
             'path/to/the/course/image',
             'multiple_credit_providers':
             False,
             'organization':
             CourseKey.from_string(course.id).org,
             'credit_provider_price':
             None,
             'seat_type':
             seat.attr.certificate_type,
             'stockrecords':
             serializers.StockRecordSerializer(
                 seat.stockrecords.first()).data,
             'title':
             course.name,
             'voucher_end_date':
             voucher.end_datetime,
         })
Beispiel #37
0
 def test_inactive_voucher(self):
     """ Verify the view alerts the user if the voucher is inactive. """
     self.mock_access_token_response()
     self.mock_account_api(self.request,
                           self.user.username,
                           data={'is_active': True})
     code = FuzzyText().fuzz()
     start_datetime = datetime.datetime.now() + datetime.timedelta(days=1)
     end_datetime = start_datetime + datetime.timedelta(days=2)
     voucher, product = prepare_voucher(code=code,
                                        start_datetime=start_datetime,
                                        end_datetime=end_datetime)
     self.basket.add_product(product)
     self.form.cleaned_data = {'code': voucher.code}
     self.assert_form_valid_message(
         "Coupon code '{code}' is not active.".format(code=voucher.code))
Beispiel #38
0
    def test_voucher_offers_listing_catalog_query_exception(self, return_value, method):
        """
        Verify the endpoint returns status 200 and an empty list of course offers
        when all product Courses and Stock Records are not found
        and range has a catalog query
        """
        course, seat = self.create_course_and_seat()
        self.mock_dynamic_catalog_course_runs_api(query='*:*', course_run=course)
        new_range, __ = Range.objects.get_or_create(catalog_query='*:*', course_seat_types='verified')
        new_range.add_product(seat)
        voucher, __ = prepare_voucher(_range=new_range)
        request = self.prepare_offers_listing_request(voucher.code)

        with mock.patch(method, mock.Mock(return_value=return_value)):
            offers = VoucherViewSet().get_offers(request=request, voucher=voucher)['results']
            self.assertEqual(len(offers), 0)
Beispiel #39
0
    def test_is_voucher_applied(self):
        """
        Verify is_voucher_applied return correct value.
        """
        product = ProductFactory(stockrecords__price_excl_tax=100)
        voucher, product = prepare_voucher(
            _range=RangeFactory(products=[product]),
            benefit_value=10
        )
        basket = prepare_basket(self.request, [product], voucher)

        # Verify is_voucher_applied returns True when voucher is applied to the basket.
        self.assertTrue(is_voucher_applied(basket, voucher))

        # Verify is_voucher_applied returns False when voucher can not be applied to the basket.
        self.assertFalse(is_voucher_applied(basket, VoucherFactory()))
Beispiel #40
0
    def test_prepare_basket_enrollment_with_voucher(self):
        """Verify the basket does not contain a voucher if enrollment code is added to it."""
        course = CourseFactory(partner=self.partner)
        course.create_or_update_seat('verified', False, 10, create_enrollment_code=True)
        enrollment_code = Product.objects.get(product_class__name=ENROLLMENT_CODE_PRODUCT_CLASS_NAME)
        voucher, product = prepare_voucher()

        basket = prepare_basket(self.request, [product], voucher)
        self.assertIsNotNone(basket)
        self.assertEqual(basket.all_lines()[0].product, product)
        self.assertTrue(basket.contains_a_voucher)

        basket = prepare_basket(self.request, [enrollment_code], voucher)
        self.assertIsNotNone(basket)
        self.assertEqual(basket.all_lines()[0].product, enrollment_code)
        self.assertFalse(basket.contains_a_voucher)
Beispiel #41
0
    def test_voucher_offers_listing_catalog_query_exception(self, return_value, method):
        """
        Verify the endpoint returns status 200 and an empty list of course offers
        when all product Courses and Stock Records are not found
        and range has a catalog query
        """
        course, seat = self.create_course_and_seat()
        self.mock_dynamic_catalog_course_runs_api(query='*:*', course_run=course)
        new_range, __ = Range.objects.get_or_create(catalog_query='*:*', course_seat_types='verified')
        new_range.add_product(seat)
        voucher, __ = prepare_voucher(_range=new_range)
        request = self.prepare_offers_listing_request(voucher.code)

        with mock.patch(method, mock.Mock(return_value=return_value)):
            offers = VoucherViewSet().get_offers(request=request, voucher=voucher)['results']
            self.assertEqual(len(offers), 0)
Beispiel #42
0
    def test_add_multiple_products_and_use_voucher(self, usage):
        """ Verify the basket accepts multiple products and a single use voucher. """
        products = ProductFactory.create_batch(3, stockrecords__partner=self.partner)
        product_range = factories.RangeFactory(products=products)
        voucher, __ = prepare_voucher(_range=product_range, usage=usage)

        qs = urllib.urlencode({
            'sku': [product.stockrecords.first().partner_sku for product in products],
            'code': voucher.code
        }, True)
        url = '{root}?{qs}'.format(root=self.path, qs=qs)
        response = self.client.get(url)
        self.assertEqual(response.status_code, 303)
        basket = response.wsgi_request.basket
        self.assertEqual(basket.status, Basket.OPEN)
        self.assertTrue(basket.contains_voucher(voucher.code))
Beispiel #43
0
    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}
        basket = prepare_basket(request, [product])
        self.assertFalse(basket.vouchers.all())
Beispiel #44
0
    def test_prepare_basket_ignores_invalid_voucher(self):
        """
        Tests that prepare_basket validates provided voucher and
        does not applies it if invalid.
        """
        voucher_start_time = now() - datetime.timedelta(days=5)
        voucher_end_time = now() - datetime.timedelta(days=3)
        product = ProductFactory(stockrecords__partner__short_code='test1', stockrecords__price_excl_tax=100)
        expired_voucher, __ = prepare_voucher(start_datetime=voucher_start_time, end_datetime=voucher_end_time)

        basket = prepare_basket(self.request, [product], expired_voucher)
        self.assertIsNotNone(basket)
        self.assertEqual(basket.status, Basket.OPEN)
        self.assertEqual(basket.lines.count(), 1)
        self.assertEqual(basket.lines.first().product, product)
        self.assertEqual(basket.vouchers.count(), 0)
Beispiel #45
0
    def test_basket_information(self):
        """ Test data return by the Api"""
        basket = BasketFactory(site=self.site)
        voucher, product = prepare_voucher(code='test101')
        basket.vouchers.add(voucher)
        basket.add_product(product)
        PaymentProcessorResponse.objects.create(basket=basket, transaction_id='PAY-123', processor_name='paypal',
                                                response=json.dumps({'state': 'approved'}))
        response = self.client.get(self.path, HTTP_AUTHORIZATION=self.token)

        self.assertEqual(response.status_code, 200)
        content = response.json()
        self.assertEqual(content['results'][0]['id'], basket.id)
        self.assertEqual(content['results'][0]['status'], basket.status)
        self.assertIsNotNone(content['results'][0]['vouchers'])
        self.assertEqual(content['results'][0]['payment_status'], "Accepted")
Beispiel #46
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))
Beispiel #47
0
    def test_voucher_offers_listing_product_found(self):
        """ Verify the endpoint returns offers data for single product range. """
        self.mock_access_token_response()
        course, seat = self.create_course_and_seat()
        self.mock_course_run_detail_endpoint(
            course,
            discovery_api_url=self.site_configuration.discovery_api_url)

        new_range = RangeFactory(products=[
            seat,
        ])
        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)
Beispiel #48
0
 def test_multi_use_voucher_valid_for_bundle(self):
     """ Verify multi use coupon works when voucher is used against a bundle. """
     self.mock_access_token_response()
     self.mock_account_api(self.request,
                           self.user.username,
                           data={'is_active': True})
     voucher, product = prepare_voucher(code=COUPON_CODE,
                                        benefit_value=10,
                                        usage=Voucher.MULTI_USE)
     new_product = factories.ProductFactory(
         categories=[], stockrecords__partner__short_code='second')
     self.basket.add_product(product)
     self.basket.add_product(new_product)
     _set_basket_bundle_status('test-bundle', self.basket)
     self.assert_form_valid_message(
         "Coupon code '{code}' added to basket.".format(code=voucher.code))
Beispiel #49
0
    def test_omitting_unavailable_seats(self):
        """ Verify an unavailable seat is omitted from offer page results. """
        course1, seat1 = self.create_course_and_seat()
        course2, seat2 = self.create_course_and_seat()
        course_run_info = {
            'count':
            2,
            'next':
            'path/to/the/next/page',
            'results': [{
                'key': course1.id,
                'title': course1.name,
                'start': '2016-05-01T00:00:00Z',
                'image': {
                    'src': 'path/to/the/course/image'
                }
            }, {
                'key': course2.id,
                'title': course2.name,
                'start': '2016-05-01T00:00:00Z',
                'image': {
                    'src': 'path/to/the/course/image'
                }
            }]
        }

        self.mock_dynamic_catalog_course_runs_api(
            query='*:*', course_run_info=course_run_info)
        new_range, __ = Range.objects.get_or_create(catalog_query='*:*')
        new_range.add_product(seat1)
        new_range.add_product(seat2)
        voucher, __ = prepare_voucher(_range=new_range)
        voucher, products = get_voucher_and_products_from_code(voucher.code)
        factory = APIRequestFactory()
        request = factory.get('/?code={}&page_size=6'.format(voucher.code))
        request.site = self.site
        request.strategy = DefaultStrategy()
        offers = VoucherViewSet().get_offers(products=products,
                                             request=request,
                                             voucher=voucher)['results']
        self.assertEqual(len(offers), 2)

        products[1].expires = pytz.utc.localize(datetime.datetime.min)
        offers = VoucherViewSet().get_offers(products=products,
                                             request=request,
                                             voucher=voucher)['results']
        self.assertEqual(len(offers), 1)
Beispiel #50
0
    def test_prepare_basket_enrollment_with_voucher(self):
        """Verify the basket does not contain a voucher if enrollment code is added to it."""
        course = CourseFactory()
        toggle_switch(ENROLLMENT_CODE_SWITCH, True)
        course.create_or_update_seat('verified', False, 10, self.partner, create_enrollment_code=True)
        enrollment_code = Product.objects.get(product_class__name=ENROLLMENT_CODE_PRODUCT_CLASS_NAME)
        voucher, product = prepare_voucher()

        basket = prepare_basket(self.request, product, voucher)
        self.assertIsNotNone(basket)
        self.assertEqual(basket.all_lines()[0].product, product)
        self.assertTrue(basket.contains_a_voucher)

        basket = prepare_basket(self.request, enrollment_code, voucher)
        self.assertIsNotNone(basket)
        self.assertEqual(basket.all_lines()[0].product, enrollment_code)
        self.assertFalse(basket.contains_a_voucher)
Beispiel #51
0
    def test_get_offers_for_single_course_voucher(self):
        """ Verify that the course offers data is returned for a single course voucher. """
        course, seat = self.create_course_and_seat()
        new_range = RangeFactory(products=[
            seat,
        ])
        voucher, __ = prepare_voucher(_range=new_range, benefit_value=10)
        voucher, products = get_voucher_and_products_from_code(voucher.code)
        benefit = voucher.offers.first().benefit
        request = self.prepare_offers_listing_request(voucher.code)
        self.mock_course_api_response(course=course)
        offers = VoucherViewSet().get_offers(products=products,
                                             request=request,
                                             voucher=voucher)
        first_offer = offers[0]

        self.assertEqual(len(offers), 1)
        self.assertDictEqual(
            first_offer, {
                'benefit': {
                    'type': benefit.type,
                    'value': benefit.value
                },
                'contains_verified':
                True,
                'course_start_date':
                '2013-02-05T05:00:00Z',
                'id':
                course.id,
                'image_url':
                get_lms_url(
                    '/asset-v1:test+test+test+type@asset+block@images_course_image.jpg'
                ),
                'organization':
                CourseKey.from_string(course.id).org,
                'seat_type':
                course.type,
                'stockrecords':
                serializers.StockRecordSerializer(
                    seat.stockrecords.first()).data,
                'title':
                course.name,
                'voucher_end_date':
                voucher.end_datetime
            })
Beispiel #52
0
    def test_get_offers_for_course_catalog_voucher(self):
        """ Verify that the course offers data is returned for a course catalog voucher. """
        catalog_id = 1
        catalog_query = '*:*'

        self.mock_access_token_response()
        # Populate database for the test case.
        course, seat = self.create_course_and_seat()
        new_range, __ = Range.objects.get_or_create(course_catalog=catalog_id, course_seat_types='verified')
        new_range.add_product(seat)
        voucher, __ = prepare_voucher(_range=new_range, benefit_value=10)

        # Mock network calls
        self.mock_course_runs_endpoint(
            query=catalog_query, course_run=course, discovery_api_url=self.site_configuration.discovery_api_url
        )
        self.mock_catalog_detail_endpoint(
            catalog_id=catalog_id, expected_query=catalog_query,
            discovery_api_url=self.site_configuration.discovery_api_url
        )

        benefit = voucher.offers.first().benefit
        request = self.prepare_offers_listing_request(voucher.code)
        offers = VoucherViewSet().get_offers(request=request, voucher=voucher)['results']
        first_offer = offers[0]

        # Verify that offers are returned when voucher is created using course catalog
        self.assertEqual(len(offers), 1)
        self.assertDictEqual(first_offer, {
            'benefit': {
                'type': benefit.type,
                'value': benefit.value
            },
            'contains_verified': True,
            'course_start_date': '2016-05-01T00:00:00Z',
            'id': course.id,
            'image_url': 'path/to/the/course/image',
            'multiple_credit_providers': False,
            'organization': CourseKey.from_string(course.id).org,
            'credit_provider_price': None,
            'seat_type': course.type,
            'stockrecords': serializers.StockRecordSerializer(seat.stockrecords.first()).data,
            'title': course.name,
            'voucher_end_date': voucher.end_datetime,
        })
Beispiel #53
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))
Beispiel #54
0
    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)
Beispiel #55
0
    def test_prepare_basket_removes_existing_basket_invalid_voucher(self):
        """
        Tests that prepare_basket removes an existing basket voucher that is invalid
        for multiple products when used to purchase any of those products.
        """
        voucher_start_time = now() - datetime.timedelta(days=5)
        voucher_end_time = now() - datetime.timedelta(days=3)
        product = ProductFactory(stockrecords__partner__short_code='xyz', stockrecords__price_excl_tax=100)
        expired_voucher, __ = prepare_voucher(start_datetime=voucher_start_time, end_datetime=voucher_end_time)

        basket = BasketFactory(owner=self.request.user, site=self.request.site)
        basket.vouchers.add(expired_voucher)

        self.assertEqual(basket.vouchers.count(), 1)
        basket = prepare_basket(self.request, [product])
        self.assertIsNotNone(basket)
        self.assertEqual(basket.lines.first().product, product)
        self.assertEqual(basket.vouchers.count(), 0)
Beispiel #56
0
    def test_expired_voucher(self):
        """ Verify an error is returned for expired coupon. """
        start_datetime = now() - datetime.timedelta(days=20)
        end_datetime = now() - datetime.timedelta(days=10)
        code = FuzzyText().fuzz()
        __, product = prepare_voucher(code=code,
                                      start_datetime=start_datetime,
                                      end_datetime=end_datetime)

        url = format_url(
            base=self.redeem_url,
            params={
                'code': code,
                'sku': StockRecord.objects.get(product=product).partner_sku
            })
        response = self.client.get(url)
        self.assertEqual(response.context['error'],
                         'This coupon code has expired.')
Beispiel #57
0
    def test_get_offers(self):
        """ Verify that the course offers data is returned. """
        course, seat = self.create_course_and_seat()
        new_range = RangeFactory(products=[
            seat,
        ])
        voucher, __ = prepare_voucher(_range=new_range, benefit_value=10)
        voucher, products = get_voucher_and_products_from_code(voucher.code)
        benefit = voucher.offers.first().benefit
        request = self.prepare_offers_listing_request(voucher.code)
        self.mock_dynamic_catalog_course_runs_api(
            course_run=course, query=new_range.catalog_query)
        offers = VoucherViewSet().get_offers(products=products,
                                             request=request,
                                             voucher=voucher)
        first_offer = offers[0]

        self.assertEqual(len(offers), 1)
        self.assertDictEqual(
            first_offer, {
                'benefit': {
                    'type': benefit.type,
                    'value': benefit.value
                },
                'contains_verified':
                True,
                'course_start_date':
                '2016-05-01T00:00:00Z',
                'id':
                course.id,
                'image_url':
                'path/to/the/course/image',
                'organization':
                CourseKey.from_string(course.id).org,
                'seat_type':
                course.type,
                'stockrecords':
                serializers.StockRecordSerializer(
                    seat.stockrecords.first()).data,
                'title':
                course.name,
                'voucher_end_date':
                voucher.end_datetime
            })
Beispiel #58
0
    def test_prepare_basket_with_voucher(self):
        """ Verify a basket is returned and contains a voucher and the voucher is applied. """
        # Prepare a product with price of 100 and a voucher with 10% discount for that product.
        product = ProductFactory(stockrecords__price_excl_tax=100)
        new_range = RangeFactory(products=[product, ])
        voucher, product = prepare_voucher(_range=new_range, benefit_value=10)

        stock_record = StockRecord.objects.get(product=product)
        self.assertEqual(stock_record.price_excl_tax, 100.00)

        basket = prepare_basket(self.request, product, voucher)
        self.assertIsNotNone(basket)
        self.assertEqual(basket.status, Basket.OPEN)
        self.assertEqual(basket.lines.count(), 1)
        self.assertEqual(basket.lines.first().product, product)
        self.assertEqual(basket.vouchers.count(), 1)
        self.assertIsNotNone(basket.applied_offers())
        self.assertEqual(basket.total_discount, 10.00)
        self.assertEqual(basket.total_excl_tax, 90.00)
    def test_omitting_unavailable_seats(self):
        """ Verify an unavailable seat is omitted from offer page results. """
        course1, seat1 = self.create_course_and_seat()
        course2, seat2 = self.create_course_and_seat()
        course_run_info = {
            'count': 2,
            'results': [{
                'key': course1.id,
                'title': course1.name,
                'start': '2016-05-01T00:00:00Z',
                'image': {
                    'src': 'path/to/the/course/image'
                }
            }, {
                'key': course2.id,
                'title': course2.name,
                'start': '2016-05-01T00:00:00Z',
                'image': {
                    'src': 'path/to/the/course/image'
                }
            }]
        }

        self.mock_dynamic_catalog_course_runs_api(query='*:*', course_run_info=course_run_info)
        new_range, __ = Range.objects.get_or_create(catalog_query='*:*')
        new_range.add_product(seat1)
        new_range.add_product(seat2)
        voucher, __ = prepare_voucher(_range=new_range)
        voucher, products = get_voucher_and_products_from_code(voucher.code)
        factory = APIRequestFactory()
        request = factory.get('/?code={}&page_size=6'.format(voucher.code))
        request.site = self.site
        request.strategy = DefaultStrategy()
        offers = VoucherViewSet().get_offers(products=products, request=request, voucher=voucher)
        self.assertEqual(len(offers), 2)

        products[1].expires = pytz.utc.localize(datetime.datetime.min)
        offers = VoucherViewSet().get_offers(products=products, request=request, voucher=voucher)
        self.assertEqual(len(offers), 1)
Beispiel #60
0
    def setUp(self):
        super(VoucherRemoveMessagesViewTests, self).setUp()
        self.user = self.create_user()
        self.client.login(username=self.user.username, password=self.password)

        self.course = CourseFactory()
        self.course.create_or_update_seat('verified', True, 50, self.partner)
        self.product = self.course.create_or_update_seat('verified', False, 0, self.partner)
        self.voucher, __ = prepare_voucher(code=COUPON_CODE)

        self.request = RequestFactory().request()
        # Fallback storage is needed in tests with messages
        setattr(self.request, 'session', 'session')
        messages = FallbackStorage(self.request)
        setattr(self.request, '_messages', messages)
        self.request.user = self.user

        basket = factories.BasketFactory(owner=self.user, site=self.site)
        basket.add_product(self.product, 1)
        self.request.basket = basket

        self.voucher_remove_view = VoucherRemoveMessagesView()