Nightwatch execute command within for loop runs out of order

泄露秘密 提交于 2019-12-11 20:14:05

问题


I'm pretty new to unit testing, but I've been trying to create a script with Nightwatch that goes through the body content of a page, clicks every link and reports back whether it's broken.

I'm trying to make a for loop that iterates through each tag in the body content, counts the number of 'a' tags contained within and then clicks on each of them, but whenever I use a browser.execute command within a for loop, the script executes out of order.

Here's my code. I've thrown in a couple of console.log statements to try and figure out what's going on:

'Click Links' : function(browser) {
browser
  //Count all tags (p/div) in content that aren't links
  .useCss()
  .execute(function() {
    return document.querySelectorAll("div.field-item.even *:not(a)").length;
  },
  function(tags){
    tag_total = tags.value;

    //Loop through every tag in content & check every a tag contained within
    for (var x = 1; x < tag_total+1; x++) {
      console.log("x val before execute: " + x);
      browser.execute(function() {
        return document.querySelectorAll("div.field-item.even *:not(a):nth-child(" + x + ") a").length;
      },
      function(links){
        console.log("x val at start of execute: " + x);
        a_total = links.value;

        for (var y = 1; y < a_total+1; y++) {
          browser.click("div.field-item.even *:not(a):nth-child(" + x + ") a:nth-child(" + y + ")");
          browser.pause(1000);

          //Conditionals for on-site 404/403 links
          browser.execute(function() {
            return document.querySelector("meta[content='Error Document']");
          }, 
          //Grabs url if link is broken
          function(result){
            if (result.value != null) {
              browser.url(function(result) {
                console.log("BROKEN LINK: " + result.value);
              });
            }
          });

          //Go back to previous page
          browser.url(process.argv[2]);
          browser.pause(1000);
        }
        console.log("x val at end of execute: " + x);
      });
    console.log("x val at end of for loop: " + x);
    }
  })

.end()
}

The output I'm getting:

 x val before execute: 1
 x val at end of for loop: 1
 x val before execute: 2
 x val at end of for loop: 2
 x val at start of execute: 3
 x val at end of execute: 3
 ERROR: Unable to locate element: "div.field-item.even *:not(a):nth-child(3) a:nth-child(1)" using: css selector

It seems like the for loop is running through and skipping the entire browser.execute block. After the loop finishes, the browser.execute block is then entered with x at an invalid number of 3.

Why does the browser.execute command cause the for loop to execute out of order, and can anything be done to fix it so that it runs in the order intended?


回答1:


This has nothing to do with Nightwatch, but with Javascript.

When you have a loop and you call a function within that loop, the variable used in such function is saved by reference. In other words, the variable doesn't change for any of the functions.

It's easier if we go through a simple example:

var myFuncs = [];
for (var i = 0; i < 3; i += 1) {
  myFuncs.push(function () {
    console.log('i is', i);
  });
}

myFuncs[0](); // i is 3
myFuncs[1](); // i is 3
myFuncs[2](); // i is 3

This is because i is saved as a reference in the function. So when i increments at the next iteration, the referenced doesn't change but the value does.

This could be easily fixed by moving the function outside of the loop:

function log (i) {
  return function () {
    console.log(i);
  }
}

var myFuncs = [];
for (var i = 0; i < 3; i += 1) {
  myFuncs.push(log(i));
}

myFuncs[0](); // i is 0
myFuncs[1](); // i is 1
myFuncs[2](); // i is 2

In case you want to explore the concept a little bit more, you can have a look at this similar SO answer (which has a very similar example - ironically).



来源:https://stackoverflow.com/questions/33549514/nightwatch-execute-command-within-for-loop-runs-out-of-order

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!