Reputation: 901
I'm trying to avoid having 20 or so very small tests that each essentially test that a list of white label sites are up and show some basic information.
I've got a list (array) of sites, their URL, expected title and the name of the site.
I want to iterate the array, going to each URL and validating the title is correct.
Like this:
var x = require('casper').selectXPath;
var white_labels = [
{
URL: "http://site1.com",
Title: "Site 1 Title",
Name: "Site 1"
},
{
URL: "http://site2.com",
Title: "Site 2 Title",
Name: "Site 2"
}
]
casper.test.begin('White Labels Test Suite', white_labels.length, function suite(test) {
var urls;
var i = -1;
casper.start(white_labels[0]["URL"], function() {
urls = white_labels;
});
casper.then(function() {
this.each(urls, function() {
i++;
this.echo("I: " + i);
this.thenOpen(urls[i].URL, function() {
this.echo("URL: " + urls[i].URL);
test.assertTitle(urls[i].Title, urls[i].Name + " title is correct");
});
});
});
casper.run(function() {
test.done();
});
});
When I run this, each time I print out "I", it is correct...0, then 1.
However, the first test fails because the title it gets back is the title of site 2, not site 1. The 2nd test succeeds.
I'm baffled at this point.
Upvotes: 1
Views: 889
Reputation: 61922
The problem is the variable scope of i
. casper.each
is essentially a synchronous for loop. Inside of it is the asynchronous casper.thenOpen
statement which only schedules an action. It is actually called synchronously and the correct url is passed into it. After the each
loop is executed, the casper step queue begins to execute (triggered through casper.run
) which includes all then*
calls.
The problem is that i
is in global and it means that when both of the casper.thenOpen
callbacks are finally executed, i
is 1 for both of them.
There are different solutions for your case:
i++;
for var j = ++i;
and all the other i
inside casper.each
for j
.casper.each
injects the iteration item into the iteration and don't use any index at all: this.each(urls, function(self, url) { ... });
.this.each
to this.eachThen
so that it itself is stepped and you don't have i
-problems.Finally, see JavaScript closure inside loops – simple practical example and How do JavaScript closures work? for more information.
Upvotes: 4