2

I'm trying to click a button on a page using SlimerJS.

On the SlimerJS documentation, I see sendEvent(eventType, arg1, arg2, button, modifier) which allows us to click on a given position by X and Y coordinates. (Doc here)

So, I tried getting these X and Y of a button coordinates the following way:

var webpage = require("webpage").create();
function clickButton(button)
{
    var rect = button.getBoundingClientRect();
    webpage.sendEvent('click',rect.left,rect.top,'left',0);
}
webpage.open(url).then(function(){
    var button = webpage.evaluate(function(){
        signInButton = document.querySelector("#signIn");
        return signInButton;
    });
    clickButton(button);
});

This way, no error is thrown, but the button doesn't seem to get clicked. Is something wrong with this practice? Is there a better way? Is there a way to click a button or a link provided just it's ID or tag name?

user1555863
  • 2,567
  • 6
  • 35
  • 50

1 Answers1

4

That is quite a hard way to do it. (Incidentally you cannot pass a DOM object, like a button, back from evaluate(), so you'd be better off moving your clickButton contents to inside the evaluate().)

The easy way is to use CasperJS, which is a higher-level abstraction layer around PhantomJS/SlimerJS. Your example then becomes:

var casper = require('casper').create();
casper.start(url, function(){
  this.click('#signIn');
  });
casper.run();

If you want to stick with PhantomJS, and you have jQuery being loaded in the page anyway, then it is also fairly easy:

var webpage = require("webpage").create();

webpage.open(url).then(function(){
    this.evaluate(function(){
        $("#signIn").click();
        });
    });

An alternative to your approach is to directly send the DOM object a click event (i.e. rather than worry about mouse coords):

var webpage = require("webpage").create();

webpage.open(url).then(function(){
    this.evaluate(function(){
      var evt = document.createEvent("MouseEvents");
      evt.initMouseEvent("click", true, true, window,
        0, 0, 0, 0, 0, false, false, false, false, 0, null);
      return document.querySelector('#signIn').dispatchEvent(evt);
      };
    });

Why do I think this is better than dealing with mouse coords? Because mouse clicks using coords have to be on visible buttons, meaning you have to worry about your viewport; see https://stackoverflow.com/a/24861718/841830

(Source for the last two was my own blog post, where I also covered using d3.)

Community
  • 1
  • 1
Darren Cook
  • 27,837
  • 13
  • 117
  • 217
  • Thanks for the answer. For the time being I have decided to go about this with CasperJS, which is indeed simpler and seems suitable so far. as for the second option, the page I'm dealing with does not include jQuery. And even if it did, it is to my understanding that `$(el).click();` will only fire up events added with jQuery, which isn't my case. As for your last alternative, good thinking. (personally didn't try this yet) – user1555863 Jul 29 '14 at 08:34