Files
edx-platform/lms/static/coffee/spec/calculator_spec.coffee
2016-06-23 19:55:28 -04:00

354 lines
10 KiB
CoffeeScript

describe 'Calculator', ->
KEY =
TAB : 9
ENTER : 13
ALT : 18
ESC : 27
SPACE : 32
LEFT : 37
UP : 38
RIGHT : 39
DOWN : 40
beforeEach ->
loadFixtures 'coffee/fixtures/calculator.html'
@calculator = new Calculator
describe 'bind', ->
it 'bind the calculator button', ->
expect($('.calc')).toHandleWith 'click', @calculator.toggle
it 'bind key up on calculator', ->
expect($('#calculator_wrapper')).toHandle 'keyup', @calculator.handleKeyUpOnHint
it 'bind the help button', ->
# This events is bind by $.click()
expect($('#calculator_hint')).toHandle 'click'
it 'bind the calculator submit', ->
expect($('form#calculator')).toHandleWith 'submit', @calculator.calculate
xit 'prevent default behavior on form submit', ->
jasmine.stubRequests()
$('form#calculator').submit (e) ->
expect(e.isDefaultPrevented()).toBeTruthy()
e.preventDefault()
$('form#calculator').submit()
describe 'toggle', ->
it 'focuses the input when toggled', (done)->
self = this
focus = ()->
deferred = $.Deferred()
# Since the focus is called asynchronously, we need to
# wait until focus() is called.
spyOn($.fn, 'focus').and.callFake (elementName) ->
deferred.resolve()
self.calculator.toggle(jQuery.Event("click"))
deferred.promise()
focus().then(
->
expect($('#calculator_wrapper #calculator_input').focus).toHaveBeenCalled()
).always(done)
it 'toggle the close button on the calculator button', ->
@calculator.toggle(jQuery.Event("click"))
expect($('.calc')).toHaveClass('closed')
@calculator.toggle(jQuery.Event("click"))
expect($('.calc')).not.toHaveClass('closed')
describe 'showHint', ->
it 'show the help overlay', ->
@calculator.showHint()
expect($('.help')).toHaveClass('shown')
expect($('.help')).toHaveAttr('aria-hidden', 'false')
describe 'hideHint', ->
it 'show the help overlay', ->
@calculator.hideHint()
expect($('.help')).not.toHaveClass('shown')
expect($('.help')).toHaveAttr('aria-hidden', 'true')
describe 'handleClickOnHintButton', ->
it 'on click hint button hint popup becomes visible ', ->
e = jQuery.Event('click');
$('#calculator_hint').trigger(e);
expect($('.help')).toHaveClass 'shown'
describe 'handleClickOnDocument', ->
it 'on click out of the hint popup it becomes hidden', ->
@calculator.showHint()
e = jQuery.Event('click');
$(document).trigger(e);
expect($('.help')).not.toHaveClass 'shown'
describe 'handleClickOnHintPopup', ->
it 'on click of hint popup it remains visible', ->
@calculator.showHint()
e = jQuery.Event('click');
$('#calculator_input_help').trigger(e);
expect($('.help')).toHaveClass 'shown'
describe 'selectHint', ->
it 'select correct hint item', ->
spyOn($.fn, 'focus')
element = $('.hint-item').eq(1)
@calculator.selectHint(element)
expect(element.focus).toHaveBeenCalled()
expect(@calculator.activeHint).toEqual(element)
expect(@calculator.hintPopup).toHaveAttr('data-calculator-hint', element.attr('id'))
it 'select the first hint if argument element is not passed', ->
@calculator.selectHint()
expect(@calculator.activeHint.attr('id')).toEqual($('.hint-item').first().attr('id'))
it 'select the first hint if argument element is empty', ->
@calculator.selectHint([])
expect(@calculator.activeHint.attr('id')).toBe($('.hint-item').first().attr('id'))
describe 'prevHint', ->
it 'Prev hint item is selected', ->
@calculator.activeHint = $('.hint-item').eq(1)
@calculator.prevHint()
expect(@calculator.activeHint.attr('id')).toBe($('.hint-item').eq(0).attr('id'))
it 'if this was the second item, select the first one', ->
@calculator.activeHint = $('.hint-item').eq(1)
@calculator.prevHint()
expect(@calculator.activeHint.attr('id')).toBe($('.hint-item').eq(0).attr('id'))
it 'if this was the first item, select the last one', ->
@calculator.activeHint = $('.hint-item').eq(0)
@calculator.prevHint()
expect(@calculator.activeHint.attr('id')).toBe($('.hint-item').eq(2).attr('id'))
it 'if this was the last item, select the second last', ->
@calculator.activeHint = $('.hint-item').eq(2)
@calculator.prevHint()
expect(@calculator.activeHint.attr('id')).toBe($('.hint-item').eq(1).attr('id'))
describe 'nextHint', ->
it 'if this was the first item, select the second one', ->
@calculator.activeHint = $('.hint-item').eq(0)
@calculator.nextHint()
expect(@calculator.activeHint.attr('id')).toBe($('.hint-item').eq(1).attr('id'))
it 'If this was the second item, select the last one', ->
@calculator.activeHint = $('.hint-item').eq(1)
@calculator.nextHint()
expect(@calculator.activeHint.attr('id')).toBe($('.hint-item').eq(2).attr('id'))
it 'If this was the last item, select the first one', ->
@calculator.activeHint = $('.hint-item').eq(2)
@calculator.nextHint()
expect(@calculator.activeHint.attr('id')).toBe($('.hint-item').eq(0).attr('id'))
describe 'handleKeyDown', ->
assertHintIsHidden = (calc, key) ->
spyOn(calc, 'hideHint')
calc.showHint()
e = jQuery.Event('keydown', { keyCode: key });
value = calc.handleKeyDown(e)
expect(calc.hideHint).toHaveBeenCalled
expect(value).toBeFalsy()
expect(e.isDefaultPrevented()).toBeTruthy()
assertHintIsVisible = (calc, key) ->
spyOn(calc, 'showHint')
spyOn($.fn, 'focus')
e = jQuery.Event('keydown', { keyCode: key });
value = calc.handleKeyDown(e)
expect(calc.showHint).toHaveBeenCalled
expect(value).toBeFalsy()
expect(e.isDefaultPrevented()).toBeTruthy()
expect(calc.activeHint.focus).toHaveBeenCalled()
assertNothingHappens = (calc, key) ->
spyOn(calc, 'showHint')
e = jQuery.Event('keydown', { keyCode: key });
value = calc.handleKeyDown(e)
expect(calc.showHint).not.toHaveBeenCalled
expect(value).toBeTruthy()
expect(e.isDefaultPrevented()).toBeFalsy()
it 'hint popup becomes hidden on press ENTER', ->
assertHintIsHidden(@calculator, KEY.ENTER)
it 'hint popup becomes visible on press ENTER', ->
assertHintIsVisible(@calculator, KEY.ENTER)
it 'hint popup becomes hidden on press SPACE', ->
assertHintIsHidden(@calculator, KEY.SPACE)
it 'hint popup becomes visible on press SPACE', ->
assertHintIsVisible(@calculator, KEY.SPACE)
it 'Nothing happens on press ALT', ->
assertNothingHappens(@calculator, KEY.ALT)
it 'Nothing happens on press any other button', ->
assertNothingHappens(@calculator, KEY.DOWN)
describe 'handleKeyDownOnHint', ->
it 'Navigation works in proper way', ->
calc = @calculator
eventToShowHint = jQuery.Event('keydown', { keyCode: KEY.ENTER } );
$('#calculator_hint').trigger(eventToShowHint);
spyOn(calc, 'hideHint')
spyOn(calc, 'prevHint')
spyOn(calc, 'nextHint')
spyOn($.fn, 'focus')
cases =
left:
event:
keyCode: KEY.LEFT
shiftKey: false
returnedValue: false
called:
'prevHint': calc
isPropagationStopped: true
leftWithShift:
returnedValue: true
event:
keyCode: KEY.LEFT
shiftKey: true
not_called:
'prevHint': calc
up:
event:
keyCode: KEY.UP
shiftKey: false
returnedValue: false
called:
'prevHint': calc
isPropagationStopped: true
upWithShift:
returnedValue: true
event:
keyCode: KEY.UP
shiftKey: true
not_called:
'prevHint': calc
right:
event:
keyCode: KEY.RIGHT
shiftKey: false
returnedValue: false
called:
'nextHint': calc
isPropagationStopped: true
rightWithShift:
returnedValue: true
event:
keyCode: KEY.RIGHT
shiftKey: true
not_called:
'nextHint': calc
down:
event:
keyCode: KEY.DOWN
shiftKey: false
returnedValue: false
called:
'nextHint': calc
isPropagationStopped: true
downWithShift:
returnedValue: true
event:
keyCode: KEY.DOWN
shiftKey: true
not_called:
'nextHint': calc
esc:
returnedValue: false
event:
keyCode: KEY.ESC
shiftKey: false
called:
'hideHint': calc
'focus': $.fn
isPropagationStopped: true
alt:
returnedValue: true
event:
which: KEY.ALT
not_called:
'hideHint': calc
'nextHint': calc
'prevHint': calc
$.each(cases, (key, data) ->
calc.hideHint.calls.reset()
calc.prevHint.calls.reset()
calc.nextHint.calls.reset()
$.fn.focus.calls.reset()
e = jQuery.Event('keydown', data.event or {});
value = calc.handleKeyDownOnHint(e)
if data.called
$.each(data.called, (method, obj) ->
expect(obj[method]).toHaveBeenCalled()
)
if data.not_called
$.each(data.not_called, (method, obj) ->
expect(obj[method]).not.toHaveBeenCalled()
)
if data.isPropagationStopped
expect(e.isPropagationStopped()).toBeTruthy()
else
expect(e.isPropagationStopped()).toBeFalsy()
expect(value).toBe(data.returnedValue)
)
describe 'calculate', ->
beforeEach ->
$('#calculator_input').val '1+2'
spyOn($, 'getWithPrefix').and.callFake (url, data, callback) ->
callback({ result: 3 })
@calculator.calculate()
it 'send data to /calculate', ->
expect($.getWithPrefix).toHaveBeenCalledWith '/calculate',
equation: '1+2'
, jasmine.any(Function)
it 'update the calculator output', ->
expect($('#calculator_output').val()).toEqual('3')