Module: ActionMCP::TestHelper::ProgressNotificationAssertions

Included in:
ActionMCP::TestHelper
Defined in:
lib/action_mcp/test_helper/progress_notification_assertions.rb

Instance Method Summary collapse

Instance Method Details

#assert_no_progress_notification_sent(token, message = nil) ⇒ Object

Assert that no progress notifications were sent with the given token



14
15
16
17
18
# File 'lib/action_mcp/test_helper/progress_notification_assertions.rb', line 14

def assert_no_progress_notification_sent(token, message = nil)
  notifications = get_progress_notifications(token)
  assert notifications.empty?,
         message || "Expected no progress notifications with token #{token}, but #{notifications.size} were sent"
end

#assert_progress_notification_count(token, expected_count, message = nil) ⇒ Object

Assert the total count of progress notifications for a token



43
44
45
46
47
48
49
# File 'lib/action_mcp/test_helper/progress_notification_assertions.rb', line 43

def assert_progress_notification_count(token, expected_count, message = nil)
  notifications = get_progress_notifications(token)
  actual_count = notifications.size

  assert_equal expected_count, actual_count,
               message || "Expected #{expected_count} progress notifications for token #{token}, but got #{actual_count}"
end

#assert_progress_notification_includes(token, expected, message = nil) ⇒ Object

Assert specific fields in the latest progress notification



30
31
32
33
34
35
36
37
38
39
40
# File 'lib/action_mcp/test_helper/progress_notification_assertions.rb', line 30

def assert_progress_notification_includes(token, expected, message = nil)
  notifications = get_progress_notifications(token)
  assert notifications.any?, "No progress notifications found for token #{token}"

  notification = notifications.last
  expected.each do |key, value|
    actual = notification.params[key]
    assert_equal value, actual,
                 message || "Expected notification to have #{key}: #{value.inspect}, but got: #{actual.inspect}"
  end
end

#assert_progress_notification_sent(token, message = nil) ⇒ Object

Assert that at least one progress notification was sent with the given token



7
8
9
10
11
# File 'lib/action_mcp/test_helper/progress_notification_assertions.rb', line 7

def assert_progress_notification_sent(token, message = nil)
  notifications = get_progress_notifications(token)
  assert notifications.any?,
         message || "Expected at least one progress notification with token #{token}, but none were sent"
end

#assert_progress_notification_valid(notification, message = nil) ⇒ Object

Assert notification follows MCP spec structure



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
# File 'lib/action_mcp/test_helper/progress_notification_assertions.rb', line 52

def assert_progress_notification_valid(notification, message = nil)
  # Convert to hash if it's a notification object
  data = notification.respond_to?(:to_h) ? notification.to_h : notification

  # Verify JSON-RPC structure
  assert_equal "2.0", data["jsonrpc"] || data[:jsonrpc],
               message || "Notification must have jsonrpc: 2.0"
  assert_equal "notifications/progress", data[:method],
               message || "Notification method must be notifications/progress"
  assert_nil data[:id],
             message || "Notifications must not have an id field"

  # Verify params
  params = data[:params]
  assert params, "Notification must have params"
  assert params[:progressToken], "Notification must have progressToken"
  assert params[:progress], "Notification must have progress value"

  # Type checks
  assert [ String, Integer ].include?(params[:progressToken].class),
         "progressToken must be string or integer"
  assert params[:progress].is_a?(Numeric),
         "progress must be numeric"

  # Optional field type checks if present
  if params.key?(:total)
    assert params[:total].is_a?(Numeric),
           "total must be numeric when present"
  end

  return unless params.key?(:message)

  assert params[:message].is_a?(String),
         "message must be string when present"
end

#assert_progress_sequence_valid(token, message = nil) ⇒ Object

Assert that progress values increase monotonically



21
22
23
24
25
26
27
# File 'lib/action_mcp/test_helper/progress_notification_assertions.rb', line 21

def assert_progress_sequence_valid(token, message = nil)
  notifications = get_progress_notifications(token)
  progress_values = notifications.map { |n| n.params[:progress] }

  assert progress_values.each_cons(2).all? { |a, b| b > a },
         message || "Progress values must increase monotonically, but got: #{progress_values.inspect}"
end

#progress_session_storeObject

Get the current session store (with helpful error if not using test store)



89
90
91
92
93
94
95
96
# File 'lib/action_mcp/test_helper/progress_notification_assertions.rb', line 89

def progress_session_store
  store = ActionMCP::Server.session_store
  unless store.respond_to?(:notifications_for_token)
    raise "Session store #{store.class} does not support notification tracking. " \
          "Use TestSessionStore for progress notification tests."
  end
  store
end