Added custom validation option to xosField component
diff --git a/views/ngXosLib/xosHelpers/spec/ui/custom-validator.test.js b/views/ngXosLib/xosHelpers/spec/ui/custom-validator.test.js
new file mode 100644
index 0000000..76f41a9
--- /dev/null
+++ b/views/ngXosLib/xosHelpers/spec/ui/custom-validator.test.js
@@ -0,0 +1,107 @@
+/**
+ * © OpenCORD
+ *
+ * Created by teone on 5/25/16.
+ */
+
+(function () {
+  'use strict';
+
+  describe('The xos.helper module', function () {
+    describe('The xosCustomValidator directive', () => {
+      let element, scope, isolatedScope, rootScope, compile, form, input;
+      const compileElement = (el) => {
+        element = el;
+
+        if(!scope){
+          scope = rootScope.$new();
+        }
+        if(angular.isUndefined(element)){
+          element = angular.element(`
+            <form name="form">
+              <input name="testInput" type="text" ng-model="value" xos-custom-validator custom-validator="validator"/>
+            </form>
+          `);
+        }
+        compile(element)(scope);
+        scope.$digest();
+        input = $(element).find('input');
+        isolatedScope = angular.element(input).isolateScope();
+        form = scope.form;
+      };
+
+      beforeEach(module('xos.helpers'));
+
+      beforeEach(inject(function ($compile, $rootScope) {
+        compile = $compile;
+        rootScope = $rootScope;
+      }));
+
+      beforeEach(() => {
+        scope = rootScope.$new();
+        scope.validator = 'validator';
+        scope.value = '';
+        compileElement();
+      });
+
+      it('should bind the validator', () => {
+        expect(isolatedScope.fn).toEqual('validator');
+      });
+
+      describe('given a validator function', () => {
+
+        beforeEach(() => {
+          scope = rootScope.$new();
+          scope.value = '';
+          scope.validator = (model) => angular.equals(model, 'test');
+          spyOn(scope, 'validator').and.callThrough();
+          compileElement();
+        });
+
+        it('should call the validator function on value change', () => {
+          form.testInput.$setViewValue('something');
+          scope.$digest();
+          expect(scope.validator).toHaveBeenCalledWith('something');
+          expect(scope.value).toEqual('something');
+        });
+
+        it('should set the field invalid', () => {
+          form.testInput.$setViewValue('something');
+          scope.$digest();
+          expect(scope.validator).toHaveBeenCalledWith('something');
+          expect(input).toHaveClass('ng-invalid');
+          expect(input).toHaveClass('ng-invalid-custom-validation');
+        });
+
+        it('should set the field valid', () => {
+          form.testInput.$setViewValue('test');
+          scope.$digest();
+          expect(scope.validator).toHaveBeenCalledWith('test');
+          expect(input).not.toHaveClass('ng-invalid');
+          expect(input).not.toHaveClass('ng-invalid-custom-validation');
+        });
+
+        describe('if the validation function return an array', () => {
+
+          beforeEach(() => {
+            scope = rootScope.$new();
+            scope.value = '';
+            scope.validator = (model) => {
+              return ['randomTest', angular.equals(model, 'test')];
+            };
+            spyOn(scope, 'validator').and.callThrough();
+            compileElement();
+          });
+
+          it('should set the field invalid', () => {
+            form.testInput.$setViewValue('something');
+            scope.$digest();
+            expect(scope.validator).toHaveBeenCalledWith('something');
+            expect(input).toHaveClass('ng-invalid');
+            expect(input).toHaveClass('ng-invalid-random-test');
+          });
+        });
+      });
+    });
+  });
+})();
\ No newline at end of file
diff --git a/views/ngXosLib/xosHelpers/spec/ui/field.test.js b/views/ngXosLib/xosHelpers/spec/ui/field.test.js
index 8b32585..8a02d4d 100644
--- a/views/ngXosLib/xosHelpers/spec/ui/field.test.js
+++ b/views/ngXosLib/xosHelpers/spec/ui/field.test.js
@@ -7,24 +7,23 @@
 (function () {
   'use strict';
 
-  let element, scope, isolatedScope, rootScope, compile;
-  const compileElement = (el) => {
-    element = el;
-
-    if(!scope){
-      scope = rootScope.$new();
-    }
-    if(angular.isUndefined(element)){
-      element = angular.element('<xos-field name="name" field="field" ng-model="ngModel"></xos-field>');
-    }
-    compile(element)(scope);
-    scope.$digest();
-    isolatedScope = element.isolateScope().vm;
-  };
-
   describe('The xos.helper module', function(){
 
     describe('The xosField component', () => {
+      let element, scope, isolatedScope, rootScope, compile;
+      const compileElement = (el) => {
+        element = el;
+
+        if(!scope){
+          scope = rootScope.$new();
+        }
+        if(angular.isUndefined(element)){
+          element = angular.element('<xos-field name="name" field="field" ng-model="ngModel"></xos-field>');
+        }
+        compile(element)(scope);
+        scope.$digest();
+        isolatedScope = element.isolateScope().vm;
+      };
 
       beforeEach(module('xos.helpers'));
 
@@ -93,7 +92,9 @@
           scope.field = {
             label: 'Label',
             type: 'text',
-            validators: {}
+            validators: {
+              custom: 'fake'
+            }
           };
           scope.ngModel = 'label';
           compileElement();
@@ -102,6 +103,12 @@
         it('should print a text field', () => {
           expect($(element).find('[name="label"]')).toHaveAttr('type', 'text');
         });
+
+        it('should attach the custom validator directive', () => {
+          let input = $(element).find('[name="label"]');
+          expect(input).toHaveAttr('xos-custom-validator');
+          expect(input).toHaveAttr('custom-validator', 'vm.field.validators.custom || null');
+        });
       });
 
       describe('when a option is selected in dropdown', () => {
@@ -266,7 +273,6 @@
         });
       });
 
-      // NOTE not sure why this tests are failing
       describe('when validation options are passed', () => {
         let input;
         describe('given a a text field', () => {