UNPKG

@danielkalen/simplybind

Version:

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

393 lines (258 loc) 13 kB
suite "Placeholders", ()-> test "Property names with periods (.) indicate a placeholder", ()-> dispatcher = 'value': 'Medium' objectA.prop = 'The size of this shirt is {{size}}, man!' if isBrowser inputA.value = 'The size of this shirt is {{size}}, man!' regA.textContent = 'The size of this shirt is {{size}}, man!' regA.setAttribute 'someattr', 'The size of this shirt is {{size}}, man!' SimplyBind('value').of(dispatcher) .to('prop.size').of(objectA) if isBrowser SimplyBind('value').of(dispatcher) .to('value.size').of(inputA) .and.to('textContent.size').of(regA) .and.to('attr:someattr.size').of(regA) expect(objectA.prop).to.equal 'The size of this shirt is Medium, man!' if isBrowser expect(inputA.value).to.equal 'The size of this shirt is Medium, man!' expect(regA.textContent).to.equal 'The size of this shirt is Medium, man!' expect(regA.getAttribute 'someattr').to.equal 'The size of this shirt is Medium, man!' restartSandbox() test "No changes should be made to the string when trying to update a placeholder that doesn't exist", ()-> objectB.prop1 = 'The size of this shirt is _____, man!' binding = SimplyBind('prop1').of(objectA).to('prop1.size').of(objectB) binding.set 'Medium' expect(objectB.prop1).to.equal 'The size of this shirt is _____, man!' restartSandbox() test "The updating value doesn't have to be a string", ()-> objectB.prop1 = 'The size of this shirt is {{size}}, man!' binding = SimplyBind('prop1').of(objectA).to('prop1.size').of(objectB) binding.set false expect(objectB.prop1).to.equal 'The size of this shirt is false, man!' binding.set null expect(objectB.prop1).to.equal 'The size of this shirt is null, man!' binding.set {} expect(objectB.prop1).to.equal 'The size of this shirt is [object Object], man!' restartSandbox() test "If a property name has more than one period, only the first will be accounted for", ()-> objectB.prop1 = 'The size of this shirt is {{size.redundant}}, man!' binding = SimplyBind('prop1').of(objectA).to('prop1.size.redundant').of(objectB) binding.set 'Medium' expect(objectB.prop1).to.equal 'The size of this shirt is Medium, man!' restartSandbox() test "Custom placeholder markers can be set", ()-> SimplyBind.settings.placeholder = ['^^', '$$'] objectB.prop1 = 'The size of this shirt is ^^size$$, man!' binding = SimplyBind('prop1').of(objectA).to('prop1.size').of(objectB) binding.set 'XXS' expect(objectB.prop1).to.equal 'The size of this shirt is XXS, man!' SimplyBind.settings.placeholder = ['{{', '}}'] restartSandbox() test "Target strings can have multiple placeholders", ()-> dispatcher = 'value': 'Large' objectA.prop = 'The size of this shirt is {{size}}, and {{size}} is {{size}}ly rad!' if isBrowser inputA.value = 'The size of this shirt is {{size}}, and {{size}} is {{size}}ly rad!' regA.textContent = 'The size of this shirt is {{size}}, and {{size}} is {{size}}ly rad!' regA.setAttribute 'someattr', 'The size of this shirt is {{size}}, and {{size}} is {{size}}ly rad!' SimplyBind('value').of(dispatcher) .to('prop.size').of(objectA) if isBrowser SimplyBind('value').of(dispatcher) .to('value.size').of(inputA) .and.to('textContent.size').of(regA) .and.to('attr:someattr.size').of(regA) expect(objectA.prop).to.equal 'The size of this shirt is Large, and Large is Largely rad!' if isBrowser expect(inputA.value).to.equal 'The size of this shirt is Large, and Large is Largely rad!' expect(regA.textContent).to.equal 'The size of this shirt is Large, and Large is Largely rad!' expect(regA.getAttribute 'someattr').to.equal 'The size of this shirt is Large, and Large is Largely rad!' restartSandbox() test "Multiple values can be set for the same target that has multiple placeholders", ()-> dispatcher = 'verb': 'not' 'nounOne': 'small' 'nounTwo': 'pretty' objectB.prop = 'The following text is {{verb}} {{nounOne}} and {{nounTwo}}' if isBrowser inputB.value = 'The following text is {{verb}} {{nounOne}} and {{nounTwo}}' regB.setAttribute 'someattr', 'The following text is {{verb}} {{nounOne}} and {{nounTwo}}' SimplyBind('verb').of(dispatcher) .to('prop.verb').of(objectB) if isBrowser SimplyBind('verb').of(dispatcher) .to('value.verb').of(inputB) .and.to('textContent.verb').of(regB) .and.to('attr:someattr.verb').of(regB) SimplyBind('nounOne').of(dispatcher) .to('prop.nounOne').of(objectB) if isBrowser SimplyBind('nounOne').of(dispatcher) .to('value.nounOne').of(inputB) .and.to('textContent.nounOne').of(regB) .and.to('attr:someattr.nounOne').of(regB) SimplyBind('nounTwo').of(dispatcher) .to('prop.nounTwo').of(objectB) if isBrowser SimplyBind('nounTwo').of(dispatcher) .to('value.nounTwo').of(inputB) .and.to('textContent.nounTwo').of(regB) .and.to('attr:someattr.nounTwo').of(regB) values = ()-> if not isBrowser then [objectB.prop] else [objectB.prop, inputB.value, regB.textContent, regB.getAttribute 'someattr'] for value in values() expect(value).to.equal 'The following text is not small and pretty' dispatcher.verb = 'very' dispatcher.nounOne = 'big' dispatcher.nounTwo = 'ugly' for value in values() expect(value).to.equal 'The following text is very big and ugly' restartSandbox() test "Multiple values can be set for the same target that has multiple placeholders + transforms", ()-> dispatcher = 'verbOne': 'not' 'verbTwo': 'not' 'nounOne': 'small' 'nounTwo': 'pretty' objectC.prop = 'The following text is {{verbOne}} ({{verbTwo}}) {{nounOne}} and {{nounTwo}}' if isBrowser inputC.value = 'The following text is {{verbOne}} ({{verbTwo}}) {{nounOne}} and {{nounTwo}}' regC.textContent = 'The following text is {{verbOne}} ({{verbTwo}}) {{nounOne}} and {{nounTwo}}' regC.setAttribute 'someattr', 'The following text is {{verbOne}} ({{verbTwo}}) {{nounOne}} and {{nounTwo}}' SimplyBind('verbOne').of(dispatcher) .to('prop.verbOne').of(objectC).transform (value)-> value.toUpperCase() if isBrowser SimplyBind('verbOne').of(dispatcher) .to('value.verbOne').of(inputC) .and.to('textContent.verbOne').of(regC) .and.to('attr:someattr.verbOne').of(regC) .transformAll (value)-> value.toUpperCase() SimplyBind('verbTwo').of(dispatcher) .to('prop.verbTwo').of(objectC).transform (value)-> value.toLowerCase() if isBrowser SimplyBind('verbTwo').of(dispatcher) .to('value.verbTwo').of(inputC) .and.to('textContent.verbTwo').of(regC) .and.to('attr:someattr.verbTwo').of(regC) .transformAll (value)-> value.toLowerCase() SimplyBind('nounOne').of(dispatcher) .to('prop.nounOne').of(objectC).transform (value)-> value.toUpperCase() if isBrowser SimplyBind('nounOne').of(dispatcher) .to('value.nounOne').of(inputC) .and.to('textContent.nounOne').of(regC) .and.to('attr:someattr.nounOne').of(regC) .transformAll (value)-> value.toUpperCase() SimplyBind('nounTwo').of(dispatcher) .to('prop.nounTwo').of(objectC).transform (value)-> value.toUpperCase() if isBrowser SimplyBind('nounTwo').of(dispatcher) .to('value.nounTwo').of(inputC) .and.to('textContent.nounTwo').of(regC) .and.to('attr:someattr.nounTwo').of(regC) .transformAll (value)-> value.toUpperCase() values = ()-> if not isBrowser then [objectC.prop] else [objectC.prop, inputC.value, regC.textContent, regC.getAttribute 'someattr'] for value in values() expect(value).to.equal 'The following text is NOT (not) SMALL and PRETTY' dispatcher.verbOne = dispatcher.verbTwo = 'Very' dispatcher.nounOne = 'Big' dispatcher.nounTwo = 'Ugly' for value in values() expect(value).to.equal 'The following text is VERY (very) BIG and UGLY' restartSandbox() test "Multiple placeholder bindings to textContent with multiple placeholders in a single textNode containing nested placeholders should function properly", ()-> if not isBrowser then @skip() else dispatcher = 'wordA':'', 'wordB':'' expect(regD.textContent).to.equal 'The following {{wordA}} and {{wordB}} replaced correctly' SimplyBind('wordA').of(dispatcher) .to('textContent.wordA').of(regD) SimplyBind('wordB').of(dispatcher) .to('textContent.wordB').of(regD) expect(regD.textContent).to.equal 'The following and replaced correctly' dispatcher.wordA = 'firstWord' dispatcher.wordB = 'secondWord' expect(regD.textContent).to.equal 'The following firstWord and secondWord replaced correctly' restartSandbox() test "A single publisher can bind to more than 1 placeholder in a subscriber", ()-> dispatcher = 'prop':'value' receiver = 'prop':'{{first}} {{second}}' SimplyBind('prop').of(dispatcher) .to('prop.first').of(receiver) .and.to('prop.second').of(receiver) expect(receiver.prop).to.equal 'value value' dispatcher.prop = 'anotherValue' expect(receiver.prop).to.equal 'anotherValue anotherValue' test "A single publisher can bind to more than 1 placeholder in a subscriber + transforms", ()-> dispatcher = 'prop':'VaLuE' receiver = 'prop':'{{first}} {{second}}' SimplyBind('prop').of(dispatcher) .to('prop.first').of(receiver).transform (value)-> value.toLowerCase() .and.to('prop.second').of(receiver).transform (value)-> value.toUpperCase() expect(receiver.prop).to.equal 'value VALUE' dispatcher.prop = 'anotherValue' expect(receiver.prop).to.equal 'anothervalue ANOTHERVALUE' test "When an object prop with placeholders is an updater, it can either update individual placeholder values or its entire value", ()-> dispatcher = 'nounA':'color', 'nounB':'car', 'adverb':'very', 'color':'red' receiver = 'prop':'The {{nounA}} of this {{nounB}} is {{adverb}} {{color}}' lastReceiver = 'prop':'' SimplyBind('nounA').of(dispatcher).to('prop.nounA').of(receiver) SimplyBind('nounB').of(dispatcher).to('prop.nounB').of(receiver) SimplyBind('adverb').of(dispatcher).to('prop.adverb').of(receiver) SimplyBind('color').of(dispatcher).to('prop.color').of(receiver) expect(receiver.prop).to.equal 'The color of this car is very red' SimplyBind('prop.nounA').of(receiver) .to('prop').of(lastReceiver) expect(lastReceiver.prop).to.equal 'color' dispatcher.nounA = 'colour' expect(lastReceiver.prop).to.equal 'colour' SimplyBind('prop.nounB').of(receiver) .to('prop').of(lastReceiver) expect(lastReceiver.prop).to.equal 'car' dispatcher.nounB = 'airplane' expect(lastReceiver.prop).to.equal 'airplane' SimplyBind('prop').of(receiver) .to('prop').of(lastReceiver) expect(lastReceiver.prop).to.equal 'The colour of this airplane is very red' test "When manually changing the value of the prop after binding, the application of the placeholders will ignore the changes", ()-> if not isBrowser then @skip() else dispatcher = 'verb':'', 'nounOne':'', 'nounTwo':'' objectA.prop1 = regB.textContent SimplyBind('verb').of(dispatcher) .to('prop1.verb').of(objectA) .and.to('textContent.verb').of(regB) SimplyBind('nounOne').of(dispatcher) .to('prop1.nounOne').of(objectA) .and.to('textContent.nounOne').of(regB) SimplyBind('nounTwo').of(dispatcher) .to('prop1.nounTwo').of(objectA) .and.to('textContent.nounTwo').of(regB) dispatcher.verb = 'looking' dispatcher.nounOne = 'nice' dispatcher.nounTwo = 'long' expect(objectA.prop1).to.equal 'The following text is looking nice and long' expect(objectA.prop1).to.equal(regB.textContent) upperCaseNodes = (nodes)-> for node in nodes if node.nodeType is 3 node.textContent = node.textContent.toUpperCase() else upperCaseNodes(node) upperCaseNodes(regB.childNodes) objectA.prop1 = 'modified' dispatcher.verb = 'not looking' dispatcher.nounOne = 'ugly' dispatcher.nounTwo = 'short' expect(objectA.prop1).to.equal 'The following text is not looking ugly and short' expect(objectA.prop1).to.equal(regB.textContent) # But new text nodes won't be replaced! $regBH1.append '<span> and some other attribute</span>' dispatcher.verb = 'looking' dispatcher.nounOne = 'nice' dispatcher.nounTwo = 'long' expect(objectA.prop1).to.equal 'The following text is looking nice and long' expect(regB.textContent).to.equal 'The following text is looking nice and long and some other attribute' test "DOM Elements that contain textContent placeholders that encapsulate the entire textNode will behave normally", ()-> if not isBrowser then @skip() else regA.innerHTML = 'This <span>{{placeholder}}</span> is separated from others' expect(regA.textContent).to.equal 'This {{placeholder}} is separated from others' SimplyBind('prop').of(objectA) .to('textContent.placeholder').of(regA) objectA.prop = 'word' expect(regA.textContent).to.equal 'This word is separated from others' restartSandbox()