angular.js/test/CompilerSpec.js

190 lines
6.1 KiB
JavaScript
Raw Normal View History

2010-04-04 00:04:36 +00:00
describe('compiler', function(){
var compiler, markup, directives, widgets, compile, log, scope;
beforeEach(function(){
log = "";
directives = {
hello: function(expression, element){
log += "hello ";
return function() {
log += expression;
};
},
watch: function(expression, element){
return function() {
this.$watch(expression, function(val){
if (val)
log += ":" + val;
});
};
}
};
2010-07-30 22:19:43 +00:00
markup = [];
2010-03-23 21:57:11 +00:00
attrMarkup = [];
widgets = extensionMap({}, 'widget');
2010-07-30 22:19:43 +00:00
compiler = new Compiler(markup, attrMarkup, directives, widgets);
compile = function(html){
2010-04-04 00:04:36 +00:00
var e = jqLite("<div>" + html + "</div>");
var scope = compiler.compile(e)(e);
scope.$init();
return scope;
};
});
afterEach(function(){
dealoc(scope);
});
it('should recognize a directive', function(){
2010-04-04 00:04:36 +00:00
var e = jqLite('<div directive="expr" ignore="me"></div>');
directives.directive = function(expression, element){
log += "found";
expect(expression).toEqual("expr");
2010-04-04 00:04:36 +00:00
expect(element).toEqual(e);
return function initFn() {
log += ":init";
};
};
var template = compiler.compile(e);
scope = template(e);
var init = scope.$init;
expect(log).toEqual("found");
init();
expect(e.hasClass('ng-directive')).toEqual(true);
expect(log).toEqual("found:init");
});
it('should recurse to children', function(){
scope = compile('<div><span hello="misko"/></div>');
expect(log).toEqual("hello misko");
});
it('should watch scope', function(){
scope = compile('<span watch="name"/>');
expect(log).toEqual("");
2010-04-04 00:04:36 +00:00
scope.$eval();
scope.$set('name', 'misko');
scope.$eval();
scope.$eval();
scope.$set('name', 'adam');
scope.$eval();
scope.$eval();
expect(log).toEqual(":misko:adam");
});
2010-03-22 20:58:04 +00:00
it('should prevent descend', function(){
directives.stop = function(){ this.descend(false); };
scope = compile('<span hello="misko" stop="true"><span hello="adam"/></span>');
expect(log).toEqual("hello misko");
});
2010-04-12 23:24:28 +00:00
2010-03-18 21:43:49 +00:00
it('should allow creation of templates', function(){
directives.duplicate = function(expr, element){
2010-04-21 01:14:13 +00:00
var parent = element.parent();
2010-03-19 23:41:02 +00:00
element.replaceWith(document.createComment("marker"));
2010-03-22 20:58:04 +00:00
element.removeAttr("duplicate");
2010-03-19 23:41:02 +00:00
var template = this.compile(element);
2010-03-18 21:43:49 +00:00
return function(marker) {
2010-04-04 00:04:36 +00:00
this.$onEval(function() {
2010-04-21 01:14:13 +00:00
marker.after(template(element.clone()).$element);
2010-03-18 21:43:49 +00:00
});
};
};
scope = compile('before<span duplicate="expr">x</span>after');
2010-04-21 01:14:13 +00:00
expect(sortedHtml(scope.$element)).toEqual('<div>before<#comment></#comment><span>x</span>after</div>');
2010-04-04 00:04:36 +00:00
scope.$eval();
2010-04-21 01:14:13 +00:00
expect(sortedHtml(scope.$element)).toEqual('<div>before<#comment></#comment><span>x</span><span>x</span>after</div>');
2010-04-04 00:04:36 +00:00
scope.$eval();
2010-04-21 01:14:13 +00:00
expect(sortedHtml(scope.$element)).toEqual('<div>before<#comment></#comment><span>x</span><span>x</span><span>x</span>after</div>');
2010-03-18 21:43:49 +00:00
});
2010-03-18 22:50:14 +00:00
it('should process markup before directives', function(){
2010-07-30 22:19:43 +00:00
markup.push(function(text, textNode, parentNode) {
2010-03-18 22:50:14 +00:00
if (text == 'middle') {
2010-03-19 00:12:38 +00:00
expect(textNode.text()).toEqual(text);
2010-03-22 20:58:04 +00:00
parentNode.attr('hello', text);
2010-04-21 20:29:49 +00:00
textNode[0].nodeValue = 'replaced';
2010-03-18 22:50:14 +00:00
}
});
scope = compile('before<span>middle</span>after');
expect(sortedHtml(scope.$element[0], true)).toEqual('<div>before<span class="ng-directive" hello="middle">replaced</span>after</div>');
2010-03-18 22:50:14 +00:00
expect(log).toEqual("hello middle");
});
2010-03-19 00:12:38 +00:00
2010-03-22 20:58:04 +00:00
it('should replace widgets', function(){
widgets['NG:BUTTON'] = function(element) {
expect(element.hasClass('ng-widget')).toEqual(true);
element.replaceWith('<div>button</div>');
2010-03-19 00:12:38 +00:00
return function(element) {
log += 'init';
};
};
scope = compile('<ng:button>push me</ng:button>');
2010-04-21 20:29:49 +00:00
expect(lowercase(scope.$element[0].innerHTML)).toEqual('<div>button</div>');
2010-03-22 20:58:04 +00:00
expect(log).toEqual('init');
2010-03-19 00:12:38 +00:00
});
2010-03-19 23:41:02 +00:00
it('should use the replaced element after calling widget', function(){
widgets['H1'] = function(element) {
// HTML elements which are augmented by acting as widgets, should not be marked as so
expect(element.hasClass('ng-widget')).toEqual(false);
var span = angular.element('<span>{{1+2}}</span>');
element.replaceWith(span);
this.descend(true);
this.directives(true);
return noop;
};
2010-07-30 22:19:43 +00:00
markup.push(function(text, textNode, parent){
if (text == '{{1+2}}')
2010-04-27 00:02:27 +00:00
parent.text('3');
});
scope = compile('<div><h1>ignore me</h1></div>');
expect(scope.$element.text()).toEqual('3');
});
it('should allow multiple markups per text element', function(){
markup.push(function(text, textNode, parent){
var index = text.indexOf('---');
if (index > -1) {
textNode.after(text.substring(index + 3));
textNode.after("<hr/>");
textNode.after(text.substring(0, index));
textNode.remove();
}
});
markup.push(function(text, textNode, parent){
var index = text.indexOf('===');
if (index > -1) {
textNode.after(text.substring(index + 3));
textNode.after("<p>");
textNode.after(text.substring(0, index));
textNode.remove();
}
});
scope = compile('A---B---C===D');
expect(sortedHtml(scope.$element)).toEqual('<div>A<hr></hr>B<hr></hr>C<p></p>D</div>');
});
describe('retrieveScope', function() {
it('should retrieve scope attached to the current element', function() {
scope = compile('<i>foo</i>');
expect(retrieveScope(scope.$element)).toBe(scope);
});
it('should walk up the dom to find scope', function() {
scope = compile('<ul><li><p><b>deep deep</b><p></li></ul>');
var deepChild = scope.$element[0].getElementsByTagName('b')[0];
expect(retrieveScope(deepChild)).toBe(scope);
});
it('should return undefined when no scope was found', function() {
var html = jqLite('<ul><li><p><b>deep deep</b><p></li></ul>'),
deepChild = html[0].getElementsByTagName('b')[0];
expect(retrieveScope(deepChild)).toBeNull();
});
});
});