feat: add course key param to track selection url (#33716)
This commit is contained in:
committed by
GitHub
parent
f880855f66
commit
a57dd7325b
@@ -149,6 +149,50 @@ class CourseModeViewTest(CatalogIntegrationMixin, UrlResetMixin, ModuleStoreTest
|
||||
self.assertRedirects(response, '/test_basket/add/?sku=TEST', fetch_redirect_response=False)
|
||||
ecomm_test_utils.update_commerce_config(enabled=False)
|
||||
|
||||
def test_verified_mode_response_contains_course_run_key(self):
|
||||
# Create only the verified mode and enroll the user
|
||||
CourseModeFactory.create(
|
||||
mode_slug='verified',
|
||||
course_id=self.course_that_started.id,
|
||||
min_price=149,
|
||||
sku="dummy"
|
||||
)
|
||||
CourseEnrollmentFactory(
|
||||
is_active=True,
|
||||
course_id=self.course_that_started.id,
|
||||
user=self.user
|
||||
)
|
||||
|
||||
# Value Prop TODO (REV-2378): remove waffle flag from tests once the new Track Selection template is rolled out.
|
||||
with override_waffle_flag(VALUE_PROP_TRACK_SELECTION_FLAG, active=True):
|
||||
with patch(GATING_METHOD_NAME, return_value=True):
|
||||
with patch(CDL_METHOD_NAME, return_value=True):
|
||||
with patch("common.djangoapps.course_modes.views.EcommerceService.is_enabled", return_value=True):
|
||||
url = reverse('course_modes_choose', args=[str(self.course_that_started.id)])
|
||||
response = self.client.get(url)
|
||||
self.assertContains(response, "&course_run_key=")
|
||||
self.assertContains(response, self.course_that_started.id)
|
||||
|
||||
def test_response_without_verified_sku_does_not_contain_course_run_key(self):
|
||||
CourseModeFactory.create(
|
||||
mode_slug='verified',
|
||||
course_id=self.course_that_started.id,
|
||||
)
|
||||
CourseEnrollmentFactory(
|
||||
is_active=True,
|
||||
course_id=self.course_that_started.id,
|
||||
user=self.user
|
||||
)
|
||||
|
||||
# Value Prop TODO (REV-2378): remove waffle flag from tests once the new Track Selection template is rolled out.
|
||||
with override_waffle_flag(VALUE_PROP_TRACK_SELECTION_FLAG, active=True):
|
||||
with patch(GATING_METHOD_NAME, return_value=True):
|
||||
with patch(CDL_METHOD_NAME, return_value=True):
|
||||
with patch("common.djangoapps.course_modes.views.EcommerceService.is_enabled", return_value=True):
|
||||
url = reverse('course_modes_choose', args=[str(self.course_that_started.id)])
|
||||
response = self.client.get(url)
|
||||
self.assertNotContains(response, "&course_run_key=")
|
||||
|
||||
@httpretty.activate
|
||||
@ddt.data(
|
||||
'',
|
||||
|
||||
@@ -191,6 +191,7 @@ class ChooseModeView(View):
|
||||
"content_gating_enabled": gated_content,
|
||||
"course_duration_limit_enabled": CourseDurationLimitConfig.enabled_for_enrollment(request.user, course),
|
||||
"search_courses_url": urljoin(settings.MKTG_URLS.get('ROOT'), '/search?tab=course'),
|
||||
"course_run_key": course_id,
|
||||
}
|
||||
context.update(
|
||||
get_experiment_user_metadata_context(
|
||||
@@ -236,7 +237,7 @@ class ChooseModeView(View):
|
||||
|
||||
if verified_mode.sku:
|
||||
context["use_ecommerce_payment_flow"] = ecommerce_service.is_enabled(request.user)
|
||||
context["ecommerce_payment_page"] = ecommerce_service.payment_page_url()
|
||||
context["ecommerce_payment_page"] = ecommerce_service.get_add_to_basket_url()
|
||||
context["sku"] = verified_mode.sku
|
||||
context["bulk_sku"] = verified_mode.bulk_sku
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ from django.conf import settings
|
||||
from django.test import TestCase
|
||||
from django.test.client import RequestFactory
|
||||
from django.test.utils import override_settings
|
||||
from edx_toggles.toggles.testutils import override_waffle_flag
|
||||
from opaque_keys.edx.locator import CourseLocator
|
||||
from waffle.testutils import override_switch
|
||||
|
||||
@@ -20,9 +21,11 @@ from common.djangoapps.student.models import CourseEnrollment
|
||||
from common.djangoapps.student.tests.factories import TEST_PASSWORD, UserFactory
|
||||
from lms.djangoapps.commerce.models import CommerceConfiguration
|
||||
from lms.djangoapps.commerce.utils import EcommerceService, refund_entitlement, refund_seat
|
||||
from lms.djangoapps.commerce.waffle import ENABLE_TRANSITION_TO_COORDINATOR_CHECKOUT
|
||||
from openedx.core.djangolib.testing.utils import skip_unless_lms
|
||||
from openedx.core.lib.log_utils import audit_log
|
||||
from xmodule.modulestore.tests.django_utils import ModuleStoreTestCase # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from xmodule.modulestore.tests.django_utils import \
|
||||
ModuleStoreTestCase # lint-amnesty, pylint: disable=wrong-import-order
|
||||
from xmodule.modulestore.tests.factories import CourseFactory # lint-amnesty, pylint: disable=wrong-import-order
|
||||
|
||||
# Entitlements is not in CMS' INSTALLED_APPS so these imports will error during test collection
|
||||
@@ -183,6 +186,27 @@ class EcommerceServiceTests(TestCase):
|
||||
|
||||
assert url == expected_url
|
||||
|
||||
@override_settings(COMMERCE_COORDINATOR_URL_ROOT='http://coordinator_url')
|
||||
@override_settings(ECOMMERCE_PUBLIC_URL_ROOT='http://ecommerce_url')
|
||||
@ddt.data(
|
||||
{'coordinator_flag_active': True},
|
||||
{'coordinator_flag_active': False}
|
||||
)
|
||||
@ddt.unpack
|
||||
def test_get_add_to_basket_url(self, coordinator_flag_active):
|
||||
with override_waffle_flag(ENABLE_TRANSITION_TO_COORDINATOR_CHECKOUT, active=coordinator_flag_active):
|
||||
|
||||
ecommerce_service = EcommerceService()
|
||||
result = ecommerce_service.get_add_to_basket_url()
|
||||
|
||||
if coordinator_flag_active:
|
||||
expected_url = 'http://coordinator_url/lms/redirect/'
|
||||
else:
|
||||
expected_url = 'http://ecommerce_url/test_basket/add/'
|
||||
|
||||
self.assertIsNotNone(result)
|
||||
self.assertEqual(result, expected_url)
|
||||
|
||||
|
||||
@ddt.ddt
|
||||
@skip_unless_lms
|
||||
|
||||
@@ -14,6 +14,7 @@ from django.utils.translation import gettext as _
|
||||
from opaque_keys.edx.keys import CourseKey
|
||||
|
||||
from common.djangoapps.course_modes.models import CourseMode
|
||||
from lms.djangoapps.commerce.waffle import should_redirect_to_commerce_coordinator_checkout
|
||||
from openedx.core.djangoapps.commerce.utils import (
|
||||
get_ecommerce_api_base_url,
|
||||
get_ecommerce_api_client,
|
||||
@@ -43,6 +44,7 @@ def is_account_activation_requirement_disabled():
|
||||
|
||||
class EcommerceService:
|
||||
""" Helper class for ecommerce service integration. """
|
||||
|
||||
def __init__(self):
|
||||
self.config = CommerceConfiguration.current()
|
||||
|
||||
@@ -103,6 +105,16 @@ class EcommerceService:
|
||||
"""
|
||||
return self.get_absolute_ecommerce_url(self.config.basket_checkout_page)
|
||||
|
||||
def get_add_to_basket_url(self):
|
||||
""" Return the URL for the payment page based on the waffle switch.
|
||||
|
||||
Example:
|
||||
http://localhost/enabled_service_api_path
|
||||
"""
|
||||
if should_redirect_to_commerce_coordinator_checkout():
|
||||
return urljoin(settings.COMMERCE_COORDINATOR_URL_ROOT, settings.COORDINATOR_CHECKOUT_REDIRECT_PATH)
|
||||
return self.payment_page_url()
|
||||
|
||||
def get_checkout_page_url(self, *skus, **kwargs):
|
||||
""" Construct the URL to the ecommerce checkout page and include products.
|
||||
|
||||
|
||||
29
lms/djangoapps/commerce/waffle.py
Normal file
29
lms/djangoapps/commerce/waffle.py
Normal file
@@ -0,0 +1,29 @@
|
||||
"""
|
||||
Configuration for features of Commerce App
|
||||
"""
|
||||
from edx_toggles.toggles import WaffleFlag
|
||||
|
||||
# Namespace for Commerce waffle flags.
|
||||
WAFFLE_FLAG_NAMESPACE = "commerce"
|
||||
|
||||
# .. toggle_name: commerce.transition_to_coordinator.checkout
|
||||
# .. toggle_implementation: WaffleFlag
|
||||
# .. toggle_default: False
|
||||
# .. toggle_description: Allows to redirect checkout to Commerce Coordinator API
|
||||
# .. toggle_use_cases: temporary
|
||||
# .. toggle_creation_date: 2023-11-22
|
||||
# .. toggle_target_removal_date: TBA
|
||||
# .. toggle_tickets: SONIC-99
|
||||
# .. toggle_status: supported
|
||||
ENABLE_TRANSITION_TO_COORDINATOR_CHECKOUT = WaffleFlag(
|
||||
f"{WAFFLE_FLAG_NAMESPACE}.transition_to_coordinator.checkout",
|
||||
__name__,
|
||||
)
|
||||
|
||||
|
||||
def should_redirect_to_commerce_coordinator_checkout():
|
||||
"""
|
||||
Redirect learners to Commerce coordinator checkout.
|
||||
|
||||
"""
|
||||
return ENABLE_TRANSITION_TO_COORDINATOR_CHECKOUT.is_enabled()
|
||||
@@ -4225,6 +4225,10 @@ ECOMMERCE_ORDERS_API_CACHE_TIMEOUT = 3600
|
||||
ECOMMERCE_SERVICE_WORKER_USERNAME = 'ecommerce_worker'
|
||||
ECOMMERCE_API_SIGNING_KEY = 'SET-ME-PLEASE'
|
||||
|
||||
# E-Commerce Commerce Coordinator Configuration
|
||||
COMMERCE_COORDINATOR_URL_ROOT = 'http://localhost:8000'
|
||||
COORDINATOR_CHECKOUT_REDIRECT_PATH = '/lms/redirect/'
|
||||
|
||||
# Exam Service
|
||||
EXAMS_SERVICE_URL = 'http://localhost:18740/api/v1'
|
||||
|
||||
|
||||
@@ -45,7 +45,8 @@ from openedx.core.djangolib.markup import HTML, Text
|
||||
$('button[name=verified_mode]').click(function(e){
|
||||
e.preventDefault();
|
||||
window.location.href = '${ecommerce_payment_page | n, js_escaped_string}?sku=' +
|
||||
encodeURIComponent('${sku | n, js_escaped_string}');
|
||||
encodeURIComponent('${sku | n, js_escaped_string}') +
|
||||
'&course_run_key=' + encodeURIComponent('${course_run_key | n, js_escaped_string}');
|
||||
});
|
||||
% endif
|
||||
});
|
||||
|
||||
@@ -21,7 +21,8 @@ from openedx.core.djangolib.js_utils import js_escaped_string
|
||||
$('button[name=verified_mode]').click(function(e){
|
||||
e.preventDefault();
|
||||
window.location.href = '${ecommerce_payment_page | n, js_escaped_string}?sku=' +
|
||||
encodeURIComponent('${sku | n, js_escaped_string}');
|
||||
encodeURIComponent('${sku | n, js_escaped_string}') +
|
||||
'&course_run_key=' + encodeURIComponent('${course_run_key | n, js_escaped_string}');
|
||||
});
|
||||
});
|
||||
% endif
|
||||
|
||||
Reference in New Issue
Block a user