From d9b58f23f6b3fe5635c3ec5259e6a0002cff78b7 Mon Sep 17 00:00:00 2001 From: Misko Hevery Date: Tue, 25 Oct 2011 14:14:18 -0700 Subject: move(compiler): appease the History God - renamed: src/Compiler.js -> src/service/compiler.js - renamed: test/CompilerSpec.js -> test/service/compilerSpec.js --- test/service/compilerSpec.js | 218 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 218 insertions(+) create mode 100644 test/service/compilerSpec.js (limited to 'test/service') diff --git a/test/service/compilerSpec.js b/test/service/compilerSpec.js new file mode 100644 index 00000000..2dec1396 --- /dev/null +++ b/test/service/compilerSpec.js @@ -0,0 +1,218 @@ +'use strict'; + +describe('compiler', function() { + var compiler, markup, attrMarkup, directives, widgets, compile, log, scope; + + beforeEach(inject(function($rootScope) { + log = ""; + directives = { + hello: function(expression, element){ + log += "hello "; + return function() { + log += expression; + }; + }, + + observe: function(expression, element){ + return function() { + this.$watch(expression, function(scope, val){ + if (val) + log += ":" + val; + }); + }; + } + + }; + markup = []; + attrMarkup = []; + widgets = extensionMap({}, 'widget'); + compiler = new Compiler(markup, attrMarkup, directives, widgets); + compile = function(html){ + var e = jqLite("
" + html + "
"); + compiler.compile(e)($rootScope); + return scope = $rootScope; + }; + })); + + + it('should not allow compilation of multiple roots', function() { + expect(function() { + compiler.compile('
A
'); + }).toThrow("Cannot compile multiple element roots: " + ie("
A
")); + function ie(text) { + return msie < 9 ? uppercase(text) : text; + } + }); + + + it('should recognize a directive', inject(function($rootScope) { + 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); + expect(log).toEqual("found"); + scope = template($rootScope); + expect(e.hasClass('ng-directive')).toEqual(true); + expect(log).toEqual("found:init"); + })); + + + it('should recurse to children', function() { + scope = compile('
'); + expect(log).toEqual("hello misko"); + }); + + + it('should observe scope', function() { + scope = compile(''); + expect(log).toEqual(""); + scope.$digest(); + scope.name = 'misko'; + scope.$digest(); + scope.$digest(); + scope.name = 'adam'; + scope.$digest(); + scope.$digest(); + expect(log).toEqual(":misko:adam"); + }); + + + it('should prevent descend', function() { + directives.stop = function() { this.descend(false); }; + scope = compile(''); + expect(log).toEqual("hello misko"); + }); + + + it('should allow creation of templates', inject(function($rootScope) { + directives.duplicate = function(expr, element){ + element.replaceWith(document.createComment("marker")); + element.removeAttr("duplicate"); + var linker = this.compile(element); + return function(marker) { + this.$watch('value', function() { + var scope = $rootScope.$new; + linker(scope, noop); + marker.after(scope.$element); + }); + }; + }; + scope = compile('beforexafter'); + expect(sortedHtml(scope.$element)). + toEqual('
' + + 'before<#comment>' + + 'after' + + '
'); + scope.value = 1; + scope.$digest(); + expect(sortedHtml(scope.$element)). + toEqual('
' + + 'before<#comment>' + + 'x' + + 'after' + + '
'); + scope.value = 2; + scope.$digest(); + expect(sortedHtml(scope.$element)). + toEqual('
' + + 'before<#comment>' + + 'x' + + 'x' + + 'after' + + '
'); + scope.value = 3; + scope.$digest(); + expect(sortedHtml(scope.$element)). + toEqual('
' + + 'before<#comment>' + + 'x' + + 'x' + + 'x' + + 'after' + + '
'); + })); + + + 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'; + } + }); + 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'; + }; + }; + 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'); + }); + 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(); + } + }); + scope = compile('A---B---C===D'); + expect(sortedHtml(scope.$element)).toEqual('

A
B
C

D
'); + }); + + + it('should add class for namespace elements', function() { + scope = compile('abc'); + var space = jqLite(scope.$element[0].firstChild); + expect(space.hasClass('ng-space')).toEqual(true); + }); +}); -- cgit v1.2.3