Python - Selenium - Get Parent Class - python

I have a website http://demoqa.com/registration/
I have been trying to verify that when a user clicks on and then clicks off a required field such as username or phone number that the error "required field" appears when no data has been entered.
Does anyone have any idea how to verify this? I was thinking
phone = self.driver.find_element_by_xpath("//div[contains(.,'Phone Number')]")
and then from that using something like getError = phone.find_element_by_xpath() and using the (..) to try and move up to the parent class, but with no luck!
I thought it would have been easy but all the elements have the same class name. I suppose I could check for the text "this field is required" but I'd like to keep it neat and write a method so I can use it on each of the fields.
I've spent alot of today searching for it and trying different thing, so any help or ideas would be great.
Thanks!
Other Info:
I can tell you what happens before and after i click the field. My best guess at attacking this issue would be to verify the class name of the field "phone number" and then once clicked off, verify that the class name has changed. As you can see on top is before a click off and below is when the required field text appears
<div class="fieldset">
<label class="" for="phone_9">Phone Number</label>
<input id="phone_9" class="input_fields piereg_validate[required,custom[phone_international]]" type="text" value="" placeholder="" name="phone_9">
</div>
<div class="fieldset error">
<label class="" for="phone_9">Phone Number</label>
<input id="phone_9" class="input_fields
piereg_validate[required,custom[phone_international]]" type="text" value=""
placeholder="" name="phone_9">
<div class="legend_txt">
<span class="legend error">* This field is required</span>
</div>
</div>

I have my solution *i think
seeing how the "div class name" changes when the required message appears I have a solution. I first find the element, get it's parents name by going up one level using the (..), i verify it's as it should be named "fieldset". I think trigger the error message, and repeat the process but make sure the "fieldset" has changed to "fieldset error"
getElementBase = self.driver.find_element_by_id('phone_9')
getElementClassRoot = getElementBase.find_element_by_xpath('..')
getElementClassRootName = getElementClassRoot.get_attribute('class')

Try to use below piece of code:
from selenium.common.exceptions import NoSuchElementException
error = "* This field is required"
phone = driver.find_element_by_xpath("//div[label='Phone Number']")
phone_input = phone.find_element_by_tag_name("input")
phone_label = phone.find_element_by_tag_name("label")
phone_input.click()
phone_label.click()
try:
phone.find_element_by_xpath(".//span[#class='legend error' and .='%s']" % error)
except NoSuchElementException:
print("No error displayed")
This should allow you to click inside input, outside input and check that error appears
If you need to make an assertion:
result = True
try:
phone.find_element_by_xpath(".//span[#class='legend error' and .='%s']" % error)
except NoSuchElementException:
result = False
assert result, "No error displayed"

Related

how to change the value of the array when the user types a new value in reached form

i am working on my recommendation system,it works fine but
when the user searches for a book ,it gives title and image of the books,but when the user type some other title with reloading the file i ,it gives the correct book title but it loads the image of the pervious
searched book
here is my search route, which get book's title and its image
#app.route('/search',methods=['GET','POST'])
def search():
choice = request.args.get('search')
# removing all the characters except alphabets and numbers.
# passing the choice to the recommend() function
# passing the choice to the recommend() function
books = recommend(choice)
image=get_image()
# if rocommendation is a string and not list then it is else part of the
# recommend() function.
if type(books) == type('string'):
return render_template('read.html', book=books,image=image,s="oppps")
else:
return render_template('read.html', book=books,image=image)
here is my code to get the image, where i have defined img list gobally
for i in indices.flatten():
img.append(data[data.index == i]
['Image'].values[0])
return book_list
I can't understand why it gives the previous searched book's image,while it should display the current searched title image (But it works fine when i rerun the py file again)
here is my searched form
{% block body %}
<form action="{{url_for('search')}}" , class="navbar-form" role="search" ,method="POST">
<input type="text" placeholder="Search Books" class="search mb-3" name="search">
<button class="search-btn">Search</button>
</form>
{% endblock %}
can u pls help me out with this
Thanks you in Advance
I think you got some logic error in your code, but from posted piece it is not clear what exactly is your issue.
For example, how did you connect that data: title of the book and it's image:
books = recommend(choice) // here you get the book(s), based on **choice** variable
image=get_image() // but what did you based on when picking the image(s) from the list
I think more code would clarify this problem.

How do I get checkbox "on" using Python Flask without causing a 400 bad request error?

I've got a form which is submitting a post request to Flask. It all works perfectly except when a checkbox is not ticked which causes a 400 error unless I have a try: except: catch for each option.
The challenge is that I have a lot of checkboxes and it seems like there would be a better way than just having a dozen try: except: checks.
Is there a more Pythonic way of doing this please?
Currently the HTML looks like this:
<div class="control">
<label class="checkbox">
<input name="option_1" type="checkbox">
Option 1
</label>
</div>
My Python code looks like:
try:
print(request.form['option_1'])
except:
print("option_1 not selected")
When a key might not exist, use .get(...) instead of accessing it directly, for example:
print(request.form.get('option_1'))
Thanks to Janos for the explanation, whoop only prints if the box is ticked with no error if it's not there.
if request.form.get('option_1'):
print('whoop')

Selenium/Python - Class name with spaces unable to local element

I'm having trouble locating an element. I'm trying to locate it and enter some data into the field. I notice that the class name has spaces and ID is generated automatically (compare these to other forms) so can't use the ID for the automation as I want to automate this to create new forms and will be using the 'Description' field every time.
Below is the html for the Description field, which I'm trying to locate.
<input size="15" maxlength="255" class="acitem description s-description ui-autocomplete-input" spinner="/assets/spinner-48c6e73f2bbe9ea753f7f8e5410541a8138d19d657ddd532b2765335ed3d62bf.gif" auto_complete="true" data-autocomplete-url="/items/auto_complete" data-autocomplete-renderer="item_autocomplete_renderer" data-autocomplete-delay="250" type="text" name="invoice[invoice_lines_attributes][68345][description]" id="invoice_invoice_lines_attributes_68345_description" autocomplete="off">
The codes that I'm using so far has failed.
test_1 = driver.find_element_by_css_selector('.acitem.description.s-description.ui-autocomplete-input')
test_1.send_keys("HELLO WORLD")
test_2 = driver.find_element_by_css_selector("input[class='acitem description s-description ui-autocomplete-input']")
test_2.send_keys("HELLO WORLD")
test_3 = Select(driver.find_element_by_xpath("//*[#class='acitem description s-description ui-autocomplete-input']"))
test_3.send_keys("HELLO WORLD")
Did I got the code wrong or is there some workaround with the class name that has spaces? Thanks.
Thanks for all your help. I solved by using start-with and contains.
Below is my code.
invc_desc =driver.find_element_by_xpath("//input[starts-with(#class,'acitem') and contains(#class,'s-description')]")
invc_desc.clear()
invc_desc.send_keys("HELLO WORLD")
Try with xpath
//input[starts-with(#id,'invoice_invoice_lines_attributes_')]
I almost all the cases, all the elements from the DOM can be accessed via XPATH.
In your case I would go with the following:
element = driver.find_element_by_xpath("//input[#id='acitem description s-description ui-autocomplete-input']")

Python Selenium can't change Select element value

I have a Select element with two options: Credit / Debit Card and Cash, with the former being the default. I have tried everything conventional and whatever else I can think of but I cannot change this value to Cash. My code as it stands is the following
pay_type_dropdown = driver.find_element_by_xpath(path_ending_in_select)
pay_type_dropdown.click()
# Have tried with and without clicking. Never seemed to make a difference.
pay_type_select = Select(pay_type_dropdown)
pay_type_select.select_by_visible_text('Cash')
But I have also tried select_by_value('CASH') - the option tag's value - and select_by_index(1), as well as
pay_type_dropdown = driver.find_element_by_xpath(path_ending_in_select)
pay_type_dropdown.click()
elems = pay_type_dropdown.find_elements_by_tag_name('option')
elems[1].click()
and
elems = pay_type_dropdown.find_elements_by_xpath(path_ending_in_select + '/option')
elems[1].click()
also to no avail. The drop box opens (if clicked on with the click() function) but no other value is selected. Nothing happens past that and there is no error. It is not in a separate frame as I am able to interact with everything else without having to shift into the correct frame. Any help would be much appreciated, thanks.
EDIT: This is the relevant HTML.
<div class="z-form-row" data-bind="visible: settings.tender.active, 'if': settings.tender.active">
<div class="z-form-field">
<label data-bind="_t: 'cart_options_payment_label'">I'll pay with:</label>
<select data-bind="value: settings.tender.selected, options: settings.tender.types, optionsText: 'label',
optionsValue: 'id', valueAllowUnset: true"><option selected="selected" value="CARD">Credit / Debit Card</option><option value="CASH">Cash</option></select>
</div>
<i class="z-row-icon z-icon-card" data-bind="css: tenderTypeIcon()"></i>
</div>

Working in Python cgi with form. Empty input error

I am trying to work with forms on python and I have 2 problems which I can't decide for a lot of time.
First if I leave the text field empty, it will give me an error. url like this:
http://localhost/cgi-bin/sayHi.py?userName=
I tried a lot of variants like try except, if username in global or local and ect but no result, equivalent in php if (isset(var)). I just want to give a message like 'Fill a form' to user if he left the input empty but pressed button Submit.
Second I want to leave what was printed on input field after submit(like search form). In php it's quite easy to do it but I can't get how to do it python
Here is my test file with it
#!/usr/bin/python
import cgi
print "Content-type: text/html \n\n"
print """
<!DOCTYPE html >
<body>
<form action = "sayHi.py" method = "get">
<p>Your name?</p>
<input type = "text" name = "userName" /> <br>
Red<input type="checkbox" name="color" value="red">
Green<input type="checkbox" name="color" value="green">
<input type = "submit" />
</form>
</body>
</html>
"""
form = cgi.FieldStorage()
userName = form["userName"].value
userName = form.getfirst('userName', 'empty')
userName = cgi.escape(userName)
colors = form.getlist('color')
print "<h1>Hi there, %s!</h1>" % userName
print 'The colors list:'
for color in colors:
print '<p>', cgi.escape(color), '</p>'
On the cgi documentation page are these words:
The FieldStorage instance can be indexed like a Python dictionary. It allows membership testing with the in operator
One way to get what you want is to use the in operator, like so:
form = cgi.FieldStorage()
if "userName" in form:
print "<h1>Hi there, %s!</h1>" % cgi.escape(form["userName"].value)
From the same page:
The value attribute of the instance yields the string value of the field. The getvalue() method returns this string value directly; it also accepts an optional second argument as a default to return if the requested key is not present.
A second solution for you might be:
print "<h1>Hi there, %s!</h1>" % cgi.escape(form.getvalue("userName","Nobody"))

Categories