Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to control time for capybara / phantomjs tests

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.

time_spec.rb:

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

user.html.erb:

<p>Today is <%= Time.now.iso8601 %></p>
<script>
  var now = moment().format()
  $('p').append("<p>Javascript says "+now+"</p>")
</script>

output of running the test:

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)>'
like image 265
Bee Avatar asked Oct 15 '25 08:10

Bee


1 Answers

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.

like image 78
Thomas Walpole Avatar answered Oct 17 '25 00:10

Thomas Walpole



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!