")
})
});
view.createLayer();
ok(view.$('#twas-called').length, "the named template was called");
});
test("template view should call the function of the associated template with itself as the context", function() {
var view = SC.TemplateView.create({
templateName: 'test_template',
_personName: "Tom DAAAALE",
_i: 0,
personName: function() {
this._i++;
return this._personName + this._i;
}.property().cacheable(),
templates: SC.Object.create({
test_template: SC.Handlebars.compile("
template was called for {{personName}}. Yea {{personName}}
")
})
});
view.createLayer();
equals("template was called for Tom DAAAALE1. Yea Tom DAAAALE1", view.$('#twas-called').text(), "the named template was called with the view as the data source");
});
test("should allow values from normal JavaScript hash objects to be used", function() {
var view = SC.TemplateView.create({
template: SC.Handlebars.compile('{{#with person}}{{firstName}} {{lastName}} (and {{pet.name}}){{/with}}'),
person: {
firstName: 'Señor',
lastName: 'CFC',
pet: {
name: 'Fido'
}
}
});
view.createLayer();
equals(view.$().text(), "Señor CFC (and Fido)", "prints out values from a hash");
});
TemplateTests = {};
test("child views can be inserted using the {{view}} Handlebars helper", function() {
var templates = SC.Object.create({
nester: SC.Handlebars.compile("
')
});
var view = SC.TemplateView.create({
templateName: 'menu',
templates: templates,
INCEPTION: "BOOOOOOOONG doodoodoodoodooodoodoodoo",
inception: false,
SAD: 'BOONG?'
});
view.createLayer();
equals(view.$('h1').text(), "BOONG?", "renders alternate if false");
SC.run(function() { view.set('inception', true); });
var tests = [false, null, undefined, [], '', 0];
tests.forEach(function(val) {
SC.run(function() {
view.set('inception', val);
});
equals(view.$('h1').text(), 'BOONG?', "renders alternate if %@".fmt(val));
SC.run(function() {
view.set('inception', true);
});
equals(view.$('h1').text(), "BOOOOOOOONG doodoodoodoodooodoodoodoo", "precond - renders block when conditional is true");
});
});
test("Should insert a localized string if the {{loc}} helper is used", function() {
SC.stringsFor('en', {
'Brazil': 'Brasilia'
});
var templates = SC.Object.create({
'loc': SC.Handlebars.compile('
Country: {{loc "Brazil"}}')
});
var view = SC.TemplateView.create({
templateName: 'loc',
templates: templates,
country: 'Brazil'
});
view.createLayer();
equals(view.$('h1').text(), 'Country: Brasilia', "returns localized value");
});
test("Template views return a no-op function if their template cannot be found", function() {
var view = SC.TemplateView.create({
templateName: 'cantBeFound'
});
var template = view.get('template');
ok(SC.typeOf(template) === 'function', 'template should be a function');
equals(template(), '', 'should return an empty string');
});
test("Template views can belong to a pane and a parent view", function() {
var templates = SC.Object.create({
toDo: SC.Handlebars.compile('
{{title}}
(Created at {{createdAt}})')
});
var didCreateLayerWasCalled = NO;
var pane = SC.MainPane.design({
childViews: ['container'],
container: SC.View.design({
childViews: ['normalView', 'template'],
normalView: SC.View,
template: SC.TemplateView.design({
templates: templates,
templateName: 'toDo',
title: 'Do dishes',
createdAt: "Today",
didCreateLayer: function() {
didCreateLayerWasCalled = YES;
}
})
})
});
pane = pane.create().append();
equals(pane.$().children().length, 1, "pane has one child DOM element");
equals(pane.$().children().children().length, 2, "container view has two child DOM elements");
equals(pane.$().children().children().eq(1).text(), "Do dishes (Created at Today)", "renders template to the correct DOM element");
ok(didCreateLayerWasCalled, "didCreateLayer gets called on a template view after it gets rendered");
pane.remove();
});
test("Template views add a layerId to child views created using the view helper", function() {
var templates = SC.Object.create({
parent: SC.Handlebars.compile(''),
child: SC.Handlebars.compile("I can't believe it's not butter.")
});
TemplateTests.ChildView = SC.TemplateView.extend({
templates: templates,
templateName: 'child'
});
var view = SC.TemplateView.create({
templates: templates,
templateName: 'parent'
});
view.createLayer();
var childView = view.getPath('childViews.firstObject');
equals(view.$().children().first().children().first().attr('id'), childView.get('layerId'));
});
test("Template views set the template of their children to a passed block", function() {
var templates = SC.Object.create({
parent: SC.Handlebars.compile('
.*.*<\/span>.*<\/h1>/), "renders the passed template inside the parent template");
});
test("should pass hash arguments to the view object", function() {
TemplateTests.bindTestObject = SC.Object.create({
bar: 'bat'
});
TemplateTests.HashArgTemplateView = SC.TemplateView.extend({
});
var view = SC.TemplateView.create({
template: SC.Handlebars.compile('{{#view TemplateTests.HashArgTemplateView fooBinding="TemplateTests.bindTestObject.bar"}}{{foo}}{{/view}}')
});
view.createLayer();
SC.run();
equals(view.$().text(), "bat", "prints initial bound value");
SC.run(function() { TemplateTests.bindTestObject.set('bar', 'brains'); });
equals(view.$().text(), "brains", "prints updated bound value");
});
test("Child views created using the view helper should have their parent view set properly", function() {
TemplateTests = {};
var template = '{{#view "SC.TemplateView"}}{{#view "SC.TemplateView"}}{{view "SC.TemplateView"}}{{/view}}{{/view}}';
var view = SC.TemplateView.create({
template: SC.Handlebars.compile(template)
});
view.createLayer();
var childView = view.childViews[0].childViews[0];
equals(childView, childView.childViews[0].parentView, 'parent view is correct');
});
test("Child views created using the view helper should have their IDs registered for events", function() {
TemplateTests = {};
var template = '{{view "SC.TemplateView"}}{{view "SC.TemplateView" id="templateViewTest"}}';
var view = SC.TemplateView.create({
template: SC.Handlebars.compile(template)
});
view.createLayer();
var childView = view.childViews[0];
var id = childView.$()[0].id;
equals(SC.View.views[id], childView, 'childView without passed ID is registered with SC.View.views so that it can properly receive events from RootResponder');
childView = view.childViews[1];
id = childView.$()[0].id;
equals(id, 'templateViewTest', 'precond -- id of childView should be set correctly');
equals(SC.View.views[id], childView, 'childView with passed ID is registered with SC.View.views so that it can properly receive events from RootResponder');
});
test("Collection views that specify an example view class have their children be of that class", function() {
TemplateTests.ExampleViewCollection = SC.TemplateCollectionView.create({
itemView: SC.TemplateView.extend({
isCustom: YES
}),
content: ['foo']
});
var parentView = SC.TemplateView.create({
template: SC.Handlebars.compile('{{#collection "TemplateTests.ExampleViewCollection"}}OHAI{{/collection}}')
});
parentView.createLayer();
ok(parentView.childViews[0].childViews[0].isCustom, "uses the example view class");
});
test("should update boundIf blocks if the conditional changes", function() {
var templates = SC.Object.create({
foo: SC.Handlebars.compile('
')
});
var view = SC.TemplateView.create({
templateName: 'foo',
templates: templates,
content: SC.Object.create({
wham: 'bam',
thankYou: "ma'am",
myApp: SC.Object.create({
isEnabled: YES
})
})
});
view.createLayer();
equals(view.$('#first').text(), "bam", "renders block when condition is true");
SC.run(function() { view.get('content').setPath('myApp.isEnabled', NO); });
equals(view.$('#first').text(), "", "re-renders without block when condition is false");
SC.run(function() { view.get('content').setPath('myApp.isEnabled', YES); });
equals(view.$('#first').text(), "bam", "re-renders block when condition changes to true");
});
test("{{view}} id attribute should set id on layer", function() {
var templates = SC.Object.create({
foo: SC.Handlebars.compile('{{#view "TemplateTests.IdView" id="bar"}}baz{{/view}}')
});
TemplateTests.IdView = SC.TemplateView.create();
var view = SC.TemplateView.create({
templateName: 'foo',
templates: templates
});
view.createLayer();
equals(view.$('#bar').length, 1, "adds id attribute to layer");
equals(view.$('#bar').text(), 'baz', "emits content");
});
test("{{view}} class attribute should set class on layer", function() {
var templates = SC.Object.create({
foo: SC.Handlebars.compile('{{#view "TemplateTests.IdView" class="bar"}}baz{{/view}}')
});
TemplateTests.IdView = SC.TemplateView.create();
var view = SC.TemplateView.create({
templateName: 'foo',
templates: templates
});
view.createLayer();
equals(view.$('.bar').length, 1, "adds class attribute to layer");
equals(view.$('.bar').text(), 'baz', "emits content");
});
test("{{view}} should be able to point to a local view", function() {
var view = SC.TemplateView.create({
template: SC.Handlebars.compile("{{view common}}"),
common: SC.TemplateView.create({
template: SC.Handlebars.compile("common")
})
});
view.createLayer();
equals(view.$().text(), "common", "tries to look up view name locally");
});
test("should be able to bind view class names to properties", function() {
var templates = SC.Object.create({
template: SC.Handlebars.compile('{{#view "TemplateTests.classBindingView" classBinding="isDone"}}foo{{/view}}')
});
TemplateTests.classBindingView = SC.TemplateView.create({
isDone: YES
});
var view = SC.TemplateView.create({
templateName: 'template',
templates: templates
});
view.createLayer();
equals(view.$('.is-done').length, 1, "dasherizes property and sets class name");
SC.run(function() {
TemplateTests.classBindingView.set('isDone', NO);
});
equals(view.$('.is-done').length, 0, "removes class name if bound property is set to false");
// There is a bug that if the view becomes first responder, its class bindings get wiped out.
// This test illustrates the bug, by adding the view to a pane and making it firstResponder
var pane = SC.MainPane.design();
pane = pane.create().append();
SC.run(function() {
pane.appendChild(view);
});
TemplateTests.classBindingView.becomeFirstResponder();
SC.run(function() {
TemplateTests.classBindingView.set('isDone', YES);
});
equals(view.$('.is-done').length, 1, "dasherizes property and sets class name after becoming first responder");
});
test("should be able to bind element attributes using {{bindAttr}}", function() {
var template = SC.Handlebars.compile('');
var view = SC.TemplateView.create({
template: template,
content: SC.Object.create({
url: "http://www.sproutcore.com/assets/images/logo.png",
title: "The SproutCore Logo"
})
});
view.createLayer();
equals(view.$('img').attr('src'), "http://www.sproutcore.com/assets/images/logo.png", "sets src attribute");
equals(view.$('img').attr('alt'), "The SproutCore Logo", "sets alt attribute");
SC.run(function() {
view.setPath('content.title', "El logo de Esproutcore");
});
equals(view.$('img').attr('alt'), "El logo de Esproutcore", "updates alt attribute when content's title attribute changes");
SC.run(function() {
view.set('content', SC.Object.create({
url: "http://www.thegooglez.com/theydonnothing",
title: "I CAN HAZ SEARCH"
}));
});
equals(view.$('img').attr('alt'), "I CAN HAZ SEARCH", "updates alt attribute when content object changes");
SC.run(function() {
view.set('content', {
url: "http://www.sproutcore.com/assets/images/logo.png",
title: "The SproutCore Logo"
});
});
equals(view.$('img').attr('alt'), "The SproutCore Logo", "updates alt attribute when content object is a hash");
SC.run(function() {
view.set('content', {
url: "http://www.sproutcore.com/assets/images/logo.png",
title: function() {
return "Nanananana SproutCore!";
}
});
});
equals(view.$('img').attr('alt'), "Nanananana SproutCore!", "updates alt attribute when title property is computed");
});
test("should be able to bind element attributes using {{bindAttr}} inside a block", function() {
var template = SC.Handlebars.compile('{{#with content}}{{/with}}');
var view = SC.TemplateView.create({
template: template,
content: SC.Object.create({
url: "http://www.sproutcore.com/assets/images/logo.png",
title: "The SproutCore Logo"
})
});
view.createLayer();
equals(view.$('img').attr('src'), "http://www.sproutcore.com/assets/images/logo.png", "sets src attribute");
equals(view.$('img').attr('alt'), "The SproutCore Logo", "sets alt attribute");
SC.run(function() {
view.setPath('content.title', "El logo de Esproutcore");
});
equals(view.$('img').attr('alt'), "El logo de Esproutcore", "updates alt attribute when content's title attribute changes");
});
test("should be able to bind class attribute with {{bindAttr}}", function() {
var template = SC.Handlebars.compile('');
var view = SC.TemplateView.create({
template: template,
foo: 'bar'
});
view.createLayer();
equals(view.$('img').attr('class'), 'bar', "renders class");
SC.run(function() {
view.set('foo', 'baz');
});
equals(view.$('img').attr('class'), 'baz', "updates class");
});
test("should be able to bind boolean element attributes using {{bindAttr}}", function() {
var template = SC.Handlebars.compile('');
var content = SC.Object.create({
isDisabled: false,
isChecked: true
});
var view = SC.TemplateView.create({
template: template,
content: content
});
view.createLayer();
ok(!view.$('input').attr('disabled'), 'attribute does not exist upon initial render');
ok(view.$('input').attr('checked'), 'attribute is present upon initial render');
SC.run(function() {
content.set('isDisabled', true);
content.set('isChecked', false);
});
ok(view.$('input').attr('disabled'), 'attribute exists after update');
ok(!view.$('input').attr('checked'), 'attribute is not present after update');
});
test("should be able to add multiple classes using {{bindAttr class}}", function() {
var template = SC.Handlebars.compile('');
var content = SC.Object.create({
isAwesomeSauce: true,
isAlsoCool: true
});
var view = SC.TemplateView.create({
template: template,
content: content
});
view.createLayer();
ok(view.$('div').hasClass('is-awesome-sauce'), "dasherizes first property and sets classname");
ok(view.$('div').hasClass('is-also-cool'), "dasherizes second property and sets classname");
SC.run(function() {
content.set('isAwesomeSauce', false);
});
ok(!view.$('div').hasClass('is-awesome-sauce'), "removes dasherized class when property is set to false");
});