UNPKG

backbone-skull

Version:

Skull sits on top of Backbone and protects your application's brains.

261 lines (209 loc) 9.33 kB
/* eslint-env mocha, browser, jquery */ /* global mocha, chai, Skull, _ */ (function (mocha, assert, Skull) { 'use strict'; var registry = new Skull.ResourceRegistry(); var passReg = {registry: registry}; var View = Skull.View; registry.register('template', new Skull.Template()); function createTemplate (name, content) { var tplNode = $('<script type="text/x-template" class="js-tpl-' + name + '">' + content + '</script>'); tplNode.appendTo('body'); return tplNode; } var viewNest = $('<div style="display: none"></div>').appendTo('body'); suite('.View', function () { teardown(function () { $('script[type="text/x-template"]').remove(); viewNest.html(''); }); suite('Renders correctly', function () { test('Static template', function () { createTemplate('staticTpl', '<%= 40 + 2 %>'); var el = $('<div class="js-test1"></div>').appendTo(viewNest); var StaticView = View.extend({ tpl: 'staticTpl' }); var staticView = new StaticView(_.extend({}, passReg, {el: el})); staticView.render(); assert.equal(el.html(), '42', ''); }); test('Passing data to template', function () { createTemplate('dataTpl', '<%= a + b %>'); var el = $('<div class="js-test2"></div>').appendTo(viewNest); var DataView = View.extend({ tpl: 'dataTpl' }); var data = { a: 40, b: 2 }; var dataView = new DataView(_.extend({}, passReg, {el: el, model: data})); dataView.render(); assert.equal(el.html(), '42'); }); test('Calling .toTemplate method', function () { createTemplate('modelTpl', '<%= a + b %>'); var el = $('<div class="js-test3"></div>').appendTo(viewNest); var ModelView = View.extend({ tpl: 'modelTpl' }); var model = { toTemplate: function () { return {a: 40, b: 2}; } }; var modelView = new ModelView(_.extend({}, passReg, {el: el, model: model})); modelView.render(); assert.equal(el.html(), '42'); }); }); suite('Replaces this.$el, when told so', function () { setup(function () { createTemplate('replace', '<div class="js-replacer"></div>'); }); test('Replaced entire element as intended', function () { var el = $('<div class="js-test1"></div>').appendTo(viewNest); var ReplacingView = View.extend({ tpl: 'replace', replaceEl: true }); var rView = new ReplacingView(_.extend({}, passReg, {el: el})); rView.render(); assert.ok(rView.$el.hasClass('js-replacer')); }); test('Replaced only content', function () { var el = $('<div class="js-test2"></div>').appendTo(viewNest); var SimpleView = View.extend({ tpl: 'replace', replaceEl: false }); var sView = new SimpleView(_.extend({}, passReg, {el: el})); sView.render(); assert.ok(sView.$('.js-replacer').length); }); }); suite('__ui__ and macros in selectors', function () { var el; setup(function () { createTemplate( 'macrosTpl', '<div class="js-node">' + ' <div class="js-node-inner">' + ' <button class="js-node-inner-sanctum"></button>' + ' </div>' + ' <div class="js-node-other"></div>' + '</div>' ); el = $('<div class="js-test4"></div>').appendTo(viewNest); }); var BasicMacroView = View.extend({ tpl: 'macrosTpl', __ui__: { root: '.js-node', inner: '$root-inner', btn: '$inner-sanctum', other: '$root-other' } }); test('Substitutes macros in __ui__', function () { var macroView = new BasicMacroView(_.extend({}, passReg, {el: el})); macroView.render(); assert.instanceOf(macroView.ui.inner[0], Node, 'One level unfolded ok'); assert.instanceOf(macroView.ui.btn[0], Node, 'Two levels unfolded ok'); }); test('Substitutes macros in events', function () { var clicked = false; var EventsMacroView = BasicMacroView.extend({ events: { 'click $btn': 'onBtnClick' }, onBtnClick: function () { clicked = true; } }); var eventsView = new EventsMacroView(_.extend({}, passReg, {el: el})); eventsView.render(); eventsView.ui.btn.click(); assert.ok(clicked, 'Macros unfolded in events hash'); }); test('Substitutes macros in __children__', function () { var OtherView = View.extend({}); var NestedMacroView = BasicMacroView.extend({ __children__: { $other: OtherView } }); var nestedView = new NestedMacroView(_.extend({}, passReg, {el: el})); nestedView.render(); assert.property(nestedView.children, '$other', 'Child view was created and assigned according to unfolded selector'); assert.lengthOf(nestedView.children.$other.$el, 1, 'Child view is attached to actual DOM element'); }); }); suite('re-rendering', function () { var el; var RerenderView = View.extend({ tpl: 'rerenderTemplate', initialize: function (options) { RerenderView.__super__.initialize.call(this, options); this.btnCounter = 0; this.elCounter = 0; }, __ui__: { btn: 'button' }, events: { 'click button': 'onBtnClick', 'click': 'onElClick' }, onBtnClick: function (event) { event.stopPropagation(); // or else this will trigger onElClick handler too this.btnCounter++; }, onElClick: function () { this.elCounter++; } }); var RerenderReplacingView = RerenderView.extend({ replaceEl: true }); setup(function () { createTemplate( 'rerenderTemplate', '<div>' + '<button>ᏍᏏᏆᏱ</button>' + '</div>' ); el = $('<div class="js-test5"></div>').appendTo(viewNest); }); test('correctly handles re-rendering when not replacing $el', function () { var rView = new RerenderView(_.extend({}, passReg, {el: el})); rView.render(); rView.ui.btn.click(); assert.equal(rView.btnCounter, 1, 'button counter ok'); rView.$el.click(); assert.equal(rView.elCounter, 1, '$el counter ok'); rView.render(); rView.render(); rView.ui.btn.click(); assert.equal(rView.btnCounter, 2, 'button counter ok after render called several times'); rView.$el.click(); assert.equal(rView.elCounter, 2, '$el counter ok after render called several times'); }); test('correctly handles re-rendering when replacing $el', function () { var rrView = new RerenderReplacingView(_.extend({}, passReg, {el: el})); rrView.render(); rrView.ui.btn.click(); assert.equal(rrView.btnCounter, 1, 'button counter ok'); rrView.$el.click(); assert.equal(rrView.elCounter, 1, '$el counter ok'); rrView.render(); rrView.render(); rrView.ui.btn.click(); assert.equal(rrView.btnCounter, 2, 'button counter ok after render called several times'); rrView.$el.click(); assert.equal(rrView.elCounter, 2, '$el counter ok after render called several times'); }); }); }); })(mocha, chai.assert, Skull);