Tengo problemas para probar el enrutador en mi aplicación, que se basa en el enrutador de interfaz de usuario angular. Lo que quiero probar es si las transiciones de estado cambian la URL de manera apropiada (habrá pruebas más complicadas más adelante, pero aquí es donde estoy comenzando).
Aquí está la parte relevante de mi código de aplicación:
angular.module('scrapbooks')
.config( function($stateProvider){
$stateProvider.state('splash', {
url: "/splash/",
templateUrl: "/app/splash/splash.tpl.html",
controller: "SplashCtrl"
})
})
Y el código de prueba:
it("should change to the splash state", function(){
inject(function($state, $rootScope){
$rootScope.$apply(function(){
$state.go("splash");
});
expect($state.current.name).to.equal("splash");
})
})
Preguntas similares sobre Stackoverflow (y el código oficial de prueba del enrutador ui) sugieren que envolver la llamada $ state.go en $ apply debería ser suficiente. Pero lo he hecho y el estado todavía no se actualiza. $ state.current.name permanece vacío.
Respuestas:
También he tenido este problema y finalmente descubrí cómo hacerlo.
Aquí hay un estado de muestra:
angular.module('myApp', ['ui.router']) .config(['$stateProvider', function($stateProvider) { $stateProvider.state('myState', { url: '/state/:id', templateUrl: 'template.html', controller: 'MyCtrl', resolve: { data: ['myService', function(service) { return service.findAll(); }] } }); }]);
La prueba unitaria a continuación cubrirá probar la URL con params y ejecutar las resoluciones que inyectan sus propias dependencias:
describe('myApp/myState', function() { var $rootScope, $state, $injector, myServiceMock, state = 'myState'; beforeEach(function() { module('myApp', function($provide) { $provide.value('myService', myServiceMock = {}); }); inject(function(_$rootScope_, _$state_, _$injector_, $templateCache) { $rootScope = _$rootScope_; $state = _$state_; $injector = _$injector_; // We need add the template entry into the templateCache if we ever // specify a templateUrl $templateCache.put('template.html', ''); }) }); it('should respond to URL', function() { expect($state.href(state, { id: 1 })).toEqual('#/state/1'); }); it('should resolve data', function() { myServiceMock.findAll = jasmine.createSpy('findAll').and.returnValue('findAll'); // earlier than jasmine 2.0, replace "and.returnValue" with "andReturn" $state.go(state); $rootScope.$digest(); expect($state.current.name).toBe(state); // Call invoke to inject dependencies and run function expect($injector.invoke($state.current.resolve.data)).toBe('findAll'); }); });
fuente
andReturn
como se menciona en el comentario anterior. Sin embargo, my $ state.current.name devuelve una cadena vacía. ¿Alguien sabe por qué?$state.current.name
: cadena vacía.$q
. Todo debe usar$q
promesas para$rootScope.$digest()
poder resolver todas las promesas. Mi caso es probablemente bastante único, pero pensé en compartirlo por si acaso.Si desea verificar solo el nombre del estado actual, es más fácil de usar
$state.transitionTo('splash')
it('should transition to splash', inject(function($state,$rootScope){ $state.transitionTo('splash'); $rootScope.$apply(); expect($state.current.name).toBe('splash'); }));
fuente
Me doy cuenta de que esto está un poco fuera de tema, pero vine aquí desde Google buscando una forma sencilla de probar la plantilla, el controlador y la URL de una ruta.
$state.get('stateName')
Te regalaré
{ url: '...', templateUrl: '...', controller: '...', name: 'stateName', resolve: { foo: function () {} } }
en tus pruebas.
Entonces, sus pruebas podrían verse así:
var state; beforeEach(inject(function ($state) { state = $state.get('otherwise'); })); it('matches a wild card', function () { expect(state.url).toEqual('/path/to/page'); }); it('renders the 404 page', function () { expect(state.templateUrl).toEqual('views/errors/404.html'); }); it('uses the right controller', function () { expect(state.controller).toEqual(...); }); it('resolves the right thing', function () { expect(state.resolve.foo()).toEqual(...); }); // etc
fuente
Por un
state
eso sinresolve
:// TEST DESCRIPTION describe('UI ROUTER', function () { // TEST SPECIFICATION it('should go to the state', function () { module('app'); inject(function ($rootScope, $state, $templateCache) { // When you transition to the state with $state, UI-ROUTER // will look for the 'templateUrl' mentioned in the state's // configuration, so supply those templateUrls with templateCache $templateCache.put('app/templates/someTemplate.html'); // Now GO to the state. $state.go('someState'); // Run a digest cycle to update the $state object // you can also run it with $state.$digest(); $state.$apply(); // TEST EXPECTATION expect($state.current.name) .toBe('someState'); }); }); });
NOTA:-
Para un estado anidado, es posible que necesitemos proporcionar más de una plantilla. Por ej. si tenemos un estado anidado
core.public.home
y cada unostate
, es decircore
,core.public
ycore.public.home
tiene untemplateUrl
definido, tendremos que agregar$templateCache.put()
para latemplateUrl
clave de cada estado : -$templateCache.put('app/templates/template1.html'); $templateCache.put('app/templates/template2.html'); $templateCache.put('app/templates/template3.html');
Espero que esto ayude. Buena suerte.
fuente
Puede utilizar
$state.$current.locals.globals
para acceder a todos los valores resueltos (consulte el fragmento de código).// Given $httpBackend .expectGET('/api/users/123') .respond(200, { id: 1, email: '[email protected]'); // When $state.go('users.show', { id: 123 }); $httpBackend.flush(); // Then var user = $state.$current.locals.globals['user'] expact(user).to.have.property('id', 123); expact(user).to.have.property('email', '[email protected]');
En ui-router 1.0.0 (actualmente beta), puede intentar invocar
$resolve.resolve(state, locals).then((resolved) => {})
en las especificaciones. Por ejemplo https://github.com/lucassus/angular-webpack-seed/blob/9a5af271439fd447510c0e3e87332959cb0eda0f/src/app/contacts/one/one.state.spec.js#L29fuente
Si no está interesado en nada en el contenido de la plantilla, simplemente puede simular $ templateCache:
beforeEach(inject(function($templateCache) { spyOn($templateCache,'get').and.returnValue('<div></div>'); }
fuente