Javascript 如何设计量角器页面对象导航以避免;window.angular未定义;错误

Javascript 如何设计量角器页面对象导航以避免;window.angular未定义;错误,javascript,protractor,Javascript,Protractor,我遇到了“window.angular是未定义的”错误,我确信这与JavaScript的异步执行有关,但我不知道如何解决这个问题。登录页面和初始登录页面是非角度页面,应用程序的其余部分是角度页面。因此,我需要使用非角度页面登录,然后一旦非角度登录页面加载,打开下拉菜单并单击加载角度页面的链接。似乎所有的动作都在继续,没有一个动作在检查Angular是否加载之前等待导航完成 我有一个页面对象的基类: export class AbstractLoadable { constructor(

我遇到了“window.angular是未定义的”错误,我确信这与JavaScript的异步执行有关,但我不知道如何解决这个问题。登录页面和初始登录页面是非角度页面,应用程序的其余部分是角度页面。因此,我需要使用非角度页面登录,然后一旦非角度登录页面加载,打开下拉菜单并单击加载角度页面的链接。似乎所有的动作都在继续,没有一个动作在检查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();
    }
}
wait方法是此类中的静态实用程序方法:

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()
    }
}
angular page类具有此构造函数,该构造函数将“true”传递给基类构造函数,表示它是一个angular page:

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未定义”错误:

控制台输出如下:

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

所有量角器调用都返回承诺。在当前代码中,您创建了它们,但并不总是等待它们得到解决。每件事都需要用then关键字链接起来

例如,这两项检查同时进行

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;
}
您必须重构您的函数以返回承诺,这样您就可以一个接一个地链接它们

initComponent() {

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

    browser.waitForAngularEnabled(this.isAngularComponent);

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

    return this;
}