我有一个Protractor测试,启动重新加载相同的Angular应用程序。有时它在Travis构建中失败,但在构建一次或两次重新启动后会通过。很少在我的本地机器上失败。 Travis构建使用Firefox,但它在我的机器上失败的时间一直在使用Firefox和Selenium的chromedriver。
我已设置rootElement: 'html'
(按this GitHub issue on Protractor中的建议),因为这是ng-app
的位置,但我仍然收到此错误:
等待Protractor与页面同步时出错:“root元素(html)没有注入器。这可能意味着它不在ng-app中。”
错误是angular.element('html').injector()
返回falsey的结果,即使Angular has loaded。量角器代码中的previous test证实了这一点。
测试涉及被重定向到恰好是同一个角应用的不同index.html
。重定向的原因是提供语言选择,然后以该语言重新加载应用程序。
有多个区域设置(为简单起见,此处显示了两个区域设置)。 app
是文档根目录,因此app/index.html
是入口点,可检测系统语言或默认为en-gb
,然后重定向到app/<locale>/index.html
。前者不是Angular应用程序(app/
);后者是(app/<locale>/
)并链接到../common/
的库和Angular模块文件。区域设置文件夹中的index.html
个文件是相同的。
访问文档根目录时会发生什么?
/
- &gt;重定向/en-gb/#/language
当你选择德语时?
/en-gb/#/language
重定向../de/#/menu
- &gt; /de/#/menu
目录结构:
└── app
├── common
│ ├── fonts
│ ├── images
│ ├── lib
│ ├── modules
│ └── styles
├── de
│ ├── i18n.js
│ └── index.html
├── en-gb
│ ├── i18n.js
│ └── index.html
└── index.html
测试:
(function () {
'use strict';
describe('Module: app, language screen:', function () {
beforeEach(function () {
browser.get('http://localhost:9000/en-gb/#/language/');
this.$germanChoice = // get the clickable element to select German
this.$buttonContinue = // get the clickable element to continue
});
describe('continue button', function () {
it('should go forward to the menu', function () {
this.$germanChoice.click();
this.$buttonContinue.click();
expect(browser.getCurrentUrl()).toBe('http://localhost:9000/de/#/menu/');
});
});
});
}());
使用缩小文件的区域设置index.html
:
<!doctype html>
<!--[if IE 8]> <html id="ng-app" ng-app="app" lang="{{ app.locale.html }}" class="no-js lt-ie10 lt-ie9"> <![endif]-->
<!--[if IE 9]> <html id="ng-app" ng-app="app" lang="{{ app.locale.html }}" class="no-js lt-ie10"> <![endif]-->
<!--[if gt IE 9]><!--> <html id="ng-app" ng-app="app" lang="{{ app.locale.html }}" class="no-js"> <!--<![endif]-->
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title ng-bind="app.page.title ? app.page.title + ' - ' + app.page.titleBase : app.page.titleBase"></title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="../common/lib/nouislider/jquery.nouislider.css" />
<!--[if gt IE 8]><!-->
<link rel="stylesheet" href="../common/styles/b8a085fb.main.css">
<!--<![endif]-->
<!--[if lt IE 9]>
<link rel="stylesheet" href="../common/styles/f71e8123.ie.css">
<![endif]-->
<!--[if lt IE 9]>
<script src="../common/scripts/a5663f12.lt-ie9.js"></script>
<![endif]-->
</head>
<body ng-class="{ 'ios6': app.environment.ios6, 'gt-ios6': app.environment.gtIos6, 'cordova': app.environment.cordova }">
<div ng-view="" autoscroll="true"></div>
<script src="../common/scripts/cbd2241e.app.js"></script>
<script src="i18n.js"></script>
</body>
</html>
答案 0 :(得分:2)
我偶尔会遇到非Angular登录页面的问题(其中一些有几个步骤)。我认为您的语言选择页面可能类似。该解决方案在您的测试中有点逻辑,并与browser.driver
中公开的Webdriver API相结合。
if ('some condition that determines you are on a non-Angular page') {
browser.driver.findElement(by.id('language-choice')).click();
}
测试的最佳条件是:
每当你不在Angular页面上时使用browser.driver
,因为它绕过了Protractor。否则,Protractor将寻找Angular,找不到它,并抛出错误。你可以在菜单的下方区域找到browser.driver
所能做的一切:http://angular.github.io/protractor/#/api
然后,为了在使用Protractor之前等待Angular页面显示,请尝试以下代码段:
browser.driver.wait(function() {
return browser.driver.getCurrentUrl().then(function(url) {
return url.toString().indexOf('my angular page url') !== -1;
}, function(err) {
throw err;
});
}, 5000, 'Timed out waiting for your Angular page to load.');
这在您的onPrepare
语句中特别有用(只需在return
之前添加browser.driver.wait
即可。测试将等待您的Angular页面加载,之后您可以将Protractor放在心里。
稍微讨论一下,这个相同的片段可用于对多步非Angular入门页面做出反应。并且,封装到它自己的整洁的小函数中,这可以在Protractor易于被转储到非Angular页面的任何地方重复使用。