Selenium Webdriver C# Unable to locate an element on the "active" dropdown class list - selenium

I am on the beginner level if it goes for the selenium Webdriver in C#. I can locate elements, write simple scripts in order to input some value, withdraw it, compare and etc. I can also get values from the dropdown list by SelectElement class and so far I have not had any issues.
Recently one of our systems was refactored to React JS and most of my automation tests have stopped working.
Right now I have been struggling with a simple logout operation. I will please my issue below, and I would be grateful for any tips or suggestions.
The hard thing is that I can not locate the logout link which is located in the dropdown list, however, the code for it looks as below. Before you click on the link which acts as an action for the drop-down list it looks like this:
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
<span class="glyphicon glyphicon-user" aria-hidden="true"></span>
UserName UserLast
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li>Logout</li>
</ul>
<div id="user-login" class="hidden">UserName.UserLast</div>
<div id="user-email" class="hidden">UserName.UserLast#companyname.com</div>
</li>
When a User clicks on the the code changes to this one below:
<li class="dropdown open">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="true">
<span class="glyphicon glyphicon-user" aria-hidden="true"></span>
UserName UserLast
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
<li>Logout</li>
</ul>
<div id="user-login" class="hidden">UserName.UserLast</div>
<div id="user-email" class="hidden">UserName.UserLast#companyname.com</div>
</li>
My test is quite simple, locate the Logout "button/link", click on it and perform the logout operation. Now I have started of location the action link which looks like this:
[FindsBy(How = How.XPath, Using = "/html/body/div[1]/div/div[2]/ul[2]/li[2]/a")]
private IWebElement userDropdown;
And my logout method looks like that's,
public void LogOut()
{
userDropdown.Click();
var userDropDownList = Browser.WebDriver.FindElement(By.XPath("/html/body/div[1]/div/div[2]/ul[2]/li[2]/ul"));
var logoutButton = userDropDownList.FindElement(By.LinkText("Logout"));
logoutButton.Click();
}
I perform the click operation on the link, look for the list with the Logout, use the click operation. Still my test does not work and I am not getting any errors at all but the logout operation is not done. I think that the issue here is not the drop-down list is not visible by selenium. I have not tried the SelectElement class because this example is not a select element or maybe I am wrong...

You will need to perform click() on 2 elements to logout:
Identify the dropdown:
[FindsBy(How = How.XPath, Using = "//li[#class='dropdown']/a[#class='dropdown-toggle']/span[#class='glyphicon glyphicon-user']")]
private IWebElement userDropdown;
logOut method:
public void logOut()
{
userDropdown.Click();
var logoutButton = Browser.WebDriver.FindElement(By.XPath("//li[#class='dropdown']//ul[#class='dropdown-menu']/li/a[#href='/Account/Logout']"));
logoutButton.Click();
}

so first things first make sure you've scrolled the item to view
var js = (IJavascriptExecutor)driver;
string idOfLinkToMakeDropDownOpen = "whatever the id is"
IWebElement obj = driver.FindElement(By.XPath("//input[#id='idOfLinkToMakeDropDownOpen']"));
js.ExecuteScript("arguments[0].scrollIntoView(true);", obj);
obj.Click();
Now the drop down should be open so click it
driver.FindElement(By.Xpath("descendant::a[text() = 'Logout']")).Click();
That should click it. You'll probably want to watch it to see if opens the drop down. You also may need to wait a second after the dom to change after having opened the drop down. That would work something like this:
IWebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(15));
after obj.Click(); you do this line:
wait.Until(ExpectedConditions.ElementIsVisible(By.Xpath("descendant::li[#class = 'dropdown open']"));

Related

Katalon performing nested Selenium WebDriver finds

I am attempting to get all <li> in a specified <ul> in Katalon Studio. I am trying this via Selenium WebDriver. I have code like this :
// login with valid account
WebUI.callTestCase(findTestCase('ValidLogin'), [('shouldCloseBrowser') : false], FailureHandling.STOP_ON_FAILURE)
// get the driver
WebDriver driver = DriverFactory.getWebDriver()
// Loop over selection of each company, and assert that we land on respective dashboard
driver.manage().timeouts().implicitlyWait(1, TimeUnit.SECONDS)
WebElement companyListContainer = driver.findElement(By.id('companyList'))
// finds this element OK
List<WebElement> companies = companyListContainer.findElements(By.xpath('.//li'))
// this failed
for (int i = 1; i <= companies.length; i++) {
// click the test object
driver.findElement(By.xpath('//ul[#id="companyList"]/li[' + i + ']')).click()
// implicitly wait 3 seconds
driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS) // we better be at the Dashboard page
// go back to "Company Select"
WebUI.click(findTestObject('a_Company Select'))
// wait three seconds again
driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS)
}
and for some reason, even though there were <li>s on the page, the List<WebElement> is null, even though companyListContainer wasn't, and contained those elements. How do I fix this?
The HTML
looks like :
<ul id="companyList" class="list-group">
<li class="list-group-item clickable " data--name="EzDine C2 - Michael" data--id="302">
EzDine C2 - Michael
<span class="list-check"><i class="fa fa-check text-success" aria-hidden="true"></i></span>
</li>
<li class="list-group-item clickable " data--name="EzDine Comp3 -Hos" data--id="303">
EzDine Comp3 -Hos
<span class="list-check"><i class="fa fa-check text-success" aria-hidden="true"></i></span>
</li>
<li class="list-group-item clickable " data--name="Test EZDine V2 Comp1" data--id="301">
Test EZDine V2 Comp1
<span class="list-check"><i class="fa fa-check text-success" aria-hidden="true"></i></span>
</li>
</ul>
The error was because of the stupidest reason (that, somehow, Katalon failed to tell me): I was trying to access the length of a list; /* that member doesn't exist in java.util.List! */
I changed to size() and it worked.
Katalon is really flawed for not having alerted me of this; /* they said something about null not being defined, but not that I was attempting to access a member that didn't exist */

trouble making in xpath for "ul" html code in selenium webdriver

HTML code:
<div id="routingPanel" class="">
<div id="routingPanelRight">
<ul id="routingList" class="ui-sortable">
<li class="ui-menu-item ui-draggable" style="display: list-item;" role="presentation" data-type="srl" data-id="15">
<a class="ui-corner-all" tabindex="-1">AS-HTTS-US-LAN-SW</a>
<span class="fa fa-trash"/>
<span class="type">[srl]</span>
</li>
<li class="ui-menu-item ui-draggable" style="display: list-item;" role="presentation" data-type="queue" data-id="119">
<a class="ui-corner-all" tabindex="-1">AS-EMEA-NORTH</a>
<span class="fa fa-trash"/>
<span class="type">[queue]</span>
</li></ul></div></div>
I need to click on a button which is having the span class"fa fa-trash" but it is inside li class. And i have list on buttons on the page with li class changing.
I am giving testdata from excel file so i can't use the direct value.
i tried to use this xpath
.//*[#id='routingList']/li[5]/span[1] //testdata1
.//*[#id='routingList']/li[2]/span[1] //testdata2
where li value changes everytime from excel file.
WebDriverWait wait = new WebDriverWait(driver, 15);
wait.until(ExpectedConditions.visibilityOfElementLocated((By.xpath("//ul[#id='routingList']/li/span[1]")))).click();
List<WebElement> options = driver.findElements(By.xpath("//ul[#id='routingList']/li/span[1]"));
for (WebElement option : options) {
if(testData.equals(option.getText()))
option.click();
Tried above code but it is deleting only one from the list ,where i have passed two more testdata that needs to be deleted.
Need suggestions Please
According to the information you gave me in comments, I think the problem is that you are trying to get a text from an element that doesn't contain text.
Let's say your testData is AS-HTTS-US-LAN-SW. In the HTML you provided and the xpath you mentioned, you are selecting an autoclosing tag <span class="fa fa-trash"/>. Once this tag is selected, you are trying to get the text inside of it, and there is none.
<ul id="routingList" class="ui-sortable">
<li class="ui-menu-item ui-draggable" style="display: list-item;" role="presentation" data-type="srl" data-id="15">
===========================
<a class="ui-corner-all" tabindex="-1">AS-HTTS-US-LAN-SW</a> ----> The text is contained here
<span class="fa fa-trash"/> ---> No text in that tag
===========================
<span class="type">[srl]</span>
</li>
</ul>
So, basically, you have to modify a little bit your xpath from : //ul[#id='routingList']/li/span[1] to : //ul[#id='routingList']/li/a to get the text, and then go back to the parent node to find your button with : ../span[contains(#class, 'fa fa-trash')]
WebDriverWait wait = new WebDriverWait(driver, 15);
wait.until(ExpectedConditions.visibilityOfElementLocated((By.xpath("//ul[#id='routingList']/li/span[1]")))) // removed the click here because you were clicking on the first element of the list
List<WebElement> options = driver.findElements(By.xpath("//ul[#id='routingList']/li/a"));
for (WebElement option : options) {
if(testData.equals(option.getText()))
option.findElement(By.xpath("../span[contains(#class, 'fa fa-trash')]")).click();
Tell me if it helped
I know you already accepted an answer but there's a more efficient way to do this. You can specify the text you are looking for as part of the XPath. So, you do a single search instead of looping through all the options which can be a performance hit if there are many options. Also, with something like this you are likely to use it more than once so put it in a function.
In this case, the function would take in the string you are looking for and then click the appropriate element.
public void selectRegion(String regionName)
{
driver.findElement(By.xpath("//a[.='" + regionName + "']/following-sibling::span[#class='fa fa-trash']")).click();
}
and you would call it like
selectRegion(testData);
The function looks for an A tag that contains the desired text and then clicks the sibling SPAN with class fa fa-trash.

Selenium Framework(finding the field name)

I am trying to find the field name "SavePLButton". The Html code behind this page is:
<ul class="button-bar">
<li class="first">
<a href="#" id="SavePLButton" type="button" name="SavePLButton" value="Save" onclick="formSubmit('SAVEEXIT');">
<i class="icon-save"/>
Save
</a>
</li>
The C# code that I am using is:
var Submit = Driver.Instance.FindElement(By.CssSelector("i.icon-save"));
Submit.Click();
I have also tried:
var Submit = Driver.Instance.FindElement(By.Id("SavePLButton"));
Submit.Click();
It is unable to find the fieldname. Can someone please help. Thank you.
Try using WebDriverWait to wait until element visible as below :-
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
var Submit = wait.Until(ExpectedConditions.ElementIsVisible(By.Id("SavePLButton")));
Submit.Click();
Note :- make sure before try this element is not inside any frame
Hope it helps.....:)

Mouse pointer/cursor pointing to webelement apart from Actions class in Selenium

I am well aware that we can use Actions class to move to a particular web element as below.
Actions(driver).moveToElement(driver.findElement(By.xpath("element"))).build().perform();
For one of the webelement as soon as I move to that element I should get a dropdown. But some times this is working and some times not. Is there any option other than Actions class to simulate mouse movement to particular webelement?
The HTML code for the element I am trying to simulate mouse pointer movement to it is one with class="dropdown-submenu"
<li ng-show="setStatusPermission" class="dropdown-submenu">Set status
<ul class="dropdown-menu" role="menu">
<li ng-show="activePermission" class="">Active</li>
<li ng-show="cancelPermission" class="">Cancelled</li>
<li ng-show="completePermission" class="ng-hide">Completed</li>
<li ng-show="errorPermission" class="ng-hide">Error</li>
<li ng-show="expiredPermission" class="ng-hide">Expired</li>
<li ng-show="suspendPermission" class="ng-hide">Suspended</li>
</ul>
</li>
Automation code snipet to perform the operations is as below.
WebElement webElementSetStatus = basePage.waitForElementToLoadAndReturnWebElement_BasePage(
bc_ui_TaskAction_Setstatus, "linkText", "15");
basePage.getActions_BasePage().moveToElement(webElementSetStatus).build().perform();
List<WebElement> options = basePage.getWebElements_BasePage(
"#bc-td-actions-dropdown-list > li.dropdown-submenu > ul > li", "cssSelector");
for (WebElement option : options)
if (!option.getAttribute("class").equals("ng-hide") && !option.getText().isEmpty())
actualAvailableStatusOptions.add(option.getText());

WebDriver: find element by CSSSelector or XPath

I have a problem to get element <i class="angle-up"></i> on the following page. The selection should be depended on "data-id" value. Thanks in advance.
<li class="recent" data-to="3" data-off="23" data-id="5">
<a class="collapse in" href="/board">
<span>
Board
</span>
<i class="angle-up"></i>
</a>
</li>
<li class="" data-to="3" data-off="23" data-id="7">
<a class="collapse in" href="/set">
<span>
Set
</span>
<i class="angle-up"></i>
</a>
</li>
Well I think if the value is data-id dependant then you might need to split the Xpath or Css selector in 3 parts as below:
Part1=//li[#data_id='
Part2= (Fetch this value at runtime using an appropriate variable)
Part3= ']//i[#class='angle-up']
and now you may use the following code to use the element
public class TestElement {
public static void main(String args[])
{
WebDriver driver= new FirefoxDriver();
driver.get(YOUR INTERNAL URL HERE.);
String elementPart1=//li[#data_id='
String elementPart2=5 //keeping the id you are looking for
String elementPart3=']//i[#class='angle-up']
WebElement element = driver.findElement(By.xpath(elementPart1+elementPart2+elementPart3);
}
}
Here as you may see one example of such xpath could be
//li[#data_id='5']//i[#class='angle-up']
Also if I would advise you to check using firefinder which is a firebug extension to verify that the xpath is correct.