Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Click on pseudo element using Selenium

I am trying to use Selenium to click on a ::after pseudo element. I realize that this cannot be done through the WebDriver directly, but cannot seem to figure out a way to do so with Javascript.

Here is what the DOM looks like:

<em class="x-btn-split" unselectable="on" id="ext-gen161">
    <button type="button" id="ext-gen33" class=" x-btn-text">
        <div class="mruIcon"></div>
        <span>Accounts</span>
    </button>
    ::after
</em>

This is what the above element looks like. The Left hand side of the object is the 'button' element and the :after element is the right hand side with the arrow which would bring down a dropdown menu when clicked. As you can see that the right hand side has no identifiers whatsoever and that is partially what is making this difficult to do.

Element to be clicked

I have seen these two links in stackoverflow and have attempted to combine the answers to form my solution, but to no avail.

Clicking an element in Selenium WebDriver using JavaScript
Locating pseudo element in Selenium WebDriver using JavaScript

Here is one my attempts:

string script = "return window.getComputedStyle(document.querySelector('#ext-gen33'),':before')";
IJavaScriptExecutor js = (IJavaScriptExecutor) Session.Driver;
js.ExecuteScript("arguments[0].click(); ", script);

In which I get this error:

System.InvalidOperationException: 'unknown error: arguments[0].click is not a function
  (Session info: chrome=59.0.3071.115)
  (Driver info: chromedriver=2.30.477700 (0057494ad8732195794a7b32078424f92a5fce41),platform=Windows NT 6.1.7601 SP1 x86_64)'

I've also tried using the Actions class in Selenium to move the mouse in reference to the left hand side, similar to this answer as well. I think it may be because I don't know what the offset is measured in and the documentation doesn't seem to give any indication. I think it is in pixels??

Actions build = new Actions(Session.Driver);
build.MoveToElement(FindElement(By.Id("ext-gen33"))).MoveByOffset(235, 15).Click().Build().Perform();

This attempt seems to click somewhere as it gives no errors, but I'm not really sure where.

I'm attempting to automate Salesforce (Service Cloud) in c# if that helps.

Maybe someone can offer a solution?

like image 950
Jand Avatar asked Aug 01 '17 00:08

Jand


People also ask

How do you click pseudo elements in selenium?

If we need to interact with a pseudo-element, Selenium WebDriver does not offer us the option to do so. and our test requires us to verify the content displayed in the ::after block. Since this is not a regular element, we cannot identify it using the regular Selenium locators we are all familiar with.

What is :: before in xpath?

::before. ::before is a pseudo element which allows you to insert content onto a page from CSS (without it needing to be in the HTML). While the end result is not actually in the DOM, it appears on the page as if it is.

What is a pseudo element selector?

A CSS pseudo-element is a keyword added to a selector that lets you style a specific part of the selected element(s). For example, ::first-line can be used to change the font of the first line of a paragraph. /* The first line of every <p> element.


2 Answers

I've encounter the same problem while writing Selenium tests for Salesforce and managed to solve it by direct control over mouse using Actions.

Wrapper table for this button has hardcoded width of 250px, and you have spotted that. To locate where the mouse is, you can use contextClick() method instead of Click(). It simulates right mouse button so it will always open browser menu.

If you do:

Actions build = new Actions(Session.Driver);
build.MoveToElement(FindElement(By.Id("ext-gen33"))).ContextClick().Build().Perform();

you will spot that mouse moves to the middle of the WebElement, not the top left corner (I thought that it does too). Since that element width is constant, we can move mouse just by 250 / 2 - 1 to the right and it will work :) code:

Actions build = new Actions(Session.Driver);
build.MoveToElement(FindElement(By.Id("ext-gen33"))).MoveByOffset(124, 0).Click().Build().Perform();
like image 102
Maciej Podstawka Avatar answered Oct 23 '22 04:10

Maciej Podstawka


For those who are trying to do this in Python, the solution is below:

elem= driver.<INSERT THE PATH TO ELEMENT HERE> ActionChains(driver).move_to_element_with_offset(elem,249,1).click().perform()

Basically here I'm finding my element in the DOM and assigning to a WebElement. The WebElement is then passed the method move_to_element_with_offset as a param.

I got the px values for the element from developer tools.

PS: use this import- from selenium.webdriver.common.action_chains import ActionChains

You can read more about Action chain class and its method move_to_element_with_offset here: http://selenium-python.readthedocs.io/api.html.

Hope this helps.

like image 28
AmrithS Avatar answered Oct 23 '22 03:10

AmrithS