Home > OS >  Selenium couldn't find iframe using its id (Java)
Selenium couldn't find iframe using its id (Java)

Time:01-14

I am working on the task from 'Automation on Java' course. In scope of this task I need to create a test which should interact with elements from this page https://cloud.google.com/products/calculator I need to create a script which will fill some specific fields from this page.

As I can see there are few iframes on this page. First of all, I need to fill the 'Number of instances' field. I see that element which I am interested in (//input[@id='input_90']) is located inside the iframe (id = 'myFrame').

enter image description here

enter image description here

Based on that, I create a method, which should switch me to this iframe using its id value:

    public void switchFrameToMyFrame() {
        driver.switchTo().frame("myFrame");
    }

But when I am trying to run this specific test

@Test
    @Order(2)
    @DisplayName("Fill Calculation Form")
    public void fillCalculationForm() {
        driver.get("https://cloud.google.com/products/calculator");
        pricingCalculatorPage.switchFrameToMyFrame();

I am getting this error message:

org.openqa.selenium.NoSuchFrameException: No frame element found by name or id myFrame

I tried several approaches how I can swich to another frame:

//using if value of the iframe
driver.switchTo().frame("myFrame");

//using xpath of the element inside the iframe
driver.switchTo().frame(driver.findElement(By.xpath("//input[@id='input_90']")));

//I tried to add this row in case if my test ends before the page iframe is loaded on the page
fluentWait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(myFrame));

//I even tried to create a method which should find the index of the iframe using its id, but seems like it found the wrong index. After I switched to iframe using the index value which I got from this method, driver was not able to find the element inside the iframe. It could be because of the iframe index is wrong
public void findIframeIndex() {
        int size = driver.findElements(By.tagName("iframe")).size();

        for (int i = 0; i < size; i  ) {
            driver.switchTo().frame(i);
            int total = driver.findElements(By.xpath("//iframe[@id='myFrame']")).size();
            System.out.println(total);
            driver.switchTo().defaultContent();
        }
    }

I've read a lot of information about how I can deal with iframes but I didn't found what I need to do in my specific case.

Could anyone help me to understand how I can interact at least with the 'Number of instances' field?

CodePudding user response:

There are 2 iframes (nested iframes), 'Number of instances', and other associated fields inside the second iframe. So you have to switch to the outer iframe and then inner iframe, try the below code:

imports:

import java.time.Duration;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

code:

WebDriver driver = new ChromeDriver();
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(15));
    
driver.get("https://cloud.google.com/products/calculator");
    
WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));

// switch to the first iframe
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.xpath(".//*[starts-with(@name,'goog_')]")));
    
// switch to the second iframe
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.id("myFrame")));
        
driver.findElement(By.id("input_90")).sendKeys("56");

After entering all the values, you can switch to the first iframe using:

driver.switchTo().defaultContent();

CodePudding user response:

The desired element is within nested iframe so you have to:

  • Induce WebDriverWait for the first frameToBeAvailableAndSwitchToIt.

  • Induce WebDriverWait for the second frameToBeAvailableAndSwitchToIt.

  • Induce WebDriverWait for the desired elementToBeClickable.

  • You can use the following locator strategies:

    import java.time.Duration;
    import org.openqa.selenium.By;
    import org.openqa.selenium.support.ui.ExpectedConditions;
    import org.openqa.selenium.support.ui.WebDriverWait;
    
    driver.get("https://cloud.google.com/products/calculator");
    WebDriverWait wait = new WebDriverWait(driver, Duration.ofSeconds(10));
    wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.cssSelector("iframe[src^='https://cloud.google.com/frame/products/calculator']")));
    wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.id("myFrame")));
    wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//input[@ng-model='listingCtrl.computeServer.quantity' and @aria-label='quantity' and @name='quantity']"))).sendKeys("4");
    
  • Browser Snapshot:

multipleFrame

  • Related