Commit 072ae5cb by Will Daly

Prevent duplicate submissions on client side by disabling submit button

parent d59288cb
......@@ -124,4 +124,49 @@ describe("OpenAssessment.ResponseView", function() {
view.submit();
expect(server.submit).toHaveBeenCalledWith('Test response');
});
it("disables the submit button on submission", function() {
// Prevent the server's response from resolving,
// so we can see what happens before view gets re-rendered.
spyOn(server, 'submit').andCallFake(function() {
return $.Deferred(function(defer) {}).promise();
});
view.response('Test response');
view.submit();
expect(view.submitEnabled()).toBe(false);
});
it("re-enables the submit button on submission error", function() {
// Simulate a server error
spyOn(server, 'submit').andCallFake(function() {
return $.Deferred(function(defer) {
defer.rejectWith(this, ['ENOUNKNOWN', 'Error occurred!']);
}).promise();
});
view.response('Test response');
view.submit();
// Expect the submit button to have been re-enabled
expect(view.submitEnabled()).toBe(true);
});
it("moves to the next step on duplicate submission error", function() {
// Simulate a "multiple submissions" server error
spyOn(server, 'submit').andCallFake(function() {
return $.Deferred(function(defer) {
defer.rejectWith(this, ['ENOMULTI', 'Multiple submissions error']);
}).promise();
});
spyOn(view, 'load');
spyOn(baseView, 'renderPeerAssessmentStep');
view.response('Test response');
view.submit();
// Expect the current and next step to have been reloaded
expect(view.load).toHaveBeenCalled();
expect(baseView.renderPeerAssessmentStep).toHaveBeenCalled();
});
});
......@@ -213,20 +213,35 @@ OpenAssessment.ResponseView.prototype = {
Send a response submission to the server and update the view.
**/
submit: function() {
// Immediately disable the submit button to prevent multiple submission
this.submitEnabled(false);
// Send the submission to the server
var submission = $('#submission__answer__value', this.element).val();
this.baseView.toggleActionError('response', null);
var view = this;
var baseView = this.baseView;
this.server.submit(submission).done(
// When we have successfully sent the submission, move on to the next step
function(studentId, attemptNum) {
view.load();
baseView.renderPeerAssessmentStep();
}
).fail(function(errCode, errMsg) {
baseView.toggleActionError('submit', errMsg);
});
var moveToNextStep = function() {
view.load();
baseView.renderPeerAssessmentStep();
};
this.server.submit(submission)
.done(moveToNextStep)
.fail(function(errCode, errMsg) {
// If the error is "multiple submissions", then we should move to the next
// step. Otherwise, the user will be stuck on the current step with no
// way to continue.
if (errCode == 'ENOMULTI') {
moveToNextStep();
}
else {
// Display the error
baseView.toggleActionError('submit', errMsg);
// Re-enable the submit button to allow the user to retry
view.submitEnabled(true);
}
});
}
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment