UNPKG

@danielkalen/simplybind

Version:

Magically simple, framework-less one-way/two-way data binding for frontend/backend in ~5kb.

299 lines (225 loc) 10.1 kB
suite "Array", ()-> test "Can bind an array property using 'array:' descriptor and update subscribers when calling the .push, .pop, .shift, .unshift, .splice, .reverse, and .sort methods", ()-> mutations = 0 SimplyBind('array:list').of(objectA).to('prop4').of(objectB).and.to ()-> mutations++ expect(objectB.prop4.length).to.equal 10 expect(mutations).to.equal 1 objectA.list.push 11 expect(objectB.prop4.length).to.equal 11 expect(mutations).to.equal 2 objectA.list.shift() objectA.list.shift() expect(objectB.prop4.length).to.equal 9 expect(mutations).to.equal 4 objectA.list.unshift 2 objectA.list.unshift 1 expect(objectB.prop4.length).to.equal 11 expect(mutations).to.equal 6 objectA.list.pop() objectA.list.pop() expect(objectB.prop4.length).to.equal 9 expect(mutations).to.equal 8 objectA.list.splice 0, 5 expect(objectB.prop4.length).to.equal 4 expect(mutations).to.equal 9 objectA.list.reverse() expect(objectB.prop4.length).to.equal 4 expect(mutations).to.equal 10 objectA.list.sort() expect(objectB.prop4.length).to.equal 4 expect(mutations).to.equal 11 objectA.list.sort ()-> 1 expect(objectB.prop4.length).to.equal 4 expect(mutations).to.equal 12 restartSandbox() test "If the array binding receives an update of another array, it will discard the previous array and make the new array 'live'", ()-> invokeCount = 0 originalArray = objectA.list SimplyBind('array:list').of(objectA).to('prop4').of(objectB).and.to ()-> invokeCount++ expect(objectB.prop4).to.equal(originalArray) expect(invokeCount).to.equal 1 objectB.prop4 = 'reset' originalArray.sort() expect(objectB.prop4).to.equal(originalArray) expect(invokeCount).to.equal 2 objectA.list = [1,2,3,4,5,6,7] newArray = objectA.list expect(objectB.prop4).to.equal(newArray) expect(invokeCount).to.equal 3 originalArray.sort() expect(objectB.prop4).to.equal(newArray) expect(invokeCount).to.equal 3 newArray.sort() expect(objectB.prop4).to.equal(newArray) expect(invokeCount).to.equal 4 newArray.push 8 originalArray.push 8 expect(objectB.prop4).to.equal(newArray) expect(invokeCount).to.equal 5 newArray.shift() originalArray.shift() expect(objectB.prop4).to.equal(newArray) expect(invokeCount).to.equal 6 newArray.unshift 1 originalArray.unshift 1 expect(objectB.prop4).to.equal(newArray) expect(invokeCount).to.equal 7 newArray.pop() originalArray.pop() expect(objectB.prop4).to.equal(newArray) expect(invokeCount).to.equal 8 newArray.splice 0, 5 originalArray.splice 0, 5 expect(objectB.prop4).to.equal(newArray) expect(invokeCount).to.equal 9 restartSandbox() test "If the array binding receives an update of another array, it will clone the new array and set it as the binding's value", ()-> invokeCount = 0 originalArray = objectA.list newArray = [1,2,3,4] SimplyBind('array:list').of(objectA).to ()-> invokeCount++ expect(objectA.list).to.equal(originalArray) expect(invokeCount).to.equal(1) originalArray.sort() expect(objectA.list).to.equal(originalArray) expect(invokeCount).to.equal(2) objectA.list = newArray expect(objectA.list).not.to.equal(originalArray) expect(objectA.list).not.to.equal(newArray) expect(objectA.list).not.to.eql(originalArray) expect(Object.values objectA.list).to.eql(newArray) expect(invokeCount).to.equal(3) originalArray.sort() expect(objectA.list).not.to.equal(originalArray) expect(objectA.list).not.to.equal(newArray) expect(objectA.list).not.to.eql(originalArray) expect(Object.values objectA.list).to.eql(newArray) expect(invokeCount).to.equal(3) newArray.sort() expect(objectA.list).not.to.equal(originalArray) expect(objectA.list).not.to.equal(newArray) expect(objectA.list).not.to.eql(originalArray) expect(Object.values objectA.list).to.eql(newArray) expect(invokeCount).to.equal(3) objectA.list.sort() expect(objectA.list).not.to.equal(originalArray) expect(objectA.list).not.to.equal(newArray) expect(objectA.list).not.to.eql(originalArray) expect(Object.values objectA.list).to.eql(newArray) expect(invokeCount).to.equal(4) restartSandbox() test "Will update subscribers with a clone when options.sendArrayCopies is on", ()-> receivedValues = copies:{current:null, prev:null}, noCopies:{current:null, prev:null} SimplyBind('array:list').of(objectA).to (currentArray, prevArray)-> receivedValues.noCopies.current = currentArray receivedValues.noCopies.prev = prevArray expect(receivedValues.noCopies.current).to.equal(objectA.list) expect(receivedValues.noCopies.prev).to.be.undefined objectA.list.sort() expect(receivedValues.noCopies.current).to.be.instanceOf(Array) expect(receivedValues.noCopies.current).to.equal(objectA.list) expect(receivedValues.noCopies.prev).to.equal(objectA.list) SimplyBind('array:list', sendArrayCopies:true).of(objectB).to (currentArray, prevArray)-> receivedValues.copies.current = currentArray receivedValues.copies.prev = prevArray prevCurrent = receivedValues.copies.current expect(receivedValues.copies.current).to.be.instanceOf(Array) expect(receivedValues.copies.current).to.eql(Object.values objectA.list) expect(receivedValues.copies.current).not.to.equal(objectA.list) expect(receivedValues.copies.prev).to.be.undefined objectB.list.sort() expect(receivedValues.copies.current).to.eql(Object.values objectA.list) expect(receivedValues.copies.current).not.to.equal(objectA.list) expect(receivedValues.copies.current).not.to.equal(prevCurrent) expect(receivedValues.copies.prev).to.equal(prevCurrent) restartSandbox() test "If an array binding receives a value that isn't an array it'll be normalized to an array", ()-> invokeCount = 0 SimplyBind('array:list').of(objectA).to ()-> invokeCount++ expect(objectA.list).to.be.instanceOf Array expect(objectA.list.length).to.equal 10 expect(invokeCount).to.equal 1 objectA.list = 'value' expect(objectA.list).to.be.instanceOf Array expect(objectA.list.length).to.equal 1 expect(objectA.list[0]).to.equal 'value' expect(invokeCount).to.equal 2 objectA.list = [1,2,3] expect(objectA.list).to.be.instanceOf Array expect(objectA.list.length).to.equal 3 expect(Object.values objectA.list).to.eql [1,2,3] expect(invokeCount).to.equal 3 restartSandbox() test "Using array: descriptors for non-array properties will cause the binding to be a regular ObjectProp binding", ()-> interfaces = {} obj = list: [0,1,2,3] object: {} arrayLike: arguments number: 5 string: '5' undefined: undefined null: null expect(()-> interfaces.list = SimplyBind('array:list').of(obj) interfaces.object = SimplyBind('array:object').of(obj) interfaces.arrayLike = SimplyBind('array:arrayLike').of(obj) interfaces.number = SimplyBind('array:number').of(obj) interfaces.string = SimplyBind('array:string').of(obj) interfaces.undefined = SimplyBind('array:undefined').of(obj) interfaces.null = SimplyBind('array:null').of(obj) ).not.to.throw() expect(interfaces.list._.type).to.equal 'Array' expect(interfaces.object._.type, 'object').to.equal 'ObjectProp' expect(interfaces.arrayLike._.type, 'arrayLike').to.equal 'ObjectProp' expect(interfaces.number._.type, 'number').to.equal 'ObjectProp' expect(interfaces.string._.type, 'string').to.equal 'ObjectProp' expect(interfaces.undefined._.type, 'undefined').to.equal 'ObjectProp' expect(interfaces.null._.type, 'null').to.equal 'ObjectProp' test "Creating an Array binding and an ObjectProp binding on the same property should work as expected", ()-> countA = array:0, object:0 countB = array:0, object:0 lastA = array:null, object:null lastB = array:null, object:null baseArray = [0,1,2,3,4,5,6,7,8,9] SimplyBind('array:list').of(objectA).to ()-> countA.array++; lastA.array = arguments[0] SimplyBind('list').of(objectA).to ()-> countA.object++; lastA.object = arguments[0] SimplyBind('list').of(objectB).to ()-> countB.object++; lastB.object = arguments[0] SimplyBind('array:list').of(objectB).to ()-> countB.array++; lastB.array = arguments[0] expect(countA.array, 'countA.array 1').to.equal 1 expect(countA.object, 'countA.object 1').to.equal 1 expect(countB.array, 'countB.array 1').to.equal 1 expect(countB.object, 'countB.object 1').to.equal 1 expect(lastA.array, 'lastA.array 1').to.eql baseArray expect(lastA.object, 'lastA.object 1').to.eql baseArray expect(lastB.array, 'lastB.array 1').to.eql baseArray expect(lastB.object, 'lastB.object 1').to.eql baseArray expect(objectA.list, 'objectA.list 1').to.eql baseArray expect(objectB.list, 'objectB.list 1').to.eql baseArray baseP1 = baseArray.concat(10) objectA.list.push(10) objectB.list.push(10) expect(countA.array, 'countA.array 2').to.equal 2 expect(countA.object, 'countA.object 2').to.equal 1 expect(countB.array, 'countB.array 2').to.equal 2 expect(countB.object, 'countB.object 2').to.equal 1 expect(lastA.array, 'lastA.array 2').to.eql baseP1 expect(lastA.object, 'lastA.object 2').to.eql baseP1 expect(lastB.array, 'lastB.array 2').to.eql baseP1 expect(lastB.object, 'lastB.object 2').to.eql baseP1 expect(objectA.list, 'objectA.list 2').to.eql baseP1 expect(objectB.list, 'objectB.list 2').to.eql baseP1 baseP2 = baseP1.concat(11) objectA.list = baseP2.slice() objectB.list = baseP2.slice() expect(countA.array, 'countA.array 3').to.equal 3 expect(countA.object, 'countA.object 3').to.equal 2 expect(countB.array, 'countB.array 3').to.equal 3 expect(countB.object, 'countB.object 3').to.equal 2 expect(lastA.array, 'lastA.array 3').to.eql baseP2 expect(lastA.object, 'lastA.object 3').to.eql baseP2 expect(lastB.array, 'lastB.array 3').to.eql baseP2 expect(lastB.object, 'lastB.object 3').to.eql baseP2 expect(objectA.list, 'objectA.list 3').to.eql baseP2 expect(objectB.list, 'objectB.list 3').to.eql baseP2