test(tui): add TDD failing test for SQLite session persistence
Add BDD scenarios that capture bug #4739 — the missing TUI SQLite session persistence layer. The cleveragents.tui.session_store module and TuiSessionStore class do not exist; these tests verify their absence and will pass once the implementation is in place. All scenarios are tagged @tdd_expected_fail so CI passes while the module is absent. The expected-fail mechanism inverts the result: a failing AssertionError means the bug still exists (CI passes). ISSUES CLOSED: #10879
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
"""Step definitions for TDD Bug #4739 — TUI SQLite session persistence not implemented.
|
||||
|
||||
These steps verify that ``cleveragents.tui.session_store`` exists and that
|
||||
``TuiSessionStore`` can persist and retrieve session records from SQLite.
|
||||
|
||||
All scenarios are tagged ``@tdd_expected_fail`` so CI passes while the
|
||||
module is absent. The expected-fail mechanism inverts the result: a
|
||||
failing assertion means the bug is still present (CI passes); a passing
|
||||
assertion means the fix has been applied (CI also passes after the
|
||||
``@tdd_expected_fail`` tag is removed in the bugfix PR).
|
||||
|
||||
Failure mode: ``AssertionError`` (not ``ImportError`` or ``RuntimeError``).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import importlib
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
import types
|
||||
|
||||
from behave import given, then, when
|
||||
from behave.runner import Context
|
||||
|
||||
|
||||
@given("the tdd4739 test environment is set up")
|
||||
def step_tdd4739_setup(context: Context) -> None:
|
||||
"""Initialise context attributes used across tdd4739 steps."""
|
||||
context.tdd4739_module: types.ModuleType | None = None
|
||||
context.tdd4739_import_error: Exception | None = None
|
||||
context.tdd4739_store: object | None = None
|
||||
context.tdd4739_tmpdir: str | None = None
|
||||
|
||||
|
||||
@given("the tdd4739 test environment is set up with a temp db path")
|
||||
def step_tdd4739_setup_with_tmpdir(context: Context) -> None:
|
||||
"""Initialise context and create a temporary directory for the SQLite db."""
|
||||
context.tdd4739_module = None
|
||||
context.tdd4739_import_error = None
|
||||
context.tdd4739_store = None
|
||||
|
||||
tmpdir = tempfile.mkdtemp(prefix="tdd4739_")
|
||||
context.tdd4739_tmpdir = tmpdir
|
||||
context.tdd4739_db_path = os.path.join(tmpdir, "tui.db")
|
||||
|
||||
def _cleanup() -> None:
|
||||
shutil.rmtree(tmpdir, ignore_errors=True)
|
||||
|
||||
context.add_cleanup(_cleanup)
|
||||
|
||||
|
||||
@when("I attempt to import cleveragents.tui.session_store")
|
||||
def step_tdd4739_import(context: Context) -> None:
|
||||
"""Attempt to import the session_store module; capture any ImportError."""
|
||||
try:
|
||||
mod = importlib.import_module("cleveragents.tui.session_store")
|
||||
context.tdd4739_module = mod
|
||||
context.tdd4739_import_error = None
|
||||
except ImportError as exc:
|
||||
context.tdd4739_module = None
|
||||
context.tdd4739_import_error = exc
|
||||
|
||||
|
||||
@then("the tdd4739 import should succeed without errors")
|
||||
def step_tdd4739_import_ok(context: Context) -> None:
|
||||
"""Assert the import succeeded — fails via AssertionError if module is absent."""
|
||||
assert context.tdd4739_import_error is None, (
|
||||
f"cleveragents.tui.session_store could not be imported: "
|
||||
f"{context.tdd4739_import_error}"
|
||||
)
|
||||
assert context.tdd4739_module is not None, (
|
||||
"cleveragents.tui.session_store module is None after import"
|
||||
)
|
||||
|
||||
|
||||
@then("the tdd4739 module should expose a TuiSessionStore class")
|
||||
def step_tdd4739_class_exists(context: Context) -> None:
|
||||
"""Assert TuiSessionStore is present in the module."""
|
||||
assert context.tdd4739_import_error is None, (
|
||||
f"cleveragents.tui.session_store could not be imported: "
|
||||
f"{context.tdd4739_import_error}"
|
||||
)
|
||||
mod = context.tdd4739_module
|
||||
assert mod is not None, "session_store module is None"
|
||||
assert hasattr(mod, "TuiSessionStore"), (
|
||||
"cleveragents.tui.session_store does not expose a TuiSessionStore class"
|
||||
)
|
||||
|
||||
|
||||
@when("I create a TuiSessionStore pointing at the temp db path")
|
||||
def step_tdd4739_create_store(context: Context) -> None:
|
||||
"""Instantiate TuiSessionStore with the temp db path."""
|
||||
try:
|
||||
mod = importlib.import_module("cleveragents.tui.session_store")
|
||||
except ImportError as exc:
|
||||
raise AssertionError(
|
||||
f"cleveragents.tui.session_store could not be imported: {exc}"
|
||||
) from exc
|
||||
|
||||
assert hasattr(mod, "TuiSessionStore"), (
|
||||
"cleveragents.tui.session_store does not expose a TuiSessionStore class"
|
||||
)
|
||||
context.tdd4739_store = mod.TuiSessionStore(db_path=context.tdd4739_db_path)
|
||||
|
||||
|
||||
@when('I save a tdd4739 session record with id "{session_id}"')
|
||||
def step_tdd4739_save_session(context: Context, session_id: str) -> None:
|
||||
"""Save a minimal session record to the store."""
|
||||
store = context.tdd4739_store
|
||||
assert store is not None, "TuiSessionStore was not created"
|
||||
store.save( # type: ignore[union-attr]
|
||||
session_id=session_id,
|
||||
persona_name="default",
|
||||
actor_identity="anthropic/claude-4-sonnet",
|
||||
title=f"Test session {session_id}",
|
||||
prompt_count=0,
|
||||
total_cost=0.0,
|
||||
created_at="2026-01-01T00:00:00Z",
|
||||
last_used="2026-01-01T00:00:00Z",
|
||||
project_path=None,
|
||||
meta_json="{}",
|
||||
)
|
||||
|
||||
|
||||
@then('the tdd4739 session record should be retrievable by id "{session_id}"')
|
||||
def step_tdd4739_get_session(context: Context, session_id: str) -> None:
|
||||
"""Assert the session record can be retrieved by its id."""
|
||||
store = context.tdd4739_store
|
||||
assert store is not None, "TuiSessionStore was not created"
|
||||
record = store.get(session_id) # type: ignore[union-attr]
|
||||
assert record is not None, (
|
||||
f"TuiSessionStore.get('{session_id}') returned None — "
|
||||
f"session was not persisted"
|
||||
)
|
||||
assert getattr(record, "id", None) == session_id or (
|
||||
isinstance(record, dict) and record.get("id") == session_id
|
||||
), (
|
||||
f"Retrieved record id mismatch: expected '{session_id}', "
|
||||
f"got {getattr(record, 'id', record)!r}"
|
||||
)
|
||||
|
||||
|
||||
@then("the tdd4739 session store should list {count:d} sessions")
|
||||
def step_tdd4739_list_sessions(context: Context, count: int) -> None:
|
||||
"""Assert the store lists the expected number of sessions."""
|
||||
store = context.tdd4739_store
|
||||
assert store is not None, "TuiSessionStore was not created"
|
||||
sessions = store.list_all() # type: ignore[union-attr]
|
||||
assert sessions is not None, "TuiSessionStore.list_all() returned None"
|
||||
actual = len(sessions)
|
||||
assert actual == count, (
|
||||
f"Expected {count} sessions in store, got {actual}"
|
||||
)
|
||||
@@ -0,0 +1,39 @@
|
||||
@tdd_issue @tdd_issue_4739
|
||||
Feature: Bug #4739 — TUI SQLite session persistence not implemented
|
||||
As a developer
|
||||
I want to verify that the TUI session persistence layer exists
|
||||
So that the bug is captured and will be caught by a regression test
|
||||
|
||||
The spec (§Session Persistence and Resume) requires TUI sessions to be
|
||||
persisted in an SQLite database at ~/.local/state/cleveragents/tui.db
|
||||
via a TuiSessionStore class in cleveragents.tui.session_store.
|
||||
|
||||
Currently no such module exists — the TUI hardcodes a single in-memory
|
||||
session and has no SQLite persistence layer.
|
||||
|
||||
@tdd_issue @tdd_issue_4739 @tdd_expected_fail
|
||||
Scenario: TuiSessionStore module can be imported from cleveragents.tui
|
||||
Given the tdd4739 test environment is set up
|
||||
When I attempt to import cleveragents.tui.session_store
|
||||
Then the tdd4739 import should succeed without errors
|
||||
|
||||
@tdd_issue @tdd_issue_4739 @tdd_expected_fail
|
||||
Scenario: TuiSessionStore class exists in the session_store module
|
||||
Given the tdd4739 test environment is set up
|
||||
When I attempt to import cleveragents.tui.session_store
|
||||
Then the tdd4739 module should expose a TuiSessionStore class
|
||||
|
||||
@tdd_issue @tdd_issue_4739 @tdd_expected_fail
|
||||
Scenario: TuiSessionStore can persist a session record to SQLite
|
||||
Given the tdd4739 test environment is set up with a temp db path
|
||||
When I create a TuiSessionStore pointing at the temp db path
|
||||
And I save a tdd4739 session record with id "test-session-001"
|
||||
Then the tdd4739 session record should be retrievable by id "test-session-001"
|
||||
|
||||
@tdd_issue @tdd_issue_4739 @tdd_expected_fail
|
||||
Scenario: TuiSessionStore lists all persisted sessions
|
||||
Given the tdd4739 test environment is set up with a temp db path
|
||||
When I create a TuiSessionStore pointing at the temp db path
|
||||
And I save a tdd4739 session record with id "sess-a"
|
||||
And I save a tdd4739 session record with id "sess-b"
|
||||
Then the tdd4739 session store should list 2 sessions
|
||||
Reference in New Issue
Block a user