Vote buttons should be disabled while in use

Clicking quickly on up/down votes in forums generates a race condition
where the votes can continue going up or down (and I can get e.g. large
negative numbers). This is client-side; the server-side is not affected.

This is caused by safeAjax calling code (including updateWithUndo) not
handling the possible undefined return value. This is returned in the case
where the element that triggers the event is already disabled.

Corrected typo in DiscussionThreadView cleanup: @responseRequest -> @responsesRequest

Resolves TNL-1061
This commit is contained in:
Mat Moore
2015-01-05 15:19:08 +00:00
parent 55edd327ac
commit d857695d62
4 changed files with 28 additions and 2 deletions

View File

@@ -195,3 +195,4 @@ Dino Cikatić <dcikatic@edx.org>
Davorin Šego <dsego@edx.org>
Marko Jevtić <mjevtic@edx.org>
Ahsan Ulhaq <ahsan@edx.org>
Mat Moore <mat@mooresoftware.co.uk>

View File

@@ -25,3 +25,24 @@ describe 'DiscussionUtil', ->
# if the ajax call ends in failure, the model state should be reverted
deferred.reject()
expect(model.attributes).toEqual({hello: false, number: 42})
it "rolls back the changes if the associated element is disabled", ->
spyOn(DiscussionUtil, "safeAjax").andCallThrough()
model = new Backbone.Model({hello: false, number: 42})
updates = {hello: "world"}
# This is the element that is disabled/enabled while the ajax request is
# in progress
$elem = jasmine.createSpyObj('$elem', ['attr'])
$elem.attr.andReturn(true)
res = DiscussionUtil.updateWithUndo(model, updates, {foo: "bar", $elem:$elem}, "error message")
expect($elem.attr).toHaveBeenCalledWith("disabled")
expect(DiscussionUtil.safeAjax).toHaveBeenCalled()
expect(model.attributes).toEqual({hello: false, number: 42})
failed = false
res.fail(() => failed = true)
expect(failed).toBe(true);

View File

@@ -134,8 +134,12 @@ class @DiscussionUtil
@safeAjax: (params) ->
$elem = params.$elem
if $elem and $elem.attr("disabled")
return
deferred = $.Deferred()
deferred.reject()
return deferred.promise()
params["url"] = URI(params["url"]).addSearch ajax: 1
params["beforeSend"] = ->
if $elem

View File

@@ -127,7 +127,7 @@ if Backbone?
$loading: elem
takeFocus: true
complete: =>
@responseRequest = null
@responsesRequest = null
success: (data, textStatus, xhr) =>
Content.loadContentInfos(data['annotated_content_info'])
if @isQuestion()