Working with Rails 8 System Tests: Handling Mobile and Web Views

Edu Depetris

- Dec 06, 2024
  • Testing
  • System Tests
  • Mobile Testing
  • Ruby On Rails
Working with Rails system tests (using Capybara under the hood), I bumped into an issue while writing tests for both mobile views and web.

My tests pass when I execute them individually or when I only run the mobile versions, but they started to fail (flaky 😞) when I run all the system tests together. In other words, when I run multiple screen sizes, they fail in a flaky manner.

My first approach was quite simple and I took it from the Rails testing guide The only change I made was the browser; I'm using headless_chrome instead of chrome (as the Rails example)

require "test_helper"

class MobileSystemTestCase < ActionDispatch::SystemTestCase
  driven_by :selenium, using: :headless_chrome, screen_size: [375, 667]
end

require "mobile_system_test_case"

class PostsTest < MobileSystemTestCase
  test "visiting the index" do
    visit posts_url
    assert_selector "h1", text: "Posts"
  end
end


After debugging a bit, I noticed that when a mobile test runs interchanged with web tests, the screen_size does not respect the specification screen_size: [375, 667]

I decided to read more about this and dove into the Rails guide for ActionDispatch::SystemTestCase. Here, I found an interesting behavior for headless_chrome:

Let's read it together:

driven_by has a required argument for the driver name. The keyword arguments are :using for the browser and :screen_size to change the size of the browser screen. These two options are not applicable for headless drivers and will be silently ignored if passed.
Headless browsers such as headless Chrome and headless Firefox are also supported. You can use these browsers by setting the :using argument to :headless_chrome or :headless_firefox.

The documentation mentions headless drivers, and since I’m using a headless browser, I wasn’t aware of the difference between these. This motived me to search for another 
solution to set the screen sizes.
 
Minitest provides two handy callbacks: setup (before every test) and teardown (after every test).

require "test_helper"

class MobileSystemTestCase < ActionDispatch::SystemTestCase
  driven_by :selenium, using: :headless_chrome, screen_size: [375, 667]
  
  setup do
    # force the mobile window size before each test
    current_window.resize_to(375, 667)
  end

  teardown do
    # go back to the default window size to avoid side effects
    current_window.resize_to(1400, 1400)
  end
end


The idea is to set the mobile screen size before the test and return to the default size after the test to prevent side effects on other tests.

Results:

After a couple of run locally and on the CI it seems to work 🎉

Happy Coding.