Writing automated tests for themes is an important part of the theme development process which can help ensure that the features being introduced by a theme continues to work well overtime with core Discourse features.
Currently, Discourse supports two ways of writing regression tests for themes. The first mainly follows EmberJS’s way and only involves testing the client side code. The second way is to write Rails system tests which allows you to test both the server side code and client side code at the same time. This document will focus on writing Rails system tests for themes and is what we recommend theme authors focus on when writing tests for their themes as well.
Rails System tests for themes
Under the hood, Discourse uses the RSpec and Capybara testing frameworks to run Rails system tests. Basic knowledge about RSpec and Capybara is required to get started and we recommend reading through the following links first before you get started:
- GitHub - rspec/rspec-core: RSpec runner and formatters
- GitHub - teamcapybara/capybara: Acceptance test framework for web applications
Guidelines and tips for writing theme system tests
These are some guidelines to follow when writing system tests:
-
System tests are expected to be located in the
spec/system
directory in the theme’s directory. -
Each file in the
spec/system
directory is expected to follow the<description_of_system_test>_spec.rb
format. -
The top level RSpec
describe
block needs thesystem: true
metadata to be present. Example:RSpec.describe "Testing A Theme or Theme Component", system: true do it "should display the component" do ... end end
-
upload_theme
andupload_theme_component
helper methods are available and needs to be called before the tests are ran. Example:RSpec.describe "Testing A Theme or Theme Component", system: true do let!(:theme) do upload_theme end # or `upload_theme_component` if your theme is a component # # let!(:theme_component) do # upload_theme_component # end it "should display the component" do ... end end
-
A theme’s setting can be changed in the system test by calling the
update_setting
method on thetheme
object and then saving the theme.Example:
RSpec.describe "Testing A Theme", system: true do let!(:theme) do upload_theme end it "should not display the theme when `should_render` theme setting is false" do theme.update_setting(:should_render, false) theme.save! expect(page).not_to have_css("#some-identifier") end end
-
Discourse uses the fabrication gem which allows us to easily setup the test data which we need for each test. The full list of fabricators available in Discourse core can be used in the theme’s system test as well.
Example:
RSpec.describe "Testing A Theme", system: true do let!(:theme) do upload_theme end it "should display the theme" do user = Fabricate(:user) category = Fabricate(:category) topic = Fabricate(:topic) topic_2 = Fabricate(:topic, title: "This is topic number 2") ... end end
-
Use the
sign_in
helper method to test against different user profiles.Example:
RSpec.describe "Testing A Theme", system: true do let!(:theme) do upload_theme end it "should not display the theme for a regular user" do user = Fabricate(:user) sign_in(user) ... end it "should display the theme for a staff user" do admin = Fabricate(:admin) sign_in(admin) ... end end
-
Sometimes you’ll want to make querying and inspecting parts of the page easier and more reusable for your system tests. To do that you can use the concept of PageObjects, which you’ll see done often in core.
Example:
# frozen_string_literal: true module PageObjects module Components class MyCustomComponent < PageObjects::Components::Base COMPONENT_SELECTOR = ".my-custom-component" def click_action_button find("#{COMPONENT_SELECTOR} .action-button").click end def has_content?(content) has_css?("#{COMPONENT_SELECTOR} .content", text: content) end end end end
and you can then use it by importing it with Ruby’s built-in
require_relative
at the top of your system test file.require_relative "page_objects/components/my_custom_component"
Running theme system tests
Theme system tests can be run using the discourse_theme CLI rubygem and can be installed with these instructions.
Once the discourse_theme
CLI has been installed, you can run all the system tests in your theme directory by running the following command:
discourse_theme rspec .
On the first run of the rspec
command for a new theme, you will be prompted on whether you would like to run the system tests using a local Discourse development environment or a Docker container which will have the development environment configured for you. Unless you are a seasoned Discourse plugin or theme developer, we recommend selecting n
and run the tests using a Docker container since everything will just work out of the box.
The discourse_theme rspec
command also supports running a single spec directory, file and file with line numbers.
discourse_theme rspec /path/to/theme/spec/system
discourse_theme rspec /path/to/theme/spec/system/my_system_spec.rb
discourse_theme rspec /path/to/theme/spec/system/my_system_spec.rb:12
Headful mode
By default, the theme system tests are ran using Google Chrome in the headless mode. This is a mode where the browser does not render anything on screen allowing test runs to complete faster. However, it is often useful to be able to see what the system test you have written is doing by using Google Chrome in the headful mode. You can enable this mode by passing the --headful
option to the discourse_theme rspec
command.
discourse_theme rspec . --headful
The above command will run the system tests in headful mode where the running of the tests can be seen visually.
You can also pause the execution of the test in your test case by using the pause_test
helper method, allowing you to inspect the current state of the application in the browser.
Example:
RSpec.describe "Testing A Theme", system: true do
let!(:theme) do
upload_theme
end
it "should display the theme" do
visit("/")
click("#some-button")
pause_test
...
end
end
This document is version controlled - suggest changes on github.
Last edited by @JammyDodger 2024-05-26T09:00:19Z
Check document
Perform check on document: