'));
+};
+
+BinderTest.prototype.testExpandEntityTagWithName = function(){
+ var c = compile('
',
+ c.node.sortedHtml());
+ assertEquals("Person", c.scope.get("friend.$entity"));
+ assertEquals("friend", c.scope.get("friend.$$anchor"));
+};
+
+BinderTest.prototype.testExpandSubmitButtonToAction = function(){
+ var html = compileToHtml('
');
+ assertTrue(html, html.indexOf('ng-action="$save()"') > 0 );
+ assertTrue(html, html.indexOf('ng-bind-attr="{"disabled":"{{$invalidWidgets}}"}"') > 0 );
+};
+
+BinderTest.prototype.testDoNotOverwriteCustomAction = function(){
+ var html = compileToHtml('
');
+ assertTrue(html.indexOf('action="foo();"') > 0 );
+};
+
+BinderTest.prototype.testReplaceFileUploadWithSwf = function(){
+ expectAsserts(1);
+ var form = jQuery("body").append('
');
+ form.data('scope', new nglr.Scope());
+ var factory = {};
+ var binder = new nglr.Binder(form.get(0), factory, new MockUrlWatcher());
+ factory.createController = function(node){
+ assertEquals(node.attr('type'), 'file');
+ return {updateModel:function(){}};
+ };
+ binder.compile();
+ jQuery("#testTag").remove();
+};
+
+BinderTest.prototype.testRepeaterAdd = function(){
+ var doc = $('
');
+ var binder = new nglr.Binder(doc[0], new nglr.WidgetFactory(), new MockUrlWatcher());
+ doc.data('scope', new nglr.Scope({items:[{x:'a'}, {x:'b'}], $binder:binder}));
+ binder.compile();
+ binder.updateView();
+ assertEquals('a', doc.find(':input')[0].value);
+ assertEquals('b', doc.find(':input')[1].value);
+
+ var first = doc.find('[ng-repeat-index="0"]');
+ first[0].value = 'ABC';
+ first.trigger('keyup');
+ assertEquals(doc.scope().get('items')[0].x, 'ABC');
+};
+
+BinderTest.prototype.testIfTextBindingThrowsErrorDecorateTheSpan = function(){
+ var doc = $('
');
+ var scope = new nglr.Scope();
+ doc.data('scope', scope);
+ var binder = new nglr.Binder(doc[0], new nglr.WidgetFactory(), new MockUrlWatcher());
+ binder.compile();
+
+ scope.set('error.throw', function(){throw "ErrorMsg1";});
+ binder.updateView();
+ var span = doc.find('span');
+ assertTrue(span.hasClass('ng-exception'));
+ assertEquals('ErrorMsg1', nglr.fromJson(span.text()));
+ assertEquals('"ErrorMsg1"', span.attr('ng-error'));
+
+ scope.set('error.throw', function(){throw "MyError";});
+ binder.updateView();
+ span = doc.find('span');
+ assertTrue(span.hasClass('ng-exception'));
+ assertTrue(span.text(), span.text().match('MyError') !== null);
+ assertEquals('"MyError"', span.attr('ng-error'));
+
+ scope.set('error.throw', function(){return "ok";});
+ binder.updateView();
+ assertFalse(span.hasClass('ng-exception'));
+ assertEquals('ok', span.text());
+ assertEquals(null, span.attr('ng-error'));
+};
+
+BinderTest.prototype.testIfAttrBindingThrowsErrorDecorateTheSpan = function(){
+ var doc = $('
');
+ var scope = new nglr.Scope();
+ doc.data('scope', scope);
+ var binder = new nglr.Binder(doc[0], new nglr.WidgetFactory(), new MockUrlWatcher());
+ binder.compile();
+
+ scope.set('error.throw', function(){throw "ErrorMsg";});
+ binder.updateView();
+ assertTrue('ng-exception', doc.hasClass('ng-exception'));
+ assertEquals('before ["ErrorMsg"] after', doc.attr('attr'));
+ assertEquals('"ErrorMsg"', doc.attr('ng-error'));
+
+ scope.set('error.throw', function(){ return 'X';});
+ binder.updateView();
+ assertFalse('!ng-exception', doc.hasClass('ng-exception'));
+ assertEquals('before X after', doc.attr('attr'));
+ assertEquals(null, doc.attr('ng-error'));
+};
+
+BinderTest.prototype.testNestedRepeater = function() {
+ var doc = html('
');
+ var scope = new nglr.Scope();
+ doc.data('scope', scope);
+ var binder = new nglr.Binder(doc[0], new nglr.WidgetFactory(), new MockUrlWatcher());
+ binder.compile();
+
+ scope.set('model', [{name:'a', item:['a1', 'a2']}, {name:'b', item:['b1', 'b2']}]);
+ binder.updateView();
+
+ assertEquals(
+ //'<#comment>#comment>'+
+ '
', doc.sortedHtml());
+};
+
+BinderTest.prototype.testRadioButtonGetsPrefixed = function () {
+ var doc = html('
');
+ var scope = new nglr.Scope();
+ doc.data('scope', scope);
+ var binder = new nglr.Binder(doc[0], new nglr.WidgetFactory(), new MockUrlWatcher());
+ binder.compile();
+
+ scope.set('model', ['a1', 'a2']);
+ binder.updateView();
+
+ assertEquals(
+ //'<#comment>#comment>'+
+ '
',
+ doc.sortedHtml());
+};
+
+BinderTest.prototype.testHideBindingExpression = function() {
+ var doc = html('
');
+ var scope = new nglr.Scope();
+ doc.data('scope', scope);
+ var binder = new nglr.Binder(doc[0], new nglr.WidgetFactory(), new MockUrlWatcher());
+ binder.compile();
+
+ scope.set('hidden', 3);
+ binder.updateView();
+
+ assertHidden(doc.children());
+
+ scope.set('hidden', 2);
+ binder.updateView();
+
+ assertVisible(doc.children());
+};
+
+BinderTest.prototype.testHideBinding = function() {
+ var doc = html('
');
+ var scope = new nglr.Scope();
+ doc.data('scope', scope);
+ var binder = new nglr.Binder(doc[0], new nglr.WidgetFactory(), new MockUrlWatcher());
+ binder.compile();
+
+ scope.set('hidden', 'true');
+ binder.updateView();
+
+ assertHidden(doc.children());
+
+ scope.set('hidden', 'false');
+ binder.updateView();
+
+ assertVisible(doc.children());
+
+ scope.set('hidden', '');
+ binder.updateView();
+
+ assertVisible(doc.children());
+};
+
+BinderTest.prototype.testShowBinding = function() {
+ var doc = html('
');
+ var scope = new nglr.Scope();
+ doc.data('scope', scope);
+ var binder = new nglr.Binder(doc[0], new nglr.WidgetFactory(), new MockUrlWatcher());
+ binder.compile();
+
+ scope.set('show', 'true');
+ binder.updateView();
+
+ assertVisible(doc.children());
+
+ scope.set('show', 'false');
+ binder.updateView();
+
+ assertHidden(doc.children());
+
+ scope.set('show', '');
+ binder.updateView();
+
+ assertHidden(doc.children());
+};
+
+BinderTest.prototype.testBindClassUndefined = function() {
+ var doc = compile('
',
+ doc.node.sortedHtml());
+};
+
+BinderTest.prototype.testBindClass = function() {
+ var doc = html('
');
+ var scope = new nglr.Scope();
+ doc.data('scope', scope);
+ var binder = new nglr.Binder(doc[0], new nglr.WidgetFactory(), new MockUrlWatcher());
+ binder.compile();
+
+ scope.set('class', 'testClass');
+ binder.updateView();
+
+ assertEquals(doc.sortedHtml(),
+ '
');
+
+ scope.set('class', ['a', 'b']);
+ binder.updateView();
+
+ assertEquals(doc.sortedHtml(),
+ '
');
+};
+
+BinderTest.prototype.testBindClassEvenOdd = function() {
+ var x = compile('
',
+ x.node.sortedHtml());
+};
+
+BinderTest.prototype.testBindStyle = function() {
+ var doc = html('
');
+ var scope = new nglr.Scope();
+ doc.data('scope', scope);
+ var binder = new nglr.Binder(doc[0], new nglr.WidgetFactory(), new MockUrlWatcher());
+ binder.compile();
+
+ scope.eval('style={color:"red"}');
+ binder.updateView();
+
+ assertEquals("red", doc.find('div').css('color'));
+
+ scope.eval('style={}');
+ binder.updateView();
+
+ assertEquals(doc.sortedHtml(), '
');
+};
+
+BinderTest.prototype.testActionOnAHrefThrowsError = function(){
+ var model = {books:[]};
+ var state = compile('
', model);
+ var input = state.node.find('a');
+ input.click();
+ assertEquals('abc', nglr.fromJson(input.attr('ng-error')).a);
+ assertNotNull(input.data('qtip'));
+ assertTrue("should have an error class", input.hasClass('ng-exception'));
+
+ input.attr('ng-action', '0');
+ input.click();
+ assertFalse('error class should be cleared', input.hasClass('ng-exception'));
+};
+
+BinderTest.prototype.testShoulIgnoreVbNonBindable = function(){
+ var c = compile("{{a}}" +
+ "
");
+ c.scope.set('a', 123);
+ c.scope.updateView();
+ assertEquals('123{{a}}{{b}}{{c}}', c.node.text());
+};
+
+BinderTest.prototype.testOptionShouldUpdateParentToGetProperBinding = function() {
+ var c = compile('
');
+ c.scope.set('s', 1);
+ c.binder.updateView();
+ assertEquals(1, c.node.find('select')[0].selectedIndex);
+};
+
+BinderTest.prototype.testRepeaterShouldBindInputsDefaults = function () {
+ var c = compile('
');
+ c.scope.set('items', [{}, {name:'misko'}]);
+ c.binder.updateView();
+
+ assertEquals("123", c.scope.eval('items[0].name'));
+ assertEquals("misko", c.scope.eval('items[1].name'));
+};
+
+BinderTest.prototype.testRepeaterShouldCreateArray = function () {
+ var c = compile('
');
+ c.binder.updateView();
+
+ assertEquals(0, c.scope.get('items').length);
+};
+
+BinderTest.prototype.testShouldTemplateBindPreElements = function () {
+ var c = compile('
');
+ c.scope.set("name", "World");
+ c.binder.updateView();
+
+ assertEquals('
', c.node.sortedHtml());
+};
+
+BinderTest.prototype.testDissableAutoSubmit = function() {
+ var c = compile('
',
+ c.node.sortedHtml());
+};
+
+BinderTest.prototype.testSettingAnchorToNullOrUndefinedRemovesTheAnchorFromURL = function() {
+ var c = compile('');
+ c.binder.urlWatcher.setUrl("http://server/#a=1&b=2");
+ c.binder.parseAnchor();
+ assertEquals('1', c.binder.anchor.a);
+ assertEquals('2', c.binder.anchor.b);
+
+ c.binder.anchor.a = null;
+ c.binder.anchor.b = null;
+ c.binder.updateAnchor();
+ assertEquals('http://server/#', c.binder.urlWatcher.getUrl());
+};
+
+BinderTest.prototype.testFillInOptionValueWhenMissing = function() {
+ var c = compile('
',
+ c.node.sortedHtml());
+};
+
+BinderTest.prototype.testValidateForm = function() {
+ var c = compile('
');
+ var items = [{}, {}];
+ c.scope.set("items", items);
+ c.binder.updateView();
+ assertEquals(3, c.scope.get("$invalidWidgets.length"));
+
+ c.scope.set('name', 'abc');
+ c.binder.updateView();
+ assertEquals(2, c.scope.get("$invalidWidgets.length"));
+
+ items[0].name = 'abc';
+ c.binder.updateView();
+ assertEquals(1, c.scope.get("$invalidWidgets.length"));
+
+ items[1].name = 'abc';
+ c.binder.updateView();
+ assertEquals(0, c.scope.get("$invalidWidgets.length"));
+};
+
+BinderTest.prototype.testDeleteAttributeIfEvaluatesFalse = function() {
+ var c = compile(
+ '
');
+ c.binder.updateView();
+ var html = c.node.html();
+ assertEquals(html + 0, 1, c.node.find("input[name='a0']:disabled").size());
+ assertEquals(html + 1, 1, c.node.find("input[name='b0']:disabled").size());
+ assertEquals(html + 2, 1, c.node.find("input[name='c0']:disabled").size());
+
+ assertEquals(html + 3, 0, c.node.find("input[name='a1']:disabled").size());
+ assertEquals(html + 4, 0, c.node.find("input[name='b1']:disabled").size());
+ assertEquals(html + 5, 0, c.node.find("input[name='c1']:disabled").size());
+};
+
+BinderTest.prototype.testRepeaterErrorShouldBePlacedOnInstanceNotOnTemplateComment = function () {
+ var c = compile(
+ '
');
+ c.binder.updateView();
+ assertTrue(c.node.find("input").hasClass("ng-exception"));
+};
+
+BinderTest.prototype.XtestItShouldApplyAttirbutesBeforeTheWidgetsAreMaterialized = function() {
+ var c = compile(
+ '
');
+ c.scope.set('person', {a:'misko', b:'adam'});
+ c.binder.updateView();
+ assertEquals("", c.node.html());
+};
+
+BinderTest.prototype.testItShouldCallListenersWhenAnchorChanges = function() {
+ var log = "";
+ var c = compile('
');
+ c.scope.set("count", 0);
+ c.scope.addWatchListener("$anchor.counter", function(newValue, oldValue){
+ log += oldValue + "->" + newValue + ";";
+ });
+ assertEquals(0, c.scope.get("count"));
+ c.binder.onUrlChange("#counter=1");
+ assertEquals(1, c.scope.get("count"));
+ c.binder.onUrlChange("#counter=1");
+ assertEquals(1, c.scope.get("count"));
+ c.binder.onUrlChange("#counter=2");
+ assertEquals(2, c.scope.get("count"));
+ c.binder.onUrlChange("#counter=2");
+ assertEquals(2, c.scope.get("count"));
+ c.binder.onUrlChange("#");
+ assertEquals("undefined->1;1->2;2->undefined;", log);
+ assertEquals(3, c.scope.get("count"));
+};
+
+BinderTest.prototype.testParseQueryString = function(){
+ var binder = new nglr.Binder();
+ assertJsonEquals({"a":"1"}, binder.parseQueryString("a=1"));
+ assertJsonEquals({"a":"1", "b":"two"}, binder.parseQueryString("a=1&b=two"));
+ assertJsonEquals({}, binder.parseQueryString(""));
+
+ assertJsonEquals({"a":"1", "b":""}, binder.parseQueryString("a=1&b="));
+ assertJsonEquals({"a":"1", "b":""}, binder.parseQueryString("a=1&b"));
+ assertJsonEquals({"a":"1", "b":" 2 "}, binder.parseQueryString("a=1&b=%202%20"));
+ assertJsonEquals({"a a":"1", "b":"2"}, binder.parseQueryString("a%20a=1&b=2"));
+
+};
+
+BinderTest.prototype.testSetBinderAnchorTriggersListeners = function(){
+ expectAsserts(2);
+ var doc = html("
")[0];
+ var binder = new nglr.Binder(doc, null, new MockUrlWatcher());
+ var scope = new nglr.Scope({$binder:binder, $anchor:binder.anchor});
+ jQuery(doc).data('scope', scope);
+
+ scope.addWatchListener("$anchor.name", function(newVal, oldVal) {
+ assertEquals("new", newVal);
+ assertEquals(undefined, oldVal);
+ });
+
+ binder.anchor.name = "new";
+ binder.onUrlChange("http://base#name=new");
+};
+
+BinderTest.prototype.testItShouldDisplayErrorWhenActionIsSyntacticlyIncorect = function(){
+ var c = compile(
+ '
' +
+ '
');
+ c.node.find("input").click();
+ assertEquals("ABC", c.scope.get('greeting'));
+ assertTrue(c.node.find(":input:last").hasClass("ng-exception"));
+};
+
+BinderTest.prototype.testItShouldSelectTheCorrectRadioBox = function() {
+ var c = compile(
+ '
' +
+ '
');
+
+ c.node.find("input[value=female]").click();
+ assertEquals("female", c.scope.get("sex"));
+ assertEquals(1, c.node.find("input:checked").size());
+ assertEquals("female", c.node.find("input:checked").attr("value"));
+
+ c.node.find("input[value=male]").click();
+ assertEquals("male", c.scope.get("sex"));
+ assertEquals(1, c.node.find("input:checked").size());
+ assertEquals("male", c.node.find("input:checked").attr("value"));
+};
+
+BinderTest.prototype.testItShouldListenOnRightScope = function() {
+ var c = compile(
+ '
' +
+ '
');
+ c.binder.executeInit();
+ c.binder.updateView();
+ assertEquals(0, c.scope.get("counter"));
+ assertEquals(0, c.scope.get("gCounter"));
+
+ c.scope.set("w", "something");
+ c.binder.updateView();
+ assertEquals(1, c.scope.get("counter"));
+ assertEquals(7, c.scope.get("gCounter"));
+};
+
+BinderTest.prototype.testItShouldRepeatOnHashes = function() {
+ var x = compile('
');
+ x.binder.updateView();
+ assertEquals(
+ '
a0
' +
+ '
b1
',
+ x.node.sortedHtml());
+};
+
+BinderTest.prototype.testItShouldFireChangeListenersBeforeUpdate = function(){
+ var x = compile('
');
+ x.scope.set("name", "");
+ x.scope.set("watched", "change");
+ x.scope.watch("watched:name=123");
+ x.scope.updateView();
+ assertEquals(123, x.scope.get("name"));
+ assertEquals(
+ '
123
',
+ x.node.sortedHtml());
+};
+
+BinderTest.prototype.testItShouldHandleMultilineBindings = function(){
+ var x = compile('
{{\n 1 \n + \n 2 \n}}
');
+ x.scope.updateView();
+ assertEquals("3", x.node.text());
+};
+
+BinderTest.prototype.testItBindHiddenInputFields = function(){
+ var x = compile('
');
+ x.scope.updateView();
+ assertEquals("abc", x.scope.get("myName"));
+};
+
+BinderTest.prototype.testItShouldRenderMultiRootHtmlInBinding = function() {
+ var x = compile('
before {{a|html}}after
');
+ x.scope.set("a", "a
c d");
+ x.binder.updateView();
+ assertEquals(
+ '
before ac d after
',
+ x.node.sortedHtml());
+};
diff --git a/test/ConsoleTest.js b/test/ConsoleTest.js
new file mode 100644
index 00000000..56e223bd
--- /dev/null
+++ b/test/ConsoleTest.js
@@ -0,0 +1,13 @@
+ConsoleTest = TestCase('ConsoleTest');
+
+ConsoleTest.prototype.testConsoleWrite = function(){
+ var consoleNode = $("
")[0];
+ nglr.consoleNode = consoleNode;
+ nglr.consoleLog("error", ["Hello", "world"]);
+ assertEquals($(consoleNode)[0].nodeName, 'DIV');
+ assertEquals($(consoleNode).text(), 'Hello world');
+ assertEquals($('div', consoleNode)[0].className, 'error');
+ nglr.consoleLog("error",["Bye"]);
+ assertEquals($(consoleNode).text(), 'Hello worldBye');
+ nglr.consoleNode = null;
+};
\ No newline at end of file
diff --git a/test/ControlBarTest.js b/test/ControlBarTest.js
new file mode 100644
index 00000000..c914c8ff
--- /dev/null
+++ b/test/ControlBarTest.js
@@ -0,0 +1,2 @@
+ControlBarTest = TestCase("ControlBarTest");
+
diff --git a/test/DataStoreTest.js b/test/DataStoreTest.js
new file mode 100644
index 00000000..9fe6c3df
--- /dev/null
+++ b/test/DataStoreTest.js
@@ -0,0 +1,617 @@
+DataStoreTest = TestCase('DataStoreTest');
+
+DataStoreTest.prototype.testSavePostsToServer = function(){
+ expectAsserts(10);
+ var response;
+ var post = function(data, callback){
+ var method = data[0][0];
+ var posted = data[0][2];
+ assertEquals("POST", method);
+ assertEquals("abc", posted.$entity);
+ assertEquals("123", posted.$id);
+ assertEquals("1", posted.$version);
+ assertFalse('function' == typeof posted.save);
+ response = nglr.fromJson(nglr.toJson(posted));
+ response.$entity = "abc";
+ response.$id = "123";
+ response.$version = "2";
+ callback(200, [response]);
+ };
+ var model;
+ var datastore = new nglr.DataStore(post);
+ model = datastore.entity('abc', {name: "value"})();
+ model.$id = "123";
+ model.$version = "1";
+
+ datastore.save(model, function(obj){
+ assertTrue(obj === model);
+ assertEquals(obj.$entity, "abc");
+ assertEquals(obj.$id, "123");
+ assertEquals(obj.$version, "2");
+ assertEquals(obj.name, "value");
+ obj.after = true;
+ });
+ datastore.flush();
+};
+
+DataStoreTest.prototype.testLoadGetsFromServer = function(){
+ expectAsserts(12);
+ var post = function(data, callback){
+ var method = data[0][0];
+ var path = data[0][1];
+ assertEquals("GET", method);
+ assertEquals("abc/1", path);
+ response = [{$entity:'abc', $id:'1', $version:'2', key:"value"}];
+ callback(200, response);
+ };
+ var datastore = new nglr.DataStore(post);
+
+ var model = datastore.entity("abc", {merge:true})();
+ assertEquals(datastore.load(model, '1', function(obj){
+ assertEquals(obj.$entity, "abc");
+ assertEquals(obj.$id, "1");
+ assertEquals(obj.$version, "2");
+ assertEquals(obj.key, "value");
+ }), model);
+ datastore.flush();
+ assertEquals(model.$entity, "abc");
+ assertEquals(model.$id, "1");
+ assertEquals(model.$version, "2");
+ assertEquals(model.key, "value");
+ assertEquals(model.merge, true);
+};
+
+DataStoreTest.prototype.testRemove = function(){
+ expectAsserts(8);
+ var response;
+ var post = function(data, callback){
+ var method = data[0][0];
+ var posted = data[0][2];
+ assertEquals("DELETE", method);
+ assertEquals("abc", posted.$entity);
+ assertEquals("123", posted.$id);
+ assertEquals("1", posted.$version);
+ assertFalse('function' == typeof posted.save);
+ response = nglr.fromJson(nglr.toJson(posted));
+ response.$entity = "abc";
+ response.$id = "123";
+ response.$version = "2";
+ callback(200, [response]);
+ };
+ var model;
+ var datastore = new nglr.DataStore(post);
+ model = datastore.entity('abc', {name: "value"})();
+ model.$id = "123";
+ model.$version = "1";
+
+ datastore.remove(model, function(obj){
+ assertEquals(obj.$id, "123");
+ assertEquals(obj.$version, "2");
+ assertEquals(obj.name, "value");
+ obj.after = true;
+ });
+ datastore.flush();
+
+};
+
+
+DataStoreTest.prototype.test401ResponseDoesNotCallCallback = function(){
+ expectAsserts(1);
+ var post = function(data, callback) {
+ callback(200, {$status_code: 401});
+ };
+
+ var datastore = new nglr.DataStore(post, {login:function(){
+ assertTrue(true);
+ }});
+
+ var onLoadAll = function(){
+ assertTrue(false, "onLoadAll should not be called when response is status 401");
+ };
+ datastore.bulkRequest.push({});
+ datastore.flush();
+ datastore.loadAll({type: "A"}, onLoadAll);
+};
+
+DataStoreTest.prototype.test403ResponseDoesNotCallCallback = function(){
+ expectAsserts(1);
+ var post = function(data, callback) {
+ callback(200, [{$status_code: 403}]);
+ };
+
+ var datastore = new nglr.DataStore(post, {notAuthorized:function(){
+ assertTrue(true);
+ }});
+
+ var onLoadAll = function(){
+ assertTrue(false, "onLoadAll should not be called when response is status 403");
+ };
+ datastore.bulkRequest.push({});
+ datastore.flush();
+ datastore.loadAll({type: "A"}, onLoadAll);
+};
+
+DataStoreTest.prototype.testLoadCalledWithoutIdShouldBeNoop = function(){
+ expectAsserts(2);
+ var post = function(url, callback){
+ assertTrue(false);
+ };
+ var datastore = new nglr.DataStore(post);
+ var model = datastore.entity("abc")();
+ assertEquals(datastore.load(model, undefined), model);
+ assertEquals(model.$entity, "abc");
+};
+
+DataStoreTest.prototype.testEntityFactory = function(){
+ var ds = new nglr.DataStore();
+ var Recipe = ds.entity("Recipe", {a:1, b:2});
+ assertEquals(Recipe.title, "Recipe");
+ assertEquals(Recipe.defaults.a, 1);
+ assertEquals(Recipe.defaults.b, 2);
+
+ var recipe = Recipe();
+ assertEquals(recipe.$entity, "Recipe");
+ assertEquals(recipe.a, 1);
+ assertEquals(recipe.b, 2);
+
+ recipe = new Recipe();
+ assertEquals(recipe.$entity, "Recipe");
+ assertEquals(recipe.a, 1);
+ assertEquals(recipe.b, 2);
+};
+
+DataStoreTest.prototype.testEntityFactoryNoDefaults = function(){
+ var ds = new nglr.DataStore();
+ var Recipe = ds.entity("Recipe");
+ assertEquals(Recipe.title, "Recipe");
+
+ recipe = new Recipe();
+ assertEquals(recipe.$entity, "Recipe");
+};
+
+DataStoreTest.prototype.testEntityFactoryWithInitialValues = function(){
+ var ds = new nglr.DataStore();
+ var Recipe = ds.entity("Recipe");
+
+ var recipe = Recipe({name: "name"});
+ assertEquals("name", recipe.name);
+};
+
+DataStoreTest.prototype.testEntityLoad = function(){
+ var ds = new nglr.DataStore();
+ var Recipe = ds.entity("Recipe", {a:1, b:2});
+ ds.load = function(instance, id, callback){
+ callback.apply(instance);
+ return instance;
+ };
+ var instance = null;
+ var recipe2 = Recipe.load("ID", function(){
+ instance = this;
+ });
+ assertTrue(recipe2 === instance);
+};
+
+DataStoreTest.prototype.testSaveScope = function(){
+ var ds = new nglr.DataStore();
+ var log = "";
+ var Person = ds.entity("Person");
+ var person1 = Person({name:"A", $entity:"Person", $id:"1", $version:"1"}, ds);
+ person1.$$anchor = "A";
+ var person2 = Person({name:"B", $entity:"Person", $id:"2", $version:"2"}, ds);
+ person2.$$anchor = "B";
+ var anchor = {};
+ ds.anchor = anchor;
+ ds._jsonRequest = function(request, callback){
+ log += "save(" + request[2].$id + ");";
+ callback({$id:request[2].$id});
+ };
+ ds.saveScope({person1:person1, person2:person2,
+ ignoreMe:{name: "ignore", save:function(callback){callback();}}}, function(){
+ log += "done();";
+ });
+ assertEquals("save(1);save(2);done();", log);
+ assertEquals(1, anchor.A);
+ assertEquals(2, anchor.B);
+};
+
+DataStoreTest.prototype.testEntityLoadAllRows = function(){
+ var ds = new nglr.DataStore();
+ var Recipe = ds.entity("Recipe");
+ var list = [];
+ ds.loadAll = function(entity, callback){
+ assertTrue(Recipe === entity);
+ callback.apply(list);
+ return list;
+ };
+ var items = Recipe.all(function(){
+ assertTrue(list === this);
+ });
+ assertTrue(items === list);
+};
+
+DataStoreTest.prototype.testLoadAll = function(){
+ expectAsserts(8);
+ var post = function(data, callback){
+ assertEquals("GET", data[0][0]);
+ assertEquals("A", data[0][1]);
+ callback(200, [[{$entity:'A', $id:'1'},{$entity:'A', $id:'2'}]]);
+ };
+ var datastore = new nglr.DataStore(post);
+ var list = datastore.entity("A").all(function(){
+ assertTrue(true);
+ });
+ datastore.flush();
+ assertEquals(list.length, 2);
+ assertEquals(list[0].$entity, "A");
+ assertEquals(list[0].$id, "1");
+ assertEquals(list[1].$entity, "A");
+ assertEquals(list[1].$id, "2");
+};
+
+DataStoreTest.prototype.testQuery = function(){
+ expectAsserts(5);
+ var post = function(data, callback) {
+ assertEquals("GET", data[0][0]);
+ assertEquals("Employee/managerId=123abc", data[0][1]);
+ callback(200, [[{$entity:"Employee", $id: "456", managerId: "123ABC"}]]);
+
+ };
+ var datastore = new nglr.DataStore(post);
+ var Employee = datastore.entity("Employee");
+ var list = Employee.query('managerId', "123abc", function(){
+ assertTrue(true);
+ });
+ datastore.flush();
+ assertJsonEquals([[{$entity:"Employee", $id: "456", managerId: "123ABC"}]], datastore._cache.$collections);
+ assertEquals(list[0].$id, "456");
+};
+
+DataStoreTest.prototype.testLoadingDocumentRefreshesExistingArrays = function() {
+ expectAsserts(12);
+ var post;
+ var datastore = new nglr.DataStore(function(r, c){post(r,c);});
+ var Book = datastore.entity('Book');
+ post = function(req, callback) {
+ callback(200, [[{$id:1, $entity:"Book", name:"Moby"},
+ {$id:2, $entity:"Book", name:"Dick"}]]);
+ };
+ var allBooks = Book.all();
+ datastore.flush();
+ var queryBooks = Book.query("a", "b");
+ datastore.flush();
+ assertEquals("Moby", allBooks[0].name);
+ assertEquals("Dick", allBooks[1].name);
+ assertEquals("Moby", queryBooks[0].name);
+ assertEquals("Dick", queryBooks[1].name);
+
+ post = function(req, callback) {
+ assertEquals('[["GET","Book/1"]]', nglr.toJson(req));
+ callback(200, [{$id:1, $entity:"Book", name:"Moby Dick"}]);
+ };
+ var book = Book.load(1);
+ datastore.flush();
+ assertEquals("Moby Dick", book.name);
+ assertEquals("Moby Dick", allBooks[0].name);
+ assertEquals("Moby Dick", queryBooks[0].name);
+
+ post = function(req, callback) {
+ assertEquals('POST', req[0][0]);
+ callback(200, [{$id:1, $entity:"Book", name:"The Big Fish"}]);
+ };
+ book.$save();
+ datastore.flush();
+ assertEquals("The Big Fish", book.name);
+ assertEquals("The Big Fish", allBooks[0].name);
+ assertEquals("The Big Fish", queryBooks[0].name);
+};
+
+DataStoreTest.prototype.testEntityProperties = function() {
+ expectAsserts(2);
+ var datastore = new nglr.DataStore();
+ var callback = {};
+
+ datastore._jsonRequest = function(request, callbackFn) {
+ assertJsonEquals(["GET", "Cheese/$properties"], request);
+ assertEquals(callback, callbackFn);
+ };
+
+ var Cheese = datastore.entity("Cheese");
+ Cheese.properties(callback);
+
+};
+
+DataStoreTest.prototype.testLoadInstanceIsNotFromCache = function() {
+ var post;
+ var datastore = new nglr.DataStore(function(r, c){post(r,c);});
+ var Book = datastore.entity('Book');
+
+ post = function(req, callback) {
+ assertEquals('[["GET","Book/1"]]', nglr.toJson(req));
+ callback(200, [{$id:1, $entity:"Book", name:"Moby Dick"}]);
+ };
+ var book = Book.load(1);
+ datastore.flush();
+ assertEquals("Moby Dick", book.name);
+ assertFalse(book === datastore._cache['Book/1']);
+};
+
+DataStoreTest.prototype.testLoadStarsIsNewDocument = function() {
+ var datastore = new nglr.DataStore();
+ var Book = datastore.entity('Book');
+ var book = Book.load('*');
+ assertEquals('Book', book.$entity);
+};
+
+DataStoreTest.prototype.testUndefinedEntityReturnsNullValueObject = function() {
+ var datastore = new nglr.DataStore();
+ var Entity = datastore.entity(undefined);
+ var all = Entity.all();
+ assertEquals(0, all.length);
+};
+
+DataStoreTest.prototype.testFetchEntities = function(){
+ expectAsserts(6);
+ var post = function(data, callback){
+ assertJsonEquals(["GET", "$entities"], data[0]);
+ callback(200, [{A:0, B:0}]);
+ };
+ var datastore = new nglr.DataStore(post);
+ var entities = datastore.entities(function(){
+ assertTrue(true);
+ });
+ datastore.flush();
+ assertJsonEquals([], datastore.bulkRequest);
+ assertEquals(2, entities.length);
+ assertEquals("A", entities[0].title);
+ assertEquals("B", entities[1].title);
+};
+
+DataStoreTest.prototype.testItShouldMigrateSchema = function() {
+ var datastore = new nglr.DataStore();
+ var Entity = datastore.entity("Entity", {a:[], user:{name:"Misko", email:""}});
+ var doc = Entity().$loadFrom({b:'abc', user:{email:"misko@hevery.com"}});
+ assertFalse(
+ nglr.toJson({a:[], b:'abc', user:{name:"Misko", email:"misko@hevery.com"}}) ==
+ nglr.toJson(doc));
+ doc.$migrate();
+ assertEquals(
+ nglr.toJson({a:[], b:'abc', user:{name:"Misko", email:"misko@hevery.com"}}),
+ nglr.toJson(doc));
+};
+
+DataStoreTest.prototype.testItShouldCollectRequestsForBulk = function() {
+ var ds = new nglr.DataStore();
+ var Book = ds.entity("Book");
+ var Library = ds.entity("Library");
+ Book.all();
+ Library.load("123");
+ assertEquals(2, ds.bulkRequest.length);
+ assertJsonEquals(["GET", "Book"], ds.bulkRequest[0]);
+ assertJsonEquals(["GET", "Library/123"], ds.bulkRequest[1]);
+};
+
+DataStoreTest.prototype.testEmptyFlushShouldDoNothing = function () {
+ var ds = new nglr.DataStore(function(){
+ fail("expecting noop");
+ });
+ ds.flush();
+};
+
+DataStoreTest.prototype.testFlushShouldCallAllCallbacks = function() {
+ var log = "";
+ function post(request, callback){
+ log += 'BulkRequest:' + nglr.toJson(request) + ';';
+ callback(200, [[{$id:'ABC'}], {$id:'XYZ'}]);
+ }
+ var ds = new nglr.DataStore(post);
+ var Book = ds.entity("Book");
+ var Library = ds.entity("Library");
+ Book.all(function(instance){
+ log += nglr.toJson(instance) + ';';
+ });
+ Library.load("123", function(instance){
+ log += nglr.toJson(instance) + ';';
+ });
+ assertEquals("", log);
+ ds.flush();
+ assertJsonEquals([], ds.bulkRequest);
+ assertEquals('BulkRequest:[["GET","Book"],["GET","Library/123"]];[{"$id":"ABC"}];{"$id":"XYZ"};', log);
+};
+
+DataStoreTest.prototype.testSaveOnNotLoggedInRetriesAfterLoggin = function(){
+ var log = "";
+ var book;
+ var ds = new nglr.DataStore(null, {login:function(c){c();}});
+ ds.post = function (request, callback){
+ assertJsonEquals([["POST", "", book]], request);
+ ds.post = function(request, callback){
+ assertJsonEquals([["POST", "", book]], request);
+ ds.post = function(){fail("too much recursion");};
+ callback(200, [{saved:"ok"}]);
+ };
+ callback(200, {$status_code:401});
+ };
+ book = ds.entity("Book")({name:"misko"});
+ book.$save();
+ ds.flush();
+ assertJsonEquals({saved:"ok"}, book);
+};
+
+DataStoreTest.prototype.testItShouldRemoveItemFromCollectionWhenDeleted = function() {
+ expectAsserts(6);
+ var ds = new nglr.DataStore();
+ ds.post = function(request, callback){
+ assertJsonEquals([["GET", "Book"]], request);
+ callback(200, [[{name:"Moby Dick", $id:123, $entity:'Book'}]]);
+ };
+ var Book = ds.entity("Book");
+ var books = Book.all();
+ ds.flush();
+ assertJsonEquals([[{name:"Moby Dick", $id:123, $entity:'Book'}]], ds._cache.$collections);
+ assertDefined(ds._cache['Book/123']);
+ var book = Book({$id:123});
+ ds.post = function(request, callback){
+ assertJsonEquals([["DELETE", "", book]], request);
+ callback(200, [book]);
+ };
+ ds.remove(book);
+ ds.flush();
+ assertUndefined(ds._cache['Book/123']);
+ assertJsonEquals([[]],ds._cache.$collections);
+};
+
+DataStoreTest.prototype.testItShouldAddToAll = function() {
+ expectAsserts(8);
+ var ds = new nglr.DataStore();
+ ds.post = function(request, callback){
+ assertJsonEquals([["GET", "Book"]], request);
+ callback(200, [[]]);
+ };
+ var Book = ds.entity("Book");
+ var books = Book.all();
+ assertEquals(0, books.length);
+ ds.flush();
+ var moby = Book({name:'moby'});
+ moby.$save();
+ ds.post = function(request, callback){
+ assertJsonEquals([["POST", "", moby]], request);
+ moby.$id = '123';
+ callback(200, [moby]);
+ };
+ ds.flush();
+ assertEquals(1, books.length);
+ assertEquals(moby, books[0]);
+
+ moby.$save();
+ ds.flush();
+ assertEquals(1, books.length);
+ assertEquals(moby, books[0]);
+};
+
+DataStoreTest.prototype.testItShouldReturnCreatedDocumentCountByUser = function(){
+ expectAsserts(2);
+ var datastore = new nglr.DataStore(
+ function(request, callback){
+ assertJsonEquals([["GET", "$users"]], request);
+ callback(200, [{misko:1, adam:1}]);
+ });
+ var users = datastore.documentCountsByUser();
+ assertJsonEquals({misko:1, adam:1}, users);
+};
+
+
+DataStoreTest.prototype.testItShouldReturnDocumentIdsForUeserByEntity = function(){
+ expectAsserts(2);
+ var datastore = new nglr.DataStore(
+ function(request, callback){
+ assertJsonEquals([["GET", "$users/misko@hevery.com"]], request);
+ callback(200, [{Book:["1"], Library:["2"]}]);
+ });
+ var users = datastore.userDocumentIdsByEntity("misko@hevery.com");
+ assertJsonEquals({Book:["1"], Library:["2"]}, users);
+};
+
+DataStoreTest.prototype.testItShouldReturnNewInstanceOn404 = function(){
+ expectAsserts(7);
+ var log = "";
+ var datastore = new nglr.DataStore(
+ function(request, callback){
+ assertJsonEquals([["GET", "User/misko"]], request);
+ callback(200, [{$status_code:404}]);
+ });
+ var User = datastore.entity("User", {admin:false});
+ var user = User.loadOrCreate('misko', function(i){log+="cb "+i.$id+";";});
+ datastore.flush();
+ assertEquals("misko", user.$id);
+ assertEquals("User", user.$entity);
+ assertEquals(false, user.admin);
+ assertEquals("undefined", typeof user.$secret);
+ assertEquals("undefined", typeof user.$version);
+ assertEquals("cb misko;", log);
+};
+
+DataStoreTest.prototype.testItShouldReturnNewInstanceOn404 = function(){
+ var log = "";
+ var datastore = new nglr.DataStore(
+ function(request, callback){
+ assertJsonEquals([["GET", "User/misko"],["GET", "User/adam"]], request);
+ callback(200, [{$id:'misko'},{$id:'adam'}]);
+ });
+ var User = datastore.entity("User");
+ var users = User.loadMany(['misko', 'adam'], function(i){log+="cb "+nglr.toJson(i)+";";});
+ datastore.flush();
+ assertEquals("misko", users[0].$id);
+ assertEquals("adam", users[1].$id);
+ assertEquals('cb [{"$id":"misko"},{"$id":"adam"}];', log);
+};
+
+DataStoreTest.prototype.testItShouldCreateJoinAndQuery = function() {
+ var datastore = new nglr.DataStore();
+ var Invoice = datastore.entity("Invoice");
+ var Customer = datastore.entity("Customer");
+ var InvoiceWithCustomer = datastore.join({
+ invoice:{join:Invoice},
+ customer:{join:Customer, on:"invoice.customer"}
+ });
+ var invoiceWithCustomer = InvoiceWithCustomer.query("invoice.month", 1);
+ assertEquals([], invoiceWithCustomer);
+ assertJsonEquals([["GET", "Invoice/month=1"]], datastore.bulkRequest);
+ var request = datastore.bulkRequest.shift();
+ request.$$callback([{$id:1, customer:1},{$id:2, customer:1},{$id:3, customer:3}]);
+ assertJsonEquals([["GET","Customer/1"],["GET","Customer/3"]], datastore.bulkRequest);
+ datastore.bulkRequest.shift().$$callback({$id:1});
+ datastore.bulkRequest.shift().$$callback({$id:3});
+ assertJsonEquals([
+ {invoice:{$id:1,customer:1},customer:{$id:1}},
+ {invoice:{$id:2,customer:1},customer:{$id:1}},
+ {invoice:{$id:3,customer:3},customer:{$id:3}}], invoiceWithCustomer);
+};
+
+DataStoreTest.prototype.testItShouldThrowIfMoreThanOneEntityIsPrimary = function() {
+ var datastore = new nglr.DataStore();
+ var Invoice = datastore.entity("Invoice");
+ var Customer = datastore.entity("Customer");
+ assertThrows("Exactly one entity needs to be primary.", function(){
+ datastore.join({
+ invoice:{join:Invoice},
+ customer:{join:Customer}
+ });
+ });
+};
+
+DataStoreTest.prototype.testItShouldThrowIfLoopInReferences = function() {
+ var datastore = new nglr.DataStore();
+ var Invoice = datastore.entity("Invoice");
+ var Customer = datastore.entity("Customer");
+ assertThrows("Infinite loop in join: invoice -> customer", function(){
+ datastore.join({
+ invoice:{join:Invoice, on:"customer.invoice"},
+ customer:{join:Customer, on:"invoice.customer"}
+ });
+ });
+};
+
+DataStoreTest.prototype.testItShouldThrowIfReferenceToNonExistantJoin = function() {
+ var datastore = new nglr.DataStore();
+ var Invoice = datastore.entity("Invoice");
+ var Customer = datastore.entity("Customer");
+ assertThrows("Named entity 'x' is undefined.", function(){
+ datastore.join({
+ invoice:{join:Invoice, on:"x.invoice"},
+ customer:{join:Customer, on:"invoice.customer"}
+ });
+ });
+};
+
+DataStoreTest.prototype.testItShouldThrowIfQueryOnNonPrimary = function() {
+ var datastore = new nglr.DataStore();
+ var Invoice = datastore.entity("Invoice");
+ var Customer = datastore.entity("Customer");
+ var InvoiceWithCustomer = datastore.join({
+ invoice:{join:Invoice},
+ customer:{join:Customer, on:"invoice.customer"}
+ });
+ assertThrows("Named entity 'customer' is not a primary entity.", function(){
+ InvoiceWithCustomer.query("customer.month", 1);
+ });
+};
diff --git a/test/EntityDeclarationTest.js b/test/EntityDeclarationTest.js
new file mode 100644
index 00000000..5cab90f4
--- /dev/null
+++ b/test/EntityDeclarationTest.js
@@ -0,0 +1,46 @@
+EntityDeclarationTest = TestCase('EntityDeclarationTest');
+
+EntityDeclarationTest.prototype.testEntityTypeOnly = function(){
+ expectAsserts(2);
+ var scope = new nglr.Scope({$datastore:{entity:function(name){
+ assertEquals("Person", name);
+ }}});
+ var init = scope.entity("Person");
+ assertEquals("", init);
+};
+
+EntityDeclarationTest.prototype.testWithDefaults = function(){
+ expectAsserts(4);
+ var scope = new nglr.Scope({$datastore:{entity:function(name, init){
+ assertEquals("Person", name);
+ assertEquals("=a:", init.a);
+ assertEquals(0, init.b.length);
+ }}});
+ var init = scope.entity('Person:{a:"=a:", b:[]}');
+ assertEquals("", init);
+};
+
+EntityDeclarationTest.prototype.testWithName = function(){
+ expectAsserts(2);
+ var scope = new nglr.Scope({$datastore:{entity:function(name, init){
+ assertEquals("Person", name);
+ return function (){ return {}; };
+ }}});
+ var init = scope.entity('friend=Person');
+ assertEquals("$anchor.friend:{friend=Person.load($anchor.friend);friend.$$anchor=\"friend\";};", init);
+};
+
+EntityDeclarationTest.prototype.testMultipleEntities = function(){
+ expectAsserts(3);
+ var expect = ['Person', 'Book'];
+ var i=0;
+ var scope = new nglr.Scope({$datastore:{entity:function(name, init){
+ assertEquals(expect[i], name);
+ i++;
+ return function (){ return {}; };
+ }}});
+ var init = scope.entity('friend=Person;book=Book;');
+ assertEquals("$anchor.friend:{friend=Person.load($anchor.friend);friend.$$anchor=\"friend\";};" +
+ "$anchor.book:{book=Book.load($anchor.book);book.$$anchor=\"book\";};",
+ init);
+};
diff --git a/test/FileControllerTest.js b/test/FileControllerTest.js
new file mode 100644
index 00000000..ca5925e4
--- /dev/null
+++ b/test/FileControllerTest.js
@@ -0,0 +1,98 @@
+FileControllerTest = TestCase('FileControllerTest');
+
+FileControllerTest.prototype.testOnSelectUpdateView = function(){
+ var view = jQuery('
');
+ var swf = {};
+ var controller = new nglr.FileController(view, null, swf);
+ swf.uploadFile = function(path){};
+ controller._on_select('A', 9, '9 bytes');
+ assertEquals(view.find('a').text(), "A");
+ assertEquals(view.find('span').text(), "9 bytes");
+};
+
+FileControllerTest.prototype.testUpdateModelView = function(){
+ var view = nglr.FileController.template('');
+ var input = $('
');
+ var controller;
+ var scope = new nglr.Scope({value:{}, $binder:{updateView:function(){
+ controller.updateView(scope);
+ }}});
+ view.data('scope', scope);
+ controller = new nglr.FileController(view, 'value.input', null, "http://server_base");
+ var value = '{"text":"A", "size":123, "id":"890"}';
+ controller._on_uploadCompleteData(value);
+ controller.updateView(scope);
+ assertEquals(scope.get('value.input.text'), 'A');
+ assertEquals(scope.get('value.input.size'), 123);
+ assertEquals(scope.get('value.input.id'), '890');
+ assertEquals(scope.get('value.input.url'), 'http://server_base/_attachments/890/A');
+ assertEquals(view.find('a').text(), "A");
+ assertEquals(view.find('a').attr('href'), "http://server_base/_attachments/890/A");
+ assertEquals(view.find('span').text(), "123 bytes");
+};
+
+FileControllerTest.prototype.testFileUpload = function(){
+ expectAsserts(1);
+ var swf = {};
+ var controller = new nglr.FileController(null, null, swf, "http://server_base");
+ swf.uploadFile = function(path){
+ assertEquals("http://server_base/_attachments", path);
+ };
+ controller.name = "Name";
+ controller.upload();
+};
+
+FileControllerTest.prototype.testFileUploadNoFileIsNoop = function(){
+ expectAsserts(0);
+ var swf = {uploadFile:function(path){
+ fail();
+ }};
+ var controller = new nglr.FileController(null, swf);
+ controller.upload("basePath", null);
+};
+
+FileControllerTest.prototype.testRemoveAttachment = function(){
+ var doc = nglr.FileController.template();
+ var input = $('
');
+ var scope = new nglr.Scope();
+ input.data('scope', scope);
+ var controller = new nglr.FileController(doc, 'file', null, null);
+ controller.updateView(scope);
+ assertEquals(false, doc.find('input').attr('checked'));
+
+ scope.set('file', {url:'url', size:123});
+ controller.updateView(scope);
+ assertEquals(true, doc.find('input').attr('checked'));
+
+ doc.find('input').attr('checked', false);
+ controller.updateModel(scope);
+ assertNull(scope.get('file'));
+
+ doc.find('input').attr('checked', true);
+ controller.updateModel(scope);
+ assertEquals('url', scope.get('file.url'));
+ assertEquals(123, scope.get('file.size'));
+};
+
+FileControllerTest.prototype.testShouldEmptyOutOnUndefined = function () {
+ var view = nglr.FileController.template('hello');
+ var controller = new nglr.FileController(view, 'abc', null, null);
+
+ var scope = new nglr.Scope();
+ scope.set('abc', {text: 'myname', url: 'myurl', size: 1234});
+
+ controller.updateView(scope);
+ assertEquals("myurl", view.find('a').attr('href'));
+ assertEquals("myname", view.find('a').text());
+ assertEquals(true, view.find('input').is(':checked'));
+ assertEquals("1.2 KB", view.find('span').text());
+
+ scope.set('abc', undefined);
+ controller.updateView(scope);
+ assertEquals("myurl", view.find('a').attr('href'));
+ assertEquals("myname", view.find('a').text());
+ assertEquals(false, view.find('input').is(':checked'));
+ assertEquals("1.2 KB", view.find('span').text());
+};
+
+
diff --git a/test/FiltersTest.js b/test/FiltersTest.js
new file mode 100644
index 00000000..8943fdd4
--- /dev/null
+++ b/test/FiltersTest.js
@@ -0,0 +1,153 @@
+FiltersTest = TestCase('FiltersTest');
+
+FiltersTest.prototype.testCurrency = function(){
+ var html = $('
');
+ var context = {element:html[0]};
+ var currency = nglr.bind(context, angular.filter.currency);
+
+ assertEquals(currency(0), '$0.00');
+ assertEquals(html.hasClass('ng-format-negative'), false);
+ assertEquals(currency(-999), '$-999.00');
+ assertEquals(html.hasClass('ng-format-negative'), true);
+ assertEquals(currency(1234.5678), '$1,234.57');
+ assertEquals(html.hasClass('ng-format-negative'), false);
+};
+
+FiltersTest.prototype.testFilterThisIsContext = function(){
+ expectAsserts(2);
+ var scope = new nglr.Scope();
+ nglr.Scope.expressionCache = {};
+ var context = {element:123};
+ angular.filter.testFn = function () {
+ assertEquals('Context not equal', this, context);
+ assertEquals('scope not equal', this.scope, scope);
+ };
+ scope.eval("0|testFn", context);
+ delete angular.filter['testFn'];
+};
+
+FiltersTest.prototype.testNumberFormat = function(){
+ var context = {jqElement:$('
')};
+ var number = nglr.bind(context, angular.filter.number);
+
+ assertEquals('0', number(0, 0));
+ assertEquals('0.00', number(0));
+ assertEquals('-999.00', number(-999));
+ assertEquals('1,234.57', number(1234.5678));
+ assertEquals('', number(Number.NaN));
+ assertEquals('1,234.57', number("1234.5678"));
+ assertEquals("", number(1/0));
+};
+
+FiltersTest.prototype.testJson = function () {
+ assertEquals(nglr.toJson({a:"b"}, true), angular.filter.json({a:"b"}));
+};
+
+FiltersTest.prototype.testPackageTracking = function () {
+ var assert = function(title, trackingNo) {
+ var val = angular.filter.trackPackage(trackingNo, title);
+ assertNotNull("Did Not Match: " + trackingNo, val);
+ assertEquals(angular.filter.Meta.TAG, val.TAG);
+ assertEquals(title + ": " + nglr.trim(trackingNo), val.text);
+ assertNotNull(val.url);
+ assertEquals(nglr.trim(trackingNo), val.trackingNo);
+ assertEquals('
' + val.text + ' ', val.html);
+ };
+ assert('UPS', ' 1Z 999 999 99 9999 999 9 ');
+ assert('UPS', '1ZW5w5220379084747');
+
+ assert('FedEx', '418822131061812');
+ assert('FedEx', '9612019 5935 3267 2473 738');
+ assert('FedEx', '9612019593532672473738');
+ assert('FedEx', '235354667129449');
+ assert('FedEx', '915368880571');
+ assert('FedEx', '901712142390');
+ assert('FedEx', '297391510063413');
+
+ assert('USPS', '9101 8052 1390 7402 4335 49');
+ assert('USPS', '9101010521297963339560');
+ assert('USPS', '9102901001301038667029');
+ assert('USPS', '910 27974 4490 3000 8916 56');
+ assert('USPS', '9102801438635051633253');
+};
+
+FiltersTest.prototype.testLink = function() {
+ var assert = function(text, url, obj){
+ var val = angular.filter.link(obj);
+ assertEquals(angular.filter.Meta.TAG, val.TAG);
+ assertEquals('
' + text + ' ', val.html);
+ };
+ assert("url", "url", "url");
+ assert("hello", "url", {text:"hello", url:"url"});
+ assert("a@b.com", "mailto:a@b.com", "a@b.com");
+};
+
+FiltersTest.prototype.testBytes = function(){
+ var controller = new nglr.FileController();
+ assertEquals(angular.filter.bytes(123), '123 bytes');
+ assertEquals(angular.filter.bytes(1234), '1.2 KB');
+ assertEquals(angular.filter.bytes(1234567), '1.1 MB');
+};
+
+FiltersTest.prototype.testImage = function(){
+ assertEquals(null, angular.filter.image());
+ assertEquals(null, angular.filter.image({}));
+ assertEquals(null, angular.filter.image(""));
+ assertEquals('
', angular.filter.image({url:"abc"}).html);
+ assertEquals(
+ '
',
+ angular.filter.image({url:"abc"}, 10).html);
+ assertEquals(
+ '
',
+ angular.filter.image({url:"abc"}, 10, 20).html);
+};
+
+FiltersTest.prototype.testQRcode = function() {
+ assertEquals(
+ '
',
+ angular.filter.qrcode('Hello world').html);
+ assertEquals(
+ '
',
+ angular.filter.qrcode('http://server?a&b=c', 100).html);
+};
+
+FiltersTest.prototype.testLowercase = function() {
+ assertEquals('abc', angular.filter.lowercase('AbC'));
+ assertEquals(null, angular.filter.lowercase(null));
+};
+
+FiltersTest.prototype.testUppercase = function() {
+ assertEquals('ABC', angular.filter.uppercase('AbC'));
+ assertEquals(null, angular.filter.uppercase(null));
+};
+
+FiltersTest.prototype.testLineCount = function() {
+ assertEquals(1, angular.filter.linecount(null));
+ assertEquals(1, angular.filter.linecount(''));
+ assertEquals(1, angular.filter.linecount('a'));
+ assertEquals(2, angular.filter.linecount('a\nb'));
+ assertEquals(3, angular.filter.linecount('a\nb\nc'));
+};
+
+FiltersTest.prototype.testIf = function() {
+ assertEquals('A', angular.filter['if']('A', true));
+ assertEquals(undefined, angular.filter['if']('A', false));
+};
+
+FiltersTest.prototype.testUnless = function() {
+ assertEquals('A', angular.filter.unless('A', false));
+ assertEquals(undefined, angular.filter.unless('A', true));
+};
+
+FiltersTest.prototype.testGoogleChartApiEncode = function() {
+ assertEquals(
+ '
',
+ angular.filter.googleChartApi.encode({cht:"qr", chl:"Hello world"}).html);
+};
+
+FiltersTest.prototype.testHtml = function() {
+ assertEquals(
+ "a
c d",
+ angular.filter.html("a
c d").html);
+ assertTrue(angular.filter.html("a
c d") instanceof angular.filter.Meta);
+};
diff --git a/test/JsonTest.js b/test/JsonTest.js
new file mode 100644
index 00000000..5c3644f5
--- /dev/null
+++ b/test/JsonTest.js
@@ -0,0 +1,69 @@
+JsonTest = TestCase("JsonTest");
+
+JsonTest.prototype.testPrimitives = function () {
+ assertEquals("null", nglr.toJson(0/0));
+ assertEquals("null", nglr.toJson(null));
+ assertEquals("true", nglr.toJson(true));
+ assertEquals("false", nglr.toJson(false));
+ assertEquals("123.45", nglr.toJson(123.45));
+ assertEquals('"abc"', nglr.toJson("abc"));
+ assertEquals('"a \\t \\n \\r b \\\\"', nglr.toJson("a \t \n \r b \\"));
+};
+
+JsonTest.prototype.testEscaping = function () {
+ assertEquals("\"7\\\\\\\"7\"", nglr.toJson("7\\\"7"));
+};
+
+JsonTest.prototype.testObjects = function () {
+ assertEquals('{"a":1,"b":2}', nglr.toJson({a:1,b:2}));
+ assertEquals('{"a":{"b":2}}', nglr.toJson({a:{b:2}}));
+ assertEquals('{"a":{"b":{"c":0}}}', nglr.toJson({a:{b:{c:0}}}));
+ assertEquals('{"a":{"b":null}}', nglr.toJson({a:{b:0/0}}));
+};
+
+JsonTest.prototype.testObjectPretty = function () {
+ assertEquals('{\n "a":1,\n "b":2}', nglr.toJson({a:1,b:2}, true));
+ assertEquals('{\n "a":{\n "b":2}}', nglr.toJson({a:{b:2}}, true));
+};
+
+JsonTest.prototype.testArray = function () {
+ assertEquals('[]', nglr.toJson([]));
+ assertEquals('[1,"b"]', nglr.toJson([1,"b"]));
+};
+
+JsonTest.prototype.testIgnoreFunctions = function () {
+ assertEquals('[null,1]', nglr.toJson([function(){},1]));
+ assertEquals('{}', nglr.toJson({a:function(){}}));
+};
+
+JsonTest.prototype.testParseNull = function () {
+ assertNull(nglr.fromJson("null"));
+};
+
+JsonTest.prototype.testParseBoolean = function () {
+ assertTrue(nglr.fromJson("true"));
+ assertFalse(nglr.fromJson("false"));
+};
+
+JsonTest.prototype.test$$isIgnored = function () {
+ assertEquals("{}", nglr.toJson({$$:0}));
+};
+
+JsonTest.prototype.testArrayWithEmptyItems = function () {
+ var a = [];
+ a[1] = "X";
+ assertEquals('[null,"X"]', nglr.toJson(a));
+};
+
+JsonTest.prototype.testItShouldEscapeUnicode = function () {
+ assertEquals(1, "\u00a0".length);
+ assertEquals(8, nglr.toJson("\u00a0").length);
+ assertEquals(1, nglr.fromJson(nglr.toJson("\u00a0")).length);
+};
+
+JsonTest.prototype.testItShouldUTCDates = function() {
+ var date = angular.String.toDate("2009-10-09T01:02:03Z");
+ assertEquals('"2009-10-09T01:02:03Z"', nglr.toJson(date));
+ assertEquals(date.getTime(),
+ nglr.fromJson('"2009-10-09T01:02:03Z"').getTime());
+};
diff --git a/test/LoaderTest.js b/test/LoaderTest.js
new file mode 100644
index 00000000..91a804a5
--- /dev/null
+++ b/test/LoaderTest.js
@@ -0,0 +1,70 @@
+LoaderTest = TestCase('LoaderTest');
+
+LoaderTest.prototype.testLoadCss = function(){
+ if ($.browser.safari) return;
+ var head = jQuery('
')[0];
+ var loader = new nglr.Loader(document, head, {});
+ var log = '';
+ loader.config.server = 'http://';
+ loader.loadCss('x');
+ assertEquals($(head).find('link').attr('href'), 'http://x');
+};
+
+LoaderTest.prototype.testDefaultDatabasePathFromSubdomain = function() {
+ var loader = new nglr.Loader(null, null, {server:"http://account.getangular.com", database:"database"});
+ loader.computeConfiguration();
+ assertEquals("database", loader.config.database);
+
+ loader = new nglr.Loader(null, null, {server:"http://account.getangular.com"});
+ loader.computeConfiguration();
+ assertEquals("account", loader.config.database);
+
+ loader = new nglr.Loader(null, null, {server:"https://account.getangular.com"});
+ loader.computeConfiguration();
+ assertEquals("account", loader.config.database);
+};
+
+
+
+UrlWatcherTest = TestCase('UrlWatcherTest');
+
+UrlWatcherTest.prototype.testUrlWatcher = function () {
+ expectAsserts(2);
+ var location = {href:"http://server", hash:""};
+ var watcher = new nglr.UrlWatcher(location);
+ watcher.delay = 1;
+ watcher.listener = function(url){
+ assertEquals('http://getangular.test', url);
+ };
+ watcher.setTimeout = function(fn, delay){
+ assertEquals(1, delay);
+ location.href = "http://getangular.test";
+ watcher.setTimeout = function(fn, delay) {
+ };
+ fn();
+ };
+ watcher.watch();
+};
+
+UrlWatcherTest.prototype.testItShouldFireOnUpdateEventWhenSpecialURLSet = function(){
+ expectAsserts(2);
+ var location = {href:"http://server", hash:"#$iframe_notify=1234"};
+ var watcher = new nglr.UrlWatcher(location);
+ nglr._iframe_notify_1234 = function () {
+ assertEquals("undefined", typeof nglr._iframe_notify_1234);
+ assertEquals("http://server2#", location.href);
+ };
+ watcher.delay = 1;
+ watcher.expectedUrl = "http://server2";
+ watcher.setTimeout = function(fn, delay){
+ watcher.setTimeout = function(fn, delay) {};
+ fn();
+ };
+ watcher.watch();
+};
+
+FunctionTest = TestCase("FunctionTest");
+
+FunctionTest.prototype.testEscapeHtml = function () {
+ assertEquals("<div>&</div>", nglr.escapeHtml('
&
'));
+};
\ No newline at end of file
diff --git a/test/ModelTest.js b/test/ModelTest.js
new file mode 100644
index 00000000..5d9119a1
--- /dev/null
+++ b/test/ModelTest.js
@@ -0,0 +1,84 @@
+ModelTest = TestCase('ModelTest');
+
+ModelTest.prototype.testLoadSaveOperations = function(){
+ var m1 = new nglr.DataStore().entity('A')();
+ m1.a = 1;
+
+ var m2 = {b:1};
+
+ m1.$loadFrom(m2);
+
+ assertTrue(!m1.a);
+ assertEquals(m1.b, 1);
+};
+
+ModelTest.prototype.testLoadfromDoesNotClobberFunctions = function(){
+ var m1 = new nglr.DataStore().entity('A')();
+ m1.id = function(){return 'OK';};
+ m1.$loadFrom({id:null});
+ assertEquals(m1.id(), 'OK');
+
+ m1.b = 'OK';
+ m1.$loadFrom({b:function(){}});
+ assertEquals(m1.b, 'OK');
+};
+
+ModelTest.prototype.testDataStoreDoesNotGetClobbered = function(){
+ var ds = new nglr.DataStore();
+ var m = ds.entity('A')();
+ assertTrue(m.$$entity.datastore === ds);
+ m.$loadFrom({});
+ assertTrue(m.$$entity.datastore === ds);
+};
+
+ModelTest.prototype.testManagedModelDelegatesMethodsToDataStore = function(){
+ expectAsserts(7);
+ var datastore = new nglr.DataStore();
+ var model = datastore.entity("A", {a:1})();
+ var fn = {};
+ datastore.save = function(instance, callback) {
+ assertTrue(model === instance);
+ assertTrue(callback === fn);
+ };
+ datastore.remove = function(instance, callback) {
+ assertTrue(model === instance);
+ assertTrue(callback === fn);
+ };
+ datastore.load = function(instance, id, callback) {
+ assertTrue(model === instance);
+ assertTrue(id === "123");
+ assertTrue(callback === fn);
+ };
+ model.$save(fn);
+ model.$delete(fn);
+ model.$loadById("123", fn);
+};
+
+ModelTest.prototype.testManagedModelCanBeForcedToFlush = function(){
+ expectAsserts(6);
+ var datastore = new nglr.DataStore();
+ var model = datastore.entity("A", {a:1})();
+
+ datastore.save = function(instance, callback) {
+ assertTrue(model === instance);
+ assertTrue(callback === undefined);
+ };
+ datastore.remove = function(instance, callback) {
+ assertTrue(model === instance);
+ assertTrue(callback === undefined);
+ };
+ datastore.flush = function(){
+ assertTrue(true);
+ };
+ model.$save(true);
+ model.$delete(true);
+};
+
+
+ModelTest.prototype.testItShouldMakeDeepCopyOfInitialValues = function (){
+ var initial = {a:[]};
+ var entity = new nglr.DataStore().entity("A", initial);
+ var model = entity();
+ model.a.push(1);
+ assertEquals(0, entity().a.length);
+};
diff --git a/test/ParserTest.js b/test/ParserTest.js
new file mode 100644
index 00000000..7fe8e6a4
--- /dev/null
+++ b/test/ParserTest.js
@@ -0,0 +1,462 @@
+LexerTest = TestCase('LexerTest');
+
+LexerTest.prototype.testTokenizeAString = function(){
+ var lexer = new nglr.Lexer("a.bc[22]+1.3|f:'a\\\'c':\"d\\\"e\"");
+ var tokens = lexer.parse();
+ var i = 0;
+ assertEquals(tokens[i].index, 0);
+ assertEquals(tokens[i].text, 'a.bc');
+
+ i++;
+ assertEquals(tokens[i].index, 4);
+ assertEquals(tokens[i].text, '[');
+
+ i++;
+ assertEquals(tokens[i].index, 5);
+ assertEquals(tokens[i].text, 22);
+
+ i++;
+ assertEquals(tokens[i].index, 7);
+ assertEquals(tokens[i].text, ']');
+
+ i++;
+ assertEquals(tokens[i].index, 8);
+ assertEquals(tokens[i].text, '+');
+
+ i++;
+ assertEquals(tokens[i].index, 9);
+ assertEquals(tokens[i].text, 1.3);
+
+ i++;
+ assertEquals(tokens[i].index, 12);
+ assertEquals(tokens[i].text, '|');
+
+ i++;
+ assertEquals(tokens[i].index, 13);
+ assertEquals(tokens[i].text, 'f');
+
+ i++;
+ assertEquals(tokens[i].index, 14);
+ assertEquals(tokens[i].text, ':');
+
+ i++;
+ assertEquals(tokens[i].index, 15);
+ assertEquals(tokens[i].text, "a'c");
+
+ i++;
+ assertEquals(tokens[i].index, 21);
+ assertEquals(tokens[i].text, ':');
+
+ i++;
+ assertEquals(tokens[i].index, 22);
+ assertEquals(tokens[i].text, 'd"e');
+};
+
+
+LexerTest.prototype.testTokenizeRegExp = function(){
+ var lexer = new nglr.Lexer("/r 1/");
+ var tokens = lexer.parse();
+ var i = 0;
+ assertEquals(tokens[i].index, 0);
+ assertEquals(tokens[i].text, 'r 1');
+ assertEquals("r 1".match(tokens[i].fn())[0], 'r 1');
+};
+
+LexerTest.prototype.testQuotedString = function(){
+ var str = "['\\'', \"\\\"\"]";
+ var lexer = new nglr.Lexer(str);
+ var tokens = lexer.parse();
+
+ assertEquals(1, tokens[1].index);
+ assertEquals("'", tokens[1].text);
+
+ assertEquals(7, tokens[3].index);
+ assertEquals('"', tokens[3].text);
+
+};
+
+LexerTest.prototype.testQuotedStringEscape = function(){
+ var str = '"\\"\\n\\f\\r\\t\\v\\u00A0"';
+ var lexer = new nglr.Lexer(str);
+ var tokens = lexer.parse();
+
+ assertEquals('"\n\f\r\t\v\u00A0', tokens[0].text);
+};
+
+LexerTest.prototype.testTokenizeUnicode = function(){
+ var lexer = new nglr.Lexer('"\\u00A0"');
+ var tokens = lexer.parse();
+ assertEquals(1, tokens.length);
+ assertEquals('\u00a0', tokens[0].text);
+};
+
+LexerTest.prototype.testTokenizeRegExpWithOptions = function(){
+ var lexer = new nglr.Lexer("/r/g");
+ var tokens = lexer.parse();
+ var i = 0;
+ assertEquals(tokens[i].index, 0);
+ assertEquals(tokens[i].text, 'r');
+ assertEquals(tokens[i].flags, 'g');
+ assertEquals("rr".match(tokens[i].fn()).length, 2);
+};
+
+LexerTest.prototype.testTokenizeRegExpWithEscape = function(){
+ var lexer = new nglr.Lexer("/\\/\\d/");
+ var tokens = lexer.parse();
+ var i = 0;
+ assertEquals(tokens[i].index, 0);
+ assertEquals(tokens[i].text, '\\/\\d');
+ assertEquals("/1".match(tokens[i].fn())[0], '/1');
+};
+
+LexerTest.prototype.testIgnoreWhitespace = function(){
+ var lexer = new nglr.Lexer("a \t \n \r b");
+ var tokens = lexer.parse();
+ assertEquals(tokens[0].text, 'a');
+ assertEquals(tokens[1].text, 'b');
+};
+
+LexerTest.prototype.testRelation = function(){
+ var lexer = new nglr.Lexer("! == != < > <= >=");
+ var tokens = lexer.parse();
+ assertEquals(tokens[0].text, '!');
+ assertEquals(tokens[1].text, '==');
+ assertEquals(tokens[2].text, '!=');
+ assertEquals(tokens[3].text, '<');
+ assertEquals(tokens[4].text, '>');
+ assertEquals(tokens[5].text, '<=');
+ assertEquals(tokens[6].text, '>=');
+};
+
+LexerTest.prototype.testStatements = function(){
+ var lexer = new nglr.Lexer("a;b;");
+ var tokens = lexer.parse();
+ assertEquals(tokens[0].text, 'a');
+ assertEquals(tokens[1].text, ';');
+ assertEquals(tokens[2].text, 'b');
+ assertEquals(tokens[3].text, ';');
+};
+
+ParserTest = TestCase('ParserTest');
+
+ParserTest.prototype.testExpressions = function(){
+ var scope = new nglr.Scope();
+ assertEquals(scope.eval("-1"), -1);
+ assertEquals(scope.eval("1 + 2.5"), 3.5);
+ assertEquals(scope.eval("1 + -2.5"), -1.5);
+ assertEquals(scope.eval("1+2*3/4"), 1+2*3/4);
+ assertEquals(scope.eval("0--1+1.5"), 0- -1 + 1.5);
+ assertEquals(scope.eval("-0--1++2*-3/-4"), -0- -1+ +2*-3/-4);
+ assertEquals(scope.eval("1/2*3"), 1/2*3);
+};
+
+ParserTest.prototype.testComparison = function(){
+ var scope = new nglr.Scope();
+ assertEquals(scope.eval("false"), false);
+ assertEquals(scope.eval("!true"), false);
+ assertEquals(scope.eval("1==1"), true);
+ assertEquals(scope.eval("1!=2"), true);
+ assertEquals(scope.eval("1<2"), true);
+ assertEquals(scope.eval("1<=1"), true);
+ assertEquals(scope.eval("1>2"), 1>2);
+ assertEquals(scope.eval("2>=1"), 2>=1);
+};
+
+ParserTest.prototype.testLogical = function(){
+ var scope = new nglr.Scope();
+ assertEquals(scope.eval("0&&2"), 0&&2);
+ assertEquals(scope.eval("0||2"), 0||2);
+ assertEquals(scope.eval("0||1&&2"), 0||1&&2);
+};
+
+ParserTest.prototype.testString = function(){
+ var scope = new nglr.Scope();
+ assertEquals(scope.eval("'a' + 'b c'"), "ab c");
+};
+
+ParserTest.prototype.testFilters = function(){
+ angular.filter.substring = function(input, start, end) {
+ return input.substring(start, end);
+ };
+
+ angular.filter.upper = {_case:function(input) {
+ return input.toUpperCase();
+ }};
+ var scope = new nglr.Scope();
+ try {
+ scope.eval("1|nonExistant");
+ fail();
+ } catch (e) {
+ assertEquals(e, "Function 'nonExistant' at column '3' in '1|nonExistant' is not defined.");
+ }
+ scope.set('offset', 3);
+ assertEquals(scope.eval("'abcd'|upper._case"), "ABCD");
+ assertEquals(scope.eval("'abcd'|substring:1:offset"), "bc");
+ assertEquals(scope.eval("'abcd'|substring:1:3|upper._case"), "BC");
+};
+
+ParserTest.prototype.testScopeAccess = function(){
+ var scope = new nglr.Scope();
+ scope.set('a', 123);
+ scope.set('b.c', 456);
+ assertEquals(scope.eval("a", scope), 123);
+ assertEquals(scope.eval("b.c", scope), 456);
+ assertEquals(scope.eval("x.y.z", scope), undefined);
+};
+
+ParserTest.prototype.testGrouping = function(){
+ var scope = new nglr.Scope();
+ assertEquals(scope.eval("(1+2)*3"), (1+2)*3);
+};
+
+ParserTest.prototype.testAssignments = function(){
+ var scope = new nglr.Scope();
+ assertEquals(scope.eval("a=12"), 12);
+ assertEquals(scope.get("a"), 12);
+
+ scope = new nglr.Scope();
+ assertEquals(scope.eval("x.y.z=123;"), 123);
+ assertEquals(scope.get("x.y.z"), 123);
+
+ assertEquals(234, scope.eval("a=123; b=234"));
+ assertEquals(123, scope.get("a"));
+ assertEquals(234, scope.get("b"));
+};
+
+ParserTest.prototype.testFunctionCallsNoArgs = function(){
+ var scope = new nglr.Scope();
+ scope.set('const', function(a,b){return 123;});
+ assertEquals(scope.eval("const()"), 123);
+};
+
+ParserTest.prototype.testFunctionCalls = function(){
+ var scope = new nglr.Scope();
+ scope.set('add', function(a,b){
+ return a+b;
+ });
+ assertEquals(3, scope.eval("add(1,2)"));
+};
+
+ParserTest.prototype.testCalculationBug = function(){
+ var scope = new nglr.Scope();
+ scope.set('taxRate', 8);
+ scope.set('subTotal', 100);
+ assertEquals(scope.eval("taxRate / 100 * subTotal"), 8);
+ assertEquals(scope.eval("subTotal * taxRate / 100"), 8);
+};
+
+ParserTest.prototype.testArray = function(){
+ var scope = new nglr.Scope();
+ assertEquals(scope.eval("[]").length, 0);
+ assertEquals(scope.eval("[1, 2]").length, 2);
+ assertEquals(scope.eval("[1, 2]")[0], 1);
+ assertEquals(scope.eval("[1, 2]")[1], 2);
+};
+
+ParserTest.prototype.testArrayAccess = function(){
+ var scope = new nglr.Scope();
+ assertEquals(scope.eval("[1][0]"), 1);
+ assertEquals(scope.eval("[[1]][0][0]"), 1);
+ assertEquals(scope.eval("[].length"), 0);
+ assertEquals(scope.eval("[1, 2].length"), 2);
+};
+
+ParserTest.prototype.testObject = function(){
+ var scope = new nglr.Scope();
+ assertEquals(nglr.toJson(scope.eval("{}")), "{}");
+ assertEquals(nglr.toJson(scope.eval("{a:'b'}")), '{"a":"b"}');
+ assertEquals(nglr.toJson(scope.eval("{'a':'b'}")), '{"a":"b"}');
+ assertEquals(nglr.toJson(scope.eval("{\"a\":'b'}")), '{"a":"b"}');
+};
+
+ParserTest.prototype.testObjectAccess = function(){
+ var scope = new nglr.Scope();
+ assertEquals("WC", scope.eval("{false:'WC', true:'CC'}[false]"));
+};
+
+ParserTest.prototype.testJSON = function(){
+ var scope = new nglr.Scope();
+ assertEquals(nglr.toJson(scope.eval("[{}]")), "[{}]");
+ assertEquals(nglr.toJson(scope.eval("[{a:[]}, {b:1}]")), '[{"a":[]},{"b":1}]');
+};
+
+ParserTest.prototype.testMultippleStatements = function(){
+ var scope = new nglr.Scope();
+ assertEquals(scope.eval("a=1;b=3;a+b"), 4);
+ assertEquals(scope.eval(";;1;;"), 1);
+};
+
+ParserTest.prototype.testParseThrow = function(){
+ expectAsserts(1);
+ var scope = new nglr.Scope();
+ scope.set('e', 'abc');
+ try {
+ scope.eval("throw e");
+ } catch(e) {
+ assertEquals(e, 'abc');
+ }
+};
+
+ParserTest.prototype.testMethodsGetDispatchedWithCorrectThis = function(){
+ var scope = new nglr.Scope();
+ var C = function (){
+ this.a=123;
+ };
+ C.prototype.getA = function(){
+ return this.a;
+ };
+
+ scope.set("obj", new C());
+ assertEquals(123, scope.eval("obj.getA()"));
+};
+ParserTest.prototype.testMethodsArgumentsGetCorrectThis = function(){
+ var scope = new nglr.Scope();
+ var C = function (){
+ this.a=123;
+ };
+ C.prototype.sum = function(value){
+ return this.a + value;
+ };
+ C.prototype.getA = function(){
+ return this.a;
+ };
+
+ scope.set("obj", new C());
+ assertEquals(246, scope.eval("obj.sum(obj.getA())"));
+};
+
+ParserTest.prototype.testObjectPointsToScopeValue = function(){
+ var scope = new nglr.Scope();
+ scope.set('a', "abc");
+ assertEquals("abc", scope.eval("{a:a}").a);
+};
+
+ParserTest.prototype.testFieldAccess = function(){
+ var scope = new nglr.Scope();
+ var fn = function(){
+ return {name:'misko'};
+ };
+ scope.set('a', fn);
+ assertEquals("misko", scope.eval("a().name"));
+};
+
+ParserTest.prototype.testArrayIndexBug = function () {
+ var scope = new nglr.Scope();
+ scope.set('items', [{}, {name:'misko'}]);
+
+ assertEquals("misko", scope.eval('items[1].name'));
+};
+
+ParserTest.prototype.testArrayAssignment = function () {
+ var scope = new nglr.Scope();
+ scope.set('items', []);
+
+ assertEquals("abc", scope.eval('items[1] = "abc"'));
+ assertEquals("abc", scope.eval('items[1]'));
+// Dont know how to make this work....
+// assertEquals("moby", scope.eval('books[1] = "moby"'));
+// assertEquals("moby", scope.eval('books[1]'));
+};
+
+ParserTest.prototype.testFiltersCanBeGrouped = function () {
+ var scope = new nglr.Scope({name:'MISKO'});
+ assertEquals('misko', scope.eval('n = (name|lowercase)'));
+ assertEquals('misko', scope.eval('n'));
+};
+
+ParserTest.prototype.testFiltersCanBeGrouped = function () {
+ var scope = new nglr.Scope({name:'MISKO'});
+ assertEquals('misko', scope.eval('n = (name|lowercase)'));
+ assertEquals('misko', scope.eval('n'));
+};
+
+ParserTest.prototype.testRemainder = function () {
+ var scope = new nglr.Scope();
+ assertEquals(1, scope.eval('1%2'));
+};
+
+ParserTest.prototype.testSumOfUndefinedIsNotUndefined = function () {
+ var scope = new nglr.Scope();
+ assertEquals(1, scope.eval('1+undefined'));
+ assertEquals(1, scope.eval('undefined+1'));
+};
+
+ParserTest.prototype.testMissingThrowsError = function() {
+ var scope = new nglr.Scope();
+ try {
+ scope.eval('[].count(');
+ fail();
+ } catch (e) {
+ assertEquals('Unexpected end of expression: [].count(', e);
+ }
+};
+
+ParserTest.prototype.testItShouldParseOnChangeIntoHashSet = function () {
+ var scope = new nglr.Scope({count:0});
+ scope.watch("$anchor.a:count=count+1;$anchor.a:count=count+20;b:count=count+300");
+
+ scope.watchListeners["$anchor.a"].listeners[0]();
+ assertEquals(1, scope.get("count"));
+ scope.watchListeners["$anchor.a"].listeners[1]();
+ assertEquals(21, scope.get("count"));
+ scope.watchListeners["b"].listeners[0]({scope:scope});
+ assertEquals(321, scope.get("count"));
+};
+ParserTest.prototype.testItShouldParseOnChangeBlockIntoHashSet = function () {
+ var scope = new nglr.Scope({count:0});
+ var listeners = {a:[], b:[]};
+ scope.watch("a:{count=count+1;count=count+20;};b:count=count+300",
+ function(n, fn){listeners[n].push(fn);});
+
+ assertEquals(1, scope.watchListeners.a.listeners.length);
+ assertEquals(1, scope.watchListeners.b.listeners.length);
+ scope.watchListeners["a"].listeners[0]();
+ assertEquals(21, scope.get("count"));
+ scope.watchListeners["b"].listeners[0]();
+ assertEquals(321, scope.get("count"));
+};
+
+ParserTest.prototype.testItShouldParseEmptyOnChangeAsNoop = function () {
+ var scope = new nglr.Scope();
+ scope.watch("", function(){fail();});
+};
+
+ParserTest.prototype.testItShouldCreateClosureFunctionWithNoArguments = function () {
+ var scope = new nglr.Scope();
+ var fn = scope.eval("{:value}");
+ scope.set("value", 1);
+ assertEquals(1, fn());
+ scope.set("value", 2);
+ assertEquals(2, fn());
+ fn = scope.eval("{():value}");
+ assertEquals(2, fn());
+};
+
+ParserTest.prototype.testItShouldCreateClosureFunctionWithArguments = function () {
+ var scope = new nglr.Scope();
+ var fn = scope.eval("{(a):value+a}");
+ scope.set("value", 1);
+ assertEquals(11, fn(10));
+ scope.set("value", 2);
+ assertEquals(12, fn(10));
+ fn = scope.eval("{(a,b):value+a+b}");
+ assertEquals(112, fn(10, 100));
+};
+
+ParserTest.prototype.testItShouldHaveDefaultArugument = function(){
+ var scope = new nglr.Scope();
+ var fn = scope.eval("{:$*2}");
+ assertEquals(4, fn(2));
+};
+
+ParserTest.prototype.testReturnFunctionsAreNotBound = function(){
+ var scope = new nglr.Scope();
+ scope.set("$datastore", new nglr.DataStore());
+ scope.entity("Group");
+ var Group = scope.get("Group");
+ assertEquals("eval Group", "function", typeof scope.eval("Group"));
+ assertEquals("direct Group", "function", typeof Group);
+ assertEquals("eval Group.all", "function", typeof scope.eval("Group.query"));
+ assertEquals("direct Group.all", "function", typeof Group.query);
+};
+
diff --git a/test/ScopeTest.js b/test/ScopeTest.js
new file mode 100644
index 00000000..c66a2329
--- /dev/null
+++ b/test/ScopeTest.js
@@ -0,0 +1,144 @@
+ScopeTest = TestCase('ScopeTest');
+
+ScopeTest.prototype.testGetScopeRetrieval = function(){
+ var scope = {};
+ var form = jQuery("
");
+ form.data('scope', scope);
+ var c = form.find('c');
+ assertTrue(scope === c.scope());
+};
+
+ScopeTest.prototype.testGetScopeRetrievalIntermediateNode = function(){
+ var scope = {};
+ var form = jQuery("
");
+ form.find("b").data('scope', scope);
+ var b = form.find('b');
+ assertTrue(scope === b.scope());
+};
+
+ScopeTest.prototype.testNoScopeDoesNotCauseInfiniteRecursion = function(){
+ var form = jQuery("
");
+ var c = form.find('c');
+ assertTrue(!c.scope());
+};
+
+ScopeTest.prototype.testScopeEval = function(){
+ var scope = new nglr.Scope({b:345});
+ assertEquals(scope.eval('b = 123'), 123);
+ assertEquals(scope.get('b'), 123);
+};
+
+ScopeTest.prototype.testScopeFromPrototype = function(){
+ var scope = new nglr.Scope({b:123});
+ scope.eval('a = b');
+ scope.eval('b = 456');
+ assertEquals(scope.get('a'), 123);
+ assertEquals(scope.get('b'), 456);
+};
+
+ScopeTest.prototype.testSetScopeGet = function(){
+ var scope = new nglr.Scope();
+ scope.set('a', 987);
+ assertEquals(scope.get('a'), 987);
+ assertEquals(scope.eval('a'), 987);
+};
+
+ScopeTest.prototype.testGetChain = function(){
+ var scope = new nglr.Scope({a:{b:987}});
+ assertEquals(scope.get('a.b'), 987);
+ assertEquals(scope.eval('a.b'), 987);
+};
+
+ScopeTest.prototype.testGetUndefinedChain = function(){
+ var scope = new nglr.Scope();
+ assertEquals(typeof scope.get('a.b'), 'undefined');
+};
+
+ScopeTest.prototype.testSetChain = function(){
+ var scope = new nglr.Scope({a:{}});
+ scope.set('a.b', 987);
+ assertEquals(scope.get('a.b'), 987);
+ assertEquals(scope.eval('a.b'), 987);
+};
+
+ScopeTest.prototype.testSetGetOnChain = function(){
+ var scope = new nglr.Scope();
+ scope.set('a.b', 987);
+ assertEquals(scope.get('a.b'), 987);
+ assertEquals(scope.eval('a.b'), 987);
+};
+
+ScopeTest.prototype.testGlobalFunctionAccess =function(){
+ window['scopeAddTest'] = function (a, b) {return a+b;};
+ var scope = new nglr.Scope({window:window});
+ assertEquals(scope.eval('window.scopeAddTest(1,2)'), 3);
+
+ scope.set('add', function (a, b) {return a+b;});
+ assertEquals(scope.eval('add(1,2)'), 3);
+
+ scope.set('math.add', function (a, b) {return a+b;});
+ assertEquals(scope.eval('math.add(1,2)'), 3);
+};
+
+ScopeTest.prototype.testValidationEval = function(){
+ expectAsserts(4);
+ var scope = new nglr.Scope();
+ angular.validator.testValidator = function(value, expect){
+ assertEquals(scope, this.scope);
+ return value == expect ? null : "Error text";
+ };
+
+ assertEquals("Error text", scope.validate("testValidator:'abc'", 'x'));
+ assertEquals(null, scope.validate("testValidator:'abc'", 'abc'));
+
+ delete angular.validator['testValidator'];
+};
+
+ScopeTest.prototype.testCallingNonExistantMethodShouldProduceFriendlyException = function() {
+ expectAsserts(1);
+ var scope = new nglr.Scope({obj:{}});
+ try {
+ scope.eval("obj.iDontExist()");
+ fail();
+ } catch (e) {
+ assertEquals("Expression 'obj.iDontExist' is not a function.", e);
+ }
+};
+
+ScopeTest.prototype.testAccessingWithInvalidPathShouldThrowError = function() {
+ var scope = new nglr.Scope();
+ try {
+ scope.get('a.{{b}}');
+ fail();
+ } catch (e) {
+ assertEquals("Expression 'a.{{b}}' is not a valid expression for accesing variables.", e);
+ }
+};
+
+ScopeTest.prototype.testItShouldHave$parent = function() {
+ var parent = new nglr.Scope({}, "ROOT");
+ var child = new nglr.Scope(parent.state);
+ assertSame("parent", child.state.$parent, parent.state);
+ assertSame("root", child.state.$root, parent.state);
+};
+
+ScopeTest.prototype.testItShouldHave$root = function() {
+ var scope = new nglr.Scope({}, "ROOT");
+ assertSame(scope.state.$root, scope.state);
+};
+
+ScopeTest.prototype.testItShouldBuildPathOnUndefined = function(){
+ var scope = new nglr.Scope({}, "ROOT");
+ scope.setEval("a.$b.c", 1);
+ assertJsonEquals({$b:{c:1}}, scope.get("a"));
+};
+
+ScopeTest.prototype.testItShouldMapUnderscoreFunctions = function(){
+ var scope = new nglr.Scope({}, "ROOT");
+ scope.set("a", [1,2,3]);
+ assertEquals('function', typeof scope.get("a.$size"));
+ scope.eval("a.$includeIf(4,true)");
+ assertEquals(4, scope.get("a.$size")());
+ assertEquals(4, scope.eval("a.$size()"));
+ assertEquals('undefined', typeof scope.get("a.dontExist"));
+};
diff --git a/test/ServerTest.js b/test/ServerTest.js
new file mode 100644
index 00000000..d1f662f9
--- /dev/null
+++ b/test/ServerTest.js
@@ -0,0 +1,42 @@
+ServerTest = TestCase("ServerTest");
+ServerTest.prototype.testBreakLargeRequestIntoPackets = function() {
+ var log = "";
+ var server = new nglr.Server("http://server", function(url){
+ log += "|" + url;
+ });
+ server.maxSize = 30;
+ server.uuid = "uuid";
+ server.request("POST", "/data/database", {}, function(code, r){
+ assertEquals(200, code);
+ assertEquals("response", r);
+ });
+ nglr.uuid0("response");
+ assertEquals(
+ "|http://server/$/uuid0/2/1?h=eyJtIjoiUE9TVCIsInAiOnt9LCJ1Ij" +
+ "|http://server/$/uuid0/2/2?h=oiL2RhdGEvZGF0YWJhc2UifQ==",
+ log);
+};
+
+ServerTest.prototype.testItShouldEncodeUsingUrlRules = function() {
+ var server = new nglr.Server("http://server");
+ assertEquals("fn5-fn5-", server.base64url("~~~~~~"));
+ assertEquals("fn5_fn5_", server.base64url("~~\u007f~~\u007f"));
+};
+
+FrameServerTest = TestCase("FrameServerTest");
+
+FrameServerTest.prototype = {
+ testRead:function(){
+ var window = {name:'$DATASET:"MyData"'};
+ var server = new nglr.FrameServer(window);
+ server.read();
+ assertEquals("MyData", server.data);
+ },
+ testWrite:function(){
+ var window = {};
+ var server = new nglr.FrameServer(window);
+ server.data = "TestData"
+ server.write();
+ assertEquals('$DATASET:"TestData"', window.name);
+ }
+};
diff --git a/test/UsersTest.js b/test/UsersTest.js
new file mode 100644
index 00000000..c808885c
--- /dev/null
+++ b/test/UsersTest.js
@@ -0,0 +1,26 @@
+// Copyright (C) 2008,2009 BRAT Tech LLC
+
+UsersTest = TestCase("UsersTest");
+
+UsersTest.prototype = {
+ setUp:function(){},
+
+ tearDown:function(){},
+
+ testItShouldFetchCurrentUser:function(){
+ expectAsserts(5);
+ var user;
+ var users = new nglr.Users({request:function(method, url, request, callback){
+ assertEquals("GET", method);
+ assertEquals("/account.json", url);
+ assertEquals("{}", nglr.toJson(request));
+ callback(200, {$status_code:200, user:{name:'misko'}});
+ }});
+ users.fetchCurrentUser(function(u){
+ user = u;
+ assertEquals("misko", u.name);
+ assertEquals("misko", users.current.name);
+ });
+ }
+
+};
diff --git a/test/ValidatorsTest.js b/test/ValidatorsTest.js
new file mode 100644
index 00000000..22c7f390
--- /dev/null
+++ b/test/ValidatorsTest.js
@@ -0,0 +1,65 @@
+ValidatorTest = TestCase('ValidatorTest');
+
+ValidatorTest.prototype.testRegexp = function() {
+ assertEquals(angular.validator.regexp("abc", /x/, "E1"), "E1");
+ assertEquals(angular.validator.regexp("abc", '/x/'),
+ "Value does not match expected format /x/.");
+ assertEquals(angular.validator.regexp("ab", '^ab$'), null);
+ assertEquals(angular.validator.regexp("ab", '^axb$', "E3"), "E3");
+};
+
+ValidatorTest.prototype.testNumber = function() {
+ assertEquals(angular.validator.number("ab"), "Value is not a number.");
+ assertEquals(angular.validator.number("-0.1",0), "Value can not be less than 0.");
+ assertEquals(angular.validator.number("10.1",0,10), "Value can not be greater than 10.");
+ assertEquals(angular.validator.number("1.2"), null);
+ assertEquals(angular.validator.number(" 1 ", 1, 1), null);
+};
+
+ValidatorTest.prototype.testInteger = function() {
+ assertEquals(angular.validator.integer("ab"), "Value is not a number.");
+ assertEquals(angular.validator.integer("1.1"), "Value is not a whole number.");
+ assertEquals(angular.validator.integer("-1",0), "Value can not be less than 0.");
+ assertEquals(angular.validator.integer("11",0,10), "Value can not be greater than 10.");
+ assertEquals(angular.validator.integer("1"), null);
+ assertEquals(angular.validator.integer(" 1 ", 1, 1), null);
+};
+
+ValidatorTest.prototype.testDate = function() {
+ var error = "Value is not a date. (Expecting format: 12/31/2009).";
+ assertEquals(angular.validator.date("ab"), error);
+ assertEquals(angular.validator.date("12/31/2009"), null);
+};
+
+ValidatorTest.prototype.testPhone = function() {
+ var error = "Phone number needs to be in 1(987)654-3210 format in North America or +999 (123) 45678 906 internationaly.";
+ assertEquals(angular.validator.phone("ab"), error);
+ assertEquals(null, angular.validator.phone("1(408)757-3023"));
+ assertEquals(null, angular.validator.phone("+421 (0905) 933 297"));
+ assertEquals(null, angular.validator.phone("+421 0905 933 297"));
+};
+
+ValidatorTest.prototype.testSSN = function() {
+ var error = "SSN needs to be in 999-99-9999 format.";
+ assertEquals(angular.validator.ssn("ab"), error);
+ assertEquals(angular.validator.ssn("123-45-6789"), null);
+};
+
+ValidatorTest.prototype.testURL = function() {
+ var error = "URL needs to be in http://server[:port]/path format.";
+ assertEquals(angular.validator.url("ab"), error);
+ assertEquals(angular.validator.url("http://server:123/path"), null);
+};
+
+ValidatorTest.prototype.testEmail = function() {
+ var error = "Email needs to be in username@host.com format.";
+ assertEquals(error, angular.validator.email("ab"));
+ assertEquals(null, angular.validator.email("misko@hevery.com"));
+};
+
+ValidatorTest.prototype.testJson = function() {
+ assertNotNull(angular.validator.json("'"));
+ assertNotNull(angular.validator.json("''X"));
+ assertNull(angular.validator.json("{}"));
+};
+
diff --git a/test/WidgetsTest.js b/test/WidgetsTest.js
new file mode 100644
index 00000000..a245abda
--- /dev/null
+++ b/test/WidgetsTest.js
@@ -0,0 +1,269 @@
+WidgetTest = TestCase('WidgetTest');
+
+WidgetTest.prototype.testRequired = function () {
+ var view = $('
');
+ var scope = new nglr.Scope({$invalidWidgets:[]});
+ var cntl = new nglr.TextController(view[0], 'a');
+ cntl.updateView(scope);
+ assertTrue(view.hasClass('ng-validation-error'));
+ assertEquals("Required Value", view.attr('ng-error'));
+ scope.set('a', 'A');
+ cntl.updateView(scope);
+ assertFalse(view.hasClass('ng-validation-error'));
+ assertEquals("undefined", typeof view.attr('ng-error'));
+};
+
+WidgetTest.prototype.testValidator = function () {
+ var view = $('
');
+ var scope = new nglr.Scope({$invalidWidgets:[]});
+ var cntl = new nglr.TextController(view[0], 'a');
+ angular.validator.testValidator = function(value, expect){
+ return value == expect ? null : "Error text";
+ };
+
+ scope.set('a', '');
+ cntl.updateView(scope);
+ assertEquals(view.hasClass('ng-validation-error'), false);
+ assertEquals(null, view.attr('ng-error'));
+
+ scope.set('a', 'X');
+ cntl.updateView(scope);
+ assertEquals(view.hasClass('ng-validation-error'), true);
+ assertEquals(view.attr('ng-error'), "Error text");
+ assertEquals("Error text", view.attr('ng-error'));
+
+ scope.set('a', 'ABC');
+ cntl.updateView(scope);
+ assertEquals(view.hasClass('ng-validation-error'), false);
+ assertEquals(view.attr('ng-error'), null);
+ assertEquals(null, view.attr('ng-error'));
+
+ delete angular.validator['testValidator'];
+};
+
+WidgetTest.prototype.testRequiredValidator = function () {
+ var view = $('
');
+ var scope = new nglr.Scope({$invalidWidgets:[]});
+ var cntl = new nglr.TextController(view[0], 'a');
+ angular.validator.testValidator = function(value, expect){
+ return value == expect ? null : "Error text";
+ };
+
+ scope.set('a', '');
+ cntl.updateView(scope);
+ assertEquals(view.hasClass('ng-validation-error'), true);
+ assertEquals("Required Value", view.attr('ng-error'));
+
+ scope.set('a', 'X');
+ cntl.updateView(scope);
+ assertEquals(view.hasClass('ng-validation-error'), true);
+ assertEquals("Error text", view.attr('ng-error'));
+
+ scope.set('a', 'ABC');
+ cntl.updateView(scope);
+ assertEquals(view.hasClass('ng-validation-error'), false);
+ assertEquals(null, view.attr('ng-error'));
+
+ delete angular.validator['testValidator'];
+};
+
+TextController = TestCase("TextController");
+
+TextController.prototype.testDatePicker = function() {
+ var input = $('
');
+ input.data('scope', new nglr.Scope());
+ var body = $(document.body);
+ body.append(input);
+ var binder = new nglr.Binder(input[0], new nglr.WidgetFactory());
+ assertTrue('before', input.data('datepicker') === undefined);
+ binder.compile();
+ assertTrue('after', input.data('datepicker') !== null);
+ assertTrue(body.html(), input.hasClass('hasDatepicker'));
+};
+
+RepeaterUpdater = TestCase("RepeaterUpdater");
+
+RepeaterUpdater.prototype.testRemoveThenAdd = function() {
+ var view = $("
");
+ var template = function () {
+ return $("
");
+ };
+ var repeater = new nglr.RepeaterUpdater(view.find("span"), "a in b", template, "");
+ var scope = new nglr.Scope();
+ scope.set('b', [1,2]);
+
+ repeater.updateView(scope);
+
+ scope.set('b', []);
+ repeater.updateView(scope);
+
+ scope.set('b', [1]);
+ repeater.updateView(scope);
+ assertEquals(1, view.find("li").size());
+};
+
+RepeaterUpdater.prototype.testShouldBindWidgetOnRepeaterClone = function(){
+ //fail();
+};
+
+RepeaterUpdater.prototype.testShouldThrowInformativeSyntaxError= function(){
+ expectAsserts(1);
+ try {
+ var repeater = new nglr.RepeaterUpdater(null, "a=b");
+ } catch (e) {
+ assertEquals("Expected ng-repeat in form of 'item in collection' but got 'a=b'.", e);
+ }
+};
+
+SelectControllerTest = TestCase("SelectControllerTest");
+
+SelectControllerTest.prototype.testShouldUpdateModelNullOnNothingSelected = function(){
+ var scope = new nglr.Scope();
+ var view = {selectedIndex:-1, options:[]};
+ var cntl = new nglr.SelectController(view, 'abc');
+ cntl.updateModel(scope);
+ assertNull(scope.get('abc'));
+};
+
+SelectControllerTest.prototype.testShouldUpdateModelWhenNothingSelected = function(){
+ var scope = new nglr.Scope();
+ var view = {value:'123'};
+ var cntl = new nglr.SelectController(view, 'abc');
+ cntl.updateView(scope);
+ assertEquals("123", scope.get('abc'));
+};
+
+BindUpdaterTest = TestCase("BindUpdaterTest");
+
+BindUpdaterTest.prototype.testShouldDisplayNothingForUndefined = function () {
+ var view = $('
');
+ var controller = new nglr.BindUpdater(view[0], "{{a}}");
+ var scope = new nglr.Scope();
+
+ scope.set('a', undefined);
+ controller.updateView(scope);
+ assertEquals("", view.text());
+
+ scope.set('a', null);
+ controller.updateView(scope);
+ assertEquals("", view.text());
+};
+
+BindUpdaterTest.prototype.testShouldDisplayJsonForNonStrings = function () {
+ var view = $('
');
+ var controller = new nglr.BindUpdater(view[0], "{{obj}}");
+
+ controller.updateView(new nglr.Scope({obj:[]}));
+ assertEquals("[]", view.text());
+
+ controller.updateView(new nglr.Scope({obj:{text:'abc'}}));
+ assertEquals('abc', nglr.fromJson(view.text()).text);
+};
+
+
+BindUpdaterTest.prototype.testShouldInsertHtmlNode = function () {
+ var view = $('
');
+ var controller = new nglr.BindUpdater(view[0], "
&{{obj}} ");
+ var scope = new nglr.Scope();
+
+ scope.set("obj", $('
myDiv
')[0]);
+ controller.updateView(scope);
+ assertEquals("
&myDiv ", view.text());
+};
+
+
+BindUpdaterTest.prototype.testShouldDisplayTextMethod = function () {
+ var view = $('
');
+ var controller = new nglr.BindUpdater(view[0], "{{obj}}");
+ var scope = new nglr.Scope();
+
+ scope.set("obj", new angular.filter.Meta({text:function(){return "abc";}}));
+ controller.updateView(scope);
+ assertEquals("abc", view.text());
+
+ scope.set("obj", new angular.filter.Meta({text:"123"}));
+ controller.updateView(scope);
+ assertEquals("123", view.text());
+
+ scope.set("obj", {text:"123"});
+ controller.updateView(scope);
+ assertEquals("123", nglr.fromJson(view.text()).text);
+};
+
+BindUpdaterTest.prototype.testShouldDisplayHtmlMethod = function () {
+ var view = $('
');
+ var controller = new nglr.BindUpdater(view[0], "{{obj}}");
+ var scope = new nglr.Scope();
+
+ scope.set("obj", new angular.filter.Meta({html:function(){return "a
b
c";}}));
+ controller.updateView(scope);
+ assertEquals("abc", view.text());
+
+ scope.set("obj", new angular.filter.Meta({html:"1
2
3"}));
+ controller.updateView(scope);
+ assertEquals("123", view.text());
+
+ scope.set("obj", {html:"123"});
+ controller.updateView(scope);
+ assertEquals("123", nglr.fromJson(view.text()).html);
+};
+
+BindUpdaterTest.prototype.testUdateBoolean = function() {
+ var view = $('
');
+ var controller = new nglr.BindUpdater(view[0], "{{true}}, {{false}}");
+ controller.updateView(new nglr.Scope());
+ assertEquals('true, false', view.text());
+};
+
+BindAttrUpdaterTest = TestCase("BindAttrUpdaterTest");
+
+BindAttrUpdaterTest.prototype.testShouldLoadBlankImageWhenBindingIsUndefined = function () {
+ var view = $('
');
+ var controller = new nglr.BindAttrUpdater(view[0], {src: '{{imageUrl}}'});
+
+ var scope = new nglr.Scope();
+ scope.set('imageUrl', undefined);
+ scope.set('config.server', 'http://server');
+
+ controller.updateView(scope);
+ assertEquals("http://server/images/blank.gif", view.attr('src'));
+};
+
+RepeaterUpdaterTest = TestCase("RepeaterUpdaterTest");
+RepeaterUpdaterTest.prototype.testShouldNotDieWhenRepeatExpressionIsNull = function() {
+ var rep = new nglr.RepeaterUpdater(null, "$item in items", null, null);
+ var scope = new nglr.Scope();
+ scope.set('items', undefined);
+ rep.updateView(scope);
+};
+
+RepeaterUpdaterTest.prototype.testShouldIterateOverKeys = function() {
+ var rep = new nglr.RepeaterUpdater(null, "($k,_v) in items", null, null);
+ assertEquals("items", rep.iteratorExp);
+ assertEquals("_v", rep.valueExp);
+ assertEquals("$k", rep.keyExp);
+};
+
+EvalUpdaterTest = TestCase("EvalUpdaterTest");
+EvalUpdaterTest.prototype.testEvalThrowsException = function(){
+ var view = $('
');
+ var eval = new nglr.EvalUpdater(view[0], 'undefined()');
+
+ eval.updateView(new nglr.Scope());
+ assertTrue(!!view.attr('ng-error'));
+ assertTrue(view.hasClass('ng-exception'));
+
+ eval.exp = "1";
+ eval.updateView(new nglr.Scope());
+ assertFalse(!!view.attr('ng-error'));
+ assertFalse(view.hasClass('ng-exception'));
+};
+
+RadioControllerTest = TestCase("RadioController");
+RadioControllerTest.prototype.testItShouldTreatTrueStringAsBoolean = function () {
+ var view = $('
');
+ var radio = new nglr.RadioController(view[0], 'select');
+ var scope = new nglr.Scope({select:true});
+ radio.updateView(scope);
+ assertTrue(view[0].checked);
+};
diff --git a/test/XSitePostTest.js b/test/XSitePostTest.js
new file mode 100644
index 00000000..8a3e4d6f
--- /dev/null
+++ b/test/XSitePostTest.js
@@ -0,0 +1,47 @@
+XSitePost = TestCase("XSitePost");
+
+var e = function(text){ return Base64.encode(text); };
+
+XSitePost.prototype.testMessageReceived = function () {
+ expectAsserts(4);
+ var xPost = new nglr.XSitePost();
+ xPost.baseUrl = "http://getangular.test";
+ xPost.post = function(url, request, callback){
+ assertEquals('http://getangular.test/url', url);
+ assertEquals('abc', request.a);
+ assertEquals('xyz', request.x);
+ };
+ xPost.incomingFragment('#id;0;1;'+e('/url')+':a:'+e('abc')+':x:'+e('xyz'));
+ assertEquals('{}', nglr.toJson(xPost.inQueue));
+};
+
+XSitePost.prototype.testMessageReceivedInParts = function () {
+ expectAsserts(5);
+ var xPost = new nglr.XSitePost();
+ xPost.baseUrl = "http://getangular.test";
+ xPost.post = function(url, request, callback){
+ assertEquals('http://getangular.test/url', url);
+ assertEquals('abc', request.a);
+ assertEquals('xyz', request.x);
+ };
+ xPost.incomingFragment('#id;1;2;:x:'+e('xyz'));
+ assertNotSame('{}', nglr.toJson(xPost.inQueue));
+ xPost.incomingFragment('#id;0;2;'+e('/url')+':a:'+e('abc'));
+ assertEquals('{}', nglr.toJson(xPost.inQueue));
+};
+
+XSitePost.prototype.testPostResponsIsEnqueued = function () {
+ var xPost = new nglr.XSitePost();
+ xPost.maxMsgSize = 11;
+ xPost.response("id", "response", "status");
+
+ assertEquals('["id:0:2:cmVzcG9uc2U","id:1:2:="]',
+ nglr.toJson(xPost.outQueue));
+};
+
+XSitePost.prototype.testPush = function () {
+ var window = {};
+ var xPost = new nglr.XSitePost(window);
+ xPost.response("id", "response", "status");
+ assertEquals('id:0:1:cmVzcG9uc2U=', xPost.outQueue[0]);
+};
diff --git a/test/formsTest.js b/test/formsTest.js
new file mode 100644
index 00000000..e834e938
--- /dev/null
+++ b/test/formsTest.js
@@ -0,0 +1,22 @@
+nglrTest = TestCase('nglrTest');
+
+nglrTest.prototype.testShiftBind = function(){
+ expectAsserts(3);
+ nglr.shiftBind('this', function(target, arg) {
+ assertEquals(this, 'this');
+ assertEquals(target, 'target');
+ assertEquals(arg, 'arg');
+ }).apply('target', ['arg']);
+};
+
+nglrTest.prototype.testBind = function(){
+ expectAsserts(2);
+ nglr.bind('this', function(arg) {
+ assertEquals(this, 'this');
+ assertEquals(arg, 'arg');
+ }).apply('XXX', ['arg']);
+};
+
+
+
+
diff --git a/test/test/StepsTest.js b/test/test/StepsTest.js
new file mode 100644
index 00000000..9d64d0a9
--- /dev/null
+++ b/test/test/StepsTest.js
@@ -0,0 +1,7 @@
+StepsTest = TestCase("StepsTest");
+
+StepsTest.prototype.testGivenDataset=function(){
+ var self = {frame:{}, dataset:[]};
+ angular.test.GIVEN.dataset.call(self);
+ assertEquals('$DATASET:{"dataset":[]}', self.frame.name);
+};
diff --git a/test/testabilityPatch.js b/test/testabilityPatch.js
new file mode 100644
index 00000000..5fca3524
--- /dev/null
+++ b/test/testabilityPatch.js
@@ -0,0 +1,129 @@
+TestCase = function(name) { return jstestdriver.testCaseManager.TestCase(name); };
+
+HIDDEN = jQuery.browser.msie ?
+ '' :
+ jQuery.browser.safari ?
+ ' style="display: none; "' :
+ ' style="display: none;"';
+
+nglr.msie = jQuery.browser.msie;
+nglr.alert = function(msg) {jstestdriver.console.log("ALERT: " + msg);};
+
+function noop(){}
+
+jstd = jstestdriver;
+
+function html(content) {
+ return jQuery("
").html(content);
+}
+
+function report(reportTest){
+ $("#tests").children().each(function(i){
+ var success = this.className == "pass";
+ var strong = this.firstChild;
+ var msg = strong.firstChild.nodeValue;
+ var parts = msg.split(" module: ");
+ var module = parts[0];
+ var name = parts[1].replace(/ *$/, "");
+ reportTest(success, module, name, this.nodeValue);
+ });
+}
+
+MockUrlWatcher = function() {
+ this.url = "http://server";
+};
+MockUrlWatcher.prototype.getUrl = function(){
+ return this.url;
+};
+MockUrlWatcher.prototype.setUrl = function(url){
+ this.url = url;
+};
+
+jQuery.fn.sortedHtml = function() {
+ var html = "";
+ var toString = function(index, node) {
+ node = node || this;
+ if (node.nodeName == "#text") {
+ html += nglr.escapeHtml(node.nodeValue);
+ } else {
+ html += '<' + node.nodeName.toLowerCase();
+ var attributes = node.attributes || [];
+ var attrs = [];
+ for(var i=0; i
';
+ var children = node.childNodes;
+ for(var j=0; j';
+ }
+ };
+ this.children().each(toString);
+ return html;
+};
+
+function encode64(obj){
+ return Base64.encode(nglr.toJson(obj));
+}
+
+function decode64(base64){
+ return nglr.fromJson(Base64.decode(base64));
+}
+
+nglr.Loader.prototype.configureJQueryPlugins();
+
+function assertHidden(node) {
+ var display = node.css('display');
+ assertEquals("Node should be hidden but vas visible: " + node.sortedHtml(), 'none', display);
+}
+
+function assertVisible(node) {
+ var display = node.css('display');
+ if (display == 'block') display = "";
+ assertEquals("Node should be visible but vas hidden: " + node.sortedHtml(), '', display);
+}
+
+function assertJsonEquals(expected, actual) {
+ assertEquals(nglr.toJson(expected), nglr.toJson(actual));
+}
+
+function assertUndefined(value) {
+ assertEquals('undefined', typeof value);
+}
+
+function assertDefined(value) {
+ assertTrue(nglr.toJson(value), !!value);
+}
+
+function assertThrows(error, fn){
+ var exception = null;
+ try {
+ fn();
+ } catch(e) {
+ exception = e;
+ }
+ if (!exception) {
+ fail("Expecting exception, none thrown");
+ }
+ assertEquals(error, exception);
+}
\ No newline at end of file
--
cgit v1.2.3