Контроллер модульного тестирования, который использует $state.transitionTo
внутри контроллера у меня есть функция, которая использует $state.transitionTo
для "перенаправления" в другое состояние.
теперь я застрял в тестировании этой функции, всегда получаю ошибку Error: No such state 'state-two'
. как я могу проверить это? это совершенно ясно для меня, что диспетчер ничего не знает о других государствах, но как я могу издеваться над этим состоянием?
некоторый код:
angular.module( 'mymodule.state-one', [
'ui.state'
])
.config(function config($stateProvider) {
$stateProvider.state('state-one', {
url: '/state-one',
views: {
'main': {
controller: 'MyCtrl',
templateUrl: 'mytemplate.tpl.html'
}
}
});
})
.controller('MyCtrl',
function ($scope, $state) {
$scope.testVar = false;
$scope.myFunc = function () {
$scope.testVar = true;
$state.transitionTo('state-two');
};
}
);
describe('- mymodule.state-one', function () {
var MyCtrl, scope
beforeEach(module('mymodule.state-one'));
beforeEach(inject(function ($rootScope, $controller) {
scope = $rootScope.$new();
MyCtrl = $controller('MyCtrl', {
$scope: scope
});
}));
describe('- myFunc function', function () {
it('- should be a function', function () {
expect(typeof scope.myFunc).toBe('function');
});
it('- should test scope.testVar to true', function () {
scope.myFunc();
expect(scope.testVar).toBe(true);
expect(scope.testVar).not.toBe(false);
});
});
});
Ответы
Ответ 1
Отказ от ответственности: я не сделал этого сам, поэтому полностью не знаю, будет ли это работать, и что вы после этого.
С головы до головы мне приходят два решения.
1.) В ваших тестах предварительно настройте $stateProvider
, чтобы вернуть состояние mocked для state-two
Это также то, что сам проект ui-router выполняет для проверки переходов состояний.
Смотрите: https://github.com/angular-ui/ui-router/blob/04d02d087b31091868c7fd64a33e3dfc1422d485/test/stateSpec.js#L29-L42
2.) поймать и разобрать исключение и интерпретировать его как выполненный тест, если пытается добраться до state-two
Второй подход кажется очень хакерским, поэтому я бы проголосовал за первое.
Однако, скорее всего, я полностью понял, что вы ошибаетесь и, вероятно, немного отдохнете.
Код решения:
beforeEach(module(function ($stateProvider) {
$stateProvider.state('state-two', { url: '/' });
}));
Ответ 2
Недавно я задал этот вопрос как вопрос github, и ему очень помогли.
https://github.com/angular-ui/ui-router/issues/537
Вы должны сделать $rootScope. $apply(), а затем сможете проверить. Обратите внимание, что по умолчанию, если вы используете templateUrl, вы получите "неожиданный запрос GET" для представления, но вы можете решить эту проблему, включив в свой шаблон свои шаблоны.
'use strict';
describe('Controller: CourseCtrl', function () {
// load the controller module
beforeEach(module('myApp'));
// load controller widgets/views/partials
var views = [
'views/course.html',
'views/main.html'
];
views.forEach(function(view) {
beforeEach(module(view));
});
var CourseCtrl,
scope;
// Initialize the controller and a mock scope
beforeEach(inject(function ($controller, $rootScope) {
scope = $rootScope.$new();
CourseCtrl = $controller('CourseCtrl', {
$scope: scope
});
}));
it('should should transition to main.course', inject(function ($state, $rootScope) {
$state.transitionTo('main.course');
$rootScope.$apply();
expect($state.current.name).toBe('main.course');
}));
});
Ответ 3
Также, если вы хотите ожидать, что переход был сделан таким образом
expect(state.current.name).toEqual('state-two')
тогда вам нужно scope.$apply
перед expect()
, чтобы он работал