Unable to perform any actions on elements which were located under flexbox

Viewed 512

Selenium is able to findElement which were located under flex box but not able to perform any actions on those elements. Below I am providing couple of sample websites for detailed understanding,


Example#1:

Website: https://condos.ca/

HTML snippet:

<div class="styles___SearchField-sc-ntshwn-1 azZjo">
   <div class="styles___SiteSearch-sc-ntshwn-3 bvlPAF">
  <div class="styles___InputIcon-sc-ntshwn-4 eAuylQ">
     <svg viewBox="0 0 59.93 60" class="styles___Svg-sc-14upfal-0 frvNPk svg-icon" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="width: 20px; height: 20px;">
        <path d="M59.23,55.73L44.33,40.81a25,25,0,1,0-3.53,3.54L55.7,59.27A2.5,2.5,0,1,0,59.23,55.73ZM5,25A20,20,0,1,1,25,45,20,20,0,0,1,5,25Z" transform="translate(-0.03)"></path>
     </svg>
  </div>
  <input aria-label="Search by address, Neighbourhood, MLS #" placeholder="Search by address, Neighbourhood, MLS #" id="search-input">
   </div>
   <div class="styles___GetLocationContainer-sc-ntshwn-5 cCBUUE">
  <button target="_blank" name="search nearby button" class="styles___AppButton-sc-5pk18n-0 jXQNUT styles___SearchNearby-sc-ntshwn-6 dYpkAS" id="">
     <svg viewBox="0 0 20 20" class="styles___Svg-sc-14upfal-0 frvNPk svg-icon" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="width: 22px; height: 22px;">
        <path d="M10,17.49c-4.19-0.02-7.57-3.39-7.55-7.53c0.02-4.14,3.42-7.48,7.61-7.47c4.18,0.02,7.56,3.37,7.55,7.51C17.6,14.15,14.19,17.5,10,17.49C10,17.49,10,17.49,10,17.49z M10,3.48C6.37,3.5,3.43,6.43,3.45,10.02c0.02,3.59,2.98,6.5,6.61,6.48c3.62-0.02,6.54-2.92,6.55-6.5c0-3.6-2.95-6.52-6.59-6.52C10.01,3.48,10.01,3.48,10,3.48z"></path>
        <path d="M10,3.48c-0.28,0-0.5-0.22-0.5-0.49V0.49C9.5,0.22,9.72,0,10,0s0.5,0.22,0.5,0.49v2.49C10.5,3.26,10.28,3.48,10,3.48z"></path>
        <path d="M10,20c-0.28,0-0.5-0.22-0.5-0.49v-2.51c0-0.27,0.22-0.49,0.5-0.49s0.5,0.22,0.5,0.49v2.51C10.5,19.78,10.28,20,10,20z"></path>
        <path d="M19.54,10.48h-2.43c-0.28,0-0.5-0.22-0.5-0.49c0-0.27,0.22-0.49,0.5-0.49h2.43c0.28,0,0.5,0.22,0.5,0.49C20.04,10.26,19.82,10.48,19.54,10.48z"></path>
        <path d="M3,10.49H0.46c-0.28,0-0.5-0.22-0.5-0.49c0-0.27,0.22-0.49,0.5-0.49H3c0.28,0,0.5,0.22,0.5,0.49C3.5,10.27,3.28,10.49,3,10.49z"></path>
        <path d="M10,13.49c-1.95-0.02-3.52-1.61-3.5-3.54c0.02-1.93,1.62-3.48,3.58-3.46c1.94,0.02,3.51,1.59,3.5,3.51c-0.01,1.94-1.61,3.5-3.57,3.49C10.01,13.49,10,13.49,10,13.49z M10,7.48C8.6,7.5,7.48,8.64,7.5,10.03c0.02,1.39,1.18,2.49,2.58,2.47c1.38-0.02,2.49-1.13,2.5-2.5c0-1.39-1.14-2.52-2.55-2.52C10.02,7.48,10.01,7.48,10,7.48z"></path>
     </svg>
  </button>
   </div>
</div>

Code:

driver.get("https://condos.ca");
driver.findElement(By.xpath("//input[@id='search-input']")).sendKeys("test");

Result: Step is being executed without throwing any errors but text was not entered.


Example#2:

Website: https://demoqa.com/slider

HTML snippet:

<div id="sliderContainer" class="form-group row">
   <div class="col-9">
  <span class="range-slider__wrap">
     <input type="range" class="range-slider range-slider--primary" min="0" max="100" value="25" style="--value:25;">
     <div class="range-slider__tooltip range-slider__tooltip--auto range-slider__tooltip--bottom" style="left: calc(25% + 5px);">
        <div class="range-slider__tooltip__label">25</div>
        <div class="range-slider__tooltip__arrow"></div>
     </div>
  </span>
   </div>
   <div class="col-3"><input id="sliderValue" class="form-control" value="25"></div>
</div>

Code:

driver.get("https://demoqa.com/slider");
JavascriptExecutor executor = (JavascriptExecutor) driver;
WebElement slider = driver.findElement(By.xpath("//input[@type='range']"));
System.out.println("Cuurent value: " + slider.getAttribute("value"));
executor.executeScript("arguments[0].setAttribute('value', ' 30 ')", slider);

Result: Printed attribute value but didn't set the new value.


Few SO questions and blogs are suggesting to use Selenium flex api to automate these these type of applications but I can see a pre-requiste to install flex plugin for eclipse and I cannot find that. Also, these post are little old (5 years old).

  • How to handle these elements?
  • Is there any new way to do this?

References:

1 Answers

Solution to Example 1

If you load the website, you will observe that the text above the search editbox initially looks like:

enter image description here

After sometime, the same element's text gets changed to: enter image description here

Only after this happens, try performing the sendkeys operation. Note that you don't have to perform the sendkeys operation on the element with id = 'search-input'. You first need to click on that element and then another element(cssSelector -> div[role='combobox'] [placeholder='Search by address, Neighbourhood, MLS #']) becomes visible on which you have to perform the sendkeys operation.

Please refer the code below for the same(tested on chrome, edge and firefox).

package usecase;

import java.time.Duration;
import java.util.regex.Pattern;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import io.github.bonigarcia.wdm.WebDriverManager;

public class Flexcase {
    public static WebDriver driver;
    private static final int maxtime = 20;

    /**
     * Creating a custom findElement method that uses Explicit wait and waits for an
     * element to be clickable
     */
    public static WebElement findElement(By by) {
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(maxtime));
        return wait.until(ExpectedConditions.elementToBeClickable(by));
    }

    /**
     * Waits for an element to contain a text matched by the given pattern(regex)
     */
    public static Boolean doesElementContainTextPattern(By by, String pattern) {
        WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(maxtime));
        return wait.until(ExpectedConditions.textMatches(by, Pattern.compile(pattern)));
    }

    public static void main(String[] args) throws InterruptedException {
        WebDriverManager.chromedriver().setup();
        driver = new ChromeDriver();
        driver.manage().window().maximize();
        driver.get("https://condos.ca/");
        // Waiting for the text to achieve a specific pattern - Search followed by 1+
        // occurrences of either digits or commas followed by 0+ occurrences of any
        // character that is not a newline character followed by the word Listings
        if (doesElementContainTextPattern(By.className("dPFjpJ"), "Search [\\d,]+.*Listings")) {
            findElement(By.id("search-input")).click();
            findElement(By.cssSelector("div[role='combobox'] [placeholder='Search by address, Neighbourhood, MLS #']"))
                    .sendKeys("Test");
        }

        Thread.sleep(10000); // Pls let me see what's happening on the screen
        driver.quit();
    }
}

Demo: enter image description here

Solution for Example 2

Instead of using javascriptexecutor, I have used the Actions class to build a composite action made up by following actions:

  • move the mouse to leftmost position of the slider by finding the slider width in pixels
  • move the mouse to the desired position on the slider proportiante to the percentage value passed

Code:(sliding accuracy can be improved)

package usecase;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.interactions.Actions;

import io.github.bonigarcia.wdm.WebDriverManager;

public class Slider {

    public static WebDriver driver;

    public static void moveSliderToPosition(By by, int percentage) throws InterruptedException {
        WebElement slider = driver.findElement(by);
        Actions builder = new Actions(driver);
        builder.moveToElement(slider, (int) (-slider.getRect().width / 2), 0) // move to the leftmost position of the
                                                                                // element
                .moveByOffset((int) (percentage * slider.getRect().width / 100), 0) // move the cursor by an offset
                                                                                    // proportionate to the value passed
                .click().build().perform();
        Thread.sleep(3000); // let me see what has happened on the screen
    }

    public static void main(String[] args) throws InterruptedException {
        WebDriverManager.chromedriver().setup();
        driver = new ChromeDriver();
        driver.manage().window().maximize();
        driver.get("https://demoqa.com/slider");
        By slider = By.cssSelector("input.range-slider");
        moveSliderToPosition(slider, 47);
        moveSliderToPosition(slider, 83);
        moveSliderToPosition(slider, 35);
        driver.quit();
    }
}

Demo: enter image description here

Related