Hey guys I am running into a bit of trouble with a simple view test written using Rspec. The case is pretty simple. I want to render a page that should display a message asking the customer if he/she is new.
The page contains several subsections that contain translations. The problem is that Rspec puts a "test" in this translation path, so the correct translation is not found.
Rspec test:
require "rails_helper"
RSpec.describe 'checkout/start/index' do
context "with no logged in customer" do
it "should render the #index page and display the registration and login form" do
render
expect(rendered).to match(/Sie sind neu bei uns?/)
end
end
end
Response:
Randomized with seed 40265
checkout/start/index
with no logged in customer
calls #index and displays the registration and login form (FAILED - 1)
Failures:
1) checkout/start/index with no logged in customer calls #index and displays the registration and login form
Failure/Error: <%= t(".checkout_#{controller_name}_sub_headline") %>
ActionView::Template::Error:
translation missing: de.checkout.shared.sub_headline.checkout_test_sub_headline
# /home/arthur/.rvm/gems/ruby-3.1.2/gems/i18n-1.12.0/lib/i18n.rb:394:in `handle_exception'
# /home/arthur/.rvm/gems/ruby-3.1.2/gems/i18n-1.12.0/lib/i18n.rb:367:in `translate_key'
# /home/arthur/.rvm/gems/ruby-3.1.2/gems/i18n-1.12.0/lib/i18n.rb:222:in `translate'
# ./app/views/checkout/shared/_sub_headline.html.erb:6:in `_app_views_checkout_shared__sub_headline_html_erb__648894094841044844_23060'
# ./app/views/checkout/start/index.html.erb:8:in `_app_views_checkout_start_index_html_erb__2185710400981636407_23000'
# ./spec/views/checkout/start_spec.rb:10:in `block (3 levels) in <top (required)>'
# ------------------
# --- Caused by: ---
# I18n::MissingTranslationData:
# translation missing: de.checkout.shared.sub_headline.checkout_test_sub_headline
# /home/arthur/.rvm/gems/ruby-3.1.2/gems/i18n-1.12.0/lib/i18n.rb:394:in `handle_exception'
Top 1 slowest examples (0.03185 seconds, 6.4% of total time):
checkout/start/index with no logged in customer calls #index and displays the registration and login form
0.03185 seconds ./spec/views/checkout/start_spec.rb:9
Finished in 0.49579 seconds (files took 1.69 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/views/checkout/start_spec.rb:9 # checkout/start/index with no logged in customer calls #index and displays the registration and login form
Randomized with seed 40265
Is there any way to override this path for the test, or any other way to tell Rspec where to look for the correct translation?
Many thanks in advance
You have created a translation that's dependent upon the controller_name, which as you're seeing is different in your test environment because of the way Rails view tests work. If you need that in your code, then in your test I would stub it out so you're providing what your code expects. I'm not sure, but that's probably something like allow(helper).to receive(:controller_name) { 'your_controller_name' }
Related
I want to undo some network settings that keeps generating my app_urls as "test.host" irrespective of the rails app I am running
I was doing a tutorial - http://apionrails.icalialabs.com/book/.
In Chapter 1, it asked us to add 'pow'/'prax' server to host the Rails 4 app.
I was unable and resulted in even trying 'puma' and eventually after none worked. I just restarted with Rails 5 and I was able to move to the next chapters.
When I progressed further; I hit a stumbling block in testing controllers. My routes_url keeps generating 'test.host' when running.
Controlled experiment. I even recreated another app thinking it was an instance setting and it does the same. So I am sure it is a setting I did.
I've tried uninstalling all settings I did when trying to add a web server manually and I am still unable to resolve it. Please indicate what else I can add to help resolve this issue.
1) UsersController GET a user returns the info as a hash
Failure/Error: get user_url(#user), params: { id: #user.id }, format: :json
ActionController::UrlGenerationError:
No route matches {:action=>"http://test.host/users/7", :controller=>"users", :format=>:json, :id=>7}
# ./spec/controllers/users_controller_spec.rb:9:in `block (3 levels) in <top (required)>'
2) UsersController GET a user
Failure/Error: get user_url(#user), params: { id: #user.id }, format: :json
ActionController::UrlGenerationError:
No route matches {:action=>"http://test.host/users/8", :controller=>"users", :format=>:json, :id=>8}
# ./spec/controllers/users_controller_spec.rb:9:in `block (3 levels) in <top (required)>'
Finished in 0.09652 seconds (files took 0.7329 seconds to load)
2 examples, 2 failures
Failed examples:
rspec ./spec/controllers/users_controller_spec.rb:12 # UsersController GET a user returns the info as a hash
rspec ./spec/controllers/users_controller_spec.rb:17 # UsersController GET a user
I expect when running an app my app_url to be "localhost:3000" but the actual output is "test.host" which is failing my routes and I am unable to test any controller.
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 wan't to write spec for a view in Rails with Rspec. I wrote this:
require 'spec_helper'
describe "homepage/index.html.erb" do
it 'has list of publications with id #publications' do
render
expect(rendered).to have_selector('ul#publications')
end
it 'has publications on the list' do
assign(:publications, [
stub_model(Publication, content: 'First publication.'),
stub_model(Publication, content: 'Second publication.')
])
render
rendered.should have_content('First publication.')
rendered.should have_content('Second publication.')
end
end
But stub_model seems to be not working.
rspec
.....F.
Failures:
1) homepage/index.html.erb has list of publications with id #publications
Failure/Error: render
ActionView::Template::Error:
undefined method `each' for nil:NilClass
# ./app/views/homepage/index.html.erb:2:in `_app_views_homepage_index_html_erb___3273264012123365698_43368240'
# ./spec/views/homepage/index.html.erb_spec.rb:5:in `block (2 levels) in <top (required)>'
Finished in 0.17634 seconds
7 examples, 1 failure
How can I stub this properly?
The description given in your failure message indicates that your failing on the example above the example with the stubs. In that example, nothing has been assigned to the instance variable #publications, so the view is presumably raising the error you're seeing as a result of executing #publications.each ....
But as #phoet implied, you really should provide the code that is failing.
I don't think that it is a good idea to stub models in such (integration or acceptance) tests.
But if you would like to do it you should stub query to DB (when you are trying to stub assigns). For example you have Publication.all in your action - so you can stub
Publication.stub(all:
[
stub_model(Publication, content: 'First publication.'),
stub_model(Publication, content: 'Second publication.')
])
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'
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?