test(messaging): behavioral tests for broadcast_message and talk_to_user (#1156) #146
Reference in New Issue
Block a user
Delete Branch "fix/1156-messaging-behavioral-tests"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Behavioral test coverage for
molecule_runtime/a2a_tools_messaging.py(regression coverage formolecule-core#1156)What
Adds
tests/test_a2a_tools_messaging.py— pytest +monkeypatchbehavioral tests for the messaging tool surface. Closes the test gap that let the regressions referenced bymolecule-core#1156ship without pinning the correct failure shape. No real network calls (matches the stubbed-httpxpattern in the existingtest_a2a_message_send_contract.py).Coverage
tool_broadcast_messagetest_broadcast_message_success_returns_delivered_count— 200 →"Broadcast sent to N workspace(s)".test_broadcast_message_403_returns_ability_disabled_error— 403 with hint →"Error: broadcast ability not enabled. <hint>".test_broadcast_message_403_without_hint_still_returns_canonical_error— 403 with no hint → no trailing space.test_broadcast_message_empty_returns_required_error—""andNoneshort-circuit to"Error: message is required"AND fire zero HTTP requests.tool_send_message_to_user(the "talk to user" surface)test_send_message_to_user_upload_failure_short_circuits_no_notify— when_upload_chat_filesreturns an error, the tool surfaces it AND does not fire/notify(the partial-attach chip regression).test_send_message_to_user_platform_error_on_notify— upload OK, platform 500 →"Error: platform returned 500"; the notify payload must carry the upload's attachments so the call was reached (not short-circuited) before being rejected._upload_chat_filestest_upload_chat_files_oserror_on_read—OSErroron the file read short-circuits to([], "Error reading ..."); no HTTP client touched.test_upload_chat_files_invalid_response_non_json— 200 with non-JSON body →([], "Error parsing upload response ...").test_upload_chat_files_invalid_response_shape_mismatch— 200 withfilesarray length != request count →([], "Error: upload returned N entries for M files").test_upload_chat_files_success_returns_metadata— happy path round-trips the platform's metadata array andNoneerror.test_upload_chat_files_empty_paths_returns_empty_no_http— no paths → no client constructed, no HTTP call.Style
monkeypatch.setattr(m.httpx, "AsyncClient", ...)for the HTTP stub (mirrors the existing test).asyncio.run(...)for async tests (the project deliberately does not depend onpytest-asyncio).stub_resolvefixture stubs_resolve_workspace_id,_resolve_platform_url,_auth_headers_for_heartbeatto deterministic values so the URL on the wire is predictable and the assertions match the exact path.Test result
References
molecule-core#1156tests/test_a2a_message_send_contract.py(the canonical contract-test pattern in this repo)🤖 Generated with Claude Code
Adds tests/test_a2a_tools_messaging.py with regression coverage for molecule-core#1156 across the three failure surfaces in molecule_runtime/a2a_tools_messaging.py: * tool_broadcast_message — success path returns delivered count, 403 surfaces broadcast-ability-disabled error with hint, empty message short-circuits without firing HTTP. * tool_send_message_to_user (a.k.a. 'talk to user') — upload failure surfaces the upload error and does NOT fire /notify; platform error on /notify surfaces the status code. * _upload_chat_files — OSError on read short-circuits before HTTP; non-JSON 200 response surfaces a parse error; shape-mismatch (file count != request count) surfaces a count error; happy path returns the platform's metadata array; empty paths is a no-op (no HTTP client constructed). All tests use pytest + monkeypatch; no real network calls. Matches the existing style in test_a2a_message_send_contract.py.APPROVED. Five-axis review complete.
Correctness/robustness: the new behavioral tests cover the broadcast success/403/empty-message paths, send_message_to_user upload-failure short-circuit and notify error path, and _upload_chat_files read/upload/parse/shape/success/no-op cases. The assertions line up with the current implementation contract and use monkeypatched httpx, so no real network calls are made.
Security: no secret/auth weakening; auth headers are stubbed only inside tests. Performance: tests are bounded, in-memory, and avoid network/sleeping. Readability: the fake response/client helpers are straightforward and scoped to the test module. No blockers found.
APPROVED
5-axis review:
a2a_tools_messaging.pycontracts.Verification:
python -m pytest -q tests/test_a2a_tools_messaging.pypassed locally (11 passed).