javascript - 如何访问指令内部的 Controller 内部功能?一切都返回未定义

标签 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");
    });
});
  • Controller 未定义
  • element.isolateScope() 未定义
  • $scope.navigateToMySchedule(testcase) 给出 Object doesn't support property or method 'navigateToMySchedule' 错误

最佳答案

确保没有任何内容覆盖函数module,并且您包含了ngMock。一种确定的方法是直接调用 angular.mock.module,比如

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

使用 $httpBackend 进行 mocking templateUrl 不会工作,现在,你的 directive 没有被已创建,因此您的所有代码都失败了。

一种简单易行的方法是使用 $templateCache

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

现在,如果您的模板mocked成功,调用element.isolateScope() 应该没问题,但后面的行不行。

$controller 检查是否通过 $controllerProvider 注册了具有给定名称的 Controller ,如果评估当前作用域上的字符串返回一个构造函数,则您的 Controller 被声明为内联指令 所以它不会被发现。如果要获取 Controller ,请使用 element.controller('mySchedule')

controller.navigateToMySchedule 将失败,因为该函数在 $scope 中而不是在 Controller 中,我的意思是,您将函数声明为 $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);
    });
});

请注意,我只是注入(inject)了运行此测试所需的内容,您可能需要更多。此外,我在 directive 中使用 this 来声明函数 navigateToMySchedule,这样我就可以从 Controller 实例中调用它。

嗯,希望对你有帮助

关于javascript - 如何访问指令内部的 Controller 内部功能?一切都返回未定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51663896/

相关文章:

javascript - 递归: How can I remove

javascript - <Helmet> ReactJs 无法在函数下工作导致错误

javascript - 如何将范围变量传递给 Angular 中的 native 输入 min 属性?

javascript - Angular ,更改模型时 View 不更新

testing - Jasmine .toHaveBeenCalledWith(aDate) 不工作

Javascript - 将值增加 4。

javascript - 将文本文件输入的信息解析为 JSON 格式

angularjs - Angular.js中的多个参数 'when'在路由期间调用

vb.net - SyncLock 在单元测试中不起作用

测试 - 间歇性错误 : 'Failed: The selector "#root 0"did not match any elements'