Selenium Webdriver - (Java) - Click a button with dynamic ID - dynamic

1) I have a dialog on my web page having 2 buttons, Yes & No.
2) IDs of these buttons are dynamicaly changing every time.
3) How to handle this situation and click on Yes button?
4) Both buttons, Yes & No, have same classname 1.e. rwInnerSpan
5) Here is the Xpath for Yes button
(.//*[#id='confirm1381468352443_content']/div/div[2]/a[1]/span/span)
the part 1381468352443 in xpath is dynamically changing.
Below is the source code of page
`
<tr class="rwTitleRow">
<tr class="rwContentRow">
<td class="rwCorner rwBodyLeft"> </td>
<td class="rwWindowContent" valign="top">
<iframe frameborder="0" name="confirm1381468352443" src="javascript:'<html></html>';" style="width: 100%; height: 100%; border: 0px none; display: none;" tabindex="0">
<div id="confirm1381468352443_content">
<div class="rwDialogPopup">
<div class="rwDialogText">
<div>
<a class="rwPopupButton" href="javascript:void(0);" onclick="$find('confirm1381468352443').close(true);" tabindex="-1">
<span class="rwOuterSpan">
<span class="rwInnerSpan">Yes</span>
</span>
</a>
<a class="rwPopupButton" href="javascript:void(0);" onclick="$find('confirm1381468352443').close(false);" tabindex="-1">
<span class="rwOuterSpan">
<span class="rwInnerSpan">No</span>
</span>
</a>`
Thanks in Advance !!

You can directly check for the text in your Xpath:
driver.findElements(By.xpath("//a[#class='rwPopupButton']/span/span[contains(text(), 'Yes')]"))

There is a way to locate objects using partial link text, so you can try this:
driver.findElement(By.partialLinkText("Yes")).click();
Plain By.linkText may not work because of additional spaces or characters in the link.

You can click on the button based on the Text. Following method will give you a webelement based on the class locator and text.
WebElement getElementBasedOnClassAndText(String classLocator, String text){
List<WebElement> elements = driver.findElements(By.className(classLocator))
for(WebElement element : elements){
if(element.getText().contentEquals(text)){
return element
}
}
Assert.fail("Unable to find any element with the said Text")
}
Once you get the element you can take any action on it.

Since it is dynamic I would look for the changed name:
//Find the dynamicly created ID
String dynamicID = driver.findElement(By
.xpath("//iframe[contains(#name,'confirm')]")
.getAttribute("name");
//Use that ID to find the Yes option
driver.findElement(By
.xpath("//*[#id='"+dynamicID +"_content']/div/div[2]/a[1]/span/span")
.click();

Related

Selenium webdriver can't find xpath

element code:
<div class="col col-2"><div class="v-input v-input--is-focused theme--light v-text-field v-text-field--is-booted v-select primary--text"><div class="v-input__control"><div role="button" aria-haspopup="listbox" aria-expanded="false" aria-owns="list-65" class="v-input__slot"><div class="v-select__slot"><label for="input-65" class="v-label v-label--active theme--light primary--text" style="left: 0px; right: auto; position: absolute;">Narystė</label><div class="v-select__selections"><input id="input-65" readonly="readonly" type="text" aria-readonly="false" autocomplete="off"></div><div class="v-input__append-inner"><div class="v-input__icon v-input__icon--append"><i aria-hidden="true" class="v-icon notranslate material-icons theme--light primary--text">arrow_drop_down</i></div></div><input type="hidden" value="[object Object]"></div><div class="v-menu"><!----></div></div><div class="v-text-field__details"><div class="v-messages theme--light primary--text"><div class="v-messages__wrapper"></div></div></div></div></div></div>
in screen you can see, that entered xpath is only one.
Here is code, where i have entered the same xpath, but getting error like this:
private static final By naryste = By.xpath("//*[contains(#class,'v-label v-label--active theme--light primary--text') and contains(text(),'Narystė')]");
#Step("Pasirenkame juridinio asmens organizaciją iš reikšmių sąrašo")
public createOrganization selectMembership() {
button.click(naryste);
return this;
}
Selenium webdriver can't find this xpath:
Find element :By.xpath: //*[contains(#class,'v-label v-label--active theme--light primary--text') and contains(text(),'Narystė')]
P.S. the same problem if i choose other elements
AND this (selenium can't find)
To locate the element you can use the following Locator Strategy:
Using xpath:
By.xpath("//label[starts-with(#for,'input') and contains(.,'Narystė')]");
PS: Do add some waits before invoking the click()

xpath with Multiple condition in Selenium

Wants to locate element with multiple condition on particular row,
I want to Click on div which contains ng-click="condition001" which has parent link contains Auto-001
So query become like : Select element xpath("//div[contains(#ng-click,'condition001')]") where Link("Auto-001")
<tr ng-repeat="(abc, xyz)" ng-show="data.length > 0">
<td class="x001">
<div class="x002">
<a class="x003" href="#">Auto-001</a>
</div>
</td>
<td class="x004">
<div class="x005">
<div class="x006">
<div class="x007" ng-click="condition001" tabindex="0">
<i class="x008"></i>
</div>
</div>
</div>
</td>
</tr>
Please suggest relevant xpath code which can work for above criteria,
To click on the WebElement identified through xpath as ("//div[contains(#ng-click,'condition001')]") where it has partialLinkText as ("Auto-001") you can use the following line of Java code :
WebElement myElem = new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//a[#class='x003' and contains(.,'Auto-001')]//following::td[1]//div[#class='x007' and #ng-click='condition001']")));

Selenium - Multiple anchor - Same ID - Not able to fetch

I want to click on anchor tag whose class id is clsArrowClick and the same id is on another anchor tag.
<td class="text-center" style="width: 25% !important;">
<td class="arrow" data-toggle="tooltip" data-container="body" title=""
style="width: 25% !important; text-align:center" data-original-
title="Select/Show Data">
**<a id="clsArrowClick" class="clsarrowClick" href="#"
onclick="javascript:OpenAddNewWellPopup(this);">
<i class="fa fa-arrow-right"/>
</a>**
<input id="hdnIsSaved0" class="hdnIsArrowSaved" value="0" type="hidden"/>
</td>
</tr>
<tr id="2">
<td style="width:50%; class=" '="" data-container="body" data-
toggle="tooltip" title="" data-original-title="abcd">abcd</td>
<td class="text-center" style="width: 25% !important;">
<td class="arrow" data-toggle="tooltip" data-container="body" title=""
style="width: 25% !important; text-align:center" data-original-
title="Select/Show Data">
**<a id="clsArrowClick" class="clsarrowClick" href="#"
onclick="javascript:OpenAddNewPopup(this);">
<i class="fa fa-arrow-right"/>
</a>**
<input id="hdnIsSaved1" class="hdnIsArrowSaved" value="0" type="hidden"/>
</td>
I tried list, wait method and simple way everything, but my program throws an error
Exception in thread "main" org.openqa.selenium.ElementNotVisibleException
Like
//WebDriverWait wait = new WebDriverWait(driver,30);
//wait.until(ExpectedConditions.presenceOfElementLocated(By.className("clsArrowClick")));
//driver.findElement(By.className("clsarrowClick"));
driver.findElement(By.xpath("(.//*[#id='clsArrowClick'])[1]")).click();
Try following xpaths might work for second link. I haven't tested that and I don't know the whole html of your page so I said might.
//a[#id='clsArrowClick'][2]
or this one
//input[#id='hdnIsSaved1']../a[#id='clsArrowClick']
or following if you are interested in clickin first link
//td[#class='arrow']/a[#id='clsArrowClick']
In your code you are using presenceOfElementLocated condition before finding the element. An important thing to note is that presenceOfElementLocated only checks for presence of element on DOM, irrespective of it's visibility. You need to make sure that the element you are fetching is visible, so for that you should use ExpectedConditions.visibilityOfElementLocated. visibilityOfElementLocated guarantees that the element is available on the DOM and also visible, so that will help in overcoming the org.openqa.selenium.ElementNotVisibleException you are facing.
So your code should look something like this:
WebDriverWait wait = new WebDriverWait(driver,30);
wait.until(ExpectedConditions.visibilityOfElementLocated(
By.xpath("(.//*[#id='clsArrowClick'])[1]")));
driver.findElement(By.xpath("(.//*[#id='clsArrowClick'])[1]")); //this step can be skipped
driver.findElement(By.xpath("(.//*[#id='clsArrowClick'])[1]")).click();
As mentioned by alessandro-da-rugna, the id should be unique and I think it should be fixed. Selenium also have limitation in terms of find element, if there are two or more elements, it will choose the first one that present, regardless it is visible or not, which click method requires the element to be visible and enabled
To solve this, there are several ways
Make sure your xpath is unique, so you get , for example //a[::following-sibling/input[#id='hdnIsSaved1']] when you find element
As mentioned by jayesh Doolani, you could use
WebElement myElement = wait.until(ExpectedConditions.elementToBeClickable(By.xpath())
myElement.click()
The second way is to use find elements, then find which element that meet your criteria, by checking its attribute, and make sure element clickable, by checks the enable method. Then do click on element that match your criteria
element = driver.findElement(By.xpath("html/body/div[9]/div/div/div[3]/button[2]"));
js = (JavascriptExecutor)driver;
js.executeScript("arguments[0].click();", element);
element = null;
js = null;

Selenium VBA select option input element

I'm using Excel VBA, Selenium and Chrome.
Threse is a dropdownbox box and I'm trying to select an option. Html code is:
<div class="x-form-field-wrap x-form-field-trigger-wrap x-abs-layout-item x-trigger-wrap-focus" id="ext-gen437" style="width: 100px; left: 330px; top: 70px;">
<input maxlength="1" spellcheck="false" id="ext-comp-1233" name="CITTADINANZA" class="x-form-text x-form-field x-field-uppercase x-trigger-noedit x-form-focus" readonly="" style="width: 75px;" />
<img src="data:image/gif;base64,R0lGODlhAQABAID/AMDAwAAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==" alt="" class="x-form-trigger x-form-arrow-trigger" id="ext-gen438" />
</div>
The dispalyed text options are "Si" and "No" but in Html code there are no options, index, value...(it's just an input element; the img element is the arrow you have to click for a dropdown)
I tried to fill the input element using:
driver.FindElementByCss("#ext-comp-1233").AsSelect.SelectByIndex
driver.FindElementByCss("#ext-comp-1233").AsSelect.SelectByValue
driver.FindElementByCss("#ext-comp-1233").AsSelect.SelectByText
driver.FindElementByCss("#ext-comp-1233").Sendkeys
but I recive the error:
"Unexpected TagName Error.
Expected=select
Got=input"
...while Sendkeys doesn't work.
Do you have any idea?
Thanks :)
Try this:
obj.FindElementByXPath("xpath of element").AsSelect.SelectByText ("option text")
Note:
driver - name of the object you've created for webdriver.
The solution is to click on the drop down image, and when the dynamically created divs are displayed, click on those divs.

Webdriver selenium java partial xpath with contains- can't click element

I am trying to click on an element using partial xpath. I can't use ID because there are more than one elements with the same ID. I know my xpath is correct because when I enter it in firepath it highlights the correct element.
Here is my HTML code:
<div class="acme_color_swatches">
<div class="acme_color_swatch " data-color="#CC0000" style=" background-color:#CC0000"></div>
<div class="acme_color_swatch " data-color="#F9F9F9" style=" background-color:#F9F9F9"></div>
<div class="acme_color_swatch" data-color="#990000" style=" background-color:#990000"></div>
<div class="acme_color_swatch" data-color="#FAFAC5" style=" background-color:#FAFAC5"></div>
<div class="acme_color_swatch selected" data-color="#333333" style=" background-color:#333333"></div>
<div class="acme_color_swatch " data-color="#F2F2F2" style=" background-color:#F2F2F2"></div>
<div class="acme_color_swatch " data-color="#F7F7F7" style=" background-color:#F7F7F7"></div>
<div class="acme_color_swatch" data-color="#CB0000" style=" background-color:#CB0000"></div>
<div class="acme_color_swatch " data-color="#DDDDDD" style=" background-color:#DDDDDD"></div>
<div class="acme_color_swatch " data-color="#E2F2FF" style=" background-color:#E2F2FF"></div>
<div class="acme_color_swatch" data-color="#F5F5F5" style=" background-color:#F5F5F5"></div>
<div class="acme_color_swatch" data-color="#0069FF" style=" background-color:#0069FF"></div>
Here is my selenium code:
driver.findElement(By.xpath("//div[contains(#style, '#0069FF')]")).click();
Here is the error I am getting:
FAILED: main
org.openqa.selenium.NoSuchElementException: Unable to locate element {"method":"xpath","selector":"//div[contains(#style, '#0069FF')]"}
What am I doing wrong?
I find the cssSelector easier and more reliable and it will likely work for you in this case. You can try something like this:
By.cssSelector("div[style$='#0069FF']");
This will find any div that has a style-attribute that ends with #0069FF.
You could use
driver.findElement(By.cssSelector("div[data-color='#0069FF']")).click();
It's looking for a DIV that has a data-color attribute = #0069FF.
I was able to resolve this issue by myself. Here is what I did:
driver.findElement(By.xpath("//div[contains(#style, ' background-color:#FAFAC5')]")).click();
There is a space between the hyphen and the ' background-. This was causing all of the grief.
These div are an array, so you can use:
driver.findElement(By.xpath("(//*[#class='acme_color_swatch'])[11]")).click();
to click on the 11th element which class is acme_color_swatch.
I think you need to use some logic here. Try to find the all webelements with classname and then find your specific color. Try the code below:
public void Findelement() throws InterruptedException {
WebElement element = driver.findElement(By.classname("acme_color_swatch"));
String Color = "#0069FF";
if (element.contains(Color)){
element.click();
}
}