Cucumber/Capybara - How to search for a specific button using XPath? - cucumber

I am trying to figure out how to write an oAuth/Twitter signin feature with Cucumber/Capybara. Part of it, consists in visiting the page: http://www.twitter.com/sessions/new and filling in the username, the password and then clicking on the 'Sign in' button. That last step is not working as expected, the html code for that page looks like this (located in french):
<fieldset class="textbox">
<label class="username">
<span>Nom d'utilisateur ou e-mail</span>
<input type="text" value="" name="session[username_or_email]" autocomplete="on" />
</label>
<label class="password">
<span>Mot de passe</span>
<input type="password" value="" name="session[password]" />
</label>
</fieldset>
<fieldset class="subchck">
<button type="submit" class="submit button">Se connecter</button>
I have a defined the step like this in web.steps (note that I am not using the default capybara driver but capybara-mechanize):
Given /^I sign in$/ do
visit 'http://twitter.com/sessions/new'
fill_in "Username or email", :with => 'xxx'
fill_in "Password", :with => 'xxx'
find(:xpath, 'button[#class="submit button"]')
....
end
The find(:xpath,..) line is not working properly. I tried to put a '/s' (regex for space character) but I still get this error message:
Unable to find '//button[#class="submit\sbutton"]' (Capybara::ElementNotFound)
I also tried:
xpath_for("submit button")
But I get a stack level too deep error!
I am not really confident with my regex/xpath element finding skills so please tell me what is wrong with my code and how I could find that button?
Thanks so much for helping me!
[EDIT]
Turns out the default selector is :css. I changed it to :xpath:
Capybara.default_selector = :xpath
But it still doesn't solve my problem.

What if you try
click_on "Se connecter"
EDIT: Trying in nokogiri (cause capybara uses nokogiri) it doesn't work for me when I use your HTML as is (meaning it doesn't even see the element in the document). But when I enclose everything in a single root node, it works.. don't know if there's an issue with your page HTML or something.. with a well formed page, it "should" work. not sure how much this helps
<html>
<fieldset class="textbox">
<label class="username">
<span>Nom d'utilisateur ou e-mail</span>
<input type="text" value="" name="session[username_or_email]" autocomplete="on" />
</label>
<label class="password">
<span>Mot de passe</span>
<input type="password" value="" name="session[password]" />
</label>
</fieldset>
<fieldset class="subchck">
<button type="submit" class="submit button">Se connecter</button>
</html>
with this HTML, I can just use the xpath
xpath('//button')

Instead:
find(:xpath, 'button[#class="submit button"]')
you should have:
find('button.submit.button')
Above is css, since it's default selector.
If you want solution with XPath look at https://stackoverflow.com/a/11752824/507018, but it's uglier.

If you have the exact match to class of button <button class="submit button">, you can try just the following:
find(:xpath, '//button[#class="submit button"]')
Make sure that you didn't forget the double slash in the beginning of the search string.

Related

Disabling igx-button when validation fails

In an Angular application, I've a dialog that's shown when the user clicks on a button
and it's defined as
<igx-dialog #dialogAdd title="Nuovo Tipo Oggetto" [rightButtonLabel]="'Inserisci'" [leftButtonLabel]="'Cancella'" (leftButtonSelect)="cancel()" (rightButtonSelect)="addRow()">
<div class="dialogNewRecord">
<app-tipi-oggetto-insert ></app-tipi-oggetto-insert>
</div>
</igx-dialog>
The content of app-tipi-oggetto-insert is
<form class="input-group-form" [formGroup]="tipoOggettoInsert" (ngSubmit)="onSubmit()">
<igx-input-group>
<label igxLabel for="productName">Tipo</label>-->
<input igxInput id="productName" type="text" [(ngModel)]="item.tipo" />
</igx-input-group>
<igx-input-group>
<label igxLabel for="unitsInStock">Descrizione</label>
<input igxInput id="unitsInStock" type="text" [(ngModel)]="item.descrizione" />
</igx-input-group>
</form>
I was wondering how can I disable the Submit button at the start and if the validation of the fields fails... I haven't put the validation here for simplicity but the main problem is that I don't know how to tell the main view to disable the button based on internal value. do I have to use an event?
Otherwise, how can I open an igniteUI dialog programmatically? I think of putting the
<igx-dialog #dialogAdd ...
inside the Add Component
Thankss

Cannot pass variables to Django 3 method from HTML template

I am a Django newbie who is trying to convert an existing HTML based website to Django 3. The only complex piece of this page is a call to a Django method that uses the django.core.mail package and everything works, but, I am trying to pull some data off of the HTML template and pass it to this method.
The method works, only it sends a blank email. I am trying to pass contact information that the end user would fill out on the form. If I hard code the data into the method it works.
I have tried passing the data through urls.py, but, everything I try fails to even parse when I call the method. When I use a request.GET.get everything seems to work, just no data.
I was hoping to use something similar to JQuery like the following in the method.
name = str(request.GET.get('Name:', '').strip())
email = str(request.GET.get('Email:', '').strip())
msg1 = str(request.GET.get('Message:', '').strip())
with the fields being in the HTML form.
I am going to include some of the relevant configuration items below.
urls.py
from django.urls import path
from django.conf import settings
from django.conf.urls import url
from django.conf.urls.static import static
from . import views
app_name = 'willdoit'
urlpatterns = [
path('', views.index),
#url(r'^contact/(?P<name>\.+)/(?P<email>\.+)/(?P<msg1>\.+)/?$', views.contact, name='contact'),
path('contact/', views.contact, name='contact'),
]
views.py
def contact(request):
name1 = request.GET.get('name', '')
email1= request.GET.get('email', '')
msg1 = request.GET.get('message1', '')
subject = 'Work needed'
from_email = settings.DEFAULT_FROM_EMAIL
message = name + ' ' + email + ' ' + msg1
recipient_list = ['pkustra914#gmail.com']
send_mail(subject, message, from_email, recipient_list, fail_silently=False)
return HttpResponse('Success')
Relevant HTML Template section
<div class="contact_content">
<div class="col-md-6 col-sm-6 col-xs-12">
<div class="contact_message wow fadeInLeft" data-wow-duration="1.5s">
<form action="#" id="formid">
<form action="#" id="formid">
<div class="form-group"> <input class="form-control" name="name"
placeholder="Name" required="" type="text"> </div>
<div class="form-group"> <input class="form-control" name="email"
placeholder="Email" required="" type="email"> </div>
<div class="form-group">
<div class="Descrizione"> <label for="InserisciDescrizione"
class=""><b>Message</b></label> <textarea class="form-control"
id="message" placeholder="Type message:" name="message1" rows="6" cols="50"
title="Message"></textarea> </div>
<a id="submit" href="{% url 'willdoit:contact' %}" class="btn btn-primary">Submit</a>
I would prefer to use the request.GET.get method, but, there is a lot more documentation passing it through the urls.
Thanks.
Your code request.GET.get('Name:', '') returns empty string when the key 'Name:' is not found.
To fix this, use request.GET.get('name', '') request.GET.get('email', '') request.GET.get('message', '') instead.
Details
I see that you are using a with template tag for nothing. The following line of code does not change the name attribute string to PascalCase. See with template tag (Docs)
{% with Name=name Email=email Message=message %}
Even if it worked, your code should be calling request.GET.get('Name', '') instead of request.GET.get('Name:', ''). But it won't work, as with would not modify the attribute names in the GET request.
#EDIT1
There are apparently more bugs in your html code. I have reformatted your code and listed up some obvious bugs.
<!--REFORMATTED CODE-->
<form action="#" id="formid"> <--------------DUPLICATES, remove one
<form action="#" id="formid"> <--------------DUPLICATES, remove one
<div class="form-group"> <input class="form-control" name="name"
placeholder="Name" required="" type="text"> </div>
<div class="form-group"> <input class="form-control" name="email"
placeholder="Email" required="" type="email"> </div>
<div class="form-group">
<div class="Descrizione">
<label for="InserisciDescrizione" class=""><b>Message</b></label>
<textarea class="form-control" id="message"
placeholder="Type message:" name="message1" rows="6" cols="50"
title="Message"></textarea>
</div>
<a id="submit" href="{% url 'willdoit:contact' %}"
class="btn btn-primary">Submit</a>
<-------- MISSING DIV END TAG
<-------- MISSING FORM END TAG
Furthermore, you are calling the server by url directly using the following code:
<a id="submit" href="{% url 'willdoit:contact' %}" class="btn btn-primary">Submit</a>
This does not tell the page which form you want to submit (there are cases where there are multiple forms).
You have two choices:
Replace the tag with standard html form submit button <input type="submit">, and add the url to the action attribute of the form. Use the following code to do so:
<form action="{% url 'willdoit:contact' %} id="formid">
...
...
<input id="submit" type="submit" class="btn btn-primary" value="Submit"/>
</form>
This solution will by default use the GET method to send a request to the server, and you will be able to get the inputted values by calling request.GET.get(name).
If you are using JQuery, you can replace the with the following:
Submit
This is however not recommended. Please use the standard html form input tag for the submit button.
Great. Moving the method call to the form tag worked great.
Thanks! You guys are the best.

Modx Formit simple contact from

I try to create a simple contact form, but I didn't get any message, the post request is made. I am pretty new with Modx.
What I tried:
Link 1
Link 2
I created 2 Chunks (emailChunkTpl and MyEmailChunk), and in my template I call for the [[$MyEmailChunk]]. Obviously I did something wrong but I am not sure what. The code is like in the examples, but with some changes,like my email.
[[!FormIt?
&hooks=`email,FormItSaveForm `
&emailTpl=`emailChunkTpl`
&emailTo=`myEmail#gmail.com`
&emailUseFieldForSubject=`1`
]]
<form action="[[~[[*id]]]]" method="post" class="contactForm">
<div class="row input-section-child">
<div class="col input-contact">
<input value="[[!+fi.input-name]]"class="input-name" name="input-name" id="input-name" type="text" placeholder="your name" />
<input value="[[!+fi.input-email]]" class="input-email" name="input-email" id="input-email" type="text" placeholder="email address" />
</div>
<div class="col input-contact-text">
<input value="[[!+fi.input-textare]]"class="input-textare" name="input-textare" id="input-textare" type="textare" placeholder="message" />
</div>
</div>
<div class="row second-row">
<div class="col checkbox">
<input value="[[!+fi.input-checkbox]]" class="input-checkbox" name="input-checkbox" id="input-checkbox" type="checkbox" ><span class="input-checkbox-span">I agree to the Privacy policy.</span>
</div>
<div class="col">
<button type="submit" class="send-button">SEND</button>
</div>
</div>
<a href="#intro" class="back-to-top"><img src="images\arrow-back.svg" /><span>Back to top</span>
</div>
</from>
You should start with cleaning up your markup, it is not valid HTML. There is a typo in your closing form tag (/from), an extra closing div tag, there is no input type of textare as far as I know, and you are missing white space around some classes. You can validate HTML here: https://validator.w3.org/
You can test to make sure your site is setup properly to send an email. There is a snippet for this called QuickEmail, download it from the extras tab in the MODX manager.
Once you're sure your site can send email, then start with a stripped down version of the Formit call -- remove all hooks except email and get it working with that first. Then add hooks one at a time.

How to change the pop html on button click

I am trying to find a way to change the pop up HTML on a chrome extension to another one when you click a button. I have tried to make a onclick function href but nothing works. I am new to both HTML and chrome extensions so I am sorry if this problem seems easy to the more experience developers.
<form id="gform" method="POST" class="pure-form pure-form-stacked" data-email="from_email#example.com"
action="https://script.google.com/a/cvsd356.org/macros/s/AKfycbxb4ZyUUQCnTN-7iYF-YRViDSy/exec">
<div class="name">
name: <input type="text" name="Name" id= "inputbox"><br>
</div>
<div class="id">
ID# <input type="text" name= "ID" id= "inputbox"><br>
</div>
<div class="MailingAddress">
Mailing Address: <input type="text" name= "Mailing Adresss" id= "inputbox" style=width:350px;><br>
</div>
<div class="sendToTr">
Send Transcript to: <input type ="text" name="College" style=width:350px; id= "inputbox" ><br>
</div>
<div class="emailmy">
<label for="email"><em>Your</em> Email Address:</label>
<input id="inputbox" name="email" type="email" value=""
required placeholder="your.name#email.com" />
</div>
<div class="sButton">
<button style=height:30px;width:70px;border-radius: 3px; class="button-success pure-button button-xlarge">
send
</button>
</div>
I think there are quite a few ways to achieve what you are asking. If I were you, I would add a JavaScript file to my project to do this.
Step 1:
I would tell my HTML page where to find this JS file. The sample below can be included near the end of your HTML file, right before </body></html>. The sample below assumes your new popup.js file is in the root folder of your project:
<script src="popup.js" type="text/javascript"></script>
Step 2:
In the popup.js file, I would create a function that tells the popup how it should be modified. In the sample below, I'm going to hide the element with an ID of "theOldElement" and show the element with an ID of "theNewElement". I'm also going to attach this function to the click event of "theButton" element.
popup.js
function updatePopup(){
document.getElementById("theNewElement").style.display = "block";
document.getElementById("theOldElement").style.display = "none";
}
document.getElementById('theButton').addEventListener('click', updatePopup);
Step 3:
I like referring to my HTML elements by ID (as I've been doing above - note the "getElementById" references), so I would:
add id="theNewElement" to the element I want to reveal
add id="theOldElement" to the element I want to hide
add id="theButton" to the button that I want to trigger this change
Note: you can insert these IDs as the first attribute within the tag you want to identify. E.g., <div id="theNewElement" ...

How to get data from a form dropdown select element?

I'm using Express.js and trying to get form data of a dropdown select element,
I tried with body-parser but what I get with eq.body.method_select is undefined.
I didn't find much info about how to do this on the web.
Here is my code html code:
<form action="url_analyse">
<div class="col-lg-6">
<div class="input-group">
<select class="custom-select mb-2 mr-sm-2 mb-sm-0" name="method_select" id="inlineFormCustomSelect">
<option value="5">Regular Search (Short)</option>
<option value="10">Intense Search (Long)</option>
<option value="20">Deep Search (Very Long)</option>
</select>
<input type="text" name="url_input" class="form-control" placeholder="Enter URL">
<span class="input-group-btn">
<button class="btn btn-secondary">Go!</button>
</span>
</div>
</div>
Here is my js code:
app.get('/url_analyse', function(req, res) {
console.log(req.body.method_select);
})
Hope you can help me with that.
Thank you.
There are two issues here:
You might want to explicitly add the leading forward slash: action="/url_analyse"
The default form submission HTTP method is GET, which means that form fields will be passed in the query string portion of the URL. This means you will instead need to access req.query to get at the form fields. You only need body-parser and req.body when you use POST and other methods (with the appropriate enctype) to submit your form.

Resources