Capybara & Rspec
Matestack apps, pages and components can be tested with various test setups. We're using Rspec and Capybara a lot when creating apps with Matestack or work on Matestack's core itself and want to show you some basic elements of this setup.
We will show you how to setup a headless chrome for testing, because a headless browser approach gives you performance benefits and is better suited to be integrated in a CI/CD pipeline.
Setup
In this guide we assume that you know the basics of Rspec and Capybara and have both gems installed. If not, please read the basics about these tools here:
Note: Make sure you set config.action_controller.allow_forgery_protection = true
in your `config/environments/test.rb' file.
Additionally you need a Chrome browser installed on your system.
We recommend to configure Capybara in a separate file and require it in your rails_helper.rb
Writing basic specs
Imagine having implemented a Matestack page like:
A spec might look like this:
and then run this spec with bundle exec rspec spec/features/hello_world_spec.rb
This should start a webserver and trigger the headless chrome to request the specified page from it. Just like Capybara is working.
Testing asynchronous features
Above, we just tested a static "hello world" rendering and didn't use any JavaScript based functionality. We need to activate the JavaScript driver in specs where Matestack's built-in (or your own) JavaScript is required.
Let's add some basic built-in reactivity of Matestack, which requires JavaScript to work:
The spec could look like this: Note that you now have to add the js: true
on line 3!
Capybara by default will wait for 2000ms before failing on an expectation. expect(page).to have_content("hello world!")
therefore may take up to 2000ms to become truthy without breaking the spec. Following the documentation of Capybara, you can adjust the default wait time or set it individually on specific expectations. This built-in wait mechanism is especially useful when working with features requiring client-server communication, like page transitions, form or action submissions!
Testing forms and actions
Imagine a matestack_form
used for creating new User
ActiveRecord Model instances:
The according spec might look like this:
If you want to test if the User model was correctly saved in the Database, you could do something like this:
Beware of the timing trap!
Without adding expect(page).to have_content("succeeded!")
after click "submit me"
the spec would fail. The User.count
would be executed too early! You somehow need to use Capybara's built-in wait mechanisim in order to identify a successful asynchronous form submission. Otherwise the spec would just click the submit button and immediately expect a database state change. Unlike Capybara, plain Rspec expectations do not wait a certain amount of time before failing! Gems like https://github.com/laserlemon/rspec-wait are trying to address this issue. In our experience, you're better of using Capybara's built-in wait mechanism like shown in the example, though.
Above described approaches and hints apply for actions as well!
Debugging specs
When running specs in a headless browser, you're loosing insights on what exactly happens when a spec is failing. You have a simple yet powerful option to overcome this issue:
As described within the Setup section, it's possible to tell Capybara, which port should be used by the webserver while executing the specs. (By default it's randomly chosen on every spec run). When adding a simple sleep
after a visit
in your spec, you can request the same page, your spec would visit in you local browser and review what's going on there by manually executing the steps your spec would perform while reviewing the DOM and browser debugging tools:
Execute the spec and then visit the logged path in your local browser via localhost:33123/xyz
for example.
This approach is especially useful when using factories in order to create temporary test data which is only accessible in your test ENV and that specific spec. In other words: you can review the test state way better compared to perform the spec steps in your local development ENV.
Last updated