modules.define(
'test',
[
'y-block',
'y-block-event',
'jquery',
'inherit'
],
function (
provide,
YBlock,
YBlockEvent,
$,
inherit
) {
describe('YBlock', function () {
var modulesStorage;
beforeEach(function () {
modulesStorage = {};
sinon.stub(modules, 'require', function (blocks, callback) {
var result = blocks.map(function (blockName) {
return modulesStorage[blockName];
});
setTimeout(function () {
callback.apply(null, result);
}, 0);
});
sinon.stub(modules, 'isDefined', function (moduleName) {
return modulesStorage[moduleName];
});
});
afterEach(function () {
modules.require.restore();
modules.isDefined.restore();
});
describe('__constructor', function () {
it('should add _init class', function () {
var block = new YBlock($('
').append(subElem);
var emitter = Block.getEmitter(elem);
var subEmitter = Block.getEmitter(subElem);
var spy = sinon.spy();
emitter.on('event', spy);
subEmitter.on('event', spy);
Block._getDomNodeDataStorage(elem).blockEvents.block.should.equal(emitter);
Block._getDomNodeDataStorage(subElem).blockEvents.block.should.equal(subEmitter);
Block.destructDomTree(elem);
Block._getDomNodeDataStorage(elem).blockEvents.should.be.empty;
Block._getDomNodeDataStorage(subElem).blockEvents.should.be.empty;
var eventName = Block._getPropagationEventName('event');
elem.trigger(eventName);
subElem.trigger(eventName);
spy.called.should.be.false;
});
});
describe('emit()', function () {
var block;
var spy1;
var spy2;
beforeEach(function () {
block = new YBlock();
spy1 = sinon.spy();
spy2 = sinon.spy();
block.on('event1', spy1);
block.on('event2', spy2);
});
afterEach(function () {
block.destruct();
});
it('should emit event on block', function () {
block.emit('event1');
var event2 = new YBlockEvent('event2');
block.emit(event2);
spy1.calledOnce.should.be.true;
var e = spy1.firstCall.args[0];
e.should.be.instanceof(YBlockEvent);
e.type.should.eq('event1');
e.target.should.eq(block);
spy2.calledOnce.should.be.true;
e = spy2.firstCall.args[0];
e.should.be.eq(event2);
e.type.should.eq('event2');
e.target.should.eq(block);
});
it('should emit event width additional data', function () {
var data = {foo: 'bar'};
block.emit('event1', data);
var event2 = new YBlockEvent('event2');
block.emit(event2, data);
spy1.calledOnce.should.be.true;
var e = spy1.firstCall.args[0];
e.should.be.instanceof(YBlockEvent);
e.type.should.eq('event1');
e.target.should.eq(block);
e.data.should.eq(data);
spy2.calledOnce.should.be.true;
e = spy2.firstCall.args[0];
e.should.be.eq(event2);
e.type.should.eq('event2');
e.target.should.eq(block);
e.data.should.eq(data);
});
});
describe('getEmitter()', function () {
it('should return the same instance for same DOM node', function () {
var dom = $('
');
YBlock.getEmitter(dom).should.equal(YBlock.getEmitter(dom));
});
it('should listen handle bubbling events', function (done) {
var SubBlock = inherit(YBlock, {
__constructor: function () {
this.__base.apply(this, arguments);
this._bindTo(this._findElement('button'), 'click', function () {
this.emit('button-click');
});
}
}, {
getBlockName: function () {
return 'sub-block';
}
});
var dom = $(
'
'
);
var block = SubBlock.find(dom);
SubBlock.getEmitter(dom).on('button-click', function (event) {
event.target.should.equal(block);
done();
});
dom.find('.sub-block__button').click();
});
it('should stop propagation', function (done) {
var SubBlock = inherit(YBlock, {
__constructor: function () {
this.__base.apply(this, arguments);
this._bindTo(this._findElement('button'), 'click', function () {
this.emit('button-click');
});
}
}, {
getBlockName: function () {
return 'sub-block';
}
});
var subDom = $(
'
'
);
var clickTriggered = false;
var dom = $('
').append(subDom);
SubBlock.find(dom); // init sub-block
SubBlock.getEmitter(subDom).on('button-click', function (event) {
clickTriggered = true;
event.stopPropagation();
});
SubBlock.getEmitter(dom).on('button-click', function () {
done(new Error('Stop propagation should work'));
});
dom.find('.sub-block__button').click();
clickTriggered.should.be.true;
done();
});
});
describe('_getDomNodeDataStorage', function () {
it('should return the same instance for the same DOM node', function () {
var dom = $('
');
YBlock._getDomNodeDataStorage(dom).should.equal(YBlock._getDomNodeDataStorage(dom));
});
});
describe('_liveBindToElement', function () {
it('should catch event on element', function (done) {
var Block = inherit(YBlock, {}, {
getBlockName: function () {
return 'block1';
},
_liveInit: function () {
this._liveBindToElement('button', 'click', function () {
this.emit('button-click');
});
}
});
var block = new Block($(
'
'
));
block.getDomNode().appendTo(document.body);
block.on('button-click', function () {
block.getDomNode().remove();
done();
});
block._findElement('button').trigger('click');
});
it('should catch event on element with exact name', function () {
var Block = inherit(YBlock, {}, {
getBlockName: function () {
return 'block2';
},
_liveInit: function () {
this._liveBindToElement('button', 'click', function () {
this.emit('button-click');
});
}
});
var block = new Block($(
'
'
));
var triggerCount = 0;
block.getDomNode().appendTo(document.body);
block.on('button-click', function () {
triggerCount++;
});
block._findElement('button').trigger('click');
block._findElement('buttons').trigger('click');
block.getDomNode().remove();
triggerCount.should.equal(1);
});
});
describe('state', function () {
describe('_getState', function () {
it('should return mod value', function () {
var block = YBlock.fromDomNode(
$('
')
);
block._getState('color').should.equal('red');
block._getState('type').should.equal(false);
});
it('should return mod value after set', function () {
var block = YBlock.fromDomNode(
$('
')
);
block._getState('color').should.equal('red');
block._setState('color', 'blue');
block._getState('color').should.equal('blue');
});
it('should not return mod value after del', function () {
var block = YBlock.fromDomNode(
$('
')
);
block._getState('color').should.equal('red');
block._removeState('color');
block._getState('color').should.equal(false);
});
});
describe('_setState', function () {
it('should set mod value', function () {
var block = YBlock.fromDomNode(
$('
')
);
block._setState('color', 'red');
block.getDomNode().attr('class').should.equal('y-block _init _color_red');
block._setState('color', 'blue');
block.getDomNode().attr('class').should.equal('y-block _init _color_blue');
block._setState('color', null);
block._setState('size', 'm');
block.getDomNode().attr('class').should.equal('y-block _init _size_m');
});
});
describe('_removeState', function () {
it('should remove mod value', function () {
var block = YBlock.fromDomNode(
$('
')
);
block._removeState('color');
block.getDomNode().attr('class').should.equal('y-block _init');
block._setState('color', 'blue');
block._removeState('color');
block.getDomNode().attr('class').should.equal('y-block _init');
});
});
describe('_getState', function () {
it('should return mod value', function () {
var block = YBlock.fromDomNode(
$('
')
);
block._getState('color').should.equal('red');
block._setState('color', 'blue');
block._getState('color').should.equal('blue');
block._setState('color', null);
block._getState('color').should.equal(false);
block._setState('color', undefined);
block._getState('color').should.equal(false);
});
});
describe('_toggleState', function () {
it('should toggle mod value', function () {
var block = YBlock.fromDomNode(
$('
')
);
block._toggleState('color', 'red', false);
block._getState('color').should.equal(false);
block._toggleState('color', false, 'red');
block._getState('color').should.equal('red');
block._toggleState('color', 'red', 'blue');
block._getState('color').should.equal('blue');
block._toggleState('color', null, 'blue');
block._toggleState('color', null, 'blue');
block._getState('color').should.equal('blue');
});
});
describe('_setElementState', function () {
it('should set mod value', function () {
var block = YBlock.fromDomNode($(
'
'
));
block._setElementState(block._findElement('button'), 'color', 'red');
block._findElement('button')
.attr('class').should.equal('y-block__button _color_red');
block._setElementState(block._findElement('button'), 'color', 'blue');
block._findElement('button')
.attr('class').should.equal('y-block__button _color_blue');
block._setElementState(block._findElement('button'), 'color', '');
block._findElement('button')
.attr('class').should.equal('y-block__button');
});
it('should set true mod value', function () {
var block = YBlock.fromDomNode($(
'
'
));
block._setElementState(block._findElement('button'), 'active');
block._findElement('button')
.attr('class').should.equal('y-block__button _active');
block._setElementState(block._findElement('button'), 'active', false);
block._findElement('button')
.attr('class').should.equal('y-block__button');
});
it('should set mod value with another view', function () {
var block = YBlock.fromDomNode($(
'
'
));
block._setElementState(block._findElement('button'), 'color', 'red');
block._findElement('button')
.attr('class').should.equal('y-block_red__button _color_red');
block._setElementState(block._findElement('button'), 'color', 'blue');
block._findElement('button')
.attr('class').should.equal('y-block_red__button _color_blue');
block._setElementState(block._findElement('button'), 'color', '');
block._findElement('button')
.attr('class').should.equal('y-block_red__button');
});
});
describe('_removeElementState', function () {
it('should remove mod value', function () {
var block = YBlock.fromDomNode($(
'
'
));
block._removeElementState(block._findElement('button'), 'color');
block._findElement('button')
.attr('class').should.equal('y-block__button');
block._setElementState(block._findElement('button'), 'color', 'blue');
block._removeElementState(block._findElement('button'), 'color');
block._findElement('button')
.attr('class').should.equal('y-block__button');
});
});
describe('_getElementState', function () {
it('should return mod value', function () {
var block = YBlock.fromDomNode($(
'
'
));
var button = block._findElement('button');
block._getElementState(button, 'color').should.equal('red');
block._setElementState(button, 'color', 'blue');
block._getElementState(button, 'color').should.equal('blue');
block._setElementState(button, 'color', null);
block._getElementState(button, 'color').should.equal(false);
block._setElementState(button, 'color', undefined);
block._getElementState(button, 'color').should.equal(false);
});
});
describe('_toggleElementState', function () {
it('should toggle mod value', function () {
var block = YBlock.fromDomNode($(
'
'
));
var button = block._findElement('button');
block._toggleElementState(button, 'color', 'red', false);
block._getElementState(button, 'color').should.equal(false);
block._toggleElementState(button, 'color', false, 'red');
block._getElementState(button, 'color').should.equal('red');
block._toggleElementState(button, 'color', 'red', 'blue');
block._getElementState(button, 'color').should.equal('blue');
block._toggleElementState(button, 'color', null, 'blue');
});
});
});
describe('options', function () {
it('should return block options', function () {
var block = YBlock.fromDomNode($(
'
'
));
block._getOptions().level.should.equal(5);
});
it('should return element options', function () {
var block = YBlock.fromDomNode($(
'
'
));
block._getElementOptions(block._findElement('test')).level.should.equal(5);
});
});
describe('destruct()', function () {
it('should remove DOM Node on destruct', function () {
var SubBlock = inherit(YBlock, {}, {
getBlockName: function () {
return 'sub-block';
}
});
var block = new SubBlock();
var blockDomNode = block.getDomNode();
blockDomNode.appendTo(document.body);
$.contains(document.body, blockDomNode[0]).should.be.true;
block.destruct();
$.contains(document.body, blockDomNode[0]).should.be.false;
});
it('should destruct child blocks in descending order', function () {
var SubBlock = inherit(YBlock, {}, {
getBlockName: function () {
return 'sub-block';
}
});
var InnerBlock = inherit(YBlock, {}, {
getBlockName: function () {
return 'inner-block';
}
});
var block = new SubBlock();
sinon.spy(block, 'destruct');
var innerBlock = new InnerBlock();
sinon.spy(innerBlock, 'destruct');
block.getDomNode().append(innerBlock.getDomNode());
var innerSubBlock = new SubBlock();
sinon.spy(innerSubBlock, 'destruct');
innerBlock.getDomNode().append(innerSubBlock.getDomNode());
block.destruct();
sinon.assert.callOrder(block.destruct, innerBlock.destruct, innerSubBlock.destruct);
});
it('should throw error on double destruct', function () {
var block = new YBlock($('
'));
block.destruct();
function destructBlockAgain() {
block.destruct();
}
destructBlockAgain.should.throw(Error, 'Block `y-block` was already destroyed');
});
});
describe('YBlock.fromDomNode()', function () {
it('should return instance of block for given DOM node', function () {
var elem = $('div');
var block = YBlock.fromDomNode(elem);
block.should.be.instanceof(YBlock);
});
it('should return same instance for same DOM node', function () {
var elem = document.createElement('div');
var block = YBlock.fromDomNode($(elem));
YBlock.fromDomNode($(elem)).should.eq(block);
});
});
});
provide();
});