Module: RatatuiRuby::TestHelper::EventInjection
- Included in:
- RatatuiRuby::TestHelper
- Defined in:
- lib/ratatui_ruby/test_helper/event_injection.rb
Overview
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
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
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
– SPDX-SnippetEnd ++
Instance Method Summary collapse
-
#inject_click(x:, y:, modifiers: []) ⇒ Object
Injects a left mouse click.
-
#inject_drag(x:, y:, modifiers: [], button: :left) ⇒ Object
Injects a mouse drag event.
-
#inject_event(event) ⇒ Object
Injects an event into the test terminal’s event queue.
-
#inject_keys(*args) ⇒ Object
(also: #inject_key)
Injects one or more key events.
-
#inject_mouse(x:, y:, kind: :down, modifiers: [], button: :left) ⇒ Object
Injects a mouse event.
-
#inject_right_click(x:, y:, modifiers: []) ⇒ Object
Injects a right mouse click.
-
#inject_sync ⇒ Object
Injects a Sync event.
Instance Method Details
#inject_click(x:, y:, modifiers: []) ⇒ Object
Injects a left mouse click.
Example
inject_click(x: 10, y: 5)
144 145 146 |
# File 'lib/ratatui_ruby/test_helper/event_injection.rb', line 144 def inject_click(x:, y:, modifiers: []) inject_mouse(x:, y:, kind: :down, modifiers:, button: :left) end |
#inject_drag(x:, y:, modifiers: [], button: :left) ⇒ Object
Injects a mouse drag event.
Example
inject_drag(x: 10, y: 5)
164 165 166 |
# File 'lib/ratatui_ruby/test_helper/event_injection.rb', line 164 def inject_drag(x:, y:, modifiers: [], button: :left) inject_mouse(x:, y:, kind: :drag, modifiers:, button:) end |
#inject_event(event) ⇒ Object
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
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
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"))
inject_event(RatatuiRuby::Event::None.new) # idle frame
– SPDX-SnippetEnd ++
- event
-
A
RatatuiRuby::Eventobject.
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/ratatui_ruby/test_helper/event_injection.rb', line 66 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., 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 when RatatuiRuby::Event::None RatatuiRuby.inject_test_event("none", {}) else raise ArgumentError, "Unknown event type: #{event.class}" end end |
#inject_keys(*args) ⇒ Object Also known as: inject_key
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
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
inject_keys("a", "b", "c")
inject_keys(:enter, :esc)
inject_keys(:ctrl_c, :alt_shift_left)
inject_keys("j", { code: "k", modifiers: ["ctrl"] })
– SPDX-SnippetEnd ++
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'lib/ratatui_ruby/test_helper/event_injection.rb', line 191 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 |
#inject_mouse(x:, y:, kind: :down, modifiers: [], button: :left) ⇒ Object
Injects a mouse event.
Example
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
inject_mouse(x: 10, y: 5, kind: :down, button: :left)
– SPDX-SnippetEnd ++
- 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.
127 128 129 130 131 132 133 134 135 136 |
# File 'lib/ratatui_ruby/test_helper/event_injection.rb', line 127 def inject_mouse(x:, y:, kind: :down, modifiers: [], button: :left) event = RatatuiRuby::Event::Mouse.new( kind: kind.to_s, x:, y:, button: .to_s, modifiers: ) inject_event(event) end |
#inject_right_click(x:, y:, modifiers: []) ⇒ Object
Injects a right mouse click.
Example
inject_right_click(x: 10, y: 5)
154 155 156 |
# File 'lib/ratatui_ruby/test_helper/event_injection.rb', line 154 def inject_right_click(x:, y:, modifiers: []) inject_mouse(x:, y:, kind: :down, modifiers:, button: :right) end |
#inject_sync ⇒ Object
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
– SPDX-SnippetBegin SPDX-FileCopyrightText: 2026 Kerrick Long SPDX-License-Identifier: MIT-0 ++
inject_key("s") # Triggers async command
inject_sync # Wait for command to complete
inject_key(:q) # Quit after seeing results
– SPDX-SnippetEnd ++
239 240 241 |
# File 'lib/ratatui_ruby/test_helper/event_injection.rb', line 239 def inject_sync inject_event(RatatuiRuby::Event::Sync.new) end |