The current page is https://www.nintendo.co.uk/Games/Games-347085.html
I've run a Selenium test with driver.findElement for div.row-page-container and it works fine
but when I try to get the price value by going further into the red line below for the page-info I can't find how to access the class, it logs: org.openqa.selenium.NoSuchElementException: no such element
How can I get the price value, while avoiding XPath if possible?
Not sure why you do not want to have XPath.
But in case if you are looking for XPath based on Game name, that can get you it's price. You can use the below XPath
//p[text()='Animal Crossing: New Horizons']//following-sibling::p[#class='price-small']//span[#data-price]
or the below CSS should suffice as well
a[href*='Animal-Crossing-New-Horizons'] > p.price-small > span:nth-child(2)
It is based on href Animal-Crossing-New-Horizons
First of all using the correct xpath is an important step to remove the the NoSuchElementException.The xpath for identifying the element is
//p[text()='Animal Crossing: New Horizons']//following-sibling::p[#class='price-small']//span[#data-price]
Even if this doesn’t identify then there might be some timing issues with the webpage i.e.
the page is still being rendered and you've already finished your element search and obtained no element exception.
You can use FluentWait to overcome this problem.
Let’s say you have an element which sometimes appears in just 1 second and sometimes it takes minutes to appear. In that case it is better to define an explicit wait using FluentWait, as this will try to find an element again and again until it finds it or until the final timer runs out.
An instance of FluentWait can be defined to configure the maximum amount of time to wait for a condition as well as the frequency at which the condition must be checked.User can also configure the wait to ignore specific types of exceptions while waiting for an element, such as NoSuchElementExceptions on the page.
// Waiting 30 seconds for an element to be present on the page, checking
// for its presence once every 5 seconds.
Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)
.withTimeout(30, SECONDS);
.pollingEvery(5, SECONDS) ;
.ignoring(NoSuchElementException.class);
Adding explicit wait might also do the trick:
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;
. . .
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement element = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("element_xpath"))); element.click();
Related
I have an element on a web page that is updated by AJAX almost immeditely after page load. I know what I expect the change to be and want Selenium to wait for the change and capture it. I am trying to use an explicit wait for this. However, I am getting a timeoutException as Selenium is not detecting the change.
I know I am properly selecting the element and value as I have used print statements. I've solved the issue using
Java Thead.sleep(1000)
and then using
driver.findElement(By.id("balance-sms")).getText()
but this is not an acceptable solution.
private void modalSend(String newBalence){
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.elementToBeClickable(modalSendButton)); //this wait works fine
modalSendButton.click(); //this results in a page refresh
//now check for the AJAX change to this element...normally takes about 1 second
wait.until(ExpectedConditions.textToBePresentInElement(driver.findElement(By.id("balance-sms")),newBalence));
//continue...
}
Try the locator using xpath and visibilityOfElementLocated with a few modifications :
//now check for the AJAX change to this element...normally takes about 1 second
wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[#id='balance-sms' and contains(text(),'" +newBalence +"')]")));
//continue...
Try with fluent wait like below instead of Thread.sleep
Wait wait = new FluentWait(WebDriver reference)
.withTimeout(timeout, SECONDS)
.pollingEvery(timeout, SECONDS)
.ignoring(Exception.class);
I am new to selenium (but experienced java developer).
I am using something like below:
WebElement searchBasket = pDriver.findElement(By.xpath("//a[contains(.,'Search&Baskets')]"));
WebElement searchproduct = pDriver.findElement(By.xpath("//a[contains(.,'Search a product')]"));
//if search an agreement is not show up, then click on other menu, then click it back
pWait.until(ExpectedConditions.elementToBeClickable(By.xpath("//a[contains(.,'Search&Baskets')]")));
pDriver.findElement(By.xpath("//a[contains(.,'Search&Baskets')]")).click();
// click on search an agreement
try {
pWait.until(ExpectedConditions.elementToBeClickable(By.xpath("//a[contains(.,'Search&Baskets')]")));
action = new Actions(pDriver);
action.moveToElement(searchBasket).build().perform();
pWait.until(ExpectedConditions.elementToBeClickable(By.xpath("//a[contains(.,'Search a product')]")));
searchproduct.click();
} catch (TimeoutException e) {
}
where pWait is:
WebDriverWait wait = new WebDriverWait(driver, 15);
however when I run the test case I get below error:
Unable to locate element: {"method":"xpath","selector":"//a[contains(.,'Search&Baskets')]"}
Command duration or timeout: 4 milliseconds
I thought it should have wait atleast 15 seconds before throwing this exception. From the log above it looks like it threw exception only in 4ms.
and i could see on console that as soon as it hit that line, it threw exception.
I have implicit waiting set as 0 and using explicit wait.
Am i missing anything here.
Also, in explicit and implicit wait, is it upto that much time OR exact that much time,
example if I set implicit wait as 10 sec, then does it mean wait for exact 10 sec OR wait upto 10 sec (if element found then proceed, even if element founf on 6th second)
is above same for explicit wait as well?
Please help
Let us analyze what is happening in our code.
We have defined two WebElements searchBasket and searchproduct as follows :
WebElement searchBasket = pDriver.findElement(By.xpath("//a[contains(.,'Search&Baskets')]"));
WebElement searchproduct = pDriver.findElement(By.xpath("//a[contains(.,'Search a product')]"));
We havn't tried to use those WebElements in our code at immediate basis, so had No Impact.
Next, we tried WebDriverWait for an WebElement as follows :
pWait.until(ExpectedConditions.elementToBeClickable(By.xpath("//a[contains(.,'Search&Baskets')]")));
Again we didn't capture the return type of the result, so had No Impact.
Now, within the try{} block we have again tried WebDriverWait:
pWait.until(ExpectedConditions.elementToBeClickable(By.xpath("//a[contains(.,'Search&Baskets')]")));
But again we havn't captured/acted on the return type of the result. That's why moving ahead when we did :
action.moveToElement(searchBasket).build().perform();
searchBasket referred to the WebElement which we have stored earlier as :
WebElement searchBasket = pDriver.findElement(By.xpath("//a[contains(.,'Search&Baskets')]"));
As this first search result (which was without WebDriverWait) may not have returned any WebElement at all and have returned Null.
Finally, the most important factor for the error Unable to locate element: {"method":"xpath","selector":"//a[contains(.,'Search&Baskets')]"} is, the
WebDriverWait instance was wait. Instead of using wait we have always tried to use pWait
So for all these reasons, WebDriverWait was never implemented properly in our code.
Mixing up ImplicitWait & ExplicitWait
The Selenium Documentation clearly mentions the following :
WARNING: Do not mix implicit and explicit waits. Doing so can cause unpredictable wait times. For example setting an implicit wait of 10 seconds and an explicit wait of 15 seconds, could cause a timeout to occur after 20 seconds.
ExpectedConditions.elementToBeClickable invokes isDisplayed() and isEnabled() methods on EXISTING WebElement.
You are providing By as a parameter which means, the driver has to find your element first. It failed to do this.
Make sure your element is present by using wait until presenceOfElementLocatedBy(By by).
Example:
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.presenceOfElementLocatedBy(By.xpath("//a[contains(.,'Search&Baskets')]")));
wait.until(ExpectedConditions.elementToBeClickable(By.xpath("//a[contains(.,'Search&Baskets')]")));
Here I have the image of my code and the image of my error. Can anyone help me to resolve this issue?
ElementNotInteractableException
ElementNotInteractableException is the W3C exception which is thrown to indicate that although an element is present on the HTML DOM, it is not in a state that can be interacted with.
Reasons & Solutions :
The reason for ElementNotInteractableException to occur can be numerous.
Temporary Overlay of other WebElement over the WebElement of our interest :
In this case, the direct solution would have been to induce ExplicitWait i.e. WebDriverWait in combination with ExpectedCondition as invisibilityOfElementLocated as folllows:
WebDriverWait wait2 = new WebDriverWait(driver, 10);
wait2.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("xpath_of_element_to_be_invisible")));
driver.findElement(By.xpath("xpath_element_to_be_clicked")).click();
A better solution will be to get a bit more granular and instead of using ExpectedCondition as invisibilityOfElementLocated we can use ExpectedCondition as elementToBeClickable as follows:
WebDriverWait wait1 = new WebDriverWait(driver, 10);
WebElement element1 = wait1.until(ExpectedConditions.elementToBeClickable(By.xpath("xpath_of_element_to_be_clicked")));
element1.click();
Permanent Overlay of other WebElement over the WebElement of our interest :
If the overlay is a permanent one in this case we have to cast the WebDriver instance as JavascriptExecutor and perform the click operation as follows:
WebElement ele = driver.findElement(By.xpath("element_xpath"));
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click();", ele);
I got this because the element I wanted to interact with was covered by another element. In my case it was an opaque overlay to make everything r/o.
When trying to click an element UNDER another element we usualy get "... other Element would receive the click " but not always :.(
This Exception we get when the element is not in an interactable state. So we can use wait till the element is Located or become clickable.
Try using the Implicit wait:
driver.manage().timeouts().implicitlyWait(Time, TimeUnit.SECONDS);
If this is not working use Explicit wait:
WebDriverWait wait=new WebDriverWait(driver, 20);
WebElement input_userName;
input_userName = wait.until(ExpectedConditions.elementToBeClickable(By.tagName("input")));
input_userName.sendkeys("suryap");
You can use ExpectedCondition.visibilityOfElementLocated() as well.
You can increase the time, for example,
WebDriverWait wait=new WebDriverWait(driver, 90);
A solution to this for Javascript looks like this. You will have to modify the time to suit your need.
driver.manage().setTimeouts({ implicit: 30000 });
Hope this is helpful to someone.
see the docs for reference
Actually the Exception is Element Not Visible
The best practice is to use Implicit wait below driver Instantiation so it get sufficient time to find element throughout the exception
driver.get("http://www.testsite.com");
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
Still facing issue as some element require more time. Use ExplicitWait for individual element to satisfy certain condition
In your case you are facing element not visible exception then use wait condition in following way-
WebDriverWait wait = new WebDriverWait(driver, 120);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.your_Elemetnt));
In my case issue was because there is some animation, and that element is not visible for some duration. And hence exception was occurring.
For some reason I couldn't make ExpectedConditions.visibilityOfElementLocated work, so I created a code to wait for some hardcoded seconds before proceeding.
from selenium.webdriver.support.ui import WebDriverWait
def explicit_wait_predicate(abc):
return False
def explicit_wait(browser, timeout):
try:
Error = WebDriverWait(browser, timeout).until(explicit_wait_predicate)
except Exception as e:
None
And now I am calling this explicit_wait function wherever I want to wait for sometime e.g.
from selenium import webdriver
from selenium.webdriver.common.by import By
browser = webdriver.Safari()
browser.get('http://localhost')
explicit_wait(browser,5) # This will wait for 5 secs
elem_un = browser.find_element(By.ID, 'userName')
i have the following issue, after perform the login, the system load the main page, its like 5 seconds doing it, so after that, the script should type over 3 fields and perform a tab to get more info, but the thing is that sometimes is working and sometimes does not, in 5 chances, only one worked, i do not know if its something about the time to get all fields or something like that, am using IE 9 cause the app only works on IE
Here´s the code:
`
System.setProperty("webdriver.ie.driver","C:\\Apps\\eclipse\\IEDriverServer.ex;
WebDriver driver = new InternetExplorerDriver();
driver.get("http://15.192.41.95/Cabina/asp/Login.asp");
WebElement text1 = driver.findElement(By.id("text1"));
text1.sendKeys("xxxx");
WebElement password1 = driver.findElement(By.id("password1"));
password1.sendKeys("xxxx");
WebElement aceptar = driver.findElement(By.id("ok1"));
aceptar.click();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.switchTo().frame(driver.findElement(By.name("menu")));
WebElement txtNumPolSol = driver.findElement (By.id("txtNumPolSol"));
txtNumPolSol.sendKeys("877885");
WebElement Text8 = driver.findElement(By.name("txtNumofic"));
Text8.sendKeys("228");
WebElement txtCveInc = driver.findElement(By.name("txtCveInc"));
txtCveInc.sendKeys("1");
WebElement clave = driver.findElement(By.id("txtCveInc"));
clave.sendKeys(Keys.TAB);
driver.switchTo().frame(driver.findElement(By.name("dest")));
WebElement txtNomrepo = driver.findElement(By.id("txtNomrepo"));
txtNomrepo.sendKeys("Jorge Villarreal");
driver.findElement(By.id("txtRelacion")).sendKeys("Conductor");
WebElement txtTelrepo = driver.findElement(By.id("txtTelrepo"));
txtTelrepo.sendKeys("83029090");`
Here the different issues i got:
1) Unable to find element with name == txtOficina
2) Element is no longer valid
3) Unable to find element with id == txtCveInc (the field is there)
4) Unable to find element with name == txtCveInc (the field is there)
The steps that the system to get the issues are:
1) Log in (so far so good)
2) The system load the main page (the page has frames and gets all fields in 5 secs...)
3) The script type over the txtNumPolSol, txtNumofic and txtCveInc (most of the issues are in the last two fields)
4) The script performs a tab
5) The system load the some information regarding the record and the script continue...
Note: Almost all the issues occur on step 3...
Thanks for your feedback!
This sounds like a timing problem. Your simulated user is proceeding faster than the page becomes ready. Depending on the timing of the page loading, different problems occur.
The solution is to add a wait after steps that trigger a DOM change than influences your next step, but doesn't cause WebDriver to wait before returning. Google 'webdriver wait for element' to get lots of ways to do it.
I was also facing the similar kind of problem but i tried to find the elements with Css_Selectors and X paths instead of ids, that worked for me
The key here is to add atleast 1 second of implicit wait after every action, i.e. send keys etc. It will allow 'driver.findElement' enough time to find the element. Though I would suggest keeping this code in a testBase or a reusable method.
driver.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS);
It will help in making your webtests less flaky.
I'm using webdriver(java) for a unique test where a page reloads itself when you log on, I've been unable to wait for the element to load because it is already there before the reload. So far the only way I've been able to get it to work is to use a thread.sleep, is there a way to listen for a page refresh?
One way to solve this is, to get a reference to the element you need, that appears both on the login-page and the reloaded page.
Then you can use the ExpectedConditions.stalenessOf to occur, and then you can be sure, that the element is removed from the DOM and a new element is created. Well, the last part is not guaranteed by this method, but at least you know that the old element is gone.
The code could look something like this:
WebElement elementOldPage = driver.findElement(By.id("yourid"));
... do login etc ...
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.stalenessOf(elementOldPage));
WebElement elementNewPage = driver.findElement(By.id("yourid"));
Building upon the accepted answer from Kim Schiller one might be interested in the following piece of code. It is surely not perfect due to the sleeps, so be free to suggest improvements to make it more bulletproof. Also note I'm no expert with selenium.
The if branch waits for the top level node in the html to go stale in case of a page reload. The else branch simply waits until the drivers url matches the request url in case we load a different page.
def safe_page_load(url):
if driver.current_url == url:
tmp = driver.find_element_by_xpath('/html')
driver.get(url)
WebDriverWait(driver, 2).until(ExpectedConditions.staleness_of(tmp))
else:
driver.get(url)
while(driver.current_url) != url:
sleep(0.3)
sleep(0.3)
Happy if I could help someone.