Skip to content
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

Support nested time travel helpers #24690

Closed

Conversation

vipulnsward
Copy link
Member

Currently travel time helpers don't restore to proper previous state if we have called them in a row, or in a nested fashion.

We simply unstub all previous occurrences. Consider following scenario:

 travel_to outer_expected_time do
     travel_to inner_expected_time do
         #perform some operations from some state here
       end
   #perform some operations from some outer state here
 end

This will fail for outer scenario in that, we simply just unstub all stubbed objects.
Here onwards we also take into account the object into account to create alias, to be more safe in returning back to previous states.

Fixes #24689

@vipulnsward
Copy link
Member Author

r? @senny

@vipulnsward
Copy link
Member Author

Sorry @senny, I don't remember why I assigned this to you. Going to assign to RF, since he originally wrote it.
r? @rafaelfranca

@rails-bot rails-bot assigned rafaelfranca and unassigned senny Apr 23, 2016
stub = stubs.first
unstub_object(stub) if stub
end
@stubs = Hash.new { |h,k| h[k] = [] }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could mutate the hash inline: @stubs.clear.

…if we have called them in a row, or in a nested fashion.

We simply unstub all previous occurrences. Consider following scenario:

 travel_to outer_expected_time do
     travel_to inner_expected_time do
         #perform some operations from some state here
       end
   #perform some operations from some outer state here
 end

This will fail for outer scenario in that, we simply just unstub all stubbed objects.
Here onwards we also take into account the object into account to create alias, to be more safe in returning back to previous states.

Fixes rails#24689
@stubs.each_value do |stubs|
stub = stubs.first
unstub_object(stub) if stub
end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be a good case for splat:

@stubs.each_value do |(stub_masking_original_methods, *)|

@kaspth
Copy link
Contributor

kaspth commented Apr 24, 2016

Are we sure we want travel_back to go all the way? Or just pop one layer?

Not sure what's intuitive here.

stub_object(stub.object, stub.method_name, stub.return_value)
else
unstub_object(current_stub)
end
Copy link
Contributor

@kaspth kaspth Apr 24, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could do with a better method name 😁

Since the stubs per method is essentially turned into a stack we could go with pop_stub.

Here's my take:

def pop_stub(object, method_name)
  key = [ object.object_id, method_name ]

  currently_stubbed_to = @stubs[key].pop

  if stub_next_in_stack = @stubs[key].last
    stub_object(object, method_name, stub_next_in_stack.return_value)
  else
    unstub_object(currently_stubbed_to)
  end
end

Renamed some variables because I found them hard to keep track of.

@sgrif
Copy link
Contributor

sgrif commented Apr 25, 2016

Are we sure we want travel_back to go all the way? Or just pop one layer?

If it's called inside of a travel_to block, it should probably raise.

@kaspth
Copy link
Contributor

kaspth commented Apr 26, 2016

That sounds reasonable, yeah 👍

@rafaelfranca
Copy link
Member

Closing in favor of #24890

vipulnsward added a commit to vipulnsward/rails that referenced this pull request Jul 2, 2016
     as this can lead to confusing time stubbing.

     Instead of:

         travel_to 2.days.from_now do
           # 2 days from today
           travel_to 3.days.from_now do
             # 5 days from today
           end
         end

     preferred way to achieve above is:

         travel_to 2.days.from_now
         # 2 days from today

         travel_back
         travel_to 5.days.from_now
         # 5 days from today

Closes rails#24690
Fixes rails#24689
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants