I have some errors while testing with RSpec. This is my code:
\spec\views\post_categories\edit.html.haml_spec.rb
require 'rails_helper'
RSpec.describe "post_categories/edit", type: :view do
before do
login_user
#post_category = FactoryBot.create(:post_category)
end
it "renders the edit post_category form" do
render
assert_select "form[method=?]", "post" do
assert_select "input[name=?]", "post_category[title]"
assert_select "textarea[name=?]", "post_category[description]"
end
end
end
After it I get such an error:
post_categories/edit renders the edit post_category form
Failure/Error: = simple_form_for(#post_category) do |f|
ActionView::Template::Error:
No route matches {:action=>"show", :controller=>"post_categories", :locale=>#<PostCategory id: 1, title:
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", description:
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...", reated_at:
"2021-11-15 11:04:50.292970000 +0000", updated_at: "2021-11-15
11:04:50.292970000 +0000">}, missing required keys: [:id]
Did you mean? post_category_url
admin_post_category_url
The #post_category exsist and corrrect, but simple_form doesn't work on test
Why #post_category got in :locale and how it repair?
I changed all link_to <subject> to link_to <subject>_path(id: subject.id)
Why it needed for rspec I don't know
Related
In my code_controller_spec.rb my tests pass when I just run the tests in code_controller_spec.rb. However, when I run the suite, only the create, edit, and update tests fail within code_controller_spec.rb. I'm really not sure where to go from here and I really don't know why my tests fail when running together. I have config.use_transactional_fixtures = false and am using database_cleaner. My app works fine locally with the below actions and I don't receive any errors when creating or updating a post. Let me know if you need additional info.
When I run the suite, the failures I get are:
1) CodesController admin pages #create posts a new code post
Failure/Error:
post :create, params: {
code: {
created_at: Date.today,
title: "Code things",
content: "The content of the code post",
user_id: user.id
}
}
ActionController::UrlGenerationError:
No route matches {:action=>"create", :code=>{:created_at=>Fri, 20 Oct 2017, :title=>"Code things", :content=>"The content of the code post", :user_id=>1}, :controller=>"codes"}
2) CodesController admin pages #edit edits a code post
Failure/Error: get :edit, params: { id: code }
ActionController::UrlGenerationError:
No route matches {:action=>"edit", :controller=>"codes", :id=>#<Code id: 1, title: "Code post title", content: "Coding speak that not everyone can understand...", created_at: "2017-10-20 00:00:00", updated_at: "2017-10-21 06:05:27", user_id: 2>}
3) CodesController admin pages #update updates a code post
Failure/Error: put :update, params: { id: code, code: code2 }
ActionController::UrlGenerationError:
No route matches {:action=>"update", :code=>{:title=>"Updated title", :content=>"Updated content"}, :controller=>"codes", :id=>#<Code id: 1, title: "Code post title", content: "Coding speak that not everyone can understand...", created_at: "2017-10-20 00:00:00", updated_at: "2017-10-21 06:05:27", user_id: 2>}
My spec/controllers/user/codes_controller_spec.rb
RSpec.describe User::CodesController, type: :controller do
let!(:user) { User.create(email: "user#example.com", password: "password") }
let!(:code) { FactoryGirl.create(:code) }
before do
sign_in_as user
expect(response).to have_http_status(:success)
end
describe "admin pages" do
render_views
context "#create" do
it "posts a new code post" do
post :create, params: {
code: {
created_at: Date.today,
title: "Code things",
content: "The content of the code post",
user_id: user.id
}
}
expect(response).to redirect_to user_codes_path
expect(flash[:success]).to eq "Post created successfully."
end
end
context "#edit" do
it "edits a code post" do
get :edit, params: { id: code }
expect(response).to render_template :edit
end
end
context "#update" do
let(:code2) do
{ title: "Updated title", content: "Updated content" }
end
it "updates a code post" do
put :update, params: { id: code, code: code2 }
code.reload
expect(response).to redirect_to user_code_path(code)
expect(code.title).to eq code2[:title]
expect(code.content).to eq code2[:content]
expect(flash[:success]).to eq "Post updated successfully."
end
end
end
end
My spec/factories/post_factories.rb
FactoryGirl.define do
factory :code do
created_at Date.today
title "Code post title"
content "Coding speak that not everyone can understand..."
association :user, factory: :user
end
factory :life do
created_at Date.today
title "Life post title"
content "The world moves in mysterious ways; whether we want it to..."
association :user, factory: :user
end
end
I run rspec --seed 123 --bisect and then I run the output of that, but all my tests pass. I should mention I'm very new to --bisect.
This is the rspec --seed 123 --bisect output and when I run this all my tests pass.
rspec ./spec/controllers/user/codes_controller_spec.rb[1:1:1:1,1:1:2:1,1:1:3:1,1:1:4:1,1:1:5:1] ./spec/controllers/user/lives_controller_spec.rb[1:1:1,1:1:2] ./spec/features/admin_create_posts_spec.rb[1:1,1:2,1:3,1:4] ./spec/features/admin_edit_post_spec.rb[1:1,1:2,1:3] ./spec/features/clearance/user_signs_out_spec.rb[1:1] ./spec/features/clearance/visitor_resets_password_spec.rb[1:1,1:2,1:3,1:4,1:5,1:6] ./spec/features/clearance/visitor_signs_in_spec.rb[1:1,1:2,1:3,1:4,1:5,1:6,1:7,1:8] ./spec/features/clearance/visitor_signs_up_spec.rb[1:1,1:2,1:3,1:4,1:5,1:6,1:7,1:8] ./spec/features/clearance/visitor_updates_password_spec.rb[1:1,1:2,1:3] ./spec/features/homepage_spec.rb[1:1,1:2] ./spec/features/login_users_spec.rb[1:1,1:2] ./spec/features/logout_user_spec.rb[1:1] ./spec/features/showing_all_posts_spec.rb[1:1,1:2] ./spec/helpers/codes_helper_spec.rb[1:1] ./spec/helpers/lives_helper_spec.rb[1:1] ./spec/helpers/user/codes_helper_spec.rb[1:1] ./spec/helpers/user/lives_helper_spec.rb[1:1] ./spec/helpers/users_helper_spec.rb[1:1] ./spec/helpers/welcome_helper_spec.rb[1:1] ./spec/models/code_spec.rb[1:1] ./spec/models/life_spec.rb[1:1]
My database_cleaner config in rails_helper.rb
require database_cleaner
RSpec.configure do |config|
config.use_transactional_fixtures = false
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
# config.fixture_path = "#{::Rails.root}/spec/fixtures"
config.before(:all) do
FactoryGirl.reload
end
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, remove the following line or assign false
# instead of true.
config.before(:suite) do
if config.use_transactional_fixtures?
raise(<<-MSG)
Delete line `config.use_transactional_fixtures = true` from rails_helper.rb (or set it to false) to prevent uncommitted transactions being used in JavaScript-dependent specs.
During testing, the app-under-test that the browser driver connects to uses a different database connection to the database connection used by the spec. The app's database connection would not be able to access uncommitted transaction data setup over the spec's database connection.
MSG
end
DatabaseCleaner.clean_with(:truncation)
end
config.before(:each) do
DatabaseCleaner.strategy = :transaction
end
config.before(:each, type: :feature) do
# :rack_test driver's Rack app under test shares database connection
# with the specs, so continue to use transaction strategy for speed.
driver_shares_db_connection_with_specs = Capybara.current_driver == :rack_test
if !driver_shares_db_connection_with_specs
# Driver is probably for an external browser with an app under test that does *not*
# share a database connection with the specs, so use truncation strategy.
DatabaseCleaner.strategy = :truncation
end
end
# adds this from
# https://stackoverflow.com/questions/37753251/actionmailer-not-delivering-confirmation-emails-in-test-environment-rails-4
config.before(:each, truncation: true) do
Database::Cleaner.strategy = :truncation
end
config.before(:each) do
DatabaseCleaner.start
end
config.append_after(:each) do
DatabaseCleaner.clean
end
end
UPDATED
Output for rails routes
Prefix Verb URI Pattern Controller#Action
root GET / welcome#index
passwords POST /passwords(.:format) clearance/passwords#create
new_password GET /passwords/new(.:format) clearance/passwords#new
session POST /session(.:format) clearance/sessions#create
edit_user_password GET /users/:user_id/password/edit(.:format) clearance/passwords#edit
user_password PATCH /users/:user_id/password(.:format) clearance/passwords#update
PUT /users/:user_id/password(.:format) clearance/passwords#update
POST /users/:user_id/password(.:format) clearance/passwords#create
users POST /users(.:format) clearance/users#create
sign_in GET /sign_in(.:format) clearance/sessions#new
sign_out DELETE /sign_out(.:format) clearance/sessions#destroy
GET /sign_out(.:format) clearance/sessions#destroy
sign_up GET /sign_up(.:format) clearance/users#new
user_lives GET /user/lives(.:format) user/lives#index
POST /user/lives(.:format) user/lives#create
new_user_life GET /user/lives/new(.:format) user/lives#new
edit_user_life GET /user/lives/:id/edit(.:format) user/lives#edit
user_life GET /user/lives/:id(.:format) user/lives#show
PATCH /user/lives/:id(.:format) user/lives#update
PUT /user/lives/:id(.:format) user/lives#update
DELETE /user/lives/:id(.:format) user/lives#destroy
user_codes GET /user/codes(.:format) user/codes#index
POST /user/codes(.:format) user/codes#create
new_user_code GET /user/codes/new(.:format) user/codes#new
edit_user_code GET /user/codes/:id/edit(.:format) user/codes#edit
user_code GET /user/codes/:id(.:format) user/codes#show
PATCH /user/codes/:id(.:format) user/codes#update
PUT /user/codes/:id(.:format) user/codes#update
DELETE /user/codes/:id(.:format) user/codes#destroy
lives GET /lives(.:format) lives#index
life GET /lives/:id(.:format) lives#show
codes GET /codes(.:format) codes#index
code GET /codes/:id(.:format) codes#show
I believe this is an autoload issue. If your ::CodesController gets loaded before the Users::CodesController then your spec for Users::CodesController is actually using ::CodesController and hence can't create the correct routes. When run singly the correct class is autoloaded and everything works correctly. To fix this require the correct class at the beginning of your spec.
# spec/controllers/user/codes_controller_spec.rb
require 'user/codes_controller'
...
and
# spec/controllers/codes_controller_spec.rb
require 'codes_controller'
...
Writing some controller tests, using render_views to check some partial rendering....
describe PromoCodeController do
render_views
describe "GET 'show" do
... a bunch of tests
it "renders 'used' partial when promo code has already been used" do
#promo_code = create(:promo_code)
#user.stub(:promo_used?).and_return(true)
get 'show', :slug => #promo_code.slug
expect(response).to render_template(:partial => 'promo_code/_used')
end
which loads in the _used partial
<article>
<p><%= #promo.description.html_safe %></p>
<p>Sorry, it appears this promo code has already been used. Please try again or contact us directly.</p>
<%= link_to "View Order", orders_path(#order), class: "box-button-black", data: { bypass: true } %>
</article>
but breaks with:
undefined method `orders_path' for #<#<Class:0x007fd4069d06e8>:0x007fd401e3e518>
Any ideas on how to either
(a) ignore the Rails link, it's irrelevant to the test
(b) include something in the test to recognize that link
(c) stub it (last resort i think)
Everything I've tried so far doesn't get past the error.
EDIT:
orders_path was wrong, it should be order_path. After changing that I get:
ActionView::Template::Error:
No route matches {:controller=>"order", :action=>"show", :id=>nil}
So the partial is looking for #order. I tried setting it with controller.instance_variable_set(:#order, create(:order)), but in the partial it comes back as nil.
A quick test by adding<% #order = Order.last %> in the view partial passes green. How to pass the var #order into the _used partial is now the question.
Instead of manually setting the spec type you can set it based off file location
# spec_helper.rb
RSpec.configure do |config|
config.infer_spec_type_from_file_location!
end
describe 'GET SHOW' do
run this in a before block
before do
controller.instance_variable_set(:#order, create(:order))
end
it "renders 'used' partial when promo code has already been used" do
promo_code = create(:promo_code)
#user.stub(:promo_used?).and_return(true)
# check if #order variable is assigned in the controller
expect(assigns(:order).to eq order
get 'show', slug: promo_code.slug
expect(response).to render_template(:partial => 'promo_code/_used')
end
end
First off, I needed to change it to order_path, orders_path was wrong. Doh.
Than I needed to stub some methods to get around the error
ActionView::Template::Error:
No route matches {:controller=>"order", :action=>"show", :id=>nil}
Ultimately, stubbing the method assign_promo_to_users_order which assigns a complete order to the current_user did the trick:
it "renders 'used' partial when promo code has already been used" do
#promo_code = create(:promo_code)
#user.stub(:promo_used?).and_return(true)
User.any_instance.stub(:assign_promo_to_users_order).and_return(create(:order, :complete))
get 'show', :slug => #promo_code.slug
expect(response).to render_template(:partial => 'promo_code/_used')
end
Try adding the spec's type.
I believe that the action controller URL helpers are included into the spec type.
Try:
describe SomeController, type: :controller do
I'm using Rails 4.2 rspec 3.5
after basic scaffold generation, i was trying to run rspec, but constantly getting this errors.
controller test
it "updates the requested" do
some_object = SomeObject.create! valid_attributes
put :update, params: {id: some_object.to_param, some_object: new_attributes}, session: valid_session
some_object.reload
skip("Add assertions for updated state")
end
gives this output
Failure/Error: put :update, params: {id: some_object.to_param, some_object: valid_attributes}, session: valid_session
ActionController::UrlGenerationError:
No route matches {:action=>"update"
And views test
require 'rails_helper'
RSpec.describe "some_objects/edit", type: :view do
before(:each) do
#some_object = assign(:some_object, SomeObject.create!(
:first_name => "MyString",
:last_name => "MyString"
))
end
it "renders the edit some_object form" do
render
assert_select "form[action=?][method=?]", some_object_path(#some_object), "post" do
assert_select "input#some_object_first_name[name=?]", "some_object[first_name]"
assert_select "input#some_object_last_name[name=?]", "some_object[last_name]"
end
end
end
gives this output:
Failure/Error: <%= form_for(#some_object) do |f| %>
ActionView::Template::Error:
undefined method `polymorphic_path' for #<#<Class:0x005606c04fff98>:0x005606c04ffb60>
This is generated code. I have changed only valid_attributes hash, and this seem to be some bug in rails/rspec. Do you have any solution
Problem is in passing params for :update. Simply remove params: and it will work:
it "updates the requested" do
some_object = SomeObject.create! valid_attributes
put :update, {id: some_object.to_param, some_object: new_attributes}, session: valid_session
some_object.reload
skip("Add assertions for updated state")
end
I got this following error while i am testing views in Rspec.
1) problems/new renders new problem form
Failure/Error:
<div class="col-md-8 col-sm-8">
<%= f.select :approval_status, options_for_select(#approval_statuses.collect { |as| [as[0].humanize, as[0]] }, selected: #problem.approval_status), {}, class: "form-control" %>
</div>
ActionView::Template::Error:
undefined method `collect' for nil:NilClass
I am passing #approval_statuses in controller action.
It's working fine in views , but in test cases i am getting this error.
Controller Action :
def new
#problem = Problem.new
#approval_statuses = Problem.approval_statuses
#visibilities = Problem.visibilities
end
In Model
enum approval_status: {not_approved: 0, approved: 1}
In new.html.erb_spec.rb
require 'rails_helper'
RSpec.describe "problems/new", type: :view do
before(:each) do
assign(:problem, Problem.new())
end
it "renders new problem form" do
render
assert_select "form[action=?][method=?]", problems_path, "post" do
end
end
end
You're setting the #problem instance variable but not #approval_statuses or #visibilities so these are both currently nil.
RSpec.describe "problems/new", type: :view do
before(:each) do
assign(:problem, Problem.new)
assign(:approval_statuses, Problem.approval_statues)
assign(:visibilities, Problem.visibilities)
end
it "renders new problem form" do
render
assert_select "form[action=?][method=?]", problems_path, "post" do
end
end
end
I'm getting the following error:
undefined method `assign' for #<RSpec::Core::ExampleGroup::Nested_1:0x0000010597f4b8>
When attempting to test per the docs.
Here's is what I have:
user_controller_spec.rb
require 'spec_helper'
describe "devise/sessions/new.html.erb" do
let(:user) do
stub_model(User).as_new_record
end
before do
assign(:user, user)
# Devise provides resource and resource_name helpers and
# mappings so stub them here.
#view.stub(:resource).and_return(user)
#view.stub(:resource_name).and_return('user')
#view.stub(:devise_mapping).and_return(Devise.mappings[:user])
end
it "renders a form to sign the user in" do
render
rendered.should have_selector("form",
:method => "post",
:action => user_session_path
) do |form|
form.should have_selector("input", :type => "submit")
end
end
end
Suggestions? Thanks
Rspec has changed a bit, it's now using assigns.
Doc here.