jeudi 9 juillet 2015

Testing an Angular Controller that uses Datatables - mocking DTOptionsBuilder and DT ColumnBuilder

I'm trying to write a test for an Angular controller that mostly creates a datatable of values from the server. I've tried mocking DTOptionsBuilder and DTColumnBuilder but this doesn't seem to work. I get the error:

'undefined' is not an object (evaluating 'DTOptionsBuilder.fromFnPromise(function(){ return MarketsFactory.getAll(); }) .withDataProp')

Here is the Controller code:

.controller('MarketsCtrl', function($scope, $compile, $state, MarketsFactory, 

DTOptionsBuilder, DTColumnBuilder) {

    $scope.edit = function(data){
        $state.go('admin.market', {id:data});
    };

    //DATATABLES CONFIGURATIONS

    $scope.dtInstance = {};

  $scope.dtOptions = DTOptionsBuilder.fromFnPromise(function(){
        return MarketsFactory.getAll();
    })
        .withDataProp('data.data')
        .withOption('createdRow', function(row, data, dataIndex) {
       $compile(angular.element(row).contents())($scope);
    })
        .withTableTools('http://cdn.datatables.net/tabletools/2.2.2/swf/copy_csv_xls_pdf.swf')
    .withTableToolsButtons([
        'copy',
        'print', {
            'sExtends': 'collection',
            'sButtonText': 'Save',
            'aButtons': ['csv', 'xls', 'pdf']
        }
    ])
    .withBootstrap()
    .withBootstrapOptions({
      TableTools: {
        classes: {
          container: 'btn-group right',
          buttons: {
              normal: 'btn btn-outline btn-default btn-sm'
          }
        }
     }
   });

    $scope.dtColumns = [
    DTColumnBuilder.newColumn('shortName').withTitle('Short Name').withClass('dt-left'),
    DTColumnBuilder.newColumn('name').withTitle('Name').withClass('dt-left'),
    DTColumnBuilder.newColumn('timezone').withTitle('Time Zone').withClass('dt-left'),
    DTColumnBuilder.newColumn('id').renderWith(function(data, type, full) {
        return '<a ng-click="edit(\'' + data + '\')">Edit</a>';
    })];
    })

And the test file:

describe('Controller: MarketsCtrl', function () {
  var scope, $state, DTOptionsBuilder, DTColumnBuilder;

  beforeEach(function(){
    var mockState = {};
    var mockDTOptionsBuilder = {};
    var mockDTColumnBuilder = {};

    module('app', function($provide) {
      $provide.value('$state', mockState);
      $provide.value('DTOptionsBuilder', mockDTOptionsBuilder);
      $provide.value('DTColumnBuilder', mockDTColumnBuilder);
    });

    inject(function() {

      mockState.go = function(target) {
        return target;
      };

      mockDTOptionsBuilder.fromFnPromise = jasmine.createSpy('DTOptionsBuilder.fromFnPromise');
      mockDTOptionsBuilder.withDataProp = jasmine.createSpy('DTOptionsBuilder.withDataProp');

      mockDTColumnBuilder.newColumn = jasmine.createSpy('DTColumnBuilder.newColumn');

    });

  });

  beforeEach(inject(function ($controller, $rootScope, _$state_, _DTColumnBuilder_, _DTOptionsBuilder_) {
    scope = $rootScope.$new();
    $state = _$state_;
    DTOptionsBuilder = _DTOptionsBuilder_;
    DTColumnBuilder = _DTColumnBuilder_;

    $controller('MarketsCtrl', {
      $scope: scope,
      $state: $state,
      DTOptionsBuilder: DTOptionsBuilder,
      DTColumnBuilder: DTColumnBuilder
    });

    scope.$digest();
  }));


  it('should provide an edit function', function () {
    expect(typeof scope.edit).toBe('function');
  });


});

I thought that creating a mock and putting a Spy on it would prevent it from calling the chained functions, but I guess not.

I'm quite new to testing, especially with Angular, so any help in general would be greatly appreciated!

Aucun commentaire:

Enregistrer un commentaire