I have an application with multiple iframes in the same screen. These iframes have different names every session, so I would like to search within the application for a button within one of the iframes with the name "Pesonal". This iframe-name should be saved to be used in another method. Anybody an idea how to do this?
Please close / delete this topic as I have found the solution:
public WebElement findElement(By locator) {
driver.switchTo().defaultContent();
//list all iframes
List<WebElement> iframeList = driver.findElements(By.tagName(("iframe")));
final List<WebElement> foundElements = new ArrayList<>();
iframeList.forEach(iframe -> {
driver.switchTo().frame(iframe);
List<WebElement> foundElementList = driver.findElements(locator);
if (foundElementList.size() > 0) {
foundElements.addAll(foundElementList);
} else driver.switchTo().defaultContent();
});
return foundElements.get(0);
}
Related
I am trying to automate application,tried first to find xpath or CSS locators unable to find looks no frame also inside the element.
I am able to handle using JavaScript but unable to enter full text in the search box,it's trimming some text,,please help me.
JavaScript which i tried.
((JavascriptExecutor)driver).executeScript("return document.querySelector('#app').shadowRoot.querySelector('#base > wego-search-form').shadowRoot.querySelector('div > wego-hotel-search-form').shadowRoot.querySelector('#loc').shadowRoot.querySelector('#item0 > div.disable-select.city-country-name').click();");
((JavascriptExecutor)driver).executeScript("return document.querySelector('#app').shadowRoot.querySelector('#base > wego-search-form').shadowRoot.querySelector('div > wego-hotel-search-form').shadowRoot.querySelector('#dates').shadowRoot.querySelector('#depart').shadowRoot.querySelector('#btn').click();");
My scenario i want to click search form and enter some destination details,If possible anyway i can handle this case using locators suggest me
Shadow DOM Elements are used in this website. Shadow DOM provides encapsulation for the JavaScript, CSS, and templating in a Web Component.
Shadow DOM allows hidden DOM trees to be attached to elements in the
regular DOM tree — this shadow DOM tree starts with a shadow root,
underneath which can be attached to any elements you want, in the same
way as the normal DOM.
Refer this To get details about it or for more details Google it.
Now handle Shadow element take reference from this blog. I've tried the below code to enter text as you expected and its working for me.
public static WebDriver driver;
public static void main(String[] args){
System.setProperty("webdriver.chrome.driver", "driver_path");
driver = new ChromeDriver();
driver.get("https://www.wego.com.my/hotels");
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
driver.manage().window().maximize();
WebElement root1 = driver.findElement(By.id("app"));
WebElement shadowRoot1 = expandRootElement(root1);
WebElement root2 = shadowRoot1.findElement(By.tagName("wego-search-form"));
WebElement shadowRoot2 = expandRootElement(root2);
WebElement root3 = shadowRoot2.findElement(By.tagName("wego-hotel-search-form"));
WebElement shadowRoot3 = expandRootElement(root3);
WebElement root4 = shadowRoot3.findElement(By.id("loc"));
WebElement shadowRoot4 = expandRootElement(root4);
shadowRoot4.findElement(By.cssSelector("div.root-container div.container")).click();
WebElement element = shadowRoot4.findElement(By.id("searchKeywordInput"));
Actions action = new Actions(driver);
action.click(element).sendKeys(Keys.chord(Keys.CONTROL, "a"));
element.sendKeys(Keys.DELETE);
element.sendKeys("narendra");
}
public static WebElement expandRootElement(WebElement element) {
WebElement newElement = (WebElement) ((JavascriptExecutor) driver).executeScript("return arguments[0].shadowRoot", element);
return newElement;
}
Updated
As an alternative of sendKeys(), JavascriptExecutor can be used to set the value of text box. Use below code
WebElement element = shadowRoot4.findElement(By.id("searchKeywordInput"));
JavascriptExecutor javascriptExecutor = (JavascriptExecutor) driver;
javascriptExecutor.executeScript("arguments[0].value='Your Text Goes Here';", element);
I've tested this so many time and this is working fine in each case.
Note: using JavascriptExecutor may not trigger the search result auto suggestion.
I am trying to automate the Google Search for "Java" and when it provides a list, I want to select "java interview questions".
I tried using the below xpath, but the script is failing.
List<WebElement> list = driver.findElements(By.xpath("//ul[#role ='listbox']//li/descendent::div[#class='sbl1']"));
Below is my code for the same -
public class GoogleSearchTest {
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver" , "C:/Users/User/Desktop/Selenium Drivers/chromedriver.exe");
WebDriver driver = new ChromeDriver();
driver.get("http://www.google.com");
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
driver.findElement(By.name("q")).sendKeys("Java");
List<WebElement> list = driver.findElements(By.xpath("//ul[#role ='listbox']//li/descendent::div[#class='sbl1']"));
System.out.println("Total no of suggestions in search box::" +list.size());
for(int i=0; i<list.size();i++) {
System.out.println(list.get(i));
if(list.get(i).getText().contains("Java Tutorial")) {
list.get(i).click();
break;
}
}
}
}
I think you are using an invalid xpath locator and you need to give some delay before identifying & fetching the elements, try the below code :
driver.get("http://www.google.com");
driver.findElement(By.name("q")).sendKeys("Java");
Thread.sleep(1000);
List<WebElement> list = driver.findElements(By.xpath("//ul[#role ='listbox']//li"));
System.out.println("Total no of suggestions in search box :: " +list.size());
for(int i=0; i<list.size();i++) {
System.out.println(list.get(i));
if(list.get(i).getText().trim().contains("java interview questions") || list.get(i).getText().trim().equalsIgnoreCase("java interview questions")) {
list.get(i).click();
break;
}
}
Below is the screenshot which describes matching xpath:
No sure why you have to iterate through all the list items, when you can handle this with simple xpath. Here is the code that worked for me.
driver.get("http://www.google.com");
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(15, TimeUnit.SECONDS);
driver.findElement(By.name("q")).sendKeys("Java");
WebElement searchElement = driver.findElement(By.xpath("//div[#class='suggestions-inner-container']//span[.='java salon']"));
System.out.println(searchElement.getText());
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].click();",searchElement);
Thread.sleep(1000); // just added time to make sure you will see the page navigation is successful.
driver.quit();
simple. You have spelling mistake in the xpath. Its descendant and not descendant.
//ul[#role='listbox']//li/descendant::div[#class='sbtc']
Use Chropath, its shows you when the xpath is invalid
That xpath appears to be invalid. I think it would be easiest to find the elements by css using their class, like this:
List<WebElement> list = driver.findElements(By.cssSelector('li.sbct'));
I am trying to dynamically search an "li" tag item and double-click on this website: www.jstree.com (the right-top hierarchy tree sample). The code does find the WebElement but does not do anything. I am trying as follows. Can someone please point to what I am doing wrong? I am using Firefox 35.0.1 and selenium 2.44.0.
driver.get(baseUrl + "http://www.jstree.com/");
WebElement we = driver.findElement(By.xpath("/html/body/div/div/div[1]/div[1]/div[2]/div[1]/ul/li[1]/ul"));
Actions action = new Actions(driver);
List<WebElement> liItems = we.findElements(By.tagName("li"));
for(WebElement liItem:liItems)
{
System.out.println(liItem.getText());
if(liItem.getText().startsWith("initially open"))
{
System.out.println("Found it...");
liItem.click();
action.moveToElement(liItem).doubleClick().build().perform();
break;
}
}
I ended up doing this:
Modified the selector to make sure ONLY the expected elements are returned. It helps a lot in terms of execution time and reducing the number of unwanted loopings. And, then find the element in run time and use Action() on that to perform double click. I also update the Selenium binding as #alecxe suggested to work with latest Firefox
public void DemoTest() throws InterruptedException {
List<WebElement> liItems = driver.findElements(By.xpath("//*[contains(text(),'initially open')]"));
for(WebElement liItem:liItems)
{
Actions actions = new Actions(driver);
actions.moveToElement(liItem).doubleClick().build().perform();
}
}
I try to run some tests on a webpage. I'm a beginner and until now everything went pretty smooth.
I'm changing some values in a webform and now want to press the "Save & Exit" button.
But when I look at the available source with the webdriver (driver.getPageSource();) , I don't see a button, only the below JavaScript. I shortened the script to one button - the one button I would like to click.
function getToolbarCfg() {
return [{ btnId: 2, icon:'images/obj16/tsave_.gif', text:'Save & Exit', qtip:'Save Record and Exit', handler:function() { cwc.getCenterWindow().tpzExecute('2',null,'detail'); } }];
Any help is appreciated.
You can have the WebDriver wait explicitly for an element to appear.
public static IWebElement WaitForElementToAppear(IWebDriver driver, int waitTime, By waitingElement)
{
IWebElement wait = new WebDriverWait(driver, TimeSpan.FromSeconds(waitTime)).Until(ExpectedConditions.ElementExists(waitingElement));
return wait;
}
Read up on Selenium's WebDriver Wait Documentation for a good explanation of explicit and implicit waits.
EDIT:
You could alternatively do this:
public static IWebElement WaitForElementToAppear(IWebDriver driver, int waitTime, By waitingElement)
{
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(waitTime));
var element = wait.Until(d =>
{
var elem = driver.FindElement(waitingElement);
if (elem.Enabled)
return elem;
else return null;
});
return element;
}
This will ping the element every .5 seconds until whatever waitTime is defined or to be OR until the element is present.
Found the solution:
The button is executing a JavaScript when clicked. One can directly call that JavaScript function with the Selenium WebDriver.
((JavascriptExecutor) driver).executeScript("cwc.getCenterWindow().tpzExecute('3',null,'detail');");
Hope this answer helps people having the same troubles.
I am having an issue with Selenium WebDriver. I try to click on a link that is outside the window page (you'd need to scroll up to see it). My current code is fairly standard:
menuItem = driver.findElement(By.id("MTP"));
menuItem.click();
// I also tried menuItem.sendKeys(Keys.RETURN);
I know I could scroll up, and it would work in this case. But in a case where you have a long list of items, you don't necessarily know how far you have to scroll down.
Is there any way to click on a link that is not on the visible part of the page (but that would be visible if you scroll)?
As a side note, I'm using Firefox, but I am planning to use IE7/8/9 and Chrome as well.
Any help would be greatly appreciated.
Edit: I'm afraid I can't give the source code, as the company I work for doesn't allow it, but I can give the code of the link I want to click on:
<div class="submenu">
<div id="MTP">Link title</div>
</div>
The exact same code works when the link is visible, only when it is not does it not work.
Edit2: Actually, oddly enough, it doesn't raise any exception and just goes to the next instruction. So basically, what happens is:
menuItem = driver.findElement(By.id("MTP")); // no exception
menuItem.click(); // no exception
//... some code ensuring we got to the next page: timeout reached
driver.findElement(By.id("smLH")).click(); // NoSuchElementException, as we're on the wrong page.
It is actually possible to scroll automatically to element. Although this is not a good solution in this case (there must be a way to get it working without scrolling) I will post it as a workaround. I hope someone will come up with better idea...
public void scrollAndClick(By by)
{
WebElement element = driver.findElement(by);
int elementPosition = element.getLocation().getY();
String js = String.format("window.scroll(0, %s)", elementPosition);
((JavascriptExecutor)driver).executeScript(js);
element.click();
}
I posted this same answer in another question so this is just a copy and paste.
I once had a combo box that wasn't in view that I needed to expand. What I did was use the Actions builder because the moveToElement() function will automatically scroll the object into view. Then it can be clicked on.
WebElement element = panel.findElement(By.className("tabComboBoxButton"));
Actions builder = new Actions(this.driver);
builder.moveToElement(element);
builder.click();
builder.build().perform();
(panel is simply a wrapped element in my POM)
Instead of move the scrollbar to the button position, which sometimes it didn't work for me, I send the enter key to the button
var element = driver.FindElement(By.Id("button"));
element.SendKeys(Keys.Enter);
I ran into a similar problem recently when there was a list of selectable objects in a JS dialog. Sometimes selenium would not select the correct object in the list. So i found this javascript suggestion:
WebElement target = driver.findElement(By.id("myId"));
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", target);
Thread.sleep(500); //not sure why the sleep was needed, but it was needed or it wouldnt work :(
target.click();
That solved my issue
Hey you can use this for ruby
variable.element.location_once_scrolled_into_view
Store the element to find in variable
It might be occurring because your header element or the footer element might be blocking the view of the element you want to perform action on. Selenium tries to scroll to the element position when it has to perform some action on the element (I am using Selenium WebDriver v3.4.0).
Here is a workaround -
private WebElement scrollToElementByOffset(WebElement element, int offset) {
JavascriptExecutor jse = (JavascriptExecutor) driver;
jse.executeScript("window.scrollTo(" + element.getLocation().getX() + "," + (element.getLocation().getY()
+ offset) + ");");
return element;
}
The above function scrolls the view to the element and then scrolls further by the offset you provide. And you can call this method by doing something like -
WebElement webElement = driver.findElement(By.id("element1"));
scrollToElementByOffset(webElement, -200).click();
Now, this is just a workaround. I gladly welcome better solutions to this issue.
This solution worked like a charm for me:
public void click(By by) throws Exception{
WebElement element = driver.findElement(by);
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", element);
Thread.sleep(500);
element.click();
}
This works for me (in c#)-
item = driver.findelement(by.....);
item.SendKeys(Keys.LeftControl);
item.Click();
Just an addition:
In my case the button was overlapped by another floating button.
Just resizing the browser window solved the problem!
I used the method below to solve a similar issue for Selenium Java:
public static void scrollToElementByElement(WebElement element) {
Coordinates coordinates = ((Locatable)element).getCoordinates();
coordinates.inViewPort();
coordinates.click(); //if needed
}
Then called on the method on my main test class
I have used below method to solve the problem of element not present in the visible area. The code scrolls down the webpage, till selenium operations can be performed on the element. Change the co ordinate of Y-axis and value of i as per requirement.
public void scrooling(By ele) throws InterruptedException {
for (int i = 0; i < 10; i++) {
try {
driver.findElement(ele);
break;
} catch (ElementNotVisibleException e) {
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("window.scrollBy(0,400)");
System.out.println("inside ElementNotVisibleException block");
Thread.sleep(3000);
} catch (NoSuchElementException e) {
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("window.scrollBy(0,400)");
System.out.println("inside NoSuchElementException block");
Thread.sleep(3000);
}
}
}