Jun 29, 2015
Table of contents:
In last week’s tutorial we wrote our first Acceptance Test for an Ember.js Application.
The process of Test Driven Developments is, write a test, watch it fail, then write just enough code to make it pass.
In today’s tutorial we will continue to see how we can write tests to drive the development of the application.
Last week we wrote a test to pull the number of open tasks from the DOM.
The easiest way of doing this is to simply hard code the tasks in the HTML.
However, in the real world we’re going to want to pull the tasks from an API.
So the first thing we need to do is to update the template file tasks.hbs
under the app/templates
directory:
<section>
<ul class="task-list">
{{#each task in open}}
<li class="task"></li>
{{/each}}
</ul>
</section>
Now if you run the tests again you will see the acceptance test fails. This is because we’re trying to iterate through something that does not exist.
The test is failing because we’re trying to iterate through a property that does not exist. In order to make the test pass we need to create a new Controller:
ember g controller tasks
This command will create a new Controller file called tasks.js
under the controllers
directory:
import Ember from "ember";
export default Ember.Controller.extend({});
To make the test pass we can add the open
property to the Controller and ensure that it returns an array of 3 items:
import Ember from "ember";
export default Ember.Controller.extend({
open: function () {
return [1, 2, 3];
}.property(),
});
In the code above we are defining a function that will return an array of items. By adding the property()
method to the end of the function we can use it as a property within the template.
Now if you run the tests again, everything should pass!
Now that we are retrieving the data from the Controller we are moving in the right direction. However, returning an array of integers is not what we want, instead we need to return an array of Task
objects.
Normally this would involve Ember Data to retrieve data from our JSON API.
However before we get into the complexity of Ember Data, our first step will be to create a simple Task
object that extends Ember.Object
.
The first thing I’m going to do is to update the test to pick the first task and then assert it has the correct text:
var task = find(".task-list .task:eq(0)");
assert.equal(task.text(), "Task 1");
This should make the test fail because currently we are only passing an array of integers to the template.
Next we can update the template to display the title
attribute of the task
:
<h2>Task List</h2>
<section>
<ul class="task-list">
{{#each task in open}}
<li class="task">{{task.title}}</li>
{{/each}}
</ul>
</section>
For now we’re going to keep things simple and use a simple Ember.Object
as the model. Create a new file called task.js
under the models
directory with the following code:
import Ember from "ember";
export default Ember.Object.extend({});
This is simply defining a new object that extends Ember.Object
.
Finally update the Controller to look like this:
import Ember from "ember";
import Task from "helplist/models/task";
export default Ember.Controller.extend({
open: function () {
var one = Task.create({ title: "Task 1" });
var two = Task.create({ title: "Task 2" });
var three = Task.create({ title: "Task 3" });
var four = Task.create({ title: "Task 4" });
var five = Task.create({ title: "Task 5" });
return [one, two, three, four, five];
}.property(),
});
Now instead of returning a simple array of integers we are returning an array of Task
objects.
Now if you run the tests again, everything should pass.
In today’s tutorial we move from a hardcoded template to getting data dynamically from the controller.
We also created a simple Ember.Object
to represent the Task model.
And we updated the template to display an attribute of the model.
We are incrementally moving towards a dynamic, server based application.
Next week we will be introduction Ember Data and mocking the API server.