Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
198d33dc
Commit
198d33dc
authored
Nov 19, 2015
by
Awais
Committed by
Awais Qureshi
Dec 04, 2015
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
New AB Testing URL for checkout page.
ECOM-2866
parent
068b439a
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
605 additions
and
61 deletions
+605
-61
lms/djangoapps/verify_student/tests/test_views.py
+121
-56
lms/djangoapps/verify_student/urls.py
+10
-0
lms/djangoapps/verify_student/views.py
+2
-0
lms/static/images/icon-sm-professional.png
+0
-0
lms/static/js/spec/main.js
+1
-0
lms/static/js/spec/verify_student/make_payment_step_view_ab_testing_spec.js
+225
-0
lms/static/js/spec/verify_student/make_payment_step_view_spec.js
+7
-0
lms/static/js/verify_student/pay_and_verify.js
+2
-1
lms/static/js/verify_student/views/make_payment_step_view.js
+13
-3
lms/static/sass/views/_verification.scss
+111
-0
lms/templates/verify_student/make_payment_step_ab_testing.underscore
+105
-0
lms/templates/verify_student/pay_and_verify.html
+8
-1
No files found.
lms/djangoapps/verify_student/tests/test_views.py
View file @
198d33dc
...
@@ -102,11 +102,17 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
...
@@ -102,11 +102,17 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
result
=
self
.
client
.
login
(
username
=
self
.
USERNAME
,
password
=
self
.
PASSWORD
)
result
=
self
.
client
.
login
(
username
=
self
.
USERNAME
,
password
=
self
.
PASSWORD
)
self
.
assertTrue
(
result
,
msg
=
"Could not log in"
)
self
.
assertTrue
(
result
,
msg
=
"Could not log in"
)
@ddt.data
(
"verified"
,
"professional"
)
@ddt.data
(
def
test_start_flow_not_verified
(
self
,
course_mode
):
(
"verified"
,
"verify_student_start_flow"
),
(
"professional"
,
"verify_student_start_flow"
),
(
"verified"
,
"verify_student_begin_flow"
),
(
"professional"
,
"verify_student_begin_flow"
)
)
@ddt.unpack
def
test_start_flow_not_verified
(
self
,
course_mode
,
payment_flow
):
course
=
self
.
_create_course
(
course_mode
)
course
=
self
.
_create_course
(
course_mode
)
self
.
_enroll
(
course
.
id
)
self
.
_enroll
(
course
.
id
)
response
=
self
.
_get_page
(
'verify_student_start_flow'
,
course
.
id
)
response
=
self
.
_get_page
(
payment_flow
,
course
.
id
)
self
.
_assert_displayed_mode
(
response
,
course_mode
)
self
.
_assert_displayed_mode
(
response
,
course_mode
)
self
.
_assert_steps_displayed
(
self
.
_assert_steps_displayed
(
response
,
response
,
...
@@ -120,11 +126,15 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
...
@@ -120,11 +126,15 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
])
])
self
.
_assert_upgrade_session_flag
(
False
)
self
.
_assert_upgrade_session_flag
(
False
)
@ddt.data
(
"no-id-professional"
)
@ddt.data
(
def
test_start_flow_with_no_id_professional
(
self
,
course_mode
):
(
"no-id-professional"
,
"verify_student_start_flow"
),
(
"no-id-professional"
,
"verify_student_begin_flow"
)
)
@ddt.unpack
def
test_start_flow_with_no_id_professional
(
self
,
course_mode
,
payment_flow
):
course
=
self
.
_create_course
(
course_mode
)
course
=
self
.
_create_course
(
course_mode
)
self
.
_enroll
(
course
.
id
)
self
.
_enroll
(
course
.
id
)
response
=
self
.
_get_page
(
'verify_student_start_flow'
,
course
.
id
)
response
=
self
.
_get_page
(
payment_flow
,
course
.
id
)
self
.
_assert_displayed_mode
(
response
,
course_mode
)
self
.
_assert_displayed_mode
(
response
,
course_mode
)
self
.
_assert_steps_displayed
(
self
.
_assert_steps_displayed
(
response
,
response
,
...
@@ -134,12 +144,26 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
...
@@ -134,12 +144,26 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
self
.
_assert_messaging
(
response
,
PayAndVerifyView
.
FIRST_TIME_VERIFY_MSG
)
self
.
_assert_messaging
(
response
,
PayAndVerifyView
.
FIRST_TIME_VERIFY_MSG
)
self
.
_assert_requirements_displayed
(
response
,
[])
self
.
_assert_requirements_displayed
(
response
,
[])
@ddt.data
(
"expired"
,
"denied"
)
def
test_ab_testing_page
(
self
):
def
test_start_flow_expired_or_denied_verification
(
self
,
verification_status
):
course
=
self
.
_create_course
(
"verified"
)
self
.
_enroll
(
course
.
id
,
"verified"
)
response
=
self
.
_get_page
(
"verify_student_begin_flow"
,
course
.
id
)
self
.
_assert_displayed_mode
(
response
,
"verified"
)
self
.
assertContains
(
response
,
"Upgrade to a Verified Certificate"
)
self
.
assertContains
(
response
,
"Before you upgrade to a certificate track,"
)
self
.
assertContains
(
response
,
"To receive a certificate, you must also verify your identity"
)
self
.
assertContains
(
response
,
"You will use your webcam to take a picture of"
)
@ddt.data
(
(
"expired"
,
"verify_student_start_flow"
),
(
"denied"
,
"verify_student_begin_flow"
)
)
@ddt.unpack
def
test_start_flow_expired_or_denied_verification
(
self
,
verification_status
,
payment_flow
):
course
=
self
.
_create_course
(
"verified"
)
course
=
self
.
_create_course
(
"verified"
)
self
.
_enroll
(
course
.
id
,
"verified"
)
self
.
_enroll
(
course
.
id
,
"verified"
)
self
.
_set_verification_status
(
verification_status
)
self
.
_set_verification_status
(
verification_status
)
response
=
self
.
_get_page
(
'verify_student_start_flow'
,
course
.
id
)
response
=
self
.
_get_page
(
payment_flow
,
course
.
id
)
# Expect the same content as when the user has not verified
# Expect the same content as when the user has not verified
self
.
_assert_steps_displayed
(
self
.
_assert_steps_displayed
(
...
@@ -154,18 +178,24 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
...
@@ -154,18 +178,24 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
])
])
@ddt.data
(
@ddt.data
(
(
"verified"
,
"submitted"
),
(
"verified"
,
"submitted"
,
"verify_student_start_flow"
),
(
"verified"
,
"approved"
),
(
"verified"
,
"approved"
,
"verify_student_start_flow"
),
(
"verified"
,
"error"
),
(
"verified"
,
"error"
,
"verify_student_start_flow"
),
(
"professional"
,
"submitted"
),
(
"professional"
,
"submitted"
,
"verify_student_start_flow"
),
(
"no-id-professional"
,
None
),
(
"no-id-professional"
,
None
,
"verify_student_start_flow"
),
(
"verified"
,
"submitted"
,
"verify_student_begin_flow"
),
(
"verified"
,
"approved"
,
"verify_student_begin_flow"
),
(
"verified"
,
"error"
,
"verify_student_begin_flow"
),
(
"professional"
,
"submitted"
,
"verify_student_begin_flow"
),
(
"no-id-professional"
,
None
,
"verify_student_begin_flow"
),
)
)
@ddt.unpack
@ddt.unpack
def
test_start_flow_already_verified
(
self
,
course_mode
,
verification_status
):
def
test_start_flow_already_verified
(
self
,
course_mode
,
verification_status
,
payment_flow
):
course
=
self
.
_create_course
(
course_mode
)
course
=
self
.
_create_course
(
course_mode
)
self
.
_enroll
(
course
.
id
)
self
.
_enroll
(
course
.
id
)
self
.
_set_verification_status
(
verification_status
)
self
.
_set_verification_status
(
verification_status
)
response
=
self
.
_get_page
(
'verify_student_start_flow'
,
course
.
id
)
response
=
self
.
_get_page
(
payment_flow
,
course
.
id
)
self
.
_assert_displayed_mode
(
response
,
course_mode
)
self
.
_assert_displayed_mode
(
response
,
course_mode
)
self
.
_assert_steps_displayed
(
self
.
_assert_steps_displayed
(
response
,
response
,
...
@@ -175,11 +205,17 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
...
@@ -175,11 +205,17 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
self
.
_assert_messaging
(
response
,
PayAndVerifyView
.
FIRST_TIME_VERIFY_MSG
)
self
.
_assert_messaging
(
response
,
PayAndVerifyView
.
FIRST_TIME_VERIFY_MSG
)
self
.
_assert_requirements_displayed
(
response
,
[])
self
.
_assert_requirements_displayed
(
response
,
[])
@ddt.data
(
"verified"
,
"professional"
)
@ddt.data
(
def
test_start_flow_already_paid
(
self
,
course_mode
):
(
"verified"
,
"verify_student_start_flow"
),
(
"professional"
,
"verify_student_start_flow"
),
(
"verified"
,
"verify_student_begin_flow"
),
(
"professional"
,
"verify_student_begin_flow"
)
)
@ddt.unpack
def
test_start_flow_already_paid
(
self
,
course_mode
,
payment_flow
):
course
=
self
.
_create_course
(
course_mode
)
course
=
self
.
_create_course
(
course_mode
)
self
.
_enroll
(
course
.
id
,
course_mode
)
self
.
_enroll
(
course
.
id
,
course_mode
)
response
=
self
.
_get_page
(
'verify_student_start_flow'
,
course
.
id
)
response
=
self
.
_get_page
(
payment_flow
,
course
.
id
)
self
.
_assert_displayed_mode
(
response
,
course_mode
)
self
.
_assert_displayed_mode
(
response
,
course_mode
)
self
.
_assert_steps_displayed
(
self
.
_assert_steps_displayed
(
response
,
response
,
...
@@ -192,15 +228,16 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
...
@@ -192,15 +228,16 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
PayAndVerifyView
.
WEBCAM_REQ
,
PayAndVerifyView
.
WEBCAM_REQ
,
])
])
def
test_start_flow_not_enrolled
(
self
):
@ddt.data
(
"verify_student_start_flow"
,
"verify_student_begin_flow"
)
def
test_start_flow_not_enrolled
(
self
,
payment_flow
):
course
=
self
.
_create_course
(
"verified"
)
course
=
self
.
_create_course
(
"verified"
)
self
.
_set_verification_status
(
"submitted"
)
self
.
_set_verification_status
(
"submitted"
)
response
=
self
.
_get_page
(
'verify_student_start_flow'
,
course
.
id
)
response
=
self
.
_get_page
(
payment_flow
,
course
.
id
)
# This shouldn't happen if the student has been auto-enrolled,
# This shouldn't happen if the student has been auto-enrolled,
# but if they somehow end up on this page without enrolling,
# but if they somehow end up on this page without enrolling,
# treat them as if they need to pay
# treat them as if they need to pay
response
=
self
.
_get_page
(
'verify_student_start_flow'
,
course
.
id
)
response
=
self
.
_get_page
(
payment_flow
,
course
.
id
)
self
.
_assert_steps_displayed
(
self
.
_assert_steps_displayed
(
response
,
response
,
PayAndVerifyView
.
PAYMENT_STEPS
,
PayAndVerifyView
.
PAYMENT_STEPS
,
...
@@ -208,7 +245,8 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
...
@@ -208,7 +245,8 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
)
)
self
.
_assert_requirements_displayed
(
response
,
[])
self
.
_assert_requirements_displayed
(
response
,
[])
def
test_start_flow_unenrolled
(
self
):
@ddt.data
(
"verify_student_start_flow"
,
"verify_student_begin_flow"
)
def
test_start_flow_unenrolled
(
self
,
payment_flow
):
course
=
self
.
_create_course
(
"verified"
)
course
=
self
.
_create_course
(
"verified"
)
self
.
_set_verification_status
(
"submitted"
)
self
.
_set_verification_status
(
"submitted"
)
self
.
_enroll
(
course
.
id
,
"verified"
)
self
.
_enroll
(
course
.
id
,
"verified"
)
...
@@ -216,7 +254,7 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
...
@@ -216,7 +254,7 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
# If unenrolled, treat them like they haven't paid at all
# If unenrolled, treat them like they haven't paid at all
# (we assume that they've gotten a refund or didn't pay initially)
# (we assume that they've gotten a refund or didn't pay initially)
response
=
self
.
_get_page
(
'verify_student_start_flow'
,
course
.
id
)
response
=
self
.
_get_page
(
payment_flow
,
course
.
id
)
self
.
_assert_steps_displayed
(
self
.
_assert_steps_displayed
(
response
,
response
,
PayAndVerifyView
.
PAYMENT_STEPS
,
PayAndVerifyView
.
PAYMENT_STEPS
,
...
@@ -225,27 +263,31 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
...
@@ -225,27 +263,31 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
self
.
_assert_requirements_displayed
(
response
,
[])
self
.
_assert_requirements_displayed
(
response
,
[])
@ddt.data
(
@ddt.data
(
(
"verified"
,
"submitted"
),
(
"verified"
,
"submitted"
,
"verify_student_start_flow"
),
(
"verified"
,
"approved"
),
(
"verified"
,
"approved"
,
"verify_student_start_flow"
),
(
"professional"
,
"submitted"
)
(
"professional"
,
"submitted"
,
"verify_student_start_flow"
),
(
"verified"
,
"submitted"
,
"verify_student_begin_flow"
),
(
"verified"
,
"approved"
,
"verify_student_begin_flow"
),
(
"professional"
,
"submitted"
,
"verify_student_begin_flow"
)
)
)
@ddt.unpack
@ddt.unpack
def
test_start_flow_already_verified_and_paid
(
self
,
course_mode
,
verification_status
):
def
test_start_flow_already_verified_and_paid
(
self
,
course_mode
,
verification_status
,
payment_flow
):
course
=
self
.
_create_course
(
course_mode
)
course
=
self
.
_create_course
(
course_mode
)
self
.
_enroll
(
course
.
id
,
course_mode
)
self
.
_enroll
(
course
.
id
,
course_mode
)
self
.
_set_verification_status
(
verification_status
)
self
.
_set_verification_status
(
verification_status
)
response
=
self
.
_get_page
(
response
=
self
.
_get_page
(
'verify_student_start_flow'
,
payment_flow
,
course
.
id
,
course
.
id
,
expected_status_code
=
302
expected_status_code
=
302
)
)
self
.
_assert_redirects_to_dashboard
(
response
)
self
.
_assert_redirects_to_dashboard
(
response
)
@patch.dict
(
settings
.
FEATURES
,
{
"IS_EDX_DOMAIN"
:
True
})
@patch.dict
(
settings
.
FEATURES
,
{
"IS_EDX_DOMAIN"
:
True
})
def
test_pay_and_verify_hides_header_nav
(
self
):
@ddt.data
(
"verify_student_start_flow"
,
"verify_student_begin_flow"
)
def
test_pay_and_verify_hides_header_nav
(
self
,
payment_flow
):
course
=
self
.
_create_course
(
"verified"
)
course
=
self
.
_create_course
(
"verified"
)
self
.
_enroll
(
course
.
id
,
"verified"
)
self
.
_enroll
(
course
.
id
,
"verified"
)
response
=
self
.
_get_page
(
'verify_student_start_flow'
,
course
.
id
)
response
=
self
.
_get_page
(
payment_flow
,
course
.
id
)
# Verify that the header navigation links are hidden for the edx.org version
# Verify that the header navigation links are hidden for the edx.org version
self
.
assertNotContains
(
response
,
"How it Works"
)
self
.
assertNotContains
(
response
,
"How it Works"
)
...
@@ -351,7 +393,8 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
...
@@ -351,7 +393,8 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
PayAndVerifyView
.
WEBCAM_REQ
,
PayAndVerifyView
.
WEBCAM_REQ
,
])
])
def
test_payment_cannot_skip
(
self
):
@ddt.data
(
"verify_student_start_flow"
,
"verify_student_begin_flow"
)
def
test_payment_cannot_skip
(
self
,
payment_flow
):
"""
"""
Simple test to verify that certain steps cannot be skipped. This test sets up
Simple test to verify that certain steps cannot be skipped. This test sets up
a scenario where the user should be on the MAKE_PAYMENT_STEP, but is trying to
a scenario where the user should be on the MAKE_PAYMENT_STEP, but is trying to
...
@@ -360,7 +403,7 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
...
@@ -360,7 +403,7 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
"""
"""
course
=
self
.
_create_course
(
"verified"
)
course
=
self
.
_create_course
(
"verified"
)
response
=
self
.
_get_page
(
response
=
self
.
_get_page
(
'verify_student_start_flow'
,
payment_flow
,
course
.
id
,
course
.
id
,
skip_first_step
=
True
skip_first_step
=
True
)
)
...
@@ -523,6 +566,7 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
...
@@ -523,6 +566,7 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
pages
=
[
pages
=
[
'verify_student_start_flow'
,
'verify_student_start_flow'
,
'verify_student_begin_flow'
,
'verify_student_verify_now'
,
'verify_student_verify_now'
,
'verify_student_upgrade_and_verify'
,
'verify_student_upgrade_and_verify'
,
]
]
...
@@ -534,16 +578,25 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
...
@@ -534,16 +578,25 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
expected_status_code
=
404
expected_status_code
=
404
)
)
@ddt.data
([],
[
"no-id-professional"
,
"professional"
],
[
"honor"
,
"audit"
])
@ddt.data
(
def
test_no_id_professional_entry_point
(
self
,
modes_available
):
([],
"verify_student_start_flow"
),
([
"no-id-professional"
,
"professional"
],
"verify_student_start_flow"
),
([
"honor"
,
"audit"
],
"verify_student_start_flow"
),
([],
"verify_student_begin_flow"
),
([
"no-id-professional"
,
"professional"
],
"verify_student_begin_flow"
),
([
"honor"
,
"audit"
],
"verify_student_begin_flow"
),
)
@ddt.unpack
def
test_no_id_professional_entry_point
(
self
,
modes_available
,
payment_flow
):
course
=
self
.
_create_course
(
*
modes_available
)
course
=
self
.
_create_course
(
*
modes_available
)
if
"no-id-professional"
in
modes_available
or
"professional"
in
modes_available
:
if
"no-id-professional"
in
modes_available
or
"professional"
in
modes_available
:
self
.
_get_page
(
"verify_student_start_flow"
,
course
.
id
,
expected_status_code
=
200
)
self
.
_get_page
(
payment_flow
,
course
.
id
,
expected_status_code
=
200
)
else
:
else
:
self
.
_get_page
(
"verify_student_start_flow"
,
course
.
id
,
expected_status_code
=
404
)
self
.
_get_page
(
payment_flow
,
course
.
id
,
expected_status_code
=
404
)
@ddt.data
(
@ddt.data
(
"verify_student_start_flow"
,
"verify_student_start_flow"
,
"verify_student_begin_flow"
,
"verify_student_verify_now"
,
"verify_student_verify_now"
,
"verify_student_upgrade_and_verify"
,
"verify_student_upgrade_and_verify"
,
)
)
...
@@ -561,6 +614,7 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
...
@@ -561,6 +614,7 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
@ddt.data
(
@ddt.data
(
"verify_student_start_flow"
,
"verify_student_start_flow"
,
"verify_student_begin_flow"
,
"verify_student_verify_now"
,
"verify_student_verify_now"
,
"verify_student_upgrade_and_verify"
,
"verify_student_upgrade_and_verify"
,
)
)
...
@@ -572,11 +626,12 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
...
@@ -572,11 +626,12 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
expected_status_code
=
404
expected_status_code
=
404
)
)
def
test_account_not_active
(
self
):
@ddt.data
(
"verify_student_start_flow"
,
"verify_student_begin_flow"
)
def
test_account_not_active
(
self
,
payment_flow
):
self
.
user
.
is_active
=
False
self
.
user
.
is_active
=
False
self
.
user
.
save
()
self
.
user
.
save
()
course
=
self
.
_create_course
(
"verified"
)
course
=
self
.
_create_course
(
"verified"
)
response
=
self
.
_get_page
(
'verify_student_start_flow'
,
course
.
id
)
response
=
self
.
_get_page
(
payment_flow
,
course
.
id
)
self
.
_assert_steps_displayed
(
self
.
_assert_steps_displayed
(
response
,
response
,
PayAndVerifyView
.
PAYMENT_STEPS
+
PayAndVerifyView
.
VERIFICATION_STEPS
,
PayAndVerifyView
.
PAYMENT_STEPS
+
PayAndVerifyView
.
VERIFICATION_STEPS
,
...
@@ -588,32 +643,36 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
...
@@ -588,32 +643,36 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
PayAndVerifyView
.
WEBCAM_REQ
,
PayAndVerifyView
.
WEBCAM_REQ
,
])
])
def
test_no_contribution
(
self
):
@ddt.data
(
"verify_student_start_flow"
,
"verify_student_begin_flow"
)
def
test_no_contribution
(
self
,
payment_flow
):
# Do NOT specify a contribution for the course in a session var.
# Do NOT specify a contribution for the course in a session var.
course
=
self
.
_create_course
(
"verified"
)
course
=
self
.
_create_course
(
"verified"
)
response
=
self
.
_get_page
(
"verify_student_start_flow"
,
course
.
id
)
response
=
self
.
_get_page
(
payment_flow
,
course
.
id
)
self
.
_assert_contribution_amount
(
response
,
""
)
self
.
_assert_contribution_amount
(
response
,
""
)
def
test_contribution_other_course
(
self
):
@ddt.data
(
"verify_student_start_flow"
,
"verify_student_begin_flow"
)
def
test_contribution_other_course
(
self
,
payment_flow
):
# Specify a contribution amount for another course in the session
# Specify a contribution amount for another course in the session
course
=
self
.
_create_course
(
"verified"
)
course
=
self
.
_create_course
(
"verified"
)
other_course_id
=
CourseLocator
(
org
=
"other"
,
run
=
"test"
,
course
=
"test"
)
other_course_id
=
CourseLocator
(
org
=
"other"
,
run
=
"test"
,
course
=
"test"
)
self
.
_set_contribution
(
"12.34"
,
other_course_id
)
self
.
_set_contribution
(
"12.34"
,
other_course_id
)
# Expect that the contribution amount is NOT pre-filled,
# Expect that the contribution amount is NOT pre-filled,
response
=
self
.
_get_page
(
"verify_student_start_flow"
,
course
.
id
)
response
=
self
.
_get_page
(
payment_flow
,
course
.
id
)
self
.
_assert_contribution_amount
(
response
,
""
)
self
.
_assert_contribution_amount
(
response
,
""
)
def
test_contribution
(
self
):
@ddt.data
(
"verify_student_start_flow"
,
"verify_student_begin_flow"
)
def
test_contribution
(
self
,
payment_flow
):
# Specify a contribution amount for this course in the session
# Specify a contribution amount for this course in the session
course
=
self
.
_create_course
(
"verified"
)
course
=
self
.
_create_course
(
"verified"
)
self
.
_set_contribution
(
"12.34"
,
course
.
id
)
self
.
_set_contribution
(
"12.34"
,
course
.
id
)
# Expect that the contribution amount is pre-filled,
# Expect that the contribution amount is pre-filled,
response
=
self
.
_get_page
(
"verify_student_start_flow"
,
course
.
id
)
response
=
self
.
_get_page
(
payment_flow
,
course
.
id
)
self
.
_assert_contribution_amount
(
response
,
"12.34"
)
self
.
_assert_contribution_amount
(
response
,
"12.34"
)
def
test_verification_deadline
(
self
):
@ddt.data
(
"verify_student_start_flow"
,
"verify_student_begin_flow"
)
def
test_verification_deadline
(
self
,
payment_flow
):
deadline
=
datetime
(
2999
,
1
,
2
,
tzinfo
=
pytz
.
UTC
)
deadline
=
datetime
(
2999
,
1
,
2
,
tzinfo
=
pytz
.
UTC
)
course
=
self
.
_create_course
(
"verified"
)
course
=
self
.
_create_course
(
"verified"
)
...
@@ -625,7 +684,7 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
...
@@ -625,7 +684,7 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
self
.
_set_deadlines
(
course
.
id
,
upgrade_deadline
=
deadline
,
verification_deadline
=
deadline
)
self
.
_set_deadlines
(
course
.
id
,
upgrade_deadline
=
deadline
,
verification_deadline
=
deadline
)
# Expect that the expiration date is set
# Expect that the expiration date is set
response
=
self
.
_get_page
(
"verify_student_start_flow"
,
course
.
id
)
response
=
self
.
_get_page
(
payment_flow
,
course
.
id
)
data
=
self
.
_get_page_data
(
response
)
data
=
self
.
_get_page_data
(
response
)
self
.
assertEqual
(
data
[
'verification_deadline'
],
"Jan 02, 2999 at 00:00 UTC"
)
self
.
assertEqual
(
data
[
'verification_deadline'
],
"Jan 02, 2999 at 00:00 UTC"
)
...
@@ -661,7 +720,9 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
...
@@ -661,7 +720,9 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
# Try to pay or upgrade.
# Try to pay or upgrade.
# We should get an error message since the deadline has passed.
# We should get an error message since the deadline has passed.
for
page_name
in
[
"verify_student_start_flow"
,
"verify_student_upgrade_and_verify"
]:
for
page_name
in
[
"verify_student_start_flow"
,
"verify_student_begin_flow"
,
"verify_student_upgrade_and_verify"
]:
response
=
self
.
_get_page
(
page_name
,
course
.
id
)
response
=
self
.
_get_page
(
page_name
,
course
.
id
)
self
.
assertContains
(
response
,
"Upgrade Deadline Has Passed"
)
self
.
assertContains
(
response
,
"Upgrade Deadline Has Passed"
)
...
@@ -708,18 +769,20 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
...
@@ -708,18 +769,20 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
self
.
assertContains
(
response
,
"Jan 02, 1999 at 00:00 UTC"
)
self
.
assertContains
(
response
,
"Jan 02, 1999 at 00:00 UTC"
)
@mock.patch.dict
(
settings
.
FEATURES
,
{
'EMBARGO'
:
True
})
@mock.patch.dict
(
settings
.
FEATURES
,
{
'EMBARGO'
:
True
})
def
test_embargo_restrict
(
self
):
@ddt.data
(
"verify_student_start_flow"
,
"verify_student_begin_flow"
)
def
test_embargo_restrict
(
self
,
payment_flow
):
course
=
self
.
_create_course
(
"verified"
)
course
=
self
.
_create_course
(
"verified"
)
with
restrict_course
(
course
.
id
)
as
redirect_url
:
with
restrict_course
(
course
.
id
)
as
redirect_url
:
# Simulate that we're embargoed from accessing this
# Simulate that we're embargoed from accessing this
# course based on our IP address.
# course based on our IP address.
response
=
self
.
_get_page
(
'verify_student_start_flow'
,
course
.
id
,
expected_status_code
=
302
)
response
=
self
.
_get_page
(
payment_flow
,
course
.
id
,
expected_status_code
=
302
)
self
.
assertRedirects
(
response
,
redirect_url
)
self
.
assertRedirects
(
response
,
redirect_url
)
@mock.patch.dict
(
settings
.
FEATURES
,
{
'EMBARGO'
:
True
})
@mock.patch.dict
(
settings
.
FEATURES
,
{
'EMBARGO'
:
True
})
def
test_embargo_allow
(
self
):
@ddt.data
(
"verify_student_start_flow"
,
"verify_student_begin_flow"
)
def
test_embargo_allow
(
self
,
payment_flow
):
course
=
self
.
_create_course
(
"verified"
)
course
=
self
.
_create_course
(
"verified"
)
self
.
_get_page
(
'verify_student_start_flow'
,
course
.
id
)
self
.
_get_page
(
payment_flow
,
course
.
id
)
def
_create_course
(
self
,
*
course_modes
,
**
kwargs
):
def
_create_course
(
self
,
*
course_modes
,
**
kwargs
):
"""Create a new course with the specified course modes. """
"""Create a new course with the specified course modes. """
...
@@ -918,7 +981,8 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
...
@@ -918,7 +981,8 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
url
=
reverse
(
'verify_student_upgrade_and_verify'
,
kwargs
=
{
'course_id'
:
unicode
(
course_id
)})
url
=
reverse
(
'verify_student_upgrade_and_verify'
,
kwargs
=
{
'course_id'
:
unicode
(
course_id
)})
self
.
assertRedirects
(
response
,
url
)
self
.
assertRedirects
(
response
,
url
)
def
test_course_upgrade_page_with_unicode_and_special_values_in_display_name
(
self
):
@ddt.data
(
"verify_student_start_flow"
,
"verify_student_begin_flow"
)
def
test_course_upgrade_page_with_unicode_and_special_values_in_display_name
(
self
,
payment_flow
):
"""Check the course information on the page. """
"""Check the course information on the page. """
mode_display_name
=
u"Introduction à l'astrophysique"
mode_display_name
=
u"Introduction à l'astrophysique"
course
=
CourseFactory
.
create
(
display_name
=
mode_display_name
)
course
=
CourseFactory
.
create
(
display_name
=
mode_display_name
)
...
@@ -932,13 +996,14 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
...
@@ -932,13 +996,14 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
)
)
self
.
_enroll
(
course
.
id
)
self
.
_enroll
(
course
.
id
)
response_dict
=
self
.
_get_page_data
(
self
.
_get_page
(
'verify_student_start_flow'
,
course
.
id
))
response_dict
=
self
.
_get_page_data
(
self
.
_get_page
(
payment_flow
,
course
.
id
))
self
.
assertEqual
(
response_dict
[
'course_name'
],
mode_display_name
)
self
.
assertEqual
(
response_dict
[
'course_name'
],
mode_display_name
)
@httpretty.activate
@httpretty.activate
@override_settings
(
ECOMMERCE_API_URL
=
TEST_API_URL
,
ECOMMERCE_API_SIGNING_KEY
=
TEST_API_SIGNING_KEY
)
@override_settings
(
ECOMMERCE_API_URL
=
TEST_API_URL
,
ECOMMERCE_API_SIGNING_KEY
=
TEST_API_SIGNING_KEY
)
def
test_processors_api
(
self
):
@ddt.data
(
"verify_student_start_flow"
,
"verify_student_begin_flow"
)
def
test_processors_api
(
self
,
payment_flow
):
"""
"""
Check that when working with a product being processed by the
Check that when working with a product being processed by the
ecommerce api, we correctly call to that api for the list of
ecommerce api, we correctly call to that api for the list of
...
@@ -957,7 +1022,7 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
...
@@ -957,7 +1022,7 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin):
content_type
=
"application/json"
,
content_type
=
"application/json"
,
)
)
# make the server request
# make the server request
response
=
self
.
_get_page
(
'verify_student_start_flow'
,
course
.
id
)
response
=
self
.
_get_page
(
payment_flow
,
course
.
id
)
self
.
assertEqual
(
response
.
status_code
,
200
)
self
.
assertEqual
(
response
.
status_code
,
200
)
# ensure the mock api call was made. NOTE: the following line
# ensure the mock api call was made. NOTE: the following line
...
...
lms/djangoapps/verify_student/urls.py
View file @
198d33dc
...
@@ -23,6 +23,16 @@ urlpatterns = patterns(
...
@@ -23,6 +23,16 @@ urlpatterns = patterns(
}
}
),
),
# This is for A/B testing.
url
(
r'^begin-flow/{course}/$'
.
format
(
course
=
settings
.
COURSE_ID_PATTERN
),
views
.
PayAndVerifyView
.
as_view
(),
name
=
"verify_student_begin_flow"
,
kwargs
=
{
'message'
:
views
.
PayAndVerifyView
.
FIRST_TIME_VERIFY_MSG
}
),
# The user is enrolled in a non-paid mode and wants to upgrade.
# The user is enrolled in a non-paid mode and wants to upgrade.
# This is the same as the "start verification" flow,
# This is the same as the "start verification" flow,
# except with slight messaging changes.
# except with slight messaging changes.
...
...
lms/djangoapps/verify_student/views.py
View file @
198d33dc
...
@@ -423,7 +423,9 @@ class PayAndVerifyView(View):
...
@@ -423,7 +423,9 @@ class PayAndVerifyView(View):
'verification_good_until'
:
verification_good_until
,
'verification_good_until'
:
verification_good_until
,
'capture_sound'
:
staticfiles_storage
.
url
(
"audio/camera_capture.wav"
),
'capture_sound'
:
staticfiles_storage
.
url
(
"audio/camera_capture.wav"
),
'nav_hidden'
:
True
,
'nav_hidden'
:
True
,
'is_ab_testing'
:
'begin-flow'
in
request
.
path
,
}
}
return
render_to_response
(
"verify_student/pay_and_verify.html"
,
context
)
return
render_to_response
(
"verify_student/pay_and_verify.html"
,
context
)
def
_redirect_if_necessary
(
def
_redirect_if_necessary
(
...
...
lms/static/images/icon-sm-professional.png
0 → 100644
View file @
198d33dc
2.82 KB
lms/static/js/spec/main.js
View file @
198d33dc
...
@@ -674,6 +674,7 @@
...
@@ -674,6 +674,7 @@
'lms/include/js/spec/verify_student/image_input_spec.js'
,
'lms/include/js/spec/verify_student/image_input_spec.js'
,
'lms/include/js/spec/verify_student/review_photos_step_view_spec.js'
,
'lms/include/js/spec/verify_student/review_photos_step_view_spec.js'
,
'lms/include/js/spec/verify_student/make_payment_step_view_spec.js'
,
'lms/include/js/spec/verify_student/make_payment_step_view_spec.js'
,
'lms/include/js/spec/verify_student/make_payment_step_view_ab_testing_spec.js'
,
'lms/include/js/spec/edxnotes/utils/logger_spec.js'
,
'lms/include/js/spec/edxnotes/utils/logger_spec.js'
,
'lms/include/js/spec/edxnotes/views/notes_factory_spec.js'
,
'lms/include/js/spec/edxnotes/views/notes_factory_spec.js'
,
'lms/include/js/spec/edxnotes/views/shim_spec.js'
,
'lms/include/js/spec/edxnotes/views/shim_spec.js'
,
...
...
lms/static/js/spec/verify_student/make_payment_step_view_ab_testing_spec.js
0 → 100644
View file @
198d33dc
define
([
'jquery'
,
'underscore'
,
'backbone'
,
'common/js/spec_helpers/ajax_helpers'
,
'common/js/spec_helpers/template_helpers'
,
'js/verify_student/views/make_payment_step_view'
],
function
(
$
,
_
,
Backbone
,
AjaxHelpers
,
TemplateHelpers
,
MakePaymentStepView
)
{
'use strict'
;
var
checkPaymentButtons
,
expectPaymentSubmitted
,
goToPayment
,
expectPaymentDisabledBecauseInactive
,
expectPaymentButtonEnabled
,
expectPriceSelected
,
createView
,
SERVER_ERROR_MSG
=
'An error occurred!'
;
describe
(
'edx.verify_student.MakePaymentStepView'
,
function
()
{
var
STEP_DATA
=
{
minPrice
:
'12'
,
currency
:
'usd'
,
processors
:
[
'test-payment-processor'
],
courseKey
:
'edx/test/test'
,
courseModeSlug
:
'verified'
,
isABTesting
:
true
};
createView
=
function
(
stepDataOverrides
)
{
var
view
=
new
MakePaymentStepView
({
el
:
$
(
'#current-step-container'
),
stepData
:
_
.
extend
(
_
.
clone
(
STEP_DATA
),
stepDataOverrides
),
errorModel
:
new
(
Backbone
.
Model
.
extend
({})
)()
}).
render
();
// Stub the payment form submission
spyOn
(
view
,
'submitForm'
).
andCallFake
(
function
()
{}
);
return
view
;
};
expectPriceSelected
=
function
(
price
)
{
var
sel
=
$
(
'input[name="contribution"]'
);
// check that contribution value is same as price given
expect
(
sel
.
length
).
toEqual
(
1
);
expect
(
sel
.
val
()
).
toEqual
(
price
);
};
expectPaymentButtonEnabled
=
function
(
isEnabled
)
{
var
el
=
$
(
'.payment-button'
),
appearsDisabled
=
el
.
hasClass
(
'is-disabled'
),
isDisabled
=
el
.
prop
(
'disabled'
);
expect
(
appearsDisabled
).
not
.
toEqual
(
isEnabled
);
expect
(
isDisabled
).
not
.
toEqual
(
isEnabled
);
};
expectPaymentDisabledBecauseInactive
=
function
()
{
var
payButton
=
$
(
'.payment-button'
);
// Payment button should be hidden
expect
(
payButton
.
length
).
toEqual
(
0
);
};
goToPayment
=
function
(
requests
,
kwargs
)
{
var
params
=
{
contribution
:
kwargs
.
amount
||
''
,
course_id
:
kwargs
.
courseId
||
''
,
processor
:
kwargs
.
processor
||
''
,
sku
:
kwargs
.
sku
||
''
};
// Click the "go to payment" button
$
(
'.payment-button'
).
click
();
// Verify that the request was made to the server
AjaxHelpers
.
expectPostRequest
(
requests
,
'/verify_student/create_order/'
,
$
.
param
(
params
)
);
// Simulate the server response
if
(
kwargs
.
succeeds
)
{
// TODO put fixture responses in the right place
AjaxHelpers
.
respondWithJson
(
requests
,
{
payment_page_url
:
'http://payment-page-url/'
,
payment_form_data
:
{
foo
:
'bar'
}}
);
}
else
{
AjaxHelpers
.
respondWithTextError
(
requests
,
400
,
SERVER_ERROR_MSG
);
}
};
expectPaymentSubmitted
=
function
(
view
,
params
)
{
var
form
;
expect
(
view
.
submitForm
).
toHaveBeenCalled
();
form
=
view
.
submitForm
.
mostRecentCall
.
args
[
0
];
expect
(
form
.
serialize
()).
toEqual
(
$
.
param
(
params
));
expect
(
form
.
attr
(
'method'
)).
toEqual
(
'POST'
);
expect
(
form
.
attr
(
'action'
)).
toEqual
(
'http://payment-page-url/'
);
};
checkPaymentButtons
=
function
(
requests
,
buttons
)
{
var
$el
=
$
(
'.payment-button'
);
expect
(
$el
.
length
).
toEqual
(
_
.
size
(
buttons
));
_
.
each
(
buttons
,
function
(
expectedText
,
expectedId
)
{
var
buttonEl
=
$
(
'#'
+
expectedId
),
request
;
buttonEl
.
removeAttr
(
'disabled'
);
expect
(
buttonEl
.
length
).
toEqual
(
1
);
expect
(
buttonEl
[
0
]
).
toHaveClass
(
'payment-button'
);
expect
(
buttonEl
[
0
]
).
toHaveText
(
expectedText
);
expect
(
buttonEl
[
0
]
).
toHaveClass
(
'action-primary-blue'
);
buttonEl
[
0
].
click
();
expect
(
buttonEl
[
0
]
).
toHaveClass
(
'is-selected'
);
expectPaymentButtonEnabled
(
false
);
request
=
AjaxHelpers
.
currentRequest
(
requests
);
expect
(
request
.
requestBody
.
split
(
'&'
)).
toContain
(
'processor='
+
expectedId
);
AjaxHelpers
.
respondWithJson
(
requests
,
{});
});
};
beforeEach
(
function
()
{
window
.
analytics
=
jasmine
.
createSpyObj
(
'analytics'
,
[
'track'
,
'page'
,
'trackLink'
]);
setFixtures
(
'<div id="current-step-container"></div>'
);
TemplateHelpers
.
installTemplate
(
'templates/verify_student/make_payment_step_ab_testing'
);
});
it
(
'A/B Testing: check Initialize method with AB testing enable '
,
function
()
{
var
view
=
createView
();
expect
(
view
.
templateName
).
toEqual
(
'make_payment_step_ab_testing'
);
expect
(
view
.
btnClass
).
toEqual
(
'action-primary-blue'
);
});
it
(
'shows users only minimum price'
,
function
()
{
var
view
=
createView
(),
requests
=
AjaxHelpers
.
requests
(
this
);
expectPriceSelected
(
STEP_DATA
.
minPrice
);
expectPaymentButtonEnabled
(
true
);
goToPayment
(
requests
,
{
amount
:
STEP_DATA
.
minPrice
,
courseId
:
STEP_DATA
.
courseKey
,
processor
:
STEP_DATA
.
processors
[
0
],
succeeds
:
true
});
expectPaymentSubmitted
(
view
,
{
foo
:
'bar'
}
);
});
it
(
'A/B Testing: provides working payment buttons for a single processor'
,
function
()
{
createView
({
processors
:
[
'cybersource'
]});
checkPaymentButtons
(
AjaxHelpers
.
requests
(
this
),
{
cybersource
:
'Checkout'
});
});
it
(
'A/B Testing: provides working payment buttons for multiple processors'
,
function
()
{
createView
({
processors
:
[
'cybersource'
,
'paypal'
,
'other'
]});
checkPaymentButtons
(
AjaxHelpers
.
requests
(
this
),
{
cybersource
:
'Checkout'
,
paypal
:
'Checkout with PayPal'
,
other
:
'Checkout with other'
});
});
it
(
'A/B Testing: by default minimum price is selected if no suggested prices are given'
,
function
()
{
var
view
=
createView
(),
requests
=
AjaxHelpers
.
requests
(
this
);
expectPriceSelected
(
STEP_DATA
.
minPrice
);
expectPaymentButtonEnabled
(
true
);
goToPayment
(
requests
,
{
amount
:
STEP_DATA
.
minPrice
,
courseId
:
STEP_DATA
.
courseKey
,
processor
:
STEP_DATA
.
processors
[
0
],
succeeds
:
true
});
expectPaymentSubmitted
(
view
,
{
foo
:
'bar'
}
);
});
it
(
'A/B Testing: min price is always selected even if contribution amount is provided'
,
function
()
{
// Pre-select a price NOT in the suggestions
createView
({
contributionAmount
:
'99.99'
});
// Expect that the price is filled in
expectPriceSelected
(
STEP_DATA
.
minPrice
);
});
it
(
'A/B Testing: disables payment for inactive users'
,
function
()
{
createView
({
isActive
:
false
});
expectPaymentDisabledBecauseInactive
();
});
it
(
'A/B Testing: displays an error if the order could not be created'
,
function
()
{
var
requests
=
AjaxHelpers
.
requests
(
this
),
view
=
createView
();
goToPayment
(
requests
,
{
amount
:
STEP_DATA
.
minPrice
,
courseId
:
STEP_DATA
.
courseKey
,
processor
:
STEP_DATA
.
processors
[
0
],
succeeds
:
false
});
// Expect that an error is displayed
expect
(
view
.
errorModel
.
get
(
'shown'
)
).
toBe
(
true
);
expect
(
view
.
errorModel
.
get
(
'errorTitle'
)
).
toEqual
(
'Could not submit order'
);
expect
(
view
.
errorModel
.
get
(
'errorMsg'
)
).
toEqual
(
SERVER_ERROR_MSG
);
// Expect that the payment button is re-enabled
expectPaymentButtonEnabled
(
true
);
});
});
}
);
lms/static/js/spec/verify_student/make_payment_step_view_spec.js
View file @
198d33dc
...
@@ -108,6 +108,7 @@ define([
...
@@ -108,6 +108,7 @@ define([
buttonEl
.
removeAttr
(
'disabled'
);
buttonEl
.
removeAttr
(
'disabled'
);
expect
(
buttonEl
.
length
).
toEqual
(
1
);
expect
(
buttonEl
.
length
).
toEqual
(
1
);
expect
(
buttonEl
[
0
]
).
toHaveClass
(
'payment-button'
);
expect
(
buttonEl
[
0
]
).
toHaveClass
(
'payment-button'
);
expect
(
buttonEl
[
0
]
).
toHaveClass
(
'action-primary'
);
expect
(
buttonEl
[
0
]
).
toHaveText
(
expectedText
);
expect
(
buttonEl
[
0
]
).
toHaveText
(
expectedText
);
buttonEl
[
0
].
click
();
buttonEl
[
0
].
click
();
...
@@ -216,6 +217,12 @@ define([
...
@@ -216,6 +217,12 @@ define([
'Try the transaction again in a few minutes.'
'Try the transaction again in a few minutes.'
);
);
});
});
it
(
'check Initialize method without AB testing '
,
function
()
{
var
view
=
createView
();
expect
(
view
.
templateName
).
toEqual
(
'make_payment_step'
);
expect
(
view
.
btnClass
).
toEqual
(
'action-primary'
);
});
});
});
}
}
);
);
lms/static/js/verify_student/pay_and_verify.js
View file @
198d33dc
...
@@ -66,7 +66,8 @@ var edx = edx || {};
...
@@ -66,7 +66,8 @@ var edx = edx || {};
verificationDeadline
:
el
.
data
(
'verification-deadline'
),
verificationDeadline
:
el
.
data
(
'verification-deadline'
),
courseModeSlug
:
el
.
data
(
'course-mode-slug'
),
courseModeSlug
:
el
.
data
(
'course-mode-slug'
),
alreadyVerified
:
el
.
data
(
'already-verified'
),
alreadyVerified
:
el
.
data
(
'already-verified'
),
verificationGoodUntil
:
el
.
data
(
'verification-good-until'
)
verificationGoodUntil
:
el
.
data
(
'verification-good-until'
),
isABTesting
:
el
.
data
(
'is-ab-testing'
)
},
},
'payment-confirmation-step'
:
{
'payment-confirmation-step'
:
{
courseKey
:
el
.
data
(
'course-key'
),
courseKey
:
el
.
data
(
'course-key'
),
...
...
lms/static/js/verify_student/views/make_payment_step_view.js
View file @
198d33dc
...
@@ -11,6 +11,15 @@ var edx = edx || {};
...
@@ -11,6 +11,15 @@ var edx = edx || {};
edx
.
verify_student
.
MakePaymentStepView
=
edx
.
verify_student
.
StepView
.
extend
({
edx
.
verify_student
.
MakePaymentStepView
=
edx
.
verify_student
.
StepView
.
extend
({
templateName
:
"make_payment_step"
,
templateName
:
"make_payment_step"
,
btnClass
:
'action-primary'
,
initialize
:
function
(
obj
)
{
_
.
extend
(
this
,
obj
);
if
(
this
.
templateContext
().
isABTesting
)
{
this
.
templateName
=
'make_payment_step_ab_testing'
;
this
.
btnClass
=
'action-primary-blue'
;
}
},
defaultContext
:
function
()
{
defaultContext
:
function
()
{
return
{
return
{
...
@@ -27,7 +36,8 @@ var edx = edx || {};
...
@@ -27,7 +36,8 @@ var edx = edx || {};
platformName
:
''
,
platformName
:
''
,
alreadyVerified
:
false
,
alreadyVerified
:
false
,
courseModeSlug
:
'audit'
,
courseModeSlug
:
'audit'
,
verificationGoodUntil
:
''
verificationGoodUntil
:
''
,
isABTesting
:
false
};
};
},
},
...
@@ -61,8 +71,8 @@ var edx = edx || {};
...
@@ -61,8 +71,8 @@ var edx = edx || {};
_getPaymentButtonHtml
:
function
(
processorName
)
{
_getPaymentButtonHtml
:
function
(
processorName
)
{
var
self
=
this
;
var
self
=
this
;
return
_
.
template
(
return
_
.
template
(
'<button class="next
action-primary
payment-button" id="<%- name %>" ><%- text %></button> '
'<button class="next
<%- btnClass %>
payment-button" id="<%- name %>" ><%- text %></button> '
)({
name
:
processorName
,
text
:
self
.
_getPaymentButtonText
(
processorName
)});
)({
name
:
processorName
,
text
:
self
.
_getPaymentButtonText
(
processorName
)
,
btnClass
:
this
.
btnClass
});
},
},
postRender
:
function
()
{
postRender
:
function
()
{
...
...
lms/static/sass/views/_verification.scss
View file @
198d33dc
...
@@ -175,6 +175,14 @@
...
@@ -175,6 +175,14 @@
color
:
$white
!
important
;
color
:
$white
!
important
;
}
}
// elements - controls
.action-primary-blue
{
@extend
%btn-primary-blue
;
// needed for override due to .register a:link styling
border
:
0
!
important
;
color
:
$white
!
important
;
}
.action-confirm
{
.action-confirm
{
@extend
%btn-verify-primary
;
@extend
%btn-verify-primary
;
// needed for override due to .register a:link styling
// needed for override due to .register a:link styling
...
@@ -821,6 +829,109 @@
...
@@ -821,6 +829,109 @@
// indiv slides - review
// indiv slides - review
#wrapper-review
{
#wrapper-review
{
color
:
$black
;
.page-title
{
@extend
%t-strong
;
border-bottom
:
2px
solid
$m-gray-d3
;
padding-bottom
:
(
$baseline
*
0
.75
);
margin-bottom
:
$baseline
;
text-transform
:
inherit
;
}
.review
{
.certificate
{
@include
font-size
(
18
);
background-repeat
:
no-repeat
;
padding-left
:
(
$baseline
*
2
.5
);
overflow
:
hidden
;
min-height
:
32px
;
p
{
@include
line-height
(
22
);
@extend
%t-strong
;
margin-top
:
0
;
color
:
$black
;
}
.purchase
{
@include
float
(
right
);
@include
margin-left
(
$baseline
*
0
.75
);
text-align
:
right
;
.product-info
{
@include
font-size
(
22
);
@extend
%t-strong
;
color
:
$blue
;
}
}
&
.verified_icon
{
background-image
:
url('
#{
$static-path
}
/images/icon-sm-verified.png')
;
}
&
.no-id-professional_icon
,
&
.professional_icon
{
background-image
:
url('
#{
$static-path
}
/images/icon-sm-professional.png')
;
}
}
.payment-buttons
{
overflow
:
auto
;
padding-bottom
:
(
$baseline
/
4
);
margin
:
{
top
:
(
$baseline
/
2
);
bottom
:
(
$baseline
*
0
.75
);
};
.payment-button
{
padding
:
(
$baseline
*
0
.4
)
$baseline
;
min-width
:
200px
;
}
.action-primary-blue
{
&
.is-selected
{
background
:
$blue
!
important
;
}
}
}
.border-gray
{
border-bottom
:
2px
solid
$gray
;
margin
:
(
$baseline
*
1
.12
)
0
;
}
}
.container
{
padding
:
(
$baseline
*
0
.75
)
0
;
p
{
@include
line-height
(
22
);
color
:
$black
;
}
.photo-requirement
{
@include
font-size
(
12
);
position
:
relative
;
padding-left
:
(
$baseline
*
2
);
margin-top
:
(
$baseline
*
0
.75
);
background-repeat
:
no-repeat
;
background-position
:
left
top
;
.fa
{
position
:
absolute
;
left
:
0
;
color
:
$mediumGrey
;
}
h6
{
font-weight
:
bold
;
color
:
$extraDarkGrey
;
}
}
}
.review-task
{
.review-task
{
margin-bottom
:
(
$baseline
*
1
.5
);
margin-bottom
:
(
$baseline
*
1
.5
);
...
...
lms/templates/verify_student/make_payment_step_ab_testing.underscore
0 → 100644
View file @
198d33dc
<div id="wrapper-review" tab-index="0" class="wrapper-view make-payment-step">
<div class="review view">
<% if (!isActive ) { %>
<h2 class="page-title">
<%- gettext("Account Not Activated")%>
</h2>
<% } else if ( !upgrade ) { %>
<h2 class="page-title">
<%= _.sprintf(
gettext( "You are enrolling in %(courseName)s"),
{ courseName: '<span class="course-title">' + courseName + '</span>' }
) %>
</h2>
<% } else { %>
<h2 class="page-title">
<%= _.sprintf(
gettext( "Upgrade to a Verified Certificate for %(courseName)s"),
{ courseName: '<span class="course-title">' + courseName + '</span>' }
) %>
</h2>
<% } %>
<% if ( !isActive ) { %>
<p>
<%- gettext("Before you upgrade to a certificate track, you must activate your account.") %>
<%- gettext("Check your email for an activation message.") %>
</p>
<% } else { %>
<div class="certificate <%- courseModeSlug %>_icon">
<div class="purchase">
<p class="product-info"><span class="product-name"></span> <%- gettext( "Total" ) %>: <span class="price">$<%- minPrice %> USD</span></p>
</div>
<p>
<% if ( courseModeSlug === 'no-id-professional' || courseModeSlug === 'professional') { %>
<%= _.sprintf(
gettext( "Professional Certificate for %(courseName)s"),{ courseName: courseName }
)%>
<% } else { %>
<%= _.sprintf(
gettext( "Verified Certificate for %(courseName)s"),{ courseName: courseName }
)%>
<% } %>
</p>
</div>
<% } %>
<% if ( isActive ) { %>
<div class="payment-buttons is-ready center">
<input type="hidden" name="contribution" value="<%- minPrice %>" />
<input type="hidden" name="sku" value="<%- sku %>" />
<div class="pay-options">
<%
// payment buttons will go here
%>
</div>
</div>
<div class="border-gray"></div>
<% } %>
</div>
<% if ( isActive ) { %>
<div class="container">
<% if ( _.some( requirements, function( isVisible ) { return isVisible; } ) ) { %>
<p>
<% if ( verificationDeadline ) { %>
<%- _.sprintf(
gettext( "To receive a certificate, you must also verify your identity before %(date)s." ),
{ date: verificationDeadline }
) %>
<% } else { %>
<%- gettext( "To receive a certificate, you must also verify your identity." ) %>
<% } %>
<%- gettext("To verify your identity, you need a webcam and a government-issued photo ID.") %>
</p>
<% if ( requirements['photo-id-required'] ) { %>
<div class="photo-requirement user_icon">
<i class="fa fa-user fa-2x" aria-hidden="true"></i>
<h6>
<%- gettext("Photo ID") %>
</h6>
<p>
<%- gettext("Your ID must be a government-issued photo ID that clearly shows your face.") %>
</p>
</div>
<% } %>
<% if ( requirements['webcam-required'] ) { %>
<div class="photo-requirement cam_icon">
<i class="fa fa-video-camera fa-2x" aria-hidden="true"></i>
<h6>
<%- gettext("Webcam") %>
</h6>
<p>
<%- gettext("You will use your webcam to take a picture of your face and of your government-issued photo ID.") %>
</p>
</div>
<% } %>
<% } %>
</div>
<% } %>
<form id="payment-processor-form"></form>
</div>
lms/templates/verify_student/pay_and_verify.html
View file @
198d33dc
...
@@ -24,9 +24,15 @@ from lms.djangoapps.verify_student.views import PayAndVerifyView
...
@@ -24,9 +24,15 @@ from lms.djangoapps.verify_student.views import PayAndVerifyView
<
%
<
%
template_names =
(
template_names =
(
["
webcam_photo
",
"
image_input
",
"
error
"]
+
["
webcam_photo
",
"
image_input
",
"
error
"]
+
["
intro_step
",
"
make_payment_step
",
"
payment_confirmation_step
"]
+
["
intro_step
",
"
payment_confirmation_step
"]
+
["
face_photo_step
",
"
id_photo_step
",
"
review_photos_step
",
"
enrollment_confirmation_step
"]
["
face_photo_step
",
"
id_photo_step
",
"
review_photos_step
",
"
enrollment_confirmation_step
"]
)
)
if
not
is_ab_testing:
template_names
.
append
("
make_payment_step
")
else:
template_names
.
append
("
make_payment_step_ab_testing
")
%
>
%
>
% for template_name in template_names:
% for template_name in template_names:
<script
type=
"text/template"
id=
"${template_name}-tpl"
>
<script
type=
"text/template"
id=
"${template_name}-tpl"
>
...
@@ -76,6 +82,7 @@ from lms.djangoapps.verify_student.views import PayAndVerifyView
...
@@ -76,6 +82,7 @@ from lms.djangoapps.verify_student.views import PayAndVerifyView
data-already-verified=
'${already_verified}'
data-already-verified=
'${already_verified}'
data-verification-good-until=
'${verification_good_until}'
data-verification-good-until=
'${verification_good_until}'
data-capture-sound=
'${capture_sound}'
data-capture-sound=
'${capture_sound}'
data-is-ab-testing=
'${json.dumps(is_ab_testing)}'
##
If
we
reached
the
verification
flow
from
an
in-course
checkpoint
,
##
If
we
reached
the
verification
flow
from
an
in-course
checkpoint
,
##
then
pass
the
checkpoint
location
in
so
that
we
can
associate
##
then
pass
the
checkpoint
location
in
so
that
we
can
associate
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment