2010-04-04 00:04:36 +00:00
|
|
|
describe('compiler', function(){
|
2010-07-30 22:19:43 +00:00
|
|
|
var compiler, markup, directives, widgets, compile, log;
|
2010-03-18 19:20:06 +00:00
|
|
|
|
|
|
|
|
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){
|
2010-11-11 00:08:54 +00:00
|
|
|
if (val)
|
|
|
|
|
log += ":" + val;
|
2010-03-18 19:20:06 +00:00
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
};
|
2010-07-30 22:19:43 +00:00
|
|
|
markup = [];
|
2010-03-23 21:57:11 +00:00
|
|
|
attrMarkup = [];
|
2010-07-20 23:55:32 +00:00
|
|
|
widgets = extensionMap({}, 'widget');
|
2010-07-30 22:19:43 +00:00
|
|
|
compiler = new Compiler(markup, attrMarkup, directives, widgets);
|
2010-03-18 19:20:06 +00:00
|
|
|
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;
|
2010-03-18 19:20:06 +00:00
|
|
|
};
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should recognize a directive', function(){
|
2010-04-04 00:04:36 +00:00
|
|
|
var e = jqLite('<div directive="expr" ignore="me"></div>');
|
2010-03-18 19:20:06 +00:00
|
|
|
directives.directive = function(expression, element){
|
|
|
|
|
log += "found";
|
|
|
|
|
expect(expression).toEqual("expr");
|
2010-04-04 00:04:36 +00:00
|
|
|
expect(element).toEqual(e);
|
2010-03-18 19:20:06 +00:00
|
|
|
return function initFn() {
|
|
|
|
|
log += ":init";
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
var template = compiler.compile(e);
|
2010-04-04 00:04:36 +00:00
|
|
|
var init = template(e).$init;
|
2010-03-18 19:20:06 +00:00
|
|
|
expect(log).toEqual("found");
|
|
|
|
|
init();
|
2010-10-27 05:02:24 +00:00
|
|
|
expect(e.hasClass('ng-directive')).toEqual(true);
|
2010-03-18 19:20:06 +00:00
|
|
|
expect(log).toEqual("found:init");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should recurse to children', function(){
|
2010-03-22 20:58:04 +00:00
|
|
|
var scope = compile('<div><span hello="misko"/></div>');
|
2010-03-18 19:20:06 +00:00
|
|
|
expect(log).toEqual("hello misko");
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('should watch scope', function(){
|
2010-03-22 20:58:04 +00:00
|
|
|
var scope = compile('<span watch="name"/>');
|
2010-03-18 19:20:06 +00:00
|
|
|
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();
|
2010-03-18 19:20:06 +00:00
|
|
|
expect(log).toEqual(":misko:adam");
|
|
|
|
|
});
|
|
|
|
|
|
2010-03-22 20:58:04 +00:00
|
|
|
it('should prevent descend', function(){
|
|
|
|
|
directives.stop = function(){ this.descend(false); };
|
|
|
|
|
var scope = compile('<span hello="misko" stop="true"><span hello="adam"/></span>');
|
2010-03-18 19:20:06 +00:00
|
|
|
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
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
};
|
2010-03-22 20:58:04 +00:00
|
|
|
var 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
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
var scope = compile('before<span>middle</span>after');
|
2010-10-27 05:02:24 +00:00
|
|
|
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) {
|
2010-10-27 05:02:24 +00:00
|
|
|
expect(element.hasClass('ng-widget')).toEqual(true);
|
2010-04-26 18:57:33 +00:00
|
|
|
element.replaceWith('<div>button</div>');
|
2010-03-19 00:12:38 +00:00
|
|
|
return function(element) {
|
|
|
|
|
log += 'init';
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
var 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
|
|
|
|
2010-04-26 18:57:33 +00:00
|
|
|
it('should use the replaced element after calling widget', function(){
|
|
|
|
|
widgets['H1'] = function(element) {
|
2010-10-27 05:02:24 +00:00
|
|
|
// HTML elements which are augmented by acting as widgets, should not be marked as so
|
|
|
|
|
expect(element.hasClass('ng-widget')).toEqual(false);
|
2010-04-26 18:57:33 +00:00
|
|
|
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){
|
2010-04-26 18:57:33 +00:00
|
|
|
if (text == '{{1+2}}')
|
2010-04-27 00:02:27 +00:00
|
|
|
parent.text('3');
|
2010-04-26 18:57:33 +00:00
|
|
|
});
|
|
|
|
|
var scope = compile('<div><h1>ignore me</h1></div>');
|
|
|
|
|
expect(scope.$element.text()).toEqual('3');
|
|
|
|
|
});
|
|
|
|
|
|
2010-10-13 04:52:04 +00:00
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
var scope = compile('A---B---C===D');
|
|
|
|
|
expect(sortedHtml(scope.$element)).toEqual('<div>A<hr></hr>B<hr></hr>C<p></p>D</div>');
|
|
|
|
|
});
|
|
|
|
|
|
2010-03-18 19:20:06 +00:00
|
|
|
});
|