How to mock one-way binding parameters with $controller decorator?

823 views Asked by At

I am writing tests for a directive's controller whose startup logic requires some one-way bound parameters to be defined. I am facing difficulties passing one-way bound parameters to the mocked controller. text-bound parameters are passed without difficulty.

NOTE: In the following code, I skip module injections and other irrelevant parts of the code

Here is the directive's definition with two types of parameters:

function DummyDirective() {
  return {
    restrict: 'E',
    scope: {},
    bindToController: 
      oneWay: '&',
      text: '@'
    },
    templateUrl: 'path/to/template.html',
    controller: 'GreatController',
    controllerAs: 'vm'
  };
}

And here is the controller:

function GreatController() {
    var vm = this;

    vm.treasure = '';

    activate();

    function activate() {
      vm.treasure = fantastic(vm.oneWay);
    }

    function fantastic(crap) {
      if(crap.stack) return 'gold';
    }
}

As for the test:

  var controller, $rootScope, $scope;
  beforeEach(inject(function(_$controller_, _$rootScope_){
    $rootScope = _$rootScope_;
    $scope = $rootScope.$new();

    controller = _$controller_(
      'GreatController',
      {$scope: $scope},
      {text: 'toGoodToBeTrue',
       oneWay: {
         stack: 'lotsOfIt',
       }
      }
    );
  }));

  it('should do the job', function(){
    expect(controller.treasure).toBe('gold');
  });

While text is properly passed to $controller, oneWay is undefined and the test fails. I have also tried to pass it a function returning an object to no avail. The documentation does not cover one-way bound parameters. Would you know how to do this without testing the directive and passing parameters as markup? In general I like to keep my tests focused and test directives and their controllers separately.

1

There are 1 answers

1
Eugene Hype On

What if make oneWay optional, adding question mark to its definition:

oneWay: '&?'