I am using Selenium 3.4 with Java. With Chrome, everything works fine. But I need to use Firefox, and there something breaks.
I am automating the testing of a Dojo UI, and need to wait while the Dojo UI does a lot of rendering. So here is what I do, and it works just fine in Chrome. Note that an implicit wait of 20 seconds is normally set in my code.
driver.switchTo().defaultContent();
driver.switchTo().frame(driver.findElement(By.id("contentframe"))); // relying on implicit wait
driver.manage().timeouts().implicitlyWait(0, TimeUnit.SECONDS);
(new WebDriverWait(driver, 120)).
until(ExpectedConditions.elementToBeClickable(By.id("some_id")));
I have simplified the code so you don't see how the implicit wait is set back to 20 seconds. When the problem happens, it does not get there, anyway. The WebDriverWait causes an exception. The exception says TypeError: can't access dead object
There is a corresponding message from inside the wait:
May 16, 2017 3:36:11 PM org.openqa.selenium.support.ui.ExpectedConditions findElement
WARNING: WebDriverException thrown by findElement(By.id:
some_id)
org.openqa.selenium.WebDriverException: TypeError: can't access dead object
There is also some JavaScript error output, apparently, by geckodriver:
JavaScript error: chrome://marionette/content/listener.js, line 1555: TypeError: can't access dead object
*************************
A coding exception was thrown and uncaught in a Task.
Full message: TypeError: can't access dead object
Full stack: find_#chrome://marionette/content/element.js:284:7
element.find/</findElements<#chrome://marionette/content/element.js:255:15
implicitlyWaitFor/</elementSearch#chrome://marionette/content/element.js:600:15
implicitlyWaitFor/<#chrome://marionette/content/element.js:627:5
implicitlyWaitFor#chrome://marionette/content/element.js:593:10
element.find/<#chrome://marionette/content/element.js:254:24
element.find#chrome://marionette/content/element.js:253:10
findElementsContent#chrome://marionette/content/listener.js:1314:19
TaskImpl_run#resource://gre/modules/Task.jsm:319:42
TaskImpl#resource://gre/modules/Task.jsm:277:3
createAsyncFunction/asyncFunction#resource://gre/modules/Task.jsm:252:14
Task_spawn#resource://gre/modules/Task.jsm:166:12
TaskImpl_handleResultValue#resource://gre/modules/Task.jsm:389:16
TaskImpl_run#resource://gre/modules/Task.jsm:327:15
TaskImpl#resource://gre/modules/Task.jsm:277:3
createAsyncFunction/asyncFunction#resource://gre/modules/Task.jsm:252:14
Task_spawn#resource://gre/modules/Task.jsm:166:12
dispatch/<#chrome://marionette/content/listener.js:186:15
*************************
*************************
A coding exception was thrown and uncaught in a Task.
Full message: TypeError: can't access dead object
Full stack: find_#chrome://marionette/content/element.js:284:7
element.find/</findElements<#chrome://marionette/content/element.js:255:15
implicitlyWaitFor/</elementSearch#chrome://marionette/content/element.js:600:15
implicitlyWaitFor/<#chrome://marionette/content/element.js:627:5
implicitlyWaitFor#chrome://marionette/content/element.js:593:10
element.find/<#chrome://marionette/content/element.js:254:24
element.find#chrome://marionette/content/element.js:253:10
findElementsContent#chrome://marionette/content/listener.js:1314:19
TaskImpl_run#resource://gre/modules/Task.jsm:319:42
TaskImpl#resource://gre/modules/Task.jsm:277:3
createAsyncFunction/asyncFunction#resource://gre/modules/Task.jsm:252:14
Task_spawn#resource://gre/modules/Task.jsm:166:12
TaskImpl_handleResultValue#resource://gre/modules/Task.jsm:389:16
TaskImpl_run#resource://gre/modules/Task.jsm:327:15
TaskImpl#resource://gre/modules/Task.jsm:277:3
createAsyncFunction/asyncFunction#resource://gre/modules/Task.jsm:252:14
Task_spawn#resource://gre/modules/Task.jsm:166:12
dispatch/<#chrome://marionette/content/listener.js:186:15
Moreover, my automatic exception processing tries to take a screenshot but that fails with the very same error. The code line is:
File snapshotTempFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
And this time the output from geckodriver is:
A coding exception was thrown and uncaught in a Task.
Full message: TypeError: can't access dead object
Full stack: capture.viewport#chrome://marionette/content/capture.js:65:7
takeScreenshot#chrome://marionette/content/listener.js:1782:14
dispatch/</req<#chrome://marionette/content/listener.js:188:22
TaskImpl_run#resource://gre/modules/Task.jsm:319:42
TaskImpl#resource://gre/modules/Task.jsm:277:3
createAsyncFunction/asyncFunction#resource://gre/modules/Task.jsm:252:14
Task_spawn#resource://gre/modules/Task.jsm:166:12
dispatch/<#chrome://marionette/content/listener.js:186:15
So, can I do anything to make this work properly? And is this something I need to raise as a geckodriver bug?
The only thing I could google out is this: https://github.com/mozilla/geckodriver/issues/614 and the only proposed solution there is driver.switchTo().defaultContent() . This might fix my screenshot routine, but the element I am waiting for is inside the content frame, so I can't use this fix for the wait.
Not sure if this will help you but when I ran into this error message, I was able to get past it by having:
driver.switchTo().defaultContent();
driver.switchTo().frame(0);
between each interaction with an element in the iframe.
Example:
driver.switchTo().frame(0);
myPage.selectElement(getCycleSummary());
driver.switchTo().defaultContent();
driver.switchTo().frame(0);
myPage.selectDisplayedElement(this.getCycleBtn());
Without the driver switches I would receive the dead object error.
It looks like the frame is reloaded with a new reference while you are waiting for the element some_id.
I would classify this issue as a bug since the error returned by the driver is not defined by the WebDriver protocol.
Your best chance to make it work is probably to implement a custom waiter to locate the frame/element and skip unhandled exceptions:
WebElement elem = waiter.Until(elementToBeClickableInFrame(By.id("contentframe"),
By.id("some_id")));
public static ExpectedCondition<WebElement> elementToBeClickableInFrame(final By locatorFrame, final By locator) {
return new ExpectedCondition<WebElement>() {
#Override
public WebElement apply(WebDriver driver) {
try {
driver.switchTo().defaultContent();
driver.switchTo().frame(driver.findElement(locatorFrame));
WebElement elem = driver.findElement(locator);
return elem.isDisplayed() && elem.isEnabled() ? elem : null;
} catch (Exception e) {
return null;
}
}
#Override
public String toString() {
return "element located by: " + locator + " in " + locatorFrame;
}
};
}
See,
There Should be a format which i am giving below:
First switch to frame. (Switch to default first in case already you are in another frame).
Perform your action (click on any element)
Switch to default content again. (if you do not switch it back, it creates problem).
driver.switchTo().defaultContent();
driver.switchTo().frame(locator or name of the frame);
driver.click(your element locator);
driver.switchTo().defaultContent();
Related
I'm attempting to create an ArrayList of WebElements from this page:
If all the elements are displayed, they're able to be added to the ArrayList just fine.
ArrayList<WebElement> TodoArray = new ArrayList<WebElement>();
TodoArray.add(todo1);
If I remove one of the elements from the web page(not code) I get this error when running my Test Case:
org.openqa.selenium.NoSuchElementException: Unable to locate element: *[name='todo[9]']
Is there any way to bypass this error and force java to skip the missing element, but continue adding the elements that are displayed?
My code is pretty straight forward. I'm using JUnit to run my test cases. The elements are defined correctly using the #FindBy annotations.
#FindBy(name="todo[1]")
WebElement todo1;
I tried surrounding the variables with Try/Catch and using NoSuchElementException, but I wasn't sure how to format it. Is using the "continue" keyword possible in this situation?
Hopefully I provided enough information. Any help would be appreciated. Thank you!
The exact syntax for Java Try/Catch would be this for you:
try {
#FindBy(name="todo[1]")
WebElement todo1;
}
catch(NoSuchElementException e) {
System.out.println("could not find element todo1");
}
...
//rest of your code
Does this help?
Or you can use fluent wait, this way:
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(10, SECONDS)
.pollingEvery(1, SECONDS)
.ignoring(NoSuchElementException.class);
I think this is a more elegant way to do it.
This is an odd variety of a common problem.
I am running a Selenium project using a headless firefox browser.
I get the common NoSuchElementExceptions. That's nothing new. However, attempting to resolve them through explicit waits does not resolve the issue.
For example, the following line throws the NoSuchElementException:
WebElement trackingInbox = methodDriver.findElement(By.id("inbox-widget-container-id"));
I then add the following above this line:
FluentWait wait = new FluentWait(methodDriver);
wait.withTimeout(90, TimeUnit.SECONDS);
wait.pollingEvery(250, TimeUnit.MILLISECONDS);
wait.until(ExpectedConditions.presenceOfElementLocated(By.id("inbox-widget-container-id")));
WebElement trackingInbox = methodDriver.findElement(By.id("inbox-widget-container-id"));
In the first instance, I get the exception at the "methodDriver.findElement . . . ."
In the second instance I get it at the "wait.until . . . "
This happens when I wait for "presenceOf . . ." and when I wait for "visibilityOf . . ." The way it appears, the element has to be available before I wait for it, which appears to defeat the purpose.
The way it currently appears, I have no option but to add implicit waits, but I know there must be some way to do the explicit waits such that the element does not have to be available before I wait for it.
I wonder if there are any ideas as to what I am doing wrong and if there are any principles I can go by to determine whether a particular wait would be useful or not.
You have actually forgot to call ignoring function at the end, This ignoring is what you want. When you are waiting for visibility of the element, it might occur that element doesn't exist but If you use Ignoring function, it would ignore if such error happens until it meet with the given condition.
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, SECONDS)
.pollingEvery(5, SECONDS)
.ignoring(NoSuchElementException.class);
I am trying to select value from the drodown. this is my code.
driver.findElement(By.xpath(".//*[#id='accountSelectContainer']/span/a/span[1]")).click();
driver.findElement(By.xpath("//ul[#id='ui-id-1']/li/a[equals(text(),'60091 - AFCENT')]")).click();
Now here i have hardcoded the value, which works perfect but i am reading my testdata from excel file . so instead of using direct hard code values , i want to declare my testdata in xpath and read it from excel file. so i tried to this:
Efforts
public void combobox(String testData)
{
driver.findElement(By.xpath(".//*[#id='accountSelectContainer']/span/a/span[1]")).click();
driver.findElement(By.xpath("//ul[#id='ui-id-1']/li/a[equals(text(),'"+testData+"')]")).click();
}
But i am getting the exception
org.openqa.selenium.InvalidSelectorException: invalid selector: Unable
to locate an element with the xpath expression
//ul[#id='ui-id-1']/li/a[equals(text(),'60091 - AFCENT')] because of
the following error: SyntaxError: Failed to execute 'evaluate' on
'Document': The string '//ul[#id='ui-id-1']/li/a[equals(text(),'60091
- AFCENT')]' is not a valid XPath expression.
I tried to change it to "+testData+" too instead of using '"+testData+"'
But same exception.
I tried this code too:
driver.findElement(By.xpath(".//*[#id='accountSelectContainer']/span/a/span[1]")).click();
List<WebElement> options = driver.findElements(By.xpath("//ul[#id='ui-id-1']/li"));
for (WebElement option : options) {
if(testData.equals(option.getText()))
option.click();
}
which works perfect but after this code execution , it is making my browser to wait for about 15 secs before executing next step or for quit too. i am not getting Why so ?
Please need suggestion or any ideas..
I doubt your fast attempt works perfect as xpath doesn't have equals. You would have gotten the same exception. To check for text equality use =
"//ul[#id='ui-id-1']/li/a[text()='"+testData+"']"
You can also use contains
"//ul[#id='ui-id-1']/li/a[contains(text(),'"+testData+"')]"
First: the exception you have got is because you xpath: //ul[#id='ui-id-1']/li/a[equals(text(),'60091 - AFCENT')] is not correct syntax.
Second: the code that you can run is not make your browser wait for 15s, it's just because problem about internet connection or you computer is a little slow.
I'm trying to pick up the string returned from JavascriptExecutor called from Java (the first time I've ever used it). I've seen several other posts on SO but they all stop before you get the string into Java.
Searching the internet, everybody says this should work:
JavascriptExecutor js =(JavascriptExecutor) driver;
js.executeScript("return document.title");
String CatchS = js.toString();
System.out.println("Output from javascript:" + CatchS);
but all that I get is Output from javascript:FirefoxDriver: firefox on XP (506d8fd0-0ce2-4693-8e56-2166a77a5136)
Which is exactly the same as you get from JavascriptExecutor if you feed it deliberately invalid JavaScript (i.e. this is it not working).
I've also tried the alternatives suggested in Get Value from ExecuteScript from JavaScriptExecutor, and even tried just returning 'hello world'. Nothing works. What am I missing?
I need it to return a string as that is what the real code I'm trying to insert will do (once it's working). Thank you.
When I execute the following
String CatchS = (String) js.executeScript("return document.title");
I get an exception of
Exception in thread "main" java.lang.Error: Unresolved compilation problem: Type mismatch: cannot convert from Object to String.
I'm trying to automate a task through selenium that deletes a set of database tables.
The corresponding code is
WebElement element=null;
while((element = driver.findElement(By.name("db__button"))) != null){
driver.findElement(By.name("db__button")).click();
driver.findElement(By.name("ConfirmButton")).click();
}
However I'm getting the following error:-
org.openqa.selenium.NoSuchElementException: Unable to locate element: {"method":"name","selector":"db_vaults__button"}
For documentation on this error, please visit: http://seleniumhq.org/exceptions/no_such_element.html
This runs fine as long as there are tables in the database but when there are no tables left then the GUI doesn't show any list (rightly so) and db__button is not present on the page and therefore By.name("db__button") is failing.
I guess there is something missing in this code which is trying to delete some tables in a loop.
The suggested link in the stack trace doesn't has any information.
Any Ideas?
Thanks.
You can do something like mentioned below:
try {
element = driver.findElement(By.name("db__button"));
driver.findElement(By.name("db__button")).click();
driver.findElement(By.name("ConfirmButton")).click();
} catch (NoSuchElementException e) {
}
The above code will try to find your button and in case it is not found will throw an exception.You can write code(if any) inside the catch block when the element(db_button) is not found.
There are several options. I recommend these.
Create a method or web driver extension as below an use it.
var elements = driver.FindElements(by);
return (elements.Count >=1) ? elements.First() : null;