Test your Stimulus controllers in Rails!
This gem provides a route in test environments by which you can render any HTML with an importmap entry point, and assert on it with the usual browser finders and actions.
This supports the latest minor versions from Rails 6.1 to 8.0. See Appraisals.
Add this line to your application's Gemfile:
gem "stimulus_tests", github: "henrahmagix/stimulus_tests", group: :testAnd then execute:
$ bundleOr install it yourself as:
$ bundle add stimulus_tests --github henrahmagix/stimulus_testsI'm unsure how to gem install this from GitHub source. Unfortunately gem install instructions will be unavailable until I publish this on RubyGems.
See also Examples. All the code examples here reference the default Stimulus controller made by bin/rails stimulus:install named hello, which replaces the element's text with "Hello World!"
First, include the DSL and set an import in your test setup scope:
include StimulusTests::DSL
import "application"Then call render_stimulus before your assertions. It can be called one of two ways:
# 1. With a HTML string.
render_stimulus '<p data-controller="hello">Initial text</p>'
# 2. With a block that gets evaluated in a View context where you can make use of tag helpers.
# The return value is used like the HTML string.
render_stimulus do
content_tag :p, 'Initial text', data: { controller: "hello" }
endNow you can assert on the browser page, like assert_text "Hello World!" ✨
Under the hood, render_stimulus visits a route defined by this gem (see Configuration), where the controller action renders javascript_importmap_tags with the given import, and then the HTML. This is how we get a test browser to load a page with just the JavaScript we need without having to commit such a page to your app.
You can also call layout to configure the layout of the controller defined by this gem:
include StimulusTests::DSL
layout "application"Most of the time you won't need both layout and import: if you have a layout with your entry point already, you can use that and you don't need to use import.
Defining an import entry point and not having a layout reduces the dependencies so you can more clearly unit-test your Stimulus controllers.
They can also be passed into render_stimulus to override the previous definitions:
render_stimulus(layout: "my_specific_layout", import: "controllers") do
'<p data-controller="hello">Initial text</p>'
endNote: if you specify both, and the layout already includes the importmap entry point, then it'll get added twice: this gem always renders the given import into the <head>.
# config/environments/test.rb
Rails.application.configure do
config.stimulus_tests.route_path = "/_stimulus_tests" # this is the default
end# test/system/hello_stimulus_controller_test.rb
require "application_system_test_case"
require "stimulus_tests"
class HelloStimulusControllerTest < ApplicationSystemTestCase
include StimulusTests::DSL
layout "application"
# or
# import "application"
test "runs my controllers" do
render_stimulus <<~HTML
<p data-controller="hello">Initial text</p>
HTML
assert_text "Hello World!"
end
endRequire this gem in your Rails helper:
# spec/rails_helper.rb
require "stimulus_tests"Every example in spec/stimulus, spec/features/stimulus, and spec/system/stimulus automatically gets the DSL included.
# spec/stimulus/hello_controller_spec.rb
require "rails_helper"
RSpec.feature "Stimulus::HelloController" do
layout "application"
# or
# import "application"
it "runs my controllers" do
render_stimulus <<~HTML
<p data-controller="hello">Initial text</p>
HTML
assert_text "Hello World!"
end
endYou can setup any other example individually by ensuring the following:
StimulusTests::DSLis included in the example group.- Examples are run with a JavaScript driver.
Please do! Issues are 👆 up there, and feel free to submit pull-requests for your ideas.
I can't guarantee when I'll be able to read and respond, sorry.
bin/appraisal installThere's a custom bin/rails script that uses the Rails 8 appraisal and proxies to the test/dummy app.
bin/rails server # in the root folderThe test/dummy app is intentionally sparse: it's just meant to exemplify one simple Stimulus controller to System tests can assert on it.
We have both Minitest and RSpec tests because this gem works with both frameworks.
This gem's tests are written in Minitest in the test/ directory. The RSpec tests in spec/ are only to test the integration of this gem with RSpec.
bin/test has been edited to run all tests by default, unless given specific paths.
bin/appraisal bin/testbin/appraisal bin/rspecTo run all the tests together:
bin/appraisal bin/test && bin/appraisal bin/rspecThe gem is available as open source under the terms of the MIT License.