Once you have loaded a page containing the user subscription form, you can fill the form and submit it back to the server. For this, we will use a new test case:
it("should submit", function(done) { Browser.visit("http://localhost:3000/users/new", function(err, browser) { if (err) throw err; browser .fill('E-mail', 'me@email.com') .fill('Password', 'mypassword') .pressButton('Submit', function(err) { if (err) throw err; assert.equal(browser.text('h1'), 'Thank you!'); assert(browser.query('a[href="/session/new"]'), 'has login link'); done(); }); }); });
Here we're revisiting the user creation form, and once the form has loaded, we're filling in the e-mail and password fills by using the browser.fill(<field>, <value>)
method. In this form, browser.fill()
accepts several types of arguments as a field identifier. Here we're using the label text that precedes the field. If you view the source for the empty user creation form, it will be:
<form action="/users" method="POST"> <p> <label for="email">E-mail</label> <input type="email" name="email" value="" id="email"> </p> <p> <label for="password">Password</label> <input type="password" name="password" id="password" value="" required=""> </p> <input type="submit" value="Submit"> </form>
Each of the two label tags we are using here has a for
attribute that indicates the id
attribute of the tag it relates to. This is what Zombie.js uses to match the field in browser.fill()
. Alternatively, we could also specify the field name or CSS selector, making the following fill directives equivalent to what we have:
browser .fill('#email', 'me@email.com') .fill('#password', 'mypassword')
You can then run the test by typing on the shell console:
$ ./node_modules/.bin/mocha test/users.js
Provided the CouchDB server is accessible, these tests should then pass:
.. ✔ 2 tests complete (577ms)
But, if you run the tests again, they should fail. Try it now:
.. ✖ 1 of 2 tests failed: 1) Users Signup Form should submit: Error: Server returned status code 409 ...
This is because we don't allow two users with the same e-mail address, and the browser yields a 409 response code as the result of such a user creation request. You could remove the user document from the database by hand before each test, but to fully remedy this, we need to automate the process.
First we're going to introduce the concept of fixtures. This is where we will define the username and password for our user, which will be used in other tests. You then need to create a file under test/fixtures.json
with the following data for now:
{ "user" : { "email": "me@email.com", "password": "mypassword" } }
This JSON file will then be consumed by the users
test file by placing require
right at the top:
var fixtures = require('./fixtures');
Then you also need to access the database, and for doing that we use the same library that the route listeners use:
var couchdb = require('../lib/couchdb'), dbName = 'users', db = couchdb.use(dbName);
Now we need to add a before hook into the Signup Form
test description scope:
before(function(done) { db.get(fixtures.user.email, function(err, doc) { if (err && err.status_code === 404) return done(); if (err) throw err; db.destroy(doc._id, doc._rev, done); }); });
This will make sure there is no such user record in our database.
Now that we're using fixtures, let's remove those hard-coded username and password strings from our test code:
it("should submit", function(done) { Browser.visit("http://localhost:3000/users/new", function(err, browser) { if (err) throw err; browser .fill('E-mail', fixtures.user.email) .fill('Password', fixtures.user.password) .pressButton('Submit', function(err) { if (err) throw err; assert.equal(browser.text('h1'), 'Thank you!'); assert(browser.query('a[href="/session/new"]'), 'has login link'); done(); }); }); });
This would then be the whole assembled user test file:
var assert = require('assert'), Browser = require('zombie'), app = require('../app'), couchdb = require('../lib/couchdb'), dbName = 'users', db = couchdb.use(dbName), fixtures = require('./fixtures'); describe('Users', function() { before(function(done) { app.start(3000, done); }); after(function(done) { app.server.close(done); }); describe('Signup Form', function() { before(function(done) { db.get(fixtures.user.email, function(err, doc) { if (err && err.status_code === 404) return done(); if (err) throw err; db.destroy(doc._id, doc._rev, done); }); }); it('should load the signup form', function(done) { Browser.visit("http://localhost:3000/users/new", function(err, browser) { if (err) throw err; assert.ok(browser.success, 'page loaded'); assert.equal(browser.text('h1'), 'New User'); var form = browser.query('form'); assert(form, 'form exists'); assert.equal(form.method, 'POST', 'uses POST method'); assert.equal(form.action, '/users', 'posts to /users'); assert(browser.query('input[type=email]#email', form), 'has email input'); assert(browser.query('input[type=password]#password', form), 'has password input'); assert(browser.query('input[type=submit]', form), 'has submit button'); done(); }); }); it("should submit", function(done) { Browser.visit("http://localhost:3000/users/new", function(err, browser) { if (err) throw err; browser .fill('E-mail', fixtures.user.email) .fill('Password', fixtures.user.password) .pressButton('Submit', function(err) { if (err) throw err; assert.equal(browser.text('h1'), 'Thank you!'); assert(browser.query('a[href="/session/new"]'), 'has login link'); done(); }); }); }); }); });
When running this test repeatedly, you should always get a success message now.