module RatatuiRuby::TestHelper::EventInjection
Event injection helpers for testing TUI interactions.
Testing keyboard navigation and mouse clicks requires simulating user input. Constructing event objects by hand for every test is verbose and repetitive.
This mixin provides convenience methods to inject keys, clicks, and other events into the test terminal’s event queue. Events are consumed by the next poll_event call.
Use it to simulate user interactions: typing, clicking, dragging, pasting.
Examples
with_test_terminal do inject_keys("h", "e", "l", "l", "o") inject_keys(:enter, :ctrl_s) inject_click(x: 10, y: 5) inject_event(RatatuiRuby::Event::Paste.new(content: "pasted text")) @app.run end
Public Instance Methods
Source
# File lib/ratatui_ruby/test_helper/event_injection.rb, line 141 def inject_click(x:, y:, modifiers: []) inject_mouse(x:, y:, kind: :down, modifiers:, button: :left) end
Source
# File lib/ratatui_ruby/test_helper/event_injection.rb, line 161 def inject_drag(x:, y:, modifiers: [], button: :left) inject_mouse(x:, y:, kind: :drag, modifiers:, button:) end
Source
# File lib/ratatui_ruby/test_helper/event_injection.rb, line 65 def inject_event(event) unless @_ratatui_test_terminal_active raise RatatuiRuby::Error::Invariant, "Events must be injected inside a `with_test_terminal` block. " \ "Calling this method outside the block causes a race condition where the event " \ "is flushed before the application starts." end case event when RatatuiRuby::Event::Key RatatuiRuby.inject_test_event("key", { code: event.code, modifiers: event.modifiers }) when RatatuiRuby::Event::Mouse RatatuiRuby.inject_test_event("mouse", { kind: event.kind, button: event.button, x: event.x, y: event.y, modifiers: event.modifiers, }) when RatatuiRuby::Event::Resize RatatuiRuby.inject_test_event("resize", { width: event.width, height: event.height }) when RatatuiRuby::Event::Paste RatatuiRuby.inject_test_event("paste", { content: event.content }) when RatatuiRuby::Event::FocusGained RatatuiRuby.inject_test_event("focus_gained", {}) when RatatuiRuby::Event::FocusLost RatatuiRuby.inject_test_event("focus_lost", {}) when RatatuiRuby::Event::Sync if RatatuiRuby::SyntheticEvents.inline_sync? # Route through native queue for deterministic ordering with key events RatatuiRuby.inject_test_event("sync", {}) else # Default 1.0 behavior: use the engine-level synthetic queue RatatuiRuby::SyntheticEvents.push(event) end else raise ArgumentError, "Unknown event type: #{event.class}" end end
Injects an event into the test terminal’s event queue.
Pass any RatatuiRuby::Event object. The event is returned by the next poll_event call.
Raises RuntimeError if called outside a with_test_terminal block.
Examples
inject_event(RatatuiRuby::Event::Key.new(code: "q")) inject_event(RatatuiRuby::Event::Mouse.new(kind: "down", button: "left", x: 10, y: 5)) inject_event(RatatuiRuby::Event::Paste.new(content: "Hello"))
- event
-
A
RatatuiRuby::Eventobject.
Source
# File lib/ratatui_ruby/test_helper/event_injection.rb, line 188 def inject_keys(*args) args.each do |arg| event = case arg when String RatatuiRuby::Event::Key.new(code: arg) when Symbol parts = arg.to_s.split("_") code = parts.pop modifiers = parts RatatuiRuby::Event::Key.new(code:, modifiers:) when Hash RatatuiRuby::Event::Key.new(**arg) when RatatuiRuby::Event::Key arg else raise ArgumentError, "Invalid key argument: #{arg.inspect}. Expected String, Symbol, Hash, or Key event." end inject_event(event) end end
Injects one or more key events.
Accepts multiple formats for convenience:
-
String: Character key (e.g.,
"a","q") -
Symbol: Named key or modifier combo (e.g.,
:enter,:ctrl_c) -
Hash: Passed to
Key.new -
Key: Passed directly
Examples
inject_keys("a", "b", "c") inject_keys(:enter, :esc) inject_keys(:ctrl_c, :alt_shift_left) inject_keys("j", { code: "k", modifiers: ["ctrl"] })
Source
# File lib/ratatui_ruby/test_helper/event_injection.rb, line 124 def inject_mouse(x:, y:, kind: :down, modifiers: [], button: :left) event = RatatuiRuby::Event::Mouse.new( kind: kind.to_s, x:, y:, button: button.to_s, modifiers: ) inject_event(event) end
Injects a mouse event.
Example
inject_mouse(x: 10, y: 5, kind: :down, button: :left)
- x
-
Integer x-coordinate.
- y
-
Integer y-coordinate.
- kind
-
Symbol
:down,:up, or:drag. - button
-
Symbol
:left,:right, or:middle. - modifiers
-
Array of modifier strings.
Source
# File lib/ratatui_ruby/test_helper/event_injection.rb, line 151 def inject_right_click(x:, y:, modifiers: []) inject_mouse(x:, y:, kind: :down, modifiers:, button: :right) end
Source
# File lib/ratatui_ruby/test_helper/event_injection.rb, line 236 def inject_sync inject_event(RatatuiRuby::Event::Sync.new) end
Injects a Sync event.
When a runtime (Tea, Kit) encounters this event, it should wait for all pending async operations to complete before processing the next event. This enables deterministic testing of async behavior.
Important: Sync waits for commands to complete. Do not use it with long-running commands that wait indefinitely (e.g., for cancellation). Those commands will block forever, causing a timeout. For cancellation tests, dispatch the cancel command without Sync.
Example
inject_key("s") # Triggers async command inject_sync # Wait for command to complete inject_key(:q) # Quit after seeing results