2017-06-23 10 views
0

我遇到了「window.angular是未定義」的錯誤,我敢肯定它與JavaScript的異步執行有關,但我不知道如何解決這個問題。登錄頁面和初始登錄頁面是非Angular頁面,應用程序的其餘部分是Angular。因此,我需要使用非Angular頁面進行登錄,然後在非角度登錄頁面加載後,打開下拉菜單並單擊加載Angular頁面的鏈接。看起來所有的動作都在飛行,他們都沒有在等待導航完成,然後檢查Angular是否加載。如何設計量角器頁面對象導航,以避免「window.angular是未定義的」錯誤

我對頁面對象這個基類:

export class AbstractLoadable { 

    constructor(isAngularComponent) { 
     this.isAngularComponent = isAngularComponent; 
    } 

    initComponent() { 

     console.log("Initializing: " + this.isAngularComponent); 

     browser.waitForAngularEnabled(this.isAngularComponent); 

     if(this.isAngularComponent) { 
      console.log("Waiting for angular"); 
      browser.waitForAngular(); 
     } 

     return this; 
    } 
} 

我有這個登錄頁面:

import {AbstractLoadable} from "./AbstractLoadable"; 
import {HomePage} from "./HomePage"; 

export class LoginPage extends AbstractLoadable { 

    constructor() { 
     super(false); 

     this.usernameInput = element(by.id("username")); 
     this.passwordInput = element(by.id("password")); 
     this.loginButton = element(by.css("[name='login']")); 
    } 

    load(baseUrl) { 
     browser.driver.get(baseUrl); 
     return this.initComponent(); 
    } 

    login(username, password) { 
     this.usernameInput.sendKeys(username); 
     this.passwordInput.sendKeys(password); 
     this.loginButton.click(); 

     return new HomePage().initComponent(); 

    } 
} 

我有這個主頁:

import {AbstractLoadable} from "./AbstractLoadable"; 
import {LoginPage} from "./LoginPage"; 
import {AngularPage} from "./AngularPage"; 
import {ExtendedExpectedConditions} from "../ExtendedExpectedConditions"; 

export class HomePage extends AbstractLoadable { 

    constructor() { 
     super(false); 

     this.menuButton = element(by.id("some locator")); 
     this.menuContainer = element(by.css("some locator")); 
     this.menuOptionLink = element(by.css("some locator")); 
    } 

    isMenuButtonPresent() { 
     return ExtendedExpectedConditions.isElementPresent(this.menuButton); 
    } 

    isMenuExpanded() { 
     return ExtendedExpectedConditions.isElementDisplayed(this.menuContainer); 
    } 

    expandMenu() { 
     this.isMenuButtonPresent().then(isPresent => { 
      if(!isPresent) { 
       ExtendedExpectedConditions.waitForElementVisible(this.menuButton, 120000) 
      } 
     }); 

     this.isMenuExpanded().then(isExpanded => { 
      if(!isExpanded) { 
       this.menuButton.click(); 
       ExtendedExpectedConditions.waitForElementVisible(this.menuContainer); 
      } 
     }); 
    } 

    loadAngularPage() { 
     this.expandMenu(); 
     this.menuOptionLink.click(); 
     return new AngularPage().initComponent(); 
    } 
} 

等待方法此類中的靜態實用方法:

export class ExtendedExpectedConditions { 

    static waitForElementPresent(element, timeout = 30000) { 
     browser.wait(ExpectedConditions.presenceOf(element), timeout); 
    } 

    static waitForElementVisible(element, timeout = 30000) { 
     browser.wait(ExpectedConditions.visibilityOf(element), timeout); 
    } 

    static isElementPresent(element) { 
     return element.isPresent() 
    } 
} 

角頁類具有此構造,其通過「真」到基類的構造,這表明它是角頁:

import {AbstractLoadable} from "./AbstractLoadable"; 

export class AngularPage extends AbstractLoadable { 

    constructor() { 
     super(true); 

     this.loadDialogButton = element(by.css("some locator")); 
    } 

    loadDialog() { 
     this.loadDialogButton.click(); 
     //This class also extends the base class and has a constructor that passes true to the base class constructor, indicating that it is an Angular component 
     return new AngularDialog().initComponent(); 
    } 
} 

當我試圖執行此測試中,我不斷收到「 window.angular是undefined」錯誤:

import {LoginPage} from "../pageobject/LoginPage.js"; 

describe("Test",() => { 
    it("Login and navigate",() => { 
     let hp = new LoginPage().load(browser.baseUrl).login("user", "pass"); 
     let ap = hp.loadAngularPage(); 
     let dialog = ap.loadDialog(); 

     //isLoaded() checks visibility of dialog container element 
     expect(dialog.isLoaded()).toBeTruthy(); 
    }); 
}); 

控制檯輸出是這樣的:

Initializing: false 
Initializing: false 
Initializing: true 
Waiting for angular 
Initializing: true 
Waiting for angular 

Failed: Error while waiting for Protractor to sync with the page: "window.angular is undefined. This could be either because this is a non-angular page or because your test involves client-side navigation, which can interfere with Protractor's bootstrapping. See http://git.io/v4gXM for details" 
Error: Error while waiting for Protractor to sync with the page: "window.angular is undefined. This could be either because this is a non-angular page or because your test involves client-side navigation, which can interfere with Protractor's bootstrapping. See http://git.io/v4gXM for details" 

我的package.json是這樣的:

{ 
    "name": "ui-tests", 
    "version": "1.0.0", 
    "description": "A description", 
    "scripts": { 
    "test": "node_modules/protractor/bin/protractor conf.js", 
    "start_selenium": "node_modules/protractor/node_modules/webdriver-manager/bin/webdriver-manager start", 
    "update_selenium": "node_modules/protractor/node_modules/webdriver-manager/bin/webdriver-manager update" 
    }, 
    "dependencies": { 
    "babel-preset-es2015": "^6.24.1", 
    "babel-register": "^6.24.1", 
    "jasmine-reporters": "^2.2.1", 
    "protractor": "^5.1.2" 
    }, 
    "keywords": [ 
    "es6" 
    ], 
    "babel": { 
    "presets": [ 
     "es2015" 
    ] 
    } 
} 

我conf.js是這樣的:

require("babel-register"); 

exports.config = { 

    framework: 'jasmine2', 
    rootElement: 'body', 
    seleniumServerJar:'./node_modules/protractor/node_modules/webdriver-manager/selenium/selenium-server-standalone-3.4.0.jar', 
    chromeDriver: './node_modules/protractor/node_modules/webdriver-manager/selenium/chromedriver_2.30', 
    specs: ['tests/*Spec.js'], 
    capabilities: { 
     browserName: 'chrome', 
     acceptSslCerts: true, 
     trustAllSSLCertificates: true, 
     chromeOptions: { 
      args: ['--no-sandbox'] 
     }, 
    }, 
    baseUrl: 'https://www.myurl.com', 

    suites: { 
     login: '../tests/theTestSpec.js' 
    }, 

    jasmineNodeOpts: { 
     showColors: true, 
     defaultTimeoutInterval: 3600000, 
     isVerbose: true 
    }, 

    getPageTimeout: 120000, 
    allScriptsTimeout: 3600000, 
    delayBrowserTimeInSeconds: 0, 

    onPrepare: function() { 

     require("babel-register"); 

     let origFn = browser.driver.controlFlow().execute; 

     browser.driver.controlFlow().execute = function() { 
      let args = arguments; 

      origFn.call(browser.driver.controlFlow(), function() { 
       return protractor.promise.delayed(this.delayBrowserTimeInSeconds * 100); 
      }); 

      return origFn.apply(browser.driver.controlFlow(), args); 
     }; 

     let getScreenSize = function() { 
      return browser.driver.executeScript(function() { 
       return { 
        width: window.screen.availWidth, 
        height: window.screen.availHeight 
       }; 
      }); 
     }; 

     getScreenSize().then(function(screenSize) { 
      browser.driver.manage().window().setSize(screenSize.width, screenSize.height); 
     }); 
    } 
}; 

回答

0

所有量角器調用返回的承諾。在你當前的代碼中創建它們,但並不總是等待它們解決。所有需要在彼此之後發生的事情需要與then關鍵字鏈接。 promises

例如,這兩項檢查都在同一時間完成。

expandMenu() { 
    this.isMenuButtonPresent().then(isPresent => { 
     if(!isPresent) { 
      ExtendedExpectedConditions.waitForElementVisible(this.menuButton, 120000) 
     } 
    }); 

    this.isMenuExpanded().then(isExpanded => { 
     if(!isExpanded) { 
      this.menuButton.click(); 
      ExtendedExpectedConditions.waitForElementVisible(this.menuContainer); 
     } 
    }); 
} 

而當browser.waitForAngular()等待異步時,這裏'this'被立即返回。

initComponent() { 

    console.log("Initializing: " + this.isAngularComponent); 

    browser.waitForAngularEnabled(this.isAngularComponent); 

    if(this.isAngularComponent) { 
     console.log("Waiting for angular"); 
     browser.waitForAngular(); 
    } 

    return this; 
} 

你將不得不重構你的函數來返回promise,所以你可以一個接一個地鏈接它們。

相關問題