test(tui): enhance TDD regression test for #11039
CI / load-versions (pull_request) Successful in 8s
CI / push-validation (pull_request) Successful in 10s
CI / helm (pull_request) Successful in 44s
CI / lint (pull_request) Successful in 3m33s
CI / typecheck (pull_request) Successful in 3m58s
CI / quality (pull_request) Successful in 4m15s
CI / security (pull_request) Successful in 4m27s
CI / build (pull_request) Successful in 6m15s
CI / unit_tests (pull_request) Successful in 9m18s
CI / docker (pull_request) Successful in 1m10s
CI / integration_tests (pull_request) Successful in 14m39s
CI / coverage (pull_request) Successful in 10m33s
CI / status-check (pull_request) Successful in 1s

- Verify inherited Widget._render() returns non-None via MRO traversal
- Actually invoke _refresh_display() and verify correct overlay content

Refs: #11039
This commit is contained in:
2026-05-15 11:18:04 +00:00
committed by CleverAgents Bot
parent 84e35cb71d
commit 93f987a73c
2 changed files with 54 additions and 0 deletions
+52
View File
@@ -532,3 +532,55 @@ def step_overlay_refresh_display_callable(context: object) -> None:
)
refresh = context._overlay._refresh_display
assert callable(refresh), "_refresh_display must be callable"
@then("the inherited Widget._render should return a proper renderable")
def step_inherited_render_returns_renderable(context: object) -> None:
"""Verify the inherited ``Widget._render()`` returns a non-None renderable.
Bug #11039: ``ActorSelectionOverlay`` defined its own ``_render() -> None``
which returned ``None``, causing Textual's layout engine to crash. The
fix renamed it to ``_refresh_display()``. This assertion confirms that
when Textual IS available, calling the real inherited ``_render()``
produces a proper renderable (not ``None``). When Textual is not
available (``_FallbackStatic`` has no ``_render``), the check passes
trivially since the fallback case cannot trigger the shadowing crash.
"""
from cleveragents.tui.widgets.actor_selection_overlay import (
ActorSelectionOverlay,
)
cls = ActorSelectionOverlay
overlay = context._overlay
render_from_mro = None
for base in cls.__mro__[1:]:
if "_render" in base.__dict__:
render_from_mro = base.__dict__["_render"]
break
if render_from_mro is None:
return
result = render_from_mro(overlay)
assert result is not None, (
"Bug #11039 regression: inherited Widget._render() returned None. "
"ActorSelectionOverlay may still be shadowing the base-class "
"_render method, which would cause a NoneType crash during "
"Textual layout in textual >=1.0."
)
@then("_refresh_display should produce correct overlay content")
def step_refresh_display_produces_content(context: object) -> None:
"""Invoke ``_refresh_display()`` and verify it renders correct content."""
from typing import cast
overlay = context._overlay
overlay._refresh_display()
content: str = cast(str, overlay._text)
assert content, "_refresh_display must produce non-empty rendered overlay content"
assert "Welcome to CleverAgents" in content, (
"_refresh_display content must include the welcome header"
)
+2
View File
@@ -206,9 +206,11 @@ Feature: TUI first-run experience with actor selection overlay
Scenario: ActorSelectionOverlay does not define its own _render method
Given a new ActorSelectionOverlay
Then the overlay should not override Textual Widget._render
And the inherited Widget._render should return a proper renderable
@tdd_issue @tdd_issue_11039
Scenario: ActorSelectionOverlay has refresh_display callable instead of render
Given a new ActorSelectionOverlay
When I call show on the overlay
Then the overlay _refresh_display method should be callable
And _refresh_display should produce correct overlay content