Julius
Julius

Reputation: 2483

AngularJS unit testing directive with ngModel

I have made a directive which uses ngModel:

.directive('datetimepicker', function () {
    return {
        restrict: 'E',
        require: ['datetimepicker', '?^ngModel'],
        controller: 'DateTimePickerController',
        replace: true,

        templateUrl: ...,

        scope: {
            model: '=ngModel'
        },

        link: function (scope, element, attributes, controllers) {
            var pickerController = controllers[0];
            var modelController = controllers[1];

            if (modelController) {
                pickerController.init(modelController);
            }
        }
    }
});

But when testing...

var scope, element;

beforeEach(module('appDateTimePicker'));
beforeEach(module('templates'));

beforeEach(inject(function ($compile, $rootScope) {
    compile = $compile;
    scope = $rootScope;

    scope.model = new Date();

    element = compile(angular.element('<datetimepicker ng-model="model"></datetimepicker>'))(scope);

    scope.$digest();
}));

I can't anyhow set value to ng-model.

Fo example, here scope.model is a date, so scope.year and scope.month should be date and year of that model, but it is undefined.

As seen in the directive's code, I'm using this.init on the controller to initialise all the process.

What am I missing?

EDIT

Example of test:

it('should test', function () {
    expect(scope.model).toBe(undefined);
    expect(scope.year).toBe(undefined);
});

EDIT

This helped to solve the problem: http://jsfiddle.net/pTv49/3/

Upvotes: 0

Views: 1964

Answers (2)

Konstantin Pelepelin
Konstantin Pelepelin

Reputation: 1563

The directive has a scope: {} block so it creates an isolate scope. I assume, in the tests scope refers to the outer scope, while element.isolateScope() should be used to reference the inner scope instead.

Upvotes: 0

runTarm
runTarm

Reputation: 11547

The '?^ngModel' mean you are asking for the ng-model on parent elements, but the html in your test has the ng-model on the same element as datetimepicker directive.

If the ng-model really have to be on parent elements, you have to change the html in the test, for example:

element = compile(angular.element('<div ng-model="model"><datetimepicker></datetimepicker></div>'))(scope);

But if it should be on the same element, just remove the ^ symbol in the require:

require: ['datetimepicker', '?ngModel'],

Upvotes: 3

Related Questions