XPath to input element near a label? - html

I am trying to reference a checkbox next to a label of a certain name containing an underscore.
An example DOM looks like
<div id="form-2143">
<div id="wrap-1353">
<label id="numberfield-1234-label">
<span class="x-form-label">admin_user&nbsp</span>
</label>
<input type="checkbox" id="checkbox-1353"
class="form-field" componentid="cb1353">
</div>
...
</div>
The aim is to select the input element so I can click it in Selenium.
The below XPath to my understanding should work
//label[span[contains(string(),"admin_user")]]../input
The problem is that the above works but only with 'admin' not 'admin_user'.
Using just with 'admin' gets multiple results. I can only guess it is to do with the '_' though it could easily be a quirk with the site i am testing.
I also can't guarantee the order of the label and input, hence the go up then down

An underscore (_) requires no special provision in XPath (sub)string testing.
Given your HTML corrected to be well-formed,
<div id="form-2143">
<div id="wrap-1353">
<label id="numberfield-1234-label">
<span class="x-form-label">admin_user </span>
</label>
<input type="checkbox" id="checkbox-1353"
class="form-field" componentid="cb1353"/>
</div>
...
</div>
this XPath,
//div[label[contains(., 'admin_user')]]/input
selects the input element contained within the div that contains a label whose string value contains the substring admin_user.

You have forgotten to make level up again
//label//span[contains(text(),'admin_user')]/../../input
For example: with two examples of "admin_user" and "admin_test"
<div id="form-2143">
<div id="wrap-1353">
<label id="numberfield-1234-label">
<span class="x-form-label">admin_user</span>
</label>
<input type="checkbox" id="checkbox-1353" class="form-field" componentid="cb1353">
</div>
<label id="numberfield-1234-label">
<span class="x-form-label">admin_test</span>
</label>
<input type="checkbox" id="checkbox-1353" class="form-field" componentid="cb1353">
</div>
</div>

Related

How to select input elements in form when only form id is unique?

I have the following form (using Forminator plugin) and I want to style it.
<form id="forminator-module-4712" class="forminator-ui forminator-custom-form forminator-custom-form-4712 forminator-design--default forminator_ajax" method="post" data-forminator-render="0" data-form-id="4712" novalidate="novalidate">
<div class="forminator-row">
<div id="email-1" class="forminator-col forminator-col-12 popup-email-field">
<div class="forminator-field"><input type="email" name="email-1" value="" placeholder="Email address" id="forminator-field-email-1" class="forminator-input forminator-email--field" data-required="true" aria-required="true">
</div>
</div>
</div>
<div class="forminator-row">
<div id="checkbox-1" class="forminator-col forminator-col-12 popup-checkbox">
<div role="group" class="forminator-field" aria-labelledby="forminator-checkbox-group-62f1212b1309c-label">
<label for="forminator-field-checkbox-1-1-62f1212b1309c" class="forminator-checkbox" title="I'd like my free gift!"><input type="checkbox" name="checkbox-1[]" value="TRUE" id="forminator-field-checkbox-1-1-62f1212b1309c" data-calculation="0" checked="checked"><span class="forminator-checkbox-box" aria-hidden="true"></span><span class="forminator-checkbox-label">I'd like my free gift!</span></label>
</div>
</div>
</div>
<input type="hidden" name="referer_url" value="">
<div class="forminator-row forminator-row-last">
<div class="forminator-col">
<div class="forminator-field">
<button class="forminator-button forminator-button-submit popup-submit">Sign Up</button>
</div>
</div>
</div>
</form>
The problem is, that I have another forminator form on the same site which I styled already.
I want to style the above form differently, but the element names (for buttons and inputs) are not unique.
Is there any way to select specific elements using CSS but in a unique way, so the styles are only applied to this specific form? How would I select email/submit button/etc on this form in a unique way?
I tried the following (but I'm missing something):
#forminator-module-4712 input.forminator-input[type="text"]
#forminator-module-4712 input#forminator-field-email-1
And other combinations.
I just needed element element selectors, this works:
#forminator-module-4712 input{}
Source: https://www.w3schools.com/cssref/sel_element_element.asp

XPath select input which occure before some div with different text

I got page with list of checkbox and labels assigned to them, its look like this:
x label1
x label2
x label3
As html it looks like this:
<div class="default-row">
<span class="row">
<input type="checkbox" value="on" id="gwt-uid-329" tabindex="0" >
<label for="gwt-uid-329"></label>
</span>
<div class="row-label" title="out1">test1</div>
</div>
<div class="default-row">
<span class="row">
<input type="checkbox" value="on" id="gwt-uid-321" tabindex="0" >
<label for="gwt-uid-321"></label>
</span>
<div class="row-label" title="out1">test2</div>
</div>
<div class="default-row">
<span class="row">
<input type="checkbox" value="on" id="gwt-uid-322" tabindex="0" >
<label for="gwt-uid-322"></label>
</span>
<div class="row-label" title="out1">test3</div>
</div>
And what I would like to achieve is to be able to select checkbox with specific label. Currently I got something like this:
//div[contains(text(), 'test1')]//preceding::input[#type='checkbox'][1]
but somehow it is selecting me first and last elements. 'test1' text is only placeholder, I am aiming for same xPath for each checkbox with only different label. Any ideas?
I can not change/add any new class names or id's.
Ok, so I just made some stupid mistake. Answer is:
//div[contains(text(), 'text1')]//preceding-sibling::span//input[#type='checkbox']
I will leave post. Maybe it will help someone. Cheers.

The for attribute of the label element must refer to a non-hidden form control

I have some errors in my code
Here is my error:
The for attribute of the label element must refer to a non-hidden form
control.
And myd code:
<form action="/search">
<span class="input input--hoshi search-wrapp main-page-open" style="display:block">
<input class="input__field input__field--hoshi" type="text" id="search" name="keyword" placeholder="Search..."/>
<label class="input__label input__label--hoshi input__label--hoshi-color-2" for="input-5">
<!--<span class="input__label-content input__label-content-hoshi">Search...</span>-->
</label>
<span class="icon-serch"></span>
</span>
<input id="search-btn" type="submit" style="display: none;"/>
</form>
What is wrong with it? Thanks!
The label for attribute must contain the input id value
<label for="foo">Foo:</label>
<input id="foo">
To omit the for and id attributes all-together, put input inside label
<label>
Foo: <input name="foo">
</label>
Also note, that input cannot be hidden <input type="hidden">, however it can be styled as hidden <input style="display:none">
The validator is expecting for your label's for field to target the id field of the input element that contains it. Here, that means that for="input-5" is expected to be for="search", as <input>'s id is search.
As you're expecting the user to add input to this field, you should be making sure they are linked to each other.

angularjs - custom DropDownList how to set default value checked

This is my HTML code. It's a custom DropDownList that I made. Can someone advise how I could set one of the options to be checked by default in this case below?
<div class="dropdownlistheader" ng-click="toggle('subdiv','item')">
<input type="text" readonly="readonly" class="dropdownlistinput" value="{{selectedItemValuesDisplay}}" />
</div>
<div id="ddl123" ng-show="showItemOptions" class="dropdownlist">
<div ng-show="showItemOptions" ng-repeat="option in ItemTypeDDL">
<input type="checkbox" ng-model="selected[$index]" ng-click="toggleItemSelection(option.TypeID, option.TypeName)"> {{option.TypeName}}
</div>
</div>
Based on the limited details provided in the questions, I'll suggest the following:
<div id="ddl123" ng-show="showItemOptions" class="dropdownlist" ng-init="selected[0] = true">
<div ng-show="showItemOptions" ng-repeat="option in ItemTypeDDL">
<input type="checkbox" ng-model="selected[$index]" ng-click="toggleItemSelection(option.TypeID, option.TypeName)"> {{option.TypeName}}
</div>
</div>
The ngInit directive will select the first element in the selected flags list, by setting the first index of the array to true

xpath advanced expression needed

I have the following code and I'm trying to isolate the radio buttons into two xpath expressions so I can click on them in nightwatch for QA.
Please keep in mind this page in particular has many other radio buttons so the expression needs to be specific to this. Also the reactid's are dynamic and change so can't hook into that. Much appreciated
<div class="form-group" data-reactid=".0.1.0.1.0.0">
<label class="control-label" data-reactid=".0.1.0.1.0.0.$label">
<span data-reactid=".0.1.0.1.0.0.$label.1" style="">Able to change e-mail</span>
</label>
<div class="wrapper" data-reactid=".0.1.0.1.0.0.$wrapper" style="">
<input type="radio" name="allow_change_email" checked="" data-reactid=".0.1.0.1.0.0.$wrapper.0:0" style="">
<span data-reactid=".0.1.0.1.0.0.$wrapper.0:1" style=""> Allow</span>
<br data-reactid=".0.1.0.1.0.0.$wrapper.0:2">
<input type="radio" name="allow_change_email" data-reactid=".0.1.0.1.0.0.$wrapper.0:3" style="">
<span data-reactid=".0.1.0.1.0.0.$wrapper.0:4" style=""> Disable</span>
</div>
This is one possible XPath : (formatted for readability)
//label[span='Able to change e-mail']
/following-sibling::div[1]
/input[#type='radio' and following-sibling::span[1][normalize-space()='Allow']]
explanation :
//label[span='Able to change e-mail'] : find label element where child span content equals "Able to change e-mail"
/following-sibling::div[1] : from such label, find the nearest following sibling div element
/input[#type='radio' and following-sibling::span[1][normalize-space()='Allow']] : from such div, return input element where type attribute equals "radio" and the nearest following sibling span equals "Allow"
xpathtester demo
output :
<input checked="" data-reactid=".0.1.0.1.0.0.$wrapper.0:0" name="allow_change_email" style="" type="radio"/>
First, you don't have valid XML.
If you manage to correct it you can use this:
//input[#type='radio']
'Corrected' XML:
<?xml version="1.0" encoding="utf-16"?>
<div class="form-group" data-reactid=".0.1.0.1.0.0">
<label class="control-label" data-reactid=".0.1.0.1.0.0.$label">
<span data-reactid=".0.1.0.1.0.0.$label.1" style="">Able to change e-mail</span>
</label>
<div class="wrapper" data-reactid=".0.1.0.1.0.0.$wrapper" style="">
<input type="radio" name="allow_change_email" checked="" data-reactid=".0.1.0.1.0.0.$wrapper.0:0" style="" />
<span data-reactid=".0.1.0.1.0.0.$wrapper.0:1" style=""> Allow</span>
<br data-reactid=".0.1.0.1.0.0.$wrapper.0:2" />
<input type="radio" name="allow_change_email" data-reactid=".0.1.0.1.0.0.$wrapper.0:3" style="" />
<span data-reactid=".0.1.0.1.0.0.$wrapper.0:4" style=""> Disable</span>
</div>
</div>
I found a solution for anyone else that may be in the same situation.
//*[text()="Able to change email"]/following::span[text()= " Allow"][1]/preceding-sibling::input[1]
For Allow:-
//div[#class='wrapper']/input[1][#type='radio']
For Disable:-
//div[#class='wrapper']/input[2][#type='radio']