Nightmare.js
There's a really awesome tool called Nightmare.js. First it was a hight-level Phantom wrapper, but since v2 it was rewritten on Atom. Nightmare is webkit-based.
Nightmare can be executed headlessly, but you'll probably need to configure your server to get that working.
Why Nightmare? Here's a code sample from the official site:
Nightmare.js
yield Nightmare()
.goto('http://yahoo.com')
.type('input[title="Search"]', 'github nightmare')
.click('.searchsubmit');
Comparing to:
Phantom.js
phantom.create(function (ph) {
ph.createPage(function (page) {
page.open('http://yahoo.com', function (status) {
page.evaluate(function () {
var el =
document.querySelector('input[title="Search"]');
el.value = 'github nightmare';
}, function (result) {
page.evaluate(function () {
var el = document.querySelector('.searchsubmit');
var event = document.createEvent('MouseEvent');
event.initEvent('click', true, false);
el.dispatchEvent(event);
}, function (result) {
ph.exit();
});
});
});
});
});
So you'll have to write significantly less code.
BUT IT'S WEBKIT-ONLY
Selenium
In order to get something working in all browsers, take a look at Selenium. It supports really many browsers and platforms.
var webdriver = require('selenium-webdriver'),
By = require('selenium-webdriver').By,
until = require('selenium-webdriver').until;
var driver = new webdriver.Builder()
.forBrowser('firefox')
.build();
driver.get('http://www.google.com/ncr');
driver.findElement(By.name('q')).sendKeys('webdriver');
driver.findElement(By.name('btnG')).click();
driver.wait(until.titleIs('webdriver - Google Search'), 1000);
driver.quit();
Just a small advice Selenium tests are likely to be more "bulky" than nightmare tests and I've seen quite a lot "Promise hell" in Selenium tests on one of my previous jobs, so before you start, my advice to you would be to use of generators and co or some other control flow library.