Context is provided in case anyone knows of an alternative way to solve the larger issue.
Problem Context
I am spearheading the development of a test automation framework for a web application which uses Web Components. This has presented a problem when testing in Internet Explorer, because Internet Explorer does not support Web Components natively; instead, a polyfill is used to provide this functionality.
A primary repercussion of this is that much of Selenium will not work as expected. It cannot 'see' the Shadow DOM in Internet Explorer the way it can in Firefox and Chrome.
The alternative is to write a test framework which provides an alternate mechanism for accessing elements via JavaScript - this allows elements to be located through the polyfill.
Our current implementation checks the WebDriver
being used, and either uses the original Selenium implementation of a method (in the case of Chrome or Firefox), or our own alternative implementation (in the case of Internet Explorer).
This means that we want our implementation to be as close as possible to Selenium's implementation, at its core, browser-interacty, level.
Problem
I am trying to replicate the functionality of Actions.click(WebElement onElement)
(source), in a simplified form (without following the Builder design pattern of the Actions
class, and making assumptions that the click is with the left mouse button and no other keys (Ctrl, Shift, Alt) are being held down).
I want to find the core code which handles the click does (specifically in Chrome, Firefox, and Internet Explorer), so I can replicate it as closely as possible, however I've found myself lost in a deep pit of classes and interfaces...
A new ClickAction
(source) is created (to later be performed). Performing this includes a 'click()' call on an instance of the Mouse
interface (source) ... aaaaand I'm lost. I see from generated JavaDoc that this is implemented by either EventFiringMouse (source) or HtmlUnitMouse (source), but I'm not sure which one will be implemented. I made an assumption (with little basis) that HtmlUnitMouse
would be used, which has led me further down the rabbit hole looking at HTMLUnit code from Gargoyle Software...
In short, I am totally lost.
Any guidance would be much appreciated :)
Research
RemoteWebDriver
(source) is subclassed by ChromeDriver
, FirefoxDriver
, and InternetExplorerDriver
. We can use the JavaScript Executor in Selenium to click an element. Selenium can execute JavaScript commands with the help of the method executeScript. Sometimes while clicking a link, we get the IllegalStateException, to avoid this exception, the JavaScript executor is used instead of the method click.
For interacting with web elements in test automation, QA engineers use the Click command offered by Selenium WebDriver. It helps simulate the click action users perform in the real world. However, there are multiple subsets of the click action – left-click, right-click, double click, drag, and drop, etc.
Selenium supports 8 different types of locators namely id, name, className, tagName, linkText, partialLinkText, CSS selector and xpath. Using id is one of the most reliable and fast methods of element recognition. Usually, the id is always unique on a given web page.
The Essentials
The drivers for Chrome, Firefox, and Internet Explorer are all RemoteWebDrivers
.
This means that any actions which Selenium performs are sent to the browser (the WebDriver
), via an HttpRequest
.
Once the request is received by the browser, it will perform the action as either a "native event" or synthetically. How a browser executes an action depends on the capabilities of the browser (and potentially a flag option).
"Native" events are OS-level events.
Actions executed synthetically are executed using JavaScript. "Automation Atoms" are used - as one infers from 'atom', they are small, simple functions to perform low-level actions.
References
RemoteWebDriver
is subclassed by ChromeDriver
, FirefoxDriver
, InternetExplorerDriver
, OperaDriver
, and SafariDriver
. (reference)
All implementations of WebDriver that communicate with the browser, or a RemoteWebDriver server shall use a common wire protocol. This wire protocol defines a RESTful web service using JSON over HTTP. (reference)
In WebDriver advanced user interactions are provided by either simulating the JavaScript events directly (i.e. synthetic events) or by letting the browser generate the JavaScript events (i.e. native events). Native events simulate the user interactions better whereas synthetic events are platform independent [...] Native events should be used whenever possible. (reference)
Browser Automation Atoms are building blocks intended to be used by Selenium implementations. By using the same pieces throughout the codebase, rather than reimplementing required functionality in multiple places, the project can reduce the number of bugs found, and can simplify the process of adding new functionality and drivers. (reference)
Automation Atoms
The wiki for the Selenium IE Driver states that it uses native events rather than JavaScript events to interact with the browser.
As the InternetExplorerDriver is Windows-only, it attempts to use so-called "native", or OS-level events to perform mouse and keyboard operations in the browser. This is in contrast to using simulated JavaScript events for the same operations.
Except for clicking <option>
elements, where it uses JavaScript.
The IE driver handles this one scenario by using the
click()
Automation Atom, which essentially sets the.selected
property of the element and simulates theonChange
event in JavaScript.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With