Rspec - obvious test is failing, how to troubleshoot? - ruby-on-rails

I have a very simple app I'm trying to test with rspec. I'm having a hard time figuring out if my configuration is the problem, or if it's the code. The first line of /people/index.html.erb is <h1>Totally Awesome Page</h1>.
The error:
expected to find text "Totally Awesome Page" in "Index"
./spec/features/people_spec.rb:19:in `block (3 levels) in <class:PeopleSpec>'
test gems:
group :development, :test do
gem 'rspec'
gem 'rspec-rails'
gem 'capybara'
gem 'factory_girl_rails'
end
spec/features/people_spec.rb:
require 'spec_helper'
class PeopleSpec < ActionDispatch::IntegrationTest
describe "People" do
describe "Index" do
before { visit '/people'}
it { should have_content('Totally Awesome Page')}
end
end
end
spec/spec_helper:
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
require 'minitest/autorun'
require 'capybara/rails'
require 'capybara/rspec'
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
ActiveRecord::Migration.maintain_test_schema!
RSpec.configure do |config|
config.use_transactional_fixtures = true
config.infer_base_class_for_anonymous_controllers = false
config.order = "random"
config.include Capybara::DSL
end
routes:
people_path GET /people(.:format) people#index
POST /people(.:format) people#create
new_person_path GET /people/new(.:format) people#new
edit_person_pathGET /people/:id/edit(.:format) people#edit
person_path GET /people/:id(.:format) people#show
PATCH /people/:id(.:format) people#update
PUT /people/:id(.:format) people#update
DELETE /people/:id(.:format) people#destroy

Add gem 'launchy' and then you can use save_and_open_page after visit to see how rendered page looks like.
Add subject { page } to the spec to fix it.
If you say it than it have to point to something. In your test it doesn't.
You can use should on page to do that (page is not the only one you can test. There are more, like response or even lambdas) that way:
it "some description" do
page.should have_content('foo')
end
or if you have many tests for page than you can write them in a short way:
it { should have_content('foo') }
but you need to specify subject for it first:
subject { page }

Related

Ruby on Rails - Rspec test with Devise is failing

I have a Problem with an rspec-request-test in my rails app. The tests, that need a user-login are failing. I have implemented the devise-tests according to this tutorial. Also I found many links, that are using a similar approach. e.g. here
Here is an extract of my gemfile:
gem 'devise', '~> 3.5'
gem 'devise-i18n'
gem 'devise-i18n-views'
gem 'cancancan', '~> 1.10'
gem 'rolify'
gem 'alchemy_cms', '~> 3.2.0'
gem 'rspec-core'
gem 'rspec-rails'
gem 'i18n-tasks', '~> 0.8.7'
gem 'factory_girl_rails'
Here is the rspec-test, that is failing: (spec/requests/campaigns_spec.rb)
require 'rails_helper'
RSpec.describe "Campaigns", type: :request do
describe "GET /campaigns" do
it "responds with 200" do
sign_in_as_a_valid_user_request
get campaigns_path
expect(response).to have_http_status(200)
end
end
end
You should only see this page, when you are logged in. So in the test I want to log in as a User (created with FactoryGirl), than go to the site, and get a 200-response. In the application itself this is working good.
spec/rails_helper.rb (extract)
...
require 'spec_helper'
require 'rspec/rails'
require 'devise'
require 'support/devise_support'
ActiveRecord::Migration.maintain_test_schema!
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
config.include Devise::TestHelpers, type: :controller
config.include Devise::TestHelpers, type: :view
config.include ValidUserRequestHelper
...
end
spec/support/devise_support.rb
module ValidUserRequestHelper
def sign_in_as_a_valid_user_request
#user ||= FactoryGirl.create :user
post_via_redirect user_session_path, 'user[email]' => #user.email, 'user[password]' => #user.password
end
end
here is the error, that the test is throwing:
1) Campaigns GET /campaigns responds with 200
Failure/Error: sign_in_as_a_valid_user_request
ActionController::RoutingError:
Alchemy::Page not found "/"
# ./spec/support/devise_support.rb:13:in `sign_in_as_a_valid_user_request'
# ./spec/requests/campaigns_spec.rb:6:in `block (3 levels) in <top (required)>'
According to the links that I found, this should work! but it doesn't... Can anyone tell me why? Why is there a routing error? The app itself is working fine.
The routing error occurs, because your host app does not know of the engines routes. That's why you have to use the routing proxy objects of rails engines in views outside the current controller scope. Please read more about rails engines and the characteristics of their routes in the official rails guides
Luckily, Alchemy comes with a handy test helper that solves your problems. Just add this to your spec_helper:
# spec/spec_helper.rb
require 'alchemy/test_support/controller_requests'
...
RSpec.configure do |config|
config.include Alchemy::TestSupport::ControllerRequests
...
end
Know you can use alchemy_get instead of get in your request specs.

Requiring module in Rspec in rails 4 application

I'm trying to include additional Devise helpers in Rspec but am receiving the following error:
rails_helper.rb:56:in `block in <top (required)>': uninitialized constant ControllerMacros (NameError)
Line 56 in rails_helpers.rb is the config.include ControllerMacros line that I have. I've tried to solve this with the solutions posted in other SO posts but can't seem to get this to work. I understand this might be a require order issue but haven't been able to sort out the right order.
rails_helper.rb
ENV["RAILS_ENV"] ||= 'test'
require 'spec_helper'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'capybara/rails'
require 'capybara/rspec'
require 'devise'
ctiveRecord::Migration.maintain_test_schema!
RSpec.configure do |config|
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.use_transactional_fixtures = true
config.infer_spec_type_from_file_location!
config.include Capybara::DSL
config.include Devise::TestHelpers, :type => :controller
config.include ControllerMacros, :type => :controller
end
spec/support/controller_macros.rb
module ControllerMacros
def login_business
before(:each) do
#request.env["devise.mapping"] = Devise.mappings[:business]
business = FactoryGirl.create(:business)
buisness.confirm!
sign_in business
end
end
end
spec/business_account_controller_spec.rb
require 'spec_helper'
require 'rails_helper'
describe BusinessAccountController do
login_business
it "should have current user" do
expect(subject).to_not be_nil
end
end
You need to require it in your rails_helper. I place all of my modules in /spec/support and then put Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f } at the top of my rails_helper

Guard not loading Capybara DSL

I'm running Rails 4, trying to set up some integration test with Rspec and Capybara. I want to set up guard to run 'zeus test .' whenever I make changes. Problem is, whenever anything form the Capybara DSL is called, or whenever I try to use route helpers, I'm given errors like this:
undefined local variable or method `root_path' for #<RSpec::Core::ExampleGroup::Nested_2::Nested_1:0x007f55682c6d60>
If I replace root_path with '/' it get:
undefined method `visit' for #<RSpec::Core::ExampleGroup::Nested_2::Nested_1:0x007f556833bbb0>
If I just run 'rspec spec .' or 'zeus test .' it works fine.
I've tried removing the 'cmd: 'zeus test .' option from my Guardfile, but I'm having the same issues. It seems clear that the problem is with Guard and unrelated to zeus.
In my Gemfile:
group :development, :test do
gem 'capybara'
gem 'rspec-rails'
gem 'factory_girl_rails'
gem 'guard-rspec', require: false
gem 'better_errors'
gem 'binding_of_caller'
end
Spec helper:
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
require 'factory_girl_rails'
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration)
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.use_transactional_fixtures = true
config.infer_base_class_for_anonymous_controllers = false
config.order = "random"
end
Spec I'm trying to run:
require 'spec_helper'
describe "HomePage" do
describe "Root page" do
before { visit root_path }
it "works!" do
page.status_code.should be(200)
end
it 'contains bottom nav buttons' do
page.should have_link 'How it works'
page.should have_link 'Customer Service'
page.should have_link 'Terms of Service'
page.should have_link 'Contact Us'
end
end
end
try add
config.include Capybara::DSL
to your spec_helper.rb
Try to add url_helpers to spec_helper.rb
RSpec.configure do |config|
...
config.include Rails.application.routes.url_helpers
end
and check my other answer about visit method missing
I fixed this problem by commenting out this line in my spec_helper.rb:
require 'rspec/autorun'
Again, the problem was only with Guard and I suppose that autorun somehow skips over the config block in the spec_helper, so everything works fine now. Hope this helps someone else having the same problem.

undefined method `visit' when using RSpec and Capybara in rails

I can't get capybara working with rspec. It gives me this error:
undefined method `visit' for #<RSpec::Core::ExampleGroup::Nested_1:0x16529f8 #example=nil>
I know there are lots of posts about this but non of the solutions are working for me. Most of them involve the specs not being in /spec/features - which mine is in.
First the error:
$bundle exec rspec spec
F
Failures:
1) security signs users in
Failure/Error: visit "/sessions/new"
NoMethodError:
undefined method `visit' for #<RSpec::Core::ExampleGroup::Nested_1:0x16529f8 #example=nil>
# ./spec/features/security_spec.rb:4:in `(root)'
Finished in 0.006 seconds
1 example, 1 failure
Failed examples:
rspec ./spec/features/security_spec.rb:3 # security signs users in
I think its important to note that at first I was using the URL Helper 'new_sessions_path' and it kept giving me an error undefined local variable or method 'new_sessions_path'. I know it is valid because:
$ rake routes
logout_sessions GET /sessions/logout(.:format) sessions#logout
sessions POST /sessions(.:format) sessions#create
new_sessions GET /sessions/new(.:format) sessions#new
contracts POST /contracts(.:format) contracts#create
new_contracts GET /contracts/new(.:format) contracts#new
edit_contracts GET /contracts/edit(.:format) contracts#edit
GET /contracts(.:format) contracts#show
PUT /contracts(.:format) contracts#update
DELETE /contracts(.:format) contracts#destroy
root / contracts#index
My Gemfile:
source 'https://rubygems.org'
gem 'rails', '3.2.11'
gem 'execjs'
group :assets do
gem 'sass-rails', '~> 3.2.3'
gem 'coffee-rails', '~> 3.2.1'
gem 'uglifier', '>= 1.0.3'
end
gem 'jquery-rails'
gem 'activerecord-oracle_enhanced-adapter', '~> 1.4.1'
gem 'jruby-openssl'
gem 'therubyrhino'
gem 'kaminari'
gem 'nokogiri'
group :development do
gem 'warbler'
end
group :test do
gem 'rspec-rails'
gem 'capybara'
gem 'activerecord-jdbcsqlite3-adapter'
end
spec_helper.rb inside of my_app/spec:
# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
# Capybara integration
require 'capybara/rspec'
require 'capybara/rails'
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
RSpec.configure do |config|
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
# config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.use_transactional_fixtures = true
config.infer_base_class_for_anonymous_controllers = false
config.order = "random"
# Include path helpers
config.include Rails.application.routes.url_helpers
end
my_app/spec/features/security_spec.rb:
describe "security", :type => :feature do
it "signs users in" do
visit "/sessions/new"
fill_in "username", :with => "user"
fill_in "password", :with => "pass"
click_button "Sign In"
page.should have_content('Login Successful')
end
end
I've tried defining the test above both with and without :type => :feature. It makes no difference either way. Any ideas what I should try next?
Try to add:
config.include Capybara::DSL
to your config block.
# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
RSpec.configure do |config|
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
# config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.use_transactional_fixtures = true
config.infer_base_class_for_anonymous_controllers = false
config.order = "random"
# Include path helpers
config.include Rails.application.routes.url_helpers
config.include Capybara::DSL
end
Adding require 'rails_helper' at the top of my feature ended up fixing my problem:
require 'rails_helper'
describe "security", :type => :feature do
it "signs users in" do
visit new_sessions_path
fill_in "username", :with => "user"
fill_in "password", :with => "pass"
click_button "Sign In"
page.should have_content('Login Successful')
end
end
This seems odd to me since every example I've seen for rspec and capybara didn't have that require, but oh well. Problem solved.
Original Answer (older versions of rspec)
require 'spec_helper' is used by older versions of RSpec. The better answer would be require 'rails_helper'.
Since Capybara 2.0 one has to use folder spec/features Capybara commands don't work in folder spec/requests anymore.
Try performing all your setup in a before block:
spec/features/security_spec.rb
describe "security" do
before do
visit "/sessions/new"
fill_in "username", :with => "user"
fill_in "password", :with => "pass"
click_button "Sign In"
end
it "signs users in" do
page.should have_content('Login Successful')
end
end
I also had this problem,
Adding require 'rails_helper' at the top of my feature ended up fixing my problem:
require 'rails_helper'
RSpec.describe "Products", type: :request do
describe "GET /products" do
it "display tasks" do
Product.create!(:name => "samsung")
visit products_path
page.should have_content("samsung")
#expect(response).to have_http_status(200)
end
end
end
And add the 'config.include Capybara::DSL' in rails_helper.rb
RSpec.configure do |config|
config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.use_transactional_fixtures = true
config.infer_spec_type_from_file_location!
config.include Capybara::DSL
end
Other than the upgrading issue which you would run into when ugprading from an older Rails app with require 'spec_helper.rb' instead of require 'rails_helper.rb', this happens for 3 known reasons:
1. Your spec isn't of type "feature"
which means Capybara doesn't know how to run it using Javascript or a browser. You want to do one of two things: 1) Typically, you want config.infer_spec_type_from_file_location! set in your RSpec.configure and that will mean that what's in the features folder will be a feature.
if you have something non-standard, you can add type: :feature to the spec describe block to turn that spec in a feature, but typically it's easier just to put them into the /features folder and let the infer setting do its job.
2. You accidentally put the visit outside of the it block
The visit must be within the it, which is within the describe. Be sure not to put the visit directly within the describe.
3. Some other kernal panic you can't see has caused Capy to shut down the spec.
This is a nasty one to diagnose but I have seen it. It means that Capy didn't actually parse this file correctly, and so somehow isn't in the right scope when it gets to the visit block. Carefully pick apart your Capy spec to figure out where you introduced it.
I induced the kernal panic today but have a let block be called page (whoops). page appears to be a reserved word for Rspec or Capy here, and it causes the kernal panic, thus leading to the spec not to parse thus leading to the visit method not being found.
in my case, it was simply changing this:
let(:page) {Page.new()}
to
let(:content_page) {Page.new()}
Notice that the word page is not reserved by Rails, and works fine as a database name and also a model name, but the specific construction of using page here as the let variable name seemed to cause Capy to get kind of crappy.

Capybara methods are undefined

I cannot get capybara to work. I am using capybara 2.0.0
I get this error
Failure/Error: visit "/users/sign_in"
NoMethodError:
undefined method `visit' for #<RSpec::Core::ExampleGroup::Nested_21:0x007fdda4c6eba0>
on this spec
spec/requests/forgot_password_spec.rb
describe "forgot password" do
it "redirects user to users firms subdomain" do
visit "/users/sign_in"
end
end
I do not get any errors that it cannot find capybara and it's included in the spec_helper.rb
spec_helper.rb
require 'rubygems'
require 'spork'
require 'database_cleaner'
Spork.prefork do
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'capybara/rspec'
require 'rspec/autorun'
require 'factory_girl'
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
RSpec.configure do |config|
config.include Devise::TestHelpers, :type => :controller
config.extend ControllerMacros, :type => :controller
config.include RequestMacros, :type => :request
config.mock_with :rspec
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
config.infer_base_class_for_anonymous_controllers = false
end
Spork.each_run do
FactoryGirl.reload
end
end
Has anybody else encountered this?
If you've got version >= 2.0, any tests that use Capybara methods like visit should go under a spec/features directory, and not under spec/requests, where they'd normally reside in Capybara 1.1.2.
Have a look at the following links for more information:
rspec-rails and capybara 2.0: what you need to know
rspec-rails gem Capybara page
If you don't want to use a spec/features directory, you should be able to mark a test as a feature in the following way and have Capybara methods work:
describe "Some action", type: :feature do
before do
visit "/users/sign_in"
# ...
end
# ...
end
In my case, I got this error because I forgot to putrequire "spec_helper"
at the top of my new spec file.
I've done it enough times that I'm adding an answer to an already answered question in hopes that it helps some other knucklehead (or most likely me searching this again in the future).

Resources