I'm upgrading a C# program that was using Selenium 3. After updating Selenium to version 4, I get this error
The type or namespace name 'ChromeMobileEmulationDeviceSettings' could not be found
using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
...
var chromeMobileEmulationDeviceSettings = new ChromeMobileEmulationDeviceSettings(userAgentString)
{
Width = width,
Height = height
};
var chromeOptions = new ChromeOptions();
chromeOptions.EnableMobileEmulation(chromeMobileEmulationDeviceSettings);
chromeOptions.AddArguments("headless");
_webDriver = new ChromeDriver(chromeOptions);
_webDriver.Manage().Window.Maximize();
I don't see any mention in the docs, etc., of that class being deprecated.
I want to force the 'browser' to have a very specific height/width when it is opened.
I've seen related answers here
How do I set browser width and height in Selenium WebDriver?
But I have a similar concern about setting the size before instantiating the driver, and also those answers are 'old', so what is best practice for doing this in Selenium 4?
You can replace ChromeMobileEmulationDeviceSettings with ChromiumMobileEmulationDeviceSettings. The name just updated.
I am trying to mouse hover on an element using Action class and then trying to go to other sub element and click, but my mouse hover is pointing some where else.
These are the IE capability which are set for IE and action class code
InternetExplorerOptions options = new InternetExplorerOptions();
options.enablePersistentHovering();
options.ignoreZoomSettings();
driverinstance = new InternetExplorerDriver(options);
WebDriverWait myWaitVar = new WebDriverWait(driver, const_waithigh);
myWaitVar.until(ExpectedConditions.elementToBeClickable(By.xpath(element1)));
Actions action = new Actions(driver.get());
action.moveToElement(driver.findElement(By.xpath(element1))).click().build().perform();
Even if you ignore zoom using options.ignoreZoomSettings(); IE doesn't calculate the correct position of the element unless your application is fully maximized and zoomed at 100%.
so use the below code once you initialize the driver instance for IE.
driver.manage().window().maximize();
driver.findElement(By.tagName('html')).sendKeys(Keys.chord(Keys.CONTROL, "0"));
We are essentially maximizing the window and pressing CTRL+0 to set to the zoom to default level. See if this fixes your issue.
org.openqa.selenium.WebDriverException: Element is obscured (WARNING: The server did not provide any stacktrace information).
This code is working fine for chrome and firefox but not with edge browser.
`public class Login {
public WebDriver driver;
By userName = By.id("ctl14_UserName");
By password = By.id("ctl14_Password");
By login = By.id("ctl14_LoginButton");
public Login(WebDriver driver) {
this.driver = driver;
}
// Set password in username textbox
public void setUserName(String strUserName) {
driver.findElement(userName).sendKeys(strUserName);
}
// Set password in password textbox
public void setPassword(String strPassword) {
driver.findElement(password).sendKeys(strPassword);
}
public void clickMyaccount(){
driver.findElement(myAccount).click();
}
// Click on login button
public void clickLogin() {
driver.findElement(login).click();
}
}
//Test class
public class AdminLogin extends BaseForDifferentLogins {
Login objLoginAdmin;
#Test(priority=0)
public void login() throws InterruptedException{
objLoginAdmin=new Login(driver);
objLoginAdmin.clickMyaccount();
Thread.sleep(3000);
objLoginAdmin.setUserName("superuser1");
objLoginAdmin.setPassword("superuser1");
Thread.sleep(3000);
objLoginAdmin.clickLogin();
Thread.sleep(3000);
}
}`
Instead of using webElement.click() you can try to build Actions with click and do perform. Had the same issue on Edge and that did the trick for me:
Actions actions = new Actions(webDriver);
actions.click(webElement).perform();
I have encountered the issue and tried several things to solve it:
enabled EdgePageLoadStrategy.Normal - did not help;
disabled the "save your password?" bubble. - did not help;
normalized the zoom level to 100% - bingo / eureka. This solved the issue.
My test script is a bit more performance-oriented, so I had no desire to add additional objects / capabilties / options. If you want your test to be more deployable add registry editing capabilities to your selenium script. This can be a starter: http://www.winhelponline.com/blog/microsoft-edge-disable-zoom-reset-zoom-level-every-start/
I encountered the same issue on the Edge browser.
It was difficult to figure out what was actually wrong, since the issue seemed to appear/disappear from time to time in my case.
So at some point I decided to contact MS and created this ticket question
Here Steven K mentioned that the obscured element error is most likely due to zoom level not being at 100% So I checked and indeed it was at 125% for some reason.
After I set it back to 100% the issue was resolved for me.
browser.send_keys [:control, '0']
I know this is a ruby+watir example, but I'm sure there is a similar Java trick for this.
I have also encountered this problem while testing Angular with Protractor in Microsoft Edge.
What finally helped me was combining two workarounds:
Set browser zoom value to 100% explicitly in beforeEach function:
browser.actions().keyDown(protractor.Key.CONTROL).sendKeys('0')
.keyUp(protractor.Key.CONTROL).perform();
Do click through browser actions:
browser.actions().mouseMove(yourElementThatIsNotActuallyObscured).click().perform();
Resetting Zoom level to 100% will fix the issue.
public void clickUntillNotObsecured(WebElement elementToClick) {
boolean obsecuredThrown = true;
int c=0;
while (obsecuredThrown && c<30) {
try {
clickOnElement(elementToClick);
obsecuredThrown = false;
} catch (WebDriverException e) {
obsecuredThrown = true;
}
c++;
}
}
You can perform the task with the Action chains in the python specially with Edge browser:
from selenium.webdriver import ActionChains
actionChains = ActionChains(driver)
button_xpath = '//xapth...'
button = driver.find_element_by_xpath(button_xpath)
actionChains.move_to_element(button).click().perform()
But sometimes Action chain does not finds the DOM element. Hence better option to use execute_script in following way which is compatible with all browsers:
button_xpath = '//xapth...'
button = driver.find_element_by_xpath(button_xpath)
driver.execute_script("arguments[0].click();", button)
Even I faced same problem today running tests on Edge, But when I observed the problem, after which step it's failing just check it up, after that step give a time delay of 5 to 10 seconds, by doing this it solved my problem. And i got the same error many times while running in Edge at different part of my program, i just added time delay at all those steps, it solved my problem and now test successfully running on EDGE.
I added delay by using
Thread.sleep(5000);
just try this, if it doesn't work for you, I found one other solution if it's failing at the time of clicking, that is perform click operation using javascript.
WebElement element = driver.findElement(By.id("gbqfd"));
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", element);
This solution I got from
https://softwaretestingboard.com/qna/363/word-around-for-edge-driver-click
https://softwaretestingboard.com/qna/745/excpetion-selenium-webdriverexception-element-obscured
First one worked for me.
Is there a way to get Selenium WebDriver to take screenshot only of the visible part of the page for PhantomJS? I've browsed the source and there is no API AFAICT. So is there a trick to do that somehow?
EDIT: Chrome already snaps only visible part, so removed it as part of question.
According to the JavaDoc API for TakesScreenshot a WebDriver extending TakesScreenshot will make a best effort to return the following in order of preference:
Entire page
Current window
Visible portion of the current frame
The screenshot of the entire display containing the browser
As PhantomJS is a headless browser it probably doesn't have menus/tabs and other similar browser chrome. So all you can control is the Dimension of the browser window.
// Portrait iPhone 6 browser dimensions
Dimension dim = new Dimension(375, 627);
driver.manage().window().setSize(dim);
Taking a screenshot will most likely capture the entire page. If you want to restrict your resulting file to the dimensions you requested you could always
crop it to your required dimensions (not ideal but PhantomJS is not a real browser).
private static void capture(String url, WebDriver driver, Dimension dim, String filename) throws IOException{
driver.manage().timeouts().implicitlyWait(30, TimeUnit.SECONDS);
driver.manage().window().setSize(dim);
driver.get(url);
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
int w = dim.getWidth();
int h = dim.getHeight();
Image orig = ImageIO.read(scrFile);
BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
bi.getGraphics().drawImage(orig, 0, 0, w, h, 0, 0, w, h, null);
ImageIO.write(bi, "png", new File(filename));
}
You can use robot class for this as belows
Robot rb=new Robot();
rb.keyPress(KeyEvent.VK_ALT);
rb.keyPress(KeyEvent.VK_PRINTSCREEN);
rb.keyRelease(KeyEvent.VK_PRINTSCREEN);
rb.keyRelease(KeyEvent.VK_ALT);
Once you have copied the screenshot on clipboard then u can save it to file.
WebDriver driver = new FirefoxDriver(); driver.get("http://www.google.com/");
File scrFile = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
FileUtils.copyFile(scrFile, new File("c:\\tmp\\screenshot.png"));
Is there a way to get the on-screen coordinates of HTML window (page body) with Selenium WebDriver?
Seen this a few times and haven't found an elegant solution from WebDriver yet (they have a param that looks to support in in their ILocatable settings but the method is not implemented yet).
What I do is use UIAutomation to get the windows AutomationElement and use a treewalker to find the actual object of the window - downside is I noticed the browsers occasionally update what their window is so the conditionals have to change every once in awhile to accommodate.
Here is some example code (I removed some company code here so it's more elegant on my end but this should work for C#)
public static Rectangle GetAbsCoordinates(this IWebElement element)
{
var driver = GetDriver(element);
var handle = GetIntPtrHandle(driver);
var ae = AutomationElement.FromHandle(handle);
AutomationElement doc = null;
var caps = ((RemoteWebDriver) driver).Capabilities;
var browserName = caps.BrowserName;
switch (browserName)
{
case "safari":
var conditions = (new AndCondition(new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Pane),
new PropertyCondition(AutomationElement.ClassNameProperty, "SearchableWebView")));
doc = ae.FindFirst(TreeScope.Descendants, conditions);
break;
case "firefox":
doc = ae.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Document));
break;
case "chrome":
doc = ae.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "Chrome Legacy Window"));
if (doc == null)
{
doc = ae.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "Google Chrome"));
if (doc == null)
throw new Exception("unable to find element containing browser window");
doc = doc.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Document));
}
break;
case "internet explorer":
doc = ae.FindFirst(TreeScope.Descendants, new AndCondition(new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Pane),
new PropertyCondition(AutomationElement.ClassNameProperty, "TabWindowClass")));
break;
}
if (doc == null)
throw new Exception("unable to find element containing browser window");
var iWinLeft = (int) doc.Current.BoundingRectangle.Left;
var iWinTop = (int)doc.Current.BoundingRectangle.Top;
var coords = ((ILocatable) element).Coordinates;
var rect = new Rectangle(iWinLeft + coords.LocationInDom.X, iWinTop + coords.LocationInDom.Y, element.Size.Width, element.Size.Height);
return rect;
}
public static IWebDriver GetDriver(this IWebElement e)
{
return ((IWrapsDriver)e).WrappedDriver;
}
public static IntPtr GetIntPtrHandle(this IWebDriver driver, int timeoutSeconds = Timeout)
{
var end = DateTime.Now.AddSeconds(timeoutSeconds);
while(DateTime.Now < end)
{
// Searching by AutomationElement is a bit faster (can filter by children only)
var ele = AutomationElement.RootElement;
foreach (AutomationElement child in ele.FindAll(TreeScope.Children, Condition.TrueCondition))
{
if (!child.Current.Name.Contains(driver.Title)) continue;
return new IntPtr(child.Current.NativeWindowHandle);;
}
}
return IntPtr.Zero;
}
The posted code by Zechtitus is amazing, I tried it under IE11 and Chrome Version 39.0.2171.95 m and it worked like a charm. Although I had to pass the real object of IWebDriver instead of using WrappedDriver because it doesn't work with Chrome. Just for your info, I have Win 7 ultimate x64 and using Selenium WebDriver 2.44. this is the code that I took it from Zechtitus and modified it:
public static Rectangle GetAbsCoordinates(IWebDriver driver, IWebElement element)
{
var handle = GetIntPtrHandle(driver);
var ae = AutomationElement.FromHandle(handle);
AutomationElement doc = null;
var caps = ((RemoteWebDriver)driver).Capabilities;
var browserName = caps.BrowserName;
switch (browserName)
{
case "safari":
var conditions = (new AndCondition(new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Pane),
new PropertyCondition(AutomationElement.ClassNameProperty, "SearchableWebView")));
doc = ae.FindFirst(TreeScope.Descendants, conditions);
break;
case "firefox":
doc = ae.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Document));
break;
case "chrome":
doc = ae.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "Chrome Legacy Window"));
if (doc == null)
{
doc = ae.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.NameProperty, "Google Chrome"));
if (doc == null)
throw new Exception("unable to find element containing browser window");
doc = doc.FindFirst(TreeScope.Descendants, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Document));
}
break;
case "internet explorer":
doc = ae.FindFirst(TreeScope.Descendants, new AndCondition(new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Pane),
new PropertyCondition(AutomationElement.ClassNameProperty, "TabWindowClass")));
break;
}
if (doc == null)
throw new Exception("unable to find element containing browser window");
var iWinLeft = (int)doc.Current.BoundingRectangle.Left;
var iWinTop = (int)doc.Current.BoundingRectangle.Top;
var coords = ((ILocatable)element).Coordinates;
var rect = new Rectangle(iWinLeft + coords.LocationInDom.X, iWinTop + coords.LocationInDom.Y, element.Size.Width, element.Size.Height);
return rect;
}
public static IntPtr GetIntPtrHandle(this IWebDriver driver, int timeoutSeconds = 20)
{
var end = DateTime.Now.AddSeconds(timeoutSeconds);
while (DateTime.Now < end)
{
// Searching by AutomationElement is a bit faster (can filter by children only)
var ele = AutomationElement.RootElement;
foreach (AutomationElement child in ele.FindAll(TreeScope.Children, Condition.TrueCondition))
{
if (!child.Current.Name.Contains(driver.Title)) continue;
return new IntPtr(child.Current.NativeWindowHandle); ;
}
}
return IntPtr.Zero;
}
and I used it like this:
Rectangle recView = GetAbsCoordinates(MyWebDriverObj, myIWebElementObj);
the correct X, Y are then stored in recView.X and recView.Y
As I said, it's working for me for both IE11 and Chrome.
Good luck
hmmm, I cannot directly comment to the one user asking about chrome so I will have to add another comment here.
Basically for UIAutomation you will want to get your hands on a tool called inspect (comes free in the 8.1 SDK). Older tools like uispy would probably work as well.
Basically you would fire up chrome and then fire up the inspector tool - your going to look at the tree like structure and then navigate down to the document which contains the DOM. Turn on highlighting in the tool to make this easier.
Chrome is quite dynamic it seems in the layout of the tree controls - have had to modify it a few times to accomodate the control I am looking at. If your using a different version than I had - basically find the document window in the tree and take a look at all of the control patterns associated with it - this is what I am passing into the PropertyCondition for how to search for the control. Intellisense should bring you up different things to query for like AutomationElement.NameProperty. It the example I had - I noticed there is a difference between when I run chrome on a winXP machine vs a win8 machine... hence the checking for null.
Like I have said before - this is not elegant and would be awesome if it was inbuilt into Selenium (I imagine they have much better methods for determining the coords of the DOM area)... I think this will also be problematic for people moving to Selenium Grid (like I am looking at doing) - far as I know with using it I don't know if you can shuttle over a bunch of supporting dll to selenium to the remote machine... at least without a lot of hacks.
If it still doesn't work for you - give me a specific idea on the OS, Chrome version and I'll try to take a look and give exact Property match. Probably best though if you fiddle yourself as these things are not static unfortunately.
Yes. Its possible. With little trick. Find below my code to get on
screen top position of web element.
public static long getScrollYPosition() {
WebDriver driver = DriverFactory.getCurrentDriver();
JavascriptExecutor jse = (JavascriptExecutor) driver;
Long scrollYPos = (Long) jse.executeScript("return window.scrollY;");
return scrollYPos;
}
long scrollPosition = getScrollYPosition();
long elemYPositionOnScreen = (long) elem.getLocation().getY() - scrollPosition;
you can try in this way:
WebDriver driver=new FirefoxDriver();
driver.get("http://www.google.com");
JavascriptExecutor js=(JavascriptExecutor) driver;
Double i= (Double) js.executeScript("var element = document.getElementById('hplogo');var position = element.getBoundingClientRect();return position.left");
System.out.print(i);
I took a quick look at chrome and you may have better luck with the following.
doc = win.Find.ByConditions(new PropertyCondition(AutomationElement.ClassNameProperty, "Chrome_RenderWidgetHostHWND"));
I think that class name is consistent for chrome... seems to work on older and newer OS's for me - chrome version 34.0.1847.116m. Hope that helps.
This should work once it's supported:
WebElement htmlElement = driver.findElement(By.tagName("html"));
Point viewPortLocation = ((Locatable) htmlElement).getCoordinates().onScreen();
int x = viewPortLocation.getX();
int y = viewPortLocation.getY();
However right now it's throwing the following error:
java.lang.UnsupportedOperationException: Not supported yet.
at org.openqa.selenium.remote.RemoteWebElement$1.onScreen(RemoteWebElement.java:342)
(on org.seleniumhq.selenium:selenium-java:2.46.0)
I needed a this in Robot Framework and I was inspired by Jeyabal's solution, so here is an adaptation that works for me:
${verticalWindow}= Execute Javascript return window.scrollY;
${verticalElement} = Get Vertical Position /xpath
${hasScrolled} = Evaluate (${verticalElement} - ${verticalWindow}) == 0
Nothing from above worked for me. A workaround is to use window.innerHeight and window.innerWidth and work your way up from the the left, bottom corner. This assumes that the browser bottom border is almost 0 (no horizontal scrollbar or thick window decoration).
win_pos = selenium.get_window_position()
win_size = selenium.get_window_size()
win_bottom_y = win_pos['y'] + win_size['height']
# We assume viewport x == window x. For y coordinate we take the bottom
# of the browser and subtract the viewport height
viewport_height = selenium.execute_script('return window.innerHeight')
viewport_width = selenium.execute_script('return window.innerWidth')
viewport_y = win_bottom_y - viewport_height
This is not 100% accurate but it's a good workaround that can be tweaked for your case.
SOOO many factors have to be considered to get the element position relative to the screen. For the longest time I was using the UIAutomation code above, but UIAutomation is unreliable, it crashes or fails to find the browser (for some reason), with EdgeDriver, tabs crash consistently making getting the values via UIAutomation now as a 'fallback'.
That said, when it works, the answer is GOLDEN as to the on-screen coordinates of the HTML page.
However, something that always works is using javascript. So we calculate that first, then also attempt to call UIAutomation. If UIAutomation fails, we use this code's answer. If UIAutomation works, we use the UIAutomation values.
// use javascript to get our html document location, but it's off by 2 pixels compared to uiautomation. uiautomation, however, failed so often that is was unreliable
int outerHeight = Int32.Parse(BrowserHelper.ExecuteJavascript(browser, "return window.outerHeight"));
int innerHeight = Int32.Parse(BrowserHelper.ExecuteJavascript(browser, "return window.innerHeight"));
int outerWidth = Int32.Parse(BrowserHelper.ExecuteJavascript(browser, "return window.outerWidth"));
int innerWidth = Int32.Parse(BrowserHelper.ExecuteJavascript(browser, "return window.innerWidth"));
int browserNavHeight = outerHeight - innerHeight;
int browserNavWidth = outerWidth - innerWidth;
iWinLeft = browserNavWidth + 2;
iWinTop = browserNavHeight + 2;
`
Try this, I hope it will help you :
Rectangle rec = new Rectangle(element.getLocation(), element.getSize());