diff --git a/test/public/app.js b/test/public/app.js
new file mode 100644
index 0000000..c9fa008
--- /dev/null
+++ b/test/public/app.js
@@ -0,0 +1,64 @@
+
+window.onload = runTests;
+
+function get(id) {
+  return document.getElementById(id);
+}
+
+function create(type) {
+  return document.createElement(type);
+}
+
+function runTests() {
+  var table = get('tests');
+  for (var name in tests) {
+    var canvas = create('canvas')
+      , tr = create('tr')
+      , tds = [create('td'), create('td')];
+    canvas.width = 200;
+    canvas.height = 200;
+    tds[1].appendChild(canvas);
+    tr.appendChild(tds[0]);
+    tr.appendChild(tds[1]);
+    table.appendChild(tr);
+    runTest(name, canvas, tds[0]);
+  }
+}
+
+function runTest(name, canvas, dest) {
+  var fn = tests[name];
+  fn(canvas.getContext('2d'));
+  renderOnServer(name, canvas, function(res){
+    if (res.error) {
+      var p = create('p');
+      p.innerText = res.error;
+      dest.appendChild(p);
+    } else if (res.data) {
+      var img = create('image');
+      img.src = res.data;
+      img.alt = name;
+      dest.appendChild(img);
+    }
+  });
+}
+
+function renderOnServer(name, canvas, fn) {
+  var req = new XMLHttpRequest
+    , json = JSON.stringify({
+      fn: tests[name].toString()
+      , width: canvas.width
+      , height: canvas.height
+    });
+  req.open('POST', '/render');
+  req.setRequestHeader('Content-Type', 'application/json');
+  req.onreadystatechange = function(){
+    if (4 == req.readyState) {
+      try {
+        fn(JSON.parse(req.responseText));
+      } catch (err) {
+        fn({ error: err });
+      }
+    }
+  };
+  req.send(json);
+}
\ No newline at end of file
diff --git a/test/public/style.css b/test/public/style.css
index d304d49..3e779ae 100644
--- a/test/public/style.css
+++ b/test/public/style.css
@@ -11,6 +11,13 @@ em {
 a {
   color: #00C5F7;
 }
+canvas, img {
+  padding: 5px;
+  border: 1px solid #eee;
+}
 #primary {
   width: 600px;
+}
+#tests {
+  margin-top: 35px;
 }
\ No newline at end of file
diff --git a/test/public/tests.js b/test/public/tests.js
new file mode 100644
index 0000000..36375fe
--- /dev/null
+++ b/test/public/tests.js
@@ -0,0 +1,33 @@
+
+var tests = {};
+
+tests['linear gradients'] = function(ctx){
+  var lingrad = ctx.createLinearGradient(0,0,0,150);
+  lingrad.addColorStop(0, '#00ABEB');
+  lingrad.addColorStop(0.5, '#fff');
+  lingrad.addColorStop(0.5, '#26C000');
+  lingrad.addColorStop(1, '#fff');
+
+  var lingrad2 = ctx.createLinearGradient(0,50,0,95);
+  lingrad2.addColorStop(0.5, '#000');
+  lingrad2.addColorStop(1, 'rgba(0,0,0,0)');
+
+  ctx.fillStyle = lingrad;
+  ctx.strokeStyle = lingrad2;
+
+  ctx.fillRect(10,10,130,130);
+  ctx.strokeRect(50,50,50,50);  
+};
+
+tests['global alpha'] = function(ctx){
+  ctx.globalAlpha = 0.5;
+  ctx.fillStyle = 'rgba(0,0,0,0.5)';
+  ctx.strokeRect(0,0,50,50);
+
+  ctx.globalAlpha = 0.8;
+  ctx.fillRect(20,20,20,20);
+
+  ctx.fillStyle = 'black';
+  ctx.globalAlpha = 1;
+  ctx.fillRect(25,25,10,10);
+};
\ No newline at end of file
diff --git a/test/server.js b/test/server.js
index a65daef..e170f8c 100644
--- a/test/server.js
+++ b/test/server.js
@@ -4,6 +4,7 @@
  */
 
 var express = require('../support/express')
+  , Canvas = require('../lib/canvas')
   , jade = require('../support/jade')
   , app = express.createServer();
 
@@ -17,6 +18,7 @@ app.set('view engine', 'jade');
 
 app.use(express.favicon());
 app.use(express.logger({ format: '\x1b[90m:remote-addr\x1b[0m - \x1b[33m:method\x1b[0m :url :status \x1b[90m:response-timems\x1b[0m' }));
+app.use(express.bodyDecoder());
 app.use(app.router);
 app.use(express.staticProvider(__dirname + '/public'));
 app.use(express.errorHandler({ showStack: true }));
@@ -27,5 +29,16 @@ app.get('/', function(req, res){
   res.render('tests');
 });
 
+app.post('/render', function(req, res, next){
+  // Do not try this at home :)
+  var fn = eval('(' + req.body.fn + ')')
+    , width = req.body.width
+    , height = req.body.height
+    , canvas = new Canvas(width, height)
+    , ctx = canvas.getContext('2d');
+  fn(ctx);
+  res.send({ data: canvas.toDataURL() });
+});
+
 app.listen(3000);
 console.log('Test server listening on port %d', app.address().port);
\ No newline at end of file
diff --git a/test/views/layout.jade b/test/views/layout.jade
index f6391f5..0dd190a 100644
--- a/test/views/layout.jade
+++ b/test/views/layout.jade
@@ -3,5 +3,7 @@ html
   head
     title node-canvas
     link(href='/style.css', rel='stylesheet')
+    script(src='/tests.js')
+    script(src='/app.js')
   body
     #primary!= body
diff --git a/test/views/tests.jade b/test/views/tests.jade
index bcb1fc9..6558860 100644
--- a/test/views/tests.jade
+++ b/test/views/tests.jade
@@ -1,5 +1,12 @@
 h1 node-canvas
+
 p.msg
   | The tests below assert visual and api integrity by running the
   em exact
-  | same code utilizing the client canvas api, as well as node-canvas.
\ No newline at end of file
+  | same code utilizing the client canvas api, as well as node-canvas.
+
+table#tests
+  thead
+    th node-canvas
+    th target
+  tbody
\ No newline at end of file