Closed raoehtesham03 closed 11 months ago
:wave: What version of rspec-rails
are you using? There is no publically released rspec
4.0.0
(the highest release of rspec itself is 3.12.x
) but rspec-rails
s current release is 6.1.0
, I would recommend trying to upgrade rspec-rails
if you are using version 4.0.x
of that.
Closing because we don't support older versions of Rails (current support is the same as Rails itself, 6.1, 7.0 and 7.1) or older versions of rspec-rails
.
I tried to upgrade the rspec-rails version to 5.0 but I am still getting the same error. I am stuck in the middle of a project because of this since a very long time. Please help me resolve this. @JonRowe
Please provide a reproducible snippet like https://github.com/rspec/rspec-rails/blob/main/snippets/use_active_record_false.rb
Please provide a reproducible snippet like https://github.com/rspec/rspec-rails/blob/main/snippets/use_active_record_false.rb
@pirj Can you please tell me how to use this ? I could not understand.
Those are self-contained scripts to reproduce issues like Rails bug templates https://guides.rubyonrails.org/contributing_to_ruby_on_rails.html#create-an-executable-test-case
I wish we had a barebones one with some instructions, but we don’t
@JonRowe I know you closed this but I think this is actually an issue with the latest.
I started a new project recently. I'm running:
rails = 7.1.2
ruby = 3.2.2
rspec-rails = 6.1.0
rspec ~> 3.12
I have this controller test to simulate what @raoehtesham03 was talking about:
(Note: the show_404
doesn't do any logic. My actual code in my project is a before_action
that checks for the presence of a particular subdomain, and otherwise renders the 404 file, but I didn't think that mattered for the purpose of highlighting this behavior.)
require "rails_helper"
RSpec.describe ApplicationController, type: :controller do
controller do
before_action :show_404
def index
render plain: "some content"
end
private
def show_404
render file: "public/404.html", status: 404, layout: false
end
end
it "renders the 404 page" do
get :index
expect(response).to have_rendered(file: "public/404.html", layout: false)
expect(response.status).to eq(404)
end
end
Here's the run:
♯ bundle exec rspec spec/controllers/application_controller_spec.rb
ApplicationController
renders the 404 page (FAILED - 1)
Failures:
1) ApplicationController renders the 404 page
Failure/Error: expect(response).to have_rendered(file: "public/404.html", layout: false)
Expected [] to include "public/404.html".
# ./spec/controllers/application_controller_spec.rb:20:in `block (2 levels) in <top (required)>'
Finished in 0.17184 seconds (files took 2 seconds to load)
1 example, 1 failure
Failed examples:
rspec ./spec/controllers/application_controller_spec.rb:18 # ApplicationController renders the 404 page
I'm using have_rendered
instead of render_template
but it looks like it's an alias anyway.
Also, the render file: "public/404.html", status: 404, layout: false
in my project code works just fine when tested in the browser. It just seems the RSpect test doesn't quite work.
Cheers!
What if you set a breakpoint inside show_404, will it stop there?
if you remove the rendered template expectation, will the response status expectation pass?
is it just for templates rendered in action filters?
Is it just for action filters defined inside controller do
?
What if you used the assert_template directly, would it work? Do we use it under the hood in our have_rendered matcher?
Hi Phil! Thanks for your questions...
I tried this:
class PagesController < ApplicationController
def index
render file: "public/404.html", status: 404, layout: false
end
end
With this test:
require 'rails_helper'
RSpec.describe PagesController, type: :controller do
it "renders the 404 file" do
get :index
expect(response.not_found?).to be_truthy
end
end
as my baseline for your questions. Note that just testing the status code passes. Result:
# bundle exec rspec spec/controllers/pages_controller_spec.rb
PagesController
renders the 404 file
Finished in 0.14765 seconds (files took 2.08 seconds to load)
1 example, 0 failures
but when I also test the rendered template it fails.
In the test:
expect(response.not_found?).to be_truthy
expect(response).to have_rendered(file: "public/404.html", layout: false)
Result:
♯ bundle exec rspec spec/controllers/pages_controller_spec.rb
PagesController
renders the 404 file (FAILED - 1)
Failures:
1) PagesController renders the 404 file
Failure/Error: expect(response).to have_rendered(file: "public/404.html", layout: false)
Expected [] to include "public/404.html".
# ./spec/controllers/pages_controller_spec.rb:7:in `block (2 levels) in <top (required)>'
What if you set a breakpoint inside show_404, will it stop there?
Yup. I tried that it and works fine. So it's running the before_action
. Also in my example above where it's just within a normal controller action (not a before_action
) it still hits. So it's not a flow issue.
if you remove the rendered template expectation, will the response status expectation pass?
Yes, as in the example above.
is it just for templates rendered in action filters?
Nope. It seems to be related to render file: "..."
. Something about it rendering a file not a template is where the bug is.
Is it just for action filters defined inside
controller do
?
Nope. See above.
What if you used the assert_template directly, would it work? Do we use it under the hood in our have_rendered matcher?
Fails similarly. In the test:
expect(response.not_found?).to be_truthy
assert_template file: "public/404.html"
With the result:
♯ bundle exec rspec spec/controllers/pages_controller_spec.rb
PagesController
renders the 404 file (FAILED - 1)
Failures:
1) PagesController renders the 404 file
Failure/Error: assert_template file: "public/404.html"
Minitest::Assertion:
Expected [] to include "public/404.html".
So I think it's something specifically about using render file: "some/file"
that isn't assertable with render_template
or assert_template
(or have_rendered
, which is just an alias). 🤷
@drsharp Instead of using this expect(response).to have_rendered(file: "public/404.html", layout: false)
Try Below code snippet.
expect(response).to render_template { "public/404.html" }
@drsharp Instead of using this expect(response).to have_rendered(file: "public/404.html", layout: false)
Try Below code snippet. expect(response).to render_template { "public/404.html" }
@raoehtesham03 thanks for the suggestion. It didn't work, though:
1) PagesController renders the 'index' action as the root path
Failure/Error: expect(response).to render_template { "public/404.html" }
ArgumentError:
wrong number of arguments (given 0, expected 1..2)
It's interesting because assert_template file: "some/file"
is very much supported:
https://github.com/rails/rails-controller-testing/blob/c203673f8011a7cdc2a8edf995ae6b3eec3417ca/lib/rails/controller/testing/template_assertions.rb#L97-L98
so I don't know why it's not working via rspec-rails. 🤷
If assert_template doesn’t work, there’s not much we can do, as we usually just wrap Rails’ assertions. You’re left to debug Rails testing code I believe.
If assert_template doesn’t work, there’s not much we can do, as we usually just wrap Rails’ assertions. You’re left to debug Rails testing code I believe.
Thanks Phil. Yeah, I'm guessing at this point it's a problem with assert_template
itself, and not an rspec-rails
problem. 🤷 Thanks for your thoughts and help here. I'll see about diving in with the Rails testing code.
Ruby version: 2.7.8 Rails version: 6.0.6.1 RSpec version: 4.0
Observed behaviour