Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch '1-0-beta'

Conflicts:
	packages/ember-application/lib/system/application.js
	packages/ember-runtime/lib/controllers.js
  • Loading branch information...
commit b71cae78d3ba11ec4bfbe0d5d36ee1fe2d4dbcf0 2 parents 3e26ac9 + 6041912
@krisselden krisselden authored
View
36 packages/ember-application/lib/system/application.js
@@ -94,29 +94,39 @@ Ember.Application = Ember.Namespace.extend(
...
});
- App.initialize(stateManager);
+ App.initialize(router);
- stateManager.get('postsController') // <App.PostsController:ember1234>
- stateManager.get('commentsController') // <App.CommentsController:ember1235>
+ router.get('postsController') // <App.PostsController:ember1234>
+ router.get('commentsController') // <App.CommentsController:ember1235>
- stateManager.getPath('postsController.stateManager') // stateManager
+ router.getPath('postsController.router') // router
*/
- initialize: function(stateManager) {
+ initialize: function(router) {
var properties = Ember.A(Ember.keys(this)),
injections = get(this.constructor, 'injections'),
namespace = this, controller, name;
- if (!stateManager && Ember.Router.detect(namespace['Router'])) {
- stateManager = namespace['Router'].create();
+ if (!router && Ember.Router.detect(namespace['Router'])) {
+ router = namespace['Router'].create();
}
- set(this, 'stateManager', stateManager);
+ if (router) {
+ set(this, 'stateManager', router);
+ }
+
+ // By default, the router's namespace is the current application.
+ //
+ // This allows it to find model classes when a state has a
+ // route like `/posts/:post_id`. In that case, it would first
+ // convert `post_id` into `Post`, and then look it up on its
+ // namespace.
+ set(router, 'namespace', this);
Ember.runLoadHooks('application', this);
properties.forEach(function(property) {
injections.forEach(function(injection) {
- injection(namespace, stateManager, property);
+ injection(namespace, router, property);
});
});
},
@@ -182,12 +192,14 @@ Ember.Application.reopenClass({
}
});
-Ember.Application.registerInjection(function(app, stateManager, property) {
+Ember.Application.registerInjection(function(app, router, property) {
if (!/^[A-Z].*Controller$/.test(property)) { return; }
var name = property[0].toLowerCase() + property.substr(1),
controller = app[property].create();
- stateManager.set(name, controller);
- controller.set('target', stateManager);
+ router.set(name, controller);
+
+ controller.set('target', router);
+ controller.set('controllers', router);
});
View
1  packages/ember-handlebars/lib/helpers.js
@@ -13,3 +13,4 @@ require("ember-handlebars/helpers/each");
require("ember-handlebars/helpers/template");
require("ember-handlebars/helpers/action");
require("ember-handlebars/helpers/yield");
+require("ember-handlebars/helpers/outlet");
View
39 packages/ember-handlebars/lib/helpers/outlet.js
@@ -0,0 +1,39 @@
+require('ember-handlebars/helpers/view');
+
+/**
+ The `outlet` helper allows you to specify that the current
+ view's controller will fill in the view for a given area.
+
+ {{outlet}}
+
+ By default, when the the current controller's `view`
+ property changes, the outlet will replace its current
+ view with the new view.
+
+ controller.set('view', someView);
+
+ You can also specify a particular name, other than view:
+
+ {{outlet masterView}}
+ {{outlet detailView}}
+
+ Then, you can control several outlets from a single
+ controller:
+
+ controller.set('masterView', postsView);
+ controller.set('detailView', postView);
+
+ @name Handlebars.helpers.outlet
+ @param {String} property the property on the controller
+ that holds the view for this outlet
+*/
+Ember.Handlebars.registerHelper('outlet', function(property, options) {
+ if (property && property.data && property.data.isRenderData) {
+ options = property;
+ property = 'view';
+ }
+
+ options.hash.currentViewBinding = "controller." + property;
+
+ return Ember.Handlebars.helpers.view.call(this, Ember.ContainerView, options);
+});
View
64 packages/ember-handlebars/tests/helpers/outlet_test.js
@@ -0,0 +1,64 @@
+var appendView = function(view) {
+ Ember.run(function() { view.appendTo('#qunit-fixture'); });
+};
+
+var compile = function(template) {
+ return Ember.Handlebars.compile(template);
+};
+
+var view;
+
+module("Handlebars {{outlet}} helpers", {
+ teardown: function() {
+ Ember.run(function () {
+ if (view) {
+ view.destroy();
+ }
+ });
+ }
+});
+
+test("outlet should allow controllers to fill in slots", function() {
+ var controller = Ember.Object.create();
+
+ var template = "<h1>HI</h1>{{outlet}}";
+ view = Ember.View.create({
+ controller: controller,
+ template: Ember.Handlebars.compile(template)
+ });
+
+ appendView(view);
+
+ equal(view.$().text(), 'HI');
+
+ Ember.run(function() {
+ controller.set('view', Ember.View.create({
+ template: compile("<p>BYE</p>")
+ }));
+ });
+
+ equal(view.$().text(), 'HIBYE');
+});
+
+
+test("outlet should support an optional name", function() {
+ var controller = Ember.Object.create();
+
+ var template = "<h1>HI</h1>{{outlet mainView}}";
+ view = Ember.View.create({
+ controller: controller,
+ template: Ember.Handlebars.compile(template)
+ });
+
+ appendView(view);
+
+ equal(view.$().text(), 'HI');
+
+ Ember.run(function() {
+ controller.set('mainView', Ember.View.create({
+ template: compile("<p>BYE</p>")
+ }));
+ });
+
+ equal(view.$().text(), 'HIBYE');
+});
View
2  packages/ember-metal/lib/mixin.js
@@ -358,6 +358,8 @@ Mixin.prototype.reopen = function() {
mixin.properties = this.properties;
delete this.properties;
this.mixins = [mixin];
+ } else if (!this.mixins) {
+ this.mixins = [];
}
var len = arguments.length, mixins = this.mixins, idx;
View
1  packages/ember-runtime/lib/controllers.js
@@ -1,2 +1,3 @@
require('ember-runtime/controllers/array_controller');
require('ember-runtime/controllers/object_controller');
+require('ember-runtime/controllers/controller');
View
3  packages/ember-runtime/lib/controllers/array_controller.js
@@ -5,6 +5,7 @@
// ==========================================================================
require('ember-runtime/system/array_proxy');
+require('ember-runtime/controllers/controller');
/**
@class
@@ -45,4 +46,4 @@ require('ember-runtime/system/array_proxy');
@extends Ember.ArrayProxy
*/
-Ember.ArrayController = Ember.ArrayProxy.extend();
+Ember.ArrayController = Ember.ArrayProxy.extend(Ember.ControllerMixin);
View
6 packages/ember-runtime/lib/controllers/controller.js
@@ -0,0 +1,6 @@
+require('ember-runtime/system/object');
+require('ember-runtime/system/string');
+
+Ember.ControllerMixin = Ember.Mixin.create();
+
+Ember.Controller = Ember.Object.extend(Ember.ControllerMixin);
View
3  packages/ember-runtime/lib/controllers/object_controller.js
@@ -1,3 +1,4 @@
require('ember-runtime/system/object_proxy');
+require('ember-runtime/controllers/controller');
-Ember.ObjectController = Ember.ObjectProxy.extend();
+Ember.ObjectController = Ember.ObjectProxy.extend(Ember.ControllerMixin);
View
17 packages/ember-runtime/lib/system/string.js
@@ -154,7 +154,7 @@ Ember.String = {
/**
Returns the lowerCaseCamel form of a string.
-
+
'innerHTML'.camelize() => 'innerHTML'
'action_name'.camelize() => 'actionName'
'css-class-name'.camelize() => 'cssClassName'
@@ -172,6 +172,19 @@ Ember.String = {
},
/**
+ Returns the UpperCamelCase form of a string.
+
+ 'innerHTML'.classify() => 'InnerHTML'
+ 'action_name'.classify() => 'ActionName'
+ 'css-class-name'.classify() => 'CssClassName'
+ 'my favorite items'.classift() => 'MyFavoriteItems'
+ */
+ classify: function(str) {
+ var camelized = Ember.String.camelize(str);
+ return camelized.charAt(0).toUpperCase() + camelized.substr(1);
+ },
+
+ /**
More general than decamelize. Returns the lower_case_and_underscored
form of a string.
@@ -189,4 +202,4 @@ Ember.String = {
return str.replace(STRING_UNDERSCORE_REGEXP_1, '$1_$2').
replace(STRING_UNDERSCORE_REGEXP_2, '_').toLowerCase();
}
-};
+};
View
75 packages/ember-states/lib/routable.js
@@ -9,9 +9,17 @@ var get = Ember.get, getPath = Ember.getPath;
// * .onURLChange(callback) - this happens when the user presses
// the back or forward button
+var paramForClass = function(classObject) {
+ var className = classObject.toString(),
+ parts = className.split("."),
+ last = parts[parts.length - 1];
+
+ return Ember.String.underscore(last) + "_id";
+};
+
Ember.Routable = Ember.Mixin.create({
init: function() {
- this.on('setupControllers', this, this.stashContext);
+ this.on('connectOutlets', this, this.stashContext);
this._super();
},
@@ -59,14 +67,73 @@ Ember.Routable = Ember.Mixin.create({
}).cacheable(),
routeMatcher: Ember.computed(function() {
- return Ember._RouteMatcher.create({ route: get(this, 'route') });
+ if (get(this, 'route')) {
+ return Ember._RouteMatcher.create({ route: get(this, 'route') });
+ }
}).cacheable(),
- deserialize: function(manager, context) {
- return context;
+ modelClass: Ember.computed(function() {
+ var modelType = get(this, 'modelType');
+
+ if (typeof modelType === 'string') {
+ return Ember.getPath(window, modelType);
+ } else {
+ return modelType;
+ }
+ }).cacheable(),
+
+ modelClassFor: function(manager) {
+ var modelClass, namespace, routeMatcher, identifiers, match, className;
+
+ // if an explicit modelType was specified, use that
+ if (modelClass = get(this, 'modelClass')) { return modelClass; }
+
+ // if the router has no lookup namespace, we won't be able to guess
+ // the modelType
+ namespace = get(manager, 'namespace');
+ if (!namespace) { return; }
+
+ // make sure this state is actually a routable state
+ routeMatcher = get(this, 'routeMatcher');
+ if (!routeMatcher) { return; }
+
+ // only guess modelType for states with a single dynamic segment
+ // (no more, no fewer)
+ identifiers = routeMatcher.identifiers;
+ if (identifiers.length !== 2) { return; }
+
+ // extract the `_id` from the end of the dynamic segment; if the
+ // dynamic segment does not end in `_id`, we can't guess the
+ // modelType
+ match = identifiers[1].match(/^(.*)_id$/);
+ if (!match) { return; }
+
+ // convert the underscored type into a class form and look it up
+ // on the router's namespace
+ className = Ember.String.classify(match[1]);
+ return get(namespace, className);
+ },
+
+ deserialize: function(manager, params) {
+ var modelClass, routeMatcher, param;
+
+ if (modelClass = this.modelClassFor(manager)) {
+ return modelClass.find(params[paramForClass(modelClass)]);
+ }
+
+ return params;
},
serialize: function(manager, context) {
+ var modelClass, routeMatcher, namespace, param, id;
+
+ if (modelClass = this.modelClassFor(manager)) {
+ param = paramForClass(modelClass);
+ id = get(context, 'id');
+ context = {};
+ context[param] = id;
+ }
+
return context;
},
View
2  packages/ember-states/lib/state.js
@@ -88,7 +88,7 @@ Ember.State = Ember.Object.extend(Ember.Evented, {
return !get(this, 'childStates').length;
}).cacheable(),
- setupControllers: Ember.K,
+ connectOutlets: Ember.K,
enter: Ember.K,
exit: Ember.K
});
View
5 packages/ember-states/lib/state_manager.js
@@ -448,7 +448,7 @@ Ember.StateManager = Ember.State.extend(
// 1. Normalize arguments
// 2. Ensure that we are in the correct state
// 3. Map provided path to context objects and send
- // appropriate setupControllers events
+ // appropriate connectOutlets events
if (Ember.empty(name)) { return; }
@@ -527,9 +527,8 @@ Ember.StateManager = Ember.State.extend(
state = this.findStatesByRoute(state, path);
state = state[state.length-1];
- state.fire('setupControllers', this, context);
+ state.fire('connectOutlets', this, context);
}, this);
- //getPath(root, path).setupControllers(this, context);
},
getState: function(name) {
View
130 packages/ember-states/tests/routable_test.js
@@ -229,7 +229,7 @@ module("Routing Serialization and Deserialization", {
show: Ember.State.create({
route: "/:post_id",
- setupControllers: function(manager, context) {
+ connectOutlets: function(manager, context) {
equal(context.post.id, 2, "should be the same value regardless of entry point");
},
@@ -277,3 +277,131 @@ test("should invoke the serialize method on a state when it is entered programma
equal(setURL, '/posts/2');
});
+var url, firstPost, firstUser;
+
+module("default serialize and deserialize with modelType", {
+ setup: function() {
+ window.TestApp = Ember.Namespace.create();
+ window.TestApp.Post = Ember.Object.extend();
+ window.TestApp.Post.find = function(id) {
+ if (id === "1") { return firstPost; }
+ };
+
+ window.TestApp.User = Ember.Object.extend();
+ window.TestApp.User.find = function(id) {
+ if (id === "1") { return firstUser; }
+ };
+
+ firstPost = window.TestApp.Post.create({ id: 1 });
+ firstUser = window.TestApp.User.create({ id: 1 });
+
+ router = Ember.Router.create({
+ location: {
+ setURL: function(passedURL) {
+ url = passedURL;
+ }
+ },
+
+ initialState: 'root',
+ root: Ember.State.extend({
+ post: Ember.State.extend({
+ route: '/posts/:post_id',
+ modelType: 'TestApp.Post',
+
+ connectOutlets: function(router, post) {
+ equal(post, firstPost, "the post should have deserialized correctly");
+ }
+ }),
+
+ user: Ember.State.extend({
+ route: '/users/:user_id',
+ modelType: window.TestApp.User,
+
+ connectOutlets: function(router, user) {
+ equal(user, firstUser, "the post should have deserialized correctly");
+ }
+ })
+ })
+ });
+ },
+
+ teardown: function() {
+ window.TestApp = undefined;
+ }
+});
+
+test("should use a specified String `modelType` in the default `serialize`", function() {
+ router.transitionTo('post', firstPost);
+ equal(url, "/posts/1");
+});
+
+test("should use a specified String `modelType` in the default `deserialize`", function() {
+ expect(1);
+
+ router.route("/posts/1");
+});
+
+test("should use a specified class `modelType` in the default `serialize`", function() {
+ router.transitionTo('user', firstUser);
+ equal(url, "/users/1");
+});
+
+test("should use a specified class `modelType` in the default `deserialize`", function() {
+ expect(1);
+
+ router.route("/users/1");
+});
+
+module("default serialize and deserialize without modelType", {
+ setup: function() {
+ window.TestApp = Ember.Namespace.create();
+ window.TestApp.Post = Ember.Object.extend();
+ window.TestApp.Post.find = function(id) {
+ if (id === "1") { return firstPost; }
+ };
+
+ window.TestApp.User = Ember.Object.extend();
+ window.TestApp.User.find = function(id) {
+ if (id === "1") { return firstUser; }
+ };
+
+ firstPost = window.TestApp.Post.create({ id: 1 });
+ firstUser = window.TestApp.User.create({ id: 1 });
+
+ router = Ember.Router.create({
+ namespace: window.TestApp,
+
+ location: {
+ setURL: function(passedURL) {
+ url = passedURL;
+ }
+ },
+
+ initialState: 'root',
+ root: Ember.State.extend({
+ post: Ember.State.extend({
+ route: '/posts/:post_id',
+
+ connectOutlets: function(router, post) {
+ equal(post, firstPost, "the post should have deserialized correctly");
+ }
+ })
+ })
+ });
+ },
+
+ teardown: function() {
+ window.TestApp = undefined;
+ }
+});
+
+test("should use a specified String `modelType` in the default `serialize`", function() {
+ router.transitionTo('post', firstPost);
+ equal(url, "/posts/1");
+});
+
+test("should use a specified String `modelType` in the default `deserialize`", function() {
+ expect(1);
+
+ router.route("/posts/1");
+});
View
18 packages/ember-states/tests/state_manager_test.js
@@ -456,7 +456,7 @@ test("goToState with current state does not trigger enter or exit", function() {
module("Transition contexts");
-test("if a context is passed to a transition, the state's setupControllers event is triggered after the transition has completed", function() {
+test("if a context is passed to a transition, the state's connectOutlets event is triggered after the transition has completed", function() {
expect(1);
var context = {};
@@ -469,7 +469,7 @@ test("if a context is passed to a transition, the state's setupControllers event
}),
next: Ember.State.create({
- setupControllers: function(manager, passedContext) {
+ connectOutlets: function(manager, passedContext) {
equal(context, passedContext, "The context is passed through");
}
})
@@ -479,7 +479,7 @@ test("if a context is passed to a transition, the state's setupControllers event
stateManager.send('goNext', context);
});
-test("if a context is passed to a transition and the path is to the current state, the state's setupControllers event is triggered again", function() {
+test("if a context is passed to a transition and the path is to the current state, the state's connectOutlets event is triggered again", function() {
expect(2);
var counter = 0;
@@ -499,7 +499,7 @@ test("if a context is passed to a transition and the path is to the current stat
manager.goToState('next', counter);
},
- setupControllers: function(manager, context) {
+ connectOutlets: function(manager, context) {
equal(context, counter, "The context is passed through");
}
})
@@ -511,7 +511,7 @@ test("if a context is passed to a transition and the path is to the current stat
stateManager.send('goNext', counter);
});
-test("if no context is provided, setupControllers is triggered with an undefined context", function() {
+test("if no context is provided, connectOutlets is triggered with an undefined context", function() {
expect(2);
Ember.run(function() {
@@ -528,8 +528,8 @@ test("if no context is provided, setupControllers is triggered with an undefined
manager.transitionTo('next');
},
- setupControllers: function(manager, context) {
- equal(context, undefined, "setupControllers is called with no context");
+ connectOutlets: function(manager, context) {
+ equal(context, undefined, "connectOutlets is called with no context");
}
})
})
@@ -552,12 +552,12 @@ test("multiple contexts can be provided in a single transitionTo", function() {
}),
planters: Ember.State.create({
- setupControllers: function(manager, context) {
+ connectOutlets: function(manager, context) {
deepEqual(context, { company: true });
},
nuts: Ember.State.create({
- setupControllers: function(manager, context) {
+ connectOutlets: function(manager, context) {
deepEqual(context, { product: true });
}
})
View
1  packages/ember-views/lib/system.js
@@ -8,3 +8,4 @@
require("ember-views/system/render_buffer");
require("ember-views/system/event_dispatcher");
require("ember-views/system/ext");
+require("ember-views/system/controller");
View
106 packages/ember-views/lib/system/controller.js
@@ -0,0 +1,106 @@
+var get = Ember.get, set = Ember.set;
+
+Ember.ControllerMixin.reopen({
+ /**
+ `connectOutlet` creates a new instance of a provided view
+ class, wires it up to its associated controller, and
+ assigns the new view to a property on the current controller.
+
+ The purpose of this method is to enable views that use
+ outlets to quickly assign new views for a given outlet.
+
+ For example, an application view's template may look like
+ this:
+
+ <h1>My Blog</h1>
+ {{outlet}}
+
+ The view for this outlet is specified by assigning a
+ `view` property to the application's controller. The
+ following code will assign a new `App.PostsView` to
+ that outlet:
+
+ applicationController.connectOutlet(App.PostsView);
+
+ You can specify a particular outlet to use as the first
+ parameter to `connectOutlet`. For example, if your
+ main template looks like:
+
+ <h1>My Blog</h1>
+ {{outlet master}}
+ {{outlet detail}}
+
+ You can assign an `App.PostsView` to the master outlet:
+
+ applicationController.connectOutlet('master', App.PostsView);
+
+ In general, you will also want to assign a controller
+ to the newly created view. By convention, a controller
+ named `postsController` will be assigned as the view's
+ controller.
+
+ In an application initialized using `app.initialize(router)`,
+ `connectOutlet` will look for `postsController` on the
+ router. The initialization process will automatically
+ create an instance of `App.PostsController` called
+ `postsController`, so you don't need to do anything
+ beyond `connectOutlet` to assign your view and wire it
+ up to its associated controller.
+
+ You can supply a `content` for the controller by supplying
+ a final argument after the view class:
+
+ applicationController.connectOutlet(App.PostsView, App.Post.find());
+
+ The only required argument is `viewClass`. You can optionally
+ specify an `outletName` before `viewClass` and/or a `context`
+ after `viewClass` in any combination.
+
+ @param {String} outletName the name of the outlet to assign
+ the newly created view to (optional)
+ @param {Class} viewClass a view class to instantiate
+ @param {Object} context a context object to assign to the
+ controller's `content` property, if a controller can be
+ found.
+ */
+ connectOutlet: function(outletName, viewClass, context) {
+ // Normalize arguments. Supported arguments:
+ //
+ // viewClass
+ // outletName, viewClass
+ // viewClass, context
+ // outletName, viewClass, context
+ if (arguments.length === 2) {
+ if (Ember.Object.detect(outletName)) {
+ context = viewClass;
+ viewClass = outletName;
+ outletName = 'view';
+ }
+ } else if (arguments.length === 1) {
+ viewClass = outletName;
+ outletName = 'view';
+ }
+
+ var parts = viewClass.toString().split("."),
+ last = parts[parts.length - 1],
+ match = last.match(/^(.*)View$/);
+
+ Ember.assert("The parameter you pass to connectOutlet must be a class ending with View", !!match);
+
+ var bareName = match[1], controllerName;
+ bareName = bareName.charAt(0).toLowerCase() + bareName.substr(1);
+
+ controllerName = bareName + "Controller";
+
+ var controller = get(get(this, 'controllers'), controllerName);
+
+ Ember.assert("You specified a context, but no " + controllerName + " was found", !context || !!controller);
+ if (context) { controller.set('content', context); }
+
+ var view = viewClass.create({ controller: controller });
+ set(this, outletName, view);
+
+ return view;
+ }
+});
+
View
80 packages/ember-views/tests/system/controller_test.js
@@ -0,0 +1,80 @@
+/*globals TestApp*/
+
+module("Ember.Controller#connectOutlet", {
+ setup: function() {
+ Ember.run(function () {
+ window.TestApp = Ember.Application.create();
+ });
+
+
+ TestApp.ApplicationController = Ember.Controller.extend();
+
+ TestApp.PostController = Ember.Controller.extend();
+ TestApp.PostView = Ember.Controller.extend();
+ },
+
+ teardown: function() {
+ Ember.run(function () {
+ window.TestApp.destroy();
+ });
+ window.TestApp = undefined;
+ }
+});
+
+test("connectOutlet instantiates a view, controller, and connects them", function() {
+ var postController = Ember.Controller.create();
+
+ var appController = TestApp.ApplicationController.create({
+ controllers: { postController: postController }
+ });
+ var view = appController.connectOutlet(TestApp.PostView);
+
+ ok(view instanceof TestApp.PostView, "the view is an instance of PostView");
+ equal(view.get('controller'), postController, "the controller is looked up on the parent's controllers hash");
+ equal(appController.get('view'), view, "the app controller's view is set");
+});
+
+test("connectOutlet takes an optional outlet name", function() {
+ var postController = Ember.Controller.create();
+
+ var appController = TestApp.ApplicationController.create({
+ controllers: { postController: postController }
+ });
+ var view = appController.connectOutlet('mainView', TestApp.PostView);
+
+ ok(view instanceof TestApp.PostView, "the view is an instance of PostView");
+ equal(view.get('controller'), postController, "the controller is looked up on the parent's controllers hash");
+ equal(appController.get('mainView'), view, "the app controller's view is set");
+});
+
+test("connectOutlet takes an optional controller context", function() {
+ var postController = Ember.Controller.create(),
+ context = {};
+
+ var appController = TestApp.ApplicationController.create({
+ controllers: { postController: postController }
+ });
+ var view = appController.connectOutlet(TestApp.PostView, context);
+
+ ok(view instanceof TestApp.PostView, "the view is an instance of PostView");
+ equal(view.get('controller'), postController, "the controller is looked up on the parent's controllers hash");
+ equal(appController.get('view'), view, "the app controller's view is set");
+ equal(view.getPath('controller.content'), context, "the controller receives the context");
+});
+
+test("connectOutlet works if all three parameters are provided", function() {
+ var postController = Ember.Controller.create(),
+ context = {};
+
+ var appController = TestApp.ApplicationController.create({
+ controllers: { postController: postController }
+ });
+ var view = appController.connectOutlet('mainView', TestApp.PostView, context);
+
+ ok(view instanceof TestApp.PostView, "the view is an instance of PostView");
+ equal(view.get('controller'), postController, "the controller is looked up on the parent's controllers hash");
+ equal(appController.get('mainView'), view, "the app controller's view is set");
+ equal(view.getPath('controller.content'), context, "the controller receives the context");
+});
+
+

1 comment on commit b71cae7

Please sign in to comment.
Something went wrong with that request. Please try again.