-
Notifications
You must be signed in to change notification settings - Fork 21.4k
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
Rename ActionView::TestCase::Behavior::{Content,RenderedViewContent}
#49856
Conversation
Technically, I think this is public API so it would require a deprecation cycle -- and that rules out backports. 🤔 |
It was added 2 months ago: #49194 |
Sure, but it also exists in 2 public releases of Rails (7.1.0 and 7.1.1), you can also make an argument that is a bug. I'm just trying to point out the technical detail that might be otherwise overlooked. |
I think we've made internal classes |
I'm happy to mark the class |
I don't think |
Let's bring this up in discord and see what kind of feedback we get. #:pray: |
Definitely, since deprecations aren't backported.
Probably some combination of deprecate_constant and assert_deprecated. |
8443668
to
f4b0e34
Compare
9fea60b
to
39b0a83
Compare
@zzak @p8 I've changed this PR to be slightly more aggressive than it was originally. While the Does that quirk warrant skipping the deprecation process? |
Closes rails#49818 Renames `ActionView::TestCase::Behavior::Content` to `RenderedViewContent`, with the goal of making it more of an internal implementation detail that's unlikely to collide with an application-side `::Content` class. The `RenderedView`-prefix mirrors the module's `RenderedViewsCollection` class. Since the intention is to treat it as a private implementation detail, `RenderedViewContent` is marked with `:nodoc:`. Along with the rename, this commit also modifies the class inheritance, replacing the `SimpleDelegator` superclass with `String`. [String.new][] accepts a `String` positional argument in the same way as `SimpleDelegator.new` accepts a delegate object positional argument. Sharing the `String` superclass also makes it a good candidate for being passed to [Capybara.string][] (and [Capybara::Node::Simple.new][]) like the documentation suggests. [Capybara.string]: https://github.com/teamcapybara/capybara/blob/3.39.2/lib/capybara.rb#L212-L242 [Capybara::Node::Simple.new]: https://github.com/teamcapybara/capybara/blob/3.39.2/lib/capybara/node/simple.rb#L23 [String.new]: https://ruby-doc.org/core/String.html#method-c-new
39b0a83
to
cebbd1c
Compare
Rename `ActionView::TestCase::Behavior::{Content,RenderedViewContent}`
Rename `ActionView::TestCase::Behavior::{Content,RenderedViewContent}`
This reverts commit f7255ec. Reason: This an empty commit applied by mistake.
@@ -1,3 +1,7 @@ | |||
* Rename `ActionView::TestCase::Behavior::{Content,RenderedViewContent}` |
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.
@seanpdoyle Could you expand this changelog to make sense in English? I understand what it means, but someone with limited bash-fu might not be looking for this
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.
Follow-up to [rails#49856][] Replace shell word expansion with full English. In addition to that change, elaborate on the changes with more detailed explanation. [rails#49856]: rails#49856 (comment)
Re-word #49856 CHANGELOG entry [ci skip]
Re-word #49856 CHANGELOG entry [ci skip]
@seanpdoyle this change caused some breakage in our view tests. When we render more than once in a test, now the later renders don't change the rendered result. It's not a huge deal, as we only do this in a couple of places, but just FYI. For example in the following test case, the second assertion fails because the view content hasn't updated: it 'renders whether bulk approval is enabled' do
render 'admin/steps/list', local_assigns
expect(rendered).not_to have_text('Bulk Approval is enabled')
step.update!(bulk_approval_enabled: true)
render 'admin/steps/list', local_assigns
expect(rendered).to have_text('Bulk Approval is enabled')
end |
How do you know it was this change? It should not cause this since it only renamed a class. |
I believe that change in behavior originates from https://github.com/rails/rails/pull/49194/files#diff-ce84a807f3491121a5230d37bd40454bb1407fcca71179e1a2fa76d4c0ddfa2aR293. Is rendering in this way intended to be supported? I have a branch locally to remove the memoization with this change: diff --git a/actionview/lib/action_view/test_case.rb b/actionview/lib/action_view/test_case.rb
index c12feeac95..006c6bf759 100644
--- a/actionview/lib/action_view/test_case.rb
+++ b/actionview/lib/action_view/test_case.rb
@@ -291,7 +291,7 @@ def rendered_views
# assert_pattern { rendered.json => { title: "Hello, world" } }
# end
def rendered
- @_rendered ||= self.class.content_class.new(@rendered)
+ self.class.content_class.new(@rendered)
end
def _routes
diff --git a/actionview/test/template/test_case_test.rb b/actionview/test/template/test_case_test.rb
index 163ec700d2..0f1f27b004 100644
--- a/actionview/test/template/test_case_test.rb
+++ b/actionview/test/template/test_case_test.rb
@@ -394,6 +394,20 @@ class RenderedViewContentTest < ActionView::TestCase
assert_match(/#{developer.name}/, rendered)
assert_includes rendered, developer.name
end
+
+ test "#rendered resets after each render" do
+ render "developers/developer", developer: DeveloperStruct.new("First")
+
+ assert_equal "First", rendered
+
+ render "developers/developer", developer: DeveloperStruct.new("Second")
+
+ assert_equal "Second", rendered
+ end
end
class HTMLParserTest < ActionView::TestCase The test is failing:
Calling While I appreciate the idea of preserving backwards compatibility, I wonder: would that particular example of test coverage be better served as two separate tests with two output buffers? |
Follow-up to [49856][] Follow-up to [49194][] The introduction of memoization as an optimization posed a backwards incompatible change to View tests that call `render` multiple times. This commit breaks resets that memoization whenever `render` is called. The optimization is preserved after rendering for test cases where `rendered` (or parser methods like `rendered.html`) might be invoked more than once. [49856]: rails#49856 (comment) [49194]: https://github.com/rails/rails/pull/49194/files#diff-ce84a807f3491121a5230d37bd40454bb1407fcca71179e1a2fa76d4c0ddfa2aR293
@mockdeep @rafaelfranca I've opened #51093 in response to #49856 (comment). |
Follow-up to [49856][] Follow-up to [49194][] The introduction of memoization as an optimization posed a backwards incompatible change to View tests that call `render` multiple times. This commit changes the `@rendered` instance variable from a `String` to an instance of the `RenderedViewContent` specialized `String` subclass. The end result is that there is no memoization to reset, and the memoization optimization side-effect is preserved after rendering for test cases where `rendered` (or parser methods like `rendered.html`) might be invoked more than once. [49856]: rails#49856 (comment) [49194]: https://github.com/rails/rails/pull/49194/files#diff-ce84a807f3491121a5230d37bd40454bb1407fcca71179e1a2fa76d4c0ddfa2aR293
Follow-up to [49856][] Follow-up to [49194][] The introduction of memoization as an optimization posed a backwards incompatible change to View tests that call `render` multiple times. This commit changes the `@rendered` instance variable from a `String` to an instance of the `RenderedViewContent` specialized `String` subclass. The end result is that there is no memoization to reset, and the memoization optimization side-effect is preserved after rendering for test cases where `rendered` (or parser methods like `rendered.html`) might be invoked more than once. [49856]: rails#49856 (comment) [49194]: https://github.com/rails/rails/pull/49194/files#diff-ce84a807f3491121a5230d37bd40454bb1407fcca71179e1a2fa76d4c0ddfa2aR293
@rafaelfranca We bisected the commits and landed on this one. It's a little confusing as to why this change would cause it, so maybe we missed something. @seanpdoyle it's not critical behavior for us, and we'll probably end up splitting up the couple of tests that failed. We're working on phasing out view specs anyway. However, if it's not supported behavior, it seems like a second render should maybe throw an error to make it clear that it's not supported. |
Upon further reflection, I do believe multiple renders is and should be supported. |
Follow-up to [49856][] Follow-up to [49194][] The introduction of memoization as an optimization posed a backwards incompatible change to View tests that call `render` multiple times. This commit changes the `@rendered` instance variable from a `String` to an instance of the `RenderedViewContent` specialized `String` subclass. The end result is that there is no memoization to reset, and the memoization optimization side-effect is preserved after rendering for test cases where `rendered` (or parser methods like `rendered.html`) might be invoked more than once. [49856]: rails#49856 (comment) [49194]: https://github.com/rails/rails/pull/49194/files#diff-ce84a807f3491121a5230d37bd40454bb1407fcca71179e1a2fa76d4c0ddfa2aR293
Follow-up to [49856][] Follow-up to [49194][] The introduction of memoization as an optimization posed a backwards incompatible change to View tests that call `render` multiple times. This commit changes the `@rendered` instance variable from a `String` to an instance of the `RenderedViewContent` specialized `String` subclass. The end result is that there is no memoization to reset, and the memoization optimization side-effect is preserved after rendering for test cases where `rendered` (or parser methods like `rendered.html`) might be invoked more than once. [49856]: rails#49856 (comment) [49194]: https://github.com/rails/rails/pull/49194/files#diff-ce84a807f3491121a5230d37bd40454bb1407fcca71179e1a2fa76d4c0ddfa2aR293
Follow-up to [49856][] Follow-up to [49194][] The introduction of memoization as an optimization posed a backwards incompatible change to View tests that call `render` multiple times. This commit changes the `@rendered` instance variable from a `String` to an instance of the `RenderedViewContent` specialized `String` subclass. The end result is that there is no memoization to reset, and the memoization optimization side-effect is preserved after rendering for test cases where `rendered` (or parser methods like `rendered.html`) might be invoked more than once. [49856]: rails#49856 (comment) [49194]: https://github.com/rails/rails/pull/49194/files#diff-ce84a807f3491121a5230d37bd40454bb1407fcca71179e1a2fa76d4c0ddfa2aR293
Follow-up to [49856][] Follow-up to [49194][] The introduction of memoization as an optimization posed a backwards incompatible change to View tests that call `render` multiple times. This commit changes the `@rendered` instance variable from a `String` to an instance of the `RenderedViewContent` specialized `String` subclass. The end result is that there is no memoization to reset, and the memoization optimization side-effect is preserved after rendering for test cases where `rendered` (or parser methods like `rendered.html`) might be invoked more than once. [49856]: rails#49856 (comment) [49194]: https://github.com/rails/rails/pull/49194/files#diff-ce84a807f3491121a5230d37bd40454bb1407fcca71179e1a2fa76d4c0ddfa2aR293
Motivation / Background
Closes #49818
Detail
Renames
ActionView::TestCase::Behavior::Content
toRenderedViewContent
, with the goal of making it more of an internalimplementation detail that's unlikely to collide with an
application-side
::Content
class.The
RenderedView
-prefix mirrors the module'sRenderedViewsCollection
class. Since the intention is to treat it as a private implementation
detail,
RenderedViewContent
is marked with:nodoc:
.Along with the rename, this commit also modifies the class inheritance,
replacing the
SimpleDelegator
superclass withString
. String.newaccepts a
String
positional argument in the same way asSimpleDelegator.new
accepts a delegate object positional argument.Sharing the
String
superclass also makes it a good candidate for beingpassed to Capybara.string (and Capybara::Node::Simple.new) like
the documentation suggests.
Additional information
Is this worth backporting into a
7.1
release?Checklist
Before submitting the PR make sure the following are checked:
[Fix #issue-number]