Properly mocked resources and promises
diff --git a/views/ngXosLib/xosHelpers/spec/ui/smart-table.test.js b/views/ngXosLib/xosHelpers/spec/ui/smart-table.test.js
index b145354..8a94632 100644
--- a/views/ngXosLib/xosHelpers/spec/ui/smart-table.test.js
+++ b/views/ngXosLib/xosHelpers/spec/ui/smart-table.test.js
@@ -23,27 +23,53 @@
 
       beforeEach(module('xos.helpers'));
 
+      beforeEach(function() {
+        jasmine.addMatchers({
+          toBeInstanceOf: function() {
+
+            return {
+              compare: (actual, expected) => {
+                var actual = actual;
+                var result = {};
+                result.pass = actual instanceof expected.constructor;
+
+                result.message = 'Expected ' + actual + ' to be instance of ' + expected;
+
+                return result;
+              },
+              negativeCompare: (actual, expected) => {
+                var actual = actual;
+                var result = {};
+                result.pass = actual instanceof expected.constructor === false;
+
+                result.message = 'Expected ' + actual + ' to be instance of ' + expected;
+
+                return result;
+              }
+            }
+          }
+        });
+      });
+
       // mock the service
       beforeEach(function(){
         module(function($provide){
           $provide.service('MockResource', function(){
-            this.query = jasmine.createSpy('query').and.callFake(() => {
-              return {$promise: {then: (cb) => cb(mockData)}};
-            });
-            this.delete = jasmine.createSpy('delete').and.callFake(() => {
-              return {$promise: {then: (cb) => cb({})}};
-            });
+            return {
+              query: '',
+              delete: ''
+            }
           });
 
           $provide.service('EmptyResource', function(){
-            this.query = jasmine.createSpy('emptyQuery').and.callFake(() => {
-              return {$promise: {then: (cb) => cb([])}};
-            });
+            return {
+              query: ''
+            }
           });
         });
       })
 
-      beforeEach(inject(function ($compile, $rootScope, MockResource) {
+      beforeEach(inject(function ($compile, $rootScope, $q, MockResource) {
         scope = $rootScope.$new();
 
         scope.config = {
@@ -53,6 +79,18 @@
 
         spy = MockResource;
 
+        spyOn(MockResource, 'query').and.callFake(function() {
+          var deferred = $q.defer();
+          deferred.resolve(mockData);
+          return {$promise: deferred.promise};
+        });
+
+        spyOn(MockResource, 'delete').and.callFake(function() {
+          var deferred = $q.defer();
+          deferred.resolve();
+          return {$promise: deferred.promise};
+        });
+
         element = angular.element('<xos-smart-table config="config"></xos-smart-table>');
         $compile(element)(scope);
         scope.$digest();
@@ -90,31 +128,51 @@
         };
         scope.$apply();
         expect($(element).find('.panel')).not.toHaveClass('ng-hide');
-        console.log($(element).find('.panel .col-xs-1 a'));
         $(element).find('.panel .col-xs-1 a')[0].click();
         expect($(element).find('.panel')[0]).toHaveClass('ng-hide');
       });
 
-      it('should save an item', () => {
-        const saveMethod = jasmine.createSpy('$save').and.callFake(() => {
-          return {then: (cb) => cb(mockData[0])};
-        });
+      it('should save an item', inject(($q) => {
+
         let model = {
           id: 1,
           first_name: 'Jon',
           last_name: 'Snow',
           hidden_field: 'hidden',
-          $save: saveMethod
+          $save: ''
         };
+
+        spyOn(model, '$save').and.callFake(function() {
+          var deferred = $q.defer();
+          deferred.resolve();
+          return deferred.promise;
+        });
+
         isolatedScope.detailedItem = model;
         scope.$apply();
         $(element).find('xos-form .btn.btn-success').click();
-        expect(saveMethod).toHaveBeenCalled();
+        expect(model.$save).toHaveBeenCalled();
+      }));
+
+      it('should have an add button', () => {
+        let addBtn = $(element).find('.row .btn.btn-success');
+        expect(addBtn.parent().parent()).not.toHaveClass('ng-hide');
       });
 
+      describe('when the add button is clicked', () => {
+        beforeEach(() => {
+          let btn = $(element).find('.row .btn.btn-success')
+          btn[0].click();
+        });
+
+        xit('should create a new model', () => {
+          expect(isolatedScope.detailedItem).toBeDefined();
+          expect(isolatedScope.detailedItem).toBeInstanceOf('Resource');
+        });
+      });
 
       describe('when fetching an empty collection', () => {
-        beforeEach(inject(function ($compile, $rootScope, EmptyResource) {
+        beforeEach(inject(function ($compile, $rootScope, $q, EmptyResource) {
           scope = $rootScope.$new();
 
           scope.config = {
@@ -123,6 +181,12 @@
 
           emptySpy = EmptyResource;
 
+          spyOn(EmptyResource, 'query').and.callFake(function() {
+            var deferred = $q.defer();
+            deferred.resolve([]);
+            return {$promise: deferred.promise};
+          });
+
           element = angular.element('<xos-smart-table config="config"></xos-smart-table>');
           $compile(element)(scope);
           scope.$digest();
@@ -134,6 +198,11 @@
           expect($(element).find('.alert').parent().parent()).not.toHaveClass('ng-hide');
           expect($(element).find('.alert')).toContainText('No data to show');
         });
+
+        it('should not have an add button', () => {
+          let addBtn = $(element).find('.row .btn.btn-success');
+          expect(addBtn.parent().parent()).toHaveClass('ng-hide');
+        });
       });
 
 
diff --git a/views/ngXosLib/xosHelpers/src/styles/main.scss b/views/ngXosLib/xosHelpers/src/styles/main.scss
index 0780d49..a427ea6 100644
--- a/views/ngXosLib/xosHelpers/src/styles/main.scss
+++ b/views/ngXosLib/xosHelpers/src/styles/main.scss
@@ -4,6 +4,8 @@
 @import '../ui_components/dumbComponents/alert/alert.scss';
 @import '../ui_components/dumbComponents/validation/validation.scss';
 
+@import '../ui_components/smartComponents/smartTable/smartTable.scss';
+
 [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
   display: none !important;
 }
\ No newline at end of file
diff --git a/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/table/table.scss b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/table/table.scss
index cf1a30d..46c4460 100644
--- a/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/table/table.scss
+++ b/views/ngXosLib/xosHelpers/src/ui_components/dumbComponents/table/table.scss
@@ -1,10 +1,8 @@
 @import '../../../styles/animations.scss';
 
 xos-table {
-  
-  tr {
-    font-weight: bold;
-  }
+
+  display: block;
 
   tr.ng-move,
   tr.ng-enter,
diff --git a/views/ngXosLib/xosHelpers/src/ui_components/smartComponents/smartTable/smartTable.component.js b/views/ngXosLib/xosHelpers/src/ui_components/smartComponents/smartTable/smartTable.component.js
index d9fa9cc..b339f89 100644
--- a/views/ngXosLib/xosHelpers/src/ui_components/smartComponents/smartTable/smartTable.component.js
+++ b/views/ngXosLib/xosHelpers/src/ui_components/smartComponents/smartTable/smartTable.component.js
@@ -28,7 +28,13 @@
         config: '='
       },
       template: `
-        <pre>{{vm.responseErr}}</pre>
+        <div class="row" ng-show="vm.data.length > 0">
+          <div class="col-xs-12 text-right">
+            <a href="" class="btn btn-success" ng-click="vm.createItem()">
+              Add
+            </a>
+          </div>
+        </div>
         <xos-table config="vm.tableConfig" data="vm.data"></xos-table>
         <div class="panel panel-default" ng-show="vm.detailedItem">
           <div class="panel-heading">
@@ -54,6 +60,10 @@
       controllerAs: 'vm',
       controller: function($injector, LabelFormatter, _){
         
+        // NOTE
+        // Corner case
+        // - if response is empty, how can we generate a form ?
+
         this.responseMsg = false;
         this.responseErr = false;
 
@@ -67,7 +77,6 @@
               cb: (item) => {
                 this.Resource.delete({id: item.id}).$promise
                 .then(() => {
-                  console.log(this.config.resource);
                   this.responseMsg = `${this.config.resource} with id ${item.id} successfully deleted`;
                 })
                 .catch(err => {
@@ -115,7 +124,12 @@
 
         this.cleanForm = () => {
           delete this.detailedItem;
-        }
+        };
+
+        this.createItem = () => {
+          this.detailedItem = new this.Resource();
+          console.log(this.detailedItem);
+        };
 
         this.Resource = $injector.get(this.config.resource);
 
diff --git a/views/ngXosLib/xosHelpers/src/ui_components/smartComponents/smartTable/smartTable.scss b/views/ngXosLib/xosHelpers/src/ui_components/smartComponents/smartTable/smartTable.scss
new file mode 100644
index 0000000..03342f1
--- /dev/null
+++ b/views/ngXosLib/xosHelpers/src/ui_components/smartComponents/smartTable/smartTable.scss
@@ -0,0 +1,5 @@
+xos-smart-table{
+  .row + xos-table {
+    margin-top: 15px;
+  }
+}
\ No newline at end of file