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': 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, })
def test_omitting_already_bought_credit_seat(self): """ Verify a seat that the user bought is omitted from offer page results. """ self.mock_access_token_response() products, request, voucher = self.prepare_get_offers_response( quantity=2, seat_type='credit') self.mock_eligibility_api(request, self.user, 'a/b/c', eligible=True) offers = VoucherViewSet().get_offers(request=request, voucher=voucher)['results'] self.assertEqual(len(offers), 2) order = OrderFactory(user=self.user) order.lines.add( OrderLineFactory(product=products[0], partner_sku='test_sku')) offers = VoucherViewSet().get_offers(request=request, voucher=voucher)['results'] self.assertEqual(len(offers), 1)
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 = '*:*' # 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_dynamic_catalog_course_runs_api( query=catalog_query, course_run=course, discovery_api_url=self.site_configuration.discovery_api_url) self.mock_fetch_course_catalog( 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, })
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': 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, })
def test_omitting_expired_courses(self): """Verify professional courses who's enrollment end datetime have passed are omitted.""" no_date_seat = CourseFactory().create_or_update_seat( 'professional', False, 100, partner=self.partner) valid_seat = CourseFactory().create_or_update_seat( 'professional', False, 100, partner=self.partner) expired_seat = CourseFactory().create_or_update_seat( 'professional', False, 100, partner=self.partner) course_discovery_results = [{ 'key': no_date_seat.attr.course_key, 'enrollment_end': None, }, { 'key': valid_seat.attr.course_key, 'enrollment_end': str(now() + datetime.timedelta(days=1)), }, { 'key': expired_seat.attr.course_key, 'enrollment_end': str(now() - datetime.timedelta(days=1)), }] products, __ = VoucherViewSet().retrieve_course_objects( course_discovery_results, 'professional') self.assertIn(no_date_seat, products) self.assertIn(valid_seat, products) self.assertNotIn(expired_seat, products)
def test_multiple_providers(self): """ Verify offer contains information about credit providers. """ course = CourseFactory() seat1 = course.create_or_update_seat('credit', False, 100, partner=self.partner, credit_provider='test_provider_1') seat2 = course.create_or_update_seat('credit', False, 100, partner=self.partner, credit_provider='test_provider_2') self.assertEqual( Product.objects.filter(parent=seat1.parent).count(), 2) self.mock_access_token_response() __, request, voucher = self.prepare_get_offers_response( seats=[seat1, seat2], seat_type='credit') self.mock_eligibility_api(request, self.user, course.id) offers = VoucherViewSet().get_offers(request=request, voucher=voucher)['results'] for offer in offers: self.assertTrue(offer['multiple_credit_providers']) self.assertIsNone(offer['credit_provider_price'])
def test_omitting_uneligible_credit_seat(self, offer_num, eligible): """ Verify a seat that the user is not eligible for is omitted from offer page results. """ self.mock_access_token_response() products, request, voucher = self.prepare_get_offers_response(quantity=1, seat_type='credit') self.mock_eligibility_api(request, self.user, products[0].attr.course_key, eligible=eligible) offers = VoucherViewSet().get_offers(request=request, voucher=voucher)['results'] self.assertEqual(len(offers), offer_num)
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)
def test_get_offers_for_enterprise_catalog_voucher(self): """ Verify that the course offers data is returned for an enterprise catalog voucher. """ Switch.objects.update_or_create( name=ENTERPRISE_OFFERS_FOR_COUPONS_SWITCH, defaults={'active': False}) self.mock_access_token_response() course, seat = self.create_course_and_seat() enterprise_catalog_id = str(uuid4()) self.mock_enterprise_catalog_course_endpoint( self.site_configuration.enterprise_api_url, enterprise_catalog_id, course_run=course) new_range, __ = Range.objects.get_or_create( catalog_query='*:*', course_seat_types='verified', enterprise_customer=str(uuid4()), enterprise_customer_catalog=enterprise_catalog_id, ) 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': course.type, 'stockrecords': serializers.StockRecordSerializer( seat.stockrecords.first()).data, 'title': course.name, 'voucher_end_date': voucher.end_datetime, })
def test_get_offers_for_enterprise_offer_no_catalog(self): """ Verify that the course offers data is returned for an enterprise catalog voucher. """ self.mock_access_token_response() enterprise_customer_id = str(uuid4()) voucher = prepare_enterprise_voucher( benefit_value=10, enterprise_customer=enterprise_customer_id, ) request = self.prepare_offers_listing_request(voucher.code) offers = VoucherViewSet().get_offers(request=request, voucher=voucher)['results'] self.assertEqual(len(offers), 0)
def test_get_offers_for_enterprise_offer(self): """ Verify that the course offers data is returned for an enterprise catalog voucher. """ self.mock_access_token_response() course, seat = self.create_course_and_seat() enterprise_customer_id = str(uuid4()) enterprise_catalog_id = str(uuid4()) self.mock_enterprise_catalog_course_endpoint( self.site_configuration.enterprise_api_url, enterprise_catalog_id, course_run=course) voucher = prepare_enterprise_voucher( benefit_value=10, enterprise_customer=enterprise_customer_id, enterprise_customer_catalog=enterprise_catalog_id) 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, })
def test_omitting_unavailable_seats(self): """ Verify an unavailable seat is omitted from offer page results. """ products, request, voucher = self.prepare_get_offers_response(quantity=2) url = self.build_offers_url(voucher) response = self.client.get(url) self.assertEqual(response.status_code, 200) self.assertEqual(len(response.data['results']), 2) product = products[0] product.expires = pytz.utc.localize(datetime.datetime.min) product.save() offers = VoucherViewSet().get_offers(request=request, voucher=voucher)['results'] self.assertEqual(len(offers), 1)
def test_get_offers_for_enterprise_offer_switch_on_no_catalog(self): """ Verify that the course offers data is returned for an enterprise catalog voucher. """ Switch.objects.update_or_create( name=ENTERPRISE_OFFERS_FOR_COUPONS_SWITCH, defaults={'active': True}) self.mock_access_token_response() enterprise_customer_id = str(uuid4()) voucher = prepare_enterprise_voucher( benefit_value=10, enterprise_customer=enterprise_customer_id, ) request = self.prepare_offers_listing_request(voucher.code) offers = VoucherViewSet().get_offers(request=request, voucher=voucher)['results'] self.assertEqual(len(offers), 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)
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 })
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 })
def test_get_course_offer_data(self): """ Verify that the course offers data is properly formatted. """ benefit = BenefitFactory() course, seat = self.create_course_and_seat() course_info = { 'start': '2016-05-01T00:00:00Z', 'image': { 'src': 'path/to/the/course/image' } } stock_record = seat.stockrecords.first() voucher = VoucherFactory() offer = VoucherViewSet().get_course_offer_data( benefit=benefit, course=course, course_info=course_info, credit_provider_price=None, multiple_credit_providers=False, is_verified=True, product=seat, stock_record=stock_record, voucher=voucher) self.assertDictEqual( offer, { 'benefit': { 'type': get_benefit_type(benefit), 'value': benefit.value }, 'contains_verified': True, 'course_start_date': course_info['start'], 'id': course.id, 'image_url': course_info['image']['src'], 'multiple_credit_providers': False, 'organization': CourseKey.from_string(course.id).org, 'credit_provider_price': None, 'seat_type': seat.attr.certificate_type, 'stockrecords': serializers.StockRecordSerializer(stock_record).data, 'title': course.name, 'voucher_end_date': voucher.end_datetime, })
def test_get_course_offer_verify_null_fields(self): """ Verify that the course offers data is properly formatted. """ benefit = BenefitFactory() course, seat = self.create_course_and_seat() course_info = { 'start': None, 'image': None, } stock_record = seat.stockrecords.first() voucher = VoucherFactory() offer = VoucherViewSet().get_course_offer_data( benefit=benefit, course=course, course_info=course_info, is_verified=True, stock_record=stock_record, voucher=voucher) self.assertEqual(offer['image_url'], '') self.assertEqual(offer['course_start_date'], None)
def test_voucher_offers_listing_product_not_found(self, code): """ Verify the endpoint returns status 400 Bad Request. """ request = self.prepare_offers_listing_request(code) response = VoucherViewSet().offers(request) self.assertEqual(response.status_code, 400)
def setUp(self): super(VoucherViewOffersEndpointTests, self).setUp() self.endpointView = VoucherViewSet.as_view({'get': 'offers'}) self.factory = APIRequestFactory() request = self.factory.get('/page=1') self.endpointView.request = request