如何访问内部指令内部控制器的功能?一切都返回未定义

时间:2018-08-03 00:41:59

标签: javascript angularjs testing jasmine

这是我的指令mySchedule.directive.js

'use strict';
angular.module('myApp')
.directive('mySchedule', function () {
    return {
        restrict: 'E',
        scope: {
            mine: '='
        },
        templateUrl: 'App/directives/mySchedule.html?v={version}',

        controller: ['$scope', 'utils', '$location',
            function ($scope, utils, $location) {
                $scope.navigateToMySchedule = function (name) {
                  utils.showConfirmationDialog(
                    myResources.resourceText.alert_Navigation, 
                    myResources.resourceText.confirmDialog_LeaveCurrentPage, 
                    'Leave page', 'Stay on page').result.then(function () {
                        $location.path("/myCar/").search("route", name);
                    //on ok button press 
                    // end on ok button press
                }, function () {
                    //on cancel button press
                });
            }
        }]
    };
});

这是我的测试文件 mySchedule.directive.spec.js

/// <reference path="../../../chutzpah.conf.js" />
'use strict';


describe('mySchedule Directive', function () {
    var $httpBackend;
    var $scope;
    var $compile;
    var utilsService;
    var $location;
    var controller;
    var $controller;

    beforeEach(module('myApp', function ($provide) {

    }));

    beforeEach(
        inject(function ($rootScope, _$compile_, $injector, _$location_, utils, _$controller_) {
            $httpBackend = $injector.get('$httpBackend');
            $httpBackend.whenGET('App/directives/mySchedule.html').respond(200, 'OK');
            $scope = $rootScope.$new();
            $compile = _$compile_;
            $location = _$location_;
            $controller = _$controller_;
            utilsService = utils
            utilsService.showconfirmationdialog = function () {
            return true;
            }
        })
    );

    afterEach(function () {
        $httpBackend.verifyNoOutstandingExpectation();
    });

    it('should redirect to my schedule', function () {
        var element = angular.element('<my-schedule></my-schedule');
        var testcase = "name"
        element = $compile(element)($scope);
        //$httpBackend.flush();
        $scope.$digest();

        // NOW NONE OF THESE LINES AFTER THIS WORK

        element.isolateScope().navigateToMySchedule(testcase);
        var controller = $controller('mySchedule', { '$scope': $scope });
        $scope.navigateToMySchedule(testcase);
        controller.navigateToMySchedule(testcase);
        expect(location.path).toEqual("/route=name");
    });
});
  • 控制器未定义
  • element.isolateScope()未定义
  • $ scope.navigateToMySchedule(testcase)给出了对象不支持属性或方法“ navigateToMySchedule”的错误

1 个答案:

答案 0 :(得分:0)

请确保没有{em>覆盖函数module,并且您要包含ngMock。确保的一种方法是直接致电angular.mock.module,例如

beforeEach(angular.mock.module('myApp', function ($provide) {}));

使用$httpBackend进行模拟操作 templateUrl不起作用,目前,您的directive尚未创建,因此所有代码均失败。

一种简单的方法可以使用$templateCache

beforeEach(function () {
    $templateCache.put('App/directives/mySchedule.html', '<div>OK</div>');
});

现在,如果您的 template 成功被嘲笑,则调用element.isolateScope()应该没问题,但后面的代码行没问题。

$controller检查是否通过$controllerProvider注册了具有给定名称的控制器,并且如果评估当前作用域上的字符串返回了构造函数,则您的控制器在directive中被声明为内联,因此找不到。如果要获取控制器,请使用element.controller('mySchedule')

controller.navigateToMySchedule将失败,因为该函数位于$scope而不是控制器中,我的意思是,您将函数声明为$scope.navigateToMySchedule = function (name)而不是this.navigateToMySchedule = function (name)。注意区别吗?

$scope.navigateToMySchedule将失败,因为变量$scope不包含指令的作用域。调用element.isolateScope()就足够了吧?但是您也可以使用element.children().scope()来获取它。

这是我在本地模拟您的一项小测试。

第一拳,模块和指令:

(function () {
    'use strict';
    angular.module('myApp', []);

})();

(function () {
    'use strict';
    angular.module('myApp')
    .directive('mySchedule', function () {
        return {
            restrict: 'E',
            scope: {
                mine: '='
            },
            templateUrl: 'App/directives/mySchedule.html',
            controller: function ($scope) {
                this.navigateToMySchedule = function (name) {
                    return name;
                }
            }
        };
    });
})();

这里是测试

describe('mySchedule Directive', function () {
    var $scope;
    var $compile;
    var $templateCache;

    beforeEach(angular.mock.module('myApp', function ($provide) {}));

    beforeEach(
        inject(['$rootScope', '$compile', '$templateCache',
            function ($rootScope, _$compile, _$templateCache) {
                $scope = $rootScope.$new();
                $compile = _$compile;
                $templateCache = _$templateCache;
        }])
    );

    beforeEach(function () {
        $templateCache.put('App/directives/mySchedule.html', '<div>OK</div>');
    });

    it("$scope should exist", function () {
        expect($scope).toBeDefined();
        expect($compile).toBeDefined();
    });

    it('should redirect to my schedule', function () {
        var element = angular.element('<my-schedule></my-schedule');
        var testcase = "name"
        element = $compile(element)($scope);
        $scope.$digest();

        var controller = element.controller('mySchedule');
        expect(controller).toBeDefined();
        expect(controller.navigateToMySchedule).toBeDefined();
        expect(controller.navigateToMySchedule(testcase)).toEqual(testcase);
    });
});

请注意,我只是注入运行此测试所需的内容,您可能需要更多。另外,我在this中使用directive来声明函数navigateToMySchedule,以便可以从控制器实例中调用它。

好吧,希望对你有帮助