How do I locate makemytrip.com 'From City' input field in Selenium? - selenium

Below is the html details for the field:
<input type="text" autocomplete="off" role="combobox" aria-autocomplete="list" aria-owns="react-autowhatever-1" aria-expanded="true" class="react-autosuggest__input react-autosuggest__input--open" placeholder="From" value="">
Tried below for the same field but not working:
//div[#class='fsw_inputBox searchCity inactiveWidget activeWidget']/div/div/div/div/input

Here you go:
//input[#id='fromCity']
Just a suggestion, please try to avoid using indexes in your xpaths as much as possible. With indexes, in case if there is one more element added in the DOM(may be because of change in design or for some new feature addition) the xpaths may no more remain valid and will result in your script failure.

Please try with CSS selector
input[placeholder="From"]
Above selector will give you only one result.

Related

KarateUI - Finding inputs by placeholder attribute

I've been having trouble around finding elements by attribute/property. Following UI visible example:
<input tabindex="0" placeholder="www.stuff.com/example" type="text" id="sub-selector-37" class="form-control" value="">
The unique piece is the placeholder text.
I've tried the following:
And waitFor('input[placeholder=www.stuff.com/example]') - Error
And waitFor('input[placeholder="www.stuff.com/example"]') - Error
And waitFor('input[placeholder='www.stuff.com/example']') Finds nothing
Also tried a more direct input approach:
Then waitFor('{}Something else')
Then input('input[placeholder=www.stuff.com/example']', 'Stuff')
I'm hoping this is just good old PEBKAC on my part. Any suggestions would be greatly appreciated.
Here you go, use double-quotes and nest single-quotes:
And waitFor("input[placeholder='www.stuff.com/example']")
A tip: use the debugger and you can experiment with things like highlightAll('input') and narrow down what works: https://twitter.com/KarateDSL/status/1252817691963830272

A field in my app has 2 html codes. When I use OR in its Xpath then it is not detecting the Element. Can anyone help me making an appropriate xpath

A field in my application has two HTML codes. I want to use OR in its XPath so that in any HTML code the command can run. But I am unable to use OR in the xpath. It's not detecting the field when I use OR. Below are both the two HTML code. Can anyone make an XPath using OR so that it runs always?
First HTML Code-
<input autocomplete="off" class="text" maxlength="30" tabindex="2" type="password" id="pswd-input" name="password" onfocus=" pswdLabel.style.display='none';pswdWrap.style.margin='0' " onblur="if(this.value==''){pswdLabel.style.display='block';pswdWrap.style.margin='0 0 -14px'}else{pswdWrap.style.margin='0'} ">
and this is Second HTML code-
<input type="password" name="password" maxlength="35;" autocomplete="off" size="37" value="">==$0
Any help will be appreciated...
Try using Pipe (|) operator
driver.findElement(By.xpath("//input[#id='pswd-input'] | //input[#type='password']"));
You were pretty close:
driver.findElement(By.xpath("//input[#id='pswd-input' or #type='password']"));
but why do you need to OR when both versions have type="password" and name="password"? Wouldn't a simple By.name be better? It would match both of these elements:
driver.findElements(By.name("password"));

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

Xpath for checkboxes without IDs

What xpath can I use for something like this without using ID? Or if there are more checkboxes but IDs are still different after refreshing page?
<td class="player" style="vertical-align: top;">
<span class="gb-CheckBox">
<input id="gb-uid-120" type="checkbox" value="on" tabindex="0" style="background-color: rgb(255, 255, 255);">
<label for="gb-uid-120"></label>
</span>
</td>
Try following:
//span[#class="gb-CheckBox"]/input[#type="checkbox"]
Why not:
//input[#type='checkbox']
this should be enough and will select all inputs that are checkbox type.
If you need only from a certain area then you need to add a constraint by adding another selector in front of this like:
//div[#class='my_prefered_area']//input[#type='checkbox']
Another way of getting the selector would be to use the pare of the id that does not change like:
//input[contains(#id, 'gb-uid')]
Of course you can also add the restriction for checkbox type:
//input[contains(#id, 'gb-uid')][#type='checkbox']
Seems like you got the answer as most of the ways mentioned above are correct.
Correcting the first one path wit CSS :
td.player>span.gb-CheckBox>input[type='checkbox']
(try it removing the spaces before and after > )
Or
td.player>span.gb-CheckBox>input
Will also work.
As you mentioned, if your Id is changing frequently, that means its an dynamic webelement and
if it is changing at the end(after gb-uid- i.e. gb-uid-120, then gb-uid-121 something like this) then use contains function on Xpath as below:
//span[#class="gb-CheckBox"]/input[contains(#id, 'gb-uid-')]
You can also locate this checkbox easily using cssSelector instead of xpath which would be much faster as below :-
td.player > span.gb-CheckBox > input[type='checkbox']

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