ViewSpec
ViewSpec helps you develop, test and document the view layer of your Rails app using example-led specifications written in an expressive Ruby DSL. Specs can be created for your app's components, partials, helpers, views and more.
Each spec is made up of one or more scenarios, each of which represents a particular state or variant of the the subject of the spec. You can define a preview, add contextual tests and include usage information for each scenario.
ViewSpec then handles generating live preview endpoints and integrating the tests into your test suite, and makes it easy to generate developer documentation from the specs you create.
[!IMPORTANT] ViewSpec is at a very early stage of development. Bugs are very likely and breaking changes may happen without warning. Please give it a try and share any thoughts, feedback or comments via issues/discussions but be aware that there will likely be significant changes to ViewSpec's functionality and API before a stable
v1.0release candidate is reached.
ViewSpec files and DSL
ViewSpec spec files are written in Ruby and should be placed in the test/view_specs directory. Their filenames should end in _vspec.rb and can be organised in whatever subfolder struture is appropriate for your needs.
ViewSpec specs are written in a bespoke Ruby DSL that should feel somewhat familiar if you have used RSpec before.
Here's what an example spec file for a button component might look like:
# test/view_specs/button_vspec.rb
ViewSpec.spec ButtonComponent do
scenario "default" do
notes <<~MD
Default button with the `primary` theme.
_Appropriate for the majority of use-cases._
MD
preview do
render ButtonComponent.new(text: "Button text")
end
tests do
test "it renders" do
render_preview
assert_selector("button")
end
test "it displays the label text" do
render_preview
assert_selector("button", text: "Button text")
end
end
end
scenario "themes" do
title "Available Themes"
notes <<~MD
There are three button themes available for use:
* `:primary` (default)
* `:secondary` (use for less important actions)
* `:danger` (use for destructive actions)
MD
preview <<~ERB
<%= render ButtonComponent.new(text: "Primary", theme: :primary) %>
<%= render ButtonComponent.new(text: "Secondary", theme: :secondary) %>
<%= render ButtonComponent.new(text: "Danger", theme: :danger) %>
ERB
tests do
test "it applies themes to the buttons" do
render_preview
assert_selector(%(button[data-theme="primary"]))
assert_selector(%(button[data-theme="secondary"]))
assert_selector(%(button[data-theme="danger"]))
end
end
end
scenario "playground" do
notes <<~MD
You can append query parameters to the preview URL to
set the button's `text`, `type` and `theme` properties.
MD
param :text, :string, default: "Button text"
param :type, :symbol, default: :button
param :theme, :symbol, default: :primary
preview do
render ButtonComponent.new(**params)
end
end
end
[!NOTE] ViewSpec is completely agnostic to your choice of component framework (e.g. ViewComponent, Phlex, etc), templating language (ERB, HAML, etc) and test suite. If you can use it with Rails you can use it with ViewSpec!
Workflow example
Below is an outline of what a ViewSpec-based workflow for developing, testing and documenting a new button component might look like.
The button component in this example will be implemented using a standard Rails/ActionView partial, but could equally be created using ViewComponent, Phlex, a view helper or even just vanilla HTML.
We'll assume that the ViewSpec gem has already been installed and configured in the example app.
1. Create the component
First we create the basic button component partial in the app/views/components directory.
<%# locals: (text:, theme: :primary, type: :button) %>
<%= button_tag(text, type: type, data: {theme: theme}, class: "button") %>
From the file above you can see that there are default values for the theme and type options. Only the button text argument is required to render the partial.
2. Add a spec file
Now we'll start by creating a bare-bones button spec at test/view_specs/button_vspec.rb that includes a single scenario describing the default state of the button.
# test/view_specs/button_vspec.rb
ViewSpec.spec "components/button" do
title "Basic button"
scenario "default" do
notes <<~MD
Default button with `primary` theme.
_Appropriate for the majority of use-cases._
MD
preview do
render "components/button", text: "Click here"
end
end
end
3. Inspect the preview
The default button preview defined above will now be available for viewing at https://localhost:3000/rails/view_spec/previews/button@default.
Previews are rendered in isolation from the rest of your app which makes them perfect for using whilst developing your components/partials/helpers etc.
[!NOTE] By default previews are only available when your app is running in
developmentandtestenvironments, although this behaviour is configurable if required.
4. Add some tests
Once a scenario preview has been added you can then add some tests to run against it.
Tests are defined within the context of the scenario in a tests do ... end block.
For this example we'll add a couple of test to check that the rendered output of this default button component state is as expected.
# test/view_specs/button_vspec.rb
ViewSpec.spec "components/button" do
# ...
scenario "default" do
# ...
preview do
render "components/button", text: "Click here"
end
tests do
setup { render_preview }
test "it renders the button component" do
assert_selector("button.button")
end
test "it has the default attributes set" do
assert_selector(%(button[type="button"][data-theme="primary"]))
end
test "it displays the label text" do
assert_selector("button", text: "Click here")
end
end
end
end
5. Run the tests
To run the tests as part of your Minitest-based test suite you will first need to add a ViewSpec test file into your tests directory. It should contain the following content:
# tests/view_specs_test.rb
require "test_helper"
module ViewSpecsTest
include ViewSpec::Minitest::Tests
end
This only needs to be done once. With with this file in place all the preview tests defined in your spec files will be included everytime your test suite is run using rails test.
If you only wish to run your ViewSpec tests then just run the ViewSpec test file directly:
rails test test/view_specs_test.rb
[!NOTE] Only Minitest is currently supported but adapters for RSpec and more are in the works!
6. Add more scenarios
At this point it often makes sense to add more scenarios to demonstrate/document other states or properties of the subject of the spec.
A spec can have as many scenarios as needed, each with it's own preview, tests and usage notes.
[!TIP] Scenarios can also be grouped together in a
group do ... endblock if required. See below for more details on scenarios and scenario groups.
7. Generate documentation
ViewSpec files are designed to act as readable developer-documentation in their own right. However you may also wish to have HTML-formatted documentation for your components/partials/views etc.
ViewSpec provides some bare-bones default templates to make it easy to generate HTML docs from your specs.
For simplicity the example below just shows how you could generate docs specifically for the single button spec defined above (although in reality you would probably want to make this dynamic so you wouldn't need to manually add a separate action for each spec file).
class DocsController < ApplicationController
def button
@spec = ViewSpec.specs.find(ButtonComponent)
@params = request.query_parameters
end
end
# views/docs/button.html.erb
<%= render @spec, params: @params %>
The example above will render documentation for the button spec using the default templates.
Styling the docs with CSS is up to you, no default stylesheet is provided. With some basic styles applied the default templates look like this:

You can override one or all of the default templates by copying them into a view_specs folder in your app/views directory, and then customising them as needed.
Usage
ViewSpec has the following requirements:
Rails 7.0+Ruby 3.1+
Installation
Add the following to your Rails app Gemfile:
gem "view_spec"
And then run bundle install. You are good to go!
Configuration
Docs coming soon
ViewSpec DSL
Docs coming soon
About ViewSpec (& Lookbook)
ViewSpec is being developed as a standalone replacement for Lookbook's underlying preview system.
It shares a lot of concepts with the existing Lookbook preview class format (which was based on ViewComponent's preview system - itself in turn inspired by Rails' ActionMailer previews). However using a pure Ruby DSL in place of YARD-style comment tags results in much better performance and has many other benefits (including 'native' syntax error handling and more).
Additionally, having a standalone file format and preview system which is not tied to any particular UI tool (such as Lookbook) or component system (such as ViewComponent) hopefully means that ViewSpec can be adopted by teams that don't want those dependencies but do still want a way to efficiently develop and document the frontend of their Rails app.
The plan is for the next major version of Lookbook to built upon the ViewSpec file format. It will provide a user interface for browsing and inspecting your ViewSpec previews in much the same way it does at the moment for the current (ViewComponent-style) preview class files.
(Note that the current v2.x branch of Lookbook is not compatible with ViewSpec and there is no intention to add support for it in the future.)
[!IMPORTANT] Projects can (and always will be able to) use ViewSpec to help preview, test and document their view layer without any requirement to use Lookbook.