Tell rspec (core) that test is testing controller - ruby-on-rails

Trying to run this test but keep getting the following error:
Failure/Error: get :index
NoMethodError:
undefined method `get' for #<RSpec::ExampleGroups::TestModuleTestController::Controller:0x007fa4bc120d00>
Note: I'm not using rspec-rails.
require "spec_helper"
module TestModule
describe TestController, :type => :controller do
describe "controller" do
it "sets X-Frame-Options to ALLOWALL" do
get :index
expect(response.headers['X-Frame-Options']).to eq('ALLOWALL')
end
end
end
end

Note: I'm not using rspec-rails.
That's your problem right there. All the rails type specs (controller, request, features, views) are part of rspec-rails not rspec-core.
Without rspec-rails the type metadata does absolutely nothing - its just a plain example group describing a class.
The solution is to add rspec-rails to your gemfile.
group :development, :test do
gem 'rspec-rails', '~> 3.6'
end
And run rails g rspec install.
https://github.com/rspec/rspec-rails

Related

How to use binding pry with rspec?

I'm running into an issue with the following in my spec/controller/admin/locations_controller_spec.rb.
Specifically here:
describe 'create' do
it 'should create the record' do
expect do
binding.pry
post :create, params: { location: FactoryBot.attributes_for(:location) }
end.to change(Location, :count).by(1)
end
end
I'm guessing I put it in the correct location to hit it. What do I actually need to call on when using rails console to get output?
Add the gem to your test group:
group :test do
gem 'rspec'
gem 'pry-byebug'
gem 'pry-rails'
end
If you have required gems installed in test environment then you would see the binding when you run your rspec test
Load pry and then type the followings:
require 'rspec/core'
require 'rspec/expectations'
include RSpec::Matchers

expected ActionController::RoutingError but was not given a block in rails app rspec

I try to test my RoR application. When i test to cause ActionController::RoutingError in my controller i get following errors:
Got 1 failure and 1 other error:
2.1) Failure/Error: expect(visit meters_path).to raise_error(ActionController::RoutingError)
expected ActionController::RoutingError but was not given a block
# ./spec/integration/meter_behavior_spec.rb:70:in `block (2 levels) in <top (required)>'
2.2) Failure/Error: raise ActionController::RoutingError.new('Not Found')
ActionController::RoutingError:
Not Found
What is the reason?
It is my list of testing gems:
group :development, :test do
gem 'factory_girl_rails'
gem 'faker'
gem 'rspec-rails'
end
group :test do
gem 'capybara'
gem 'database_cleaner'
gem 'launchy'
gem 'selenium-webdriver', '2.53.4'
gem 'capybara-webkit'
gem 'shoulda-matchers', '~> 3.1'
end
my spec file
meter_behavior_spec.rb
scenario 'a visitor cannot to view meters pages', driver: :webkit do
user = FactoryGirl.create(:client1)
user.meters.create(attributes_for(:meter))
expect(visit meters_path).to raise_error(ActionController::RoutingError)
end
meters_controller.rb:
before_action only: :index do
access_allowed_for(['Client'])
end
# GET /meters
# GET /meters.json
def index
respond_to do |format|
format.json { render json: MetersDatatable.new(view_context, current_user) }
format.html
end
end
application_controller.rb:
def access_allowed_for(statuses_ary=[])
statuses_ary << 'Admin'
if !user_signed_in? || statuses_ary.exclude?(current_user.try(:status))
raise ActionController::RoutingError.new('Not Found')
end
end
The first issue as pointed out in Jean-Christophe's answer is that the raise_error matcher needs a block. The second issue is you're testing something that would really be better tested in a controller test (not Capybara driven) instead of a feature test.
If you insist on testing this in a feature test then there's a few things you need to verify
Make sure you don't have any gems in the test environment that are catching the errors and producing nice/detailed error pages. This would include gems like web_console, better_errors, etc. Those gems should be only in the development environment.
Make sure you have set Capybara.raise_server_errors = true in your test config
You may need to add a second Capybara statement inside the block. This is because Capybara runs the app in a separate thread from the tests and the visit call may occur asynchronously (depending on the driver you use). That means the error may not have actually been raised when the visit call returns. By adding a second call to a capybara method it will wait a little bit for the visit to finish and then detect that an error was raised in the server/app thread and re-raise that error in the test thread.
expect{
visit meters_path
page.has_text? 'Random text' # only here to give time for app to raise error
}.to raise_error(ActionController::RoutingError)
I believe you should simply pass visit meters_path as a block and not as an argument, like so :
expect{visit meters_path}.to raise_error(ActionController::RoutingError)
See :
https://www.relishapp.com/rspec/rspec-expectations/v/2-2/docs/matchers/expect-error
Tell me if it works.

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.

adding spring gem breaks tests - rails

I have some test using rails spec (and also capybara and factory girl) and passing just fine
describe "project creation" do
before(:each) do
#project = FactoryGirl.create(:project)
end
it "create projects fluently" do
visit root_path
#project.should validate_presence_of(:title)
end
end
Then I installed spring, and when I run spring rspec spec/features/projects_spec.rb, it throws
Failure/Error: #project.should validate_presence_of(:title)
NoMethodError:
undefined method `validate_presence_of' for #<RSpec::Core::ExampleGroup...
How can it be
This issue was discussed here: https://github.com/rails/spring/issues/209, but in the readme file of shoulda-matchers gem say how install it with a preloader, basically my solution was:
Move the rspec-rails line in Gemfile above the shoulda-matchers
Add require: :false to shoulda-matchers in Gemfile
Add require 'shoulda/matchers' in spec_helper.rb
My Gemfile look like:
group :test do
gem "rspec-rails"
gem 'shoulda-matchers', require: false
gem 'machinist'
end
Now my specs with shoulda helper work fine with spring!

railstutorial.org - undefined method `Factory'

I'm attempting to follow railstutorial.org, and am currently on Chapter 7, where you start using factories: http://railstutorial.org/chapters/modeling-and-viewing-users-two#sec:tests_with_factories
I'm using Rails 3.0.1 and ruby-1.9.2-p0
I can't for the life of me get my rspec tests to pass though, the error i get is
Failures:
1) UsersController GET 'show' should be successful
Failure/Error: #user = Factory(:user)
undefined method `Factory' for #<RSpec::Core::ExampleGroup::Nested_2::Nested_1:0x00000101cc5608>
# ./spec/controllers/users_controller_spec.rb:9:in `block (3 levels) in <top (required)>'
my factories.rb looks like this:
# By using the symbol ':user', we get Factory Girl to simulate the User model.
Factory.define :user do |user|
user.name "Michael Hartl"
user.email "mhartl#example.com"
user.password "foobar"
user.password_confirmation "foobar"
end
and this is my users_controller_spec.rb file:
require 'spec_helper'
describe UsersController do
render_views
describe "GET 'show'" do
before(:each) do
#user = Factory(:user)
end
it "should be successful" do
get :show, :id => #user
response.should be_success
end
here is my Gemfile, if it helps:
source 'http://rubygems.org'
gem 'rails', '3.0.1'
# Bundle edge Rails instead:
# gem 'rails', :git => 'git://github.com/rails/rails.git'
gem 'sqlite3-ruby', :require => 'sqlite3'
gem 'gravatar_image_tag'
group :development do
gem 'rspec-rails'
gem 'annotate-models'
end
group :test do
gem 'rspec'
gem 'webrat'
gem 'spork'
gem 'factory_girl_rails'
end
As per the latest version of Factory Girl (currently v4.0.0)
rewrite factories.rb
FactoryGirl.define do
factory :user do
name "Michael Hartl"
email "mhartl#example.com"
password "foobar"
password_confirmation "foobar"
end
end
then call it from your users controller specs as:
FactoryGirl.create(:user)
I got this exact same error message. I just restarted my Spork server and Autotest and everything went green for me.
Maybe you should try the new syntax (see github readme of factory girl)
FactoryGirl.define :user do |user|
user.name "Michael Hartl"
user.email "mhartl#example.com"
user.password "foobar"
user.password_confirmation "foobar"
end
In your spec use
#user = FactoryGirl(:user)
instead of
#user = Factory(:user)
I had this problem, but it was because I had placed the factory girl gem under the development section instead of the test section of the Gemfile. Once under the test section, it worked. One difference I note between my entry and yours is that mine specifies 1.0:
group :test do
gem 'rspec-rails', '2.6.1'
gem 'webrat', '0.7.1'
gem 'factory_girl_rails', '1.0'
end
For me I had to add require 'factory_girl' to test_helper.rb
My solution: I've accidentally included it in the :development block, and simply had to move it to the :test block
(I've listed it here, because it might help someone who doesn't follow the tutorial correctly)
I have done so,
add require 'factory_girl' to test_helper.rb and
#user = FactoryGirl.create(:user)
For those finding this page now: note where you once used "FactoryGirl" you must now use "FactoryBot" in your tests. From the thoughtbot announcement page:
"We’re renaming factory_girl to factory_bot (and factory_girl_rails to
factory_bot_rails). All the same functionality of factory_girl, now
under a different name."
More details here:
https://robots.thoughtbot.com/factory_bot
I was determined to use the newest version of Factory Girl, so I tried to adapt the code. Didn't work for me, so I used
gem 'factory_girl_rails', '1.0'
in the Gemfile to lock the version at 1.0
bundle update
restart spork and autotest and it worked.

Resources