Merge pull request #14181 from edx/mdikan/add-utm-tracking-to-free-purchases
Adding support for UTM Tracking to apply to free purhases
This commit is contained in:
@@ -31,6 +31,11 @@ from student.tests.tests import EnrollmentEventTestMixin
|
||||
from xmodule.modulestore.django import modulestore
|
||||
from commerce.api.v0.views import SAILTHRU_CAMPAIGN_COOKIE
|
||||
|
||||
UTM_COOKIE_NAME = 'edx.test.utm'
|
||||
UTM_COOKIE_CONTENTS = {
|
||||
'utm_source': 'test-source'
|
||||
}
|
||||
|
||||
|
||||
@attr(shard=1)
|
||||
@ddt.ddt
|
||||
@@ -39,7 +44,7 @@ class BasketsViewTests(EnrollmentEventTestMixin, UserMixin, ModuleStoreTestCase)
|
||||
"""
|
||||
Tests for the commerce orders view.
|
||||
"""
|
||||
def _post_to_view(self, course_id=None, marketing_email_opt_in=False):
|
||||
def _post_to_view(self, course_id=None, marketing_email_opt_in=False, include_utm_cookie=False):
|
||||
"""
|
||||
POST to the view being tested.
|
||||
|
||||
@@ -55,6 +60,8 @@ class BasketsViewTests(EnrollmentEventTestMixin, UserMixin, ModuleStoreTestCase)
|
||||
payload["email_opt_in"] = True
|
||||
|
||||
self.client.cookies[SAILTHRU_CAMPAIGN_COOKIE] = 'sailthru id'
|
||||
if include_utm_cookie:
|
||||
self.client.cookies[UTM_COOKIE_NAME] = json.dumps(UTM_COOKIE_CONTENTS)
|
||||
return self.client.post(self.url, payload)
|
||||
|
||||
def assertResponseMessage(self, response, expected_msg):
|
||||
@@ -160,12 +167,12 @@ class BasketsViewTests(EnrollmentEventTestMixin, UserMixin, ModuleStoreTestCase)
|
||||
self.assertValidEcommerceInternalRequestErrorResponse(response)
|
||||
self.assertUserNotEnrolled()
|
||||
|
||||
def _test_successful_ecommerce_api_call(self, is_completed=True):
|
||||
def _test_successful_ecommerce_api_call(self, is_completed=True, utm_tracking_present=False):
|
||||
"""
|
||||
Verifies that the view contacts the E-Commerce API with the correct data and headers.
|
||||
"""
|
||||
with mock.patch('commerce.api.v0.views.audit_log') as mock_audit_log:
|
||||
response = self._post_to_view()
|
||||
response = self._post_to_view(include_utm_cookie=utm_tracking_present)
|
||||
|
||||
# Verify that an audit message was logged
|
||||
self.assertTrue(mock_audit_log.called)
|
||||
@@ -177,9 +184,15 @@ class BasketsViewTests(EnrollmentEventTestMixin, UserMixin, ModuleStoreTestCase)
|
||||
else:
|
||||
self.assertResponsePaymentData(response)
|
||||
|
||||
# make sure ecommerce API call forwards Sailthru cookie
|
||||
# Make sure ecommerce API call forwards Sailthru cookie
|
||||
self.assertIn('{}=sailthru id'.format(SAILTHRU_CAMPAIGN_COOKIE), httpretty.last_request().headers['cookie'])
|
||||
|
||||
# Check that UTM tracking cookie is passed along in request to ecommerce for attribution
|
||||
if utm_tracking_present:
|
||||
cookie_string = '{cookie_name}={cookie_contents}'.format(
|
||||
cookie_name=UTM_COOKIE_NAME, cookie_contents=json.dumps(UTM_COOKIE_CONTENTS))
|
||||
self.assertIn(cookie_string, httpretty.last_request().headers['cookie'])
|
||||
|
||||
@ddt.data(True, False)
|
||||
def test_course_with_honor_seat_sku(self, user_is_active):
|
||||
"""
|
||||
@@ -193,7 +206,14 @@ class BasketsViewTests(EnrollmentEventTestMixin, UserMixin, ModuleStoreTestCase)
|
||||
|
||||
return_value = {'id': TEST_BASKET_ID, 'payment_data': None, 'order': {'number': TEST_ORDER_NUMBER}}
|
||||
with mock_create_basket(response=return_value):
|
||||
# Test that call without utm tracking works
|
||||
self._test_successful_ecommerce_api_call()
|
||||
with mock.patch('student.models.RegistrationCookieConfiguration.current') as config:
|
||||
instance = config.return_value
|
||||
instance.utm_cookie_name = UTM_COOKIE_NAME
|
||||
|
||||
# Test that call with cookie passes cookie along
|
||||
self._test_successful_ecommerce_api_call(utm_tracking_present=True)
|
||||
|
||||
@ddt.data(True, False)
|
||||
def test_course_with_paid_seat_sku(self, user_is_active):
|
||||
@@ -207,7 +227,7 @@ class BasketsViewTests(EnrollmentEventTestMixin, UserMixin, ModuleStoreTestCase)
|
||||
|
||||
return_value = {'id': TEST_BASKET_ID, 'payment_data': TEST_PAYMENT_DATA, 'order': None}
|
||||
with mock_create_basket(response=return_value):
|
||||
self._test_successful_ecommerce_api_call(False)
|
||||
self._test_successful_ecommerce_api_call(is_completed=False)
|
||||
|
||||
def _test_course_without_sku(self, enrollment_mode=CourseMode.DEFAULT_MODE_SLUG):
|
||||
"""
|
||||
@@ -334,7 +354,7 @@ class BasketsViewTests(EnrollmentEventTestMixin, UserMixin, ModuleStoreTestCase)
|
||||
self.assertIsNotNone(get_enrollment(self.user.username, unicode(self.course.id)))
|
||||
|
||||
with mock_create_basket():
|
||||
self._test_successful_ecommerce_api_call(False)
|
||||
self._test_successful_ecommerce_api_call(is_completed=False)
|
||||
|
||||
@mock.patch('commerce.api.v0.views.update_email_opt_in')
|
||||
@ddt.data(*itertools.product((False, True), (False, True), (False, True)))
|
||||
|
||||
@@ -22,7 +22,7 @@ from openedx.core.djangoapps.commerce.utils import ecommerce_api_client
|
||||
from openedx.core.djangoapps.user_api.preferences.api import update_email_opt_in
|
||||
from openedx.core.lib.api.authentication import OAuth2AuthenticationAllowInactiveUser
|
||||
from openedx.core.lib.log_utils import audit_log
|
||||
from student.models import CourseEnrollment
|
||||
from student.models import CourseEnrollment, RegistrationCookieConfiguration
|
||||
from util.json_request import JsonResponse
|
||||
|
||||
|
||||
@@ -150,13 +150,11 @@ class BasketsView(APIView):
|
||||
# Make the API call
|
||||
try:
|
||||
# Pass along Sailthru campaign id
|
||||
campaign_cookie = request.COOKIES.get(SAILTHRU_CAMPAIGN_COOKIE)
|
||||
if campaign_cookie:
|
||||
cookie = {SAILTHRU_CAMPAIGN_COOKIE: campaign_cookie}
|
||||
if api_session.cookies:
|
||||
requests.utils.add_dict_to_cookiejar(api_session.cookies, cookie)
|
||||
else:
|
||||
api_session.cookies = requests.utils.cookiejar_from_dict(cookie)
|
||||
self._add_request_cookie_to_api_session(api_session, request, SAILTHRU_CAMPAIGN_COOKIE)
|
||||
|
||||
# Pass along UTM tracking info
|
||||
utm_cookie_name = RegistrationCookieConfiguration.current().utm_cookie_name
|
||||
self._add_request_cookie_to_api_session(api_session, request, utm_cookie_name)
|
||||
|
||||
response_data = api.baskets.post({
|
||||
'products': [{'sku': default_enrollment_mode.sku}],
|
||||
@@ -194,6 +192,18 @@ class BasketsView(APIView):
|
||||
self._handle_marketing_opt_in(request, course_key, user)
|
||||
return response
|
||||
|
||||
def _add_request_cookie_to_api_session(self, server_session, request, cookie_name):
|
||||
""" Add cookie from user request into server session """
|
||||
user_cookie = None
|
||||
if cookie_name:
|
||||
user_cookie = request.COOKIES.get(cookie_name)
|
||||
if user_cookie:
|
||||
server_cookie = {cookie_name: user_cookie}
|
||||
if server_session.cookies:
|
||||
requests.utils.add_dict_to_cookiejar(server_session.cookies, server_cookie)
|
||||
else:
|
||||
server_session.cookies = requests.utils.cookiejar_from_dict(server_cookie)
|
||||
|
||||
|
||||
class BasketOrderView(APIView):
|
||||
""" Retrieve the order associated with a basket. """
|
||||
|
||||
Reference in New Issue
Block a user