5

I am trying to write xpath to find a checkbox selected or not, this checkbox is being changed using css ::after element. Below are two elements I have

//div[@class='FormBlock-formItem2' and .//text()='Scoped In']//div[@class='FormBlock-controlIndicator']

two elements for checkboxes

I need to find that 'Scoped Out' is not selected and 'Scoped In' is selected. The only difference I see is '::after' in the second section of checkbox. I tried the xpath :" //div[@class='FormBlock-formItem2' and .//text()='Scoped In']//div[@class='FormBlock-controlIndicator'] " but this is finding the 'Scoped In' element but I am not able to verify if its checked or not. Struggling from couple of days. Kindly help.

Naveen kumar
  • 239
  • 2
  • 6
  • 19
  • 3
    Pseudo-elements don't exist in the DOM tree (hence the name), therefore they cannot be selected with XPath. – Tomalak Aug 23 '18 at 18:39
  • @Tomalak : Hi, Thanks for the comment,I got to know this point after some search in google, but is there any way to find if the checkbox is selected or not? – Naveen kumar Aug 23 '18 at 18:41
  • Not without asking Javascript, I would assume. – Tomalak Aug 23 '18 at 18:49
  • 2
    @Naveenkumar Can you update the question with text based formatted _HTML_ of either of the element 1)Without being checked and 2)Being checked? – undetected Selenium Aug 23 '18 at 19:27

5 Answers5

7

Check code below if return correct true/false:

driver.findElement(By.xpath("//label[./div[@class='FormBlock-itemText' and .='Scope In']]/input")).isSelected();
Sers
  • 12,047
  • 2
  • 12
  • 31
4

Unfortunately, that's not possible with XPath. As mentioned by Tomalak, Pseudo-elements don't exist in the DOM tree (hence the name), therefore they cannot be selected with XPath and Selenium does not expose them as well. In general, ::before and ::after pseudo-elements are used for styling of containing element.

If you want to check whether ::before or ::after pseudo-elements are present or what's their content you can use a CSS selector, like this:

console.log(window.window.getComputedStyle(
 document.querySelector('#item'), ':begin'
));
//or
window.getComputedStyle(
 document.querySelector('#item'), ':after'
).getPropertyValue('color');
#item::after {
    content: 'checked';
    color: rgb(255, 0, 0);
}
<div id="item">
</div>

And then use a JavascriptExecutor to inject the JS into the browser and get the return value:

JavascriptExecutor js = (JavascriptExecutor) driver;         
js.executeScript("return document.title");
wp78de
  • 18,207
  • 7
  • 43
  • 71
  • I was wondering though... CSS is declarative - `::before` and `::after` only exist *because of* something tangible in the DOM tree. Their existence is governed by a CSS rule, therefore it must be possible to infer that they exist by applying same CSS rule in selenium. – Tomalak Aug 23 '18 at 19:16
  • @wp78de Hi , thanks for the response, I am not able to use my xpath //div[@class='FormBlock-formBlock' and .//text()='Scope Status']//div[(@class='FormBlock-formItem' or @class='FormBlock-formItem2') and .//text()='Scoped In']//div[@class='FormBlock-controlIndicator'] in the querySelector, and I am not able to convert my xpath to css as css wont support traversing with conditions like in my xpath. How can I execute my xpath in document.. – Naveen kumar Aug 24 '18 at 07:48
  • Hi, I tried this but its returning only rgb(0,0,0) but not the actual color : window.getComputedStyle( document.evaluate("//div[@class='FormBlock-formBlock' and .//text()='Scope Status']//div[(@class='FormBlock-formItem' or @class='FormBlock-formItem2') and .//text()='Scoped In']//div[@class='FormBlock-controlIndicator']", document, null, XPathResult.ANY_TYPE, null ).iterateNext(), ':after' ).getPropertyValue('background'); – Naveen kumar Aug 24 '18 at 08:35
1

You can try using UI state pseudo-classes, using which we can find elements for various states, such as when control is enabled, disabled, and checked.

Pseudo-classes with input example are -

  1. input:enabled - This will find all the elements that are enabled for user input.
  2. input:disabled - This will find all the elements that are disabled for user input.
  3. input:checked - This will find all the elements(check boxes) that are checked.

    WebElement checkBoxStatus = driver.findElement(By.cssSelector("input:checked"));

More details can be found here on w3c site

Amit Jain
  • 4,389
  • 2
  • 18
  • 21
0

Please check the below screenshot. I try using the CSS selector and checking visibility of element located with wait driver time. It worked.

Html code with after:: pseudo code

python code with css selector and wait time that worked out

0

It is possible to use XPath in Selenium WebDriver to access pseudo-elements, but not directly - via JavascriptExecutor.

  1. Find the needed parent element for pseudo-element by XPath and Selenium, save it as e.g. webElement.
  2. Call window.getComputedStyle() function via Selenium JavascriptExecutor, use webElement as parameter. It can be accessible in script by arguments[0] variable.
WebElement webElement = driver.findElement(By.xpath("//div[@class='FormBlock-controlIndicator']");
String script = "return window.getComputedStyle(arguments[0],':after').getPropertyValue('content')";
IJavaScriptExecutor js = (IJavaScriptExecutor)_driver;
String content = (String) js.ExecuteScript(script, webElement);
Viktor Chmel
  • 145
  • 7