最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Unit testing an AngularJS directive that contains $watch() not being compiled - Stack Overflow

programmeradmin2浏览0评论

I'm currently researching my problem but I thought adding a question here may help as I'm new to AngularJS and even newer to Unit Testing.

I have the current directive that works, it users the $watch() function to track a variable, if the variable is not present a default message is provided, for example "Deleted User Value" ...

angular.module('myModule')


.directive('displayName', function ($transform) {
    return {
        restrict: 'A',
        scope: {
            displayName: '='
        },
        link: function (scope, element) {
            scope.$watch('displayName', function(value){
                if(!value) {
                    element.html($transform('users.profile.deletedUser'));
                } else {
                    element.html(value);
                }
            });
        }
    };
})

;

and I have the following unit test (please note that I have amended this on the advice of Maurice) :

beforeEach(module('myModule'));

beforeEach(inject(function($pile, $rootScope) {
    $scope = $rootScope;
    element = angular.element('<div class="name" display-name="name"></div>');
    $pile(element)($scope);
}));


it('should display the deleted user name', inject(function() {
    $scope.displayName = null;
    element.scope().$apply();
    console.log(element);
    expect(element.html()).toBe('Deleted User Value');

}));

However I am getting the following issue: TypeError: Attempted to assign to readonly property. and the console.log is not being outputted, can anyone advise where I am going wrong? Sorry for my stupidity but I am trying to learn unit testing "on the job" and I am still very new to AngularJS

I'm currently researching my problem but I thought adding a question here may help as I'm new to AngularJS and even newer to Unit Testing.

I have the current directive that works, it users the $watch() function to track a variable, if the variable is not present a default message is provided, for example "Deleted User Value" ...

angular.module('myModule')


.directive('displayName', function ($transform) {
    return {
        restrict: 'A',
        scope: {
            displayName: '='
        },
        link: function (scope, element) {
            scope.$watch('displayName', function(value){
                if(!value) {
                    element.html($transform('users.profile.deletedUser'));
                } else {
                    element.html(value);
                }
            });
        }
    };
})

;

and I have the following unit test (please note that I have amended this on the advice of Maurice) :

beforeEach(module('myModule'));

beforeEach(inject(function($pile, $rootScope) {
    $scope = $rootScope;
    element = angular.element('<div class="name" display-name="name"></div>');
    $pile(element)($scope);
}));


it('should display the deleted user name', inject(function() {
    $scope.displayName = null;
    element.scope().$apply();
    console.log(element);
    expect(element.html()).toBe('Deleted User Value');

}));

However I am getting the following issue: TypeError: Attempted to assign to readonly property. and the console.log is not being outputted, can anyone advise where I am going wrong? Sorry for my stupidity but I am trying to learn unit testing "on the job" and I am still very new to AngularJS

Share Improve this question edited Dec 30, 2013 at 12:42 Mike Sav asked Dec 30, 2013 at 10:47 Mike SavMike Sav 15.3k31 gold badges102 silver badges150 bronze badges 1
  • Is there a typo at the top? $tranform should be $transform? – Michal Charemza Commented Dec 30, 2013 at 12:20
Add a ment  | 

1 Answer 1

Reset to default 7

There seem to be several things wrong with the code.

The directive has a dependency on $translate which isn't used while a $transform is used but not injected.

Secondly in your second test you are calling element.$scope().$apply();. That should be element.scope().$apply(); instead.

Finally you are setting the displayName property on the scope but binding to the name property in the test code using <div class="name" display-name="name"></div>.

I would write the tests something like this:

describe("The displayName directive", function () {
    var $scope, element;

    beforeEach(module('myModule'));

    beforeEach(inject(function ($pile, $rootScope) {
        $scope = $rootScope;
        element = angular.element('<div class="name" display-name="name"></div>');
        $pile(element)($scope);
    }));

    it('should display the deleted user name', function () {
        element.scope().$apply();
        expect(element.text()).toBe('users.profile.deletedUser');

    });

    it('should display the actual user name', function () {
        $scope.name = "Maurice";
        element.scope().$apply();
        expect(element.text()).toBe('Maurice');
    });
});
发布评论

评论列表(0)

  1. 暂无评论