Files
cleveragents-core/features/tui_permission_question_widget.feature
HAL9000 0799369407 fix(tui): render inline diffs in PermissionQuestionWidget
Enabled inline diff rendering by default in PermissionQuestionWidget when diffs are available.

Added a public show_diff property with getter and setter to control diff visibility, and updated refresh to honor this property.

Extended Behave feature scenarios to cover default diff rendering, visibility toggling, and no-diff behavior.

Introduced supporting step definitions for toggling show_diff and asserting absence of diff text.

ISSUES CLOSED: #8303
2026-04-23 23:01:46 +00:00

181 lines
9.9 KiB
Gherkin

Feature: Permission Question Widget
As a TUI user
I want an inline permission question widget
So that I can allow or reject single-file operations without leaving the conversation stream
Background:
Given the permission question widget module is imported
# ── Domain model ──────────────────────────────────────────────────────────
Scenario: Create InlinePermissionQuestion with file path and type
When I create an InlinePermissionQuestion for "src/auth/handler.py" with type "file_write"
Then the question file path should be "src/auth/handler.py"
And the question request type should be "file_write"
And the question has_diff should be False
Scenario: InlinePermissionQuestion with diff content
Given an InlinePermissionQuestion for "src/main.py" with type "file_write" and diff "@@ -1,3 +1,4 @@\n+import os"
Then the question has_diff should be True
Scenario: InlinePermissionQuestion description_line for file_write
When I create an InlinePermissionQuestion for "src/auth/handler.py" with type "file_write"
Then the description line should contain "write to"
Scenario: InlinePermissionQuestion description_line for file_delete
When I create an InlinePermissionQuestion for "src/old.py" with type "file_delete"
Then the description line should contain "delete"
Scenario: InlinePermissionQuestion description_line for shell_exec
When I create an InlinePermissionQuestion for "make test" with type "shell_exec"
Then the description line should contain "execute"
# ── Widget creation ───────────────────────────────────────────────────────
Scenario: Widget creation renders permission request
When I create a PermissionQuestionWidget for "src/auth/handler.py" with type "file_write"
Then the widget text should contain "Permission Required"
And the widget text should contain "src/auth/handler.py"
And the widget text should contain "Allow once"
And the widget text should contain "Reject once"
Scenario: Widget creation shows diff hint when no diff
When I create a PermissionQuestionWidget for "src/auth/handler.py" with type "file_write"
Then the widget text should contain "PermissionsScreen"
Scenario: Widget creation with diff content shows diff hint
Given a PermissionQuestionWidget for "src/main.py" with type "file_write" and diff "@@ -1 +1 @@\n+x=1"
Then the widget text should contain "PermissionsScreen"
Scenario: Widget creation with diff content renders diff by default
Given a PermissionQuestionWidget for "src/main.py" with type "file_write" and diff "@@ -1 +1 @@\n+x=1"
Then the widget text should contain " diff "
And the widget text should contain "+x=1"
And the widget show_diff property should be True
Scenario: Widget diff visibility can be toggled off
Given a PermissionQuestionWidget for "src/main.py" with type "file_write" and diff "@@ -1 +1 @@\n+x=1"
When I set the widget show_diff flag to False
Then the widget text should not contain " diff "
And the widget show_diff property should be False
Scenario: Widget diff visibility can be toggled on after hiding
Given a PermissionQuestionWidget for "src/main.py" with type "file_write" and diff "@@ -1 +1 @@\n+x=1"
When I set the widget show_diff flag to False
And I set the widget show_diff flag to True
Then the widget text should contain " diff "
And the widget show_diff property should be True
Scenario: Widget show_diff property stays False without diff content
When I create a PermissionQuestionWidget for "src/auth/handler.py" with type "file_write"
Then the widget show_diff property should be False
When I set the widget show_diff flag to True
Then the widget show_diff property should be False
# ── Allow action ──────────────────────────────────────────────────────────
Scenario: Allow once via key "a"
When I create a PermissionQuestionWidget for "src/auth/handler.py" with type "file_write"
And I press key "a" on the widget
Then a PermissionDecisionEvent should be returned
And the decision should be "allow_once"
Scenario: Allow always via key "A"
When I create a PermissionQuestionWidget for "src/auth/handler.py" with type "file_write"
And I press key "A" on the widget
Then a PermissionDecisionEvent should be returned
And the decision should be "allow_always"
Scenario: Allow once via enter on first option
When I create a PermissionQuestionWidget for "src/auth/handler.py" with type "file_write"
And I press key "enter" on the widget
Then a PermissionDecisionEvent should be returned
And the decision should be "allow_once"
# ── Reject action ─────────────────────────────────────────────────────────
Scenario: Reject once via key "r"
When I create a PermissionQuestionWidget for "src/auth/handler.py" with type "file_write"
And I press key "r" on the widget
Then a PermissionDecisionEvent should be returned
And the decision should be "reject_once"
Scenario: Reject always via key "R"
When I create a PermissionQuestionWidget for "src/auth/handler.py" with type "file_write"
And I press key "R" on the widget
Then a PermissionDecisionEvent should be returned
And the decision should be "reject_always"
# ── Navigation ────────────────────────────────────────────────────────────
Scenario: Navigate down moves selection
When I create a PermissionQuestionWidget for "src/auth/handler.py" with type "file_write"
And I press key "down" on the widget
Then the widget selected index should be 1
And no decision event should be returned
Scenario: Navigate up wraps around
When I create a PermissionQuestionWidget for "src/auth/handler.py" with type "file_write"
And I press key "up" on the widget
Then the widget selected index should be 3
Scenario: Navigate down then enter selects second option
When I create a PermissionQuestionWidget for "src/auth/handler.py" with type "file_write"
And I press key "down" on the widget
And I press key "enter" on the widget
Then a PermissionDecisionEvent should be returned
And the decision should be "allow_always"
Scenario: Navigate down twice then enter selects third option
When I create a PermissionQuestionWidget for "src/auth/handler.py" with type "file_write"
And I press key "down" on the widget
And I press key "down" on the widget
And I press key "enter" on the widget
Then a PermissionDecisionEvent should be returned
And the decision should be "reject_once"
# ── Open full screen ──────────────────────────────────────────────────────
Scenario: Press v sets open_full_screen flag
When I create a PermissionQuestionWidget for "src/auth/handler.py" with type "file_write"
And I press key "v" on the widget
Then the open_full_screen flag should be True
And no decision event should be returned
# ── Unknown key ───────────────────────────────────────────────────────────
Scenario: Unknown key returns None
When I create a PermissionQuestionWidget for "src/auth/handler.py" with type "file_write"
And I press key "x" on the widget
Then no decision event should be returned
# ── Inline rendering in conversation ─────────────────────────────────────
Scenario: render_permission_question returns correct structure
When I render a permission question for "src/auth/handler.py" with type "file_write"
Then the permission question rendered text should contain "Permission Required"
And the permission question rendered text should contain "src/auth/handler.py"
And the permission question rendered text should contain "Allow once"
Scenario: render_permission_question with selected_index 2 highlights third option
When I render a permission question for "src/auth/handler.py" with type "file_write" at index 2
Then the permission question rendered text should contain "Reject once"
Scenario: render_permission_question with diff shows diff content when show_diff is True
Given a permission question for "src/main.py" with type "file_write" and diff "+import os" rendered at index 0 with show_diff
Then the permission question rendered text should contain "+import os"
# ── Widget exports ────────────────────────────────────────────────────────
Scenario: PermissionQuestionWidget is exported from tui.widgets
Then PermissionQuestionWidget should be importable from tui.widgets
And PermissionDecisionEvent should be importable from tui.widgets
And render_permission_question should be importable from tui.widgets
# ── Domain model exports ──────────────────────────────────────────────────
Scenario: InlinePermissionQuestion is exported from domain.models.core
Then InlinePermissionQuestion should be importable from domain.models.core
And PermissionDecision should be importable from domain.models.core
And PermissionRequestType should be importable from domain.models.core