Selenium (Python): Strategy for locating item with inconsistent Xpath - selenium

writing a Python selenium script to auto-populate many forms. On one particular form, I have to add the entry, then click the "Add Another" button in order add the next entry. I successfully located the "Add Another" button via find.element(By.XPATH, xx), which works on the first two iterations with an xpath that looks like this:
//*[#id="7d977bf8-9863-5be0-ab89-c90cff57953d"]/div[3]/div[2]/div[2]/div/div[1]/div/div[2]/button[1]
But it is unable to locate the button on the third pass through. I found that the xpath changed ever so slighty: The index of the second /div in the path changed from "2" to "6":
//*[#id="7d977bf8-9863-5be0-ab89-c90cff57953d"]/div[3]/div[6]/div[2]/div/div[1]/div/div[2]/button[1]
My immediate reaction was to code for a NoSuchElementException and if the original is not found, search for the second. But given the observed behavior, I'm not sure I can be certain it's just those two Xpaths. I may need to "Add Another" 40 or 50 times, I could end up with a block of code that tries 10 or 20 xpaths (I am not a web developer, so I have no idea why this change of path is happening, or when it may happen again on the same Form).
So I'm trying to come up with another method to locate this button. Here is the HTML:
<button class="grid-button" data-bind="click: function() { imagetrend.formComposer.controlHandlers.grid.addAnotherButtonClickHandler($context) }, css: { 'disabled' : imagetrend.FormComposer.isReadOnly($context) }, disableEvent: { 'click': imagetrend.FormComposer.isReadOnly.bind(null, $context) }"> <i class="fa fa-lg fa-plus"></i> Add Another </button>
I don't see any unique element in there that I can search by given what I know about Selenium: Tag, ID, CSS_Selector...I tried locating by the "fa fa-lg fa-plus" class, but that isn't found (I think I've deduced that's for the large plug sign in the button).
So is there some sort of bulletproof way I can find this element without coding for every potential xpath I find along the way? Thanks.

I didn't find an alternate method to identify that element, but found that with only that second /div index changing, a wildcard character suited my needs.
so it ended up as:
driver.find_element(By.XPATH,'//*[#id="7d977bf8-9863-5be0-ab89-c90cff57953d"]/div[3]/div[*]/div[2]/div/div[1]/div/div[2]/button[1]').click()
And that XPATH matches any instance of the button that may pop up.
Thanks to Prophet and Akzy for keeping me on my toes!

Related

How can I find my web element using the correct relative xpath

I am having trouble identifying a specific web element from the DOM. It is a button element, and there are 4 of them in the DOM, exact the same. The one that I need is the third one from the top.
So far I have written the following Xpath:
//button[#class='btn btn-success add-instrument']
This gives me 4 options. I have also tried:
//button[contains(text(), 'texthere')]
This also gives me 4 options. I have tried traversing from above and below, but that does not work either.
I want to: Index the third element, but can't get it to work.
What I have tried (with both options, mentioned above)
//button[contains(text(), 'texthere')]//[3]
I have also tried other indexes, but it finds nothing.
SOLVED BY USING:
"(//button[#class='btn btn-success add-instrument'])[3]"
Try this below xpath.It will identify the 3rd button.
"(//button[contains(text(), 'texthere')])[3]"
or
"(//button[#class='btn btn-success add-instrument'])[3]"

If multiple edit buttons is having same HTML coding how will I click the button in Selenium

I'm new to Selenium. Below is code:
<i _ngcontent-c13="" aria-hidden="true" class="fa fa-edit" style="color: green;cursor: pointer;"></i>
I have all edit buttons with the same type. How do I click on each of the buttons? Can anyone help me with the XPath?
EASY
Right click on element in browser > inspect > right click on the highlighted code > copy > copy xpath. Now we have the xpath so:
driver.findElement(By.xpath("paste_xpath")).some_action();
Let me know if this works, there are more other options to discuss + add the code block that contains all the buttons.
HARD
First we need to get the xpath, you can build it based on the formula:
Xpath=//tagname[#attribute='value']
Where:
// : Select current node.
Tagname: Tagname of the particular node.
#:Select attribute. Attribute: Attribute name of the node.
Value: Value of the attribute.
More details you can find HERE
Thanks,

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?

Selenium Web driver - Locate by Class name

I want to click on the search auto complete BUTTON in a webmail application.
<button class="_n_r ms-bg-color-themeLight-hover o365button _n_s ms-bg-color-themeLighter ms-font-color-neutralPrimary ms-border-color-themePrimary" type="button" autoid="_n_4" aria-label="Activate Search Textbox">
<span class="_n_u owaimg ms-Icon--search ms-icon-font-size-20 ms-fcl-ts-b"/>
<span class="_n_t ms-font-weight-semilight ms-font-color-neutralPrimary">Search Mail and People</span>
When clicking the BUTTON, we get this INPUT
<input class="_is_x ms-font-weight-semibold ms-font-color-neutralPrimary ms-bg-color-themeLight ms-bg-color-themeLight-hover allowTextSelection textbox ms-font-s ms-fwt-sl ms-fcl-np ms-bcl-nta ms-bcl-nsa-h hideClearButton" autoid="_is_3" role="combobox" aria-autocomplete="list" aria-label="Search mail and people, type your search term then press enter to search."/>
I'm getting the following error while trying to use the class name from the input.
"The given selector _n_r ms-bg-color-themeLight-hover o365button _n_sms-bg-color-themeLighter ms-border-color-themeLighter is either invalid or does not result in a WebElement. The following error occurred: InvalidSelectorError: Compound class names not permitted"
We tried to use selenium IDE to fetch the value, but we are getting only the xpath. Is there any way to locate autocomplete search field with out using the xpath?
That's a LOT of classes on that INPUT. :) I would use a different attribute. I would start with one of these and see which one works for you. You didn't specify the language you are using so here's some code in Java.
driver.findElement(By.cssSelector("input[autoid='_is_3']"));
driver.findElement(By.cssSelector("input[aria-label='Search mail and people, type your search term then press enter to search.']"));
Quick note since you were asking about classes. You can go the classes route and use CSS Selectors to find them. A simple example.
<button class="one two">
You can find the BUTTON above using
driver.findElement(By.cssSelector("button.one.two"));
A period (.) indicates a CSS class so you would need a period before each class name. You don't necessarily need to include all the classes, only enough to make the element unique so you can locate it.
CSS Selectors reference
CSS Selectors tips

How to get the xpath for the span button

I am new to selenium IDE and trying to get the target in the right order.
I have tried many combination to get the right element when there is span for the button. I need to get the xpath for the "Read More" button.Can someone please advise how the target in the IDE should be.
Here is the code:
<div class="is_centered l_bottom_pad">
<a class="btn_teal_outline has_arrow" href="https://test.com/jobs/view.php?id=8">
<span>Read More</span>
</a>
</div>
In some browsers (I think it was mainly MSIE) it is necessary to address the <a> element, not its child <span> in order to click a button or link. So you should adress:
//a[span[text()='Read More']]
Or you go directly for LinkText ("Read More") instead of XPath!
Targeting for span button is very simple. Just see what is unique attribute in that element.
I feel the button text itself is unique.Try this one
xpath=.//span[text()='Read More']