diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..28b5e4144f669385317d941e904af31785e60941
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+/node_modules
+/npm-debug.log
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000000000000000000000000000000000000..9bdccd0e3ecfd2de1c39aea746c040cccaf82f0c
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,6 @@
+language: node_js
+node_js:
+  - 0.8
+before_script:
+  - "export DISPLAY=:99.0"
+  - "sh -e /etc/init.d/xvfb start"
diff --git a/package.json b/package.json
index 622db008d94a733eef51174078387790ea29ac9b..0c61f59157b7dd6b7655d4ca8a43eddf5d76ddb3 100644
--- a/package.json
+++ b/package.json
@@ -12,6 +12,12 @@
     "directories": {
         "lib": "./lib"
     },
+    "scripts": {
+        "test": "node ./test/run.js"
+    },
+    "devDependencies": {
+        "node-static": "0.6.0"
+    },
     "bugs": "http://github.com/marijnh/CodeMirror2/issues",
     "keywords": ["JavaScript", "CodeMirror", "Editor"],
     "homepage": "http://codemirror.net",
diff --git a/test/phantom_driver.js b/test/phantom_driver.js
new file mode 100644
index 0000000000000000000000000000000000000000..ad48fd1a8439fd132e7240cfa4414a75ce511e40
--- /dev/null
+++ b/test/phantom_driver.js
@@ -0,0 +1,30 @@
+var page = require('webpage').create();
+
+page.open("http://localhost:3000/test/index.html", function (status) {
+  if (status != "success") {
+    console.log("page couldn't be loaded successfully");
+    phantom.exit(1);
+  }
+  waitFor(function () {
+    return page.evaluate(function () {
+      var output = document.getElementById('output');
+      if (!output) { return false; }
+      return (/(\d+ failures?|all passed)$/i).test(output.innerText);
+    });
+  }, function () {
+    var failed = page.evaluate(function () { return window.failed; });
+    var output = page.evaluate(function () {
+      return document.getElementById('output').innerText;
+    });
+    console.log(output);
+    phantom.exit(failed > 0 ? 1 : 0);
+  });
+});
+
+function waitFor (test, cb) {
+  if (test()) {
+    cb();
+  } else {
+    setTimeout(function () { waitFor(test, cb); }, 250);
+  }
+}
\ No newline at end of file
diff --git a/test/run.js b/test/run.js
new file mode 100755
index 0000000000000000000000000000000000000000..8477f0966d34de7f15c96ad523be53d22db5655d
--- /dev/null
+++ b/test/run.js
@@ -0,0 +1,25 @@
+#!/usr/bin/env node
+
+var files = new (require('node-static').Server)('.');
+
+var server = require('http').createServer(function (req, res) {
+  req.addListener('end', function () {
+    files.serve(req, res);
+  });
+}).addListener('error', function (err) {
+  throw err;
+}).listen(3000, function () {
+  var child_process = require('child_process');
+  child_process.exec("which phantomjs", function (err) {
+    if (err) {
+      console.error("PhantomJS is not installed. Download from http://phantomjs.org");
+      process.exit(1);
+    }
+    var cmd = 'phantomjs test/phantom_driver.js';
+    child_process.exec(cmd, function (err, stdout) {
+      server.close();
+      console.log(stdout);
+      process.exit(err ? 1 : 0);
+    });
+  });
+});