/* global define, describe, it, expect, beforeEach, sinon */ define(['directive', 'update-dom', 'js-helpers', 'dom-helpers'], function(Directive, updateDOM, _, $) { "use strict"; describe('muuDirective', function() { var registry; beforeEach(function() { registry = { linkAll: sinon.spy(), renderer: sinon.spy(function(template) { return template; }), updateDOM: updateDOM, events: ['keydown', 'keyup', 'click', 'change', 'search'], }; }); describe('update', function() { it('renders the new data to the DOM', function() { var element = document.createElement('div'); var template = 'foo bar'; var directive = new Directive(element, template, registry); var data = 'testdata'; directive.update(data); expect(registry.renderer.calledWith(template, data)).to.be(true); expect(element.querySelector('.test').textContent).to.equal('foo bar'); data = 5; directive.update(data); expect(registry.renderer.calledWith(template, data)).to.be(true); }); it('registers event aliases', function() { var element = document.createElement('div'); var template = ''; var directive = new Directive(element, template, registry); directive.update({}); var button = element.querySelector('.button'); var spy = sinon.spy(); element.addEventListener('muu-test', spy, false); expect(spy.callCount).to.equal(0); button.dispatchEvent($.createEvent('click')); expect(spy.callCount).to.equal(1); button.dispatchEvent($.createEvent('click')); expect(spy.callCount).to.equal(2); button.dispatchEvent($.createEvent('click')); expect(spy.callCount).to.equal(3); }); it('registers event aliases for non-target elements', function() { var element = document.createElement('div'); var template = '
'; var directive = new Directive(element, template, registry); directive.update({}); var button = element.querySelector('.button'); var spy = sinon.spy(); element.addEventListener('muu-test', spy, false); document.body.appendChild(element); expect(spy.callCount).to.equal(0); button.dispatchEvent($.createEvent('click', true)); expect(spy.callCount).to.equal(1); button.dispatchEvent($.createEvent('click', true)); expect(spy.callCount).to.equal(2); button.dispatchEvent($.createEvent('click', true)); expect(spy.callCount).to.equal(3); document.body.removeChild(element); }); it('initialises new child directives', function() { var element = document.createElement('div'); var template = ''; var directive = new Directive(element, template, registry); directive.update({}); expect(registry.linkAll.calledWith(directive)).to.be(true); }); it('triggers the "muu-parent-update" event on child directives', function() { var element = document.createElement('div'); var template = ''; var directive = new Directive(element, template, registry); directive.update({}); var subdirective = element.querySelector('muu'); var spy = sinon.spy(); subdirective.addEventListener('muu-parent-update', spy, false); expect(spy.callCount).to.equal(0); directive.update({}); expect(spy.callCount).to.equal(1); directive.update({}); expect(spy.callCount).to.equal(2); directive.update({}); expect(spy.callCount).to.equal(3); }); }); describe('querySelectorAll', function() { it('returns the first matching descendant that is not isolated', function() { var element = document.createElement('div'); var template = '
1
'; template += '2'; template += '3'; var directive = new Directive(element, template, registry); directive.update({}); var results = directive.querySelectorAll('.test'); expect(_.map(results, function(r) { return r.textContent; })).to.eql(['2', '3']); }); }); describe('querySelector', function() { it('returns the first matching descendant that is not isolated', function() { var element = document.createElement('div'); var template = '
1
'; template += '2'; template += '3'; var directive = new Directive(element, template, registry); directive.update({}); expect(directive.querySelector('.test').textContent).to.equal('2'); }); }); describe('on', function() { var directive; var button; beforeEach(function() { var element = document.createElement('div'); var template = ''; directive = new Directive(element, template, registry); directive.update({}); button = element.querySelector('.button'); }); it('registers an event listener for an event alias', function() { var spy = sinon.spy(); directive.on('test', spy); expect(spy.callCount).to.equal(0); button.dispatchEvent($.createEvent('click')); expect(spy.callCount).to.equal(1); button.dispatchEvent($.createEvent('click')); expect(spy.callCount).to.equal(2); button.dispatchEvent($.createEvent('click')); expect(spy.callCount).to.equal(3); }); it('calls callback with original event', function() { var spy = sinon.spy(); directive.on('test', spy); button.dispatchEvent($.createEvent('click', undefined, undefined, 'asd')); expect(spy.firstCall.args[0].detail).to.equal('asd'); }); it('can register more than one event listener', function() { var spy1 = sinon.spy(); directive.on('test', spy1); expect(spy1.callCount).to.equal(0); button.dispatchEvent($.createEvent('click')); expect(spy1.callCount).to.equal(1); var spy2 = sinon.spy(); directive.on('test', spy2); expect(spy2.callCount).to.equal(0); button.dispatchEvent($.createEvent('click')); expect(spy1.callCount).to.equal(2); expect(spy2.callCount).to.equal(1); button.dispatchEvent($.createEvent('click')); expect(spy1.callCount).to.equal(3); expect(spy2.callCount).to.equal(2); }); it('returns an unregister function', function() { var spy = sinon.spy(); var unregister = directive.on('test', spy); expect(spy.callCount).to.equal(0); button.dispatchEvent($.createEvent('click')); expect(spy.callCount).to.equal(1); unregister(); button.dispatchEvent($.createEvent('click')); expect(spy.callCount).to.equal(1); button.dispatchEvent($.createEvent('click')); expect(spy.callCount).to.equal(1); }); }); describe('getModel', function() { var directive; beforeEach(function() { var element = document.createElement('div'); var template = ''; template += ''; template += ''; template += ''; template += ''; directive = new Directive(element, template, registry); directive.update({}); }); it('returns the value of the form input with the specified name', function() { expect(directive.getModel('test')).to.equal('foobar'); }); it('still returns the value of the form input with the specified name if it is empty', function() { expect(directive.getModel('test-empty')).to.equal(''); }); it('returns default if no input with the specified name exists', function() { expect(directive.getModel('noexistent')).to.be(undefined); expect(directive.getModel('noexistent', 123)).to.be(123); }); it('returns a boolean for checkboxes', function() { expect(directive.getModel('yes')).to.be(true); expect(directive.getModel('no')).to.be(false); }); it('returns the selected value for radioboxes', function() { expect(directive.getModel('test-radio')).to.equal('foo'); }); it('returns the selected value as number for number input', function() { expect(directive.getModel('test-number')).to.equal(1.5); }); it('returns all formdata as a flat object if no name is specified', function() { expect(directive.getModel()).to.eql({ test: 'foobar', 'test-empty': '', yes: true, no: false, 'test-radio': 'foo', 'test-number': 1.5 }); }); }); describe('setModel', function() { var directive; var element; var byName = function(name) { return element.querySelector('[name=' + name + ']'); }; beforeEach(function() { element = document.createElement('div'); var template = ''; template += ''; template += ''; directive = new Directive(element, template, registry); directive.update({}); }); it('sets the value of the form input with the specified name', function() { directive.setModel('test', 'baz'); expect(byName('test').value).to.equal('baz'); }); it('sets the checked property on checkboxes', function() { directive.setModel('test-check', true); expect(byName('test-check').checked).to.be(true); directive.setModel('test-check', false); expect(byName('test-check').checked).to.be(false); directive.setModel('test-check', true); expect(byName('test-check').checked).to.be(true); }); it('sets the checked property on radioboxes', function() { var choices = element.querySelectorAll('[name=test-model]'); directive.setModel('test-radio', 'foo'); for (var i = 0; i < choices.length; i++) { expect(choices[i].checked).to.be(i === 0); } directive.setModel('test-radio', 'bar'); for (i = 0; i < choices.length; i++) { expect(choices[i].checked).to.be(i === 1); } directive.setModel('test-radio', 'baz'); for (i = 0; i < choices.length; i++) { expect(choices[i].checked).to.be(false); } }); it('throws if no input with the specified name exists', function() { expect(directive.setModel).withArgs('noexistent', 123).to.throwError(); }); }); }); });