How can I find an element with unconstant id and name? - selenium

Well, I am new to selenium and trying to automate some form pages.
I was trying to locate and select the field below I pasted, but name and ID are changing every time the page loads. Is there any way to select that field with selenium?
I am using python btw in case that changes anything.
<dd>
<input type="text" class="input" name="0e9c304b1edf4e01c023790b6ee5442ac6663bf6" autocomplete="username" required="required" autofocus="autofocus" maxlength="25" id="_xfUid-4-1583549932">
</dd>

You can use the following xpath:
//dd/input[#class='input']
if there are other inputs then
//dd/input[#class='input'][1]
or you can try
//dd/input[#autocomplete='username']

Related

Splinter Is it possible to use browser.fill without name as a query

I would like to use an absolute xpath to fill in a search bar. The ids and classes are dynamically generated and there is no name variable or instance. So it feels like I'm stuck without a tool to fill in boxes without the named variable.
Is there a way around this? Can I somehow change the absolute xpath to look like its a name assignment and then query and fill based on the new 'type' I assigned the absolute xpath?
Is there a method for this in Selenium if not available in Splinter?
I've select by CSS and I'm finding this error 'selenium.common.exceptions.InvalidElementStateException: Message: Element is not currently interactable and may not be manipulated'
Edit:
<div class="type-ahead-input-container" role="search">
<div class="type-ahead-input-wrapper">
<div class="type-ahead-input">
<label class="visually-hidden" for="a11y-ember10393">
Search
</label>
<!---->
<input id="a11y-ember10393" class="ember-text-field ember-view" aria-
autocomplete="list" autocomplete="off" spellcheck="false"
placeholder="Search" autocorrect="off" autocapitalize="off" role="combobox"
aria-expanded="true" aria-owns="ember11064" data-artdeco-is-focused="true"/>
<div class="type-ahead-input-icons">
<!---->
</div>
</div>
<!---->
</div>
</div>
As you have asked Is there a method for this in Selenium, the Answer is Yes.
Selenium supports Sikuli. Sikuli automates anything you see on the screen. It uses image recognition to identify and control GUI components. It is useful when there is no easy access to a GUI's internal or source code.
You can find more about Sikuli here.
Let me know if this answers your question.
When you get an error-message like that, it could be that your search result is not what you expected. It could be that you are getting more than one result, ie a list. On a list you can not input.
You can find the input boxes with an xpath, select the prefered one from the list (by trying) and put a text in it with the WebDriverElement _set_value method. That is not appropriate because of the _, but it is usefull.
input_list = browser.find_by_xpath('//div[#class="type-ahead-input"]/input[#class="ember-textfield ember-view"]')
input_list[1]._set_value('just a text to see whether it is working')

Checkbox id keeps changing in webpage causing selenium script to fail

I am trying to automate a click on a certain checkbox. However after every run the checkbox id changes and script fails to find the element. Is there an alternate way of writing an xpath
<span id="field_key$0993573c-83b4-30d4-9139-44e44b496d0f$1food_contamination-checkbox" class="v-checkbox v-widget" ca-help-field-id="undefined">
<input id="gwt-uid-193" type="checkbox" value="on" tabindex="0" checked=""/>
<label for="gwt-uid-193"/>
</span>
xpath I used was this:
//*[#id='gwt-uid-193']
If the parent <span> id is fixed you can use it and go one level down to the checkbox
driver.findElement(By.cssSelector("#field_key$0993573c-83b4-30d4-9139-44e44b496d0f$1food_contamination-checkbox > input"));
Or use the parent class
driver.findElement(By.cssSelector(".checkbox > input"));
And if you have only one checkbox you can use the type attribute
driver.findElement(By.cssSelector("[type='checkbox']"));
I found a solution myself. We can use xpath based on the position of the checkbox, i.e.:
// input[#type='checkbox'])[position()=3]
This can be used for radio buttons as well. Replace checkbox with radio.

how to create xpath for the following check box

I am finding it hard to create a relative xpath for a check box . I have attached the code snippet below. Firebug gives me an absolute xpath as:
html/body/div[6]/div[2]/form/table[1]/tbody/tr[3]/td[1]/input[1].
But the form changes if there is separate entry and then absolute xpath changes to:
html/body/div[6]/div[2]/form/table[1]/tbody/tr[4]/td[1]/input[1]
(or tr[5] or any number). I tried to use the relative xpath but the firebug shows the xpath in red colour (so it is invalid)-
.//*[#id='responderSelection'155939'1']
Please help.
<form id="pollGroupForm" method="post" action="/consoleapp/newSurvey.jspx">
<div class="filter"/>
<table class="dataTable">
<tbody>
<tr>
<tr class="alternateRow">
<tr>
<td>
<input id="responderSelection'155939'1" type="checkbox" value="true" name="responderSelection['155939']"/>
<input type="hidden" value="on" name="_responderSelection['155939']"/>
</td>
<td>twoway_2</td>
<td> 26161 </td>
<td>
</tr>
</tbody>
</table>
<table>
</form>
</div>
</div>
<div id="footer">
Would you try a partial search using cssSelector? I assume the numbers with the id is dynamic so the following cssSelector let's you find the checkbox with the partial match of the id(^ means starts with)
[id^='responderSelection']
If you really want xpath then contains() is the equivalence to the css above
//input[contains(#id,'responderSelection')]
There are several different ways to do this, depending on the exact conditions.
If there is only on checkbox in that table, then you can focus on that: //table//input[#type='checkbox'].
Possibly safer selector would be to look for a checkbox in your form, as that has a fixed id attribute: //form[#id='pollGroupForm']//input[#type='checkbox']. If you can, always start from fixed ids.
If you want to get the Xpath of an element which ID is changing dynamically, there is a little trick: simply inspect the element with Firebug, delete its ID by double clicking on it (delete the whole id parameter, or change the value to "")and you will get the correct Xpath.
For example if you have the following structure:
<div id="fix-id">
<div id="dynamic-id-1214151"></div>
</div>
You will get //*[#id="fix-id"]/div[1] instead of //*[#id="dynamic-id-1214151"].

Can't select label by text when label contains more than text

I am driving myself bonkers with this.
I have three form fields in a form:
Customer: required dropdown field
Weight: required text field
Status: optional text field
Each element has that label. The required fields' labels contain a span with an asterisk.
I'm using Xpather in Chrome. When I search for this, I receive 2 results, when I should get 3:
//*[contains(text(),'t')]
This makes no sense to me At All.
Customer, which is working:
<label for='customer-field'>
<span class='required-marker'>*</span>
Customer
<input id='customer-field' type='text' />
</label>
Weight, which is not working:
<label class='control-label'>
<span id='ctl01_requiredMarker' class='required-marker'>*</span>
Weight
</label>
Status, which is working:
<label class='control-label'>
Status
</label>
The only workaround that works for me is removing the required marker from the Weight label container. However, that doesn't explain how "Customer" gets matched at all.
Noteworthy: I'm trying to automate testing this page, so I can't really remove that span tag.
What's going on? And/or what do I do?
Try changing your XPath to the following:
//*[text()[contains(.,'t')]]
The source of this fix breaks it down far better than I could've done, so refer to that for detailed explanation! I've tested it myself using the XPath Checker extension for Firefox, and it matches your three items.
Try with the below method
driver.findElement(By.xpath("//span[#class='required-marker']/..")).getText().contains("Weight")
Please Let me know above method is working or not.
I think your html is where the issue lies.
This is probably what your html should look like:
<span class='required-marker'>*
<label for='customer-field'>Customer</label>
<input id='customer-field' type='text' />
</span>
<span id='ctl01_requiredMarker' class='required-marker'>*
<label class='control-label'>Weight</label>
</span>
<label class='control-label'>Status</label>
Are you using Selenium or WebDriver? What does WebDriver return as a response? Also make sure you add a "." before the xpath like .//*[contains(text(),'t')]
What does this print?
List<WebElement> elements = driver.findElement(By.xpath(".//*[contains(text(),'t')]"));
s.o.p(elements.size());

Does RFT have equivalent for jQuery .next() ?

I need to make work select in RFT in case the select is done via jQuery AJAX select where the html code looks like
<select style="display: none;" id="_campus_id" name="_campus_id">
<option id="CAMPUS1" value="1">camp</option>
<option id="CAMPUS2" value="2">camp2</option>
</select>
<input aria-haspopup="true" aria-autocomplete="list" role="textbox" autocomplete="off" class="ui-autocomplete-input ui-widget ui-widget-content ui-corner-left">
<button aria-disabled="false" role="button" class="ui-button ui-widget ui-state-default ui-button-icon-only ui-corner-right ui-button-icon" title="Show All Items" tabindex="-1">
<span class="ui-button-icon-primary ui-icon ui-icon-triangle-1-s"></span><span class="ui-button-text">
</span>
<button>
I need to "go" to input box and type text then "press" {DOWN} and {ENTER}. I have this part ready but the input box doesn't have any unique id so I want to find the input box based on the select which got property ID.
It would be possible using something like getNext() but I guess it doesn't exist in RFT.
Any other idea how to make this work? In case there are more than one AJAX selects on the page?
Is it the child of a specific unique object, say, a div or a form? If so, you can use the find() method to search for the child of a specific object.
Is the string "ui-autocomplete-input ui-widget ui-widget-content ui-corner-left" unique among objects of that type? You can do a find() to get all the input boxes and then loop through them checking the properties with getProperty() until you're sure you have the right one. This can be combined with the above suggestion.
Confirmed with IBM support that RFT doen't have any equivalent to jQuery .next() method as per current version. I created a ticket for an enhancement.
You can get everything from the select box and use some regular expression to search for keywords or a full sentance in that pick that as your option.