Java Selenium: Switch to iframe inside shadow-root open inside webview - java

I am trying to automate some tests on my node webkit app using Java Selenium. The way it works is that the chromedriver attaches to the main window, but any site that I access is in the DOM as a webview like so:
Picture with the DOM:
How would I approach this? After expanding the shadow root element in java and trying to switch the context to the iframe below it, I just get random errors (in my opinion) that do not pertain to the function I'm calling. For example:
WebElement shadowRoot = expandShadowElement(root);
WebElement iframe = shadowRoot.findElement(By.cssSelector("iframe"));
Driver.getWebDriver().switchTo().frame(iframe);
WebElement city = Driver.getWebDriver().findElement(By.className("input-btn-group"));
The second line gives me a "Argument to isShown must be of type Element", but that does not make sense as I am not calling the isShown function.

As per your question, once you expanding the shadow root element induce WebDriverWait for the desired <iframe> to be frameToBeAvailableAndSwitchToIt as follows:
WebElement shadow_root = Driver.getWebDriver().findElement(By.xpath("//webview[#class='sel' and contains(#src,'https://www.google.com/?')][starts-with(#id,'w_Webo')]"));
WebElement shadow_root_element = (WebElement)((JavascriptExecutor)driver).executeScript("return arguments[0].shadowRoot", shadow_root);
new WebDriverWait(Driver.getWebDriver(), 10).until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.tagName("iframe")));
Note: As per the screenshot you have shared the element identified as By.className("input-btn-group") isn't visible and is not included within the answer.

We can switch to iframe inside shadow dow by following these 3 steps
step 1: get the shadow root element
step 2: Using that shadow root element find the iframe web element
step 3: Now switch into the iframe which we got in step 2
loc = Locator.new(:xpath,"//locator_used_to_get_shadow_root")
sr = #driver.gets_shadow_root(loc)
iframe_inside_shadowroot = sr.find_elements(:css, "iframe")
driver.switch_to.frame(iframe_inside_shadowroot)

Solve similar issue for electron. In electron they have their own wrapper on top of webview, that based on Chromium webview.
But for chrome webdriver solution's may be the same.
https://stackoverflow.com/a/63227482/4577788

Related

Selenium webdriver (java) - Click on desired link of some search results

I am doing automation using selenium webdriver (java) on a search engine BookMyCrop (http://www.bookmycrop.com). Here, I searched for a crop but, I am not able to click on desired search result. Please help me with it.
Code :
WebElement search = driver.findElement(By.xpath("//*[#id=\"search_keyword\"]"));
search.sendKeys("59825");
search.sendKeys(Keys.ENTER);
driver.findElement(By.partialLinkText("Cashew")).click();
------My 1st try-------------
//WebElement link = driver.findElement(By.xpath("\"//div[#id = 'Links']/a[3]\""));
//link.click();
------My 2nd try-------------
//List<WebElement> find = driver.findElements(By.xpath("/html/body/section[2]/div[2]/div/div/div/div[1]"));
//find.get(1).click();
}
} –
You can use the css selector based on class names: ".product-block.inner-product-block" and get the list of all the search results.
Then click on whatever index you want to click.
I am not using an IDE for this but it would look something like this:
driver.findElements(By.cssSelector(".product-block.inner-product-block")).get(0).click();
As said, you can try with css ".product-block.inner-product-block"
Then
get List of WebElements
do loop
inside loop, try get text of each element or innerText attribute
cross check if it is required one or not by simple if condition
If so, click on that web element and break loop
if this locator is not giving required info, try other locator. say $$("a h3") for veg names.
The below code worked for me. It is navigates to the correct link
WebDriver driver = new ChromeDriver();
driver.manage().timeouts().setScriptTimeout(20, TimeUnit.SECONDS);
driver.manage().window().maximize();
driver.get("http://www.bookmycrop.com");
WebElement search = driver.findElement(By.xpath("//*[#id=\"search_keyword\"]"));
search.sendKeys("59825");
search.sendKeys(Keys.ENTER);
driver.findElement(By.partialLinkText("Cashew")).click();

Why no elements can be tergeted on this website?

I'm trying to use selenium to type in data in inputboxes. But I cant get any element (NoSuchElementException). Problem is only with this site.
I tried searching by name/id but it failed.
WebDriver driver = new FirefoxDriver();
driver.get("https://ekrs.ms.gov.pl/web/wyszukiwarka-krs/strona-glowna");
System.out.println(driver.getCurrentUrl());
System.out.println("Successfully opened the website");
WebElement wb = driver.findElement(By.id("rejestrPrzedsiebiorcy"));
My goal (for now) is just to get this element :P.
The problem is the form is included in the source via <iframe> element. You can see that it has attribute src="https://ekrs.ms.gov.pl/krsrdf/krs/wyszukiwaniepodmiotu?". If you go to that link, you will see standalone form. The question is - how to access an included source? It's quite simple ;)
Find the <iframe> element:
WebElement frame = driver.findElement(By.xpath("//div[#class='portlet-body']/div/iframe"))
Switch to that frame:
driver.switchTo().frame(frame)
And that's it! Now you are in the <iframe> element context, and you can search inside it. so this will work now:
WebElement wb = driver.findElement(By.id("rejestrPrzedsiebiorcy"));
To switch back (get out of the frame context) you just have to call:
driver.switchTo().defaultContent();
Note that this site has dynamically generated ids to prevent automation, and uses CaptchaV3 (you can see I used xpath expression to find the iframe). Selenium is easily detectable if you are not careful.
Carefully observe the HTML code after inspecting required element. If you element is inside <iframe> then you need to switch on to frame first and then find that element.
below is the way to switch to frame:
driver.switchTo().frame() method takes one of the three possible arguments:
A number.
Select a frame by its (zero-based) index. That is, if a page has three frames, the first frame would be at index 0, the second at index 1 and the third at index 2. Once the frame has been selected, all subsequent calls on the WebDriver interface are made to that frame.
driver.switchTo().frame(0)
A name or ID.
Select a frame by its name or ID. Frames located by matching name attributes are always given precedence over those matched by ID.
driver.switchTo().frame("name here");
A previously found WebElement.
Select a frame using its previously located WebElement.
WebElement iframeElement = driver.findElement(By.id("IF1"));
//now use the switch command
driver.switchTo().frame(iframeElement);
Try driver.findElement(By.id("form-main")); first, then driver.findElement(By.id("rejestrPrzedsiebiorcy")); again.

How to identify the element with text as Sign in with Google through xpath in java selenium

I am performing Automation for a redbus application but I am finding the web elements using firebug and it will highlight the firefox browser but it doesn't work in a chrome browser.
Please review the following screenshots:
Redbus website link
step 1 Open redbus application URL =https://www.redbus.in/
step 2 Click Accounts module
step 3 Click sign or signup link
My XPath is :
.//*[#id='g-signin2']//span[text()='Sign in with Google']
Chrome browser screenshot: Can not identify the webElement
Google sign up link is in Iframe , in order to interact with elements which are inside the frame/iframe , you need to change the focus of your web driver to that particular frame.
How you can do that in your case :
driver.switchTo.frame("//iframe[#class='modalIframe']")
Then you can interact with Sign in with Google.
WebElement signupButton = new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(By.xpath("//span[contains(#id,'signed') and text()='Sign in with Google']")))
signupButton.click();
HTH !
To identify and invoke click() on the element with text as Sign in with Google, as the element is within an . So you have to induce WebDriverWait for both the cases, once for the frame to be available and again for the desired element to be clickable and you can use the following solution :
new WebDriverWait(driver, 10).until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.xpath("//iframe[#class='modalIframe' and #src='/account?pageName=Home&noReload=noReload']")));
new WebDriverWait(driver, 10).until(ExpectedConditions.elementToBeClickable(By.xpath("//span[#class='abcRioButtonContents']//span[normalize-space()='Sign in with Google']"))).click();
What You have here is modal frame, You should first switch on it, and the do actions on elements:
driver.switchTo().frame("modalIframe");
or maybe this:
driver.switchTo().activeElement()
It looks the login popup is available inside the iframe tag. First navigate to that particular frame as below and then add the sign in xpath step.
driver.switchTo().frame(0);

selenium.ElementNotVisibleException: Element is not currently visible JAVA

I am working on selenium, while running Java code I tried to CLICK a menu from the web page but encounter error of selenium.ElementNotVisibleException: Element is not currently visible Kindly advise on this matters . Thanks you
HTML code for text field :
<li onclick="goin('pages/AbcProxy/proxyGroupList.do')>
TESTABC
JAVA code:
WebdriverWait wait = new WebDriverWait(driver,50);
wait until(ExpectedConditions.presenceOfElementLocated(By.xpath("/html/body/div/div/ul/li[12]/a")));
presenceOfElementLocated checks if the element exists in the DOM. To check if the element is visible use visibilityOfElementLocated
WebdriverWait wait = new WebDriverWait(driver,50);
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("/html/body/div/div/ul/li[12]/a")));
element.click();
It might be that your xpath is to a different a element that is invisible (css display none or such).
It would be better to use some id first (maybe for the parent ul?) and then a relative xpath from there, full xpaths from root are not recommended as it makes the test very brittle

Identifying number of iframes in a page using Selenium with java?

Is there any method to identify the following in Selenium?
Number of iframes in a page
Attributes/Details of the current iframe
driver.findElements(By.xpath("//iframe")).size();
For acquiring details of current frame I propose you switch to it using a WebElement object and switchTo, and then get attributes like you normally do, with getAttribute
UPD
In fact, yes, first will give the amount of iframes in current context. If you don't want to do it recursively, but want a quick and working (dirty) solution - just get the page source and find all inclusions of "<iframe" string
As the other answers have stated, you can identify the number of frames in the currently focused context using:
driver.findElements(By.xpath("//iframe")).size();
However this will not identify any frames that are children of another frame. To do so, you will need to switch to that parent frame first.
To retrieve attributes such as name or id for the currently focused frame you can use JavascriptExecutor like so:
String currentFrameName = (String)((JavascriptExecutor) driver).executeScript("return window.frameElement.name");
Here an example how you can approach it:
WebDriver driver = new FirefoxDriver();
driver.get("http://the-internet.herokuapp.com/iframe");
// find all your iframes
List<WebElement> iframes = driver.findElements(By.xpath("//iframe"));
// print your number of frames
System.out.println(iframes.size());
// you can reach each frame on your site
for (WebElement iframe : iframes) {
// switch to every frame
driver.switchTo().frame(iframe);
// now within the frame you can navigate like you are used to
System.out.println(driver.findElement(By.id("tinymce")).getText());
}

Categories

Resources