feat(req-013): add portfolio-list-user-required requirement and batch
- Add REQ-013: Portfolio list filtered by user requirement with acceptance criteria - Add DCY-003 discovery document for portfolio list user filtering - Create BAT-003 batch with planning, design, implementation, and verification - Enhance app/cli/commands/portfolio.py with user-based list filtering - Add comprehensive tests for portfolio list CLI command with user filtering - Update docs indices (discovery, srs, batches) - Improve README with latest capability status
This commit is contained in:
+68
-4
@@ -458,10 +458,14 @@ def _portfolio() -> Portfolio:
|
||||
|
||||
|
||||
def test_cli_list_renders_table() -> None:
|
||||
repo = FakeRepo(_portfolio())
|
||||
repo = FakeRepo()
|
||||
user = repo.create_user("alice", permission="read")
|
||||
p = _portfolio()
|
||||
p.owner_user_id = user.id
|
||||
repo._portfolio = p
|
||||
runner = build_runner(repo)
|
||||
|
||||
result = runner.invoke(runner.app, ["portfolio", "list"])
|
||||
result = runner.invoke(runner.app, ["portfolio", "list", "--user", "alice"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "005930:tv" in result.stdout
|
||||
@@ -820,11 +824,15 @@ def test_cli_tag_add_and_list() -> None:
|
||||
|
||||
|
||||
def test_cli_list_supports_tag_filters() -> None:
|
||||
repo = FakeRepo(_portfolio())
|
||||
repo = FakeRepo()
|
||||
user = repo.create_user("alice", permission="read")
|
||||
p = _portfolio()
|
||||
p.owner_user_id = user.id
|
||||
repo._portfolio = p
|
||||
repo.add_tag("005930:tv", tag="grade:A")
|
||||
runner = build_runner(repo)
|
||||
|
||||
result = runner.invoke(runner.app, ["portfolio", "list", "--include-tag", "grade:A", "--match-mode", "AND"])
|
||||
result = runner.invoke(runner.app, ["portfolio", "list", "--include-tag", "grade:A", "--match-mode", "AND", "--user", "alice"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "005930:tv" in result.stdout
|
||||
@@ -1166,3 +1174,59 @@ def test_cli_service_token_rotate_can_abort() -> None:
|
||||
token = repo.get_service_token_by_name("permanent")
|
||||
assert token is not None
|
||||
assert token.token_prefix == "pref"
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# portfolio list --user (REQ-013)
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def test_cli_portfolio_list_without_user_exits_error() -> None:
|
||||
repo = FakeRepo()
|
||||
runner = build_runner(repo)
|
||||
|
||||
result = runner.invoke(runner.app, ["portfolio", "list"])
|
||||
|
||||
assert result.exit_code == 1
|
||||
assert "--user" in result.stdout
|
||||
|
||||
|
||||
def test_cli_portfolio_list_with_valid_user_filters_by_owner() -> None:
|
||||
repo = FakeRepo()
|
||||
alice = repo.create_user("alice", permission="read")
|
||||
bob = repo.create_user("bob", permission="read")
|
||||
alice_portfolio = _portfolio()
|
||||
alice_portfolio.owner_user_id = alice.id
|
||||
repo._portfolio = alice_portfolio
|
||||
runner = build_runner(repo)
|
||||
|
||||
result_alice = runner.invoke(runner.app, ["portfolio", "list", "--user", "alice"])
|
||||
result_bob = runner.invoke(runner.app, ["portfolio", "list", "--user", "bob"])
|
||||
|
||||
assert result_alice.exit_code == 0
|
||||
assert "005930:tv" in result_alice.stdout
|
||||
assert result_bob.exit_code == 0
|
||||
assert "005930:tv" not in result_bob.stdout
|
||||
|
||||
|
||||
def test_cli_portfolio_list_with_unknown_user_exits_error() -> None:
|
||||
repo = FakeRepo()
|
||||
runner = build_runner(repo)
|
||||
|
||||
result = runner.invoke(runner.app, ["portfolio", "list", "--user", "nobody"])
|
||||
|
||||
assert result.exit_code == 1
|
||||
assert "nobody" in result.stdout
|
||||
|
||||
|
||||
def test_cli_portfolio_list_in_memory_mode_filters_owner() -> None:
|
||||
repo = FakeRepo()
|
||||
user = repo.create_user("alice", permission="read")
|
||||
p = _portfolio()
|
||||
p.owner_user_id = user.id
|
||||
repo._portfolio = p
|
||||
runner = build_runner(repo)
|
||||
|
||||
result = runner.invoke(runner.app, ["portfolio", "list", "--user", "alice"])
|
||||
|
||||
assert result.exit_code == 0
|
||||
assert "005930:tv" in result.stdout
|
||||
|
||||
Reference in New Issue
Block a user