31472b5413
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 21s
CI / helm (pull_request) Successful in 22s
CI / lint (pull_request) Successful in 3m20s
CI / quality (pull_request) Successful in 3m43s
CI / typecheck (pull_request) Successful in 3m58s
CI / security (pull_request) Successful in 4m8s
CI / integration_tests (pull_request) Successful in 9m33s
CI / unit_tests (pull_request) Successful in 10m12s
CI / docker (pull_request) Successful in 1m28s
CI / coverage (pull_request) Successful in 12m18s
CI / e2e_tests (pull_request) Successful in 19m51s
CI / status-check (pull_request) Successful in 1s
CI / build (push) Successful in 15s
CI / helm (push) Successful in 22s
CI / lint (push) Successful in 3m18s
CI / quality (push) Successful in 3m41s
CI / typecheck (push) Successful in 3m57s
CI / benchmark-regression (push) Has been skipped
CI / security (push) Successful in 4m10s
CI / unit_tests (push) Failing after 6m58s
CI / docker (push) Has been skipped
CI / integration_tests (push) Successful in 9m15s
CI / coverage (push) Successful in 12m26s
CI / e2e_tests (push) Successful in 23m11s
CI / status-check (push) Failing after 1s
CI / benchmark-publish (push) Successful in 28m31s
CI / benchmark-regression (pull_request) Successful in 54m53s
Add Behave feature/step pairs that exercise uncovered branches across handlers, LSP, CLI, and service layers to reach the coverage gate. ISSUES CLOSED: #1232
358 lines
13 KiB
Python
358 lines
13 KiB
Python
"""Step definitions for materializers_coverage_r3.feature.
|
|
|
|
These steps target uncovered lines in materializers.py:
|
|
- Line 344: _BaseBufferStrategy.on_element_closed with final_state=None
|
|
- Line 473: _LiveMaterializationStrategy._render_element base class
|
|
- Lines 486-487: _LiveMaterializationStrategy.on_element_created with initial_state=None
|
|
- Line 495: _LiveMaterializationStrategy.on_element_updated with unknown handle_id
|
|
- Line 497: _LiveMaterializationStrategy.on_element_updated for frozen element
|
|
- Line 509: _LiveMaterializationStrategy.on_element_closed with unknown handle_id
|
|
- Line 550: _LiveMaterializationStrategy._render_frame with empty dirty set
|
|
- Line 610: _AccumulateStrategy.on_element_updated returns immediately
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from unittest.mock import patch
|
|
|
|
from behave import given, then, when
|
|
from behave.runner import Context
|
|
|
|
from cleveragents.cli.output.handles import (
|
|
ElementClosed,
|
|
ElementCreated,
|
|
ElementUpdated,
|
|
Panel,
|
|
StatusMessage,
|
|
)
|
|
from cleveragents.cli.output.materializers import (
|
|
JsonMaterializer,
|
|
PlainMaterializer,
|
|
_LiveMaterializationStrategy,
|
|
)
|
|
|
|
# ===========================================================================
|
|
# Line 344: _BaseBufferStrategy.on_element_closed with final_state=None
|
|
# ===========================================================================
|
|
|
|
|
|
@given("matcov3 a PlainMaterializer instance")
|
|
def step_matcov3_given_plain(context: Context) -> None:
|
|
context.matcov3_plain = PlainMaterializer()
|
|
|
|
|
|
@given('matcov3 the strategy has a registered handle "{handle_id}" at index {idx:d}')
|
|
def step_matcov3_register_handle(context: Context, handle_id: str, idx: int) -> None:
|
|
# Simulate on_element_created so the handle is registered in _index_map
|
|
event = ElementCreated(
|
|
event_type="created",
|
|
handle_id=handle_id,
|
|
element_kind="panel",
|
|
declaration_index=idx,
|
|
initial_state=Panel(title="Placeholder"),
|
|
)
|
|
context.matcov3_plain.on_element_created(event)
|
|
|
|
|
|
@when(
|
|
'matcov3 an ElementClosed event with handle "{handle_id}" and no final state is dispatched'
|
|
)
|
|
def step_matcov3_close_no_final_state(context: Context, handle_id: str) -> None:
|
|
event = ElementClosed(
|
|
event_type="closed",
|
|
handle_id=handle_id,
|
|
element_kind="panel",
|
|
final_state=None, # This triggers the early return on line 344
|
|
)
|
|
try:
|
|
context.matcov3_plain.on_element_closed(event)
|
|
context.matcov3_error = None
|
|
except Exception as exc:
|
|
context.matcov3_error = exc
|
|
|
|
|
|
@then("matcov3 the plain strategy output is empty")
|
|
def step_matcov3_plain_output_empty(context: Context) -> None:
|
|
output = context.matcov3_plain.get_output()
|
|
assert output == "", f"Expected empty output, got {output!r}"
|
|
assert context.matcov3_error is None, f"Unexpected error: {context.matcov3_error}"
|
|
|
|
|
|
# ===========================================================================
|
|
# Line 473: _LiveMaterializationStrategy._render_element base class
|
|
# ===========================================================================
|
|
|
|
|
|
@given("matcov3 a raw LiveMaterializationStrategy instance")
|
|
def step_matcov3_given_live_strategy(context: Context) -> None:
|
|
context.matcov3_live = _LiveMaterializationStrategy()
|
|
|
|
|
|
@given('matcov3 a StatusMessage element with message "{msg}"')
|
|
def step_matcov3_given_status_element(context: Context, msg: str) -> None:
|
|
context.matcov3_status_element = StatusMessage(message=msg, level="info")
|
|
|
|
|
|
@when("matcov3 I call the live base class _render_element")
|
|
def step_matcov3_call_live_render(context: Context) -> None:
|
|
try:
|
|
context.matcov3_live_render_result = context.matcov3_live._render_element(
|
|
context.matcov3_status_element
|
|
)
|
|
context.matcov3_error = None
|
|
except Exception as exc:
|
|
context.matcov3_error = exc
|
|
context.matcov3_live_render_result = ""
|
|
|
|
|
|
@then('matcov3 the rendered text contains "{text}"')
|
|
def step_matcov3_rendered_contains(context: Context, text: str) -> None:
|
|
assert context.matcov3_error is None, f"Unexpected error: {context.matcov3_error}"
|
|
assert text in context.matcov3_live_render_result, (
|
|
f"Expected {text!r} in {context.matcov3_live_render_result!r}"
|
|
)
|
|
|
|
|
|
# ===========================================================================
|
|
# Lines 486-487: _LiveMaterializationStrategy.on_element_created
|
|
# with initial_state=None
|
|
# ===========================================================================
|
|
|
|
|
|
@when(
|
|
"matcov3 an ElementCreated event with no initial state is dispatched to the live strategy"
|
|
)
|
|
def step_matcov3_live_created_no_initial(context: Context) -> None:
|
|
context.matcov3_decl_idx = 3
|
|
event = ElementCreated(
|
|
event_type="created",
|
|
handle_id="hdl-no-initial",
|
|
element_kind="panel",
|
|
declaration_index=context.matcov3_decl_idx,
|
|
initial_state=None, # Triggers lines 486-487
|
|
)
|
|
# Mock time.monotonic so _maybe_render_frame triggers a frame render
|
|
patcher = patch("time.monotonic", return_value=999999.0)
|
|
patcher.start()
|
|
context.add_cleanup(patcher.stop)
|
|
|
|
try:
|
|
context.matcov3_live.on_element_created(event)
|
|
context.matcov3_error = None
|
|
except Exception as exc:
|
|
context.matcov3_error = exc
|
|
|
|
|
|
@then("matcov3 the live strategy has an empty rendered entry at the declaration index")
|
|
def step_matcov3_live_empty_rendered(context: Context) -> None:
|
|
assert context.matcov3_error is None, f"Unexpected error: {context.matcov3_error}"
|
|
idx = context.matcov3_decl_idx
|
|
assert idx in context.matcov3_live._rendered, (
|
|
f"Declaration index {idx} not in _rendered"
|
|
)
|
|
assert context.matcov3_live._rendered[idx] == "", (
|
|
f"Expected empty string at index {idx}, got {context.matcov3_live._rendered[idx]!r}"
|
|
)
|
|
|
|
|
|
@then("matcov3 the live strategy has height zero at the declaration index")
|
|
def step_matcov3_live_zero_height(context: Context) -> None:
|
|
idx = context.matcov3_decl_idx
|
|
assert idx in context.matcov3_live._heights, (
|
|
f"Declaration index {idx} not in _heights"
|
|
)
|
|
assert context.matcov3_live._heights[idx] == 0, (
|
|
f"Expected height 0 at index {idx}, got {context.matcov3_live._heights[idx]}"
|
|
)
|
|
|
|
|
|
# ===========================================================================
|
|
# Line 495: _LiveMaterializationStrategy.on_element_updated
|
|
# with unknown handle_id
|
|
# ===========================================================================
|
|
|
|
|
|
@when(
|
|
'matcov3 an ElementUpdated event for unknown handle "{handle_id}" is dispatched to the live strategy'
|
|
)
|
|
def step_matcov3_live_update_unknown(context: Context, handle_id: str) -> None:
|
|
event = ElementUpdated(
|
|
event_type="updated",
|
|
handle_id=handle_id,
|
|
element_kind="panel",
|
|
update_type="content",
|
|
element_snapshot=StatusMessage(message="ghost update"),
|
|
)
|
|
try:
|
|
context.matcov3_live.on_element_updated(event)
|
|
context.matcov3_error = None
|
|
except Exception as exc:
|
|
context.matcov3_error = exc
|
|
|
|
|
|
@then("matcov3 the live strategy rendered dict is empty")
|
|
def step_matcov3_live_rendered_empty(context: Context) -> None:
|
|
assert context.matcov3_error is None, f"Unexpected error: {context.matcov3_error}"
|
|
assert len(context.matcov3_live._rendered) == 0, (
|
|
f"Expected empty _rendered, got {context.matcov3_live._rendered}"
|
|
)
|
|
|
|
|
|
# ===========================================================================
|
|
# Line 497: _LiveMaterializationStrategy.on_element_updated
|
|
# for a frozen (closed) element
|
|
# ===========================================================================
|
|
|
|
|
|
@given(
|
|
'matcov3 a live element "{handle_id}" is created and then closed at index {idx:d}'
|
|
)
|
|
def step_matcov3_live_create_and_close(
|
|
context: Context, handle_id: str, idx: int
|
|
) -> None:
|
|
context.matcov3_frozen_handle_id = handle_id
|
|
context.matcov3_frozen_idx = idx
|
|
|
|
# Mock time to allow frames to render
|
|
patcher = patch("time.monotonic", return_value=999999.0)
|
|
patcher.start()
|
|
context.add_cleanup(patcher.stop)
|
|
|
|
# Create the element
|
|
create_event = ElementCreated(
|
|
event_type="created",
|
|
handle_id=handle_id,
|
|
element_kind="status",
|
|
declaration_index=idx,
|
|
initial_state=StatusMessage(message="frozen-element"),
|
|
)
|
|
context.matcov3_live.on_element_created(create_event)
|
|
|
|
# Close the element (adds to _closed_indices)
|
|
close_event = ElementClosed(
|
|
event_type="closed",
|
|
handle_id=handle_id,
|
|
element_kind="status",
|
|
final_state=StatusMessage(message="frozen-element-final"),
|
|
)
|
|
context.matcov3_live.on_element_closed(close_event)
|
|
|
|
|
|
@when(
|
|
'matcov3 an ElementUpdated event for handle "{handle_id}" is dispatched to the live strategy'
|
|
)
|
|
def step_matcov3_live_update_frozen(context: Context, handle_id: str) -> None:
|
|
event = ElementUpdated(
|
|
event_type="updated",
|
|
handle_id=handle_id,
|
|
element_kind="status",
|
|
update_type="content",
|
|
element_snapshot=StatusMessage(message="should-be-ignored"),
|
|
)
|
|
try:
|
|
context.matcov3_live.on_element_updated(event)
|
|
context.matcov3_error = None
|
|
except Exception as exc:
|
|
context.matcov3_error = exc
|
|
|
|
|
|
@then("matcov3 no error is raised for the frozen update")
|
|
def step_matcov3_no_error_frozen(context: Context) -> None:
|
|
assert context.matcov3_error is None, f"Unexpected error: {context.matcov3_error}"
|
|
# Verify the update was ignored - rendered content should still be the final state
|
|
idx = context.matcov3_frozen_idx
|
|
rendered = context.matcov3_live._rendered.get(idx, "")
|
|
assert "should-be-ignored" not in rendered, (
|
|
f"Frozen element should not have been updated, but got: {rendered!r}"
|
|
)
|
|
|
|
|
|
# ===========================================================================
|
|
# Line 509: _LiveMaterializationStrategy.on_element_closed
|
|
# with unknown handle_id
|
|
# ===========================================================================
|
|
|
|
|
|
@when(
|
|
'matcov3 an ElementClosed event for unknown handle "{handle_id}" is dispatched to the live strategy'
|
|
)
|
|
def step_matcov3_live_close_unknown(context: Context, handle_id: str) -> None:
|
|
event = ElementClosed(
|
|
event_type="closed",
|
|
handle_id=handle_id,
|
|
element_kind="panel",
|
|
final_state=Panel(title="Ghost Close"),
|
|
)
|
|
try:
|
|
context.matcov3_live.on_element_closed(event)
|
|
context.matcov3_error = None
|
|
except Exception as exc:
|
|
context.matcov3_error = exc
|
|
|
|
|
|
@then("matcov3 the live strategy closed indices set is empty")
|
|
def step_matcov3_live_closed_indices_empty(context: Context) -> None:
|
|
assert context.matcov3_error is None, f"Unexpected error: {context.matcov3_error}"
|
|
assert len(context.matcov3_live._closed_indices) == 0, (
|
|
f"Expected empty _closed_indices, got {context.matcov3_live._closed_indices}"
|
|
)
|
|
|
|
|
|
# ===========================================================================
|
|
# Line 550: _LiveMaterializationStrategy._render_frame with empty dirty set
|
|
# ===========================================================================
|
|
|
|
|
|
@when("matcov3 I call _render_frame on the live strategy with an empty dirty set")
|
|
def step_matcov3_live_render_frame_empty_dirty(context: Context) -> None:
|
|
# Ensure dirty set is empty (it is by default on a fresh instance)
|
|
assert len(context.matcov3_live._dirty) == 0, (
|
|
f"Expected empty dirty set, got {context.matcov3_live._dirty}"
|
|
)
|
|
try:
|
|
# _render_frame expects caller to hold the lock
|
|
with context.matcov3_live._lock:
|
|
context.matcov3_live._render_frame()
|
|
context.matcov3_error = None
|
|
except Exception as exc:
|
|
context.matcov3_error = exc
|
|
|
|
|
|
@then("matcov3 the live strategy stream is still empty")
|
|
def step_matcov3_live_stream_empty(context: Context) -> None:
|
|
assert context.matcov3_error is None, f"Unexpected error: {context.matcov3_error}"
|
|
output = context.matcov3_live.get_output()
|
|
assert output == "", f"Expected empty stream output, got {output!r}"
|
|
|
|
|
|
# ===========================================================================
|
|
# Line 610: _AccumulateStrategy.on_element_updated returns immediately
|
|
# ===========================================================================
|
|
|
|
|
|
@given("matcov3 a JsonMaterializer instance")
|
|
def step_matcov3_given_json_materializer(context: Context) -> None:
|
|
context.matcov3_json = JsonMaterializer()
|
|
|
|
|
|
@when("matcov3 an ElementUpdated event is dispatched to the accumulate strategy")
|
|
def step_matcov3_accum_update(context: Context) -> None:
|
|
event = ElementUpdated(
|
|
event_type="updated",
|
|
handle_id="hdl-accum-test",
|
|
element_kind="status",
|
|
update_type="content",
|
|
element_snapshot=StatusMessage(message="accum update ignored"),
|
|
)
|
|
try:
|
|
result = context.matcov3_json.on_element_updated(event)
|
|
context.matcov3_accum_result = result
|
|
context.matcov3_error = None
|
|
except Exception as exc:
|
|
context.matcov3_error = exc
|
|
|
|
|
|
@then("matcov3 no error is raised for the accumulate update")
|
|
def step_matcov3_no_error_accum(context: Context) -> None:
|
|
assert context.matcov3_error is None, f"Unexpected error: {context.matcov3_error}"
|