Selenium, JAVA - how to find such element? - java

Do you know how to find and click at an element like this:
<div class="offer ctrlOpenOfferInfo">
<a class="linkOffer" href="offer_view.html?id=1007"/>
<p class="photo">
<p class="name">New offer</p>
<p class="price">123</p>
<div class="rate ctrlViewRateOffer" data-value="0.0000">
<p class="date"/>
<div class="hide info">
<div class="bgInfo"/>
using Selenium WebDriver and using the name of the element as there are few very similiar elements on the page?
Here's what I've tired so far:
WebDriverWait wait = new WebDriverWait(driver, 30);
wait.until(ExpectedConditions.invisibilityOfElementLocated(By.xpath("//*[text()='New offer']")));
wait.until(ExpectedConditions.elementToBeClickable(By.xpath(".//*[#id='formDevelopmentElementAdd'][text()='New offer']")));
driver.findElement(By.xpath(".//*[#id='formDevelopmentElementAdd']/div/p[2][text()='New offer']")).click();
or:
driver.findElement(By.xpath("//p[#class='name'][text()='New offer']")).click();
or:
String address = driver.findElement(By.xpath("//*[contains(text(), 'New offer') and #class='name']")).getAttribute("href");
driver.get(baseUrl + address);
or:
driver.findElement(By.xpath("//a[Text()='New offer']")).click();
I've tried these with text, class, xpath...

Assuming you want to click the p tag containing New offer:
I would think this element is not inside an iframe. If so, you must use driver.switchTo().frame("name or xpath or css for frame locator"); first before start looking for element.
Now, how can you find that element. Consider the following options:
Using xpath text based search
//p[.='New offer']
//to be more precise you can do
//p[#classs='name'][.='New offer']
You can use By.className('name') to identify that element even though that name does not look like unique to me
Using cssSelector
.name
using nth-child() function of cssSelector
.offer.ctrlOpenOfferInfo>a>p:nth-child(2)

Related

Selenium (Java) unable to find element by visible link text

I've gotten one of the more frustrating Selenium problems.
I've got a table on a page, where one of the elements have a link. The link is called "Send brev".
<td data-e2e-selector="sakHendelser" id="sakHendelser_0" class="ng-star-inserted">
<saksnytt><!----><!----><!---->
<div class="hb-tekst--ingenBryting ng-star-inserted">
<!----><!----><!---->
<button class="hb-knapp hb-knapp--lenke hb-knapp--alignTeks hb-knapp-lenke-nopadding ng-star-inserted"
data-e2e-selector="saksnytt-link">
<i aria-hidden="true" class="fa fa-flag fa-envelope"></i>
<span class="hb-knapp-tekst">Send brev </span></button>
<!----><span aria-hidden="true" class="fa fa-info-circle ng-star-inserted"
id="reservert-info">
</span><!----><!----><!----></div><!---->
</saksnytt></td>
This has worked before, and I haven't found a reason for why it's stopped working now. But no matter how I try to find it, Selenium responds with
no such element: Unable to locate element: {"method":"xpath","selector":"//data-e2e-selector[contains(text(),'Send brev ')]"}
or similar-
I've tried the following:
Browser.Wait().until(presenceOfElementLocated(By.linkText(merknad + " ")));
This times out.
driver.findElement(By.linkText(merknad + " ")).click();
driver.findElement(By.partialLinkText(merknad + " ")).click();
driver.findElement(By.xpath("//data-e2e-selector[contains(text(),'" + "Send brev" +"')]"));
driver.findElement(By.xpath("//id[contains(text(),'" + "Send brev" +"')]"));
data-e2e-selector="sakHendelser" id="sakHendelser
I've also tried adding a space after the "v" in the link text, with no luck.
How can Selenium not find an element that is clearly visible and interactable like this?
Since the code is generated in Angular, and is more or less dynamic, I cannot create a tag for this specific element either, so I'm left with trying to find it by text. Which I cannot get to work.
Any ideas?
I AM able to click it with this code:
driver.findElement(By.xpath("//*[#id='sakHendelser_0']/saksnytt/div/button/span")).click();
But I want to be able to send the link text to the method instead of hardcoding the xpath like that.
LinkText and PartialLinkText will only work with text inside an A tag. You don't have that given your HTML so this will not work. Your only option to locate an element given the contained text is to use XPath.
The way you are using XPath by placing // before an attribute (such as //id or //data-e2e-selector) is not correct. These are element attributes, not tags.
The text Send brev is contained in a span element, so trying to locate it by querying on data-e2e-selector will not work -- that's also not a WebElement, it's an attribute on button.
Because you mention this item has some visible link text that you want to use as a parameter, I would query on only text and use a contains to work around any hidden whitespace:
driver.findElement(By.xpath("//span[contains(text(), 'Send brev')]")).click();
You can use link text as a parameter as such:
string linkText = "Send brev"
driver.findElement(By.xpath("//span[contains(text(), '" + linkText + "')]")).click();
You might have better luck clicking on the button itself though:
driver.findElement(By.xpath("//button[span[contains(text(), '" + linkText + "')]]")).click();
Try using normalize-space with xpath:
//span[normalize-space(text())='Send brev']
You need to take care of a couple of things as follows:
By.linkText() and By.partialLinkText() works only for <a> tags, where as the desired element is within a <span> tag.
data-e2e-selector and id are attributes of an WebElement but you have tried to use them as tagName.
The text Send brev is with in a <span> tag.
So identify the element with text as Send brev and moving ahead to interact with it you need to induce WebDriverWait for the elementToBeClickable() and you can use either of the following Locator Strategies:
cssSelector:
new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.cssSelector("button.hb-knapp.hb-knapp--lenke.hb-knapp--alignTeks.hb-knapp-lenke-nopadding.ng-star-inserted[data-e2e-selector='saksnytt-link'] span.hb-knapp-tekst"))).click();
xpath:
new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//button[#class='hb-knapp hb-knapp--lenke hb-knapp--alignTeks hb-knapp-lenke-nopadding ng-star-inserted' and #data-e2e-selector='saksnytt-link']//span[#class='hb-knapp-tekst' and contains(., 'Send brev')]"))).click();

How to select a nested webelement in html?

I would like to retrieve a webelement out of a nested html path using either css selectors or xpath. My specific use case is that I would like to select the i element in the following snippet:
<td class="headerActionsTd" data-rolename="Speaker">
<div class="headerActions">
<span class="addNewParticipantSection">
<i class="icon fa fa-user-plus" title="Add New"></i>
</span>
How do I obtain the i webelement for this using either css selector or xpath?
Use this xpath: //td[#data-rolename='Speaker']//div//span//i[#title='Add New'] or
css : div.headerActions i
driver.findElement(By.cssSelector("div.headerActions i"));
for multiple elements :
List<WebElement> users = driver.findElements(By.xpath("//td[#data-rolename='Speaker']//div//span//i[#title='Add New']"));
A simple one would be this :
CSS_SELECTOR
i.icon.fa.fa-user-plus[title='Add New']
Note that, if there is multiple element with this css selector, then you have this facility to differentiate between them:
:first-child
:nth-child(n)
:nth-last-child(n)
More can be found at this link
XPATH : would be :
//td[#data-rolename='Speaker']/descendant::span[#class='addNewParticipantSection']/i
Hope that helps.
Since you said data-role only changes in the comment of the other person, here is the xpath you can use
"//td[#data-role='Speaker']//i"
Or
"//td[#data-role='Speaker']/div/span/i"
Another option is that you can attempt to locate elements inside other elements. For example, you could store the addNewParticipantSection div in a WebElement, then use that WebElement's findElement method to locate the i element within it. Like so:
WebElement section = driver.findElement(By.className("addNewParticipantSection"));
WebElement icon = section.findElement(By.tagName("i"));
icon.click();

Clicking on <li> list item not using Selenium Java

The following list represents page navigation buttons:
<div class="list">
<ul class="pageNav">
<li class="paginate_button ">
1</li>
<li class="paginate_button ">
2</li>
<li class="paginate_button ">
3</li>
</ul>
</div>
To go to the second page for instance, I am using this Selenium Java code:
//after setting up webdriver
List<WebElement> li = driver.findElements(By.className("pageNav"));
System.out.println(li.get(2).getText());
li.get(2).click();
It's printing the text correctly "2", but not clicking or navigating correctly as if I was manually doing it on the actual website. I also tried replacing the link with an actual link like:
Visit our page
But still no luck. What am I doing wrong?
Thank you in advanced!
Try any of these below code.
In your tried code, I have noticed that you were using class locator to click on links element. But your <ul> tag does not contains the link. Inside <ul> tag, <li> tag is present and each <li> tag contains separate <a> tag.
so, here you should go with xpath or cssSelector locator.
Method 1) By using xpath locator
List<WebElement> links = driver.findElements(By.xpath("//ul[#class='pageNav']/li/a"));
System.out.println(links.size());
links.get(1).click(); //indexing start from 0, if you want to click on second link then pass indexing as 1.
Suggestion:- Instead of using absolute xpath, use relative xpath.
Method 2) By using cssSelector locator
List<WebElement> links = driver.findElements(By.cssSelector("ul.pageNav>li>a"));
System.out.println(links.size());
links.get(1).click(); //indexing start from 0, if you want to click on second link then pass indexing as 1.
Try below code
//getting all the anchor tag elements and storing in a list
List<WebElement> links = driver.findElements(By.xpath("//ul[#class='pageNav']//li[starts-with(#class,'paginate_button')]/a"));
System.out.println(links.size());
//performs click on second links
links.get(1).click();
If you're facing any abnormal difficulty which you are not able to handle directly , then you can first try to move to that element using actions class then click it as below:
WebElement we = driver.findElement(By.cssSelector("div.list > ul.pageNav li:nth-child(2));
Actions action = new Actions(driver);
action.moveToElement(we).click().build().perform();

Cannot find webelement using Selenium if they are dynamic

I'm having difficulties in locating a web element in seleniumn the html is as follows:
<div class="d2l-fieldgroup">
<div class=" vui-field-row">
<span class="d2l-field vui-label d2l-offscreen">Do not ask me again for this application</span>
<label class="d2l-checkbox-container">
<input name="dontAsk" value="0" type="hidden">
<input id="dontAsk" class="d2l-checkbox vui-input vui-outline" type="checkbox">
Do not ask me again for this application
</label>
</div>
</div>
I need to click on the checkbox or text but I just cant seem to be able to do this as I always get an error back saying:
Unable to locate element: {"method":"class name","selector"
I tried this:
WebElement do_not_ask_resourcebank = driver.findElement(By.className("d2l-fieldgroup"));
do_not_ask_resourcebank.click();
But get the following error:
no such element: Unable to locate element: {"method":"class name","selector":"d2l-fieldgroup"}
I also tried replacing d2l-fieldgroup with vui-field-row and d2l-checkbox-container
I also tried:
WebElement do_not_ask_resourcebank = driver.findElement(By.cssSelector("html/body/form/div/div[3]/div/label"));
and
WebElement do_not_ask_resourcebank = driver.findElement(By.xpath("id('confirmForm')/x:div/x:div[3]/x:div/x:label"));
but I just cannot seem to click on this element, very frustrating for a newbie like myself. Can someone point me to where I am going wrong?
If you are getting NoSuchElementException as your provided exception, There may be following reasons :-
May be you are locating with incorrect locator, you're locating actually <div> element with class name which looks like dynamically generated class name instead of actual <input type = 'checkbox'> element which you want. And other also looks unstable, You should try to locate desire element using By.id() as :-
WebElement do_not_ask_resourcebank = driver.findElement(By.id("dontAsk"));
May be when you are going to find element, it would not be present on the DOM, So you should implement WebDriverWait to wait until element visible as below :-
WebDriverWait wait = new WebDriverWait(driver, 10);
WebElement el = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("dontAsk")));
May be this element is inside any frame or iframe. If it is, you need to switch that frame or iframe before finding the element as below :-
WebDriverWait wait = new WebDriverWait(driver, 10);
//Find frame or iframe and switch
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt("your frame id or name"));
//Now find the element
WebElement el = wait.until(ExpectedConditions.visibilityOfElementLocated(By.id("dontAsk")));
//Once all your stuff done with this frame need to switch back to default
driver.switchTo().defaultContent();
Edited :
I havent tried the iframe yet because I am not sure what I am doing I havent used this tool much. The html code for the iframe is : <iframe id="d2l_1_69_954" class="d2l-iframe d2l-iframe-fullscreen d2l_1_67_746" name="d2l_1_69_954" src="/d2l/lms/remoteplugins/lti/launchLti.d2l?ou=6606&plugin‌​Id=f8acc58b-c6d5-42d‌​f-99d9-e334f825c011&‌​d2l_body_type=3" title="TALLPOD" scrolling="auto" allowfullscreen="" onload="this.m_loaded=true;" style="height: 314px;" frameborder="0"> how do you locate this iframe using your example above?
Looks like iframe id and name both are dynamically generated which could be change every time when you locate, you should try to locate this iframe with unique locator, I think it's title name is unique and fixed so you should try to locate this iframe before locating desired element as :-
wait.until(ExpectedConditions.frameToBeAvailableAndSwitchToIt(By.cssSelector("iframe[title='TAFEPOC']"));

How can I find the body of TinyMCE editor using CSS selectors in Selenium?

I am trying to find an element on a page using Selenium. Here is some example content:
<body id="tinymce" class="mceContentBody " contenteditable="true" dir="ltr" style="overflow: auto;">
Here is how I am trying to select it:
driver.findElement(By.cssSelector("body#tinymce")).sendKeys("Hello, everyone!! Don't worry it is a test letter to check connection!!");
I do not get an element returned though.
It looks like you are testing against TinyMCE editor.
The issues are:
It's in an iframe, you need to switch into to the iframe first.
You need to send keys to <body> element (not <input>) inside that iframe
Here is what to do:
// switch to iframe, use locator of your choice, "#editMe_ifr" here as an example
WebElement editorFrame = driver.findElement(By.cssSelector("#editMe_ifr"));
driver.switchTo().frame(editorFrame);
WebElement body = driver.findElement(By.TagName("body")); // then you find the body
body.sendKeys(Keys.CONTROL + "a"); // send 'ctrl+a' to select all
body.SendKeys("Some text");
Further reading:
Interact with a cute editor using webdriver
Using C# with selenium and cleditor.
You can change your HTML to this:
<body>
<input id="tinymce" type="text"/>
</body>
And you can change the selector from body#tinymce to #tinymce. You shouldn't need to specify the tagname when using id because the id should be unique anyway.

Categories