strix/tests/test_cli_resume_picker.py
Ian f1386cad37
Some checks are pending
CI / python (push) Waiting to run
CI / tui (push) Waiting to run
CI / viewer (push) Waiting to run
CI / package (push) Waiting to run
CI / workflows (push) Waiting to run
CI / ci-passed (push) Blocked by required conditions
feat(cli): add -r for --resume and a title column to the resume picker
2026-10-06 07:51:00 +03:00

126 lines
4.1 KiB
Python

"""Tests for `strix --resume` without a run name."""
from __future__ import annotations
import importlib
import json
import sys
from typing import TYPE_CHECKING, Any
import pytest
if TYPE_CHECKING:
from pathlib import Path
cli_main: Any = importlib.import_module("strix.interface.main")
def _write_run(base: Path, name: str, *, state: bool = True) -> None:
run_dir = base / name
(run_dir / ".state").mkdir(parents=True)
(run_dir / "run.json").write_text(
json.dumps(
{
"run_name": name,
"status": "completed",
"start_time": "2026-10-04T10:00:00+00:00",
"targets_info": [
{
"type": "web_application",
"details": {"target_url": "https://example.com"},
"original": "https://example.com",
}
],
}
),
encoding="utf-8",
)
if state:
(run_dir / ".state" / "agents.json").write_text("{}", encoding="utf-8")
@pytest.mark.parametrize("flag", ["--resume", "-r"])
def test_bare_resume_defers_to_the_picker(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, flag: str
) -> None:
monkeypatch.chdir(tmp_path)
_write_run(tmp_path / "strix_runs", "example-com_1111")
monkeypatch.setattr(sys, "argv", ["strix", flag])
args = cli_main.parse_arguments()
assert args.resume is None
assert args.resume_picker is True
assert args.needs_setup is False
assert args.targets_info == []
def test_bare_resume_keeps_the_new_instruction_as_resume_guidance(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.chdir(tmp_path)
_write_run(tmp_path / "strix_runs", "example-com_1111")
monkeypatch.setattr(sys, "argv", ["strix", "--resume", "--instruction", "focus on auth"])
args = cli_main.parse_arguments()
assert args.resume_picker is True
assert args.user_explicit_instruction == "focus on auth"
def test_bare_resume_with_no_runs_is_an_error(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
) -> None:
monkeypatch.chdir(tmp_path)
monkeypatch.setattr(sys, "argv", ["strix", "--resume"])
with pytest.raises(SystemExit):
cli_main.parse_arguments()
assert "no runs in ./strix_runs" in capsys.readouterr().err
def test_bare_resume_headless_lists_the_runs_instead_of_prompting(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
) -> None:
monkeypatch.chdir(tmp_path)
_write_run(tmp_path / "strix_runs", "example-com_1111")
_write_run(tmp_path / "strix_runs", "example-com_2222", state=False)
monkeypatch.setattr(sys, "argv", ["strix", "-n", "--resume"])
with pytest.raises(SystemExit):
cli_main.parse_arguments()
err = capsys.readouterr().err
assert "--resume needs a run name in headless mode" in err
assert "example-com_1111 completed 2026-10-04T10:00:00 https://example.com" in err
assert "example-com_2222 completed 2026-10-04T10:00:00 https://example.com" in err
assert "example-com_2222" in err
def test_bare_resume_still_rejects_targets(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
) -> None:
monkeypatch.chdir(tmp_path)
_write_run(tmp_path / "strix_runs", "example-com_1111")
monkeypatch.setattr(sys, "argv", ["strix", "--resume", "-t", "https://example.com"])
with pytest.raises(SystemExit):
cli_main.parse_arguments()
assert "Cannot combine --resume with --target" in capsys.readouterr().err
def test_named_resume_without_agent_state_is_an_error(
tmp_path: Path, monkeypatch: pytest.MonkeyPatch, capsys: pytest.CaptureFixture[str]
) -> None:
monkeypatch.chdir(tmp_path)
_write_run(tmp_path / "strix_runs", "example-com_1111", state=False)
monkeypatch.setattr(sys, "argv", ["strix", "--resume", "example-com_1111"])
with pytest.raises(SystemExit):
cli_main.parse_arguments()
assert "never reached its first agent snapshot" in capsys.readouterr().err