量角器登录gmail无法无头,无法无头工作

时间:2018-06-18 23:37:58

标签: protractor gmail headless

我有一个使用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

SLIGHT UPDATE:我清理了代码,只使用明确的等待和直接的Protractor(这是我在阅读基于其他语言的网页上之前的原始版本)。这是修改后的版本,它仍然没有通过无头而且无头(我还删除了OnPrepare()中的隐式等待设置以及除了前三个chrome选项之外的其他所有选项。

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

所以Protractor是正确的,它无法通过ID identifierID找到。但是怎么了?

FINAL: 因此,无论是否无头,谷歌都会重定向到两个不同的网址,其中包含两组不同的ID和名称。我发布了修改后的代码,在我的回答中处理了这两个代码。

感谢所有人的指导。

1 个答案:

答案 0 :(得分:1)

因此,事实证明Google会将邮件服务请求重定向到其界面的两个不同版本,具体取决于一个人是否无头。我重写了代码来处理其中任何一个。我还尝试简化了可能的地方,包括不再进行隐式等待和添加更多链接(在Oleksii的评论鼓励下,我也将脚趾浸入ES6中)。

    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。