Module: Plushie::Test::EventDecoder

Defined in:
lib/plushie/test/event_decoder.rb

Overview

Simplified event decoder for test context.

Converts raw wire event hashes (from interact_response / interact_step) into Ruby Event structs. Handles the subset of event families commonly seen in tests. Returns nil for unrecognized families.

For production decoding, use Plushie::Protocol::Decode.decode_event. This module exists as a lighter-weight alternative that test helpers can use without pulling in the full protocol layer.

Examples:

Decoding a widget click event

raw = {"family" => "click", "id" => "form/save", "value" => nil}
event = Plushie::Test::EventDecoder.decode(raw)
event.class #=> Plushie::Event::Widget
event.id    #=> "save"
event.scope #=> ["form"]

Class Method Summary collapse

Class Method Details

.decode(raw) ⇒ Event::Widget, ...

Decode a raw wire event hash into an Event struct.

Parameters:

  • raw (Hash)

    wire event with string keys

Returns:



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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
# File 'lib/plushie/test/event_decoder.rb', line 28

def decode(raw)
  return nil unless raw.is_a?(Hash)

  family = raw["family"]
  data = raw["data"] || {}

  case family

  # Widget interactions (the most common in tests)
  when "click", "input", "submit", "toggle", "select", "slide", "slide_release",
    "canvas_element_enter", "canvas_element_leave", "canvas_element_click",
    "canvas_element_drag", "canvas_element_drag_end", "canvas_element_focused",
    "canvas_element_blurred", "canvas_focused", "canvas_blurred",
    "canvas_group_focused", "canvas_group_blurred"
    id, scope = split_scoped_id(raw["id"])
    Event::Widget.new(
      type: family.to_sym, id: id,
      value: raw["value"], scope: scope, data: raw["data"]
    )

  # Key events
  when "key_press"
    kd = data.empty? ? raw : data
    Event::Key.new(
      type: :press,
      key: Protocol::Keys.parse_key(kd["key"]),
      modifiers: parse_modifiers(raw["modifiers"] || kd["modifiers"] || {}),
      text: kd["text"],
      repeat: kd["repeat"] || false
    )

  when "key_release"
    kd = data.empty? ? raw : data
    Event::Key.new(
      type: :release,
      key: Protocol::Keys.parse_key(kd["key"]),
      modifiers: parse_modifiers(raw["modifiers"] || kd["modifiers"] || {}),
      text: nil,
      repeat: false
    )

  # Mouse subscription events
  when "cursor_moved"
    Event::Mouse.new(type: :moved, x: data["x"], y: data["y"])

  when "button_pressed"
    Event::Mouse.new(
      type: :button_pressed,
      button: Protocol::Parsers.parse_mouse_button(raw["value"])
    )

  when "button_released"
    Event::Mouse.new(
      type: :button_released,
      button: Protocol::Parsers.parse_mouse_button(raw["value"])
    )

  else
    # Unrecognized family
    nil
  end
end

.parse_modifiers(mods) ⇒ Hash

Parse a modifiers hash.

Parameters:

  • mods (Hash, nil)

Returns:

  • (Hash)


106
107
108
109
110
111
112
113
114
115
# File 'lib/plushie/test/event_decoder.rb', line 106

def parse_modifiers(mods)
  return {shift: false, ctrl: false, alt: false, logo: false, command: false}.freeze if mods.nil? || mods.empty?
  {
    shift: mods["shift"] || false,
    ctrl: mods["ctrl"] || false,
    alt: mods["alt"] || false,
    logo: mods["logo"] || false,
    command: mods["command"] || false
  }.freeze
end

.split_scoped_id(full_id) ⇒ Array(String, Array<String>)

Split a scoped wire ID (same logic as Protocol::Decode).

Parameters:

  • full_id (String, nil)

Returns:

  • (Array(String, Array<String>))


95
96
97
98
99
100
# File 'lib/plushie/test/event_decoder.rb', line 95

def split_scoped_id(full_id)
  return [full_id.to_s, []] unless full_id&.include?("/")
  parts = full_id.split("/")
  id = parts.pop
  [id, parts.reverse]
end