aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorMisko Hevery2010-03-18 12:20:06 -0700
committerMisko Hevery2010-03-18 12:20:06 -0700
commit7634a3ed5227f8bc2a2ba83752d0e2c78adb6051 (patch)
treeef94843f25eae83d0492b18149a084868829693c /test
parentf1b50b92ac69f5c58984f5e88015507552d29df2 (diff)
downloadangular.js-7634a3ed5227f8bc2a2ba83752d0e2c78adb6051.tar.bz2
initial revision of new plugable compiler
Diffstat (limited to 'test')
-rw-r--r--test/CompilerSpec.js186
1 files changed, 186 insertions, 0 deletions
diff --git a/test/CompilerSpec.js b/test/CompilerSpec.js
new file mode 100644
index 00000000..35e0e605
--- /dev/null
+++ b/test/CompilerSpec.js
@@ -0,0 +1,186 @@
+function Template() {
+ this.paths = [];
+ this.children = [];
+ this.inits = [];
+}
+
+Template.prototype = {
+ init: function(element, scope) {
+ foreach(this.inits, function(fn) {
+ scope.apply(fn, element);
+ });
+
+ var i,
+ childNodes = element.childNodes,
+ children = this.children,
+ paths = this.paths,
+ length = paths.length;
+ for (i = 0; i < length; i++) {
+ children[i].init(childNodes[paths[i]], scope);
+ }
+ },
+
+ addInit:function(init) {
+ if (init) {
+ this.inits.push(init);
+ }
+ },
+
+
+ addChild: function(index, template) {
+ this.paths.push(index);
+ this.children.push(template);
+ }
+};
+
+function Compiler(directives){
+ this.directives = directives;
+}
+
+DIRECTIVE = /^ng-(.*)$/;
+
+/**
+ * return {
+ * element:
+ * init: function(element){...}
+ * }
+ *
+ * internal data structure: {
+ * paths: [4, 5, 6],
+ * directive: name,
+ * init: function(expression, element){}
+ * }
+ *
+ * template : {
+ * inits: [fn(), fn()}
+ * paths: [1, 5],
+ * templates: [
+ * inits: []
+ * paths: []
+ * templates:
+ * ]
+ * }
+ */
+Compiler.prototype = {
+ compile: function(element) {
+ var template = this.templetize(element);
+ return function(){
+ var scope = new Scope();
+ return {
+ scope: scope,
+ element:element,
+ init: bind(template, template.init, element, scope)
+ };
+ };
+ },
+
+ templetize: function(element){
+ var items, item, length, i, directive, init, template,
+ childTemplate, recurse = true;
+
+ // Process attributes/directives
+ for (i = 0, items = element.attributes, length = items.length;
+ i < length; i++) {
+ item = items[i];
+ var match = item.name.match(DIRECTIVE);
+ if (match) {
+ directive = this.directives[match[1]];
+ if (directive) {
+ init = directive.call({}, item.value, element);
+ template = template || new Template();
+ template.addInit(init);
+ recurse = recurse && init;
+ }
+ }
+ }
+
+ // Process children
+ if (recurse) {
+ for (i = 0, items = element.childNodes, length = items.length;
+ i < length; i++) {
+ if(childTemplate = this.templetize(items[i])) {
+ template = template || new Template();
+ template.addChild(i, childTemplate);
+ }
+ }
+ }
+ return template;
+ }
+};
+
+describe('compiler', function(){
+ function element(html) {
+ return jQuery(html)[0];
+ }
+
+ var compiler, directives, 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;
+ });
+ };
+ }
+
+ };
+ compiler = new Compiler(directives);
+ compile = function(html){
+ var e = element(html);
+ var view = compiler.compile(e)(e);
+ view.init();
+ return view.scope;
+ };
+ });
+
+ it('should recognize a directive', function(){
+ var e = element('<div ng-directive="expr" ignore="me"></div>');
+ 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(log).toEqual("found:init");
+ });
+
+ it('should recurse to children', function(){
+ var scope = compile('<div><span ng-hello="misko"/></div>');
+ expect(log).toEqual("hello misko");
+ });
+
+ it('should watch scope', function(){
+ var scope = compile('<span ng-watch="name"/>');
+ expect(log).toEqual("");
+ scope.updateView();
+ scope.set('name', 'misko');
+ scope.updateView();
+ scope.updateView();
+ scope.set('name', 'adam');
+ scope.updateView();
+ scope.updateView();
+ expect(log).toEqual(":misko:adam");
+ });
+
+ it('should prevent recursion', function(){
+ directives.stop = function(){ return false; };
+ var scope = compile('<span ng-hello="misko" ng-stop="true"><span ng-hello="adam"/></span>');
+ expect(log).toEqual("hello misko");
+ });
+});