Check the label of a checkbox using Selenium and behave in Python - python

I want to write a test that checks if the correct text is shown on a website. It mostly works, but I am stuck with checking the label of a checkbox.
HTML:
<div class="checkbox">
<label>
<input id="remember_me" name="remember_me" tabindex="130" type="checkbox" value="y">
" Remain logged in
"
</label>
</div>
Behave:
Scenario: See the formular for log in
Given I am on the "/login" page
Then I should see header "Log In"
...
And I should see the checkbox for "remember_me"
And I should see label "Remain logged in"
The header is found without issue:
#then(u'I should see header "{header}"')
def step_impl(context, header):
assert context.browser.find_element_by_xpath("//h1[contains(text(), '{}')]".format(header))
as well as the checkbox itself:
#then(u'I should see the checkbox for "{name}"')
def step_impl(context, name):
assert len(context.browser.find_elements_by_xpath("//input[#type='checkbox'][#name='{}']".format(name))) > 0
I don't know how to specifically check for the label "Remain logged in" however. Anything I tried, including checking for the text itself with find_text() or in such a way:
def step_impl(context, label):
assert context.browser.find_element_by_xpath("//input[#type='checkbox' and contains(text(), '{}')]".format(name))) > 0
has not work.
Does Selenium allow to check the text of the label and if yes, how would I go about it?

Are you locating label element correctly? the following code should return the text from the label webelement.
label_element = browser.find_element_by_xpath("//div[#class='checkbox']/label")
TextValue = label_element.text
or
TextValue = label_element.get_attribute('textContent')

Related

Python - How can I pass variable in Flask when clicked on a button

I am working on a Flask project that has two pages (firstpage, secondpage). The first page has two buttons. When a user clicks on one of them, it should send a variable (variable name is value) with text to the second page. The second page should display message depending on what button the user clicked in the first page. But my program is always printing the second value even when the first button is clicked. If I declared the variable global, can I use it in the secondpage?
My html code looks kind of like this:
<form action="/firstpage" method="post">
<div><h2 class="header">Click one button</h2></div>
<div class="pickitem">
<button class="btn one" name="btn-one" type="submit">ONE</button><br>
<button class="btn two" name="btn-two" type="submit">TWO</button></div>
</form>
and my Python code looks like this:
var value=""
#app.route("/firstpage", methods=["GET", "POST"])
def mymethod():
value = ""
if request.method == "POST":
if request.form.get("btn-one"):
value = "uno"
else:
request.form.get("btn-two"):
value = "dos"
print (value)
return render_template("secondpage.html")
else:
return render_template("firstpage.html")
You can use an hidden input field for this.
HTML:
<form action="/firstpage" method="post">
<div><h2 class="header">Click one button</h2></div>
<input type="hidden" name="btn-pressed" class="hidden-field">
<div class="pickitem">
<button class="btn one" name="btn-one" type="submit">ONE</button><br>
<button class="btn two" name="btn-two" type="submit">TWO</button></div>
</form>
Change its value depending upon the button clicked.
JavaScript:
document.addEventListener('click', (e) => {
// do not process if the clicked element is not a form button
if ( ! e.target.matches('form .btn') ) return;
// prevent form submission
e.preventDefault();
// change hidden field value
let field = document.querySelector('.hidden-field');
field.value = e.target.getAttribute('name');
// submit the form
e.target.closest('form').submit();
});
Then in Python, you can get the value through the name btn-pressed
Python:
request.form.get("btn-pressed") # to get the hidden field value
A few syntax errors you might need to fix.
It seems like you are mixing up different programming languages. In the first line, you entered var value="". Try to remove the var.
Make sure your indentation is correct! Indent the block from def mymethod(): to the bottom.
Remove the colon from the line request.form.get("btn-two"):. Did you mean if request.form.get("btn-two"): instead?
Apart from that, the reason value ends up not being either "uno" or "dos" is because of the if-statements in the code. To fix the issue, change them to:
if list(request.form)[0] == 'btn-one':
Why does this work? The request.form looks like this:
ImmutableMultiDict(['btn-one', ''])
Transforming this into a list (i.e., getting its keys, which is either btn-one or btn-two) and taking the first item will tell us the button pressed.
Hope this helps :)

How to set a text in a textarea by using Mechanical Soup?

I'm learning to create an Omegle bot, but the Omegle interface was created in HTML and I don't know very much about HTML nor MechanicalSoup.
In the part where the text is inserted, the code snippet is as follows:
<td class="chatmsgcell">
<div class="chatmsgwrapper">
<textarea class="chatmsg " cols="80" rows="3"></textarea>
</div>
</td>
In the part of the button to send the text, the code snippet is:
<td class="sendbthcell">
<div class="sendbtnwrapper">
<button class="sendbtn">Send<div class="btnkbshortcut">Enter</div></button>
</div>
</td>
I want to set a text in textarea and send it via button.
Looking at some examples in HTML, I guess the correct way to set text in a textarea is as follows:
<textarea>Here's a text.</textarea>
Also, I'm new at MechanicalSoup, but I think I know how to find and set a value in an HTML code:
# example in the Twitter interface
login_form = login_page.soup.find("form", {"class": "signin"})
LOGIN = "yourlogin"
login_form.find("input", {"name": "session[username_or_email]"})["value"] = LOGIN
From what I understand, the first argument is the name of the tag and a second argument is a dictionary whose first element is the name of the attribute and the second element is the value of the attribute.
But the tag textarea don't have an attribute for setting a text, like value="Here's a text.". What I should do for set a text in a textarea using MechanicalSoup?
I know it's not the answer you expect, but reading the doc would help ;-).
The full documentation is available at:
https://mechanicalsoup.readthedocs.io/
You probably want to start with the tutorial:
https://mechanicalsoup.readthedocs.io/en/stable/tutorial.html
In short, you need to select the form you want to fill-in:
browser.select_form('form[action="/post"]')
Then, filling-in fields is as simple as
browser["custname"] = "Me"
browser["custtel"] = "00 00 0001"
browser["custemail"] = "nobody#example.com"
browser["comments"] = "This pizza looks really good :-)"

Radio button does not get clicked in Selenium / Python

Folks, this is driving me crazy. I have snippets like the following
<label class="" for="M37_Q_POSWECHSEL_BETT_B1">
<input id="M37_Q_POSWECHSEL_BETT_B1" name="M37_Q_POSWECHSEL_BETT" value="B1" aria-describedby="M37_Q_POSWECHSEL_BETT_error_0" aria-invalid="true" data-clipboard="M37_Q_POSWECHSEL_BETT#B1" type="radio">
0
</label>
Here, I'd like to select the radio buttons and select them with the following code:
radios = driver.find_elements_by_xpath("//input[starts-with(#id, 'M37_Q_')][#value='B1']")
for radio in radios:
# just check the id
print(radio.get_attribute('id'))
radio.click()
It correctly selects the elements in question. However, it does not get selected nor does it yield any obvious errors. Can we use .click() to select radio buttons here? Is this some kind of handler problem?
Try this,
driver.execute_script("arguments[0].checked = true;",element)
You can also try by sending ENTER Key to the element.
Try using following Css selector:
Actions action = new Actions(drive);
action.moveToElement(drive.findElement( By.cssSelector("label > input[id^='M37_Q_']"))).build().perform();
drive.findElement( By.cssSelector("label > input[id^='M37_Q_']")).click();

Verify input box text using Python + Selenium

I have gone through other similar questions and the general advice was to use the get_attribute() method with input 'value'.
However, this doesn't seem to work in my case.
The tag I am trying to test is -:
<input class="form-control required" id="email" name="email" placeholder="Enter your E-mail / Username" required="" type="text" value="">
and the code I am using is as follows -:
def enter_keys_by_id(self, id, text):
"""
Finds a form element by ID and then proceeds
to enter text into the form.
"""
find_element = self.driver.find_element_by_id(id)
assert find_element.get_attribute('value') == ""
find_element.send_keys(text)
assert find_element.get_attribute('value') == text
return find_element
with the function call -:
enter_keys_by_id("email", "someemail#email.com")
The 'value' attribute is set to blank in the tag. How would I go about it in this particular case?
So, you type email to the "empty" input, but I think that you need to submit the form, ie save the value to the input before retrieveing it. I guess you are trying to verify that the email was saved correctly, so you can:
Type email
Submit the form (you didn't provide html, but I guess there is some submit button near to the email field)
And after that try to assert find_element.get_attribute('value') == text (or to wait for the input with value='your text')

Checking for a field error using Selenium Webdriver

I've been trying to implement tests to check for field validation in forms. A check for specific field error messages was straightforward, but I've also tried a generic check to identify the parent element of a field for an error class. This however isn't working.
A field with an error has the following HTML;
<div class="field clearfix error ">
<div class="error">
<p>Please enter a value</p>
</div>
<label for="id_fromDate">
<input id="id_fromDate" type="text" value="" name="fromDate">
</div>
So to check for an error I've got the following function;
def assertValidationFail(self, field_id):
# Checks for a div.error sibling element
el = self.find(field_id)
try:
error_el = el.find_element_by_xpath('../div[#class="error"]')
except NoSuchElementException:
error_el = None
self.assertIsNotNone(error_el)
So el is the input field, but then the xpath always fails. I believed that ../ went up a level in the same way that command line navigation does - is this not the case?
Misunderstood your question earlier. You may try the following logic: find the parent div, then check if it contains class error, rather than find parent div.error and check NoSuchElementException.
Because .. is the way to go upper level, ../div means parent's children div.
// non-working code, only the logic
parent_div = el.find_element_by_xpath("..") # the parent div
self.assertTrue("error" in parent_div.get_attribute("class"))
When you're using a relative xpath (based on an existing element), it needs to start with ./ like this:
el.find_element_by_xpath('./../div[#class="error"]')
Only after the ./ can you start specifying xpath nodes etc.

Categories

Resources