DEPR-43 - Remove JS that refers to shoppingcart receipt page. (#24890)

https://openedx.atlassian.net/browse/DEPR-43

Co-authored-by: Jeremy Bowman <jbowman@edx.org>
This commit is contained in:
Diana Huang
2020-09-29 16:08:42 -04:00
committed by GitHub
parent bf0de81c57
commit 657da20c6e
12 changed files with 9 additions and 580 deletions

View File

@@ -1328,61 +1328,6 @@ class ShoppingCartViewsTests(SharedModuleStoreTestCase, XssTestMixin):
self._assert_404(reverse('shoppingcart.views.reset_code_redemption', args=[]), use_post=True)
self._assert_404(reverse('billing_details', args=[]))
def test_upgrade_postpay_callback_emits_ga_event(self):
# Enroll as honor in the course with the current user.
CourseEnrollment.enroll(self.user, self.course_key)
# add verified mode
CourseMode.objects.create(
course_id=self.verified_course_key,
mode_slug="verified",
mode_display_name="verified cert",
min_price=self.cost
)
# Purchase a verified certificate
self.cart = Order.get_cart_for_user(self.user)
CertificateItem.add_to_order(self.cart, self.verified_course_key, self.cost, 'verified')
self.cart.start_purchase()
self.login_user()
# setting the attempting upgrade session value.
session = self.client.session
session['attempting_upgrade'] = True
session.save()
ordered_params = OrderedDict([
('amount', self.cost),
('currency', 'usd'),
('transaction_type', 'sale'),
('orderNumber', str(self.cart.id)),
('access_key', '123456789'),
('merchantID', 'edx'),
('djch', '012345678912'),
('orderPage_version', 2),
('orderPage_serialNumber', '1234567890'),
('profile_id', "00000001"),
('reference_number', str(self.cart.id)),
('locale', 'en'),
('signed_date_time', '2014-08-18T13:59:31Z'),
])
resp_params = PaymentFakeView.response_post_params(sign(ordered_params))
self.assertTrue(self.client.session.get('attempting_upgrade'))
url = reverse('shoppingcart.views.postpay_callback')
self.client.post(url, resp_params, follow=True)
self.assertFalse(self.client.session.get('attempting_upgrade'))
self.mock_tracker.emit.assert_any_call(
'edx.course.enrollment.upgrade.succeeded',
{
'user_id': self.user.id,
'course_id': text_type(self.verified_course_key),
'mode': 'verified'
}
)
class ReceiptRedirectTest(SharedModuleStoreTestCase):
"""Test special-case redirect from the receipt page. """
@@ -1414,40 +1359,6 @@ class ReceiptRedirectTest(SharedModuleStoreTestCase):
password=self.PASSWORD
)
def test_postpay_callback_redirect_to_verify_student(self):
# Create other carts first
# This ensures that the order ID and order item IDs do not match
Order.get_cart_for_user(self.user).start_purchase()
Order.get_cart_for_user(self.user).start_purchase()
Order.get_cart_for_user(self.user).start_purchase()
# Purchase a verified certificate
self.cart = Order.get_cart_for_user(self.user)
CertificateItem.add_to_order(
self.cart,
self.course_key,
self.COST,
'verified'
)
self.cart.start_purchase()
# Simulate hitting the post-pay callback
with patch('lms.djangoapps.shoppingcart.views.process_postpay_callback') as mock_process:
mock_process.return_value = {'success': True, 'order': self.cart}
url = reverse('shoppingcart.views.postpay_callback')
resp = self.client.post(url, follow=True)
# Expect to be redirected to the payment confirmation
# page in the verify_student app
redirect_url = reverse(
'verify_student_payment_confirmation',
kwargs={'course_id': six.text_type(self.course_key)}
)
redirect_url += '?payment-order-num={order_num}'.format(
order_num=self.cart.id
)
self.assertIn(redirect_url, resp.redirect_chain[0][0])
@patch.dict('django.conf.settings.FEATURES', {'ENABLE_PAID_COURSE_REGISTRATION': True})
class ShoppingcartViewsClosedEnrollment(ModuleStoreTestCase):

View File

@@ -87,12 +87,8 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin, Tes
PASSWORD = "test_password"
NOW = now()
YESTERDAY = 'yesterday'
TOMORROW = 'tomorrow'
NEXT_YEAR = 'next_year'
DATES = {
YESTERDAY: NOW - timedelta(days=1),
TOMORROW: NOW + timedelta(days=1),
NEXT_YEAR: NOW + timedelta(days=360),
None: None,
}
@@ -372,61 +368,24 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin, Tes
response = self._get_page('verify_student_verify_now', course.id)
self._assert_user_details(response, self.user.profile.name)
@ddt.data(
"verify_student_verify_now",
"verify_student_payment_confirmation"
)
def test_verify_now_not_enrolled(self, page_name):
def test_verify_now_not_enrolled(self):
course = self._create_course("verified")
response = self._get_page(page_name, course.id, expected_status_code=302)
response = self._get_page("verify_student_verify_now", course.id, expected_status_code=302)
self._assert_redirects_to_start_flow(response, course.id)
@ddt.data(
"verify_student_verify_now",
"verify_student_payment_confirmation"
)
def test_verify_now_unenrolled(self, page_name):
def test_verify_now_unenrolled(self):
course = self._create_course("verified")
self._enroll(course.id, "verified")
self._unenroll(course.id)
response = self._get_page(page_name, course.id, expected_status_code=302)
response = self._get_page("verify_student_verify_now", course.id, expected_status_code=302)
self._assert_redirects_to_start_flow(response, course.id)
@ddt.data(
"verify_student_verify_now",
"verify_student_payment_confirmation"
)
def test_verify_now_not_paid(self, page_name):
def test_verify_now_not_paid(self):
course = self._create_course("verified")
self._enroll(course.id)
response = self._get_page(page_name, course.id, expected_status_code=302)
response = self._get_page("verify_student_verify_now", course.id, expected_status_code=302)
self._assert_redirects_to_upgrade(response, course.id)
def test_payment_confirmation(self):
course = self._create_course("verified")
self._enroll(course.id, "verified")
response = self._get_page('verify_student_payment_confirmation', course.id)
self._assert_messaging(response, PayAndVerifyView.PAYMENT_CONFIRMATION_MSG)
self.assert_no_xss(response, '<script>alert("XSS")</script>')
# Expect that *all* steps are displayed,
# but we start at the payment confirmation step
self._assert_steps_displayed(
response,
PayAndVerifyView.PAYMENT_STEPS + PayAndVerifyView.VERIFICATION_STEPS,
PayAndVerifyView.PAYMENT_CONFIRMATION_STEP,
)
# These will be hidden from the user anyway since they're starting
# after the payment step. We're already including the payment
# steps, so it's easier to include these as well.
self._assert_requirements_displayed(response, [
PayAndVerifyView.PHOTO_ID_REQ,
PayAndVerifyView.WEBCAM_REQ,
])
@ddt.data("verify_student_start_flow", "verify_student_begin_flow")
def test_payment_cannot_skip(self, payment_flow):
"""
@@ -454,64 +413,6 @@ class TestPayAndVerifyView(UrlResetMixin, ModuleStoreTestCase, XssTestMixin, Tes
PayAndVerifyView.MAKE_PAYMENT_STEP,
)
def test_payment_confirmation_already_verified(self):
course = self._create_course("verified")
self._enroll(course.id, "verified")
self._set_verification_status("submitted")
response = self._get_page('verify_student_payment_confirmation', course.id)
# Other pages would redirect to the dashboard at this point,
# because the user has paid and verified. However, we want
# the user to see the confirmation page even if there
# isn't anything for them to do here except return
# to the dashboard.
self._assert_steps_displayed(
response,
PayAndVerifyView.PAYMENT_STEPS,
PayAndVerifyView.PAYMENT_CONFIRMATION_STEP,
)
def test_payment_confirmation_already_verified_skip_first_step(self):
course = self._create_course("verified")
self._enroll(course.id, "verified")
self._set_verification_status("submitted")
response = self._get_page(
'verify_student_payment_confirmation',
course.id,
skip_first_step=True
)
# There are no other steps, so stay on the
# payment confirmation step
self._assert_steps_displayed(
response,
PayAndVerifyView.PAYMENT_STEPS,
PayAndVerifyView.PAYMENT_CONFIRMATION_STEP,
)
@ddt.data(
(YESTERDAY, True),
(TOMORROW, False)
)
@ddt.unpack
def test_payment_confirmation_course_details(self, course_start, show_courseware_url):
course = self._create_course("verified", course_start=self.DATES[course_start])
self._enroll(course.id, "verified")
response = self._get_page('verify_student_payment_confirmation', course.id)
courseware_url = (
reverse("course_root", kwargs={'course_id': six.text_type(course.id)})
if show_courseware_url else ""
)
self._assert_course_details(
response,
six.text_type(course.id),
course.display_name,
courseware_url
)
@ddt.data("verified", "professional")
def test_upgrade(self, course_mode):
course = self._create_course(course_mode)

View File

@@ -62,20 +62,6 @@ urlpatterns = [
}
),
# The user is returning to the flow after paying.
# This usually occurs after a redirect from the shopping cart
# once the order has been fulfilled.
url(
r'^payment-confirmation/{course}/$'.format(course=settings.COURSE_ID_PATTERN),
views.PayAndVerifyView.as_view(),
name="verify_student_payment_confirmation",
kwargs={
'always_show_payment': True,
'current_step': views.PayAndVerifyView.PAYMENT_CONFIRMATION_STEP,
'message': views.PayAndVerifyView.PAYMENT_CONFIRMATION_MSG
}
),
url(
r'^create_order',
views.create_order,

View File

@@ -116,7 +116,6 @@ class PayAndVerifyView(View):
#
INTRO_STEP = 'intro-step'
MAKE_PAYMENT_STEP = 'make-payment-step'
PAYMENT_CONFIRMATION_STEP = 'payment-confirmation-step'
FACE_PHOTO_STEP = 'face-photo-step'
ID_PHOTO_STEP = 'id-photo-step'
REVIEW_PHOTOS_STEP = 'review-photos-step'
@@ -125,7 +124,6 @@ class PayAndVerifyView(View):
ALL_STEPS = [
INTRO_STEP,
MAKE_PAYMENT_STEP,
PAYMENT_CONFIRMATION_STEP,
FACE_PHOTO_STEP,
ID_PHOTO_STEP,
REVIEW_PHOTOS_STEP,
@@ -134,7 +132,6 @@ class PayAndVerifyView(View):
PAYMENT_STEPS = [
MAKE_PAYMENT_STEP,
PAYMENT_CONFIRMATION_STEP
]
VERIFICATION_STEPS = [
@@ -152,7 +149,6 @@ class PayAndVerifyView(View):
STEP_TITLES = {
INTRO_STEP: ugettext_lazy("Intro"),
MAKE_PAYMENT_STEP: ugettext_lazy("Make payment"),
PAYMENT_CONFIRMATION_STEP: ugettext_lazy("Payment confirmation"),
FACE_PHOTO_STEP: ugettext_lazy("Take photo"),
ID_PHOTO_STEP: ugettext_lazy("Take a photo of your ID"),
REVIEW_PHOTOS_STEP: ugettext_lazy("Review your info"),
@@ -171,7 +167,6 @@ class PayAndVerifyView(View):
VERIFY_NOW_MSG = 'verify-now'
VERIFY_LATER_MSG = 'verify-later'
UPGRADE_MSG = 'upgrade'
PAYMENT_CONFIRMATION_MSG = 'payment-confirmation'
# Requirements
#
@@ -496,9 +491,8 @@ class PayAndVerifyView(View):
if already_verified and already_paid:
# If they've already paid and verified, there's nothing else to do,
# so redirect them to the dashboard.
if message != self.PAYMENT_CONFIRMATION_MSG:
url = reverse('dashboard')
elif message in [self.VERIFY_NOW_MSG, self.VERIFY_LATER_MSG, self.PAYMENT_CONFIRMATION_MSG]:
url = reverse('dashboard')
elif message in [self.VERIFY_NOW_MSG, self.VERIFY_LATER_MSG]:
if is_enrolled:
# If the user is already enrolled but hasn't yet paid,
# then the "upgrade" messaging is more appropriate.

View File

@@ -1886,7 +1886,6 @@ verify_student_js = [
'js/verify_student/views/step_view.js',
'js/verify_student/views/intro_step_view.js',
'js/verify_student/views/make_payment_step_view.js',
'js/verify_student/views/payment_confirmation_step_view.js',
'js/verify_student/views/face_photo_step_view.js',
'js/verify_student/views/id_photo_step_view.js',
'js/verify_student/views/review_photos_step_view.js',

View File

@@ -10,7 +10,6 @@ define(['jquery', 'common/js/spec_helpers/template_helpers', 'js/verify_student/
'id_photo_step',
'intro_step',
'make_payment_step',
'payment_confirmation_step',
'review_photos_step',
'webcam_photo',
'image_input'
@@ -25,10 +24,6 @@ define(['jquery', 'common/js/spec_helpers/template_helpers', 'js/verify_student/
{
name: 'make-payment-step',
title: 'Make Payment'
},
{
name: 'payment-confirmation-step',
title: 'Payment Confirmation'
}
];
@@ -86,9 +81,6 @@ define(['jquery', 'common/js/spec_helpers/template_helpers', 'js/verify_student/
expectStepRendered('make-payment-step');
// Iterate through the steps, ensuring that each is rendered
view.nextStep();
expectStepRendered('payment-confirmation-step');
view.nextStep();
expectStepRendered('face-photo-step');
@@ -129,21 +121,6 @@ define(['jquery', 'common/js/spec_helpers/template_helpers', 'js/verify_student/
expectStepRendered('enrollment-confirmation-step');
});
it('starts from a later step', function() {
// Start from the payment confirmation step
var view = createView(
DISPLAY_STEPS_FOR_PAYMENT.concat(DISPLAY_STEPS_FOR_VERIFICATION),
'payment-confirmation-step'
);
// Verify that we start on the right step
expectStepRendered('payment-confirmation-step');
// Try moving to the next step
view.nextStep();
expectStepRendered('face-photo-step');
});
it('jumps to a particular step', function() {
// Start on the review photos step
var view = createView(

View File

@@ -72,13 +72,6 @@ var edx = edx || {};
verificationGoodUntil: $el.data('verification-good-until'),
isABTesting: $el.data('is-ab-testing')
},
'payment-confirmation-step': {
courseKey: $el.data('course-key'),
courseName: $el.data('course-name'),
coursewareUrl: $el.data('courseware-url'),
platformName: $el.data('platform-name'),
requirements: $el.data('requirements')
},
'face-photo-step': {
platformName: $el.data('platform-name'),
captureSoundPath: $el.data('capture-sound')

View File

@@ -53,7 +53,6 @@ var edx = edx || {};
subviewConstructors = {
'intro-step': edx.verify_student.IntroStepView,
'make-payment-step': edx.verify_student.MakePaymentStepView,
'payment-confirmation-step': edx.verify_student.PaymentConfirmationStepView,
'face-photo-step': edx.verify_student.FacePhotoStepView,
'id-photo-step': edx.verify_student.IDPhotoStepView,
'review-photos-step': edx.verify_student.ReviewPhotosStepView,

View File

@@ -1,161 +0,0 @@
/**
* View for the "payment confirmation" step of the payment/verification flow.
*/
var edx = edx || {};
(function($, _, gettext) {
'use strict';
edx.verify_student = edx.verify_student || {};
edx.verify_student.PaymentConfirmationStepView = edx.verify_student.StepView.extend({
templateName: 'payment_confirmation_step',
defaultContext: function() {
return {
courseKey: '',
courseName: '',
coursewareUrl: '',
platformName: '',
requirements: []
};
},
/**
* Retrieve receipt information from the shopping cart.
*
* We make this request from JavaScript to encapsulate
* the verification Django app from the shopping cart app.
*
* This method checks the query string param
* ?payment-order-num, which can be set by the shopping cart
* before redirecting to the payment confirmation page.
* This step then reads the param and requests receipt information
* from the shopping cart. At no point does the "verify student"
* Django app interact directly with the shopping cart.
*
* @param {object} templateContext The original template context.
* @return {object} A JQuery promise that resolves with the modified
* template context.
*/
updateContext: function(templateContext) {
var view = this;
return $.Deferred(
function(defer) {
var paymentOrderNum = $.url('?payment-order-num');
if (paymentOrderNum) {
// If there is a payment order number, try to retrieve
// the receipt information from the shopping cart.
view.getReceiptData(paymentOrderNum).done(
function(data) {
// Add the receipt info to the template context
_.extend(templateContext, {receipt: this.receiptContext(data)});
defer.resolveWith(view, [templateContext]);
}
).fail(function() {
// Display an error
// This can occur if the user does not have access to the receipt
// or the order number is invalid.
defer.rejectWith(
this,
[
gettext('Error'),
gettext('Could not retrieve payment information')
]
);
});
} else {
// If no payment order is provided, return the original context
// The template is responsible for displaying a default state.
_.extend(templateContext, {receipt: null});
defer.resolveWith(view, [templateContext]);
}
}
).promise();
},
/**
* The "Verify Later" button goes directly to the dashboard,
* The "Verify Now" button sends the user to the verification flow.
* For this reason, we don't need any custom click handlers here, except for
* those used to track business intelligence events.
*/
postRender: function() {
var $verifyNowButton = $('#verify_now_button'),
$verifyLaterButton = $('#verify_later_button');
// Track a virtual pageview, for easy funnel reconstruction.
window.analytics.page('payment', this.templateName);
// Track the user's decision to verify immediately
window.analytics.trackLink($verifyNowButton, 'edx.bi.user.verification.immediate', {
category: 'verification'
});
// Track the user's decision to defer their verification
window.analytics.trackLink($verifyLaterButton, 'edx.bi.user.verification.deferred', {
category: 'verification'
});
},
/**
* Retrieve receipt data from the shoppingcart.
* @param {int} paymentOrderNum The order number of the payment.
* @return {object} JQuery Promise.
*/
getReceiptData: function(paymentOrderNum) {
return $.ajax({
url: _.sprintf('/shoppingcart/receipt/%s/', paymentOrderNum),
type: 'GET',
dataType: 'json',
context: this
});
},
/**
* Construct the template context from data received
* from the shopping cart receipt.
*
* @param {object} data Receipt data received from the server
* @return {object} Receipt template context.
*/
receiptContext: function(data) {
var view = this,
receiptContext;
receiptContext = {
orderNum: data.orderNum,
currency: data.currency,
purchasedDatetime: data.purchase_datetime,
totalCost: view.formatMoney(data.total_cost),
isRefunded: data.status === 'refunded',
billedTo: {
firstName: data.billed_to.first_name,
lastName: data.billed_to.last_name,
city: data.billed_to.city,
state: data.billed_to.state,
postalCode: data.billed_to.postal_code,
country: data.billed_to.country
},
items: []
};
receiptContext.items = _.map(
data.items,
function(item) {
return {
lineDescription: item.line_desc,
cost: view.formatMoney(item.line_cost)
};
}
);
return receiptContext;
},
formatMoney: function(moneyStr) {
return Number(moneyStr).toFixed(2);
}
});
}(jQuery, _, gettext));

View File

@@ -428,15 +428,6 @@
'js/verify_student/views/step_view'
]
},
'js/verify_student/views/payment_confirmation_step_view': {
exports: 'edx.verify_student.PaymentConfirmationStepView',
deps: [
'jquery',
'underscore',
'gettext',
'js/verify_student/views/step_view'
]
},
'js/verify_student/views/face_photo_step_view': {
exports: 'edx.verify_student.FacePhotoStepView',
deps: [
@@ -491,7 +482,6 @@
'js/verify_student/models/verification_model',
'js/verify_student/views/intro_step_view',
'js/verify_student/views/make_payment_step_view',
'js/verify_student/views/payment_confirmation_step_view',
'js/verify_student/views/face_photo_step_view',
'js/verify_student/views/id_photo_step_view',
'js/verify_student/views/review_photos_step_view',

View File

@@ -14,8 +14,6 @@ from lms.djangoapps.verify_student.views import PayAndVerifyView
<%block name="pagetitle">
% if message_key == PayAndVerifyView.UPGRADE_MSG:
${_("Upgrade Your Enrollment For {course_name}.").format(course_name=course.display_name)}
% elif message_key == PayAndVerifyView.PAYMENT_CONFIRMATION_MSG:
${_("Receipt For {course_name}").format(course_name=course.display_name)}
% elif message_key in [PayAndVerifyView.VERIFY_NOW_MSG, PayAndVerifyView.VERIFY_LATER_MSG]:
${_("Verify For {course_name}").format(course_name=course.display_name)}
% else:
@@ -27,7 +25,7 @@ from lms.djangoapps.verify_student.views import PayAndVerifyView
<%
template_names = (
["webcam_photo", "image_input", "error"] +
["intro_step", "payment_confirmation_step"] +
["intro_step"] +
["face_photo_step", "id_photo_step", "review_photos_step", "enrollment_confirmation_step"]
)

View File

@@ -1,158 +0,0 @@
<div class="wrapper-content-main payment-confirmation-step">
<article class="content-main">
<h3 class="title">
<%= HtmlUtils.interpolateHtml(
gettext( "Thank you! We have received your payment for {courseName}." ),
{ courseName: HtmlUtils.joinHtml(
HtmlUtils.HTML('<span class="course-title">'),
courseName,
HtmlUtils.HTML('</span>')
) }
) %>
</h3>
<% if ( receipt ) { %>
<div class="list-info">
<div class="info-item payment-info">
<div class="copy">
<p><%- gettext( "Please print this page for your records; it serves as your receipt. You will also receive an email with the same information." ) %></p>
</div>
<div class="wrapper-report">
<table class="report report-receipt">
<thead>
<tr>
<th scope="col" ><%- gettext( "Order No." ) %></th>
<th scope="col" ><%- gettext( "Description" ) %></th>
<th scope="col" ><%- gettext( "Date" ) %></th>
<th scope="col" ><%- gettext( "Amount" ) %></th>
</tr>
</thead>
<tbody>
<% for ( var i = 0; i < receipt.items.length; i++ ) { %>
<% if ( receipt.isRefunded ) { %>
<td><del><%- receipt.orderNum %></del></td>
<td><del><%- receipt.items[i].lineDescription %></del></td>
<td><del><%- receipt.purchasedDatetime %></del></td>
<td><del><%- receipt.items[i].cost %> (<%- receipt.currency.toUpperCase() %>)</del></td>
<% } else { %>
<tr>
<td><%- receipt.orderNum %></td>
<td><%- receipt.items[i].lineDescription %></td>
<td><%- receipt.purchasedDatetime %></td>
<td><%- receipt.items[i].cost %> (<%- receipt.currency.toUpperCase() %>)</td>
</tr>
<% } %>
<% } %>
</tbody>
<tfoot>
<tr>
<th scope="row" class="total-label" colspan="1"><%- gettext( "Total" ) %></th>
<td class="total-value" colspan="3">
<span class="value-amount"><%- receipt.totalCost %></span>
<span class="value-currency">(<%- receipt.currency.toUpperCase() %>)</span>
</td>
</tr>
</tfoot>
</table>
<% if ( receipt.isRefunded ) { %>
<div class="msg msg-refunds">
<h4 class="title sr"><%- gettext( "Please Note" ) %>: </h4>
<div class="copy">
<p><%- gettext( "Crossed out items have been refunded." ) %></p>
</div>
</div>
<% } %>
</div>
<div class="copy">
<p><%- gettext( "Billed to" ) %>:
<span class="name-first"><%- receipt.billedTo.firstName %></span>
<span class="name-last"><%- receipt.billedTo.lastName %></span>
(<span class="address-city"><%- receipt.billedTo.city %></span>,
<span class="address-state"><%- receipt.billedTo.state %></span>
<span class="address-postalcode"><%- receipt.billedTo.postalCode %></span>
<span class="address-country"><%- receipt.billedTo.country.toUpperCase() %></span>)
</p>
</div>
</div>
</div>
<% } else { %>
<p class="no-content"><%- gettext( "No receipt available" ) %></p>
<% } %>
<% if ( nextStepTitle ) { %>
<h3 class="title"><%- gettext( "Next Step: Confirm your identity" ) %></h3>
<div class="requirements-container">
<ul class="list-reqs <% if ( requirements['account-activation-required'] ) { %>account-not-activated<% } %>">
<% if ( requirements['account-activation-required'] ) { %>
<li class="req req-0 req-activate">
<h4 class="title"><%- gettext( "Activate Your Account" ) %></h4>
<div class="placeholder-art">
<span class="icon fa fa-envelope-o" aria-hidden="true"></span>
</div>
<div class="copy">
<p>
<span class="copy-super"><%- gettext( "Check your email" ) %></span>
<span class="copy-sub"><%-
gettext( "You need to activate your account before you can enroll in courses. Check your inbox for an activation email." )
%>
</span>
</p>
</div>
</li>
<% } else { %>
<% if ( requirements['photo-id-required'] ) { %>
<li class="req req-1 req-id">
<h4 class="title"><%- gettext( "Photo ID" ) %></h4>
<div class="placeholder-art fa-lg">
<span class="icon fa fa-list-alt fa-stack-2x" aria-hidden="true"></span>
<span class="icon fa fa-user id-photo fa-stack-1x" aria-hidden="true"></span>
</div>
<div class="copy">
<p>
<span class="copy-sub"><%- gettext( "A driver's license, passport, or government-issued ID with your name and photo." ) %></span>
</p>
</div>
</li>
<% } %>
<% if ( requirements['webcam-required'] ) { %>
<li class="req req-2 req-webcam">
<h4 class="title"><%- gettext( "Webcam" ) %></h4>
<div class="placeholder-art">
<span class="icon fa fa-video-camera" aria-hidden="true"></span>
</div>
<div class="copy"></div>
</li>
<% } %>
<% } %>
</ul>
</div>
<nav class="nav-wizard is-ready">
<a id="verify_later_button" class="next action-secondary verify-later nav-link" href="/dashboard" data-tooltip="<%- _.sprintf( gettext( "If you don't verify your identity now, you can still explore your course from your dashboard. You will receive periodic reminders from %(platformName)s to verify your identity." ), { platformName: platformName } ) %>">
<%- gettext( "Want to confirm your identity later?" ) %>
</a>
<a id="verify_now_button"
class="next action-primary right"
href="<%- _.sprintf( '/verify_student/verify-now/%(courseKey)s', { courseKey: courseKey } ) %>"
>
<%- _.sprintf(
gettext( "Next: %(nextStepTitle)s" ),
{ nextStepTitle: nextStepTitle }
) %>
</a>
</nav>
<% } %>
</article>
</div>