Trying to use Selenium to find a specific entry in a list when what you type highlights that word - selenium

DOM:
<span class="item">Does not <span class="highlight">match</span>.</span>
<span class="item">Also not <span class="highlight">match</span>ing.</span>
<span class="item"><span class="highlight">match</span></span>
Issue:
I've got a list of items. When I type into a text box, it eliminates items that do not match, and highlights the ones that do inside a /span. The issue is that if I type something that matches multiple things, I want to select the EXACT String, and not the ones that partially match (see above DOM example... the ideal match would be the 3rd one).
So, is my only hope here to go one by one until I find my perfect match, or is there something else that I've been missing?

You are trying to find a span that has no text, with an inner span that has some highlighted text. Here is an XPath selector for that:
//span[#class='item'][not(text())]/span[#class='highlight'][‌​text()='match']

Related

Click on parent element based on two conditions in child elements Selenium Driver

Using Selenium 4.8 in .NET 6, I have the following html structure to parse.
<ul class="search-results">
<li>
<a href=//to somewhere>
<span class="book-desc">
<div class="book-title">some title</div>
<span class="book-author">some author</span>
</span>
</a>
</li>
</ul>
I need to find and click on the right li where the book-title matches my variable input (ideally ignore sentence case too) AND the book author also matches my variable input. So far I'm not getting that xpath syntax correct. I've tried different variations of something along these lines:
var matchingBooks = driver.FindElements(By.XPath($"//li[.//span[#class='book-author' and text()='{b.Authors}' and #class='book-title' and text()='{b.Title}']]"));
then I check if matchingBooks has a length before clicking on the first element. But matchingBooks is always coming back as 0.
class="book-author" belongs to span while class="book-title" belongs to div child element.
Also it cane be extra spaces additionally to the text, so it's better to use contains instead of exact equals validation.
So, instead of "//li[.//span[#class='book-author' and text()='{b.Authors}' and #class='book-title' and text()='{b.Title}']]" please try this:
"//li[.//span[#class='book-author' and(contains(text(),'{b.Authors}'))] and .//div[#class='book-title' and(contains(text(),'{b.Title}'))]]"
UPD
The following XPath should work. This is a example specific XPath I tried and it worked "//li[.//span[#class='book-author' and(contains(text(),'anima'))] and .//div[#class='book-title' and(contains(text(),'Coloring'))]]" for blood of the fold search input.
Also, I guess you should click on a element inside the li, not on the li itself. So, it's try to click the following element:
"//li[.//span[#class='book-author' and(contains(text(),'{b.Authors}'))] and .//div[#class='book-title' and(contains(text(),'{b.Title}'))]]//a"

Selenium XPath find element where second text child element contains certain text (use contains on array item)

The page contains a multi-select dropdown (similar to the one below)
The html code looks like the below:
<div class="button-and-dropdown-div>
<button class="Multi-Select-Button">multi-select button</button>
<div class="dropdown-containing-options>
<label class="dropdown-item">
<input class="checkbox">
"
Name
"
</label>
<label class="dropdown-item">
<input class="checkbox">
"
Address
"
</label>
</div>
After testing in firefox developer tools, I was finally able to figure out the xPath needed in order to get the text for a certain label ...
The below XPath statement will return the the text "Phone"
$x("(//label[#class='dropdown-item'])[4]/text()[2]")
The label contains multiple text items (although it looks like there is just one text object when looking at the UI) in the label element. There are actually two text elements within each label element. The first is always empty, the second contains the actual text (as shown in the below image when observing the element through the Firefox developer tool's console window):
Question:
How do I modify the XPath shown above in order to use in Selenium's FindElement?
Driver.FindElement(By.XPath("?"));
I know how to use the contains tool, but apparently not with more complex XPath statements. I was pretty sure one of the below would work but they did not (develop tool complain of a syntax error):
$x("(//label[#class='dropdown-item' and text()[2][contains(., 'Name')]]")
$x("(//label[#class='dropdown-item' and contains(text()[2], 'Name')]")
I am using the 'contains' in order to avoid white-space conflicts.
Additional for learning purposes (good for XPath debugging):
just in case anyone comes across this who is new to XPath, I wanted to show what the data structure of these label objects looked like. You can explore the data structure of objects within your webpage by using the Firefox Console window within the developer tools (F12). As you can see, the label element contains three sub-items; text which is empty, then the inpput checkbox, then some more text which has the actual text in it (not ideal). In the picture below, you can see the part of the webpage that corresponds to the label data structure.
If you are looking to find the element that contains "Name" given the HTML above, you can use
//label[#class='dropdown-item'][contains(.,'Name')]
So finally got it to work. The Firefox developer environment was correct when it stated there was a syntax problem with the XPath strings.
The following XPath string finally returned the desired result:
$x("//label[#class='dropdown-item' and contains(text()[2], 'Name')]")

How to populate drop down when it is built using an input tag using java and selenium

I have a drop down built with extJS.
<input id="combo-1786-inputEl" data-ref="inputEl" type="text" size="1" name="Query Category" placeholder="Select query category" role="combobox" aria-hidden="false" aria-disabled="false" aria-readonly="false" aria-invalid="true" aria-required="true" aria-haspopup="true" aria-expanded="false" aria-autocomplete="list" class="x-form-field x-form-required-field x-form-text x-form-text-default x-form-invalid-field x-form-invalid-field-default x-form-empty-field x-form-empty-field-default" autocomplete="off" data-componentid="combo-1786" data-errorqtip="<ul class="x-list-plain"><li>This field is required</li></ul>" aria-describedby="combo-1786-ariaErrorEl">
As we can see the tag used is 'input' and not 'select'.
So when I looked up about how to populate it, most answers were made under the assumption that it was created using a 'select' tag and it did not work.
Also the drop downitems are fetched from DB only when I click on the arrow on the dropdown:
So as a result of this, the drop down items cant be found on the page source.
Can someone one please suggest how to populate such downs using the best practice?
P.S-I do have a workaround, but its not at all good code practice and not at all generic:
driver.findElement(By.xpath("//*[#id='combo-1731-trigger-picker']")).click();//clicking on the arrow key of the drop down.
//Once the drop down item comes, I am trying to replicate pressing the keyboard arrow key,by sending down arrow key to the drop down item(web element)
//This works for me because I know the extact position of my drop down item in the drop down item list.It will stop working if the postion of the drop item changes
//so below loop just presses the down arrow key required number of times.
for(int i=0;i<5;i++){
driver.findElement(By.xpath("//*[#id='combo-1731-inputEl']")).sendKeys(Keys.ARROW_DOWN);
}
driver.findElement(By.xpath("//*[#id='combo-1731-inputEl']")).sendKeys(Keys.ENTER);
If you read the comments mentioned along with the above code, then you can understand how fragile the logic is.
Please help.
You are trying to click/ select the item in the drop down correct?
Do the drop down items have unique id's? If so you should be able to just pass it the specific xpath id.
I personally use Css to find elements, in that case it would be
driver.find_element(By.CSS_SELECTOR,'#combo-1731-trigger-picker').click()
driver.find_element(By.CSS_SELECTOR, '#combo-1731-inputEl > nth:child(x)').click()
where x = the count of your drop down item.
or if they have unique id's then use
driver.find_element(By.CSS_SELECTOR, '#theUniqueIdGoesHere').click()
I wrote a whole weeks worth of tests, using xpath selectors, it was painful day to day running the test and watching it fail. Going back and changing everything to Css selectors has saved me many head aches since I started writing Auto tests.
Edit: you could try the following,
driver.findElement(By.linkText("Your Links Text Here")).click();
This will only work if each links text is unique as well, if not it will select the first one it finds.
If these work for you would you mind accepting my answer?

Finding XPath with the text that is below a closed tag

I have the following HTML. I need to get the XPath using DOWN as a keyword.
<span>
"DEVICE: some random values that I'm not bothered about"
<span class="c-emoji_plain_text">:sensor_1000_4_1:</span>
"/interfaces/:/interfaces/:mib2d], TRIGGER: interface_status, MESSAGE:
$interface_name is DOWN"
</span>
The problem I'm facing here is, when I use the following XPath, it's not recognized:
//span[contains(text(),'DOWN')]
I see that the text above child span is used but not the text below it.
Kindly help.
Try to replace
//span[contains(text(),'DOWN')]
with
//span[contains(.,'DOWN')]
to select required span node
Note that such selector can match several elements. To make it more specific you can use
//span[span and contains(.,'DOWN')]
This will match span that contains span child node as well as "DOWN" substring
Also
//span[contains(text()[2],'DOWN')]
should do the trick

Unable to click the elements in the dynamical list

For the below code
<li class="user ui-menu-item" role="presentation">
<a id="ui-id-52" class="ui-corner-all" tabindex="-1">
<em>User:</em>
Staff User
</a>
</li>
This is the scenario:
There is a text field, in which I enter the name Staff, with that the related values for the staff are displayed in the dynamic list box, in the above scenario the id is dynamically generated, and when I tried to select the value by class, it is same for all the elements.
I want an xpath expression to select the first available options in the list. I tried in many ways like with contains and starts-with, but no use. Please let me know your valuable suggestion.
Thanks in Advance
Shiva.
I think this should work
WebElement ele = webdriver.findElement(By.Xpath("//li[#class='user ui-menu-item'][1]"))
Did you try forming a List and then just directly using the first element of that List?
List<WebElement> list = driver.findElements(By.xpath("//li[#class(contains, 'user')]";
list[0].getText();
I'm still not 100% percentage sure what you want to do with the element once you have found it though. It would probably be better to form the List, then iterate over that list and perform whatever action you require per element.
Use this xpath
"(.//a[#class='ui-corner-all'])[1]"
source: XPath query to get nth instance of an element
Use the xpath. It should work
//li[#role = 'presentation']//a[1]