How to select md-autocomplete option with Selenium or Selenide? - java

Here is my Java attempt, but what should I fix?
SelenideElement product = $(By.id("product"));
Assertions.assertEquals("Search product", product.attr("md-floating-label"));
product.find(By.tagName("input")).val("test");
SelenideElement span = product.find(By.tagName("span")); //this one and last lines does not work as expected
product.sendKeys(Keys.ARROW_DOWN);
product.pressEnter();
And HTML code
<md-autocomplete id="product" flex="85" md-selected-item="ctrl.orderItem.product" md-search-text="ctrl.productQuery" md-items="item in ctrl.findProduct(ctrl.productQuery)" md-item-text="item.name" md-delay="300" md-floating-label="Search product">
<div layout="row" class="item" layout-align="start center">
<span md-highlight-text="ctrl.productQuery">{{item.name}}</span>
</div>
</md-autocomplete>

Instead of doing product.find(By.tagName("span")); I would try replacing it with an XPath as such:
SelenideElement span = product.find(By.xpath("//*[#id='product']/div/span"));
The issue was that span is not a direct child element of product (which is a md-autocomplete element), so you need a slightly more complex locator to find the span.

Maybe you dont need to do this thing Assertions.assertEquals("Search product", product.attr("md-floating-label"));
Just try find your span element like this SelenideElement span = $(By.xpath("//md-autocomplete[#id='product' and #md-floating-label= 'Search product"]//span'));
span.sendKeys(Keys.ARROW_DOWN);
span.pressEnter();
If element with label 'Search product' is not exist, you get a SoSuchElementException

Related

Is it possible to find an element according to "p" tag but click "a" tag those are inside "div"?

I'd like to select some schemas on the screen for testing. But there are 8 different types schemas. And I couldn't select any schema without click on the schema's image. The element is displayed like this;
I created web element list and filtered it on value that i wanted to select schema name with java 8 stream than i can replace filtered element with (up div[class=' up template-list-board row']>div>P to div[class='template-list-board row']>div>a) , but it was not a good idea, i've experienced.
So , is there any way to click that "a" tag?
The html is displayed like this;
<div class="template-list-board row">
<div class="template-item-list">
<a class="item-image-click" ....> </a>
<p class="item-name">Meeting Agenda</p>
</div>
<div class="template-item-list">
...
</div>
I am not sure if I am understanding you correctly, but my solution would be something like this (with XPATH not css):
1) create a string for the locator:
String locator = "//div[class='template-list-board row']//p[text()='" + hereYourNameVariableAsString + "']/preceding-sibling::a";
2) Then create your element :
WebElement element = driver.findELement(by.xpath(locator));
Here the important thing is that you locator is dynamic you will have to provide you menu name or whatever that name represent such as "Meeting Agenda". Then it will find that menu and the previous sbling a for clicking. I hope I understand the problem correctly and this helps.

How to merge 2 xpath in one

Html
<li class="wdappchrome-ai" data-automation-id="searchInputAutoCompleteResult" tabindex="-2" aria-posinset="1" aria-setsize="3">
<span data-automation-id="searchInputAutoCompleteResultFullText">
<span style="font-weight:500">
<span data-automation-id="searchInputAutoCompleteResultToken" style="font-weight:400">mike</span>
<span data-automation-id="searchInputAutoCompleteResultToken" style="font-weight:400">diana</span>
</span>
</span>
</li>
I am getting user full name divided into spans so I want to build xpath which returns me combine text of both/multiple span from single list.
For now I am using 2 or more xpath based on name of user divided into span.
I use : //li[.//span[text()='mike']] //li[.//span[text()='diana']]
Then I do gettext() for above both xpath and merge using java grammatically. So I am looking for solution which give me full text of all span within particular li tag from above.
Try below XPath to match element by one of the spans:
//li[.//span='diana' or .//span='mike']
or by both spans:
//li[.//span='diana' and .//span='mike']
To get the full text of all span within particular li tag in a single line you can use the following code block :
ArrayList<String> nameList = new ArrayList<String>();
List<WebElement> firstName_lastname = driver.findElements(By.xpath("//li[#class='wdappchrome-ai']//span[#data-automation-id='searchInputAutoCompleteResultToken']"));
for (WebElement fN_lN:firstName_lastname)
nameList.add(fN_lN.getAttribute("innerHTML"));
System.out.println(nameList);

How to get text inside depth div tag with Selenium

I am trying to get the text content of the items inside the following 2 div elements. It work using absolute path:
element = driver.findElement(By.xpath(".//*[#id='page-wrapper']/section/section/div/div[2]/section/div/div/div/div[45]"));
data = element.getText();
System.out.println(data);
The text that I am trying to get is:
45
Se
Selenium
I am trying to get text using relative XPath, but it always fails.
I am trying use this combination:
element = driver.findElement(By.xpath("//div[contains(#class,'elemBox noclaim noclaim-tt') and contains(text(),'45')]"));
or
element = driver.findElement(By.xpath("//div[contains(#class,'elemBox noclaim noclaim-tt')]/div[contains(text(),'45')]"));
but still failed.
I have HTML code like this:
<div class="elemBox noclaim noclaim-tt text-right m-t-lg animated-add pulse-add animated pulse animated-add-active pulse-add-active" >
<div class="" ng-show="(filterTool(elementName.name)) || (name === '')">
<div class="text-right ng-binding">45</div>
<div class="text-left ng-binding">
<span class="elemSym ng-binding">Se</span>
<br/>
Selenium
</div>
</div>
What should I do?
By using contains(text(),'45'), only the first direct-child text node will be evaluated. This is the reason you attempted XPath failed to find the div; because the text '45' is nested 2 levels from the outer div :
//div[contains(#class,'elemBox noclaim noclaim-tt') and contains(div/div/text(),'45')]
Or you might want to try using . instead of text to evaluate the entire texts within the outer div as opposed to evaluating only first direct-child text node :
//div[contains(#class,'elemBox noclaim noclaim-tt') and contains(.,'45')]
I think, you don't need to use contains word inside xpath.
textRightElement = driver.findElement(By.xpath("//div[#class='elemBox noclaim noclaim-tt']/div[#class='text-right']"));
or if class text-right is unique, just use
textRightElement = driver.findElement(By.xpath("//div[#class='text-right']"));
.... if you really need to find the element with it's value,
textRightElement = driver.findElement(By.xpath("//div[text()='45']"));

Get xpath of div having multiple occurence in page

I am having a weird requirement. I am having a div class named "expandThisSection". And I have
<div id=​"requiredAccessoriesContentPlaceHolder" class=​"expandThisSection">​No required accessories are available for this product.​</div>​
<div id=​"requiredAccessoriesContentPlaceHolderMeasurement" class=​"expandThisSection">​ ​</div>​
<div id=​"optionalAccessoriesContentPlaceHolder" class=​"expandThisSection">​No optional accessories are available for this product.​</div>​
<div id=​"optionalAccessoriesContentPlaceHolderMeasurement" class=​"expandThisSection">​ ​</div>​
<div class=​"expandThisSection">​
<div style=​"width:​95%">​mytext</div>​
​<ul class=​"movePos">​…​</ul>​
<div><b>test</b>​</div>
​<div>​<b>abc</b> Get this text</div>
​<div id=​"vendLogo">​…​</div>
</div>
<div class="expandThisSection">
<table>...</table>
</div>
I want the content of the div that has style of 95% width.That is value I want is "mytext". But I am not able to find out xpath for the same.
Also I want xpath for finding the div content just above div with id=​"vendLogo". That is I want "Get this text".
NOTE: ITS ASSURED THAT THIS Bold tag WILL CONTAIN "abc"
How to do it? I am using selenium with Java
Got the first one. Not able to get second one.
Code:
List<WebElement> currentSkuDescription = driver.findElements(By.xpath("//div[#class='expandThisSection']/div"));
for(WebElement currentItem: currentSkuDescription) {
WebElement descriptionBlock = currentItem.findElement(By.xpath("//div[contains(#style, 'width:95%')]"));
description= descriptionBlock.getText();
}
Try dropping the #class='expandThisSection' because the div you want does not have that class attribute (it's parent does). Also, an exact match may be possible.
By.xpath("//div[#style='width:95%']
By.xpath("//div[contains(#style, 'width:95%')]
Either of those should work. If you want to make sure you are grabbing the right one, relative to the parent, use XPath axes...
//div[contains(#class, 'expandThisSection')]/child::div[contains(#style, 'width:95%')]
If you to search for the div by a specific text (in this case 'mytext') this you can use this xpath:
"//div[text()[contains(.,'mytext')]]/ancestor::div[#class='expandThisSection']"
Or if you want by the styling, the you can use this xpath:
"//div[#style='width:95%']/ancestor::div[#class='expandThisSection']"
Note that the second xpath will only work where the inline styling is done on the tag.
For the second query, try this xpath:
"//div[#id='vendLogo']/preceding-sibling::div[1]"
To get the specific text you require, you can do the following:
String text = driver.findElement(By.xpath("//div[#id='vendLogo']/preceding-sibling::div[1]")).getText();
text.replace(div.findElement(By.tagName("b")).getText(), "");

Xpath for checkbox element by locating it's following label element by value

I have been working for quite a while on this and still haven't found an answer specific to my problem in stackoverflow or from experimenting with the Xpath myself. I am quite inexperienced so I alpogise if this is a simple problem but I would really appreciate any help.
I am working with Selenium to test a web app that uses Wicket. I need the Xpath to the checkbox that correlates to the respective label. This is because I need to be able to enter the value shown on the label and for it to find the relevant checkbox based on the label text such as "001", as the checkbox ids do not match the values.
Mockup below shows the checkboxes and their corresponding labels;
The corresponding HTML is show below;
<span wicket:id="excludeDepotCheckBox" id="excludeDepotCheckBox5">
<input name="adminPreferenceSection:excludeDepotCheckBox" type="checkbox" value="0" id="excludeDepotCheckBox5-adminPreferenceSection:excludeDepotCheckBox_0">
<label for="excludeDepotCheckBox5-adminPreferenceSection:excludeDepotCheckBox_0">001</label>
<br>
<input name="adminPreferenceSection:excludeDepotCheckBox" type="checkbox" value="1" id="excludeDepotCheckBox5-adminPreferenceSection:excludeDepotCheckBox_1">
<label for="excludeDepotCheckBox5-adminPreferenceSection:excludeDepotCheckBox_1">009</label>
<br>
</span>
Another problem I also face is that the Xpath must include the fact that it is inside the span shown in the html as there are 3 other groups of checkboxes on the page with the same values so it must be specific for each span for example:
id="excludeDepotCheckBox5"
I have tried the following Xpaths to no avail;
//span[#id='excludeDepotCheckBox5' and contains(., '009')]"
"//*[#id='excludeDepotCheckBox5' and ./label/text()='009']/preceding-sibling::*[#name='adminPreferenceSection:excludeDepotCheckBox']
//*[#id='excludeDepotCheckBox5' and ./label/text()='009']/preceding-sibling::input[1]"
Again I aplogise if it is a simple syntax/understanding problem but I would really appreciate any help.
Since "preceding-sibling" is so error-prone (it will break as soon as the HTML structure changes a little bit), here's a more stable variant (wrapped for legibility):
//span[#id = 'excludeDepotCheckBox5']//input[
#id = //span[#id = 'excludeDepotCheckBox5']//label[normalize-space() = '001']/#for
]
You can use the below xpaths:
1- For checking the checkbox related to label '001':
//span[#id='excludeDepotCheckBox5']/label[.='001']/preceding-sibling::input[1]
2- For checking the checkbox related to label '009':
//span[#id='excludeDepotCheckBox5']/label[.='009']/preceding-sibling::input[1]
NOTE: It will check for the 'input' element which is the first preceeding sibling of label element with exact innerHTML/text as '001' or '009' under a span element with id='excludeDepotCheckBox5'.
//*[#id='excludeDepotCheckBox5']/label[contains(text(),'001')]//preceding-sibling::input[1]

Categories

Resources