Rogerio
Rogerio

Reputation: 148

CasperJS with jQuery and CSS3 selectors not working as expected

I'm having some trouble selecting elements in some pages with old HTML.

If I inject jQuery in Chrome javascript console and execute the code myself, it returns the right value. However when I try to do that in CasperJS it doesn't work. So I made a small script to test what was going on:

(casper.start and casper.run ommited)

casper.then(function() {
    this.echo("1: Entire Row");
    this.echo(this.evaluate(function() {
        return $("#table20 > tbody > tr:nth-child(3)").html();
    }));

    this.echo("2: More specific");
    this.echo(this.evaluate(function() {
        return $("#table20 > tbody > tr:nth-child(3) > td:nth-child(2)").html();
    }));

    this.echo("3: More specific");
    this.echo(this.evaluate(function() {
        return $("#table20 > tbody > tr:nth-child(3) > td:nth-child(2) > p").html();
    }));

    this.echo("4: Even more specific");
    this.echo(this.evaluate(function() {
        return $("#table20 > tbody > tr:nth-child(3) > td:nth-child(2) > p > font").html();
    }));

    this.echo("5: Using jQuery functions");
    this.echo(this.evaluate(function() {
        return $("#table20 > tbody > tr:nth-child(3)").children("td:nth-child(2)").children("p").children("font").html();
    })); //Ugly workaround

});

And when I run it, this is the result:

1: Entire Row
<td height="23" width="226" style="border-style: solid; border-width: 1px" bordercolor="#666666" colspan="2">
        <p>
        <img width="16px" height="16px" src="upload/imagens/bandeira_eua.gif">
        <strong>Dólar americano (USD)</strong>
</p></td>
<td height="23" width="80" style="border-style: solid; border-width: 1px" bordercolor="#666666">
        <p><font size="2">2,400</font>
</p></td>
<td height="23" width="81" style="border-style: solid; border-width: 1px" bordercolor="#666666">
        <p><font size="2">2,600</font>
</p></td>

2: More specific //Correct so far...
<p><font size="2">2,400</font> 
</p>

3: More specific //What? This is from another row!!
<font size="2">3,060</font>

4: Even more specific
null //What??

5: Using jQuery functions
2,400 //Correct result

However, if I visit the website with Chrome and inject the same jQuery in the console, then it runs as expected:

$("#table20 > tbody > tr:nth-child(3) > td:nth-child(2) > p > font").html();
"2,400"

What is happening??? Using native CasperJS methods to retrieve the value doesn't work too.

ps: CasperJS version 1.1.0-beta3 with PhantomJS version 1.9.0

ps1: The CSS Path was generated in Chrome Dev Tools, "Copy CSS Path".

EDIT: Even weirder: This script

casper.then(function() {
    this.echo(this.evaluate(function() {
        return $("#table20 > tbody > tr:nth-child(3) > td:nth-child(2) > p > font").html();
    }));

    this.echo(this.evaluate(function() {
        return $("#table20 > tbody > tr:nth-child(3) > td:nth-child(2) > p > font").html();
    }));
});

returns:

2,400
null

It consistently only works for the first time, even if I split into 2 casper.then.

Upvotes: 2

Views: 667

Answers (1)

Chris Hawkes
Chris Hawkes

Reputation: 12420

Unfortunately Casper / PhantomJS Webkit is not the same as chrome's. Xpath's that work on chrome will not always work on PhantomJS and to find the reason would be to dig through complex C++ code.

Basically this does not answer the question but confirms I have run into the same situations before. the work around is to find a more consistent drilled down xpath to locate the element via text, attribute, class, id etc... than drill down from there. Even if you have to go past your element to work it's way up to a parent or sibling etc... is more reliable than absolute dom path based on generic tags.

xpath's such as //div/div/div/p/a/span/text() are not very reliable in phantomjs.

Upvotes: 2

Related Questions