diff --git a/Makefile b/Makefile
index 2a56369..1522a69 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
 MOCHA_OPTS= --check-leaks
-REPORTER = progress
+REPORTER = spec
 
 test: 
 	@NODE_ENV=test ./node_modules/.bin/mocha \
diff --git a/src/formatter.js b/src/formatter.js
index 63c91ed..fa6d325 100644
--- a/src/formatter.js
+++ b/src/formatter.js
@@ -13,6 +13,23 @@
 
 (function() {
 
+
+  /////////////////////////////////////////////////////
+  // Setup
+  // - inspiration from underscore.js
+  /////////////////////////////////////////////////////
+  
+  // Establish the root object, window in the browser,
+  // or exports on the server.
+  var root = this;
+
+  if (typeof module !== 'undefined' && module.exports) {
+    exports.Formatter = Formatter;
+  } else {
+    root.Formatter = Formatter;
+  }
+
+
   /////////////////////////////////////////////////////
   // Defaults
   /////////////////////////////////////////////////////
@@ -27,7 +44,7 @@
   // Class
   /////////////////////////////////////////////////////
 
-  this.Formatter = function(el, opts) {
+  function Formatter(el, opts) {
     // Cache this
     var self = this;
 
@@ -50,7 +67,7 @@
       // Cache position before manipulating
       var pos = self._getCaretPosition(self.el);
       // Set text value
-      self.el.value = self._addChars(self.el.value);
+      self.el.value = self._addChars(self.el.value, self.chars);
       // Update cursorPosition
       self._updateCursorPos(pos);
     });
@@ -60,13 +77,13 @@
   // @private
   // Create an array holding all input matches
   //
-  Formatter.prototype._findMatches = function () {
+  Formatter.prototype._findMatches = function (str) {
     var matchExp = new RegExp('{{([^}]+)}}', 'g'),
         matches  = [],
         match;
 
     // Create array of matches
-    while(match = matchExp.exec(this.opts.str)) {
+    while(match = matchExp.exec(str)) {
       matches.push(match);
     }
     return matches;
@@ -77,11 +94,11 @@
   // Create an object holding all formatted characters
   // with corresponding positions
   //
-  Formatter.prototype._findChars = function () {
+  Formatter.prototype._findChars = function (str) {
     var DELIM_SIZE = 4;
-    var strLength  = this.opts.str.length,
+    var strLength  = str.length,
         matchIncr  = 0,
-        matches    = this._findMatches(),
+        matches    = this._findMatches(str),
         chars      = {};
 
     // Loop over all characters of the string 
@@ -93,7 +110,7 @@
         i += (match[1].length + DELIM_SIZE - 1);
         matchIncr ++;
       } else {
-        chars[i - (matchIncr * DELIM_SIZE)] = this.opts.str[i];
+        chars[i - (matchIncr * DELIM_SIZE)] = str[i];
       }
     }
     return chars;
@@ -117,13 +134,13 @@
   // @private
   // Return updated string with formatted characters added
   //
-  Formatter.prototype._addChars = function (str) {
+  Formatter.prototype._addChars = function (str, chars) {
     // Does not cache str length as it changes during iteration
     for (var i = 0; i < str.length; i++) {
       // If character exists at position but has not
       // yet been added, add at location
-      if (this.chars[i] && (str[i] !== this.chars[i])) {
-        str = str.substr(0, i) + this.chars[i] + str.substr(i, str.length);
+      if (chars[i] && (str[i] !== chars[i])) {
+        str = str.substr(0, i) + chars[i] + str.substr(i, str.length);
       }
     }
     return str
@@ -144,6 +161,7 @@
         destObj[key] = arguments[i][key];
       }
     }
+    return destObj;
   }
 
   //
diff --git a/test/formatter.js b/test/formatter.js
index 47f2cec..b249827 100644
--- a/test/formatter.js
+++ b/test/formatter.js
@@ -5,21 +5,149 @@
  * MIT LICENCE
  *
  */ 
-var Formatter = require('../lib/base-station'),
-    should    = require('chai').should(),
-    assert    = require('chai').assert;
+
+// 3rd party
+var should = require('chai').should(),
+    assert = require('chai').assert;
+
+// first party
+var Formatter = require('../src/formatter').Formatter;
+
+
+/////////////////////////////////////////////////////
+// Unit Tests
+/////////////////////////////////////////////////////
 
 //
-// Tests
+// ._extend
 //
-describe('Formatter Suite', function () {
+var testExtend = function () {
+  // Setup Data
+  var defaults, opts;
+  defaults = {
+    'extend'   : 'should',
+    'overwrite': 'all'
+  };
+  opts = {
+    'overwrite': 'default',
+    'values'   : 'to',
+    'the'      : 'destObj'
+  };
+
+  // Run extend
+  var result = Formatter.prototype._extend({}, defaults, opts);
+  // Check results
+  assert.deepEqual(result, {
+    'extend'   : 'should',
+    'overwrite': 'default',
+    'values'   : 'to',
+    'the'      : 'destObj'
+  });
+  // Make sure defaults & opts were not changed
+  assert.deepEqual({
+    'extend'   : 'should',
+    'overwrite': 'all'
+  }, defaults);
+  assert.deepEqual({
+    'overwrite': 'default',
+    'values'   : 'to',
+    'the'      : 'destObj'
+  }, opts);
+};
 
-  describe('Formatter unit tests', function () {
+//
+// ._findMatches
+//
+var testFindMatches = function () {
+  // Run _findMatches
+  var testStr = '({{XXX}}) {{XXX}}.{{XXXX}}',
+      result = Formatter.prototype._findMatches(testStr);
+  // Check results
+  assert.deepEqual([
+    { 
+      '0': '{{XXX}}',
+      '1': 'XXX',
+      'index': 1,
+      'input': '({{XXX}}) {{XXX}}.{{XXXX}}'
+    },
+    { 
+      '0': '{{XXX}}',
+      '1': 'XXX',
+      'index': 10,
+      'input': '({{XXX}}) {{XXX}}.{{XXXX}}'
+    },
+    { 
+      '0': '{{XXXX}}',
+      '1': 'XXXX',
+      'index': 18,
+      'input': '({{XXX}}) {{XXX}}.{{XXXX}}'
+    }
+  ], result);
+};
+
+//
+// ._findChars
+//
+var testFindChars = function () {
+  // Run _findMatches
+  var testStr = '({{XXX}}) {{XXX}}.{{XXXX}}',
+    result = Formatter.prototype._findChars(testStr);
 
+  // Check results
+  assert.deepEqual(result, {
+    '0': '(',
+    '4': ')',
+    '5': ' ',
+    '9': '.'
   });
+};
+
+//
+// ._addChars
+//
+var testAddChars = function () {
+  // Cache character pattern
+  var chars = {
+    '0': '(',
+    '4': ')',
+    '5': ' ',
+    '9': '.'
+  };
+
+  // full raw number
+  var fullResult = Formatter.prototype._addChars('8002364717', chars);
+  assert.equal(fullResult, '(800) 236.4717');
+
+  // partial formatted number
+  var partialResult = Formatter.prototype._addChars('(800)236.4717', chars);
+  assert.equal(fullResult, '(800) 236.4717');
+};
 
-  // describe('Formatter functional tests', function () {
 
-  // });
+/////////////////////////////////////////////////////
+// Selenium Tests
+/////////////////////////////////////////////////////
+
+// Comming soon
+
+
+/////////////////////////////////////////////////////
+// Test Suite
+/////////////////////////////////////////////////////
+
+describe('# formatter.js', function () {
+  // Unit
+  describe('# unit tests', function () {
+    describe('# class utils', function () {
+      it('Should return an object with merged properties', testExtend);
+    });
+    describe('# class methods', function () {
+      it('Should create an array holding match objs', testFindMatches);
+      it('Should create an object holding all chars', testFindChars);
+      it('Should add chars to str in correct positions', testAddChars);
+    });
+  });
 
+  // Selenium
+  // describe('selenium tests', seleniumTests);
 });
\ No newline at end of file
