xosSmartPie done
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