Repository: ember-cli/ember-cli
Pull request #6103 (2016-07-25 05:01:53)

store add-on initialization/lookup times
This will enable further logging/instrumenting/warnings

Turbo87: @stefanpenner can you fix the ESLint issues?

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b5b27b197..9762e8b39 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,70 +1,5 @@
 # ember-cli Changelog
 
-### 2.8.0-beta.1
-
-The following changes are required if you are upgrading from the previous
-version:
-
-- Users
-  + [`ember new` diff](https://github.com/ember-cli/ember-new-output/compare/v2.7.0...v2.8.0-beta.1)
-  + Upgrade your project's ember-cli version - [docs](http://ember-cli.com/user-guide/#upgrading)
-- Addon Developers
-  + [`ember addon` diff](https://github.com/ember-cli/ember-addon-output/compare/v2.7.0...v2.8.0-beta.1)
-  + No changes required
-- Core Contributors
-  + No changes required
-
-#### Community Contributions
-
-- [#6050](https://github.com/ember-cli/ember-cli/pull/6050) Make app/addon readmes consistent [@elwayman02](https://github.com/elwayman02)
-- [#6005](https://github.com/ember-cli/ember-cli/pull/6005) [BUGFIX] Fixes broccoli errors when `tests` dir is not present [@twokul](https://github.com/twokul)
-- [#5986](https://github.com/ember-cli/ember-cli/pull/5986) added transparent-proxy option to ember serve command [@badazz91](https://github.com/badazz91)
-- [#6012](https://github.com/ember-cli/ember-cli/pull/6012) switch to a rollup subset of lodash and shave off 20 - 30%+ boot time [@stefanpenner](https://github.com/stefanpenner)
-- [#6017](https://github.com/ember-cli/ember-cli/pull/6017) Allow `ember install addon_name --save` in addons. [@xcambar](https://github.com/xcambar)
-- [#6030](https://github.com/ember-cli/ember-cli/pull/6030) [ENHANCEMENT] Asset Sizes I moved the creation of asset sizes to an object. [@kiwiupover](https://github.com/kiwiupover)
-- [#6052](https://github.com/ember-cli/ember-cli/pull/6052) Turn on strict mode for tests. [@nathanhammond](https://github.com/nathanhammond)
-- [#6043](https://github.com/ember-cli/ember-cli/pull/6043) [BUGFIX beta] Test nested addon import [@xcambar](https://github.com/xcambar)
-- [#6045](https://github.com/ember-cli/ember-cli/pull/6045) [Enhancement] Return raw asset-size as data instead of strings [@kiwiupover](https://github.com/kiwiupover)
-- [#6072](https://github.com/ember-cli/ember-cli/pull/6072) Makes sure dependecies are loaded on demand [@twokul](https://github.com/twokul)
-- [#6092](https://github.com/ember-cli/ember-cli/pull/6092) Remove ember-qunit-notifications [@trentmwillis](https://github.com/trentmwillis)
-- [#6094](https://github.com/ember-cli/ember-cli/pull/6094) Remove jQuery usage to read meta config. [@rwjblue](https://github.com/rwjblue)
-- [#6095](https://github.com/ember-cli/ember-cli/pull/6095) [INTERNAL] Remove unused 'es3Safe' option [@ursm](https://github.com/ursm)
-- [#6102](https://github.com/ember-cli/ember-cli/pull/6102) Refactor/cleanup/reduce slow tests [@stefanpenner](https://github.com/stefanpenner)
-- [#6112](https://github.com/ember-cli/ember-cli/pull/6112) More specific docs for included hook [@xcambar](https://github.com/xcambar)
-
-Thank you to all who took the time to contribute!
-
-
-### 2.7.0
-
-The following changes are required if you are upgrading from the previous
-version:
-
-- Users
-  + [`ember new` diff](https://github.com/ember-cli/ember-new-output/compare/v2.6.3...v2.7.0)
-  + Upgrade your project's ember-cli version - [docs](http://ember-cli.com/user-guide/#upgrading)
-- Addon Developers
-  + [`ember addon` diff](https://github.com/ember-cli/ember-addon-output/compare/v2.6.3...v2.7.0)
-- Core Contributors
-  + No changes required
-
-#### Community Contributions
-
-- [#5972](https://github.com/ember-cli/ember-cli/pull/5972) [BUGFIX release] ease core-object upgrade for addons which lack .project [@stefanpenner](https://github.com/stefanpenner)
-- [#5877](https://github.com/ember-cli/ember-cli/pull/5877) Uniform import API [@ef4](https://github.com/ef4)
-- [#5979](https://github.com/ember-cli/ember-cli/pull/5979) Use `ember try:one` in travis [@san650](https://github.com/san650)
-- [#5984](https://github.com/ember-cli/ember-cli/pull/5984) Replace "stub" helper with "testdouble" [@Turbo87](https://github.com/Turbo87)
-- [#5985](https://github.com/ember-cli/ember-cli/pull/5985) Use blueprint test helpers [@Turbo87](https://github.com/Turbo87)
-- [#5792](https://github.com/ember-cli/ember-cli/pull/5792) Add "rootURL" setting to deprecate "baseURL" [@Turbo87](https://github.com/Turbo87)
-- [#5997](https://github.com/ember-cli/ember-cli/pull/5997) Prints correct phantomjs version [@twokul](https://github.com/twokul)
-- [#6043](https://github.com/ember-cli/ember-cli/pull/6043) Test nested addon import [@xcambar](https://github.com/xcambar)
-- [#6072](https://github.com/ember-cli/ember-cli/pull/6072) Makes sure dependecies are loaded on demand [@twokul](https://github.com/twokul)
-- [#6105](https://github.com/ember-cli/ember-cli/pull/6105) Update Ember Data to v2.7.0 [@bmac](https://github.com/bmac)
-- [#6106](https://github.com/ember-cli/ember-cli/pull/6106) Update Ember to 2.7.0 [@rwjblue](https://github.com/rwjblue)
-
-Thank you to all who took the time to contribute!
-
-
 ### 2.7.0-beta.6
 
 The following changes are required if you are upgrading from the previous
@@ -216,27 +151,6 @@ version:
 Thank you to all who took the time to contribute!
 
 
-### 2.6.3
-
-The following changes are required if you are upgrading from the previous
-version:
-
-- Users
-  + [`ember new` diff](https://github.com/ember-cli/ember-new-output/compare/v2.6.2...v2.6.3)
-  + Upgrade your project's ember-cli version - [docs](http://ember-cli.com/user-guide/#upgrading)
-- Addon Developers
-  + [`ember addon` diff](https://github.com/ember-cli/ember-addon-output/compare/v2.6.2...v2.6.3)
-  + Upgrade your project's ember-cli version - [docs](http://ember-cli.com/user-guide/#upgrading)
-- Core Contributors
-  + No changes required
-
-#### Community Contributions
-
-- [#6068](https://github.com/ember-cli/ember-cli/pull/6068) Allow more then 10 exit handlers [@nathanhammond](https://github.com/nathanhammond)
-
-Thank you to all who took the time to contribute!
-
-
 ### 2.6.2
 
 The following changes are required if you are upgrading from the previous
diff --git a/blueprints/app/files/bower.json b/blueprints/app/files/bower.json
index 91e41e95b..3f9cf018f 100644
--- a/blueprints/app/files/bower.json
+++ b/blueprints/app/files/bower.json
@@ -1,7 +1,7 @@
 {
   "name": "<%= name %>",
   "dependencies": {
-    "ember": "~2.8.0-beta.1",
+    "ember": "~2.7.0-beta.4",
     "ember-cli-shims": "0.1.1"
   }
 }
diff --git a/blueprints/app/files/package.json b/blueprints/app/files/package.json
index 075bb51f6..5088a6e89 100644
--- a/blueprints/app/files/package.json
+++ b/blueprints/app/files/package.json
@@ -34,7 +34,7 @@
     "ember-cli-sri": "^2.1.0",
     "ember-cli-test-loader": "^1.1.0",
     "ember-cli-uglify": "^1.2.0",
-    "ember-data": "^2.8.0-beta.1",
+    "ember-data": "^2.7.0-beta.3",
     "ember-export-application-global": "^1.0.5",
     "ember-load-initializers": "^0.5.1",
     "ember-resolver": "^2.0.3",
diff --git a/blueprints/in-repo-addon/index.js b/blueprints/in-repo-addon/index.js
index d26aadf93..2dc4f5e8f 100755
--- a/blueprints/in-repo-addon/index.js
+++ b/blueprints/in-repo-addon/index.js
@@ -30,28 +30,6 @@ module.exports = {
       paths.push(newPath);
     }
 
-    fs.writeFileSync(packagePath, JSON.stringify(contents, null, 2));
-  },
-
-  afterUninstall: function(options) {
-    var packagePath = path.join(this.project.root, 'package.json');
-    var contents    = fs.readJsonSync(packagePath);
-    var name        = stringUtil.dasherize(options.entity.name);
-    var newPath     = ['lib', name].join('/');
-    var paths;
-    var newPathIndex;
-
-    contents['ember-addon'] = contents['ember-addon'] || {};
-    paths = contents['ember-addon']['paths'] = contents['ember-addon']['paths'] || [];
-    newPathIndex = paths.indexOf(newPath);
-
-    if (newPathIndex > -1) {
-      paths.splice(newPathIndex, 1);
-      if (paths.length === 0) {
-        delete contents['ember-addon']['paths'];
-      }
-    }
-
     fs.writeFileSync(packagePath, JSON.stringify(contents, null, 2));
   }
 };
diff --git a/dev/add-to-output-repos.sh b/dev/add-to-output-repos.sh
index efb328b9f..7e1383f49 100755
--- a/dev/add-to-output-repos.sh
+++ b/dev/add-to-output-repos.sh
@@ -25,7 +25,7 @@ for i in ${commands[@]}; do
   git clone https://github.com/ember-cli/$repo_folder.git --branch $branch
   pushd $repo_folder
   git rm -rf .
-  ember $command $local_folder -sb -sn -sg
+  ember new $local_folder -sb -sn -sg
   cp -r $local_folder/ .
   rm -r $local_folder
 
diff --git a/lib/models/addon.js b/lib/models/addon.js
index 7f76397d6..c903cdd65 100644
--- a/lib/models/addon.js
+++ b/lib/models/addon.js
@@ -383,6 +383,7 @@ var Addon = CoreObject.extend({
 
     @private
     @method _findHost
+    ```
   */
   _findHost: function() {
     var app = this.app;
@@ -411,16 +412,16 @@ var Addon = CoreObject.extend({
 
     @public
     @method included
-    @param {EmberApp|EmberAddon} parent The parent object which included this addon
+    @param {EmberApp} app The application object
 
     @example
     ```js
-    included: function(parent) {
+    included: function() {
       this.import(somePath);
     }
     ```
   */
-  included: function(/* parent */) {
+  included: function(/* app */) {
     if (!this._addonsInitialized) {
       // someone called `this._super.included` without `apply` (because of older
       // core-object issues that prevent a "real" super call from working properly)
@@ -990,6 +991,7 @@ Addon.resolvePath = function(addon) {
 */
 Addon.lookup = function(addon) {
   var Constructor, addonModule, modulePath, moduleDir;
+  var start = Date.now();
 
   modulePath = Addon.resolvePath(addon);
   moduleDir  = path.dirname(modulePath);
@@ -1013,6 +1015,14 @@ Addon.lookup = function(addon) {
     throw new SilentError('The `' + addon.pkg.name + '` addon could not be found at `' + addon.path + '`.');
   }
 
+  var lookupDuration = Date.now() - start;
+
+  Constructor._meta_ = {
+    modulePath: modulePath,
+    lookupDuration: lookupDuration,
+    initializeIn: 0
+  };
+
   return Constructor;
 };
 
diff --git a/lib/models/addons-factory.js b/lib/models/addons-factory.js
index bdd117ef4..058696df5 100644
--- a/lib/models/addons-factory.js
+++ b/lib/models/addons-factory.js
@@ -44,6 +44,7 @@ var AddonsFactory = CoreObject.extend({
     graph.topsort(function (vertex) {
       var addonInfo = vertex.value;
       if (addonInfo) {
+        var start = Date.now();
         var AddonConstructor = Addon.lookup(addonInfo);
         var addon = new AddonConstructor(addonParent, project);
         if (addon.initializeAddons) {
@@ -51,12 +52,20 @@ var AddonsFactory = CoreObject.extend({
         } else {
           addon.addons = [];
         }
+        AddonConstructor._meta_.initializeIn = Date.now() - start;
+        addon.constructor = AddonConstructor;
         addons.push(addon);
       }
     });
 
-    debug(' addons ordered as:', addons.map(function(addon) {
-      return addon.name;
+    debug(' addon info %o', addons.map(function(addon) {
+      return {
+        name: addon.name,
+        times: {
+          initialize: addon.constructor._meta_.initializeIn,
+          lookup: addon.constructor._meta_.lookupIn,
+        }
+      };
     }));
 
     return addons;
diff --git a/lib/models/server-watcher.js b/lib/models/server-watcher.js
index 78803869a..950df972e 100644
--- a/lib/models/server-watcher.js
+++ b/lib/models/server-watcher.js
@@ -1,48 +1,62 @@
 'use strict';
 
-var Watcher = require('./watcher');
+var Task    = require('./task');
 
-var ServerWatcher = Watcher.extend({
-  constructWatcher: function(options) {
-    return new (require('sane'))(this.watchedDir, options);
-  },
+module.exports = Task.extend({
+  verbose: true,
 
   init: function() {
-    this._super.init.apply(this, arguments);
+    this._super.apply(this, arguments);
+    this.watcher = this.watcher || new (require('sane'))(this.watchedDir, {
+      verbose: this.verbose,
+      poll: this.polling()
+    });
 
+    this.watcher.on('change', this.didChange.bind(this));
     this.watcher.on('add',    this.didAdd.bind(this));
     this.watcher.on('delete', this.didDelete.bind(this));
   },
 
-  didChange: function(relativePath) {
-    var description = 'File changed: "' + relativePath + '"';
+  didChange: function (filepath) {
+    this.ui.writeLine('Server file changed: ' + filepath);
 
-    this.ui.writeLine(description);
     this.analytics.track({
-      name: 'server file changed',
-      description: description
+      name: 'server file change',
+      description: 'File changed: "' + filepath + '"'
     });
   },
 
-  didAdd: function (relativePath) {
-    var description = 'File added: "' + relativePath + '"';
+  didAdd: function (filepath) {
+    this.ui.writeLine('Server file added: ' + filepath);
 
-    this.ui.writeLine(description);
     this.analytics.track({
       name: 'server file addition',
-      description: description
+      description: 'File added: "' + filepath + '"'
     });
   },
 
-  didDelete: function (relativePath) {
-    var description = 'File deleted: "' + relativePath + '"';
+  didDelete: function (filepath) {
+    this.ui.writeLine('Server file deleted: ' + filepath);
 
-    this.ui.writeLine(description);
     this.analytics.track({
       name: 'server file deletion',
-      description: description
+      description: 'File deleted: "' + filepath + '"'
     });
   },
-});
 
-module.exports = ServerWatcher;
+  then: function() {
+    return this.watcher.then.apply(this.watcher, arguments);
+  },
+
+  on: function() {
+    this.watcher.on.apply(this.watcher, arguments);
+  },
+
+  off: function() {
+    this.watcher.off.apply(this.watcher, arguments);
+  },
+
+  polling: function () {
+    return this.options && this.options.watcher === 'polling';
+  }
+});
diff --git a/lib/models/watcher.js b/lib/models/watcher.js
index 9fcf02acd..ab110bc2d 100644
--- a/lib/models/watcher.js
+++ b/lib/models/watcher.js
@@ -12,21 +12,16 @@ var Watcher = Task.extend({
 
   init: function() {
     this._super.apply(this, arguments);
-
     var options = this.buildOptions();
 
     debug('initialize %o', options);
 
-    this.watcher = this.watcher || this.constructWatcher(options);
+    this.watcher = this.watcher || new (require('broccoli-sane-watcher'))(this.builder, options);
 
     this.watcher.on('error', this.didError.bind(this));
     this.watcher.on('change', this.didChange.bind(this));
   },
 
-  constructWatcher: function(options) {
-    return new (require('broccoli-sane-watcher'))(this.builder, options);
-  },
-
   didError: function(error) {
     debug('didError %o', error);
     this.ui.writeError(error);
@@ -66,7 +61,6 @@ var Watcher = Task.extend({
   off: function() {
     this.watcher.off.apply(this.watcher, arguments);
   },
-
   buildOptions: function() {
     var watcher = this.options && this.options.watcher;
 
diff --git a/lib/tasks/serve.js b/lib/tasks/serve.js
index e634cb7db..ce0d4ac08 100644
--- a/lib/tasks/serve.js
+++ b/lib/tasks/serve.js
@@ -7,8 +7,8 @@ var ExpressServer    = require('./server/express-server');
 var Promise          = require('../ext/promise');
 var Task             = require('../models/task');
 var Watcher          = require('../models/watcher');
-var ServerWatcher    = require('../models/server-watcher');
 var Builder          = require('../models/builder');
+var ServerWatcher    = require('../models/server-watcher');
 
 module.exports = Task.extend({
   run: function(options) {
@@ -32,8 +32,7 @@ module.exports = Task.extend({
       serverWatcher = new ServerWatcher({
         ui: this.ui,
         analytics: this.analytics,
-        watchedDir: path.resolve(serverRoot),
-        options: options
+        watchedDir: path.resolve(serverRoot)
       });
     }
 
diff --git a/package.json b/package.json
index 60401c5d0..1846aeb8a 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "ember-cli",
-  "version": "2.8.0-beta.1",
+  "version": "2.7.0-beta.6",
   "main": "lib/cli/index.js",
   "description": "Command line tool for developing ambitious ember.js apps",
   "homepage": "http://ember-cli.com/",
@@ -88,7 +88,7 @@
     "is-git-url": "^0.2.0",
     "isbinaryfile": "^3.0.0",
     "leek": "0.0.22",
-    "lodash": "^4.14.1",
+    "lodash": "^4.12.0",
     "markdown-it": "7.0.0",
     "lodash.template": "^4.2.5",
     "markdown-it-terminal": "0.0.3",
@@ -114,7 +114,7 @@
     "through": "^2.3.6",
     "tiny-lr": "0.2.1",
     "tree-sync": "^1.1.0",
-    "walk-sync": "^0.3.0",
+    "walk-sync": "^0.2.6",
     "yam": "0.0.21"
   },
   "devDependencies": {
@@ -126,7 +126,7 @@
     "ember-cli-blueprint-test-helpers": "^0.13.0",
     "ember-cli-internal-test-helpers": "^0.8.1",
     "eslint-plugin-chai-expect": "^1.1.1",
-    "github": "^2.4.0",
+    "github": "^2.0.0",
     "istanbul": "^0.4.2",
     "mocha": "^2.4.5",
     "mocha-eslint": "^2.0.1",
@@ -134,7 +134,7 @@
     "multiline": "^1.0.2",
     "nock": "^8.0.0",
     "proxyquire": "^1.7.7",
-    "supertest": "^2.0.0",
+    "supertest": "^1.2.0",
     "testdouble": "^1.3.0",
     "yuidocjs": "0.10.2",
     "yuidoc-ember-cli-theme": "^1.0.0"


Test patch:
diff --git a/lib/commands/test.js b/lib/commands/test.js
index 8cc84297c..5d1ce17ca 100644
--- a/lib/commands/test.js
+++ b/lib/commands/test.js
@@ -154,7 +154,6 @@ module.exports = Command.extend({
         var TestTask = this.tasks.Test;
         var test     = new TestTask(options);
 
-
         if (hasBuild) {
           session = test.run(testOptions);
         } else {
@@ -167,7 +166,7 @@ module.exports = Command.extend({
           })
           .then(function() {
             return test.run(testOptions);
-          });
+          })
         }
       }
 
diff --git a/tests/acceptance/addon-smoke-test-slow.js b/tests/acceptance/addon-smoke-test-slow.js
index 90b47969e..03c2783d0 100644
--- a/tests/acceptance/addon-smoke-test-slow.js
+++ b/tests/acceptance/addon-smoke-test-slow.js
@@ -22,8 +22,7 @@ var chai = require('../chai');
 var expect = chai.expect;
 var dir = chai.dir;
 
-var addonName = 'some-cool-addon';
-var addonRoot = path.resolve(__dirname + '/../../tmp/' + addonName) + '/';
+var addonName  = 'some-cool-addon';
 
 describe('Acceptance: addon-smoke-test', function() {
   this.timeout(450000);
@@ -43,8 +42,6 @@ describe('Acceptance: addon-smoke-test', function() {
   });
 
   afterEach(function() {
-    fs.remove(addonRoot + 'node_modules/developing-addon');
-
     return cleanupRun(addonName).then(function() {
       expect(dir('tmp/' + addonName)).to.not.exist;
     });
@@ -67,47 +64,137 @@ describe('Acceptance: addon-smoke-test', function() {
     return ember(['test']);
   });
 
-  it('works in most common scenarios for an example addon', function() {
-    return copyFixtureFiles('addon/kitchen-sink').then(function() {
-      var packageJsonPath = addonRoot + 'package.json'
-      var packageJson = fs.readJsonSync(packageJsonPath);
+  it('ember addon without addon/ directory', function() {
+    return remove('addon')
+      .then(function() {
+        return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'server', '--port=54323','--live-reload=false', {
+          onOutput: function(string, child) {
+            if (string.match(/Build successful/)) {
+              killCliProcess(child);
+            }
+          }
+        })
+        .catch(function() {
+          // just eat the rejection as we are testing what happens
+        });
+      });
+  });
 
-      packageJson.dependencies = packageJson.dependencies || {};
-      // add HTMLBars for templates (generators do this automatically when components/templates are added)
-      packageJson.dependencies['ember-cli-htmlbars'] = 'latest';
+  it('can render a component with a manually imported template', function() {
+    return copyFixtureFiles('addon/component-with-template')
+      .then(function() {
+        var packageJsonPath = path.join(__dirname, '..', '..', 'tmp', addonName, 'package.json');
+        var packageJson = fs.readJsonSync(packageJsonPath);
+        packageJson.dependencies = packageJson.dependencies || {};
+        packageJson.dependencies['ember-cli-htmlbars'] = 'latest';
 
-      // build with addon deps being developed
-      packageJson.dependencies['developing-addon'] = 'latest';
+        return fs.writeJsonSync(packageJsonPath, packageJson);
+      })
+      .then(function() {
+        return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'test');
+      });
+  });
 
-      fs.writeJsonSync(packageJsonPath, packageJson)
+  it('can add things to `{{content-for "head"}}` section', function() {
+    return copyFixtureFiles('addon/content-for-head')
+      .then(function() {
+        return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'build');
+      })
+      .then(function() {
+        var indexPath = path.join('dist', 'index.html');
+        var contents = fs.readFileSync(indexPath, { encoding: 'utf8' });
 
-      symlinkOrCopySync(path.resolve('../../tests/fixtures/addon/developing-addon'), addonRoot + 'node_modules/developing-addon');
+        expect(contents).to.contain('"SOME AWESOME STUFF"');
+      });
+  });
 
-      return runCommand('node_modules/ember-cli/bin/ember', 'build').then(function(result) {
-        expect(result.code).to.eql(0);
-        var contents;
+  it('build with only pod templates', function() {
+    return copyFixtureFiles('addon/pod-templates-only')
+      .then(function() {
+        var packageJsonPath = path.join(__dirname, '..', '..', 'tmp', addonName, 'package.json');
+        var packageJson = fs.readJsonSync(packageJsonPath);
+        packageJson.dependencies = packageJson.dependencies || {};
+        packageJson.dependencies['ember-cli-htmlbars'] = 'latest';
 
-        contents = fs.readFileSync(addonRoot + 'dist/index.html', { encoding: 'utf8' });
-        expect(contents).to.contain('"SOME AWESOME STUFF"');
+        return fs.writeJsonSync(packageJsonPath, packageJson);
+      }).then(function() {
+        return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'build');
+      })
+      .then(function() {
+        var indexPath = path.join('dist', 'assets', 'vendor.js');
+        var contents = fs.readFileSync(indexPath, { encoding: 'utf8' });
+        expect(contents).to.contain('MY-COMPONENT-TEMPLATE-CONTENT');
+      });
+  });
+
+  it('build with addon dependencies being developed', function() {
+    var packageJsonPath = path.join(__dirname, '..', '..', 'tmp', addonName, 'package.json');
+    var packageJson = fs.readJsonSync(packageJsonPath);
+    packageJson.dependencies = packageJson.dependencies || {};
+    packageJson.dependencies['ember-cli-htmlbars'] = 'latest';
+    packageJson.dependencies['developing-addon'] = 'latest';
+
+    fs.writeJsonSync(packageJsonPath, packageJson);
+
+    symlinkOrCopySync(path.resolve('../../tests/fixtures/addon/developing-addon'), path.resolve('../../tmp/', addonName, 'node_modules/developing-addon'));
+
+    return ember(['test'])
+      .then(function(result) {
+        expect(result.exitCode).to.eql(0);
+      });
+  });
 
-        var cssPath = 'dist/assets/vendor.css';
-        contents = fs.readFileSync(cssPath, { encoding: 'utf8' });
+  it('ember addon with addon/styles directory', function() {
+    return copyFixtureFiles('addon/with-styles')
+      .then(function() {
+        return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'build');
+      })
+      .then(function() {
+        var cssPath = path.join('dist', 'assets', 'vendor.css');
+        var contents = fs.readFileSync(cssPath, { encoding: 'utf8' });
 
         expect(contents).to.contain('addon/styles/app.css is present');
+      });
+  });
+
+  it('ember addon with addon-test-support directory', function() {
+    return copyFixtureFiles('addon/with-addon-test-support')
+      .then(function() {
+        return ember(['test']);
+      })
+      .then(function(result) {
+        expect(result.exitCode).to.eql(0);
+      });
+  });
 
-        var robotsPath = 'dist/robots.txt';
-        contents = fs.readFileSync(robotsPath, { encoding: 'utf8' });
+  it('ember addon with linting errors', function() {
+    return copyFixtureFiles('addon/with-linting-errors')
+      .then(function() {
+        return ember(['test']);
+      })
+      .then(function() {
+        expect(false, 'should have rejected with a failed linter').to.be.ok;
+      })
+      .catch(function(result) {
+        expect(result.exitCode).to.not.eql(0);
+      });
+  });
 
-        expect(contents).to.contain('tests/dummy/public/robots.txt is present');
+  it('ember addon with tests/dummy/public directory', function() {
+    return copyFixtureFiles('addon/with-dummy-public')
+      .then(function() {
+        return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'build');
+      })
+      .then(function() {
+        var robotsPath = path.join('dist', 'robots.txt');
+        var contents = fs.readFileSync(robotsPath, { encoding: 'utf8' });
 
-        return runCommand('node_modules/ember-cli/bin/ember', 'test').then(function(result) {
-          expect(result.code).to.eql(0);
-        });
+        expect(contents).to.contain('tests/dummy/public/robots.txt is present');
       });
-    });
   });
 
   it('npm pack does not include unnecessary files', function() {
+    console.log('    running the slow end-to-end it will take some time');
     var handleError = function(error, commandName) {
       if (error.code === 'ENOENT') {
         console.warn(chalk.yellow('      Your system does not provide ' + commandName + ' -> Skipped this test.'));
@@ -163,4 +250,41 @@ describe('Acceptance: addon-smoke-test', function() {
       handleError(error, 'npm');
     });
   });
+
+  function wait(time) {
+    return new Promise(function(resolve) {
+      setTimeout(function() {
+        resolve();
+      }, time);
+    });
+  }
+
+  var isWindows = /^win/.test(process.platform);
+
+  (isWindows ? it.skip : it)('doesn\'t fail to build new files', function() {
+    var testemOutput = '';
+    return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'test', '--launch=PhantomJS', '--server', {
+      onOutput: function(string) {
+        testemOutput += string;
+      },
+      onChildSpawned: function(child) {
+        return wait(12000).then(function() {
+
+          return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'generate', 'initializer', 'foo')
+          .then(function() {
+            return wait(5000);
+          })
+          .then(function() {
+            child.stdin.write('q'); // quit test server
+            child.stdin.end();
+            expect(testemOutput).to.contain('✔');
+            expect(testemOutput).to.not.contain('✘');
+          });
+
+        });
+
+      }
+    });
+
+  });
 });
diff --git a/tests/acceptance/brocfile-smoke-test-slow.js b/tests/acceptance/brocfile-smoke-test-slow.js
index 6821ce6a8..8ee2a87c1 100644
--- a/tests/acceptance/brocfile-smoke-test-slow.js
+++ b/tests/acceptance/brocfile-smoke-test-slow.js
@@ -149,6 +149,20 @@ describe('Acceptance: brocfile-smoke-test', function() {
       });
   });
 
+  it('default development build does not fail', function() {
+    return copyFixtureFiles('brocfile-tests/query')
+      .then(function() {
+        return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'build');
+      });
+  });
+
+  it('default development build tests', function() {
+    return copyFixtureFiles('brocfile-tests/default-development')
+    .then(function() {
+      return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'test');
+    });
+  });
+
   it('app.import works properly with test tree files', function() {
     return copyFixtureFiles('brocfile-tests/app-test-import')
       .then(function() {
@@ -191,6 +205,20 @@ describe('Acceptance: brocfile-smoke-test', function() {
       });
   });
 
+  it('app.import fails when options.type is not `vendor` or `test`', function() {
+    return expect(copyFixtureFiles('brocfile-tests/app-import')
+      .then(function() {
+        var packageJsonPath = path.join(__dirname, '..', '..', 'tmp', appName, 'package.json');
+        var packageJson = fs.readJsonSync(packageJsonPath);
+        packageJson.devDependencies['ember-bad-addon'] = 'latest';
+
+        return fs.writeJsonSync(packageJsonPath, packageJson);
+      })
+      .then(function() {
+        return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'build');
+      })).to.be.rejected;
+  });
+
   it('addons can have a public tree that is merged and returned namespaced by default', function() {
     return copyFixtureFiles('brocfile-tests/public-tree')
       .then(function() {
diff --git a/tests/acceptance/install-test-slow.js b/tests/acceptance/install-test-slow.js
index 3f6b8e4bb..40a872971 100644
--- a/tests/acceptance/install-test-slow.js
+++ b/tests/acceptance/install-test-slow.js
@@ -59,6 +59,7 @@ describe('Acceptance: ember install', function() {
         .to.match(/"ember-cli-photoswipe": ".*"/);
 
       expect(file('bower.json'))
+        .to.match(/"fastclick": ".*"/)
         .to.match(/"photoswipe": ".*"/);
 
       expect(result.outputStream.join()).not.to.include('The `ember generate` command ' +
diff --git a/tests/acceptance/smoke-test-slow.js b/tests/acceptance/smoke-test-slow.js
index 4fabd3b1a..a144ed726 100644
--- a/tests/acceptance/smoke-test-slow.js
+++ b/tests/acceptance/smoke-test-slow.js
@@ -82,6 +82,58 @@ describe('Acceptance: smoke-test', function() {
       });
   });
 
+  it('ember test exits with non-zero when tests fail', function() {
+    return copyFixtureFiles('smoke-tests/failing-test')
+      .then(function() {
+        return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'test')
+          .then(function() {
+            expect(false, 'should have rejected with a failing test').to.be.ok;
+          })
+          .catch(function(result) {
+            expect(result.code).to.equal(1);
+          });
+      });
+  });
+
+  it('ember test exits with non-zero when build fails', function() {
+    return copyFixtureFiles('smoke-tests/test-with-syntax-error')
+      .then(function() {
+        return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'test')
+          .then(function() {
+            expect(false, 'should have rejected with a failing test').to.be.ok;
+          })
+          .catch(function(result) {
+            expect(result.code).to.equal(1);
+          });
+      });
+  });
+
+  it('ember test exits with non-zero when no tests are run', function() {
+    return copyFixtureFiles('smoke-tests/no-testem-launchers')
+      .then(function() {
+        return runCommand(path.join('.', 'node_modules', 'ember-cli', 'bin', 'ember'), 'test')
+          .then(function() {
+            expect(false, 'should have rejected with a failing test').to.be.ok;
+          })
+          .catch(function(result) {
+            expect(result.code).to.equal(1);
+          });
+      });
+  });
+
+  it('ember test exits with zero when tests pass', function() {
+    return copyFixtureFiles('smoke-tests/passing-test')
+      .then(function() {
+        return ember(['test'])
+          .then(function(result) {
+            expect(result.exitCode).to.equal(0);
+          })
+          .catch(function() {
+            expect(false, 'should NOT have rejected with a failing test').to.be.ok;
+          });
+      });
+  });
+
   it('ember test still runs when only a JavaScript testem config exists', function() {
     return copyFixtureFiles('smoke-tests/js-testem-config')
       .then(function() {
diff --git a/tests/fixtures/addon/kitchen-sink/addon/components/basic-thing.js b/tests/fixtures/addon/kitchen-sink/addon/components/basic-thing.js
deleted file mode 100644
index 7ba03a3b1..000000000
--- a/tests/fixtures/addon/kitchen-sink/addon/components/basic-thing.js
+++ /dev/null
@@ -1,6 +0,0 @@
-import Ember from 'ember';
-import template from '../templates/components/basic-thing';
-
-export default Ember.Component.extend({
-  layout: template
-});
diff --git a/tests/fixtures/addon/kitchen-sink/addon/components/some-foo/template.hbs b/tests/fixtures/addon/kitchen-sink/addon/components/some-foo/template.hbs
deleted file mode 100644
index 32f72011f..000000000
--- a/tests/fixtures/addon/kitchen-sink/addon/components/some-foo/template.hbs
+++ /dev/null
@@ -1,1 +0,0 @@
-<h1>Hi!</h1>
diff --git a/tests/fixtures/addon/kitchen-sink/addon/index.js b/tests/fixtures/addon/kitchen-sink/addon/index.js
deleted file mode 100644
index 03eb16bca..000000000
--- a/tests/fixtures/addon/kitchen-sink/addon/index.js
+++ /dev/null
@@ -1,2 +0,0 @@
-import BasicThing from "./components/basic-thing";
-export default BasicThing;
diff --git a/tests/fixtures/addon/kitchen-sink/addon/styles/app.css b/tests/fixtures/addon/kitchen-sink/addon/styles/app.css
deleted file mode 100644
index 441f327ae..000000000
--- a/tests/fixtures/addon/kitchen-sink/addon/styles/app.css
+++ /dev/null
@@ -1,1 +0,0 @@
-/* addon/styles/app.css is present */
diff --git a/tests/fixtures/addon/kitchen-sink/addon/templates/components/basic-thing.hbs b/tests/fixtures/addon/kitchen-sink/addon/templates/components/basic-thing.hbs
deleted file mode 100644
index 8c0ab5bfe..000000000
--- a/tests/fixtures/addon/kitchen-sink/addon/templates/components/basic-thing.hbs
+++ /dev/null
@@ -1,3 +0,0 @@
-<div class="basic-thing">
-  {{yield}}
-</div>
diff --git a/tests/fixtures/addon/kitchen-sink/app/components/basic-thing.js b/tests/fixtures/addon/kitchen-sink/app/components/basic-thing.js
deleted file mode 100644
index de31891b1..000000000
--- a/tests/fixtures/addon/kitchen-sink/app/components/basic-thing.js
+++ /dev/null
@@ -1,2 +0,0 @@
-import BasicThing from 'kitchen-sink/components/basic-thing';
-export default BasicThing;
diff --git a/tests/fixtures/addon/kitchen-sink/index.js b/tests/fixtures/addon/kitchen-sink/index.js
deleted file mode 100644
index 73b2ed042..000000000
--- a/tests/fixtures/addon/kitchen-sink/index.js
+++ /dev/null
@@ -1,9 +0,0 @@
-module.exports = {
-  name: 'kitchen-sink',
-
-  contentFor: function(type, config) {
-    if (type === 'head') {
-      return '"SOME AWESOME STUFF"';
-    }
-  }
-};
diff --git a/tests/fixtures/addon/kitchen-sink/tests/acceptance/main-test.js b/tests/fixtures/addon/kitchen-sink/tests/acceptance/main-test.js
deleted file mode 100644
index b4ad265cd..000000000
--- a/tests/fixtures/addon/kitchen-sink/tests/acceptance/main-test.js
+++ /dev/null
@@ -1,30 +0,0 @@
-import startApp from '../helpers/start-app';
-import destroyApp from '../helpers/destroy-app';
-import { module, test } from 'qunit';
-
-module('Acceptance', {
-  beforeEach: function() {
-    this.application = startApp();
-  },
-  afterEach: function() {
-    destroyApp(this.application);
-  }
-});
-
-test('renders properly', function(assert) {
-  visit('/');
-
-  andThen(function() {
-    var element = find('.basic-thing');
-    assert.equal(element.first().text().trim(), 'WOOT!!');
-  });
-});
-
-test('renders imported component', function(assert) {
-  visit('/');
-
-  andThen(function() {
-    var element = find('.second-thing');
-    assert.equal(element.first().text().trim(), 'SECOND!!');
-  });
-});
diff --git a/tests/fixtures/addon/kitchen-sink/tests/dummy/app/components/second-thing.js b/tests/fixtures/addon/kitchen-sink/tests/dummy/app/components/second-thing.js
deleted file mode 100644
index 78b72a137..000000000
--- a/tests/fixtures/addon/kitchen-sink/tests/dummy/app/components/second-thing.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import BasicThing from 'kitchen-sink/components/basic-thing';
-
-export default BasicThing.extend({
-  classNames: ['second-thing']
-});
diff --git a/tests/fixtures/addon/kitchen-sink/tests/dummy/app/templates/application.hbs b/tests/fixtures/addon/kitchen-sink/tests/dummy/app/templates/application.hbs
deleted file mode 100644
index 885261e68..000000000
--- a/tests/fixtures/addon/kitchen-sink/tests/dummy/app/templates/application.hbs
+++ /dev/null
@@ -1,2 +0,0 @@
-{{#basic-thing}}WOOT!!{{/basic-thing}}
-{{#second-thing}}SECOND!!{{/second-thing}}
diff --git a/tests/fixtures/addon/kitchen-sink/addon/components/my-component/component.js b/tests/fixtures/addon/pod-templates-only/addon/components/my-component/component.js
similarity index 100%
rename from tests/fixtures/addon/kitchen-sink/addon/components/my-component/component.js
rename to tests/fixtures/addon/pod-templates-only/addon/components/my-component/component.js
diff --git a/tests/fixtures/addon/kitchen-sink/addon/components/my-component/template.hbs b/tests/fixtures/addon/pod-templates-only/addon/components/my-component/template.hbs
similarity index 100%
rename from tests/fixtures/addon/kitchen-sink/addon/components/my-component/template.hbs
rename to tests/fixtures/addon/pod-templates-only/addon/components/my-component/template.hbs
diff --git a/tests/fixtures/addon/pod-templates-only/app/components/my-component.js b/tests/fixtures/addon/pod-templates-only/app/components/my-component.js
new file mode 100644
index 000000000..56a7a290c
--- /dev/null
+++ b/tests/fixtures/addon/pod-templates-only/app/components/my-component.js
@@ -0,0 +1,1 @@
+import { default } from 'some-cool-addon/components/my-component/component';
diff --git a/tests/fixtures/addon/with-addon-test-support/addon-test-support/current-text.js b/tests/fixtures/addon/with-addon-test-support/addon-test-support/current-text.js
new file mode 100644
index 000000000..8829ca839
--- /dev/null
+++ b/tests/fixtures/addon/with-addon-test-support/addon-test-support/current-text.js
@@ -0,0 +1,9 @@
+import Ember from 'ember';
+
+const { $ } = Ember;
+
+export default function(application) {
+  let rootElement = application.rootElement;
+
+  return $(rootElement).text();
+}
diff --git a/tests/fixtures/addon/with-addon-test-support/tests/acceptance/main-test.js b/tests/fixtures/addon/with-addon-test-support/tests/acceptance/main-test.js
new file mode 100644
index 000000000..51233169d
--- /dev/null
+++ b/tests/fixtures/addon/with-addon-test-support/tests/acceptance/main-test.js
@@ -0,0 +1,22 @@
+import startApp from '../helpers/start-app';
+import destroyApp from '../helpers/destroy-app';
+import { module, test } from 'qunit';
+import currentText from 'some-cool-addon/test-support/current-text';
+
+module('Acceptance', {
+  beforeEach: function() {
+    this.application = startApp();
+  },
+  afterEach: function() {
+    destroyApp(this.application);
+  }
+});
+
+test('can invoke helper', function(assert) {
+  assert.expect(1);
+
+  visit('/')
+    .then(() => {
+      assert.ok(currentText(this.application).indexOf('Stuff Here!') !== -1);
+    });
+});
diff --git a/tests/fixtures/addon/with-addon-test-support/tests/dummy/app/templates/application.hbs b/tests/fixtures/addon/with-addon-test-support/tests/dummy/app/templates/application.hbs
new file mode 100644
index 000000000..f1b58b1a6
--- /dev/null
+++ b/tests/fixtures/addon/with-addon-test-support/tests/dummy/app/templates/application.hbs
@@ -0,0 +1,1 @@
+Stuff Here!
diff --git a/tests/fixtures/addon/kitchen-sink/tests/dummy/public/robots.txt b/tests/fixtures/addon/with-dummy-public/tests/dummy/public/robots.txt
similarity index 100%
rename from tests/fixtures/addon/kitchen-sink/tests/dummy/public/robots.txt
rename to tests/fixtures/addon/with-dummy-public/tests/dummy/public/robots.txt
diff --git a/tests/fixtures/addon/with-linting-errors/addon/index.js b/tests/fixtures/addon/with-linting-errors/addon/index.js
new file mode 100644
index 000000000..d2fe7ab9d
--- /dev/null
+++ b/tests/fixtures/addon/with-linting-errors/addon/index.js
@@ -0,0 +1,3 @@
+export default function() {
+  var unused;
+}
diff --git a/tests/unit/blueprints/in-repo-addon-test.js b/tests/unit/blueprints/in-repo-addon-test.js
index aa18a8b75..c382dcf93 100644
--- a/tests/unit/blueprints/in-repo-addon-test.js
+++ b/tests/unit/blueprints/in-repo-addon-test.js
@@ -5,11 +5,9 @@ var path = require('path');
 var blueprintHelpers = require('ember-cli-blueprint-test-helpers/helpers');
 var setupTestHooks = blueprintHelpers.setupTestHooks;
 var emberNew = blueprintHelpers.emberNew;
-var emberGenerate = blueprintHelpers.emberGenerate;
-var emberDestroy = blueprintHelpers.emberDestroy;
+var emberGenerateDestroy = blueprintHelpers.emberGenerateDestroy;
 
 var expect = require('ember-cli-blueprint-test-helpers/chai').expect;
-var file = require('ember-cli-blueprint-test-helpers/chai').file;
 
 describe('Acceptance: ember generate and destroy in-repo-addon', function() {
   setupTestHooks(this, {
@@ -24,33 +22,23 @@ describe('Acceptance: ember generate and destroy in-repo-addon', function() {
         expect(fs.readJsonSync('package.json')['ember-addon']).to.be.undefined;
       })
       .then(function() {
-        return emberGenerate(args);
-      })
-      .then(function() {
-        expect(file('lib/foo-bar/package.json')).to.exist;
-        expect(file('lib/foo-bar/index.js')).to.exist;
-
-        expect(fs.readJsonSync('lib/foo-bar/package.json')).to.deep.equal({
-          "name": "foo-bar",
-          "keywords": [
-            "ember-addon",
-          ],
-        });
-
-        expect(fs.readJsonSync('package.json')['ember-addon']).to.deep.equal({
-          "paths": [
-            "lib/foo-bar",
-          ],
+        return emberGenerateDestroy(args, function(file) {
+          expect(file('lib/foo-bar/package.json')).to.exist;
+          expect(file('lib/foo-bar/index.js')).to.exist;
+
+          expect(fs.readJsonSync('lib/foo-bar/package.json')).to.deep.equal({
+            "name": "foo-bar",
+            "keywords": [
+              "ember-addon",
+            ],
+          });
+
+          expect(fs.readJsonSync('package.json')['ember-addon']).to.deep.equal({
+            "paths": [
+              "lib/foo-bar",
+            ],
+          });
         });
-      })
-      .then(function() {
-        return emberDestroy(args);
-      })
-      .then(function() {
-        expect(file('lib/foo-bar/package.json')).to.not.exist;
-        expect(file('lib/foo-bar/index.js')).to.not.exist;
-
-        expect(fs.readJsonSync('package.json')['ember-addon']['paths']).to.be.undefined;
       });
   });
 });
diff --git a/tests/unit/broccoli/ember-app-test.js b/tests/unit/broccoli/ember-app-test.js
index d1293af06..325bfdd26 100644
--- a/tests/unit/broccoli/ember-app-test.js
+++ b/tests/unit/broccoli/ember-app-test.js
@@ -19,7 +19,7 @@ var EmberApp = proxyquire('../../../lib/broccoli/ember-app', {
 });
 
 describe('broccoli/ember-app', function() {
-  var project, projectPath, app, addon;
+  var project, projectPath, emberApp, addon;
 
   function setupProject(rootPath) {
     var packageContents = require(path.join(rootPath, 'package.json'));
@@ -178,7 +178,7 @@ describe('broccoli/ember-app', function() {
       project._addonsInitialized = true;
       project.addons = [];
 
-      app = new EmberApp({
+      emberApp = new EmberApp({
         project: project
       });
 
@@ -202,7 +202,7 @@ describe('broccoli/ember-app', function() {
           }
         });
 
-        var actual = app.contentFor(config, defaultMatch, 'foo');
+        var actual = emberApp.contentFor(config, defaultMatch, 'foo');
 
         expect(calledConfig).to.deep.equal(config);
         expect(calledType).to.equal('foo');
@@ -222,7 +222,7 @@ describe('broccoli/ember-app', function() {
           }
         });
 
-        var actual = app.contentFor(config, defaultMatch, 'foo');
+        var actual = emberApp.contentFor(config, defaultMatch, 'foo');
 
         expect(actual).to.equal('blammo\nblahzorz');
       });
@@ -250,7 +250,7 @@ describe('broccoli/ember-app', function() {
           }
         });
 
-        var actual = app.contentFor(config, defaultMatch, 'foo');
+        var actual = emberApp.contentFor(config, defaultMatch, 'foo');
 
         expect(calledContent).to.deep.equal(['zero', 'one']);
         expect(actual).to.equal('zero\ntwo');
@@ -261,19 +261,19 @@ describe('broccoli/ember-app', function() {
       it('includes the `meta` tag in `head` by default', function() {
         var escapedConfig = escape(JSON.stringify(config));
         var metaExpected = '<meta name="cool-foo/config/environment" ' +
-          'content="' + escapedConfig + '" />';
-        var actual = app.contentFor(config, defaultMatch, 'head');
+                           'content="' + escapedConfig + '" />';
+        var actual = emberApp.contentFor(config, defaultMatch, 'head');
 
         expect(actual).to.contain(metaExpected);
       });
 
       it('does not include the `meta` tag in `head` if storeConfigInMeta is false', function() {
-        app.options.storeConfigInMeta = false;
+        emberApp.options.storeConfigInMeta = false;
 
         var escapedConfig = escape(JSON.stringify(config));
         var metaExpected = '<meta name="cool-foo/config/environment" ' +
-          'content="' + escapedConfig + '" />';
-        var actual = app.contentFor(config, defaultMatch, 'head');
+                           'content="' + escapedConfig + '" />';
+        var actual = emberApp.contentFor(config, defaultMatch, 'head');
 
         expect(actual).to.not.contain(metaExpected);
       });
@@ -282,7 +282,7 @@ describe('broccoli/ember-app', function() {
         config.locationType = 'auto';
         config.baseURL = '/';
         var expected = '<base href="/" />';
-        var actual = app.contentFor(config, defaultMatch, 'head');
+        var actual = emberApp.contentFor(config, defaultMatch, 'head');
 
         expect(actual).to.contain(expected);
       });
@@ -291,7 +291,7 @@ describe('broccoli/ember-app', function() {
         config.locationType = 'none';
         config.baseURL = '/';
         var expected = '<base href="/" />';
-        var actual = app.contentFor(config, defaultMatch, 'head');
+        var actual = emberApp.contentFor(config, defaultMatch, 'head');
 
         expect(actual).to.contain(expected);
       });
@@ -300,14 +300,14 @@ describe('broccoli/ember-app', function() {
         config.locationType = 'hash';
         config.baseURL = '/foo/bar';
         var expected = '<base href="/foo/bar/" />';
-        var actual = app.contentFor(config, defaultMatch, 'head');
+        var actual = emberApp.contentFor(config, defaultMatch, 'head');
 
         expect(actual).to.not.contain(expected);
       });
 
       it('does not include the `base` tag in `head` if baseURL is undefined', function() {
         var expected = '<base href=';
-        var actual = app.contentFor(config, defaultMatch, 'head');
+        var actual = emberApp.contentFor(config, defaultMatch, 'head');
 
         expect(actual).to.not.contain(expected);
       });
@@ -318,25 +318,25 @@ describe('broccoli/ember-app', function() {
         var metaSnippetPath = path.join(__dirname, '..','..','..','lib','broccoli','app-config-from-meta.js');
         var expected = fs.readFileSync(metaSnippetPath, { encoding: 'utf8' });
 
-        var actual = app.contentFor(config, defaultMatch, 'config-module');
+        var actual = emberApp.contentFor(config, defaultMatch, 'config-module');
 
         expect(actual).to.contain(expected);
       });
 
       it('includes the raw config if storeConfigInMeta is false', function() {
-        app.options.storeConfigInMeta = false;
+        emberApp.options.storeConfigInMeta = false;
 
         var expected = JSON.stringify(config);
-        var actual = app.contentFor(config, defaultMatch, 'config-module');
+        var actual = emberApp.contentFor(config, defaultMatch, 'config-module');
 
         expect(actual).to.contain(expected);
       });
     });
 
     it('has no default value other than `head`', function() {
-      expect(app.contentFor(config, defaultMatch, 'foo')).to.equal('');
-      expect(app.contentFor(config, defaultMatch, 'body')).to.equal('');
-      expect(app.contentFor(config, defaultMatch, 'blah')).to.equal('');
+      expect(emberApp.contentFor(config, defaultMatch, 'foo')).to.equal('');
+      expect(emberApp.contentFor(config, defaultMatch, 'body')).to.equal('');
+      expect(emberApp.contentFor(config, defaultMatch, 'blah')).to.equal('');
     });
   });
 
@@ -355,12 +355,12 @@ describe('broccoli/ember-app', function() {
           this.addons = [ addon ];
         };
 
-        var app = new EmberApp({
+        emberApp = new EmberApp({
           project: project
         });
 
         expect(called).to.be.true;
-        expect(passedApp).to.equal(app);
+        expect(passedApp).to.equal(emberApp);
       });
 
       it('does not throw an error if the addon does not implement `included`', function() {
@@ -371,7 +371,7 @@ describe('broccoli/ember-app', function() {
         };
 
         expect(function() {
-          new EmberApp({
+          emberApp = new EmberApp({
             project: project
           });
         }).to.not.throw(/addon must implement the `included`/);
@@ -389,16 +389,21 @@ describe('broccoli/ember-app', function() {
           this.addons = [ addon ];
         };
 
-        app = new EmberApp({
-          project: project
-        });
       });
 
       it('addonTreesFor returns an empty array if no addons return a tree', function() {
-        expect(app.addonTreesFor('blah')).to.deep.equal([]);
+        emberApp = new EmberApp({
+          project: project
+        });
+
+        expect(emberApp.addonTreesFor('blah')).to.deep.equal([]);
       });
 
       it('addonTreesFor calls treesFor on the addon', function() {
+        emberApp = new EmberApp({
+          project: project
+        });
+
         var sampleAddon = project.addons[0];
         var actualTreeName;
 
@@ -408,44 +413,44 @@ describe('broccoli/ember-app', function() {
           return 'blazorz';
         };
 
-        expect(app.addonTreesFor('blah')).to.deep.equal(['blazorz']);
+        expect(emberApp.addonTreesFor('blah')).to.deep.equal(['blazorz']);
         expect(actualTreeName).to.equal('blah');
       });
 
       it('addonTreesFor does not throw an error if treeFor is not defined', function() {
         delete addon.treeFor;
 
-        app = new EmberApp({
+        emberApp = new EmberApp({
           project: project
         });
 
         expect(function() {
-          app.addonTreesFor('blah');
+          emberApp.addonTreesFor('blah');
         }).not.to.throw(/addon must implement the `treeFor`/);
       });
 
       describe('addonTreesFor is called properly', function() {
         beforeEach(function() {
-          app = new EmberApp({
+          emberApp = new EmberApp({
             project: project
           });
 
-          app.addonTreesFor = td.function();
-          td.when(app.addonTreesFor(), {ignoreExtraArgs: true}).thenReturn(['batman']);
+          emberApp.addonTreesFor = td.function();
+          td.when(emberApp.addonTreesFor(), {ignoreExtraArgs: true}).thenReturn(['batman']);
         });
 
         it('_processedVendorTree calls addonTreesFor', function() {
-          app._processedVendorTree();
+          emberApp._processedVendorTree();
 
-          var args = td.explain(app.addonTreesFor).calls.map(function(call) { return call.args[0]; });
+          var args = td.explain(emberApp.addonTreesFor).calls.map(function(call) { return call.args[0]; });
 
           expect(args).to.deep.equal(['addon', 'vendor']);
         });
 
         it('_processedAppTree calls addonTreesFor', function() {
-          app._processedAppTree();
+          emberApp._processedAppTree();
 
-          var args = td.explain(app.addonTreesFor).calls.map(function(call) { return call.args[0]; });
+          var args = td.explain(emberApp.addonTreesFor).calls.map(function(call) { return call.args[0]; });
 
           expect(args).to.deep.equal(['app']);
         });
@@ -454,26 +459,28 @@ describe('broccoli/ember-app', function() {
 
     describe('postprocessTree is called properly', function() {
       beforeEach(function() {
-        app = new EmberApp({
+        emberApp = new EmberApp({
           project: project
         });
 
-        app.addonPostprocessTree = td.function();
-        td.when(app.addonPostprocessTree(), {ignoreExtraArgs: true}).thenReturn(['batman']);
+        emberApp.addonPostprocessTree = td.function();
+        td.when(emberApp.addonPostprocessTree(), {ignoreExtraArgs: true}).thenReturn(['batman']);
       });
 
+
       it('styles calls addonTreesFor', function() {
-        app.styles();
+        emberApp.styles();
 
         var captor = td.matchers.captor();
-        td.verify(app.addonPostprocessTree('css', captor.capture()));
+        td.verify(emberApp.addonPostprocessTree('css', captor.capture()));
 
         expect(captor.value.description).to.equal('styles', 'should be called with consolidated tree');
       });
 
+
       it('template type is called', function() {
-        var oldLoad = app.registry.load;
-        app.registry.load = function(type) {
+        var oldLoad = emberApp.registry.load;
+        emberApp.registry.load = function(type) {
           if (type === 'template') {
             return [
               {
@@ -484,14 +491,14 @@ describe('broccoli/ember-app', function() {
                 }
               }];
           } else {
-            return oldLoad.call(app.registry, type);
+            return oldLoad.call(emberApp.registry, type);
           }
         };
 
-        app._processedTemplatesTree();
+        emberApp._processedTemplatesTree();
 
         var captor = td.matchers.captor();
-        td.verify(app.addonPostprocessTree('template', captor.capture()));
+        td.verify(emberApp.addonPostprocessTree('template', captor.capture()));
 
         expect(captor.value.description).to.equal('template', 'should be called with consolidated tree');
       });
@@ -509,37 +516,37 @@ describe('broccoli/ember-app', function() {
           this.addons = [ addon ];
         };
 
-        app = new EmberApp({
+        emberApp = new EmberApp({
           project: project
         });
       });
 
       it('calls postProcessTree if defined', function() {
-        app.toArray = td.function();
+        emberApp.toArray = td.function();
 
-        td.when(app.toArray(), {ignoreExtraArgs: true}).thenReturn([]);
+        td.when(emberApp.toArray(), {ignoreExtraArgs: true}).thenReturn([]);
         td.when(addon.postprocessTree(), {ignoreExtraArgs: true}).thenReturn('derp');
 
-        expect(app.toTree()).to.equal('derp');
+        expect(emberApp.toTree()).to.equal('derp');
       });
 
       it('calls addonPostprocessTree', function() {
-        app.toArray = td.function();
-        app.addonPostprocessTree = td.function();
+        emberApp.toArray = td.function();
+        emberApp.addonPostprocessTree = td.function();
 
-        td.when(app.toArray(), {ignoreExtraArgs: true}).thenReturn([]);
-        td.when(app.addonPostprocessTree(), {ignoreExtraArgs: true}).thenReturn('blap');
+        td.when(emberApp.toArray(), {ignoreExtraArgs: true}).thenReturn([]);
+        td.when(emberApp.addonPostprocessTree(), {ignoreExtraArgs: true}).thenReturn('blap');
 
-        expect(app.toTree()).to.equal('blap');
+        expect(emberApp.toTree()).to.equal('blap');
       });
 
       it('calls each addon postprocessTree hook', function() {
-        app._processedTemplatesTree = td.function();
+        emberApp._processedTemplatesTree = td.function();
 
-        td.when(app._processedTemplatesTree(), {ignoreExtraArgs: true}).thenReturn('x');
+        td.when(emberApp._processedTemplatesTree(), {ignoreExtraArgs: true}).thenReturn('x');
         td.when(addon.postprocessTree(), {ignoreExtraArgs: true}).thenReturn('blap');
 
-        expect(app.toTree()).to.equal('blap');
+        expect(emberApp.toTree()).to.equal('blap');
 
         var args = td.explain(addon.postprocessTree).calls.map(function(call) { return call.args[0]; });
 
@@ -561,29 +568,28 @@ describe('broccoli/ember-app', function() {
       describe('isEnabled is called properly', function() {
         describe('with environment', function() {
           var emberFooEnvAddonFixture;
-
           beforeEach(function() {
             emberFooEnvAddonFixture = require(path.resolve(projectPath, 'node_modules/ember-foo-env-addon/index.js'));
           });
 
           it('development', function() {
             process.env.EMBER_ENV = 'development';
-            var app = new EmberApp({ project: project });
+            emberApp = new EmberApp({ project: project });
 
-            emberFooEnvAddonFixture.app = app;
-            expect(app._addonEnabled(emberFooEnvAddonFixture)).to.be.false;
+            emberFooEnvAddonFixture.app = emberApp;
+            expect(emberApp._addonEnabled(emberFooEnvAddonFixture)).to.be.false;
 
-            expect(app.project.addons.length).to.equal(8);
+            expect(emberApp.project.addons.length).to.equal(8);
           });
 
           it('foo', function() {
             process.env.EMBER_ENV = 'foo';
-            var app = new EmberApp({ project: project });
+            emberApp = new EmberApp({ project: project });
 
-            emberFooEnvAddonFixture.app = app;
-            expect(app._addonEnabled(emberFooEnvAddonFixture)).to.be.true;
+            emberFooEnvAddonFixture.app = emberApp;
+            expect(emberApp._addonEnabled(emberFooEnvAddonFixture)).to.be.true;
 
-            expect(app.project.addons.length).to.equal(9);
+            expect(emberApp.project.addons.length).to.equal(9);
           });
         });
       });
@@ -591,30 +597,28 @@ describe('broccoli/ember-app', function() {
       describe('blacklist', function() {
         it('prevents addons to be added to the project', function() {
           process.env.EMBER_ENV = 'foo';
-
-          var app = new EmberApp({
+          emberApp = new EmberApp({
             project: project,
             addons: {
               blacklist: ['ember-foo-env-addon']
             }
           });
 
-          expect(app._addonDisabledByBlacklist({ name: 'ember-foo-env-addon' })).to.be.true;
-          expect(app._addonDisabledByBlacklist({ name: 'Ember Random Addon' })).to.be.false;
-          expect(app.project.addons.length).to.equal(8);
+          expect(emberApp._addonDisabledByBlacklist({ name: 'ember-foo-env-addon' })).to.be.true;
+          expect(emberApp._addonDisabledByBlacklist({ name: 'Ember Random Addon' })).to.be.false;
+          expect(emberApp.project.addons.length).to.equal(8);
         });
 
         it('throws if unavailable addon is specified', function() {
-          function load() {
+          var load = function() {
             process.env.EMBER_ENV = 'foo';
-
-            var app = new EmberApp({
+            emberApp = new EmberApp({
               project: project,
               addons: {
                 blacklist: ['ember-cli-self-troll']
               }
             });
-          }
+          };
 
           expect(load).to.throw('Addon "ember-cli-self-troll" defined in blacklist is not found');
         });
@@ -623,29 +627,28 @@ describe('broccoli/ember-app', function() {
       describe('whitelist', function() {
         it('prevents non-whitelisted addons to be added to the project', function() {
           process.env.EMBER_ENV = 'foo';
-
-          var app = new EmberApp({
+          emberApp = new EmberApp({
             project: project,
             addons: {
               whitelist: ['ember-foo-env-addon']
             }
           });
 
-          expect(app._addonDisabledByWhitelist({ name: 'ember-foo-env-addon' })).to.be.false;
-          expect(app._addonDisabledByWhitelist({ name: 'Ember Random Addon' })).to.be.true;
-          expect(app.project.addons.length).to.equal(1);
+          expect(emberApp._addonDisabledByWhitelist({ name: 'ember-foo-env-addon' })).to.be.false;
+          expect(emberApp._addonDisabledByWhitelist({ name: 'Ember Random Addon' })).to.be.true;
+          expect(emberApp.project.addons.length).to.equal(1);
         });
 
         it('throws if unavailable addon is specified', function() {
-          function load() {
+          var load = function() {
             process.env.EMBER_ENV = 'foo';
-            app = new EmberApp({
+            emberApp = new EmberApp({
               project: project,
               addons: {
                 whitelist: ['ember-cli-self-troll']
               }
             });
-          }
+          };
 
           expect(load).to.throw('Addon "ember-cli-self-troll" defined in whitelist is not found');
         });
@@ -654,7 +657,7 @@ describe('broccoli/ember-app', function() {
       describe('blacklist wins over whitelist', function() {
         it('prevents addon to be added to the project', function() {
           process.env.EMBER_ENV = 'foo';
-          app = new EmberApp({
+          emberApp = new EmberApp({
             project: project,
             addons: {
               whitelist: ['ember-foo-env-addon'],
@@ -662,7 +665,7 @@ describe('broccoli/ember-app', function() {
             }
           });
 
-          expect(app.project.addons.length).to.equal(0);
+          expect(emberApp.project.addons.length).to.equal(0);
         });
       });
     });
@@ -677,13 +680,13 @@ describe('broccoli/ember-app', function() {
           this.addons = [ addon ];
         };
 
-        app = new EmberApp({
+        emberApp = new EmberApp({
           project: project
         });
       });
 
       it('does not throw an error if lintTree is not defined', function() {
-        app.addonLintTree();
+        emberApp.addonLintTree();
       });
 
       it('calls lintTree on the addon', function() {
@@ -691,7 +694,7 @@ describe('broccoli/ember-app', function() {
 
         td.when(addon.lintTree('blah', 'blam')).thenReturn('blazorz');
 
-        app.addonLintTree('blah', 'blam');
+        emberApp.addonLintTree('blah', 'blam');
 
         td.verify(mergeTreesStub(['blazorz'], {
           overwrite: true,
@@ -704,7 +707,7 @@ describe('broccoli/ember-app', function() {
 
         td.when(addon.lintTree(), {ignoreExtraArgs: true}).thenReturn(false);
 
-        app.addonLintTree();
+        emberApp.addonLintTree();
 
         td.verify(mergeTreesStub([]), {ignoreExtraArgs: true});
       });
@@ -712,54 +715,56 @@ describe('broccoli/ember-app', function() {
   });
 
   describe('import', function() {
-    beforeEach(function() {
-      app = new EmberApp({
+    it('appends dependencies to vendor by default', function() {
+      emberApp = new EmberApp({
         project: project
       });
-    });
-
-    afterEach(function() {
-      process.env.EMBER_ENV = undefined;
-    });
-
-    it('appends dependencies to vendor by default', function() {
-      app.import('vendor/moment.js');
-      var outputFile = app._scriptOutputFiles['/assets/vendor.js'];
+      emberApp.import('vendor/moment.js');
+      var outputFile = emberApp._scriptOutputFiles['/assets/vendor.js'];
 
       expect(outputFile).to.be.instanceof(Array);
       expect(outputFile.indexOf('vendor/moment.js')).to.equal(outputFile.length - 1);
     });
     it('appends dependencies', function() {
-      app.import('vendor/moment.js', {type: 'vendor'});
+      emberApp = new EmberApp({
+        project: project
+      });
+      emberApp.import('vendor/moment.js', {type: 'vendor'});
 
-      var outputFile = app._scriptOutputFiles['/assets/vendor.js'];
+      var outputFile = emberApp._scriptOutputFiles['/assets/vendor.js'];
 
       expect(outputFile).to.be.instanceof(Array);
       expect(outputFile.indexOf('vendor/moment.js')).to.equal(outputFile.length - 1);
     });
-
     it('prepends dependencies', function() {
-      app.import('vendor/es5-shim.js', {type: 'vendor', prepend: true});
+      emberApp = new EmberApp({
+        project: project
+      });
+      emberApp.import('vendor/es5-shim.js', {type: 'vendor', prepend: true});
 
-      var outputFile = app._scriptOutputFiles['/assets/vendor.js'];
+      var outputFile = emberApp._scriptOutputFiles['/assets/vendor.js'];
 
       expect(outputFile).to.be.instanceof(Array);
       expect(outputFile.indexOf('vendor/es5-shim.js')).to.equal(0);
     });
-
     it('prepends dependencies to outputFile', function() {
-      app.import('vendor/moment.js', {outputFile: 'moment.js', prepend: true});
+      emberApp = new EmberApp({
+        project: project
+      });
+      emberApp.import('vendor/moment.js', {outputFile: 'moment.js', prepend: true});
 
-      var outputFile = app._scriptOutputFiles['moment.js'];
+      var outputFile = emberApp._scriptOutputFiles['moment.js'];
 
       expect(outputFile).to.be.instanceof(Array);
       expect(outputFile.indexOf('vendor/moment.js')).to.equal(0);
     });
-
     it('appends dependencies to outputFile', function() {
-      app.import('vendor/moment.js', {outputFile: 'moment.js'});
+      emberApp = new EmberApp({
+        project: project
+      });
+      emberApp.import('vendor/moment.js', {outputFile: 'moment.js'});
 
-      var outputFile = app._scriptOutputFiles['moment.js'];
+      var outputFile = emberApp._scriptOutputFiles['moment.js'];
 
       expect(outputFile).to.be.instanceof(Array);
       expect(outputFile.indexOf('vendor/moment.js')).to.equal(outputFile.length - 1);
@@ -767,28 +772,27 @@ describe('broccoli/ember-app', function() {
 
     it('defaults to development if production is not set', function() {
       process.env.EMBER_ENV = 'production';
-      app.import({
+      emberApp = new EmberApp({
+        project: project
+      });
+      emberApp.import({
         'development': 'vendor/jquery.js'
       });
-
-      var outputFile = app._scriptOutputFiles['/assets/vendor.js'];
+      var outputFile = emberApp._scriptOutputFiles['/assets/vendor.js'];
       expect(outputFile.indexOf('vendor/jquery.js')).to.equal(outputFile.length - 1);
+      process.env.EMBER_ENV = undefined;
     });
-
     it('honors explicitly set to null in environment', function() {
       process.env.EMBER_ENV = 'production';
-      // set EMBER_ENV before creating the project
-
-      app = new EmberApp({
+      emberApp = new EmberApp({
         project: project
       });
-
-      app.import({
+      emberApp.import({
         'development': 'vendor/jquery.js',
         'production':  null
       });
-
-      expect(app._scriptOutputFiles['/assets/vendor.js']).to.not.contain('vendor/jquery.js');
+      expect(emberApp._scriptOutputFiles['/assets/vendor.js']).to.not.contain('vendor/jquery.js');
+      process.env.EMBER_ENV = undefined;
     });
   });
 
@@ -832,36 +836,36 @@ describe('broccoli/ember-app', function() {
     });
 
     it('defines vendorFiles by default', function() {
-      app = new EmberApp({
+      emberApp = new EmberApp({
         project: project
       });
-      expect(Object.keys(app.vendorFiles)).to.deep.equal(defaultVendorFiles);
+      expect(Object.keys(emberApp.vendorFiles)).to.deep.equal(defaultVendorFiles);
     });
 
     it('redefines a location of a vendor asset', function() {
-      app = new EmberApp({
+      emberApp = new EmberApp({
         project: project,
 
         vendorFiles: {
           'ember.js': 'vendor/ember.js'
         }
       });
-      expect(app.vendorFiles['ember.js']).to.equal('vendor/ember.js');
+      expect(emberApp.vendorFiles['ember.js']).to.equal('vendor/ember.js');
     });
 
     it('defines vendorFiles in order even when option for it is passed', function() {
-      app = new EmberApp({
+      emberApp = new EmberApp({
         project: project,
 
         vendorFiles: {
           'ember.js': 'vendor/ember.js'
         }
       });
-      expect(Object.keys(app.vendorFiles)).to.deep.equal(defaultVendorFiles);
+      expect(Object.keys(emberApp.vendorFiles)).to.deep.equal(defaultVendorFiles);
     });
 
     it('removes dependency in vendorFiles', function() {
-      app = new EmberApp({
+      emberApp = new EmberApp({
         project: project,
 
         vendorFiles: {
@@ -869,7 +873,7 @@ describe('broccoli/ember-app', function() {
           'handlebars.js': null
         }
       });
-      var vendorFiles = Object.keys(app.vendorFiles);
+      var vendorFiles = Object.keys(emberApp.vendorFiles);
       expect(vendorFiles).to.not.contain('ember.js');
       expect(vendorFiles).to.not.contain('handlebars.js');
     });
@@ -877,27 +881,27 @@ describe('broccoli/ember-app', function() {
     it('defaults to ember.debug.js if exists in bower_components', function () {
       var root = path.resolve(__dirname, '../../fixtures/app/with-default-ember-debug');
 
-      app = new EmberApp({
+      emberApp = new EmberApp({
         project: setupProject(root)
       });
 
-      var files = app.vendorFiles['ember.js'];
-      expect(files.development).to.equal('bower_components/ember/ember.debug.js');
+      var emberFiles = emberApp.vendorFiles['ember.js'];
+      expect(emberFiles.development).to.equal('bower_components/ember/ember.debug.js');
     });
 
     it('switches the default ember.debug.js to ember.js if it does not exist', function () {
       var root = path.resolve(__dirname, '../../fixtures/app/without-ember-debug');
 
-      app = new EmberApp({
+      emberApp = new EmberApp({
         project: setupProject(root)
       });
 
-      var files = app.vendorFiles['ember.js'];
-      expect(files.development).to.equal('bower_components/ember/ember.js');
+      var emberFiles = emberApp.vendorFiles['ember.js'];
+      expect(emberFiles.development).to.equal('bower_components/ember/ember.js');
     });
 
     it('does not clobber an explicitly configured ember development file', function () {
-      app = new EmberApp({
+      emberApp = new EmberApp({
         project: project,
 
         vendorFiles: {
@@ -906,39 +910,27 @@ describe('broccoli/ember-app', function() {
           }
         }
       });
-      var files = app.vendorFiles['ember.js'];
-      expect(files.development).to.equal('vendor/ember.debug.js');
-    });
-  });
-
-  it('fails with invalid type', function() {
-    var app = new EmberApp({
-      project: project
+      var emberFiles = emberApp.vendorFiles['ember.js'];
+      expect(emberFiles.development).to.equal('vendor/ember.debug.js');
     });
-
-    expect(function() {
-      app.import('vendor/b/c/foo.js', { type: 'javascript'});
-    }).to.throw(/You must pass either `vendor` or `test` for options.type in your call to `app.import` for file: foo.js/)
   });
 
   describe('_resolveLocal', function() {
     it('resolves a path relative to the project root', function() {
-      var app = new EmberApp({
+      var emberApp = new EmberApp({
         project: project
       });
 
-      var result = app._resolveLocal('foo');
+      var result = emberApp._resolveLocal('foo');
       expect(result).to.equal(path.join(project.root, 'foo'));
     });
   });
 
   describe('concatFiles()', function() {
-    beforeEach(function() {
-      app = new EmberApp({ project: project });
-    });
-
     it('shows deprecation message if called directly', function() {
-      app.concatFiles(null, {
+      var emberApp = new EmberApp({ project: project });
+
+      var result = emberApp.concatFiles(null, {
         outputFile: 'foo.js'
       });
 
@@ -946,7 +938,9 @@ describe('broccoli/ember-app', function() {
     });
 
     it('ignores deprecation message if called through _concatFiles()', function() {
-      app._concatFiles(null, {
+      var emberApp = new EmberApp({ project: project });
+
+      var result = emberApp._concatFiles(null, {
         outputFile: 'foo.js'
       });
 
diff --git a/tests/unit/models/server-watcher-test.js b/tests/unit/models/server-watcher-test.js
index 0f780da15..436f97952 100644
--- a/tests/unit/models/server-watcher-test.js
+++ b/tests/unit/models/server-watcher-test.js
@@ -25,18 +25,35 @@ describe('Server Watcher', function() {
     });
   });
 
+  describe('watcher strategy selection', function() {
+    it('selects the events-based watcher by default', function () {
+      subject.options = null;
+      expect(!!subject.polling()).to.equal(false);
+    });
+
+    it('selects the events-based watcher when given events watcher option', function () {
+      subject.options = { watcher: 'events' };
+      expect(!!subject.polling()).to.equal(false);
+    });
+
+    it('selects the polling watcher when given polling watcher option', function () {
+      subject.options = { watcher: 'polling' };
+      expect(!!subject.polling()).to.be.ok;
+    });
+  });
+
   describe('watcher:change', function() {
     beforeEach(function () {
       watcher.emit('change', 'foo.txt');
     });
 
     it('logs that the file was changed', function() {
-      expect(ui.output).to.equal('File changed: "foo.txt"' + EOL);
+      expect(ui.output).to.equal('Server file changed: foo.txt' + EOL);
     });
 
     it('tracks changes', function() {
       expect(analytics.tracks).to.deep.equal([{
-        name: 'server file changed',
+        name: 'server file change',
         description: 'File changed: "foo.txt"'
       }]);
     });
@@ -48,7 +65,7 @@ describe('Server Watcher', function() {
     });
 
     it('logs that the file was added', function() {
-      expect(ui.output).to.equal('File added: "foo.txt"' + EOL);
+      expect(ui.output).to.equal('Server file added: foo.txt' + EOL);
     });
 
     it('tracks additions', function() {
@@ -65,7 +82,7 @@ describe('Server Watcher', function() {
     });
 
     it('logs that the file was deleted', function() {
-      expect(ui.output).to.equal('File deleted: "foo.txt"' + EOL);
+      expect(ui.output).to.equal('Server file deleted: foo.txt' + EOL);
     });
 
     it('tracks deletions', function() {