У меня возникла проблема при запуске транспортира 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']);
бутстрап.js:
var appElm = $('html');
appElm.addClass('ng-app'); // this
angular.bootstrap(document, ['app']);
Это работает на практике, и Angular запускается правильно. Когда я просматриваю источник html, я не вижу атрибут ng-app, отображаемый в элементе html. Может быть, Protractor также не может этого сделать?
Я использую образец конфигурации транспортира и изменил соответствующие значения в соответствии с моим приложением:
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-приложение, поэтому у сайтов, загружаемых вручную, будут проблемы. Надеемся, что в ближайшее время будет задокументировано обходное решение.
Хорошо, спасибо за обновление. Когда вы найдете обходной путь, вы можете опубликовать его в этом выпуске?
Извините за медленный ответ - вы должны быть в состоянии исправить, выполнив
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('...')
, но ничего не работает.
Любые подсказки/советы/исправления с благодарностью получены.
@magnetized , вам понадобится какой-то способ сообщить вашему тесту, чтобы он дождался завершения входа в систему, прежде чем пытаться выполнить другие тесты. Я думаю, что происходит то, что вы пытаетесь использовать ptor.findElement до того, как Angular загрузится на страницу.
Ваша спецификация «Может войти в систему» должна заканчиваться оператором ожидания, который проверяет какое-либо условие для вашего приложения. Посмотрите пример здесь - https://github.com/angular/protractor/blob/master/spec/login/viaConfigConf.js .
@juliemr Великолепно, это работает отлично.
Я понял, что транспортир будет «ждать, пока загрузится angular», но я думаю, вы не можете охватить все случаи.
Еще раз спасибо.
У меня точно такая же установка. @juliemr , не могли бы вы поделиться своим решением? Каково ваше состояние ожидания? Спасибо!
@jorgenfb Интересно, вы имели в виду, что этот комментарий был адресован мне?
Мое решение просто включало ожидание загрузки углового маршрутизатора и изменение 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), когда Protractor не находит Angular, хотя Angular очень просто загружен и работает. Является ли простое решение (тестирование без попыток найти Angular) тем путем, которым мы должны идти? Кажется, это противоречит цели Protractor, специально созданного для тестирования приложений Angular.
редактировать: я также должен отметить, что предложенное решение в этом вопросе не работает для меня.
+1 за лучшую документацию по ручной загрузке angular
это еще актуально?
Я, честно говоря, не знаю, так как с тех пор я отказался от попыток, и у меня действительно нет времени вернуться и посмотреть, изменилось ли что-то. Учитывая изменения версии с тех пор, если вы хотите закрыть это, я бы не стал спорить. Его всегда можно открыть позже.
Я только начал использовать транспортир сегодня, и наше приложение использует require.js ... если были какие-либо обновления в отношении тестирования приложения, которое загружается вручную, я, например, заинтересован. :-)
Та же проблема здесь. Получил приложение со страницей входа вне углового приложения. Обходной путь в предыдущих комментариях кажется устаревшим. Очень хотелось бы обновить документ о том, как проверить такой сценарий.
@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
(Selenium-сервер)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.
Хотя я использовал временной интервал по умолчанию как defaultTimeou tInterval: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 для Concat/Uglify моего кода до одного JS-файла, который является единственным скриптом, упомянутым в index.html, с тегом script. Назовем его script.js. В разделе «Разработка» я запускаю другую задачу Grunt, которая объединяет только те файлы, которые мне нужны, чтобы загрузить остальные файлы JS по отдельности, асинхронно и с отметками времени для предотвращения кэширования. Этот объединенный набор скриптов заменяет script.js, пока я разрабатываю. В любом случае я загружаю script.js только из index.html и с тегом script.
Итак, в разработке я должен выполнить ручную загрузку. Это легко, потому что я могу включить один файл, который я не объединяю, в производственный JS, и я обязательно загружу этот скрипт после того, как все остальные JS загрузятся.
bootstrap_dev.js
.element(document.body)
.ready(function() {
angular.bootstrap(document.body, ['App']);
});
В продакшене я не могу вручную загрузиться, потому что Protractor это не нравится. И я использую Protractor для своего производственного кода. Я также удалил атрибут «ng-app» из моего HTML, чтобы приложение не загружалось преждевременно в процессе разработки, поэтому нормальная автоматическая загрузка не происходит. Я компенсирую это в производстве, помещая скрипт перед всеми остальными JS в script.js.
bootstrap_prod.js
window.document.body.setAttribute("ng-app", "myApp");
Просто замените «myApp» на имя вашего основного модуля.
В разработке, если вы сделаете вышеописанное, вы можете загрузить свой скрипт асинхронно и выполнить начальную загрузку вручную. Но если вы согласны запускать тесты Protractor только с производственным кодом (который можно загрузить из одного файла с помощью тега сценария), просто добавьте директиву ng-app перед загрузкой Angular, чтобы он выполнял автоматическую загрузку. Теперь у вас есть асинхронная загрузка ваших различных сценариев в разработке и запуск тестов Protractor для вашего производственного кода.
Что в итоге сработало для меня, так это добавление в мой 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() нарушит транспортир или приложение. Таким образом, ng-app в теле вообще не нужен, и вы можете сами вызвать angular.boostrap(), и он будет обрабатываться транспортиром с помощью NG_DEFER_BOOTSTRAP! должным образом.
Убедитесь, что window.name не изменено каким-либо кодом приложения во время загрузки и загрузки. В моем случае это делал jquery , не могу понять, почему. Полностью удалил jquery из моего проекта, и тесты заработали. В этом корень проблемы!
Я пока ищу, как вернуть jquery, не ломая тесты, потому что это нужно моему проекту!
Ну наконец то,
наша проблема заключалась в двух версиях jQuery на одной странице (вторая версия была загружена внешней библиотекой). Удалил его и оставил на странице только наш jQuery и все работает.
Некоторый код, может быть полезен:
index.html
<body>
...
<script data-main="require.conf" type="text/javascript" src="bower_components/requirejs/require.js"></script>
</body>
конфигурация requirejs
...
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 Мне помогло, спасибо~
Привет, ребята, странная вещь, имеющая отношение к этой теме.
У меня есть обычное угловое приложение - никаких требований или чего-то еще, я использую транспортир 2.0.0.
Когда я запускаю системные тесты в промежуточной среде, это работает.
Когда я запускаю его локально, он дает мне:
org.openqa.selenium.WebDriverException: unknown error: [ng:btstrpd] App Already Bootstrapped with this Element
... сообщение
Когда я настраиваю сервер Nginx для обслуживания статического ресурса вместо grunt:server
, все работает.
Действительно ли имеет значение, запускаю ли я его с livereload в разработке?
Похоже, что статические серверы ведут себя по-другому, и grunt обслуживает некоторые 404 или редиректы, поэтому веб-драйвер сходит с ума.
Всем привет,
после долгого чтения и чтения я нашел одно решение, которое хорошо работает для моего проекта ( исправить поток выполнения транспортира )
?protractor-test
к URL-адресу ( код проекта )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. В моем приложении ng-App определен в теге body на странице входа. Мой тест продолжает жаловаться, говоря: «Angular не может быть найден на странице httP://(адрес веб-сайта): angular никогда не предоставлял резюмеBootstrap», но выполнение теста в порядке. Не уверен в проблеме (если я включу параметр ignoresync браузера, тогда он работает нормально, но это неправильный способ), я могу попробовать то, что предлагает Juliemr (использовать устаревший драйвер для навигации), но просто пытаюсь понять, почему мое приложение жалуется хотя в теге body есть ng-App. Функциональное поведение приложения выглядит следующим образом.. Страница входа.. После входа в систему щелкните какую-либо ссылку на домашней странице, и откроется другое окно/вкладка. Может ли кто-нибудь помочь мне найти шаги, которые все должны проверить, чтобы убедиться, что начальная загрузка выполняется автоматически (один из параметров ng-app в теге body)? Нужно ли мне что-то проверять в файле bootstrap.js (я не вижу никаких параметров ng-app в файле начальной загрузки, поэтому проверяю. Спасибо
Есть ли обновления по этому вопросу? Каковы передовые методы или методы настройки транспортира для работы с угловым приложением, у которого нет ng-приложения? @erkobridee , не могли бы вы объяснить свой пример подробнее? И может ли кто-нибудь объяснить, как правильно обрабатывать window.name в отношении того, как транспортир должен ждать, когда angular завершит загрузку?
@juliemr В Angular 1.5 ручная загрузка является предпочтительным способом загрузки. Есть ли на пути поддержка благословенного транспортира?
+1 Я думаю, что эта проблема должна быть более приоритетной. Если Protractor не работает с ручной загрузкой, то нет смысла использовать Protractor. Весь смысл использования Protractor поверх Webdriver заключается в том, что Protractor выполняет всю угловую синхронизацию за вас.
У меня такая же проблема. Любое обновление?
привет, есть ли какой-либо план или процесс, чтобы улучшить это?
Странно, что нет обратной связи. У меня в приложениях отсутствует ng-app и я не могу проверить
их с транспортиром
16 июля 2016 г., 5:01, «millerwx» [email protected] написал:
привет, есть ли какой-либо план или процесс, чтобы улучшить это?
—
Вы получаете это, потому что вы прокомментировали.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/angular/protractor/issues/66#issuecomment-233104701 ,
или заглушить тему
https://github.com/notifications/unsubscribe-auth/AOghFs2ff0e-88DLafNGD3iCH8uCOgVaks5qWEmIgaJpZM4A82d7
.
На сегодняшний день в 2016 году это все еще было для меня проблемой. Я последовал ответу Magnetized, чтобы решить проблему. Я просто сделал несколько изменений. Что приятно и выходит за рамки разговора, так это отслеживать перенаправления и возвращаться обратно в ваше приложение. * Я сделал это с помощью 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.
Я столкнулся с той же проблемой при ручной загрузке. и нашел решение работать с ворчанием.
используется транспортир версии 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 = истина;
браузер.получить(URL);
browser.ignoreSynchronization = ложь;
Самый полезный комментарий
@sjelin Каков задокументированный способ поддержки ручной загрузки? Я не могу найти соответствующую информацию для транспортира 5.0.