-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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 only stubbed changes to Spree::Config
in specs
#3220
Allow only stubbed changes to Spree::Config
in specs
#3220
Conversation
2e6845d
to
f77f434
Compare
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.
Thanks @spaghetticode, this is fantastic work and I look forward to having it merged in core. I left a preliminary review with some questions, also I'd like to have your opinion on deprecating reset_spree_preferences
at all so even stores and extensions will stop using it.
@@ -73,6 +73,8 @@ module PromotionHandler | |||
end | |||
|
|||
context 'with a custom shipping action' do | |||
let!(:default_actions) { Spree::Config.environment.promotions.shipping_actions } |
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.
Is it not possible to stub this one as well?
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.
👍 yes it is, thanks for noticing it!
@@ -14,7 +14,9 @@ | |||
click_link "RoR Mug" | |||
click_button "Add To Cart" | |||
# Now that we have an order... | |||
Spree::Config[:currency] = "AUD" | |||
visit spree.root_path | |||
with_unfrozen_spree_preference_store do |
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.
I think we should document in the commit message why it's not possible to stub this preference (mainly because is not entirely clear to me yet :P ).
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.
I am also curious about this one.
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.
Being an old regression spec I wanted to keep the code as similar as the original as possible in order to avoid making the spec irrelevant by overlooking some details, so I did not stubbed it in the beginning, but after running this spec against the original code for spree/spree#2340 I think this can be safely stubbed as well. See also the fix for issue 2340: spree/spree@58585fc
As far as I understand this spec basically ensured that this old line would find no order:
current_order = Spree::Order.find_by_id_and_currency(session[:order_id], current_currency, :include => :adjustments)
by changing the backend currency, thus making the line that followed (before the fix) raise an exception:
current_order.last_ip_address = ip_address
I think this spec is not much relevant anymore, as that part of the code is long gone, so I guess it may be safely removed. What do you think? Maybe in another PR to keep things clean and focused here.
Spree::Config.preference_store = Spree::Config[:unfrozen_preference_store] | ||
yield | ||
ensure | ||
reset_spree_preferences |
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.
I'm not sure to get why this reset_spree_preferences
is needed. If we are replacing the preference store with the frozen one generated at the test suite boot we should have it in the same state without the need of a reset, right?
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.
👍 Especially after my latest update, it's not needed anymore.
One thing worth noticing that surprised me is that reset_spree_preferences
returns configuration values to the very default ones for the preference.
For example, Spree::Config.mails_from
is returned to this default value instead of the one set in dummy_app.rb.
I think this is another good reason for avoiding to use it, or deprecate it as you already suggested.
f77f434
to
916204a
Compare
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.
I really like this change @spaghetticode. I would just like to see a comment explaining the purpose of stub_spree_preferences
. Great work! 👍
The method `#stub_spree_preferences` is the preferred way to change global preferences accessible via `Spree::Config`. The method stubs the provided preference calls without changing the actual preference, removing the need to return the preference value to its original.
In order to reuse the helper method `stub_spree_preferences` multiple times ( i.e. in a `before` block and then in a subsequent `it` block) it is necessary to keep previous stubs by not running the line: allow(Spree::Config).to receive(:[]).and_call_original if already executed once.
The method allows to temporarily change `Spree::Config.preference_store` to its original unfrozen values. Changes to the `Spree::Config` settings are reverted automatically at the end of the method execution. This method is required by some existing specs, where the conventional way to change Spree preferences by stubbing does not work or does not make sense. The unfrozen original `preference_store` is stored in `Spree::Config` itself for praticity. The unfrozen original includes changes made by application initializers, such as `dummy_app.rb` when running the test suite.
This is not needed anymore as changes to Spree::Config should only be via stubs.
The configuration preference store is now frozen in order to avoid global state changes that could affect other specs, when not reverted. The unfrozen original configuration is stored for later use in the config preference `unfrozen_preference_store`.
`Spree::Config.mails_from` is set in `dummy_app.rb`, but when using the method `reset_spree_preferences` that change is lost. In order to successfully test the method by veryfing that preference, it's necessary to execute `reset_spree_preferences` before checking the value for `mails_from`, so the before/after values are the same.
Spree::Config changes required by test setups are stubbed so the global configuration is never affected.
Spree::Config changes required by test setups are stubbed so the global configuration is never affected.
Spree::Config changes required by test setups are stubbed so the global configuration is never affected.
Spree::Config changes required test setups are stubbed so the global configuration is never affected.
2ad9eb4
to
364510a
Compare
@kennyadsl I agree with you on deprecating |
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.
I like this change, this is a great idea. Well done @spaghetticode!
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.
Left the last comment, thanks Andrea!
@@ -4,7 +4,23 @@ | |||
|
|||
RSpec.describe Spree::TestingSupport::Preferences do | |||
describe 'resetting the app configuration' do | |||
around do |example| | |||
with_unfrozen_spree_preference_store do | |||
behavior = Spree::Deprecation.behavior |
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.
I think you should use Spree::Deprecation.silence {}
instead here, right?
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.
@kennyadsl 👍 that's much better, thank you!
Helper method `reset_spree_preferences` has been deprecated, as its usage contributed to the bad practice of changing Spree::Config preference values without returning them to the original values. Also, by using `reset_spree_preferences`, preference values set in application initializers such as `dummy_app.rb` are lost. As the method is now deprecated, specs that test it must temporarily change the deprecation behavior or the test suite on circleci will fail.
364510a
to
b3fe321
Compare
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.
👍thanks @spaghetticode, this is great!
By freezing
Spree::Config.preference_store
and allowing changes toSpree::Config
settings only via RSpec stubs we ensure no global settings state change will leak outside the lifecycle of each spec example.Also, stubbing changes to
Spree::Config
removes the necessity to reset these settings before each spec is run, which in the past encouraged the not-so-good practice of changing the global state and not returning it to the original values.When writing tests, the preferred way to change
Spree::Config
settings is by using the helper methodstub_spree_preferences
:The helper method
with_unfrozen_spree_preference_store
can be used when for exceptional reasons one needs to use the unfrozen version of thepreference_store
. This helper method has the advantage of automatically returning the configuration state to the original value:resolve #3219
Checklist: