Reputation: 14427
I want to test that some deadlines are getting displayed to users correctly in different timezones and at different times of day. My tests are using capybara+rspec+phantomjs.
I am passing a block to Timecop.travel(datetime) and the code in the test within that block is getting the mocked datetime correctly, but it looks like PhantomJS / the mocked browser are not getting the mocked time.
Is there any known way to get PhantomJS to work with Timecop? Or other ways to mock out or manipulate time for testing purposes?
Here's a simple example to illustrate what I mean.
it "should show the Time travel date" do
# current date is 2017-01-24
Date.today.should == Date.parse("2017-01-24")
Timecop.travel( Time.parse("2001-01-01 01:01") ) {
sign_in(user)
visit "/#{user.username}"
Date.today.should == Date.parse("2001-01-01")
page.should have_text("Today is 2001-01-01")
page.should have_text("Javascript says 2001-01-01")
}
end
<p>Today is <%= Time.now.iso8601 %></p>
<script>
var now = moment().format()
$('p').append("<p>Javascript says "+now+"</p>")
</script>
Failures:
1) Dashboard should show the time travel date
Failure/Error: page.should have_text("Javascript says 2001-01-01")
expected to find text "Javascript says 2001-01-01" in
"Today is 2001-01-01T01:01:00-08:00 Javascript says 2017-01-24T12:36:02-08:00"
# ./spec/features/time_spec.rb:67:in `block (3 levels) in <top (required)>'
# /gems/ruby-2.2.0/gems/timecop-0.8.0/lib/timecop/timecop.rb:147:in `travel'
# /gems/ruby-2.2.0/gems/timecop-0.8.0/lib/timecop/timecop.rb:121:in `send_travel'
# /gems/ruby-2.2.0/gems/timecop-0.8.0/lib/timecop/timecop.rb:62:in `travel'
# ./spec/features/time_spec.rb:59:in `block (2 levels) in <top (required)>'
Upvotes: 4
Views: 1610
Reputation: 49910
As you've discovered TimeCop only adjusts the servers time, but the browser uses system time. There are a number of JS libraries to allow for time faking, that all work by mocking the JS Date Class. One I have used successfully is Sinon.JS which I implemented in my _head.html.haml
file by doing
- if defined?(Timecop) && Timecop.top_stack_item
= javascript_include_tag "testing/sinon-1.17.3.js"
- unix_millis = (Time.now.to_f * 1000.0).to_i
:javascript
sinon.useFakeTimers(#{unix_millis});
before requiring any other JS. This will set the browser time in any page rendered to whatever Timecop is set to.
Upvotes: 5