Reputation: 802
I am a newbie in selenium. I am trying to run a suite on Stack overflow website with the below code. The code generates NoSuchElement exception. I am using selenium java client and server (3.7.1) with Chrome Driver (2.33). Using Java 9. On windows 10.
I have validated the css selector using the find feature on Chrome developer tools.
What could be the problem?
public class Suite {
private static final String home = "https://stackoverflow.com";
private WebDriver driver = null;
public static void main(String[] args) {
Suite suite = new Suite(true);
suite.login()
.clickByCSSSelector("a.my-profile");
}
public Suite(boolean isHeadLess) {
ChromeOptions option = new ChromeOptions();
if (isHeadLess) option.addArguments("--headless");
System.setProperty("webdriver.chrome.driver", "D:\\work\\webscraping\\chromedriver\\chromedriver.exe");
driver = new ChromeDriver(option);
}
public Suite login() {
this.navigate(home)
.setValue("email", "[email protected]")
.setValue("password", "xxxxxx")
.click("submit-button");
return this;
}
public Suite navigate(String target) {
driver.navigate().to(target);
return this;
}
public Suite setValue(String elementId, String value) {
driver.findElement(By.id(elementId)).sendKeys(value);
return this;
}
public Suite clickByXpath(String xpath) {
this.findByXpath(xpath).click();
return this;
}
public Suite clickByCSSSelector(String selector) {
this.findByCSSSelector(selector).click();
return this;
}
private WebElement findByCSSSelector(String selector) {
return driver.findElement(By.cssSelector(selector));
}
public WebElement findByXpath(String xpath) {
return this.find(By.xpath(xpath));
}
public WebElement find(By element) {
return driver.findElement(element);
}
public Suite click(String elementId) {
this.find(elementId).click();
return this;
}
public WebElement find(String elementId) {
return this.find(By.id(elementId));
}
}
Exception:
Exception in thread "main" org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"css selector","selector":"a.my-profile"}
(Session info: headless chrome=62.0.3202.94)
(Driver info: chromedriver=2.33.506120 (e3e53437346286c0bc2d2dc9aa4915ba81d9023f),platform=Windows NT 10.0.14393 x86_64) (WARNING: The server did not provide any stacktrace information)
Command duration or timeout: 0 milliseconds
For documentation on this error, please visit: http://seleniumhq.org/exceptions/no_such_element.html
Build info: version: '3.7.1', revision: '8a0099a', time: '2017-11-06T21:01:39.354Z'
System info: host: 'HMECL000593', ip: '10.0.75.1', os.name: 'Windows 10', os.arch: 'amd64', os.version: '10.0', java.version: '9'
Driver info: org.openqa.selenium.chrome.ChromeDriver
Capabilities {acceptSslCerts: true, applicationCacheEnabled: false, browserConnectionEnabled: false, browserName: chrome, chrome: {chromedriverVersion: 2.33.506120 (e3e53437346286..., userDataDir: C:\Users\TOMS~1.VAR\AppData...}, cssSelectorsEnabled: true, databaseEnabled: false, handlesAlerts: true, hasTouchScreen: false, javascriptEnabled: true, locationContextEnabled: true, mobileEmulationEnabled: false, nativeEvents: true, networkConnectionEnabled: false, pageLoadStrategy: normal, platform: XP, platformName: XP, rotatable: false, setWindowRect: true, takesHeapSnapshot: true, takesScreenshot: true, unexpectedAlertBehaviour: , unhandledPromptBehavior: , version: 62.0.3202.94, webStorageEnabled: true}
Session ID: fa8665d6bf99e34431e27b91ec3a1458
*** Element info: {Using=css selector, value=a.my-profile}
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:488)
at org.openqa.selenium.remote.ErrorHandler.createThrowable(ErrorHandler.java:214)
at org.openqa.selenium.remote.ErrorHandler.throwIfResponseFailed(ErrorHandler.java:166)
at org.openqa.selenium.remote.http.JsonHttpResponseCodec.reconstructValue(JsonHttpResponseCodec.java:40)
at org.openqa.selenium.remote.http.AbstractHttpResponseCodec.decode(AbstractHttpResponseCodec.java:80)
at org.openqa.selenium.remote.http.AbstractHttpResponseCodec.decode(AbstractHttpResponseCodec.java:44)
at org.openqa.selenium.remote.HttpCommandExecutor.execute(HttpCommandExecutor.java:164)
at org.openqa.selenium.remote.service.DriverCommandExecutor.execute(DriverCommandExecutor.java:83)
at org.openqa.selenium.remote.RemoteWebDriver.execute(RemoteWebDriver.java:600)
at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:370)
at org.openqa.selenium.remote.RemoteWebDriver.findElementByCssSelector(RemoteWebDriver.java:464)
at org.openqa.selenium.By$ByCssSelector.findElement(By.java:430)
at org.openqa.selenium.remote.RemoteWebDriver.findElement(RemoteWebDriver.java:362)
at com.tv.webscraping.selenium.SeleniumClient.findByCSSSelector(SeleniumClient.java:81)
at com.tv.webscraping.selenium.SeleniumClient.clickByCSSSelector(SeleniumClient.java:76)
at com.tv.webscraping.selenium.Suite.main(Suite.java:19)
Chrome Develper tools:
Upvotes: 0
Views: 1434
Reputation: 56
You can also add implicit wait after get(url) shown below. It works throughout script for all elements and waits for page to load. Its good practise to use implicit wait once at the start.
driver.get(url); driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
Try this one instead of explicit wait suggested above. And even after using implicit wait, if you get ElementNotVisibleException then add explicit wait for that particular web element.
But using implicit wait will generally help you giving load time for all elements throughout your script.
Hope it helps.
Upvotes: 0
Reputation: 287
You may also need to include a wait prior to your click
WebDriverWait wait = new WebDriverWait(webDriver, timeoutInSeconds);
wait.until(ExpectedConditions.visibilityOfElementLocated(By.id<locator>));
See more information for Waits here: WebDriver - wait for element using Java
If this doesn't work, try the following xpath instead, in combination with the wait above .clickByXpath("//a[contains(@class, 'my-profile')]");
Some more information below to explain xpaths:
//div[@class='class' and contains(text(), 'text')]
//span[contains(class, 'class')]
//input[starts-with(@name,'input')
These are more beneficial when handling dynamic elements and will be robust.See more information for xpaths here: https://sqa.stackexchange.com/questions/10342/how-to-find-element-using-contains-in-xpath
Please note: I'd only advise using xpaths when an element is either dynamic, or has no unique ID
Additionally, you could use classname rather then xpath, and example of how I do this in c# is driver.FindElement(By.ClassName("my-profile js-gps-track");
If all the above does not work, you may require the use of actions, something like the below:
Actions actions = new Actions(driver);
actions.moveToElement(driver.findElement(By.id(id)));
actions.click();
actions.build().perform();
Upvotes: 2