I have a div like this:
<div class="alert alert-danger">Please enter an email address</div>
I want to write a XPath expression such that if the div contains Please enter an email address and class is exact equal to alert alert-danger it should return me the element. Currently I have this xpath "//*[contains(text(),'Please enter an email address')]"
How do I add this condition so it only returns if the class attribute is "alert alert-danger". If it contains "alert alert-danger hello" it should not return i.e it should do a n equal match and not a LIKE match
//div[#class="alert alert-danger"][.="Please enter an email address"]
you can use 'and' and chain the conditionals, for example:
"//*[contains(text(), 'Please enter an email address') and #class='alert alert-danger']"
Related
How to access "Testing Field 1" from Label without using contains or adding span tag in Xpath
<label id="138:" for="136:" class="rcmFormFieldLabel">
<span class="requiredField" aria-hidden="true" role="presentation">*</span>
Testing Field 1
</label>
my xpath
//label[contains(text(),'Testing Field 1')]/ancestor::div[1]//select
but my xpath have contains which i dont want
You can use these XPath-1.0 expressions:
This
//label/*/following-sibling::text()[normalize-space()]
Or this
//label/text()[normalize-space()]
Result in both cases is
Testing Field 1
<ul>
<li class="xyz">
<div class="divClass">
<span class="ContentItem---status---dL0iS">
<span>Success</span>
</span>
<p class="ContentItem---title---37IqA">
<span>Test Check</span>
: Please display the text
</p>
</div>
</li>
<li class="xyz">
<div class="divClass">
<span class="ContentItem---status---dL0iS">
<span>Not COMPLETED</span>
</span>
<p class="ContentItem---title---37IqA">
<span>Knowledge</span> A Team
</p>
</div>
</li>
.... and so on
</ul>
This is my html structure.I have this text Test Check inside a Span and : Please display the text inside a Paragraph tag.
What i need is ,i need to identify, whether my structure contains this complete text or not Test Check: Please display the text.
I have tried multiple ways and couldn't identify the complete path.Please find the way which i have tried
//span[text()='Test Check']/p[text()=': Please display the text']
Can you please provide me the xpath for this?
I think there is one possible solution to identify within the given html text and retrieve. I hope this solves your problem.
def get_tag_if_present(html_text):
soup_obj = BeautifulSoup(html_text,"html.parser")
test_check = soup_obj.find_all(text = re.compile(r"Test Check"))
result_val = "NOT FOUND"
if test_check:
for each_value in test_check:
parent_tag_span = each_value.parent
if parent_tag_span.name == "span":
parent_p_tag = parent_tag_span.parent
if parent_p_tag.name == "p" and "Please display the text" in parent_p_tag.get_text():
result_val = parent_p_tag
break
return result_val
The returned result_val will have the tag corresponding to the p tag element with the parameter. It would return NOT FOUND, if no such element exists.
I've taken this with the assumption that the corresponding data entries would exist in a "p" tag and "span" tag respectively , feel free to remove the said conditions for all identifications of the text in the given html text.
I'm working with a web page with the following HTML where I want to identify the first <input> field inside the <span> using a text_field from within a page-object.
<div id="131:"> Please enter your name:
<span class="autocompspan " style="position:static;">
<input style="position: static;" class="autocompinput yui-ac-input" id="132:" name="132:"
onfocus="juic.fire("132:","_focus",event);"
onchange="juic.fire("132:","_despatchChange",event);"
onblur="juic.fire("132:","_blur",event);" size="60"
onkeydown="juic.fire("132:","_onkeydown",event);"
onkeyup="juic.fire("132:","_onkeyup",event);" aria-disabled="false" value=""
role="combobox" aria-autocomplete="list" aria-owns="132:_divList"
aria-activedescendant="132:_divAD" findtype="proxy" delimchar="" hideusername="false"
fetchusername="false" autocomplete="off" type="text">
<input value="" id="132:_hidden" name="132:_hidden" type="hidden">
</span>
</div>
If I use :id => '132:' to identify the field things work fine. I.e. text_field(:target_user_name, :id => '132:' ) works.
The issue is that this HTML is generated by the underlying app (SAP) which does not always generated the same value for the <input> field id so using the id cannot be relied upon to consistently identify the element.
So, given the above HTML what other ways might I go about reliably finding this <input> field.
I've tried the following, none of which work. Most of them time out waiting for the element to be located.
text_field(:target_user_name, :xpath => "//*[#class='autocompinput yui-ac-input' and #role = 'combobox']" )
text_field(:target_user_name, :xpath => "//*[#class='autocompinput' and #role = 'combobox']" )
text_field(:target_user_name, :xpath => "//span/input[#class='autocompinput yui-ac-input' and #role = 'combobox']" )
text_field(:target_user_name, :xpath => "//input[#class='autocompinput yui-ac-input' and #role = 'combobox']" )
text_field(:target_user_name, :class => 'autocompinput yui-ac-input')
Any thoughts?
When an element does not have unique identifiable attributes, you should look at the elements around it. In this case, there is user visible text that helps a user identify the purpose of the field. That same text can be used to identify the element in Watir.
As the surrounding div only contains the labelling text, you can search for that div by its text and get the only text field in it:
browser.div(text: 'Please enter your name:').text_field
As a page-object accessor:
text_field(:target_user_name) { div_element(text: 'Please enter your name:').text_field_element }
Firstly, Watir is designed to make it so that you shouldn't have to use XPATH.
It depends on how many different elements/ids are on the page, but I've found that using regular expressions often works well with dynamically generated ids. So either grab the id and use it elsewhere:
id = browser.text_field(id: /\d\d\d/).tr(':', '')
or just use it directly:
text_field(:target_user_name, id: /\d\d\d:/)
In this particular case you can check the first input field after 'Please enter your name:' text using below xpath:
//div[text()='Please enter your name:']//following::input[1]
In general if you encounter fields that does not have a unique identifier you can rely on static text or fields and then use xpath functions such as following, preceding etc.
How can i enter a text into a Editinplace element as shown below using PageObject:-
New Rule Name
as right now i have to click on the class="editInPlace" and sendkeys to it to enter some text into it
<div id="ruleContainer">
<div class="splitPanel basicInfo">
<div class="subPanel">
<div id="ruleName" class="editInPlace">New Rule Name</div>
</div>
Based on the example you provided you simply need to change the call to use the *_element generated method. Try this:
def name_rule
rule_name_element.send_keys "Test"
end
All element declarations will generate a method that has the pattern "name you provided"_element. This method will return the actual underlying html element that you can make calls on.
I have dropdown list with some universities and in case the user is in a university that isn't in the list he can add it with an input box. My issue is that after the user clicks the submit button I can't get the value from the dropdown.
My code in the view is:
echo "University:";
?>
<div id="university2" style="display:block;">
<?php
echo form_dropdown('university2',$this->session->userdata('user'));
echo " ";
echo "<a href= javascript:ShowContentuni('university')>Other</a>";
?>
</div>
<div id="university" style="display:none;">
<?php
echo form_input('university',$this->input->post('university'));?>
</div>
And my code in the controller is:
if(isset($_POST['university']))$university= $this->input->post['university'];
else if(isset($_POST['university2']))$university=$this->input->post('university2');
Any ideas what I'm doing wrong??
It looks like there are two problems:
always overriding the value of $university with the post value of 'university2', even if it is empty
the form has two inputs called university, only the second one is being referred to
A quick fix would be to first delete the second 'university' form element, i.e. delete this:
echo form_input('university',$this->input->post('university'));
Then check that the user if the user has manually entered a university name, and use that if so. If the user did not enter a university name, use whatever the dropdown value is. The code would look like this:
$universityFromDropdown = $this->input->post('university');
$universityFromManualInput = $this->input->post('university2');
$university = is_string($universityFromManualInput)
&& strlen($universityFromManualInput) > 1
? $universityFromManualInput : $universityFromDropdown;