1 | if mocha? and window?
|
2 | isBrowser = true
|
3 | mocha.setup('tdd')
|
4 | mocha.bail() unless @isSauceLabsTest or location.hostname
|
5 | else
|
6 | isBrowser = false
|
7 | global.window = global
|
8 | chai = require 'chai'
|
9 | chaiSpies = require 'chai-spies'
|
10 | SimplyBind = require '../dist/simplybind.node.js'
|
11 | startSandbox = require('./spec-helper.js').startSandbox
|
12 | restartSandbox = require('./spec-helper.js').restartSandbox
|
13 | chai.use chaiSpies
|
14 |
|
15 | expect = chai.expect
|
16 | should = chai.should()
|
17 |
|
18 |
|
19 |
|
20 | suite "SimplyBind", ()->
|
21 | suiteSetup(startSandbox)
|
22 |
|
23 | suite "Options", ()->
|
24 | test "SimplyBind.options should contain the global options list", ()->
|
25 | options = SimplyBind.options
|
26 | expect(options.silent).not.to.be.undefined
|
27 | expect(options.liveProps).not.to.be.undefined
|
28 | expect(options.dispatchEvents).not.to.be.undefined
|
29 | expect(options.updateEvenIfSame).not.to.be.undefined
|
30 | expect(options.updateOnBind).not.to.be.undefined
|
31 | expect(options.mutateInherited).not.to.be.undefined
|
32 | expect(options.trackArrayChildren).not.to.be.undefined
|
33 | expect(options.simpleSelector).not.to.be.undefined
|
34 | expect(options.promiseTransforms).not.to.be.undefined
|
35 | expect(options.placeholder).not.to.be.undefined
|
36 |
|
37 |
|
38 |
|
39 | test "SimplyBind.options should return a non-editable copy of the global options list", ()->
|
40 | expect(SimplyBind.options.dispatchEvents).to.be.false
|
41 | SimplyBind.options.dispatchEvents = true
|
42 | expect(SimplyBind.options.dispatchEvents).to.be.false
|
43 |
|
44 |
|
45 |
|
46 | test "SimplyBind.setOption() should set a new value for a single option", ()->
|
47 | expect(SimplyBind.options.silent).to.equal false
|
48 | SimplyBind.setOption 'silent', true
|
49 | expect(SimplyBind.options.silent).to.equal true
|
50 | SimplyBind.setOption 'silent', false
|
51 |
|
52 |
|
53 |
|
54 |
|
55 | test "SimplyBind.setOptions() should set new values for a all the options passed", ()->
|
56 | expect(SimplyBind.options.silent).to.equal false
|
57 | expect(SimplyBind.options.liveProps).to.equal true
|
58 |
|
59 | SimplyBind.setOptions
|
60 | 'silent': true
|
61 | 'liveProps': false
|
62 |
|
63 | expect(SimplyBind.options.silent).to.equal true
|
64 | expect(SimplyBind.options.liveProps).to.equal false
|
65 |
|
66 | SimplyBind.setOptions
|
67 | 'silent': false
|
68 | 'liveProps': true
|
69 | SimplyBind.setOptions {}
|
70 |
|
71 | expect(SimplyBind.options.silent).to.equal false
|
72 | expect(SimplyBind.options.liveProps).to.equal true
|
73 |
|
74 |
|
75 |
|
76 | test "SimplyBind.setOptions() should not add non-registered options", ()->
|
77 | SimplyBind.setOptions
|
78 | placeholder: ['{{', '}}']
|
79 | youtube: 'yea!'
|
80 |
|
81 | expect(SimplyBind.options.placeholder[0]).to.equal '{{'
|
82 | expect(SimplyBind.options.placeholder[1]).to.equal '}}'
|
83 | expect(SimplyBind.options.youtube).to.be.undefined
|
84 |
|
85 |
|
86 |
|
87 | test "<bound instance>.setOption should update a registered option only for the instance", ()->
|
88 | SimplyBind.setOption 'updateOnBind', false
|
89 | expect(SimplyBind.options.updateOnBind).to.be.false
|
90 |
|
91 | binding = SimplyBind('prop1').of(objectA)
|
92 | expect(binding._.options.updateOnBind).to.be.false
|
93 |
|
94 | binding.setOption 'updateOnBind', true
|
95 | expect(binding._.options.updateOnBind).to.be.true
|
96 | expect(SimplyBind.options.updateOnBind).to.be.false
|
97 |
|
98 | SimplyBind.setOption 'updateOnBind', true
|
99 | restartSandbox()
|
100 |
|
101 |
|
102 |
|
103 | test "Creating a new binding interface for a cached binding without passing an options object shouldn't overwrite existing options", ()->
|
104 | SimplyBind.setOption 'updateOnBind', false
|
105 | expect(SimplyBind.options.updateOnBind).to.be.false
|
106 |
|
107 | binding = SimplyBind('prop1').of(objectA)
|
108 | expect(binding._.options.updateOnBind).to.be.false
|
109 |
|
110 | binding.setOption 'updateOnBind', true
|
111 | expect(SimplyBind('prop1').of(objectA)._.options.updateOnBind).to.be.true
|
112 | expect(SimplyBind.options.updateOnBind).to.be.false
|
113 |
|
114 | SimplyBind.setOption 'updateOnBind', true
|
115 | restartSandbox()
|
116 |
|
117 |
|
118 |
|
119 | test "<bound instance>.setOption should update a registered option only for the instance", ()->
|
120 | binding = SimplyBind('prop1').of(objectA)
|
121 |
|
122 | binding.setOption 'placeholder', ['{{', '}}']
|
123 | binding.setOption 'youtube', 'yea'
|
124 |
|
125 | expect(binding._.options.placeholder[0]).to.equal '{{'
|
126 | expect(binding._.options.placeholder[1]).to.equal '}}'
|
127 | expect(binding._.options.youtube).to.be.undefined
|
128 |
|
129 | restartSandbox()
|
130 |
|
131 |
|
132 |
|
133 | test "Passing an options object as the 2nd param of .of() should update registered options only for the instance", ()->
|
134 | SimplyBind.setOption 'updateOnBind', false
|
135 | expect(SimplyBind.options.updateOnBind).to.be.false
|
136 |
|
137 | binding = SimplyBind('prop1', {'updateOnBind':true}).of(objectA)
|
138 | expect(binding._.options.updateOnBind).to.be.true
|
139 | expect(SimplyBind.options.updateOnBind).to.be.false
|
140 |
|
141 | SimplyBind.setOption 'updateOnBind', true
|
142 | restartSandbox()
|
143 |
|
144 |
|
145 |
|
146 | test "Passing an options object as the 2nd param of .of() should update the options even for an existing binding instance", ()->
|
147 | SimplyBind.setOption 'updateOnBind', false
|
148 | expect(SimplyBind.options.updateOnBind).to.be.false
|
149 |
|
150 | binding = SimplyBind('prop1').of(objectA)
|
151 | expect(binding._.options.updateOnBind).to.be.false
|
152 |
|
153 | binding = SimplyBind('prop1', {'updateOnBind':true, 'nonexistent':true}).of(objectA)
|
154 | expect(binding._.options.updateOnBind).to.be.true
|
155 | expect(binding._.options.nonexistent).to.be.undefined
|
156 | expect(SimplyBind.options.updateOnBind).to.be.false
|
157 |
|
158 | SimplyBind.setOption 'updateOnBind', true
|
159 | restartSandbox()
|
160 |
|
161 |
|
162 |
|
163 | test "Passing an options object as the 2nd param of .of() for an existing binding should invoke the required methods for these options", ()->
|
164 | SimplyBind.setOption 'liveProps', false
|
165 | SimplyBind.setOption 'updateOnBind', false
|
166 | SimplyBind.setOption 'mutateInherited', false
|
167 | SimplyBind.setOption 'trackArrayChildren', false
|
168 | Object::id = ''
|
169 |
|
170 | arrayInvokeCount = 0
|
171 | newOptions = {'liveProps':true, 'mutateInherited':true, 'trackArrayChildren':true}
|
172 | bindings =
|
173 | 'liveProps': SimplyBind('prop1').of(objectA)
|
174 | 'mutateInherited': SimplyBind('id').of(objectB)
|
175 | 'trackArrayChildren': SimplyBind(arrayA).to ()-> arrayInvokeCount++
|
176 |
|
177 | objectA.prop1 = '1'
|
178 | expect(bindings.liveProps.value).not.to.equal '1'
|
179 |
|
180 | objectB.id = '1'
|
181 | expect(bindings.mutateInherited.value).not.to.equal '1'
|
182 |
|
183 | arrayA[3] = '1'
|
184 | expect(arrayInvokeCount).to.equal 0
|
185 |
|
186 |
|
187 |
|
188 | SimplyBind.setOption 'liveProps', true
|
189 | SimplyBind.setOption 'updateOnBind', true
|
190 |
|
191 | SimplyBind('prop1', newOptions).of(objectA)
|
192 | SimplyBind('id', newOptions).of(objectB)
|
193 | SimplyBind(arrayA, newOptions)
|
194 |
|
195 | objectA.prop1 = '2'
|
196 | expect(bindings.liveProps.value).to.equal '2'
|
197 |
|
198 | objectB.id = '2'
|
199 | expect(bindings.mutateInherited.value).to.equal '2'
|
200 |
|
201 | arrayA[5] = '2'
|
202 | expect(arrayInvokeCount).to.equal 1
|
203 |
|
204 | delete Object::id
|
205 | restartSandbox()
|
206 |
|
207 |
|
208 |
|
209 |
|
210 |
|
211 |
|
212 |
|
213 |
|
214 |
|
215 |
|
216 |
|
217 |
|
218 |
|
219 |
|
220 |
|
221 |
|
222 |
|
223 |
|
224 | suite "Argument Values", ()->
|
225 | suiteSetup(restartSandbox)
|
226 |
|
227 | suite "SimplyBind() function", ()->
|
228 | test "Can only accept an object type of String, Number, Array, Function, or an existing binding instance", ()->
|
229 | expect ()-> SimplyBind('s')
|
230 | .not.to.throw()
|
231 |
|
232 | expect ()-> SimplyBind(0)
|
233 | .not.to.throw()
|
234 |
|
235 | expect ()-> SimplyBind([])
|
236 | .not.to.throw()
|
237 |
|
238 | expect ()-> SimplyBind(()->)
|
239 | .not.to.throw()
|
240 |
|
241 | expect ()-> SimplyBind(SimplyBind('prop1').of(objectA))
|
242 | .not.to.throw()
|
243 |
|
244 | expect ()-> SimplyBind(true)
|
245 | .to.throw()
|
246 |
|
247 | expect ()-> SimplyBind(null)
|
248 | .to.throw()
|
249 |
|
250 | expect ()-> SimplyBind(undefined)
|
251 | .to.throw()
|
252 |
|
253 | expect ()-> SimplyBind({})
|
254 | .to.throw()
|
255 |
|
256 | expect ()-> SimplyBind(new Date())
|
257 | .to.throw()
|
258 |
|
259 | if isBrowser
|
260 | expect ()-> SimplyBind($('<div />')[0])
|
261 | .to.throw()
|
262 |
|
263 | if window.Map and window.Set and window.Symbol
|
264 | expect ()-> SimplyBind(new Map())
|
265 | .to.throw()
|
266 |
|
267 | expect ()-> SimplyBind(new WeakMap())
|
268 | .to.throw()
|
269 |
|
270 | expect ()-> SimplyBind(new Set())
|
271 | .to.throw()
|
272 |
|
273 | expect ()-> SimplyBind(new WeakSet())
|
274 | .to.throw()
|
275 |
|
276 | expect ()-> SimplyBind(Symbol('a'))
|
277 | .to.throw()
|
278 |
|
279 |
|
280 |
|
281 | test "Should throw when passing an empty string", ()->
|
282 | expect ()-> SimplyBind('')
|
283 | .to.throw()
|
284 |
|
285 |
|
286 |
|
287 | suite ".of() method", ()->
|
288 | test "Can only accept non-primitive objects", ()->
|
289 | expect ()-> SimplyBind(0).of([])
|
290 | .not.to.throw()
|
291 |
|
292 | expect ()-> SimplyBind(0).of(()->)
|
293 | .not.to.throw()
|
294 |
|
295 | expect ()-> SimplyBind(0).of({})
|
296 | .not.to.throw()
|
297 |
|
298 | expect ()-> SimplyBind(0).of(new Date())
|
299 | .not.to.throw()
|
300 |
|
301 | if isBrowser
|
302 | expect ()-> SimplyBind(0).of($('<div />')[0])
|
303 | .not.to.throw()
|
304 |
|
305 | if window.Map and window.Set and window.Symbol
|
306 | expect ()-> SimplyBind(0).of(new Map())
|
307 | .not.to.throw()
|
308 |
|
309 | expect ()-> SimplyBind(0).of(new WeakMap())
|
310 | .not.to.throw()
|
311 |
|
312 | expect ()-> SimplyBind(0).of(new Set())
|
313 | .not.to.throw()
|
314 |
|
315 | expect ()-> SimplyBind(0).of(new WeakSet())
|
316 | .not.to.throw()
|
317 |
|
318 | expect ()-> SimplyBind(0).of(Symbol(0))
|
319 | .to.throw()
|
320 |
|
321 | expect ()-> SimplyBind(0).of(SimplyBind('prop1').of(objectA))
|
322 | .not.to.throw()
|
323 |
|
324 | expect ()-> SimplyBind(0).of('s')
|
325 | .to.throw()
|
326 |
|
327 | expect ()-> SimplyBind(0).of(0)
|
328 | .to.throw()
|
329 |
|
330 | expect ()-> SimplyBind(0).of(true)
|
331 | .to.throw()
|
332 |
|
333 | expect ()-> SimplyBind(0).of(null)
|
334 | .to.throw()
|
335 |
|
336 | expect ()-> SimplyBind(0).of(undefined)
|
337 | .to.throw()
|
338 |
|
339 |
|
340 |
|
341 |
|
342 | test "Will extract and use the subject bound object from the instance if passed a binding instance", ()->
|
343 | bound = SimplyBind('prop3').of(objectA).to('prop3').of(objectB)
|
344 |
|
345 | bound.set 'standard'
|
346 | expect(objectA.prop3).to.equal 'standard'
|
347 | expect(objectB.prop3).to.equal 'standard'
|
348 |
|
349 | bound2 = SimplyBind('prop4').of(bound).to('prop4').of(objectB)
|
350 |
|
351 | bound2.set 'ofBounded'
|
352 | expect(objectA.prop4).to.equal 'ofBounded'
|
353 | expect(objectB.prop4).to.equal 'ofBounded'
|
354 |
|
355 |
|
356 |
|
357 | suite ".ofEvent() method", ()->
|
358 | test "Can only accept string values", ()->
|
359 | expect ()-> SimplyBind(0).ofEvent('s')
|
360 | .not.to.throw()
|
361 |
|
362 | expect ()-> SimplyBind(0).of(objectA).toEvent('s')
|
363 | .not.to.throw()
|
364 |
|
365 | expect ()-> SimplyBind(0).ofEvent([])
|
366 | .to.throw()
|
367 |
|
368 | expect ()-> SimplyBind(0).ofEvent(()->)
|
369 | .to.throw()
|
370 |
|
371 | expect ()-> SimplyBind(0).ofEvent({})
|
372 | .to.throw()
|
373 |
|
374 | expect ()-> SimplyBind(0).ofEvent(new Date())
|
375 | .to.throw()
|
376 |
|
377 | if isBrowser
|
378 | expect ()-> SimplyBind(0).ofEvent($('<div />')[0])
|
379 | .to.throw()
|
380 |
|
381 | if window.Map and window.Set and window.Symbol
|
382 | expect ()-> SimplyBind(0).ofEvent(new Map())
|
383 | .to.throw()
|
384 |
|
385 | expect ()-> SimplyBind(0).ofEvent(new WeakMap())
|
386 | .to.throw()
|
387 |
|
388 | expect ()-> SimplyBind(0).ofEvent(new Set())
|
389 | .to.throw()
|
390 |
|
391 | expect ()-> SimplyBind(0).ofEvent(new WeakSet())
|
392 | .to.throw()
|
393 |
|
394 | expect ()-> SimplyBind(0).ofEvent(Symbol(0))
|
395 | .to.throw()
|
396 |
|
397 | expect ()-> SimplyBind(0).ofEvent(SimplyBind(0).ofEvent('s'))
|
398 | .to.throw()
|
399 |
|
400 | expect ()-> SimplyBind(0).ofEvent(0)
|
401 | .to.throw()
|
402 |
|
403 | expect ()-> SimplyBind(0).ofEvent(true)
|
404 | .to.throw()
|
405 |
|
406 | expect ()-> SimplyBind(0).ofEvent(null)
|
407 | .to.throw()
|
408 |
|
409 | expect ()-> SimplyBind(0).ofEvent(undefined)
|
410 | .to.throw()
|
411 |
|
412 |
|
413 |
|
414 | suite ".transform/condition/All/Self() methods", ()->
|
415 | test "Can only accept function values", ()->
|
416 | window.origLog = console.warn
|
417 | console.warn = chai.spy()
|
418 | timesCalled = 0
|
419 |
|
420 | SimplyBind(0).of({}).to(()->).transform(()->)
|
421 | expect(console.warn).to.have.been.called.exactly(timesCalled += 0)
|
422 |
|
423 | SimplyBind(0).of({}).to(()->).transformAll(()->)
|
424 | expect(console.warn).to.have.been.called.exactly(timesCalled += 0)
|
425 |
|
426 | SimplyBind(0).of({}).to(()->).condition(()->)
|
427 | expect(console.warn).to.have.been.called.exactly(timesCalled += 0)
|
428 |
|
429 | SimplyBind(0).of({}).to(()->).conditionAll(()->)
|
430 | expect(console.warn).to.have.been.called.exactly(timesCalled += 0)
|
431 |
|
432 | SimplyBind(0).of({}).transformSelf(()->)
|
433 | expect(console.warn).to.have.been.called.exactly(timesCalled += 0)
|
434 |
|
435 | SimplyBind(0).of({}).to(()->).transform([])
|
436 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
437 |
|
438 | SimplyBind(0).of({}).to(()->).transformAll({})
|
439 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
440 |
|
441 | SimplyBind(0).of({}).to(()->).conditionAll(new Date())
|
442 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
443 |
|
444 | if isBrowser
|
445 | SimplyBind(0).of({}).to(()->).condition($('<div />')[0])
|
446 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
447 |
|
448 | if window.Map and window.Set and window.Symbol
|
449 | SimplyBind(0).of({}).to(()->).transform(new Map())
|
450 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
451 |
|
452 | SimplyBind(0).of({}).to(()->).transformAll(new WeakMap())
|
453 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
454 |
|
455 | SimplyBind(0).of({}).to(()->).condition(new Set())
|
456 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
457 |
|
458 | SimplyBind(0).of({}).to(()->).conditionAll(new WeakSet())
|
459 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
460 |
|
461 | SimplyBind(0).of({}).transformSelf(Symbol(0))
|
462 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
463 |
|
464 | SimplyBind(0).of({}).to(()->).transform(SimplyBind('prop1').of(objectA))
|
465 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
466 |
|
467 | SimplyBind(0).of({}).to(()->).transformAll('s')
|
468 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
469 |
|
470 | SimplyBind(0).of({}).to(()->).condition(0)
|
471 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
472 |
|
473 | SimplyBind(0).of({}).to(()->).conditionAll(true)
|
474 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
475 |
|
476 | SimplyBind(0).of({}).transformSelf(null)
|
477 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
478 |
|
479 | SimplyBind(0).of({}).transformSelf(undefined)
|
480 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
481 |
|
482 | console.warn = origLog
|
483 |
|
484 |
|
485 |
|
486 | suite ".throttle()", ()->
|
487 | test "Will only accept a truthy number-type argument or a boolean false", ()->
|
488 | binding = SimplyBind('prop').of(objectA)._
|
489 | expect(binding.throttleRate or binding.thR).to.be.undefined
|
490 |
|
491 | SimplyBind('prop').of(objectA).throttle(200)
|
492 | expect(binding.throttleRate or binding.thR).to.equal 200
|
493 |
|
494 | SimplyBind('prop').of(objectA).throttle(false)
|
495 | expect(binding.throttleRate or binding.thR).to.equal.undefined
|
496 |
|
497 | SimplyBind('prop').of(objectA).throttle(0)
|
498 | expect(binding.throttleRate or binding.thR).to.equal.undefined
|
499 |
|
500 | SimplyBind('prop').of(objectA).throttle('0')
|
501 | expect(binding.throttleRate or binding.thR).to.equal.undefined
|
502 |
|
503 | SimplyBind('prop').of(objectA).throttle(NaN)
|
504 | expect(binding.throttleRate or binding.thR).to.equal.undefined
|
505 |
|
506 | SimplyBind('prop').of(objectA).throttle({})
|
507 | expect(binding.throttleRate or binding.thR).to.equal.undefined
|
508 |
|
509 | SimplyBind('prop').of(objectA).throttle([])
|
510 | expect(binding.throttleRate or binding.thR).to.equal.undefined
|
511 |
|
512 | SimplyBind('prop').of(objectA).throttle(()->)
|
513 | expect(binding.throttleRate or binding.thR).to.equal.undefined
|
514 |
|
515 | if window.Map and window.Set and window.Symbol
|
516 | SimplyBind('prop').of(objectA).throttle(new Map())
|
517 | expect(binding.throttleRate or binding.thR).to.equal.undefined
|
518 |
|
519 | SimplyBind('prop').of(objectA).throttle(new WeakMap())
|
520 | expect(binding.throttleRate or binding.thR).to.equal.undefined
|
521 |
|
522 | SimplyBind('prop').of(objectA).throttle(new Set())
|
523 | expect(binding.throttleRate or binding.thR).to.equal.undefined
|
524 |
|
525 | SimplyBind('prop').of(objectA).throttle(new WeakSet())
|
526 | expect(binding.throttleRate or binding.thR).to.equal.undefined
|
527 |
|
528 | SimplyBind('prop').of(objectA).throttle(Symbol(9))
|
529 | expect(binding.throttleRate or binding.thR).to.equal.undefined
|
530 |
|
531 |
|
532 | restartSandbox()
|
533 |
|
534 |
|
535 |
|
536 |
|
537 |
|
538 |
|
539 |
|
540 |
|
541 |
|
542 |
|
543 |
|
544 |
|
545 |
|
546 |
|
547 |
|
548 |
|
549 |
|
550 |
|
551 | suite "Errors & Warnings", ()->
|
552 | suiteSetup(restartSandbox)
|
553 |
|
554 | test "Warning when binding a property of a jQuery object containing multiple els", ()-> if not isBrowser then @skip() else
|
555 | window.origLog = console.warn
|
556 | console.warn = chai.spy()
|
557 |
|
558 | SimplyBind('value').of $('input')
|
559 | expect(console.warn).to.have.been.called()
|
560 |
|
561 | console.warn = origLog
|
562 |
|
563 |
|
564 | test "Warning when binding a property of a jQuery/NodeList/HTMLCollection object containing zero els", ()-> if not isBrowser then @skip() else
|
565 | expect ()-> SimplyBind('value').of $('nonexistent')
|
566 | .to.throw()
|
567 |
|
568 | expect ()-> SimplyBind('value').of document.querySelectorAll('nonexistent')
|
569 | .to.throw()
|
570 |
|
571 | expect ()-> SimplyBind('value').of document.getElementsByTagName('nonexistent')
|
572 | .to.throw()
|
573 |
|
574 |
|
575 | test "Warning when binding a property of a jQuery object containing zero els", ()-> if not isBrowser then @skip() else
|
576 | expect ()-> SimplyBind('value').of $('input[type="nonexistent"]')
|
577 | .to.throw()
|
578 |
|
579 |
|
580 | test "Warning when binding a property of a NodeList/HTMLCollection containing multiple els", ()-> if not isBrowser then @skip() else
|
581 | origLog = console.warn
|
582 | console.warn = chai.spy()
|
583 |
|
584 | SimplyBind('value').of document.querySelectorAll('input')
|
585 | expect(console.warn).to.have.been.called()
|
586 |
|
587 | console.warn = origLog
|
588 |
|
589 |
|
590 | test "No Warning when binding 'checked' of a jQuery object containing multiple radio/checkbox inputs", ()-> if not isBrowser then @skip() else
|
591 | origLog = console.warn
|
592 | console.warn = chai.spy()
|
593 |
|
594 | SimplyBind('checked').of $radioFields
|
595 | expect(console.warn).not.to.have.been.called()
|
596 |
|
597 | SimplyBind('value').of $radioFields
|
598 | expect(console.warn).to.have.been.called.exactly(1)
|
599 |
|
600 | console.warn = origLog
|
601 |
|
602 |
|
603 | test "No Warning when binding 'checked' of a NodeList/HTMLCollection/Array containing multiple radio/checkbox inputs", ()-> if not isBrowser then @skip() else
|
604 | origLog = console.warn
|
605 | console.warn = chai.spy()
|
606 |
|
607 | SimplyBind('checked').of $radioFields.toArray()
|
608 | expect(console.warn).not.to.have.been.called()
|
609 |
|
610 | SimplyBind('checked').of radioFields
|
611 | expect(console.warn).not.to.have.been.called()
|
612 |
|
613 | SimplyBind('value').of $radioFields.toArray()
|
614 | SimplyBind('value').of radioFields
|
615 | expect(console.warn).to.have.been.called.exactly(2)
|
616 |
|
617 | console.warn = origLog
|
618 |
|
619 |
|
620 | test "Warning when binding a property of a NodeList/HTMLCollection/Array/jQuery containing elements with mixed types", ()-> if not isBrowser then @skip() else
|
621 | origLog = console.warn
|
622 | console.warn = chai.spy()
|
623 |
|
624 | SimplyBind('checked').of $radioFields.add($checkboxFields).toArray()
|
625 | expect(console.warn).to.have.been.called.exactly(1)
|
626 |
|
627 | SimplyBind('checked').of $radioFields.add($checkboxFields)
|
628 | expect(console.warn).to.have.been.called.exactly(2)
|
629 |
|
630 | SimplyBind('checked').of document.querySelectorAll 'input'
|
631 | expect(console.warn).to.have.been.called.exactly(3)
|
632 |
|
633 | console.warn = origLog
|
634 |
|
635 |
|
636 | test "Warning when creating a binding and passing a non-function object to .transform/.condition/All", ()->
|
637 | binding = SimplyBind('prop1').of(objectA).to('prop1').of(objectB)
|
638 | origLog = console.warn
|
639 | console.warn = chai.spy()
|
640 | timesCalled = 0
|
641 |
|
642 | binding.transform []
|
643 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
644 |
|
645 | binding.transformAll []
|
646 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
647 |
|
648 | binding.transform {}
|
649 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
650 |
|
651 | binding.transform new Date()
|
652 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
653 |
|
654 | if isBrowser
|
655 | binding.transform $('<div />')[0]
|
656 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
657 |
|
658 | if window.Map and window.Set and window.Symbol
|
659 | binding.transform new Map()
|
660 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
661 |
|
662 | binding.transform new WeakMap()
|
663 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
664 |
|
665 | binding.transform new Set()
|
666 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
667 |
|
668 | binding.transform new WeakSet()
|
669 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
670 |
|
671 | binding.transform Symbol(0)
|
672 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
673 |
|
674 | binding.transform 's'
|
675 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
676 |
|
677 | binding.transform 0
|
678 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
679 |
|
680 | binding.transform true
|
681 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
682 |
|
683 | binding.transform null
|
684 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
685 |
|
686 | binding.transform undefined
|
687 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
688 |
|
689 | binding.condition []
|
690 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
691 |
|
692 | binding.conditionAll []
|
693 | expect(console.warn).to.have.been.called.exactly(timesCalled += 1)
|
694 |
|
695 |
|
696 | console.warn = origLog
|
697 | restartSandbox()
|
698 |
|
699 |
|
700 | test "Warning when passed a non-number argument selector to an event binding", ()->
|
701 | origLog = console.warn
|
702 | console.warn = chai.spy()
|
703 |
|
704 | SimplyBind('value').ofEvent 'someEvent'
|
705 | SimplyBind('15').ofEvent 'someEvent'
|
706 | SimplyBind(' 1aos95').ofEvent 'someEvent'
|
707 |
|
708 | expect(console.warn).to.have.been.called.exactly(1)
|
709 | console.warn = origLog
|
710 |
|
711 |
|
712 |
|
713 | test "No warnings should be thrown when SimplyBind.options.silent is on", ()->
|
714 | SimplyBind.setOption 'silent', true
|
715 |
|
716 | origLog = console.warn
|
717 | console.warn = chai.spy()
|
718 |
|
719 | SimplyBind('value').ofEvent('someEvent')
|
720 | SimplyBind('prop3').of(objectA).to('prop3').of(objectB).transform []
|
721 |
|
722 | expect(console.warn).not.to.have.been.called()
|
723 |
|
724 | console.warn = origLog
|
725 | SimplyBind.setOption 'silent', false
|
726 |
|
727 |
|
728 | test "Errors should still be thrown when SimplyBind.options.silent is on", ()->
|
729 | SimplyBind.setOption 'silent', true
|
730 |
|
731 | expect ()-> SimplyBind ''
|
732 | .to.throw()
|
733 |
|
734 | SimplyBind.setOption 'silent', false
|
735 |
|
736 |
|
737 | test "No errors should be thrown when scanning for placeholders on a non-string object", ()->
|
738 | dispatcher = 'prop':'value'
|
739 | receiver = 'prop':null
|
740 | expect(()->
|
741 | SimplyBind('prop').of(dispatcher)
|
742 | .to('prop.placeholder').of(receiver)
|
743 | ).not.to.throw()
|
744 |
|
745 | expect(receiver.prop).not.to.equal('value')
|
746 |
|
747 |
|
748 |
|
749 |
|
750 |
|
751 |
|
752 |
|
753 |
|
754 |
|
755 |
|
756 |
|
757 |
|
758 |
|
759 |
|
760 |
|
761 |
|
762 |
|
763 |
|
764 | suite "Internal Behavior", ()->
|
765 | suiteSetup(restartSandbox)
|
766 |
|
767 |
|
768 |
|
769 |
|
770 | test "A binding should have the correct public properies available", ()->
|
771 | binding = SimplyBind('prop1').of(objectA).to('prop2').of(objectB)
|
772 | expect(binding.ID).not.to.be.undefined
|
773 | expect(binding.value).not.to.be.undefined
|
774 | expect(binding.original).not.to.be.undefined
|
775 | expect(binding.dependents).not.to.be.undefined
|
776 | expect(binding._).not.to.be.undefined
|
777 | restartSandbox()
|
778 |
|
779 |
|
780 |
|
781 |
|
782 | test "Bindings to a nonexistent object prop should not create instantiate the object prop at first", ()->
|
783 | expect(objectA.prop20).to.be.undefined
|
784 | expect(objectB.prop20).to.be.undefined
|
785 |
|
786 | binding = SimplyBind('prop20').of(objectA).to('prop20').of(objectB)
|
787 | expect(objectA.prop20).to.be.undefined
|
788 | expect(objectB.prop20).to.be.undefined
|
789 |
|
790 | binding.set 'new value'
|
791 | expect(objectA.prop20).to.equal 'new value'
|
792 | expect(objectB.prop20).to.equal 'new value'
|
793 | restartSandbox()
|
794 |
|
795 |
|
796 |
|
797 |
|
798 | test "The binding.value property and binding.get() method should return the same value", ()->
|
799 | tempObject =
|
800 | 'a': 'with'
|
801 | 'b': 'text {{verb}} a placeholder'
|
802 |
|
803 | SimplyBind('a').of(tempObject).to('b.verb').of tempObject
|
804 |
|
805 |
|
806 | bound = SimplyBind('b.verb').of(tempObject)
|
807 | expect(tempObject.b).to.equal 'text with a placeholder'
|
808 | expect(bound.value).to.equal 'text with a placeholder'
|
809 | expect(bound.get()).to.equal 'with'
|
810 |
|
811 |
|
812 | tempObject.a = 'without'
|
813 | expect(tempObject.b).to.equal 'text without a placeholder'
|
814 | expect(bound.value).to.equal 'text without a placeholder'
|
815 | expect(bound.get()).to.equal 'without'
|
816 |
|
817 |
|
818 |
|
819 |
|
820 | suite "Method availablity in different stages", ()->
|
821 | test "Stage 0 (Selection Stage)", ()->
|
822 | binding = ()-> SimplyBind('1')
|
823 | expect(()-> binding().of objectA).not.to.throw()
|
824 | expect(()-> binding().ofEvent objectA).to.throw()
|
825 | expect(()-> binding().to 'prop2').to.throw()
|
826 | expect(()-> binding().toEvent '/local').to.throw()
|
827 | expect(()-> binding().and 'prop2').to.throw()
|
828 | expect(()-> binding().set 'value').to.throw()
|
829 | expect(()-> binding().get()).to.throw()
|
830 | expect(()-> binding().transform ()->).to.throw()
|
831 | expect(()-> binding().transformAll ()->).to.throw()
|
832 | expect(()-> binding().transformSelf ()->).to.throw()
|
833 | expect(()-> binding().condition ()->).to.throw()
|
834 | expect(()-> binding().conditionAll ()->).to.throw()
|
835 | expect(()-> binding().bothWays()).to.throw()
|
836 | expect(()-> binding().stopPolling()).to.throw()
|
837 | expect(()-> binding().pollEvery(1000).stopPolling()).to.throw()
|
838 | expect(()-> binding().unBind()).to.throw()
|
839 | expect(()-> binding().chainTo ()->).to.throw()
|
840 | expect(()-> binding().updateDepsOnEvent 'a').to.throw()
|
841 | expect(()-> binding().removeEvent 'a').to.throw()
|
842 | expect(()-> binding().throttle 5).to.throw()
|
843 |
|
844 | binding = ()-> SimplyBind('1').ofEvent 'click'
|
845 | expect(()-> binding().of objectA).not.to.throw()
|
846 | expect(()-> binding().ofEvent objectA).to.throw()
|
847 | expect(()-> binding().to 'prop2').to.throw()
|
848 | expect(()-> binding().toEvent '/local').to.throw()
|
849 | expect(()-> binding().and 'prop2').to.throw()
|
850 | expect(()-> binding().set 'value').to.throw()
|
851 | expect(()-> binding().get()).to.throw()
|
852 | expect(()-> binding().transform ()->).to.throw()
|
853 | expect(()-> binding().transformAll ()->).to.throw()
|
854 | expect(()-> binding().transformSelf ()->).to.throw()
|
855 | expect(()-> binding().condition ()->).to.throw()
|
856 | expect(()-> binding().conditionAll ()->).to.throw()
|
857 | expect(()-> binding().bothWays()).to.throw()
|
858 | expect(()-> binding().stopPolling()).to.throw()
|
859 | expect(()-> binding().pollEvery(1000).stopPolling()).to.throw()
|
860 | expect(()-> binding().unBind()).to.throw()
|
861 | expect(()-> binding().chainTo ()->).to.throw()
|
862 | expect(()-> binding().updateDepsOnEvent 'a').to.throw()
|
863 | expect(()-> binding().removeEvent 'a').to.throw()
|
864 | expect(()-> binding().throttle 5).to.throw()
|
865 |
|
866 |
|
867 |
|
868 |
|
869 |
|
870 | test "Stage 1 (Indication Stage)", ()->
|
871 | binding = ()-> SimplyBind('1').of objectA
|
872 | expect(()-> binding().of objectA).to.throw()
|
873 | expect(()-> binding().ofEvent objectA).to.throw()
|
874 | expect(()-> binding().to 'prop2').not.to.throw()
|
875 | expect(()-> binding().toEvent '/local').not.to.throw()
|
876 | expect(()-> binding().and 'prop2').to.throw()
|
877 | expect(()-> binding().set 'value').not.to.throw()
|
878 | expect(()-> binding().get()).not.to.throw()
|
879 | expect(()-> binding().transform ()->).to.throw()
|
880 | expect(()-> binding().transformAll ()->).to.throw()
|
881 | expect(()-> binding().transformSelf ()->).not.to.throw()
|
882 | expect(()-> binding().condition ()->).to.throw()
|
883 | expect(()-> binding().conditionAll ()->).to.throw()
|
884 | expect(()-> binding().bothWays()).to.throw()
|
885 | expect(()-> binding().stopPolling()).to.throw()
|
886 | expect(()-> binding().pollEvery(1000).stopPolling()).to.throw()
|
887 | expect(()-> binding().unBind()).to.throw()
|
888 | expect(()-> binding().chainTo ()->).to.throw()
|
889 | expect(()-> binding().updateDepsOnEvent 'a').to.throw()
|
890 | expect(()-> binding().removeEvent 'a').to.throw()
|
891 | expect(()-> binding().throttle 5).not.to.throw()
|
892 |
|
893 | binding = ()-> SimplyBind('1').ofEvent('click').of eventEmitterA
|
894 | expect(()-> binding().of objectA).to.throw()
|
895 | expect(()-> binding().ofEvent objectA).to.throw()
|
896 | expect(()-> binding().to 'prop2').not.to.throw()
|
897 | expect(()-> binding().toEvent '/local').not.to.throw()
|
898 | expect(()-> binding().and 'prop2').to.throw()
|
899 | expect(()-> binding().set 'value').not.to.throw()
|
900 | expect(()-> binding().get()).not.to.throw()
|
901 | expect(()-> binding().transform ()->).to.throw()
|
902 | expect(()-> binding().transformAll ()->).to.throw()
|
903 | expect(()-> binding().transformSelf ()->).not.to.throw()
|
904 | expect(()-> binding().condition ()->).to.throw()
|
905 | expect(()-> binding().conditionAll ()->).to.throw()
|
906 | expect(()-> binding().bothWays()).to.throw()
|
907 | expect(()-> binding().stopPolling()).to.throw()
|
908 | expect(()-> binding().pollEvery(1000).stopPolling()).to.throw()
|
909 | expect(()-> binding().unBind()).to.throw()
|
910 | expect(()-> binding().chainTo ()->).to.throw()
|
911 | expect(()-> binding().updateDepsOnEvent 'a').to.throw()
|
912 | expect(()-> binding().removeEvent 'a').to.throw()
|
913 | expect(()-> binding().throttle 5).not.to.throw()
|
914 |
|
915 |
|
916 |
|
917 |
|
918 |
|
919 | test "Stage 2 (Binding Selection Stage)", ()->
|
920 | binding = ()-> SimplyBind('1').of(objectA).to 'prop1'
|
921 | expect(()-> binding().of objectA).not.to.throw()
|
922 | expect(()-> binding().ofEvent objectA).to.throw()
|
923 | expect(()-> binding().to 'prop2').to.throw()
|
924 | expect(()-> binding().toEvent '/local').to.throw()
|
925 | expect(()-> binding().and 'prop2').to.throw()
|
926 | expect(()-> binding().set 'value').to.throw()
|
927 | expect(()-> binding().get()).to.throw()
|
928 | expect(()-> binding().transform ()->).to.throw()
|
929 | expect(()-> binding().transformAll ()->).to.throw()
|
930 | expect(()-> binding().transformSelf ()->).to.throw()
|
931 | expect(()-> binding().condition ()->).to.throw()
|
932 | expect(()-> binding().conditionAll ()->).to.throw()
|
933 | expect(()-> binding().bothWays()).to.throw()
|
934 | expect(()-> binding().stopPolling()).to.throw()
|
935 | expect(()-> binding().pollEvery(1000).stopPolling()).to.throw()
|
936 | expect(()-> binding().unBind()).to.throw()
|
937 | expect(()-> binding().chainTo ()->).to.throw()
|
938 | expect(()-> binding().updateDepsOnEvent 'a').to.throw()
|
939 | expect(()-> binding().removeEvent 'a').to.throw()
|
940 | expect(()-> binding().throttle 5).to.throw()
|
941 |
|
942 |
|
943 | binding = ()-> SimplyBind('1').of(objectA).to('prop:prop1').of(objectB).and 'prop2'
|
944 | expect(()-> binding().of objectA).not.to.throw()
|
945 | expect(()-> binding().ofEvent objectA).to.throw()
|
946 | expect(()-> binding().to 'prop2').to.throw()
|
947 | expect(()-> binding().toEvent '/local').to.throw()
|
948 | expect(()-> binding().and 'prop2').to.throw()
|
949 | expect(()-> binding().set 'value').to.throw()
|
950 | expect(()-> binding().get()).to.throw()
|
951 | expect(()-> binding().transform ()->).to.throw()
|
952 | expect(()-> binding().transformAll ()->).to.throw()
|
953 | expect(()-> binding().transformSelf ()->).to.throw()
|
954 | expect(()-> binding().condition ()->).to.throw()
|
955 | expect(()-> binding().conditionAll ()->).to.throw()
|
956 | expect(()-> binding().bothWays()).to.throw()
|
957 | expect(()-> binding().stopPolling()).to.throw()
|
958 | expect(()-> binding().pollEvery(1000).stopPolling()).to.throw()
|
959 | expect(()-> binding().unBind()).to.throw()
|
960 | expect(()-> binding().chainTo ()->).to.throw()
|
961 | expect(()-> binding().updateDepsOnEvent 'a').to.throw()
|
962 | expect(()-> binding().removeEvent 'a').to.throw()
|
963 | expect(()-> binding().throttle 5).to.throw()
|
964 |
|
965 |
|
966 |
|
967 |
|
968 |
|
969 | test "Stage 3 (Binding Complete Stage)", ()->
|
970 | binding = ()-> SimplyBind('1').of(objectA).to('prop1').of objectB
|
971 | expect(()-> binding().of objectA).to.throw()
|
972 | expect(()-> binding().ofEvent objectA).to.throw()
|
973 | expect(()-> binding().to 'prop2').to.throw()
|
974 | expect(()-> binding().toEvent '/local').to.throw()
|
975 | expect(()-> binding().and 'prop2').not.to.throw()
|
976 | expect(()-> binding().set 'value').not.to.throw()
|
977 | expect(()-> binding().get()).not.to.throw()
|
978 | expect(()-> binding().transform ()->).not.to.throw()
|
979 | expect(()-> binding().transformAll ()->).not.to.throw()
|
980 | expect(()-> binding().transformSelf ()->).to.throw()
|
981 | expect(()-> binding().condition ()->).not.to.throw()
|
982 | expect(()-> binding().conditionAll ()->).not.to.throw()
|
983 | expect(()-> binding().bothWays()).not.to.throw()
|
984 | expect(()-> binding().stopPolling()).not.to.throw()
|
985 | expect(()-> binding().pollEvery(1000).stopPolling()).not.to.throw()
|
986 | expect(()-> binding().unBind()).not.to.throw()
|
987 | expect(()-> binding().chainTo ()->).not.to.throw()
|
988 | expect(()-> binding().updateDepsOnEvent 'a').not.to.throw()
|
989 | expect(()-> binding().removeEvent 'a').not.to.throw()
|
990 | expect(()-> binding().throttle 5).not.to.throw()
|
991 |
|
992 | binding = ()-> SimplyBind('1').of(objectA).to('prop1').of(objectB).and('prop2').of objectB
|
993 | expect(()-> binding().of objectA).to.throw()
|
994 | expect(()-> binding().ofEvent objectA).to.throw()
|
995 | expect(()-> binding().to 'prop2').to.throw()
|
996 | expect(()-> binding().toEvent '/local').to.throw()
|
997 | expect(()-> binding().and 'prop2').not.to.throw()
|
998 | expect(()-> binding().set 'value').not.to.throw()
|
999 | expect(()-> binding().get()).not.to.throw()
|
1000 | expect(()-> binding().transform ()->).not.to.throw()
|
1001 | expect(()-> binding().transformAll ()->).not.to.throw()
|
1002 | expect(()-> binding().transformSelf ()->).to.throw()
|
1003 | expect(()-> binding().condition ()->).not.to.throw()
|
1004 | expect(()-> binding().conditionAll ()->).not.to.throw()
|
1005 | expect(()-> binding().bothWays()).not.to.throw()
|
1006 | expect(()-> binding().stopPolling()).not.to.throw()
|
1007 | expect(()-> binding().pollEvery(1000).stopPolling()).not.to.throw()
|
1008 | expect(()-> binding().unBind()).not.to.throw()
|
1009 | expect(()-> binding().chainTo ()->).not.to.throw()
|
1010 | expect(()-> binding().updateDepsOnEvent 'a').not.to.throw()
|
1011 | expect(()-> binding().removeEvent 'a').not.to.throw()
|
1012 | expect(()-> binding().throttle 5).not.to.throw()
|
1013 |
|
1014 | binding = ()-> SimplyBind('1').of(objectA).to('prop1').of(objectB).bothWays()
|
1015 | expect(()-> binding().of objectA).to.throw()
|
1016 | expect(()-> binding().ofEvent objectA).to.throw()
|
1017 | expect(()-> binding().to 'prop2').to.throw()
|
1018 | expect(()-> binding().toEvent '/local').to.throw()
|
1019 | expect(()-> binding().and 'prop2').not.to.throw()
|
1020 | expect(()-> binding().set 'value').not.to.throw()
|
1021 | expect(()-> binding().get()).not.to.throw()
|
1022 | expect(()-> binding().transform ()->).not.to.throw()
|
1023 | expect(()-> binding().transformAll ()->).not.to.throw()
|
1024 | expect(()-> binding().transformSelf ()->).to.throw()
|
1025 | expect(()-> binding().condition ()->).not.to.throw()
|
1026 | expect(()-> binding().conditionAll ()->).not.to.throw()
|
1027 | expect(()-> binding().bothWays()).not.to.throw()
|
1028 | expect(()-> binding().stopPolling()).not.to.throw()
|
1029 | expect(()-> binding().pollEvery(1000).stopPolling()).not.to.throw()
|
1030 | expect(()-> binding().unBind()).not.to.throw()
|
1031 | expect(()-> binding().chainTo ()->).not.to.throw()
|
1032 | expect(()-> binding().updateDepsOnEvent 'a').not.to.throw()
|
1033 | expect(()-> binding().removeEvent 'a').not.to.throw()
|
1034 | expect(()-> binding().throttle 5).not.to.throw()
|
1035 |
|
1036 | binding = ()-> SimplyBind('1').of(objectA).to('prop1').of(objectB).transform ()->
|
1037 | expect(()-> binding().of objectA).to.throw()
|
1038 | expect(()-> binding().ofEvent objectA).to.throw()
|
1039 | expect(()-> binding().to 'prop2').to.throw()
|
1040 | expect(()-> binding().toEvent '/local').to.throw()
|
1041 | expect(()-> binding().and 'prop2').not.to.throw()
|
1042 | expect(()-> binding().set 'value').not.to.throw()
|
1043 | expect(()-> binding().get()).not.to.throw()
|
1044 | expect(()-> binding().transform ()->).to.throw()
|
1045 | expect(()-> binding().transformAll ()->).to.throw()
|
1046 | expect(()-> binding().transformSelf ()->).to.throw()
|
1047 | expect(()-> binding().condition ()->).not.to.throw()
|
1048 | expect(()-> binding().conditionAll ()->).not.to.throw()
|
1049 | expect(()-> binding().bothWays()).not.to.throw()
|
1050 | expect(()-> binding().stopPolling()).not.to.throw()
|
1051 | expect(()-> binding().pollEvery(1000).stopPolling()).not.to.throw()
|
1052 | expect(()-> binding().unBind()).not.to.throw()
|
1053 | expect(()-> binding().chainTo ()->).not.to.throw()
|
1054 | expect(()-> binding().updateDepsOnEvent 'a').not.to.throw()
|
1055 | expect(()-> binding().removeEvent 'a').not.to.throw()
|
1056 | expect(()-> binding().throttle 5).not.to.throw()
|
1057 |
|
1058 | binding = ()-> SimplyBind('1').of(objectA).to('prop1').of(objectB).transformAll ()->
|
1059 | expect(()-> binding().of objectA).to.throw()
|
1060 | expect(()-> binding().ofEvent objectA).to.throw()
|
1061 | expect(()-> binding().to 'prop2').to.throw()
|
1062 | expect(()-> binding().toEvent '/local').to.throw()
|
1063 | expect(()-> binding().and 'prop2').to.throw()
|
1064 | expect(()-> binding().set 'value').not.to.throw()
|
1065 | expect(()-> binding().get()).not.to.throw()
|
1066 | expect(()-> binding().transform ()->).to.throw()
|
1067 | expect(()-> binding().transformAll ()->).to.throw()
|
1068 | expect(()-> binding().transformSelf ()->).to.throw()
|
1069 | expect(()-> binding().condition ()->).not.to.throw()
|
1070 | expect(()-> binding().conditionAll ()->).not.to.throw()
|
1071 | expect(()-> binding().bothWays()).to.throw()
|
1072 | expect(()-> binding().stopPolling()).not.to.throw()
|
1073 | expect(()-> binding().pollEvery(1000).stopPolling()).not.to.throw()
|
1074 | expect(()-> binding().unBind()).not.to.throw()
|
1075 | expect(()-> binding().chainTo ()->).not.to.throw()
|
1076 | expect(()-> binding().updateDepsOnEvent 'a').not.to.throw()
|
1077 | expect(()-> binding().removeEvent 'a').not.to.throw()
|
1078 | expect(()-> binding().throttle 5).not.to.throw()
|
1079 |
|
1080 | binding = ()-> SimplyBind('1').of(objectA).to('prop1').of(objectB).condition ()->
|
1081 | expect(()-> binding().of objectA).to.throw()
|
1082 | expect(()-> binding().ofEvent objectA).to.throw()
|
1083 | expect(()-> binding().to 'prop2').to.throw()
|
1084 | expect(()-> binding().toEvent '/local').to.throw()
|
1085 | expect(()-> binding().and 'prop2').not.to.throw()
|
1086 | expect(()-> binding().set 'value').not.to.throw()
|
1087 | expect(()-> binding().get()).not.to.throw()
|
1088 | expect(()-> binding().transform ()->).not.to.throw()
|
1089 | expect(()-> binding().transformAll ()->).not.to.throw()
|
1090 | expect(()-> binding().transformSelf ()->).to.throw()
|
1091 | expect(()-> binding().condition ()->).not.to.throw()
|
1092 | expect(()-> binding().conditionAll ()->).not.to.throw()
|
1093 | expect(()-> binding().bothWays()).not.to.throw()
|
1094 | expect(()-> binding().stopPolling()).not.to.throw()
|
1095 | expect(()-> binding().pollEvery(1000).stopPolling()).not.to.throw()
|
1096 | expect(()-> binding().unBind()).not.to.throw()
|
1097 | expect(()-> binding().chainTo ()->).not.to.throw()
|
1098 | expect(()-> binding().updateDepsOnEvent 'a').not.to.throw()
|
1099 | expect(()-> binding().removeEvent 'a').not.to.throw()
|
1100 | expect(()-> binding().throttle 5).not.to.throw()
|
1101 |
|
1102 | binding = ()-> SimplyBind('1').of(objectA).to('prop1').of(objectB).conditionAll ()->
|
1103 | expect(()-> binding().of objectA).to.throw()
|
1104 | expect(()-> binding().ofEvent objectA).to.throw()
|
1105 | expect(()-> binding().to 'prop2').to.throw()
|
1106 | expect(()-> binding().toEvent '/local').to.throw()
|
1107 | expect(()-> binding().and 'prop2').not.to.throw()
|
1108 | expect(()-> binding().set 'value').not.to.throw()
|
1109 | expect(()-> binding().get()).not.to.throw()
|
1110 | expect(()-> binding().transform ()->).not.to.throw()
|
1111 | expect(()-> binding().transformAll ()->).not.to.throw()
|
1112 | expect(()-> binding().transformSelf ()->).to.throw()
|
1113 | expect(()-> binding().condition ()->).not.to.throw()
|
1114 | expect(()-> binding().conditionAll ()->).not.to.throw()
|
1115 | expect(()-> binding().bothWays()).not.to.throw()
|
1116 | expect(()-> binding().stopPolling()).not.to.throw()
|
1117 | expect(()-> binding().pollEvery(1000).stopPolling()).not.to.throw()
|
1118 | expect(()-> binding().unBind()).not.to.throw()
|
1119 | expect(()-> binding().chainTo ()->).not.to.throw()
|
1120 | expect(()-> binding().updateDepsOnEvent 'a').not.to.throw()
|
1121 | expect(()-> binding().removeEvent 'a').not.to.throw()
|
1122 | expect(()-> binding().throttle 5).not.to.throw()
|
1123 |
|
1124 | binding = ()-> SimplyBind('1').of(objectA).to('prop1').of(objectB).transform(()->).and ()->
|
1125 | expect(()-> binding().of objectA).to.throw()
|
1126 | expect(()-> binding().ofEvent objectA).to.throw()
|
1127 | expect(()-> binding().to 'prop2').to.throw()
|
1128 | expect(()-> binding().toEvent '/local').to.throw()
|
1129 | expect(()-> binding().and 'prop2').not.to.throw()
|
1130 | expect(()-> binding().set 'value').not.to.throw()
|
1131 | expect(()-> binding().get()).not.to.throw()
|
1132 | expect(()-> binding().transform ()->).not.to.throw()
|
1133 | expect(()-> binding().transformAll ()->).not.to.throw()
|
1134 | expect(()-> binding().transformSelf ()->).to.throw()
|
1135 | expect(()-> binding().condition ()->).not.to.throw()
|
1136 | expect(()-> binding().conditionAll ()->).not.to.throw()
|
1137 | expect(()-> binding().bothWays()).not.to.throw()
|
1138 | expect(()-> binding().stopPolling()).not.to.throw()
|
1139 | expect(()-> binding().pollEvery(1000).stopPolling()).not.to.throw()
|
1140 | expect(()-> binding().unBind()).not.to.throw()
|
1141 | expect(()-> binding().chainTo ()->).not.to.throw()
|
1142 | expect(()-> binding().updateDepsOnEvent 'a').not.to.throw()
|
1143 | expect(()-> binding().removeEvent 'a').not.to.throw()
|
1144 | expect(()-> binding().throttle 5).not.to.throw()
|
1145 |
|
1146 | binding = ()-> SimplyBind('1').of(objectA).to('prop1').of(objectB).transform(()->).and(()->).chainTo ()->
|
1147 | expect(()-> binding().of objectA).to.throw()
|
1148 | expect(()-> binding().ofEvent objectA).to.throw()
|
1149 | expect(()-> binding().to 'prop2').to.throw()
|
1150 | expect(()-> binding().toEvent '/local').to.throw()
|
1151 | expect(()-> binding().and 'prop2').not.to.throw()
|
1152 | expect(()-> binding().set 'value').not.to.throw()
|
1153 | expect(()-> binding().get()).not.to.throw()
|
1154 | expect(()-> binding().transform ()->).not.to.throw()
|
1155 | expect(()-> binding().transformAll ()->).not.to.throw()
|
1156 | expect(()-> binding().transformSelf ()->).to.throw()
|
1157 | expect(()-> binding().condition ()->).not.to.throw()
|
1158 | expect(()-> binding().conditionAll ()->).not.to.throw()
|
1159 | expect(()-> binding().bothWays()).not.to.throw()
|
1160 | expect(()-> binding().stopPolling()).not.to.throw()
|
1161 | expect(()-> binding().pollEvery(1000).stopPolling()).not.to.throw()
|
1162 | expect(()-> binding().unBind()).not.to.throw()
|
1163 | expect(()-> binding().chainTo ()->).not.to.throw()
|
1164 | expect(()-> binding().updateDepsOnEvent 'a').not.to.throw()
|
1165 | expect(()-> binding().removeEvent 'a').not.to.throw()
|
1166 | expect(()-> binding().throttle 5).not.to.throw()
|
1167 |
|
1168 |
|
1169 |
|
1170 |
|
1171 | suite "Cached Bindings", ()->
|
1172 | test "A cached version of the binding should be returned when re-creating an existing one", ()->
|
1173 |
|
1174 | expect(SimplyBind('prop1').of(objectA).ID)
|
1175 | .to.equal(SimplyBind('prop1').of(objectA).ID)
|
1176 |
|
1177 | expect(SimplyBind('prop1').of(objectA).to('prop1').of(objectB)._.deps[0].ID)
|
1178 | .to.equal(SimplyBind('prop1').of(objectB).ID)
|
1179 |
|
1180 | if isBrowser
|
1181 |
|
1182 | expect(SimplyBind('attr:someattr').of(regA).ID)
|
1183 | .to.equal(SimplyBind('attr:someattr').of(regA).ID)
|
1184 |
|
1185 | expect(SimplyBind('attr:someattr').of(regA).to('attr:someattr').of(regB)._.deps[0].ID)
|
1186 | .to.equal(SimplyBind('attr:someattr').of(regB).ID)
|
1187 |
|
1188 |
|
1189 |
|
1190 | expect(SimplyBind('value').of(inputA).ID)
|
1191 | .to.equal(SimplyBind('value').of(inputA).ID)
|
1192 |
|
1193 | expect(SimplyBind('value').of(inputA).to('value').of(inputB)._.deps[0].ID)
|
1194 | .to.equal(SimplyBind('value').of(inputB).ID)
|
1195 |
|
1196 |
|
1197 |
|
1198 | expect(SimplyBind('checked').of(checkboxA).ID)
|
1199 | .to.equal(SimplyBind('checked').of(checkboxA).ID)
|
1200 |
|
1201 | expect(SimplyBind('checked').of(checkboxA).to('checked').of(checkboxB)._.deps[0].ID)
|
1202 | .to.equal(SimplyBind('checked').of(checkboxB).ID)
|
1203 |
|
1204 |
|
1205 |
|
1206 | expect(SimplyBind('checked').of($checkboxFields).ID)
|
1207 | .to.equal(SimplyBind('checked').of($checkboxFields).ID)
|
1208 |
|
1209 |
|
1210 |
|
1211 | expect(SimplyBind('checked').of($radioFields).ID)
|
1212 | .to.equal(SimplyBind('checked').of($radioFields).ID)
|
1213 |
|
1214 |
|
1215 |
|
1216 | expect(SimplyBind('textContent').of(regA).ID)
|
1217 | .to.equal(SimplyBind('textContent').of(regA).ID)
|
1218 |
|
1219 | expect(SimplyBind('textContent').of(regA).to('textContent').of(regB)._.deps[0].ID)
|
1220 | .to.equal(SimplyBind('textContent').of(regB).ID)
|
1221 |
|
1222 |
|
1223 |
|
1224 | expect(SimplyBind(0).ofEvent('someEvent').of(eventEmitterA).ID)
|
1225 | .to.equal(SimplyBind(0).ofEvent('someEvent').of(eventEmitterA).ID)
|
1226 |
|
1227 | expect(SimplyBind(0).ofEvent('someEvent').of(eventEmitterA).toEvent('someEvent').of(eventEmitterB)._.deps[0].ID)
|
1228 | .to.equal(SimplyBind(0).ofEvent('someEvent').of(eventEmitterB).ID)
|
1229 |
|
1230 |
|
1231 |
|
1232 | expect(SimplyBind(arrayA).ID)
|
1233 | .to.equal(SimplyBind(arrayA).ID)
|
1234 |
|
1235 | expect(SimplyBind(arrayA).to(arrayB)._.deps[0].ID)
|
1236 | .to.equal(SimplyBind(arrayB).ID)
|
1237 |
|
1238 |
|
1239 |
|
1240 | expect(SimplyBind(fnA).ID)
|
1241 | .to.equal(SimplyBind(fnA).ID)
|
1242 |
|
1243 | expect(SimplyBind(fnA).to(fnB)._.deps[0].ID)
|
1244 | .to.equal(SimplyBind(fnB).ID)
|
1245 |
|
1246 |
|
1247 | restartSandbox()
|
1248 |
|
1249 |
|
1250 |
|
1251 | 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", ()->
|
1252 | dispatcher = 'prop':'This is an {{size}} size shirt'
|
1253 | receiver = 'prop':''
|
1254 |
|
1255 | SimplyBind('prop').of(dispatcher)
|
1256 | .to('prop').of(receiver)
|
1257 |
|
1258 | expect(receiver.prop).to.equal(dispatcher.prop)
|
1259 | expect(dispatcher.prop).to.equal 'This is an {{size}} size shirt'
|
1260 |
|
1261 |
|
1262 | SimplyBind('prop').of(dispatcher)
|
1263 | .to('prop.size').of(receiver)
|
1264 |
|
1265 | dispatcher.prop = 'XXL'
|
1266 | expect(dispatcher.prop).to.equal 'XXL'
|
1267 | expect(receiver.prop).to.equal 'This is an XXL size shirt'
|
1268 |
|
1269 |
|
1270 |
|
1271 | 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", ()->
|
1272 | dispatcher = 'noun':'', 'adjective':''
|
1273 | receiver = 'prop':'This {{noun}} is **adjective**'
|
1274 |
|
1275 | SimplyBind('noun').of(dispatcher)
|
1276 | .to('prop.noun').of(receiver)
|
1277 |
|
1278 | dispatcher.noun = 'test'
|
1279 | expect(receiver.prop).to.equal 'This test is **adjective**'
|
1280 |
|
1281 |
|
1282 | SimplyBind.setOption 'placeholder', ['**', '**']
|
1283 |
|
1284 | SimplyBind('adjective').of(dispatcher)
|
1285 | .to('prop.adjective').of(receiver)
|
1286 |
|
1287 | dispatcher.adjective = 'good'
|
1288 | expect(receiver.prop).to.equal 'This test is **adjective**'
|
1289 |
|
1290 | dispatcher.noun = 'suite'
|
1291 | expect(receiver.prop).to.equal 'This suite is **adjective**'
|
1292 |
|
1293 | SimplyBind.setOption 'placeholder', ['{{', '}}']
|
1294 |
|
1295 |
|
1296 |
|
1297 | test "When re-binding an object prop that was deleted manually make sure to re-make the property a live one", ()->
|
1298 | objectA.prop = 1
|
1299 | SimplyBind('prop').of(objectA)
|
1300 | .to('prop').of(objectB)
|
1301 |
|
1302 | expect(objectB.prop).to.equal(objectA.prop)
|
1303 | objectA.prop = 2
|
1304 | expect(objectB.prop).to.equal(objectA.prop)
|
1305 |
|
1306 | delete objectB.prop
|
1307 | objectA.prop = 3
|
1308 | expect(objectB.prop).not.to.equal(objectA.prop)
|
1309 |
|
1310 |
|
1311 | SimplyBind('prop').of(objectA)
|
1312 | .to('prop').of(objectB)
|
1313 |
|
1314 | expect(objectB.prop).to.equal(objectA.prop)
|
1315 |
|
1316 | objectA.prop = 4
|
1317 | expect(objectB.prop).to.equal(objectA.prop)
|
1318 |
|
1319 | restartSandbox()
|
1320 |
|
1321 |
|
1322 |
|
1323 | 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", ()->
|
1324 | invokeCount = 0
|
1325 | SimplyBind(arrayA, 'trackArrayChildren':true).to ()-> invokeCount++
|
1326 |
|
1327 | expect(invokeCount).to.equal 1
|
1328 |
|
1329 | arrayA[3] = 44
|
1330 | expect(invokeCount).to.equal 2
|
1331 |
|
1332 | arrayA[20] = 21
|
1333 | expect(invokeCount).to.equal 2
|
1334 |
|
1335 | SimplyBind('18').of(arrayA)
|
1336 | arrayA[18] = 188
|
1337 | expect(invokeCount).to.equal 4
|
1338 |
|
1339 | arrayA[18] = 1888
|
1340 | expect(invokeCount).to.equal 5
|
1341 |
|
1342 |
|
1343 |
|
1344 |
|
1345 |
|
1346 |
|
1347 |
|
1348 |
|
1349 |
|
1350 |
|
1351 |
|
1352 |
|
1353 |
|
1354 |
|
1355 |
|
1356 |
|
1357 |
|
1358 |
|
1359 |
|
1360 |
|
1361 |
|
1362 |
|
1363 |
|
1364 |
|
1365 |
|
1366 |
|
1367 |
|
1368 |
|
1369 |
|
1370 |
|
1371 |
|
1372 |
|
1373 |
|
1374 |
|
1375 |
|
1376 |
|
1377 |
|
1378 |
|
1379 | suite "Data Binding Behavior", ()->
|
1380 | suiteSetup(restartSandbox)
|
1381 | test "Object properties should behave the same way across all object types", ()->
|
1382 | dispatcher =
|
1383 | 'standard': objectA
|
1384 | 'array': arrayA
|
1385 | 'function': ()->
|
1386 | 'domDiv': if isBrowser then $('<div />')[0] else {}
|
1387 | 'domInput': if isBrowser then $('<input />')[0] else {}
|
1388 | 'domNode': if isBrowser then $('<div>text</div>')[0].childNodes[0] else {}
|
1389 | 'date': new Date()
|
1390 | receiver =
|
1391 | 'standard': objectB
|
1392 | 'array': arrayB
|
1393 | 'function': ()->
|
1394 | 'domDiv': if isBrowser then $('<div />')[0] else {}
|
1395 | 'domInput': if isBrowser then $('<input />')[0] else {}
|
1396 | 'domNode': if isBrowser then $('<div>text</div>')[0].childNodes[0] else {}
|
1397 | 'date': new Date()
|
1398 |
|
1399 | for name,object of dispatcher
|
1400 | SimplyBind('prop').of(dispatcher[name]).to('prop').of(receiver[name])
|
1401 | expect(receiver[name].prop).to.be.undefined
|
1402 |
|
1403 | SimplyBind('prop').of(dispatcher[name]).set(100)
|
1404 | expect(receiver[name].prop).to.equal(100)
|
1405 |
|
1406 | restartSandbox()
|
1407 |
|
1408 |
|
1409 |
|
1410 | test "Object properties should be made into live properties when SimplyBind.options.liveProps is on", ()->
|
1411 | expect(SimplyBind.options.liveProps).to.be.true
|
1412 | invokeCount = 0
|
1413 |
|
1414 | SimplyBind('prop1').of(objectA).to ()-> invokeCount++
|
1415 | expect(invokeCount).to.equal(1)
|
1416 |
|
1417 | objectA.prop1 = !objectA.prop1
|
1418 | expect(invokeCount).to.equal(2)
|
1419 |
|
1420 | SimplyBind('prop1').of(objectA).set !objectA.prop1
|
1421 | expect(invokeCount).to.equal(3)
|
1422 |
|
1423 |
|
1424 | SimplyBind.setOption 'liveProps', false
|
1425 | invokeCount = 0
|
1426 |
|
1427 | SimplyBind('prop1').of(objectB).to ()-> invokeCount++
|
1428 | expect(invokeCount).to.equal(1)
|
1429 |
|
1430 | objectB.prop1 = !objectB.prop1
|
1431 | expect(invokeCount).to.equal(1)
|
1432 |
|
1433 | SimplyBind('prop1').of(objectB).set !objectB.prop1
|
1434 | expect(invokeCount).to.equal(2)
|
1435 |
|
1436 |
|
1437 |
|
1438 | SimplyBind.setOption 'liveProps', true
|
1439 | restartSandbox()
|
1440 |
|
1441 |
|
1442 |
|
1443 | test "Object properties inherited from the prototype should be made into live properties when SimplyBind.options.mutateInherited is on", ()->
|
1444 | testArray = []
|
1445 |
|
1446 | SimplyBind.setOption 'mutateInherited', true
|
1447 | Array::inherited = 'I was inherited'
|
1448 |
|
1449 | SimplyBind('inherited').of(testArray).to('prop1').of objectB
|
1450 |
|
1451 | testArray.inherited = 'inherited live prop change :)'
|
1452 | expect(objectB.prop1).to.equal 'inherited live prop change :)'
|
1453 | delete Array::inherited
|
1454 |
|
1455 |
|
1456 |
|
1457 | SimplyBind.setOption 'mutateInherited', false
|
1458 | Array::inherited2 = 'I was inherited'
|
1459 |
|
1460 | SimplyBind('inherited2').of(testArray).to('prop2').of objectB
|
1461 |
|
1462 | testArray.inherited2 = 'inherited prop shouldn\'t change'
|
1463 | expect(objectB.prop2).not.to.equal 'inherited prop shouldn\'t change'
|
1464 | delete Array::inherited2
|
1465 |
|
1466 |
|
1467 | SimplyBind.setOption 'mutateInherited', false
|
1468 | restartSandbox()
|
1469 |
|
1470 |
|
1471 |
|
1472 | test "The property's original setter (if exists) should be invoked during a live property update", ()->
|
1473 | prop7 = 'hey!'
|
1474 | invokeCountGet = 0
|
1475 | invokeCountSet = 0
|
1476 |
|
1477 | Object.defineProperty objectA, 'prop7',
|
1478 | enumerable: true
|
1479 | configurable: true
|
1480 | get: ()->
|
1481 | invokeCountGet++
|
1482 | prop7
|
1483 | set: (val)->
|
1484 | invokeCountSet++
|
1485 | prop7 = val
|
1486 |
|
1487 |
|
1488 |
|
1489 | expect(objectA.prop7).to.equal 'hey!'
|
1490 | expect(invokeCountGet).to.equal 1
|
1491 | expect(invokeCountSet).to.equal 0
|
1492 |
|
1493 | SimplyBind('prop7').of(objectA).to('prop3').of objectB
|
1494 |
|
1495 | objectA.prop7 = 'hello!'
|
1496 | expect(invokeCountGet).to.equal 2
|
1497 | expect(invokeCountSet).to.equal 1
|
1498 | expect(objectA.prop7).to.equal 'hello!'
|
1499 |
|
1500 | objectA.prop7 = 'hi!'
|
1501 | expect(invokeCountGet).to.equal 2
|
1502 | expect(invokeCountSet).to.equal 2
|
1503 | restartSandbox()
|
1504 |
|
1505 |
|
1506 |
|
1507 | test "Bindings will update dependents even if their value is falsy", ()->
|
1508 | binding = SimplyBind('prop1').of(objectA).to('prop1').of(objectB)
|
1509 |
|
1510 | binding.set ''
|
1511 | expect(objectB.prop1).to.equal ''
|
1512 |
|
1513 | binding.set 0
|
1514 | expect(objectB.prop1).to.equal 0
|
1515 |
|
1516 | binding.set false
|
1517 | expect(objectB.prop1).to.equal false
|
1518 |
|
1519 | binding.set undefined
|
1520 | expect(objectB.prop1).to.equal undefined
|
1521 |
|
1522 | binding.set null
|
1523 | expect(objectB.prop1).to.equal null
|
1524 |
|
1525 | restartSandbox()
|
1526 |
|
1527 |
|
1528 |
|
1529 | test "Update dependents of a binding even if it's unchanged when SimplyBind.options.updateEvenIfSame is on or if the binding type is Func or Event", ()->
|
1530 | invokeCount = object:0, func:0, event:0
|
1531 | objectA.prop6 = 'start'
|
1532 | objectB.prop6 = ''
|
1533 |
|
1534 | eventEmitterA.on 'alwaysEmit', ()-> invokeCount.event++
|
1535 |
|
1536 | bindings =
|
1537 | 'object': SimplyBind('prop6').of(objectA).to('prop6').of(objectB).transform (value)-> invokeCount.object++; return value
|
1538 | 'func': SimplyBind('prop7', updateEvenIfSame:true).of(objectA).to(()-> invokeCount.func++)
|
1539 | 'event': SimplyBind('prop8', updateEvenIfSame:true).of(objectA).toEvent('alwaysEmit').of(eventEmitterA)
|
1540 |
|
1541 | expect(objectB.prop6).to.equal 'start'
|
1542 | expect(invokeCount.object).to.equal 1
|
1543 |
|
1544 | objectA.prop6 = "shouldn't update"
|
1545 | expect(objectB.prop6).to.equal "shouldn't update"
|
1546 | expect(invokeCount.object).to.equal 2
|
1547 |
|
1548 | objectA.prop6 = "shouldn't update"
|
1549 | expect(objectB.prop6).to.equal "shouldn't update"
|
1550 | expect(invokeCount.object).to.equal 2
|
1551 |
|
1552 |
|
1553 | expect(invokeCount.func).to.equal 1
|
1554 |
|
1555 | objectA.prop7 = 'should update'
|
1556 | expect(invokeCount.func).to.equal 2
|
1557 |
|
1558 | objectA.prop7 = 'should update'
|
1559 | expect(invokeCount.func).to.equal 3
|
1560 |
|
1561 |
|
1562 |
|
1563 | expect(invokeCount.event).to.equal 1
|
1564 |
|
1565 | objectA.prop8 = 'should update'
|
1566 | expect(invokeCount.event).to.equal 2
|
1567 |
|
1568 | objectA.prop8 = 'should update'
|
1569 | expect(invokeCount.event).to.equal 3
|
1570 |
|
1571 |
|
1572 |
|
1573 | bindings.object.setOption 'updateEvenIfSame', true
|
1574 |
|
1575 | objectA.prop6 = 'should update'
|
1576 | expect(objectB.prop6).to.equal 'should update'
|
1577 | expect(invokeCount.object).to.equal 3
|
1578 |
|
1579 | objectA.prop6 = 'should update'
|
1580 | objectA.prop6 = 'should update'
|
1581 | objectA.prop6 = 'should update'
|
1582 | objectA.prop6 = 'should update'
|
1583 | expect(invokeCount.object).to.equal 7
|
1584 |
|
1585 |
|
1586 | bindings.object.setOption 'updateEvenIfSame', false
|
1587 |
|
1588 | objectA.prop6 = "shouldn't update"
|
1589 | expect(objectB.prop6).to.equal "shouldn't update"
|
1590 | expect(invokeCount.object).to.equal 8
|
1591 |
|
1592 | objectA.prop6 = "shouldn't update"
|
1593 | objectA.prop6 = "shouldn't update"
|
1594 | objectA.prop6 = "shouldn't update"
|
1595 | objectA.prop6 = "shouldn't update"
|
1596 | expect(invokeCount.object).to.equal 8
|
1597 | restartSandbox()
|
1598 |
|
1599 |
|
1600 |
|
1601 | test "Should update dependents even when its new value is undefined", ()->
|
1602 | binding = SimplyBind('prop1').of(objectA).to('prop1').of(objectB)
|
1603 | objectA.prop1 = 10
|
1604 | expect(objectB.prop1).to.equal 10
|
1605 |
|
1606 | objectA.prop1 = window.nonexistent
|
1607 | expect(objectB.prop1).to.be.undefined
|
1608 |
|
1609 |
|
1610 | objectA.prop1 = 20
|
1611 | expect(objectB.prop1).to.equal 20
|
1612 |
|
1613 | objectA.prop1 = window.nonexistent
|
1614 | expect(objectB.prop1).to.be.undefined
|
1615 |
|
1616 | restartSandbox()
|
1617 |
|
1618 |
|
1619 |
|
1620 | test "Dependents should update their subdependents when being updated by an independent, even if these dependents are not liveProps", ()-> if not isBrowser then @skip() else
|
1621 | objectA.prop2 = 0.8
|
1622 |
|
1623 | SimplyBind('prop2').of(objectA)
|
1624 | .to('opacity').of regA.style
|
1625 |
|
1626 | SimplyBind('opacity').of(regA.style)
|
1627 | .to('font-size').of(regA.style)
|
1628 | .transform (opacity)-> opacity * 20 + 'px'
|
1629 | .and('font-size').of(regB.style)
|
1630 | .transform (opacity)-> opacity * 40 + 'px'
|
1631 |
|
1632 |
|
1633 | expect(regA.style.opacity.toString()).to.equal '0.8'
|
1634 | expect(regA.style['font-size']).to.equal '16px'
|
1635 | expect(regB.style['font-size']).to.equal '32px'
|
1636 |
|
1637 |
|
1638 | objectA.prop2 = 0.5
|
1639 | expect(regA.style.opacity.toString()).to.equal '0.5'
|
1640 | expect(regA.style['font-size']).to.equal '10px'
|
1641 | expect(regB.style['font-size']).to.equal '20px'
|
1642 | restartSandbox()
|
1643 |
|
1644 |
|
1645 |
|
1646 | test "Placeholder indicators in a property name will be ignored if SimplyBind.options.simpleSelector is on", ()->
|
1647 | objA = 'first': 'This {{placeholder}} will change'
|
1648 | objB = 'second': 'This {{nonplaceholder}} will remain the same'
|
1649 |
|
1650 | SimplyBind('prop1').of(objectA).to('first.placeholder').of(objA)
|
1651 | objectA.prop1 = 'placeholder'
|
1652 |
|
1653 | SimplyBind('prop1').of(objectB).to('second.nonplaceholder', {'simpleSelector':true}).of(objB)
|
1654 | objectB.prop1 = 'placeholder'
|
1655 |
|
1656 | expect(objA['first']).to.equal 'This placeholder will change'
|
1657 | expect(objB['second']).to.equal 'This {{nonplaceholder}} will remain the same'
|
1658 |
|
1659 |
|
1660 |
|
1661 | test "Dependents shouldn't be updated when SimplyBind.options.updateOnBind is off even when a transform function is applied", ()->
|
1662 | dispatcher = 'value': 123
|
1663 | invokeCount =
|
1664 | 'object': 0
|
1665 | 'array': 0
|
1666 | 'function': 0
|
1667 | 'domAttr': 0
|
1668 | 'domText': 0
|
1669 | 'domInput': 0
|
1670 | 'jQueryProp': 0
|
1671 | 'event': 0
|
1672 |
|
1673 | fakeTransform = (value)-> value
|
1674 | SimplyBind.setOption 'updateOnBind', false
|
1675 | SimplyBind('prop').of(objectA).to(()-> invokeCount.object++).transform(fakeTransform)
|
1676 | SimplyBind(arrayA).to(()-> invokeCount.array++).transform(fakeTransform)
|
1677 | SimplyBind(fn = ()-> true).to(()-> invokeCount.function++).transform(fakeTransform)
|
1678 | SimplyBind('attr:prop').of(regA).to(()-> invokeCount.domAttr++).transform(fakeTransform) if isBrowser
|
1679 | SimplyBind('textContent').of(regA).to(()-> invokeCount.domText++).transform(fakeTransform) if isBrowser
|
1680 | SimplyBind('value').of(inputA).to(()-> invokeCount.domInput++).transform(fakeTransform) if isBrowser
|
1681 | SimplyBind('prop').of($regB).to(()-> invokeCount.jQueryProp++).transform(fakeTransform) if isBrowser
|
1682 | SimplyBind(0).ofEvent('someEvent').of(eventEmitterA).to(()-> invokeCount.event++).transform(fakeTransform)
|
1683 |
|
1684 |
|
1685 | SimplyBind.setOption 'updateOnBind', true
|
1686 |
|
1687 | SimplyBind('value').of(dispatcher).to('prop').of(objectA)
|
1688 | SimplyBind('value').of(dispatcher).to(arrayA)
|
1689 | SimplyBind('value').of(dispatcher).to(fn)
|
1690 | SimplyBind('value').of(dispatcher).to('attr:prop').of(regA) if isBrowser
|
1691 | SimplyBind('value').of(dispatcher).to('textContent').of(regA) if isBrowser
|
1692 | SimplyBind('value').of(dispatcher).to('value').of(inputA) if isBrowser
|
1693 | SimplyBind('value').of(dispatcher).to('prop').of($regB) if isBrowser
|
1694 | SimplyBind('value').of(dispatcher).toEvent('someEvent').of(eventEmitterA)
|
1695 |
|
1696 | expect(invokeCount.object).to.equal 1
|
1697 | expect(invokeCount.array).to.equal 0
|
1698 | expect(invokeCount.function).to.equal 3
|
1699 | expect(invokeCount.event).to.equal 1
|
1700 | if isBrowser
|
1701 | expect(invokeCount.domAttr).to.equal 1
|
1702 | expect(invokeCount.domText).to.equal 1
|
1703 | expect(invokeCount.domInput).to.equal 1
|
1704 | expect(invokeCount.jQueryProp).to.equal 1
|
1705 |
|
1706 | restartSandbox()
|
1707 |
|
1708 |
|
1709 |
|
1710 |
|
1711 |
|
1712 |
|
1713 |
|
1714 |
|
1715 |
|
1716 |
|
1717 |
|
1718 |
|
1719 |
|
1720 |
|
1721 |
|
1722 |
|
1723 | suite "Data Binding", ()->
|
1724 | suiteSetup(restartSandbox)
|
1725 | test "Live properties should be supported on all object properties", ()->
|
1726 | dispatcher =
|
1727 | 'standard': objectA
|
1728 | 'array': arrayA
|
1729 | 'function': ()->
|
1730 | 'domDiv': if isBrowser then $('<div />')[0] else {}
|
1731 | 'domInput': if isBrowser then $('<input />')[0] else {}
|
1732 | 'domNode': if isBrowser then $('<div>text</div>')[0].childNodes[0] else {}
|
1733 | receiver =
|
1734 | 'standard': null
|
1735 | 'array': null
|
1736 | 'function': null
|
1737 | 'domDiv': null
|
1738 | 'domInput': null
|
1739 | 'domNode': null
|
1740 |
|
1741 | for name,object of dispatcher
|
1742 | SimplyBind('prop').of(dispatcher[name]).to(name).of(receiver)
|
1743 | expect(receiver[name]).to.equal(undefined)
|
1744 |
|
1745 | object.prop = 100
|
1746 | expect(receiver[name]).to.equal(100)
|
1747 |
|
1748 | restartSandbox()
|
1749 |
|
1750 |
|
1751 |
|
1752 |
|
1753 |
|
1754 | test "Infinite loops should not occur in looping update chains", ()->
|
1755 | SimplyBind.setOption 'updateEvenIfSame', true
|
1756 |
|
1757 |
|
1758 | SimplyBind('prop').of(objectA)
|
1759 | .to('prop').of(objectB).bothWays()
|
1760 | .chainTo('prop').of(objectC).bothWays()
|
1761 | .chainTo('prop').of(objectA).bothWays()
|
1762 |
|
1763 | objectA.prop = 'from objectA'
|
1764 | expect(objectA.prop).to.equal 'from objectA'
|
1765 | expect(objectB.prop).to.equal 'from objectA'
|
1766 | expect(objectC.prop).to.equal 'from objectA'
|
1767 |
|
1768 | objectB.prop = 'from objectB'
|
1769 | expect(objectA.prop).to.equal 'from objectB'
|
1770 | expect(objectB.prop).to.equal 'from objectB'
|
1771 | expect(objectC.prop).to.equal 'from objectB'
|
1772 |
|
1773 |
|
1774 |
|
1775 |
|
1776 | SimplyBind(0).of(arrayA)
|
1777 | .to(0).of(arrayB).bothWays()
|
1778 | .chainTo(0).of(arrayC).bothWays()
|
1779 | .chainTo(0).of(arrayA).bothWays()
|
1780 |
|
1781 | arrayA[0] = 'from arrayA'
|
1782 | expect(arrayA[0]).to.equal 'from arrayA'
|
1783 | expect(arrayB[0]).to.equal 'from arrayA'
|
1784 | expect(arrayC[0]).to.equal 'from arrayA'
|
1785 |
|
1786 | arrayB[0] = 'from arrayB'
|
1787 | expect(arrayA[0]).to.equal 'from arrayB'
|
1788 | expect(arrayB[0]).to.equal 'from arrayB'
|
1789 | expect(arrayC[0]).to.equal 'from arrayB'
|
1790 |
|
1791 |
|
1792 |
|
1793 | if isBrowser
|
1794 |
|
1795 | SimplyBind('attr:someattr').of(regA)
|
1796 | .to('attr:someattr').of(regB).bothWays()
|
1797 | .chainTo('attr:someattr').of(regC).bothWays()
|
1798 | .chainTo('attr:someattr').of(regA).bothWays()
|
1799 |
|
1800 |
|
1801 | SimplyBind('attr:someattr').of(regA).set('from regElementA')
|
1802 | expect(regA.getAttribute 'someattr').to.equal 'from regElementA'
|
1803 | expect(regB.getAttribute 'someattr').to.equal 'from regElementA'
|
1804 | expect(regC.getAttribute 'someattr').to.equal 'from regElementA'
|
1805 |
|
1806 |
|
1807 | SimplyBind('attr:someattr').of(regB).set('from regElementB')
|
1808 | expect(regA.getAttribute 'someattr').to.equal 'from regElementB'
|
1809 | expect(regB.getAttribute 'someattr').to.equal 'from regElementB'
|
1810 | expect(regC.getAttribute 'someattr').to.equal 'from regElementB'
|
1811 |
|
1812 |
|
1813 |
|
1814 |
|
1815 | SimplyBind('textContent').of(regA)
|
1816 | .to('textContent').of(regB).bothWays()
|
1817 | .chainTo('textContent').of(regC).bothWays()
|
1818 | .chainTo('textContent').of(regA).bothWays()
|
1819 |
|
1820 | SimplyBind('textContent').of(regA).set 'from regElementA'
|
1821 | expect(regA.textContent).to.equal 'from regElementA'
|
1822 | expect(regB.textContent).to.equal 'from regElementA'
|
1823 | expect(regC.textContent).to.equal 'from regElementA'
|
1824 |
|
1825 | SimplyBind('textContent').of(regB).set 'from regElementB'
|
1826 | expect(regA.textContent).to.equal 'from regElementB'
|
1827 | expect(regB.textContent).to.equal 'from regElementB'
|
1828 | expect(regC.textContent).to.equal 'from regElementB'
|
1829 |
|
1830 |
|
1831 |
|
1832 |
|
1833 | SimplyBind('value').of(inputA)
|
1834 | .to('value').of(inputB).bothWays()
|
1835 | .chainTo('value').of(inputC).bothWays()
|
1836 | .chainTo('value').of(inputA).bothWays()
|
1837 |
|
1838 | inputA.value = 'from inputElementA'
|
1839 | inputA.emit 'change'
|
1840 | expect(inputA.value).to.equal 'from inputElementA'
|
1841 | expect(inputB.value).to.equal 'from inputElementA'
|
1842 | expect(inputC.value).to.equal 'from inputElementA'
|
1843 |
|
1844 | inputB.value = 'from inputElementB'
|
1845 | inputB.emit 'change'
|
1846 | expect(inputA.value).to.equal 'from inputElementB'
|
1847 | expect(inputB.value).to.equal 'from inputElementB'
|
1848 | expect(inputC.value).to.equal 'from inputElementB'
|
1849 |
|
1850 |
|
1851 |
|
1852 |
|
1853 | SimplyBind(0).ofEvent('eventA').of(eventEmitterA)
|
1854 | .toEvent('eventB').of(eventEmitterA).bothWays()
|
1855 |
|
1856 | SimplyBind(0).ofEvent('eventB').of(eventEmitterA)
|
1857 | .toEvent('eventC').of(eventEmitterA).bothWays()
|
1858 |
|
1859 | SimplyBind(0).ofEvent('eventC').of(eventEmitterA)
|
1860 | .toEvent('eventA').of(eventEmitterA).bothWays()
|
1861 |
|
1862 | invokeCountA = invokeCountB = invokeCountC = 0
|
1863 | eventEmitterA.on 'eventA', ()-> invokeCountA++
|
1864 | eventEmitterA.on 'eventB', ()-> invokeCountB++
|
1865 | eventEmitterA.on 'eventC', ()-> invokeCountC++
|
1866 |
|
1867 | eventEmitterA.emit 'eventA'
|
1868 | eventEmitterA.emit 'eventB'
|
1869 | eventEmitterA.emit 'eventC'
|
1870 |
|
1871 | expect(invokeCountA).to.equal 3
|
1872 | expect(invokeCountB).to.equal 3
|
1873 | expect(invokeCountC).to.equal 3
|
1874 | SimplyBind.setOption 'updateEvenIfSame', false
|
1875 | restartSandbox()
|
1876 |
|
1877 |
|
1878 |
|
1879 |
|
1880 | test "Infinite loops should not occur for colliding two-way bindings", ()->
|
1881 | SimplyBind.setOption 'updateEvenIfSame', true
|
1882 | dispatcher = 'prop': 0
|
1883 | objectA.prop1 = 0
|
1884 | objectB.prop1 = 0
|
1885 | objectC.prop1 = 0
|
1886 | SimplyBind('prop').of(dispatcher)
|
1887 | .to('prop1').of(objectA).bothWays().transform (v, ov)-> v+ov
|
1888 | .and('prop1').of(objectB).bothWays().transform (v, ov)-> v+ov
|
1889 | .and('prop1').of(objectC).bothWays().transform (v, ov)-> v+ov
|
1890 |
|
1891 | expect(dispatcher.prop).to.equal 0
|
1892 | expect(objectA.prop1).to.equal 0
|
1893 | expect(objectB.prop1).to.equal 0
|
1894 | expect(objectC.prop1).to.equal 0
|
1895 |
|
1896 | dispatcher.prop = 1
|
1897 | expect(dispatcher.prop).to.equal 1
|
1898 | expect(objectA.prop1).to.equal 1
|
1899 | expect(objectB.prop1).to.equal 1
|
1900 | expect(objectC.prop1).to.equal 1
|
1901 |
|
1902 | objectA.prop1 = 2
|
1903 | expect(dispatcher.prop).to.equal 3
|
1904 | expect(objectA.prop1).to.equal 2
|
1905 | expect(objectB.prop1).to.equal 4
|
1906 | expect(objectC.prop1).to.equal 4
|
1907 |
|
1908 | objectC.prop1 = 3
|
1909 | expect(dispatcher.prop).to.equal 6
|
1910 | expect(objectA.prop1).to.equal 8
|
1911 | expect(objectB.prop1).to.equal 10
|
1912 | expect(objectC.prop1).to.equal 3
|
1913 |
|
1914 |
|
1915 | SimplyBind.setOption 'updateEvenIfSame', false
|
1916 | restartSandbox()
|
1917 |
|
1918 |
|
1919 |
|
1920 | test "Infinite loops should occur only when a value is bound to a function and that function updates the value", ()->
|
1921 | invokeCount = 0
|
1922 |
|
1923 | SimplyBind('prop1').of(objectA)
|
1924 | .to ()-> unless invokeCount is 15
|
1925 | objectA.prop1 = ++invokeCount
|
1926 |
|
1927 | expect(invokeCount).to.equal(objectA.prop1)
|
1928 | expect(invokeCount).to.equal(15)
|
1929 | restartSandbox()
|
1930 |
|
1931 |
|
1932 |
|
1933 |
|
1934 | test "Update dependents", ()->
|
1935 | invokeCount =
|
1936 | 'object': 0
|
1937 | 'array': 0
|
1938 | 'function': 0
|
1939 | 'domAttr': 0
|
1940 | 'domText': 0
|
1941 | 'domValue': 0
|
1942 | 'domCheckboxSingle': 0
|
1943 | 'domCheckbox': 0
|
1944 | 'domRadioSingle': 0
|
1945 | 'domRadio': 0
|
1946 | 'event': 0
|
1947 | SimplyBind.setOption('updateOnBind', false)
|
1948 |
|
1949 |
|
1950 |
|
1951 | SimplyBind('prop').of(objectA).to ()-> invokeCount.object++
|
1952 | objectA.prop = true
|
1953 | expect(invokeCount.object).to.equal(1)
|
1954 |
|
1955 |
|
1956 |
|
1957 | SimplyBind(arrayA).to ()-> invokeCount.array++
|
1958 | arrayA.push(1)
|
1959 | arrayA.unshift(1)
|
1960 | arrayA.pop()
|
1961 | arrayA.shift()
|
1962 | arrayA.splice(0,1)
|
1963 | expect(invokeCount.array).to.equal(5)
|
1964 |
|
1965 |
|
1966 |
|
1967 | SimplyBind(()->true).to ()-> invokeCount.function++
|
1968 | expect(invokeCount.function).to.equal(1)
|
1969 |
|
1970 |
|
1971 | if isBrowser
|
1972 |
|
1973 | SimplyBind('attr:someattr').of(regA).to ()-> invokeCount.domAttr++
|
1974 | regA.setAttribute('someattr', 10)
|
1975 | SimplyBind('attr:someattr').of(regA).set(true)
|
1976 | expect(invokeCount.domAttr).to.equal(1)
|
1977 |
|
1978 |
|
1979 |
|
1980 | SimplyBind('textContent').of(regA).to ()-> invokeCount.domText++
|
1981 | SimplyBind('textContent').of(regA).set 'true'
|
1982 | expect(invokeCount.domText).to.equal(1)
|
1983 |
|
1984 |
|
1985 |
|
1986 | SimplyBind('value').of(inputA).to ()-> invokeCount.domValue++
|
1987 | inputA.value = 'true'
|
1988 | inputA.emit 'change'
|
1989 | expect(invokeCount.domValue).to.equal(1)
|
1990 |
|
1991 |
|
1992 |
|
1993 | SimplyBind('checked').of(checkboxA).to ()-> invokeCount.domCheckboxSingle++
|
1994 | checkboxA.checked = true
|
1995 | checkboxA.emit 'change'
|
1996 | expect(invokeCount.domCheckboxSingle).to.equal(1)
|
1997 |
|
1998 |
|
1999 |
|
2000 | SimplyBind('checked').of(checkboxFields).to ()-> invokeCount.domCheckbox++
|
2001 | checkboxB.checked = true
|
2002 | checkboxB.emit 'change'
|
2003 | expect(invokeCount.domCheckbox).to.equal(1)
|
2004 |
|
2005 |
|
2006 |
|
2007 | SimplyBind('checked').of(radioA).to ()-> invokeCount.domRadioSingle++
|
2008 | radioA.checked = true
|
2009 | radioA.emit 'change'
|
2010 | expect(invokeCount.domRadioSingle).to.equal(1)
|
2011 |
|
2012 |
|
2013 |
|
2014 | SimplyBind('checked').of(radioFields).to ()-> invokeCount.domRadio++
|
2015 | radioB.checked = true
|
2016 | radioB.emit 'change'
|
2017 | expect(invokeCount.domRadio).to.equal(1)
|
2018 |
|
2019 |
|
2020 |
|
2021 | SimplyBind.setOption('updateEvenIfSame', true)
|
2022 | SimplyBind(0).ofEvent('someEvent').of(eventEmitterA).to ()-> invokeCount.event++
|
2023 | eventEmitterA.emit 'someEvent'
|
2024 |
|
2025 |
|
2026 | expect(invokeCount.event).to.equal(1)
|
2027 |
|
2028 | SimplyBind.setOption('updateEvenIfSame', false)
|
2029 | SimplyBind.setOption('updateOnBind', true)
|
2030 | restartSandbox()
|
2031 |
|
2032 |
|
2033 |
|
2034 |
|
2035 |
|
2036 |
|
2037 |
|
2038 | test "Receive a value as a dependent", ()->
|
2039 | invokeCount =
|
2040 | 'object': 0
|
2041 | 'array': 0
|
2042 | 'function': 0
|
2043 | 'domAttr': 0
|
2044 | 'domText': 0
|
2045 | 'domValue': 0
|
2046 | 'domCheckboxSingle': 0
|
2047 | 'domCheckbox': 0
|
2048 | 'domRadio': 0
|
2049 | 'event': 0
|
2050 | SimplyBind.setOption('updateOnBind', false)
|
2051 |
|
2052 |
|
2053 |
|
2054 | SimplyBind('prop').of(objectA).to ()-> invokeCount.object++
|
2055 | SimplyBind(()-> true).to('prop').of(objectA)
|
2056 |
|
2057 | expect(objectA.prop).to.equal(true)
|
2058 | expect(invokeCount.object).to.equal(1)
|
2059 |
|
2060 |
|
2061 |
|
2062 | SimplyBind(arrayA).to ()-> invokeCount.array++
|
2063 | SimplyBind(()-> []).to('prop').of(objectA)
|
2064 |
|
2065 | expect(arrayA.length).not.to.equal(0)
|
2066 | expect(invokeCount.array).to.equal(0)
|
2067 |
|
2068 | if isBrowser
|
2069 |
|
2070 | SimplyBind('attr:someattr').of(regA).to ()-> invokeCount.domAttr++
|
2071 | SimplyBind(()-> 'true').to('attr:someattr').of(regA)
|
2072 |
|
2073 | expect(regA.getAttribute('someattr')).to.equal('true')
|
2074 | expect(invokeCount.domAttr).to.equal(1)
|
2075 |
|
2076 |
|
2077 |
|
2078 | SimplyBind('textContent').of(regA).to ()-> invokeCount.domText++
|
2079 | SimplyBind(()-> 'true').to('textContent').of(regA)
|
2080 |
|
2081 | expect(regA.textContent).to.equal('true')
|
2082 | expect(invokeCount.domText).to.equal(1)
|
2083 |
|
2084 |
|
2085 |
|
2086 | SimplyBind('value').of(inputA).to ()-> invokeCount.domValue++
|
2087 | SimplyBind(()-> 'true').to('value').of(inputA)
|
2088 |
|
2089 | expect(inputA.value).to.equal('true')
|
2090 | expect(invokeCount.domValue).to.equal(1)
|
2091 |
|
2092 |
|
2093 |
|
2094 | expect(checkboxA.checked).to.be.false
|
2095 | SimplyBind('checked').of(checkboxA).to ()-> invokeCount.domCheckboxSingle++
|
2096 | SimplyBind(()-> 'truthy').to('checked').of(checkboxA)
|
2097 |
|
2098 | expect(checkboxA.checked).to.be.true
|
2099 | expect(invokeCount.domCheckboxSingle).to.equal(1)
|
2100 |
|
2101 |
|
2102 |
|
2103 | SimplyBind('checked').of($checkboxFields).to ()-> invokeCount.domCheckbox++
|
2104 | SimplyBind(()-> ['checkboxB', 'checkboxC']).to('checked').of($checkboxFields)
|
2105 |
|
2106 | expect(checkboxA.checked).to.be.false
|
2107 | expect(checkboxB.checked).to.be.true
|
2108 | expect(checkboxC.checked).to.be.true
|
2109 | expect(invokeCount.domCheckbox).to.equal(1)
|
2110 |
|
2111 | SimplyBind(()-> 'checkboxA').to('checked').of($checkboxFields)
|
2112 |
|
2113 | expect(checkboxA.checked).to.be.true
|
2114 | expect(checkboxB.checked).to.be.false
|
2115 | expect(checkboxC.checked).to.be.false
|
2116 | expect(invokeCount.domCheckbox).to.equal(2)
|
2117 |
|
2118 |
|
2119 |
|
2120 | SimplyBind('checked').of($radioFields).to ()-> invokeCount.domRadio++
|
2121 | SimplyBind(()-> 'radioC').to('checked').of($radioFields)
|
2122 |
|
2123 | expect(radioA.checked).to.be.false
|
2124 | expect(radioB.checked).to.be.false
|
2125 | expect(radioC.checked).to.be.true
|
2126 | expect(invokeCount.domRadio).to.equal(1)
|
2127 |
|
2128 |
|
2129 |
|
2130 | SimplyBind(0).ofEvent('someEvent').of(eventEmitterA).to ()-> invokeCount.event++
|
2131 | SimplyBind(()-> true).toEvent('someEvent').of(eventEmitterA)
|
2132 |
|
2133 | expect(invokeCount.event).to.equal(1)
|
2134 |
|
2135 |
|
2136 | SimplyBind.setOption('updateOnBind', true)
|
2137 | restartSandbox()
|
2138 |
|
2139 |
|
2140 |
|
2141 |
|
2142 |
|
2143 |
|
2144 |
|
2145 |
|
2146 | suite "Placeholders", ()->
|
2147 | test "Property names with periods (.) indicate a placeholder", ()->
|
2148 | dispatcher = 'value': 'Medium'
|
2149 |
|
2150 | objectA.prop = 'The size of this shirt is {{size}}, man!'
|
2151 | if isBrowser
|
2152 | inputA.value = 'The size of this shirt is {{size}}, man!'
|
2153 | regA.textContent = 'The size of this shirt is {{size}}, man!'
|
2154 | regA.setAttribute 'someattr', 'The size of this shirt is {{size}}, man!'
|
2155 |
|
2156 | SimplyBind('value').of(dispatcher)
|
2157 | .to('prop.size').of(objectA)
|
2158 |
|
2159 | if isBrowser
|
2160 | SimplyBind('value').of(dispatcher)
|
2161 | .to('value.size').of(inputA)
|
2162 | .and('textContent.size').of(regA)
|
2163 | .and('attr:someattr.size').of(regA)
|
2164 |
|
2165 | expect(objectA.prop).to.equal 'The size of this shirt is Medium, man!'
|
2166 | if isBrowser
|
2167 | expect(inputA.value).to.equal 'The size of this shirt is Medium, man!'
|
2168 | expect(regA.textContent).to.equal 'The size of this shirt is Medium, man!'
|
2169 | expect(regA.getAttribute 'someattr').to.equal 'The size of this shirt is Medium, man!'
|
2170 | restartSandbox()
|
2171 |
|
2172 |
|
2173 |
|
2174 | test "No changes should be made to the string when trying to update a placeholder that doesn't exist", ()->
|
2175 | objectB.prop1 = 'The size of this shirt is _____, man!'
|
2176 | binding = SimplyBind('prop1').of(objectA).to('prop1.size').of(objectB)
|
2177 |
|
2178 | binding.set 'Medium'
|
2179 | expect(objectB.prop1).to.equal 'The size of this shirt is _____, man!'
|
2180 | restartSandbox()
|
2181 |
|
2182 |
|
2183 |
|
2184 | test "The updating value doesn't have to be a string", ()->
|
2185 | objectB.prop1 = 'The size of this shirt is {{size}}, man!'
|
2186 | binding = SimplyBind('prop1').of(objectA).to('prop1.size').of(objectB)
|
2187 | binding.set false
|
2188 | expect(objectB.prop1).to.equal 'The size of this shirt is false, man!'
|
2189 | binding.set null
|
2190 | expect(objectB.prop1).to.equal 'The size of this shirt is null, man!'
|
2191 | binding.set {}
|
2192 | expect(objectB.prop1).to.equal 'The size of this shirt is [object Object], man!'
|
2193 |
|
2194 | restartSandbox()
|
2195 |
|
2196 |
|
2197 |
|
2198 | test "If a property name has more than one period, only the first will be accounted for", ()->
|
2199 | objectB.prop1 = 'The size of this shirt is {{size.redundant}}, man!'
|
2200 | binding = SimplyBind('prop1').of(objectA).to('prop1.size.redundant').of(objectB)
|
2201 |
|
2202 | binding.set 'Medium'
|
2203 | expect(objectB.prop1).to.equal 'The size of this shirt is Medium, man!'
|
2204 | restartSandbox()
|
2205 |
|
2206 |
|
2207 |
|
2208 | test "Custom placeholder markers can be set", ()->
|
2209 | SimplyBind.setOption 'placeholder', ['^^', '$$']
|
2210 |
|
2211 | objectB.prop1 = 'The size of this shirt is ^^size$$, man!'
|
2212 |
|
2213 | binding = SimplyBind('prop1').of(objectA).to('prop1.size').of(objectB)
|
2214 | binding.set 'XXS'
|
2215 |
|
2216 | expect(objectB.prop1).to.equal 'The size of this shirt is XXS, man!'
|
2217 | SimplyBind.setOption 'placeholder', ['{{', '}}']
|
2218 |
|
2219 | restartSandbox()
|
2220 |
|
2221 |
|
2222 |
|
2223 | test "Target strings can have multiple placeholders", ()->
|
2224 | dispatcher = 'value': 'Large'
|
2225 |
|
2226 | objectA.prop = 'The size of this shirt is {{size}}, and {{size}} is {{size}}ly rad!'
|
2227 | if isBrowser
|
2228 | inputA.value = 'The size of this shirt is {{size}}, and {{size}} is {{size}}ly rad!'
|
2229 | regA.textContent = 'The size of this shirt is {{size}}, and {{size}} is {{size}}ly rad!'
|
2230 | regA.setAttribute 'someattr', 'The size of this shirt is {{size}}, and {{size}} is {{size}}ly rad!'
|
2231 |
|
2232 | SimplyBind('value').of(dispatcher)
|
2233 | .to('prop.size').of(objectA)
|
2234 |
|
2235 | if isBrowser
|
2236 | SimplyBind('value').of(dispatcher)
|
2237 | .to('value.size').of(inputA)
|
2238 | .and('textContent.size').of(regA)
|
2239 | .and('attr:someattr.size').of(regA)
|
2240 |
|
2241 | expect(objectA.prop).to.equal 'The size of this shirt is Large, and Large is Largely rad!'
|
2242 | if isBrowser
|
2243 | expect(inputA.value).to.equal 'The size of this shirt is Large, and Large is Largely rad!'
|
2244 | expect(regA.textContent).to.equal 'The size of this shirt is Large, and Large is Largely rad!'
|
2245 | expect(regA.getAttribute 'someattr').to.equal 'The size of this shirt is Large, and Large is Largely rad!'
|
2246 | restartSandbox()
|
2247 |
|
2248 |
|
2249 |
|
2250 |
|
2251 | test "Multiple values can be set for the same target that has multiple placeholders", ()->
|
2252 | dispatcher =
|
2253 | 'verb': 'not'
|
2254 | 'nounOne': 'small'
|
2255 | 'nounTwo': 'pretty'
|
2256 |
|
2257 | objectB.prop = 'The following text is {{verb}} {{nounOne}} and {{nounTwo}}'
|
2258 | if isBrowser
|
2259 | inputB.value = 'The following text is {{verb}} {{nounOne}} and {{nounTwo}}'
|
2260 | regB.setAttribute 'someattr', 'The following text is {{verb}} {{nounOne}} and {{nounTwo}}'
|
2261 |
|
2262 | SimplyBind('verb').of(dispatcher)
|
2263 | .to('prop.verb').of(objectB)
|
2264 |
|
2265 | if isBrowser
|
2266 | SimplyBind('verb').of(dispatcher)
|
2267 | .to('value.verb').of(inputB)
|
2268 | .and('textContent.verb').of(regB)
|
2269 | .and('attr:someattr.verb').of(regB)
|
2270 |
|
2271 |
|
2272 |
|
2273 | SimplyBind('nounOne').of(dispatcher)
|
2274 | .to('prop.nounOne').of(objectB)
|
2275 |
|
2276 | if isBrowser
|
2277 | SimplyBind('nounOne').of(dispatcher)
|
2278 | .to('value.nounOne').of(inputB)
|
2279 | .and('textContent.nounOne').of(regB)
|
2280 | .and('attr:someattr.nounOne').of(regB)
|
2281 |
|
2282 |
|
2283 |
|
2284 | SimplyBind('nounTwo').of(dispatcher)
|
2285 | .to('prop.nounTwo').of(objectB)
|
2286 |
|
2287 | if isBrowser
|
2288 | SimplyBind('nounTwo').of(dispatcher)
|
2289 | .to('value.nounTwo').of(inputB)
|
2290 | .and('textContent.nounTwo').of(regB)
|
2291 | .and('attr:someattr.nounTwo').of(regB)
|
2292 |
|
2293 |
|
2294 | values = ()-> if not isBrowser then [objectB.prop] else [objectB.prop, inputB.value, regB.textContent, regB.getAttribute 'someattr']
|
2295 | for value in values()
|
2296 | expect(value).to.equal 'The following text is not small and pretty'
|
2297 |
|
2298 |
|
2299 |
|
2300 | dispatcher.verb = 'very'
|
2301 | dispatcher.nounOne = 'big'
|
2302 | dispatcher.nounTwo = 'ugly'
|
2303 | for value in values()
|
2304 | expect(value).to.equal 'The following text is very big and ugly'
|
2305 |
|
2306 |
|
2307 | restartSandbox()
|
2308 |
|
2309 |
|
2310 |
|
2311 |
|
2312 | test "Multiple values can be set for the same target that has multiple placeholders + transforms", ()->
|
2313 | dispatcher =
|
2314 | 'verbOne': 'not'
|
2315 | 'verbTwo': 'not'
|
2316 | 'nounOne': 'small'
|
2317 | 'nounTwo': 'pretty'
|
2318 |
|
2319 | objectC.prop = 'The following text is {{verbOne}} ({{verbTwo}}) {{nounOne}} and {{nounTwo}}'
|
2320 | if isBrowser
|
2321 | inputC.value = 'The following text is {{verbOne}} ({{verbTwo}}) {{nounOne}} and {{nounTwo}}'
|
2322 | regC.textContent = 'The following text is {{verbOne}} ({{verbTwo}}) {{nounOne}} and {{nounTwo}}'
|
2323 | regC.setAttribute 'someattr', 'The following text is {{verbOne}} ({{verbTwo}}) {{nounOne}} and {{nounTwo}}'
|
2324 |
|
2325 |
|
2326 |
|
2327 | SimplyBind('verbOne').of(dispatcher)
|
2328 | .to('prop.verbOne').of(objectC).transform (value)-> value.toUpperCase()
|
2329 |
|
2330 | if isBrowser
|
2331 | SimplyBind('verbOne').of(dispatcher)
|
2332 | .to('value.verbOne').of(inputC)
|
2333 | .and('textContent.verbOne').of(regC)
|
2334 | .and('attr:someattr.verbOne').of(regC)
|
2335 | .transformAll (value)-> value.toUpperCase()
|
2336 |
|
2337 |
|
2338 |
|
2339 | SimplyBind('verbTwo').of(dispatcher)
|
2340 | .to('prop.verbTwo').of(objectC).transform (value)-> value.toLowerCase()
|
2341 |
|
2342 | if isBrowser
|
2343 | SimplyBind('verbTwo').of(dispatcher)
|
2344 | .to('value.verbTwo').of(inputC)
|
2345 | .and('textContent.verbTwo').of(regC)
|
2346 | .and('attr:someattr.verbTwo').of(regC)
|
2347 | .transformAll (value)-> value.toLowerCase()
|
2348 |
|
2349 |
|
2350 |
|
2351 | SimplyBind('nounOne').of(dispatcher)
|
2352 | .to('prop.nounOne').of(objectC).transform (value)-> value.toUpperCase()
|
2353 |
|
2354 | if isBrowser
|
2355 | SimplyBind('nounOne').of(dispatcher)
|
2356 | .to('value.nounOne').of(inputC)
|
2357 | .and('textContent.nounOne').of(regC)
|
2358 | .and('attr:someattr.nounOne').of(regC)
|
2359 | .transformAll (value)-> value.toUpperCase()
|
2360 |
|
2361 |
|
2362 |
|
2363 | SimplyBind('nounTwo').of(dispatcher)
|
2364 | .to('prop.nounTwo').of(objectC).transform (value)-> value.toUpperCase()
|
2365 |
|
2366 | if isBrowser
|
2367 | SimplyBind('nounTwo').of(dispatcher)
|
2368 | .to('value.nounTwo').of(inputC)
|
2369 | .and('textContent.nounTwo').of(regC)
|
2370 | .and('attr:someattr.nounTwo').of(regC)
|
2371 | .transformAll (value)-> value.toUpperCase()
|
2372 |
|
2373 |
|
2374 |
|
2375 | values = ()-> if not isBrowser then [objectC.prop] else [objectC.prop, inputC.value, regC.textContent, regC.getAttribute 'someattr']
|
2376 | for value in values()
|
2377 | expect(value).to.equal 'The following text is NOT (not) SMALL and PRETTY'
|
2378 |
|
2379 |
|
2380 | dispatcher.verbOne = dispatcher.verbTwo = 'Very'
|
2381 | dispatcher.nounOne = 'Big'
|
2382 | dispatcher.nounTwo = 'Ugly'
|
2383 | for value in values()
|
2384 | expect(value).to.equal 'The following text is VERY (very) BIG and UGLY'
|
2385 |
|
2386 |
|
2387 | restartSandbox()
|
2388 |
|
2389 |
|
2390 |
|
2391 |
|
2392 | 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
|
2393 | dispatcher = 'wordA':'', 'wordB':''
|
2394 |
|
2395 | expect(regD.textContent).to.equal 'The following {{wordA}} and {{wordB}} replaced correctly'
|
2396 |
|
2397 | SimplyBind('wordA').of(dispatcher)
|
2398 | .to('textContent.wordA').of(regD)
|
2399 |
|
2400 | SimplyBind('wordB').of(dispatcher)
|
2401 | .to('textContent.wordB').of(regD)
|
2402 |
|
2403 | expect(regD.textContent).to.equal 'The following and replaced correctly'
|
2404 |
|
2405 |
|
2406 | dispatcher.wordA = 'firstWord'
|
2407 | dispatcher.wordB = 'secondWord'
|
2408 | expect(regD.textContent).to.equal 'The following firstWord and secondWord replaced correctly'
|
2409 | restartSandbox()
|
2410 |
|
2411 |
|
2412 |
|
2413 |
|
2414 | test "When an object prop with placeholders is an updater, it can either update individual placeholder values or its entire value", ()->
|
2415 | window.dispatcher = 'nounA':'color', 'nounB':'car', 'adverb':'very', 'color':'red'
|
2416 | window.receiver = 'prop':'The {{nounA}} of this {{nounB}} is {{adverb}} {{color}}'
|
2417 | window.lastReceiver = 'prop':''
|
2418 |
|
2419 | SimplyBind('nounA').of(dispatcher).to('prop.nounA').of(receiver)
|
2420 | SimplyBind('nounB').of(dispatcher).to('prop.nounB').of(receiver)
|
2421 | SimplyBind('adverb').of(dispatcher).to('prop.adverb').of(receiver)
|
2422 | SimplyBind('color').of(dispatcher).to('prop.color').of(receiver)
|
2423 | expect(receiver.prop).to.equal 'The color of this car is very red'
|
2424 |
|
2425 | SimplyBind('prop.nounA').of(receiver)
|
2426 | .to('prop').of(lastReceiver)
|
2427 |
|
2428 | expect(lastReceiver.prop).to.equal 'color'
|
2429 | dispatcher.nounA = 'colour'
|
2430 | expect(lastReceiver.prop).to.equal 'colour'
|
2431 |
|
2432 |
|
2433 | SimplyBind('prop.nounB').of(receiver)
|
2434 | .to('prop').of(lastReceiver)
|
2435 |
|
2436 | expect(lastReceiver.prop).to.equal 'car'
|
2437 | dispatcher.nounB = 'airplane'
|
2438 | expect(lastReceiver.prop).to.equal 'airplane'
|
2439 |
|
2440 |
|
2441 | SimplyBind('prop').of(receiver)
|
2442 | .to('prop').of(lastReceiver)
|
2443 |
|
2444 | expect(lastReceiver.prop).to.equal 'The colour of this airplane is very red'
|
2445 |
|
2446 |
|
2447 |
|
2448 |
|
2449 | 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
|
2450 | dispatcher = 'verb':'', 'nounOne':'', 'nounTwo':''
|
2451 | objectA.prop1 = regB.textContent
|
2452 |
|
2453 | SimplyBind('verb').of(dispatcher)
|
2454 | .to('prop1.verb').of(objectA)
|
2455 | .and('textContent.verb').of(regB)
|
2456 |
|
2457 | SimplyBind('nounOne').of(dispatcher)
|
2458 | .to('prop1.nounOne').of(objectA)
|
2459 | .and('textContent.nounOne').of(regB)
|
2460 |
|
2461 | SimplyBind('nounTwo').of(dispatcher)
|
2462 | .to('prop1.nounTwo').of(objectA)
|
2463 | .and('textContent.nounTwo').of(regB)
|
2464 |
|
2465 | dispatcher.verb = 'looking'
|
2466 | dispatcher.nounOne = 'nice'
|
2467 | dispatcher.nounTwo = 'long'
|
2468 | expect(objectA.prop1).to.equal 'The following text is looking nice and long'
|
2469 | expect(objectA.prop1).to.equal(regB.textContent)
|
2470 |
|
2471 |
|
2472 | upperCaseNodes = (nodes)-> for node in nodes
|
2473 | if node.nodeType is 3
|
2474 | node.textContent = node.textContent.toUpperCase()
|
2475 | else
|
2476 | upperCaseNodes(node)
|
2477 |
|
2478 | upperCaseNodes(regB.childNodes)
|
2479 | objectA.prop1 = 'modified'
|
2480 |
|
2481 | dispatcher.verb = 'not looking'
|
2482 | dispatcher.nounOne = 'ugly'
|
2483 | dispatcher.nounTwo = 'short'
|
2484 | expect(objectA.prop1).to.equal 'The following text is not looking ugly and short'
|
2485 | expect(objectA.prop1).to.equal(regB.textContent)
|
2486 |
|
2487 |
|
2488 | $regBH1.append '<span> and some other attribute</span>'
|
2489 | dispatcher.verb = 'looking'
|
2490 | dispatcher.nounOne = 'nice'
|
2491 | dispatcher.nounTwo = 'long'
|
2492 | expect(objectA.prop1).to.equal 'The following text is looking nice and long'
|
2493 | expect(regB.textContent).to.equal 'The following text is looking nice and long and some other attribute'
|
2494 |
|
2495 |
|
2496 |
|
2497 |
|
2498 |
|
2499 |
|
2500 |
|
2501 |
|
2502 |
|
2503 |
|
2504 |
|
2505 | suite "Binding-Type Specific", ()->
|
2506 | suite "DOMValue", ()->
|
2507 | suiteSetup ()-> if not isBrowser then @skip()
|
2508 | test "Dispatching an event isn't necessary when updating the value for a binding's .set()/.update() method", ()->
|
2509 | binding = SimplyBind('value').of(inputA).to('prop2').of(objectA)
|
2510 | binding.set 'changed from binding instance'
|
2511 | expect(objectA.prop2).to.equal 'changed from binding instance'
|
2512 |
|
2513 |
|
2514 | test "Bindings to a DOM element's .value property will only create a DOMValue binding if it is an input/select/textarea field", ()->
|
2515 | expect(SimplyBind('value').of(inputA)._.type).to.equal 'DOMValue'
|
2516 | expect(SimplyBind('value').of(regA)._.type).to.equal 'ObjectProp'
|
2517 | expect(SimplyBind('value').of(document)._.type).to.equal 'ObjectProp'
|
2518 |
|
2519 |
|
2520 | test "When passing an element collection to .of() in the form of a jQuery object/NodeList/HTMLCollection, only the first element will be used", ()->
|
2521 | SimplyBind('prop1').of(objectA)
|
2522 | .to('value').of $inputA
|
2523 | .and('value').of document.querySelectorAll('#input2')
|
2524 |
|
2525 | objectA.prop1 = 'updated'
|
2526 | expect($inputA.val()).to.equal 'updated'
|
2527 | expect($inputB.val()).to.equal 'updated'
|
2528 | restartSandbox()
|
2529 |
|
2530 |
|
2531 | test "A change event will be dispatched upon value update if SimplyBind.options.dispatchEvents is on", ()->
|
2532 | invokeCountSelect = 0
|
2533 | invokeCountRadio = 0
|
2534 | SimplyBind.setOption 'dispatchEvents', true
|
2535 | SimplyBind.setOption 'updateEvenIfSame', true
|
2536 |
|
2537 |
|
2538 | SimplyBind('prop4').of(objectA)
|
2539 | .to('value').of $select
|
2540 | .and('checked').of $radioFields
|
2541 |
|
2542 | $select[0].on 'change', ()-> invokeCountSelect++
|
2543 | $radioFields.each ()-> @on 'change', ()-> invokeCountRadio++
|
2544 | objectA.prop4 = 'radioA'
|
2545 | objectA.prop4 = 'radioB'
|
2546 | objectA.prop4 = 'radioB'
|
2547 |
|
2548 |
|
2549 | expect(invokeCountSelect).to.equal 3
|
2550 | expect(invokeCountRadio).to.equal 3
|
2551 |
|
2552 | SimplyBind.setOption 'dispatchEvents', false
|
2553 | SimplyBind.setOption 'updateEvenIfSame', false
|
2554 | restartSandbox()
|
2555 |
|
2556 |
|
2557 |
|
2558 |
|
2559 |
|
2560 | suite "DOMCheckbox", ()->
|
2561 | suiteSetup ()-> if not isBrowser then @skip()
|
2562 | test "When attempting to bind a property other than 'checked' of a checkbox element list, only the first element will be used", ()->
|
2563 | origLog = console.warn
|
2564 | console.warn = chai.spy()
|
2565 | SimplyBind('prop1').of(objectA)
|
2566 | .to('newProp').of checkboxFields
|
2567 | .and('newProp').of [].reverse.call($checkboxFields)
|
2568 |
|
2569 | objectA.prop1 = 'updated'
|
2570 | expect(checkboxA.newProp).to.equal 'updated'
|
2571 | expect(checkboxC.newProp).to.equal 'updated'
|
2572 | expect(checkboxB.newProp).not.to.be.defined
|
2573 | expect(console.warn).to.have.been.called()
|
2574 |
|
2575 | console.warn = origLog
|
2576 | restartSandbox()
|
2577 |
|
2578 |
|
2579 | test "A change event will be dispatched upon value update if SimplyBind.options.dispatchEvents is on", ()->
|
2580 | invokeCount = 0
|
2581 | SimplyBind.setOption 'dispatchEvents', true
|
2582 | SimplyBind.setOption 'updateEvenIfSame', true
|
2583 |
|
2584 |
|
2585 | SimplyBind('prop4').of(objectA)
|
2586 | .to('checked').of checkboxFields
|
2587 |
|
2588 | $checkboxFields.each ()-> @on 'change', ()-> invokeCount++
|
2589 | objectA.prop4 = 'checkboxA'
|
2590 | objectA.prop4 = 'checkboxB'
|
2591 | objectA.prop4 = 'checkboxB'
|
2592 |
|
2593 | expect(invokeCount).to.equal 3
|
2594 |
|
2595 | SimplyBind.setOption 'dispatchEvents', false
|
2596 | SimplyBind.setOption 'updateEvenIfSame', false
|
2597 | restartSandbox()
|
2598 |
|
2599 |
|
2600 | test "Initial checked values should be noted during initial binding", ()->
|
2601 | expect(checkboxA.checked).to.be.false
|
2602 | expect(checkboxB.checked).to.be.false
|
2603 | expect(checkboxC.checked).to.be.false
|
2604 |
|
2605 | checkboxB.checked = true
|
2606 | checkboxC.checked = true
|
2607 |
|
2608 | SimplyBind('checked').of(checkboxFields).to (checkedFields)->
|
2609 | expect(checkedFields).to.be.instanceOf Array
|
2610 | expect(checkedFields.length).to.equal 2
|
2611 | expect(checkedFields[0]).to.equal 'checkboxB'
|
2612 | expect(checkedFields[1]).to.equal 'checkboxC'
|
2613 |
|
2614 |
|
2615 |
|
2616 |
|
2617 |
|
2618 | suite "DOMRadio", ()->
|
2619 | suiteSetup ()-> if not isBrowser then @skip()
|
2620 | test "When attempting to bind a property other than 'checked' of a radio element list, only the first element will be used", ()->
|
2621 | origLog = console.warn
|
2622 | console.warn = chai.spy()
|
2623 | SimplyBind('prop1').of(objectA)
|
2624 | .to('newProp').of radioFields
|
2625 | .and('newProp').of [].reverse.call($radioFields)
|
2626 |
|
2627 | objectA.prop1 = 'updated'
|
2628 | expect(radioA.newProp).to.equal 'updated'
|
2629 | expect(radioC.newProp).to.equal 'updated'
|
2630 | expect(radioB.newProp).not.to.be.defined
|
2631 | expect(console.warn).to.have.been.called()
|
2632 |
|
2633 | console.warn = origLog
|
2634 | restartSandbox()
|
2635 |
|
2636 |
|
2637 | test "A change event will be dispatched upon value update if SimplyBind.options.dispatchEvents is on", ()->
|
2638 | invokeCount = 0
|
2639 | SimplyBind.setOption 'dispatchEvents', true
|
2640 | SimplyBind.setOption 'updateEvenIfSame', true
|
2641 |
|
2642 |
|
2643 | SimplyBind('prop4').of(objectA)
|
2644 | .to('checked').of radioFields
|
2645 |
|
2646 | $radioFields.each ()-> @on 'change', ()-> invokeCount++
|
2647 | objectA.prop4 = 'radioA'
|
2648 | objectA.prop4 = 'radioB'
|
2649 | objectA.prop4 = 'radioB'
|
2650 |
|
2651 | expect(invokeCount).to.equal 3
|
2652 |
|
2653 | SimplyBind.setOption 'dispatchEvents', false
|
2654 | SimplyBind.setOption 'updateEvenIfSame', false
|
2655 | restartSandbox()
|
2656 |
|
2657 |
|
2658 | test "Initial checked values should be noted during initial binding", ()->
|
2659 | expect(radioA.checked).to.be.false
|
2660 | expect(radioB.checked).to.be.false
|
2661 | expect(radioC.checked).to.be.false
|
2662 |
|
2663 | radioB.checked = true
|
2664 |
|
2665 | SimplyBind('checked').of(radioFields).to (selectedRadio)->
|
2666 | expect(selectedRadio).to.equal 'radioB'
|
2667 |
|
2668 |
|
2669 |
|
2670 |
|
2671 | suite "DOMAttr", ()->
|
2672 | suiteSetup ()-> if not isBrowser then @skip()
|
2673 | test "Requires the 'attr:' prefix in the property name in order to bind the attribute values and not the property values", ()->
|
2674 | nonPrefix = SimplyBind('first').of(regA).to('first').of(regB)
|
2675 | withPrefix = SimplyBind('attr:second').of(regA).to('attr:second').of(regB)
|
2676 |
|
2677 | nonPrefix.set 'someValue'
|
2678 | expect(regA.first).to.equal 'someValue'
|
2679 | expect(regB.first).to.equal 'someValue'
|
2680 | expect(regA.getAttribute 'first').not.to.equal 'someValue'
|
2681 | expect(regB.getAttribute 'first').not.to.equal 'someValue'
|
2682 |
|
2683 | withPrefix.set 'someValue'
|
2684 | expect(regA.second).not.to.equal 'someValue'
|
2685 | expect(regB.second).not.to.equal 'someValue'
|
2686 | expect(regA.getAttribute 'second').to.equal 'someValue'
|
2687 | expect(regB.getAttribute 'second').to.equal 'someValue'
|
2688 | restartSandbox()
|
2689 |
|
2690 |
|
2691 |
|
2692 | suite "Function", ()->
|
2693 | test "Will be invoked on bind and have its return value used as the value that the dependents will receive", ()->
|
2694 | SimplyBind ()-> 123
|
2695 | .to('prop').of(objectA)
|
2696 |
|
2697 | expect(objectA.prop).to.equal 123
|
2698 |
|
2699 |
|
2700 | 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", ()->
|
2701 | invokeCount = 0
|
2702 | objectA.prop1 = 'some value'
|
2703 | SimplyBind('prop1').of(objectA)
|
2704 | .to (newValue, prevValue)->
|
2705 | switch invokeCount
|
2706 | when 0
|
2707 | expect(newValue).to.equal 'some value'
|
2708 | expect(prevValue).to.be.undefined
|
2709 | when 1
|
2710 | expect(newValue).to.equal 'new value'
|
2711 | expect(prevValue).to.equal 'some value'
|
2712 | when 2
|
2713 | expect(newValue).to.equal 'newer value'
|
2714 | expect(prevValue).to.equal 'new value'
|
2715 | invokeCount++
|
2716 |
|
2717 | objectA.prop1 = 'new value'
|
2718 | objectA.prop1 = 'newer value'
|
2719 |
|
2720 | restartSandbox()
|
2721 |
|
2722 |
|
2723 | test "Will be invoked when is the first part of an argument regardless of whether or not SimplyBind.options.updateOnBind is on", ()->
|
2724 | invokeCount = 0
|
2725 | expect(SimplyBind.options.updateOnBind).to.be.true
|
2726 |
|
2727 | SimplyBind ()-> invokeCount++; 123
|
2728 | .to('prop').of(objectA)
|
2729 | expect(invokeCount).to.equal 1
|
2730 |
|
2731 |
|
2732 | SimplyBind.setOption 'updateOnBind', false
|
2733 |
|
2734 | SimplyBind ()-> invokeCount++; 456
|
2735 | .to('prop').of(objectA)
|
2736 | expect(invokeCount).to.equal 2
|
2737 |
|
2738 | SimplyBind.setOption 'updateOnBind', true
|
2739 |
|
2740 |
|
2741 |
|
2742 |
|
2743 | suite "Array", ()->
|
2744 | test "can bind an array to anything and update dependents even when calling the .push, .pop, .shift, .unshift, .splice, .reverse, and .sort methods", ()->
|
2745 | sampleArray = [1,2,3,4,5,6,7,8,9,10]
|
2746 | mutations = 0
|
2747 | SimplyBind(sampleArray).to('prop4').of(objectB).and ()-> mutations++
|
2748 |
|
2749 | expect(objectB.prop4.length).to.equal 10
|
2750 | expect(mutations).to.equal 1
|
2751 | sampleArray.push 11
|
2752 | expect(objectB.prop4.length).to.equal 11
|
2753 | expect(mutations).to.equal 2
|
2754 | sampleArray.shift()
|
2755 | sampleArray.shift()
|
2756 | expect(objectB.prop4.length).to.equal 9
|
2757 | expect(mutations).to.equal 4
|
2758 | sampleArray.unshift 2
|
2759 | sampleArray.unshift 1
|
2760 | expect(objectB.prop4.length).to.equal 11
|
2761 | expect(mutations).to.equal 6
|
2762 | sampleArray.pop()
|
2763 | sampleArray.pop()
|
2764 | expect(objectB.prop4.length).to.equal 9
|
2765 | expect(mutations).to.equal 8
|
2766 | sampleArray.splice 0, 5
|
2767 | expect(objectB.prop4.length).to.equal 4
|
2768 | expect(mutations).to.equal 9
|
2769 | sampleArray.reverse()
|
2770 | expect(objectB.prop4.length).to.equal 4
|
2771 | expect(mutations).to.equal 10
|
2772 | sampleArray.sort()
|
2773 | expect(objectB.prop4.length).to.equal 4
|
2774 | expect(mutations).to.equal 11
|
2775 | sampleArray.sort ()->
|
2776 | 1
|
2777 | expect(objectB.prop4.length).to.equal 4
|
2778 | expect(mutations).to.equal 12
|
2779 |
|
2780 |
|
2781 |
|
2782 | test "it's impossible to replace the array object in an array binding.", ()->
|
2783 | sampleArray = [1,2,3,4,5,6,7,8,9,10]
|
2784 | mutations = 0
|
2785 | SimplyBind(sampleArray).to('prop4').of(objectB).and ()-> mutations++
|
2786 |
|
2787 | expect(objectB.prop4.length).to.equal 10
|
2788 | expect(mutations).to.equal 1
|
2789 | SimplyBind(sampleArray).set [1,2,3,4,5,6,7,8,9,10]
|
2790 |
|
2791 | SimplyBind(sampleArray).set [1,2,3,4,5,6,7,8,9,10]
|
2792 | SimplyBind(sampleArray).set [1,2,3,4,5,6,7,8,9,10]
|
2793 | sampleArray.push 11
|
2794 | expect(objectB.prop4.length).to.equal 11
|
2795 | expect(mutations).to.equal 2
|
2796 | sampleArray.shift()
|
2797 | sampleArray.shift()
|
2798 | expect(objectB.prop4.length).to.equal 9
|
2799 | expect(mutations).to.equal 4
|
2800 | sampleArray.unshift 2
|
2801 | sampleArray.unshift 1
|
2802 | expect(objectB.prop4.length).to.equal 11
|
2803 | expect(mutations).to.equal 6
|
2804 | sampleArray.pop()
|
2805 | sampleArray.pop()
|
2806 | expect(objectB.prop4.length).to.equal 9
|
2807 | expect(mutations).to.equal 8
|
2808 | sampleArray.splice 0, 5
|
2809 | expect(objectB.prop4.length).to.equal 4
|
2810 | expect(mutations).to.equal 9
|
2811 |
|
2812 |
|
2813 |
|
2814 | test "will update dependents when its children get modified if specified via the trackArrayChildren option", ()->
|
2815 | sampleArray = [1,2,3,4,5,6,7,8,9,10]
|
2816 | sampleArray2 = [1,2,3,4,5,6,7,8,9,10]
|
2817 | mutations = 0
|
2818 | SimplyBind(sampleArray).to('prop5').of(objectA).and ()-> mutations++
|
2819 |
|
2820 | expect(objectA.prop5).to.equal sampleArray
|
2821 | sampleArray[0] = 100
|
2822 | sampleArray[1] = 200
|
2823 | sampleArray[2] = 300
|
2824 | expect(objectA.prop5[0]).to.equal 100
|
2825 | expect(objectA.prop5[1]).to.equal 200
|
2826 | expect(objectA.prop5[2]).to.equal 300
|
2827 | expect(mutations).to.equal 1
|
2828 | mutations = 0
|
2829 | SimplyBind(sampleArray2, 'trackArrayChildren': true).to('prop6').of(objectA).and ()-> mutations++
|
2830 |
|
2831 | expect(objectA.prop6).to.equal sampleArray2
|
2832 | sampleArray2[0] = 100
|
2833 | sampleArray2[1] = 200
|
2834 | sampleArray2[2] = 300
|
2835 | expect(objectA.prop6[0]).to.equal 100
|
2836 | expect(objectA.prop6[1]).to.equal 200
|
2837 | expect(objectA.prop6[2]).to.equal 300
|
2838 | expect(mutations).to.equal 4
|
2839 |
|
2840 |
|
2841 |
|
2842 | test "will update dependents even when there is a sepearate binding on a reference of the same array", ()->
|
2843 | sampleArrayA = [1,2,3,4,5,6,7,8,9,10]
|
2844 | sampleArrayB = sampleArrayA
|
2845 | mutationsA = 0
|
2846 | mutationsB = 0
|
2847 | SimplyBind(sampleArrayA)
|
2848 | .to('prop6').of(objectA)
|
2849 | .and ()-> mutationsA++
|
2850 |
|
2851 | SimplyBind(sampleArrayB)
|
2852 | .to('prop6').of(objectB)
|
2853 | .and ()-> mutationsB++
|
2854 |
|
2855 | expect(sampleArrayA).to.equal sampleArrayB
|
2856 | expect(mutationsA).to.equal 1
|
2857 | expect(mutationsB).to.equal 1
|
2858 | sampleArrayA.push 11
|
2859 | sampleArrayA.push 12
|
2860 | sampleArrayB.push 13
|
2861 | sampleArrayB.push 14
|
2862 | expect(mutationsA).to.equal 5
|
2863 | expect(mutationsB).to.equal 5
|
2864 |
|
2865 |
|
2866 | test "Will update Func dependents with a clone to prevent possible infinite loops and for comparison", ()->
|
2867 | receivedValues = 'current':null, 'prev':null
|
2868 | middleMan = 'value':null
|
2869 | prevCurrent = null
|
2870 |
|
2871 | SimplyBind(arrayA).to (currentArray, prevArray)->
|
2872 | receivedValues.current = currentArray
|
2873 | receivedValues.prev = prevArray
|
2874 |
|
2875 | prevCurrent = receivedValues.current
|
2876 | expect(receivedValues.current).to.be.instanceOf(Array)
|
2877 | expect(receivedValues.current.length).to.equal(arrayA.length)
|
2878 | expect(receivedValues.current).not.to.equal(arrayA)
|
2879 | expect(receivedValues.prev).to.be.undefined
|
2880 |
|
2881 | arrayA.push(10)
|
2882 | expect(receivedValues.current.length).to.equal(arrayA.length)
|
2883 | expect(receivedValues.current).not.to.equal(arrayA)
|
2884 | expect(receivedValues.current).not.to.equal(prevCurrent)
|
2885 | expect(receivedValues.prev).to.equal(prevCurrent)
|
2886 |
|
2887 |
|
2888 | SimplyBind(arrayB)
|
2889 | .to('value').of(middleMan).transform (array)-> array.length
|
2890 | .chainTo (currentArray, prevArray)->
|
2891 | receivedValues.current = currentArray
|
2892 | receivedValues.prev = prevArray
|
2893 |
|
2894 | arrayB.unshift(-1)
|
2895 | expect(middleMan.value).to.equal(arrayB.length)
|
2896 | expect(receivedValues.current).to.equal(arrayB.length)
|
2897 |
|
2898 | restartSandbox()
|
2899 |
|
2900 |
|
2901 |
|
2902 |
|
2903 |
|
2904 | suite "Event", ()->
|
2905 | test "The specified selector will indicate which argument index of the event emitter callback should be saved to the binding", ()->
|
2906 | emptyObj = {}
|
2907 | sampleObject = 'holder': emptyObj
|
2908 |
|
2909 | SimplyBind(0).ofEvent('focus').of(eventEmitterA)
|
2910 | .to('holder').of sampleObject
|
2911 |
|
2912 | expect(sampleObject.holder).to.equal emptyObj
|
2913 |
|
2914 | eventEmitterA.emit 'focus', eventEmitterA
|
2915 | if isBrowser
|
2916 | expect(sampleObject.holder.target).to.equal eventEmitterA
|
2917 | else
|
2918 | expect(sampleObject.holder).to.equal eventEmitterA
|
2919 |
|
2920 | restartSandbox()
|
2921 |
|
2922 |
|
2923 |
|
2924 |
|
2925 | test "Custom events will behave exactly like regular events", ()->
|
2926 | emptyObj = {}
|
2927 | sampleObject = 'holder': emptyObj
|
2928 |
|
2929 | SimplyBind(0).ofEvent('somethingCustom').of(eventEmitterA).to('holder').of sampleObject
|
2930 | expect(sampleObject.holder).to.equal emptyObj
|
2931 |
|
2932 | eventEmitterA.emit 'somethingCustom', eventEmitterA
|
2933 | if isBrowser
|
2934 | expect(sampleObject.holder.target).to.equal eventEmitterA
|
2935 | else
|
2936 | expect(sampleObject.holder).to.equal eventEmitterA
|
2937 |
|
2938 |
|
2939 |
|
2940 |
|
2941 | test "Custom listener/emitter methods can be used", ()->
|
2942 | emitCount = 0
|
2943 | receiveCount = 0
|
2944 | $eventEmitterA.customListener 'click', ()-> emitCount++
|
2945 |
|
2946 | SimplyBind('prop2').of(objectA)
|
2947 | .toEvent('click', 'customEmitter', 'customListener').of($eventEmitterA).bothWays ()-> ++receiveCount
|
2948 | expect(emitCount).to.equal 1
|
2949 | expect(receiveCount).to.equal 0
|
2950 |
|
2951 | objectA.prop2 = 'whatever'
|
2952 | expect(emitCount).to.equal 2
|
2953 |
|
2954 | $eventEmitterA.customEmitter 'click'
|
2955 | expect(receiveCount).to.equal 1
|
2956 | expect(objectA.prop2).to.equal 1
|
2957 | expect(emitCount).to.equal 3
|
2958 |
|
2959 | objectA.prop2 = 'whatever again'
|
2960 | expect(emitCount).to.equal 4
|
2961 |
|
2962 | $eventEmitterA.customEmitter 'click'
|
2963 | expect(receiveCount).to.equal 2
|
2964 | expect(objectA.prop2).to.equal 2
|
2965 | restartSandbox()
|
2966 |
|
2967 |
|
2968 |
|
2969 |
|
2970 | test "jQuery listener/emitter methods can be used", ()-> if not isBrowser then @skip() else
|
2971 | emitCount = 0
|
2972 | receiveCount = 0
|
2973 | $eventEmitterA.on 'click', ()-> emitCount++
|
2974 |
|
2975 | SimplyBind('prop2').of(objectA)
|
2976 | .toEvent('click', 'trigger', 'on').of($eventEmitterA).bothWays ()-> ++receiveCount
|
2977 | expect(emitCount).to.equal 1
|
2978 | expect(receiveCount).to.equal 0
|
2979 |
|
2980 | objectA.prop2 = 'whatever'
|
2981 | expect(emitCount).to.equal 2
|
2982 |
|
2983 | $eventEmitterA.trigger 'click'
|
2984 | expect(receiveCount).to.equal 1
|
2985 | expect(objectA.prop2).to.equal 1
|
2986 | expect(emitCount).to.equal 3
|
2987 |
|
2988 | objectA.prop2 = 'whatever again'
|
2989 | expect(emitCount).to.equal 4
|
2990 |
|
2991 | $eventEmitterA.trigger 'click'
|
2992 | expect(receiveCount).to.equal 2
|
2993 | expect(objectA.prop2).to.equal 2
|
2994 | restartSandbox()
|
2995 |
|
2996 |
|
2997 |
|
2998 |
|
2999 | test "Default listener/emitter methods will be used if custom listener/emitter methods don't exist on the target object", ()->
|
3000 | emitCount = 0
|
3001 | receiveCount = 0
|
3002 | $eventEmitterA.customListener 'click', ()-> emitCount++
|
3003 |
|
3004 | SimplyBind('prop2').of(objectA)
|
3005 | .toEvent('click', 'nonexistentDispatcher', 'nonexistentListener').of($eventEmitterA).bothWays ()-> ++receiveCount
|
3006 | expect(emitCount).to.equal 1
|
3007 | expect(receiveCount).to.equal 0
|
3008 |
|
3009 | objectA.prop2 = 'whatever'
|
3010 | expect(emitCount).to.equal 2
|
3011 |
|
3012 | $eventEmitterA.customEmitter 'click'
|
3013 | expect(receiveCount).to.equal 1
|
3014 | expect(objectA.prop2).to.equal 1
|
3015 | expect(emitCount).to.equal 3
|
3016 |
|
3017 | objectA.prop2 = 'whatever again'
|
3018 | expect(emitCount).to.equal 4
|
3019 |
|
3020 | $eventEmitterA.customEmitter 'click'
|
3021 | expect(receiveCount).to.equal 2
|
3022 | expect(objectA.prop2).to.equal 2
|
3023 | restartSandbox()
|
3024 |
|
3025 |
|
3026 |
|
3027 |
|
3028 |
|
3029 |
|
3030 |
|
3031 |
|
3032 |
|
3033 | suite "Create bindings to/from multiple objects using the 'multi:' descriptor as a shortcut", ()->
|
3034 |
|
3035 | suite "Basic Bindings", ()->
|
3036 | test "Binding single prop to multiple ObjectProps", ()->
|
3037 | dispatcher = 'prop':'value1'
|
3038 | objectA.prop1 = objectB.prop1 = objectC.prop1 = null
|
3039 |
|
3040 | SimplyBind('prop').of(dispatcher)
|
3041 | .to('multi:prop1').of([objectA, objectB, objectC])
|
3042 |
|
3043 | expect(objectA.prop1).to.equal 'value1'
|
3044 | expect(objectB.prop1).to.equal 'value1'
|
3045 | expect(objectC.prop1).to.equal 'value1'
|
3046 |
|
3047 | dispatcher.prop = 'value2'
|
3048 | expect(objectA.prop1).to.equal 'value2'
|
3049 | expect(objectB.prop1).to.equal 'value2'
|
3050 | expect(objectC.prop1).to.equal 'value2'
|
3051 |
|
3052 | restartSandbox()
|
3053 |
|
3054 |
|
3055 |
|
3056 | test "Binding multiple ObjectProp to a single prop", ()->
|
3057 | receiver = 'prop':null
|
3058 | objectA.prop1 = objectB.prop1 = objectC.prop1 = 'value1'
|
3059 |
|
3060 | SimplyBind('multi:prop1').of([objectA, objectB, objectC])
|
3061 | .to('prop').of(receiver)
|
3062 |
|
3063 | expect(receiver.prop).to.equal 'value1'
|
3064 | expect(objectA.prop1).to.equal 'value1'
|
3065 | expect(objectB.prop1).to.equal 'value1'
|
3066 | expect(objectC.prop1).to.equal 'value1'
|
3067 |
|
3068 | objectA.prop1 = 'value2'
|
3069 | expect(receiver.prop).to.equal 'value2'
|
3070 | expect(objectA.prop1).to.equal 'value2'
|
3071 | expect(objectB.prop1).to.equal 'value1'
|
3072 | expect(objectC.prop1).to.equal 'value1'
|
3073 |
|
3074 | objectB.prop1 = 'value3'
|
3075 | expect(receiver.prop).to.equal 'value3'
|
3076 | expect(objectA.prop1).to.equal 'value2'
|
3077 | expect(objectB.prop1).to.equal 'value3'
|
3078 | expect(objectC.prop1).to.equal 'value1'
|
3079 |
|
3080 | objectC.prop1 = 'value4'
|
3081 | expect(receiver.prop).to.equal 'value4'
|
3082 | expect(objectA.prop1).to.equal 'value2'
|
3083 | expect(objectB.prop1).to.equal 'value3'
|
3084 | expect(objectC.prop1).to.equal 'value4'
|
3085 |
|
3086 | restartSandbox()
|
3087 |
|
3088 |
|
3089 |
|
3090 | test "Binding multiple ObjectProp to a single prop both ways", ()->
|
3091 | receiverDispatcher = 'prop':'valueP1'
|
3092 | objectA.prop1 = objectB.prop1 = objectC.prop1 = 'value1'
|
3093 |
|
3094 | SimplyBind('multi:prop1').of([objectA, objectB, objectC])
|
3095 | .to('prop').of(receiverDispatcher).bothWays()
|
3096 |
|
3097 | expect(receiverDispatcher.prop).to.equal 'value1'
|
3098 | expect(objectA.prop1).to.equal 'value1'
|
3099 | expect(objectB.prop1).to.equal 'value1'
|
3100 | expect(objectC.prop1).to.equal 'value1'
|
3101 |
|
3102 | objectA.prop1 = 'value2'
|
3103 | expect(receiverDispatcher.prop).to.equal 'value2'
|
3104 | expect(objectA.prop1).to.equal 'value2'
|
3105 | expect(objectB.prop1).to.equal 'value2'
|
3106 | expect(objectC.prop1).to.equal 'value2'
|
3107 |
|
3108 | objectB.prop1 = 'value3'
|
3109 | receiverDispatcher.prop = 'valueP3'
|
3110 | expect(receiverDispatcher.prop).to.equal 'valueP3'
|
3111 | expect(objectA.prop1).to.equal 'valueP3'
|
3112 | expect(objectB.prop1).to.equal 'valueP3'
|
3113 | expect(objectC.prop1).to.equal 'valueP3'
|
3114 |
|
3115 | objectC.prop1 = 'value4'
|
3116 | expect(receiverDispatcher.prop).to.equal 'value4'
|
3117 | expect(objectA.prop1).to.equal 'value4'
|
3118 | expect(objectB.prop1).to.equal 'value4'
|
3119 | expect(objectC.prop1).to.equal 'value4'
|
3120 |
|
3121 | restartSandbox()
|
3122 |
|
3123 |
|
3124 |
|
3125 |
|
3126 |
|
3127 | suite "Transform Bindings", ()->
|
3128 | test "Binding single prop to multiple ObjectProps + transform", ()->
|
3129 | dispatcher = 'prop':'value1'
|
3130 | objectA.prop1 = objectB.prop1 = objectC.prop1 = null
|
3131 |
|
3132 | SimplyBind('prop').of(dispatcher)
|
3133 | .to('multi:prop1').of([objectA, objectB, objectC])
|
3134 | .transform (value)-> value.toUpperCase()
|
3135 |
|
3136 | dispatcher.prop = 'value2'
|
3137 | expect(dispatcher.prop).to.equal 'value2'
|
3138 | expect(objectA.prop1).to.equal 'VALUE2'
|
3139 | expect(objectB.prop1).to.equal 'VALUE2'
|
3140 | expect(objectC.prop1).to.equal 'VALUE2'
|
3141 |
|
3142 | restartSandbox()
|
3143 |
|
3144 |
|
3145 |
|
3146 | test "Binding multiple ObjectProp to a single prop + transform", ()->
|
3147 | receiver = 'prop':null
|
3148 | objectA.prop1 = objectB.prop1 = objectC.prop1 = 'value1'
|
3149 |
|
3150 | SimplyBind('multi:prop1').of([objectA, objectB, objectC])
|
3151 | .to('prop').of(receiver)
|
3152 | .transform (value)-> value.toUpperCase()
|
3153 |
|
3154 |
|
3155 | objectA.prop1 = 'value2'
|
3156 | expect(receiver.prop).to.equal 'VALUE2'
|
3157 | expect(objectA.prop1).to.equal 'value2'
|
3158 | expect(objectB.prop1).to.equal 'value1'
|
3159 | expect(objectC.prop1).to.equal 'value1'
|
3160 |
|
3161 | objectB.prop1 = 'value3'
|
3162 | expect(receiver.prop).to.equal 'VALUE3'
|
3163 | expect(objectA.prop1).to.equal 'value2'
|
3164 | expect(objectB.prop1).to.equal 'value3'
|
3165 | expect(objectC.prop1).to.equal 'value1'
|
3166 |
|
3167 | objectC.prop1 = 'value4'
|
3168 | expect(receiver.prop).to.equal 'VALUE4'
|
3169 | expect(objectA.prop1).to.equal 'value2'
|
3170 | expect(objectB.prop1).to.equal 'value3'
|
3171 | expect(objectC.prop1).to.equal 'value4'
|
3172 |
|
3173 | restartSandbox()
|
3174 |
|
3175 |
|
3176 |
|
3177 | test "Binding multiple ObjectProp to a single prop both ways + transform", ()->
|
3178 | receiverDispatcher = 'prop':'valueP1'
|
3179 | objectA.prop1 = objectB.prop1 = objectC.prop1 = 'value1'
|
3180 |
|
3181 | SimplyBind('multi:prop1').of([objectA, objectB, objectC])
|
3182 | .to('prop').of(receiverDispatcher).bothWays()
|
3183 | .transform (value)-> value.toUpperCase()
|
3184 |
|
3185 | objectA.prop1 = 'value2'
|
3186 | expect(receiverDispatcher.prop).to.equal 'VALUE2'
|
3187 | expect(objectA.prop1).to.equal 'value2'
|
3188 | expect(objectB.prop1).to.equal 'VALUE2'
|
3189 | expect(objectC.prop1).to.equal 'VALUE2'
|
3190 |
|
3191 | objectB.prop1 = 'value3'
|
3192 | receiverDispatcher.prop = 'valueP3'
|
3193 | expect(receiverDispatcher.prop).to.equal 'valueP3'
|
3194 | expect(objectA.prop1).to.equal 'VALUEP3'
|
3195 | expect(objectB.prop1).to.equal 'VALUEP3'
|
3196 | expect(objectC.prop1).to.equal 'VALUEP3'
|
3197 |
|
3198 | objectC.prop1 = 'value4'
|
3199 | expect(receiverDispatcher.prop).to.equal 'VALUE4'
|
3200 | expect(objectA.prop1).to.equal 'VALUE4'
|
3201 | expect(objectB.prop1).to.equal 'VALUE4'
|
3202 | expect(objectC.prop1).to.equal 'value4'
|
3203 |
|
3204 | restartSandbox()
|
3205 |
|
3206 |
|
3207 |
|
3208 |
|
3209 |
|
3210 | suite "Condition Bindings", ()->
|
3211 | test "Binding single prop to multiple ObjectProps + condition", ()->
|
3212 | dispatcher = 'prop':'value1'
|
3213 | objectA.prop1 = objectB.prop1 = objectC.prop1 = null
|
3214 | allowUpdate = false
|
3215 |
|
3216 | SimplyBind('prop', {updateOnBind:false}).of(dispatcher)
|
3217 | .to('multi:prop1').of([objectA, objectB, objectC])
|
3218 | .condition ()-> allowUpdate
|
3219 |
|
3220 | expect(objectA.prop1).to.equal null
|
3221 | expect(objectB.prop1).to.equal null
|
3222 | expect(objectC.prop1).to.equal null
|
3223 |
|
3224 | dispatcher.prop = 'value2'
|
3225 | expect(dispatcher.prop).to.equal 'value2'
|
3226 | expect(objectA.prop1).to.equal null
|
3227 | expect(objectB.prop1).to.equal null
|
3228 | expect(objectC.prop1).to.equal null
|
3229 |
|
3230 | allowUpdate = true
|
3231 | dispatcher.prop = 'value3'
|
3232 | expect(dispatcher.prop).to.equal 'value3'
|
3233 | expect(objectA.prop1).to.equal 'value3'
|
3234 | expect(objectB.prop1).to.equal 'value3'
|
3235 | expect(objectC.prop1).to.equal 'value3'
|
3236 |
|
3237 | restartSandbox()
|
3238 |
|
3239 |
|
3240 |
|
3241 | test "Binding multiple ObjectProp to a single prop + condition", ()->
|
3242 | receiver = 'prop':null
|
3243 | objectA.prop1 = objectB.prop1 = objectC.prop1 = 'value1'
|
3244 | allowUpdate = false
|
3245 |
|
3246 | SimplyBind('multi:prop1', {updateOnBind:false}).of([objectA, objectB, objectC])
|
3247 | .to('prop').of(receiver)
|
3248 | .condition ()-> allowUpdate
|
3249 |
|
3250 | expect(receiver.prop).to.equal null
|
3251 | expect(objectA.prop1).to.equal 'value1'
|
3252 | expect(objectB.prop1).to.equal 'value1'
|
3253 | expect(objectC.prop1).to.equal 'value1'
|
3254 |
|
3255 | objectA.prop1 = 'value2'
|
3256 | expect(receiver.prop).to.equal null
|
3257 | expect(objectA.prop1).to.equal 'value2'
|
3258 | expect(objectB.prop1).to.equal 'value1'
|
3259 | expect(objectC.prop1).to.equal 'value1'
|
3260 |
|
3261 | allowUpdate = true
|
3262 | objectB.prop1 = 'value3'
|
3263 | expect(receiver.prop).to.equal 'value3'
|
3264 | expect(objectA.prop1).to.equal 'value2'
|
3265 | expect(objectB.prop1).to.equal 'value3'
|
3266 | expect(objectC.prop1).to.equal 'value1'
|
3267 |
|
3268 | restartSandbox()
|
3269 |
|
3270 |
|
3271 |
|
3272 | test "Binding multiple ObjectProp to a single prop both ways + condition", ()->
|
3273 | receiverDispatcher = 'prop':'valueP1'
|
3274 | objectA.prop1 = objectB.prop1 = objectC.prop1 = 'value1'
|
3275 | allowUpdate = false
|
3276 |
|
3277 | SimplyBind('multi:prop1', {updateOnBind:false}).of([objectA, objectB, objectC])
|
3278 | .to('prop').of(receiverDispatcher).bothWays()
|
3279 | .condition ()-> allowUpdate
|
3280 |
|
3281 | expect(receiverDispatcher.prop).to.equal 'valueP1'
|
3282 | expect(objectA.prop1).to.equal 'value1'
|
3283 | expect(objectB.prop1).to.equal 'value1'
|
3284 | expect(objectC.prop1).to.equal 'value1'
|
3285 |
|
3286 | objectA.prop1 = 'value2'
|
3287 | expect(receiverDispatcher.prop).to.equal 'valueP1'
|
3288 | expect(objectA.prop1).to.equal 'value2'
|
3289 | expect(objectB.prop1).to.equal 'value1'
|
3290 | expect(objectC.prop1).to.equal 'value1'
|
3291 |
|
3292 | allowUpdate = true
|
3293 | receiverDispatcher.prop = 'valueP3'
|
3294 | expect(receiverDispatcher.prop).to.equal 'valueP3'
|
3295 | expect(objectA.prop1).to.equal 'valueP3'
|
3296 | expect(objectB.prop1).to.equal 'valueP3'
|
3297 | expect(objectC.prop1).to.equal 'valueP3'
|
3298 |
|
3299 | objectC.prop1 = 'value4'
|
3300 | expect(receiverDispatcher.prop).to.equal 'value4'
|
3301 | expect(objectA.prop1).to.equal 'value4'
|
3302 | expect(objectB.prop1).to.equal 'value4'
|
3303 | expect(objectC.prop1).to.equal 'value4'
|
3304 |
|
3305 | restartSandbox()
|
3306 |
|
3307 |
|
3308 |
|
3309 |
|
3310 | suite "Miscellenious", ()->
|
3311 | test "Binding single prop to multiple ObjectProps' placeholders", ()->
|
3312 | dispatcher = 'prop':'word'
|
3313 | objectA.prop1 = objectB.prop1 = objectC.prop1 = 'some {{noun}} here'
|
3314 |
|
3315 | SimplyBind('prop').of(dispatcher)
|
3316 | .to('multi:prop1.noun').of([objectA, objectB, objectC])
|
3317 |
|
3318 | expect(objectA.prop1).to.equal 'some word here'
|
3319 | expect(objectB.prop1).to.equal 'some word here'
|
3320 | expect(objectC.prop1).to.equal 'some word here'
|
3321 |
|
3322 | dispatcher.prop = 'letter'
|
3323 | expect(objectA.prop1).to.equal 'some letter here'
|
3324 | expect(objectB.prop1).to.equal 'some letter here'
|
3325 | expect(objectC.prop1).to.equal 'some letter here'
|
3326 |
|
3327 | restartSandbox()
|
3328 |
|
3329 |
|
3330 |
|
3331 | test "Fetching the value using the .get() method of a multi binding should yield an array of all the values", ()->
|
3332 | objectA.prop1 = 'A'
|
3333 | objectB.prop1 = 'B'
|
3334 | objectC.prop1 = 'C'
|
3335 |
|
3336 | binding = SimplyBind('multi:prop1').of([objectA, objectB, objectC])
|
3337 | values = binding.get()
|
3338 |
|
3339 | expect(objectA.prop1).to.equal 'A'
|
3340 | expect(objectB.prop1).to.equal 'B'
|
3341 | expect(objectC.prop1).to.equal 'C'
|
3342 | expect(values).to.be.instanceOf Array
|
3343 | expect(values[0]).to.equal 'A'
|
3344 | expect(values[1]).to.equal 'B'
|
3345 | expect(values[2]).to.equal 'C'
|
3346 |
|
3347 | restartSandbox()
|
3348 |
|
3349 |
|
3350 |
|
3351 | test "Fetching the value using the .get() method of a multi binding w/ placeholders should yield an the value of the first binding only", ()->
|
3352 | dispatcher = 'prop':'word'
|
3353 | objectA.prop1 = objectB.prop1 = objectC.prop1 = 'some {{noun}} here'
|
3354 |
|
3355 | SimplyBind('prop').of(dispatcher)
|
3356 | .to('multi:prop1.noun').of([objectA, objectB, objectC])
|
3357 |
|
3358 | binding = SimplyBind('multi:prop1.noun').of([objectA, objectB, objectC])
|
3359 | value = binding.get()
|
3360 |
|
3361 | expect(objectA.prop1).to.equal 'some word here'
|
3362 | expect(objectB.prop1).to.equal 'some word here'
|
3363 | expect(objectC.prop1).to.equal 'some word here'
|
3364 | expect(value).to.equal 'word'
|
3365 |
|
3366 | restartSandbox()
|
3367 |
|
3368 |
|
3369 |
|
3370 | test "Binding single prop to multiple ObjectProps with a self transform should be applied to all bindings", ()->
|
3371 | dispatcher = 'prop':'value1'
|
3372 | objectA.prop1 = objectB.prop1 = objectC.prop1 = null
|
3373 |
|
3374 | SimplyBind('prop').of(dispatcher)
|
3375 | .to('multi:prop1').of([objectA, objectB, objectC])
|
3376 |
|
3377 | SimplyBind('multi:prop1.noun').of([objectA, objectB, objectC])
|
3378 | .transformSelf (value)-> value.toUpperCase()
|
3379 |
|
3380 | expect(objectA.prop1).to.equal 'VALUE1'
|
3381 | expect(objectB.prop1).to.equal 'VALUE1'
|
3382 | expect(objectC.prop1).to.equal 'VALUE1'
|
3383 |
|
3384 | dispatcher.prop = 'value2'
|
3385 | expect(objectA.prop1).to.equal 'VALUE2'
|
3386 | expect(objectB.prop1).to.equal 'VALUE2'
|
3387 | expect(objectC.prop1).to.equal 'VALUE2'
|
3388 |
|
3389 | restartSandbox()
|
3390 |
|
3391 |
|
3392 |
|
3393 | test ".throttle() on a multi binding will throttle the dep update frequency to once in a given timeframe", (done)->
|
3394 | invokeCount = 0
|
3395 | lastValue = null
|
3396 | objectA.prop1 = objectB.prop1 = objectC.prop1 = 'same'
|
3397 |
|
3398 | SimplyBind('multi:prop1').of([objectA, objectB, objectC])
|
3399 | .to (v)-> lastValue=v; invokeCount++
|
3400 | .throttle(15)
|
3401 |
|
3402 | expect(invokeCount).to.equal(3)
|
3403 | expect(lastValue).to.equal 'same'
|
3404 |
|
3405 | objectA.prop1 = 'another1'
|
3406 | objectA.prop1 = 'another2'
|
3407 | objectA.prop1 = 'another3'
|
3408 | objectA.prop1 = 'another4'
|
3409 | expect(invokeCount).to.equal(4)
|
3410 | expect(lastValue).to.equal('another1')
|
3411 |
|
3412 | objectB.prop1 = 'another5'
|
3413 | expect(lastValue).to.equal('another5')
|
3414 | expect(invokeCount).to.equal(5)
|
3415 |
|
3416 | objectC.prop1 = 'another6'
|
3417 | expect(lastValue).to.equal('another6')
|
3418 | expect(invokeCount).to.equal(6)
|
3419 |
|
3420 | objectC.prop1 = 'another7'
|
3421 | expect(invokeCount).to.equal(6)
|
3422 | expect(lastValue).to.equal('another6')
|
3423 |
|
3424 | setTimeout ()->
|
3425 | expect(invokeCount).to.equal(8)
|
3426 | expect(lastValue).to.equal('another7')
|
3427 | done()
|
3428 | restartSandbox()
|
3429 | , 25
|
3430 |
|
3431 |
|
3432 |
|
3433 | test "Using the 'multi:' descriptor on a empty DOM list should throw an error", ()->
|
3434 | expect ()-> SimplyBind('multi:prop').of($('nonexistent'))
|
3435 | .to.throw()
|
3436 |
|
3437 | expect ()-> SimplyBind('multi:prop').of(document.querySelectorAll('nonexistent'))
|
3438 | .to.throw()
|
3439 |
|
3440 | expect ()-> SimplyBind('multi:prop').of([])
|
3441 | .to.throw()
|
3442 |
|
3443 | restartSandbox()
|
3444 |
|
3445 |
|
3446 |
|
3447 | suite "Unbinding", ()->
|
3448 | test "Binding single prop to multiple ObjectProps and then calling .unBind() should unbind all", ()->
|
3449 | dispatcher = 'prop':'value1'
|
3450 | objectA.prop1 = objectB.prop1 = objectC.prop1 = null
|
3451 |
|
3452 | binding = SimplyBind('prop').of(dispatcher)
|
3453 | .to('multi:prop1').of([objectA, objectB, objectC])
|
3454 |
|
3455 | expect(objectA.prop1).to.equal 'value1'
|
3456 | expect(objectB.prop1).to.equal 'value1'
|
3457 | expect(objectC.prop1).to.equal 'value1'
|
3458 |
|
3459 | binding.unBind()
|
3460 |
|
3461 | dispatcher.prop = 'value2'
|
3462 | expect(objectA.prop1).to.equal 'value1'
|
3463 | expect(objectB.prop1).to.equal 'value1'
|
3464 | expect(objectC.prop1).to.equal 'value1'
|
3465 |
|
3466 | restartSandbox()
|
3467 |
|
3468 |
|
3469 |
|
3470 | test "Binding multiple ObjectProps to a single prop and then calling .unBind() should unbind all props from that single prop", ()->
|
3471 | receiver = 'prop':null
|
3472 | objectA.prop1 = objectB.prop1 = objectC.prop1 = 'value1'
|
3473 |
|
3474 | binding = SimplyBind('multi:prop1').of([objectA, objectB, objectC])
|
3475 | .to('prop').of(receiver)
|
3476 |
|
3477 | expect(receiver.prop).to.equal 'value1'
|
3478 | expect(objectA.prop1).to.equal 'value1'
|
3479 | expect(objectB.prop1).to.equal 'value1'
|
3480 | expect(objectC.prop1).to.equal 'value1'
|
3481 |
|
3482 | binding.unBind()
|
3483 |
|
3484 | objectA.prop1 = 'value2'
|
3485 | expect(receiver.prop).to.equal 'value1'
|
3486 | expect(objectA.prop1).to.equal 'value2'
|
3487 | expect(objectB.prop1).to.equal 'value1'
|
3488 | expect(objectC.prop1).to.equal 'value1'
|
3489 |
|
3490 | objectB.prop1 = 'value3'
|
3491 | expect(receiver.prop).to.equal 'value1'
|
3492 | expect(objectA.prop1).to.equal 'value2'
|
3493 | expect(objectB.prop1).to.equal 'value3'
|
3494 | expect(objectC.prop1).to.equal 'value1'
|
3495 |
|
3496 | objectC.prop1 = 'value4'
|
3497 | expect(receiver.prop).to.equal 'value1'
|
3498 | expect(objectA.prop1).to.equal 'value2'
|
3499 | expect(objectB.prop1).to.equal 'value3'
|
3500 | expect(objectC.prop1).to.equal 'value4'
|
3501 |
|
3502 | restartSandbox()
|
3503 |
|
3504 |
|
3505 |
|
3506 |
|
3507 |
|
3508 |
|
3509 |
|
3510 |
|
3511 |
|
3512 |
|
3513 |
|
3514 |
|
3515 | suite "Stage 3 methods", ()->
|
3516 | suite ".and()", ()->
|
3517 | suiteSetup(restartSandbox)
|
3518 | test "Behaves just like .to() which allows to bind a value to multiple targets", ()->
|
3519 | SimplyBind('prop1').of(objectA)
|
3520 | .to('prop1').of(objectB)
|
3521 | .and('prop2').of(objectB)
|
3522 | .and('prop3').of(objectB)
|
3523 | .and('prop4').of(objectB)
|
3524 |
|
3525 | objectA.prop1 = 'all at once'
|
3526 | expect(objectB.prop1).to.equal 'all at once'
|
3527 | expect(objectB.prop2).to.equal 'all at once'
|
3528 | expect(objectB.prop3).to.equal 'all at once'
|
3529 | expect(objectB.prop4).to.equal 'all at once'
|
3530 | restartSandbox()
|
3531 |
|
3532 |
|
3533 |
|
3534 |
|
3535 |
|
3536 |
|
3537 |
|
3538 |
|
3539 |
|
3540 |
|
3541 |
|
3542 |
|
3543 |
|
3544 |
|
3545 |
|
3546 |
|
3547 |
|
3548 |
|
3549 | suite ".chainTo()/.pipe()", ()->
|
3550 | suiteSetup(restartSandbox)
|
3551 |
|
3552 | test "Helps create complex chainings", ()->
|
3553 | outerstate =
|
3554 | 'first': null
|
3555 | 'second': null
|
3556 | 'third': null
|
3557 |
|
3558 | objectA.prop1 = 'Hello World'
|
3559 | SimplyBind('prop1').of(objectA)
|
3560 | .to('prop1').of(objectB)
|
3561 | .and('prop2').of(objectA)
|
3562 | .and (val)-> outerstate.first = val
|
3563 | .transformAll (val)-> val.toUpperCase()
|
3564 |
|
3565 | .chainTo('prop2').of(objectB)
|
3566 | .and('prop3').of(objectA)
|
3567 | .transform (val)-> val.toLowerCase()
|
3568 |
|
3569 | .chainTo('prop3').of(objectB)
|
3570 | .and('prop4').of(objectA)
|
3571 | .and (val)-> outerstate.second = val
|
3572 |
|
3573 | .chainTo('prop4').of(objectB)
|
3574 | .and (val)-> outerstate.third = val.slice(0, 5)
|
3575 |
|
3576 |
|
3577 |
|
3578 | expect(outerstate.first).to.equal 'HELLO WORLD'
|
3579 | expect(outerstate.second).to.equal 'hello world'
|
3580 | expect(outerstate.third).to.equal 'hello'
|
3581 | expect(objectA.prop1).to.equal 'Hello World'
|
3582 | expect(objectA.prop2).to.equal 'HELLO WORLD'
|
3583 | expect(objectB.prop1).to.equal 'HELLO WORLD'
|
3584 | expect(objectB.prop2).to.equal 'HELLO WORLD'
|
3585 | expect(objectA.prop3).to.equal 'hello world'
|
3586 | expect(objectB.prop3).to.equal 'hello world'
|
3587 | expect(objectA.prop4).to.equal 'hello world'
|
3588 | expect(objectB.prop4).to.equal 'hello world'
|
3589 | restartSandbox()
|
3590 |
|
3591 |
|
3592 |
|
3593 |
|
3594 |
|
3595 |
|
3596 |
|
3597 |
|
3598 |
|
3599 |
|
3600 |
|
3601 |
|
3602 |
|
3603 |
|
3604 |
|
3605 |
|
3606 |
|
3607 |
|
3608 |
|
3609 |
|
3610 | suite ".transform()", ()->
|
3611 | suiteSetup(restartSandbox)
|
3612 | test "Will apply a transformation to the value before updating the dependent", ()->
|
3613 | dispatcher = 'value': 'current'
|
3614 | transformFn = (newValue, currentValue)-> newValue+'+'+currentValue
|
3615 |
|
3616 | objectA.prop = ''
|
3617 | if isBrowser
|
3618 | inputA.value = ''
|
3619 | regA.textContent = ''
|
3620 | regA.setAttribute 'someattr', ''
|
3621 |
|
3622 | SimplyBind('value').of(dispatcher)
|
3623 | .to('prop').of(objectA).transform(transformFn)
|
3624 |
|
3625 | if isBrowser
|
3626 | SimplyBind('value').of(dispatcher)
|
3627 | .to('value').of(inputA).transform(transformFn)
|
3628 | .and('textContent').of(regA).transform(transformFn)
|
3629 | .and('attr:someattr').of(regA).transform(transformFn)
|
3630 |
|
3631 |
|
3632 | values = ()-> if not isBrowser then [objectA.prop] else [objectA.prop, inputA.value, regA.textContent, regA.getAttribute 'someattr']
|
3633 | for value in values()
|
3634 | expect(value).to.equal 'current+current'
|
3635 |
|
3636 |
|
3637 | dispatcher.value = 'new'
|
3638 | for value in values()
|
3639 | expect(value).to.equal 'new+current+current'
|
3640 |
|
3641 |
|
3642 | dispatcher.value = 'new'
|
3643 | for value in values()
|
3644 | expect(value).to.equal 'new+current+current'
|
3645 |
|
3646 |
|
3647 | dispatcher.value = 'newer'
|
3648 | for value in values()
|
3649 | expect(value).to.equal 'newer+new+current+current'
|
3650 |
|
3651 | restartSandbox()
|
3652 |
|
3653 |
|
3654 |
|
3655 |
|
3656 | test "Will apply transformations to event bindings", ()-> if not isBrowser then @skip() else
|
3657 | resultHolder = 'event':null
|
3658 |
|
3659 | SimplyBind(0).ofEvent('someEvent').of(eventEmitterA)
|
3660 | .to('event').of(resultHolder)
|
3661 | .transform (event)-> event.type
|
3662 |
|
3663 | eventEmitterA.emit 'someEvent'
|
3664 | expect(resultHolder.event).to.equal 'someEvent'
|
3665 |
|
3666 |
|
3667 |
|
3668 |
|
3669 | test "Will cause a re-update only to the last proxied dependent", ()->
|
3670 | invokeCount =
|
3671 | 'A':0
|
3672 | 'B':0
|
3673 | 'C':0
|
3674 |
|
3675 | SimplyBind('prop1').of(objectA)
|
3676 | .to ()-> invokeCount.A++
|
3677 | .transform (v)-> v
|
3678 | .and ()-> invokeCount.B++
|
3679 | .transform (v)-> v
|
3680 | .and ()-> invokeCount.C++
|
3681 | .transform (v)-> v
|
3682 |
|
3683 | expect(invokeCount.A).to.equal 2
|
3684 | expect(invokeCount.B).to.equal 2
|
3685 | expect(invokeCount.C).to.equal 2
|
3686 |
|
3687 | objectA.prop1 = !objectA.prop1
|
3688 | expect(invokeCount.A).to.equal 3
|
3689 | expect(invokeCount.B).to.equal 3
|
3690 | expect(invokeCount.C).to.equal 3
|
3691 |
|
3692 |
|
3693 |
|
3694 | test "Promise transforms can be used instead of regular return values if SimplyBind.options.promiseTransforms is on", (done)->
|
3695 | objectA.prop2 = 'current'
|
3696 |
|
3697 | SimplyBind('prop1', {'updateOnBind':false}).of(objectA)
|
3698 | .to (result)-> expect(result.then).not.to.be.undefined
|
3699 | .transform ()-> new Promise ()->
|
3700 |
|
3701 | SimplyBind('prop2', {'promiseTransforms':true}).of(objectA)
|
3702 | .to('prop2').of(objectB)
|
3703 | .transform (newValue, currentValue)-> new Promise (resolve)-> resolve(newValue+'+'+currentValue)
|
3704 |
|
3705 | setTimeout ()->
|
3706 | expect(objectB.prop2).to.equal 'current+current'
|
3707 | objectA.prop2 = 'new'
|
3708 |
|
3709 | setTimeout ()->
|
3710 | expect(objectB.prop2).to.equal 'new+current+current'
|
3711 | restartSandbox()
|
3712 | done()
|
3713 | , 0
|
3714 | , 0
|
3715 |
|
3716 |
|
3717 |
|
3718 |
|
3719 | test "A transform will only be used for the last declared dependent", ()->
|
3720 | dispatcher = 'value': 'test'
|
3721 | objectA.prop1 = ''
|
3722 | objectB.prop1 = ''
|
3723 |
|
3724 | SimplyBind('value').of(dispatcher)
|
3725 | .to('prop1').of(objectA)
|
3726 | .and('prop1').of(objectB)
|
3727 | .transform (value)-> value.toUpperCase()
|
3728 |
|
3729 | expect(objectA.prop1).to.equal 'test'
|
3730 | expect(objectB.prop1).to.equal 'TEST'
|
3731 |
|
3732 | restartSandbox()
|
3733 |
|
3734 |
|
3735 |
|
3736 | test "A transform will be used both ways when .bothWays() is called after the .transform declaration", ()->
|
3737 | dispatcher = 'value': 'test'
|
3738 | objectA.prop = ''
|
3739 |
|
3740 | SimplyBind('value').of(dispatcher)
|
3741 | .to('prop').of(objectA)
|
3742 | .transform (value)-> value.toUpperCase()
|
3743 | .bothWays()
|
3744 |
|
3745 | expect(dispatcher.value).to.equal 'test'
|
3746 | expect(objectA.prop).to.equal 'TEST'
|
3747 |
|
3748 | dispatcher.value = 'from dispatcher'
|
3749 | expect(dispatcher.value).to.equal 'from dispatcher'
|
3750 | expect(objectA.prop).to.equal 'FROM DISPATCHER'
|
3751 |
|
3752 | objectA.prop = 'from objectA'
|
3753 | expect(dispatcher.value).to.equal 'FROM OBJECTA'
|
3754 | expect(objectA.prop).to.equal 'from objectA'
|
3755 |
|
3756 | restartSandbox()
|
3757 |
|
3758 |
|
3759 |
|
3760 | test "A transform will be used both ways when .bothWays() is called before the .transform declaration", ()->
|
3761 | dispatcher = 'value': 'test'
|
3762 | objectA.prop = ''
|
3763 |
|
3764 | SimplyBind('value').of(dispatcher)
|
3765 | .to('prop').of(objectA).bothWays()
|
3766 | .transform (value)-> value.toUpperCase()
|
3767 |
|
3768 | expect(dispatcher.value).to.equal 'test'
|
3769 | expect(objectA.prop).to.equal 'TEST'
|
3770 |
|
3771 | dispatcher.value = 'from dispatcher'
|
3772 | expect(dispatcher.value).to.equal 'from dispatcher'
|
3773 | expect(objectA.prop).to.equal 'FROM DISPATCHER'
|
3774 |
|
3775 | objectA.prop = 'from objectA'
|
3776 | expect(dispatcher.value).to.equal 'FROM OBJECTA'
|
3777 | expect(objectA.prop).to.equal 'from objectA'
|
3778 |
|
3779 | restartSandbox()
|
3780 |
|
3781 |
|
3782 |
|
3783 | test "A different transform will be used backwards if a function is passed to .bothWays() as the first argument", ()->
|
3784 | dispatcher = 'value': 'test'
|
3785 | objectA.prop = ''
|
3786 |
|
3787 | SimplyBind('value').of(dispatcher)
|
3788 | .to('prop').of(objectA)
|
3789 | .transform (value)-> value.toUpperCase()
|
3790 | .bothWays (value)-> value.toLowerCase()
|
3791 |
|
3792 | expect(dispatcher.value).to.equal 'test'
|
3793 | expect(objectA.prop).to.equal 'TEST'
|
3794 |
|
3795 | dispatcher.value = 'From Dispatcher'
|
3796 | expect(dispatcher.value).to.equal 'From Dispatcher'
|
3797 | expect(objectA.prop).to.equal 'FROM DISPATCHER'
|
3798 |
|
3799 | objectA.prop = 'From ObjectA'
|
3800 | expect(dispatcher.value).to.equal 'from objecta'
|
3801 | expect(objectA.prop).to.equal 'From ObjectA'
|
3802 |
|
3803 |
|
3804 |
|
3805 | test "No transform will be used backwards if a false value is passed to .bothWays() as the first argument", ()->
|
3806 | dispatcher = 'value': 'test'
|
3807 | objectA.prop = ''
|
3808 |
|
3809 | SimplyBind('value').of(dispatcher)
|
3810 | .to('prop').of(objectA)
|
3811 | .transform (value)-> value.toUpperCase()
|
3812 | .bothWays(false)
|
3813 |
|
3814 | expect(dispatcher.value).to.equal 'test'
|
3815 | expect(objectA.prop).to.equal 'TEST'
|
3816 |
|
3817 | dispatcher.value = 'From Dispatcher'
|
3818 | expect(dispatcher.value).to.equal 'From Dispatcher'
|
3819 | expect(objectA.prop).to.equal 'FROM DISPATCHER'
|
3820 |
|
3821 | objectA.prop = 'From ObjectA'
|
3822 | expect(dispatcher.value).to.equal 'From ObjectA'
|
3823 | expect(objectA.prop).to.equal 'From ObjectA'
|
3824 |
|
3825 |
|
3826 |
|
3827 |
|
3828 |
|
3829 |
|
3830 |
|
3831 |
|
3832 |
|
3833 |
|
3834 |
|
3835 |
|
3836 |
|
3837 |
|
3838 |
|
3839 |
|
3840 |
|
3841 |
|
3842 | suite ".transformAll()", ()->
|
3843 | suiteSetup(restartSandbox)
|
3844 | test "Behaves the same way as .transform() does, except it applies the transform to all of the declared dependents", ()->
|
3845 | dispatcher = 'value': 'current'
|
3846 |
|
3847 | objectA.prop = objectC.prop = objectC.prop = ''
|
3848 |
|
3849 | SimplyBind('value').of(dispatcher)
|
3850 | .to('prop').of(objectA)
|
3851 | .and('prop').of(objectB)
|
3852 | .and('prop').of(objectC)
|
3853 | .transformAll (newValue, currentValue)-> newValue+'+'+currentValue
|
3854 |
|
3855 | for value in [objectA.prop, objectB.prop, objectC.prop]
|
3856 | expect(value).to.equal 'current+current'
|
3857 |
|
3858 |
|
3859 | dispatcher.value = 'new'
|
3860 | for value in [objectA.prop, objectB.prop, objectC.prop]
|
3861 | expect(value).to.equal 'new+current+current'
|
3862 |
|
3863 |
|
3864 | dispatcher.value = 'new'
|
3865 | for value in [objectA.prop, objectB.prop, objectC.prop]
|
3866 | expect(value).to.equal 'new+current+current'
|
3867 |
|
3868 |
|
3869 | dispatcher.value = 'newer'
|
3870 | for value in [objectA.prop, objectB.prop, objectC.prop]
|
3871 | expect(value).to.equal 'newer+new+current+current'
|
3872 |
|
3873 | restartSandbox()
|
3874 |
|
3875 |
|
3876 |
|
3877 | test "Will not allow additional binding dependents after being called", ()->
|
3878 | expect(()->
|
3879 | SimplyBind('prop1').of(objectA)
|
3880 | .to('prop1').of(objectB)
|
3881 | .and('prop2').of(objectB)
|
3882 | .and('prop3').of(objectB)
|
3883 | .transformAll (value)-> value
|
3884 | .and('prop4').of(objectB)
|
3885 | ).to.throw()
|
3886 |
|
3887 |
|
3888 |
|
3889 |
|
3890 |
|
3891 |
|
3892 |
|
3893 |
|
3894 |
|
3895 |
|
3896 |
|
3897 |
|
3898 |
|
3899 |
|
3900 |
|
3901 |
|
3902 |
|
3903 |
|
3904 |
|
3905 | suite ".transformSelf()", ()->
|
3906 | suiteSetup(restartSandbox)
|
3907 |
|
3908 | suite "Will transform any received value", ()->
|
3909 | test "ObjectProp", ()->
|
3910 | object = 'prop':'value'
|
3911 |
|
3912 | SimplyBind('prop').of(object)
|
3913 | .transformSelf (value)-> value.toUpperCase()
|
3914 |
|
3915 | expect(object.prop).to.equal 'VALUE'
|
3916 |
|
3917 | object.prop = 'anotherValue'
|
3918 | expect(object.prop).to.equal 'ANOTHERVALUE'
|
3919 |
|
3920 |
|
3921 |
|
3922 | test "DOMText", ()-> if not isBrowser then @skip() else
|
3923 | regA.textContent = 'value'
|
3924 |
|
3925 | SimplyBind('textContent').of(regA)
|
3926 | .transformSelf (value)-> value.toUpperCase()
|
3927 |
|
3928 | expect(regA.textContent).to.equal 'VALUE'
|
3929 |
|
3930 | SimplyBind('textContent').of(regA).update('anotherValue')
|
3931 | expect(regA.textContent).to.equal 'ANOTHERVALUE'
|
3932 |
|
3933 | restartSandbox()
|
3934 |
|
3935 |
|
3936 |
|
3937 | test "DOMAttr", ()-> if not isBrowser then @skip() else
|
3938 | regA.setAttribute 'someattr', 'value'
|
3939 |
|
3940 | SimplyBind('attr:someattr').of(regA)
|
3941 | .transformSelf (value)-> value.toUpperCase()
|
3942 |
|
3943 | expect(regA.getAttribute 'someattr').to.equal 'VALUE'
|
3944 |
|
3945 | SimplyBind('attr:someattr').of(regA).update('anotherValue')
|
3946 | expect(regA.getAttribute 'someattr').to.equal 'ANOTHERVALUE'
|
3947 |
|
3948 | restartSandbox()
|
3949 |
|
3950 |
|
3951 |
|
3952 | test "DOMValue", ()-> if not isBrowser then @skip() else
|
3953 | inputA.value = 'value'
|
3954 |
|
3955 | SimplyBind('value').of(inputA)
|
3956 | .transformSelf (value)-> value.toUpperCase()
|
3957 |
|
3958 | expect(inputA.value).to.equal 'VALUE'
|
3959 |
|
3960 | inputA.value = 'anotherValue'
|
3961 | inputA.emit 'change'
|
3962 | expect(inputA.value).to.equal 'ANOTHERVALUE'
|
3963 |
|
3964 | restartSandbox()
|
3965 |
|
3966 |
|
3967 |
|
3968 | test "Array", ()->
|
3969 | expect ()-> SimplyBind(arrayA).transformSelf (v)->v
|
3970 | .to.throw()
|
3971 |
|
3972 | restartSandbox()
|
3973 |
|
3974 |
|
3975 |
|
3976 | test "Function", ()->
|
3977 | dispatcher = 'prop':'value'
|
3978 | receiver = 'prop':'value'
|
3979 | fn = (value)-> value
|
3980 |
|
3981 | SimplyBind(fn).transformSelf (value)-> value?.toUpperCase()
|
3982 | SimplyBind('prop').of(dispatcher)
|
3983 | .to(fn)
|
3984 | .chainTo('prop').of(receiver)
|
3985 |
|
3986 | expect(dispatcher.prop).to.equal 'value'
|
3987 | expect(receiver.prop).to.equal 'VALUE'
|
3988 |
|
3989 | dispatcher.prop = 'anotherValue'
|
3990 | expect(dispatcher.prop).to.equal 'anotherValue'
|
3991 | expect(receiver.prop).to.equal 'ANOTHERVALUE'
|
3992 |
|
3993 |
|
3994 |
|
3995 | test "Event", ()->
|
3996 | dispatcher = 'prop':eventEmitterA
|
3997 | receiver = 'prop':'N/A'
|
3998 | eventEmitterA.type = 'someEvent'
|
3999 | eventEmitterB.type = 'someEvent'
|
4000 |
|
4001 | SimplyBind(0).ofEvent('someEvent').of(eventEmitterA)
|
4002 | .transformSelf (event)-> event?.type or event
|
4003 |
|
4004 | SimplyBind('prop').of(dispatcher)
|
4005 | .toEvent('someEvent').of(eventEmitterA)
|
4006 | .chainTo('prop').of(receiver)
|
4007 |
|
4008 | expect(dispatcher.prop).to.equal eventEmitterA
|
4009 | expect(receiver.prop).to.equal 'N/A'
|
4010 |
|
4011 | receiver.prop = 'reset'
|
4012 | dispatcher.prop = eventEmitterB
|
4013 | expect(dispatcher.prop).to.equal eventEmitterB
|
4014 | expect(receiver.prop).to.equal 'someEvent'
|
4015 |
|
4016 |
|
4017 |
|
4018 |
|
4019 |
|
4020 |
|
4021 | suite "Will not transform value on bind if SimplyBind.options.updateOnBind is off", ()->
|
4022 | suiteSetup ()-> SimplyBind.setOption 'updateOnBind', false
|
4023 | suiteTeardown ()-> SimplyBind.setOption 'updateOnBind', true
|
4024 |
|
4025 | test "ObjectProp", ()->
|
4026 | object = 'prop':'value'
|
4027 |
|
4028 | SimplyBind('prop').of(object)
|
4029 | .transformSelf (value)-> value.toUpperCase()
|
4030 |
|
4031 | expect(object.prop).to.equal 'value'
|
4032 |
|
4033 | object.prop = 'anotherValue'
|
4034 | expect(object.prop).to.equal 'ANOTHERVALUE'
|
4035 |
|
4036 |
|
4037 |
|
4038 | test "DOMText", ()-> if not isBrowser then @skip() else
|
4039 | regA.textContent = 'value'
|
4040 |
|
4041 | SimplyBind('textContent').of(regA)
|
4042 | .transformSelf (value)-> value.toUpperCase()
|
4043 |
|
4044 | expect(regA.textContent).to.equal 'value'
|
4045 |
|
4046 | SimplyBind('textContent').of(regA).update('anotherValue')
|
4047 | expect(regA.textContent).to.equal 'ANOTHERVALUE'
|
4048 |
|
4049 | restartSandbox()
|
4050 |
|
4051 |
|
4052 |
|
4053 | test "DOMAttr", ()-> if not isBrowser then @skip() else
|
4054 | regA.setAttribute 'someattr', 'value'
|
4055 |
|
4056 | SimplyBind('attr:someattr').of(regA)
|
4057 | .transformSelf (value)-> value.toUpperCase()
|
4058 |
|
4059 | expect(regA.getAttribute 'someattr').to.equal 'value'
|
4060 |
|
4061 | SimplyBind('attr:someattr').of(regA).update('anotherValue')
|
4062 | expect(regA.getAttribute 'someattr').to.equal 'ANOTHERVALUE'
|
4063 |
|
4064 | restartSandbox()
|
4065 |
|
4066 |
|
4067 |
|
4068 | test "DOMValue", ()-> if not isBrowser then @skip() else
|
4069 | inputA.value = 'value'
|
4070 |
|
4071 | SimplyBind('value').of(inputA)
|
4072 | .transformSelf (value)-> value.toUpperCase()
|
4073 |
|
4074 | expect(inputA.value).to.equal 'value'
|
4075 |
|
4076 | inputA.value = 'anotherValue'
|
4077 | inputA.emit 'change'
|
4078 | expect(inputA.value).to.equal 'ANOTHERVALUE'
|
4079 |
|
4080 | restartSandbox()
|
4081 |
|
4082 |
|
4083 |
|
4084 | test "Function", ()->
|
4085 | dispatcher = 'prop':'value'
|
4086 | receiver = 'prop':'value'
|
4087 | fn = (value)-> value
|
4088 |
|
4089 | SimplyBind(fn).transformSelf (value)-> value?.toUpperCase()
|
4090 | SimplyBind('prop').of(dispatcher)
|
4091 | .to(fn)
|
4092 | .chainTo('prop').of(receiver)
|
4093 |
|
4094 | expect(dispatcher.prop).to.equal 'value'
|
4095 | expect(receiver.prop).to.be.undefined
|
4096 |
|
4097 | dispatcher.prop = 'anotherValue'
|
4098 | expect(dispatcher.prop).to.equal 'anotherValue'
|
4099 | expect(receiver.prop).to.equal 'ANOTHERVALUE'
|
4100 | restartSandbox()
|
4101 |
|
4102 |
|
4103 |
|
4104 | test "Event", ()->
|
4105 | dispatcher = 'prop':eventEmitterA
|
4106 | receiver = 'prop':'N/A'
|
4107 | eventEmitterA.type = 'someEvent'
|
4108 | eventEmitterB.type = 'someEvent'
|
4109 |
|
4110 | SimplyBind(0).ofEvent('someEvent').of(eventEmitterA)
|
4111 | .transformSelf (event)-> event?.type or event
|
4112 |
|
4113 | SimplyBind('prop').of(dispatcher)
|
4114 | .toEvent('someEvent').of(eventEmitterA)
|
4115 | .chainTo('prop').of(receiver)
|
4116 |
|
4117 | expect(dispatcher.prop).to.equal eventEmitterA
|
4118 | expect(receiver.prop).to.equal 'N/A'
|
4119 |
|
4120 | receiver.prop = 'reset'
|
4121 | dispatcher.prop = eventEmitterB
|
4122 | expect(dispatcher.prop).to.equal eventEmitterB
|
4123 | expect(receiver.prop).to.equal 'someEvent'
|
4124 |
|
4125 |
|
4126 |
|
4127 |
|
4128 |
|
4129 |
|
4130 |
|
4131 |
|
4132 |
|
4133 |
|
4134 |
|
4135 |
|
4136 |
|
4137 |
|
4138 |
|
4139 |
|
4140 |
|
4141 |
|
4142 |
|
4143 |
|
4144 | suite ".condition()", ()->
|
4145 | suiteSetup(restartSandbox)
|
4146 |
|
4147 | test "Will pass the value to the condition before updating the dependent and will update the dep only if the return value is truthy", ()->
|
4148 | shouldAllowUpdate = false
|
4149 | objectA.prop1 = objectB.prop1 = 0
|
4150 |
|
4151 | SimplyBind('prop1').of(objectA)
|
4152 | .to('prop1').of(objectB)
|
4153 | .condition ()-> shouldAllowUpdate
|
4154 |
|
4155 | objectA.prop1 = 1
|
4156 | expect(objectB.prop1).to.equal 0
|
4157 |
|
4158 | objectA.prop1 = 2
|
4159 | expect(objectB.prop1).to.equal 0
|
4160 |
|
4161 | shouldAllowUpdate = true
|
4162 |
|
4163 | objectA.prop1 = 3
|
4164 | expect(objectB.prop1).to.equal 3
|
4165 |
|
4166 | restartSandbox()
|
4167 |
|
4168 |
|
4169 |
|
4170 | test "Will update the dependent upon initial bind regardless of the condition unless SimplyBind.options.updateOnBind is on", ()->
|
4171 | shouldAllowUpdate = false
|
4172 | objectA.prop1 = objectA.prop2 = 1
|
4173 | objectB.prop1 = objectB.prop2 = 0
|
4174 |
|
4175 | SimplyBind('prop1').of(objectA)
|
4176 | .to('prop1').of(objectB)
|
4177 | .condition ()-> shouldAllowUpdate
|
4178 |
|
4179 | expect(objectA.prop1).to.equal 1
|
4180 | expect(objectB.prop1).to.equal 1
|
4181 |
|
4182 | objectA.prop1 = 2
|
4183 | expect(objectB.prop1).to.equal 1
|
4184 |
|
4185 |
|
4186 |
|
4187 | SimplyBind.setOption 'updateOnBind', false
|
4188 |
|
4189 | SimplyBind('prop2').of(objectA)
|
4190 | .to('prop2').of(objectB)
|
4191 | .condition ()-> shouldAllowUpdate
|
4192 |
|
4193 | expect(objectA.prop2).to.equal 1
|
4194 | expect(objectB.prop2).to.equal 0
|
4195 |
|
4196 | SimplyBind.setOption 'updateOnBind', true
|
4197 | restartSandbox()
|
4198 |
|
4199 |
|
4200 |
|
4201 | test "Condition will be added only to the last-proxied dependent", ()->
|
4202 | shouldAllowUpdate = false
|
4203 | objectA.prop1 = objectB.prop1 = objectC.prop1 = 0
|
4204 |
|
4205 | SimplyBind('prop1').of(objectA)
|
4206 | .to('prop1').of(objectB).condition ()-> shouldAllowUpdate
|
4207 | .and('prop1').of(objectC)
|
4208 |
|
4209 | objectA.prop1 = 1
|
4210 | expect(objectB.prop1).to.equal 0
|
4211 | expect(objectC.prop1).to.equal 1
|
4212 |
|
4213 | objectA.prop1 = 2
|
4214 | expect(objectB.prop1).to.equal 0
|
4215 | expect(objectC.prop1).to.equal 2
|
4216 |
|
4217 | shouldAllowUpdate = true
|
4218 |
|
4219 | objectA.prop1 = 3
|
4220 | expect(objectB.prop1).to.equal 3
|
4221 | expect(objectC.prop1).to.equal 3
|
4222 |
|
4223 | restartSandbox()
|
4224 |
|
4225 |
|
4226 |
|
4227 | test "The condition will be added both ways if declared after the .bothWays() call", ()->
|
4228 | shouldAllowUpdate = false
|
4229 | objectA.prop1 = objectB.prop1 = 0
|
4230 |
|
4231 | SimplyBind('prop1').of(objectA)
|
4232 | .to('prop1').of(objectB).bothWays()
|
4233 | .condition ()-> shouldAllowUpdate
|
4234 |
|
4235 | objectA.prop1 = 1
|
4236 | expect(objectA.prop1).to.equal 1
|
4237 | expect(objectB.prop1).to.equal 0
|
4238 |
|
4239 | objectB.prop1 = 2
|
4240 | expect(objectA.prop1).to.equal 1
|
4241 | expect(objectB.prop1).to.equal 2
|
4242 |
|
4243 | shouldAllowUpdate = true
|
4244 |
|
4245 | objectA.prop1 = 3
|
4246 | expect(objectA.prop1).to.equal 3
|
4247 | expect(objectB.prop1).to.equal 3
|
4248 |
|
4249 | objectB.prop1 = 4
|
4250 | expect(objectA.prop1).to.equal 4
|
4251 | expect(objectB.prop1).to.equal 4
|
4252 |
|
4253 | restartSandbox()
|
4254 |
|
4255 |
|
4256 |
|
4257 | test "The condition will be added both ways if declared before the .bothWays() call", ()->
|
4258 | shouldAllowUpdate = false
|
4259 | objectA.prop1 = objectB.prop1 = 0
|
4260 |
|
4261 | SimplyBind('prop1').of(objectA)
|
4262 | .to('prop1').of(objectB)
|
4263 | .condition ()-> shouldAllowUpdate
|
4264 | .bothWays()
|
4265 |
|
4266 | objectA.prop1 = 1
|
4267 | expect(objectA.prop1).to.equal 1
|
4268 | expect(objectB.prop1).to.equal 0
|
4269 |
|
4270 | objectB.prop1 = 2
|
4271 | expect(objectA.prop1).to.equal 1
|
4272 | expect(objectB.prop1).to.equal 2
|
4273 |
|
4274 | shouldAllowUpdate = true
|
4275 |
|
4276 | objectA.prop1 = 3
|
4277 | expect(objectA.prop1).to.equal 3
|
4278 | expect(objectB.prop1).to.equal 3
|
4279 |
|
4280 | objectB.prop1 = 4
|
4281 | expect(objectA.prop1).to.equal 4
|
4282 | expect(objectB.prop1).to.equal 4
|
4283 |
|
4284 | restartSandbox()
|
4285 |
|
4286 |
|
4287 |
|
4288 | 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", ()->
|
4289 | invokeCount = 0
|
4290 | shouldAllowUpdate = true
|
4291 |
|
4292 | SimplyBind('prop1').of(objectA)
|
4293 | .to('prop1').of(objectB)
|
4294 | .transform (val)-> invokeCount++; val
|
4295 | .condition ()-> shouldAllowUpdate
|
4296 |
|
4297 | expect(objectB.prop1).to.equal(objectA.prop1)
|
4298 | expect(invokeCount).to.equal 1
|
4299 |
|
4300 | objectA.prop1 = 2
|
4301 | expect(objectB.prop1).to.equal(objectA.prop1)
|
4302 | expect(invokeCount).to.equal 2
|
4303 |
|
4304 | shouldAllowUpdate = false
|
4305 | objectA.prop1 = 3
|
4306 | expect(objectB.prop1).not.to.equal(objectA.prop1)
|
4307 | expect(invokeCount).to.equal 3
|
4308 |
|
4309 | objectA.prop1 = 4
|
4310 | expect(objectB.prop1).not.to.equal(objectA.prop1)
|
4311 | expect(invokeCount).to.equal 4
|
4312 |
|
4313 | restartSandbox()
|
4314 |
|
4315 |
|
4316 |
|
4317 | test "If a binding has a placeholder, the condition will be used only for that placeholder", ()->
|
4318 | dispatcher = 'prop':''
|
4319 | receiver = 'prop':'This {{noun}} works'
|
4320 | lastPassedNoun = null
|
4321 | shouldAllowUpdate = true
|
4322 |
|
4323 | SimplyBind('prop').of(dispatcher)
|
4324 | .to('prop.noun').of(receiver)
|
4325 | .condition (noun)-> lastPassedNoun=noun; return shouldAllowUpdate
|
4326 |
|
4327 | dispatcher.prop = 'test1'
|
4328 | expect(lastPassedNoun).to.equal 'test1'
|
4329 | expect(receiver.prop).to.equal 'This test1 works'
|
4330 |
|
4331 | shouldAllowUpdate = false
|
4332 | dispatcher.prop = 'test2'
|
4333 | expect(lastPassedNoun).to.equal 'test2'
|
4334 | expect(receiver.prop).to.equal 'This test1 works'
|
4335 |
|
4336 |
|
4337 |
|
4338 |
|
4339 |
|
4340 |
|
4341 |
|
4342 |
|
4343 |
|
4344 |
|
4345 |
|
4346 |
|
4347 |
|
4348 |
|
4349 |
|
4350 |
|
4351 | suite ".conditionAll()", ()->
|
4352 | suiteSetup(restartSandbox)
|
4353 |
|
4354 | test "Behaves the same way as .condition() does, except it applies the condition to all of the declared dependents", ()->
|
4355 | shouldAllowUpdate = false
|
4356 | dispatcher = 'prop':0
|
4357 | objectA.prop1 = objectB.prop1 = objectC.prop1 = 0
|
4358 |
|
4359 | SimplyBind('prop').of(dispatcher)
|
4360 | .to('prop1').of(objectA)
|
4361 | .and('prop1').of(objectB)
|
4362 | .and('prop1').of(objectC)
|
4363 | .conditionAll ()-> shouldAllowUpdate
|
4364 |
|
4365 | dispatcher.prop = 1
|
4366 | expect(objectA.prop1).to.equal 0
|
4367 | expect(objectB.prop1).to.equal 0
|
4368 | expect(objectC.prop1).to.equal 0
|
4369 |
|
4370 | dispatcher.prop = 2
|
4371 | expect(objectA.prop1).to.equal 0
|
4372 | expect(objectB.prop1).to.equal 0
|
4373 | expect(objectC.prop1).to.equal 0
|
4374 |
|
4375 | shouldAllowUpdate = true
|
4376 |
|
4377 | dispatcher.prop = 3
|
4378 | expect(objectA.prop1).to.equal 3
|
4379 | expect(objectB.prop1).to.equal 3
|
4380 | expect(objectC.prop1).to.equal 3
|
4381 |
|
4382 | restartSandbox()
|
4383 |
|
4384 |
|
4385 |
|
4386 |
|
4387 |
|
4388 |
|
4389 |
|
4390 |
|
4391 |
|
4392 |
|
4393 |
|
4394 |
|
4395 |
|
4396 |
|
4397 |
|
4398 |
|
4399 |
|
4400 |
|
4401 |
|
4402 | suite ".bothWays()", ()->
|
4403 | suiteSetup(restartSandbox)
|
4404 | test "Create two-way bindings", ()->
|
4405 |
|
4406 | SimplyBind('prop').of(objectA).to('prop').of(objectB).bothWays()
|
4407 | expect(objectA.prop).to.be.undefined
|
4408 |
|
4409 | objectA.prop = 'from objectA'
|
4410 | expect(objectA.prop).to.equal 'from objectA'
|
4411 | expect(objectB.prop).to.equal 'from objectA'
|
4412 |
|
4413 | objectB.prop = 'from objectB'
|
4414 | expect(objectA.prop).to.equal 'from objectB'
|
4415 | expect(objectB.prop).to.equal 'from objectB'
|
4416 |
|
4417 |
|
4418 |
|
4419 | SimplyBind(arrayA).to(arrayB).bothWays()
|
4420 | expect(arrayA.length).to.equal 10
|
4421 | expect(arrayB.length).to.equal 10
|
4422 |
|
4423 | arrayA.push(1)
|
4424 | arrayA.push(1)
|
4425 | expect(arrayA.length).to.equal 12
|
4426 | expect(arrayB.length).to.equal 10
|
4427 |
|
4428 | arrayB.push(1)
|
4429 | arrayB.push(1)
|
4430 | expect(arrayA.length).to.equal 12
|
4431 | expect(arrayB.length).to.equal 12
|
4432 |
|
4433 |
|
4434 | if isBrowser
|
4435 |
|
4436 | SimplyBind('attr:someattr').of(regA).to('attr:someattr').of(regB).bothWays()
|
4437 | expect(regA.getAttribute('someattr')).to.equal null
|
4438 |
|
4439 | SimplyBind('attr:someattr').of(regA).set 'from regElementA'
|
4440 | expect(regA.getAttribute('someattr')).to.equal 'from regElementA'
|
4441 | expect(regB.getAttribute('someattr')).to.equal 'from regElementA'
|
4442 |
|
4443 | SimplyBind('attr:someattr').of(regB).set 'from regElementB'
|
4444 | expect(regA.getAttribute('someattr')).to.equal 'from regElementB'
|
4445 | expect(regB.getAttribute('someattr')).to.equal 'from regElementB'
|
4446 |
|
4447 |
|
4448 |
|
4449 | regA.textContent = ''
|
4450 | SimplyBind('textContent').of(regA).to('textContent').of(regB).bothWays()
|
4451 | expect(regA.textContent).to.equal ''
|
4452 |
|
4453 | SimplyBind('textContent').of(regA).set 'from regElementA'
|
4454 | expect(regA.textContent).to.equal 'from regElementA'
|
4455 | expect(regB.textContent).to.equal 'from regElementA'
|
4456 |
|
4457 | SimplyBind('textContent').of(regB).set 'from regElementB'
|
4458 | expect(regA.textContent).to.equal 'from regElementB'
|
4459 | expect(regB.textContent).to.equal 'from regElementB'
|
4460 |
|
4461 |
|
4462 |
|
4463 | SimplyBind('value').of(inputA).to('value').of(inputB).bothWays()
|
4464 | expect(inputA.value).to.equal ''
|
4465 |
|
4466 | inputA.value = 'from inputA'
|
4467 | inputA.emit 'change'
|
4468 | expect(inputA.value).to.equal 'from inputA'
|
4469 | expect(inputB.value).to.equal 'from inputA'
|
4470 |
|
4471 | inputB.value = 'from inputB'
|
4472 | inputB.emit 'change'
|
4473 | expect(inputA.value).to.equal 'from inputB'
|
4474 | expect(inputB.value).to.equal 'from inputB'
|
4475 |
|
4476 |
|
4477 |
|
4478 | binding = SimplyBind('checked').of(checkboxFields).to('prop2').of(objectB).bothWays()
|
4479 | expect(objectB.prop2).to.be.instanceOf Array
|
4480 | expect(objectB.prop2.length).to.equal 0
|
4481 |
|
4482 | objectB.prop2 = 'changed from objectB'
|
4483 | expect($checkboxFields.filter(':checked').length).to.equal 0
|
4484 | expect(binding.value).to.be.instanceOf Array
|
4485 | expect(binding.value.length).to.equal 0
|
4486 |
|
4487 | objectB.prop2 = 'checkboxB'
|
4488 | expect($checkboxFields.filter(':checked').val()).to.equal 'checkboxB'
|
4489 | expect(binding.value.length).to.equal 1
|
4490 |
|
4491 | objectB.prop2 = ['checkboxA', 'checkboxC']
|
4492 | expect($checkboxFields.filter(':checked').length).to.equal 2
|
4493 | expect(binding.value.length).to.equal 2
|
4494 |
|
4495 | $checkboxA.click()
|
4496 | expect(objectB.prop2).to.be.instanceOf Array
|
4497 | expect(objectB.prop2.length).to.equal 1
|
4498 | expect(objectB.prop2[0]).to.equal 'checkboxC'
|
4499 |
|
4500 | restartSandbox()
|
4501 |
|
4502 |
|
4503 |
|
4504 | SimplyBind('checked').of(radioFields).to('prop3').of(objectB).bothWays()
|
4505 |
|
4506 | objectB.prop3 = 'changed from objectB'
|
4507 | expect($radioFields.filter(':checked').length).to.equal 0
|
4508 |
|
4509 | objectB.prop3 = 'radioB'
|
4510 | expect($radioFields.filter(':checked').val()).to.equal 'radioB'
|
4511 |
|
4512 | $radioA.click()
|
4513 | expect(objectB.prop3).to.equal 'radioA'
|
4514 |
|
4515 | restartSandbox()
|
4516 |
|
4517 |
|
4518 |
|
4519 | SimplyBind.setOption('updateOnBind', true)
|
4520 | restartSandbox()
|
4521 |
|
4522 |
|
4523 |
|
4524 |
|
4525 |
|
4526 |
|
4527 |
|
4528 | test "Will apply the call only to the last proxied dependent", ()->
|
4529 | restartSandbox()
|
4530 | SimplyBind('prop1').of(objectA)
|
4531 | .to('prop1').of(objectB).bothWays()
|
4532 | .and('prop2').of(objectB)
|
4533 | .and('prop3').of(objectB).bothWays()
|
4534 | .and('prop4').of objectB
|
4535 |
|
4536 | objectA.prop1 = 'all at once'
|
4537 | expect(objectB.prop1).to.equal 'all at once'
|
4538 | expect(objectB.prop2).to.equal 'all at once'
|
4539 | expect(objectB.prop3).to.equal 'all at once'
|
4540 | expect(objectB.prop4).to.equal 'all at once'
|
4541 |
|
4542 | objectB.prop1 = 'almost all as well since objectA.prop1 gets updated and updates all of its decendents'
|
4543 | expect(objectA.prop1).to.equal 'almost all as well since objectA.prop1 gets updated and updates all of its decendents'
|
4544 | expect(objectB.prop2).to.equal 'almost all as well since objectA.prop1 gets updated and updates all of its decendents'
|
4545 | expect(objectB.prop3).to.equal 'almost all as well since objectA.prop1 gets updated and updates all of its decendents'
|
4546 | expect(objectB.prop4).to.equal 'almost all as well since objectA.prop1 gets updated and updates all of its decendents'
|
4547 |
|
4548 | objectB.prop3 = 'just a few'
|
4549 | expect(objectA.prop1).to.equal 'just a few'
|
4550 | expect(objectB.prop1).to.equal 'just a few'
|
4551 | expect(objectB.prop2).to.equal 'just a few'
|
4552 | expect(objectB.prop4).to.equal 'just a few'
|
4553 |
|
4554 |
|
4555 |
|
4556 |
|
4557 |
|
4558 |
|
4559 | suite "DOMValue other than input", ()->
|
4560 | suiteSetup ()-> if not isBrowser then @skip()
|
4561 | test "Create two-way bindings between textarea fields", ()->
|
4562 | SimplyBind('value').of(textarea).to('value').of(inputB).bothWays()
|
4563 |
|
4564 | $textarea.val('changed from input1')[0].emit 'change'
|
4565 | expect($inputB.val()).to.equal 'changed from input1'
|
4566 |
|
4567 | $inputB.val('changed from input2')[0].emit 'change'
|
4568 | expect($textarea.val()).to.equal 'changed from input2'
|
4569 |
|
4570 |
|
4571 |
|
4572 |
|
4573 | test "Create two-way bindings between select fields", ()->
|
4574 | SimplyBind('value').of($select).to('prop3').of(objectB).bothWays()
|
4575 |
|
4576 | objectB.prop3 = 'valid'
|
4577 | expect($select.val()).to.equal 'valid'
|
4578 |
|
4579 | $select.val('valid2')[0].emit 'change'
|
4580 | expect(objectB.prop3).to.equal 'valid2'
|
4581 | restartSandbox()
|
4582 |
|
4583 |
|
4584 |
|
4585 |
|
4586 |
|
4587 |
|
4588 |
|
4589 |
|
4590 |
|
4591 |
|
4592 |
|
4593 |
|
4594 |
|
4595 |
|
4596 |
|
4597 |
|
4598 |
|
4599 |
|
4600 |
|
4601 |
|
4602 |
|
4603 |
|
4604 |
|
4605 |
|
4606 |
|
4607 |
|
4608 |
|
4609 |
|
4610 |
|
4611 |
|
4612 |
|
4613 |
|
4614 |
|
4615 |
|
4616 |
|
4617 |
|
4618 |
|
4619 |
|
4620 |
|
4621 |
|
4622 |
|
4623 |
|
4624 |
|
4625 |
|
4626 |
|
4627 |
|
4628 |
|
4629 |
|
4630 |
|
4631 |
|
4632 |
|
4633 |
|
4634 |
|
4635 | suite ".unBind()", ()->
|
4636 | suiteSetup(restartSandbox)
|
4637 | suite "Will unbind from the all defined proxied dependents one-way", ()->
|
4638 | test "ObjectProp", ()->
|
4639 | binding = SimplyBind('prop1').of(objectA)
|
4640 | .to('prop1').of(objectB).bothWays()
|
4641 |
|
4642 | objectA.prop1 = 1
|
4643 | expect(objectB.prop1).to.equal 1
|
4644 |
|
4645 | objectB.prop1 = 2
|
4646 | expect(objectA.prop1).to.equal 2
|
4647 |
|
4648 | binding.unBind()
|
4649 |
|
4650 | objectA.prop1 = 3
|
4651 | expect(objectB.prop1).to.equal 2
|
4652 |
|
4653 | objectB.prop1 = 4
|
4654 | expect(objectA.prop1).to.equal 4
|
4655 |
|
4656 | restartSandbox()
|
4657 |
|
4658 |
|
4659 |
|
4660 | test "DOMText", ()-> if not isBrowser then @skip() else
|
4661 | binding = SimplyBind('textContent').of(regA)
|
4662 | .to('textContent').of(regB).bothWays()
|
4663 |
|
4664 | SimplyBind('textContent').of(regA).set '1'
|
4665 | expect(regB.textContent).to.equal '1'
|
4666 |
|
4667 | SimplyBind('textContent').of(regB).set '2'
|
4668 | expect(regA.textContent).to.equal '2'
|
4669 |
|
4670 | binding.unBind()
|
4671 |
|
4672 | SimplyBind('textContent').of(regA).set '3'
|
4673 | expect(regB.textContent).to.equal '2'
|
4674 |
|
4675 | SimplyBind('textContent').of(regB).set '4'
|
4676 | expect(regA.textContent).to.equal '4'
|
4677 |
|
4678 | restartSandbox()
|
4679 |
|
4680 |
|
4681 |
|
4682 | test "DOMAttr", ()-> if not isBrowser then @skip() else
|
4683 | binding = SimplyBind('attr:someattr').of(regA)
|
4684 | .to('attr:someattr').of(regB).bothWays()
|
4685 |
|
4686 | SimplyBind('attr:someattr').of(regA).set '1'
|
4687 | expect(regB.getAttribute 'someattr').to.equal '1'
|
4688 |
|
4689 | SimplyBind('attr:someattr').of(regB).set '2'
|
4690 | expect(regA.getAttribute 'someattr').to.equal '2'
|
4691 |
|
4692 | binding.unBind()
|
4693 |
|
4694 | SimplyBind('attr:someattr').of(regA).set '3'
|
4695 | expect(regB.getAttribute 'someattr').to.equal '2'
|
4696 |
|
4697 | SimplyBind('attr:someattr').of(regB).set '4'
|
4698 | expect(regA.getAttribute 'someattr').to.equal '4'
|
4699 |
|
4700 | restartSandbox()
|
4701 |
|
4702 |
|
4703 |
|
4704 | test "DOMValue", ()-> if not isBrowser then @skip() else
|
4705 | binding = SimplyBind('value').of(inputA)
|
4706 | .to('value').of(inputB).bothWays()
|
4707 |
|
4708 | inputA.value = '1'
|
4709 | inputA.emit 'change'
|
4710 | expect(inputB.value).to.equal '1'
|
4711 |
|
4712 | inputB.value = '2'
|
4713 | inputB.emit 'change'
|
4714 | expect(inputA.value).to.equal '2'
|
4715 |
|
4716 | binding.unBind()
|
4717 |
|
4718 | inputA.value = '3'
|
4719 | inputA.emit 'change'
|
4720 | expect(inputB.value).to.equal '2'
|
4721 |
|
4722 | inputB.value = '4'
|
4723 | inputB.emit 'change'
|
4724 | expect(inputA.value).to.equal '4'
|
4725 |
|
4726 | restartSandbox()
|
4727 |
|
4728 |
|
4729 |
|
4730 | test "Array", ()->
|
4731 | binding = SimplyBind(arrayA, {'trackArrayChildren':true})
|
4732 | .to('prop1').of(objectA)
|
4733 |
|
4734 | expect(objectA.prop1).to.equal arrayA
|
4735 |
|
4736 | objectA.prop1 = 'reset'
|
4737 | arrayA.push(1)
|
4738 | expect(objectA.prop1).to.equal arrayA
|
4739 |
|
4740 | objectA.prop1 = 'reset'
|
4741 | arrayA[5] = 19
|
4742 | expect(objectA.prop1).to.equal arrayA
|
4743 |
|
4744 |
|
4745 | objectA.prop1 = 'reset'
|
4746 | binding.unBind()
|
4747 |
|
4748 | arrayA.push(1)
|
4749 | arrayA[3] = 23
|
4750 | expect(objectA.prop1).to.equal 'reset'
|
4751 |
|
4752 | restartSandbox()
|
4753 |
|
4754 |
|
4755 |
|
4756 | test "Function", ()->
|
4757 | passedValue = null
|
4758 | valueToPass = 1
|
4759 | takeFromReceiver = false
|
4760 | fn = (fromReceiver)-> passedValue = if takeFromReceiver then fromReceiver else valueToPass
|
4761 | invoker = 'prop':'value'
|
4762 | receiver = 'prop':undefined
|
4763 |
|
4764 | SimplyBind('prop').of(invoker).to(fn)
|
4765 | binding = SimplyBind(fn).to('prop').of(receiver).bothWays()
|
4766 |
|
4767 | expect(receiver.prop).to.equal 1
|
4768 | expect(passedValue).to.equal 1
|
4769 |
|
4770 | valueToPass = 5
|
4771 | invoker.prop = 'anotherValue'
|
4772 | expect(receiver.prop).to.equal 5
|
4773 | expect(passedValue).to.equal 5
|
4774 |
|
4775 | takeFromReceiver = true
|
4776 | receiver.prop = 10
|
4777 | takeFromReceiver = false
|
4778 | expect(passedValue).to.equal 10
|
4779 |
|
4780 |
|
4781 | binding.unBind()
|
4782 | valueToPass = 15
|
4783 | invoker.prop = 'newValue'
|
4784 | expect(receiver.prop).to.equal 10
|
4785 | expect(passedValue).to.equal 15
|
4786 |
|
4787 | takeFromReceiver = true
|
4788 | receiver.prop = 20
|
4789 | takeFromReceiver = false
|
4790 | expect(passedValue).to.equal 20
|
4791 |
|
4792 |
|
4793 |
|
4794 | test "Event", ()->
|
4795 | eventInvokeCount = 0
|
4796 | eventObject = null
|
4797 | objectA.prop = objectB.prop = 'someValue'
|
4798 | eventEmitterA.on 'someEvent', (event)-> eventObject = event or @
|
4799 |
|
4800 | binding = SimplyBind(0).ofEvent('someEvent').of(eventEmitterA).transformSelf ()-> eventObject
|
4801 | .to('prop').of(objectA).bothWays()
|
4802 | .and('prop').of(objectB).bothWays()
|
4803 | .and ()-> eventInvokeCount++
|
4804 |
|
4805 |
|
4806 | eventEmitterA.emit 'someEvent'
|
4807 | expect(objectA.prop).to.equal eventObject
|
4808 | expect(objectB.prop).to.equal(objectA.prop)
|
4809 | expect(eventInvokeCount).to.equal 1
|
4810 |
|
4811 | objectA.prop = 'different value'
|
4812 | expect(objectA.prop).to.equal 'different value'
|
4813 |
|
4814 | expect(eventInvokeCount).to.equal 2
|
4815 |
|
4816 | objectB.prop = 'different value2'
|
4817 | expect(eventInvokeCount).to.equal 3
|
4818 |
|
4819 |
|
4820 | binding.unBind()
|
4821 | objectA.prop = 'different value'
|
4822 | eventEmitterA.emit 'someEvent'
|
4823 | eventEmitterA.on 'someEvent', ()-> eventInvokeCount++
|
4824 |
|
4825 | expect(objectA.prop).to.equal 'different value'
|
4826 | expect(objectB.prop).to.equal 'different value2'
|
4827 | expect(eventInvokeCount).to.equal 3
|
4828 |
|
4829 |
|
4830 | objectA.prop = 'another value'
|
4831 | expect(objectA.prop).to.equal 'another value'
|
4832 | expect(objectB.prop).to.equal 'different value2'
|
4833 |
|
4834 | objectB.prop = 'another value2'
|
4835 | expect(objectA.prop).to.equal 'another value'
|
4836 | expect(objectB.prop).to.equal 'another value2'
|
4837 | expect(eventInvokeCount).to.equal 5
|
4838 | expect(binding._.deps.length).to.equal 0
|
4839 |
|
4840 | restartSandbox()
|
4841 |
|
4842 |
|
4843 |
|
4844 | suite "Will unbind from the all defined proxied dependents both-ways", ()->
|
4845 | test "ObjectProp", ()->
|
4846 | binding = SimplyBind('prop1').of(objectA)
|
4847 | .to('prop1').of(objectB).bothWays()
|
4848 |
|
4849 | objectA.prop1 = 1
|
4850 | expect(objectB.prop1).to.equal 1
|
4851 |
|
4852 | objectB.prop1 = 2
|
4853 | expect(objectA.prop1).to.equal 2
|
4854 |
|
4855 | binding.unBind(true)
|
4856 |
|
4857 | objectA.prop1 = 3
|
4858 | expect(objectB.prop1).to.equal 2
|
4859 |
|
4860 | objectB.prop1 = 4
|
4861 | expect(objectA.prop1).to.equal 3
|
4862 |
|
4863 | restartSandbox()
|
4864 |
|
4865 |
|
4866 |
|
4867 | test "DOMText", ()-> if not isBrowser then @skip() else
|
4868 | binding = SimplyBind('textContent').of(regA)
|
4869 | .to('textContent').of(regB).bothWays()
|
4870 |
|
4871 | SimplyBind('textContent').of(regA).set '1'
|
4872 | expect(regB.textContent).to.equal '1'
|
4873 |
|
4874 | SimplyBind('textContent').of(regB).set '2'
|
4875 | expect(regA.textContent).to.equal '2'
|
4876 |
|
4877 | binding.unBind(true)
|
4878 |
|
4879 | SimplyBind('textContent').of(regA).set '3'
|
4880 | expect(regB.textContent).to.equal '2'
|
4881 |
|
4882 | SimplyBind('textContent').of(regB).set '4'
|
4883 | expect(regA.textContent).to.equal '3'
|
4884 |
|
4885 | restartSandbox()
|
4886 |
|
4887 |
|
4888 |
|
4889 | test "DOMAttr", ()-> if not isBrowser then @skip() else
|
4890 | binding = SimplyBind('attr:someattr').of(regA)
|
4891 | .to('attr:someattr').of(regB).bothWays()
|
4892 |
|
4893 | SimplyBind('attr:someattr').of(regA).set '1'
|
4894 | expect(regB.getAttribute 'someattr').to.equal '1'
|
4895 |
|
4896 | SimplyBind('attr:someattr').of(regB).set '2'
|
4897 | expect(regA.getAttribute 'someattr').to.equal '2'
|
4898 |
|
4899 | binding.unBind(true)
|
4900 |
|
4901 | SimplyBind('attr:someattr').of(regA).set '3'
|
4902 | expect(regB.getAttribute 'someattr').to.equal '2'
|
4903 |
|
4904 | SimplyBind('attr:someattr').of(regB).set '4'
|
4905 | expect(regA.getAttribute 'someattr').to.equal '3'
|
4906 |
|
4907 | restartSandbox()
|
4908 |
|
4909 |
|
4910 |
|
4911 | test "DOMValue", ()-> if not isBrowser then @skip() else
|
4912 | binding = SimplyBind('value').of(inputA)
|
4913 | .to('value').of(inputB).bothWays()
|
4914 |
|
4915 | inputA.value = '1'
|
4916 | inputA.emit 'change'
|
4917 | expect(inputB.value).to.equal '1'
|
4918 |
|
4919 | inputB.value = '2'
|
4920 | inputB.emit 'change'
|
4921 | expect(inputA.value).to.equal '2'
|
4922 |
|
4923 | binding.unBind(true)
|
4924 |
|
4925 | inputA.value = '3'
|
4926 | inputA.emit 'change'
|
4927 | expect(inputB.value).to.equal '2'
|
4928 |
|
4929 | inputB.value = '4'
|
4930 | inputB.emit 'change'
|
4931 | expect(inputA.value).to.equal '3'
|
4932 |
|
4933 | restartSandbox()
|
4934 |
|
4935 |
|
4936 |
|
4937 | test "Function", ()->
|
4938 | passedValue = null
|
4939 | valueToPass = 1
|
4940 | takeFromReceiver = false
|
4941 | fn = (fromReceiver)-> passedValue = if takeFromReceiver then fromReceiver else valueToPass
|
4942 | invoker = 'prop':'value'
|
4943 | receiver = 'prop':undefined
|
4944 |
|
4945 | SimplyBind('prop').of(invoker).to(fn)
|
4946 | binding = SimplyBind(fn).to('prop').of(receiver).bothWays()
|
4947 |
|
4948 | expect(receiver.prop).to.equal 1
|
4949 | expect(passedValue).to.equal 1
|
4950 |
|
4951 | valueToPass = 5
|
4952 | invoker.prop = 'anotherValue'
|
4953 | expect(receiver.prop).to.equal 5
|
4954 | expect(passedValue).to.equal 5
|
4955 |
|
4956 | takeFromReceiver = true
|
4957 | receiver.prop = 10
|
4958 | takeFromReceiver = false
|
4959 | expect(passedValue).to.equal 10
|
4960 |
|
4961 |
|
4962 | binding.unBind(true)
|
4963 | valueToPass = 15
|
4964 | invoker.prop = 'newValue'
|
4965 | expect(receiver.prop).to.equal 10
|
4966 | expect(passedValue).to.equal 15
|
4967 |
|
4968 | takeFromReceiver = true
|
4969 | receiver.prop = 20
|
4970 | takeFromReceiver = false
|
4971 | expect(passedValue).to.equal 15
|
4972 |
|
4973 |
|
4974 |
|
4975 | test "Event", ()->
|
4976 | eventInvokeCount = 0
|
4977 | eventObject = null
|
4978 | objectA.prop = objectB.prop = 'someValue'
|
4979 | eventEmitterA.on 'someEvent', (event)-> eventObject = event or @
|
4980 |
|
4981 | binding = SimplyBind(0).ofEvent('someEvent').of(eventEmitterA).transformSelf ()-> eventObject
|
4982 | .to('prop').of(objectA).bothWays()
|
4983 | .and('prop').of(objectB).bothWays()
|
4984 | .and ()-> eventInvokeCount++
|
4985 |
|
4986 |
|
4987 | eventEmitterA.emit 'someEvent'
|
4988 | expect(objectA.prop).to.equal eventObject
|
4989 | expect(objectB.prop).to.equal(objectA.prop)
|
4990 | expect(eventInvokeCount).to.equal 1
|
4991 |
|
4992 |
|
4993 | objectA.prop = 'different value'
|
4994 | expect(objectA.prop).to.equal 'different value'
|
4995 |
|
4996 | expect(eventInvokeCount).to.equal 2
|
4997 |
|
4998 | objectB.prop = 'different value2'
|
4999 | expect(eventInvokeCount).to.equal 3
|
5000 |
|
5001 |
|
5002 | binding.unBind(true)
|
5003 | objectA.prop = 'different value'
|
5004 | eventEmitterA.emit 'someEvent'
|
5005 | eventEmitterA.on 'someEvent', ()-> eventInvokeCount++
|
5006 |
|
5007 | expect(objectA.prop).to.equal 'different value'
|
5008 | expect(objectB.prop).to.equal 'different value2'
|
5009 | expect(eventInvokeCount).to.equal 3
|
5010 |
|
5011 |
|
5012 | objectA.prop = 'another value'
|
5013 | expect(objectA.prop).to.equal 'another value'
|
5014 | expect(objectB.prop).to.equal 'different value2'
|
5015 |
|
5016 | objectB.prop = 'another value2'
|
5017 | expect(objectA.prop).to.equal 'another value'
|
5018 | expect(objectB.prop).to.equal 'another value2'
|
5019 | expect(eventInvokeCount).to.equal 3
|
5020 | expect(binding._.deps.length).to.equal 0
|
5021 |
|
5022 | restartSandbox()
|
5023 |
|
5024 |
|
5025 |
|
5026 |
|
5027 |
|
5028 |
|
5029 |
|
5030 |
|
5031 |
|
5032 |
|
5033 |
|
5034 |
|
5035 |
|
5036 |
|
5037 |
|
5038 |
|
5039 |
|
5040 |
|
5041 |
|
5042 |
|
5043 |
|
5044 |
|
5045 |
|
5046 | suite ".pollEvery() + .stopPolling()", ()->
|
5047 | suiteSetup(restartSandbox)
|
5048 | test 'Will cause the value to be manually polled from the subject at a given interval', (done)->
|
5049 | shouldFinish = false
|
5050 | lastValue = undefined
|
5051 | binding = undefined
|
5052 | arr = []
|
5053 |
|
5054 | fn = (length)->
|
5055 | if shouldFinish
|
5056 | expect(length).to.equal 2
|
5057 | binding.stopPolling()
|
5058 | done()
|
5059 | else
|
5060 | lastValue = length
|
5061 |
|
5062 |
|
5063 |
|
5064 | binding = SimplyBind('length').of(arr).to(fn)
|
5065 | expect(lastValue).to.equal 0
|
5066 | arr.push 'some value'
|
5067 | arr.push 'and another'
|
5068 | expect(lastValue).to.equal 0
|
5069 | arr = []
|
5070 | binding = SimplyBind('length').of(arr).to(fn).pollEvery(5)
|
5071 |
|
5072 | setTimeout ()->
|
5073 | shouldFinish = true
|
5074 | expect(lastValue).to.equal 0
|
5075 | arr.push 'some value'
|
5076 | arr.push 'and another'
|
5077 | expect(lastValue).to.equal 0
|
5078 | , 8
|
5079 |
|
5080 |
|
5081 |
|
5082 | test 'Will invoke a function upon poll', (done)->
|
5083 | invokeCountA = 0
|
5084 | invokeCountB = 0
|
5085 |
|
5086 | binding = SimplyBind(()-> ++invokeCountA).to(()-> ++invokeCountB).pollEvery(5)
|
5087 | setTimeout ()->
|
5088 | expect(invokeCountA).to.be.gt(1)
|
5089 | expect(invokeCountB).to.be.gt(1)
|
5090 | binding.stopPolling()
|
5091 | done()
|
5092 | , 15
|
5093 |
|
5094 |
|
5095 |
|
5096 | test "Will re-create the interval poll if called .pollEvery() twice with different values", (done)->
|
5097 | invokeCount = 0
|
5098 | objectA.prop = 200
|
5099 |
|
5100 | expect ()-> SimplyBind('prop', {'updateEvenIfSame':true}).of(objectA).to(()->invokeCount++).pollEvery(50).pollEvery(5)
|
5101 | .not.to.throw()
|
5102 |
|
5103 | setTimeout ()->
|
5104 | expect(invokeCount).to.be.gte(3)
|
5105 | done()
|
5106 | restartSandbox()
|
5107 | , 50
|
5108 |
|
5109 |
|
5110 |
|
5111 | test "Will not throw errors when calling .stopPolling() on a binding with no pre-set interval", ()->
|
5112 | expect ()-> SimplyBind('prop').of(objectA).to('prop').of(objectB).stopPolling()
|
5113 | .not.to.throw()
|
5114 |
|
5115 | restartSandbox()
|
5116 |
|
5117 |
|
5118 |
|
5119 |
|
5120 |
|
5121 |
|
5122 |
|
5123 |
|
5124 |
|
5125 |
|
5126 |
|
5127 |
|
5128 |
|
5129 |
|
5130 |
|
5131 |
|
5132 |
|
5133 |
|
5134 |
|
5135 | suite ".updateDepsOnEvent() + .removeEvent()", ()->
|
5136 | suiteSetup(restartSandbox)
|
5137 | test "Will listen for events on the target and upon emit will poll (and update if changed) the binding's value", ()->
|
5138 | binding = SimplyBind('inheritedProp').of(eventEmitterA).to('prop1').of(objectA).updateDepsOnEvent('click')
|
5139 |
|
5140 | binding.set 'one'
|
5141 | expect(objectA.prop1).to.equal 'one'
|
5142 |
|
5143 | eventEmitterA.inheritedProp = 'two'
|
5144 | expect(objectA.prop1).to.equal 'one'
|
5145 |
|
5146 | eventEmitterA.emit 'click'
|
5147 | expect(objectA.prop1).to.equal 'two'
|
5148 |
|
5149 | binding.removeEvent 'click'
|
5150 | eventEmitterA.inheritedProp = 'three'
|
5151 | expect(objectA.prop1).to.equal 'two'
|
5152 |
|
5153 | eventEmitterA.emit 'click'
|
5154 | expect(objectA.prop1).to.equal 'two'
|
5155 | restartSandbox()
|
5156 |
|
5157 |
|
5158 |
|
5159 | test "Can use custom supplied methods to apply/remove event listerners", ()->
|
5160 | eventEmitterA.customAdd = ()-> eventEmitterA.on.apply eventEmitterA, arguments
|
5161 | eventEmitterA.customRemove = ()-> eventEmitterA.removeListener.apply eventEmitterA, arguments
|
5162 |
|
5163 | binding = SimplyBind('inheritedProp').of(eventEmitterA)
|
5164 | .to('prop1').of(objectA)
|
5165 | .updateDepsOnEvent('click', 'customAdd')
|
5166 |
|
5167 | binding.set 'one'
|
5168 | expect(objectA.prop1).to.equal 'one'
|
5169 |
|
5170 | eventEmitterA.inheritedProp = 'two'
|
5171 | expect(objectA.prop1).to.equal 'one'
|
5172 |
|
5173 | eventEmitterA.emit 'click'
|
5174 | expect(objectA.prop1).to.equal 'two'
|
5175 |
|
5176 | binding.removeEvent 'click', 'customRemove'
|
5177 | eventEmitterA.inheritedProp = 'three'
|
5178 | expect(objectA.prop1).to.equal 'two'
|
5179 |
|
5180 | eventEmitterA.emit 'click'
|
5181 | expect(objectA.prop1).to.equal 'two'
|
5182 |
|
5183 | restartSandbox()
|
5184 |
|
5185 |
|
5186 |
|
5187 | 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", ()->
|
5188 | binding = SimplyBind('inheritedProp').of(eventEmitterB).to('prop1').of(objectA).updateDepsOnEvent('click')
|
5189 | atEvs = binding._.attachedEvents or binding._.atEV;
|
5190 | expect(atEvs.length).to.equal 1
|
5191 |
|
5192 | binding = SimplyBind('inheritedProp').of(eventEmitterB).to('prop1').of(objectA).updateDepsOnEvent('click')
|
5193 | binding = SimplyBind('inheritedProp').of(eventEmitterB).to('prop1').of(objectA).updateDepsOnEvent('change')
|
5194 | expect(atEvs.length).to.equal 2
|
5195 |
|
5196 | binding.removeEvent 'clicker'
|
5197 | expect(atEvs.length).to.equal 2
|
5198 |
|
5199 | binding.removeEvent 'click'
|
5200 | expect(atEvs.length).to.equal 1
|
5201 |
|
5202 | binding.removeEvent 'change'
|
5203 | expect(atEvs.length).to.equal 0
|
5204 |
|
5205 | restartSandbox()
|
5206 |
|
5207 |
|
5208 |
|
5209 | test "Will use the default event methods if the supplied custom methods don't exist", ()->
|
5210 | binding = SimplyBind('inheritedProp').of(eventEmitterA).to('prop1').of(objectA).updateDepsOnEvent('click', 'customAdd')
|
5211 |
|
5212 | binding.set 'one'
|
5213 | expect(objectA.prop1).to.equal 'one'
|
5214 |
|
5215 | eventEmitterA.inheritedProp = 'two'
|
5216 | expect(objectA.prop1).to.equal 'one'
|
5217 |
|
5218 | eventEmitterA.emit 'click'
|
5219 | expect(objectA.prop1).to.equal 'two'
|
5220 |
|
5221 | binding.removeEvent 'click', 'customRemove'
|
5222 | eventEmitterA.inheritedProp = 'three'
|
5223 | expect(objectA.prop1).to.equal 'two'
|
5224 |
|
5225 | eventEmitterA.emit 'click'
|
5226 | expect(objectA.prop1).to.equal 'two'
|
5227 | restartSandbox()
|
5228 |
|
5229 |
|
5230 |
|
5231 | test "Can use jQuery's .on and .off methods on DOM elements", ()-> if not isBrowser then @skip() else
|
5232 | $h1 = $regAH1
|
5233 | binding = SimplyBind('attr:data-attr').of($h1).to('prop1').of(objectA).updateDepsOnEvent('customevent', 'on')
|
5234 |
|
5235 | binding.set 'one'
|
5236 | expect(objectA.prop1).to.equal 'one'
|
5237 |
|
5238 | $h1.attr 'data-attr', 'two'
|
5239 | expect(objectA.prop1).to.equal 'one'
|
5240 |
|
5241 | $h1.trigger 'customevent'
|
5242 | expect(objectA.prop1).to.equal 'two'
|
5243 | binding.removeEvent 'customevent', 'off'
|
5244 |
|
5245 | $h1.attr 'data-attr', 'three'
|
5246 | expect(objectA.prop1).to.equal 'two'
|
5247 |
|
5248 | $h1.trigger 'customevent'
|
5249 | expect(objectA.prop1).to.equal 'two'
|
5250 |
|
5251 |
|
5252 |
|
5253 |
|
5254 |
|
5255 |
|
5256 |
|
5257 |
|
5258 |
|
5259 |
|
5260 |
|
5261 |
|
5262 |
|
5263 |
|
5264 |
|
5265 |
|
5266 |
|
5267 |
|
5268 |
|
5269 | suite ".throttle()", ()->
|
5270 | suiteSetup(restartSandbox)
|
5271 | test "Will throttle the dep update frequency to once in a given timeframe", (done)->
|
5272 | invokeCount = 0
|
5273 | lastValue = null
|
5274 | dispatcher = 'prop':1
|
5275 |
|
5276 | SimplyBind('prop').of(dispatcher)
|
5277 | .to (v)-> lastValue=v; invokeCount++
|
5278 | .throttle(15)
|
5279 |
|
5280 | expect(invokeCount).to.equal(1)
|
5281 | expect(lastValue).to.equal(1)
|
5282 |
|
5283 | dispatcher.prop = 2
|
5284 | dispatcher.prop = 3
|
5285 | dispatcher.prop = 4
|
5286 | dispatcher.prop = 5
|
5287 | expect(invokeCount).to.equal(2)
|
5288 | expect(lastValue).to.equal(2)
|
5289 |
|
5290 | setTimeout ()->
|
5291 | expect(invokeCount).to.equal(3)
|
5292 | expect(lastValue).to.equal(5)
|
5293 | done()
|
5294 | , 25
|
5295 |
|
5296 |
|
5297 | test "Will remove existing throttles if passed boolean false", ()->
|
5298 | invokeCount = 0
|
5299 | lastValue = null
|
5300 | dispatcher = 'prop':1
|
5301 |
|
5302 | binding = SimplyBind('prop').of(dispatcher)
|
5303 | .to (v)-> lastValue=v; invokeCount++
|
5304 | .throttle(15)
|
5305 |
|
5306 | expect(invokeCount).to.equal(1)
|
5307 | expect(lastValue).to.equal(1)
|
5308 |
|
5309 | binding.throttle(false)
|
5310 | dispatcher.prop = 2
|
5311 | dispatcher.prop = 3
|
5312 | dispatcher.prop = 4
|
5313 | dispatcher.prop = 5
|
5314 | expect(invokeCount).to.equal(5)
|
5315 | expect(lastValue).to.equal(5)
|
5316 |
|
5317 |
|
5318 |
|
5319 |
|
5320 |
|
5321 |
|
5322 |
|
5323 |
|
5324 |
|
5325 |
|
5326 |
|
5327 |
|
5328 |
|
5329 |
|
5330 |
|
5331 |
|
5332 |
|
5333 |
|
5334 |
|
5335 |
|
5336 |
|
5337 |
|
5338 |
|
5339 |
|
5340 |
|
5341 |
|
5342 |
|
5343 |
|
5344 |
|
5345 |
|
5346 | suite "SimplyBind.unBindAll", ()->
|
5347 | suite "Will unBind all bindings, but only in one direction", ()->
|
5348 | suiteSetup(restartSandbox)
|
5349 |
|
5350 | test "ObjectProp", ()->
|
5351 | SimplyBind('prop1').of(objectA)
|
5352 | .to('prop1').of(objectB).bothWays()
|
5353 |
|
5354 | SimplyBind('prop2').of(objectA)
|
5355 | .to('prop2').of(objectB).bothWays()
|
5356 |
|
5357 | objectA.prop1 = 'objectA.prop1'
|
5358 | expect(objectA.prop1).to.equal 'objectA.prop1'
|
5359 | expect(objectB.prop1).to.equal 'objectA.prop1'
|
5360 |
|
5361 | objectB.prop2 = 'objectB.prop2'
|
5362 | expect(objectA.prop2).to.equal 'objectB.prop2'
|
5363 | expect(objectB.prop2).to.equal 'objectB.prop2'
|
5364 |
|
5365 | objectB.prop1 = 'reset'
|
5366 | objectB.prop2 = 'reset'
|
5367 | SimplyBind.unBindAll(objectA)
|
5368 |
|
5369 | objectA.prop1 = 'objectA.prop1'
|
5370 | expect(objectA.prop1).to.equal 'objectA.prop1'
|
5371 | expect(objectB.prop1).to.equal 'reset'
|
5372 |
|
5373 | objectA.prop2 = 'objectA.prop2'
|
5374 | expect(objectA.prop2).to.equal 'objectA.prop2'
|
5375 | expect(objectB.prop2).to.equal 'reset'
|
5376 |
|
5377 | objectB.prop2 = 'objectB.prop2'
|
5378 | expect(objectA.prop2).to.equal 'objectB.prop2'
|
5379 | expect(objectB.prop2).to.equal 'objectB.prop2'
|
5380 |
|
5381 | restartSandbox()
|
5382 |
|
5383 |
|
5384 |
|
5385 | test "DOMText", ()-> if not isBrowser then @skip() else
|
5386 | SimplyBind('textContent').of(regA)
|
5387 | .to('textContent').of(regB).bothWays()
|
5388 |
|
5389 | SimplyBind('textContent').of(regA).set 'regA.textContent'
|
5390 | expect(regA.textContent).to.equal 'regA.textContent'
|
5391 | expect(regB.textContent).to.equal 'regA.textContent'
|
5392 |
|
5393 | SimplyBind('textContent').of(regB).set 'reset'
|
5394 | SimplyBind.unBindAll(regA)
|
5395 |
|
5396 | SimplyBind('textContent').of(regA).set 'regA.textContent'
|
5397 | expect(regA.textContent).to.equal 'regA.textContent'
|
5398 | expect(regB.textContent).to.equal 'reset'
|
5399 |
|
5400 | SimplyBind('textContent').of(regB).set 'regB.textContent'
|
5401 | expect(regA.textContent).to.equal 'regB.textContent'
|
5402 | expect(regB.textContent).to.equal 'regB.textContent'
|
5403 |
|
5404 | restartSandbox()
|
5405 |
|
5406 |
|
5407 |
|
5408 | test "DOMValue", ()-> if not isBrowser then @skip() else
|
5409 | SimplyBind('value').of(inputA)
|
5410 | .to('value').of(inputB).bothWays()
|
5411 |
|
5412 | inputA.value = 'inputA.value'
|
5413 | inputA.emit 'change'
|
5414 | expect(inputA.value).to.equal 'inputA.value'
|
5415 | expect(inputB.value).to.equal 'inputA.value'
|
5416 |
|
5417 |
|
5418 | inputB.value = 'reset'
|
5419 | SimplyBind.unBindAll($inputA)
|
5420 |
|
5421 | inputA.value = 'inputA.value'
|
5422 | inputA.emit 'change'
|
5423 | expect(inputA.value).to.equal 'inputA.value'
|
5424 | expect(inputB.value).to.equal 'reset'
|
5425 |
|
5426 | inputB.value = 'inputB.value'
|
5427 | inputB.emit 'change'
|
5428 | expect(inputA.value).to.equal 'inputB.value'
|
5429 | expect(inputB.value).to.equal 'inputB.value'
|
5430 |
|
5431 | restartSandbox()
|
5432 |
|
5433 |
|
5434 |
|
5435 | test "Array", ()->
|
5436 | SimplyBind(arrayA, {'trackArrayChildren':true})
|
5437 | .to('prop1').of(objectA)
|
5438 | .and('prop1').of(objectB)
|
5439 |
|
5440 | expect(objectA.prop1).to.equal arrayA
|
5441 | expect(objectB.prop1).to.equal arrayA
|
5442 |
|
5443 | objectA.prop1 = 'reset'
|
5444 | objectB.prop1 = 'reset'
|
5445 | arrayA.push(1)
|
5446 | expect(objectA.prop1).to.equal arrayA
|
5447 | expect(objectB.prop1).to.equal arrayA
|
5448 |
|
5449 | objectA.prop1 = 'reset'
|
5450 | objectB.prop1 = 'reset'
|
5451 | arrayA[5] = 19
|
5452 | expect(objectA.prop1).to.equal arrayA
|
5453 | expect(objectB.prop1).to.equal arrayA
|
5454 |
|
5455 |
|
5456 |
|
5457 | objectA.prop1 = 'reset'
|
5458 | objectB.prop1 = 'reset'
|
5459 |
|
5460 | SimplyBind.unBindAll(arrayA)
|
5461 | arrayA.push(1)
|
5462 | arrayA[3] = 23
|
5463 | expect(objectA.prop1).to.equal 'reset'
|
5464 | expect(objectB.prop1).to.equal 'reset'
|
5465 | restartSandbox()
|
5466 |
|
5467 |
|
5468 |
|
5469 | test "Function", ()->
|
5470 | passedValue = null
|
5471 | valueToPass = 1
|
5472 | takeFromReceiver = false
|
5473 | fn = (fromReceiver)-> passedValue = if takeFromReceiver then fromReceiver else valueToPass
|
5474 | invoker = 'prop':'value'
|
5475 | receiver = 'prop':undefined
|
5476 |
|
5477 | SimplyBind('prop').of(invoker).to(fn)
|
5478 | SimplyBind(fn).to('prop').of(receiver).bothWays()
|
5479 |
|
5480 | expect(receiver.prop).to.equal 1
|
5481 | expect(passedValue).to.equal 1
|
5482 |
|
5483 | valueToPass = 5
|
5484 | invoker.prop = 'anotherValue'
|
5485 | expect(receiver.prop).to.equal 5
|
5486 | expect(passedValue).to.equal 5
|
5487 |
|
5488 | takeFromReceiver = true
|
5489 | receiver.prop = 10
|
5490 | takeFromReceiver = false
|
5491 | expect(passedValue).to.equal 10
|
5492 |
|
5493 |
|
5494 | SimplyBind.unBindAll(fn)
|
5495 | valueToPass = 15
|
5496 | invoker.prop = 'newValue'
|
5497 | expect(receiver.prop).to.equal 10
|
5498 | expect(passedValue).to.equal 15
|
5499 |
|
5500 | takeFromReceiver = true
|
5501 | receiver.prop = 20
|
5502 | takeFromReceiver = false
|
5503 | expect(passedValue).to.equal 20
|
5504 |
|
5505 |
|
5506 |
|
5507 | test "Event", ()->
|
5508 | eventInvokeCount = 0
|
5509 | eventObject = null
|
5510 | objectA.prop = objectB.prop = 'someValue'
|
5511 | eventEmitterA.on 'someEvent', (event)-> eventObject = event or @
|
5512 |
|
5513 | binding = SimplyBind(0).ofEvent('someEvent').of(eventEmitterA).transformSelf ()-> eventObject
|
5514 | .to('prop').of(objectA).bothWays()
|
5515 | .and('prop').of(objectB).bothWays()
|
5516 | .and ()-> eventInvokeCount++
|
5517 |
|
5518 |
|
5519 | eventEmitterA.emit 'someEvent'
|
5520 | expect(objectA.prop).to.equal eventObject
|
5521 | expect(objectB.prop).to.equal(objectA.prop)
|
5522 | expect(eventInvokeCount).to.equal 1
|
5523 |
|
5524 |
|
5525 | objectA.prop = 'different value'
|
5526 | expect(objectA.prop).to.equal 'different value'
|
5527 |
|
5528 | expect(eventInvokeCount).to.equal 2
|
5529 |
|
5530 | objectB.prop = 'different value2'
|
5531 | expect(eventInvokeCount).to.equal 3
|
5532 |
|
5533 |
|
5534 | SimplyBind.unBindAll(eventEmitterA)
|
5535 | objectA.prop = 'different value'
|
5536 | eventEmitterA.emit 'someEvent'
|
5537 | eventEmitterA.on 'someEvent', ()-> eventInvokeCount++
|
5538 |
|
5539 | expect(objectA.prop).to.equal 'different value'
|
5540 | expect(objectB.prop).to.equal 'different value2'
|
5541 | expect(eventInvokeCount).to.equal 3
|
5542 |
|
5543 |
|
5544 | objectA.prop = 'another value'
|
5545 | expect(objectA.prop).to.equal 'another value'
|
5546 | expect(objectB.prop).to.equal 'different value2'
|
5547 |
|
5548 | objectB.prop = 'another value2'
|
5549 | expect(objectA.prop).to.equal 'another value'
|
5550 | expect(objectB.prop).to.equal 'another value2'
|
5551 | expect(eventInvokeCount).to.equal 5
|
5552 | expect(binding._.deps.length).to.equal 0
|
5553 |
|
5554 | restartSandbox()
|
5555 |
|
5556 |
|
5557 |
|
5558 |
|
5559 |
|
5560 | suite "Will unBind all bindings in both directions if passed true as the second argument", ()->
|
5561 | suiteSetup(restartSandbox)
|
5562 |
|
5563 | test "ObjectProp", ()->
|
5564 | SimplyBind('prop1').of(objectA)
|
5565 | .to('prop1').of(objectB).bothWays()
|
5566 |
|
5567 | SimplyBind('prop2').of(objectA)
|
5568 | .to('prop2').of(objectB).bothWays()
|
5569 |
|
5570 | objectA.prop1 = 'objectA.prop1'
|
5571 | expect(objectA.prop1).to.equal 'objectA.prop1'
|
5572 | expect(objectB.prop1).to.equal 'objectA.prop1'
|
5573 |
|
5574 | objectB.prop2 = 'objectB.prop2'
|
5575 | expect(objectA.prop2).to.equal 'objectB.prop2'
|
5576 | expect(objectB.prop2).to.equal 'objectB.prop2'
|
5577 |
|
5578 | objectB.prop1 = 'reset'
|
5579 | objectB.prop2 = 'reset'
|
5580 | SimplyBind.unBindAll(objectA, true)
|
5581 |
|
5582 | objectA.prop1 = 'objectA.prop1'
|
5583 | expect(objectA.prop1).to.equal 'objectA.prop1'
|
5584 | expect(objectB.prop1).to.equal 'reset'
|
5585 |
|
5586 | objectA.prop2 = 'objectA.prop2'
|
5587 | expect(objectA.prop2).to.equal 'objectA.prop2'
|
5588 | expect(objectB.prop2).to.equal 'reset'
|
5589 |
|
5590 | objectB.prop2 = 'objectB.prop2'
|
5591 | expect(objectA.prop2).to.equal 'objectA.prop2'
|
5592 | expect(objectB.prop2).to.equal 'objectB.prop2'
|
5593 |
|
5594 | restartSandbox()
|
5595 |
|
5596 |
|
5597 |
|
5598 | test "DOMText", ()-> if not isBrowser then @skip() else
|
5599 | SimplyBind('textContent').of(regA)
|
5600 | .to('textContent').of(regB).bothWays()
|
5601 |
|
5602 | SimplyBind('textContent').of(regA).set 'regA.textContent'
|
5603 | expect(regA.textContent).to.equal 'regA.textContent'
|
5604 | expect(regB.textContent).to.equal 'regA.textContent'
|
5605 |
|
5606 | SimplyBind('textContent').of(regB).set 'reset'
|
5607 | SimplyBind.unBindAll(regA, true)
|
5608 |
|
5609 | SimplyBind('textContent').of(regA).set 'regA.textContent'
|
5610 | expect(regA.textContent).to.equal 'regA.textContent'
|
5611 | expect(regB.textContent).to.equal 'reset'
|
5612 |
|
5613 | SimplyBind('textContent').of(regB).set 'regB.textContent'
|
5614 | expect(regA.textContent).to.equal 'regA.textContent'
|
5615 | expect(regB.textContent).to.equal 'regB.textContent'
|
5616 |
|
5617 | restartSandbox()
|
5618 |
|
5619 |
|
5620 |
|
5621 | test "DOMValue", ()-> if not isBrowser then @skip() else
|
5622 | SimplyBind('value').of(inputA)
|
5623 | .to('value').of(inputB).bothWays()
|
5624 |
|
5625 | inputA.value = 'inputA.value'
|
5626 | inputA.emit 'change'
|
5627 | expect(inputA.value).to.equal 'inputA.value'
|
5628 | expect(inputB.value).to.equal 'inputA.value'
|
5629 |
|
5630 |
|
5631 | inputB.value = 'reset'
|
5632 | SimplyBind.unBindAll(inputA, true)
|
5633 |
|
5634 | inputA.value = 'inputA.value'
|
5635 | inputA.emit 'change'
|
5636 | expect(inputA.value).to.equal 'inputA.value'
|
5637 | expect(inputB.value).to.equal 'reset'
|
5638 |
|
5639 | inputB.value = 'inputB.value'
|
5640 | inputB.emit 'change'
|
5641 | expect(inputA.value).to.equal 'inputA.value'
|
5642 | expect(inputB.value).to.equal 'inputB.value'
|
5643 |
|
5644 | restartSandbox()
|
5645 |
|
5646 |
|
5647 |
|
5648 | test "Function", ()->
|
5649 | passedValue = null
|
5650 | valueToPass = 1
|
5651 | takeFromReceiver = false
|
5652 | fn = (fromReceiver)-> passedValue = if takeFromReceiver then fromReceiver else valueToPass
|
5653 | invoker = 'prop':'value'
|
5654 | receiver = 'prop':undefined
|
5655 |
|
5656 | SimplyBind('prop').of(invoker).to(fn)
|
5657 | SimplyBind(fn).to('prop').of(receiver).bothWays()
|
5658 |
|
5659 | expect(receiver.prop).to.equal 1
|
5660 | expect(passedValue).to.equal 1
|
5661 |
|
5662 | valueToPass = 5
|
5663 | invoker.prop = 'anotherValue'
|
5664 | expect(receiver.prop).to.equal 5
|
5665 | expect(passedValue).to.equal 5
|
5666 |
|
5667 | takeFromReceiver = true
|
5668 | receiver.prop = 10
|
5669 | takeFromReceiver = false
|
5670 | expect(passedValue).to.equal 10
|
5671 |
|
5672 |
|
5673 | SimplyBind.unBindAll(fn, true)
|
5674 | valueToPass = 15
|
5675 | invoker.prop = 'newValue'
|
5676 | expect(receiver.prop).to.equal 10
|
5677 | expect(passedValue).to.equal 15
|
5678 |
|
5679 | takeFromReceiver = true
|
5680 | receiver.prop = 20
|
5681 | takeFromReceiver = false
|
5682 | expect(passedValue).to.equal 15
|
5683 |
|
5684 |
|
5685 |
|
5686 | test "Event", ()->
|
5687 | eventInvokeCount = 0
|
5688 | eventObject = null
|
5689 | objectA.prop = objectB.prop = 'someValue'
|
5690 | eventEmitterA.on 'someEvent', (event)-> eventObject = event or @
|
5691 |
|
5692 | binding = SimplyBind(0).ofEvent('someEvent').of(eventEmitterA).transformSelf ()-> eventObject
|
5693 | .to('prop').of(objectA).bothWays()
|
5694 | .and('prop').of(objectB).bothWays()
|
5695 | .and ()-> eventInvokeCount++
|
5696 |
|
5697 |
|
5698 | eventEmitterA.emit 'someEvent'
|
5699 | expect(objectA.prop).to.equal eventObject
|
5700 | expect(objectB.prop).to.equal(objectA.prop)
|
5701 | expect(eventInvokeCount).to.equal 1
|
5702 |
|
5703 |
|
5704 | objectA.prop = 'different value'
|
5705 | expect(objectA.prop).to.equal 'different value'
|
5706 |
|
5707 | expect(eventInvokeCount).to.equal 2
|
5708 |
|
5709 | objectB.prop = 'different value2'
|
5710 | expect(eventInvokeCount).to.equal 3
|
5711 |
|
5712 |
|
5713 | SimplyBind.unBindAll(eventEmitterA, true)
|
5714 | objectA.prop = 'different value'
|
5715 | eventEmitterA.emit 'someEvent'
|
5716 | eventEmitterA.on 'someEvent', ()-> eventInvokeCount++
|
5717 |
|
5718 | expect(objectA.prop).to.equal 'different value'
|
5719 | expect(objectB.prop).to.equal 'different value2'
|
5720 | expect(eventInvokeCount).to.equal 3
|
5721 |
|
5722 |
|
5723 | objectA.prop = 'another value'
|
5724 | expect(objectA.prop).to.equal 'another value'
|
5725 | expect(objectB.prop).to.equal 'different value2'
|
5726 |
|
5727 | objectB.prop = 'another value2'
|
5728 | expect(objectA.prop).to.equal 'another value'
|
5729 | expect(objectB.prop).to.equal 'another value2'
|
5730 | expect(eventInvokeCount).to.equal 3
|
5731 | expect(binding._.deps.length).to.equal 0
|
5732 |
|
5733 | restartSandbox()
|
5734 |
|
5735 |
|
5736 |
|
5737 |
|
5738 |
|
5739 |
|
5740 |
|
5741 |
|
5742 |
|
5743 | test "Passing objects that were never bound to anything should have no effects and shouldn't trigger any errors", ()->
|
5744 | expect(()->
|
5745 | SimplyBind.unBindAll 'nonbinded': 'object'
|
5746 | SimplyBind.unBindAll 'string'
|
5747 | SimplyBind('prop1').of(objectA).to ()->
|
5748 | SimplyBind.unBindAll objectA
|
5749 | SimplyBind.unBindAll objectA
|
5750 | ).not.to.throw()
|
5751 |
|
5752 |
|
5753 |
|
5754 |
|
5755 |
|
5756 |
|
5757 |
|
5758 |
|
5759 |
|
5760 |
|
5761 |
|
5762 |
|
5763 |
|
5764 |
|
5765 |
|
5766 |
|
5767 |
|
5768 |
|
5769 |
|
5770 |
|
5771 |
|
5772 |
|
5773 |
|
5774 |
|
5775 |
|
5776 |
|
5777 |
|