Merge pull request #14304 from edx/asadiqbal08/WL-606
WL-606: Coupon Creation UI should not display for Otto courses
This commit is contained in:
@@ -272,6 +272,7 @@ def create_mode(request, course_id):
|
||||
`min_price` (int): The minimum price a user must pay to enroll in the new course mode
|
||||
`suggested_prices` (str): Comma-separated prices to suggest to the user.
|
||||
`currency` (str): The currency in which to list prices.
|
||||
`sku` (str): The product SKU value.
|
||||
|
||||
By default, this endpoint will create an 'honor' mode for the given course with display name
|
||||
'Honor Code', a minimum price of 0, no suggested prices, and using USD as the currency.
|
||||
@@ -289,6 +290,7 @@ def create_mode(request, course_id):
|
||||
'min_price': 0,
|
||||
'suggested_prices': u'',
|
||||
'currency': u'usd',
|
||||
'sku': None,
|
||||
}
|
||||
|
||||
# Try pulling querystring parameters out of the request
|
||||
|
||||
@@ -14,7 +14,8 @@ class ModeCreationPage(PageObject):
|
||||
created for an existing course.
|
||||
"""
|
||||
|
||||
def __init__(self, browser, course_id, mode_slug=None, mode_display_name=None, min_price=None, suggested_prices=None, currency=None):
|
||||
def __init__(self, browser, course_id, mode_slug=None, mode_display_name=None, min_price=None,
|
||||
suggested_prices=None, currency=None, sku=None):
|
||||
"""The mode creation page is an endpoint for HTTP GET requests.
|
||||
|
||||
By default, it will create an 'honor' mode for the given course with display name
|
||||
@@ -30,6 +31,7 @@ class ModeCreationPage(PageObject):
|
||||
min_price (int): The minimum price a user must pay to enroll in the new course mode
|
||||
suggested_prices (str): Comma-separated prices to suggest to the user.
|
||||
currency (str): The currency in which to list prices.
|
||||
sku (str): The product SKU value.
|
||||
"""
|
||||
super(ModeCreationPage, self).__init__(browser)
|
||||
|
||||
@@ -51,6 +53,9 @@ class ModeCreationPage(PageObject):
|
||||
if currency is not None:
|
||||
self._parameters['currency'] = currency
|
||||
|
||||
if sku is not None:
|
||||
self._parameters['sku'] = sku
|
||||
|
||||
@property
|
||||
def url(self):
|
||||
"""Construct the mode creation URL."""
|
||||
|
||||
@@ -92,6 +92,15 @@ class InstructorDashboardPage(CoursePage):
|
||||
email_section.wait_for_page()
|
||||
return email_section
|
||||
|
||||
def select_ecommerce_tab(self):
|
||||
"""
|
||||
Selects the E-commerce tab and returns an EcommercePage.
|
||||
"""
|
||||
self.q(css='[data-section="e-commerce"]').first.click()
|
||||
ecommerce_section = EcommercePage(self.browser)
|
||||
ecommerce_section.wait_for_page()
|
||||
return ecommerce_section
|
||||
|
||||
@staticmethod
|
||||
def get_asset_path(file_name):
|
||||
"""
|
||||
@@ -1416,3 +1425,19 @@ class CertificatesPage(PageObject):
|
||||
Returns the message (error/success) in "Certificate Invalidation" section.
|
||||
"""
|
||||
return self.get_selector('.certificate-invalidation-container div.message')
|
||||
|
||||
|
||||
class EcommercePage(PageObject):
|
||||
"""
|
||||
E-commerce section of the Instructor dashboard.
|
||||
"""
|
||||
url = None
|
||||
|
||||
def is_browser_on_page(self):
|
||||
return self.q(css='[data-section="e-commerce"].active-section').present
|
||||
|
||||
def get_sections_header_values(self):
|
||||
"""
|
||||
Returns a list of the headings text under div.
|
||||
"""
|
||||
return self.q(css="div.wrap h3").text
|
||||
|
||||
@@ -1202,3 +1202,112 @@ class CertificateInvalidationTest(BaseInstructorDashboardTest):
|
||||
'.certificates-wrapper'
|
||||
])
|
||||
self.certificates_section.a11y_audit.check_for_accessibility_errors()
|
||||
|
||||
|
||||
@attr(shard=10)
|
||||
class EcommerceTest(BaseInstructorDashboardTest):
|
||||
"""
|
||||
Bok Choy tests for the "E-Commerce" tab.
|
||||
"""
|
||||
def setUp(self):
|
||||
super(EcommerceTest, self).setUp()
|
||||
|
||||
def setup_course(self, course_number):
|
||||
"""
|
||||
Sets up the course
|
||||
"""
|
||||
self.course_info['number'] = course_number
|
||||
course_fixture = CourseFixture(
|
||||
self.course_info["org"],
|
||||
self.course_info["number"],
|
||||
self.course_info["run"],
|
||||
self.course_info["display_name"]
|
||||
)
|
||||
course_fixture.install()
|
||||
|
||||
def log_in_as_unique_user(self):
|
||||
"""
|
||||
Log in as a valid lms user.
|
||||
"""
|
||||
AutoAuthPage(
|
||||
self.browser,
|
||||
username="test_instructor",
|
||||
email="test_instructor@example.com",
|
||||
password="password",
|
||||
course_id=self.course_id
|
||||
).visit()
|
||||
|
||||
def visit_ecommerce_section(self):
|
||||
"""
|
||||
Log in to visit Instructor dashboard and click E-commerce tab
|
||||
"""
|
||||
self.log_in_as_unique_user()
|
||||
instructor_dashboard_page = self.visit_instructor_dashboard()
|
||||
return instructor_dashboard_page.select_ecommerce_tab()
|
||||
|
||||
def add_course_mode(self, sku_value=None):
|
||||
"""
|
||||
Add an honor mode to the course
|
||||
"""
|
||||
ModeCreationPage(browser=self.browser, course_id=self.course_id, mode_slug=u'honor', min_price=10,
|
||||
sku=sku_value).visit()
|
||||
|
||||
def test_enrollment_codes_section_visible_for_non_ecommerce_course(self):
|
||||
"""
|
||||
Test Enrollment Codes UI, under E-commerce Tab, should be visible in the Instructor Dashboard with non
|
||||
e-commerce course
|
||||
"""
|
||||
# Setup course
|
||||
non_ecommerce_course_number = "34039497242734583224814321005482849780"
|
||||
self.setup_course(non_ecommerce_course_number)
|
||||
|
||||
# Add an honor mode to the course
|
||||
self.add_course_mode()
|
||||
|
||||
# Log in and visit E-commerce section under Instructor dashboard
|
||||
self.assertIn(u'Enrollment Codes', self.visit_ecommerce_section().get_sections_header_values())
|
||||
|
||||
def test_coupon_codes_section_visible_for_non_ecommerce_course(self):
|
||||
"""
|
||||
Test Coupon Codes UI, under E-commerce Tab, should be visible in the Instructor Dashboard with non
|
||||
e-commerce course
|
||||
"""
|
||||
# Setup course
|
||||
non_ecommerce_course_number = "34039497242734583224814321005482849781"
|
||||
self.setup_course(non_ecommerce_course_number)
|
||||
|
||||
# Add an honor mode to the course
|
||||
self.add_course_mode()
|
||||
|
||||
# Log in and visit E-commerce section under Instructor dashboard
|
||||
self.assertIn(u'Coupon Code List', self.visit_ecommerce_section().get_sections_header_values())
|
||||
|
||||
def test_enrollment_codes_section_not_visible_for_ecommerce_course(self):
|
||||
"""
|
||||
Test Enrollment Codes UI, under E-commerce Tab, should not be visible in the Instructor Dashboard with
|
||||
e-commerce course
|
||||
"""
|
||||
# Setup course
|
||||
ecommerce_course_number = "34039497242734583224814321005482849782"
|
||||
self.setup_course(ecommerce_course_number)
|
||||
|
||||
# Add an honor mode to the course with sku value
|
||||
self.add_course_mode('test_sku')
|
||||
|
||||
# Log in and visit E-commerce section under Instructor dashboard
|
||||
self.assertNotIn(u'Enrollment Codes', self.visit_ecommerce_section().get_sections_header_values())
|
||||
|
||||
def test_coupon_codes_section_not_visible_for_ecommerce_course(self):
|
||||
"""
|
||||
Test Coupon Codes UI, under E-commerce Tab, should not be visible in the Instructor Dashboard with
|
||||
e-commerce course
|
||||
"""
|
||||
# Setup course
|
||||
ecommerce_course_number = "34039497242734583224814321005482849783"
|
||||
self.setup_course(ecommerce_course_number)
|
||||
|
||||
# Add an honor mode to the course with sku value
|
||||
self.add_course_mode('test_sku')
|
||||
|
||||
# Log in and visit E-commerce section under Instructor dashboard
|
||||
self.assertNotIn(u'Coupon Code List', self.visit_ecommerce_section().get_sections_header_values())
|
||||
|
||||
74
common/test/db_fixtures/course_access_role.json
Normal file
74
common/test/db_fixtures/course_access_role.json
Normal file
@@ -0,0 +1,74 @@
|
||||
[
|
||||
{
|
||||
"pk": 1,
|
||||
"model": "auth.user",
|
||||
"fields": {
|
||||
"username": "test_instructor",
|
||||
"email":"test_instructor@example.com",
|
||||
"password": "password",
|
||||
"is_staff": true,
|
||||
"is_active": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 1,
|
||||
"model": "student.userprofile",
|
||||
"fields": {
|
||||
"user": 1,
|
||||
"name": "test instructor",
|
||||
"courseware": "course.xml"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 1,
|
||||
"model": "student.registration",
|
||||
"fields": {
|
||||
"user": 1,
|
||||
"activation_key": "52bfac10384d49219385dcd4cc17177q"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 1,
|
||||
"model": "student.courseaccessrole",
|
||||
"fields": {
|
||||
"id": "1",
|
||||
"org": "test_org",
|
||||
"course_id": "course-v1:test_org+34039497242734583224814321005482849780+test_run",
|
||||
"role": "finance_admin",
|
||||
"user_id": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 2,
|
||||
"model": "student.courseaccessrole",
|
||||
"fields": {
|
||||
"id": "2",
|
||||
"org": "test_org",
|
||||
"course_id": "course-v1:test_org+34039497242734583224814321005482849781+test_run",
|
||||
"role": "finance_admin",
|
||||
"user_id": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 3,
|
||||
"model": "student.courseaccessrole",
|
||||
"fields": {
|
||||
"id": "3",
|
||||
"org": "test_org",
|
||||
"course_id": "course-v1:test_org+34039497242734583224814321005482849782+test_run",
|
||||
"role": "finance_admin",
|
||||
"user_id": "1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"pk": 4,
|
||||
"model": "student.courseaccessrole",
|
||||
"fields": {
|
||||
"id": "4",
|
||||
"org": "test_org",
|
||||
"course_id": "course-v1:test_org+34039497242734583224814321005482849783+test_run",
|
||||
"role": "finance_admin",
|
||||
"user_id": "1"
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -30,7 +30,7 @@ class TestECommerceDashboardViews(SiteMixin, SharedModuleStoreTestCase):
|
||||
|
||||
# URL for instructor dash
|
||||
cls.url = reverse('instructor_dashboard', kwargs={'course_id': cls.course.id.to_deprecated_string()})
|
||||
cls.e_commerce_link = '<button type="button" class="btn-link" data-section="e-commerce">E-Commerce</button>'
|
||||
cls.ecommerce_link = '<button type="button" class="btn-link" data-section="e-commerce">E-Commerce</button>'
|
||||
|
||||
def setUp(self):
|
||||
super(TestECommerceDashboardViews, self).setUp()
|
||||
@@ -50,7 +50,7 @@ class TestECommerceDashboardViews(SiteMixin, SharedModuleStoreTestCase):
|
||||
Test Pass E-commerce Tab is in the Instructor Dashboard
|
||||
"""
|
||||
response = self.client.get(self.url)
|
||||
self.assertIn(self.e_commerce_link, response.content)
|
||||
self.assertIn(self.ecommerce_link, response.content)
|
||||
# Coupons should show up for White Label sites with priced honor modes.
|
||||
self.assertIn('Coupon Code List', response.content)
|
||||
|
||||
@@ -61,7 +61,7 @@ class TestECommerceDashboardViews(SiteMixin, SharedModuleStoreTestCase):
|
||||
self.use_site(site=self.site_other)
|
||||
self.client.login(username=self.instructor.username, password="test")
|
||||
response = self.client.get(self.url)
|
||||
self.assertIn(self.e_commerce_link, response.content)
|
||||
self.assertIn(self.ecommerce_link, response.content)
|
||||
self.assertIn('Create Enrollment Report', response.content)
|
||||
|
||||
def test_reports_section_not_under_e_commerce_tab(self):
|
||||
@@ -70,12 +70,12 @@ class TestECommerceDashboardViews(SiteMixin, SharedModuleStoreTestCase):
|
||||
value
|
||||
"""
|
||||
response = self.client.get(self.url)
|
||||
self.assertIn(self.e_commerce_link, response.content)
|
||||
self.assertIn(self.ecommerce_link, response.content)
|
||||
self.assertNotIn('Create Enrollment Report', response.content)
|
||||
|
||||
def test_user_has_finance_admin_rights_in_e_commerce_tab(self):
|
||||
response = self.client.get(self.url)
|
||||
self.assertIn(self.e_commerce_link, response.content)
|
||||
self.assertIn(self.ecommerce_link, response.content)
|
||||
|
||||
# Order/Invoice sales csv button text should render in e-commerce page
|
||||
self.assertIn('Total Credit Card Purchases', response.content)
|
||||
@@ -96,7 +96,7 @@ class TestECommerceDashboardViews(SiteMixin, SharedModuleStoreTestCase):
|
||||
the instructor dashboard
|
||||
"""
|
||||
response = self.client.get(self.url)
|
||||
self.assertIn(self.e_commerce_link, response.content)
|
||||
self.assertIn(self.ecommerce_link, response.content)
|
||||
|
||||
# Total amount html should render in e-commerce page, total amount will be 0
|
||||
course_honor_mode = CourseMode.mode_for_course(self.course.id, 'honor')
|
||||
@@ -351,6 +351,39 @@ class TestECommerceDashboardViews(SiteMixin, SharedModuleStoreTestCase):
|
||||
|
||||
# Get the response value, ensure the Coupon section is not included.
|
||||
response = self.client.get(self.url)
|
||||
self.assertIn(self.e_commerce_link, response.content)
|
||||
self.assertIn(self.ecommerce_link, response.content)
|
||||
# Coupons should show up for White Label sites with priced honor modes.
|
||||
self.assertNotIn('Coupons List', response.content)
|
||||
|
||||
def test_coupon_code_section_not_under_e_commerce_tab(self):
|
||||
"""
|
||||
Test Coupon Creation UI, under E-commerce Tab, should not be available in the Instructor Dashboard with
|
||||
e-commerce course
|
||||
"""
|
||||
# Setup e-commerce course
|
||||
CourseMode.objects.filter(course_id=self.course.id).update(sku='test_sku')
|
||||
|
||||
response = self.client.get(self.url)
|
||||
self.assertIn(self.ecommerce_link, response.content)
|
||||
self.assertNotIn('Coupon Code List', response.content)
|
||||
|
||||
def test_enrollment_codes_section_not_under_e_commerce_tab(self):
|
||||
"""
|
||||
Test Enrollment Codes UI, under E-commerce Tab, should not be available in the Instructor Dashboard with
|
||||
e-commerce course
|
||||
"""
|
||||
# Setup e-commerce course
|
||||
CourseMode.objects.filter(course_id=self.course.id).update(sku='test_sku')
|
||||
|
||||
response = self.client.get(self.url)
|
||||
self.assertIn(self.ecommerce_link, response.content)
|
||||
self.assertNotIn('<h3 class="hd hd-3">Enrollment Codes</h3>', response.content)
|
||||
|
||||
def test_enrollment_codes_section_visible_for_non_ecommerce_course(self):
|
||||
"""
|
||||
Test Enrollment Codes UI, under E-commerce Tab, should be available in the Instructor Dashboard with non
|
||||
e-commerce course
|
||||
"""
|
||||
response = self.client.get(self.url)
|
||||
self.assertIn(self.ecommerce_link, response.content)
|
||||
self.assertIn('<h3 class="hd hd-3">Enrollment Codes</h3>', response.content)
|
||||
|
||||
@@ -285,7 +285,8 @@ def _section_e_commerce(course, access, paid_mode, coupons_enabled, reports_enab
|
||||
'coupons_enabled': coupons_enabled,
|
||||
'reports_enabled': reports_enabled,
|
||||
'course_price': course_price,
|
||||
'total_amount': total_amount
|
||||
'total_amount': total_amount,
|
||||
'is_ecommerce_course': is_ecommerce_course(course_key)
|
||||
}
|
||||
return section_data
|
||||
|
||||
@@ -695,3 +696,12 @@ def _section_metrics(course, access):
|
||||
'post_metrics_data_csv_url': reverse('post_metrics_data_csv'),
|
||||
}
|
||||
return section_data
|
||||
|
||||
|
||||
def is_ecommerce_course(course_key):
|
||||
"""
|
||||
Checks if the given course is an e-commerce course or not, by checking its SKU value from
|
||||
CourseMode records for the course
|
||||
"""
|
||||
sku_count = len([mode.sku for mode in CourseMode.modes_for_course(course_key) if mode.sku])
|
||||
return sku_count > 0
|
||||
|
||||
@@ -14,7 +14,8 @@ import pytz
|
||||
<div class="ecommerce-wrapper">
|
||||
<div class="error-msgs" id="error-msg"></div>
|
||||
<div id = "accordion">
|
||||
<div class="wrap">
|
||||
%if not section_data['is_ecommerce_course']:
|
||||
<div class="wrap">
|
||||
<h3 class="hd hd-3">${_('Enrollment Codes')}</h3>
|
||||
<div>
|
||||
%if section_data['sales_admin']:
|
||||
@@ -53,6 +54,7 @@ import pytz
|
||||
<a id="registration_code_generation_link-trigger" href="#registration_code_generation_modal" rel="leanModal"></a>
|
||||
</div>
|
||||
</div>
|
||||
%endif
|
||||
<!-- end wrap -->
|
||||
%if section_data['coupons_enabled']:
|
||||
<div class="wrap">
|
||||
@@ -145,7 +147,7 @@ import pytz
|
||||
</div>
|
||||
</div><!-- end wrap -->
|
||||
%endif
|
||||
%if section_data['coupons_enabled']:
|
||||
%if section_data['coupons_enabled'] and not section_data['is_ecommerce_course']:
|
||||
<div class="wrap">
|
||||
<h3 class="hd hd-3">${_("Coupon Code List")}</h3>
|
||||
<div>
|
||||
|
||||
Reference in New Issue
Block a user