I'm playing around with RoR for the first time and hit a weird error. I have the following test code for my navigation links:
describe "when logged in" do
before(:each) do
#user = Factory(:user)
visit login_path
#the line below is the weird one
fill_in "session[user_name]", :with => #user.user_name
fill_in :password, :with => #user.password
click_button
end
it "should have navigation links" do
response.should have_selector("nav")
end
it "should have link to log out" do
response.should have_selector("a", :href => logout_path, :content => "Log out")
end
end
the code above works just fine, but if I would change the line
fill_in "session[user_name]", :with => #user.user_name
to
fill_in :user_name, :with => #user.user_name
it won't work and I can't figure out why. The error I get is
Failure/Error: fill_in :user_name, :with => #user.user_name
Webrat::NotFoundError:
Could not find field: :user_name
The relevant generated html is:
<label for="session_user_name">User name</label><br/>
<input id="session_user_name" name="session[user_name]" size="30" type="text" />
<label for="session_password">Password</label><br/>
<input id="session_password" name="session[password]" size="30" type="password" />
If you look at the code you see I do exactly that for the password, and that works just fine. I would like to use the syntax which is causing the error so am I doing something wrong?
Try this:
fill_in "user name", :with => #user.user_name
I think webrat is being nice, and its able to find your label 'Password' because it is case insensitive and its turning :password into 'Password'.
You could also use the HTML id attribute, i.e.
fill_in :session_user_name, :with => #user.user_name
One gotcha here is if you are thinking of switching to use Capybara rather than Webrat: Capybara is case-sensitive, so it would fail on fill_in "user name".
I'm not sure what the best practice is here, but I have switched to using the HTML id and name attributes rather than the label text in my own code. The reason for this is that it is less brittle because people change the customer-facing text on the site more than they change the semantic elements and names.
Related
I´m learning Ruby on Rails and i´m working on an application that use stripe to create premium accounts. Also, i´m using Rspec and Capybara to do the integration tests.
require 'spec_helper'
feature "user upgrade account to a premium plan" do
scenario "user upgrade account", :js => true do
user = FactoryGirl.create :user
visit new_user_session_path
fill_in 'Email', :with => user.email
fill_in 'Password', :with => user.password
click_button 'Sign in'
visit new_charge_path
click_button "Pay with Card"
fill_in 'Email', :with => 'persona#example.com'
fill_in "Card number", :with => "4242424242424242"
fill_in 'CVC', :with => '123'
fill_in 'MM/YY', :with => '11/14'
click_button 'Pay $5.00'
end
I run the test and i get an error message that says:
Failure/Error: fill_in "Card number", :with => "4242424242424242"
Capybara::ElementNotFound:
Unable to find field "Card number"
Anyone knows, what can be the problem?
Thanks.
Depending on how you're integrating Stripe, it might be rendering the form inside an iframe. If that's the case, you'll need to use Capybara.within_frame to target the actions to the correct frame:
scenario "user upgrade account", :js => true do
user = FactoryGirl.create :user
visit new_user_session_path
fill_in 'Email', :with => user.email
fill_in 'Password', :with => user.password
click_button 'Sign in'
visit new_charge_path
click_button "Pay with Card"
Capybara.within_frame 'stripe_checkout_app' do
fill_in 'Email', :with => 'persona#example.com'
fill_in "Card number", :with => "4242424242424242"
fill_in 'CVC', :with => '123'
fill_in 'MM/YY', :with => '11/14'
click_button 'Pay $5.00'
end
end
Try to use element id instead of field label.
fill_in 'card_number', :with => '4242424242424242'
fill_in 'cvc', :with => '123'
(Being card_number and cvc the ids of input fields.)
= f.text_field :card_number, :class => 'span12', :id => :card_number
= f.text_field :cvc, :class => 'span12', :id => :cvc
I had the same problem and I used this solution, not sure if it's good practice, but works for me.
for capybara with stripe testing:
Capybara.within_frame 'stripe_checkout_app' do
fill_in "Card number", :with => "4242424242424242"
fill_in 'CVC', :with => '123'
fill_in 'Expiry', :with => '11/22'
click_button 'Pay $5.00'
end
edit the exipry date to a month and year of future always.
I'm trying to use capybara+rspec and get this error: Unable to find field "Name" (Capybara::ElementNotFound)
Here is my form:
%h2 Sign up
= simple_form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => {:class => 'form-vertical' }) do |f|
= f.error_notification
= display_base_errors resource
= f.input :name, :autofocus => true
= f.button :submit, 'Sign up', :class => 'btn-primary'
= render "devise/shared/links"
Here is my user_steps.rb
When /^I sign up with valid user data$/ do
create_visitor
sign_up
end
def create_visitor
#visitor ||= { :name => "Test visitor"}
end
def sign_up
visit '/users/sign_up'
fill_in "Name", :with => #visitor[:name]
click_button "Sign up"
end
What's wrong????
I encountered this issue and realized that Capybara filtered out hidden fields--my element belonged to a non-active tab (hidden) in a multi-tab page. I just passed the :visible arg and set it to false, and voila! the element was found.
fill_in "content", with: 'foo bar', visible: false
or
find('#item_content', visible: false).set 'foo bar'
It looks like to me that you are looking for a field label Name, but your name field does not have a label, so you probably need to use the ID of the field or the name which is probably:
"#{resource_name}[name]"
Also, as #nmott said in his comment, you should try using save_and_open_page so that you can actually look at the page, However, be aware you need the launchy gem to use this method.
Furthermore, what you might discover is you're not even on the right page. My usual problem when testing pages OTHER than the sign up page is that I've been redirected and didn't know it. So after using visit, you should also use assert_template to make sure you're on the right page.
I have the same problem myself and I had to stop using fill_in all together.
What I did was replacing all occurrences of fill_in with the following code :
element = page.find("Name")
element.set(#visitor[:name])
I guess you can encapsulate this into a method in order to make your tests more smooth
Try to narrow down your scope from within the form as such
within("form#whatever_form_id") do
fill_in "Name", :with => #visitor[:name]
click_button "Sign up"
end
Ok guys I found it out having the same issue , its very simple :
In capybara or rspec they need you to but "Name" and in your form or label field you need to write "name" in small....there you go works for me.
For me it was the next line of the spec that was causing the problem not the fill_in "name" line. It didn't matter whether or not name was "Name" or "name".
The next click_button line for me had click_button "Wrong Name" which was the wrong name for the button, and this did not give the expected error of "can't click on button "Wrong Name" but instead gave can't find field "name".
A bit verbose for my first even post on stack overflow. Bottom line. Consider the line below the line given in the capybara error message.
I'm running some request specs using the selenium driver for capybara, and while they work, they take too long to complete. The test starts, Firefox starts, clicks on the link and hangs for like 15 seconds before filling in the form. Here's the spec code:
it "should let an invited user sign up" do
# Invite the user
invitation = Factory.create :invitation, :invitee => nil
# Sign up
visit invitation_path(:controller => :sessions, :action => :invitation, :token => invitation.token)
current_path.should eq(login_path)
click_link "Connect with Facebook"
current_path.should eq(edit_user_path(User.order('created_at desc').first))
# Fill form
# THIS IS THE PART THAT TAKES WAY TOO LONG TO BEGIN
fill_in "Username", :with => "johndoe"
fill_in "Email", :with => "john#doe.com"
fill_in "City", :with => "Santiago"
fill_in "Commune", :with => "Santiago"
select_date Time.now, :from => "user_birthday"
click_on "Save"
# THIS ASSERTION ALSO TAKES VERY LONG TO BE RUN
current_path.should eq(root_path)
end
Any ideas as to what is going on? Is this expected behavior for selenium? Is there a way to speed this up?
From Original Poster:
I found out it had to do with some long-polling javascript on the page, so selenium didn't detect that the page had finished loading (because of the long-poll request on the background).
I am trying to get tests working after switching from Webrat to Capybara. When I try to sign in to the application I am getting a "Invalid username/password" error, despite just having created the user in a Factory using factory_girl. The way I understand it, the user should persist for the entirety of the fixture, right?
factories.rb:
Factory.define :user do |user|
user.firstname "Test"
user.lastname "Test"
user.email "test#test.com"
user.password "testtest"
user.password_confirmation "testtest"
end
layout_links.spec.rb:
describe "LayoutLinks" do
before(:each) do
wrong_user = Factory(:user)
integration_sign_in(wrong_user)
end
it "should have a dashboard page" do
get '/dashboard'
page.should have_css('h1', :text => "Navigation#dashboard")
end
spec_helper.rb
def integration_sign_in(user)
visit signin_path
fill_in :email, :with => user.email
fill_in :password, :with => user.password
click_button "Sign in"
puts page.body
end
Also in spec_helper.rb is the following:
config.use_transactional_fixtures = false
config.before(:suite) do
DatabaseCleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.start
end
config.after(:each) do
DatabaseCleaner.clean
end
Shouldn't the user persist and then be successful in the integration_sign_in function? I can still sign in correctly through the browser in the development environment, which has a user and the sign in was working correctly with webrat before the migration, so I am not sure what to think. Thanks!
UPDATE: It looks like the session isn't going to the server correctly. On the server, when I check the value of email and password in the session, the values are incorrect:
puts "Post Email: " + params[:session][:email]
puts "Post Password: " + params[:session][:password]
the email variable has the password variable, and the password variable has no value. Why would this be? The client integration test maps the fields correctly:
fill_in :email, :with => user.email
fill_in :password, :with => user.password
How can I test this further? Thanks.
So this worked for me
fill_in "Email", :with => user.email
fill_in "Password", :with => user.password
whereas using the symbols failed
It looks like the session wasn't going to the server correctly. I am not sure how to account for this.
I am using capybara for an integration test and it looks like something is wrong with the session that gets passed to my controller for my "sign in" part of a test. The sign in works fine when going through a browser, but is failing in capybara.
def integration_sign_in(user)
visit signin_path
puts "Pre email: " + user.email
puts "Pre password: " + user.password
# When I use these, everything works correctly
fill_in "session_email", :with => user.email
fill_in "session_password", :with => user.password
# When I use these, the session is wrong
# The params[:session][:email] on the server has the password field
# The params[:session][:password] on the server is nil
#fill_in :email, :with => user.email
#fill_in :password, :with => user.password
click_button "Sign in"
end
Can I not use symbols for the capybara tests? My guess is that the first field (email) is being filled in for both fields in the failing case, which is why the session only has a value for email and that value is password.
It looks like the latest version of capybara doesn't accept symbols correctly. It only works when the full string of the field is entered.