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

Instance Method Details

#inject_click(x:, y:, modifiers: []) ⇒ Object

Injects a left mouse click.

Example

inject_click(x: 10, y: 5)


141
142
143
# 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

#inject_drag(x:, y:, modifiers: [], button: :left) ⇒ Object

Injects a mouse drag event.

Example

inject_drag(x: 10, y: 5)


161
162
163
# 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

#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"))

– SPDX-SnippetEnd ++

event

A RatatuiRuby::Event object.



65
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
# 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

#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 ++



188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
# 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

#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.



124
125
126
127
128
129
130
131
132
133
# 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

#inject_right_click(x:, y:, modifiers: []) ⇒ Object

Injects a right mouse click.

Example

inject_right_click(x: 10, y: 5)


151
152
153
# 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

#inject_syncObject

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 ++



236
237
238
# File 'lib/ratatui_ruby/test_helper/event_injection.rb', line 236

def inject_sync
  inject_event(RatatuiRuby::Event::Sync.new)
end