我很难尝试测试模态控制器(使用Angular UI Bootstrap创建)。我尽可能地降低了测试代码,但我仍然收到错误。这是模态控制器(其中的一部分):
var controllersModule = angular.module('forge.geomanagement.controllers');
controllersModule.controller('EditGeofenceModalController', function ($timeout, $scope: , $modalInstance, forgeGeoTriggerService, $rootScope, geofence, triggerID) {
var searchAddressInput: HTMLInputElement;
//make a copy of geofence obj passed into modal
$scope.geofence = {
FriendlyName: geofence.FriendlyName,
Coords: angular.copy(geofence.Boundary),
GeoTags: angular.copy(geofence.GeoTags)
};
$scope.goefenceID = triggerID;
var gCLength = $scope.geofence.Coords.length;
//wrap it in timeout function to paint the map after its container is rendered
$timeout(function () {
$scope.geofenceMap = new google.maps.Map(document.getElementById('map_canvas'), $scope.mapOptions);
//autocomplete functionality
searchAddressInput = <HTMLInputElement>document.getElementById('pac-input');
$scope.autocomplete = new google.maps.places.Autocomplete(searchAddressInput, $scope.mapOptions);
$scope.autocomplete.bindTo('bounds', $scope.geofenceMap); //set autocomplete suggestion bounds to map's current viewport
//bind autocomplete to the map
google.maps.event.addListener($scope.autocomplete, 'place_changed', function () {
$scope.place = $scope.autocomplete.getPlace();
$scope.geofenceMap.panTo($scope.place.geometry.location);
$scope.geofenceMap.setZoom(12);
$scope.model.searchAddress = $scope.place.formatted_address;
$scope.$digest();
});
//GEOFENCE FUNCTIONALITY
forgeGeoTriggerService.GeofenceCreator($scope.geofenceMap, $scope.geofence.Coords);
//show geofence in edit mode
forgeGeoTriggerService.ShowGeofence($scope.geofenceMap, $scope.geofence.Coords);
$scope.$on("polygonPath.updated", function (event, geofenceCoords) {
$scope.$apply(function () {
$scope.geofence.Coords = geofenceCoords;
});
});
//clear geofence area btn
$scope.clearGeofenceArea = function () {
forgeGeoTriggerService.ClearGeofenceArea();
$scope.geofence.Coords.length = 0; // clear geofence array
};
}, 0);
$scope.cancel = function () {
$modalInstance.close()
};
$scope.saveGeofence = function () {
forgeGeoTriggerService.EditGeofence($scope.geofence, $scope.goefenceID)
.then(function (data) {
$scope.successMessage = 'Geofence Updated Successfully'
$rootScope.$broadcast('geotrigger.edited');
$timeout(function () {
$modalInstance.close();
}, 2000);
}, function (data) {
$scope.errorMessage = 'There was an error when updating geofence. Please try again.';
});
}
});
这是模态控制器测试
describe("forge.geomanagement.GeoApp", function () {
var scope, controller, modalInstance, timeout, forgeGeoTriggerService, window = {},
geofencemock, geofence, triggerID;
beforeEach(module('forge.geomanagement.GeoApp'));
describe("Controller: EditGeofenceModalController", function () {
beforeEach(inject(function ($controller, $rootScope, $timeout, _forgeGeoTriggerService_) {
scope = $rootScope.$new();
timeout = $timeout;
modalInstance = {
close: jasmine.createSpy('modalInstance.close'),
dismiss: jasmine.createSpy('modalInstance.dismiss'),
result: {
then: jasmine.createSpy('modalInstance.result.then')
}
}
geofencemock = {
FriendlyName: 'mock geofence',
Coords: [
{
"lat": 53.5598889724547,
"lng": -6.36953830718994
},
{
"lat": 53.463525599115,
"lng": -6.53707981109619
},
{
"lat": 53.3685818160803,
"lng": -6.46841526031494
},
{
"lat": 53.384966558115,
"lng": -5.75430393218994
},
{
"lat": 53.5598889724547,
"lng": -6.34756565093994
},
{
"lat": 53.5598889724547,
"lng": -6.36953830718994
}
],
GeoTags: ['tag1','tag2','tag3']
}
triggerIDmock = 1;
forgeGeoTriggerService = _forgeGeoTriggerService_;
controller = $controller("EditGeofenceModalController", {
$scope: scope,
$timeout: timeout,
$modalInstance: modalInstance,
forgeGeoTriggerService: forgeGeoTriggerService,
geofence: geofencemock,
triggerID: triggerIDmock
});
}));
it('2 is 2', function () {
expect(2).toBe(2);
})
it("geofence should be defined", function () {
expect(geofencemock).toBeDefined();
});
it("should contain reference to forgeGeoTriggerService", function () {
expect(forgeGeoTriggerService).not.toBeNull();
});
it("$modalInstance obj should be defined when modal is open", function () {
expect(modalInstance).toBeDefined();
});
it("cancel function should close edit geofence modal", function () {
scope.cancel();
expect(modalInstance.close).toHaveBeenCalled();
});
});
});
但是当我尝试运行它时,我收到错误:"无法读取未定义的属性长度",对应于 $scope.geofence.Coords 属性 - 一个从父控制器成功复制到模态的数组。如您所见,我还创建了一个geofencemock对象,并尝试在非常简单的测试中使用它,但看起来它没有被拾取。我真的很感激一些意见,因为我已经花了几个小时试图修复它或在线找到解决方案,但无济于事。
谢谢。
您正在从geofence.Boundary
设置$scope.geofence.Coords
:
$scope.geofence = {
FriendlyName: geofence.FriendlyName,
Coords: angular.copy(geofence.Boundary),
GeoTags: angular.copy(geofence.GeoTags)
};
但你直接用Coords
嘲笑geofence
:
geofencemock = {
FriendlyName: 'mock geofence',
Coords: [
{
"lat": 53.5598889724547,
"lng": -6.36953830718994
},
将后者更改为geofencemock.Boundary
,您应该没问题。
好的,我让它工作了。错误"无法读取未定义的属性'lat'"与地理围栏模拟对象中的坐标无关,而与地理围栏有关。我在带有地理围栏的控制器中使用的 Center.lat 属性。Center.lng 来定位地图的中心。让我解释一下:我们从服务器获取多边形详细信息,然后将它们传递到编辑模式窗口(Angular UI 引导程序):
forgeGeoTriggerService.GetGeoFence(geotriggerID)
.then(function (geofenceData) {
$scope.modalInstance = $modal.open({
windowClass: 'popup-geofence-modal',
templateUrl: TemplateUrlProvider.GetUrl('GeofenceModal'),
controller: 'EditGeofenceModalController',
resolve: {//pass geofenceData from server to geofence obj inside modal
geofence: function () {
return geofenceData;
},
triggerID: function () {
return geotriggerID
}
}
});
}, function (error) {
$scope.errorMessage = 'There was an error when trying to fetch geofencene details. Please try again later.';
});
然后在 编辑地理围栏模式控制器 我们利用从上面的父控制器传递的地理围栏对象
'use strict';
var controllersModule = angular.module('forge.geomanagement.controllers');
controllersModule.controller('EditGeofenceModalController', function ($timeout, $scope, $modalInstance, forgeGeoTriggerService, $rootScope, geofence, triggerID) {
var searchAddressInput: HTMLInputElement;
//make a copy of geofence obj passed into modal
$scope.geofence = {
FriendlyName: geofence.FriendlyName,
Coords: angular.copy(geofence.Boundary),
GeoTags: angular.copy(geofence.GeoTags)
};
$scope.goefenceID = triggerID;
var gCLength = $scope.geofence.Coords.length;
//if first and last coords are the same - remove the last one
if ($scope.geofence.Coords[0].lat === $scope.geofence.Coords[gCLength - 1].lat
&& $scope.geofence.Coords[0].lng === $scope.geofence.Coords[gCLength - 1].lng) {
$scope.geofence.Coords.pop();
}
//!!!!!!!set the map center to geofence.Center
var geofenceCenter: google.maps.LatLng = new google.maps.LatLng(
geofence.Center.lat, geofence.Center.lng
);
注意带有感叹号的评论行。这是我设置地图中心的地方。从服务器返回的地理围栏对象具有中心属性 - 具有纬度和 LNG 属性的 obj。一旦我按照@rayners的建议在测试中的地理围栏模拟对象中将坐标更改为边界,它仍然缺少中心属性。在测试文件中这样设置它解决了问题,我的测试通过了:
geofencemock = {
FriendlyName: 'mock geofence',
Boundary: [
{
"lat": 53.5598889724547,
"lng": -6.36953830718994
},
{
"lat": 53.463525599115,
"lng": -6.53707981109619
},
{
"lat": 53.3685818160803,
"lng": -6.46841526031494
},
{
"lat": 53.384966558115,
"lng": -5.75430393218994
},
{
"lat": 53.5598889724547,
"lng": -6.34756565093994
},
{
"lat": 53.5598889724547,
"lng": -6.36953830718994
}
],
GeoTags: ['tag1', 'tag2', 'tag3'],
Center: {
"lat": 53.46769593973309,
"lng": -6.2952017905716735
}
}