我遇到了「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);
});
}
};