कोणीय ui राउटर इकाई परीक्षण (उरल्स के लिए राज्य)


81

मुझे अपने एप्लिकेशन में राउटर का परीक्षण करने में कुछ परेशानी हो रही है, जो कि कोणीय यूआई राउटर पर बनाया गया है। मैं परीक्षण करना चाहता हूं कि क्या राज्य परिवर्तन URL को उचित रूप से बदलते हैं (बाद में अधिक जटिल परीक्षण होंगे, लेकिन यह वह जगह है जहां यह शुरू हो रहा है।)

यहाँ मेरे आवेदन कोड का प्रासंगिक हिस्सा है:

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

और परीक्षण कोड:

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

Stackoverflow (और आधिकारिक ui राउटर टेस्ट कोड) पर इसी तरह के सवाल $ अवस्था को लपेटने का सुझाव देते हैं। $ लागू में कॉल पर्याप्त होना चाहिए। लेकिन मैंने ऐसा किया है और राज्य अभी भी अपडेट नहीं कर रहा है। $ state.current.name रिक्त रहता है।


ठीक है, यह पता लगा (जैसे) अगर मैं एक नकली राउटर को परिभाषित करता हूं, तो टेम्प्लेट यूआरएल के बजाय इनलाइन टेम्प्लेट के साथ, ट्रांस्फ़ॉर्म होता है।
टेरेंस डे

क्या आप उत्तर के रूप में अपना कार्य कोड पोस्ट कर सकते हैं?
लेवी हैकविथ

2
मैंने यह सवाल लगभग एक साल पहले पूछा था। मेरा विचार अब यह है कि इस समस्या को हल करने का सबसे अच्छा तरीका कर्म में एनजी-टेम्पलेट-टू-जे प्रीप्रोसेसर का उपयोग करना है।
टेरेंस

अधिक विशेष रूप से: मुद्दा यह है कि यदि टेम्पलेट डाउनलोड परीक्षण में विफल रहता है (क्योंकि सर्वर नहीं है), तो राज्य परिवर्तन विफल हो जाएगा। हालांकि, जब तक आप $ StateChangeError इवेंट के लिए नहीं देख रहे हैं, तब तक आपको त्रुटि नहीं दिखाई देगी। फिर भी, क्योंकि राज्य परिवर्तन विफल हो जाता है, $ state.current.name अपडेट नहीं किया जाएगा।
टेरेंस

जवाबों:


125

के रूप में अच्छी तरह से यह मुद्दा रहा है, और अंत में यह कैसे करना है पता लगा।

यहाँ एक नमूना स्थिति है:

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

नीचे दिए गए यूनिट टेस्ट में URL w / params का परीक्षण किया जाएगा, और अपने स्वयं के आश्रितों को इंजेक्ट करने वाले रिज़ॉल्यूशन को निष्पादित करेगा:

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

1
यदि आप किसी सेवा को परिभाषित करने के लिए स्ट्रिंग्स का उपयोग कर रहे हैं, तो महान पोस्ट, समय सेवर, इनवोक के बजाय उपयोग करें। उम्मीद ($ injector.get ($ state.current.resolve.data)) टोबे ( 'findAll')।
एलन क्विगले

2
मैंने उपरोक्त कोड को समायोजन के साथ अनुसरण किया andReturnजैसा कि उपरोक्त टिप्पणी में वर्णित है। हालाँकि, मेरी $ state.current.name एक रिक्त स्ट्रिंग लौटाती है। किसी को भी पता है क्यों?
विक्की लेयोंग

5
@Pipip मैं एक ही समस्या $state.current.nameका सामना कर रहा हूँ खाली स्ट्रिंग है।
जॉय

1
@ जॉय @ वीलॉन्ग मुझे यही समस्या थी, तब मुझे एहसास हुआ कि ui- राउटर की उपयोगिता के कारण मैं लिख रहा हूं, इसके बजाय ES6 वादों का उपयोग कर रहा था $q। सभी वादों को हल $qकरने के लिए वादों का उपयोग करना चाहिए $rootScope.$digest()। मेरा मामला शायद बहुत अनोखा है, लेकिन मुझे लगा कि मैं अभी मामले में साझा करूंगा।
स्ट्रगलर

1
@ जोय मैं $ state.current.name के साथ एक ही समस्या हो रही थी एक खाली स्ट्रिंग लौटा। मुझे $ httpBackend.flush () के साथ $ rootScope। $ डाइजेस्ट () को बदलना पड़ा। उस बदलाव के बाद, मुझे वह मिला जिसकी मुझे उम्मीद थी।
जेसन बुकानन

18

यदि आप केवल वर्तमान स्थिति का नाम जांचना चाहते हैं, तो इसका उपयोग करना आसान है $state.transitionTo('splash')

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

4
इसे सरल रखने के लिए मुझे यह उत्तर सबसे स्वीकार्य लगता है। परीक्षण अच्छा है और सभी है, लेकिन एक परीक्षण जो अब है तो मेरी पूरी ui- रूट परिभाषा लिखने के लिए एक एकल बिंदु का परीक्षण करने के लिए सिर्फ अक्षम करने का तरीका है। किसी भी मामले में मैं इसे वोट कर रहा हूं
थॉमस

15

मुझे लगता है कि यह थोड़ा बंद विषय है, लेकिन मैं Google से एक मार्ग के टेम्पलेट, नियंत्रक और URL का परीक्षण करने का एक सरल तरीका ढूंढ रहा हूं।

$state.get('stateName')

तुम्हे दूंगा

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

आपके परीक्षणों में।

तो आपके परीक्षण कुछ इस तरह दिख सकते हैं:

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

1

एक के लिए stateबिना कि 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');
        });
    });
});

ध्यान दें:-

एक नेस्टेड राज्य के लिए हमें एक से अधिक टेम्पलेट की आपूर्ति करने की आवश्यकता हो सकती है। पूर्व के लिए। अगर हमारे पास एक नेस्टेड स्टेट है core.public.homeऔर प्रत्येक state, यानी core, core.publicऔर core.public.homeएक templateUrlपरिभाषित है, तो हमें $templateCache.put()प्रत्येक राज्य की templateUrlकुंजी के लिए जोड़ना होगा : -

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

उम्मीद है की यह मदद करेगा। शुभ लाभ।


1

आप $state.$current.locals.globalsसभी हल किए गए मानों को एक्सेस करने के लिए उपयोग कर सकते हैं (कोड स्निपेट देखें)।

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

यूआई-राउटर 1.0.0 (वर्तमान में बीटा) में आप $resolve.resolve(state, locals).then((resolved) => {})ऐनक में आह्वान करने की कोशिश कर सकते हैं । उदाहरण के लिए https://github.com/lucassus/angular-webpack-seed/blob/9a5af271439fd447510c0e3e87332959cb0eda0f/brc/app/contacts/one/one.state.spec.js#L2929


1

यदि आप टेम्प्लेट की सामग्री में कुछ भी रुचि नहीं रखते हैं, तो आप $ खाका का मजाक उड़ा सकते हैं:

beforeEach(inject(function($templateCache) {
        spyOn($templateCache,'get').and.returnValue('<div></div>');
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.