@danielkalen/simplybind
Version:
Magically simple, framework-less one-way/two-way data binding for frontend/backend in ~5kb.
123 lines (103 loc) • 4.54 kB
JavaScript
import './setup';
import {ViewCompiler} from '../src/view-compiler';
import {ViewResources} from '../src/view-resources';
class MockBindingLanguage {
inspectAttribute(resources, elementName, attrName, attrValue) {
}
createAttributeInstruction(resources, element, info, existingInstruction) {
}
inspectTextContent(resources, value) {
}
}
describe('ViewCompiler', () => {
var viewCompiler, language, resources;
beforeAll(() => {
language = new MockBindingLanguage();
viewCompiler = new ViewCompiler(language);
resources = new ViewResources(new ViewResources(), 'app.html');
});
describe('compile', () => {
it('compiles an empty template', () => {
var template = document.createElement('template'),
node = document.createDocumentFragment(),
factory;
template.appendChild(node);
factory = viewCompiler.compile(template, resources, null);
expect(factory).not.toBe(null);
});
});
describe('compileNode', () => {
it('concatenates adjacent text nodes', () => {
var instructions = [], parentInjectorId = 'root', targetLightDOM = true,
node, parentNode;
parentNode = document.createElement('div');
node = document.createTextNode('Hello');
parentNode.appendChild(node);
parentNode.appendChild(document.createTextNode(' '));
parentNode.appendChild(document.createTextNode('World'));
parentNode.appendChild(document.createTextNode('!'));
spyOn(language, 'inspectTextContent');
node = viewCompiler._compileNode(node, resources, instructions, parentNode, parentInjectorId, targetLightDOM);
expect(language.inspectTextContent).toHaveBeenCalledWith(resources, 'Hello World!');
expect(node).toBe(null);
});
it('does not concatenate non-adjacent text nodes', () => {
var instructions = [], parentInjectorId = 'root', targetLightDOM = true,
node, parentNode, nextNode;
parentNode = document.createElement('div');
node = document.createTextNode('Hello');
parentNode.appendChild(node);
parentNode.appendChild(document.createTextNode(' '));
nextNode = document.createElement('em');
nextNode.textContent = 'World';
parentNode.appendChild(nextNode);
parentNode.appendChild(document.createTextNode('!'));
spyOn(language, 'inspectTextContent');
node = viewCompiler._compileNode(node, resources, instructions, parentNode, parentInjectorId, targetLightDOM);
expect(language.inspectTextContent).toHaveBeenCalledWith(resources, 'Hello ');
expect(node).toBe(nextNode);
});
it('clears class attributes containing interpolation expressions', () => {
var instructions = [], parentInjectorId = 'root', targetLightDOM = true,
node = document.createElement('div'), parentNode = null;
node.setAttribute('class', 'foo ${bar} baz');
spyOn(language, 'inspectAttribute').and.returnValue({
attrName: 'class',
expression: {attrToRemove: 'class'},
command: null
});
spyOn(language, 'createAttributeInstruction').and.returnValue({
attributes: {
'class': {
discrete: true,
attrToRemove: 'class'
}
}, attrName: 'class'
});
viewCompiler._compileNode(node, resources, instructions, parentNode, parentInjectorId, targetLightDOM);
expect(node.className).toBe('au-target');
});
it('does not clear class attributes with no interpolation expressions', () => {
var instructions = [], parentInjectorId = 'root', targetLightDOM = true,
node = document.createElement('div'), parentNode = null;
node.setAttribute('class', 'foo bar baz');
node.setAttribute('class.bind', 'someProperty');
spyOn(language, 'inspectAttribute').and.callFake((resources, attrName, attrValue) => {
if (attrName === 'class') {
return {attrName: 'class', expression: null, command: null}
} else {
return {attrName: 'class', expression: null, command: 'bind'};
}
});
spyOn(language, 'createAttributeInstruction').and.callFake((resources, node, info) => {
if (info.command) {
return {attributes: {'class': {discrete: true}}, attrName: 'class'};
} else {
return null;
}
});
viewCompiler._compileNode(node, resources, instructions, parentNode, parentInjectorId, targetLightDOM);
expect(node.className).toBe('foo bar baz au-target');
});
});
});