View specs have no render method - ruby-on-rails

I’m trying to write some view specs that test some template logic. I’m following the instructions in the RSpec book, and also checking other online references. I don’t seem to have access to render or assign.
require "spec_helper"
describe "projects/index.html.erb" do
it "displays an entry for each project" do
projects = 5.times { FactoryGirl.create :project }
render
expect(all(".project-index-entry").count).to eq 5
end
end
When I run the above, I get:
Failure/Error: render
NameError:
undefined local variable or method `render' for #<RSpec::ExampleGroups::ProjectsIndexHtmlErb:0x007fa2950d4140>
# ./spec/views/projects/index.html.erb_spec.rb:7:in `block (2 levels) in <top (required)>'
The same thing happens if I try to use assign. I know I could use visit, but then I would have to simulate the act of the user signing in before each spec. I may be misunderstood, but I think the render method is meant to be more isolated, allowing me to skip the authentication check I have in the controller.
So, why don’t I have the view spec methods I was expecting?
Versions:
- capybara 2.4.1
- rails 4.1.0
- rspec-core 3.1.3
- rspec-expectations 3.1.1
- rspec-mocks 3.1.0
- rspec-rails 3.1.0

As it turns out, I updated rspec some time ago and the previous version used a significantly different spec_helper. After the update, the logic was split into spec_helper and rails_helper, so to fix this problem I had to rerun rails generate rspec:install.

Related

RSpec, Rails 6 and Devise

Currently have a Rails 6 project with Devise. Trying to build some RSpec tests (I'm just learning RSpec). The user authentication seems to be causing this problem. This error occurs when running the RSPec test for a view.
Failure/Error: <%= form.hidden_field :user_id, :value => current_user.id%>
ActionView::Template::Error:
Devise could not find the `Warden::Proxy` instance on your request environment.
Make sure that your application is loading Devise and Warden as expected and that the `Warden::Manager` middleware is present in your middleware stack.
If you are seeing this on one of your tests, ensure that your tests are either executing the Rails middleware stack or that your tests are using the `Devise::Test::ControllerHelpers` module to inject the `request.env['warden']` object for you.
# ./app/views/agent_quotes/edit.html.erb:38:in `block in _app_views_agent_quotes_edit_html_erb___1192221995643336498_23640'
# ./app/views/agent_quotes/edit.html.erb:35:in `_app_views_agent_quotes_edit_html_erb___1192221995643336498_23640'
# ./spec/views/agent_quotes/edit.html.erb_spec.rb:16:in `block (2 levels) in <main>'
# ------------------
# --- Caused by: ---
# Devise::MissingWarden:
# Devise could not find the `Warden::Proxy` instance on your request environment.
# Make sure that your application is loading Devise and Warden as expected and that the `Warden::Manager` middleware is present in your middleware stack.
# If you are seeing this on one of your tests, ensure that your tests are either executing the Rails middleware stack or that your tests are using the `Devise::Test::ControllerHelpers` module to inject the `request.env['warden']` object for you.
# ./app/views/agent_quotes/edit.html.erb:38:in `block in _app_views_agent_quotes_edit_html_erb___1192221995643336498_23640'
I've searched for solutions and incorporate suggestions such as adding
config.include Devise::Test::ControllerHelpers, type: :controller
and require 'spec_helper' to my rails_helper.rb file but no change. Most of the suggestions seemed to be for earlier versions of Rails. I'll keep looking at docs but if anyone has run into this please let me know.

capybara have_title NoMethodError

At the moment, this is a simple project - just a couple of static pages. I'm developing a generic test framework but am struggling to differentiate between the different test options. I have added Rspec, Capybara, Faker, Factory Girl, Spring, and shoulda (though I'm not using the shoulda matchers at the moment).
I have this controller test file:
require 'rails_helper'
RSpec.describe StaticPagesController, type: :controller do
describe "GET #a_page" do
before(:each) { get :a_page }
it "returns http success" do
expect(response).to have_http_status(:success)
end
it "has a page title Static Site" do
expect(response).to have_title('Static Site')
end
end
end
When this runs through guard, it throws an error stack:
23:13:39 - INFO - Run all
23:13:39 - INFO - Running all specs
Running via Spring preloader in process 4498
Running via Spring preloader in process 4506
/home/steve/workspaces/static_site/db/schema.rb doesn't exist yet. Run `rake db:migrate` to create it, then try again. If you do not intend to use a database, you should instead alter /home/steve/workspaces/static_site/config/application.rb to limit the frameworks that will be loaded.
.F
Failures:
1) StaticPagesController GET #a_page has a page title Static Site
Failure/Error: expect(response).to have_title('Static Site')
NoMethodError:
undefined method `match' for nil:NilClass
Did you mean? catch
# /home/steve/.rvm/gems/ruby-2.3.1/gems/capybara-2.7.1/lib/capybara/queries/title_query.rb:18:in `resolves_for?'
# /home/steve/.rvm/gems/ruby-2.3.1/gems/capybara-2.7.1/lib/capybara/node/document_matchers.rb:20:in `block in assert_title'
# /home/steve/.rvm/gems/ruby-2.3.1/gems/capybara-2.7.1/lib/capybara/node/simple.rb:144:in `synchronize'
# /home/steve/.rvm/gems/ruby-2.3.1/gems/capybara-2.7.1/lib/capybara/node/document_matchers.rb:19:in `assert_title'
# /home/steve/.rvm/gems/ruby-2.3.1/gems/capybara-2.7.1/lib/capybara/rspec/matchers.rb:105:in `matches?'
# ./spec/controllers/static_pages_controller_spec.rb:34:in `block (3 levels) in <top (required)>'
# /home/steve/.rvm/gems/ruby-2.3.1/gems/spring-commands-rspec-1.0.4/lib/spring/commands/rspec.rb:18:in `call'
# /home/steve/.rvm/gems/ruby-2.3.1/gems/spring-1.7.1/lib/spring/command_wrapper.rb:38:in `call'
# /home/steve/.rvm/gems/ruby-2.3.1/gems/spring-1.7.1/lib/spring/application.rb:191:in `block in serve'
# /home/steve/.rvm/gems/ruby-2.3.1/gems/spring-1.7.1/lib/spring/application.rb:161:in `fork'
# /home/steve/.rvm/gems/ruby-2.3.1/gems/spring-1.7.1/lib/spring/application.rb:161:in `serve'
# /home/steve/.rvm/gems/ruby-2.3.1/gems/spring-1.7.1/lib/spring/application.rb:131:in `block in run'
# /home/steve/.rvm/gems/ruby-2.3.1/gems/spring-1.7.1/lib/spring/application.rb:125:in `loop'
# /home/steve/.rvm/gems/ruby-2.3.1/gems/spring-1.7.1/lib/spring/application.rb:125:in `run'
# /home/steve/.rvm/gems/ruby-2.3.1/gems/spring-1.7.1/lib/spring/application/boot.rb:19:in `<top (required)>'
# -e:1:in `<main>'
Finished in 0.029 seconds (files took 2.54 seconds to load)
2 examples, 1 failure
Failed examples:
rspec ./spec/controllers/static_pages_controller_spec.rb:33 # StaticPagesController GET #a_page has a page title Static Site
The first test runs OK and, without the second, I get a clean result. I've spent a lot of time going over my config and it looks OK. I have also looked at the docs and some support sites.
Can anybody help out?
Capybara matchers need to be called against a html/xml document element (or a string that parses into a document), not against a response object. By default Capybaras matchers are normally only available in feature and view specs (not controller) was there a particular reason you included them into controller specs? Verifying a pages title really should lean more towards being a view spec than controller (by default views aren't rendered in controller specs - https://www.relishapp.com/rspec/rspec-rails/docs/controller-specs).
As #Thomas Walpole pointed out, Capybara is not enabled in controller specs by default. One option is to change the type of the test to feature (type: :feature).
To make Capybara's built-in matcher have_title work, you need to use visit from Capybara's API, not get from ActionDispatch::IntegrationTest.

Minitest on Rails 4 & Ruby 2 - getting 'assert_not' to work

I'm trying to use minitest (with rails 4.1.1 & ruby 2.0). For a the below spec, I'm getting an error:
it "is invalid when phone number too short" do
#contact.phone = "123456789"
assert_not #contact.valid?
end
1) Error:
Contact#test_0009_is invalid when phone number too short:
NoMethodError: undefined method `assert_not' for #<#<Class:0x007f8d6ac14608>:0x007f8d6b843488>
test/models/contact_test.rb:32:in `block (2 levels) in <top (required)>'
My dev & test for gem file has the following:
gem 'minitest-rails', '~> 2.0.1'
gem 'minitest', '~> 5.3.4'
By the way, I just upgraded to ruby 2.1.2 to no avail.
If available, please share with me clear documentation on setting rails 4 with minitest.
The assert_not method is added in ActiveSupport::TestCase, and is not present in vanilla Minitest tests. Most likely your test is not using ActiveSupport::TestCase. The easiest way to check is to add the following line to your test:
assert_includes self.class.ancestors, ActiveSupport::TestCase
The next question is why. I don't know what the rest of your test looks like so I can't say for sure. Whatever you are passing to the describe method isn't being matched to ActiveSupport::TestCase. New in minitest-rails 2.0 is the ability to match on an optional second parameter to describe. So an easy way to ensure ActiveSupport::TestCase is to provide :model.
describe "I'm not sure what you are doing here", :model do
it "is invalid when phone number too short" do
#contact.phone = "123456789"
assert_not #contact.valid?
end
end
Just found out that assert_not is only available inside ActiveSupport::TestCase when you use Spec it's not present

rails 3.2 and machinist issues

I've just upgraded to Rails 3.2.1 with Ruby 1.9.3-p0 and I'm using Machinist 2.0. Before updating a large project all my tests passed. The problem I"m having is when I create a blueprint within a 'let' call in my rspec tests and then refer to it in a before do block.
let (:new_post) {Post.make!}
before do
Post.stub!(:new).and_return(new_post)
end
This used to work, and now I get the following error:
1) PostsController GET index assigns all posts as #posts
Failure/Error: let (:new_post) {Post.make!}
NoMethodError:
undefined method `title=' for nil:NilClass
# ./spec/support/blueprints.rb:22:in `block in <top (required)>'
# ./spec/controllers/posts_controller_spec.rb:37:in `block (2 levels) in <top (required)>'
# ./spec/controllers/posts_controller_spec.rb:40:in `block (2 levels) in <top (required)>'
Here is my blueprint:
require 'machinist/active_record'
Post.blueprint do
title {"Post"}
body {"hello world"}
end
For now my work around is to create them using instance variables within the before do block, but it would be nice to use the 'let' calls as it keeps my rspec tests cleaner.
Funny, I just ran across the exact same problem, although I'm on Rails 3.2.1, Machinist 2.0, and ruby 1.9.2-p290. I think there's a conflict between the execution of the Post.stub(:new) stub method and the Machinist make method, but I haven't dug into the code.
The best solution I've come up with is:
before do
new_post
Post.stub!(:new).and_return(new_post)
end
This will initialize the let (since let is lazy-loaded in rspec) before it gets to the stub method. It's hacky, but at least you (and I) can keep the let statement.

Integration tests with webrat and Rails3

I'm upgrading a Rails 2.3.5 app to Rails 3.0.3. But my integration tests
aren't working. I'm getting this error:
NoMethodError: undefined method `content_type' for nil:NilClass
The line to blame is
assert_select "input#artist.title.unsolved", 1
My test_helper.rb for webrat looks likes this:
require "webrat"
require 'webrat/core/matchers'
include Webrat::Methods
Webrat.configure do |config|
config.mode = :rack
end
I'm using shoulda 2.11.3 and webrat 0.7.3 for the testing. I've read,
that webrat and shoulda are compatible with Rails3.
Anyone an idea how to fix this?
Thanks!
tux
ADDITION:
It seems, that the NoMethodError appears from shoulda, not from Webrat, as mentioned in the title. Here is the trace:
NoMethodError: undefined method `content_type' for nil:NilClass
/Users/23tux/.rvm/gems/ruby-1.9.2-p136#rails3/gems/activesupport-3.0.3/lib/active_support/whiny_nil.rb:48:in `method_missing'
/Users/23tux/.rvm/gems/ruby-1.9.2-p136#rails3/gems/actionpack-3.0.3/lib/action_dispatch/testing/assertions/selector.rb:605:in `response_from_page_or_rjs'
/Users/23tux/.rvm/gems/ruby-1.9.2-p136#rails3/gems/actionpack-3.0.3/lib/action_dispatch/testing/assertions/selector.rb:213:in `assert_select'
test/integration/user_integration_test.rb:52:in `block (3 levels) in <class:UserIntegrationTest>'
/Users/23tux/.rvm/gems/ruby-1.9.2-p136#rails3/gems/shoulda-context-1.0.0.beta1/lib/shoulda/context/context.rb:412:in `call'
/Users/23tux/.rvm/gems/ruby-1.9.2-p136#rails3/gems/shoulda-context-1.0.0.beta1/lib/shoulda/context/context.rb:412:in `block in run_current_setup_blocks'
/Users/23tux/.rvm/gems/ruby-1.9.2-p136#rails3/gems/shoulda-context-1.0.0.beta1/lib/shoulda/context/context.rb:411:in `each'
/Users/23tux/.rvm/gems/ruby-1.9.2-p136#rails3/gems/shoulda-context-1.0.0.beta1/lib/shoulda/context/context.rb:411:in `run_current_setup_blocks'
/Users/23tux/.rvm/gems/ruby-1.9.2-p136#rails3/gems/shoulda-context-1.0.0.beta1/lib/shoulda/context/context.rb:393:in `block in create_test_from_should_hash'
And here is the whole block context around the assert_select:
class SongIntegrationTest < ActionController::IntegrationTest
context "a visitor" do
context "solving a song" do
setup do
#song = Song.make
visit song_path(#song)
end
should "have two guess fields" do
assert_select "input#artist.title.unsolved", 1
assert_select "input#title.title.unsolved", 1
end
Maybe the assert_select isn't longer available in Rails 3 with Shoulda.
Hope someone can help me!
thx!
There is a fork of webrat that works with rails3 at https://github.com/joakimk/webrat. At some point it should get pulled into the main branch. rails 2.3 is still very popular at this time.

Resources