I am automating amazon.com, and I am currently trying to move to a specific element in a drop down menu. No matter how specific I make my xpath for this element, WebDriver will only move the mouse to the first item in the list.
Here is the HTML code:
<div class="nav-template nav-flyout-content nav-tpl-itemList">
<span class="nav-hasPanel nav-item" data-nav-panelkey="InstantVideoPanel" role="navigation" aria-label="Amazon Video">
<span class="nav-text">Amazon Video</span>
</span>
<span class="nav-hasPanel nav-item" data-nav-panelkey="DigitalMusicPanel" role="navigation" aria-label="Amazon Music">
<span class="nav-text">Amazon Music</span>
</span>
<span class="nav-hasPanel nav-item" data-nav-panelkey="AndroidPanel" role="navigation" aria-label="Appstore for Android">
<span class="nav-text">Appstore for Android</span>
</span>
Here is my automation code:
#Test
public void departmentsDropMusic1() throws Exception {
driver = new FirefoxDriver();
driver.get("https://www.amazon.com");
Thread.sleep(3000L);
WebElement element = driver.findElement(By.xpath("//a[#id='nav-link-shopall']"));
Actions action = new Actions(driver);
action.moveToElement(element).build().perform();
Thread.sleep(3000L);
WebElement dropDown = driver.findElement(By.cssSelector("#nav-flyout-shopAll > div:nth-child(2)"));
if (dropDown.isDisplayed()) {
System.out.println("pass");
} else {
Assert.fail();
}
WebElement musicSubMenu = driver.findElement(By.xpath(//span[contains(text(), 'Amazon Music')]"));
action.moveToElement(musicSubMenu).build().perform();
Thread.sleep(3000L);
I have tried other xpaths as well, using the various labels provided in the html code, to no avail. WebDriver will only move to the first element (aria-label "Amazon Video"), and not the other elements listed.
Interestingly enough, when I use a for-loop to move through all of the items in the menu, there are no issues.
It is moving to first element in the dropdown as all elements of sub categories are loading when we move to first element in the list.
To overcome this, we need to move to the first element before moving to any other elements in the list. I have created one method to solve your issue. If you pass the sub menu name than it will move over on the sub menu.
The code is given below.
#Test
public void departmentsDropMusic1() throws Exception {
System.setProperty("webdriver.gecko.driver", "C:\\Projects\\SeleniumDrivers\\geckodriver.exe");
driver = new FirefoxDriver();
driver.get("https://www.amazon.com");
Thread.sleep(5000L);
openSubMenu("Amazon Music");
openSubMenu("Fire TV");
}
The open sub menu method code is here,
public void openSubMenu(String menu) throws InterruptedException{
//mouse over on Main menu 'Departments'
WebElement element = driver.findElement(By.xpath("//a[#id='nav-link-shopall']"));
Actions action = new Actions(driver);
action.moveToElement(element).build().perform();
Thread.sleep(5000L);
//verify sub menus are listed or not
WebElement dropDown = driver.findElement(By.cssSelector("#nav-flyout-shopAll"));
if (dropDown.isDisplayed()) {
System.out.println("pass");
} else {
Assert.fail();
}
//
WebElement subMenu1 = driver.findElement(By.cssSelector("#nav-flyout-shopAll > div.nav-tpl-itemList>span:nth-child(1)"));
WebElement subMenuWantedToOpen = driver.findElement(By.cssSelector("#nav-flyout-shopAll > div.nav-tpl-itemList>span[aria-label='"+menu.trim()+"']"));
action.moveToElement(subMenu1).moveToElement(subMenuWantedToOpen).build().perform();
Thread.sleep(5000L);
WebElement subMenuCat = driver.findElement(By.cssSelector(".nav-subcats > div.nav-subcat[style='display: block;']"));
if(subMenuCat.isDisplayed()){
System.out.println(subMenuCat.getText());
}
}
It is working fine for me. Check and let me know if any difficulties.
When you are automating the large sites like amazon.com, please be sure that the element has no child node, when you try to inspect it through firebug, and some times it depends on the browser itself make sure you are using latest web browser version.
Related
I tried to implement a logout test method through selenium in Spring Boot but I cannot detect dropdown menu located top right hand side.
How can I fix it?
Here is the test method shown below.
#Test
#Order(4)
public void logout() throws InterruptedException {
login();
driver.get("https://github.com");
Thread.sleep(1000);
// Header-item position-relative mr-0 d-none d-md-flex
WebElement profileDropdown = driver.findElement(By.cssSelector(".Header-item.position-relative.mr-0.d-none.d-md-flex")); // cannot work
// dropdown-item dropdown-signout
WebElement signOutButton = driver.findElement(By.cssSelector(".dropdown-item.dropdown-signout")); // cannot work
profileDropdown.click();
Thread.sleep(1000);
signOutButton.click();
}
Here is the error part shown below
java.net.SocketException: Connection reset
org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"css selector","selector":".dropdown-item.dropdown-signout"}
1st Edited
String xpathProfile = "//*[#aria-label='View profile and more']";
WebElement profileDropdown = driver.findElement(By.xpath(xpathProfile));
String xpathSignOut = "//button[contains(#class,'dropdown-signout')]";
WebElement signOutButton = driver.findElement(By.xpath(xpathSignOut));
I got this issue shown below.
org.openqa.selenium.NoSuchElementException: no such element: Unable to locate element: {"method":"xpath","selector":"//button[contains(#class,'dropdown-signout')]"}
This is a bad practice to try to locate elements like this, you should be more specific. Given this DOM that you are working with I would try using a selector somewhat like this:
String xpathProfile = "//*[#aria-label='View profile and more']";
String xpathSignOut = "//button[contains(#class,'dropdown-signout')]";
As you can see it's an xpath type selector and I would recommend learning xpath as it is far more readable once you get used to it and it also works in a few edge cases where you wouldn't be able to use css selector.
Also I've noticed that if you make the window size smaller, at some point the profile button you are trying to click is hidden in github, so maybe that is why your button is not getting clicked. You could try setting a specific bigger window size using chromeOptions:
ChromeOptions options = new ChromeOptions();
options.addArgument("--window-size=1920,1080");
ChromeDriver driver = new ChromeDriver(options);
Can you actually see the button when the test is running?
Here is the answer shown below
public void logout() throws InterruptedException {
login();
driver.get("https://github.com");
Thread.sleep(1000);
// Header-item position-relative mr-0 d-none d-md-flex
WebElement profileDropdown = driver.findElement(By.cssSelector(".Header-item.position-relative.mr-0.d-none.d-md-flex"));
profileDropdown.click();
Thread.sleep(1000);
// dropdown-item dropdown-signout
WebElement signOutButton = driver.findElement(By.cssSelector(".dropdown-item.dropdown-signout"));
signOutButton.click();
Thread.sleep(2000);
}
I am doing pagination on the web page. In which 20 account has been load on the page and after clicking the button again another 20 account has been loaded. After third click button disappeared from the web page and all accounts has been loaded. But I am getting below error:
"org.openqa.selenium.StaleElementReferenceException: stale element reference: element is not attached to the page document"
Below is the code:
public static WebDriver driver;
public static List<WebElement> tarif;
public static Actions action;
public static boolean flag;
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
tarif = driver.findElements(By.xpath("//button[contains(text(),'tarife')]"));
flag = true;
while(flag) {
System.out.println(flag);
System.out.println(tarif.size());
if (tarif.size() > 0) {
//try {
Actions action = new Actions(driver);
action.moveToElement(tarif.get(0)).build().perform();
Thread.sleep(5000);
tarif.get(0).click();
} else {
flag = false;
}
}
Thread.sleep(5000);
driver.quit();
Can you all please help me regarding above?
Stale element exception means element is there on web page but selenium could not interct that element , there are 2 ways to resolve that
1.Try with page refresh(driver.navigate().refresh();)
2.Just use loop element until click that element
I am trying to click "Radio Button" which is inside iFrame. I tried to switch iFrame but facing issues.
I have tried to identify in which iFrame my Element lies but facing error as No such Frame.
Sharing my Script, which navigate to the page where I am facing issue clicking on any of the Radio Button.
WebDriver driver;
JavascriptExecutor jse;
public static void main(String[] args)
{
Sap_Demo demoObj = new Sap_Demo();
demoObj.invokeBrowser();
demoObj.initializeSAPFiory();
demoObj.forecastMD61();
}
public void invokeBrowser()
{
System.setProperty("webdriver.chrome.driver", "U:\\Research Paper\\Selenium\\Drivers\\Chrome\\chromedriver_win32\\chromedriver.exe");
driver = new ChromeDriver();
driver.manage().deleteAllCookies();
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(40, TimeUnit.SECONDS);
driver.manage().timeouts().pageLoadTimeout(40, TimeUnit.SECONDS);
}
public void initializeSAPFiory()
{
try
{
Thread.sleep(1200);
driver.get("https://dijon.cob.csuchico.edu:8042/erp");
driver.findElement(By.id("USERNAME_FIELD-inner")).sendKeys("H4");
Thread.sleep(1200);
driver.findElement(By.id("PASSWORD_FIELD-inner")).sendKeys("Onsjhjsa1087");
Thread.sleep(1200);
driver.findElement(By.id("CLIENT_FIELD-inner")).clear();
Thread.sleep(1200);
driver.findElement(By.id("CLIENT_FIELD-inner")).sendKeys("485");
Thread.sleep(1200);
driver.findElement(By.xpath("//span[#class='sapMBtnContent sapMLabelBold sapUiSraDisplayBeforeLogin']")).click();
}
catch (InterruptedException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void forecastMD61()
{
try {
driver.findElement(By.id("erpsim-tcode-btn-img")).click();
Thread.sleep(1200);
driver.findElement(By.id("TCode-input-inner")).sendKeys("MD61");
Thread.sleep(1200);
driver.findElement(By.id("TCode-launchBtn-content")).click();
Thread.sleep(1200);
/*driver.switchTo().frame(driver.findElement(By.xpath("//span[#id='M0:46:::4:2-imgSymb']")));
driver.findElement(By.xpath("//span[#id='M0:46:::4:2-imgSymb']")).sendKeys("ABC");*/
//driver.manage().timeouts().implicitlyWait(40, TimeUnit.SECONDS);
//Thread.sleep(1600);
driver.switchTo().frame("ITSFRAME1");
WebDriverWait wait = new WebDriverWait(driver, 10);
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt("ITSFRAME1"));
//WebElement E1 = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("M0:46:::4:2-imgStd")));
WebElement E1 = driver.findElement(By.xpath("//span[#id='M0:46:::4:2-imgSymb']"));
E1.click();
//driver.findElement(By.id("M0:46:::4:2-imgStd")).click();
//driver.findElement(By.xpath("//span[#id='M0:46:::4:2-imgStd']")).click();
//Thread.sleep(1200);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
Receiving error as :
Exception in thread "main" org.openqa.selenium.NoSuchFrameException: no such frame
HTML Source:
for iframe:
<iframe id="ITSFRAME1" name="itsframe1_20190401041759.3908120" noresize="1" frameborder="0" framespacing="0" border="0" scrolling="no" onload="null" style="visibility: visible; z-index: 999; top: 0px; left: 0px;" src="javascript:(function(){document.open();document.domain='dijon.cob.csuchico.edu';self.frameElement.oWguHandlerItsMgrFrame.finalize(); })();"></iframe>
For Radio Buttons:
enter code here <span id="M0:46:::4:2-imgStd" class="lsRBImgStd lsCBImgStdDef lsCBImgStdDefHv"><span id="M0:46:::4:2-imgSymb" class="lsRBImgSymb lsRBImgSel"></span></span>
Here is my answer from a previous question on this. (Copy/Paste) It works 100% of the time (assuming you have JQuery available on the page; if not we can make an alternative):
So this is ultimately the perfect use case for an extension I made. Here is the most important part of it:
/// <summary>
/// Selenium sometimes has trouble finding elements on the page. Give it some help by using JQuery to grab the full qualified xpath to that element.
/// </summary>
/// <param name="cssSelector"></param>
/// <returns></returns>
public static string GetFullyQualifiedXPathToElement(string cssSelector, bool isFullJQuery = false, bool noWarn = false)
{
if (cssSelector.Contains("$(") && !isFullJQuery) {
isFullJQuery = true;
}
string finder_method = #"
function getPathTo(element) {
if(typeof element == 'undefined') return '';
if (element.tagName == 'HTML')
return '/HTML[1]';
if (element===document.body)
return '/HTML[1]/BODY[1]';
var ix= 0;
var siblings = element.parentNode.childNodes;
for (var i= 0; i< siblings.length; i++) {
var sibling= siblings[i];
if (sibling===element)
return getPathTo(element.parentNode)+'/'+element.tagName+'['+(ix+1)+']';
if (sibling.nodeType===1 && sibling.tagName===element.tagName)
ix++;
}
}
";
if(isFullJQuery) {
cssSelector = cssSelector.TrimEnd(';');
}
string executable = isFullJQuery ? string.Format("{0} return getPathTo({1}[0]);", finder_method, cssSelector) : string.Format("{0} return getPathTo($('{1}')[0]);", finder_method, cssSelector.Replace("'", "\""));
string xpath = string.Empty;
try {
xpath = BaseTest.Driver.ExecuteJavaScript<string>(executable);
} catch (Exception e) {
if (!noWarn) {
Check.Warn(string.Format("Exception occurred while building a dynamic Xpath. Css selector supplied to locate element is \"{0}\". Exception [{1}].", cssSelector, e.Message));
}
}
if (!noWarn && string.IsNullOrEmpty(xpath)) {
Check.Warn(string.Format("Supplied cssSelector did not point to an element. Selector is \"{0}\".", cssSelector));
}
return xpath;
}
With this logic, you can pass a Jquery selector into your browser via javascript executor. JQuery has no problems finding elements nested within iframes. Try something like this:
driver.FindElement(By.XPath(GetFullyQualifiedXPathToElement("#MyDeeplyNestedElement")).Click();
https://gist.github.com/tsibiski/04410e9646ee9ced9f3794266d6c5a82
Feel free to remove whatever is in that method/class that does not apply to your situation.
Why/How does this suddenly make an element findable to Selenium????
You may have noticed that if you tell selenium to find an iframe html element, and then explicitly search within the WebElement of the iframe, that you can find child elements under it. However, without first finding each child iframe, Selenium does not seem to look inside the iframes without you explicitly helping it through the DOM.
JQuery does not have this limitation. It sees every registered DOM element just fine, and will grab it normally. Once you have the element as a JQuery object, you can build out a path of tags, parent by parent, all the way up the DOM. When the logic is complete, you will have a fully-qualified XPath from the top of the DOM down to the nested child element. Then, once this explicit XPath is supplied to Selenium, you are holding its hand down the rabbit hole through one or more iframes until it runs into the object you want.
Try these...
driver.SwitchTo().DefaultContent();
IWebElement iframe = driver.FindElement(By.Id("ITSFRAME1"));
driver.SwitchTo().Frame(iframe);
public class Bwinbe {
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver", "mypath");
WebDriver driver = new ChromeDriver();
driver.get("http://test.www.bwin.be/");
WebDriverWait wait = new WebDriverWait(driver,20);
driver.findElement(By.id("login-overlay-button")).click();
driver.findElement(By.id("username")).sendKeys("passport3");
driver.findElement(By.id("password")).sendKeys("qwe123");
driver.findElement(By.id("submit")).click();
}
}
getting exception while running this. its not able to find the elements by name or id
You may be need to wait some times after clicking on login button. the following code may work for you.
public class Bwinbe {
public static void main(String[] args) {
System.setProperty("webdriver.chrome.driver", "mypath");
WebDriver driver = new ChromeDriver();
driver.get("http://test.www.bwin.be/");
WebDriverWait wait = new WebDriverWait(driver,20);
driver.findElement(By.id("login-overlay-button")).click();
wait.until(ExpectedConditions.elementToBeClickable(By.id("username")));
driver.findElement(By.id("username")).sendKeys("passport3");
driver.findElement(By.id("password")).sendKeys("qwe123");
driver.findElement(By.id("submit")).click();
}
}
As I saw page You are trying to automate, You are trying to login with button.
You should search by this element:
This is button html:
<a class="btn-s1" data-loading="Loading..." href="/en/authentication/loginoverlay" id="login-overlay-button" onclick="return false;" data-hasqtip="true" aria-describedby="qtip-0">LOG IN</a>
so try to search with
driver.findElement(By.className("btn-s1")).click();
then You have to switch to iFrame element to input username and password:
This is frame html:
<iframe id="bcx_local_storage_frame" src="https://assets.bounceexchange.com/assets/bounce/local_storage_frame9.min.html#2582" style="display: none;" kwframeid="1"></iframe>
command would be something like this:
driver.switchTo().frame("bcx_local_storage_frame");
and then rest of Your code
driver.findElement(By.id("username")).sendKeys("passport3");
driver.findElement(By.id("password")).sendKeys("qwe123");
driver.findElement(By.id("submit")).click();
Hope this helps,
Scenario:
Login to www.flipkart.com and choose "Samsung" from "Electronics" after successful login.
Now, I need to scroll to the bottom of the page and from the left side, I need click on Availability to choose the "Exclude out of stock option" but
on clicking Availability, I am getting the message
FAILED: Test_Samsung
org.openqa.selenium.WebDriverException: Element is not clickable at point (119, 9). Other element would receive the click: <div class="_1H5F__" data-reactid="10"></div>
Command duration or timeout: 133 milliseconds
//class for successful flipkart login
public class Flipkart_Login
{
#FindBy(xpath="//a[text()='Log In']") WebElement Login_Click;
#FindBy(xpath="//input[#class='_2zrpKA' and #type='text']") WebElement Enter_Email;
#FindBy(xpath="//input[#class='_2zrpKA _3v41xv' and #type='password']") WebElement Enter_Pass;
#FindBy(xpath="//button[#type='submit' and #class='_3zLR9i _1LctnI _36SmAs']") WebElement Login_Button;
#FindBy(xpath="//span[text()='Please enter valid Email ID/Mobile number']") WebElement Blank_Email;
#FindBy(xpath="//span[text()='Please enter Password']") WebElement Blank_Pass;
public void Valid_Login()
{
Login_Click.click();
Enter_Email.sendKeys("abc#gmail.com");
Enter_Pass.sendKeys("abcde");
Login_Button.click();
}
}
//class for choosing Samsung from Electronics menu and clicking Availability
public class Flipkart_Electronics_Samsung_Mobile
{
#CacheLookup
#FindBy(xpath="//a[#title='Electronics']//span[text()='Electronics']") WebElement Electronics_Menu;
#CacheLookup
#FindBy(xpath="//a[#title='Samsung']//span[text()='Samsung']") WebElement Samsung_Mobile_Click;
#CacheLookup
#FindBy(xpath="//div[#class='_3QT2gR _1AgMas']//div[text()='Availability']") WebElement Availability;
#CacheLookup
#FindBy(xpath="//div[#class='_1p7h2j']") WebElement Exclude_Out_Of_Stock;
public void Choose_Samsung_Mobile()
{
WebDriverWait wait = new WebDriverWait(driver, 30);
Actions act = new Actions(driver);
act.moveToElement(Electronics_Menu).perform();
act.click(wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//a[#title='Samsung']//span[text()='Samsung']")))).build().perform();
WebElement Availability = wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[#class='_3QT2gR _1AgMas']//div[text()='Availability']")));
JavascriptExecutor js = (JavascriptExecutor)driver;
js.executeScript("arguments[0].scrollIntoView(true);", Availability);
Availability.click();
}
}
//class which calls the methods from above two classes
public class Flipkart_Electronics_Samsung_Search
{
WebDriver driver;
#Test
public void Test_Samsung()
{
driver = BrowserFactory.getBrowser("Firefox");
driver.get(DataProviderFactory.getConfig().getURL());
Flipkart_Login login = PageFactory.initElements(driver, Flipkart_Login.class);
login.Valid_Login();
Flipkart_Electronics_Samsung_Mobile Samsung = PageFactory.initElements(driver, Flipkart_Electronics_Samsung_Mobile.class);
Samsung.Choose_Samsung_Mobile();
}
}
You can try to click using JavascriptExecutor So you should replace below line :-
js.executeScript("arguments[0].scrollIntoView(true);", Availability);
Availability.click();
To
js.executeScript("arguments[0].click()", Availability);
Element is not clickable at point (119, 9). Other element would receive the click: Command duration or timeout: 133 milliseconds
It clearly says, the element we want to click is hidden by some other element div in this case, which would receive the click.
I think it is problem with UI which shouldn't hide the element, but you can try few things :
1. Maximize the window of browser from webdriver to see if element is still hidden
driver.manage().window().maximize()
Use JavaScript to click element
WebElement element = driver.findElement(By.<locator>);
JavascriptExecutor executor = (JavascriptExecutor)driver;
executor.executeScript("arguments[0].click()", element)