BinderTest = TestCase('BinderTest');
function compile(content, initialScope, config) {
var h = html(content);
config = config || {autoSubmit:true};
var scope = new Scope($.extend({$invalidWidgets:[]}, initialScope), "ROOT");
h.data('scope', scope);
var datastore = new DataStore();
var binder = new Binder(h[0], new WidgetFactory(), datastore, new MockLocation(), config);
scope.set("$updateView", _(binder.updateView).bind(binder));
scope.set("$anchor", binder.anchor);
binder.entity(scope);
binder.compile();
return {node:h, binder:binder, scope:scope, datastore:datastore};
}
function compileToHtml(content) {
return compile(content).node.sortedHtml();
}
BinderTest.prototype.testParseTextWithNoBindings = function(){
var parts = Binder.parseBindings("a");
assertEquals(parts.length, 1);
assertEquals(parts[0], "a");
assertTrue(!Binder.binding(parts[0]));
};
BinderTest.prototype.testParseEmptyText = function(){
var parts = Binder.parseBindings("");
assertEquals(parts.length, 1);
assertEquals(parts[0], "");
assertTrue(!Binder.binding(parts[0]));
};
BinderTest.prototype.testParseInnerBinding = function(){
var parts = Binder.parseBindings("a{{b}}c");
assertEquals(parts.length, 3);
assertEquals(parts[0], "a");
assertTrue(!Binder.binding(parts[0]));
assertEquals(parts[1], "{{b}}");
assertEquals(Binder.binding(parts[1]), "b");
assertEquals(parts[2], "c");
assertTrue(!Binder.binding(parts[2]));
};
BinderTest.prototype.testParseEndingBinding = function(){
var parts = Binder.parseBindings("a{{b}}");
assertEquals(parts.length, 2);
assertEquals(parts[0], "a");
assertTrue(!Binder.binding(parts[0]));
assertEquals(parts[1], "{{b}}");
assertEquals(Binder.binding(parts[1]), "b");
};
BinderTest.prototype.testParseBeggingBinding = function(){
var parts = Binder.parseBindings("{{b}}c");
assertEquals(parts.length, 2);
assertEquals(parts[0], "{{b}}");
assertEquals(Binder.binding(parts[0]), "b");
assertEquals(parts[1], "c");
assertTrue(!Binder.binding(parts[1]));
};
BinderTest.prototype.testParseLoanBinding = function(){
var parts = Binder.parseBindings("{{b}}");
assertEquals(parts.length, 1);
assertEquals(parts[0], "{{b}}");
assertEquals(Binder.binding(parts[0]), "b");
};
BinderTest.prototype.testParseTwoBindings = function(){
var parts = Binder.parseBindings("{{b}}{{c}}");
assertEquals(parts.length, 2);
assertEquals(parts[0], "{{b}}");
assertEquals(Binder.binding(parts[0]), "b");
assertEquals(parts[1], "{{c}}");
assertEquals(Binder.binding(parts[1]), "c");
};
BinderTest.prototype.testParseTwoBindingsWithTextInMiddle = function(){
var parts = Binder.parseBindings("{{b}}x{{c}}");
assertEquals(parts.length, 3);
assertEquals(parts[0], "{{b}}");
assertEquals(Binder.binding(parts[0]), "b");
assertEquals(parts[1], "x");
assertTrue(!Binder.binding(parts[1]));
assertEquals(parts[2], "{{c}}");
assertEquals(Binder.binding(parts[2]), "c");
};
BinderTest.prototype.testParseMultiline = function(){
var parts = Binder.parseBindings('"X\nY{{A\nB}}C\nD"');
assertTrue(!!Binder.binding('{{A\nB}}'));
assertEquals(parts.length, 3);
assertEquals(parts[0], '"X\nY');
assertEquals(parts[1], '{{A\nB}}');
assertEquals(parts[2], 'C\nD"');
};
BinderTest.prototype.testHasBinding = function(){
assertTrue(Binder.hasBinding("{{a}}"));
assertTrue(!Binder.hasBinding("a"));
assertTrue(Binder.hasBinding("{{b}}x{{c}}"));
};
BinderTest.prototype.tearDown = function(){
jQuery("*", document).die();
jQuery(document).unbind();
};
BinderTest.prototype.testChangingTextfieldUpdatesModel = function(){
var state = compile('', {model:{}});
state.binder.updateView();
assertEquals('abc', state.scope.get('model').price);
};
BinderTest.prototype.testChangingTextareaUpdatesModel = function(){
var c = compile('');
c.binder.updateView();
assertEquals(c.scope.get('model').note, 'abc');
};
BinderTest.prototype.testChangingRadioUpdatesModel = function(){
var c = compile('' +
'');
c.binder.updateView();
assertEquals(c.scope.get('model').price, 'A');
};
BinderTest.prototype.testChangingCheckboxUpdatesModel = function(){
var form = compile('');
form.scope.set('model', {});
form.binder.updateView();
assertEquals(true, form.scope.get('model').price);
};
BinderTest.prototype.testBindUpdate = function() {
var c = compile('
');
c.binder.updateView();
assertEquals(123, c.scope.get('a'));
};
BinderTest.prototype.testChangingSelectNonSelectedUpdatesModel = function(){
var form = compile('');
form.scope.set('model', {});
form.binder.updateView();
assertEquals('A', form.scope.get('model').price);
};
BinderTest.prototype.testChangingMultiselectUpdatesModel = function(){
var form = compile('');
form.scope.set("Invoice", {});
form.binder.updateView();
assertJsonEquals(["A", "B"], form.scope.get('Invoice').options);
};
BinderTest.prototype.testChangingSelectSelectedUpdatesModel = function(){
var form = compile('');
form.scope.set('model', {});
form.binder.updateView();
assertEquals(form.scope.get('model').price, 'b');
};
BinderTest.prototype.testExecuteInitialization = function() {
var form = html('
');
var scope = new Scope();
form.data('scope', scope);
var binder = new Binder(form.get(0));
binder.executeInit();
assertEquals(scope.get('a'), 123);
};
BinderTest.prototype.testExecuteInitializationStatements = function() {
var form = html('
');
var scope = new Scope();
form.data('scope', scope);
var binder = new Binder(form.get(0));
binder.executeInit();
assertEquals(scope.get('a'), 123);
assertEquals(scope.get('b'), 345);
};
BinderTest.prototype.testApplyTextBindings = function(){
var form = compile('
x
');
form.scope.set('model', {a:123});
form.binder.compile();
form.binder.updateView();
assertEquals('123', form.node.text());
};
BinderTest.prototype.testReplaceBindingInTextWithSpan = function() {
assertEquals(compileToHtml("a{{b}}c"), 'ac');
assertEquals(compileToHtml("{{b}}"), '');
};
BinderTest.prototype.testReplaceBindingCreatesCorrectNumberOfWidgets = function() {
var h = html("space{{a}}{{a}}a{{a}}{{a}}");
h.data('scope', new Scope());
var binder = new Binder(h.get(0), new WidgetFactory());
binder.compile();
assertEquals(4, h.scope().widgets.length);
};
BinderTest.prototype.testBindingSpaceConfusesIE = function() {
if (!msie) return;
var span = document.createElement("span");
span.innerHTML = ' ';
var nbsp = span.firstChild.nodeValue;
assertEquals(
''+nbsp+'',
compileToHtml("{{a}} {{b}}"));
assertEquals(
''+nbsp+'x '+nbsp+'(',
compileToHtml("{{A}} x {{B}} ({{C}})"));
};
BinderTest.prototype.testBindingOfAttributes = function() {
var form = html("");
form.data('scope', new Scope());
var binder = new Binder(form.get(0));
binder.compile();
var attrbinding = form.find("a").attr("ng-bind-attr");
var bindings = fromJson(attrbinding);
assertEquals("http://s/a{{b}}c", decodeURI(bindings.href));
assertTrue(!bindings.foo);
};
BinderTest.prototype.testMarkMultipleAttributes = function() {
var form = html("");
form.data('scope', new Scope());
var binder = new Binder(form.get(0));
binder.compile();
var attrbinding = form.find("a").attr("ng-bind-attr");
var bindings = fromJson(attrbinding);
assertEquals(decodeURI(bindings.href), "http://s/a{{b}}c");
assertEquals(bindings.foo, "{{d}}");
};
BinderTest.prototype.testAttributesNoneBound = function() {
var form = html("");
form.data('scope', new Scope());
var binder = new Binder(form.get(0));
binder.compile();
var a = form.find("a");
assertEquals(a.get(0).nodeName, "A");
assertTrue(!a.attr("ng-bind-attr"));
};
BinderTest.prototype.testExistingAttrbindingIsAppended = function() {
var form = html("");
form.data('scope', new Scope());
var binder = new Binder(form.get(0));
binder.compile();
var a = form.find("a");
assertEquals('{"b":"{{def}}","href":"http://s/{{abc}}"}', a.attr('ng-bind-attr'));
};
BinderTest.prototype.testAttributesAreEvaluated = function(){
var c = compile('');
var binder = c.binder, form = c.node;
c.scope.eval('a=1;b=2');
binder.updateView();
var a = form.find("a");
assertEquals(a.attr('a'), 'a');
assertEquals(a.attr('b'), 'a+b=3');
};
BinderTest.prototype.testInputsAreUpdated = function(){
var a =
compile('' +
'' +
'' +
'' +
'' +
'' +
'');
var binder = a.binder, form = a.node;
a.scope.set('A', {text:"t1", textarea:"t2", radio:"r", checkbox:"c", select:"S"});
binder.compile();
binder.updateView();
assertEquals(form.find("input[type=text]").attr('value'), 't1');
assertEquals(form.find("textarea").attr('value'), 't2');
assertTrue(form.find("input[name=A.radio]").attr('checked'));
assertTrue(!form.find("input[name=A.radioOff]").attr('checked'));
assertTrue(form.find("input[name=A.checkbox]").attr('checked'));
assertTrue(!form.find("input[name=A.checkboxOff]").attr('checked'));
assertEquals(form.find("select").attr('value'), 'S');
assertEquals(form.find("option[selected]").text(), 'b');
};
BinderTest.prototype.testInputTypeButtonActionExecutesInScope = function(){
var savedCalled = false;
var c = compile('');
c.scope.set("person.save", function(){
savedCalled = true;
});
c.node.find("#apply").click();
assertTrue(savedCalled);
};
BinderTest.prototype.testInputTypeButtonActionExecutesInScope = function(){
expectAsserts(1);
var c = compile('');
c.scope.set("action", function(){
assertTrue(true);
});
c.node.find("#apply").click();
};
BinderTest.prototype.testButtonElementActionExecutesInScope = function(){
var savedCalled = false;
var c = compile('');
c.scope.set("person.save", function(){
savedCalled = true;
});
c.node.find("#apply").click();
assertTrue(savedCalled);
};
BinderTest.prototype.testParseEmptyAnchor = function(){
var binder = compile("").binder;
var location = binder.location;
var anchor = binder.anchor;
location.url = "a#x=1";
binder.parseAnchor();
assertEquals(1, binder.anchor.x);
location.url = "a#";
binder.parseAnchor();
assertTrue("old values did not get removed", !binder.anchor.x);
assertTrue("anchor gor replaced", anchor === binder.anchor);
assertEquals('undefined', typeof (anchor[""]));
};
BinderTest.prototype.testParseAnchor = function(){
var binder = compile("").binder;
var location = binder.location;
location.url = "a#x=1";
binder.parseAnchor();
assertEquals(binder.anchor.x, "1");
location.url = "a#a=b&c=%20&d";
binder.parseAnchor();
assertEquals(binder.anchor.a, 'b');
assertEquals(binder.anchor.c, ' ');
assertTrue(binder.anchor.d !== null);
assertTrue(!binder.anchor.x);
};
BinderTest.prototype.testWriteAnchor = function(){
var binder = compile("").binder;
binder.location.set('a');
binder.anchor.a = 'b';
binder.anchor.c = ' ';
binder.anchor.d = true;
binder.updateAnchor();
assertEquals(binder.location.get(), "a#a=b&c=%20&d");
};
BinderTest.prototype.testWriteAnchorAsPartOfTheUpdateView = function(){
var binder = compile("").binder;
binder.location.set('a');
binder.anchor.a = 'b';
binder.updateView();
assertEquals(binder.location.get(), "a#a=b");
};
BinderTest.prototype.testRepeaterUpdateBindings = function(){
var a = compile('
');
var form = a.node;
var items = [{a:"A"}, {a:"B"}];
a.scope.set('model', {items:items});
a.binder.updateView();
assertEquals('