@edx/edx-proctoring
Advanced tools
Comparing version 3.7.16 to 3.8.0
@@ -48,6 +48,2 @@ edx = edx || {}; | ||
this.setElement($('.student-proctored-exam-container')); | ||
this.enable_exam_resume_proctoring_improvements = | ||
this.$el.data('enable-exam-resume-proctoring-improvements'); | ||
this.enable_exam_resume_proctoring_improvements = this.enable_exam_resume_proctoring_improvements && | ||
this.enable_exam_resume_proctoring_improvements.toLowerCase() === 'true'; | ||
this.course_id = this.$el.data('course-id'); | ||
@@ -57,9 +53,4 @@ this.template = null; | ||
if (!this.enable_exam_resume_proctoring_improvements) { | ||
this.collection = new edx.instructor_dashboard.proctoring.ProctoredExamAttemptCollection(); | ||
this.template_url = '/static/proctoring/templates/student-proctored-exam-attempts.underscore'; | ||
} else { | ||
this.collection = new edx.instructor_dashboard.proctoring.ProctoredExamAttemptGroupedCollection(); | ||
this.template_url = '/static/proctoring/templates/student-proctored-exam-attempts-grouped.underscore'; | ||
} | ||
this.collection = new edx.instructor_dashboard.proctoring.ProctoredExamAttemptGroupedCollection(); | ||
this.template_url = '/static/proctoring/templates/student-proctored-exam-attempts-grouped.underscore'; | ||
@@ -237,31 +228,17 @@ | ||
if (!self.enable_exam_resume_proctoring_improvements) { | ||
self.model.fetch({ | ||
headers: { | ||
'X-CSRFToken': this.getCSRFToken() | ||
}, | ||
type: 'DELETE', | ||
success: function() { | ||
// fetch the attempts again. | ||
self.hydrate(); | ||
$('body').css('cursor', 'auto'); | ||
} | ||
}); | ||
} else { | ||
// call reset endpoint that can be used to delete all attempts for a given | ||
// user and exam | ||
$.ajax({ | ||
url: '/api/edx_proctoring/v1/proctored_exam/exam_id/' + examId + | ||
'/user_id/' + userId + '/reset_attempts', | ||
type: 'DELETE', | ||
headers: { | ||
'X-CSRFToken': this.getCSRFToken() | ||
}, | ||
success: function() { | ||
// fetch the attempts again. | ||
self.hydrate(); | ||
$('body').css('cursor', 'auto'); | ||
} | ||
}); | ||
} | ||
// call reset endpoint that can be used to delete all attempts for a given | ||
// user and exam | ||
$.ajax({ | ||
url: '/api/edx_proctoring/v1/proctored_exam/exam_id/' + examId + | ||
'/user_id/' + userId + '/reset_attempts', | ||
type: 'DELETE', | ||
headers: { | ||
'X-CSRFToken': this.getCSRFToken() | ||
}, | ||
success: function() { | ||
// fetch the attempts again. | ||
self.hydrate(); | ||
$('body').css('cursor', 'auto'); | ||
} | ||
}); | ||
}, | ||
@@ -268,0 +245,0 @@ onResumeAttempt: function(event) { |
@@ -5,3 +5,2 @@ describe('ProctoredExamAttemptView', function() { | ||
var html = ''; | ||
var groupedHtml = ''; | ||
var deletedProctoredExamAttemptJson = [{ | ||
@@ -56,5 +55,37 @@ attempt_url: '/api/edx_proctoring/v1/proctored_exam/attempt/course_id/edX/DemoX/Demo_Course', | ||
user: { | ||
id: 1, | ||
username: 'testuser1', | ||
email: 'testuser1@test.com' | ||
} | ||
}, | ||
all_attempts: [{ | ||
allowed_time_limit_mins: 1, | ||
attempt_code: '20C32387-372E-48BD-BCAC-A2BE9DC91E09', | ||
completed_at: null, | ||
created: '2015-08-10T09:15:45Z', | ||
external_id: '40eceb15-bcc3-4791-b43f-4e843afb7ae8', | ||
id: 43, | ||
is_sample_attempt: false, | ||
last_poll_ipaddr: null, | ||
last_poll_timestamp: null, | ||
modified: '2015-08-10T09:15:45Z', | ||
started_at: '2015-08-10T09:15:45Z', | ||
status: status, | ||
taking_as_proctored: true, | ||
proctored_exam: { | ||
content_id: 'i4x://edX/DemoX/sequential/9f5e9b018a244ea38e5d157e0019e60c', | ||
course_id: 'edX/DemoX/Demo_Course', | ||
exam_name: 'Normal Exam', | ||
external_id: null, | ||
id: 17, | ||
is_active: true, | ||
is_practice_exam: isPracticeExam, | ||
is_proctored: true, | ||
time_limit_mins: 1 | ||
}, | ||
user: { | ||
id: 1, | ||
username: 'testuser1', | ||
email: 'testuser1@test.com' | ||
} | ||
}] | ||
}] | ||
@@ -217,100 +248,2 @@ }] | ||
'<table class="exam-attempts-table"> <thead><tr class="exam-attempt-headings">' + | ||
'<th class="username">Username</th>' + | ||
'<th class="exam-name">Exam Name</th>' + | ||
'<th class="attempt-allowed-time">Allowed Time (Minutes)</th>' + | ||
'<th class="attempt-started-at">Started At</th>' + | ||
'<th class="attempt-completed-at">Completed At</th>' + | ||
'<th class="attempt-status">Status</th>' + | ||
'<th class="c_action">Actions</th>' + | ||
'</tr></thead>' + | ||
'<% if (is_proctored_attempts) { %>' + | ||
'<tbody>' + | ||
'<% _.each(proctored_exam_attempts, function(proctored_exam_attempt, dashboard_index){' + | ||
'%><tr class="allowance-items">' + | ||
'<td>' + | ||
' <%= proctored_exam_attempt.user.username %> ' + | ||
' </td>' + | ||
'<td>' + | ||
' <%- interpolate(gettext(" %(exam_display_name)s "),' + | ||
'{ exam_display_name: proctored_exam_attempt.proctored_exam.exam_name }, true) %>' + | ||
'</td>' + | ||
'<td>' + | ||
' <%= proctored_exam_attempt.allowed_time_limit_mins %> ' + | ||
'</td>' + | ||
'<td>' + | ||
' <%= getDateFormat(proctored_exam_attempt.started_at) %>' + | ||
'</td>' + | ||
'<td>' + | ||
' <%= getDateFormat(proctored_exam_attempt.completed_at) %>' + | ||
'</td>' + | ||
'<td>' + | ||
' <% if (proctored_exam_attempt.status){ %> <%= proctored_exam_attempt.status %> <% } else { %> N/A <% } %> ' + | ||
'</td>' + | ||
'<td>' + | ||
'<% if (proctored_exam_attempt.status){ %> ' + | ||
'<a href="#" class="remove-attempt" data-attempt-id="<%= proctored_exam_attempt.id %>" >[x]</a>' + | ||
' <% } else { %>N/A <% } %>' + | ||
'</td>' + | ||
'</tr>' + | ||
' <% }); %> ' + | ||
'</tbody>' + | ||
' <% } %>' + | ||
' </table>' + | ||
'<% if (!is_proctored_attempts) { %> ' + | ||
'<p> No exam results found. </p>' + | ||
'<% } %> ' + | ||
'</div> </div>'; | ||
this.server = sinon.fakeServer.create(); | ||
this.server.autoRespond = true; | ||
setFixtures('<div class="student-proctored-exam-container" data-course-id="test_course_id"></div>'); | ||
// load the underscore template response before calling the proctored exam attemp view. | ||
this.server.respondWith('GET', '/static/proctoring/templates/student-proctored-exam-attempts.underscore', | ||
[ | ||
200, | ||
{'Content-Type': 'text/html'}, | ||
html | ||
] | ||
); | ||
groupedHtml = '<div class="wrapper-content wrapper">' + | ||
'<% var is_proctored_attempts = proctored_exam_attempts.length !== 0 %>' + | ||
'<div class="content exam-attempts-content">' + | ||
'<div class="top-header">' + | ||
'<div class="search-attempts">' + | ||
'<input type="text" id="search_attempt_id" placeholder="e.g johndoe or john.doe@gmail.com"' + | ||
'<% if (inSearchMode) { %> value="<%= searchText %>" <%} %> /> ' + | ||
'<span class="search">' + | ||
'<span class="icon fa fa-search" id="attempt-search-indicator" aria-hidden="true"></span>' + | ||
'<div aria-live="polite" aria-relevant="all">' + | ||
'<div id="attempt-loading-indicator" class="hidden">' + | ||
'<span class="icon fa fa-spinner fa-pulse" aria-hidden="true"></span>' + | ||
'<span class="sr"><%- gettext("Loading") %></span>' + | ||
'</div>' + | ||
'</div>' + | ||
'</span>' + | ||
'<span class="clear-search"><span class="icon fa fa-remove" aria-hidden="true"></span></span>' + | ||
'</div>' + | ||
'<ul class="pagination">' + | ||
'<% if (!pagination_info.has_previous){ %>' + | ||
'<li class="disabled"> <a aria-label="Previous"> <span aria-hidden="true">«</span> </a> </li>' + | ||
'<% } else { %>' + | ||
'<li>' + | ||
'<a class="target-link " data-target-url="' + | ||
'<%- interpolate("%(attempt_url)s?page=%(count)s ",' + | ||
'{attempt_url: attempt_url, count: pagination_info.current_page - 1}, true) %>' + | ||
'"' + | ||
'href="#" aria-label="Previous">' + | ||
'<span aria-hidden="true">«</span> </a> </li> <% }%>' + | ||
'<% for(var n = 1; n <= pagination_info.total_pages; n++) { %>' + | ||
'<li> <a class="target-link <% if (pagination_info.current_page == n){ %> active <% } %>" data-target-url=" ' + | ||
'<%- interpolate("%(attempt_url)s?page=%(count)s ", {attempt_url: attempt_url, count: n}, true) %>' + | ||
'"href="#"><%= n %> </a></li> <% } %>' + | ||
'<% if (!pagination_info.has_next){ %>' + | ||
'<li class="disabled"> <a aria-label="Next"> <span aria-hidden="true">»</span> </a></li>' + | ||
'<% } else { %> <li> <a class="target-link" href="#" aria-label="Next" data-target-url="' + | ||
'<%- interpolate("%(attempt_url)s?page=%(count)s ",' + | ||
'{attempt_url: attempt_url, count: pagination_info.current_page + 1}, true) %>' + | ||
'" > <span aria-hidden="true">»</span></a> </li> <% }%> </ul><div class="clearfix"></div></div>' + | ||
'<table class="exam-attempts-table"> <thead><tr class="exam-attempt-headings">' + | ||
'<th class="more"></th>' + | ||
@@ -335,5 +268,3 @@ '<th class="username">Username</th>' + | ||
'>' + | ||
'<tr' + | ||
'class="allowance-items"' + | ||
'>' + | ||
'<tr class="allowance-items">' + | ||
'<td>' + | ||
@@ -428,4 +359,7 @@ '<% if (proctored_exam_attempt.all_attempts.length > 1) { %>' + | ||
'</div>'; | ||
this.server = sinon.fakeServer.create(); | ||
this.server.autoRespond = true; | ||
setFixtures('<div class="student-proctored-exam-container" data-course-id="test_course_id"></div>'); | ||
// load the underscore template response before calling the proctored exam attemp view. | ||
// load the underscore template response before calling the proctored exam attempt view. | ||
this.server.respondWith( | ||
@@ -437,3 +371,3 @@ 'GET', | ||
{'Content-Type': 'text/html'}, | ||
groupedHtml | ||
html | ||
] | ||
@@ -447,3 +381,3 @@ ); | ||
it('should render the proctored exam attempt view properly', function() { | ||
this.server.respondWith('GET', '/api/edx_proctoring/v1/proctored_exam/attempt/course_id/test_course_id', | ||
this.server.respondWith('GET', '/api/edx_proctoring/v1/proctored_exam/attempt/grouped/course_id/test_course_id', | ||
[ | ||
@@ -462,67 +396,9 @@ 200, | ||
expect(this.proctored_exam_attempt_view.$el.find('tr.allowance-items')).toContainHtml('<td> testuser1 </td>'); | ||
expect(this.proctored_exam_attempt_view.$el.find('tr.allowance-items')).toContainHtml('<td> testuser1 </td>'); | ||
expect(this.proctored_exam_attempt_view.$el.find('tr.allowance-items').html()).toContain('Normal Exam'); | ||
}); | ||
it('should delete the proctored exam attempt', function() { | ||
this.server.respondWith('GET', '/api/edx_proctoring/v1/proctored_exam/attempt/course_id/test_course_id', | ||
[ | ||
200, | ||
{ | ||
'Content-Type': 'application/json' | ||
}, | ||
JSON.stringify(getExpectedProctoredExamAttemptWithAttemptStatusJson('started')) | ||
] | ||
); | ||
this.proctored_exam_attempt_view = new edx.instructor_dashboard.proctoring.ProctoredExamAttemptView(); | ||
// Process all requests so far | ||
this.server.respond(); | ||
this.server.respond(); | ||
expect(this.proctored_exam_attempt_view.$el.find('tr.allowance-items')).toContainHtml('<td> testuser1 </td>'); | ||
expect(this.proctored_exam_attempt_view.$el.find('tr.allowance-items').html()).toContain('Normal Exam'); | ||
// delete the proctored exam attempt | ||
this.server.respondWith('DELETE', '/api/edx_proctoring/v1/proctored_exam/attempt/43', | ||
[ | ||
200, | ||
{ | ||
'Content-Type': 'application/json' | ||
}, | ||
JSON.stringify([]) | ||
] | ||
); | ||
// again fetch the results after the proctored exam attempt deletion | ||
this.server.respondWith('GET', '/api/edx_proctoring/v1/proctored_exam/attempt/course_id/test_course_id', | ||
[ | ||
200, | ||
{ | ||
'Content-Type': 'application/json' | ||
}, | ||
JSON.stringify(deletedProctoredExamAttemptJson) | ||
] | ||
); | ||
spyOn(window, 'confirm').and.callFake(function() { | ||
return true; | ||
}); | ||
// trigger the remove attempt event. | ||
spyOnEvent('.remove-attempt', 'click'); | ||
$('.remove-attempt').trigger('click'); | ||
// process the deleted attempt requests. | ||
this.server.respond(); | ||
this.server.respond(); | ||
expect(this.proctored_exam_attempt_view.$el.find('tr.allowance-items').html()).not.toContain('testuser1'); | ||
expect(this.proctored_exam_attempt_view.$el.find('tr.allowance-items').html()).not.toContain('Normal Exam'); | ||
}); | ||
it('should search for the proctored exam attempt', function() { | ||
var searchText = 'testuser1'; | ||
this.server.respondWith('GET', '/api/edx_proctoring/v1/proctored_exam/attempt/course_id/test_course_id', | ||
this.server.respondWith('GET', '/api/edx_proctoring/v1/proctored_exam/attempt/grouped/course_id/test_course_id', | ||
[ | ||
@@ -543,3 +419,3 @@ 200, | ||
expect(this.proctored_exam_attempt_view.$el.find('tr.allowance-items')).toContainHtml('<td> testuser1 </td>'); | ||
expect(this.proctored_exam_attempt_view.$el.find('tr.allowance-items')).toContainHtml('<td> testuser1 </td>'); | ||
expect(this.proctored_exam_attempt_view.$el.find('tr.allowance-items').html()).toContain('Normal Exam'); | ||
@@ -556,3 +432,3 @@ expect(this.proctored_exam_attempt_view.$el.find('#attempt-search-indicator').hasClass('hidden')) | ||
'GET', | ||
'/api/edx_proctoring/v1/proctored_exam/attempt/course_id/test_course_id/search/' + searchText, | ||
'/api/edx_proctoring/v1/proctored_exam/attempt/grouped/course_id/test_course_id/search/' + searchText, | ||
[ | ||
@@ -592,3 +468,3 @@ 200, | ||
var searchText = 'invalid_search_text'; | ||
this.server.respondWith('GET', '/api/edx_proctoring/v1/proctored_exam/attempt/course_id/test_course_id', | ||
this.server.respondWith('GET', '/api/edx_proctoring/v1/proctored_exam/attempt/grouped/course_id/test_course_id', | ||
[ | ||
@@ -608,3 +484,3 @@ 200, | ||
expect(this.proctored_exam_attempt_view.$el.find('tr.allowance-items')).toContainHtml('<td> testuser1 </td>'); | ||
expect(this.proctored_exam_attempt_view.$el.find('tr.allowance-items')).toContainHtml('<td> testuser1 </td>'); | ||
expect(this.proctored_exam_attempt_view.$el.find('tr.allowance-items').html()).toContain('Normal Exam'); | ||
@@ -617,3 +493,3 @@ | ||
'GET', | ||
'/api/edx_proctoring/v1/proctored_exam/attempt/course_id/test_course_id/search/' + searchText, | ||
'/api/edx_proctoring/v1/proctored_exam/attempt/grouped/course_id/test_course_id/search/' + searchText, | ||
[ | ||
@@ -640,3 +516,3 @@ 200, | ||
this.server.respondWith('GET', '/api/edx_proctoring/v1/proctored_exam/attempt/course_id/test_course_id', | ||
this.server.respondWith('GET', '/api/edx_proctoring/v1/proctored_exam/attempt/grouped/course_id/test_course_id', | ||
[ | ||
@@ -663,6 +539,2 @@ 200, | ||
it('should mark exam attempt "ready_to_resume" on resume', function() { | ||
// enable the dropdown via the enable-exam-resume-proctoring-improvements data attribute | ||
setFixtures('<div class="student-proctored-exam-container" data-course-id="test_course_id" ' + | ||
'data-enable-exam-resume-proctoring-improvements="True"></div>'); | ||
this.server.respondWith('GET', '/api/edx_proctoring/v1/proctored_exam/attempt/grouped/course_id/test_course_id', | ||
@@ -746,6 +618,2 @@ [ | ||
it('should not display actions dropdown for practice exam attempts', function() { | ||
// enable the dropdown via the enable-exam-resume-proctoring-improvements data attribute | ||
setFixtures('<div class="student-proctored-exam-container" data-course-id="test_course_id" ' + | ||
'data-enable-exam-resume-proctoring-improvements="True"></div>'); | ||
this.server.respondWith('GET', '/api/edx_proctoring/v1/proctored_exam/attempt/grouped/course_id/test_course_id', | ||
@@ -777,5 +645,2 @@ [ | ||
setFixtures('<div class="student-proctored-exam-container" data-course-id="test_course_id" ' + | ||
'data-enable-exam-resume-proctoring-improvements="True"></div>'); | ||
this.server.respondWith('GET', '/api/edx_proctoring/v1/proctored_exam/attempt/grouped/course_id/test_course_id', | ||
@@ -812,6 +677,3 @@ [ | ||
it('deletes attempts using new endpoint', function() { | ||
setFixtures('<div class="student-proctored-exam-container" data-course-id="test_course_id" ' + | ||
'data-enable-exam-resume-proctoring-improvements="True"></div>'); | ||
it('deletes attempts', function() { | ||
this.server.respondWith('GET', '/api/edx_proctoring/v1/proctored_exam/attempt/grouped/course_id/test_course_id', | ||
@@ -886,5 +748,2 @@ [ | ||
it('shows and hides accordion when toggled', function() { | ||
setFixtures('<div class="student-proctored-exam-container" data-course-id="test_course_id" ' + | ||
'data-enable-exam-resume-proctoring-improvements="True"></div>'); | ||
this.server.respondWith('GET', '/api/edx_proctoring/v1/proctored_exam/attempt/grouped/course_id/test_course_id', | ||
@@ -918,4 +777,2 @@ [ | ||
var searchText = 'testuser1'; | ||
setFixtures('<div class="student-proctored-exam-container" data-course-id="test_course_id" ' + | ||
'data-enable-exam-resume-proctoring-improvements="True"></div>'); | ||
@@ -922,0 +779,0 @@ this.server.respondWith('GET', '/api/edx_proctoring/v1/proctored_exam/attempt/grouped/course_id/test_course_id', |
@@ -5,3 +5,3 @@ { | ||
"//": "Note that the version format is slightly different than that of the Python version when using prereleases.", | ||
"version": "3.7.16", | ||
"version": "3.8.0", | ||
"main": "edx_proctoring/static/index.js", | ||
@@ -8,0 +8,0 @@ "scripts":{ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
976206
46
18035