我有一个使用Protractor登录gmail的例程,它是从脚本的中间调用的(这就是为什么有些看起来不必要的东西在那里),但是我已经尽可能地隔离它了。当我运行它时,它不是无头的,而是经过的。当我无头运行时,它就失败了。我查看了相关的帖子,它们似乎并不是特定于Protractor的,而且它们似乎与我的代码并行。
以下是代码:
const EC = ExpectedConditions;
beforeAll(function(){
});
beforeEach(function() {
//because I am using gmail after sending an email from an angular app with a link to get back into one
browser.waitForAngularEnabled(true);
browser.ignoreSynchronization = false;
});
afterEach(function() {
browser.waitForAngularEnabled(true);
browser.ignoreSynchronization = false;
});
var gmailLogin = function(){
browser.waitForAngularEnabled(false);//gmail screens not angular
browser.ignoreSynchronization = true;
browser.sleep(2000);//because ignore sync takes time to settle in
browser.driver.manage().timeouts().implicitlyWait(10000);//set in config, but seems to work only if here
browser.get("https://mail.google.com/mail");
browser.wait(EC.titleContains("Gmail"), 10000, "wait for gmail page");
$('[data-g-label="Sign in"]').click().then(
//this sometimes appears and sometimes is skipped, so ignore result
function(retval){},function(err){}
)
var variousInput = element(by.id('identifierId'));
browser.wait(EC.presenceOf(variousInput), 10000, "wait for identier ID prompt").then(
function(retVal){
var variousInput2 = browser.driver.findElement(by.id('identifierId'));
variousInput2.sendKeys("myemail here");
variousInput2=browser.driver.findElement(by.id("identifierNext"));
variousInput2.click();
variousInput2 = browser.driver.findElement(by.name('password'));
variousInput2.sendKeys('my password here');
variousInput2=browser.driver.findElement(by.id("passwordNext"));
variousInput2.click();
},
function(err){}//assume not found because cookie still around, proceed to next step
)
browser.wait(EC.titleContains("Inbox"), 10000, "wait for inbox");
}
describe('runs gmail test for so', function() {
it('tests gmail', function() {
gmailLogin();
expect(browser.getTitle()).toContain('Inbox');
}, 2 * 60 * 1000); //should always come up within 2 minutes
}); //end of describe下面是标题配置文件:
exports.config = {
directConnect: true,
allScriptsTimeout: 120000,
getPageTimeout: 60000,
// Capabilities to be passed to the webdriver instance.
capabilities: {
'browserName': 'chrome',
chromeOptions: {
//args: ["--headless","--disable-gpu","--no-sandbox"]
},
// Framework to use. Jasmine is recommended.
framework: 'jasmine',
// Spec patterns are relative to the current working directory when
// protractor is called.
specs: [
'./so.ts'
],
// Options to be passed to Jasmine.
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 180000
},
beforeLaunch: function() {
},
onPrepare() {
browser.manage().window().setSize(1600, 1000);
browser.driver.manage().timeouts().implicitlyWait(15000);
}
}
}这是无头的(你可以看到我把厨房的水槽扔到了选项上)。
exports.config = {
directConnect: true,
allScriptsTimeout: 60000,
getPageTimeout: 30000,
// Capabilities to be passed to the webdriver instance.
capabilities: {
'browserName': 'chrome',
chromeOptions: {
args: ["--headless","--disable-gpu","--window-size=1600,1000","--disable-infobars","--disable-extensions","--auth-server-whitelist","--remote-debugging-port=9222"]
},
// Framework to use. Jasmine is recommended.
framework: 'jasmine',
// Spec patterns are relative to the current working directory when
// protractor is called.
specs: [
'./so.ts'
],
// Options to be passed to Jasmine.
jasmineNodeOpts: {
showColors: true,
defaultTimeoutInterval: 180000
},
beforeLaunch: function() {
},
onPrepare() {
// screen size set in chrome options
browser.driver.manage().timeouts().implicitlyWait(15000);
}
}
}如果有某种潜在的,无文件的智慧,关于哪个定位器工作或不工作无头,我很想知道。
谢谢,jk
轻微的更新:我清理了代码,只使用了显式的等待和直接的Protractor (这是我在web上阅读其他语言的文章之前最初使用的方式)。下面是修改后的版本,它仍然不传递无头,并且失败了无头(我还删除了OnPrepare()中的隐式等待设置,以及除前三个铬选项之外的所有的无头操作)。
var gmailLogin = function() {
browser.waitForAngularEnabled(false); //gmail screens not angular
browser.ignoreSynchronization = true;
browser.sleep(2000); //because ignore sync takes time to settle in
browser.get("https://mail.google.com/mail");
browser.wait(EC.titleContains("Gmail"), 10000, "wait for gmail page");
$('[data-g-label="Sign in"]').click().then(
//this sometimes appears and sometimes is skipped, so ignore result
function(retval) {},
function(err) {}
);
var variousInput = element(by.id('identifierId'));
browser.wait(EC.presenceOf(variousInput), 10000, "wait for identifier ID prompt").then(
function(retVal) {
var variousInput2 = element(by.id('identifierId'));
variousInput2.sendKeys("email address");
variousInput2 = element(by.id("identifierNext"));
variousInput2.click();
variousInput2 = element(by.name('password'));
browser.wait(EC.presenceOf(variousInput2), 10000, "wait for password prompt");
browser.wait(EC.visibilityOf(variousInput2), 10000, "wait for password prompt");
variousInput2.sendKeys('my password');
variousInput2 = element(by.id("passwordNext"));
variousInput2.click();
},
function(err) {} //assume not found because cookie still around, proceed to next step
)
browser.wait(EC.titleContains("Inbox"), 10000, "wait for inbox");
}更大的更新:这可能是什么古怪的无头毕竟。在等待标识符ID element(by.tagName('html')).getText().then(function(text){console.log(text);});之前,我在非无头模式下添加了以下行,这将生成
Sign in
to continue to Gmail
Email or phone
Forgot email?
Not your computer? Use Guest mode to sign in privately.
Learn more
NEXT
Create account
English (United States)
HelpPrivacyTerms在无头,它给了
One account. All of Google.
Sign in to continue to Gmail
Find my account
Create account
One Google Account for everything Google
About Google Privacy Terms Help接下来是一长串从南非荷兰语到繁體中的语言。因此,似乎在“无头浏览器”中,浏览器已经忘记了它生活在哪里(至少添加了一个帐户,所有的谷歌和语言都说它不是苹果)。这让我怀疑,在这种情况下,IdentifierId是否也会有不同的名称。现在最后一次更新:要调试,我在第一页加载时添加了以下代码:
var inputs=element.all(by.tagName('input'));
inputs.each(function(element,index){
element.getAttribute("Id").then(function(text){console.log('input '+index+' '+text);})
})不是无头的,我们得到:
input 0 identifierId
input 1 null
input 2 ca
input 3 ct
input 4 pstMsg
input 5 checkConnection
input 6 checkedDomains但我们得到的是:
input 0 null
input 1 null
input 2 null
input 3 null
input 4 null
input 5 null
input 6 null
input 7 null
input 8 null
input 9 null
input 10 null
input 11 profile-information
input 12 session-state
input 13 null
input 14 _utf8
input 15 bgresponse
input 16 Email
input 17 Passwd-hidden
input 18 next所以量角器是正确的,它不能通过ID identifierID找到。但是为什么呢?
最后:因此,取决于无头或无头,google重定向到两个不同的urls,具有两组不同的Ids和名称。在我的回答中,我发布了处理这两个问题的修改代码。
谢谢你的指导,所有人。
发布于 2018-06-19 22:31:57
因此,谷歌将把邮件服务请求重定向到其界面的两个不同版本,这取决于其中一个版本是否是无头的。我重写了代码来处理任何一个。我还试图简化可能的地方,包括没有更多的隐含等待和添加更多的链接(我也尝试了我的脚趾在ES6鼓励下,因为Oleksii的评论)。
const EC = ExpectedConditions;
beforeAll(function(){
});
beforeEach(function() {
//because I am using gmail after sending an email from an angular app with a link to get back into one
browser.waitForAngularEnabled(true);
browser.ignoreSynchronization = false;
});
afterEach(function() {
browser.waitForAngularEnabled(true);
browser.ignoreSynchronization = false;
});
var waitForIds = (id1,id2)=>{//waits for one of two ids, assumes they must exist or else it is an error
var elm = element.all(by.xpath("//*[@id = '"+id1+"' or @id = '"+id2+"']")).first();
browser.wait(EC.presenceOf(elm), 30000, "wait for "+id1+" or "+ id2);
return elm;
}
var gmailLogin = () => {
browser.waitForAngularEnabled(false); //gmail screens not angular
browser.ignoreSynchronization = true;
browser.sleep(2000); //because ignore sync takes time to settle in
browser.get("https://accounts.google.com/ServiceLogin?service=mail");
browser.sleep(2000);
element(by.id('gbqfq')).isPresent().then((present) => {
//if present, we are already on the inbox screen, because we found the search pane
if (!present) { //still work to do to get there
browser.wait(EC.titleContains("Gmail"), 10000, "wait for a gmail page");
$('[data-g-label="Sign in"]').click().then(
//this sometimes appears and sometimes is skipped, so ignore result
(retval) => {}, (err) => {}
);
waitForIds('Email', 'identifierId').sendKeys("my email here");
waitForIds("identifierNext", "next").click();
waitForIds('Passwd', 'password').getAttribute('id').then((text) => {
element(by.name(text)).sendKeys('my password here');
waitForIds("signIn", "passwordNext").click();
})
}
})
browser.wait(EC.titleContains("Inbox"), 10000, "wait for inbox");
}
describe('runs gmail test for so', function() {
it('tests gmail', function() {
gmailLogin();
expect(browser.getTitle()).toContain('Inbox');
}, 2 * 60 * 1000); //should always come up within 2 minutes
}); //end of describe更新:我之所以接受这一观点,是因为它解决了我的问题,即发生了什么,为什么和如何直接解决。我完全同意,尽管回答了这个问题,但还是有更好的方法来完成我真正想要做的事情(从电子邮件中获取href ),或者是在发送邮件时捕获它,或者使用gmail api。
https://stackoverflow.com/questions/50918799
复制相似问题