使用selenium-webdriver执行序列(对于Node JS)

时间:2015-06-21 09:15:59

标签: node.js selenium-webdriver mocha

我对selenium-webdriver命令的执行顺序有点困惑。

以下示例的正确编码是什么。 我想:

  1. 首先,在文本框中输入文字
  2. 那么,点击按钮
  3. 以下代码是否保证了正确的顺序?

       // Enter the text
        driver.findElement(webdriver.By.id('txt'))
          .sendKeys('bla bla')
          .then(
            function() {},
            function(err) {
              console.log(err);
              done(err); 
            }
          );
    
        // Press the button
        driver.findElement(webdriver.By.id('btn'))
          .click()
          .then(
            function() {
              done();
            },
            function(err) {
              console.log(err);
              done(err); 
            }
          );
    

    或者我应该做这样的事情?

    // Enter the pass
    driver.findElement(webdriver.By.id('txt_pass'))    
      .sendKeys('sifra')
      .then(
        function() {
          // Press the login button
          driver.findElement(webdriver.By.id('btn_login'))
            .click()
            .then(
              function() {
                done();
              },
              function(err) {
                console.log(err);
                done(err); 
              }
            );
        },
        function(err) {
          console.log(err);
          done(err); 
        }
      );
    

    如果第二种情况是正确的,当需要连续两行以上时,我该如何编写代码?我会非常复杂,不得不维持。

    更新

    现在说我想要清除第一个findElement中找到的元素" txt"并在我输入文本之前就这样做。根据路易斯的回答,我怀疑它应该是这样的:

       // Clear the textbox
        driver.findElement(webdriver.By.id('txt'))
          .clear()
          .then(
            function() {},
            function(err) {
              console.log(err);
              done(err); 
            }
          );
    
        // Enter the text
        driver.findElement(webdriver.By.id('txt'))
          .sendKeys('bla bla')
          .then(
            function() {},
            function(err) {
              console.log(err);
              done(err); 
            }
          );
    
        // go on with the further sequence...
    

    我发现这不太好,它太长而且笨拙,特别是如果同一个元素上有更多的操作。是否有一种通用的方法来缩短它,使它更紧凑?

    像链接的东西:

    findElement('txt').clear().sendKeys('bla, bla'); // This does not work, as clear is a void
    

1 个答案:

答案 0 :(得分:5)

你这样做的第一种方式是正确的。您似乎缺少的信息是 WebDriver的JavaScript实现使用“承诺管理器”为您排序承诺。这在说明的"Control Flows"部分进行了解释。这是一个例子:

var webdriver = require('selenium-webdriver');

var driver = new webdriver.Builder().
   withCapabilities(webdriver.Capabilities.chrome()).
   build();

// Do not implicitly wait for anything.
driver.manage().timeouts().implicitlyWait(0);

// Set the script wait timeout to 10 seconds.
driver.manage().timeouts().setScriptTimeout(10 * 1000);

driver.get('http://www.example.com');

function err() {
    console.log("ERR", arguments);
}

var start = Date.now();
driver.executeAsyncScript(
    "var done = arguments[0];" +
    "setTimeout(function () { document.body.innerHTML = '<p id=\"foo\"></p>'; done() }, 5000)")
    .then(function () {
        console.log("created foo!", Date.now() - start);
    },
          err);

driver.findElement(webdriver.By.tagName("body")).then(function () {
    console.log("here", Date.now() - start);
});

driver.findElement(webdriver.By.id("foo")).then(function () {
    console.log("found foo!", Date.now() - start);
}, err);

这将输出到控制台的以下行,总是以相同的顺序:

created foo! 5639
here 5657
found foo! 5670

数字会有所不同,但它们总是> 5000并且非常密切地跟随彼此(除非在过载或可笑的慢速系统上运行)。首先执行的executeAsyncScript用于说明需要一段时间才能完成的操作将允许对同一驱动程序的后续操作继续进行。除了执行脚本而不是查找元素这一事实之外,它与findElement没有任何区别:在下一个操作可以继续之前,promise管理器等待操作完成,甚至如果两个操作没有使用.then()明确排序。

如果promise Manager没有依次对操作进行排序,那么.findElement(webdriver.By.tagName("body"))将在异步脚本完成之前执行,并且会在"here"打印到"created foo!"之前打印body控制台,因为页面确实有一个.findElement元素。

此外,如果promise Manager没有依次对操作进行排序,那么最后一个id将无法找到foo值为findElement的元素。在脚本的早期,我关闭了隐式等待,因此foo调用肯定不会等待 clear出现。

的情况下,您希望更多地执行此操作,就像您在第二个代码段中执行此操作一样,但您没有在问题中包含任何明确的理由应该这样做。

另外,如果不是Selenium的承诺经理,那么你做类似你的第二个片段的事情,因为一般来说没有任何顺序承诺给你。

关于如何对sendKeysdriver.findElement(webdriver.By.id('txt')).then(function (el) { el.clear(); el.sendKeys('bla bla'); }); 进行排序的问题,您可以这样做:

 echo  $json_data["alt_ids"]["place_id"];

此结构使用“控制流”功能的"framing"功能。