Rails system test with mobile viewport

While building my subscription tracking service I broke the mobile navigation menu and deployed it to production. It was only after a day or so that a user emailed me to report this bug. I directly understood why my ads did not convert! This should never happen again, let’s create a system test with mobile viewport sizes that verifies the menu works correctly.

Default screen size desktop

As you might know, the default Rails system tests use dimensions that are defined in test/application_system_test_case.rb with a line such as:

driven_by :selenium, using: :headless_chrome, screen_size: [1400, 1400]

The most simple solution would be to just modify the sizes in that array. However, this would make all system test cases use the mobile viewport, which is not what I want.

Every test case a different screen size

After some searching I found that the Rails APIs did not support setting the screen size for one test case. Capybara, which is used as an underlying gem, does however. So as the first line to a mobile viewport test case you can set the screen size using:

Capybara.current_session.current_window.resize_to(360, 740) # Galaxy S9

The naive solution to resetting the screen size after this test case would be to repeat this call with the original 1400, 1400 as arguments. However, if the test does not succeed, it will not execute that line. It is therefore better to reset the viewport in a seperate teardown method, for example in your test/application_system_test_case.rb file:

teardown do
  Capybara.current_session.current_window.resize_to(1400, 1400)
end

You can DRY the resulting test/application_system_test_case.rb a bit by storing the default size in a const array and using that in the various calls. The one I use now looks like this:

# frozen_string_literal: true

require 'test_helper'

class ApplicationSystemTestCase < ActionDispatch::SystemTestCase
  WINDOW_SIZE = [1400, 1400].freeze
  driven_by :selenium, using: :headless_chrome, screen_size: WINDOW_SIZE

  teardown do
    Capybara.current_session.current_window.resize_to(*WINDOW_SIZE)
  end
end

Subscribe to the RSS feed to be notified of my next blog post!