@danielkalen/simplybind
Version:
Magically simple, framework-less one-way/two-way data binding for frontend/backend in ~5kb.
245 lines (164 loc) • 6.67 kB
text/coffeescript
suite ".transform()", ()->
suiteSetup(restartSandbox)
test "Will apply a transformation to the value before updating the dependent", ()->
dispatcher = 'value': 'current'
transformFn = (newValue, currentValue)-> newValue+'+'+currentValue
objectA.prop = ''
if isBrowser
inputA.value = ''
regA.textContent = ''
regA.setAttribute 'someattr', ''
SimplyBind('value').of(dispatcher)
.to('prop').of(objectA).transform(transformFn)
if isBrowser
SimplyBind('value').of(dispatcher)
.to('value').of(inputA).transform(transformFn)
.and.to('textContent').of(regA).transform(transformFn)
.and.to('attr:someattr').of(regA).transform(transformFn)
values = ()-> if not isBrowser then [objectA.prop] else [objectA.prop, inputA.value, regA.textContent, regA.getAttribute 'someattr']
for value in values()
expect(value).to.equal 'current+current'
dispatcher.value = 'new'
for value in values()
expect(value).to.equal 'new+current+current'
dispatcher.value = 'newer'
for value in values()
expect(value).to.equal 'newer+new+current+current'
restartSandbox()
test "Will apply transformations to event bindings", ()-> if not isBrowser then @skip() else
resultHolder = 'event':null
SimplyBind('event:someEvent').of(eventEmitterA)
.to('event').of(resultHolder)
.transform (event)-> event.type
eventEmitterA.emit 'someEvent'
expect(resultHolder.event).to.equal 'someEvent'
test "Will receive the subject object as the third argument", ()->
dispatcher = 'prop':1
receivers = [objectA, objectB, objectC]
index = 0
SimplyBind('prop').of(dispatcher)
.to('prop').of(objectA)
.and.to('prop').of(objectB)
.and.to('prop').of(objectC)
.transformAll (current, prev, target)->
expect(target).to.equal(receivers[index++])
return current
expect(index).to.equal(3)
restartSandbox()
test "Will cause a re-update only to the last proxied dependent", ()->
invokeCount =
'A':0
'B':0
'C':0
SimplyBind('prop1').of(objectA)
.to ()-> invokeCount.A++
.transform (v)-> v+v
.and.to ()-> invokeCount.B++
.transform (v)-> v+v
.and.to ()-> invokeCount.C++
.transform (v)-> v+v
expect(invokeCount.A).to.equal 2
expect(invokeCount.B).to.equal 2
expect(invokeCount.C).to.equal 2
objectA.prop1 = !objectA.prop1
expect(invokeCount.A).to.equal 3
expect(invokeCount.B).to.equal 3
expect(invokeCount.C).to.equal 3
test "Promise transforms can be used instead of regular return values if SimplyBind.options.promiseTransforms is on", (done)->
objectA.prop2 = 'current'
SimplyBind('prop1', {'updateOnBind':false}).of(objectA)
.to (result)-> expect(result.then).not.to.be.undefined
.transform ()-> new Promise ()->
SimplyBind('prop2', {'promiseTransforms':true}).of(objectA)
.to('prop2').of(objectB)
.transform (newValue, currentValue)-> new Promise (resolve)-> resolve(newValue+'+'+currentValue)
setTimeout ()->
expect(objectB.prop2).to.equal 'current+current'
objectA.prop2 = 'new'
setTimeout ()->
expect(objectB.prop2).to.equal 'new+current+current'
restartSandbox()
done()
, 0
, 0
test "A transform will only be used for the last declared dependent", ()->
dispatcher = 'value': 'test'
objectA.prop1 = ''
objectB.prop1 = ''
SimplyBind('value').of(dispatcher)
.to('prop1').of(objectA)
.and.to('prop1').of(objectB)
.transform (value)-> value.toUpperCase()
expect(objectA.prop1).to.equal 'test'
expect(objectB.prop1).to.equal 'TEST'
restartSandbox()
test "Only a single transform can be used for a binding and if two transforms are added, only the last one will be used", ()->
dispatcher = 'value': 'tEsT'
objectA.prop1 = ''
SimplyBind('value').of(dispatcher)
.to('prop1').of(objectA)
.transform (value)-> value.toUpperCase()
.transform (value)-> value.toLowerCase()
expect(objectA.prop1).to.equal 'test'
restartSandbox()
test "A transform will be used both ways when .bothWays() is called after the .transform declaration", ()->
dispatcher = 'value': 'test'
objectA.prop = ''
SimplyBind('value').of(dispatcher)
.to('prop').of(objectA)
.transform (value)-> value.toUpperCase()
.bothWays()
expect(dispatcher.value).to.equal 'test'
expect(objectA.prop).to.equal 'TEST'
dispatcher.value = 'from dispatcher'
expect(dispatcher.value).to.equal 'from dispatcher'
expect(objectA.prop).to.equal 'FROM DISPATCHER'
objectA.prop = 'from objectA'
expect(dispatcher.value).to.equal 'FROM OBJECTA'
expect(objectA.prop).to.equal 'from objectA'
restartSandbox()
test "A transform will be used both ways when .bothWays() is called before the .transform declaration", ()->
dispatcher = 'value': 'test'
objectA.prop = ''
SimplyBind('value').of(dispatcher)
.to('prop').of(objectA).bothWays()
.transform (value)-> value.toUpperCase()
expect(dispatcher.value).to.equal 'test'
expect(objectA.prop).to.equal 'TEST'
dispatcher.value = 'from dispatcher'
expect(dispatcher.value).to.equal 'from dispatcher'
expect(objectA.prop).to.equal 'FROM DISPATCHER'
objectA.prop = 'from objectA'
expect(dispatcher.value).to.equal 'FROM OBJECTA'
expect(objectA.prop).to.equal 'from objectA'
restartSandbox()
test "A different transform will be used backwards if a function is passed to .bothWays() as the first argument", ()->
dispatcher = 'value': 'test'
objectA.prop = ''
SimplyBind('value').of(dispatcher)
.to('prop').of(objectA)
.transform (value)-> value.toUpperCase()
.bothWays (value)-> value.toLowerCase()
expect(dispatcher.value).to.equal 'test'
expect(objectA.prop).to.equal 'TEST'
dispatcher.value = 'From Dispatcher'
expect(dispatcher.value).to.equal 'From Dispatcher'
expect(objectA.prop).to.equal 'FROM DISPATCHER'
objectA.prop = 'From ObjectA'
expect(dispatcher.value).to.equal 'from objecta'
expect(objectA.prop).to.equal 'From ObjectA'
test "No transform will be used backwards if a false value is passed to .bothWays() as the first argument", ()->
dispatcher = 'value': 'test'
objectA.prop = ''
SimplyBind('value').of(dispatcher)
.to('prop').of(objectA)
.transform (value)-> value.toUpperCase()
.bothWays(false)
expect(dispatcher.value).to.equal 'test'
expect(objectA.prop).to.equal 'TEST'
dispatcher.value = 'From Dispatcher'
expect(dispatcher.value).to.equal 'From Dispatcher'
expect(objectA.prop).to.equal 'FROM DISPATCHER'
objectA.prop = 'From ObjectA'
expect(dispatcher.value).to.equal 'From ObjectA'
expect(objectA.prop).to.equal 'From ObjectA'