NOTE: let's call 'click' is end-user click. 'js click' is click via JS
Why is clicking "via JavaScript" works when a regular WebDriver click does not?
There are 2 cases for this to happen:
I. If you are using PhamtomJS
Then this is the most common known behavior of PhantomJS
. Some elements are sometimes not clickable, for example <div>
. This is because PhantomJS
was original made for simulating the engine of browsers (like initial HTML + CSS -> computing CSS -> rendering). But it does not mean to be interacted with as an end user's way (viewing, clicking, dragging). Therefore PhamtomJS
is only partially supported with end-users interaction.
WHY DOES JS CLICK WORK? As for either click, they are all mean click. It is like a gun with 1 barrel and 2 triggers. One from the viewport, one from JS. Since PhamtomJS
great in simulating browser's engine, a JS click should work perfectly.
II. The event handler of "click" got to bind in the bad period of time.
For example, we got a <div>
-> We do some calculation
-> then we bind event of click to the <div>
.
-> Plus with some bad coding of angular (e.g. not handling scope's cycle properly)
We may end up with the same result. Click won't work, because WebdriverJS trying to click on the element when it has no click event handler.
WHY DOES JS CLICK WORK? Js click is like injecting js directly into the browser. Possible with 2 ways,
Fist is through devtools console (yes, WebdriverJS does communicate with devtools' console).
Second is inject a <script>
tag directly into HTML.
For each browser, the behavior will be different. But regardless, these methods are more complicating than clicking on the button. Click is using what already there (end-users click), js click is going through backdoor.
And for js click will appear to be an asynchronous task. This is related a with a kinda complex topic of 'browser asynchronous task and CPU task scheduling' (read it a while back can't find the article again). For short this will mostly result as js click will need to wait for a cycle of task scheduling of CPU and it will be ran a bit slower after the binding of the click event.
(You could know this case when you found the element sometimes clickable, sometimes not.
)
When exactly is this happening and what is the downside of this
workaround (if any)?
=> As mention above, both mean for one purpose, but about using which entrance:
- Click: is using what providing by default of browser.
- JS click: is going through backdoor.
=> For performance, it is hard to say because it relies on browsers. But generally:
- Click: doesn't mean faster but only signed higher position in schedule list of CPU execution task.
- JS click: doesn't mean slower but only it signed into the last position of schedule list of CPU task.
=> Downsides:
- Click: doesn't seem to have any downside except you are using PhamtomJS.
- JS click: very bad for health. You may accidentally click on something that doesn't there on the view. When you use this, make sure the element is there and available to view and click as the point of view of end-user.
P.S. if you are looking for a solution.
- Using PhantomJS? I will suggest using Chrome headless instead. Yes, you can set up Chrome headless on Ubuntu. Thing runs just like Chrome but it only does not have a view and less buggy like PhantomJS.
- Not using PhamtomJS but still having problems? I will suggest using ExpectedCondition of Protractor with
browser.wait()
(check this for more information)
(I want to make it short, but ended up badly. Anything related with theory is complicated to explain...)