Does RFT have equivalent for jQuery .next() ? - rft

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.

Related

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

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']

How to identify an element whose id is dynamically changing and has no other attributes in selenium?

I've this html body for a kendo dropdown list which has only one attribute i.e. id which is dynamically changing, how do i identify this object on every page refresh accurately.
other attributes like class and tab index already are present with same values multiple times on the same page for other dropdowns-
<span role="listbox" unselectable="on" class="k-dropdown-wrap k-state-default" id="dde13a91-2bf3-4e41-af72-bee1b881a8d9" dir="ltr" readonly="false" tabindex="0" aria-disabled="false" aria-readonly="false" aria-haspopup="true" aria-expanded="false" aria-owns="48f666d8-4c3c-43a8-a4dc-8e7a9961a0ef" aria-activedescendant="ca3c4431-3ebf-46c0-9510-a64a32eae108-C.US.0000110896">
<span unselectable="on" class="k-input">
<!---->
<!---->2018 ALBERTSONS / Beverage Mixes
</span>
<span unselectable="on" class="k-select">
<span class="k-i-arrow-s k-icon"></span>
</span>
<!---->
</span>
If there is a always present value in dropdown, You can try to find this value by text or something, and then get a parent:
XPath: Get parent node from child node
Other way is to get it by xpath of structure, like: div[3]/.../span etc. It is not good as every change can fail Your test, but if You have no other options, then You might want to try this.
To click on the element with the only attribute-text as 2018 ALBERTSONS / Beverage Mixes you need to induce WebDriverWait for the element to be clickable and you can use the following solution:
(Java) xpath:
new WebDriverWait(driver, 20).until(ExpectedConditions.elementToBeClickable(By.xpath("//span[#class='k-dropdown-wrap k-state-default' and #role='listbox']//span[#class='k-input']"))).click();
I found a workaround to locate the element:
First get the xpath of the span tag inside the dropdown using it's text as below:
//text()[contains(.,'2018 ')]
since '2018 ' is common irrespective of adjacent text
Then move up to the parent tag of the dropdown to locate the dropdown frame which can be collapsed on click:
//text()[contains(.,'2018 ')]/parent::/parent::
then simply click on the element which is located.
driver.findElement(By.xpath("//text()[contains(.,'2018 ')]/parent::/parent::")).click();

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.

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());