Capybara NoMethodError: undefined method `visit' for - ruby-on-rails

Thank for response.
I getting error in application Git application with the error
Failures:
1) Page pages page creation with invalid information should not create a page
Failure/Error: before(:each) { visit new_admin_page_path }
NoMethodError:
undefined method `visit' for #<Page:0x00000005094bb0>
# ./spec/requests/page_request_spec.rb:13:in `block (3 levels) in <top (required)>'
2) Page pages page creation with invalid information error messages
Failure/Error: before(:each) { visit new_admin_page_path }
NoMethodError:
undefined method `visit' for #<Page:0x000000051671f0>
# ./spec/requests/page_request_spec.rb:13:in `block (3 levels) in <top (required)>'
Finished in 1.21 seconds
14 examples, 2 failures
What I've missed ?

I cloned your repository and ran the spec. The problem is that you are using the term page for two different things, the Capybara page (subject { page }) and your model with the name Page (which you also name page). Those two names conflict, which is why rspec is complaining that there is no method visit for #<Page:0x00000005094bb0>.
To solve this just rename the page you create in the initial let:
let(:mypage) { Factory.create(:page) }
That will avoid the conflict by naming your page model mypage instead of page.
There are other issues however. Your user factory does not use a sequence for assigning emails, so you get a validation error because it says the email is already taken.
I changed your user factory to this:
sequence(:email) { |n| "abc#{n}#example.com"}
factory :user do
email
password "foobar"
password_confirmation "foobar"
...
That fixes the validation error, but you now get another error. In the line in your first spec, you should be checking that count does not change on the class Page, not the record page (or mypage).
So change that to:
expect { click_button "Create Page" }.not_to change(Page, :count)
This will still leave you with errors, because you also do not have any create action for your PagesController. From what you wrote, it seems like the information is invalid so it should not even get to this action. I don't know exactly what you're trying to do here so I'll leave the rest for you to figure out.

If you recently upgraded to Capybara 2.0 & your integration tests were working with previous version of Capybara, you may try renaming requests directory to features. Check http://www.codelearn.org/blog/how-to-make-old-integration-tests-work-with-capybara-2-0

Add the following to your spec/spec_helper.rb (in your Spork.prefork block):
require 'capybara/rspec'
require 'capybara/rails'

Related

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.

Routes Increment when I Run Rspec feature

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.

rspec show failure even when the condition is fulfilled

I am using rspec to validate if a string exist in a page. I am new to rails and following tutorial http://ruby.railstutorial.org/chapters/static-pages#top
Is there anything I am missing?
require 'spec_helper'
describe "Static pages" do
describe "Home page" do
it "should have the content 'Sample App'" do
visit '/static_pages/home'
page.should have_content('Sample App')
end
end
end
In my home page app/views/static_pages/home.html.erb I have following code.
<h1>Sample App</h1>
Command I am using to validate the condition.
bundle exec rspec spec/requests/static_pages_spec.rb
Test is failing don't know why.
←[31mF←[0m
Failures:
1) Static pages Home page should have the content 'Sample App'
←[31mFailure/Error:←[0m ←[31mvisit '/static_pages/home'←[0m
←[31mNoMethodError←[0m:
←[31mundefined method `visit' for #<RSpec::Core::ExampleGroup::Nested_1::
Nested_1:0x4067a60>←[0m
←[36m # ./spec/requests/static_pages_spec.rb:8:in `block (3 levels) in <top(required)>'←[0m
Finished in 0.023 seconds
←[31m1 example, 1 failure←[0m
Failed examples:
←[31mrspec ./spec/requests/static_pages_spec.rb:7←[0m ←[36m# Static pages Home page should have the content 'Sample App'←[0m
Randomized with seed 44188
Going by what the tutorial has you do and without your Gemfile to double check, I believe you are experiencing a conflict between Capybara 2.0 and RSpec on the visit keyword. You have two options for a solution (don't need to do both):
Option 1: Move your test from the spec/requests folder into the spec/features folder.
or
Option 2: Use the keyword feature instead of describe.
This conflict is caused by a change to Capybara noted at the top of this gist (second paragraph): https://gist.github.com/jnicklas/3980553. Quoted:
Notably, we changed the :type that Capybara assumes your specs run under in RSpec to :feature (previously it was :request). The latest release of spec/features. Alternatively you can use the Capybara Feature DSL (feature instead of describe), which should work without any additional tweaking. If you see errors like undefined method visit, then you're probably encountering this issue. If you're including modules into :request specs, you will probably need to change that to :feature.

Rails Engine with RSpec and FactoryGirl

I followed a few tutorials and docs of FactoryGirl to use with RSpec. Currently I get one error when trying to use FactoryGirl.create:
describe "GenericRecipesController" do
describe "GET 'index'" do
it "displays list of generic recipes" do
generic_recipe = FactoryGirl.create(:generic_recipe)
visit '/recipe'
response.should be_success
end
end
end
And the error:
GenericRecipesController GET 'index' displays list of generic recipes
Failure/Error: generic_recipe = FactoryGirl.create(:generic_recipe)
NameError:
uninitialized constant GenericRecipe
# ./spec/integration/generic_recipes_spec.rb:8:in `block (3 levels) in <top (required)>'
The rest of code is there.
You can try this:
factory :generic_recipe, class: EdibleRecipe::GenericRecipe do
# ...
end
I think problem in a nesting model in module
Upd: delete file /spec/factories.rb, in file /spec/support/factories.rb make
factory :generic_recipe, class: EdibleRecipe::GenericRecipe do
When you will run tests, probably will see 'can not load table'. Make
rake db:migrate RAILS_ENV=test
and try again.
You don't seem to have a GenericRecipe model in your app. Factory Girl is looking for a Model called GenericReciper and can't find it.

RSpec fails for no obvious reason

So I'm using rspec to test my code as I'm going through the Rails Tutorial, and I keep getting this error when I test the code in listing 3.20. Everything checks out when I look at it with my eyeball, but RSpec doesn't seem to like it.
(Note that I just did one of the pages, not all three because they all give the same error)
james#tristan:~/rails_projects/sample_app$
rspec
spec/controllers/pages_controller_spec.rb
F...
Failures:
1) PagesController should have the
right title
Failure/Error: response.should have_selector("title",
expected following output to contain a | Home tag:
# ./spec/controllers/pages_controller_spec.rb:13:in
`block (2 levels) in '
Finished in 0.97999 seconds 4
examples, 1 failure
james#tristan:~/rails_projects/sample_app$
At the top of that spec file it says:
before(:each) do
#
# Define #base_title here.
#
end
Does your spec assign a value to #base_title?

Resources