javascript - Prueba de unidades de enrutadores ui angulares(estados a urls)
unit-testing angularjs (6)
He tenido este problema también, 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á la prueba de la URL con params y la ejecución de los resuelve 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'');
});
});
Tengo problemas para probar el enrutador en mi aplicación, que está construida en el enrutador ui angular. Lo que quiero probar es si las transiciones de estado cambian la URL apropiadamente (habrá más pruebas 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 hice y el estado todavía no se está actualizando. $ state.current.name permanece vacío.
Me doy cuenta de que esto está un poco fuera del tema, pero vine aquí desde Google en busca de 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 tus pruebas podrían verse más o menos 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
Para un state
que sin resolve
:
// 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 suministrar más de una plantilla. Por ej. si tenemos un estado anidado core.public.home
y cada state
, es decir, core
, core.public
y core.public.home
tiene una templateUrl
definida, tendremos que agregar $templateCache.put()
para la clave templateUrl
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.
Puede usar $state.$current.locals.globals
para acceder a todos los valores resueltos (vea 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#L29
Si desea verificar solo el nombre del estado actual, es más fácil usar $state.transitionTo(''splash'')
it(''should transition to splash'', inject(function($state,$rootScope){
$state.transitionTo(''splash'');
$rootScope.$apply();
expect($state.current.name).toBe(''splash'');
}));
Si no está interesado en nada en el contenido de la plantilla, puede simular $ templateCache:
beforeEach(inject(function($templateCache) {
spyOn($templateCache,''get'').and.returnValue(''<div></div>'');
}