@danielkalen/simplybind
Version:
Magically simple, framework-less one-way/two-way data binding for frontend/backend in ~5kb.
1,432 lines (975 loc) • 181 kB
text/coffeescript
if mocha? and window?
isBrowser = true
mocha.setup('tdd')
mocha.bail() unless @isSauceLabsTest or location.hostname
else
isBrowser = false
global.window = global
chai = require 'chai'
chaiSpies = require 'chai-spies'
SimplyBind = require '../dist/simplybind.node.js'
startSandbox = require('./spec-helper.js').startSandbox
restartSandbox = require('./spec-helper.js').restartSandbox
chai.use chaiSpies
expect = chai.expect
should = chai.should()
suite "SimplyBind", ()->
suiteSetup(startSandbox)
suite "Settings/Binding-Options", ()->
test "SimplyBind.settings should contain the global settings list", ()->
settings = SimplyBind.settings
expect(settings.silent).not.to.be.undefined
expect(settings.placeholder).not.to.be.undefined
expect(settings.trackArrayChildren).not.to.be.undefined
test "SimplyBind.defaultOptions should contain the default binding options list", ()->
options = SimplyBind.defaultOptions
expect(options.dispatchEvents).not.to.be.undefined
expect(options.updateEvenIfSame).not.to.be.undefined
expect(options.updateOnBind).not.to.be.undefined
expect(options.simpleSelector).not.to.be.undefined
expect(options.promiseTransforms).not.to.be.undefined
test "SimplyBind.settings.placeholder should only accept arrays with lengths of 2 as a new value", ()->
expect(SimplyBind.settings.placeholder).to.eql ['{{', '}}']
SimplyBind.settings.placeholder = 'na'
expect(SimplyBind.settings.placeholder).to.eql ['{{', '}}']
SimplyBind.settings.placeholder = undefined
expect(SimplyBind.settings.placeholder).to.eql ['{{', '}}']
SimplyBind.settings.placeholder = null
expect(SimplyBind.settings.placeholder).to.eql ['{{', '}}']
SimplyBind.settings.placeholder = ()->
expect(SimplyBind.settings.placeholder).to.eql ['{{', '}}']
SimplyBind.settings.placeholder = []
expect(SimplyBind.settings.placeholder).to.eql ['{{', '}}']
SimplyBind.settings.placeholder = ['{{', '{{', '}}']
expect(SimplyBind.settings.placeholder).to.eql ['{{', '}}']
SimplyBind.settings.placeholder = ['[[', ']]']
expect(SimplyBind.settings.placeholder).to.eql ['[[', ']]']
SimplyBind.settings.placeholder = ['{{', '}}']
expect(SimplyBind.settings.placeholder).to.eql ['{{', '}}']
test "A custom binding options object can be passed as SimplyBind's second argument to be used for all subscribers added to that publisher interface", ()->
expect(SimplyBind.defaultOptions.updateOnBind).to.be.true
dispatcher = value:'uniqueValue'
receiver = {1,2,3,4}
SimplyBind('value', updateOnBind:false).of(dispatcher)
.to('1').of(receiver)
.and.to('2').of(receiver)
.and.to('3').of(receiver)
expect(receiver[1]).not.to.equal 'uniqueValue'
expect(receiver[2]).not.to.equal 'uniqueValue'
expect(receiver[3]).not.to.equal 'uniqueValue'
SimplyBind('value').of(dispatcher)
.to('4').of(receiver)
expect(receiver[4]).to.equal 'uniqueValue'
expect(SimplyBind.defaultOptions.updateOnBind).to.be.true
restartSandbox()
test "A truthy value can be passed as SimplyBind's third argument to save the specified options to all subscribers and future subscribers of a publisher", ()->
expect(SimplyBind.defaultOptions.updateOnBind).to.be.true
dispatcher = value:'uniqueValue'
receiver = {1,2,3,4}
SimplyBind('value', {updateOnBind:false}, true).of(dispatcher)
.to('1').of(receiver)
.and.to('2').of(receiver)
.and.to('3').of(receiver)
expect(receiver[1]).not.to.equal 'uniqueValue'
expect(receiver[2]).not.to.equal 'uniqueValue'
expect(receiver[3]).not.to.equal 'uniqueValue'
SimplyBind('value').of(dispatcher)
.to('4').of(receiver)
expect(receiver[4]).not.to.equal 'uniqueValue'
expect(SimplyBind.defaultOptions.updateOnBind).to.be.true
restartSandbox()
test "A custom binding options object can be used even for a cached binding/publisher", ()->
expect(SimplyBind.defaultOptions.updateOnBind).to.be.true
dispatcher = value:'uniqueValue'
receiver = {1,2,3,4}
SimplyBind('value', {updateOnBind:false}, true).of(dispatcher)
.to('1').of(receiver)
.and.to('2').of(receiver)
.and.to('3').of(receiver)
expect(receiver[1]).not.to.equal 'uniqueValue'
expect(receiver[2]).not.to.equal 'uniqueValue'
expect(receiver[3]).not.to.equal 'uniqueValue'
SimplyBind('value', updateOnBind:true).of(dispatcher)
.to('4').of(receiver)
expect(receiver[4]).to.equal 'uniqueValue'
expect(SimplyBind.defaultOptions.updateOnBind).to.be.true
restartSandbox()
test "Creating a new binding interface for a cached binding without passing an options object shouldn't overwrite existing options", ()->
expect(SimplyBind.defaultOptions.updateOnBind).to.be.true
dispatcher = value:'uniqueValue'
receiver = {1,2,3,4}
SimplyBind('value', {updateOnBind:false}, true).of(dispatcher)
.to('1').of(receiver)
.and.to('2').of(receiver)
.and.to('3').of(receiver)
expect(receiver[1]).not.to.equal 'uniqueValue'
expect(receiver[2]).not.to.equal 'uniqueValue'
expect(receiver[3]).not.to.equal 'uniqueValue'
SimplyBind('value', null, true).of(dispatcher)
.to('4').of(receiver)
expect(receiver[4]).not.to.equal 'uniqueValue'
expect(SimplyBind.defaultOptions.updateOnBind).to.be.true
restartSandbox()
suite "Argument Values", ()->
suiteSetup(restartSandbox)
suite "SimplyBind() function", ()->
test "Can only accept an object type of String, Number, Array, Function, or an existing binding instance", ()->
expect ()-> SimplyBind('s')
.not.to.throw()
expect ()-> SimplyBind(0)
.not.to.throw()
expect ()-> SimplyBind([])
.not.to.throw()
expect ()-> SimplyBind(()->)
.not.to.throw()
expect ()-> SimplyBind(SimplyBind('prop1').of(objectA))
.not.to.throw()
expect ()-> SimplyBind(true)
.to.throw()
expect ()-> SimplyBind(null)
.to.throw()
expect ()-> SimplyBind(undefined)
.to.throw()
expect ()-> SimplyBind({})
.to.throw()
expect ()-> SimplyBind(new Date())
.to.throw()
if isBrowser
expect ()-> SimplyBind($('<div />')[0])
.to.throw()
if window.Map and window.Set and window.Symbol
expect ()-> SimplyBind(new Map())
.to.throw()
expect ()-> SimplyBind(new WeakMap())
.to.throw()
expect ()-> SimplyBind(new Set())
.to.throw()
expect ()-> SimplyBind(new WeakSet())
.to.throw()
expect ()-> SimplyBind(Symbol('a'))
.to.throw()
test "Should throw when passing an empty string", ()->
expect ()-> SimplyBind('')
.to.throw()
suite ".of() method", ()->
test "Can only accept non-primitive objects", ()->
expect ()-> SimplyBind(0).of([])
.not.to.throw()
expect ()-> SimplyBind(0).of(()->)
.not.to.throw()
expect ()-> SimplyBind(0).of({})
.not.to.throw()
expect ()-> SimplyBind(0).of(new Date())
.not.to.throw()
if isBrowser
expect ()-> SimplyBind(0).of($('<div />')[0])
.not.to.throw()
if window.Map and window.Set and window.Symbol
expect ()-> SimplyBind(0).of(new Map())
.not.to.throw()
expect ()-> SimplyBind(0).of(new WeakMap())
.not.to.throw()
expect ()-> SimplyBind(0).of(new Set())
.not.to.throw()
expect ()-> SimplyBind(0).of(new WeakSet())
.not.to.throw()
expect ()-> SimplyBind(0).of(Symbol(0))
.to.throw()
expect ()-> SimplyBind(0).of(SimplyBind('prop1').of(objectA))
.not.to.throw()
expect ()-> SimplyBind(0).of('s')
.to.throw()
expect ()-> SimplyBind(0).of(0)
.to.throw()
expect ()-> SimplyBind(0).of(true)
.to.throw()
expect ()-> SimplyBind(0).of(null)
.to.throw()
expect ()-> SimplyBind(0).of(undefined)
.to.throw()
test "Will extract and use the subject bound object from the instance if passed a binding instance", ()->
bound = SimplyBind('prop3').of(objectA).to('prop3').of(objectB)
bound.set 'standard'
expect(objectA.prop3).to.equal 'standard'
expect(objectB.prop3).to.equal 'standard'
bound2 = SimplyBind('prop4').of(bound).to('prop4').of(objectB)
bound2.set 'ofBounded'
expect(objectA.prop4).to.equal 'ofBounded'
expect(objectB.prop4).to.equal 'ofBounded'
suite ".ofEvent() method", ()->
test "Can only accept string values", ()->
expect ()-> SimplyBind(0).ofEvent('s')
.not.to.throw()
expect ()-> SimplyBind(0).of(objectA).toEvent('s')
.not.to.throw()
expect ()-> SimplyBind(0).ofEvent([])
.to.throw()
expect ()-> SimplyBind(0).ofEvent(()->)
.to.throw()
expect ()-> SimplyBind(0).ofEvent({})
.to.throw()
expect ()-> SimplyBind(0).ofEvent(new Date())
.to.throw()
if isBrowser
expect ()-> SimplyBind(0).ofEvent($('<div />')[0])
.to.throw()
if window.Map and window.Set and window.Symbol
expect ()-> SimplyBind(0).ofEvent(new Map())
.to.throw()
expect ()-> SimplyBind(0).ofEvent(new WeakMap())
.to.throw()
expect ()-> SimplyBind(0).ofEvent(new Set())
.to.throw()
expect ()-> SimplyBind(0).ofEvent(new WeakSet())
.to.throw()
expect ()-> SimplyBind(0).ofEvent(Symbol(0))
.to.throw()
expect ()-> SimplyBind(0).ofEvent(SimplyBind(0).ofEvent('s'))
.to.throw()
expect ()-> SimplyBind(0).ofEvent(0)
.to.throw()
expect ()-> SimplyBind(0).ofEvent(true)
.to.throw()
expect ()-> SimplyBind(0).ofEvent(null)
.to.throw()
expect ()-> SimplyBind(0).ofEvent(undefined)
.to.throw()
suite ".transform/condition/All/Self() methods", ()->
test "Can only accept function values", ()->
window.origLog = console.warn
console.warn = chai.spy()
timesCalled = 0
SimplyBind(0).of({}).to(()->).transform(()->)
expect(console.warn).to.have.been.called.exactly(timesCalled += 0)
SimplyBind(0).of({}).to(()->).transformAll(()->)
expect(console.warn).to.have.been.called.exactly(timesCalled += 0)
SimplyBind(0).of({}).to(()->).condition(()->)
expect(console.warn).to.have.been.called.exactly(timesCalled += 0)
SimplyBind(0).of({}).to(()->).conditionAll(()->)
expect(console.warn).to.have.been.called.exactly(timesCalled += 0)
SimplyBind(0).of({}).transformSelf(()->)
expect(console.warn).to.have.been.called.exactly(timesCalled += 0)
SimplyBind(0).of({}).to(()->).transform([])
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
SimplyBind(0).of({}).to(()->).transformAll({})
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
SimplyBind(0).of({}).to(()->).conditionAll(new Date())
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
if isBrowser
SimplyBind(0).of({}).to(()->).condition($('<div />')[0])
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
if window.Map and window.Set and window.Symbol
SimplyBind(0).of({}).to(()->).transform(new Map())
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
SimplyBind(0).of({}).to(()->).transformAll(new WeakMap())
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
SimplyBind(0).of({}).to(()->).condition(new Set())
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
SimplyBind(0).of({}).to(()->).conditionAll(new WeakSet())
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
SimplyBind(0).of({}).transformSelf(Symbol(0))
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
SimplyBind(0).of({}).to(()->).transform(SimplyBind('prop1').of(objectA))
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
SimplyBind(0).of({}).to(()->).transformAll('s')
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
SimplyBind(0).of({}).to(()->).condition(0)
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
SimplyBind(0).of({}).to(()->).conditionAll(true)
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
SimplyBind(0).of({}).transformSelf(null)
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
SimplyBind(0).of({}).transformSelf(undefined)
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
console.warn = origLog
suite ".throttle()", ()->
test "Will only accept a truthy number-type argument or a boolean false", ()->
binding = SimplyBind('prop').of(objectA)._
expect(binding.throttleRate or binding.thR).to.be.undefined
SimplyBind('prop').of(objectA).throttle(200)
expect(binding.throttleRate or binding.thR).to.equal 200
SimplyBind('prop').of(objectA).throttle(false)
expect(binding.throttleRate or binding.thR).to.equal.undefined
SimplyBind('prop').of(objectA).throttle(0)
expect(binding.throttleRate or binding.thR).to.equal.undefined
SimplyBind('prop').of(objectA).throttle('0')
expect(binding.throttleRate or binding.thR).to.equal.undefined
SimplyBind('prop').of(objectA).throttle(NaN)
expect(binding.throttleRate or binding.thR).to.equal.undefined
SimplyBind('prop').of(objectA).throttle({})
expect(binding.throttleRate or binding.thR).to.equal.undefined
SimplyBind('prop').of(objectA).throttle([])
expect(binding.throttleRate or binding.thR).to.equal.undefined
SimplyBind('prop').of(objectA).throttle(()->)
expect(binding.throttleRate or binding.thR).to.equal.undefined
if window.Map and window.Set and window.Symbol
SimplyBind('prop').of(objectA).throttle(new Map())
expect(binding.throttleRate or binding.thR).to.equal.undefined
SimplyBind('prop').of(objectA).throttle(new WeakMap())
expect(binding.throttleRate or binding.thR).to.equal.undefined
SimplyBind('prop').of(objectA).throttle(new Set())
expect(binding.throttleRate or binding.thR).to.equal.undefined
SimplyBind('prop').of(objectA).throttle(new WeakSet())
expect(binding.throttleRate or binding.thR).to.equal.undefined
SimplyBind('prop').of(objectA).throttle(Symbol(9))
expect(binding.throttleRate or binding.thR).to.equal.undefined
restartSandbox()
suite "Errors & Warnings", ()->
suiteSetup(restartSandbox)
test "Warning when binding a property of a jQuery object containing multiple els", ()-> if not isBrowser then @skip() else
window.origLog = console.warn
console.warn = chai.spy()
SimplyBind('value').of $('input')
expect(console.warn).to.have.been.called()
console.warn = origLog
test "Warning when binding a property of a jQuery/NodeList/HTMLCollection object containing zero els", ()-> if not isBrowser then @skip() else
expect ()-> SimplyBind('value').of $('nonexistent')
.to.throw()
expect ()-> SimplyBind('value').of document.querySelectorAll('nonexistent')
.to.throw()
expect ()-> SimplyBind('value').of document.getElementsByTagName('nonexistent')
.to.throw()
test "Warning when binding a property of a jQuery object containing zero els", ()-> if not isBrowser then @skip() else
expect ()-> SimplyBind('value').of $('input[type="nonexistent"]')
.to.throw()
test "Warning when binding a property of a NodeList/HTMLCollection containing multiple els", ()-> if not isBrowser then @skip() else
origLog = console.warn
console.warn = chai.spy()
SimplyBind('value').of document.querySelectorAll('input')
expect(console.warn).to.have.been.called()
console.warn = origLog
test "No Warning when binding 'checked' of a jQuery object containing multiple radio/checkbox inputs", ()-> if not isBrowser then @skip() else
origLog = console.warn
console.warn = chai.spy()
SimplyBind('checked').of $radioFields
expect(console.warn).not.to.have.been.called()
SimplyBind('value').of $radioFields
expect(console.warn).to.have.been.called.exactly(1)
console.warn = origLog
test "No Warning when binding 'checked' of a NodeList/HTMLCollection/Array containing multiple radio/checkbox inputs", ()-> if not isBrowser then @skip() else
origLog = console.warn
console.warn = chai.spy()
SimplyBind('checked').of $radioFields.toArray()
expect(console.warn).not.to.have.been.called()
SimplyBind('checked').of radioFields
expect(console.warn).not.to.have.been.called()
SimplyBind('value').of $radioFields.toArray()
SimplyBind('value').of radioFields
expect(console.warn).to.have.been.called.exactly(2)
console.warn = origLog
test "Warning when binding a property of a NodeList/HTMLCollection/Array/jQuery containing elements with mixed types", ()-> if not isBrowser then @skip() else
origLog = console.warn
console.warn = chai.spy()
SimplyBind('checked').of $radioFields.add($checkboxFields).toArray()
expect(console.warn).to.have.been.called.exactly(1)
SimplyBind('checked').of $radioFields.add($checkboxFields)
expect(console.warn).to.have.been.called.exactly(2)
SimplyBind('checked').of document.querySelectorAll 'input'
expect(console.warn).to.have.been.called.exactly(3)
console.warn = origLog
test "Warning when creating a binding and passing a non-function object to .transform/.condition/All", ()->
binding = SimplyBind('prop1').of(objectA).to('prop1').of(objectB)
origLog = console.warn
console.warn = chai.spy()
timesCalled = 0
binding.transform []
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
binding.transformAll []
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
binding.transform {}
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
binding.transform new Date()
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
if isBrowser
binding.transform $('<div />')[0]
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
if window.Map and window.Set and window.Symbol
binding.transform new Map()
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
binding.transform new WeakMap()
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
binding.transform new Set()
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
binding.transform new WeakSet()
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
binding.transform Symbol(0)
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
binding.transform 's'
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
binding.transform 0
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
binding.transform true
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
binding.transform null
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
binding.transform undefined
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
binding.condition []
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
binding.conditionAll []
expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
console.warn = origLog
restartSandbox()
test "Warning when passed a non-number argument selector to an event binding", ()->
origLog = console.warn
console.warn = chai.spy()
SimplyBind('value').ofEvent 'someEvent'
SimplyBind('15').ofEvent 'someEvent'
SimplyBind(' 1aos95').ofEvent 'someEvent'
expect(console.warn).to.have.been.called.exactly(1)
console.warn = origLog
test "No warnings should be thrown when SimplyBind.options.silent is on", ()->
SimplyBind.settings.silent = true
origLog = console.warn
console.warn = chai.spy()
SimplyBind('value').ofEvent('someEvent')
SimplyBind('prop3').of(objectA).to('prop3').of(objectB).transform []
expect(console.warn).not.to.have.been.called()
console.warn = origLog
SimplyBind.settings.silent = false
test "Errors should still be thrown when SimplyBind.options.silent is on", ()->
SimplyBind.settings.silent = true
expect ()-> SimplyBind ''
.to.throw()
SimplyBind.settings.silent = false
test "No errors should be thrown when scanning for placeholders on a non-string object", ()->
dispatcher = 'prop':'value'
receiver = 'prop':null
expect(()->
SimplyBind('prop').of(dispatcher)
.to('prop.placeholder').of(receiver)
).not.to.throw()
expect(receiver.prop).not.to.equal('value')
suite "Internal Behavior", ()->
suiteSetup(restartSandbox)
test "A binding should have the correct public properies available", ()->
binding = SimplyBind('prop1').of(objectA).to('prop2').of(objectB)
expect(binding.value).not.to.be.undefined
expect(binding.original).not.to.be.undefined
expect(binding.subscribers).not.to.be.undefined
expect(binding._).not.to.be.undefined
restartSandbox()
test "Bindings to a nonexistent object prop should not create instantiate the object prop at first", ()->
expect(objectA.prop20).to.be.undefined
expect(objectB.prop20).to.be.undefined
binding = SimplyBind('prop20').of(objectA).to('prop20').of(objectB)
expect(objectA.prop20).to.be.undefined
expect(objectB.prop20).to.be.undefined
binding.set 'new value'
expect(objectA.prop20).to.equal 'new value'
expect(objectB.prop20).to.equal 'new value'
restartSandbox()
test "The binding.value property and binding.get() method should return the same value", ()->
tempObject =
'a': 'with'
'b': 'text {{verb}} a placeholder'
SimplyBind('a').of(tempObject).to('b.verb').of tempObject
bound = SimplyBind('b.verb').of(tempObject)
expect(tempObject.b).to.equal 'text with a placeholder'
expect(bound.value).to.equal 'text with a placeholder'
expect(bound.get()).to.equal 'with'
tempObject.a = 'without'
expect(tempObject.b).to.equal 'text without a placeholder'
expect(bound.value).to.equal 'text without a placeholder'
expect(bound.get()).to.equal 'without'
suite "Method availablity in different stages", ()->
test "Stage 0 (Selection Stage)", ()->
binding = ()-> SimplyBind('1')
expect(()-> binding().of objectA).not.to.throw()
expect(()-> binding().ofEvent objectA).to.throw()
expect(()-> binding().to 'prop2').to.throw()
expect(()-> binding().toEvent '/local').to.throw()
expect(()-> binding().and.to 'prop2').to.throw()
expect(()-> binding().set 'value').to.throw()
expect(()-> binding().get()).to.throw()
expect(()-> binding().transform ()->).to.throw()
expect(()-> binding().transformAll ()->).to.throw()
expect(()-> binding().transformSelf ()->).to.throw()
expect(()-> binding().condition ()->).to.throw()
expect(()-> binding().conditionAll ()->).to.throw()
expect(()-> binding().bothWays()).to.throw()
expect(()-> binding().stopPolling()).to.throw()
expect(()-> binding().pollEvery(1000).stopPolling()).to.throw()
expect(()-> binding().unBind()).to.throw()
expect(()-> binding().chainTo ()->).to.throw()
expect(()-> binding().updateSubsOnEvent 'a').to.throw()
expect(()-> binding().removeEvent 'a').to.throw()
expect(()-> binding().throttle 5).to.throw()
binding = ()-> SimplyBind('1').ofEvent 'click'
expect(()-> binding().of objectA).not.to.throw()
expect(()-> binding().ofEvent objectA).to.throw()
expect(()-> binding().to 'prop2').to.throw()
expect(()-> binding().toEvent '/local').to.throw()
expect(()-> binding().and.to 'prop2').to.throw()
expect(()-> binding().set 'value').to.throw()
expect(()-> binding().get()).to.throw()
expect(()-> binding().transform ()->).to.throw()
expect(()-> binding().transformAll ()->).to.throw()
expect(()-> binding().transformSelf ()->).to.throw()
expect(()-> binding().condition ()->).to.throw()
expect(()-> binding().conditionAll ()->).to.throw()
expect(()-> binding().bothWays()).to.throw()
expect(()-> binding().stopPolling()).to.throw()
expect(()-> binding().pollEvery(1000).stopPolling()).to.throw()
expect(()-> binding().unBind()).to.throw()
expect(()-> binding().chainTo ()->).to.throw()
expect(()-> binding().updateSubsOnEvent 'a').to.throw()
expect(()-> binding().removeEvent 'a').to.throw()
expect(()-> binding().throttle 5).to.throw()
binding = ()-> SimplyBind('1').of(objectA).to 'prop1'
expect(()-> binding().of objectA).not.to.throw()
expect(()-> binding().ofEvent objectA).to.throw()
expect(()-> binding().to 'prop2').to.throw()
expect(()-> binding().toEvent '/local').to.throw()
expect(()-> binding().and.to 'prop2').to.throw()
expect(()-> binding().set 'value').to.throw()
expect(()-> binding().get()).to.throw()
expect(()-> binding().transform ()->).to.throw()
expect(()-> binding().transformAll ()->).to.throw()
expect(()-> binding().transformSelf ()->).to.throw()
expect(()-> binding().condition ()->).to.throw()
expect(()-> binding().conditionAll ()->).to.throw()
expect(()-> binding().bothWays()).to.throw()
expect(()-> binding().stopPolling()).to.throw()
expect(()-> binding().pollEvery(1000).stopPolling()).to.throw()
expect(()-> binding().unBind()).to.throw()
expect(()-> binding().chainTo ()->).to.throw()
expect(()-> binding().updateSubsOnEvent 'a').to.throw()
expect(()-> binding().removeEvent 'a').to.throw()
expect(()-> binding().throttle 5).to.throw()
binding = ()-> SimplyBind('1').of(objectA).to('prop:prop1').of(objectB).and.to 'prop2'
expect(()-> binding().of objectA).not.to.throw()
expect(()-> binding().ofEvent objectA).to.throw()
expect(()-> binding().to 'prop2').to.throw()
expect(()-> binding().toEvent '/local').to.throw()
expect(()-> binding().and.to 'prop2').to.throw()
expect(()-> binding().set 'value').to.throw()
expect(()-> binding().get()).to.throw()
expect(()-> binding().transform ()->).to.throw()
expect(()-> binding().transformAll ()->).to.throw()
expect(()-> binding().transformSelf ()->).to.throw()
expect(()-> binding().condition ()->).to.throw()
expect(()-> binding().conditionAll ()->).to.throw()
expect(()-> binding().bothWays()).to.throw()
expect(()-> binding().stopPolling()).to.throw()
expect(()-> binding().pollEvery(1000).stopPolling()).to.throw()
expect(()-> binding().unBind()).to.throw()
expect(()-> binding().chainTo ()->).to.throw()
expect(()-> binding().updateSubsOnEvent 'a').to.throw()
expect(()-> binding().removeEvent 'a').to.throw()
expect(()-> binding().throttle 5).to.throw()
test "Stage 1 (Indication Stage)", ()->
binding = ()-> SimplyBind('1').of objectA
expect(()-> binding().of objectA).to.throw()
expect(()-> binding().ofEvent objectA).to.throw()
expect(()-> binding().to 'prop2').not.to.throw()
expect(()-> binding().toEvent '/local').not.to.throw()
expect(()-> binding().and.to 'prop2').to.throw()
expect(()-> binding().set 'value').not.to.throw()
expect(()-> binding().get()).not.to.throw()
expect(()-> binding().transform ()->).to.throw()
expect(()-> binding().transformAll ()->).to.throw()
expect(()-> binding().transformSelf ()->).not.to.throw()
expect(()-> binding().condition ()->).to.throw()
expect(()-> binding().conditionAll ()->).to.throw()
expect(()-> binding().bothWays()).to.throw()
expect(()-> binding().stopPolling()).to.throw()
expect(()-> binding().pollEvery(1000).stopPolling()).to.throw()
expect(()-> binding().unBind()).to.throw()
expect(()-> binding().chainTo ()->).to.throw()
expect(()-> binding().updateSubsOnEvent 'a').to.throw()
expect(()-> binding().removeEvent 'a').to.throw()
expect(()-> binding().throttle 5).not.to.throw()
binding = ()-> SimplyBind('1').ofEvent('click').of eventEmitterA
expect(()-> binding().of objectA).to.throw()
expect(()-> binding().ofEvent objectA).to.throw()
expect(()-> binding().to 'prop2').not.to.throw()
expect(()-> binding().toEvent '/local').not.to.throw()
expect(()-> binding().and.to 'prop2').to.throw()
expect(()-> binding().set 'value').not.to.throw()
expect(()-> binding().get()).not.to.throw()
expect(()-> binding().transform ()->).to.throw()
expect(()-> binding().transformAll ()->).to.throw()
expect(()-> binding().transformSelf ()->).not.to.throw()
expect(()-> binding().condition ()->).to.throw()
expect(()-> binding().conditionAll ()->).to.throw()
expect(()-> binding().bothWays()).to.throw()
expect(()-> binding().stopPolling()).to.throw()
expect(()-> binding().pollEvery(1000).stopPolling()).to.throw()
expect(()-> binding().unBind()).to.throw()
expect(()-> binding().chainTo ()->).to.throw()
expect(()-> binding().updateSubsOnEvent 'a').to.throw()
expect(()-> binding().removeEvent 'a').to.throw()
expect(()-> binding().throttle 5).not.to.throw()
test "Stage 2 (Binding Complete Stage)", ()->
binding = ()-> SimplyBind('1').of(objectA).to('prop1').of objectB
expect(()-> binding().of objectA).to.throw()
expect(()-> binding().ofEvent objectA).to.throw()
expect(()-> binding().to 'prop2').to.throw()
expect(()-> binding().toEvent '/local').to.throw()
expect(()-> binding().and.to 'prop2').not.to.throw()
expect(()-> binding().set 'value').not.to.throw()
expect(()-> binding().get()).not.to.throw()
expect(()-> binding().transform ()->).not.to.throw()
expect(()-> binding().transformAll ()->).not.to.throw()
expect(()-> binding().transformSelf ()->).to.throw()
expect(()-> binding().condition ()->).not.to.throw()
expect(()-> binding().conditionAll ()->).not.to.throw()
expect(()-> binding().bothWays()).not.to.throw()
expect(()-> binding().stopPolling()).not.to.throw()
expect(()-> binding().pollEvery(1000).stopPolling()).not.to.throw()
expect(()-> binding().unBind()).not.to.throw()
expect(()-> binding().chainTo ()->).not.to.throw()
expect(()-> binding().updateSubsOnEvent 'a').not.to.throw()
expect(()-> binding().removeEvent 'a').not.to.throw()
expect(()-> binding().throttle 5).not.to.throw()
binding = ()-> SimplyBind('1').of(objectA).to('prop1').of(objectB).and.to('prop2').of objectB
expect(()-> binding().of objectA).to.throw()
expect(()-> binding().ofEvent objectA).to.throw()
expect(()-> binding().to 'prop2').to.throw()
expect(()-> binding().toEvent '/local').to.throw()
expect(()-> binding().and.to 'prop2').not.to.throw()
expect(()-> binding().set 'value').not.to.throw()
expect(()-> binding().get()).not.to.throw()
expect(()-> binding().transform ()->).not.to.throw()
expect(()-> binding().transformAll ()->).not.to.throw()
expect(()-> binding().transformSelf ()->).to.throw()
expect(()-> binding().condition ()->).not.to.throw()
expect(()-> binding().conditionAll ()->).not.to.throw()
expect(()-> binding().bothWays()).not.to.throw()
expect(()-> binding().stopPolling()).not.to.throw()
expect(()-> binding().pollEvery(1000).stopPolling()).not.to.throw()
expect(()-> binding().unBind()).not.to.throw()
expect(()-> binding().chainTo ()->).not.to.throw()
expect(()-> binding().updateSubsOnEvent 'a').not.to.throw()
expect(()-> binding().removeEvent 'a').not.to.throw()
expect(()-> binding().throttle 5).not.to.throw()
binding = ()-> SimplyBind('1').of(objectA).to('prop1').of(objectB).bothWays()
expect(()-> binding().of objectA).to.throw()
expect(()-> binding().ofEvent objectA).to.throw()
expect(()-> binding().to 'prop2').to.throw()
expect(()-> binding().toEvent '/local').to.throw()
expect(()-> binding().and.to 'prop2').not.to.throw()
expect(()-> binding().set 'value').not.to.throw()
expect(()-> binding().get()).not.to.throw()
expect(()-> binding().transform ()->).not.to.throw()
expect(()-> binding().transformAll ()->).not.to.throw()
expect(()-> binding().transformSelf ()->).to.throw()
expect(()-> binding().condition ()->).not.to.throw()
expect(()-> binding().conditionAll ()->).not.to.throw()
expect(()-> binding().bothWays()).not.to.throw()
expect(()-> binding().stopPolling()).not.to.throw()
expect(()-> binding().pollEvery(1000).stopPolling()).not.to.throw()
expect(()-> binding().unBind()).not.to.throw()
expect(()-> binding().chainTo ()->).not.to.throw()
expect(()-> binding().updateSubsOnEvent 'a').not.to.throw()
expect(()-> binding().removeEvent 'a').not.to.throw()
expect(()-> binding().throttle 5).not.to.throw()
binding = ()-> SimplyBind('1').of(objectA).to('prop1').of(objectB).transform ()->
expect(()-> binding().of objectA).to.throw()
expect(()-> binding().ofEvent objectA).to.throw()
expect(()-> binding().to 'prop2').to.throw()
expect(()-> binding().toEvent '/local').to.throw()
expect(()-> binding().and.to 'prop2').not.to.throw()
expect(()-> binding().set 'value').not.to.throw()
expect(()-> binding().get()).not.to.throw()
expect(()-> binding().transform ()->).not.to.throw()
expect(()-> binding().transformAll ()->).not.to.throw()
expect(()-> binding().transformSelf ()->).to.throw()
expect(()-> binding().condition ()->).not.to.throw()
expect(()-> binding().conditionAll ()->).not.to.throw()
expect(()-> binding().bothWays()).not.to.throw()
expect(()-> binding().stopPolling()).not.to.throw()
expect(()-> binding().pollEvery(1000).stopPolling()).not.to.throw()
expect(()-> binding().unBind()).not.to.throw()
expect(()-> binding().chainTo ()->).not.to.throw()
expect(()-> binding().updateSubsOnEvent 'a').not.to.throw()
expect(()-> binding().removeEvent 'a').not.to.throw()
expect(()-> binding().throttle 5).not.to.throw()
binding = ()-> SimplyBind('1').of(objectA).to('prop1').of(objectB).transformAll ()->
expect(()-> binding().of objectA).to.throw()
expect(()-> binding().ofEvent objectA).to.throw()
expect(()-> binding().to 'prop2').to.throw()
expect(()-> binding().toEvent '/local').to.throw()
expect(()-> binding().and.to 'prop2').not.to.throw()
expect(()-> binding().set 'value').not.to.throw()
expect(()-> binding().get()).not.to.throw()
expect(()-> binding().transform ()->).not.to.throw()
expect(()-> binding().transformAll ()->).not.to.throw()
expect(()-> binding().transformSelf ()->).to.throw()
expect(()-> binding().condition ()->).not.to.throw()
expect(()-> binding().conditionAll ()->).not.to.throw()
expect(()-> binding().bothWays()).not.to.throw()
expect(()-> binding().stopPolling()).not.to.throw()
expect(()-> binding().pollEvery(1000).stopPolling()).not.to.throw()
expect(()-> binding().unBind()).not.to.throw()
expect(()-> binding().chainTo ()->).not.to.throw()
expect(()-> binding().updateSubsOnEvent 'a').not.to.throw()
expect(()-> binding().removeEvent 'a').not.to.throw()
expect(()-> binding().throttle 5).not.to.throw()
binding = ()-> SimplyBind('1').of(objectA).to('prop1').of(objectB).condition ()->
expect(()-> binding().of objectA).to.throw()
expect(()-> binding().ofEvent objectA).to.throw()
expect(()-> binding().to 'prop2').to.throw()
expect(()-> binding().toEvent '/local').to.throw()
expect(()-> binding().and.to 'prop2').not.to.throw()
expect(()-> binding().set 'value').not.to.throw()
expect(()-> binding().get()).not.to.throw()
expect(()-> binding().transform ()->).not.to.throw()
expect(()-> binding().transformAll ()->).not.to.throw()
expect(()-> binding().transformSelf ()->).to.throw()
expect(()-> binding().condition ()->).not.to.throw()
expect(()-> binding().conditionAll ()->).not.to.throw()
expect(()-> binding().bothWays()).not.to.throw()
expect(()-> binding().stopPolling()).not.to.throw()
expect(()-> binding().pollEvery(1000).stopPolling()).not.to.throw()
expect(()-> binding().unBind()).not.to.throw()
expect(()-> binding().chainTo ()->).not.to.throw()
expect(()-> binding().updateSubsOnEvent 'a').not.to.throw()
expect(()-> binding().removeEvent 'a').not.to.throw()
expect(()-> binding().throttle 5).not.to.throw()
binding = ()-> SimplyBind('1').of(objectA).to('prop1').of(objectB).conditionAll ()->
expect(()-> binding().of objectA).to.throw()
expect(()-> binding().ofEvent objectA).to.throw()
expect(()-> binding().to 'prop2').to.throw()
expect(()-> binding().toEvent '/local').to.throw()
expect(()-> binding().and.to 'prop2').not.to.throw()
expect(()-> binding().set 'value').not.to.throw()
expect(()-> binding().get()).not.to.throw()
expect(()-> binding().transform ()->).not.to.throw()
expect(()-> binding().transformAll ()->).not.to.throw()
expect(()-> binding().transformSelf ()->).to.throw()
expect(()-> binding().condition ()->).not.to.throw()
expect(()-> binding().conditionAll ()->).not.to.throw()
expect(()-> binding().bothWays()).not.to.throw()
expect(()-> binding().stopPolling()).not.to.throw()
expect(()-> binding().pollEvery(1000).stopPolling()).not.to.throw()
expect(()-> binding().unBind()).not.to.throw()
expect(()-> binding().chainTo ()->).not.to.throw()
expect(()-> binding().updateSubsOnEvent 'a').not.to.throw()
expect(()-> binding().removeEvent 'a').not.to.throw()
expect(()-> binding().throttle 5).not.to.throw()
binding = ()-> SimplyBind('1').of(objectA).to('prop1').of(objectB).transform(()->).and.to ()->
expect(()-> binding().of objectA).to.throw()
expect(()-> binding().ofEvent objectA).to.throw()
expect(()-> binding().to 'prop2').to.throw()
expect(()-> binding().toEvent '/local').to.throw()
expect(()-> binding().and.to 'prop2').not.to.throw()
expect(()-> binding().set 'value').not.to.throw()
expect(()-> binding().get()).not.to.throw()
expect(()-> binding().transform ()->).not.to.throw()
expect(()-> binding().transformAll ()->).not.to.throw()
expect(()-> binding().transformSelf ()->).to.throw()
expect(()-> binding().condition ()->).not.to.throw()
expect(()-> binding().conditionAll ()->).not.to.throw()
expect(()-> binding().bothWays()).not.to.throw()
expect(()-> binding().stopPolling()).not.to.throw()
expect(()-> binding().pollEvery(1000).stopPolling()).not.to.throw()
expect(()-> binding().unBind()).not.to.throw()
expect(()-> binding().chainTo ()->).not.to.throw()
expect(()-> binding().updateSubsOnEvent 'a').not.to.throw()
expect(()-> binding().removeEvent 'a').not.to.throw()
expect(()-> binding().throttle 5).not.to.throw()
binding = ()-> SimplyBind('1').of(objectA).to('prop1').of(objectB).transform(()->).and.to(()->).chainTo ()->
expect(()-> binding().of objectA).to.throw()
expect(()-> binding().ofEvent objectA).to.throw()
expect(()-> binding().to 'prop2').to.throw()
expect(()-> binding().toEvent '/local').to.throw()
expect(()-> binding().and.to 'prop2').not.to.throw()
expect(()-> binding().set 'value').not.to.throw()
expect(()-> binding().get()).not.to.throw()
expect(()-> binding().transform ()->).not.to.throw()
expect(()-> binding().transformAll ()->).not.to.throw()
expect(()-> binding().transformSelf ()->).to.throw()
expect(()-> binding().condition ()->).not.to.throw()
expect(()-> binding().conditionAll ()->).not.to.throw()
expect(()-> binding().bothWays()).not.to.throw()
expect(()-> binding().stopPolling()).not.to.throw()
expect(()-> binding().pollEvery(1000).stopPolling()).not.to.throw()
expect(()-> binding().unBind()).not.to.throw()
expect(()-> binding().chainTo ()->).not.to.throw()
expect(()-> binding().updateSubsOnEvent 'a').not.to.throw()
expect(()-> binding().removeEvent 'a').not.to.throw()
expect(()-> binding().throttle 5).not.to.throw()
suite "Cached Bindings", ()->
test "A cached version of the binding should be returned when re-creating an existing one", ()->
# ==== ObjectProp =================================================================================
expect(SimplyBind('prop1').of(objectA)._.ID)
.to.equal(SimplyBind('prop1').of(objectA)._.ID)
expect(SimplyBind('prop1').of(objectA).to('prop1').of(objectB)._.subs[0].ID)
.to.equal(SimplyBind('prop1').of(objectB)._.ID)
if isBrowser
# ==== DOMAttr =================================================================================
expect(SimplyBind('attr:someattr').of(regA)._.ID)
.to.equal(SimplyBind('attr:someattr').of(regA)._.ID)
expect(SimplyBind('attr:someattr').of(regA).to('attr:someattr').of(regB)._.subs[0].ID)
.to.equal(SimplyBind('attr:someattr').of(regB)._.ID)
# ==== DOMValue =================================================================================
expect(SimplyBind('value').of(inputA)._.ID)
.to.equal(SimplyBind('value').of(inputA)._.ID)
expect(SimplyBind('value').of(inputA).to('value').of(inputB)._.subs[0].ID)
.to.equal(SimplyBind('value').of(inputB)._.ID)
# ==== DOMCheckbox Single =================================================================================
expect(SimplyBind('checked').of(checkboxA)._.ID)
.to.equal(SimplyBind('checked').of(checkboxA)._.ID)
expect(SimplyBind('checked').of(checkboxA).to('checked').of(checkboxB)._.subs[0].ID)
.to.equal(SimplyBind('checked').of(checkboxB)._.ID)
# ==== DOMCheckbox =================================================================================
expect(SimplyBind('checked').of($checkboxFields)._.ID)
.to.equal(SimplyBind('checked').of($checkboxFields)._.ID)
# ==== DOMRadio =================================================================================
expect(SimplyBind('checked').of($radioFields)._.ID)
.to.equal(SimplyBind('checked').of($radioFields)._.ID)
# ==== DOMText =================================================================================
expect(SimplyBind('textContent').of(regA)._.ID)
.to.equal(SimplyBind('textContent').of(regA)._.ID)
expect(SimplyBind('textContent').of(regA).to('textContent').of(regB)._.subs[0].ID)
.to.equal(SimplyBind('textContent').of(regB)._.ID)
# ==== Event =================================================================================
expect(SimplyBind(0).ofEvent('someEvent').of(eventEmitterA)._.ID)
.to.equal(SimplyBind(0).ofEvent('someEvent').of(eventEmitterA)._.ID)
expect(SimplyBind(0).ofEvent('someEvent').of(eventEmitterA).toEvent('someEvent').of(eventEmitterB)._.subs[0].ID)
.to.equal(SimplyBind(0).ofEvent('someEvent').of(eventEmitterB)._.ID)
# ==== Array =================================================================================
expect(SimplyBind(arrayA)._.ID)
.to.equal(SimplyBind(arrayA)._.ID)
expect(SimplyBind(arrayA).to(arrayB)._.subs[0].ID)
.to.equal(SimplyBind(arrayB)._.ID)
# ==== Function =================================================================================
expect(SimplyBind(fnA)._.ID)
.to.equal(SimplyBind(fnA)._.ID)
expect(SimplyBind(fnA).to(fnB)._.subs[0].ID)
.to.equal(SimplyBind(fnB)._.ID)
restartSandbox()
test "When binding an object prop with a placeholder indicator in the selector for an existing binding that didn't have indicators, placeholders will be rescanned", ()->
dispatcher = 'prop':'This is an {{size}} size shirt'
receiver = 'prop':''
SimplyBind('prop').of(dispatcher)
.to('prop').of(receiver)
expect(receiver.prop).to.equal(dispatcher.prop)
expect(dispatcher.prop).to.equal 'This is an {{size}} size shirt'
SimplyBind('prop').of(dispatcher)
.to('prop.size').of(receiver)
dispatcher.prop = 'XXL'
expect(dispatcher.prop).to.equal 'XXL'
expect(receiver.prop).to.equal 'This is an XXL size shirt'
test "When re-binding a binding with placeholder where the global placeholders regEx has changed to a diff regEx from present in the original binding, the binding's regEx shouldn't change", ()->
dispatcher = 'noun':'', 'adjective':''
receiver = 'prop':'This {{noun}} is **adjective**'
SimplyBind('noun').of(dispatcher)
.to('prop.noun').of(receiver)
dispatcher.noun = 'test'
expect(receiver.prop).to.equal 'This test is **adjective**'
SimplyBind.settings.placeholder = ['**', '**']
SimplyBind('adjective').of(dispatcher)
.to('prop.adjective').of(receiver)
dispatcher.adjective = 'good'
expect(receiver.prop).to.equal 'This test is **adjective**'
dispatcher.noun = 'suite'
expect(receiver.prop).to.equal 'This suite is **adjective**'
SimplyBind.settings.placeholder = ['{{', '}}']
test "When re-binding an object prop that was deleted manually make sure to re-make the property a live one", ()->
objectA.prop = 1
SimplyBind('prop').of(objectA)
.to('prop').of(objectB)
expect(objectB.prop).to.equal(objectA.prop)
objectA.prop = 2
expect(objectB.prop).to.equal(objectA.prop)
delete objectB.prop
objectA.prop = 3
expect(objectB.prop).not.to.equal(objectA.prop)
SimplyBind('prop').of(objectA)
.to('prop').of(objectB)
expect(objectB.prop).to.equal(objectA.prop)
objectA.prop = 4
expect(objectB.prop).to.equal(objectA.prop)
restartSandbox()
test "When binding an index of an array that's brand new and the array is tracked and so are its children, the new index should be made so it also tracked", ()->
SimplyBind.settings.trackArrayChildren = true
invokeCount = 0
SimplyBind(arrayA).to ()-> invokeCount++
expect(invokeCount).to.equal 1
arrayA[3] = 44
expect(invokeCount).to.equal 2
arrayA[20] = 21
expect(invokeCount).to.equal 2
SimplyBind('18').of(arrayA)
arrayA[18] = 188
expect(invokeCount).to.equal 4
arrayA[18] = 1888
expect(invokeCount).to.equal 5
SimplyBind.settings.trackArrayChildren = false
restartSandbox()
suite "Data Binding Behavior", ()->
suiteSetup(restartSandbox)
test "Object properties should behave the same way across all object types", ()->
dispatcher =
'standard': objectA
'array': arrayA
'function': ()->
'domDiv': if isBrowser then $('<div />')[0] else {}
'domInput': if isBrowser then $('<input />')[0] else {}
'domNode': if isBrowser then $('<div>text</div>')[0].childNodes[0] else {}
'date': new Date()
receiver =
'standard': objectB
'array': arrayB
'function': ()->
'domDiv': if isBrowser then $('<div />')[0] else {}
'domInput': if isBrowser then $('<input />')[0] else {}
'domNode': if isBrowser then $('<div>text</div>')[0].childNodes[0] else {}
'date': new Date()
for name,object of dispatcher
SimplyBind('prop').of(dispatcher[name]).to('prop').of(receiver[name])
expect(receiver[name].prop).to.be.undefined
SimplyBind('prop').of(dispatcher[name]).set(100)
expect(receiver[name].prop).to.equal(100)
restartSandbox()
test "Object properties should be made into live properties unless they are inherited or unconfigurable", ()->
SimplyBind.defaultOptions.updateOnBind = false
invokeCount = 0
### ========================================================================== ###
SimplyBind('prop1').of(objectA).to ()-> invokeCount++
expect(invokeCount).to.equal(0)
objectA.prop1 = !objectA.prop1
expect(invokeCount).to.equal(1)
### ========================================================================== ###
SimplyBind('nonexistent').of(objectA).to ()-> invokeCount++
expect(invokeCount).to.equal(1)
objectA.nonexistent = !objectA.nonexistent
expect(invokeCount).to.equal(2)
### ========================================================================== ###
Object.defineProperty objectA, 'protected', value:'cant touch this'
SimplyBind('protected').of(objectA).to ()-> invokeCount++
expect(invokeCount).to.equal(2)
objectA.protected = !objectA.protected
expect(invokeCount).to.equal(2)
### ========================================================================== ###
obj = Object.create(protected:'cant touch this')
SimplyBind('protected').of(obj).to ()-> invokeCount++
expect(invokeCount).to.equal(2)
obj.protected = !obj.protected
expect(invokeCount).to.equal(2)
SimplyBind.defaultOptions.updateOnBind = true
restartSandbox()
test "The property's original setter (if exists) should be invoked during a live property update", ()->
prop7 = 'hey!'
invokeCountGet = 0
invokeCountSet = 0
Object.defineProperty objectA, 'prop7',
enumerable: true
configurable: true
get: ()->
invokeCountGet++
prop7
set: (val)->
invokeCountSet++
prop7 = val
expect(objectA.prop7).to.equal 'hey!'
expect(invokeCountGet).to.equal 1
expect(invokeCountSet).to.equal 0
SimplyBind('prop7').of(objectA).to('prop3').of objectB
objectA.prop7 = 'hello!'
expect(invokeCountGet).to.equal 2
expect(invokeCountSet).to.equal 1
expect(objectA.prop7