如何访问指令中的控制器内部功能?所有内容返回未定义



这是我的指令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.sisolateScope((未定义
  • $scope.navigateToMySchedule(testcase(给出Object不支持属性或方法"navigateToMySchedule"错误

确保没有任何东西覆盖函数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>');
});

现在,如果模板成功模拟,那么调用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);
});
});

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

希望它能帮助

最新更新