I want to use a WebElement as a root to find elements from instead of the driver. I know this is possible since the WebElement and WebDriver both extends the SearchContext class. But I want to be able to have a search that looks like this.
WebDriver chromeDriver = new ChromeDriver();
WebDriver driver = chromeDriver;
// Set a new search root
public void setSearchRoot(){
if(i want a element as a root){
this.driver = (WebDriver)this.driver.findElement(By.xpath("PATH"));
}else{
this.driver = chromeDriver;
}
}
//find a element
public void findMyElement(){
this.driver.findElement(By.xpath("PATH"));
}
instead of something like this
WebDriver driver = new ChromeDriver();
WebDriver rootElement = this.driver.findElement(By.xpath("PATH"));
//find a element
public void findMyElement(){
if(i want a element as a root){
this.rootElement.findElement(By.xpath("PATH"));
}else{
this.driver.findElement(By.xpath("PATH"));
}
}
It might look a bit messy but basically I want to be able to set a WebElement as a starting point instead of a WebDriver without having to do a if statement or have two different methods whenever I want to get a element. Because sometimes I want to use the WebDriver as a root and sometimes a Webelement and this without having to change anything with the get code. is it possible somehow? And yes I am aware that this might not be best practice, just wondering if it's possible.
using OpenQA.Selenium.Support.UI;
if element is a type of ISearchContext or IWebElement
then this cast worked for me
var driver = ((IWrapsDriver)element).WrappedDriver;
No, WebElement and WebDriver are not descendants of each other.
If your IWebElement happens to be a RemoteWebElement, then you can get the IWebDriver with
var remoteElement = (RemoteWebElement)element;
var webDriver = remoteElement.WrappedDriver;
If you only need to use the "root" to find elements under it and not to do other WebDriver specific stuff (like navigation or managing options or timeouts) you can use SearchContext instead of WebDriver.
Your code would look like this:
WebDriver chromeDriver = new ChromeDriver();
SearchContext driver = chromeDriver; // Use SearchContext instead of WebDriver
// Set a new search root
public void setSearchRoot() {
if(i want a element as a root) {
this.driver = this.driver.findElement(By.xpath("PATH")); // No cast needed
} else {
this.driver = chromeDriver;
}
}
//find a element
public void findMyElement() {
this.driver.findElement(By.xpath("PATH"));
}
I noticed in my own projects that I often had methods expecting a parameter of type WebDriver when really it only called findElements on it. By changing the type to SearchContext my utilities became a lot more flexible.
public WebElement findMyElement(SearchContext webDriver) {
return webDriver.findElement(By.xpath("PATH"));
}
Use it like this:
WebDriver webDriver = new ChromeDriver();
WebElement customElement = findMyElement(webDriver);
WebElement nestedElement = findMyElement(customElement);
Related
I have tried all the methods including xpath but I am still not able to click on the Accept button on cookies popup on https://www.news.sky.com
Tried css selector, xpath, frame etc everything.
Here is my code:
public class Browser {
WebDriver driver;
public void browser_open() {
String projectPath = System.getProperty("user.dir");
System.setProperty("webdriver.chrome.driver", projectPath+"\\Drivers\\chromedriver\\chromedriver.exe");
driver = new ChromeDriver();
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
driver.manage().timeouts().pageLoadTimeout(30, TimeUnit.SECONDS);
}
public void navigate() throws InterruptedException {
driver.get("http://news.sky.com");
//Thread.sleep(5000);
driver.switchTo().frame("sp_message_iframe_368417");
driver.findElement(By.xpath("/html/body/div/div[3]/div[3]/button[1]")).click();
}
}
Please can someone help me on this?
I have already gone through a lot of posts on this and other forums but couldn't find an solution.
Thanks
I would suggest the xpath of //button[#title='Accept'] for what it's worth.
It's possible the switch to doesn't work because the element doesn't exist yet in the frame.
driver.switchTo().frame("sp_message_iframe_368417");
WebDriverWait wait = new WebDriverWait(driver, 10000);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//button[#title='Accept']")));
driver.findElement(By.xpath("//button[#title='Accept']")).click();
This is my HomePage of Page Object where I created WebElement of UserName method and now want to call it in test case case but it not working.
Showing me the error on element line.
public class HomePage {
WebDriver driver;
By username = By.xpath("/html[1]/body[1]/form[1]/table[1]/tbody[1]/tr[1]/td[2]/input[1]");
By password = By.xpath("/html[1]/body[1]/form[1]/table[1]/tbody[1]/tr[2]/td[2]/input[1]");
By login = By.xpath("/html[1]/body[1]/form[1]/table[1]/tbody[1]/tr[3]/td[2]/input[1]");
static WebElement element = null;
//Experiment with webelement
public static WebElement UserName(WebDriver driver) {
element.findElement(By.xpath("/html[1]/body[1]/form[1]/table[1]/tbody[1]/tr[1]/td[2]/input[1]"));
return element;
}
public static WebElement Password(WebDriver driver) {
element.findElement(By.xpath("/html[1]/body[1]/form[1]/table[1]/tbody[1]/tr[2]/td[2]/input[1]"));
return element;
}
public static WebElement ClickLogin(WebDriver driver) {
element.findElement(By.xpath("/html[1]/body[1]/form[1]/table[1]/tbody[1]/tr[3]/td[2]/input[1]"));
return element;
}
}
These are the code of test class
//objLogin = new HomePage();
HomePage objLogin = new HomePage();
//input the username, password and click login.
objLogin.UserName(driver).sendKeys("mngr279645");
objLogin.Password(driver).sendKeys("YzarAzy");
objLogin.ClickLogin(driver).click();
Any help will be appreciated.....
First of all I don't understand why would you need WebDriver driver as you parameter in every selector when you are no using it and it shouldn't be there.
And second I suggest you study more of a PageObject architecture and using Xpath in general. In your comment above I still cannot see error message being shown.
By changing the scope in pom.xml from test to compile . It's Worked for me
I have a problem with Selenium tests for Java when using standalone-webdriver-firefox docker image v.2.53.0. The problem is when I want insert text to input with placehoder. And this placehoder sometimes appear or not. I tried clean input before insert text but the result was the same. I increased wait time but that not help. When I using APIwebdriver this problem not appear.
These are my methods
#FindBy(how = How.XPATH, using = "//input[contains(#id, 'redirect-uri')]")
private List<WebElement> inputTextRedirectUriElements;
public EdEnvironmentPage enterRedirectUri(String redirectUri) {
WebElement webElement = inputTextRedirectUriElements.get(inputTextRedirectUriElements.size() -1);
webElement.sendKeys(redirectUri);
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].blur(); return true", webElement);
WaitUtil.waitUntilPageIsLoaded(driver);
return this;
}
public EdEnvironmentPage enterRedirectUriWithoutHttps(String redirectUri) {
WebElement webElement = inputTextRedirectUriElements.get(inputTextRedirectUriElements.size() -1);
webElement.clear();
webElement.sendKeys(redirectUri);
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("arguments[0].blur(); return true", webElement);
WaitUtil.waitUntilPageIsLoaded(driver);
return this;
}
WaitUtil
public static void waitUntilPageIsLoaded(WebDriver driver) {
new WebDriverWait(driver, 30).until(ExpectedConditions.and(
ExpectedConditions.presenceOfElementLocated(By.id("loading-completed")),
ExpectedConditions.invisibilityOfElementLocated(By.className("loader"))
));
}
Problem resolve change selenium version to 2.53.1
I am trying to learn Selenium from Youtube. I have written the simple code below on Frames. I want to click on linkText which is not visible but manually can scroll and click on it. I am trying with the below code but getting the error:
org.openqa.selenium.WebDriverException: unknown error: Element is not clickable
My code:
public class Frame_Test {
WebDriver driver;
#Test
public void test1() {
System.setProperty("webdriver.chrome.driver", "C:\\chromedriver_win32\\chromedriver.exe");
ChromeOptions options = new ChromeOptions();
options.addArguments("--start-maximized");
driver = new ChromeDriver(options);
driver.get("http://seleniumhq.github.io/selenium/docs/api/java/index.html");
driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS);
driver.switchTo().frame("packageListFrame");
driver.findElement(By.linkText("org.openqa.selenium.safari")).click();
}
}
You can scroll down with screen height using this code:
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript("window.scrollTo(0, document.body.scrollHeight);");
Scrolling down for some number of pixels:
js.executeScript("scroll(0, 300);");
Scrolling up for some number of pixels:
js.executeScript("scroll(0, -300);");
Hope it helps you!
You can use the below method:
public static void scrollToElement(By elementToken, WebDriver driver){
WebElement element = driver.findElement(elementToken);
((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", element);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Or if you don't want to use the explicit method you can use the scroll code in your code:
driver.get("http://seleniumhq.github.io/selenium/docs/api/java/index.html";
driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS);
driver.switchTo().frame("packageListFrame");
WebElement element = driver.findElement(By.linkText("org.openqa.selenium.safari"));((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView(true);", element);
driver.findElement(By.linkText("org.openqa.selenium.safari")).click();
I am using Java and Selenium to write a test. I have a drop down menu from which I need to select something. This is my code:
Select s= new Select(driver.findElement(By.xpath("blabla")));
s.selectByVisibleText("theName");
it works on Chrome but on Firefox 47 I get this error:
org.openqa.selenium.ElementNotVisibleException:
Element is not currently visible and so may not be interacted with
I know how to handle selecting from drop down menu by other ways, but I need to use Select object.
Use fluent wait to wait element, chrome is faster:
public static void waitUntilElementIsVisible(WebElement element, WebDriver driver)
{
FluentWait<WebDriver> wait = new FluentWait<WebDriver>(driver);
wait.pollingEvery(250, TimeUnit.MILLISECONDS);
wait.withTimeout(2, TimeUnit.MINUTES);
wait.ignoring(ElementNotVisibleException.class); //make sure that this exception is ignored
Function<WebDriver, WebElement> function = new Function<WebDriver, WebElement>()
{
public WebElement apply(WebDriver driver) {
System.out.println("Checking for the element!!");
if(element.isDisplayed() != true)
{
System.out.println("Target element is not visible");
}
return element;
}
};
wait.until(function);
}
Then you can call it:
WebElement el = driver.findElement(By.xpath("blabla"));
waitUntilElementIsVisible(el, driver);
You can use the WebDriverWait class to wait for the visibility of the element like this:
WebDriverWait wait = new WebDriverWait(driver, customTime);
WebDriver driver = new FirefoxDriver();
Select s = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("blabla")));
s.selectByVisibleText("theName");