Skip to content

Instantly share code, notes, and snippets.

@maxbeatty
Created July 9, 2014 02:31
Show Gist options
  • Save maxbeatty/13da72529895ed4522ec to your computer and use it in GitHub Desktop.
Save maxbeatty/13da72529895ed4522ec to your computer and use it in GitHub Desktop.
Promises make dealing with validation + AJAX cases a breeze when testing
saveDraft: -> $.Deferred (deferred) =>
# do validation
validationError = @validate()
if validationError
# use deferred to return immediately with failure
return deferred.reject validationError
$.post @url, @toJSON()
.done (payload, response, options) ->
# things went well
deferred.resolve()
.fail (jqXHR, textStatus, errorThrown) ->
# poop
try
res = JSON.parse jqXHR.responseText
msg = if res.error then res.error else res
catch e
msg = jqXHR.responseText
# tell whomever about the failure
deferred.reject msg
describe 'saveDraft', ->
beforeEach ->
# stub anything not in the method we're testing
@validateStub = sinon.stub(@collection, 'validate').returns undefined
it 'should reject if validation error', (done) ->
# control the fail case (returns anything)
@validateStub.returns 'test msg'
# use promise chaining for assertions
@collection.saveDraft().fail (msg) ->
msg.should.equal 'test msg'
done()
it 'should reject if post fails', (done) ->
# validate is taken care of for us in the beforeEach
# control jQuery AJAX by returning a Deferred that we can control (reject)
sinon.stub($, 'post').returns do -> $.Deferred().reject('test').promise()
# use promise chaining for assertion
@collection.saveDraft().fail (msg) ->
msg.should.equal 'test'
done()
# what it ends up looking like without explainer comments:
it 'should succeed', (done) ->
sinon.stub($, 'post').returns do -> $.Deferred().resolve().promise()
@collection.saveDraft().done done
# view method triggered by click event on button
saveDraft: ->
# change UI
@$clBtn.button('loading')
# do data things
@collection.saveDraft().fail (msg) =>
# if data things go wrong...
@makeUnsaved()
alert msg
# the same promise-based concepts work for our view as well since Deferreds are returned up the stack
describe 'saveDraft', ->
it 'should make unsaved and alert if saving fails', (done) ->
sinon.stub(@collection, 'saveDraft').returns do -> $.Deferred().reject('test').promise()
@view.saveDraft().fail (msg) ->
msg.should.equal 'test'
done()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment