I have the following capybara feature scenario:
scenario 'user can create an account' do
visit new_user_path
within(:css, "form[action='/users']") do
fill_in 'user[username]', with: 'dummy'
fill_in 'user[email]', with: 'dummy#email.com'
fill_in 'user[password]', with: 'password'
fill_in 'user[password_confirmation]', with: 'password'
fill_in 'user[address]', with: 'brasilia'
find("input[type='submit']").click
end
expect(page).to have_current_path(root_path)
end
When I execute it, I get the following error:
1) CreateAccount user can create an account
Failure/Error: expect(page).to have_current_path(root_path)
expected "/users" to equal "/"
# ./spec/features/create_account_spec.rb:14:in `block (2 levels) in <top (required)>'
So I tested in development environment with the same params, and everything is working. I used save_and_open_screenshot inside the scenario and I get this message:
Method not Allowed
I don't know what's is happening. Thanks in advance for any help!
Edit 1
I inspect the log but I didn't able to see any request being made, but only an error related to database. Here what I found:
SELECT schemaname || '.' || tablename
FROM pg_tables
WHERE
tablename !~ '_prt_' AND
tablename <> 'schema_migrations' AND
schemaname = ANY (current_schemas(false))
I don't know if this will help but the only log snippet thats looks like an error.
Edit 2
I runned rails s -e test and discovered that the hidden_tag authencity token is missing inside the form tag that mades the request. Can this be the cause of method not allowed?
Related
I have started to test my app via Rspec (Capybara). This is how I am doing it:
require 'rails_helper'
RSpec.describe "Homepages", type: :request do
describe "GET / without login" , js: true do
before(:all) do
Employee.create(username: "username", password: "12345", password_confirmation: "12345")
end
it "works!" do
visit root_path
fill_in "loginname", with: "username"
fill_in "password", with: "12345"
click_button('sign_in')
end
end
end
Because of env namely "TEST-ENV" I have to create an employee at first.
the problem is, if I run 'rake spec:requests', I get this errors:
1) Homepages GET / without login works!
Got 0 failures and 2 other errors:
1.1) Failure/Error:
def initialize(template, original_exception)
super(original_exception.message)
#template, #original_exception = template, original_exception
#sub_templates = nil
set_backtrace(original_exception.backtrace)
end
ArgumentError:
wrong number of arguments (1 for 2)
#/.rvm/gems/ruby-2.1.1/gems/actionview-4.2.7/lib/action_view/template/error.rb:64:in `initialize'
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara/session.rb:128:in `exception'
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara/session.rb:128:in `raise'
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara/session.rb:128:in `rescue in raise_server_error!'
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara/session.rb:125:in `raise_server_error!'
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara/session.rb:113:in `reset!'
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara.rb:334:in `block in reset_sessions!'
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara.rb:334:in `reverse_each'
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara.rb:334:in `reset_sessions!'
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara/rspec.rb:21:in `block (2 levels) in <top (required)>'
# ------------------
# --- Caused by: ---
# Capybara::CapybaraError:
# Your application server raised an error - It has been raised in your test code because Capybara.raise_server_errors == true
# /.rvm/gems/ruby-2.1.1/gems/capybara-2.10.1/lib/capybara/session.rb:126:in `raise_server_error!'
I'm not sure but I think better if type = feature
Sample
require "rails_helper"
RSpec.feature "Homepages", type: :feature do
before do
Employee.create(username: "username", password: "12345", password_confirmation: "12345")
end
context "GET / without login" do
scenario "works!", js: true do
visit root_path
fill_in "loginname", with: "username"
fill_in "password", with: "12345"
click_button('sign_in')
end
end
end
Please make sure your input name is correct by inspect element to get the input name
I think
fill_in "loginname", with: "username"
maybe be
fill_in "user[loginname]", with: "username"
As others have stated, Capybara tests should be of type 'feature' not 'request', however that's not the primary cause of your error. Your apps code is raising an exception during template rendering, and then you're running into a bug in the current version of Capybara with handling exceptions whose initializers take multiple parameters. As long as you're not using jRuby you can lock your Capybara version to 2.10.0 and you should see the correct error your app is raising. If you are using jRuby, or if you prefer to not lock to an older version, you can specify to use the master branch of Capybara
gem 'capybara', github: 'teamcapybara/capybara'
which has the bug fixed.
As a side-note, you've tagged this question with capybara-webkit when you're not actually using the capybara-webkit driver (since it only supports up to Capybara 2.7.1 currently), so you might want to change the tag to just capybara.
So, for some reason my routes increment by 11 when I run my comment feature test.
Exhibit A: I hit save on my comment_spec.rb
RSpec.feature "Adding comments to movies" do
before do
#kyle = Admin.create(email: "kyle#example.com", password: "password")
#jill = Member.create(email: "jill#example.com", password: "password")
#movie = Movie.create!(title: "First movie", synopsis: "Synopsis of first movie", year_released: '2000', admin: #kyle)
end
scenario "permits a signed in member to write a comment" do
login_as(#jill, scope: :member)
visit "/"
click_link #movie.title
fill_in "New Review", with: "An awesome movie"
click_button "Add Review"
expect(page).to have_content("Review has been created")
expect(page).to have_content("An awesome movie")
# must implement a nested route in order for this to work.
expect(current_path).to eq(movie_path(#movie.comments.last.id))
end
end
Then the test passes
moviesmoviesmovies/spec/features/comments_spec.rb:3)
Finished in 0.99879 seconds (files took 2.4 seconds to load) 1
example, 0 failures
Now, I hit enter in the terminal and get this:
Adding comments to movies permits a signed in member to write a comment
Failure/Error: expect(current_path).to eq(movie_path(#movie.comments.last.id))
expected: "/movies/2"
got: "/movies/4"
(compared using ==)
# ./spec/features/comments_spec.rb:26:in `block (2 levels) in <top (required)>'
Then I save the comment_spec.rb again and get this:
Adding comments to movies permits a signed in member to write a comment
Failure/Error: expect(current_path).to eq(movie_path(#movie.comments.last.id))
expected: "/movies/3"
got: "/movies/15"
(compared using ==)
# ./spec/features/comments_spec.rb:26:in `block (2 levels) in <top (required)>'
After this happens, I run:
bundle exec rails db:test:prepare
Then the tests pass again, but the above repeats. What in the world is making this happen? haha, but really?
My GitHub if needed.
The issue you're having is that your database isn't being reset after each feature test, as you likely expect it is. Specifically, the problem is with Capybara and the config.use_transactional_fixtures = true line which is set in your spec config.
Capybara effectively tests your application as an external process using a virtual browser. This means that your capybara tests only have visibility into the client-side behavior of your app (i.e. the page variable). In other words, from Capybara's perspective your app is a "Black box". Therefore, capaybara doesn't see controller objects like your session, params, or request variables, nor can it see or control the specific database transactions which occur during testing.
Rather than relying on transactional fixtures, consider using database cleaner, which manually resets the database after each feature test. You can find the gem here: https://github.com/DatabaseCleaner/database_cleaner. Make sure you follow the directions on integrating with Capybara: https://github.com/DatabaseCleaner/database_cleaner#rspec-with-capybara-example.
I've formatted my computer and while reinstalling Rails changed my database to postgres, and now a few tests that were previously passing are failing, for example the following code:
describe "Tickets" do
subject { page }
describe "when creating a new ticket successfully" do
before do
login_as_user
visit new_ticket_path
fill_in "Subject", with: "Test ticket"
fill_in "Description", with: "This is a test ticket"
select 'Billing', from: "ticket[category]"
click_button "Submit Ticket"
TicketNotifier.drain
Sidekiq::Extensions::DelayedMailer.drain
end
specify { last_email.to.should include("my.email#gmail.com") }
it { should have_selector('title', text: "Ticket #1") }
it { should have_content("ticket has been submitted successfully") }
end
end
Returns the following errors:
10) Tickets when creating a new ticket successfully
Failure/Error: TicketNotifier.drain
ActiveRecord::RecordNotFound:
Couldn't find Ticket with id=366
# ./app/workers/ticket_notifier.rb:5:in `perform'
# ./spec/requests/blas_spec.rb:14:in `block (3 levels) in <top (required)>'
# same error repeated a few times...
Or:
context "should not be able to edit other user's website" do
before { visit edit_rental_path(1) }
it { should have_selector('title', text: "Your Websites") }
it { should have_selector(notice, text: "You do not have access to this domain.") }
end
Throwing a few of the following:
2) Websites create a user with 2 websites log user out log in second user should not be able to edit other user's website
Failure/Error: before { visit edit_website_path(1) }
ActiveRecord::RecordNotFound:
Couldn't find Website with id=1
# ./app/controllers/websites_controller.rb:116:in `correct_user'
# ./spec/requests/websites_spec.rb:187:in `block (6 levels) in <top (required)>'
So, is it creating a new object for every it { should ... } clause?
Even when I try something like the following it can't find by id:
#site = Website.where(link: "http://google.com").first
visit website_path(#site)
What has changed that's creating these issues?
Update
I've emptied my gemset as suggested by depa and now I don't get errors for the first test I posted, even when I specify it { should have_selector('title', text: "Ticket #1") }. The #1 comes from the ID of the ticket, so for some reason it's working on those tests like it used to, but I'm still getting errors on others unless I change them to:
before do
# create the ticket
#ticket = Ticket.where(...).first
end
it { should have_selector('h2', text: "Ticket ##{#ticket.id}") }
Whereas previously if I just left it as Ticket #1 the tests would pass. Do postgres and sqlite work differently as test databases?
I would try resetting your gem environment, starting from gem pristine rspec-rails and gem pristine capybara and going as far as rvm gemset empty if you use RVM.
I am following railscast #275 with testing the forgot me password. I am having troubles getting past the email has already been taken error. With the coding I have by following the tutorial I am suppose to receive this error, "error for no link with title or text "password". Instead this is what I am getting, "Validation failed: Email has already been taken (ActiveRecord::RecordInvalid)"
I have done a search, unable to find a solution for it.
Here's password_resets_spec.rb:
require 'spec_helper'
describe "PasswordResets" do
it "emails user when requesting password reset"
user = FactoryGirl.create(:user)
visit login_path
click_link "password"
fill_in "Email", :with => user.email
click_button "Reset Password"
end
factories.rb:
FactoryGirl.define do
factory :user do
sequence :email do |n| "test#{n}#example.com"
end
password "secret"
end
end
Here's what I did when I finally notice it started to work. I installed database cleaner. Then I did the commands:
rake db:reset
rake db:migrate
rake db:test:prepare
Following that I noticed I had to add a "do" to the end of " it "emails user when requesting password reset".
Now I have no errors and I can continue in my testing adventure. Thanks to those who tried to assist.
The factory definition seems OK.
I would start by making sure that your test database is empty before running the spec. There may be an existing user record "test1#example.com" lingering. Also, have you tried to run only that example? Does it make any difference?
Looks like while running your test cases the factory that was created didn't rolled back/deleted the record.
add a before(:each) deletes previous records before the example executes
before(:each) do
User.delete_all
end
I'm trying to test the order process in a request spec by filling out the purchase form:
describe "CC order" do
before do
visit order_path "product"
fill_in "full_name", with: "test name"
fill_in "email", with: "test#email.com"
fill_in "card_number", with: "4242424242424242"
fill_in "card_cvc", with: "123"
# etc...
click_on "complete-button"
end
it "should display confirmation message" do
page.should have_content "Thanks for your order!"
end
end
A new User and Order should be saved after the purchase form is submitted and does so correctly in development. However, my test fails because instead of processing the order it tells me that the database is locked:
I do have transactional fixtures turned on and some of my other tests use them. Is there another way I should be testing my order process?
EDIT: It seems like it open happens when I use page in the it block. If I just make the test block empty, everything works fine.
I was running out of ideas so I switched from sqlite to postgresql in development + test. That fixed the problem.