Oscar McCullough
Oscar McCullough

Reputation: 375

Testing multiple HTML pages with CasperJS?

I'm working with CasperJS on a webpage that has a search box. Using Casper, I'm successfully able to perform a search and see that the form is filled and execute the search, however I'm having trouble specifically getting the number of results to test that it's valid.

When I look at the source of the webpage, I have the XPath of the element and it's nested in a few divs.

But when I try to either do assertExists() on that path, or even return the result of getElementByXPath() to a var, it doesn't work. In the first case the test fails and in the second case it prints null.

This is the XPath:

//*[@id="total"]

Here is what the snippet of source looks like:

<div id="pgContent"><div id="results_pagination1_container">
    <span style="float: right; font-size: .9em">
    Found <span id="total">721</span> item(s)</span>
</div>

This is the CasperJS code, relevant to here.

casper.test.begin(
    'Testing that we get the right amount of results for a search query',
    2, function suite(test) {
        casper.start(catapult, function() {
            test.assertTitle("Search", "Search"); // Good
            test.assertExists('#input-searchbox'); // Good
            this.fillSelectors('form#inputForm', {
                'input[name="queryStr"]' : 'airplane'
            }, true);

            //this.click('input#btnSearch');
        });
        casper.then(function() {
             var resultsNum = __utils__.getElementByXPath('//*[@id="total"]');
            this.echo(resultsNum);
            test.assertExists('//*[@id="total"]'); 
        });

Upvotes: 2

Views: 222

Answers (1)

Artjom B.
Artjom B.

Reputation: 61922

Clientutils and DOM access only in page context

The CasperJS clientutils module is only defined in the page context. Whenever CasperJS starts, it injects those utils into the page for later convenience. The problem is that the page and its DOM are only accessible from inside of the evaluate() function.

Another thing to remember is that you cannot get DOM nodes out of the page context. Either you do your stuff completely in the page context (inside of evaluate()) or you get a representation of the node like the textContent property:

var resultsNum = this.evaluate(function(){
    return __utils__.getElementByXPath('//*[@id="total"]').textContent;
});

Here is the bit from the documentation (since CasperJS is built on top of PhantomJS):

Note: The arguments and the return value to the evaluate function must be a simple primitive object. The rule of thumb: if it can be serialized via JSON, then it is fine.

Closures, functions, DOM nodes, etc. will not work!


Difference between CSS selectors and XPath expressions

The other thing is that if not otherwise noted through the name all functions assume that the selectors are CSS selectors. Looking at test.assertExists('//*[@id="total"]'); makes it clear that '//*[@id="total"]' is not a CSS selector, but an XPath expression. You can use XPath expressions in CasperJS through the XPath utility:

var x = require('casper').selectXPath;
test.assertExists(x('//*[@id="total"]'));

or you can simply use the equivalent CSS selector:

test.assertExists('#total');

Upvotes: 1

Related Questions