module Rooibos::TestHelper
Assertions and test utilities for Rooibos applications.
Custom commands run in background threads. Forgetting to include Command::Custom causes cryptic Ractor errors. Validating protocol compliance manually is tedious.
This module provides Rooibos-specific assertions. It also includes RatatuiRuby::TestHelper, giving you access to with_test_terminal, inject_key, etc.
Use it in Minitest classes to validate commands and control test terminals.
Example
class TestMyApp < Minitest::Test include Rooibos::TestHelper def test_app_exits_on_ctrl_c with_test_terminal do inject_key(:ctrl_c) Rooibos.run(MyApp) end end end
Constants
- ClearView
-
Simple view that just clears the terminal
- ExitOnAnyKeyUpdate
-
Update that exits immediately on any key
- ExitOnQUpdate
-
Update that exits on ‘q’ key, passes through all other messages
Public Instance Methods
Source
# File lib/rooibos/test_helper.rb, line 105 def assert_no_errors(messages, msg = nil) error = messages.find { |m| m.is_a?(Rooibos::Message::Error) } return unless error error_detail = "#{error.exception.class}: #{error.exception.message}" failure_msg = msg ? "#{msg}\n#{error_detail}" : "Unexpected Message::Error: #{error_detail}" if respond_to?(:flunk) # rubocop:disable Style/SendWithLiteralMethodName public_send(:flunk, failure_msg) # rubocop:enable Style/SendWithLiteralMethodName else raise failure_msg end end
Fails if any Message::Error is present in the messages array.
Call after running the runtime and before asserting on expected messages. This ensures tests fail fast with helpful error messages instead of silently passing when errors occur.
- messages
-
Array of messages collected from the update function.
- msg
-
Optional custom failure message prefix.
Example
def test_dashboard_loads_data messages = [] update = -> (msg, m) do # ... handle keys ... messages << msg [m, nil] end with_test_terminal do inject_key("s") inject_sync inject_key("q") Rooibos::Runtime.run(model:, view:, update:) end assert_no_errors(messages) # ... rest of assertions end
Source
# File lib/rooibos/test_helper.rb, line 55 def validate_rooibos_command!(command) unless command.respond_to?(:rooibos_command?) raise Rooibos::Error::Invariant, "#{command.class} does not respond to #rooibos_command?. " \ "Include Command::Custom or implement the rooibos_command? predicate." end unless command.respond_to?(:call) raise Rooibos::Error::Invariant, "#{command.class} does not respond to #call. " \ "Implement call(out, token) to execute the command." end unless command.respond_to?(:rooibos_cancellation_grace_period) raise Rooibos::Error::Invariant, "#{command.class} does not respond to #rooibos_cancellation_grace_period. " \ "Include Command::Custom or implement this method." end end
Validates a command implements the Rooibos command protocol.
Custom commands run in background threads. They dispatch work and send messages. Forgetting to include <tt>Command::Custom</tt> breaks dispatch. The runtime treats <tt>[model, bad_command]</tt> as a model, not a tuple. Tests fail with confusing Ractor shareability errors.
This method checks the protocol. Call it in tests to catch mistakes early.
- command
-
The command object to validate.
Example
def test_websocket_command_protocol cmd = WebSocketCommand.new("wss://example.com") validate_rooibos_command!(cmd) end