Commit fecd3d55 by Kevin Falcone

Merge branch 'release'

parents f78be26a 44bea2ea
...@@ -277,7 +277,7 @@ def _absolute_url(is_secure, url_path): ...@@ -277,7 +277,7 @@ def _absolute_url(is_secure, url_path):
def _absolute_url_staticfile(is_secure, name): def _absolute_url_staticfile(is_secure, name):
"""Construct an absolute URL back to a static resource on the site. """Construct an absolute URL to a static resource on the site.
Arguments: Arguments:
is_secure (bool): If true, use HTTPS as the protocol. is_secure (bool): If true, use HTTPS as the protocol.
...@@ -288,4 +288,13 @@ def _absolute_url_staticfile(is_secure, name): ...@@ -288,4 +288,13 @@ def _absolute_url_staticfile(is_secure, name):
""" """
url_path = staticfiles_storage.url(name) url_path = staticfiles_storage.url(name)
# In production, the static files URL will be an absolute
# URL pointing to a CDN. If this happens, we can just
# return the URL.
if urlparse.urlparse(url_path).netloc:
return url_path
# For local development, the returned URL will be relative,
# so we need to make it absolute.
return _absolute_url(is_secure, url_path) return _absolute_url(is_secure, url_path)
...@@ -102,6 +102,26 @@ class TestFooter(TestCase): ...@@ -102,6 +102,26 @@ class TestFooter(TestCase):
# Copyright # Copyright
self.assertIn("copyright", json_data) self.assertIn("copyright", json_data)
def test_absolute_urls_with_cdn(self):
self._set_feature_flag(True)
# Ordinarily, we'd use `override_settings()` to override STATIC_URL,
# which is what the staticfiles storage backend is using to construct the URL.
# Unfortunately, other parts of the system are caching this value on module
# load, which can cause other tests to fail. To ensure that this change
# doesn't affect other tests, we patch the `url()` method directly instead.
cdn_url = "http://cdn.example.com/static/image.png"
with mock.patch('branding.api.staticfiles_storage.url', return_value=cdn_url):
resp = self._get_footer()
self.assertEqual(resp.status_code, 200)
json_data = json.loads(resp.content)
self.assertEqual(json_data["logo_image"], cdn_url)
for link in json_data["mobile_links"]:
self.assertEqual(link["url"], cdn_url)
@ddt.data( @ddt.data(
("en", "registered trademarks"), ("en", "registered trademarks"),
("eo", u"régïstéréd trädémärks"), # Dummy language string ("eo", u"régïstéréd trädémärks"), # Dummy language string
......
...@@ -1185,10 +1185,15 @@ class RegistrationCodeRedemption(models.Model): ...@@ -1185,10 +1185,15 @@ class RegistrationCodeRedemption(models.Model):
Returns RegistrationCodeRedemption object if registration code Returns RegistrationCodeRedemption object if registration code
has been used during the course enrollment else Returns None. has been used during the course enrollment else Returns None.
""" """
try: # theoretically there could be more than one (e.g. someone self-unenrolls
return cls.objects.get(course_enrollment=course_enrollment) # then re-enrolls with a different regcode)
except RegistrationCodeRedemption.DoesNotExist: reg_codes = cls.objects.filter(course_enrollment=course_enrollment).order_by('-redeemed_at')
return None if reg_codes:
# return the first one. In all normal use cases of registration codes
# the user will only have one
return reg_codes[0]
return None
@classmethod @classmethod
def is_registration_code_redeemed(cls, course_reg_code): def is_registration_code_redeemed(cls, course_reg_code):
......
...@@ -27,7 +27,8 @@ from shoppingcart.models import ( ...@@ -27,7 +27,8 @@ from shoppingcart.models import (
Order, OrderItem, CertificateItem, Order, OrderItem, CertificateItem,
InvalidCartItem, CourseRegistrationCode, PaidCourseRegistration, CourseRegCodeItem, InvalidCartItem, CourseRegistrationCode, PaidCourseRegistration, CourseRegCodeItem,
Donation, OrderItemSubclassPK, Donation, OrderItemSubclassPK,
Invoice, CourseRegistrationCodeInvoiceItem, InvoiceTransaction, InvoiceHistory Invoice, CourseRegistrationCodeInvoiceItem, InvoiceTransaction, InvoiceHistory,
RegistrationCodeRedemption
) )
from student.tests.factories import UserFactory from student.tests.factories import UserFactory
from student.models import CourseEnrollment from student.models import CourseEnrollment
...@@ -470,6 +471,60 @@ class PaidCourseRegistrationTest(ModuleStoreTestCase): ...@@ -470,6 +471,60 @@ class PaidCourseRegistrationTest(ModuleStoreTestCase):
# check that the registration codes are generated against the order # check that the registration codes are generated against the order
self.assertEqual(len(CourseRegistrationCode.objects.filter(order=self.cart)), item.qty) self.assertEqual(len(CourseRegistrationCode.objects.filter(order=self.cart)), item.qty)
def test_regcode_redemptions(self):
"""
Asserts the data model around RegistrationCodeRedemption
"""
self.cart.order_type = 'business'
self.cart.save()
CourseRegCodeItem.add_to_order(self.cart, self.course_key, 2)
self.cart.purchase()
reg_code = CourseRegistrationCode.objects.filter(order=self.cart)[0]
enrollment = CourseEnrollment.enroll(self.user, self.course_key)
redemption = RegistrationCodeRedemption(
registration_code=reg_code,
redeemed_by=self.user,
course_enrollment=enrollment
)
redemption.save()
test_redemption = RegistrationCodeRedemption.registration_code_used_for_enrollment(enrollment)
self.assertEqual(test_redemption.id, redemption.id) # pylint: disable=no-member
def test_regcode_multi_redemptions(self):
"""
Asserts the data model around RegistrationCodeRedemption and
what happens when we do multiple redemptions by same user
"""
self.cart.order_type = 'business'
self.cart.save()
CourseRegCodeItem.add_to_order(self.cart, self.course_key, 2)
self.cart.purchase()
reg_codes = CourseRegistrationCode.objects.filter(order=self.cart)
self.assertEqual(len(reg_codes), 2)
enrollment = CourseEnrollment.enroll(self.user, self.course_key)
ids = []
for reg_code in reg_codes:
redemption = RegistrationCodeRedemption(
registration_code=reg_code,
redeemed_by=self.user,
course_enrollment=enrollment
)
redemption.save()
ids.append(redemption.id) # pylint: disable=no-member
test_redemption = RegistrationCodeRedemption.registration_code_used_for_enrollment(enrollment)
self.assertIn(test_redemption.id, ids) # pylint: disable=no-member
def test_add_with_default_mode(self): def test_add_with_default_mode(self):
""" """
Tests add_to_cart where the mode specified in the argument is NOT in the database Tests add_to_cart where the mode specified in the argument is NOT in the database
......
...@@ -14,6 +14,7 @@ class SoftwareSecurePhotoVerificationAdmin(admin.ModelAdmin): ...@@ -14,6 +14,7 @@ class SoftwareSecurePhotoVerificationAdmin(admin.ModelAdmin):
""" """
list_display = ('id', 'user', 'status', 'receipt_id', 'submitted_at', 'updated_at') list_display = ('id', 'user', 'status', 'receipt_id', 'submitted_at', 'updated_at')
exclude = ('window',) # TODO: Remove after deleting this field from the model. exclude = ('window',) # TODO: Remove after deleting this field from the model.
raw_id_fields = ('user', 'reviewing_user')
search_fields = ( search_fields = (
'receipt_id', 'receipt_id',
) )
...@@ -26,6 +27,7 @@ class VerificationStatusAdmin(admin.ModelAdmin): ...@@ -26,6 +27,7 @@ class VerificationStatusAdmin(admin.ModelAdmin):
list_display = ('timestamp', 'user', 'status', 'checkpoint') list_display = ('timestamp', 'user', 'status', 'checkpoint')
readonly_fields = () readonly_fields = ()
search_fields = ('checkpoint__checkpoint_location', 'user__username') search_fields = ('checkpoint__checkpoint_location', 'user__username')
raw_id_fields = ('user',)
def get_readonly_fields(self, request, obj=None): def get_readonly_fields(self, request, obj=None):
"""When editing an existing record, all fields should be read-only. """When editing an existing record, all fields should be read-only.
...@@ -47,6 +49,7 @@ class VerificationStatusAdmin(admin.ModelAdmin): ...@@ -47,6 +49,7 @@ class VerificationStatusAdmin(admin.ModelAdmin):
class SkippedReverificationAdmin(admin.ModelAdmin): class SkippedReverificationAdmin(admin.ModelAdmin):
"""Admin for the SkippedReverification table. """ """Admin for the SkippedReverification table. """
list_display = ('created_at', 'user', 'course_id', 'checkpoint') list_display = ('created_at', 'user', 'course_id', 'checkpoint')
raw_id_fields = ('user',)
readonly_fields = ('user', 'course_id') readonly_fields = ('user', 'course_id')
search_fields = ('user__username', 'course_id', 'checkpoint__checkpoint_location') search_fields = ('user__username', 'course_id', 'checkpoint__checkpoint_location')
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment