If you have a select box in a form, you can also instruct Zombie to select a list item for you. Let's change our to-do item creation form to include an additional select box that describes the scope of the item—whether the item is related to work, family, or if it's a personal task.
First, we need to introduce this additional field into the to-do item creation form in templates/todos/new.html
, right after the What
text area field:
<label for="scope"> Scope <select name="scope" id="scope"> <option value="" selected="selected">Please select</option> <option value="work">Work</option> <option value="personal">Personal</option> <option value="family">Family</option> </select> </label>
This will present the following form containing the additional Scope label and a select box:
Now we need to have a test that verifies that this form contains the select
element and the option
items. For that, let's keep extending the file in test/todos.js
, inside the Todo creation form
description scope:
it('should present the scope select box', login(function(browser, done) { browser.visit('http://localhost:3000/todos/new', function(err) { if (err) throw err; var select = browser.queryAll('form select[name=scope]'); assert.equal(select.length, 1); var options = browser.queryAll('form select[name=scope] option'); assert.equal(options.length, 4); options = options.map(function(option) { return [option.value, option.textContent]; }); var expectedOptions = [ [null, 'Please select'], ['work', 'Work'], ['personal', 'Personal'], ['family', 'Family'] ]; assert.deepEqual(options, expectedOptions); done(); }); }) );
Here we're testing that the select
element exists, that it has four option
items, and that each item has the expected value and text.
Now we need to change the to-do list to present this new scope field. For that, we need to introduce it in the templates/todos/index.html
file:
<h1>Your To-Dos</h1> <a class="btn" href="/todos/new">New To-Do</a> <table class="table"> <thead> <tr> <th>#</th> <th>What</th> <th>Scope</th> <th></th> </tr> </thead> <tbody id="todo-list"> <tr class="todo"> <td class="pos"></td> <td class="what"></td> <td class="scope"></td> <td class="remove"> <form action="/todos/delete" method="POST"> <input type="hidden" name="pos" value="" /> <input type="submit" name="Delete" value="Delete" /> </form> </td> </tr> </tbody> </table>
We also need to fill the value when presenting the to-do item list in the routes/todos.js
file, in the GET /
route listener:
this.get('/', [loggedIn, function() {
var res = this.res;
db.get(this.req.session.user.email, function(err, todos) {
if (err && err.status_code !== 404) {
res.writeHead(500);
return res.end(err.stack);
}
if (! todos) todos = {todos: []};
todos = todos.todos;
todos.forEach(function(todo, idx) {
if (todo) todo.pos = idx + 1;
});
var map = Plates.Map();
map.className('todo').to('todo');
map.className('pos').to('pos');
map.className('what').to('what');
map.className('scope').to('scope');
map.where('name').is('pos').use('pos').as('value');
var main = Plates.bind(templates.index, {todo: todos}, map);
res.writeHead(200, {'Content-Type': 'text/html'});
res.end(layout(main, 'To-Dos'));
});
This will result in a to-do list like the one shown in the following screenshot, where the scope
attribute of each to-do item is presented:
Now we need to test that the to-do item creation succeeds in capturing the scope value. For this, we'll slightly change the test named should allow to create a todo
:
it('should allow to create a todo', login(function(browser, done) { browser.visit('http://localhost:3000/todos/new', function(err) { if (err) throw err; browser .fill('What', 'Laundry') .select('scope', 'Personal') .pressButton('Create', function(err) { if (err) throw err; assert.equal(browser.location.pathname, '/todos', 'should be redirected to /todos after creation'); var list = browser.queryAll('#todo-list tr.todo'); assert.equal(list.length, 1, 'To-do list length should be 1'); var todo = list[0]; assert.equal(browser.text('td.pos', todo), 1); assert.equal(browser.text('td.what', todo), 'Laundry'); assert.equal(browser.text('td.scope', todo), 'personal'); done(); }); }); }));