我在运行量角器 0.8 时遇到问题,并且在手动引导的应用程序上运行量角器时遇到问题。
以下是一些片段,揭示了应用程序和设置的相关部分:
索引.html:
<script type="text/javascript" data-main="js/main" src="js/libraries/require.js"></script>
js/main.js:
require({
shim: {
.... snip ..
}
},
['require', ..... ], function(require) {
return require(['bootstrap']);
bootstrap.js:
var appElm = $('html');
appElm.addClass('ng-app'); // this
angular.bootstrap(document, ['app']);
这在实践中有效,并且 Angular 以正确的方式启动。 当我查看 html 源代码时,我看不到 ng-app 属性出现在 html 元素上。 可能是量角器也没有这样做?
我使用量角器示例配置并更改了相关值以适合我的应用程序:
specs: [
'../src/test/javascript/protractorSpec/*_spec.js',
],
baseUrl: 'http://localhost:8080/Viewer/',
rootElement: 'html',
样品测试:
describe('List SMC Charts', function() {
var ptor= protractor.getInstance();
beforeEach(function() {
ptor.get('#/smcChart');
});
it('list, no filter', function() {
var selectOption = ptor.findElement(ptor.By.input("selectOption"));
});
});
当我运行这个测试时,会出现两个错误:
1) List SMC Charts list, no filter
Message:
Error: Angular could not be found on the page http://localhost:8080/Viewer/#/smcChart
Stacktrace:
Error: Angular could not be found on the page http://localhost:8080/Viewer/#/smcChart
at /usr/local/lib/node_modules/protractor/lib/protractor.js:392:15
和
2) List SMC Charts list, no filter
Message:
TypeError: Cannot call method 'input' of undefined
Stacktrace:
TypeError: Cannot call method 'input' of undefined
at null.<anonymous> (/Users/........//Viewer/src/test/javascript/protractorSpec/some_spec.js:9:55)
第一个错误似乎是最重要的,但最后一个错误也很有趣。 在我看来,这行:ptor.By.input 不起作用。
有任何想法吗?
页面中是否包含 Angular 代码? 看起来您需要 shim、bootstrap 和其他工具,但未显示angular.min.js
。
'app': {
deps: ['libraries/angular', 'libraries/angular-resource', 'libraries/angular-strap']
},
上面的代码片段位于 shim{} 元素中,我将其排除在代码片段之外,因为它似乎与我不太相关。 但这是加载 angular.js 的方式。
你好,
是的,Protractor 目前需要一个 ng-app,所以手动引导的站点会有问题。 希望尽快找到解决此问题的方法。
好的谢谢更新。 当您找到解决方法后,您可以在此问题中发布它吗?
抱歉回复慢 - 你应该可以通过这样做来解决
describe('List SMC Charts', function() {
var ptor= protractor.getInstance();
beforeEach(function() {
ptor.driver.get('#/smcChart'); // Just use the plain old webdriver here, it won't complain if Angular isn't loaded yet.
});
it('list, no filter', function() {
var selectOption = ptor.findElement(ptor.By.input("selectOption"));
});
});
您是否在某处设置了 ptor 变量? 例如var ptor = protractor.getInstance()
?
这事有进一步更新吗? 您建议的修复方法对我不起作用(量角器@0.10.0,角度@1.0.7)
我有一个尴尬的非角度登录屏幕组合,后跟一个 requirejs,手动引导的应用程序:
describe('User levels', function() {
var ptor, driver;
var findByName = function (name) {
return driver.findElement(protractor.By.name(name));
};
describe('Editors', function() {
ptor = protractor.getInstance();
driver = ptor.driver;
it('Can log in', function() {
driver.get('http://localhost:8000/');
findByName('login').sendKeys('test_editor');
findByName('pass').sendKeys('rubbish');
driver.findElement(protractor.By.css('button[type="submit"]')).click();
}, 20000);
it('Shows the homepage', function() {
var el = ptor.findElement(protractor.By.css('h1[field="pageTitle"]'));
expect(el.getText()).toEqual('Welcome to Home');
}, 30000);
});
});
还有我的main.js
:
require([
'angular',
'app'
], function (angular, app) {
'use strict';
var body = document.body, name = app.name;
body.setAttribute('ng-app', name);
body.setAttribute('id', 'ng-app');
angular.bootstrap(body, [name]);
});
登录部分有效,我可以看到在量角器出现UnknownError: javascript error: angular is not defined
错误之前加载受保护页面的闪光。 我尝试使用driver.get('...')
甚至ptor.get('...')
重新加载页面,但没有任何效果。
感激地收到任何提示/建议/修复。
@magnetised您需要某种方式告诉您的测试等到登录完成后再尝试其他测试。 我认为发生的事情是您在 Angular 加载到页面之前尝试使用 ptor.findElement 。
您的“可以登录”规范应以等待语句结束,该语句检查您的应用程序的某些条件。 在此处查看示例 - https://github.com/angular/protractor/blob/master/spec/login/viaConfigConf.js
@juliemr Brilliant,效果很好。
我知道量角器会做“等到加载角度”,但我想你不能涵盖所有情况。
再次感谢。
我有完全相同的设置。 @juliemr你介意分享你的解决方案吗? 你的等待条件是什么? 谢谢!
@jorgenfb我想知道你的意思是不是针对我的评论?
我的解决方案只涉及等待 Angular 路由器启动并将 url 从登录系统将您重定向到的裸露的“/”更改为默认路由——在我们的例子中为“/#view”。
我把它做成了一个函数,我可以在所有测试中重用它:
var waitUntilLoaded = function() {
ptor.wait(function() {
return ptor.driver.getCurrentUrl().then(function(url) {
return /view/.test(url);
});
});
};
我不知道这是否适合您,这取决于您的路由配置。
@juliemr谢谢,就像一个魅力:)
我遇到了类似的问题(在 SO 上找到:http://stackoverflow.com/questions/19391813/protractor-fails-to-find-angular),即使 Angular 非常简单地加载和运行,Protractor 也找不到 Angular。 简单的解决方案(在不试图找到 Angular 的情况下进行测试)是我们应该采用的方式吗? 它似乎违背了 Protractor 专门用于测试 Angular 应用程序的目的。
编辑:我还应该注意,这个问题中提出的解决方案对我不起作用。
+1 以获得更好的角度手动引导文档
这仍然相关吗?
老实说,我不知道,因为我已经放弃了尝试,也没有时间回去看看是否发生了变化。 考虑到从那时起的版本变化,如果你想关闭它,我不会争辩。 它总是可以稍后重新打开。
我今天刚开始使用量角器,我们的应用程序使用 require.js... 如果在测试手动引导的应用程序方面有任何更新,我对此很感兴趣。 :-)
这里同样的问题。 在 Angular 应用程序之外获取登录页面的应用程序。 先前评论中的解决方法似乎已过时。 非常希望更新关于如何能够测试这种场景的文档。
@hankduan是的,我想是的。
我现在正在努力解决这个问题。 背景类似:我有一个更大的应用程序,它的依赖项是通过 RequireJS 管理的。
我已经使用window.name='NG_DEFER_BOOTSTRAP!';
& angular.resumeBootstrap()
更新了我的应用程序,但它仍然无法正常工作。
说到这里,我不知道接下来该怎么办。 为了进一步调查,我在https://github.com/knalli/protractor-with-deferred-bootstrap设置了一个测试用例
git clone https://github.com/knalli/protractor-with-deferred-bootstrap.git
cd protractor-with-deferred-bootstrap
npm install
npm run-script webdriver
(硒服务器)npm run-script server
(服务于迷你 AJS 应用的演示应用服务器)npm run-script e2e-test
(运行量角器...)结果是
Using the selenium server at http://localhost:4444/wd/hub
Login: Click
Login: Waiting...
A Jasmine spec timed out. Resetting the WebDriver Control Flow.
The last active task was:
unknown
F
Failures:
其次是
UnknownError: unknown error: [ng:btstrpd] App Already Bootstrapped with this Element '
最后一个错误有点奇怪,甚至可能具有误导性:测试已经执行(就预期而言是成功的,并且我们可以在浏览器中看到)。
交叉检查:如果我将演示应用程序切换到使用手动包含的非延迟引导(此变体在分支no-deferred
中可用),那么它将成功运行。
我已经尝试了一些所谓的“解决方法”:
protractor.getInstance()
和ignoreSynchronization
--> 没有区别clientSideScripts.js/waitForAngular
--> 没有区别我昨天写了我的第一个量角器测试,并且遇到了与 knalli 相同的问题。
感谢您编写示例@knalli。 过几天我看看
所以我的量角器测试所有工作(除了一次失败,但这是我的错:-P)。
让我知道这是否有帮助。
这是我的设置:
量角器版本:
版本 1.0.0-rc4
硒独立:
已是最新
铬驱动程序:
已是最新
/*jshint expr: true*/
/*global browser: true*/
var TEST_DIR = '../tests/';
exports.config = {
seleniumAddress: 'http://localhost:4444/wd/hub'
, specs : [ '../tests/e2e/_protractor.js' ]
, capabilities: {'browserName': 'chrome' }
, chromeDriver: './chromedriver' // <---- I remember not being able to get chromedriver working
// for some reason, so I just downloaded the executable and put it
// in my config directory
, onPrepare: function() {
"use strict";
browser.driver.get('http://localhost:5000/register');
browser.driver.wait(function() {
return browser.driver.getCurrentUrl().then(function(url) {
return /\#\/registration/.test(url);
});
});
}
// chromeOnly: true,
// baseUrl: 'http://localhost:5000/register'
, jasmineNodeOpts: {
showColors: true
}
};
/*jshint expr: true, undef: true */
/* global element: true, by: true, browser: true, model:true */
(function(){
"use strict";
var RegistrationPage = function(){
browser.driver.wait(function() {
return browser.driver.getCurrentUrl().then(function(url) {
return /\#\/registration/.test(url);
});
});
};
var account = new RegistrationPage();
account.elem = element.all(by.name('account_exists'));
account.accountNumber = element(by.name('account_number'));
account.submitAccountButton = element(by.css('#account_input button'));
account.selectHasAccount = function(){
account.elem.get(0).click();
return browser.getCurrentUrl();
};
account.enterAccountNumber = function(keys){
account.selectHasAccount().then(function(){
account.accountNumber.sendKeys(keys);
return account.submitAccountButton.click()
.then(function(){
return browser.getCurrentUrl();
});
//this wont log because already returned ^
// console.log('need to return again');
});
};
account.noAccount = function(){
account.elem.get(1).click();
};
describe('registration page', function() {
it("will survive", function(){
var registrationPage = new RegistrationPage()
, title = browser.getTitle();
expect(title).toBe('Web Shop | Homepage');
});
it('will change route on account_exists radiobox click', function(){
var elem = element.all(by.name('account_exists'))
, _url;
elem.get(0).click()
.then(function(){
_url = browser.getCurrentUrl().then(function(_url){
expect(_url).toBe('http://localhost:5000/register#/registration/has');
});
})
.then(function(){
elem.get(1).click().then(function(){
_url = browser.getCurrentUrl();
expect(_url).toBe('http://localhost:5000/register#/registration/no');
});
});
});
describe('navigate the hasAccount path:', function(){
it('will click hasAccount which will cause a route change.', function () {
expect(account.selectHasAccount()).toBe('http://localhost:5000/register#/registration/has');
});
it("will submit a valid account number", function(){
expect(account.enterAccountNumber('1231231231')).toBe('http://localhost:5000/register#/user');
});
});
it('will click noAccount which will cause a route change.', function () {
var _url;
account.noAccount();
_url = browser.getCurrentUrl();
expect(_url).toBe('http://localhost:5000/register#/registration/no');
});
});
})();
var pathToJQuery
if('querySelector' in document
&& 'localStorage' in window
&& 'addEventListener' in window) {
//ie9+ and all browsers
pathToJQuery = 'lib/jquery/dist/jquery'
} else {
//ie8 and ie7
pathToJQuery = 'lib/jquery-1.7.2.min'
}
requirejs.config({
paths : {
// Paths
"reg": 'js/registration'
, "com": 'js/common'
, "init": 'js/init'
, "regD": 'js/registration/directives'
, "regC": 'js/registration/controllers'
, "regS": 'js/registration/services'
, "regM": 'js/registration/modules'
//
// Frameworks
, "angular": "lib/angular/angular"
, "angular.animate" : "lib/angular-animate/angular-animate"
, "jquery": pathToJQuery //< = == v long story; don't judge me.
, "jqueryMigrate" : "lib/jquery-migrate/jquery-migrate"
, "mocks": "lib/angular-mocks/angular-mocks"
, "ui_router": "lib/angular-ui-router/release/angular-ui-router"
, "Q": "lib/q/q"
// Init
, "apps_init" : 'js/init/apps_init'
, "apps_bootstrap" : 'js/init/apps_bootstrap'
// , "jquery_bootstrap" : 'js/init/jquery_bootstrap'
, "registration": "js/init/registration"
// Common
// Registration
, "registration": "js/registration/registration"
// Controllers
, "account.controller" : 'js/registration/controllers/account.controller'
, "user.controller" : 'js/registration/controllers/user.controller'
// Directives
, "account.directive" : 'js/registration/directives/account.directive'
// Services
, "user.service" : "js/registration/services/user.service"
}
, shim: {
'angular': {
exports : 'angular'
}
, 'angular.animate' : {deps: ['angular']}
, 'jqueryMigrate' : {deps: ['jquery']}
, 'ui_router' : ['angular']
, 'mocks': { deps: ['angular'], 'exports': 'angular.mock' }
}
});
if( pathToJQuery === 'lib/jquery/dist/jquery' ){
requirejs([
'angular' , 'jquery' , 'jqueryMigrate', 'init/jquery_bootstrap', 'init/apps_bootstrap' ]
, function(angular, jquery, jquery_bootstrap, apps_bootstrap) {
}
);
} else {
requirejs([
'angular' , 'jquery' , 'jqueryMigrate', 'init/jquery_bootstrap', 'init/apps_bootstrap' ]
, function(angular, jquery, jqueryMigrate, jquery_bootstrap, apps_bootstrap) {
}
);
}
console.log("working");
<!DOCTYPE html>
<html xmlns:ng="http://angularjs.org"
xmlns:fab="http://angularjs.org"
xmlns:ui ="http://angularjs.org"
lang = "en" class = "no-js" >
<head >
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=Edge"/>
<meta charset="utf-8">
<link rel="shortcut icon" type="image/x-icon" media="all" href="/images/favicon.ico" />
<script type="text/javascript" src="lib/modernizr.js"></script>
<!-- Default ie theme files:-->
<!--[if lte IE 9]><script type="text/javascript">console = {}; console.log = function(){};</script><![endif]-->
<!--[if IE 8]><link type="text/css" rel="stylesheet" href="build/css/ie8/theme.css" /><![endif]-->
<!--[if IE 7]><link type="text/css" rel="stylesheet" href="build/css/ie7/theme.css" /><![endif]-->
<!-- Normal styles -->
<link type="text/css" href="css/style.css" rel="stylesheet">
<!--[if IE 8]> <link type="text/css" rel="stylesheet" href="build/css/ie8/ie_8.css" /> <![endif]-->
<!--[if IE 7]> <link type="text/css" rel="stylesheet" href="build/css/ie7/lte_ie7.css"/> <link type="text/css" rel="stylesheet" href="build/css/ie7/ie_7.css" /><![endif]-->
<script data-main="main" src="lib/requirejs/require.js"></script>
</head >
<body class = "page-homepage language-en" >
<div id = "wrapper" >
<div id = "page" data-currency-iso-code = "USD" >
{{> _header}}
<a href = "#skip-to-content" class = "skiptocontent" >Skip to content</a >
<a href = "#skiptonavigation" class = "skiptonavigation" >Skip to navigation menu</a >
<!--[if lte IE 10]> <p class="browsehappy" style="margin-top: 10px; ">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p><![endif]-->
<main ng-cloak id = "content" role = "main" class = "page_main <!--[if IE7]>ng-cloak<![endif]-->" >
</main>
</div >
</div >
</body >
</html >
(function(){
"use strict";
// node requires
//==============================
// express-hbs
// express
//
const express = require('express')
, portN = 5000
, hbs = require('express-hbs')
, app = express()
, path = require('path')
, Server = require('./server')
, bodyParser = require('body-parser')
, serveStatic = require('serve-static')
, session = require('express-session')
, router = express.Router()
, logger = require('morgan')
, methodOverride = require('method-override')
, errorhandler = require('errorhandler')
// view paths
//==============================
//
//
//
, viewsD = __dirname + '/views/'
, partialsD = viewsD + 'partials/'
, layoutsD = viewsD + 'layouts/'
, testsD = __dirname + '/tests/'
, publicD = __dirname + '/public/'
, styleguideD = publicD+ '/styleguide/'
, defaultF = layoutsD + 'default.hbs';
// Express setup.
//==============================
//
//
//
app.use(express.static(publicD))
.use(bodyParser())
.use(logger('dev'))
.use(methodOverride())
.use(serveStatic(path.join(__dirname, 'public')))
.use(errorhandler());
app.set('view engine', 'hbs')
.set('port', process.env.PORT || portN)
.set('cache', false)
.set('views', viewsD);
app.engine('hbs', hbs.express3({
partialsDir: partialsD,
defaultLayout: defaultF,
layoutsDir: layoutsD
}));
var indx = {};
app.get( '/' ,function (req, res) {
res.render(partialsD + '_home.hbs', indx);
});
app.get( '/register' ,function (req, res) {
res.render(partialsD + '_register.hbs', indx);
});
new Server(app);
})();
module.exports = function(app){
"use strict";
var http = require('http');
http.createServer(app).listen(app.get('port'), function(){
console.log('Express server listening on port ' + app.get('port'));
});
};
module.exports = function (app) {
"use strict";
var http = require ('http');
http.createServer (app).listen (app.get ('port'),function () {
console.log ('Express server listening on port ' + app.get ('port'));
}).on ('error', function (e) {
console.log ("got error: " + e.message);
});
};
"dependencies": {
"body-parser": "^1.2.1",
"bower": "^1.3.2",
"errorhandler": "^1.0.1",
"express": "^4.3.1",
"express-hbs": "^0.7.9",
"express-session": "^1.2.0",
"node-dev": "^2.3.0"
},
"scripts": {
"start": "node --harmony $* ./node_modules/.bin/node-dev controller.js",
},
"devDependencies": {
"browserstack-webdriver": "^2.41.1",
"grunt-protractor-runner": "^1.0.0",
"method-override": "^1.0.2",
"morgan": "^1.1.1",
"protractor": "^0.23.1",
"requirejs": "^2.1.11",
"serve-static": "^1.1.0",
},
"author": "Andrew Luhring"
config/
protractor.config.js
chromedriver
server.js
controller.js
public/
main.js
js/
lib/
tests/
e2e/
_protractor.js <=== test file.
views/
layouts/
default.hbs
partials/
_head.hbs
_register.hbs <=== file being tested.
很确定这是我的整个设置。 想我会去冗长的。 希望有帮助。
我需要做的是:
见https://github.com/mikaraento/protractor-reuse/blob/master/index.js
我可以知道为什么在 chrome 和 firefox 浏览器中执行得很好的量角器脚本不能在 Internet Explorer 中执行吗?
尽管相同的脚本在其他浏览器中可以完美执行,但在 Internet Explorer 中无法始终以相同的方式执行。 我经常遇到错误,例如超时异常
消息:'超时:等待规范完成 30000 毫秒后超时',
跟踪:{堆栈:未定义}}]
并且有时在 Internet Explorer 中未检测到元素。
虽然我使用默认时间间隔作为 defaultTimeoutInterval :1000000 ,但在我的脚本中,我在 Internet Explorer 中执行时遇到了上述错误...
谁能帮我解决这个问题?
问候,
桑托什·春楚
我不认为这只是手动引导的问题吗? 或者您是否能够在 Chrome 和 Firefox 中运行手动引导的应用程序?
@hankduan你已经看过测试用例了吗? 也许有什么我们可以帮忙的?
我有一个 CL,它改变了量角器的引导工作方式(https://github.com/angular/protractor/pull/1155)。 它的主要目的是解决许多其他问题,但我认为它应该通过手动引导来修复(或至少有帮助),具体取决于您的引导方式。 但是,我从未设置手动引导程序进行测试,所以这只是理论上的。
这个 PR 需要改量角器和改 Angular,所以短时间内可能不会发布。
在寻找手动引导 Angular 以与 Protractor 一起使用的方法时,这个问题似乎是最热门的搜索结果,所以我认为这与建议其他解决方案一样好。 这适用于您的整个界面是 Angular 应用程序的情况(而不是像上面的示例那样在登录后在 div 上进行引导)。
虽然可以将 Protractor 的测试延迟到加载 Angular 之后,但官方 Angular 文档声明您不能使用 Protractor 进行手动引导。 我倾向于回避官方文档似乎禁止的解决方法。
我正在使用 Grunt 将我的代码合并/Uglify 到单个 JS 文件,这是 index.html 中引用的唯一脚本,带有脚本标记。 我们称之为 script.js。 在开发中,我运行了一个不同的 Grunt 任务,它只将我需要的文件连接在一起,以便单独、异步地加载其余的 JS 文件,并带有时间戳以防止缓存。 在我开发时,这组连接的脚本替换了 script.js。 在任何一种情况下,我都只从 index.html 加载 script.js,并带有一个 script 标签。
因此,在开发中,我必须进行手动引导。 这很容易,因为我可以将一个我没有连接到生产 JS 中的单个文件包含在内,并且我确保在所有其他 JS 加载后加载此脚本。
bootstrap_dev.js
.element(document.body)
.ready(function() {
angular.bootstrap(document.body, ['App']);
});
在生产中,我不能手动引导,因为 Protractor 不喜欢它。 我正在针对我的生产代码运行量角器。 我还从我的 HTML 中删除了“ng-app”属性,因此应用程序不会在开发中过早引导,因此不会发生正常的自动引导。 我在生产中通过在 script.js 中的所有其他 JS 之前放置一个脚本来弥补这一点。
bootstrap_prod.js
window.document.body.setAttribute("ng-app", "myApp");
只需将“myApp”替换为主模块的名称即可。
在开发中,如果您执行上述操作,您可以异步加载您的脚本并执行手动引导。 但是,如果您可以只针对生产代码运行 Protractor 测试(可以通过脚本标签从单个文件加载,只需在加载 Angular 之前添加 ng-app 指令,以便它自动引导。现在您有了异步脚本加载开发中的各种脚本,并为生产代码运行量角器测试。
最终为我工作的是在我的 protractor.conf.js 中添加以下函数:
onPrepare: function()
{
// implicit and page load timeouts
browser.manage().timeouts().pageLoadTimeout(40000);
browser.manage().timeouts().implicitlyWait(25000);
// for non-angular page
browser.ignoreSynchronization = true;
// sign in before all tests
}
如果有更好的方法,请告诉我=]
有类似的问题。 找到了这个有用的信息:
没有区别,应用程序如何在生产中被提升,但在测试中量角器正在这样做:
因此,请确保您的生产代码与此过程不冲突,因为 angular 只能被引导一次,第二次调用 angular.boostrap() 或 angular.resumeBoostrap() 将破坏量角器或应用程序。 所以,完全不需要body中的ng-app ,你可以自己调用angular.boostrap(),它会被protractor使用NG_DEFER_BOOTSTRAP处理! 适当地。
确保在加载和启动期间任何应用程序代码都不会更改window.name 。 就我而言, jquery正在这样做,不知道为什么。 从我的项目中完全删除jquery并且测试有效。 这是问题的根源!
现在,我正在搜索,如何在不破坏测试的情况下恢复 jquery,因为我的项目需要它!
最后,
我们的问题是在一个页面上有两个版本的 jQuery(第二个版本是由外部库加载的)。 删除它,只在页面上留下我们的 jQuery,一切正常。
一些代码,可能会有所帮助:
索引.html
<body>
...
<script data-main="require.conf" type="text/javascript" src="bower_components/requirejs/require.js"></script>
</body>
需要配置
...
deps: ["proto/main"],
...
原型.js
// We just load deps and register the module:
define(["deps"],function(){
angular.module('proto'...
}
原型/main.js
define(["require", "exports", "proto", "angular"],
function (require, exports) {
angular.bootstrap(document, ['proto']);
});
实际上,测试规范
var protractor = require('protractor');
var ptor;
function prepareBrowser() {
ptor = protractor.getInstance();
return ptor.get(ptor["baseUrl"] + '/login').then(function () {
console.log("got");
return ptor.waitForAngular().then(function () {
console.log("ngwaited");
});
});
}
describe('container', function () {
beforeEach(function () {
return prepareBrowser();
});
describe('form tests', function () {
it('form is shown', function () {
expect($('[ng-controller=LoginContr]').isDisplayed()).toBeTruthy();
});
});
});
输出
Using the selenium server at http://localhost:4444/wd/hub
got
ngwaited
container
form tests
form is shown - pass
Finished in 3.112 seconds
1 test, 1 assertion, 0 failures
万岁!
当我们从使用ng-app
切换到angular.bootstrap()
时,将rootElement: 'div'
添加到 projotractor.conf 是我们需要让量角器再次工作的唯一更改。 我们正在使用角度 1.3.0 和量角器 1.3.1。
@jongunnip是的,这对我也有用,谢谢!
@mikaraento它对我有用,谢谢~
嗨,伙计们,与此线程相关的奇怪事情。
我有一个常规的 Angular 应用程序 - 没有 requirejs 或任何东西,我使用的是量角器 2.0.0。
当我在登台环境上运行系统测试时,它可以工作。
当我在本地运行它时,它给了我:
org.openqa.selenium.WebDriverException: unknown error: [ng:btstrpd] App Already Bootstrapped with this Element
... 消息
当我将 Nginx 服务器配置为提供静态资源而不是grunt:server
时,一切正常。
如果我在开发中使用 livereload 运行它真的很重要吗?
似乎静态服务器的行为不同,并且 grunt 提供一些 404 或重定向,所以 webdriver 发疯了。
大家好,
经过大量时间阅读和阅读,我找到了一种适用于我的项目的解决方案(修复量角器执行流程)
if(location.href.indexOf("protractor-test") < 0){
// start angular app
angular.bootstrap(document, [module.name]);
} else {
// start angular app to protractor tests
window.name = 'NG_DEFER_BOOTSTRAP!' + window.name;
angular.bootstrap(document, [module.name]);
}
终于又重新开始工作了\o/
复制@juliemr
我最近(仅 1-2 周)开始使用 Protractor 来测试我的 Angular 应用程序。 我的应用程序在登录页面的 body 标记中定义了 ng-App。 我的测试一直抱怨说“在页面 httP://(网站地址)上找不到 Angular:角度从未提供 resumeBootstrap”但测试执行很好。 不确定这个问题(如果我打开浏览器忽略同步参数,那么它工作正常,但这不是正确的方法),我可以尝试 Juliemr 的建议(使用旧版驱动程序导航),但只是想了解我的应用程序抱怨的原因即使它在 body 标签中有 ng-App。 应用程序功能行为是这样的..登录页面..一旦登录单击主页上的某个链接,它会打开另一个窗口/选项卡。 有人可以帮我找到所有需要验证的步骤,以确保引导是自动完成的(一个是正文标签中的 ng-app 参数)? 我是否需要检查 bootstrap.js 文件中的某些内容(我在 bootstrap 文件中没有看到任何 ng-app 参数,因此需要检查。谢谢
这个问题有更新吗? 配置量角器以使用没有 ng-app 的 Angular 应用程序的最佳实践或方法是什么? @erkobridee你能进一步解释你的例子吗? 有人可以解释如何正确处理 window.name 关于量角器在加载角度时应该如何等待的问题吗?
@juliemr使用 Angular 1.5,手动引导是引导的首选方式。 途中是否有祝福的量角器支持?
+1 我认为这个问题应该是更高的优先级。 如果 Protractor 不能与手动引导程序一起使用,那么使用 Protractor 没有任何好处。 在 Webdriver 上使用 Protractor 的全部意义在于 Protractor 为您处理所有角度同步。
我有同样的问题。 任何更新?
嗨,有什么计划或流程来改善这个吗?
奇怪的是没有反馈。 我的应用程序缺少 ng-app,我无法测试
他们用量角器
2016 年 7 月 16 日上午 5:01,“millerwx” [email protected]写道:
嗨,有什么计划或流程来改善这个吗?
—
您收到此消息是因为您发表了评论。
直接回复此邮件,在 GitHub 上查看
https://github.com/angular/protractor/issues/66#issuecomment -233104701,
或使线程静音
https://github.com/notifications/unsubscribe-auth/AOghFs2ff0e-88DLafNGD3iCH8uCOgVaks5qWEmIgaJpZM4A82d7
.
直到 2016 年的这个日期,这对我来说仍然是一个问题。 我按照磁化答案解决了这个问题。 我只是做了一些改变。 对话的好处和超出范围的是跟踪重定向并返回您的应用程序。 *我是用 Babel 做的,但你可以用 ES5 来代替。
`describe('登录界面', ()=>{
var urlTimeout = 9000;
const waitForUrlRegex = (regex, urlMatcher )=>{
return driver.wait(()=>{
return driver.getCurrentUrl().then( (url)=>{
return regex.test(url);
});
}, urlTimeout, "Expectation error: Timeout for url not matching " + urlMatcher );
};
const waitForRoute = (route)=>{
return waitForUrlRegex( new RegExp( route + "$" ), route );
}
const waitForUrl = (url)=>{
return waitForUrlRegex( new RegExp( "^https?:\/\/" + url ), url );
}
it('should go to homepage and click login button', ()=>{
driver.get( app_url, urlTimeout);
//there is a redirect to welcome route
expect( waitForRoute("welcome") ).toBe(true);
const loginButton = element.all(by.className("login_button")).get(0);
loginButton.click();
});
it( 'should enter credentials', ()=>{
expect( waitForUrl( non_angular_login_url ) ).toBe(true);
driver.findElement( by.name("user")).sendKeys( "username");
driver.findElement( by.name("password")).sendKeys( "userpassword");
driver.findElement( by.tagName("button")).click();
});
it( 'should go back to app, and continue testing', ()=>{
expect( waitForRoute( "user-screen") ).toBe(true);
});
});`
config.onPrepare
onPrepare: ()=>{
require("babel-register");
global.driver = browser.driver;
}
如果您不想查看重定向,只需让驱动程序睡眠,然后开始使用量角器。
`driver.get(app_url+ "/#/welcome", urlTimeout);
driver.sleep( 1000 );
const loginButton = element.all(by.className("login_button")).get(0);
loginButton.click();`
我们确实支持手动引导,这个信息是旧的。 一旦我们处理了https://github.com/angular/protractor/issues/3857 ,引导程序将变得更加可靠。
@sjelin支持手动引导的记录方法是什么? 我找不到量角器 5.0 的相关信息。
我在手动引导时遇到了同样的问题。 并找到了使用 grunt 运行的解决方案。
使用量角器 2.5.1 版。
grunt.initConfig({
protractor: {
options: {
configFile: "protractor.conf.js", // Default protractor config file
keepAlive: true, // If false, the grunt process stops when the test fails.
noColor: false, // If true, protractor will not use colors in its output.
args: {
// Arguments passed to the command
}
},
e2e: {
options: {
// Stops Grunt process if a test fails
keepAlive: true
}
}
}
})
安装npm install grunt-protractor-runner --save-dev
并添加加载任务grunt.loadNpmTasks('grunt-protractor-runner')
使用以下命令运行量角器:
grunt protractor
或带有套件名称grunt protractor --suite suite_name
请让我知道它是否适合您。
这对我有用。
browser.ignoreSynchronization = true;
browser.get(url);
browser.ignoreSynchronization = false;
最有用的评论
@sjelin支持手动引导的记录方法是什么? 我找不到量角器 5.0 的相关信息。