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).to.equal 'hello!'
		
			objectA.prop7 = 'hi!'
			expect(invokeCountGet).to.equal 2
			expect(invokeCountSet).to.equal 2
			restartSandbox()



		test "Publishers will update subscribers even if their value is falsy", ()->
			binding = SimplyBind('prop1').of(objectA).to('prop1').of(objectB)
			
			binding.set ''
			expect(objectB.prop1).to.equal ''
			
			binding.set 0
			expect(objectB.prop1).to.equal 0
			
			binding.set false
			expect(objectB.prop1).to.equal false
			
			binding.set undefined
			expect(objectB.prop1).to.equal undefined
			
			binding.set null
			expect(objectB.prop1).to.equal null

			restartSandbox()



		test "Update subscribers of a binding even if it's unchanged when SimplyBind.options.updateEvenIfSame is on or if the binding type is Func or Event", ()->
			expect(SimplyBind.defaultOptions.updateEvenIfSame).to.be.false
			invokeCount = object:0, func:0, event:0
			dispatcher = object:'start', func:'start', event:'start'

			eventEmitterA.on 'alwaysEmit', ()-> invokeCount.event++
			
			bindings =
				'object': SimplyBind('object').of(dispatcher).to('prop').of(objectB).chainTo (value)-> invokeCount.object++
				'func': SimplyBind('func', updateEvenIfSame:false).of(dispatcher).to(()-> invokeCount.func++)
				'event': SimplyBind('event', updateEvenIfSame:false).of(dispatcher).toEvent('alwaysEmit').of(eventEmitterA)
			
			expect(objectB.prop).to.equal 'start'
			expect(invokeCount.object).to.equal 1
			
			dispatcher.object = "shouldn't update"
			expect(objectB.prop).to.equal "shouldn't update"
			expect(invokeCount.object).to.equal 2
			
			dispatcher.object = "shouldn't update"
			expect(objectB.prop).to.equal "shouldn't update"
			expect(invokeCount.object).to.equal 2
			

			expect(invokeCount.func).to.equal 1
			
			dispatcher.func = 'should update'
			expect(invokeCount.func).to.equal 2

			dispatcher.func = 'should update'
			expect(invokeCount.func).to.equal 3
			


			expect(invokeCount.event).to.equal 1
			
			dispatcher.event = 'should update'
			expect(invokeCount.event).to.equal 2

			dispatcher.event = 'should update'
			expect(invokeCount.event).to.equal 3



			SimplyBind('object').of(dispatcher).to('prop').of(objectB).setOption 'updateEvenIfSame', true
			
			dispatcher.object = 'should update'
			expect(objectB.prop).to.equal 'should update'
			expect(invokeCount.object).to.equal 3
		
			dispatcher.object = 'should update'
			dispatcher.object = 'should update'
			dispatcher.object = 'should update'
			dispatcher.object = 'should update'
			expect(invokeCount.object).to.equal 7
			

			SimplyBind('object').of(dispatcher).to('prop').of(objectB).setOption 'updateEvenIfSame', false
			
			dispatcher.object = "shouldn't update"
			expect(objectB.prop).to.equal "shouldn't update"
			expect(invokeCount.object).to.equal 8
			
			dispatcher.object = "shouldn't update"
			dispatcher.object = "shouldn't update"
			dispatcher.object = "shouldn't update"
			dispatcher.object = "shouldn't update"
			expect(invokeCount.object).to.equal 8
			restartSandbox()



		test "Should update subscribers even when its new value is undefined", ()->
			binding = SimplyBind('prop1').of(objectA).to('prop1').of(objectB)
			objectA.prop1 = 10
			expect(objectB.prop1).to.equal 10
			
			objectA.prop1 = window.nonexistent # undefined value
			expect(objectB.prop1).to.be.undefined
			

			objectA.prop1 = 20
			expect(objectB.prop1).to.equal 20
			
			objectA.prop1 = window.nonexistent # undefined value
			expect(objectB.prop1).to.be.undefined
			
			restartSandbox()



		test "Subscribers should update their own subscribers when being updated by a publisher, even if these subscribers are not liveProps", ()-> if not isBrowser then @skip() else
			objectA.prop2 = 0.8
			
			SimplyBind('prop2').of(objectA)
				.to('opacity').of regA.style
			
			SimplyBind('opacity').of(regA.style)
				.to('font-size').of(regA.style)
					.transform (opacity)-> opacity * 20 + 'px'
				.and.to('font-size').of(regB.style)
					.transform (opacity)-> opacity * 40 + 'px'
			

			expect(regA.style.opacity.toString()).to.equal '0.8'
			expect(regA.style['font-size']).to.equal '16px'
			expect(regB.style['font-size']).to.equal '32px'
			

			objectA.prop2 = 0.5
			expect(regA.style.opacity.toString()).to.equal '0.5'
			expect(regA.style['font-size']).to.equal '10px'
			expect(regB.style['font-size']).to.equal '20px'
			restartSandbox()



		test "Placeholder indicators in a property name will be ignored if SimplyBind.options.simpleSelector is on", ()->
			objA = 'first': 'This {{placeholder}} will change'
			objB = 'second': 'This {{nonplaceholder}} will remain the same'

			SimplyBind('prop1').of(objectA).to('first.placeholder').of(objA)
			objectA.prop1 = 'placeholder'

			SimplyBind('prop1').of(objectB).to('second.nonplaceholder', {'simpleSelector':true}).of(objB)
			objectB.prop1 = 'placeholder'

			expect(objA['first']).to.equal 'This placeholder will change'
			expect(objB['second']).to.equal 'This {{nonplaceholder}} will remain the same'



		test "Subscribers shouldn't be re-updated when a transform function is added if SimplyBind.options.updateOnBind is off", ()->
			dispatcher = 'value': 123
			invokeCount =
				'object': 0
				'array': 0
				'function': 0
				'domAttr': 0
				'domText': 0
				'domInput': 0
				'jQueryProp': 0
				'event': 0

			fakeTransform = (value)-> value
			SimplyBind.defaultOptions.updateOnBind = false
		
			SimplyBind('prop').of(objectA).to(()-> invokeCount.object++).transform(fakeTransform)
			SimplyBind(arrayA).to(()-> invokeCount.array++).transform(fakeTransform)
			SimplyBind(fn = ()-> true).to(()-> invokeCount.function++).transform(fakeTransform)
			SimplyBind('attr:prop').of(regA).to(()-> invokeCount.domAttr++).transform(fakeTransform) if isBrowser
			SimplyBind('textContent').of(regA).to(()-> invokeCount.domText++).transform(fakeTransform) if isBrowser
			SimplyBind('value').of(inputA).to(()-> invokeCount.domInput++).transform(fakeTransform) if isBrowser
			SimplyBind('prop').of($regB).to(()-> invokeCount.jQueryProp++).transform(fakeTransform) if isBrowser
			SimplyBind(0).ofEvent('someEvent').of(eventEmitterA).to(()-> invokeCount.event++).transform(fakeTransform)

			SimplyBind.defaultOptions.updateOnBind = true

			
			SimplyBind('value').of(dispatcher).to('prop').of(objectA)
			SimplyBind('value').of(dispatcher).to(arrayA)
			SimplyBind('value').of(dispatcher).to(fn)
			SimplyBind('value').of(dispatcher).to('attr:prop').of(regA) if isBrowser
			SimplyBind('value').of(dispatcher).to('textContent').of(regA) if isBrowser
			SimplyBind('value').of(dispatcher).to('value').of(inputA) if isBrowser
			SimplyBind('value').of(dispatcher).to('prop').of($regB) if isBrowser
			SimplyBind('value').of(dispatcher).toEvent('someEvent').of(eventEmitterA)

			expect(invokeCount.object).to.equal 1
			expect(invokeCount.array).to.equal 0 # Cannot get updated
			expect(invokeCount.function).to.equal 3 # Ignores updateOnBind
			expect(invokeCount.event).to.equal 1
			if isBrowser
				expect(invokeCount.domAttr).to.equal 1
				expect(invokeCount.domText).to.equal 1
				expect(invokeCount.domInput).to.equal 1
				expect(invokeCount.jQueryProp).to.equal 1

			restartSandbox()
















	suite "Data Binding", ()->
		suiteSetup(restartSandbox)
		test "Live properties should be supported on all object properties", ()->
			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 {}
			receiver =
				'standard': null
				'array': null
				'function': null
				'domDiv': null
				'domInput': null
				'domNode': null

			for name,object of dispatcher
				SimplyBind('prop').of(dispatcher[name]).to(name).of(receiver)
				expect(receiver[name]).to.equal(undefined)
				
				object.prop = 100
				expect(receiver[name]).to.equal(100)

			restartSandbox()





		test "Infinite loops should not occur in looping update chains", ()->
			SimplyBind.defaultOptions.updateEvenIfSame = true

			# ==== Objects =================================================================================
			SimplyBind('prop').of(objectA)
				.to('prop').of(objectB).bothWays()
					.chainTo('prop').of(objectC).bothWays()
						.chainTo('prop').of(objectA).bothWays()

			objectA.prop = 'from objectA'
			expect(objectA.prop).to.equal 'from objectA'
			expect(objectB.prop).to.equal 'from objectA'
			expect(objectC.prop).to.equal 'from objectA'

			objectB.prop = 'from objectB'
			expect(objectA.prop).to.equal 'from objectB'
			expect(objectB.prop).to.equal 'from objectB'
			expect(objectC.prop).to.equal 'from objectB'



			# ==== Arrays =================================================================================
			SimplyBind(0).of(arrayA)
				.to(0).of(arrayB).bothWays()
					.chainTo(0).of(arrayC).bothWays()
						.chainTo(0).of(arrayA).bothWays()

			arrayA[0] = 'from arrayA'
			expect(arrayA[0]).to.equal 'from arrayA'
			expect(arrayB[0]).to.equal 'from arrayA'
			expect(arrayC[0]).to.equal 'from arrayA'

			arrayB[0] = 'from arrayB'
			expect(arrayA[0]).to.equal 'from arrayB'
			expect(arrayB[0]).to.equal 'from arrayB'
			expect(arrayC[0]).to.equal 'from arrayB'
			


			if isBrowser
				# ==== DOMAttr =================================================================================
				SimplyBind('attr:someattr').of(regA)
					.to('attr:someattr').of(regB).bothWays()
						.chainTo('attr:someattr').of(regC).bothWays()
							.chainTo('attr:someattr').of(regA).bothWays()

				# regA.setAttribute 'someattr', 'from regElementA'
				SimplyBind('attr:someattr').of(regA).set('from regElementA')
				expect(regA.getAttribute 'someattr').to.equal 'from regElementA'
				expect(regB.getAttribute 'someattr').to.equal 'from regElementA'
				expect(regC.getAttribute 'someattr').to.equal 'from regElementA'

				# regB.setAttribute 'someattr', 'from regElementB'
				SimplyBind('attr:someattr').of(regB).set('from regElementB')
				expect(regA.getAttribute 'someattr').to.equal 'from regElementB'
				expect(regB.getAttribute 'someattr').to.equal 'from regElementB'
				expect(regC.getAttribute 'someattr').to.equal 'from regElementB'
				


				# ==== DOMText =================================================================================
				SimplyBind('textContent').of(regA)
					.to('textContent').of(regB).bothWays()
						.chainTo('textContent').of(regC).bothWays()
							.chainTo('textContent').of(regA).bothWays()

				SimplyBind('textContent').of(regA).set 'from regElementA'
				expect(regA.textContent).to.equal 'from regElementA'
				expect(regB.textContent).to.equal 'from regElementA'
				expect(regC.textContent).to.equal 'from regElementA'

				SimplyBind('textContent').of(regB).set 'from regElementB'
				expect(regA.textContent).to.equal 'from regElementB'
				expect(regB.textContent).to.equal 'from regElementB'
				expect(regC.textContent).to.equal 'from regElementB'
				


				# ==== DOMValue =================================================================================
				SimplyBind('value').of(inputA)
					.to('value').of(inputB).bothWays()
						.chainTo('value').of(inputC).bothWays()
							.chainTo('value').of(inputA).bothWays()

				inputA.value = 'from inputElementA'
				inputA.emit 'change'
				expect(inputA.value).to.equal 'from inputElementA'
				expect(inputB.value).to.equal 'from inputElementA'
				expect(inputC.value).to.equal 'from inputElementA'

				inputB.value = 'from inputElementB'
				inputB.emit 'change'
				expect(inputA.value).to.equal 'from inputElementB'
				expect(inputB.value).to.equal 'from inputElementB'
				expect(inputC.value).to.equal 'from inputElementB'



			# ==== Events =================================================================================			
			SimplyBind(0).ofEvent('eventA').of(eventEmitterA)
				.toEvent('eventB').of(eventEmitterA).bothWays()
			
			SimplyBind(0).ofEvent('eventB').of(eventEmitterA)
				.toEvent('eventC').of(eventEmitterA).bothWays()
			
			SimplyBind(0).ofEvent('eventC').of(eventEmitterA)
				.toEvent('eventA').of(eventEmitterA).bothWays()

			invokeCountA = invokeCountB = invokeCountC = 0
			eventEmitterA.on 'eventA', ()-> invokeCountA++
			eventEmitterA.on 'eventB', ()-> invokeCountB++
			eventEmitterA.on 'eventC', ()-> invokeCountC++
			
			eventEmitterA.emit 'eventA'
			eventEmitterA.emit 'eventB'
			eventEmitterA.emit 'eventC'

			expect(invokeCountA).to.equal 3
			expect(invokeCountB).to.equal 3
			expect(invokeCountC).to.equal 3
			SimplyBind.defaultOptions.updateEvenIfSame = false
			restartSandbox()




		test "Infinite loops should not occur for colliding two-way bindings", ()->
			SimplyBind.defaultOptions.updateEvenIfSame = true
			dispatcher = 'prop': 0
			objectA.prop1 = 0
			objectB.prop1 = 0
			objectC.prop1 = 0
			SimplyBind('prop').of(dispatcher)
				.to('prop1').of(objectA).bothWays().transform (v, ov)-> v+ov
				.and.to('prop1').of(objectB).bothWays().transform (v, ov)-> v+ov
				.and.to('prop1').of(objectC).bothWays().transform (v, ov)-> v+ov

			expect(dispatcher.prop).to.equal 0
			expect(objectA.prop1).to.equal 0
			expect(objectB.prop1).to.equal 0
			expect(objectC.prop1).to.equal 0
			
			dispatcher.prop = 1
			expect(dispatcher.prop).to.equal 1
			expect(objectA.prop1).to.equal 1
			expect(objectB.prop1).to.equal 1
			expect(objectC.prop1).to.equal 1

			objectA.prop1 = 2
			expect(dispatcher.prop).to.equal 3
			expect(objectA.prop1).to.equal 2
			expect(objectB.prop1).to.equal 4 # not 3 because dispatcher.prop gets a 2 from objectA.prop1 but then it transforms it to 3 and passes to this binding.
			expect(objectC.prop1).to.equal 4 # not 3 because dispatcher.prop gets a 2 from objectA.prop1 but then it transforms it to 3 and passes to this binding.

			objectC.prop1 = 3
			expect(dispatcher.prop).to.equal 6
			expect(objectA.prop1).to.equal 8
			expect(objectB.prop1).to.equal 10
			expect(objectC.prop1).to.equal 3


			SimplyBind.defaultOptions.updateEvenIfSame = false
			restartSandbox()	



		test "Infinite loops should occur only when a value is bound to a function and that function updates the value", ()->
			invokeCount = 0

			SimplyBind('prop1').of(objectA)
				.to ()-> unless invokeCount is 15
					objectA.prop1 = ++invokeCount

			expect(invokeCount).to.equal(objectA.prop1)
			expect(invokeCount).to.equal(15)
			restartSandbox()




		test "Update subscribers", ()->
			SimplyBind.defaultOptions.updateOnBind = false
			invokeCount =
				'object': 0
				'array': 0
				'function': 0
				'proxy': 0
				'domAttr': 0
				'domText': 0
				'domValue': 0
				'domCheckboxSingle': 0
				'domCheckbox': 0
				'domRadioSingle': 0
				'domRadio': 0
				'event': 0
			

			# ==== Objects =================================================================================
			SimplyBind('prop').of(objectA).to ()-> invokeCount.object++
			objectA.prop = true
			expect(invokeCount.object).to.equal(1)


			# ==== Arrays =================================================================================
			SimplyBind(arrayA).to ()-> invokeCount.array++
			arrayA.push(1)
			arrayA.unshift(1)
			arrayA.pop()
			arrayA.shift()
			arrayA.splice(0,1)
			expect(invokeCount.array).to.equal(5)


			# ==== Functions =================================================================================
			SimplyBind(()->true).to ()-> invokeCount.function++
			expect(invokeCount.function).to.equal(1)


			# ==== Proxy functions =================================================================================
			obj = base:10, test:(a,b)-> (a+b)*@base
			SimplyBind.func('test').of(obj).to (value)->
				expect(value.result).to.equal 50
				expect(value.args).to.eql [2,3]
				invokeCount.proxy++

			obj.test(2,3)
			expect(invokeCount.proxy).to.equal(1)


			if isBrowser
				# ==== DOMAttr =================================================================================
				SimplyBind('attr:someattr').of(regA).to ()-> invokeCount.domAttr++
				regA.setAttribute('someattr', 10)
				SimplyBind('attr:someattr').of(regA).set(true)
				expect(invokeCount.domAttr).to.equal(1)


				# ==== DOMText =================================================================================
				SimplyBind('textContent').of(regA).to ()-> invokeCount.domText++
				SimplyBind('textContent').of(regA).set 'true'
				expect(invokeCount.domText).to.equal(1)


				# ==== DOMValue =================================================================================
				SimplyBind('value').of(inputA).to ()-> invokeCount.domValue++
				inputA.value = 'true'
				inputA.emit 'change'
				expect(invokeCount.domValue).to.equal(1)


				# ==== DOMCheckbox Single =================================================================================
				SimplyBind('checked').of(checkboxA).to ()-> invokeCount.domCheckboxSingle++
				checkboxA.checked = true
				checkboxA.emit 'change'
				expect(invokeCount.domCheckboxSingle).to.equal(1)


				# ==== DOMCheckbox =================================================================================
				SimplyBind('checked').of(checkboxFields).to ()-> invokeCount.domCheckbox++
				checkboxB.checked = true
				checkboxB.emit 'change'
				expect(invokeCount.domCheckbox).to.equal(1)


				# ==== DOMRadio Single =================================================================================
				SimplyBind('checked').of(radioA).to ()-> invokeCount.domRadioSingle++
				radioA.checked = true
				radioA.emit 'change'
				expect(invokeCount.domRadioSingle).to.equal(1)


				# ==== DOMRadio =================================================================================
				SimplyBind('checked').of(radioFields).to ()-> invokeCount.domRadio++
				radioB.checked = true
				radioB.emit 'change'
				expect(invokeCount.domRadio).to.equal(1)


			# ==== Event =================================================================================
			SimplyBind.defaultOptions.updateEvenIfSame = true
			SimplyBind(0).ofEvent('someEvent').of(eventEmitterA).to ()-> invokeCount.event++
			eventEmitterA.emit 'someEvent'
			

			expect(invokeCount.event).to.equal(1)
	
			SimplyBind.defaultOptions.updateEvenIfSame = false
			SimplyBind.defaultOptions.updateOnBind = true
			restartSandbox()







		test "Receive a value as a dependent", ()->
			SimplyBind.defaultOptions.updateOnBind = false
			invokeCount =
				'object': 0
				'array': 0
				'proxy': 0
				'function': 0
				'domAttr': 0
				'domText': 0
				'domValue': 0
				'domCheckboxSingle': 0
				'domCheckbox': 0
				'domRadio': 0
				'event': 0
			

			# ==== Objects =================================================================================
			SimplyBind('prop').of(objectA).to ()-> invokeCount.object++
			SimplyBind(()-> true).to('prop').of(objectA)

			expect(objectA.prop).to.equal(true)
			expect(invokeCount.object).to.equal(1)


			# ==== Arrays =================================================================================
			SimplyBind(arrayA).to ()-> invokeCount.array++
			SimplyBind(()-> []).to('prop').of(objectA)
			
			expect(arrayA.length).not.to.equal(0)
			expect(invokeCount.array).to.equal(0)


			# ==== Proxy functions =================================================================================
			obj = base:10, test:(a,b)-> (a+b)*@base
			proxyInterface = SimplyBind.func('test').of(obj).to ()-> invokeCount.proxy++
			SimplyBind(()-> true).to(proxyInterface)
			expect(invokeCount.proxy).to.equal(0)



			if isBrowser
				# ==== DOMAttr =================================================================================
				SimplyBind('attr:someattr').of(regA).to ()-> invokeCount.domAttr++
				SimplyBind(()-> 'true').to('attr:someattr').of(regA)

				expect(regA.getAttribute('someattr')).to.equal('true')
				expect(invokeCount.domAttr).to.equal(1)


				# ==== DOMText =================================================================================
				SimplyBind('textContent').of(regA).to ()-> invokeCount.domText++
				SimplyBind(()-> 'true').to('textContent').of(regA)

				expect(regA.textContent).to.equal('true')
				expect(invokeCount.domText).to.equal(1)


				# ==== DOMValue =================================================================================
				SimplyBind('value').of(inputA).to ()-> invokeCount.domValue++
				SimplyBind(()-> 'true').to('value').of(inputA)
				
				expect(inputA.value).to.equal('true')
				expect(invokeCount.domValue).to.equal(1)


				# ==== DOMCheckbox Single =================================================================================
				expect(checkboxA.checked).to.be.false
				SimplyBind('checked').of(checkboxA).to ()-> invokeCount.domCheckboxSingle++
				SimplyBind(()-> 'truthy').to('checked').of(checkboxA)
				
				expect(checkboxA.checked).to.be.true
				expect(invokeCount.domCheckboxSingle).to.equal(1)


				# ==== DOMCheckbox =================================================================================
				SimplyBind('checked').of($checkboxFields).to ()-> invokeCount.domCheckbox++
				SimplyBind(()-> ['checkboxB', 'checkboxC']).to('checked').of($checkboxFields)
				
				expect(checkboxA.checked).to.be.false
				expect(checkboxB.checked).to.be.true
				expect(checkboxC.checked).to.be.true
				expect(invokeCount.domCheckbox).to.equal(1)
				
				SimplyBind(()-> 'checkboxA').to('checked').of($checkboxFields)
				
				expect(checkboxA.checked).to.be.true
				expect(checkboxB.checked).to.be.false
				expect(checkboxC.checked).to.be.false
				expect(invokeCount.domCheckbox).to.equal(2)


				# ==== DOMRadio =================================================================================
				SimplyBind('checked').of($radioFields).to ()-> invokeCount.domRadio++
				SimplyBind(()-> 'radioC').to('checked').of($radioFields)
				
				expect(radioA.checked).to.be.false
				expect(radioB.checked).to.be.false
				expect(radioC.checked).to.be.true
				expect(invokeCount.domRadio).to.equal(1)


			# ==== Event =================================================================================
			SimplyBind(0).ofEvent('someEvent').of(eventEmitterA).to ()-> invokeCount.event++
			SimplyBind(()-> true).toEvent('someEvent').of(eventEmitterA)

			expect(invokeCount.event).to.equal(1)
			

			SimplyBind.defaultOptions.updateOnBind = true
			restartSandbox()








		suite "Placeholders", ()->
			test "Property names with periods (.) indicate a placeholder", ()->
				dispatcher = 'value': 'Medium'

				objectA.prop = 'The size of this shirt is {{size}}, man!'
				if isBrowser
					inputA.value = 'The size of this shirt is {{size}}, man!'
					regA.textContent = 'The size of this shirt is {{size}}, man!'
					regA.setAttribute 'someattr', 'The size of this shirt is {{size}}, man!'

				SimplyBind('value').of(dispatcher)
					.to('prop.size').of(objectA)

				if isBrowser
					SimplyBind('value').of(dispatcher)
						.to('value.size').of(inputA)
						.and.to('textContent.size').of(regA)
						.and.to('attr:someattr.size').of(regA)
					
				expect(objectA.prop).to.equal 'The size of this shirt is Medium, man!'
				if isBrowser
					expect(inputA.value).to.equal 'The size of this shirt is Medium, man!'
					expect(regA.textContent).to.equal 'The size of this shirt is Medium, man!'
					expect(regA.getAttribute 'someattr').to.equal 'The size of this shirt is Medium, man!'
				restartSandbox()
			


			test "No changes should be made to the string when trying to update a placeholder that doesn't exist", ()->
				objectB.prop1 = 'The size of this shirt is _____, man!'
				binding = SimplyBind('prop1').of(objectA).to('prop1.size').of(objectB)

				binding.set 'Medium'
				expect(objectB.prop1).to.equal 'The size of this shirt is _____, man!'
				restartSandbox()



			test "The updating value doesn't have to be a string", ()->
				objectB.prop1 = 'The size of this shirt is {{size}}, man!'
				binding = SimplyBind('prop1').of(objectA).to('prop1.size').of(objectB)
				binding.set false
				expect(objectB.prop1).to.equal 'The size of this shirt is false, man!'
				binding.set null
				expect(objectB.prop1).to.equal 'The size of this shirt is null, man!'
				binding.set {}
				expect(objectB.prop1).to.equal 'The size of this shirt is [object Object], man!'

				restartSandbox()



			test "If a property name has more than one period, only the first will be accounted for", ()->
				objectB.prop1 = 'The size of this shirt is {{size.redundant}}, man!'
				binding = SimplyBind('prop1').of(objectA).to('prop1.size.redundant').of(objectB)
				
				binding.set 'Medium'
				expect(objectB.prop1).to.equal 'The size of this shirt is Medium, man!'
				restartSandbox()



			test "Custom placeholder markers can be set", ()->
				SimplyBind.settings.placeholder = ['^^', '$$']
				
				objectB.prop1 = 'The size of this shirt is ^^size$$, man!'
				
				binding = SimplyBind('prop1').of(objectA).to('prop1.size').of(objectB)
				binding.set 'XXS'
				
				expect(objectB.prop1).to.equal 'The size of this shirt is XXS, man!'
				SimplyBind.settings.placeholder = ['{{', '}}']

				restartSandbox()



			test "Target strings can have multiple placeholders", ()->
				dispatcher = 'value': 'Large'

				objectA.prop = 'The size of this shirt is {{size}}, and {{size}} is {{size}}ly rad!'
				if isBrowser
					inputA.value = 'The size of this shirt is {{size}}, and {{size}} is {{size}}ly rad!'
					regA.textContent = 'The size of this shirt is {{size}}, and {{size}} is {{size}}ly rad!'
					regA.setAttribute 'someattr', 'The size of this shirt is {{size}}, and {{size}} is {{size}}ly rad!'

				SimplyBind('value').of(dispatcher)
					.to('prop.size').of(objectA)

				if isBrowser
					SimplyBind('value').of(dispatcher)
						.to('value.size').of(inputA)
						.and.to('textContent.size').of(regA)
						.and.to('attr:someattr.size').of(regA)
				
				expect(objectA.prop).to.equal 'The size of this shirt is Large, and Large is Largely rad!'
				if isBrowser
					expect(inputA.value).to.equal 'The size of this shirt is Large, and Large is Largely rad!'
					expect(regA.textContent).to.equal 'The size of this shirt is Large, and Large is Largely rad!'
					expect(regA.getAttribute 'someattr').to.equal 'The size of this shirt is Large, and Large is Largely rad!'
				restartSandbox()




			test "Multiple values can be set for the same target that has multiple placeholders", ()->
				dispatcher =
					'verb': 'not'
					'nounOne': 'small'
					'nounTwo': 'pretty'

				objectB.prop = 'The following text is {{verb}} {{nounOne}} and {{nounTwo}}'
				if isBrowser
					inputB.value = 'The following text is {{verb}} {{nounOne}} and {{nounTwo}}'
					regB.setAttribute 'someattr', 'The following text is {{verb}} {{nounOne}} and {{nounTwo}}'

				SimplyBind('verb').of(dispatcher)
					.to('prop.verb').of(objectB)
				
				if isBrowser
					SimplyBind('verb').of(dispatcher)
						.to('value.verb').of(inputB)
						.and.to('textContent.verb').of(regB)
						.and.to('attr:someattr.verb').of(regB)
				


				SimplyBind('nounOne').of(dispatcher)
					.to('prop.nounOne').of(objectB)
				
				if isBrowser
					SimplyBind('nounOne').of(dispatcher)
						.to('value.nounOne').of(inputB)
						.and.to('textContent.nounOne').of(regB)
						.and.to('attr:someattr.nounOne').of(regB)
				


				SimplyBind('nounTwo').of(dispatcher)
					.to('prop.nounTwo').of(objectB)
				
				if isBrowser
					SimplyBind('nounTwo').of(dispatcher)
						.to('value.nounTwo').of(inputB)
						.and.to('textContent.nounTwo').of(regB)
						.and.to('attr:someattr.nounTwo').of(regB)
				

				values = ()-> if not isBrowser then [objectB.prop] else [objectB.prop, inputB.value, regB.textContent, regB.getAttribute 'someattr']
				for value in values()
					expect(value).to.equal 'The following text is not small and pretty'



				dispatcher.verb = 'very'
				dispatcher.nounOne = 'big'
				dispatcher.nounTwo = 'ugly'
				for value in values()
					expect(value).to.equal 'The following text is very big and ugly'


				restartSandbox()




			test "Multiple values can be set for the same target that has multiple placeholders + transforms", ()->
				dispatcher =
					'verbOne': 'not'
					'verbTwo': 'not'
					'nounOne': 'small'
					'nounTwo': 'pretty'

				objectC.prop = 'The following text is {{verbOne}} ({{verbTwo}}) {{nounOne}} and {{nounTwo}}'
				if isBrowser
					inputC.value = 'The following text is {{verbOne}} ({{verbTwo}}) {{nounOne}} and {{nounTwo}}'
					regC.textContent = 'The following text is {{verbOne}} ({{verbTwo}}) {{nounOne}} and {{nounTwo}}'
					regC.setAttribute 'someattr', 'The following text is {{verbOne}} ({{verbTwo}}) {{nounOne}} and {{nounTwo}}'



				SimplyBind('verbOne').of(dispatcher)
					.to('prop.verbOne').of(objectC).transform (value)-> value.toUpperCase()

				if isBrowser
					SimplyBind('verbOne').of(dispatcher)
						.to('value.verbOne').of(inputC)
						.and.to('textContent.verbOne').of(regC)
						.and.to('attr:someattr.verbOne').of(regC)
						.transformAll (value)-> value.toUpperCase()



				SimplyBind('verbTwo').of(dispatcher)
					.to('prop.verbTwo').of(objectC).transform (value)-> value.toLowerCase()

				if isBrowser
					SimplyBind('verbTwo').of(dispatcher)
						.to('value.verbTwo').of(inputC)
						.and.to('textContent.verbTwo').of(regC)
						.and.to('attr:someattr.verbTwo').of(regC)
						.transformAll (value)-> value.toLowerCase()
				


				SimplyBind('nounOne').of(dispatcher)
					.to('prop.nounOne').of(objectC).transform (value)-> value.toUpperCase()

				if isBrowser
					SimplyBind('nounOne').of(dispatcher)
						.to('value.nounOne').of(inputC)
						.and.to('textContent.nounOne').of(regC)
						.and.to('attr:someattr.nounOne').of(regC)
						.transformAll (value)-> value.toUpperCase()
				


				SimplyBind('nounTwo').of(dispatcher)
					.to('prop.nounTwo').of(objectC).transform (value)-> value.toUpperCase()

				if isBrowser
					SimplyBind('nounTwo').of(dispatcher)
						.to('value.nounTwo').of(inputC)
						.and.to('textContent.nounTwo').of(regC)
						.and.to('attr:someattr.nounTwo').of(regC)
						.transformAll (value)-> value.toUpperCase()
				


				values = ()-> if not isBrowser then [objectC.prop] else [objectC.prop, inputC.value, regC.textContent, regC.getAttribute 'someattr']
				for value in values()
					expect(value).to.equal 'The following text is NOT (not) SMALL and PRETTY'


				dispatcher.verbOne = dispatcher.verbTwo = 'Very'
				dispatcher.nounOne = 'Big'
				dispatcher.nounTwo = 'Ugly'
				for value in values()
					expect(value).to.equal 'The following text is VERY (very) BIG and UGLY'


				restartSandbox()




			test "Multiple placeholder bindings to textContent with multiple placeholders in a single textNode containing nested placeholders should function properly", ()-> if not isBrowser then @skip() else
				dispatcher = 'wordA':'', 'wordB':''

				expect(regD.textContent).to.equal 'The following {{wordA}} and {{wordB}} replaced correctly'

				SimplyBind('wordA').of(dispatcher)
					.to('textContent.wordA').of(regD)

				SimplyBind('wordB').of(dispatcher)
					.to('textContent.wordB').of(regD)

				expect(regD.textContent).to.equal 'The following  and  replaced correctly'


				dispatcher.wordA = 'firstWord'
				dispatcher.wordB = 'secondWord'
				expect(regD.textContent).to.equal 'The following firstWord and secondWord replaced correctly'
				restartSandbox()




			test "When an object prop with placeholders is an updater, it can either update individual placeholder values or its entire value", ()->
				dispatcher = 'nounA':'color', 'nounB':'car', 'adverb':'very', 'color':'red'
				receiver = 'prop':'The {{nounA}} of this {{nounB}} is {{adverb}} {{color}}'
				lastReceiver = 'prop':''

				SimplyBind('nounA').of(dispatcher).to('prop.nounA').of(receiver)
				SimplyBind('nounB').of(dispatcher).to('prop.nounB').of(receiver)
				SimplyBind('adverb').of(dispatcher).to('prop.adverb').of(receiver)
				SimplyBind('color').of(dispatcher).to('prop.color').of(receiver)
				expect(receiver.prop).to.equal 'The color of this car is very red'
				
				SimplyBind('prop.nounA').of(receiver)
					.to('prop').of(lastReceiver)

				expect(lastReceiver.prop).to.equal 'color'
				dispatcher.nounA = 'colour'
				expect(lastReceiver.prop).to.equal 'colour'


				SimplyBind('prop.nounB').of(receiver)
					.to('prop').of(lastReceiver)

				expect(lastReceiver.prop).to.equal 'car'
				dispatcher.nounB = 'airplane'
				expect(lastReceiver.prop).to.equal 'airplane'


				SimplyBind('prop').of(receiver)
					.to('prop').of(lastReceiver)

				expect(lastReceiver.prop).to.equal 'The colour of this airplane is very red'




			test "When manually changing the value of the prop after binding, the application of the placeholders will ignore the changes", ()-> if not isBrowser then @skip() else
				dispatcher = 'verb':'', 'nounOne':'', 'nounTwo':''
				objectA.prop1 = regB.textContent

				SimplyBind('verb').of(dispatcher)
					.to('prop1.verb').of(objectA)
					.and.to('textContent.verb').of(regB)
				
				SimplyBind('nounOne').of(dispatcher)
					.to('prop1.nounOne').of(objectA)
					.and.to('textContent.nounOne').of(regB)
				
				SimplyBind('nounTwo').of(dispatcher)
					.to('prop1.nounTwo').of(objectA)
					.and.to('textContent.nounTwo').of(regB)

				dispatcher.verb = 'looking'
				dispatcher.nounOne = 'nice'
				dispatcher.nounTwo = 'long'
				expect(objectA.prop1).to.equal 'The following text is looking nice and long'
				expect(objectA.prop1).to.equal(regB.textContent)


				upperCaseNodes = (nodes)-> for node in nodes
					if node.nodeType is 3
						node.textContent = node.textContent.toUpperCase()
					else
						upperCaseNodes(node)
				
				upperCaseNodes(regB.childNodes)
				objectA.prop1 = 'modified'
				
				dispatcher.verb = 'not looking'
				dispatcher.nounOne = 'ugly'
				dispatcher.nounTwo = 'short'
				expect(objectA.prop1).to.equal 'The following text is not looking ugly and short'
				expect(objectA.prop1).to.equal(regB.textContent)

				# But new text nodes won't be replaced!
				$regBH1.append '<span> and some other attribute</span>'
				dispatcher.verb = 'looking'
				dispatcher.nounOne = 'nice'
				dispatcher.nounTwo = 'long'
				expect(objectA.prop1).to.equal 'The following text is looking nice and long'
				expect(regB.textContent).to.equal 'The following text is looking nice and long and some other attribute'











		suite "Binding-Type Specific", ()->
			suite "DOMValue", ()->
				suiteSetup ()-> if not isBrowser then @skip()
				test "Dispatching an event isn't necessary when updating the value for a binding's .set()/.update() method", ()->
					binding = SimplyBind('value').of(inputA).to('prop2').of(objectA)
					binding.set 'changed from binding instance'
					expect(objectA.prop2).to.equal 'changed from binding instance'


				test "Bindings to a DOM element's .value property will only create a DOMValue binding if it is an input/select/textarea field", ()->
					expect(SimplyBind('value').of(inputA)._.type).to.equal 'DOMValue'
					expect(SimplyBind('value').of(regA)._.type).to.equal 'ObjectProp'
					expect(SimplyBind('value').of(document)._.type).to.equal 'ObjectProp'


				test "When passing an element collection to .of() in the form of a jQuery object/NodeList/HTMLCollection, only the first element will be used", ()->
					SimplyBind('prop1').of(objectA)
						.to('value').of $inputA
						.and.to('value').of document.querySelectorAll('#input2')
					
					objectA.prop1 = 'updated'
					expect($inputA.val()).to.equal 'updated'
					expect($inputB.val()).to.equal 'updated'
					restartSandbox()


				test "A DOM select field with multiple options shouldn't be interpreted as an iterable interface", ()->
					origLog = console.warn
					console.warn = chai.spy()
					SimplyBind('value').of(select)
					
					expect(console.warn).not.to.have.been.called()

					console.warn = origLog
					restartSandbox()


				test "A change event will be dispatched upon value update if SimplyBind.options.dispatchEvents is on", ()->
					invokeCountSelect = 0
					invokeCountRadio = 0
					SimplyBind.settings.dispatchEvents = true
					SimplyBind.defaultOptions.updateEvenIfSame = true
					
					
					SimplyBind('prop4').of(objectA)
						.to('value').of $select
						.and.to('checked').of $radioFields
					
					$select[0].on 'change', ()-> invokeCountSelect++
					$radioFields.each ()-> @on 'change', ()-> invokeCountRadio++
					objectA.prop4 = 'radioA'
					objectA.prop4 = 'radioB'
					objectA.prop4 = 'radioB'
					
					expect(invokeCountSelect).to.equal 3
					expect(invokeCountRadio).to.equal 2
					
					SimplyBind.settings.dispatchEvents = false
					SimplyBind.defaultOptions.updateEvenIfSame = false
					restartSandbox()





			suite "DOMCheckbox", ()->
				suiteSetup ()-> if not isBrowser then @skip()
				test "When attempting to bind a property other than 'checked' of a checkbox element list, only the first element will be used", ()->
					origLog = console.warn
					console.warn = chai.spy()
					SimplyBind('prop1').of(objectA)
						.to('newProp').of checkboxFields
						.and.to('newProp').of [].reverse.call($checkboxFields)
					
					objectA.prop1 = 'updated'
					expect(checkboxA.newProp).to.equal 'updated'
					expect(checkboxC.newProp).to.equal 'updated'
					expect(checkboxB.newProp).not.to.be.defined
					expect(console.warn).to.have.been.called()

					console.warn = origLog
					restartSandbox()


				test "A change event will be dispatched upon value update if SimplyBind.options.dispatchEvents is on", ()->
					invokeCount = 0
					SimplyBind.settings.dispatchEvents = true
					SimplyBind.defaultOptions.updateEvenIfSame = true
					
					
					SimplyBind('prop4').of(objectA)
						.to('checked').of checkboxFields
					
					$checkboxFields.each ()-> @on 'change', ()-> invokeCount++
					objectA.prop4 = 'checkboxA'
					objectA.prop4 = 'checkboxB'
					objectA.prop4 = 'checkboxB'
					
					expect(invokeCount).to.equal 3
					
					SimplyBind.settings.dispatchEvents = false
					SimplyBind.defaultOptions.updateEvenIfSame = false
					restartSandbox()


				test "Initial checked values should be noted during initial binding", ()->
					expect(checkboxA.checked).to.be.false
					expect(checkboxB.checked).to.be.false
					expect(checkboxC.checked).to.be.false

					checkboxB.checked = true
					checkboxC.checked = true

					SimplyBind('checked').of(checkboxFields).to (checkedFields)->
						expect(checkedFields).to.be.instanceOf Array
						expect(checkedFields.length).to.equal 2
						expect(checkedFields[0]).to.equal 'checkboxB'
						expect(checkedFields[1]).to.equal 'checkboxC'





			suite "DOMRadio", ()->
				suiteSetup ()-> if not isBrowser then @skip()
				test "When attempting to bind a property other than 'checked' of a radio element list, only the first element will be used", ()->
					origLog = console.warn
					console.warn = chai.spy()
					SimplyBind('prop1').of(objectA)
						.to('newProp').of radioFields
						.and.to('newProp').of [].reverse.call($radioFields)
					
					objectA.prop1 = 'updated'
					expect(radioA.newProp).to.equal 'updated'
					expect(radioC.newProp).to.equal 'updated'
					expect(radioB.newProp).not.to.be.defined
					expect(console.warn).to.have.been.called()

					console.warn = origLog
					restartSandbox()


				test "A change event will be dispatched upon value update if SimplyBind.options.dispatchEvents is on", ()->
					invokeCount = 0
					SimplyBind.settings.dispatchEvents = true
					SimplyBind.defaultOptions.updateEvenIfSame = true
					
					
					SimplyBind('prop4').of(objectA)
						.to('checked').of radioFields
					
					$radioFields.each ()-> @on 'change', ()-> invokeCount++
					objectA.prop4 = 'radioA'
					objectA.prop4 = 'radioB'
					objectA.prop4 = 'radioB'
					
					expect(invokeCount).to.equal 2
					
					SimplyBind.settings.dispatchEvents = false
					SimplyBind.defaultOptions.updateEvenIfSame = false
					restartSandbox()


				test "Initial checked values should be noted during initial binding", ()->
					expect(radioA.checked).to.be.false
					expect(radioB.checked).to.be.false
					expect(radioC.checked).to.be.false

					radioB.checked = true

					SimplyBind('checked').of(radioFields).to (selectedRadio)->
						expect(selectedRadio).to.equal 'radioB'




			suite "DOMAttr", ()->
				suiteSetup ()-> if not isBrowser then @skip()
				test "Requires the 'attr:' prefix in the property name in order to bind the attribute values and not the property values", ()->
					nonPrefix = SimplyBind('first').of(regA).to('first').of(regB)
					withPrefix = SimplyBind('attr:second').of(regA).to('attr:second').of(regB)

					nonPrefix.set 'someValue'
					expect(regA.first).to.equal 'someValue'
					expect(regB.first).to.equal 'someValue'
					expect(regA.getAttribute 'first').not.to.equal 'someValue'
					expect(regB.getAttribute 'first').not.to.equal 'someValue'
					
					withPrefix.set 'someValue'
					expect(regA.second).not.to.equal 'someValue'
					expect(regB.second).not.to.equal 'someValue'
					expect(regA.getAttribute 'second').to.equal 'someValue'
					expect(regB.getAttribute 'second').to.equal 'someValue'
					restartSandbox()



			suite "Function", ()->
				test "Will be invoked on bind and have its return value used as the value that the subscribers will receive", ()->
					SimplyBind ()-> 123
						.to('prop').of(objectA)

					expect(objectA.prop).to.equal 123
				

				test "Will be invoked on bind as a dependent and will receive 2 arguments - 1st is the new value passed while the 2nd is the prev value passed", ()->
					invokeCount = 0
					objectA.prop1 = 'some value'
					SimplyBind('prop1').of(objectA)
						.to (newValue, prevValue)->
							switch invokeCount
								when 0
									expect(newValue).to.equal 'some value'
									expect(prevValue).to.be.undefined
								when 1
									expect(newValue).to.equal 'new value'
									expect(prevValue).to.equal 'some value'
								when 2
									expect(newValue).to.equal 'newer value'
									expect(prevValue).to.equal 'new value'
							invokeCount++

					objectA.prop1 = 'new value'
					objectA.prop1 = 'newer value'

					restartSandbox()


				test "Will be invoked when is the first part of an argument regardless of whether or not SimplyBind.options.updateOnBind is on", ()->
					invokeCount = 0
					expect(SimplyBind.defaultOptions.updateOnBind).to.be.true
					
					SimplyBind ()-> invokeCount++; 123
						.to('prop').of(objectA)
					expect(invokeCount).to.equal 1

					
					SimplyBind.defaultOptions.updateOnBind = false

					SimplyBind ()-> invokeCount++; 456
						.to('prop').of(objectA)
					expect(invokeCount).to.equal 2

					SimplyBind.defaultOptions.updateOnBind = true




			suite "Array", ()->
				test "can bind an array to anything and update subscribers even when calling the .push, .pop, .shift, .unshift, .splice, .reverse, and .sort methods", ()->
					sampleArray = [1,2,3,4,5,6,7,8,9,10]
					mutations = 0
					SimplyBind(sampleArray).to('prop4').of(objectB).and.to ()-> mutations++

					expect(objectB.prop4.length).to.equal 10
					expect(mutations).to.equal 1
					sampleArray.push 11
					expect(objectB.prop4.length).to.equal 11
					expect(mutations).to.equal 2
					sampleArray.shift()
					sampleArray.shift()
					expect(objectB.prop4.length).to.equal 9
					expect(mutations).to.equal 4
					sampleArray.unshift 2
					sampleArray.unshift 1
					expect(objectB.prop4.length).to.equal 11
					expect(mutations).to.equal 6
					sampleArray.pop()
					sampleArray.pop()
					expect(objectB.prop4.length).to.equal 9
					expect(mutations).to.equal 8
					sampleArray.splice 0, 5
					expect(objectB.prop4.length).to.equal 4
					expect(mutations).to.equal 9
					sampleArray.reverse()
					expect(objectB.prop4.length).to.equal 4
					expect(mutations).to.equal 10
					sampleArray.sort()
					expect(objectB.prop4.length).to.equal 4
					expect(mutations).to.equal 11
					sampleArray.sort ()->
						1
					expect(objectB.prop4.length).to.equal 4
					expect(mutations).to.equal 12
					restartSandbox()



				test "it's impossible to replace the array object in an array binding.", ()->
					sampleArray = [1,2,3,4,5,6,7,8,9,10]
					mutations = 0
					SimplyBind(sampleArray).to('prop4').of(objectB).and.to ()-> mutations++

					expect(objectB.prop4.length).to.equal 10
					expect(mutations).to.equal 1
					SimplyBind(sampleArray).set [1,2,3,4,5,6,7,8,9,10]
					# Replace array. If it were to replace it, the mutations count will increase by one.
					SimplyBind(sampleArray).set [1,2,3,4,5,6,7,8,9,10]
					SimplyBind(sampleArray).set [1,2,3,4,5,6,7,8,9,10]
					sampleArray.push 11
					expect(objectB.prop4.length).to.equal 11
					expect(mutations).to.equal 2
					sampleArray.shift()
					sampleArray.shift()
					expect(objectB.prop4.length).to.equal 9
					expect(mutations).to.equal 4
					sampleArray.unshift 2
					sampleArray.unshift 1
					expect(objectB.prop4.length).to.equal 11
					expect(mutations).to.equal 6
					sampleArray.pop()
					sampleArray.pop()
					expect(objectB.prop4.length).to.equal 9
					expect(mutations).to.equal 8
					sampleArray.splice 0, 5
					expect(objectB.prop4.length).to.equal 4
					expect(mutations).to.equal 9
					restartSandbox()



				test "will update subscribers when its children get modified if specified via the trackArrayChildren option", ()->
					sampleArray = [1,2,3,4,5,6,7,8,9,10]
					sampleArray2 = [1,2,3,4,5,6,7,8,9,10]
					mutations = 0
					SimplyBind(sampleArray).to('prop5').of(objectA).and.to ()-> mutations++

					expect(objectA.prop5).to.equal sampleArray
					sampleArray[0] = 100
					sampleArray[1] = 200
					sampleArray[2] = 300
					expect(objectA.prop5[0]).to.equal 100
					expect(objectA.prop5[1]).to.equal 200
					expect(objectA.prop5[2]).to.equal 300
					expect(mutations).to.equal 1
					mutations = 0

					SimplyBind.settings.trackArrayChildren = true
					SimplyBind(sampleArray2).to('prop6').of(objectA).and.to ()-> mutations++

					expect(objectA.prop6).to.equal sampleArray2
					sampleArray2[0] = 100
					sampleArray2[1] = 200
					sampleArray2[2] = 300
					expect(objectA.prop6[0]).to.equal 100
					expect(objectA.prop6[1]).to.equal 200
					expect(objectA.prop6[2]).to.equal 300
					expect(mutations).to.equal 4
					SimplyBind.settings.trackArrayChildren = false
					restartSandbox()



				test "will update subscribers even when there is a sepearate binding on a reference of the same array", ()->
					sampleArrayA = [1,2,3,4,5,6,7,8,9,10]
					sampleArrayB = sampleArrayA
					mutationsA = 0
					mutationsB = 0
					SimplyBind(sampleArrayA)
						.to('prop6').of(objectA)
						.and.to ()-> mutationsA++
					
					SimplyBind(sampleArrayB)
						.to('prop6').of(objectB)
						.and.to ()-> mutationsB++

					expect(sampleArrayA).to.equal sampleArrayB
					expect(mutationsA).to.equal 1
					expect(mutationsB).to.equal 1
					sampleArrayA.push 11
					sampleArrayA.push 12
					sampleArrayB.push 13
					sampleArrayB.push 14
					expect(mutationsA).to.equal 5
					expect(mutationsB).to.equal 5
					restartSandbox()


				test "Will update Func subscribers with a clone to prevent possible infinite loops and for comparison", ()->
					receivedValues = 'current':null, 'prev':null
					middleMan = 'value':null
					prevCurrent = null
					
					SimplyBind(arrayA).to (currentArray, prevArray)->
						receivedValues.current = currentArray
						receivedValues.prev = prevArray

					prevCurrent = receivedValues.current
					expect(receivedValues.current).to.be.instanceOf(Array)
					expect(receivedValues.current.length).to.equal(arrayA.length)
					expect(receivedValues.current).not.to.equal(arrayA)
					expect(receivedValues.prev).to.be.undefined

					arrayA.push(10)
					expect(receivedValues.current.length).to.equal(arrayA.length)
					expect(receivedValues.current).not.to.equal(arrayA)
					expect(receivedValues.current).not.to.equal(prevCurrent)
					expect(receivedValues.prev).to.equal(prevCurrent)


					SimplyBind(arrayB)
						.to('value').of(middleMan).transform (array)-> array.length
						.chainTo (currentArray, prevArray)->
							receivedValues.current = currentArray
							receivedValues.prev = prevArray

					arrayB.unshift(-1)
					expect(middleMan.value).to.equal(arrayB.length)
					expect(receivedValues.current).to.equal(arrayB.length)

					restartSandbox()





			suite "Event", ()->
				test "The specified selector will indicate which argument index of the event emitter callback should be saved to the binding", ()->
					emptyObj = {}
					sampleObject = 'holder': emptyObj

					SimplyBind(0).ofEvent('focus').of(eventEmitterA)
						.to('holder').of sampleObject
					
					expect(sampleObject.holder).to.equal emptyObj
					
					eventEmitterA.emit 'focus', eventEmitterA
					if isBrowser
						expect(sampleObject.holder.target).to.equal eventEmitterA
					else
						expect(sampleObject.holder).to.equal eventEmitterA

					restartSandbox()




				test "Custom events will behave exactly like regular events", ()->
					emptyObj = {}
					sampleObject = 'holder': emptyObj

					SimplyBind(0).ofEvent('somethingCustom').of(eventEmitterA).to('holder').of sampleObject
					expect(sampleObject.holder).to.equal emptyObj

					eventEmitterA.emit 'somethingCustom', eventEmitterA
					if isBrowser
						expect(sampleObject.holder.target).to.equal eventEmitterA
					else
						expect(sampleObject.holder).to.equal eventEmitterA




				test "Custom listener/emitter methods can be used", ()->
					emitCount = 0
					receiveCount = 0
					$eventEmitterA.customListener 'click', ()-> emitCount++

					SimplyBind('prop2').of(objectA)
						.toEvent('click', 'customEmitter', 'customListener').of($eventEmitterA).bothWays ()-> ++receiveCount
					expect(emitCount).to.equal 1
					expect(receiveCount).to.equal 0
					
					objectA.prop2 = 'whatever'
					expect(emitCount).to.equal 2
					
					$eventEmitterA.customEmitter 'click'
					expect(receiveCount).to.equal 1
					expect(objectA.prop2).to.equal 1
					expect(emitCount).to.equal 3
					
					objectA.prop2 = 'whatever again'
					expect(emitCount).to.equal 4
					
					$eventEmitterA.customEmitter 'click'
					expect(receiveCount).to.equal 2
					expect(objectA.prop2).to.equal 2
					restartSandbox()




				test "jQuery listener/emitter methods can be used", ()-> if not isBrowser then @skip() else
					emitCount = 0
					receiveCount = 0
					$eventEmitterA.on 'click', ()-> emitCount++

					SimplyBind('prop2').of(objectA)
						.toEvent('click', 'trigger', 'on').of($eventEmitterA).bothWays ()-> ++receiveCount
					expect(emitCount).to.equal 1
					expect(receiveCount).to.equal 0
					
					objectA.prop2 = 'whatever'
					expect(emitCount).to.equal 2
					
					$eventEmitterA.trigger 'click'
					expect(receiveCount).to.equal 1
					expect(objectA.prop2).to.equal 1
					expect(emitCount).to.equal 3
					
					objectA.prop2 = 'whatever again'
					expect(emitCount).to.equal 4
					
					$eventEmitterA.trigger 'click'
					expect(receiveCount).to.equal 2
					expect(objectA.prop2).to.equal 2
					restartSandbox()




				test "Default listener/emitter methods will be used if custom listener/emitter methods don't exist on the target object", ()->
					emitCount = 0
					receiveCount = 0
					$eventEmitterA.customListener 'click', ()-> emitCount++

					SimplyBind('prop2').of(objectA)
						.toEvent('click', 'nonexistentDispatcher', 'nonexistentListener').of($eventEmitterA).bothWays ()-> ++receiveCount
					expect(emitCount).to.equal 1
					expect(receiveCount).to.equal 0
					
					objectA.prop2 = 'whatever'
					expect(emitCount).to.equal 2
					
					$eventEmitterA.customEmitter 'click'
					expect(receiveCount).to.equal 1
					expect(objectA.prop2).to.equal 1
					expect(emitCount).to.equal 3
					
					objectA.prop2 = 'whatever again'
					expect(emitCount).to.equal 4
					
					$eventEmitterA.customEmitter 'click'
					expect(receiveCount).to.equal 2
					expect(objectA.prop2).to.equal 2
					restartSandbox()









		suite "Create bindings to/from multiple objects using the 'multi:' descriptor as a shortcut", ()->

			suite "Basic Bindings", ()->
				test "Binding single prop to multiple ObjectProps", ()->
					dispatcher = 'prop':'value1'
					objectA.prop1 = objectB.prop1 = objectC.prop1 = null

					SimplyBind('prop').of(dispatcher)
						.to('multi:prop1').of([objectA, objectB, objectC])

					expect(objectA.prop1).to.equal 'value1'
					expect(objectB.prop1).to.equal 'value1'
					expect(objectC.prop1).to.equal 'value1'

					dispatcher.prop = 'value2'
					expect(objectA.prop1).to.equal 'value2'
					expect(objectB.prop1).to.equal 'value2'
					expect(objectC.prop1).to.equal 'value2'

					restartSandbox()



				test "Binding multiple ObjectProp to a single prop", ()->
					receiver = 'prop':null
					objectA.prop1 = objectB.prop1 = objectC.prop1 = 'value1'

					SimplyBind('multi:prop1').of([objectA, objectB, objectC])
						.to('prop').of(receiver)

					expect(receiver.prop).to.equal 'value1'
					expect(objectA.prop1).to.equal 'value1'
					expect(objectB.prop1).to.equal 'value1'
					expect(objectC.prop1).to.equal 'value1'

					objectA.prop1 = 'value2'
					expect(receiver.prop).to.equal 'value2'
					expect(objectA.prop1).to.equal 'value2'
					expect(objectB.prop1).to.equal 'value1'
					expect(objectC.prop1).to.equal 'value1'

					objectB.prop1 = 'value3'
					expect(receiver.prop).to.equal 'value3'
					expect(objectA.prop1).to.equal 'value2'
					expect(objectB.prop1).to.equal 'value3'
					expect(objectC.prop1).to.equal 'value1'

					objectC.prop1 = 'value4'
					expect(receiver.prop).to.equal 'value4'
					expect(objectA.prop1).to.equal 'value2'
					expect(objectB.prop1).to.equal 'value3'
					expect(objectC.prop1).to.equal 'value4'

					restartSandbox()



				test "Binding multiple ObjectProp to a single prop both ways", ()->
					receiverDispatcher = 'prop':'valueP1'
					objectA.prop1 = objectB.prop1 = objectC.prop1 = 'value1'

					SimplyBind('multi:prop1').of([objectA, objectB, objectC])
						.to('prop').of(receiverDispatcher).bothWays()

					expect(receiverDispatcher.prop).to.equal 'value1'
					expect(objectA.prop1).to.equal 'value1'
					expect(objectB.prop1).to.equal 'value1'
					expect(objectC.prop1).to.equal 'value1'

					objectA.prop1 = 'value2'
					expect(receiverDispatcher.prop).to.equal 'value2'
					expect(objectA.prop1).to.equal 'value2'
					expect(objectB.prop1).to.equal 'value2'
					expect(objectC.prop1).to.equal 'value2'

					objectB.prop1 = 'value3'
					receiverDispatcher.prop = 'valueP3'
					expect(receiverDispatcher.prop).to.equal 'valueP3'
					expect(objectA.prop1).to.equal 'valueP3'
					expect(objectB.prop1).to.equal 'valueP3'
					expect(objectC.prop1).to.equal 'valueP3'

					objectC.prop1 = 'value4'
					expect(receiverDispatcher.prop).to.equal 'value4'
					expect(objectA.prop1).to.equal 'value4'
					expect(objectB.prop1).to.equal 'value4'
					expect(objectC.prop1).to.equal 'value4'

					restartSandbox()





			suite "Transform Bindings", ()->
				test "Binding single prop to multiple ObjectProps + transform", ()->
					dispatcher = 'prop':'value1'
					objectA.prop1 = objectB.prop1 = objectC.prop1 = null

					SimplyBind('prop').of(dispatcher)
						.to('multi:prop1').of([objectA, objectB, objectC])
							.transform (value)-> value.toUpperCase()

					dispatcher.prop = 'value2'
					expect(dispatcher.prop).to.equal 'value2'
					expect(objectA.prop1).to.equal 'VALUE2'
					expect(objectB.prop1).to.equal 'VALUE2'
					expect(objectC.prop1).to.equal 'VALUE2'

					restartSandbox()



				test "Binding multiple ObjectProp to a single prop + transform", ()->
					receiver = 'prop':null
					objectA.prop1 = objectB.prop1 = objectC.prop1 = 'value1'

					SimplyBind('multi:prop1').of([objectA, objectB, objectC])
						.to('prop').of(receiver)
							.transform (value)-> value.toUpperCase()


					objectA.prop1 = 'value2'
					expect(receiver.prop).to.equal 'VALUE2'
					expect(objectA.prop1).to.equal 'value2'
					expect(objectB.prop1).to.equal 'value1'
					expect(objectC.prop1).to.equal 'value1'

					objectB.prop1 = 'value3'
					expect(receiver.prop).to.equal 'VALUE3'
					expect(objectA.prop1).to.equal 'value2'
					expect(objectB.prop1).to.equal 'value3'
					expect(objectC.prop1).to.equal 'value1'

					objectC.prop1 = 'value4'
					expect(receiver.prop).to.equal 'VALUE4'
					expect(objectA.prop1).to.equal 'value2'
					expect(objectB.prop1).to.equal 'value3'
					expect(objectC.prop1).to.equal 'value4'

					restartSandbox()



				test "Binding multiple ObjectProp to a single prop both ways + transform", ()->
					receiverDispatcher = 'prop':'valueP1'
					objectA.prop1 = objectB.prop1 = objectC.prop1 = 'value1'

					SimplyBind('multi:prop1').of([objectA, objectB, objectC])
						.to('prop').of(receiverDispatcher).bothWays()
							.transform (value)-> value.toUpperCase()

					objectA.prop1 = 'value2'
					expect(receiverDispatcher.prop).to.equal 'VALUE2'
					expect(objectA.prop1).to.equal 'value2'
					expect(objectB.prop1).to.equal 'VALUE2'
					expect(objectC.prop1).to.equal 'VALUE2'

					objectB.prop1 = 'value3'
					receiverDispatcher.prop = 'valueP3'
					expect(receiverDispatcher.prop).to.equal 'valueP3'
					expect(objectA.prop1).to.equal 'VALUEP3'
					expect(objectB.prop1).to.equal 'VALUEP3'
					expect(objectC.prop1).to.equal 'VALUEP3'

					objectC.prop1 = 'value4'
					expect(receiverDispatcher.prop).to.equal 'VALUE4'
					expect(objectA.prop1).to.equal 'VALUE4'
					expect(objectB.prop1).to.equal 'VALUE4'
					expect(objectC.prop1).to.equal 'value4'

					restartSandbox()





			suite "Condition Bindings", ()->
				test "Binding single prop to multiple ObjectProps + condition", ()->
					dispatcher = 'prop':'value1'
					objectA.prop1 = objectB.prop1 = objectC.prop1 = null
					allowUpdate = false

					SimplyBind('prop', {updateOnBind:false}).of(dispatcher)
						.to('multi:prop1').of([objectA, objectB, objectC])
							.condition ()-> allowUpdate

					expect(objectA.prop1).to.equal null
					expect(objectB.prop1).to.equal null
					expect(objectC.prop1).to.equal null

					dispatcher.prop = 'value2'
					expect(dispatcher.prop).to.equal 'value2'
					expect(objectA.prop1).to.equal null
					expect(objectB.prop1).to.equal null
					expect(objectC.prop1).to.equal null

					allowUpdate = true
					dispatcher.prop = 'value3'
					expect(dispatcher.prop).to.equal 'value3'
					expect(objectA.prop1).to.equal 'value3'
					expect(objectB.prop1).to.equal 'value3'
					expect(objectC.prop1).to.equal 'value3'

					restartSandbox()



				test "Binding multiple ObjectProp to a single prop + condition", ()->
					receiver = 'prop':null
					objectA.prop1 = objectB.prop1 = objectC.prop1 = 'value1'
					allowUpdate = false

					SimplyBind('multi:prop1', {updateOnBind:false}).of([objectA, objectB, objectC])
						.to('prop').of(receiver)
							.condition ()-> allowUpdate

					expect(receiver.prop).to.equal null
					expect(objectA.prop1).to.equal 'value1'
					expect(objectB.prop1).to.equal 'value1'
					expect(objectC.prop1).to.equal 'value1'

					objectA.prop1 = 'value2'
					expect(receiver.prop).to.equal null
					expect(objectA.prop1).to.equal 'value2'
					expect(objectB.prop1).to.equal 'value1'
					expect(objectC.prop1).to.equal 'value1'

					allowUpdate = true
					objectB.prop1 = 'value3'
					expect(receiver.prop).to.equal 'value3'
					expect(objectA.prop1).to.equal 'value2'
					expect(objectB.prop1).to.equal 'value3'
					expect(objectC.prop1).to.equal 'value1'

					restartSandbox()



				test "Binding multiple ObjectProp to a single prop both ways + condition", ()->
					receiverDispatcher = 'prop':'valueP1'
					objectA.prop1 = objectB.prop1 = objectC.prop1 = 'value1'
					allowUpdate = false

					SimplyBind('multi:prop1', {updateOnBind:false}).of([objectA, objectB, objectC])
						.to('prop').of(receiverDispatcher).bothWays()
							.condition ()-> allowUpdate
					
					expect(receiverDispatcher.prop).to.equal 'valueP1'
					expect(objectA.prop1).to.equal 'value1'
					expect(objectB.prop1).to.equal 'value1'
					expect(objectC.prop1).to.equal 'value1'

					objectA.prop1 = 'value2'
					expect(receiverDispatcher.prop).to.equal 'valueP1'
					expect(objectA.prop1).to.equal 'value2'
					expect(objectB.prop1).to.equal 'value1'
					expect(objectC.prop1).to.equal 'value1'

					allowUpdate = true
					receiverDispatcher.prop = 'valueP3'
					expect(receiverDispatcher.prop).to.equal 'valueP3'
					expect(objectA.prop1).to.equal 'valueP3'
					expect(objectB.prop1).to.equal 'valueP3'
					expect(objectC.prop1).to.equal 'valueP3'

					objectC.prop1 = 'value4'
					expect(receiverDispatcher.prop).to.equal 'value4'
					expect(objectA.prop1).to.equal 'value4'
					expect(objectB.prop1).to.equal 'value4'
					expect(objectC.prop1).to.equal 'value4'

					restartSandbox()




			suite "Miscellenious", ()->
				test "Binding single prop to multiple ObjectProps' placeholders", ()->
					dispatcher = 'prop':'word'
					objectA.prop1 = objectB.prop1 = objectC.prop1 = 'some {{noun}} here'

					SimplyBind('prop').of(dispatcher)
						.to('multi:prop1.noun').of([objectA, objectB, objectC])

					expect(objectA.prop1).to.equal 'some word here'
					expect(objectB.prop1).to.equal 'some word here'
					expect(objectC.prop1).to.equal 'some word here'

					dispatcher.prop = 'letter'
					expect(objectA.prop1).to.equal 'some letter here'
					expect(objectB.prop1).to.equal 'some letter here'
					expect(objectC.prop1).to.equal 'some letter here'

					restartSandbox()
				


				test "Fetching the value using the .get() method of a multi binding should yield an array of all the values", ()->
					objectA.prop1 = 'A'
					objectB.prop1 = 'B'
					objectC.prop1 = 'C'

					binding = SimplyBind('multi:prop1').of([objectA, objectB, objectC])
					values = binding.get()

					expect(objectA.prop1).to.equal 'A'
					expect(objectB.prop1).to.equal 'B'
					expect(objectC.prop1).to.equal 'C'
					expect(values).to.be.instanceOf Array
					expect(values[0]).to.equal 'A'
					expect(values[1]).to.equal 'B'
					expect(values[2]).to.equal 'C'

					restartSandbox()
				


				test "Fetching the value using the .get() method of a multi binding w/ placeholders should yield an array containing the values of each binding", ()->
					dispatcher = 'prop':'word'
					objectA.prop1 = objectB.prop1 = objectC.prop1 = 'some {{noun}} here'

					SimplyBind('prop').of(dispatcher)
						.to('multi:prop1.noun').of([objectA, objectB, objectC])

					binding = SimplyBind('multi:prop1.noun').of([objectA, objectB, objectC])
					value = binding.get()

					expect(objectA.prop1).to.equal 'some word here'
					expect(objectB.prop1).to.equal 'some word here'
					expect(objectC.prop1).to.equal 'some word here'
					expect(value.length).to.equal 3
					expect(value[0]).to.equal 'word'

					restartSandbox()



				test "Binding single prop to multiple ObjectProps with a self transform should be applied to all bindings", ()->
					dispatcher = 'prop':'value1'
					objectA.prop1 = objectB.prop1 = objectC.prop1 = null

					SimplyBind('prop').of(dispatcher)
						.to('multi:prop1').of([objectA, objectB, objectC])

					SimplyBind('multi:prop1.noun').of([objectA, objectB, objectC])
						.transformSelf (value)-> value.toUpperCase()

					expect(objectA.prop1).to.equal 'VALUE1'
					expect(objectB.prop1).to.equal 'VALUE1'
					expect(objectC.prop1).to.equal 'VALUE1'

					dispatcher.prop = 'value2'
					expect(objectA.prop1).to.equal 'VALUE2'
					expect(objectB.prop1).to.equal 'VALUE2'
					expect(objectC.prop1).to.equal 'VALUE2'

					restartSandbox()



				test ".throttle() on a multi binding will throttle the dep update frequency to once in a given timeframe", (done)->
					@slow(150)
					invokeCount = 0
					lastValue = null
					objectA.prop1 = objectB.prop1 = objectC.prop1 = 'same'

					SimplyBind('multi:prop1').of([objectA, objectB, objectC])
						.to (v)-> lastValue=v; invokeCount++
						.throttle(15)

					expect(invokeCount).to.equal(3)
					expect(lastValue).to.equal 'same'

					objectA.prop1 = 'another1'
					objectA.prop1 = 'another2'
					objectA.prop1 = 'another3'
					objectA.prop1 = 'another4'
					expect(invokeCount).to.equal(4)
					expect(lastValue).to.equal('another1')

					objectB.prop1 = 'another5'
					expect(lastValue).to.equal('another5')
					expect(invokeCount).to.equal(5)

					objectC.prop1 = 'another6'
					expect(lastValue).to.equal('another6')
					expect(invokeCount).to.equal(6)
					
					objectC.prop1 = 'another7'
					expect(invokeCount).to.equal(6)
					expect(lastValue).to.equal('another6')

					setTimeout ()->
						expect(invokeCount).to.equal(8)
						expect(lastValue).to.equal('another7')
						done()
						restartSandbox()
					, 50



				test "Using the 'multi:' descriptor on a empty DOM list should throw an error", ()->
					expect ()-> SimplyBind('multi:prop').of($('nonexistent'))
						.to.throw()
					
					expect ()-> SimplyBind('multi:prop').of(document.querySelectorAll('nonexistent'))
						.to.throw()

					expect ()-> SimplyBind('multi:prop').of([])
						.to.throw()

					restartSandbox()



			suite "Unbinding", ()->
				test "Binding single prop to multiple ObjectProps and then calling .unBind() should unbind all", ()->
					dispatcher = 'prop':'value1'
					objectA.prop1 = objectB.prop1 = objectC.prop1 = null

					binding = SimplyBind('prop').of(dispatcher)
						.to('multi:prop1').of([objectA, objectB, objectC])

					expect(objectA.prop1).to.equal 'value1'
					expect(objectB.prop1).to.equal 'value1'
					expect(objectC.prop1).to.equal 'value1'

					binding.unBind()

					dispatcher.prop = 'value2'
					expect(objectA.prop1).to.equal 'value1'
					expect(objectB.prop1).to.equal 'value1'
					expect(objectC.prop1).to.equal 'value1'

					restartSandbox()
				


				test "Binding multiple ObjectProps to a single prop and then calling .unBind() should unbind all props from that single prop", ()->
					receiver = 'prop':null
					objectA.prop1 = objectB.prop1 = objectC.prop1 = 'value1'

					binding = SimplyBind('multi:prop1').of([objectA, objectB, objectC])
						.to('prop').of(receiver)

					expect(receiver.prop).to.equal 'value1'
					expect(objectA.prop1).to.equal 'value1'
					expect(objectB.prop1).to.equal 'value1'
					expect(objectC.prop1).to.equal 'value1'

					binding.unBind()
					
					objectA.prop1 = 'value2'
					expect(receiver.prop).to.equal 'value1'
					expect(objectA.prop1).to.equal 'value2'
					expect(objectB.prop1).to.equal 'value1'
					expect(objectC.prop1).to.equal 'value1'

					objectB.prop1 = 'value3'
					expect(receiver.prop).to.equal 'value1'
					expect(objectA.prop1).to.equal 'value2'
					expect(objectB.prop1).to.equal 'value3'
					expect(objectC.prop1).to.equal 'value1'

					objectC.prop1 = 'value4'
					expect(receiver.prop).to.equal 'value1'
					expect(objectA.prop1).to.equal 'value2'
					expect(objectB.prop1).to.equal 'value3'
					expect(objectC.prop1).to.equal 'value4'

					restartSandbox()












	suite "Stage 2 methods", ()->
		suite ".and", ()->
			suiteSetup(restartSandbox)
			test "Allows to add additional publishers to a binding interface during stage 1", ()->
				SimplyBind.defaultOptions.updateOnBind = false
				invokeCount = 0
				
				SimplyBind('prop1').of(objectA)
					.and('prop2').of(objectA)
					.and('prop1').of(objectB)
					.and('prop2').of(objectB)
						.to ()-> invokeCount++

				expect(invokeCount).to.equal 0
			
				objectA.prop1 += 1
				expect(invokeCount).to.equal 1
				
				objectA.prop2 += 1
				expect(invokeCount).to.equal 2
				
				objectB.prop1 += 1
				objectB.prop2 += 1
				expect(invokeCount).to.equal 4

				SimplyBind.defaultOptions.updateOnBind = true
				restartSandbox()
			


			test "Allows to bind a publisher to additional subscribers during stage 2", ()->
				SimplyBind('prop1').of(objectA)
					.to('prop1').of(objectB)
					.and.to('prop2').of(objectB)
					.and.to('prop3').of(objectB)
					.and.to('prop4').of(objectB)

				expect ()-> SimplyBind('prop').of(objectA).to('prop').of(objectB).to('prop').of(objectC)
					.to.throw()
			
				objectA.prop1 = 'all at once'
				expect(objectB.prop1).to.equal 'all at once'
				expect(objectB.prop2).to.equal 'all at once'
				expect(objectB.prop3).to.equal 'all at once'
				expect(objectB.prop4).to.equal 'all at once'
				restartSandbox()





		suite ".once", ()->
			suiteSetup(restartSandbox)
			test "Allows to bind a publisher to a subscriber to be updated only once", ()->
				invokeCountOnce = 0
				invokeCountTotal = 0
				
				SimplyBind('prop1').of(objectA)
					.once.to ()-> invokeCountOnce++
					.and.to ()-> invokeCountTotal++

				expect(invokeCountOnce).to.equal(0)
				expect(invokeCountTotal).to.equal(1)

				objectA.prop1 += 1
				expect(invokeCountOnce).to.equal(1)
				expect(invokeCountTotal).to.equal(2)

				objectA.prop1 += 1
				expect(invokeCountOnce).to.equal(1)
				expect(invokeCountTotal).to.equal(3)











		suite ".setOption()", ()->
			test "should update the specified option only for the target interface and not modify global default options", ()->
				SimplyBind.defaultOptions.updateOnBind = false
				expect(SimplyBind.defaultOptions.updateOnBind).to.be.false

				pubInterface = SimplyBind('prop1').of(objectA)
				subInterface = SimplyBind('prop1').of(objectB)
				binding = pubInterface.to(subInterface)
				optsMap = pubInterface._.subOpts or pubInterface._.sO
				
				expect(optsMap[subInterface._.ID].updateOnBind).to.be.false


				binding.setOption 'updateOnBind', true
				expect(optsMap[subInterface._.ID].updateOnBind).to.be.true
				expect(SimplyBind.defaultOptions.updateOnBind).to.be.false

				SimplyBind.defaultOptions.updateOnBind = true
				restartSandbox()



			test "should only update the options for the last added sub in a chain", ()->
				SimplyBind.defaultOptions.updateEvenIfSame = false
				SimplyBind.defaultOptions.updateOnBind = false
				dispatcher = 'prop':'value'
				receivers = {1,2,3,4}
				updateCount = 1:0, 2:0, 3:0, 4:0

				SimplyBind(1).of(receivers).to ()-> updateCount[1]++
				SimplyBind(2).of(receivers).to ()-> updateCount[2]++
				SimplyBind(3).of(receivers).to ()-> updateCount[3]++
				SimplyBind(4).of(receivers).to ()-> updateCount[4]++
				expect(updateCount[1]).to.equal 0
				expect(updateCount[2]).to.equal 0
				expect(updateCount[3]).to.equal 0
				expect(updateCount[4]).to.equal 0
				

				SimplyBind('prop').of(dispatcher)
					.to(1).of(receivers)
					.and.to(2).of(receivers)
					.and.to(3).of(receivers).setOption('updateEvenIfSame', true)
					.and.to(4).of(receivers)

				dispatcher.prop = 'anotherValue'
				expect(updateCount[1]).to.equal 1
				expect(updateCount[2]).to.equal 1
				expect(updateCount[3]).to.equal 1
				expect(updateCount[4]).to.equal 1

				dispatcher.prop = dispatcher.prop
				expect(updateCount[1]).to.equal 1
				expect(updateCount[2]).to.equal 1
				expect(updateCount[3]).to.equal 2
				expect(updateCount[4]).to.equal 1

				SimplyBind.defaultOptions.updateOnBind = true
				restartSandbox()












		suite ".chainTo()/.pipe()", ()->
			suiteSetup(restartSandbox)
			
			test "Helps create complex chainings", ()->
				outerstate = 
					'first': null
					'second': null
					'third': null
			
				objectA.prop1 = 'Hello World'
				SimplyBind('prop1').of(objectA)
					.to('prop1').of(objectB)
					.and.to('prop2').of(objectA)
					.and.to (val)-> outerstate.first = val
						.transformAll (val)-> val.toUpperCase()
					
					.chainTo('prop2').of(objectB)
						.and.to('prop3').of(objectA)
							.transform (val)-> val.toLowerCase()
					
							.chainTo('prop3').of(objectB)
								.and.to('prop4').of(objectA)
								.and.to (val)-> outerstate.second = val
					
								.chainTo('prop4').of(objectB)
									.and.to (val)-> outerstate.third = val.slice(0, 5)



				expect(outerstate.first).to.equal 'HELLO WORLD'
				expect(outerstate.second).to.equal 'hello world'
				expect(outerstate.third).to.equal 'hello'
				expect(objectA.prop1).to.equal 'Hello World'
				expect(objectA.prop2).to.equal 'HELLO WORLD'
				expect(objectB.prop1).to.equal 'HELLO WORLD'
				expect(objectB.prop2).to.equal 'HELLO WORLD'
				expect(objectA.prop3).to.equal 'hello world'
				expect(objectB.prop3).to.equal 'hello world'
				expect(objectA.prop4).to.equal 'hello world'
				expect(objectB.prop4).to.equal 'hello world'
				restartSandbox()

			


















		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(0).ofEvent('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
					.and.to ()-> invokeCount.B++
						.transform (v)-> v
					.and.to ()-> invokeCount.C++
						.transform (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'


















		suite ".transformAll()", ()->
			suiteSetup(restartSandbox)
			test "Behaves the same way as .transform() does, except it applies the transform to all of the declared subscribers", ()->
				dispatcher = 'value': 'current'

				objectA.prop = objectC.prop = objectC.prop = ''

				SimplyBind('value').of(dispatcher)
					.to('prop').of(objectA)
					.and.to('prop').of(objectB)
					.and.to('prop').of(objectC)
						.transformAll (newValue, currentValue)-> newValue+'+'+currentValue
				
				for value in [objectA.prop, objectB.prop, objectC.prop]
					expect(value).to.equal 'current+current'
				
				
				dispatcher.value = 'new'
				for value in [objectA.prop, objectB.prop, objectC.prop]
					expect(value).to.equal 'new+current+current'
				
				
				dispatcher.value = 'newer'
				for value in [objectA.prop, objectB.prop, objectC.prop]
					expect(value).to.equal 'newer+new+current+current'

				restartSandbox()



			test "Will allow additional binding subscribers after being called", ()->
				expect(()->
					SimplyBind('prop1').of(objectA)
						.to('prop1').of(objectB)
						.and.to('prop2').of(objectB)
						.and.to('prop3').of(objectB)
							.transformAll (value)-> value
						.and.to('prop4').of(objectB)
				).not.to.throw()



















		suite ".transformSelf()", ()->
			suiteSetup(restartSandbox)

			suite "Will transform any received value", ()->
				test "ObjectProp", ()->
					object = 'prop':'value'

					SimplyBind('prop').of(object)
						.transformSelf (value)-> value.toUpperCase()

					expect(object.prop).to.equal 'VALUE'

					object.prop = 'anotherValue'
					expect(object.prop).to.equal 'ANOTHERVALUE'
				
		

				test "DOMText", ()-> if not isBrowser then @skip() else
					regA.textContent = 'value'

					SimplyBind('textContent').of(regA)
						.transformSelf (value)-> value.toUpperCase()

					expect(regA.textContent).to.equal 'VALUE'

					SimplyBind('textContent').of(regA).update('anotherValue')
					expect(regA.textContent).to.equal 'ANOTHERVALUE'

					restartSandbox()
				
		

				test "DOMAttr", ()-> if not isBrowser then @skip() else
					regA.setAttribute 'someattr', 'value'

					SimplyBind('attr:someattr').of(regA)
						.transformSelf (value)-> value.toUpperCase()

					expect(regA.getAttribute 'someattr').to.equal 'VALUE'

					SimplyBind('attr:someattr').of(regA).update('anotherValue')
					expect(regA.getAttribute 'someattr').to.equal 'ANOTHERVALUE'

					restartSandbox()
				
		

				test "DOMValue", ()-> if not isBrowser then @skip() else
					inputA.value = 'value'

					SimplyBind('value').of(inputA)
						.transformSelf (value)-> value.toUpperCase()

					expect(inputA.value).to.equal 'VALUE'

					inputA.value = 'anotherValue'
					inputA.emit 'change'
					expect(inputA.value).to.equal 'ANOTHERVALUE'

					restartSandbox()
				


				test "Array", ()->
					receivedArray = null
					
					SimplyBind(arrayA).transformSelf ()-> ['another array']
						.to (array)-> receivedArray = array
					
					expect(receivedArray).to.eql arrayA
					restartSandbox()



				test "Function", ()->
					dispatcher = 'prop':'value'
					receiver = 'prop':'value'
					fn = (value)-> value

					SimplyBind(fn).transformSelf (value)-> value?.toUpperCase()
					SimplyBind('prop').of(dispatcher)
						.to(fn)
							.chainTo('prop').of(receiver)

					expect(dispatcher.prop).to.equal 'value'
					expect(receiver.prop).to.equal 'VALUE'

					dispatcher.prop = 'anotherValue'
					expect(dispatcher.prop).to.equal 'anotherValue'
					expect(receiver.prop).to.equal 'ANOTHERVALUE'



				test "Event", ()->
					dispatcher = 'prop':eventEmitterA
					receiver = 'prop':'N/A'
					eventEmitterA.type = 'someEvent'
					eventEmitterB.type = 'someEvent'

					SimplyBind(0).ofEvent('someEvent').of(eventEmitterA)
						.transformSelf (event)-> event?.type or event
					
					SimplyBind('prop').of(dispatcher)
						.toEvent('someEvent').of(eventEmitterA)
							.chainTo('prop').of(receiver)

					expect(dispatcher.prop).to.equal eventEmitterA
					expect(receiver.prop).to.equal 'N/A'

					receiver.prop = 'reset'
					dispatcher.prop = eventEmitterB
					expect(dispatcher.prop).to.equal eventEmitterB
					expect(receiver.prop).to.equal 'someEvent'






			suite "Will not transform value on bind if SimplyBind.options.updateOnBind is off", ()->
				suiteSetup ()-> SimplyBind.defaultOptions.updateOnBind = false
				suiteTeardown ()-> SimplyBind.defaultOptions.updateOnBind = true
				
				test "ObjectProp", ()->
					object = 'prop':'value'

					SimplyBind('prop').of(object)
						.transformSelf (value)-> value.toUpperCase()

					expect(object.prop).to.equal 'value'

					object.prop = 'anotherValue'
					expect(object.prop).to.equal 'ANOTHERVALUE'
				
		

				test "DOMText", ()-> if not isBrowser then @skip() else
					regA.textContent = 'value'

					SimplyBind('textContent').of(regA)
						.transformSelf (value)-> value.toUpperCase()

					expect(regA.textContent).to.equal 'value'

					SimplyBind('textContent').of(regA).update('anotherValue')
					expect(regA.textContent).to.equal 'ANOTHERVALUE'

					restartSandbox()
				
		

				test "DOMAttr", ()-> if not isBrowser then @skip() else
					regA.setAttribute 'someattr', 'value'

					SimplyBind('attr:someattr').of(regA)
						.transformSelf (value)-> value.toUpperCase()

					expect(regA.getAttribute 'someattr').to.equal 'value'

					SimplyBind('attr:someattr').of(regA).update('anotherValue')
					expect(regA.getAttribute 'someattr').to.equal 'ANOTHERVALUE'

					restartSandbox()
				
		

				test "DOMValue", ()-> if not isBrowser then @skip() else
					inputA.value = 'value'

					SimplyBind('value').of(inputA)
						.transformSelf (value)-> value.toUpperCase()

					expect(inputA.value).to.equal 'value'

					inputA.value = 'anotherValue'
					inputA.emit 'change'
					expect(inputA.value).to.equal 'ANOTHERVALUE'

					restartSandbox()



				test "Function", ()->
					dispatcher = 'prop':'value'
					receiver = 'prop':'value'
					fn = (value)-> value

					SimplyBind(fn).transformSelf (value)-> value?.toUpperCase()
					SimplyBind('prop').of(dispatcher)
						.to(fn)
						.chainTo('prop').of(receiver)

					expect(dispatcher.prop).to.equal 'value'
					expect(receiver.prop).to.be.undefined

					dispatcher.prop = 'anotherValue'
					expect(dispatcher.prop).to.equal 'anotherValue'
					expect(receiver.prop).to.equal 'ANOTHERVALUE'
					restartSandbox()



				test "Event", ()->
					dispatcher = 'prop':eventEmitterA
					receiver = 'prop':'N/A'
					eventEmitterA.type = 'someEvent'
					eventEmitterB.type = 'someEvent'

					SimplyBind(0).ofEvent('someEvent').of(eventEmitterA)
						.transformSelf (event)-> event?.type or event
					
					SimplyBind('prop').of(dispatcher)
						.toEvent('someEvent').of(eventEmitterA)
							.chainTo('prop').of(receiver)

					expect(dispatcher.prop).to.equal eventEmitterA
					expect(receiver.prop).to.equal 'N/A'

					receiver.prop = 'reset'
					dispatcher.prop = eventEmitterB
					expect(dispatcher.prop).to.equal eventEmitterB
					expect(receiver.prop).to.equal 'someEvent'




















		suite ".condition()", ()->
			suiteSetup(restartSandbox)

			test "Will pass the value to the condition before updating the dependent and will update the dep only if the return value is truthy", ()->
				shouldAllowUpdate = false
				objectA.prop1 = objectB.prop1 = 0

				SimplyBind('prop1').of(objectA)
					.to('prop1').of(objectB)
					.condition ()-> shouldAllowUpdate

				objectA.prop1 = 1
				expect(objectB.prop1).to.equal 0
				
				objectA.prop1 = 2
				expect(objectB.prop1).to.equal 0

				shouldAllowUpdate = true
				
				objectA.prop1 = 3
				expect(objectB.prop1).to.equal 3

				restartSandbox()



			test "Will update the dependent upon initial bind regardless of the condition unless SimplyBind.options.updateOnBind is on", ()->
				shouldAllowUpdate = false
				objectA.prop1 = objectA.prop2 = 1
				objectB.prop1 = objectB.prop2 = 0

				SimplyBind('prop1').of(objectA)
					.to('prop1').of(objectB)
					.condition ()-> shouldAllowUpdate

				expect(objectA.prop1).to.equal 1
				expect(objectB.prop1).to.equal 1

				objectA.prop1 = 2
				expect(objectB.prop1).to.equal 1

				
				
				SimplyBind.defaultOptions.updateOnBind = false
				
				SimplyBind('prop2').of(objectA)
					.to('prop2').of(objectB)
					.condition ()-> shouldAllowUpdate
				
				expect(objectA.prop2).to.equal 1
				expect(objectB.prop2).to.equal 0
				
				SimplyBind.defaultOptions.updateOnBind = true
				restartSandbox()




			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)
						.conditionAll (current, prev, target)->
							expect(target).to.equal(receivers[index++])
							return true

				dispatcher.prop++
				expect(index).to.equal(3)
				restartSandbox()



			test "Condition will be added only to the last-proxied dependent", ()->
				shouldAllowUpdate = false
				objectA.prop1 = objectB.prop1 = objectC.prop1 = 0

				SimplyBind('prop1').of(objectA)
					.to('prop1').of(objectB).condition ()-> shouldAllowUpdate
					.and.to('prop1').of(objectC)

				objectA.prop1 = 1
				expect(objectB.prop1).to.equal 0
				expect(objectC.prop1).to.equal 1
				
				objectA.prop1 = 2
				expect(objectB.prop1).to.equal 0
				expect(objectC.prop1).to.equal 2

				shouldAllowUpdate = true
				
				objectA.prop1 = 3
				expect(objectB.prop1).to.equal 3
				expect(objectC.prop1).to.equal 3

				restartSandbox()



			test "The condition will be added both ways if declared after the .bothWays() call", ()->
				shouldAllowUpdate = false
				objectA.prop1 = objectB.prop1 = 0

				SimplyBind('prop1').of(objectA)
					.to('prop1').of(objectB).bothWays()
						.condition ()-> shouldAllowUpdate

				objectA.prop1 = 1
				expect(objectA.prop1).to.equal 1
				expect(objectB.prop1).to.equal 0
				
				objectB.prop1 = 2
				expect(objectA.prop1).to.equal 1
				expect(objectB.prop1).to.equal 2

				shouldAllowUpdate = true
				
				objectA.prop1 = 3
				expect(objectA.prop1).to.equal 3
				expect(objectB.prop1).to.equal 3
				
				objectB.prop1 = 4
				expect(objectA.prop1).to.equal 4
				expect(objectB.prop1).to.equal 4

				restartSandbox()



			test "The condition will be added both ways if declared before the .bothWays() call", ()->
				shouldAllowUpdate = false
				objectA.prop1 = objectB.prop1 = 0

				SimplyBind('prop1').of(objectA)
					.to('prop1').of(objectB)
						.condition ()-> shouldAllowUpdate
						.bothWays()

				objectA.prop1 = 1
				expect(objectA.prop1).to.equal 1
				expect(objectB.prop1).to.equal 0
				
				objectB.prop1 = 2
				expect(objectA.prop1).to.equal 1
				expect(objectB.prop1).to.equal 2

				shouldAllowUpdate = true
				
				objectA.prop1 = 3
				expect(objectA.prop1).to.equal 3
				expect(objectB.prop1).to.equal 3
				
				objectB.prop1 = 4
				expect(objectA.prop1).to.equal 4
				expect(objectB.prop1).to.equal 4

				restartSandbox()



			test "If a the dependent has a transform and a condition, the new value will be run through the transform prior to testing the condition", ()->
				invokeCount = 0
				shouldAllowUpdate = true

				SimplyBind('prop1').of(objectA)
					.to('prop1').of(objectB)
						.transform (val)-> invokeCount++; val
						.condition ()-> shouldAllowUpdate

				expect(objectB.prop1).to.equal(objectA.prop1)
				expect(invokeCount).to.equal 1

				objectA.prop1 = 2
				expect(objectB.prop1).to.equal(objectA.prop1)
				expect(invokeCount).to.equal 2

				shouldAllowUpdate = false
				objectA.prop1 = 3
				expect(objectB.prop1).not.to.equal(objectA.prop1)
				expect(invokeCount).to.equal 3
				
				objectA.prop1 = 4
				expect(objectB.prop1).not.to.equal(objectA.prop1)
				expect(invokeCount).to.equal 4

				restartSandbox()



			test "If a binding has a placeholder, the condition will be used only for that placeholder", ()->
				dispatcher = 'prop':''
				receiver = 'prop':'This {{noun}} works'
				lastPassedNoun = null
				shouldAllowUpdate = true

				SimplyBind('prop').of(dispatcher)
					.to('prop.noun').of(receiver)
					.condition (noun)-> lastPassedNoun=noun; return shouldAllowUpdate

				dispatcher.prop = 'test1'
				expect(lastPassedNoun).to.equal 'test1'
				expect(receiver.prop).to.equal 'This test1 works'
				
				shouldAllowUpdate = false
				dispatcher.prop = 'test2'
				expect(lastPassedNoun).to.equal 'test2'
				expect(receiver.prop).to.equal 'This test1 works'
















		suite ".conditionAll()", ()->
			suiteSetup(restartSandbox)

			test "Behaves the same way as .condition() does, except it applies the condition to all of the declared subscribers", ()->
				shouldAllowUpdate = false
				dispatcher = 'prop':0
				objectA.prop1 = objectB.prop1 = objectC.prop1 = 0

				SimplyBind('prop').of(dispatcher)
					.to('prop1').of(objectA)
					.and.to('prop1').of(objectB)
					.and.to('prop1').of(objectC)
					.conditionAll ()-> shouldAllowUpdate

				dispatcher.prop = 1
				expect(objectA.prop1).to.equal 0
				expect(objectB.prop1).to.equal 0
				expect(objectC.prop1).to.equal 0
				
				dispatcher.prop = 2
				expect(objectA.prop1).to.equal 0
				expect(objectB.prop1).to.equal 0
				expect(objectC.prop1).to.equal 0

				shouldAllowUpdate = true
				
				dispatcher.prop = 3
				expect(objectA.prop1).to.equal 3
				expect(objectB.prop1).to.equal 3
				expect(objectC.prop1).to.equal 3

				restartSandbox()



















		suite ".bothWays()", ()->
			suiteSetup(restartSandbox)
			test "Create two-way bindings", ()->
				# ==== Objects =================================================================================
				SimplyBind('prop').of(objectA).to('prop').of(objectB).bothWays()
				expect(objectA.prop).to.be.undefined
				
				objectA.prop = 'from objectA'
				expect(objectA.prop).to.equal 'from objectA'
				expect(objectB.prop).to.equal 'from objectA'

				objectB.prop = 'from objectB'
				expect(objectA.prop).to.equal 'from objectB'
				expect(objectB.prop).to.equal 'from objectB'


				# ==== Arrays =================================================================================
				SimplyBind(arrayA).to(arrayB).bothWays()
				expect(arrayA.length).to.equal 10
				expect(arrayB.length).to.equal 10
				
				arrayA.push(1)
				arrayA.push(1)
				expect(arrayA.length).to.equal 12
				expect(arrayB.length).to.equal 10
				
				arrayB.push(1)
				arrayB.push(1)
				expect(arrayA.length).to.equal 12
				expect(arrayB.length).to.equal 12


				if isBrowser
					# ==== DOMAttr =================================================================================
					SimplyBind('attr:someattr').of(regA).to('attr:someattr').of(regB).bothWays()
					expect(regA.getAttribute('someattr')).to.equal null
					
					SimplyBind('attr:someattr').of(regA).set 'from regElementA'
					expect(regA.getAttribute('someattr')).to.equal 'from regElementA'
					expect(regB.getAttribute('someattr')).to.equal 'from regElementA'

					SimplyBind('attr:someattr').of(regB).set 'from regElementB'
					expect(regA.getAttribute('someattr')).to.equal 'from regElementB'
					expect(regB.getAttribute('someattr')).to.equal 'from regElementB'


					# ==== DOMText =================================================================================
					regA.textContent = ''
					SimplyBind('textContent').of(regA).to('textContent').of(regB).bothWays()
					expect(regA.textContent).to.equal ''
					
					SimplyBind('textContent').of(regA).set 'from regElementA'
					expect(regA.textContent).to.equal 'from regElementA'
					expect(regB.textContent).to.equal 'from regElementA'

					SimplyBind('textContent').of(regB).set 'from regElementB'
					expect(regA.textContent).to.equal 'from regElementB'
					expect(regB.textContent).to.equal 'from regElementB'


					# ==== DOMValue =================================================================================
					SimplyBind('value').of(inputA).to('value').of(inputB).bothWays()
					expect(inputA.value).to.equal ''
					
					inputA.value = 'from inputA'
					inputA.emit 'change'
					expect(inputA.value).to.equal 'from inputA'
					expect(inputB.value).to.equal 'from inputA'

					inputB.value = 'from inputB'
					inputB.emit 'change'
					expect(inputA.value).to.equal 'from inputB'
					expect(inputB.value).to.equal 'from inputB'


					# ==== DOMCheckbox =================================================================================
					binding = SimplyBind('checked').of(checkboxFields).to('prop2').of(objectB).bothWays()
					expect(objectB.prop2).to.be.instanceOf Array
					expect(objectB.prop2.length).to.equal 0
					
					objectB.prop2 = 'changed from objectB'
					expect($checkboxFields.filter(':checked').length).to.equal 0
					expect(binding.value).to.be.instanceOf Array
					expect(binding.value.length).to.equal 0
					
					objectB.prop2 = 'checkboxB'
					expect($checkboxFields.filter(':checked').val()).to.equal 'checkboxB'
					expect(binding.value.length).to.equal 1
					
					objectB.prop2 = ['checkboxA', 'checkboxC']
					expect($checkboxFields.filter(':checked').length).to.equal 2
					expect(binding.value.length).to.equal 2
					
					$checkboxA.click()
					expect(objectB.prop2).to.be.instanceOf Array
					expect(objectB.prop2.length).to.equal 1
					expect(objectB.prop2[0]).to.equal 'checkboxC'

					restartSandbox()


					# ==== DOMRadio =================================================================================
					SimplyBind('checked').of(radioFields).to('prop3').of(objectB).bothWays()
					
					objectB.prop3 = 'changed from objectB'
					expect($radioFields.filter(':checked').length).to.equal 0
					
					objectB.prop3 = 'radioB'
					expect($radioFields.filter(':checked').val()).to.equal 'radioB'
					
					$radioA.click()
					expect(objectB.prop3).to.equal 'radioA'

					restartSandbox()



				SimplyBind.defaultOptions.updateOnBind = true
				restartSandbox()



			



			test "Will apply the call only to the last proxied dependent", ()->
				restartSandbox()
				SimplyBind('prop1').of(objectA)
					.to('prop1').of(objectB).bothWays()
					.and.to('prop2').of(objectB)
					.and.to('prop3').of(objectB).bothWays()
					.and.to('prop4').of objectB
				
				objectA.prop1 = 'all at once'
				expect(objectB.prop1).to.equal 'all at once'
				expect(objectB.prop2).to.equal 'all at once'
				expect(objectB.prop3).to.equal 'all at once'
				expect(objectB.prop4).to.equal 'all at once'
				
				objectB.prop1 = 'almost all as well since objectA.prop1 gets updated and updates all of its decendents'
				expect(objectA.prop1).to.equal 'almost all as well since objectA.prop1 gets updated and updates all of its decendents'
				expect(objectB.prop2).to.equal 'almost all as well since objectA.prop1 gets updated and updates all of its decendents'
				expect(objectB.prop3).to.equal 'almost all as well since objectA.prop1 gets updated and updates all of its decendents'
				expect(objectB.prop4).to.equal 'almost all as well since objectA.prop1 gets updated and updates all of its decendents'
			
				objectB.prop3 = 'just a few'
				expect(objectA.prop1).to.equal 'just a few'
				expect(objectB.prop1).to.equal 'just a few'
				expect(objectB.prop2).to.equal 'just a few'
				expect(objectB.prop4).to.equal 'just a few'






			suite "DOMValue other than input", ()->
				suiteSetup ()-> if not isBrowser then @skip()
				test "Create two-way bindings between textarea fields", ()->
					SimplyBind('value').of(textarea).to('value').of(inputB).bothWays()

					$textarea.val('changed from input1')[0].emit 'change'
					expect($inputB.val()).to.equal 'changed from input1'

					$inputB.val('changed from input2')[0].emit 'change'
					expect($textarea.val()).to.equal 'changed from input2'




				test "Create two-way bindings between select fields", ()->
					SimplyBind('value').of($select).to('prop3').of(objectB).bothWays()
				
					objectB.prop3 = 'valid'
					expect($select.val()).to.equal 'valid'
				
					$select.val('valid2')[0].emit 'change'
					expect(objectB.prop3).to.equal 'valid2'
					restartSandbox()



			# suite "DOMRadio", ()->
			# 	test "Create two-way bindings between radio fields", ()->
			# 		SimplyBind('value').of($('#radio').children()).to('prop3').of(objectB).bothWays()
					
			# 		objectB.prop3 = 'changed from objectB'
			# 		expect($('input:checked').length).to.equal 0
					
			# 		objectB.prop3 = 'radioB'
			# 		expect($('input:checked').val()).to.equal 'radioB'
					
			# 		$radioA.click()[0].emit 'change'
			# 		expect(objectB.prop3).to.equal 'radioA'

			# 		restartSandbox()



			# suite "DOMCheckbox", ()->
			# 	test "Create two-way bindings between checkbox fields", ()->
			# 		$checkboxA.prop 'checked', true
			# 		SimplyBind('value').of($('#checkbox')[0].children).to('prop3').of(objectB).bothWays()
					
			# 		objectB.prop3 = 'changed from objectB'
			# 		expect($('input:checked').length).to.equal 0
					
			# 		objectB.prop3 = 'checkboxB'
			# 		expect($('input:checked').val()).to.equal 'checkboxB'
					
			# 		$checkboxA.click()[0].emit 'change'
			# 		expect(objectB.prop3).to.equal 'checkboxA'

			# 		restartSandbox()


















		suite ".unBind()", ()->
			suiteSetup(restartSandbox)
			suite "Will unbind from the all defined proxied subscribers one-way", ()->
				test "ObjectProp", ()->
					binding = SimplyBind('prop1').of(objectA)
						.to('prop1').of(objectB).bothWays()

					objectA.prop1 = 1
					expect(objectB.prop1).to.equal 1
					
					objectB.prop1 = 2
					expect(objectA.prop1).to.equal 2

					binding.unBind()

					objectA.prop1 = 3
					expect(objectB.prop1).to.equal 2
					
					objectB.prop1 = 4
					expect(objectA.prop1).to.equal 4

					restartSandbox()
				
		

				test "DOMText", ()-> if not isBrowser then @skip() else
					binding = SimplyBind('textContent').of(regA)
						.to('textContent').of(regB).bothWays()

					SimplyBind('textContent').of(regA).set '1'
					expect(regB.textContent).to.equal '1'
					
					SimplyBind('textContent').of(regB).set '2'
					expect(regA.textContent).to.equal '2'

					binding.unBind()

					SimplyBind('textContent').of(regA).set '3'
					expect(regB.textContent).to.equal '2'
					
					SimplyBind('textContent').of(regB).set '4'
					expect(regA.textContent).to.equal '4'

					restartSandbox()
				
		

				test "DOMAttr", ()-> if not isBrowser then @skip() else
					binding = SimplyBind('attr:someattr').of(regA)
						.to('attr:someattr').of(regB).bothWays()

					SimplyBind('attr:someattr').of(regA).set '1'
					expect(regB.getAttribute 'someattr').to.equal '1'
					
					SimplyBind('attr:someattr').of(regB).set '2'
					expect(regA.getAttribute 'someattr').to.equal '2'

					binding.unBind()

					SimplyBind('attr:someattr').of(regA).set '3'
					expect(regB.getAttribute 'someattr').to.equal '2'
					
					SimplyBind('attr:someattr').of(regB).set '4'
					expect(regA.getAttribute 'someattr').to.equal '4'

					restartSandbox()
				
		

				test "DOMValue", ()-> if not isBrowser then @skip() else
					binding = SimplyBind('value').of(inputA)
						.to('value').of(inputB).bothWays()

					inputA.value = '1'
					inputA.emit 'change'
					expect(inputB.value).to.equal '1'
					
					inputB.value = '2'
					inputB.emit 'change'
					expect(inputA.value).to.equal '2'

					binding.unBind()

					inputA.value = '3'
					inputA.emit 'change'
					expect(inputB.value).to.equal '2'
					
					inputB.value = '4'
					inputB.emit 'change'
					expect(inputA.value).to.equal '4'

					restartSandbox()
				


				test "Array", ()->
					SimplyBind.settings.trackArrayChildren = true
					binding = SimplyBind(arrayA)
						.to('prop1').of(objectA)

					expect(objectA.prop1).to.equal arrayA

					objectA.prop1 = 'reset'
					arrayA.push(1)
					expect(objectA.prop1).to.equal arrayA

					objectA.prop1 = 'reset'
					arrayA[5] = 19
					expect(objectA.prop1).to.equal arrayA


					objectA.prop1 = 'reset'
					binding.unBind()
					
					arrayA.push(1)
					arrayA[3] = 23
					expect(objectA.prop1).to.equal 'reset'
					
					SimplyBind.settings.trackArrayChildren = false
					restartSandbox()



				test "Function", ()->
					passedValue = null
					valueToPass = 1
					takeFromReceiver = false
					fn = (fromReceiver)-> passedValue = if takeFromReceiver then fromReceiver else valueToPass
					invoker = 'prop':'value'
					receiver = 'prop':undefined

					SimplyBind('prop').of(invoker).to(fn)
					binding = SimplyBind(fn).to('prop').of(receiver).bothWays()

					expect(receiver.prop).to.equal 1
					expect(passedValue).to.equal 1
					
					valueToPass = 5
					invoker.prop = 'anotherValue'
					expect(receiver.prop).to.equal 5
					expect(passedValue).to.equal 5
					
					takeFromReceiver = true
					receiver.prop = 10
					takeFromReceiver = false
					expect(passedValue).to.equal 10

					
					binding.unBind()
					valueToPass = 15
					invoker.prop = 'newValue'
					expect(receiver.prop).to.equal 10
					expect(passedValue).to.equal 15

					takeFromReceiver = true
					receiver.prop = 20
					takeFromReceiver = false
					expect(passedValue).to.equal 20



				test "Event", ()->
					eventInvokeCount = 0
					eventObject = null
					objectA.prop = objectB.prop = 'someValue'
					eventEmitterA.on 'someEvent', (event)-> eventObject = event or @
					
					binding = SimplyBind(0).ofEvent('someEvent').of(eventEmitterA).transformSelf ()-> eventObject
						.to('prop').of(objectA).bothWays()
						.and.to('prop').of(objectB).bothWays()
						.and.to ()-> eventInvokeCount++
					

					eventEmitterA.emit 'someEvent'
					expect(objectA.prop).to.equal eventObject
					expect(objectB.prop).to.equal(objectA.prop)
					expect(eventInvokeCount).to.equal 1
		
					objectA.prop = 'different value'
					expect(objectA.prop).to.equal 'different value'
					# expect(objectB.prop).to.equal eventObject
					expect(eventInvokeCount).to.equal 2
					
					objectB.prop = 'different value2'
					expect(eventInvokeCount).to.equal 3


					binding.unBind()
					objectA.prop = 'different value'
					eventEmitterA.emit 'someEvent'
					eventEmitterA.on 'someEvent', ()-> eventInvokeCount++

					expect(objectA.prop).to.equal 'different value'
					expect(objectB.prop).to.equal 'different value2'
					expect(eventInvokeCount).to.equal 3
					

					objectA.prop = 'another value'
					expect(objectA.prop).to.equal 'another value'
					expect(objectB.prop).to.equal 'different value2'
					
					objectB.prop = 'another value2'
					expect(objectA.prop).to.equal 'another value'
					expect(objectB.prop).to.equal 'another value2'
					expect(eventInvokeCount).to.equal 5
					expect(binding._.subs.length).to.equal 0
					
					restartSandbox()



			suite "Will unbind from the all defined proxied subscribers both-ways", ()->
				test "ObjectProp", ()->
					binding = SimplyBind('prop1').of(objectA)
						.to('prop1').of(objectB).bothWays()

					objectA.prop1 = 1
					expect(objectB.prop1).to.equal 1
					
					objectB.prop1 = 2
					expect(objectA.prop1).to.equal 2

					binding.unBind(true)

					objectA.prop1 = 3
					expect(objectB.prop1).to.equal 2
					
					objectB.prop1 = 4
					expect(objectA.prop1).to.equal 3

					restartSandbox()
				
		

				test "DOMText", ()-> if not isBrowser then @skip() else
					binding = SimplyBind('textContent').of(regA)
						.to('textContent').of(regB).bothWays()

					SimplyBind('textContent').of(regA).set '1'
					expect(regB.textContent).to.equal '1'
					
					SimplyBind('textContent').of(regB).set '2'
					expect(regA.textContent).to.equal '2'

					binding.unBind(true)

					SimplyBind('textContent').of(regA).set '3'
					expect(regB.textContent).to.equal '2'
					
					SimplyBind('textContent').of(regB).set '4'
					expect(regA.textContent).to.equal '3'

					restartSandbox()
				
		

				test "DOMAttr", ()-> if not isBrowser then @skip() else
					binding = SimplyBind('attr:someattr').of(regA)
						.to('attr:someattr').of(regB).bothWays()

					SimplyBind('attr:someattr').of(regA).set '1'
					expect(regB.getAttribute 'someattr').to.equal '1'
					
					SimplyBind('attr:someattr').of(regB).set '2'
					expect(regA.getAttribute 'someattr').to.equal '2'

					binding.unBind(true)

					SimplyBind('attr:someattr').of(regA).set '3'
					expect(regB.getAttribute 'someattr').to.equal '2'
					
					SimplyBind('attr:someattr').of(regB).set '4'
					expect(regA.getAttribute 'someattr').to.equal '3'

					restartSandbox()
				
		

				test "DOMValue", ()-> if not isBrowser then @skip() else
					binding = SimplyBind('value').of(inputA)
						.to('value').of(inputB).bothWays()

					inputA.value = '1'
					inputA.emit 'change'
					expect(inputB.value).to.equal '1'
					
					inputB.value = '2'
					inputB.emit 'change'
					expect(inputA.value).to.equal '2'

					binding.unBind(true)

					inputA.value = '3'
					inputA.emit 'change'
					expect(inputB.value).to.equal '2'
					
					inputB.value = '4'
					inputB.emit 'change'
					expect(inputA.value).to.equal '3'

					restartSandbox()



				test "Function", ()->
					passedValue = null
					valueToPass = 1
					takeFromReceiver = false
					fn = (fromReceiver)-> passedValue = if takeFromReceiver then fromReceiver else valueToPass
					invoker = 'prop':'value'
					receiver = 'prop':undefined

					SimplyBind('prop').of(invoker).to(fn)
					binding = SimplyBind(fn).to('prop').of(receiver).bothWays()

					expect(receiver.prop).to.equal 1
					expect(passedValue).to.equal 1
					
					valueToPass = 5
					invoker.prop = 'anotherValue'
					expect(receiver.prop).to.equal 5
					expect(passedValue).to.equal 5
					
					takeFromReceiver = true
					receiver.prop = 10
					takeFromReceiver = false
					expect(passedValue).to.equal 10

					
					binding.unBind(true)
					valueToPass = 15
					invoker.prop = 'newValue'
					expect(receiver.prop).to.equal 10
					expect(passedValue).to.equal 15

					takeFromReceiver = true
					receiver.prop = 20
					takeFromReceiver = false
					expect(passedValue).to.equal 15



				test "Event", ()->
					eventInvokeCount = 0
					eventObject = null
					objectA.prop = objectB.prop = 'someValue'
					eventEmitterA.on 'someEvent', (event)-> eventObject = event or @
					
					binding = SimplyBind(0).ofEvent('someEvent').of(eventEmitterA).transformSelf ()-> eventObject
						.to('prop').of(objectA).bothWays()
						.and.to('prop').of(objectB).bothWays()
						.and.to ()-> eventInvokeCount++
					

					eventEmitterA.emit 'someEvent'
					expect(objectA.prop).to.equal eventObject
					expect(objectB.prop).to.equal(objectA.prop)
					expect(eventInvokeCount).to.equal 1
		

					objectA.prop = 'different value'
					expect(objectA.prop).to.equal 'different value'
					# expect(objectB.prop).to.equal eventObject
					expect(eventInvokeCount).to.equal 2
					
					objectB.prop = 'different value2'
					expect(eventInvokeCount).to.equal 3


					binding.unBind(true)
					objectA.prop = 'different value'
					eventEmitterA.emit 'someEvent'
					eventEmitterA.on 'someEvent', ()-> eventInvokeCount++

					expect(objectA.prop).to.equal 'different value'
					expect(objectB.prop).to.equal 'different value2'
					expect(eventInvokeCount).to.equal 3
					

					objectA.prop = 'another value'
					expect(objectA.prop).to.equal 'another value'
					expect(objectB.prop).to.equal 'different value2'
					
					objectB.prop = 'another value2'
					expect(objectA.prop).to.equal 'another value'
					expect(objectB.prop).to.equal 'another value2'
					expect(eventInvokeCount).to.equal 3
					expect(binding._.subs.length).to.equal 0
					
					restartSandbox()























		suite ".pollEvery() + .stopPolling()", ()->
			suiteSetup(restartSandbox)
			test 'Will cause the value to be manually polled from the subject at a given interval', (done)->
				shouldFinish = false
				lastValue = undefined
				binding = undefined
				arr = []

				fn = (length)->
					if shouldFinish
						expect(length).to.equal 2
						binding.stopPolling()
						done()
					else
						lastValue = length



				binding = SimplyBind('length').of(arr).to(fn)
				expect(lastValue).to.equal 0
				arr.push 'some value'
				arr.push 'and another'
				expect(lastValue).to.equal 0
				arr = []
				binding = SimplyBind('length').of(arr).to(fn).pollEvery(5)
				
				setTimeout ()->
					shouldFinish = true
					expect(lastValue).to.equal 0
					arr.push 'some value'
					arr.push 'and another'
					expect(lastValue).to.equal 0
				, 8



			test 'Will invoke a function upon poll', (done)->
				@slow(150)
				invokeCountA = 0
				invokeCountB = 0

				binding = SimplyBind(()-> ++invokeCountA).to(()-> ++invokeCountB).pollEvery(5)
				setTimeout ()->
					expect(invokeCountA).to.be.gt(1)
					expect(invokeCountB).to.be.gt(1)
					binding.stopPolling()
					done()
				, 15



			test "Will re-create the interval poll if called .pollEvery() twice with different values", (done)->
				@slow(200)
				invokeCount = 0
				objectA.prop = 200
				
				expect ()-> SimplyBind('prop', {'updateEvenIfSame':true}).of(objectA).to(()->invokeCount++).pollEvery(50).pollEvery(5)
					.not.to.throw()

				setTimeout ()->
					expect(invokeCount).to.be.gte(3)
					done()
					restartSandbox()
				, 75



			test "Will not throw errors when calling .stopPolling() on a binding with no pre-set interval", ()->
				expect ()-> SimplyBind('prop').of(objectA).to('prop').of(objectB).stopPolling()
					.not.to.throw()

				restartSandbox()



			test "Polling will be removed upon binding destruction", (done)->
				invokeCount = 0
				
				binding = SimplyBind('prop', {updateEvenIfSame:true, updateOnBind:false}).of(objectA)
						.transformSelf ()-> invokeCount++
					.to(noop)
				binding.pollEvery(5)
				
				setTimeout ()->
					expect(invokeCount).to.be.gte(1)
					lastCount = invokeCount
					SimplyBind.unBindAll(objectA)
					
					setTimeout ()->
						expect(invokeCount).to.equal lastCount
						done()
					, 15
				, 15


















		suite ".updateSubsOnEvent() + .removeEvent()", ()->
			suiteSetup(restartSandbox)
			test "Will listen for events on the target and upon emit will poll (and update if changed) the binding's value", ()->
				binding = SimplyBind('inheritedProp').of(eventEmitterA).to('prop1').of(objectA).updateSubsOnEvent('click')

				binding.set 'one'
				expect(objectA.prop1).to.equal 'one'

				eventEmitterA.inheritedProp = 'two'
				expect(objectA.prop1).to.equal 'one'

				eventEmitterA.emit 'click'
				expect(objectA.prop1).to.equal 'two'

				binding.removeEvent 'click'
				eventEmitterA.inheritedProp = 'three'
				expect(objectA.prop1).to.equal 'two'

				eventEmitterA.emit 'click'
				expect(objectA.prop1).to.equal 'two'
				restartSandbox()



			test "Can use custom supplied methods to apply/remove event listerners", ()->
				eventEmitterA.customAdd = ()-> eventEmitterA.on.apply eventEmitterA, arguments
				eventEmitterA.customRemove = ()-> eventEmitterA.removeListener.apply eventEmitterA, arguments

				binding = SimplyBind('inheritedProp').of(eventEmitterA)
					.to('prop1').of(objectA)
						.updateSubsOnEvent('click', 'customAdd')
				
				binding.set 'one'
				expect(objectA.prop1).to.equal 'one'
				
				eventEmitterA.inheritedProp = 'two'
				expect(objectA.prop1).to.equal 'one'
				
				eventEmitterA.emit 'click'
				expect(objectA.prop1).to.equal 'two'
				
				binding.removeEvent 'click', 'customRemove'
				eventEmitterA.inheritedProp = 'three'
				expect(objectA.prop1).to.equal 'two'
				
				eventEmitterA.emit 'click'
				expect(objectA.prop1).to.equal 'two'

				restartSandbox()



			test "Will do nothing when trying to remove an event that wasn't registered or when trying to add an event that was already registered", ()->
				binding = SimplyBind('inheritedProp').of(eventEmitterB).to('prop1').of(objectA).updateSubsOnEvent('click')
				atEvs = binding._.attachedEvents or binding._.atEV;
				expect(atEvs.length).to.equal 1
				
				binding = SimplyBind('inheritedProp').of(eventEmitterB).to('prop1').of(objectA).updateSubsOnEvent('click')
				binding = SimplyBind('inheritedProp').of(eventEmitterB).to('prop1').of(objectA).updateSubsOnEvent('change')
				expect(atEvs.length).to.equal 2
				
				binding.removeEvent 'clicker'
				expect(atEvs.length).to.equal 2
				
				binding.removeEvent 'click'
				expect(atEvs.length).to.equal 1
				
				binding.removeEvent 'change'
				expect(atEvs.length).to.equal 0

				restartSandbox()



			test "Will use the default event methods if the supplied custom methods don't exist", ()->
				binding = SimplyBind('inheritedProp').of(eventEmitterA).to('prop1').of(objectA).updateSubsOnEvent('click', 'customAdd')
				
				binding.set 'one'
				expect(objectA.prop1).to.equal 'one'
				
				eventEmitterA.inheritedProp = 'two'
				expect(objectA.prop1).to.equal 'one'
				
				eventEmitterA.emit 'click'
				expect(objectA.prop1).to.equal 'two'
				
				binding.removeEvent 'click', 'customRemove'
				eventEmitterA.inheritedProp = 'three'
				expect(objectA.prop1).to.equal 'two'
				
				eventEmitterA.emit 'click'
				expect(objectA.prop1).to.equal 'two'
				restartSandbox()



			test "Can use jQuery's .on and .off methods on DOM elements", ()-> if not isBrowser then @skip() else
				$h1 = $regAH1
				binding = SimplyBind('attr:data-attr').of($h1).to('prop1').of(objectA).updateSubsOnEvent('customevent', 'on')

				binding.set 'one'
				expect(objectA.prop1).to.equal 'one'

				$h1.attr 'data-attr', 'two'
				expect(objectA.prop1).to.equal 'one'

				$h1.trigger 'customevent'
				expect(objectA.prop1).to.equal 'two'
				binding.removeEvent 'customevent', 'off'

				$h1.attr 'data-attr', 'three'
				expect(objectA.prop1).to.equal 'two'

				$h1.trigger 'customevent'
				expect(objectA.prop1).to.equal 'two'



















		suite ".throttle()", ()->
			suiteSetup(restartSandbox)
			test "Will throttle the dep update frequency to once in a given timeframe", (done)->
				invokeCount = 0
				lastValue = null
				dispatcher = 'prop':1

				SimplyBind('prop').of(dispatcher)
					.to (v)-> lastValue=v; invokeCount++
					.throttle(15)

				expect(invokeCount).to.equal(1)
				expect(lastValue).to.equal(1)

				dispatcher.prop = 2
				dispatcher.prop = 3
				dispatcher.prop = 4
				dispatcher.prop = 5
				expect(invokeCount).to.equal(2)
				expect(lastValue).to.equal(2)

				setTimeout ()->
					expect(invokeCount).to.equal(3)
					expect(lastValue).to.equal(5)
					done()
				, 25
			

			test "Will remove existing throttles if passed boolean false", ()->
				invokeCount = 0
				lastValue = null
				dispatcher = 'prop':1

				binding = SimplyBind('prop').of(dispatcher)
					.to (v)-> lastValue=v; invokeCount++
					.throttle(15)

				expect(invokeCount).to.equal(1)
				expect(lastValue).to.equal(1)

				binding.throttle(false)
				dispatcher.prop = 2
				dispatcher.prop = 3
				dispatcher.prop = 4
				dispatcher.prop = 5
				expect(invokeCount).to.equal(5)
				expect(lastValue).to.equal(5)






























	suite "SimplyBind.unBindAll", ()->
		suite "Will unBind all bindings, but only in one direction", ()->
			suiteSetup(restartSandbox)

			test "ObjectProp", ()->
				SimplyBind('prop1').of(objectA)
					.to('prop1').of(objectB).bothWays()
				
				SimplyBind('prop2').of(objectA)
					.to('prop2').of(objectB).bothWays()

				objectA.prop1 = 'objectA.prop1'
				expect(objectA.prop1).to.equal 'objectA.prop1'
				expect(objectB.prop1).to.equal 'objectA.prop1'
				
				objectB.prop2 = 'objectB.prop2'
				expect(objectA.prop2).to.equal 'objectB.prop2'
				expect(objectB.prop2).to.equal 'objectB.prop2'
				
				objectB.prop1 = 'reset'
				objectB.prop2 = 'reset'
				SimplyBind.unBindAll(objectA)

				objectA.prop1 = 'objectA.prop1'
				expect(objectA.prop1).to.equal 'objectA.prop1'
				expect(objectB.prop1).to.equal 'reset'
				
				objectA.prop2 = 'objectA.prop2'
				expect(objectA.prop2).to.equal 'objectA.prop2'
				expect(objectB.prop2).to.equal 'reset'
				
				objectB.prop2 = 'objectB.prop2'
				expect(objectA.prop2).to.equal 'objectB.prop2'
				expect(objectB.prop2).to.equal 'objectB.prop2'

				restartSandbox()



			test "DOMText", ()-> if not isBrowser then @skip() else
				SimplyBind('textContent').of(regA)
					.to('textContent').of(regB).bothWays()
				
				SimplyBind('textContent').of(regA).set 'regA.textContent'
				expect(regA.textContent).to.equal 'regA.textContent'
				expect(regB.textContent).to.equal 'regA.textContent'
								
				SimplyBind('textContent').of(regB).set 'reset'
				SimplyBind.unBindAll(regA)

				SimplyBind('textContent').of(regA).set 'regA.textContent'
				expect(regA.textContent).to.equal 'regA.textContent'
				expect(regB.textContent).to.equal 'reset'
								
				SimplyBind('textContent').of(regB).set 'regB.textContent'
				expect(regA.textContent).to.equal 'regB.textContent'
				expect(regB.textContent).to.equal 'regB.textContent'

				restartSandbox()



			test "DOMValue", ()-> if not isBrowser then @skip() else
				SimplyBind('value').of(inputA)
					.to('value').of(inputB).bothWays()
				
				inputA.value = 'inputA.value'
				inputA.emit 'change'
				expect(inputA.value).to.equal 'inputA.value'
				expect(inputB.value).to.equal 'inputA.value'
				

				inputB.value = 'reset'
				SimplyBind.unBindAll($inputA)

				inputA.value = 'inputA.value'
				inputA.emit 'change'
				expect(inputA.value).to.equal 'inputA.value'
				expect(inputB.value).to.equal 'reset'

				inputB.value = 'inputB.value'
				inputB.emit 'change'
				expect(inputA.value).to.equal 'inputB.value'
				expect(inputB.value).to.equal 'inputB.value'

				restartSandbox()



			test "Array", ()->
				SimplyBind.settings.trackArrayChildren = true
				SimplyBind(arrayA)
					.to('prop1').of(objectA)
					.and.to('prop1').of(objectB)

				expect(objectA.prop1).to.equal arrayA
				expect(objectB.prop1).to.equal arrayA

				objectA.prop1 = 'reset'
				objectB.prop1 = 'reset'
				arrayA.push(1)
				expect(objectA.prop1).to.equal arrayA
				expect(objectB.prop1).to.equal arrayA

				objectA.prop1 = 'reset'
				objectB.prop1 = 'reset'
				arrayA[5] = 19
				expect(objectA.prop1).to.equal arrayA
				expect(objectB.prop1).to.equal arrayA



				objectA.prop1 = 'reset'
				objectB.prop1 = 'reset'
				
				SimplyBind.unBindAll(arrayA)
				arrayA.push(1)
				arrayA[3] = 23
				expect(objectA.prop1).to.equal 'reset'
				expect(objectB.prop1).to.equal 'reset'

				SimplyBind.settings.trackArrayChildren = false
				restartSandbox()



			test "Function", ()->
				passedValue = null
				valueToPass = 1
				takeFromReceiver = false
				fn = (fromReceiver)-> passedValue = if takeFromReceiver then fromReceiver else valueToPass
				invoker = 'prop':'value'
				receiver = 'prop':undefined

				SimplyBind('prop').of(invoker).to(fn)
				SimplyBind(fn).to('prop').of(receiver).bothWays()

				expect(receiver.prop).to.equal 1
				expect(passedValue).to.equal 1
				
				valueToPass = 5
				invoker.prop = 'anotherValue'
				expect(receiver.prop).to.equal 5
				expect(passedValue).to.equal 5
				
				takeFromReceiver = true
				receiver.prop = 10
				takeFromReceiver = false
				expect(passedValue).to.equal 10

				
				SimplyBind.unBindAll(fn)
				valueToPass = 15
				invoker.prop = 'newValue'
				expect(receiver.prop).to.equal 10
				expect(passedValue).to.equal 15

				takeFromReceiver = true
				receiver.prop = 20
				takeFromReceiver = false
				expect(passedValue).to.equal 20
				


			test "Event", ()->
				eventInvokeCount = 0
				eventObject = null
				objectA.prop = objectB.prop = 'someValue'
				eventEmitterA.on 'someEvent', (event)-> eventObject = event or @
				
				binding = SimplyBind(0).ofEvent('someEvent').of(eventEmitterA).transformSelf ()-> eventObject
					.to('prop').of(objectA).bothWays()
					.and.to('prop').of(objectB).bothWays()
					.and.to ()-> eventInvokeCount++
				

				eventEmitterA.emit 'someEvent'
				expect(objectA.prop).to.equal eventObject
				expect(objectB.prop).to.equal(objectA.prop)
				expect(eventInvokeCount).to.equal 1
	

				objectA.prop = 'different value'
				expect(objectA.prop).to.equal 'different value'
				# expect(objectB.prop).to.equal eventObject
				expect(eventInvokeCount).to.equal 2
				
				objectB.prop = 'different value2'
				expect(eventInvokeCount).to.equal 3


				SimplyBind.unBindAll(eventEmitterA)
				objectA.prop = 'different value'
				eventEmitterA.emit 'someEvent'
				eventEmitterA.on 'someEvent', ()-> eventInvokeCount++

				expect(objectA.prop).to.equal 'different value'
				expect(objectB.prop).to.equal 'different value2'
				expect(eventInvokeCount).to.equal 3
				

				objectA.prop = 'another value'
				expect(objectA.prop).to.equal 'another value'
				expect(objectB.prop).to.equal 'different value2'
				
				objectB.prop = 'another value2'
				expect(objectA.prop).to.equal 'another value'
				expect(objectB.prop).to.equal 'another value2'
				expect(eventInvokeCount).to.equal 5
				expect(binding._.subs.length).to.equal 0
				
				restartSandbox()





		suite "Will unBind all bindings in both directions if passed true as the second argument", ()->
			suiteSetup(restartSandbox)

			test "ObjectProp", ()->
				SimplyBind('prop1').of(objectA)
					.to('prop1').of(objectB).bothWays()
				
				SimplyBind('prop2').of(objectA)
					.to('prop2').of(objectB).bothWays()

				objectA.prop1 = 'objectA.prop1'
				expect(objectA.prop1).to.equal 'objectA.prop1'
				expect(objectB.prop1).to.equal 'objectA.prop1'
				
				objectB.prop2 = 'objectB.prop2'
				expect(objectA.prop2).to.equal 'objectB.prop2'
				expect(objectB.prop2).to.equal 'objectB.prop2'
				
				objectB.prop1 = 'reset'
				objectB.prop2 = 'reset'
				SimplyBind.unBindAll(objectA, true)

				objectA.prop1 = 'objectA.prop1'
				expect(objectA.prop1).to.equal 'objectA.prop1'
				expect(objectB.prop1).to.equal 'reset'
				
				objectA.prop2 = 'objectA.prop2'
				expect(objectA.prop2).to.equal 'objectA.prop2'
				expect(objectB.prop2).to.equal 'reset'
				
				objectB.prop2 = 'objectB.prop2'
				expect(objectA.prop2).to.equal 'objectA.prop2'
				expect(objectB.prop2).to.equal 'objectB.prop2'

				restartSandbox()



			test "DOMText", ()-> if not isBrowser then @skip() else
				SimplyBind('textContent').of(regA)
					.to('textContent').of(regB).bothWays()
				
				SimplyBind('textContent').of(regA).set 'regA.textContent'
				expect(regA.textContent).to.equal 'regA.textContent'
				expect(regB.textContent).to.equal 'regA.textContent'
								
				SimplyBind('textContent').of(regB).set 'reset'
				SimplyBind.unBindAll(regA, true)

				SimplyBind('textContent').of(regA).set 'regA.textContent'
				expect(regA.textContent).to.equal 'regA.textContent'
				expect(regB.textContent).to.equal 'reset'
								
				SimplyBind('textContent').of(regB).set 'regB.textContent'
				expect(regA.textContent).to.equal 'regA.textContent'
				expect(regB.textContent).to.equal 'regB.textContent'

				restartSandbox()



			test "DOMValue", ()-> if not isBrowser then @skip() else
				SimplyBind('value').of(inputA)
					.to('value').of(inputB).bothWays()
				
				inputA.value = 'inputA.value'
				inputA.emit 'change'
				expect(inputA.value).to.equal 'inputA.value'
				expect(inputB.value).to.equal 'inputA.value'
				

				inputB.value = 'reset'
				SimplyBind.unBindAll(inputA, true)

				inputA.value = 'inputA.value'
				inputA.emit 'change'
				expect(inputA.value).to.equal 'inputA.value'
				expect(inputB.value).to.equal 'reset'

				inputB.value = 'inputB.value'
				inputB.emit 'change'
				expect(inputA.value).to.equal 'inputA.value'
				expect(inputB.value).to.equal 'inputB.value'

				restartSandbox()



			test "Function", ()->
				passedValue = null
				valueToPass = 1
				takeFromReceiver = false
				fn = (fromReceiver)-> passedValue = if takeFromReceiver then fromReceiver else valueToPass
				invoker = 'prop':'value'
				receiver = 'prop':undefined

				SimplyBind('prop').of(invoker).to(fn)
				SimplyBind(fn).to('prop').of(receiver).bothWays()

				expect(receiver.prop).to.equal 1
				expect(passedValue).to.equal 1
				
				valueToPass = 5
				invoker.prop = 'anotherValue'
				expect(receiver.prop).to.equal 5
				expect(passedValue).to.equal 5
				
				takeFromReceiver = true
				receiver.prop = 10
				takeFromReceiver = false
				expect(passedValue).to.equal 10

				
				SimplyBind.unBindAll(fn, true)
				valueToPass = 15
				invoker.prop = 'newValue'
				expect(receiver.prop).to.equal 10
				expect(passedValue).to.equal 15

				takeFromReceiver = true
				receiver.prop = 20
				takeFromReceiver = false
				expect(passedValue).to.equal 15
				


			test "Event", ()->
				eventInvokeCount = 0
				eventObject = null
				objectA.prop = objectB.prop = 'someValue'
				eventEmitterA.on 'someEvent', (event)-> eventObject = event or @
				
				binding = SimplyBind(0).ofEvent('someEvent').of(eventEmitterA).transformSelf ()-> eventObject
					.to('prop').of(objectA).bothWays()
					.and.to('prop').of(objectB).bothWays()
					.and.to ()-> eventInvokeCount++
				

				eventEmitterA.emit 'someEvent'
				expect(objectA.prop).to.equal eventObject
				expect(objectB.prop).to.equal(objectA.prop)
				expect(eventInvokeCount).to.equal 1
	

				objectA.prop = 'different value'
				expect(objectA.prop).to.equal 'different value'
				# expect(objectB.prop).to.equal eventObject
				expect(eventInvokeCount).to.equal 2
				
				objectB.prop = 'different value2'
				expect(eventInvokeCount).to.equal 3


				SimplyBind.unBindAll(eventEmitterA, true)
				objectA.prop = 'different value'
				eventEmitterA.emit 'someEvent'
				eventEmitterA.on 'someEvent', ()-> eventInvokeCount++

				expect(objectA.prop).to.equal 'different value'
				expect(objectB.prop).to.equal 'different value2'
				expect(eventInvokeCount).to.equal 3
				

				objectA.prop = 'another value'
				expect(objectA.prop).to.equal 'another value'
				expect(objectB.prop).to.equal 'different value2'
				
				objectB.prop = 'another value2'
				expect(objectA.prop).to.equal 'another value'
				expect(objectB.prop).to.equal 'another value2'
				expect(eventInvokeCount).to.equal 3
				expect(binding._.subs.length).to.equal 0
				
				restartSandbox()
				

	






		test "Passing objects that were never bound to anything should have no effects and shouldn't trigger any errors", ()->
			expect(()->
				SimplyBind.unBindAll 'nonbinded': 'object'
				SimplyBind.unBindAll 'string'
				SimplyBind('prop1').of(objectA).to ()->
				SimplyBind.unBindAll objectA
				SimplyBind.unBindAll objectA
			).not.to.throw()
			restartSandbox()



		test "Destruction of the binding is guaranteed if the binding doesn't have any subscribers or publishers", ()->
			SimplyBind('prop1').of(objectA)
				.to('prop1').of(objectB).bothWays()

			SimplyBind.unBindAll(objectA)
			expect(objectA._sb_map).not.to.be.undefined
			expect(objectB._sb_map).not.to.be.undefined
			
			

			SimplyBind('prop1').of(objectA)
				.to('prop1').of(objectB).bothWays()
			
			SimplyBind.unBindAll(objectA, true)
			expect(objectA._sb_map).to.be.undefined
			expect(objectB._sb_map).to.be.undefined

			restartSandbox()



























