xosSmartPie done
diff --git a/views/ngXosLib/README.md b/views/ngXosLib/README.md
index f4b9c8f..b19cd1f 100644
--- a/views/ngXosLib/README.md
+++ b/views/ngXosLib/README.md
@@ -39,6 +39,9 @@
 
 To develop components inside this folder there is a particular command: `npm run dev`, this will watch the helpers file and rebuild them with sourcemaps. For this reason remember to build them when done developing.
 
+>While developing components in this library you should execute the test. The `npm test` command will run Jasmine test for the whole complete library.
+>If you want to specify a single test file to be execute, you can add it to the command like: `npm test smart-pie`, the tool will now read only the test specified in the `smart-pie.test.js` file.
+
 When some changes are applied to this common library it should be rebuilt with: `npm run build`
 
 To generate the relative documentation use: `npm run doc`
diff --git a/views/ngXosLib/karma.conf.js b/views/ngXosLib/karma.conf.js
index 36ddda1..ed2ec3e 100644
--- a/views/ngXosLib/karma.conf.js
+++ b/views/ngXosLib/karma.conf.js
@@ -3,6 +3,12 @@
 
 /* eslint indent: [2,2], quotes: [2, "single"]*/
 
+// this is to load a different suite of test while developing
+var testFiles = '*';
+if(process.argv[4]){
+  testFiles = process.argv[4];
+}
+
 /*eslint-disable*/
 var wiredep = require('wiredep');
 var path = require('path');
@@ -15,7 +21,7 @@
   'node_modules/babel-polyfill/dist/polyfill.js',
   'xosHelpers/src/**/*.module.js',
   'xosHelpers/src/**/*.js',
-  'xosHelpers/spec/**/*.test.js'
+  `xosHelpers/spec/**/${testFiles}.test.js`
   // 'xosHelpers/spec/ui/smart-pie.test.js'
 ]);
 
@@ -89,7 +95,7 @@
     // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
     browsers: [
       'PhantomJS',
-      'Chrome'
+      // 'Chrome'
     ],
 
 
diff --git a/views/ngXosLib/package.json b/views/ngXosLib/package.json
index c4f902d..e0fa151 100644
--- a/views/ngXosLib/package.json
+++ b/views/ngXosLib/package.json
@@ -4,7 +4,7 @@
   "description": "Angular Version of XosLib, containing Helpers and ngResources",
   "main": "index.js",
   "scripts": {
-    "test": "karma start",
+    "test": "karma start karma.conf.js",
     "test:ci": "karma start karma.conf.ci.js",
     "apigen": "node apigen/blueprintToNgResource.js",
     "swagger": "node xos-swagger-def.js",
diff --git a/views/ngXosLib/xosHelpers/spec/ui/smart-pie.test.js b/views/ngXosLib/xosHelpers/spec/ui/smart-pie.test.js
index 7106e35..4c90421 100644
--- a/views/ngXosLib/xosHelpers/spec/ui/smart-pie.test.js
+++ b/views/ngXosLib/xosHelpers/spec/ui/smart-pie.test.js
@@ -7,16 +7,37 @@
 (function () {
   'use strict';
 
-  let mockData;
+  let mockData, compile, rootScope, spy, scope, isolatedScope, element, interval;
+
+  const compileElement = () => {
+
+    if(!scope){
+      scope = rootScope.$new();
+    }
+
+    element = angular.element('<xos-smart-pie config="config"></xos-smart-pie>');
+    compile(element)(scope);
+    scope.$digest();
+    isolatedScope = element.isolateScope().vm;
+  }
 
   describe('The xos.helper module', function(){
     describe('The xos-smart-pie component', () => {
 
-      var spy, scope, isolatedScope, element, interval;
 
       beforeEach(module('xos.helpers'));
 
-      beforeEach(function() {
+      beforeEach(function(){
+        module(function($provide){
+          $provide.service('MockResource', function(){
+            return {
+              query: ''
+            }
+          });
+        });
+      });
+
+      beforeEach(inject(function ($compile, $rootScope) {
 
         // set mockData
         mockData = [
@@ -40,106 +61,151 @@
           }
         ]
 
-      });
-
-      // mock the service
-      beforeEach(function(){
-        module(function($provide){
-          $provide.service('MockResource', function(){
-            return {
-              query: ''
-            }
-          });
-        });
-      })
-
-      beforeEach(inject(function ($compile, $rootScope, $q, MockResource) {
-        scope = $rootScope.$new();
-
-        scope.config = {
-          resource: 'MockResource',
-          groupBy: 'category',
-          classes: 'my-test-class'
-        };
-
-        spy = MockResource;
-
-        spyOn(MockResource, 'query').and.callFake(function() {
-          var deferred = $q.defer();
-          deferred.resolve(mockData);
-          return {$promise: deferred.promise};
-        });
-
-        element = angular.element('<xos-smart-pie config="config"></xos-smart-pie>');
-        $compile(element)(scope);
-        scope.$digest();
-        isolatedScope = element.isolateScope().vm;
+        compile = $compile;
+        rootScope = $rootScope;
       }));
 
-      it('should attach provided classes', () => {
-        expect($(element).find('canvas')).toHaveClass('my-test-class');
-      });
-
-      it('should group elements', () => {
-        let groupedData = [2, 1];
-        expect(spy.query).toHaveBeenCalled();
-        expect(isolatedScope.data).toEqual(groupedData);
-      });
-
-      describe('when a labelFormatter function is provided', () => {
-        beforeEach(inject(function ($compile, $rootScope){
+      it('should throw an error if no resource and no data are passed in the config', inject(($compile, $rootScope) => {
+        function errorFunctionWrapper(){
+          // setup the parent scope
           scope = $rootScope.$new();
+          scope.config = {};
+          compileElement();
+        }
+        expect(errorFunctionWrapper).toThrow(new Error('[xosSmartPie] Please provide a resource or an array of data in the configuration'));
+      }));
+
+      describe('when data are passed in the configuration', () => {
+        beforeEach(inject(function ($compile, $rootScope) {
+          scope = $rootScope.$new();
+
           scope.config = {
-            resource: 'MockResource',
+            data: mockData,
             groupBy: 'category',
-            classes: 'label-formatter-test',
-            labelFormatter: (labels) => {
+            classes: 'my-test-class'
+          };
+
+          compileElement();
+        }));
+        
+
+        it('should attach provided classes', () => {
+          expect($(element).find('canvas')).toHaveClass('my-test-class');
+        });
+
+        it('should group elements', () => {
+          let groupedData = [2, 1];
+          expect(isolatedScope.data).toEqual(groupedData);
+        });
+
+        describe('when a labelFormatter function is provided', () => {
+          beforeEach(() => {
+            scope.config.labelFormatter = (labels) => {
               return labels.map(l => l === '1' ? 'First' : 'Second');
-            }
-          };
-          element = angular.element('<xos-smart-pie config="config"></xos-smart-pie>');
-          $compile(element)(scope);
-          scope.$digest();
-          isolatedScope = element.isolateScope().vm;
-        }));
+            };
+            compileElement();
+          });
+          it('should format labels', () => {
+            expect(isolatedScope.labels).toEqual(['First', 'Second'])
+          });
+        });
 
-        it('should format labels', () => {
-          expect(isolatedScope.labels).toEqual(['First', 'Second'])
+        describe('when provided data changes', () => {
+          beforeEach(() => {
+            scope.config.data.push({
+              id: 2,
+              first_name: 'Danaerys',
+              last_name: 'Targaryen',
+              category: 1
+            });
+            scope.$digest();
+          });
+          it('should calculate again the data', () => {
+            expect(isolatedScope.data).toEqual([3, 1]);
+          });
         });
       });
 
-      describe('when polling is enabled', () => {
-        beforeEach(inject(function ($compile, $rootScope, $interval){
+      
+      describe('when a resource is specified in the configuration', () => {
 
-          //mocked $interval (by ngMock)
-          interval = $interval;
-
-          // cleaning the spy
-          spy.query.calls.reset()
-
+        beforeEach(inject(function ($compile, $rootScope, $q, MockResource) {
           scope = $rootScope.$new();
+
           scope.config = {
             resource: 'MockResource',
             groupBy: 'category',
-            classes: 'label-formatter-test',
-            poll: 2
+            classes: 'my-test-class'
           };
-          element = angular.element('<xos-smart-pie config="config"></xos-smart-pie>');
-          $compile(element)(scope);
-          scope.$digest();
-          isolatedScope = element.isolateScope().vm;
+
+          spy = MockResource;
+
+          spyOn(MockResource, 'query').and.callFake(function() {
+            var deferred = $q.defer();
+            deferred.resolve(mockData);
+            return {$promise: deferred.promise};
+          });
+
+          compileElement();
         }));
 
-        it('should call the backend every 2 second', () => {
+
+        it('should call the server and group elements', () => {
+          let groupedData = [2, 1];
           expect(spy.query).toHaveBeenCalled();
-          expect(spy.query.calls.count()).toEqual(1);
-          interval.flush(2000);
-          expect(spy.query.calls.count()).toEqual(2);
-          interval.flush(2000);
-          expect(spy.query.calls.count()).toEqual(3)
+          expect(isolatedScope.data).toEqual(groupedData);
+        });
+
+        describe('when a labelFormatter function is provided', () => {
+          beforeEach(inject(function ($compile, $rootScope){
+            scope = $rootScope.$new();
+            scope.config = {
+              resource: 'MockResource',
+              groupBy: 'category',
+              classes: 'label-formatter-test',
+              labelFormatter: (labels) => {
+                return labels.map(l => l === '1' ? 'First' : 'Second');
+              }
+            };
+            compileElement();
+          }));
+
+          it('should format labels', () => {
+            expect(isolatedScope.labels).toEqual(['First', 'Second'])
+          });
+        });
+
+        describe('when polling is enabled', () => {
+          beforeEach(inject(function ($compile, $rootScope, $interval){
+
+            //mocked $interval (by ngMock)
+            interval = $interval;
+
+            // cleaning the spy
+            spy.query.calls.reset()
+
+            scope = $rootScope.$new();
+            scope.config = {
+              resource: 'MockResource',
+              groupBy: 'category',
+              classes: 'label-formatter-test',
+              poll: 2
+            };
+            compileElement();
+          }));
+
+          it('should call the backend every 2 second', () => {
+            expect(spy.query).toHaveBeenCalled();
+            expect(spy.query.calls.count()).toEqual(1);
+            interval.flush(2000);
+            expect(spy.query.calls.count()).toEqual(2);
+            interval.flush(2000);
+            expect(spy.query.calls.count()).toEqual(3)
+          });
         });
       });
 
+
     });
   });
 })();
\ No newline at end of file
diff --git a/views/ngXosLib/xosHelpers/spec/ui/table.test.js b/views/ngXosLib/xosHelpers/spec/ui/table.test.js
index 7279995..a6d85c8 100644
--- a/views/ngXosLib/xosHelpers/spec/ui/table.test.js
+++ b/views/ngXosLib/xosHelpers/spec/ui/table.test.js
@@ -94,7 +94,6 @@
         xdescribe('when a field type is provided', () => {
           describe('and is boolean', () => {
             beforeEach(() => {
-              console.log('iS: ' + isolatedScope);
               isolatedScope.config = {
                 columns: [
                   {
@@ -118,7 +117,6 @@
             it('should render an incon', () => {
               let td1 = $(element).find('tbody tr:first-child td')[0];
               let td2 = $(element).find('tbody tr:last-child td')[0];
-              console.log(td2);
               expect($(td1).find('i')).toHaveClass('glyphicon-ok');
               expect($(td2).find('i')).toHaveClass('glyphicon-remove');
             });
@@ -126,7 +124,6 @@
 
           describe('and is date', () => {
             beforeEach(() => {
-              console.log('iS: ' + isolatedScope);
               isolatedScope.config = {
                 columns: [
                   {
diff --git a/views/ngXosLib/xosHelpers/src/ui_components/smartComponents/smartPie/smartPie.component.js b/views/ngXosLib/xosHelpers/src/ui_components/smartComponents/smartPie/smartPie.component.js
index 2290583..6616b50 100644
--- a/views/ngXosLib/xosHelpers/src/ui_components/smartComponents/smartPie/smartPie.component.js
+++ b/views/ngXosLib/xosHelpers/src/ui_components/smartComponents/smartPie/smartPie.component.js
@@ -32,14 +32,97 @@
     * ```
     * @scope
     * @example
-     <example module="sampleSmartPie">
+    
+    Displaying Local data
+
+    <example module="sampleSmartPieLocal">
+      <file name="index.html">
+        <div ng-controller="SampleCtrlLocal as vm">
+          <xos-smart-pie config="vm.configLocal"></xos-smart-pie>
+        </div>
+      </file>
+      <file name="script.js">
+        angular.module('sampleSmartPieLocal', ['xos.uiComponents'])
+        .factory('_', function($window){
+          return $window._;
+        })
+        .controller('SampleCtrlLocal', function($timeout){
+          
+          this.datas = [
+            {id: 1, first_name: 'Jon', last_name: 'aaa', category: 2},
+            {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 1},
+            {id: 3, first_name: 'Aria', last_name: 'Stark', category: 2}
+          ];
+
+          this.configLocal = {
+            data: [],
+            groupBy: 'category',
+            classes: 'local',
+            labelFormatter: (labels) => {
+              return labels.map(l => l === '1' ? 'North' : 'Dragon');
+            }
+          };
+          
+          $timeout(() => {
+            // this need to be triggered in this way just because of ngDoc,
+            // otherwise you can assign data directly in the config
+            this.configLocal.data = this.datas;
+          }, 1)
+        });
+      </file>
+    </example>
+
+    Fetching data from API
+
+    <example module="sampleSmartPieResource">
       <file name="index.html">
         <div ng-controller="SampleCtrl as vm">
           <xos-smart-pie config="vm.config"></xos-smart-pie>
         </div>
       </file>
       <file name="script.js">
-        angular.module('sampleSmartPie', ['xos.uiComponents', 'ngResource', 'ngMockE2E'])
+        angular.module('sampleSmartPieResource', ['xos.uiComponents', 'ngResource', 'ngMockE2E'])
+        .controller('SampleCtrl', function(){
+          this.config = {
+            resource: 'SampleResource',
+            groupBy: 'category',
+            classes: 'resource',
+            labelFormatter: (labels) => {
+              return labels.map(l => l === '1' ? 'North' : 'Dragon');
+            }
+          };
+        });
+      </file>
+      <file name="backendPoll.js">
+        angular.module('sampleSmartPieResource')
+        .run(function($httpBackend, _){
+          let datas = [
+            {id: 1, first_name: 'Jon', last_name: 'Snow', category: 1},
+            {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 2},
+            {id: 3, first_name: 'Aria', last_name: 'Stark', category: 1}
+          ];
+
+          $httpBackend.whenGET('/test').respond(200, datas)
+        })
+        .factory('_', function($window){
+          return $window._;
+        })
+        .service('SampleResource', function($resource){
+          return $resource('/test/:id', {id: '@id'});
+        })
+      </file>
+    </example>
+
+    Polling data from API
+
+    <example module="sampleSmartPiePoll">
+      <file name="index.html">
+        <div ng-controller="SampleCtrl as vm">
+          <xos-smart-pie config="vm.config"></xos-smart-pie>
+        </div>
+      </file>
+      <file name="script.js">
+        angular.module('sampleSmartPiePoll', ['xos.uiComponents', 'ngResource', 'ngMockE2E'])
         .controller('SampleCtrl', function(){
           this.config = {
             resource: 'SampleResource',
@@ -52,7 +135,7 @@
         });
       </file>
       <file name="backend.js">
-        angular.module('sampleSmartPie')
+        angular.module('sampleSmartPiePoll')
         .run(function($httpBackend, _){
           let mock = [
             [
@@ -88,44 +171,6 @@
         })
       </file>
     </example>
-
-    <example module="sampleSmartPiePoll">
-      <file name="index.html">
-        <div ng-controller="SampleCtrl as vm">
-          <xos-smart-pie config="vm.config"></xos-smart-pie>
-        </div>
-      </file>
-      <file name="script.js">
-        angular.module('sampleSmartPiePoll', ['xos.uiComponents', 'ngResource', 'ngMockE2E'])
-        .controller('SampleCtrl', function(){
-          this.config = {
-            resource: 'SampleResource',
-            groupBy: 'category',
-            labelFormatter: (labels) => {
-              return labels.map(l => l === '1' ? 'North' : 'Dragon');
-            }
-          };
-        });
-      </file>
-      <file name="backendPoll.js">
-        angular.module('sampleSmartPiePoll')
-        .run(function($httpBackend, _){
-          let datas = [
-            {id: 1, first_name: 'Jon', last_name: 'Snow', category: 1},
-            {id: 2, first_name: 'Danaerys', last_name: 'Targaryen', category: 2},
-            {id: 3, first_name: 'Aria', last_name: 'Stark', category: 1}
-          ];
-
-          $httpBackend.whenGET('/test').respond(200, datas)
-        })
-        .factory('_', function($window){
-          return $window._;
-        })
-        .service('SampleResource', function($resource){
-          return $resource('/test/:id', {id: '@id'});
-        })
-      </file>
-    </example>
     */
   .directive('xosSmartPie', function(){
     return {
@@ -142,31 +187,53 @@
       `,
       bindToController: true,
       controllerAs: 'vm',
-      controller: function($injector, $timeout, $interval, _){
+      controller: function($injector, $timeout, $interval, $scope, _){
 
-        this.Resource = $injector.get(this.config.resource);
+        if(!this.config.resource && !this.config.data){
+          throw new Error('[xosSmartPie] Please provide a resource or an array of data in the configuration');
+        }
 
-        const getData = () => {
-          this.Resource.query().$promise
-          .then((res) => {
+        const groupData = (data) => _.groupBy(data, this.config.groupBy);
+        const formatData = (data) => _.reduce(Object.keys(data), (list, group) => list.concat(data[group].length), []);
+        const formatLabels = (data) => angular.isFunction(this.config.labelFormatter) ? this.config.labelFormatter(Object.keys(data)) : Object.keys(data);
 
-            if(!res[0]){
-              return;
+        const prepareData = (data) => {
+          // group data
+          let grouped = groupData(data);
+          this.data = formatData(grouped);
+          // create labels
+          this.labels = formatLabels(grouped);
+        }
+
+        if(this.config.resource){
+
+          this.Resource = $injector.get(this.config.resource);
+          const getData = () => {
+            this.Resource.query().$promise
+            .then((res) => {
+
+              if(!res[0]){
+                return;
+              }
+
+              prepareData(res);
+            });
+          }
+
+          getData();
+
+          if(this.config.poll){
+            $interval(() => {getData()}, this.config.poll * 1000)
+          }
+        }
+        else {
+          $scope.$watch(() => this.config.data, (data) => {
+            if(data){
+              prepareData(this.config.data);
             }
-
-            // group data
-            let grouped = _.groupBy(res, this.config.groupBy);
-            this.data = _.reduce(Object.keys(grouped), (data, group) => data.concat(grouped[group].length), []);
-            // create labels
-            this.labels = angular.isFunction(this.config.labelFormatter) ? this.config.labelFormatter(Object.keys(grouped)) : Object.keys(grouped);
-          });
+          }, true);
         }
 
-        getData();
-
-        if(this.config.poll){
-          $interval(() => {getData()}, this.config.poll * 1000)
-        }
       }
     };
   });