describe('compiler', function(){ var compiler, markup, directives, widgets, compile, log; 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){ log += ":" + val; }); }; } }; markup = []; attrMarkup = []; widgets = extensionMap({}, 'widget'); compiler = new Compiler(markup, attrMarkup, directives, widgets); compile = function(html){ var e = jqLite("
" + html + "
"); var scope = compiler.compile(e)(e); scope.$init(); return scope; }; }); it('should recognize a directive', function(){ var e = jqLite('
'); directives.directive = function(expression, element){ log += "found"; expect(expression).toEqual("expr"); expect(element).toEqual(e); return function initFn() { log += ":init"; }; }; var template = compiler.compile(e); var init = template(e).$init; expect(log).toEqual("found"); init(); expect(e.hasClass('ng-directive')).toEqual(true); expect(log).toEqual("found:init"); }); it('should recurse to children', function(){ var scope = compile('
'); expect(log).toEqual("hello misko"); }); it('should watch scope', function(){ var scope = compile(''); expect(log).toEqual(""); scope.$eval(); scope.$set('name', 'misko'); scope.$eval(); scope.$eval(); scope.$set('name', 'adam'); scope.$eval(); scope.$eval(); expect(log).toEqual(":misko:adam"); }); it('should prevent descend', function(){ directives.stop = function(){ this.descend(false); }; var scope = compile(''); expect(log).toEqual("hello misko"); }); it('should allow creation of templates', function(){ directives.duplicate = function(expr, element){ var parent = element.parent(); element.replaceWith(document.createComment("marker")); element.removeAttr("duplicate"); var template = this.compile(element); return function(marker) { this.$onEval(function() { marker.after(template(element.clone()).$element); }); }; }; var scope = compile('beforexafter'); expect(sortedHtml(scope.$element)).toEqual('
before<#comment>xafter
'); scope.$eval(); expect(sortedHtml(scope.$element)).toEqual('
before<#comment>xxafter
'); scope.$eval(); expect(sortedHtml(scope.$element)).toEqual('
before<#comment>xxxafter
'); }); it('should process markup before directives', function(){ markup.push(function(text, textNode, parentNode) { if (text == 'middle') { expect(textNode.text()).toEqual(text); parentNode.attr('hello', text); textNode[0].nodeValue = 'replaced'; } }); var scope = compile('beforemiddleafter'); expect(sortedHtml(scope.$element[0], true)).toEqual('
beforereplacedafter
'); expect(log).toEqual("hello middle"); }); it('should replace widgets', function(){ widgets['NG:BUTTON'] = function(element) { expect(element.hasClass('ng-widget')).toEqual(true); element.replaceWith('
button
'); return function(element) { log += 'init'; }; }; var scope = compile('push me'); expect(lowercase(scope.$element[0].innerHTML)).toEqual('
button
'); expect(log).toEqual('init'); }); 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('{{1+2}}'); element.replaceWith(span); this.descend(true); this.directives(true); return noop; }; markup.push(function(text, textNode, parent){ if (text == '{{1+2}}') parent.text('3'); }); var scope = compile('

ignore me

'); 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("
"); 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("

"); textNode.after(text.substring(0, index)); textNode.remove(); } }); var scope = compile('A---B---C===D'); expect(sortedHtml(scope.$element)).toEqual('

A
B
C

D
'); }); });