In my Dashboard#Index I have this in my controller:
tagged_nodes = Node.includes(:user_tags).tagged_with(current_user.email)
This is my spec:
it "assigns all the nodes that are tagged with the current_user email to local variable 'tagged_nodes'" do
get :index
expect(assigns(:tagged_users)).to eq Node.includes(:user_tags).tagged_with(#user.email)
end
This is the error I am getting:
Failure/Error: expect(assigns(:tagged_users)).to eq Node.includes(:user_tags).tagged_with(#user.email)
expected: #<ActiveRecord::Relation []>
got: nil
(compared using ==)
I suspect it is because of the tagged_with which is a helper method from the gem acts_as_taggable_on
Is that what is indeed causing this error? If so, how do I get around that?
If not, what could be causing that error?
Have you tried to reproduce this problem outside of your tests? If not, I think that's the first logical step.
I'd start by trying to reproduce this issue in the controller itself (ie. in your controller action, sprinkle puts statements or insert a binding.pry if you have the excellent Pry gem). If #tagged_users gets populated properly in the controller action when running the dev site, but doesn't get populated when running a spec with the exact same setup, then consider it an Rspec issue. This boils down to "eliminate as many variables as possible in order to isolate the problem".
Related
I have a model named EventSeries, which is the same singular as it is plural. I have added this in every way I can imagine to the inflector:
inflect.uncountable %w( fish sheep EventSeries event_series Series series )
I have an event_series.yml fixtures file within spec/fixtures. I have even tried adding:
_fixture:
model_class: EventSeries
at the top of the yml file, but it does not help.
I have also tried changing change the filename to event_serieses.yml and call event_serieses(:d30_short_series), and I get NoMethodError undefined method event_serieses.
I use RSpec for testing. In a system spec, I have the following declaration:
let(:subject_series) { event_series(:d30_short_series) }
When I run the spec, I get this error:
NoMethodError: undefined method `event_series' for <RSpec::MySpecFile>
I have many other models and this pattern works for every other model (using the plural version, like users or events), so I assume this is a pluralization issue. I've searched for answers and found this issue, which indicates the problem can be solved by adding the model name to the inflector, but that has not helped in my case.
I've managed to get all the other inherent problems with uncountable names working; for example, my path helpers are all working properly and Rails find my view files as expected. But I haven't been able to solve this fixture problem.
Is there a way to point RSpec to the correct method to access my fixtures?
Using Rails 5.2, Ruby 2.6.0, and RSpec 3.8.
Thanks for sharing your open source project, it was simpler to investigate and solve the issue.
The problem with this specific spec is that the needed fixtures were not being loaded.
You have two options to solve this problem.
Option 1: Add :event_series to config.global_fixtures in your rails_helper.rb.
RSpec.configure do |config|
config.global_fixtures = :a, :event_series, ..., :n
Option 2: Load the fixture just on that spec visit_event_series_spec.rb
RSpec.describe 'visit an event series page' do
fixtures :event_series
let(:user) { users(:third_user) }
Then the spec will now fail but for different reasons:
Failures:
1) visit an event series page when the user is a visitor when all categories are populated Visit the page
Failure/Error: expect(page).to have_link(resource.send(attr), href: path)
expected to find visible link "Dirty 30 Running" but there were no matches. Also found "Dirty 30 Running", which matched the selector but not all filters.
Which I believe you have a better understanding than me of why the following event link is not being displayed on the page.
So I recently pulled in the Rails best practices gem and it said I should use the current_user.find instead of doing it a different way. The issue is, this of course throws ActiveRecord::RecordNotFound when the current_user doesn't have the record. Now in my integration tests, I explicitly test that a user cannot access another users records. This causes the error to be thrown. The issue is, I want to handle this error since I expect it to be thrown. It's currently making my tests red. How can I get my tests to go green, while still testing that the error is thrown? Any help is clarification on best practices would be greatly appreciated! Thank you!
sidenote
As you can see, I'm attempting to use assert_raise. Which isn't catching the error of course... And assert_field_no_difference is just one of my helper methods..
Also, I've been searching for answers for a while now. Most people address how to handle it within the controller, in respect to render a page, or redirecting, but I haven't found anyone addressing how to handle it as expected behavior within a test.
my integration test
test "tries to edit resource not associated with user" do
login(#user)
assert_field_no_difference #resource, 'url' do
assert_raise ActiveRecord::RecordNotFound do
put community_resource_path(#resource), params: { community_resource: {
url: 'http://www.example.com'}}
end
end
end
error being thown as expected
Error:
Community::ResourcesFlowsTest#test_tries_to_edit_resource_not_associated_with_user:
ActiveRecord::RecordNotFound: Couldn't find Community::Resource with 'id'=1 [WHERE "community_resources"."user_id" = $1]
app/controllers/community/resources_controller.rb:106:in `set_allowable_access_resource'
test/integration/community/resources_flows_test.rb:110:in `block in <class:ResourcesFlowsTest>'
I have a weird issue when creating a controller spec for a namespaced controller when there also is a global controller with the same name.
The controller names are HomeController and Backend::HomeController.
Note that I have not yet created the file app/controllers/backend/home_controller.rb, only the global controller exists app/controllers/home_controller.rb
Therefore I expect the test to explode with errors, but it does not. It passes, all green and happy.
My spec looks like this
#spec/controllers/backend/home_controller_spec.rb
require 'rails_helper'
RSpec.describe Backend::HomeController, type: :controller do
before do
user = FactoryGirl.create(:user)
allow(controller).to receive(:authenticate_user!).and_return(true)
allow(controller).to receive(:current_user).and_return(user)
end
describe "GET #index" do
it "returns http success" do
get :index
expect(response).to have_http_status(:success)
end
end
end
However if I change the name in my global HomeController to something else, e.g NotMyHomeController the test fails with errors saying
Unable to autoload constant HomeController, expected app/controllers/home_controller.rb to define it
Which makes me suspect that Rspec doesn't bother with the "Backend" part in the Rspec.describe function.
Am I doing something wrong or am I missing some other vital part? IMHO, this spec shouldn't pass (to paraphrase Gandalf).
I'm using Rails 4.2.6, Rspec-Rails 3.4.2
Update
As Max pointed out, this is probably not at Rspec issue but instead something with Rails autoloading.
However i tried just typing
Backend::HomeController
In the Rails console, but there I get the expected error
NameError: uninitialized constant Backend::HomeController
And according to the Rails guide, both the console and the test suite autoloads. However I think I'm on the right track here.
I had this same problem before - you can read about the whole issue here:
Object.const_get and Rails - cutting off parent module names
but the meat of the answer comes from this answer from user Apneadiving:
Be aware that there are vicious cases in Rails development mode. In order to gain speed, the strict minimum is loaded. Then Rails looks for classes definitions when needed.
But this sometimes fails big time example, when you have say ::User already loaded, and then look for ::Admin::User. Rails would not look for it, it will think ::User does the trick.
This can be solved using require_dependency statements in your code.
I'm trying to add tests to an old app I started working on, but I'm failing miserably :(
It's a Rails 2.3.8 app with Rspec 1.3.2 and Rspec-rails 1.3.4.
This is all I have right now on a controller spec:
before(:each) do
#attributes = { ... }
end
it 'should create a notification' do
post 'create', :notification => #attributes
assigns[:notification].should_not be_new_record
end
I spent hours trying to figure out why the #notification variable wasn't being set, and I just found out the response has been 501 Not Implemented all this time...
Of course the controller works fine from a browser, so for the life of me I can't figure out why I'm getting that error.
Any ideas?
Bah, I forgot to clone the test database so some of the attributes I was assigning weren't on the test DB, and thus the error.
I only found out after I remembered log/test.log exists... I'm glad nobody answered first or I'd be even more embarrased :D
I have generated some scaffolding for my rails app.
I am running the generated tests and they are failing.
for example
test "should create area" do
assert_difference('Area.count') do
post :create, :area => { :name => 'area1' }
end
assert_redirected_to area_path(assigns(:area))
end
This test is failing saying that :
1) Failure:
test_should_create_area(AreasControllerTest)
[/test/functional/areas_controller_test.rb:16]:
"Area.count" didn't change by 1. <3>
expected but was <2>.
There is only one field in the model : name. I am populating this so it cant be because I am failing to populate the only field.
I can run the site and create an area with the name 'area1'. So reality is succeeding, but the test is failing.
I cant ask why its failing, because Im sure theres not enough information here for anyone here to know why. Im just stuck at knowing what avenues to go down to work out why the test is failing. Even putting puts into the code dont print out...
What steps can I take to track this down?
Per the request above, and matching what I was expecting that you'd find when you dug into your logs, you have an authorization that isn't being met in your test.
#request and #response are also useful objects to look at (i.e. puts #response inside your test). I don't know what authentication you are using, but check RAILS_ROOT/lib for authenticated_test_helper, or the /lib, or /test of your authentication gem. You'll find methods for performing a login.