At Pivotal, we often use Capybara to write a suite of integration tests that navigate a browser through any scenario that can emerge in the application. We use these tests to guard against regressions and to drive out the design of the application in a red-green cycle throughout the day.
When it comes to styling the HTML/CSS/JS of the application, it’s common to switch to development mode and manually simulate a scenario so the page of interest can be refreshed in a tight cycle to observe the changes. This can be a rather manual process if the page is only served in response to a complex user flow or an exception case.
If you use capybara and run save_page, it will save a copy of the page it’s currently on and return the file path of the page. If you open that file, however, stylesheets are unavailable because it’s a save file and asset links are relative.
The workaround
Create a controller along the lines of `FilePreviewsController` and use Mac’s open
command to save and open the page.
#app/controllers/file_previews_controller.rb
class FilePreviewsController < ApplicationController
def show
render text: IO.read(params[:file])
end
end
#spec/spec_helper.rb or spec/support/feature_helpers.rb
def save_and_open_preview
`open #{file_preview_url(host: 'localhost:3000', file: save_page)}`
end
#config/routes.rb
if Rails.env.test? || Rails.env.development?
resource :file_preview, only: [:show]
end
That’s it! You can now create complex flows in your feature specs, add save_and_open_preview
, and use the browser to iterate on page’s look and feel.
Here are my top 3 use-cases for using capybara to style your page.
- Getting to rare pages or particular datasets. This includes error pages, email-triggered flows like password-reset, or pages guarded by complex permissions.
- Simulating large amount of content: wonder how to style a gallery with 20 items without manually creating all the items or running a one-off command.
- Outputting views of the application for conversation with PM or designers. Just sprinkle as many of the above helper calls through a user flow and you have a deck to demonstrate a working feature.