【问题标题】:Stub browser time and time zone with CapybaraCapybara 的存根浏览器时间和时区
【发布时间】:2018-03-27 04:18:17
【问题描述】:

我有一个严重依赖于 -

的 JavaScript 组件(例如日期选择器)
  1. 当前系统时间
  2. 当前系统时区

在 Ruby 和 Capybara 中,可以随时借助诸如 Timecop 之类的库来存根。

是否也可以在 Capybara 控制的无头浏览器中存根这些值?

谢谢!

编辑:这是一个 Ruby 如何被存根但 Capybara 的浏览器仍然使用系统时间的示例

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"

【问题讨论】:

    标签: ruby-on-rails rspec mocking capybara


    【解决方案1】:

    正如您所发现的,Timecop 只影响测试和被测应用程序的时间。浏览器作为一个单独的进程运行,完全不受 Timecop 的影响。因此,您需要在浏览器中存根/模拟时间,以及使用许多旨在执行此操作的 JS 库之一。我通常使用的是 sinon - http://sinonjs.org/ - ,我有条件地使用类似的东西将其安装在页面 head

    - 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});
    

    这应该在haml 模板中工作(如果使用erb 进行调整),并且在使用 Timecop 模拟应用程序时间时,每当访问页面时都会安装和模拟浏览器时间。

    【讨论】:

    • 谢谢! sinon 可以很好地模拟 time,尽管它并没有真正存根浏览器的 time zone。为此,我必须设置类似before(:suite) { ENV['TZ'] = 'America/Los_Angeles' } 的内容,我已成功测试。问题是它必须在整个测试套件之前,这样它才能在无头浏览器启动之前运行。如果我想在每个测试中运行它,我需要重新启动浏览器本身。 Capybara有没有重启无头浏览器的好方法?再次感谢您的帮助。
    • @user2490003 不是真的要重新启动,但您可以使用带有“using_session”的命名会话来启动多个浏览器实例
    【解决方案2】:

    我知道这个问题有点老了,但我们有同样的要求,并找到了以下与 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
    

    【讨论】:

    • 谢谢!这对我帮助很大!
    【解决方案3】:

    这有助于我与 zonebie gem 配对使用

    RSpec.configure do |config|
      config.before(:suite) do
        ENV['TZ'] = Time.zone.tzinfo.name
        # ...
      end
    end
    

    【讨论】:

      猜你喜欢
      • 2018-05-18
      • 1970-01-01
      • 2022-11-19
      • 2016-08-22
      • 2012-02-14
      • 2012-05-17
      • 2017-07-16
      • 2015-02-10
      • 2020-11-28
      相关资源
      最近更新 更多