I've decided to start a new project using the new Rspec 3 (+ capybara/factory_girl) and am having trouble learning the new syntax. Right now I have
user_pages_spec.rb (Feature)
scenario "Signing Up" do
let(:submit) { "Sign up" }
scenario "With valid information" do
background do
fill_in "Username", with: "example"
fill_in "Email", with: "example#example.com"
fill_in "Password", with: "foobar123"
fill_in "Password confirmation", with: "foobar123"
end
scenario "should create a user" do
expect { click_button submit }.to change(User, :count).by(1)
end
end
end
Fails with undefined method 'let'. And:
static_pages_spec.rb (controller)
describe StaticPagesController do
describe "GET 'home'" do
it "returns http success" do
get :home
expect(response).to be_success
end
end
end
with "undefined method 'get'. (This is just the default controller spec)
When upgrading existing project from RSpec 2.x to 3.0 had same problem.
It was fixed for me with an explicit setting of the type.
Could you try this:
describe StaticPagesController, type: :controller do
EDIT:
I found now that the more structural cause and solution is that
in RSpec 3, I needed to add:
config.infer_spec_type_from_file_location!
in the config block in spec_helper.rb
You are getting undefined method let because capybara defines scenario an alias of it and feature as alias of describe. However, let is available in an example group context (a describe or context block) but not an individual example (and it block). So your example is equivalent to:
it "Signing Up" do
let(:submit) { "Sign up" }
it "With valid information" do
background do
fill_in "Username", with: "example"
fill_in "Email", with: "example#example.com"
fill_in "Password", with: "foobar123"
fill_in "Password confirmation", with: "foobar123"
end
it "should create a user" do
expect { click_button submit }.to change(User, :count).by(1)
end
end
end
...but should be:
feature "Signing Up" do
let(:submit) { "Sign up" }
context "With valid information" do
background do
fill_in "Username", with: "example"
fill_in "Email", with: "example#example.com"
fill_in "Password", with: "foobar123"
fill_in "Password confirmation", with: "foobar123"
end
scenario "should create a user" do
expect { click_button submit }.to change(User, :count).by(1)
end
end
end
Or, if you want to stick with pure RSpec constructs (rather than the capybara aliases):
describe "Signing Up" do
let(:submit) { "Sign up" }
context "With valid information" do
before do
fill_in "Username", with: "example"
fill_in "Email", with: "example#example.com"
fill_in "Password", with: "foobar123"
fill_in "Password confirmation", with: "foobar123"
end
it "should create a user" do
expect { click_button submit }.to change(User, :count).by(1)
end
end
end
Related
I have a problem.
I'm trying to use capybara to do integration tests, but I can not get the id on my page for it to make the visit when I test the context "edit new tarefa". I'm using devise, so I create the user at the beginning of the code.
Below is the code:
require 'rails_helper'
describe "Tarefas", :type => :feature do
feature "New Tarefa" do
background do
user = FactoryGirl.create(:user)
login_as(user, :scope => :user)
end
context "create new tarefa" do
it "preenchendo os campos" do
visit '/tarefas/new'
within("#new_tarefa") do
fill_in 'tarefa_titulo', with: 'user#example.com'
fill_in 'tarefa_descricao', with: 'password'
fill_in 'tarefa_data', with: '18/06/1990 20:00'
end
click_button 'submit'
expect(page).to have_content 'Mostra a tarefa selecionada'
end
end
context "edit new tarefa" do
it "alterando os campos" do
visit "tarefas/#{Tarefa.last.id}/edit"
within("#new_tarefa") do
fill_in 'tarefa_titulo', with: 'user#exa12mple.com'
fill_in 'tarefa_descricao', with: 'passw213ord'
fill_in 'tarefa_data', with: '18/06/1990 21:00'
end
click_button 'submit'
expect(page).to have_content 'Mostra a tarefa selecionada'
end
end
end
end
You should not rely on the tarefa you have created in "create new tarefa" to be available in you next spec as:
It won't work since the ordering is random.
It would create a coupling where one spec relies on the outcome of another.
Instead you want to use database_cleaner to clean out the DB after each spec and use let and let! to setup the requirements for each spec:
require 'rails_helper'
# You can use `feature` as a top level block.
# No need to nest it in descibe.
RSpec.feature "New Tarefa" do
let(:user) { FactoryGirl.create(:user) }
let(:tarefa) { FactoryGirl.create(:tarefa) }
background do
login_as(user, scope: :user)
end
context "create new tarefa" do
it "preenchendo os campos" do
visit '/tarefas/new'
within("#new_tarefa") do
fill_in 'tarefa_titulo', with: 'user#example.com'
fill_in 'tarefa_descricao', with: 'password'
fill_in 'tarefa_data', with: '18/06/1990 20:00'
end
click_button 'submit'
expect(page).to have_content 'Mostra a tarefa selecionada'
end
end
context "edit new tarefa" do
it "alterando os campos" do
# tarefa is created when you reference it.
visit "tarefas/#{tarefa.to_param}/edit"
within("#new_tarefa") do
fill_in 'tarefa_titulo', with: 'user#exa12mple.com'
fill_in 'tarefa_descricao', with: 'passw213ord'
fill_in 'tarefa_data', with: '18/06/1990 21:00'
end
click_button 'submit'
expect(page).to have_content 'Mostra a tarefa selecionada'
end
end
end
My issue is that I have to create a new user and login for each individual capybara test.
An example is below:
require 'spec_helper'
describe "users" do
describe "user registration" do
it "should create a new user and log in" do
# Register a new user to be used during the testing process
visit signup_path
fill_in 'Email', with: 'testuser'
fill_in 'Password', with: 'testpass'
fill_in 'Password confirmation', with: 'testpass'
click_button 'Create User'
current_path.should == root_path
page.should have_content 'Thank you for signing up!'
end
end
describe "user login" do
it "should log in" do
# log in
visit login_path
fill_in 'Email', with: 'testuser'
fill_in 'Password', with: 'testpass'
click_button 'Log In'
current_path.should == root_path
page.should have_content 'Logged in!'
end
end
end
The login test fails because the user no longer exists in the database for that test.
This could be fixed simply by putting both in one test, but I believe that is bad practice.
Also I have another file which currently is registering and logging in between each test using a before_do, which also seems to be quite bad... you can see that code here.
For the record this is my first rails app so perhaps I am trying to do this the wrong way. I would like to dry it up as much as possible..
Is capybara really this bad to use on pages that require user login?
I have done it this way.
require "spec_helper"
describe "Users" do
subject { page }
describe "User Registration" do
before { visit signup_path }
let(:submit) { "Sign up" }
describe "with invalid information" do
it "should not create a user" do
expect { click_button submit }.not_to change(User, :count)
end
end
describe "with valid information" do
before do
fill_in "Email", with: "user#example.com"
fill_in "Password", with: "foobar12"
fill_in "Password confirmation", with: "foobar12"
end
it "should create a user" do
expect { click_button submit }.to change(User, :count).by(1)
end
describe "after registration" do
before { click_button submit }
it { should have_content 'Thank you for signing up!' }
end
describe "after registration signout and login" do
let(:user) { User.find_by_email('user#example.com') }
before do
click_button submit
visit signout_path
sign_in user # sign_in is a method which u can define in your spec/support/utilities.rb . Define once and use at multiple places.
end
it { should have_content 'Logged In!' }
it { should have_link('Logout') }
end
end
end
end
# spec/support/utilities.rb
def sign_in(user)
visit sign_path
fill_in "Email", with: user.email
fill_in "Password", with: user.password
click_button "Log in"
end
your every describe and it block will run after the before block in parent that's why we need to click_button in every block in above test cases.
I'm new to Ruby and Rails and I'm trying to implement tests the correct way. I'm currently working on having users sign up. I would like the first user to sign up to be an admin and then every user after that to be a regular user.
I'm currently thinking I need to write my test as a feature but I'm wondering if this should actually be a model test.
My current code is right here
require 'spec_helper'
describe "User pages" do
subject { page }
describe "Sign up page" do
before { visit signup_path }
it { should have_button('Create!') }
end
describe "Creating an account" do
before { visit signup_path }
let(:submit) { "Create!" }
describe "with invalid information" do
it "should not create the user account" do
expect { click_button "Create!"}.not_to change(User, :count)
end
describe "it should display errors" do
before { click_button submit }
it { should have_content('Failed signup') }
end
end
describe "with valid information" do
before do
fill_in "Name", with: "Example User"
fill_in "Email", with: "user#example.com"
fill_in "Password", with: "password"
fill_in "Confirm Password", with: "password"
end
it "should create the user" do
expect { click_button submit }.to change(User, :count).by(1)
end
# User sign in not implemented at this point
describe "the first user" do
User.all.count.should == 0
click_button submit
User.all.count.should == 1
#firstUser = User.first
#firstUser.is_admin?.should == true
describe "the second user" do
before do
visit signup_path
fill_in "Name", with: "Example User2"
fill_in "Email", with: "user2#example.com"
fill_in "Password", with: "password"
fill_in "Confirm Password", with: "password"
end
click_button submit
#secondUser = User.all.last
#secondUser.is_admin?.should == false
end
end
end
end
end
I'm mostly concerned with the "with valid information" part and would like to clean that up so it fits in with rspec/capybara correctly.
you can try this great tutorial by michael hartl , he use Rspec in this tutorial you can learn from it :)
i am a beginner too and i started with it :D
I have my Login form into the Jquery UI Dialog popup box. When I start doing RSpec test, I got an error with
Failure/Error: fill_in "Username", with: "user#example.com"
Capybara::ElementNotFound
cannot fill in, no text field, text area or password field with id, name, or label 'Username' found
Here is my spec/request page:
describe "create user", :js => true do
before { visit new_enr_rds_dea_path }
let(:submit) { "Create Dea" }
describe "with invalid information" do
it "should not create a user" do
expect { click_button submit }.not_to change(Enr::Rds::Dea, :count)
end
end
describe "with valid information" do
before do
fill_in "Username", with: "user#example.com"
fill_in "Password", with: "foobar"
fill_in "Confirm password", with: "foobar"
fill_in "Organisation", with: "foobar"
end
it "should create a user" do
expect { click_link_or_button submit }.to change(Enr::Rds::Dea, :count).by()
end
end
Factories.rb
FactoryGirl.define do
factory :dea_user do |user|
user.dea_user "example#in4systems.com"
user.dea_pwd "foobar"
user.dea_pwd_confirmation "foobar"
user.pro_organisation_id "NHER"
end
end
I am rendering my new and edit page to the Form partial. Both New and edit button has :remote => true method to open the JqueryUI dialog box. Thanks..
try this
describe "with valid information" do
before do
fill_in "username text-input-field-id", :with => "user#example.com"
...
...
end
replace with the id of the field, as Dipak suggests or use all lowercase. Sometimes it's not Username but just username that Capybara is seeing... or Seleminum to be exact.
I am using rspec for testing devise authentication. Following is my code
require 'spec_helper'
describe User do
describe "user registration" do
it "allows new users to register with an email address and password" do
get "/users/sign_up"
fill_in "Email", :with => "abc#example.com"
fill_in "Password", :with => "abc123"
fill_in "Password confirmation", :with => "abc123"
click_button "Sign up"
response.should have_content("Welcome! You have signed up successfully.")
end
end
end
I am getting the following error.
"NoMethodError:undefined method `get' for #"
You are using controller methods and integration test methods (Capybara) in a Model spec. It will not work.
A model spec (UNIT test) will contain things like:
Test your validators/relationships
Test scopes
Methods of your model
Check out this series of Blog articles on testing with RSpec, it should help:
http://everydayrails.com/2012/03/12/testing-series-intro.html
This seems to be an model spec (describe User) which does not allow to run requests, but you probably want to write a controller spec (describe UsersController) or even an integration test.
If you are using the default rspec layout, just move your code to the appropriate directory (spec/controllers or spec/integration). I would do an integration test:
# In spec/integration/user_registration_spec.rb
require 'spec_helper'
describe "User registration" do
it "allows new users to register with an email address and password" do
get "/users/sign_up"
fill_in "Email", :with => "abc#example.com"
fill_in "Password", :with => "abc123"
fill_in "Password confirmation", :with => "abc123"
click_button "Sign up"
response.body.should have_content("Welcome! You have signed up successfully.")
end
end
Is this file in the spec/models directory? I'm guessing that's the case since you're describeing a User. The way you wrote your test is a mix between a controller-style test and an integration (acceptance) test. This is probably what you want:
require 'spec_helper'
describe User do
describe "user registration" do
it "allows new users to register with an email address and password" do
visit "/users/sign_up"
fill_in "Email", :with => "abc#example.com"
fill_in "Password", :with => "abc123"
fill_in "Password confirmation", :with => "abc123"
click_button "Sign up"
page.should have_content("Welcome! You have signed up successfully.")
end
end
end
Put this file in the spec/integration or spec/requests directory.
I would probably try something like this
require 'spec_helper'
describe User do
describe "user registration" do
it "allows new users to register with an email address and password" do
visit new_user_registration_path
current_path.should be(new_user_registration_path)
fill_in "user[email]", :with => "abc#example.com"
fill_in "user[password]", :with => "abc123"
fill_in "user[password_confirmation]", :with => "abc123"
click_button "Sign up"
expect { click_button submit }.to change(User, :count).by(1)
response.should be_redirect
response.should have_content("Welcome! You have signed up successfully.")
end
end
end
But I can highly recommend to using FactoryGirl for generating new values. Also check, which Devise modules do you use. For example if you are using a Confirmable modul, is obvious that this approach is wrong. Some useful article.