Commit 83bfb178 by Will Daly

Use new-style course locators consistently when setting the donation amount in the session

Update devstack settings to use new CyberSource API
parent 9a554ec3
import ddt
import unittest
import decimal
import ddt
from django.conf import settings
from django.test.utils import override_settings
from django.core.urlresolvers import reverse
......@@ -162,7 +163,7 @@ class CourseModeViewTest(ModuleStoreTestCase):
POST_PARAMS_FOR_COURSE_MODE = {
'audit': {'audit_mode': True},
'honor': {'honor-code': True},
'verified': {'certificate_mode': True}
'verified': {'certificate_mode': True, 'contribution': '1.23'}
}
# TODO (ECOM-16): Remove the auto-register flag once the AB-test completes
......@@ -203,3 +204,20 @@ class CourseModeViewTest(ModuleStoreTestCase):
self.fail("Must provide a valid redirect URL name")
self.assertRedirects(resp, redirect_url)
def test_remember_donation_for_course(self):
# Create the course modes
for mode in ('audit', 'honor', 'verified'):
CourseModeFactory(mode_slug=mode, course_id=self.course.id)
# Choose the mode (POST request)
choose_track_url = reverse('course_modes_choose', args=[unicode(self.course.id)])
self.client.post(choose_track_url, self.POST_PARAMS_FOR_COURSE_MODE['verified'])
# Expect that the contribution amount is stored in the user's session
self.assertIn('donation_for_course', self.client.session)
self.assertIn(unicode(self.course.id), self.client.session['donation_for_course'])
actual_amount = self.client.session['donation_for_course'][unicode(self.course.id)]
expected_amount = decimal.Decimal(self.POST_PARAMS_FOR_COURSE_MODE['verified']['contribution'])
self.assertEqual(actual_amount, expected_amount)
......@@ -16,7 +16,6 @@ from edxmako.shortcuts import render_to_response
from course_modes.models import CourseMode
from courseware.access import has_access
from student.models import CourseEnrollment
from verify_student.models import SoftwareSecurePhotoVerification
from opaque_keys.edx.locations import SlashSeparatedCourseKey
from xmodule.modulestore.django import modulestore
......@@ -92,7 +91,7 @@ class ChooseModeView(View):
)
donation_for_course = request.session.get("donation_for_course", {})
chosen_price = donation_for_course.get(course_key, None)
chosen_price = donation_for_course.get(unicode(course_key), None)
course = modulestore().get_course(course_key)
context = {
......@@ -164,7 +163,7 @@ class ChooseModeView(View):
return self.get(request, course_id, error=error_msg)
donation_for_course = request.session.get("donation_for_course", {})
donation_for_course[course_key] = amount_value
donation_for_course[unicode(course_key)] = amount_value
request.session["donation_for_course"] = donation_for_course
return redirect(
......
......@@ -13,6 +13,7 @@ verify_student/start?course_id=MITx/6.002x/2013_Spring # create
import json
import mock
import urllib
import decimal
from mock import patch, Mock
import pytz
from datetime import timedelta, datetime
......@@ -98,6 +99,21 @@ class TestVerifyView(ModuleStoreTestCase):
response = self.client.get(url, {'upgrade': "True"})
self.assertIn("You are upgrading your registration for", response.content)
def test_show_selected_contribution_amount(self):
# Set the donation amount in the client's session
session = self.client.session
session['donation_for_course'] = {
unicode(self.course_key): decimal.Decimal('1.23')
}
session.save()
# Retrieve the page
url = reverse('verify_student_verify', kwargs={"course_id": unicode(self.course_key)})
response = self.client.get(url)
# Expect that the user's contribution amount is shown on the page
self.assertContains(response, '1.23')
@override_settings(MODULESTORE=MODULESTORE_CONFIG)
class TestVerifiedView(ModuleStoreTestCase):
......@@ -126,6 +142,25 @@ class TestVerifiedView(ModuleStoreTestCase):
# Location should contains dashboard.
self.assertIn('dashboard', response._headers.get('location')[1])
def test_show_selected_contribution_amount(self):
# Configure the course to have a verified mode
for mode in ('audit', 'honor', 'verified'):
CourseModeFactory(mode_slug=mode, course_id=self.course.id)
# Set the donation amount in the client's session
session = self.client.session
session['donation_for_course'] = {
unicode(self.course_id): decimal.Decimal('1.23')
}
session.save()
# Retrieve the page
url = reverse('verify_student_verified', kwargs={"course_id": unicode(self.course_id)})
response = self.client.get(url)
# Expect that the user's contribution amount is shown on the page
self.assertContains(response, '1.23')
@override_settings(MODULESTORE=MODULESTORE_CONFIG)
class TestReverifyView(ModuleStoreTestCase):
......@@ -548,6 +583,26 @@ class TestCreateOrder(ModuleStoreTestCase):
data = json.loads(response.content)
self.assertEqual(data['override_custom_receipt_page'], "http://testserver/shoppingcart/postpay_callback/")
def test_create_order_set_donation_amount(self):
# Verify the student so we don't need to submit photos
self._verify_student()
# Create an order
url = reverse('verify_student_create_order')
params = {
'course_id': unicode(self.course.id),
'contribution': '1.23'
}
self.client.post(url, params)
# Verify that the client's session contains the new donation amount
self.assertIn('donation_for_course', self.client.session)
self.assertIn(unicode(self.course.id), self.client.session['donation_for_course'])
actual_amount = self.client.session['donation_for_course'][unicode(self.course.id)]
expected_amount = decimal.Decimal('1.23')
self.assertEqual(actual_amount, expected_amount)
def _verify_student(self):
""" Simulate that the student's identity has already been verified. """
attempt = SoftwareSecurePhotoVerification.objects.create(user=self.user)
......
......@@ -82,7 +82,7 @@ class VerifyView(View):
if not current_mode:
return redirect(reverse('dashboard'))
if course_id.to_deprecated_string() in request.session.get("donation_for_course", {}):
chosen_price = request.session["donation_for_course"][course_id.to_deprecated_string()]
chosen_price = request.session["donation_for_course"][unicode(course_id)]
else:
chosen_price = current_mode.min_price
......@@ -145,7 +145,7 @@ class VerifiedView(View):
if not current_mode:
return redirect(reverse('dashboard'))
if course_id.to_deprecated_string() in request.session.get("donation_for_course", {}):
chosen_price = request.session["donation_for_course"][course_id.to_deprecated_string()]
chosen_price = request.session["donation_for_course"][unicode(course_id)]
else:
chosen_price = current_mode.min_price
......@@ -189,15 +189,15 @@ def create_order(request):
course_id = request.POST['course_id']
course_id = SlashSeparatedCourseKey.from_deprecated_string(course_id)
donation_for_course = request.session.get('donation_for_course', {})
current_donation = donation_for_course.get(course_id, decimal.Decimal(0))
contribution = request.POST.get("contribution", donation_for_course.get(course_id, 0))
current_donation = donation_for_course.get(unicode(course_id), decimal.Decimal(0))
contribution = request.POST.get("contribution", donation_for_course.get(unicode(course_id), 0))
try:
amount = decimal.Decimal(contribution).quantize(decimal.Decimal('.01'), rounding=decimal.ROUND_DOWN)
except decimal.InvalidOperation:
return HttpResponseBadRequest(_("Selected price is not valid number."))
if amount != current_donation:
donation_for_course[course_id] = amount
donation_for_course[unicode(course_id)] = amount
request.session['donation_for_course'] = donation_for_course
# prefer professional mode over verified_mode
......
......@@ -84,8 +84,15 @@ PIPELINE_SASS_ARGUMENTS = '--debug-info --require {proj_dir}/static/sass/bourbon
FEATURES['AUTOMATIC_VERIFY_STUDENT_IDENTITY_FOR_TESTING'] = True
FEATURES['ENABLE_PAYMENT_FAKE'] = True
for processor in CC_PROCESSOR.values():
processor['PURCHASE_ENDPOINT'] = '/shoppingcart/payment_fake/'
CC_PROCESSOR_NAME = 'CyberSource2'
CC_PROCESSOR = {
'CyberSource2': {
"PURCHASE_ENDPOINT": '/shoppingcart/payment_fake/',
"SECRET_KEY": 'abcd123',
"ACCESS_KEY": 'abcd123',
"PROFILE_ID": 'edx',
}
}
#####################################################################
# See if the developer has any local overrides.
......
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