-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow assert_template(file:) to work using Rails 6 #46
Conversation
An `ActionView::Template`'s `virtual_path` is deprecated under Rails 6. This commit: rails/rails@9a343d1#diff-40f2a5bcf9edfd65a8efe42a05c53736L437 causes the virtual path for templates rendered using `file:` to no longer have their `virtual_path` explicitly set to nil. `rails-controller-testing` uses the absence of the `virtual_path` attribute to indicate that the template was rendered as using `file:`. See: https://github.com/rails/rails-controller-testing/blob/master/lib/rails/controller/testing/template_assertions.rb#L34 Because the attribute is never nil with Rails 6, the ability to test something like `assert_template(file: "#{Rails.root}/public/404.html")` is broken. This commit changes the way rendered `file:` templates are tracked. Instead of paying attention calls to `ActionView::Template#render` ( subscribing to`"!render_template.action_view"`) this update instead focuses on `ActionView::TemplateRenderer#determine_template`. Because `determine_tempalte` is not already instrumented, we need to provide our own instrumentation by redefining the method, adding instrumentation, and then handing off to `super`.
+1 |
We use this branch call these error: render plain: 'xxx' causes
|
This patch is working great for us, thank you. |
It seems it is still being set to |
What do you mean it is running against a Rails 5 dummy application? We are also running against the master branch. Does it make different which Rails version the application was generated? It should not. |
OK. I know the problem now. I don't think |
@@ -10,16 +11,19 @@ def self.install | |||
ActiveSupport.on_load(:action_controller_test_case) do | |||
include Rails::Controller::Testing::TestProcess | |||
include Rails::Controller::Testing::TemplateAssertions | |||
ActionView::TemplateRenderer.prepend(InstrumentDetermineTemplate) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should include this inside an on_load(:action_view)
otherwise we could prepend this same module three times to the same class when running tests.
@rafaelfranca Thanks for the comments/questions.
It's been about six months since I've looked at this so I'm a little fuzzy but I believe rails/rails#35662 re-introduced a
That's my confusion. I didn't realize at the time how testing was set up. When I wrote that,
I think this might be new behavior since I opened the PR. If this PR resolves that issue then it's probably a happy coincidence. It's not super fresh in my mind so I'll probably need to go back and take a look before I can comment for sure. I can go head and make the callback change you requested just to get that done and out of the way. |
Alternative but similar solution based on the work in this PR that works in current Rails v6.0.0. |
Is there anything we can do to help get this or @tconst's patch merged? |
@cpruitt We recently changed a Failure/Error: send_data result, type: 'text/csv', filename: filename
NoMethodError:
undefined method `virtual_path' for text template:ActionView::Template::Text
# /Users/bbugh/.rvm/gems/ruby-2.6.5/bundler/gems/rails-controller-testing-f047f57530f1/lib/rails/controller/testing/template_instrumentation.rb:8:in `block in determine_template'
# /Users/bbugh/.rvm/gems/ruby-2.6.5/bundler/gems/rails-controller-testing-f047f57530f1/lib/rails/controller/testing/template_instrumentation.rb:6:in `tap'
# /Users/bbugh/.rvm/gems/ruby-2.6.5/bundler/gems/rails-controller-testing-f047f57530f1/lib/rails/controller/testing/template_instrumentation.rb:6:in `determine_template'
# ./app/controllers/files_controller.rb:27:in `render_csv'
# ./app/controllers/files_controller.rb:16:in `block (2 levels) in show'
# ./app/controllers/files_controller.rb:15:in `show'
# /Users/bbugh/.rvm/gems/ruby-2.6.5/bundler/gems/rails-controller-testing-f047f57530f1/lib/rails/controller/testing/integration.rb:13:in `block (2 levels) in <module:Integration>'
# ./spec/requests/files_controller_spec.rb:23:in `block (4 levels) in <top (required)>' |
def determine_template(options) | ||
super.tap do |found| | ||
if found | ||
instrument_payload = { template_identifier: found.identifier, virtual_path: found.virtual_path, options: options } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instrument_payload = { template_identifier: found.identifier, virtual_path: found.virtual_path, options: options } | |
instrument_payload = { template_identifier: found.identifier, virtual_path: found.try(:virtual_path), options: options } |
@cpruitt virtual_path
isn't always available, like if you're rendering a string rather than a template. This should try
to call virtual_path
so it doesn't fail if the method is missing.
I reported this error here: #46 (comment)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bbugh Thanks for the suggested change. Our test implementation changed such that I'm not in a great position to reproduce this problem or test this fix. I believe the original issue that this PR was intended to resolve changed and this PR just happened to still fix a similar problem. I'm not currently able to allocate time to get up to speed to verify that and test this out. If you have available time, I'd wholeheartedly endorse you taking this and running with it in a new PR. I'm happy to help answer any questions I can (thought I don't know how much help that would be). 🙂
I'd defer to tconst@7c8f078 for a fix. I'm currently out of date on my knowledge of this issue and don't think I have context or ability to reproduce and test this in a timely enough way to push this forward. |
Full support for Rails 6 would be great, is there anything left that needs to be done? |
I've been using tconst@7c8f078 now for some time and recently upgraded from rails 6.1 to 7.0.1 with no issues. I can open a PR if that would help move this along for others. |
I would appreciate it 👍 |
* Brings back `!render_template.action_view` instrumentation when rendering with ActionView::Template::RawFile See rails#46 for discussion.
#76 contains my commit, thanks @airdrummingfool. I have been dealing with a newborn apologies for not getting back to this. |
I'm closing this as there are better alternative PRs out there and it's, like... old. 🙂 |
Note: There may be a better way to approach this or ways to address some of my concerns below. I'd be very happy to get any feedback / suggestions on improving this.
An
ActionView::Template
'svirtual_path
is deprecated under Rails 6. This commit:rails/rails@9a343d1#diff-40f2a5bcf9edfd65a8efe42a05c53736L437
causes the virtual path for templates rendered using
file:
to no longer have theirvirtual_path
explicitly set tonil
.rails-controller-testing
uses the absence of thevirtual_path
attribute to indicate that the template was rendered as usingfile:
. See:https://github.com/rails/rails-controller-testing/blob/master/lib/rails/controller/testing/template_assertions.rb#L34
Because the attribute is never nil with Rails 6, the ability to test something like
assert_template(file: "#{Rails.root}/public/404.html")
is broken.This commit changes the way rendered
file:
templates are tracked. Instead of paying attention to calls toActionView::Template#render
( subscribing to"!render_template.action_view"
) this update instead focuses onActionView::TemplateRenderer#determine_template
. Becausedetermine_tempalte
is not already instrumented, we need to provide our own instrumentation by redefining the method, adding instrumentation, and then handing off tosuper
.Concerns
This probably is not ideal for at least a few reasons:
determine_template
is a few steps removed fromActionView::Template#render
but is the last place in which we have information about what template is being rendered and whether or not it was rendered as afile:
.This method overrides
ActionView::TemplateRenderer#determine_template
for all tests, regardless of whether or not file assertions are required. It would be better if the overriding module was prepended only when necessary and removed afterward.The testing logic applied to
file:
templates is different than for other template types. I'm not extremely happy about that, but given thatActionView::Template#render
is probably a better place to be watching, the change only applies to file templates, not partials, etc...Testing:
All current tests continue to pass, but this is running against a Rails 5 dummy application so the Rails 6 issue isn't actually tested. The fix worked in our test suite running against a Rails 6 application, but it may be that a Rails 6 branch of
rails_controller_testing
with an upgraded dummy app is in order? (I'm not sure what's best there.)