Test dell’unità angular del router ui (indica agli url)

Sto riscontrando dei problemi con l’unità che testava il router nella mia applicazione, che è stata costruita sul router ui Angular. Quello che voglio testare è se le transizioni di stato cambiano l’URL in modo appropriato (ci saranno test più complicati più tardi, ma è qui che sto iniziando).

Ecco la porzione pertinente del mio codice dell’applicazione:

angular.module('scrapbooks') .config( function($stateProvider){ $stateProvider.state('splash', { url: "/splash/", templateUrl: "/app/splash/splash.tpl.html", controller: "SplashCtrl" }) }) 

E il codice di test:

 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"); }) }) 

Domande simili su Stackoverflow (e il codice di test del router ui ufficiale) suggeriscono di avvolgere la chiamata $ state.go in $ apply dovrebbe essere sufficiente. Ma l’ho fatto e lo stato non si sta ancora aggiornando. $ state.current.name rimane vuoto.

Ho avuto anche questo problema e finalmente ho capito come farlo.

Ecco uno stato di esempio:

 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(); }] } }); }]); 

Il test unitario di seguito coprirà il test dell’URL con parametri e l’esecuzione dei resolves che iniettano le sue dipendenze:

 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'); }); }); 

Se vuoi controllare solo il nome dello stato corrente è più facile usare $state.transitionTo('splash')

 it('should transition to splash', inject(function($state,$rootScope){ $state.transitionTo('splash'); $rootScope.$apply(); expect($state.current.name).toBe('splash'); })); 

Mi rendo conto che è leggermente fuori tema, ma sono venuto qui da Google alla ricerca di un modo semplice per testare il modello, il controller e l’URL di una rotta.

 $state.get('stateName') 

ti darò

 { url: '...', templateUrl: '...', controller: '...', name: 'stateName', resolve: { foo: function () {} } } 

nei tuoi test.

Quindi i tuoi test potrebbero assomigliare a questo:

 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 

Per uno state che senza 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:-

Per uno stato annidato potremmo dover fornire più di un modello. Per es. se abbiamo uno stato nidificato core.public.home e ogni state , cioè core , core.public e core.public.home ha definito templateUrl , dovremo aggiungere $templateCache.put() per la chiave templateUrl ogni stato: –

$templateCache.put('app/templates/template1.html'); $templateCache.put('app/templates/template2.html'); $templateCache.put('app/templates/template3.html');

Spero che questo ti aiuti. In bocca al lupo.

È ansible utilizzare $state.$current.locals.globals per accedere a tutti i valori risolti (vedere lo snippet di codice).

 // Given $httpBackend .expectGET('/api/users/123') .respond(200, { id: 1, email: 'test@email.com'); // 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', 'test@email.com'); 

Se non sei interessato a nulla nel contenuto del modello, potresti semplicemente prendere in giro $ templateCache:

 beforeEach(inject(function($templateCache) { spyOn($templateCache,'get').and.returnValue('
'); }