suite ".transform()", ()->
	suiteSetup(restartSandbox)
	test "Will apply a transformation to the value before updating the dependent", ()->
		dispatcher = 'value': 'current'
		transformFn = (newValue, currentValue)-> newValue+'+'+currentValue

		objectA.prop = ''
		if isBrowser
			inputA.value = ''
			regA.textContent = ''
			regA.setAttribute 'someattr', ''

		SimplyBind('value').of(dispatcher)
			.to('prop').of(objectA).transform(transformFn)

		if isBrowser
			SimplyBind('value').of(dispatcher)
				.to('value').of(inputA).transform(transformFn)
				.and.to('textContent').of(regA).transform(transformFn)
				.and.to('attr:someattr').of(regA).transform(transformFn)


		values = ()-> if not isBrowser then [objectA.prop] else [objectA.prop, inputA.value, regA.textContent, regA.getAttribute 'someattr']
		for value in values()
			expect(value).to.equal 'current+current'
		
		
		dispatcher.value = 'new'
		for value in values()
			expect(value).to.equal 'new+current+current'
		
		
		dispatcher.value = 'newer'
		for value in values()
			expect(value).to.equal 'newer+new+current+current'

		restartSandbox()




	test "Will apply transformations to event bindings", ()-> if not isBrowser then @skip() else
		resultHolder = 'event':null

		SimplyBind('event:someEvent').of(eventEmitterA)
			.to('event').of(resultHolder)
				.transform (event)-> event.type

		eventEmitterA.emit 'someEvent'
		expect(resultHolder.event).to.equal 'someEvent'




	test "Will receive the subject object as the third argument", ()->
		dispatcher = 'prop':1
		receivers = [objectA, objectB, objectC]
		index = 0

		SimplyBind('prop').of(dispatcher)
			.to('prop').of(objectA)
			.and.to('prop').of(objectB)
			.and.to('prop').of(objectC)
				.transformAll (current, prev, target)->
					expect(target).to.equal(receivers[index++])
					return current

		expect(index).to.equal(3)
		restartSandbox()




	test "Will cause a re-update only to the last proxied dependent", ()->
		invokeCount = 
			'A':0
			'B':0
			'C':0

		SimplyBind('prop1').of(objectA)
			.to ()-> invokeCount.A++
				.transform (v)-> v+v
			.and.to ()-> invokeCount.B++
				.transform (v)-> v+v
			.and.to ()-> invokeCount.C++
				.transform (v)-> v+v

		expect(invokeCount.A).to.equal 2
		expect(invokeCount.B).to.equal 2
		expect(invokeCount.C).to.equal 2

		objectA.prop1 = !objectA.prop1
		expect(invokeCount.A).to.equal 3
		expect(invokeCount.B).to.equal 3
		expect(invokeCount.C).to.equal 3



	test "Promise transforms can be used instead of regular return values if SimplyBind.options.promiseTransforms is on", (done)->
		objectA.prop2 = 'current'
		
		SimplyBind('prop1', {'updateOnBind':false}).of(objectA)
			.to (result)-> expect(result.then).not.to.be.undefined
			.transform ()-> new Promise ()->

		SimplyBind('prop2', {'promiseTransforms':true}).of(objectA)
			.to('prop2').of(objectB)
			.transform (newValue, currentValue)-> new Promise (resolve)-> resolve(newValue+'+'+currentValue)

		setTimeout ()->
			expect(objectB.prop2).to.equal 'current+current'
			objectA.prop2 = 'new'
			
			setTimeout ()->
				expect(objectB.prop2).to.equal 'new+current+current'
				restartSandbox()
				done()
			, 0
		, 0




	test "A transform will only be used for the last declared dependent", ()->
		dispatcher = 'value': 'test'
		objectA.prop1 = ''
		objectB.prop1 = ''

		SimplyBind('value').of(dispatcher)
			.to('prop1').of(objectA)
			.and.to('prop1').of(objectB)
				.transform (value)-> value.toUpperCase()

		expect(objectA.prop1).to.equal 'test'
		expect(objectB.prop1).to.equal 'TEST'

		restartSandbox()




	test "Only a single transform can be used for a binding and if two transforms are added, only the last one will be used", ()->
		dispatcher = 'value': 'tEsT'
		objectA.prop1 = ''

		SimplyBind('value').of(dispatcher)
			.to('prop1').of(objectA)
				.transform (value)-> value.toUpperCase()
				.transform (value)-> value.toLowerCase()

		expect(objectA.prop1).to.equal 'test'
		restartSandbox()



	test "A transform will be used both ways when .bothWays() is called after the .transform declaration", ()->
		dispatcher = 'value': 'test'
		objectA.prop = ''

		SimplyBind('value').of(dispatcher)
			.to('prop').of(objectA)
				.transform (value)-> value.toUpperCase()
				.bothWays()

		expect(dispatcher.value).to.equal 'test'
		expect(objectA.prop).to.equal 'TEST'
		
		dispatcher.value = 'from dispatcher'
		expect(dispatcher.value).to.equal 'from dispatcher'
		expect(objectA.prop).to.equal 'FROM DISPATCHER'
		
		objectA.prop = 'from objectA'
		expect(dispatcher.value).to.equal 'FROM OBJECTA'
		expect(objectA.prop).to.equal 'from objectA'

		restartSandbox()



	test "A transform will be used both ways when .bothWays() is called before the .transform declaration", ()->
		dispatcher = 'value': 'test'
		objectA.prop = ''

		SimplyBind('value').of(dispatcher)
			.to('prop').of(objectA).bothWays()
				.transform (value)-> value.toUpperCase()

		expect(dispatcher.value).to.equal 'test'
		expect(objectA.prop).to.equal 'TEST'
		
		dispatcher.value = 'from dispatcher'
		expect(dispatcher.value).to.equal 'from dispatcher'
		expect(objectA.prop).to.equal 'FROM DISPATCHER'
		
		objectA.prop = 'from objectA'
		expect(dispatcher.value).to.equal 'FROM OBJECTA'
		expect(objectA.prop).to.equal 'from objectA'

		restartSandbox()



	test "A different transform will be used backwards if a function is passed to .bothWays() as the first argument", ()->
		dispatcher = 'value': 'test'
		objectA.prop = ''

		SimplyBind('value').of(dispatcher)
			.to('prop').of(objectA)
				.transform (value)-> value.toUpperCase()
				.bothWays (value)-> value.toLowerCase()

		expect(dispatcher.value).to.equal 'test'
		expect(objectA.prop).to.equal 'TEST'
		
		dispatcher.value = 'From Dispatcher'
		expect(dispatcher.value).to.equal 'From Dispatcher'
		expect(objectA.prop).to.equal 'FROM DISPATCHER'
		
		objectA.prop = 'From ObjectA'
		expect(dispatcher.value).to.equal 'from objecta'
		expect(objectA.prop).to.equal 'From ObjectA'



	test "No transform will be used backwards if a false value is passed to .bothWays() as the first argument", ()->
		dispatcher = 'value': 'test'
		objectA.prop = ''

		SimplyBind('value').of(dispatcher)
			.to('prop').of(objectA)
				.transform (value)-> value.toUpperCase()
				.bothWays(false)

		expect(dispatcher.value).to.equal 'test'
		expect(objectA.prop).to.equal 'TEST'
		
		dispatcher.value = 'From Dispatcher'
		expect(dispatcher.value).to.equal 'From Dispatcher'
		expect(objectA.prop).to.equal 'FROM DISPATCHER'
		
		objectA.prop = 'From ObjectA'
		expect(dispatcher.value).to.equal 'From ObjectA'
		expect(objectA.prop).to.equal 'From ObjectA'

