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/systemdirectory in the theme’s directory. -
Each file in the
spec/systemdirectory is expected to follow the<description_of_system_test>_spec.rbformat. -
The top level RSpec
describeblock needs thesystem: truemetadata to be present. Example:RSpec.describe "Testing A Theme or Theme Component", system: true do it "displays the component" do ... end end -
upload_themeandupload_theme_componenthelper 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 "displays the component" do ... end end -
A theme’s setting can be changed in the system test by calling the
update_settingmethod on thethemeobject and then saving the theme.Example:
RSpec.describe "Testing A Theme", system: true do let!(:theme) do upload_theme end it "does 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 "displays 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_inhelper method to test against different user profiles.Example:
RSpec.describe "Testing A Theme", system: true do let!(:theme) do upload_theme end it "does not display the theme for a regular user" do user = Fabricate(:user) sign_in(user) ... end it "displays 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 endand you can then use it by importing it with Ruby’s built-in
require_relativeat 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 "displays the theme" do
visit("/")
click("#some-button")
pause_test
# ...
end
end
This document is version controlled - suggest changes on github.