Google News
logo
Ember.js Interview Questions
Ember.js is an open-source JavaScript web framework for building modern web applications, utilizing a component-service pattern. It includes everything you need to build rich UIs that work on any device. It does so by providing developers many features that are essential to manage complexity in modern single-page web applications, as well as an integrated development toolkit that enables rapid iteration.

Ember.js was developed by Yehuda Katz in initially released 8 December 2011. Now upgraded versions are take care by Ember core team.
Ember CLI : A robust development toolkit to create, develop, and build Ember applications. Learn basic commands from the CLI Guides.

Components : The fundamental construct used in Ember applications, used to create reusable UI elements and define the layout and the functionality of the app.

Routing : A central part of an Ember application. Enables developers to drive the application state from the URL.

Services : The way to store long-term state in your application and pass it around.

Ember Data : Ember Data provides a consistent way to communicate with external APIs and manage application state

Ember Inspector : A browser extension, or bookmarklet, to inspect your application live. It's also useful for spotting Ember applications in the wild.
The Ember CLI (command line interface) is the official way to create, build, test, and serve the files that make up an Ember app or addon. Many things have to happen before a web app is ready for the browser. Ember CLI helps you get there with zero configuration.
npm install -g ember-cli
The Ember CLI is like a dependency packager, test runner, optimizer, and local server—all rolled into one. Since all features were built to work together, common tasks (e.g. upgrading the app version and deploying the app) can be automated with production-ready, open source plugins. The CLI is backwards-compatible with older Ember apps and maintains a 6-week release schedule.
 
The CLI was also built with the idea that a developer should be able to focus on building great apps, not re-engineering how to fit pieces together throughout an app's lifecycle. Apps become maintainable and approachable, since there are established architectural patterns across individuals, teams, and companies. However, if you want to make your own adjustments, such as using a different testing library, you still can.
When an npm package offers some Ember-specific features, we call it an "addon." An addon provides a way to write reusable code, share components and styling, extend the build tooling, and more—all with minimal configuration. You can visit Ember Observer to search addons.
 
You can also use npm packages that were made for the wider JavaScript community.
 
Since v3.x, Ember apps include the ember-auto-import dependency, which enables importing npm packages directly. For example, if you want to use highcharts in your application, you can install and import it without any other configuration. Be sure to visit the ember-auto-import documentation for more advanced usage!
Once you've installed Ember CLI via npm, you will have access to a new ember command in your terminal. You can use the ember new command to create a new application.
ember new ember-quickstart --lang en
This one command will create a new directory called ember-quickstart and set up a new Ember application inside of it. The --lang en option sets the app's primary language to English to help improve accessibility. Out of the box, your application will include:
 
* A development server.
* Template compilation.
* JavaScript and CSS minification.
* Modern features via Babel.

By providing everything you need to build production-ready web applications in an integrated package, Ember makes starting new projects a breeze.
 
Let's make sure everything is working properly. cd into the application directory ember-quickstart and start the development server by typing:
cd ember-quickstart
ember serve
After a few seconds, you should see output that looks like this:
Livereload server on http://localhost:7020
Serving on http://localhost:4200/
(To stop the server at any time, type Ctrl-C in your terminal.)
 
Open http://localhost:4200 in your browser of choice. You should see an Ember welcome page.
Some concepts used in Ember.js:
 
Store : This is a central repository and cache of all records available in an application. Controller and admin can access it.

Models : It specifies a class which defines the data of properties and behavior.

Records : It specifies an instance of a model which contains loaded information from a server.

Adapter : It is responsible for translating requested records into the appropriate calls.

Serializer : It is used to translate JSON data into a record object.

Automatic Caching : It is used for caching.
It is an open source framework. So, it gives developers unlimited access for customizing for desired output.

Ember.js doesn't require server requests to perform its task.

DOM is directly updated when a user comes in contact with the browser or press any button over there.
Let's build an application that shows a list of scientists. To do that, the first step is to create a route. For now, you can think of routes as being the different pages that make up your application.
 
Ember comes with generators that automate the boilerplate code for common tasks. To generate a route, type this in a new terminal window in your ember-quickstart directory :
ember generate route scientists
You'll see output like this :
installing route
  create app/routes/scientists.js
  create app/templates/scientists.hbs
updating router
  add route scientists
installing route-test
  create tests/unit/routes/scientists-test.js
That is Ember telling you that it has created :
 
* A template to be displayed when the user visits /scientists.
* A Route object that fetches the model used by that template.
* An entry in the application's router (located in app/router.js).
* A unit test for this route.

Open the newly-created template in app/templates/scientists.hbs and add the following HTML :
{{page-title "Scientists"}}
<h2>List of Scientists</h2>
In your browser, open http://localhost:4200/scientists. You should see the <h2> we put in the scientists.hbs template right below the <h1> from our application.hbs template.
 
Since the scientist route is nested under the application route, Ember will render its content inside the application route template's {{outlet}} directive.
 
Now that we've got the scientists template rendering, let's give it some data to render. We do that by specifying a model for that route, and we can specify a model by editing app/routes/scientists.js.
 
We'll take the code created for us by the generator and add a model() method to the Route:
import Route from '@ember/routing/route';

export default class ScientistsRoute extends Route {
  model() {
    return ['Marie Curie', 'Mae Jemison', 'Albert Hofmann'];
  }
}
This code example uses a feature of JavaScript called classes.
 
In a route's model() method, you return whatever data you want to make available to the template. If you need to fetch data asynchronously, the model() method supports any library that uses JavaScript Promises.
 
Now let's tell Ember how to turn that array of strings into HTML. Open the scientists template and add the following code to loop through the array and print it :
<h2>List of Scientists</h2>

<ul>
  {{#each @model as |scientist|}}
    <li>{{scientist}}</li>
  {{/each}}
</ul>
Here, we use the each helper to loop over each item in the array we provided from the model() hook. Ember will render the block contained inside the {{#each}}...{{/each}} helper once for each item (each scientist in our case) in the array. The item (the scientist) that is being rendered currently will be made available in the scientist variable, as denoted by as |scientist| in the each helper.
 
The end result is that there will be one <li> element corresponding to each scientist in the array inside the <ul> unordered list.
MDynamic Models : It provides the routes with dynamic segments. These segments are used to access the value from URL
Ember.Route.extend ({  
   model(parameter) {  
      //code block  
   }  
});  
  
Router.map(function() {  
   this.route('linkpage', { path: 'identifiers' });  
});  
Multiple Models : It is used to define multiple models through RSVP.hash.

Example :
Ember.Route.extend ({  
   model() {  
      return Ember.RSVP.hash({  
         //code block  
      })  
   }  
});  
The architectural structure of the Ember.js application is based on MVC (Model, View, Controller) pattern.
 
Models : Models define the data that is used in an application.

Controllers : Controllers are used to modifying the queries, edit the data and provide user interactions.

Views : Views are used to display the data and capture the user actions to be repeated easily if needed in the future.
In Ember.js, instead of majority of your application’s logic living on the server, an ember.js application downloads everything it required to run in the initial page load. So user does not have to load a new page while using the app and UI will responds quickly. The advantage of this architecture is that your web application uses the same REST API as your native App.
First way :
* By extending the Em.View class, you have to create an oject in your JavaScript to define a view. You can declare your functions and variables inside that.
* Now to insert a view in your template,  you have to follow the write the handlebar script {{ #view App.ViewName}}
 
Second Way :
* In this technique, the name of the view object is not required, while inserting into the template. But inside the object you have another property called as templateName which should be initialized with the value same as data template name attribute in handlebar’s script tag, in your template.
The prime role of an adapter is to handle queries related to the task assigned to it. There are different adapters that can be assigned different tasks. It can also query the back as well as the front end. The common adapters in Ember.js are Rest, JSON, LS Adapter, and the latter deals with local storage or when data needs to be stored in low. 
In Ember.js, we can call the extend() method on Ember.Object to define a new ember class.
 
Example :
App.Person = Ember.Object.extend({  
  say: function(thing) {  
    alert(thing);  
  }  
});  
The above example defines a new App.Person class with a say() method.
 
We can also create a subclass from any existing class by calling its extend() method. See the following example if you want to create a subclass of Ember's built-in Ember.View class.
 
Example :
App.PersonView = Ember.View.extend({  
  tagName: 'li',  
  classNameBindings: ['isAdministrator']  
}); 
While defining a subclass, you can override methods but still access the implementation of your parent class by calling the special _super() method.
 
Example :
App.Person = Ember.Object.extend({  
  say: function(thing) {  
    var name = this.get('name');  
    alert(name + " says: " + thing);  
  }  
});  
AppApp.Soldier = App.Person.extend({  
  say: function(thing) {  
    this._super(thing + ", sir!");  
  }  
});  
var sam = App.Soldier.create({  
  name: "Free Time Leaarn"  
});  
sam.say("Reporting"); // alerts "Free Time Leaarn says: Reporting, sir!"  
In Ember.js, a service is a long-lived Ember object that can be available in different parts of your application. The following syntax is used to create the Ember.js service.
 
Syntax :
"ember. Service"​
Following is a list of some examples of Ember.js services :
 
* Logging
* User/session authentication
* Geolocation
* Third-party API's
* Web Sockets
* Server sent events or notifications
* Server-backed API calls that may not fit ember-data etc.

Ember CLI service generator is used to generate the service. To get access to a service, inject it either in an initializer or use the following syntax :
"ember.Inject"  
By using this method, you can also access the properties and methods using services.
 
Use the following syntax to define a service.
 
Syntax :
ember generate service service_name;  
Component templates can leave one or more placeholders that users can fill with their own HTML. These are called blocks. Here's an example that provides a component with the implicit default block.
<ExampleComponent>
  This is the default <b>block content</b> that will
  replace `{{yield}}` (or `{{yield to="default"}}`)
  in the `ExampleComponent` template.
</ExampleComponent>
This is equivalent to explicitly naming the default block using the named block syntax.
<ExampleComponent>
  <:default>
    This is the default <b>block content</b> that will
    replace `{{yield}}` (or `{{yield to="default"}}`)
    in the `ExampleComponent` template.
  </:default>
</ExampleComponent>
Through Block Content, users of the component can add additional styling and behavior by using HTML, modifiers, and other components within the block.
Helper functions are JavaScript functions that you can call from your template.
 
Ember's template syntax limits what you can express to keep the structure of your application clear at a glance. When you need to compute something using JavaScript, you can use helper functions. It's possible to create your own helpers or just use the built-in ones.
 
For instance, let's take a look at a generic message component from a messaging app.
 
app/components/message.hbs :
<Message::Avatar
  @title={{@avatarTitle}}
  @initial={{@avatarInitial}}
  @isActive={{@userIsActive}}
  class={{if @isCurrentUser "current-user"}}
/>
<section>
  <Message::Username
    @name={{@username}}
    @localTime={{@userLocalTime}}
  />

  {{yield}}
</section>
<Message
  @username="Tomster"
  @userIsActive={{true}}
  @userLocalTime="4:56pm"
  @avatarTitle="Tomster's avatar"
  @avatarInitial="T"
>
  <p>
    Hey Zoey, have you had a chance to look at the EmberConf
    brainstorming doc I sent you?
  </p>
</Message>
By looking at how we use the <Message> component, we can see that some of the arguments are fairly repetitive. Both @avatarTitle and @avatarInitial are based on the user's @username, but the title has more text, and the initial is only the first letter of the name. We'd rather just pass a username to the <Message> component and compute the value of the title and initial.
 
Let's update the component to do that. It'll take a @username argument and calculate the title and initial.
Helpers can also be defined using class syntax. For instance, we could define the substring helper using classes instead.
 
app/helpers/substring.js :
import { helper } from '@ember/component/helper';
import Helper from '@ember/component/helper';

function substring([string], { start, length }) {
export default class Substring extends Helper {
  compute([string], { start, end }) {
    return string.substring(start || 0, end);
  }
}
Class helpers are useful when the helper logic is fairly complicated, requires fine-grained control of the helper lifecycle, or is stateful (we'll be discussing state in the next chapter).
Ember provides 2 components for building a form :
 
* <Input>
* <Textarea>

These components are similar in HTML markup to the native <input> or <textarea> elements. In contrast to the native elements, <Input> and <Textarea> automatically update the state of their bound values.
 
<Input> : We mentioned that the built-in components are similar in HTML markup to their native counterparts.
 
Consider the following example in a template file.
<label for="user-question">Ask a question about Ember:</label>
<Input
  id="user-question"
  @type="text"
  @value="How do text fields work?"
/>
 
<Textarea> : The following example shows how to bind this.userComment to a text area's value.
<label for="user-comment">Comment:</label>
<Textarea
  id="user-comment"
  @value={{this.userComment}}
  rows="6"
  cols="80"
/>
Setting attributes on <Textarea> : With the exception of @value argument, you can use any attribute that <textarea> natively supports.
The error and loading substates exist as a part of each route, so they should not be added to your router.js file. To utilize a substate, the route, controller, and template may be optionally defined as desired.
 
loading substates : During the beforeModel, model, and afterModel hooks, data may take some time to load. Technically, the router pauses the transition until the promises returned from each hook fulfill.
 
Consider the following :
 
app/router.js :
Router.map(function() {
  this.route('slow-model');
});
app/routes/slow-model.js :
import Route from '@ember/routing/route';
import { service } from '@ember/service';

export default class SlowModelRoute extends Route {
  @service store;

  model() {
    return this.store.findAll('slow-model');
  }
}
 
error substates : Ember provides an analogous approach to loading substates in the case of errors encountered during a transition.
 
Similar to how the default loading event handlers are implemented, the default error handlers will look for an appropriate error substate to enter, if one can be found.
 
app/router.js :
Router.map(function() {
  this.route('articles', function() {
    this.route('overview');
  });
});
As with the loading substate, on a thrown error or rejected promise returned from the articles.overview route's model hook (or beforeModel or afterModel) Ember will look for an error template or route in the following order :
 
* articles.overview-error
* articles.error or articles-error
* error or application-error
Route and Router both are different terms in Ember.js.

A router is a medium which is used to connect the application with a browser's address. On the other side, Route is a location where the request of a user reaches first after it is made or translated by a Router. Route only is responsible for defining the data that is to be sent to the Template.
Various template components are potent in Ember.js and are used for specific purposes related to running the code in an error-free manner.
 
These template components are :
 
* View
* Outlet
* Render
* Partial
* Yield

They are similar in one aspect, and that is they can be called in all the programs with similar functions.
The different common functions of Ember.js package are :
 
empty : It returns true if the value of the dependent property is null, an empty array, empty string, or empty function.

bind :
 It provides an easy way to integrate third-party libraries into your Ember application asynchronously.

isArray :
 It returns true if the passed object is an array or Array-like.

compare :
 It compares two javascript values.

typeOf :
 It returns a consistent type for the passed object.

isEqual :
 It compares two objects, returning true if they are equal
In Ember.js, project structure is also called directory structure. It contains the following files and directories :
 
I-app : It contains folders and files for models, components, routes, templates, and styles.
 
I-bower_components/ bower.json : It is a dependency management tool which is used in Ember CLI to manage front-end plugins and component dependencies.
 
I-config : It contains the environment.js which controls configure settings for your app.
 
I-dist : It contains the created output files when we build our app for deployment.
 
I-node_nodules/package.json : Directory and files are from npm. Npm is the package manager for node.js.
 
Public : The public directory contains assets such as image and fonts.
 
Vendor : This directory specifies a location where front-end dependencies that are not managed by Bower go.
 
Tests/testem.js : Automated tests for our app go in the test folder, and testing is configured in testem.js.
 
Tmp : Ember CLI temporary files live here.
 
Ember-cli-build.js : This file describes how Ember CLI should build our app.
For doing anything, it is always good to check the procedure with sample data. This is because the task is sensitive and needs a lot of care for accomplishment. This can be done with the help of long-term persistence fixtures. However, it is necessary that applications must be connected with each other. The application adapter is to be made the extension of Ds.Fixture. For communication purposes, the adapters can be deployed easily. At the last, the file is to be updated to the model todo.js
There is an object named Enumerable that generally contains child objects. Using the operator Ember. Enumerable API, it is possible to work with these child objects. However, in some applications that have complex sizes, the native JavaScript array is the commonly used enumerable. 
Ember supports observing any property which also includes computed properties. Observers are something which contains the behavior that reacts to the changes made in other properties. Observers are used when we need to perform some behavior after binding has finished synchronizing. New ember developers often use observers. Observers are mostly used within the ember framework and for that; computed properties are the appropriate solution.

An observer can be set on an object using the following syntax - "ember.observer" Observers in ember are synchronous. They fire as soon as they observe a change in the properties. So, because of this, it is easy to introduce bugs where properties are not yet synchronized.
A model is a class that defines the properties and behavior of the data that you present to the user. Anything that the user expects to see if they leave your app and come back later (or if they refresh the page) should be represented by a model.
 
When you want a new model for your application you need to create a new file under the models folder and extend from Model. This is more conveniently done by using one of Ember CLI's generator commands. For instance, let's create a person model:
ember generate model person
This will generate the following file :
 
app/models/person.js :
import Model from '@ember-data/model';

export default class PersonModel extends Model {
}
 
The Ember Data store provides an interface for retrieving records of a single type.
 
Retrieving a Single Record : Use store.findRecord() to retrieve a record by its type and ID. This will return a promise that fulfills with the requested record:
// GET /blog-posts/1
this.store.findRecord('blog-post', 1)  // => GET /blog-posts/1
  .then(function(blogPost) {
      // Do something with `blogPost`
  });
Use store.peekRecord() to retrieve a record by its type and ID, without making a network request. This will return the record only if it is already present in the store:
let blogPost = this.store.peekRecord('blog-post', 1); // => no network request
Retrieving Multiple Records : Use store.findAll() to retrieve all of the records for a given type:
// GET /blog-posts
this.store.findAll('blog-post') // => GET /blog-posts
  .then(function(blogPosts) {
    // Do something with `blogPosts`
  });
Use store.peekAll() to retrieve all of the records for a given type that are already loaded into the store, without making a network request:
let blogPosts = this.store.peekAll('blog-post'); // => no network request
store.findAll() returns a PromiseArray that fulfills to a RecordArray and store.peekAll directly returns a RecordArray.
Creating Records : You can create records by calling the createRecord() method on the store.
store.createRecord('post', {
  title: 'Rails is Omakase',
  body: 'Lorem ipsum'
});
The store object is available in controllers and routes using this.store.
 
Updating Records : Making changes to Ember Data records is as simple as setting the attribute you want to change:
this.store.findRecord('post', 1).then(function(post) {
  // ...after the record has loaded
  post.title = 'A new post';
});
 
Deleting Records : Deleting records is as straightforward as creating records. Call deleteRecord() on any instance of Model. This flags the record as isDeleted. The deletion can then be persisted using save(). Alternatively, you can use the destroyRecord method to delete and persist at the same time.
let post = store.peekRecord('post', 1);
post.deleteRecord();
post.isDeleted; // => true
post.save(); // => DELETE to /posts/1

// OR
post = store.peekRecord('post', 2);
post.destroyRecord(); // => DELETE to /posts/2
Ember Data includes several built-in relationship types to help you define how your models relate to each other.
 
One-to-One : To declare a one-to-one relationship between two models, use belongsTo:
 
app/models/user.js :
import Model, { belongsTo } from '@ember-data/model';

export default class UserModel extends Model {
  @belongsTo('profile') profile;
}
app/models/profile.js :
import Model, { belongsTo } from '@ember-data/model';

export default class ProfileModel extends Model {
  @belongsTo('user') user;
}

One-to-Many : 
To declare a one-to-many relationship between two models, use belongsTo in combination with hasMany, like this:
 
app/models/blog-post.js
import Model, { hasMany } from '@ember-data/model';

export default class BlogPostModel extends Model {
  @hasMany('comment') comments;
}
app/models/comment.js :
import Model, { belongsTo } from '@ember-data/model';

export default class CommentModel extends Model {
  @belongsTo('blog-post') blogPost;
}

Many-to-Many : 
To declare a many-to-many relationship between two models, use hasMany:
 
app/models/blog-post.js :
import Model, { hasMany } from '@ember-data/model';

export default class BlogPostModel extends Model {
  @hasMany('tag') tags;
}
app/models/tag.js :
import Model, { hasMany } from '@ember-data/model';

export default class TagModel extends Model {
  @hasMany('blog-post') blogPosts;
}
Along with the records returned from your store, you'll likely need to handle some kind of metadata. Metadata is data that goes along with a specific model or type instead of a record.
 
Pagination is a common example of using metadata. Imagine a blog with far more posts than you can display at once. You might query it like so:
let result = this.store.query('post', {
  limit: 10,
  offset: 0
});
 
Each serializer will expect the metadata to be returned differently. For example, Ember Data's JSON deserializer looks for a meta key:
{
  "post": {
    "id": 1,
    "title": "Progressive Enhancement is Dead",
    "comments": ["1", "2"],
    "links": {
      "user": "/people/tomdale"
    },
    // ...
  },

  "meta": {
    "total": 100
  }
}
Regardless of the serializer used, this metadata is extracted from the response. You can then read it with .meta.

This can be done on the result of a store.query() call :
store.query('post').then(result => {
  let meta = result.meta;
});
On a belongsTo relationship :
let post = store.peekRecord('post', 1);

let author = await post.author;
let meta = author.meta;
Or on a hasMany relationship :
let post = store.peekRecord('post', 1);

let comments = await post.comments;
let meta = comments.meta;
After reading it, meta.total can be used to calculate how many pages of posts you'll have.
 
To use the meta data outside of the model hook, you need to return it:
 
app/routes/users.js :
import Route from '@ember/routing/route';
import { service } from '@ember/service';

export default class UsersRoute extends Route {
  @service store;

  model() {
    return this.store.query('user', {}).then((results) => {
      return {
        users: results,
        meta: results.meta
      };
    });
  }
  setupController(controller, { users, meta }) {
    super.setupController(controller, users);
    controller.meta = meta;
  }
}
To customize metadata extraction, check out the documentation for your serializer.
Autotracking is how Ember's reactivity model works - how it decides what to rerender, and when. This guide covers tracking in more depth, including how it can be used in various types of classes, and how it interacts with arrays and POJOs.
 
When Ember first renders a component, it renders the initial state of that component - the state of the instance, and state of the arguments that are passed to it:
 
app/components/hello.hbs :
{{this.greeting}}, {{@name}}!
app/components/hello.js :
import Component from '@glimmer/component';

export default class HelloComponent extends Component {
  language = 'en';

  get greeting() {
    switch (this.language) {
      case 'en':
        return 'Hello';
      case 'de':
        return 'Hallo';
      case 'es':
        return 'Hola';
    }
  }
}
app/templates/application.hbs
<Hello @name="Free Time Learning">
When Ember renders this template, we get:
Hello, Free Time Learning!
Native classes were first added to JavaScript in ES2015 (also known as ES6). They are defined using the class keyword, and look like this :
class Person {
  helloWorld() {
    console.log('Hello, world!');
  }
}
Ember applications utilize the dependency injection ("DI") design pattern to declare and instantiate classes of objects and dependencies between them.
 
Generally, Services are Ember's primary method for sharing state via dependency injection. In most cases, you shouldn't need to learn about how to work with Ember's DI system directly, or how to manually register and setup dependencies. However, there are times when it may be necessary. 
Initializers provide an opportunity to configure your application as it boots.
 
There are two types of initializers :
* Application initializers
* Application instance initializers

Application initializers : Application initializers can be created with Ember CLI's initializer generator:
ember generate initializer shopping-cart
Let's customize the shopping-cart initializer to inject a cart property into all the routes in your application:
 
app/initializers/shopping-cart.js :
export function initialize(application) {
  application.inject('route', 'cart', 'service:shopping-cart');
};

export default {
  initialize
};
 
Application Instance Initializers : Application instance initializers can be created with Ember CLI's instance-initializer generator :
ember generate instance-initializer logger
Let's add some simple logging to indicate that the instance has booted:
 
app/instance-initializers/logger.js :
export function initialize(applicationInstance) {
  let logger = applicationInstance.lookup('logger:main');
  logger.log('Hello from the instance initializer!');
}

export default {
  initialize
};
The most common case for using the run loop is integrating with a non-Ember API that includes some sort of asynchronous callback.

For example :
 
* DOM update and event callbacks
* setTimeout and setInterval callbacks
* postMessage and messageChannel event handlers
* fetch or ajax callbacks
* WebSocket callbacks
Very often, batching similar work has benefits. Web browsers do something quite similar by batching changes to the DOM.
 
Consider the following HTML snippet :
<div id="foo"></div>
<div id="bar"></div>
<div id="baz"></div>
 
and executing the following code :
foo.style.height = '500px' // write
foo.offsetHeight // read (recalculate style, layout, expensive!)

bar.style.height = '400px' // write
bar.offsetHeight // read (recalculate style, layout, expensive!)

baz.style.height = '200px' // write
baz.offsetHeight // read (recalculate style, layout, expensive!)
Ember Engines allow multiple logical applications to be composed together into a single application from the user's perspective, that provide functionality to their host applications. Engines are isolated, composable applications, they have almost all the same features as normal Ember applications, except an Engine requires a host application to boot it and provide a Router instance.
Large organizations often use Ember.js to power sophisticated web applications. These apps may require collaboration among several teams, sometimes distributed around the world. Typically, responsibility is shared by dividing the application into one or more "sections". How this division is actually implemented varies from team to team.
 
Maintaining large monolithic applications poses the following challenges:
 
* Side effects : if you change something, it may be unclear how it could affect the rest of platform.

* Coordination :
 when you develop a new feature or make big changes, many teams may need to be in sync to approve it.

* Complexity :
 with a huge dependency tree and many layers of abstraction, developers cannot iterate quickly, and features suffer as a result.

* Killing Innovation :
 a/b testing a cutting-edge feature is hard to do without disrupting the rest of the app and the teams working on it.

* Slow Onboarding :
 new people coming into the team are overwhelmed.

Engines provide an antidote to these problems by allowing for distributed development, testing, and packaging of logically-grouped pieces of an application.
The flag status in the generated build is controlled by the @ember/canary-features package. This package exports a list of all available features and their current status.
 
A feature can have one of a three flags :
 
* true : The feature is present and enabled: the code behind the flag is always enabled in the generated build.

* null : The feature is present but disabled in the build output. It must be enabled at runtime.

* false : The feature is entirely disabled: the code behind the flag is not present in the generated build.

The process of removing the feature flags from the resulting build output is handled by defeatureify.
Ember provides 3 types of tests out of the box :
 
* Unit tests
* Rendering tests (previously known as integration tests)
* Application tests (previously known as acceptance tests)

Broadly speaking, these tests differ in two aspects :
* Which parts of your app they check for correctness. Having different types of tests help separate testing concerns.
* How fast they execute.
Container testing methods and computed properties follow previous patterns shown in Testing Basics because DS.Model extends Ember.Object.
 
Ember Data Models can be tested in a module that uses the setupTest helper.
 
Let's assume we have a Player model that has level and levelName attributes. We want to call levelUp() to increment the level and assign a new levelName when the player reaches level 5.
 
You can follow along by generating your own model with ember generate model player.
 
app/models/player.js :
import Model, { attr } from '@ember-data/model';

export default class Player extends Model {
  @attr('number', { defaultValue: 0 }) level;
  @attr('string', { defaultValue: 'Noob' }) levelName;

  levelUp() {
    let newLevel = this.level++;
    if (newLevel === 5) {
      this.levelName = 'Professional';
    }
  }
}
Now let's create a test which will call levelUp on the player when they are level 4 to assert that the levelName changes. We will use module together with the setupTest helper method :
 
tests/unit/models/player-test.js :
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
import { run } from '@ember/runloop';

module('Unit | Model | player', function(hooks) {
  setupTest(hooks);

  // Specify the other units that are required for this test.
  test('should increment level when told to', function(assert) {
    const player = run(() =>
      this.owner.lookup('service:store').createRecord('player')
    );

    // wrap asynchronous call in run loop
    run(() => player.levelUp());

    assert.equal(player.level, 5, 'level gets incremented');
    assert.equal(
      player.levelName,
      'Professional',
      'new level is called professional'
    );
  });
});​
Controllers can be tested using the setupTest helper which is part of the ember-qunit framework. The tests written for instances like Ember.Controller are also described as container tests.
 
Testing Controller Actions : Here we have a controller PostsController with two properties, a method that sets one of those properties, and an action named setProps.
 
You can follow along by generating your own controller with ember generate controller posts.
 
app/controllers/posts.js :
import Controller from '@ember/controller';
import { action } from '@ember/object';

export default class PostsController extends Controller {
  propA = 'You need to write tests';
  propB = 'And write one for me too';

  setPropB(str) {
    this.propB = str;
  }

  @action
  setProps(str) {
    this.propA = 'Testing is cool';
    this.setPropB(str);
  }
}
The setProps action directly sets one property, and calls the method to set the other. In our generated test file, Ember CLI already uses the module and the setupTest helpers to set up a test container:
 
tests/unit/controllers/posts-test.js :
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';

module('Unit | Controller | posts', function(hooks) {
  setupTest(hooks);
});
 
Next we use the owner API to gain access to the controller we'd like to test. Using the this.owner.lookup method we get the instance of the PostsController and can check the action in our test. The this.owner.lookup helper returns objects generated by the framework in your applications and is also exposed in tests for your usage. Here it will return a singleton instance of the PostsController.
 
tests/unit/controllers/posts-test.js :
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';

module('Unit | Controller | posts', function(hooks) {
  setupTest(hooks);

  test('should update A and B on setProps action', function(assert) {
    assert.expect(4);

    // get the controller instance
    let controller = this.owner.lookup('controller:posts');

    // check the properties before the action is triggered
    assert.equal(
      controller.propA,
      'You need to write tests',
      'propA initialized'
    );
    assert.equal(
      controller.propB,
      'And write one for me too',
      'propB initialized'
    );

    // trigger the action on the controller by using the `send` method,
    // passing in any params that our action may be expecting
    controller.send('setProps', 'Testing Rocks!');

    // finally we assert that our values have been updated
    // by triggering our action.
    assert.equal(controller.propA, 'Testing is cool', 'propA updated');
    assert.equal(controller.propB, 'Testing Rocks!', 'propB updated');
  });
});​