2014-05-16 94 views
5

我正在使用AngularJs和來自Angular-UI的ui-router創建SPA。現在我正在嘗試創建身份驗證邏輯。AngulaJs ui路由器。量角器測試失敗

$rootScope.$on("$stateChangeStart", function (event, toState) { 
    if(toState.authenticate && !MainService.isAuthenticated()) { 
     if($cookieStore.get('authToken')) { 
      MainService.loginWithToken($cookieStore.get('authToken')) 
      .then(function() { 
       $state.go(toState.name); 
       event.preventDefault(); 
      }); 
     } 

     $rootScope.requestPath = toState.name; 
     $state.go('public.login'); 
     event.preventDefault(); 
    } 

    if(toState.url == '/login' && MainService.isAuthenticated()) { 
     $state.go('private.main'); 
     event.preventDefault(); 
    } 
}); 

在狀態改變時,這將檢查狀態是否需要驗證,並在必要時轉換爲登錄狀態。此外,如果用戶登錄,它會阻止進入登錄狀態。身份驗證是通過cookie中存儲的令牌完成的。

這是我的量角器測試場景:

describe('Routes', function() { 
it('Should go to the selected path if user logged in', function() { 
    browser.get('/'); 
    expect(browser.getLocationAbsUrl()).toMatch("/login"); 

    browser.manage().addCookie("authToken", "aaa"); 

    browser.manage().getCookie("authToken").then(function(cookie) { 
     expect(cookie.name).toBe('authToken'); 
     expect(cookie.value).toBe('aaa'); 
    }); 

    browser.get('/'); 
    expect(browser.getLocationAbsUrl()).toMatch("/main"); 

    browser.get('/#/main'); 
    expect(browser.getLocationAbsUrl()).toMatch("/main"); 

    /* This part fails, because, when the user is logged in, 
    he should be transfered to main state, if he is trying to reach the 
    login page. In this failing case, the user is able to reach the 
    /login even if he is logged in. */ 

    browser.get('/#/login'); 
    expect(browser.getLocationAbsUrl()).toMatch("/main"); 

    browser.manage().deleteCookie("authToken"); 

    browser.get('/#/login'); 
    expect(browser.getLocationAbsUrl()).toMatch("/login"); 

    browser.get('/#/main'); 
    expect(browser.getLocationAbsUrl()).toMatch("/login"); 
}); 

});

當我嘗試模擬測試行爲自己,一切正常,但是當我運行量角器:

Message: 
Expected 'http://localhost/#/login' to match '/main'. 

堆棧跟蹤: 錯誤:無法期望

回答

0

您可能需要等待頁面得到加載:

browser.get('/#/main'); 
var ptor = protractor.getInstance(); 
ptor.waitForAngular(); 
expect(browser.getLocationAbsUrl()).toMatch("/main"); 
+0

沒有運氣,測試仍然失敗 – nn4n4s

+0

你看右頁運行測試時得到加載?如果是這樣,請嘗試使用'ptor.sleep(1000);',這是我絕望時使用的。如果您找到更好的方法,請告訴我... 如果您沒有看到正確的頁面正在加載,那麼您的cookie刪除可能有問題嗎? – Cal

1

我碰到另一個問題解決了這個問題。

基本上,您等待新頁面中的元素出現,而不是依靠量角器等待狀態/頁面加載完成。在編寫這個答案的時候,量角器在等待頁面完全加載到UI路由器上仍然不可靠。量角器等待$超時和$ http完成。

official doc

因此,如果您使用的WebSocket,它可能不會被覆蓋(至少根據我的觀察)。

你需要使用該API browser.wait

browser.wait(function() { 
     return $('#test321').isPresent(); // keeps waiting until this statement resolves to true 
     }, 
     timeToWaitInMilliseconds, 
     'message to log to console if element is not present after that time' 
    ); 

    expect($('#test321').isPresent()).toBe(true); 

您可以在下面的鏈接細節 Protractor, AngularJS, Parse -- Protractor does not wait for Angular to resolve

0

注意,在角1.3版browser.getLocationAbsUrl()只返回相對路徑。見https://github.com/angular/protractor/issues/1436問題:

Using angular 1.3 in the app under test and protractor 1.3.1 browser.getLocationAbsUrl() returns a relative url instead of the absUrl due to using angular.getTestability().getLocation() instead of $location.absUrl(). It's probably as easy as adding a getLocationAbs() to $$testability, but that goes into architectural questions I don't have context for.