0

I would like to test a click event on an anchor tag triggers the right DOM transformations. What I see in the browser works and I've pretty much checked each line of my code returns what I want, except when I let PhantomJS do it, the expected DOM transformations don't seem to trigger.

Here is my code:

page.open(url, function(status) {
    if (status === "success") {                     

        var specifications = page.evaluate(function() {
            var a = document.querySelector("a[href='#Specifications']");
            var e = document.createEvent('MouseEvents');

            e.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
            a.dispatchEvent(e);

            return document.querySelector("div#Specifications").innerHTML;              
        });

        console.log(specifications);
        phantom.exit()

    } else {
       phantom.exit(1);
    });
});

I initially just called document.querySelector("a[href='#Specifications']").click(); with the same result. In my web browser, clicking on that link triggers the DOM transformations. I can't however reproduce it in PhantomJS.

JackyJohnson
  • 3,106
  • 3
  • 28
  • 35

1 Answers1

1

So after much time figuring out what is going on, here are some recommendations for people who run into a similar problem.

First, make sure your selectors are not the problem. In my case I decided to stick with the document API. Unlike what some people have said about sending click events, the following works fine:

document.querySelector("a[href='#some_section']").click();

You should be able to use jQuery with page.includeJs() too.

Make sure the page resources are being requested and received after you call click() by using onResourceRequested and onResourceReceived like this:

page.onResourceRequested = function(data, request) {
    console.log("phantomJS: resource requested: " + data.url);
};

page.onResourceReceived = function(response) {
    console.log("phantomJS: resource received: " + response.url);
};

Finally, make sure if you are evaluating some value that needs to be inserted after a click event that it is done after the resource is received. What I ended up doing is:

setTimeout(function() {
    var data = page.evaluate(function() {
        return document.querySelector('div#InsertDiv').innerHTML;
    });
    console.log(data);

    phantom.exit();
}, 2000);

Basically, if external resource is being requested, you have to set an asynchronous wait time for it.

JackyJohnson
  • 3,106
  • 3
  • 28
  • 35
  • [This answer](http://stackoverflow.com/a/21401636/1816580) should be helpful in removing that static wait with `setTimeout` – Artjom B. Mar 11 '16 at 09:56