Skip to content

Instantly share code, notes, and snippets.

@EndangeredMassa
Created June 18, 2012 18:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save EndangeredMassa/2950032 to your computer and use it in GitHub Desktop.
Save EndangeredMassa/2950032 to your computer and use it in GitHub Desktop.
JavaScript Testing Best Practices: Part 1
OrderSystem =
init: ->
$('#container').append('<div id="order-system" />')
# init is included at the end of the file
OrderSystem.init()
it 'OrderSystem init works', ->
OrderSystem.init() # now called twice
expect($('#order-system').length).toBe(1) #FAILS
# Global State
window.allowTax = true
window.allowShipping = true
hasCustomSettings = ->
return window.allowTax || window.allowShipping
beforeEach ->
# save current state
@allowTax = window.allowTax
@allowShipping = window.allowShipping
afterEach ->
# restore state
window.allowTax = @allowTax
window.allowShipping = @allowShipping
it 'tests shouldShowCoolStuff', ->
window.allowTax = false
window.allowShipping = true
result = hasCustomSettings()
expect(result).toBe(true)
# do not care
spyOn(Cookie, 'set')
# do care
spyOn(Cookie, 'set')
doWork()
expect(Cookie.set).toHaveBeenCalled()
# verify
document.cookie == ''
addModalDom = ($element, message) ->
$element.append("<div class='modal'>#{message}</div>")
addModalLocal = ($element, message) ->
  $element.append("<div class='modal'>#{message}</div>")
beforeEach ->
# your project may have something like this to keep the dom clean, but beware!
$('#jasmine_content').html('');
it 'initializes a modal (DOM)', ->
addModalDom('hey there');
expect($('.modal').length).toBe(1)
it 'initializes a modal (local)', ->
container = $('<div />')
addModalLocal(container, 'hey there');
expect(container.find('.modal').length).toBe(1)
# global state
window.allowTax = true
window.allowShipping = true
# method that calls our method under test
processOrder = ->
if hasCustomSettings(window.allowTax, window.allowShipping)
handleCustomSettings()
# the above is just for reference
# the below is all we actually care about
hasCustomSettings = (allowTax, allowShipping) ->
return allowTax || allowShipping
it 'tests hasCustomSettings', ->
result = hasCustomSettings(true, true)
expect(result).toBe(true)
# $.ajax
spyOn($, 'ajax').andCallFake (options) ->
options.success(someData)
expect($.ajax).toHaveBeenCalled()
# sinon
server = sinon.fakeServer.create()
server.respondWith('url', '<div>text</div>')
doWork()
server.respond()
# DOM Requests
addImage = (url) ->
$(document).append('<img src="something">')
spyOn(window, 'addImage')
expect(window.addImage).toHaveBeenCalledWith('someurl)
createOrder = (orderData) ->
Cookie.set('atLeastOneOrderCreated', true)
API.createOrder(orderData)
return orderData.id
# this test causes a cookie to be set and an API call to be made
it 'createOrder returns the id', ->
orderData =
id: 3
expect(createOrder(orderData).id).toBe(3)
# this test causes a cookie to be set
it 'createOrder calls the API', ->
spyOn(API, 'createOrder')
createOrder()
expect(API.createOrder).toHaveBeenCalled()
# ideally, there would be a before each that spys on both
beforeEach ->
spyOn(API, 'createOrder')
spyOn(Cookie, 'set')
App = ->
createGlobals = ->
renderLayout = ->
renderSidebar = ->
renderContent = ->
importSavedSettings = ->
settings = getSettingsFromLocalOrServer()
loadSettings(settings)
initApp = ->
createGlobals()
renderLayout()
renderSidebar()
renderContent()
importSavedSettings()
return {
init: initApp
}
it 'App init', ->
app = new App
app.init()
# now we're stuck testing side effects
App = ->
createGlobals = ->
renderLayout = ->
renderSidebar = ->
renderContent = ->
importSavedSettings = ->
settings = getSettingsFromLocalOrServer()
loadSettings(settings)
initApp = ->
createGlobals()
renderLayout()
renderSidebar()
renderContent()
importSavedSettings()
return {
init: initApp
createGlobals: createGlobals
renderLayout: renderLayout
renderSidebar: renderSidebar
renderContent: renderContent
importSavedSettings: importSavedSettings
}
it 'App imports saved settings', ->
app = new App()
app.importSavedSettings()
# now we can test methods directly!
Settings =
getSettingsFromLocalOrServer: ->
loadSettings: ->
importSavedSettings: ->
settings = @getSettingsFromLocalOrServer()
@loadSettings(settings)
Renderer =
renderLayout: ->
renderSidebar: ->
renderContent: ->
render: ->
@renderLayout()
@renderSidebar()
@renderContent()
App = ->
createGlobals = ->
initApp = ->
createGlobals()
Renderer.render()
Settings.import()
return {
createGlobals: createGlobals
init: initApp
}
it 'App createGlobals creates globals', ->
app = new App
app.createGlobals()
# test output
describe 'App init', ->
beforeEach ->
app = new App
spyOn(Renderer, 'render')
spyOn(Settings, 'import')
spyOn(app, 'createGlobals')
app.init()
it 'renders content', ->
expect(Renderer.render).toHaveBeenCalled()
it 'loads settings', ->
expect(Settings.import).toHaveBeenCalled()
it 'creates globals', ->
expect(app.createGlobals).toHaveBeenCalled()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment