Reputation: 11900
I have a JavaScript component (e.g. a date picker) that heavily depends on -
In Ruby and Capybara it's possible to stub any time with the help of libraries such as Timecop.
Is it also possible to stub these values in the headless browser that Capybara controls?
Thanks!
Edit: Here's an example of how Ruby is stubbed but Capybara's browser still uses the system time
before do
now = Time.zone.parse("Apr 15, 2018 12:00PM")
Timecop.freeze(now)
visit root_path
binding.pry
end
> Time.zone.now
=> Sun, 15 Apr 2018 12:00:00 UTC +00:00
> page.evaluate_script("new Date();")
=> "2018-03-27T04:15:44Z"
Upvotes: 9
Views: 4710
Reputation: 881
You can pass a time zone for testing when registering the Capybara driver:
Capybara.register_driver :selenium_remote_chrome do |app|
options = Selenium::WebDriver::Chrome::Options.new
# Set Chrome to use UTC instead of the computer's timezone.
options.add_argument('--time-zone-for-testing=UTC')
end
Upvotes: 3
Reputation: 9688
I know that the question is a bit old, but we had the same request and found the following solution to work with rails 6:
context 'different timezones between back-end and front-end' do
it 'shows the event timestamp according to front-end timezone' do
# Arrange
previous_timezone = Time.zone
previous_timezone_env = ENV['TZ']
server_timezone = "Europe/Copenhagen"
browser_timezone = "America/Godthab"
Time.zone = server_timezone
ENV['TZ'] = browser_timezone
Capybara.using_session(browser_timezone) do
freeze_time do
# Act
# ... Code here
# Assert
server_clock = Time.zone.now.strftime('%H:%M')
client_clock = Time.zone.now.in_time_zone(browser_timezone).strftime('%H:%M')
expect(page).not_to have_content(server_clock)
expect(page).to have_content(client_clock)
end
end
# (restore)
Time.zone = previous_timezone
ENV['TZ'] = previous_timezone_env
end
end
Upvotes: 5
Reputation: 1115
This helps me for usage in pair with zonebie
gem
RSpec.configure do |config|
config.before(:suite) do
ENV['TZ'] = Time.zone.tzinfo.name
# ...
end
end
Upvotes: 1
Reputation: 49910
As you've discovered, Timecop only affects the time in the tests and application under test. The browser is run as a separate process and completely unaffected by Timecop. Because of that you need to stub/mock the time in the browser as well using one of many JS libraries designed to do that. The one I generally use is sinon
- http://sinonjs.org/ - , which I conditionally install in the pages head
using something like
- if defined?(Timecop) && Timecop.top_stack_item
= javascript_include_tag "sinon.js" # adjust based on where you're loading sinon from
- unix_millis = (Time.now.to_f * 1000.0).to_i
:javascript
sinon.useFakeTimers(#{unix_millis});
That should work in a haml
template (adjust if using erb
) and would install and mock the browsers time whenever a page is visited while Timecop is being used to mock the apps time.
Upvotes: 8