diff --git a/features/tui/persona/steps/tdd_persona_state_set_active_persona_reset_steps.py b/features/tui/persona/steps/tdd_persona_state_set_active_persona_reset_steps.py new file mode 100644 index 000000000..7771f9115 --- /dev/null +++ b/features/tui/persona/steps/tdd_persona_state_set_active_persona_reset_steps.py @@ -0,0 +1,110 @@ +"""Step definitions for tdd_persona_state_set_active_persona_reset.feature. + +These steps capture bug #10500: PersonaState.set_active_persona() does not +reset the active preset to "default" when switching to a different persona. + +The current implementation only initialises the preset when the session has +no preset entry at all. If the session already has a non-default preset +(e.g. because the user cycled through presets), switching persona leaves +that preset unchanged instead of resetting it to "default". + +Expected (correct) behaviour: + state.set_active_persona(session_id, new_persona) + -> state.current_preset(session_id) == "default" + +Actual (buggy) behaviour: + state.set_active_persona(session_id, new_persona) + -> state.current_preset(session_id) == +""" + +from unittest.mock import MagicMock + +from behave import given, then, when + +from cleveragents.tui.persona.schema import Persona +from cleveragents.tui.persona.state import PersonaState + +# --------------------------------------------------------------------------- +# Helpers +# --------------------------------------------------------------------------- + + +def _make_persona(name, actor="ns/actor"): + """Build a minimal real Persona for testing.""" + return Persona(name=name, actor=actor) + + +def _make_mock_registry(personas): + """Return a MagicMock that quacks like PersonaRegistry.""" + registry = MagicMock() + default = next(iter(personas.values())) + registry.ensure_default.return_value = default + registry.get_last_persona.return_value = None + registry.set_last_persona = MagicMock() + + def _get(name): + return personas.get(name) + + registry.get.side_effect = _get + return registry + + +# --------------------------------------------------------------------------- +# Given steps +# --------------------------------------------------------------------------- + + +@given( + 'a session "{session_id}" with persona "{persona_name}"' + ' and a non-default preset "{preset_name}"' +) +def step_session_with_persona_and_preset( + context, session_id, persona_name, preset_name +): + """Set up a session that already has a non-default preset.""" + coder = _make_persona("coder", actor="ns/coder") + analyst = _make_persona("analyst", actor="ns/analyst") + registry = _make_mock_registry({"coder": coder, "analyst": analyst}) + context.state = PersonaState( + registry=registry, + active_by_session={session_id: persona_name}, + preset_by_session={session_id: preset_name}, + ) + + +@given('the preset for session "{session_id}" has been updated to "{preset_name}"') +def step_update_preset(context, session_id, preset_name): + """Directly update the preset for a session (simulates cycling).""" + context.state.preset_by_session[session_id] = preset_name + + +# --------------------------------------------------------------------------- +# When steps +# --------------------------------------------------------------------------- + + +@when('I switch session "{session_id}" to persona "{persona_name}"') +def step_switch_persona(context, session_id, persona_name): + """Call set_active_persona to switch the active persona.""" + context.state.set_active_persona(session_id, persona_name) + + +# --------------------------------------------------------------------------- +# Then steps +# --------------------------------------------------------------------------- + + +@then('the preset for session "{session_id}" should be "{expected_preset}"') +def step_verify_preset(context, session_id, expected_preset): + """Assert that the preset has been reset to the expected value. + + This assertion will FAIL while bug #10500 is unfixed because + set_active_persona() does not reset an existing preset to "default". + The @tdd_expected_fail tag inverts this failure so CI passes. + """ + actual = context.state.current_preset(session_id) + assert actual == expected_preset, ( + f"Bug #10500: expected preset '{expected_preset}' after switching persona " + f"but got '{actual}'. set_active_persona() does not reset an existing " + f"non-default preset to 'default'." + ) diff --git a/features/tui/persona/tdd_persona_state_set_active_persona_reset.feature b/features/tui/persona/tdd_persona_state_set_active_persona_reset.feature new file mode 100644 index 000000000..394e56765 --- /dev/null +++ b/features/tui/persona/tdd_persona_state_set_active_persona_reset.feature @@ -0,0 +1,23 @@ +@tdd_issue @tdd_issue_10499 +Feature: TDD Bug #10500 — PersonaState.set_active_persona() does not reset preset + As a TUI user + I want switching to a different persona to reset the active preset to "default" + So that I do not accidentally carry over a preset from a previous persona + + When a session has cycled to a non-default preset and the user then switches + to a different persona, the preset should be reset to "default". The current + implementation only initialises the preset when the session has no preset at + all; it leaves an existing non-default preset unchanged. + + @tdd_issue @tdd_issue_10499 @tdd_expected_fail + Scenario: Bug #10500 - switching persona resets preset to default + Given a session "sess-reset-1" with persona "coder" and a non-default preset "turbo" + When I switch session "sess-reset-1" to persona "analyst" + Then the preset for session "sess-reset-1" should be "default" + + @tdd_issue @tdd_issue_10499 @tdd_expected_fail + Scenario: Bug #10500 - switching persona resets preset even after multiple cycles + Given a session "sess-reset-2" with persona "coder" and a non-default preset "fast" + And the preset for session "sess-reset-2" has been updated to "slow" + When I switch session "sess-reset-2" to persona "analyst" + Then the preset for session "sess-reset-2" should be "default"