195fbac109
CI / lint (pull_request) Successful in 40s
CI / helm (pull_request) Successful in 38s
CI / build (pull_request) Successful in 48s
CI / quality (pull_request) Successful in 1m0s
CI / typecheck (pull_request) Successful in 1m29s
CI / security (pull_request) Successful in 1m28s
CI / push-validation (pull_request) Successful in 20s
CI / unit_tests (pull_request) Successful in 5m8s
CI / docker (pull_request) Successful in 1m27s
CI / integration_tests (pull_request) Successful in 8m39s
CI / coverage (pull_request) Successful in 11m1s
CI / status-check (pull_request) Successful in 3s
Add domain-scenario Gherkin tags to all A2A, session, and CLI feature files (30 files) so tests can be filtered individually via behave. - 8 A2A feature files: @a2a tag - 7 session feature files: @session tag - 15 CLI feature files: @cli tag ISSUES CLOSED: #9124
135 lines
6.7 KiB
Gherkin
135 lines
6.7 KiB
Gherkin
@a2a
|
||
@mock_only
|
||
Feature: A2A events module uncovered-line coverage (round 3)
|
||
As a CleverAgents developer
|
||
I want complete coverage of the A2aEventQueue, EventBusBridge, and related code
|
||
So that all error paths and edge-case branches in events.py are exercised
|
||
|
||
# -----------------------------------------------------------------------
|
||
# A2aEventQueue.publish – non-A2aEvent argument (line 63)
|
||
# -----------------------------------------------------------------------
|
||
|
||
Scenario: Publishing a non-A2aEvent raises TypeError
|
||
Given aecov3 a fresh A2aEventQueue
|
||
When aecov3 I publish a plain dict instead of an A2aEvent
|
||
Then aecov3 a TypeError should be stored with message "event must be an A2aEvent instance"
|
||
|
||
# -----------------------------------------------------------------------
|
||
# A2aEventQueue.publish – subscriber callback raises (lines 73-76)
|
||
# -----------------------------------------------------------------------
|
||
|
||
Scenario: A failing subscriber callback is caught and logged
|
||
Given aecov3 a fresh A2aEventQueue
|
||
And aecov3 a subscriber callback that raises RuntimeError
|
||
When aecov3 I publish a valid A2aEvent
|
||
Then aecov3 no error should be stored
|
||
And aecov3 the event should be in the queue
|
||
|
||
# -----------------------------------------------------------------------
|
||
# A2aEventQueue.subscribe_local – non-callable (line 82)
|
||
# -----------------------------------------------------------------------
|
||
|
||
Scenario: Subscribing with a non-callable raises TypeError
|
||
Given aecov3 a fresh A2aEventQueue
|
||
When aecov3 I subscribe with a non-callable value
|
||
Then aecov3 a TypeError should be stored with message "callback must be callable"
|
||
|
||
# -----------------------------------------------------------------------
|
||
# A2aEventQueue.unsubscribe – bad subscription_id (line 91)
|
||
# -----------------------------------------------------------------------
|
||
|
||
Scenario: Unsubscribing with an empty string raises ValueError
|
||
Given aecov3 a fresh A2aEventQueue
|
||
When aecov3 I unsubscribe with an empty string
|
||
Then aecov3 a ValueError should be stored with message "subscription_id must be a non-empty string"
|
||
|
||
Scenario: Unsubscribing with a non-string raises ValueError
|
||
Given aecov3 a fresh A2aEventQueue
|
||
When aecov3 I unsubscribe with a non-string value
|
||
Then aecov3 a ValueError should be stored with message "subscription_id must be a non-empty string"
|
||
|
||
# -----------------------------------------------------------------------
|
||
# A2aEventQueue.get_events – bad limit (line 100)
|
||
# -----------------------------------------------------------------------
|
||
|
||
Scenario: Getting events with limit zero raises ValueError
|
||
Given aecov3 a fresh A2aEventQueue
|
||
When aecov3 I call get_events with limit 0
|
||
Then aecov3 a ValueError should be stored with message "limit must be a positive integer"
|
||
|
||
Scenario: Getting events with a non-integer limit raises ValueError
|
||
Given aecov3 a fresh A2aEventQueue
|
||
When aecov3 I call get_events with a string limit
|
||
Then aecov3 a ValueError should be stored with message "limit must be a positive integer"
|
||
|
||
# -----------------------------------------------------------------------
|
||
# A2aEventQueue.subscribe_remote – bad endpoint (line 126)
|
||
# -----------------------------------------------------------------------
|
||
|
||
Scenario: Remote subscribe with an empty endpoint raises ValueError
|
||
Given aecov3 a fresh A2aEventQueue
|
||
When aecov3 I call subscribe_remote with an empty endpoint
|
||
Then aecov3 a ValueError should be stored with message "endpoint must be a non-empty string"
|
||
|
||
Scenario: Remote subscribe with a non-string endpoint raises ValueError
|
||
Given aecov3 a fresh A2aEventQueue
|
||
When aecov3 I call subscribe_remote with a non-string endpoint
|
||
Then aecov3 a ValueError should be stored with message "endpoint must be a non-empty string"
|
||
|
||
# -----------------------------------------------------------------------
|
||
# EventBusBridge.stop – disposes subscription (lines 234-238)
|
||
# -----------------------------------------------------------------------
|
||
|
||
Scenario: Stopping the bridge disposes the subscription
|
||
Given aecov3 a fresh A2aEventQueue
|
||
And aecov3 a mock EventBus that returns a disposable subscription
|
||
And aecov3 an EventBusBridge connecting the bus and queue
|
||
When aecov3 the bridge is started
|
||
And aecov3 the bridge is stopped
|
||
Then aecov3 the subscription dispose should have been called
|
||
And aecov3 the bridge subscription should be None
|
||
|
||
Scenario: Stopping the bridge without dispose attribute still clears subscription
|
||
Given aecov3 a fresh A2aEventQueue
|
||
And aecov3 a mock EventBus that returns a non-disposable subscription
|
||
And aecov3 an EventBusBridge connecting the bus and queue
|
||
When aecov3 the bridge is started
|
||
And aecov3 the bridge is stopped
|
||
Then aecov3 the bridge subscription should be None
|
||
|
||
# -----------------------------------------------------------------------
|
||
# EventBusBridge._on_domain_event – event_type is None (line 244)
|
||
# -----------------------------------------------------------------------
|
||
|
||
Scenario: Bridge ignores domain event with no event_type attribute
|
||
Given aecov3 a fresh A2aEventQueue
|
||
And aecov3 a mock EventBus that captures the callback
|
||
And aecov3 an EventBusBridge connecting the bus and queue
|
||
When aecov3 the bridge is started
|
||
And aecov3 the bridge receives a domain event without event_type
|
||
Then aecov3 the queue should be empty
|
||
|
||
# -----------------------------------------------------------------------
|
||
# EventBusBridge._on_domain_event – str fallback (line 250)
|
||
# -----------------------------------------------------------------------
|
||
|
||
Scenario: Bridge converts a plain string event_type without .value
|
||
Given aecov3 a fresh A2aEventQueue
|
||
And aecov3 a mock EventBus that captures the callback
|
||
And aecov3 an EventBusBridge connecting the bus and queue
|
||
When aecov3 the bridge is started
|
||
And aecov3 the bridge receives a domain event with string event_type "PLAN_CREATED"
|
||
Then aecov3 the queue should contain a TaskStatusUpdateEvent
|
||
|
||
# -----------------------------------------------------------------------
|
||
# EventBusBridge._on_domain_event – unknown type (line 258)
|
||
# -----------------------------------------------------------------------
|
||
|
||
Scenario: Bridge passes through an unknown domain event type as-is
|
||
Given aecov3 a fresh A2aEventQueue
|
||
And aecov3 a mock EventBus that captures the callback
|
||
And aecov3 an EventBusBridge connecting the bus and queue
|
||
When aecov3 the bridge is started
|
||
And aecov3 the bridge receives a domain event with string event_type "SOME_CUSTOM_EVENT"
|
||
Then aecov3 the queue should contain an event with type "SOME_CUSTOM_EVENT"
|