"""Supercharge tests for ``muse reset``. Coverage tiers -------------- Unit — TypedDict shape, alias registration, docstring completeness. Integration — ``-j`` alias, ``-n`` alias, ``exit_code``/``duration_ms`` in JSON, ``schema_version`` field, dry-run JSON envelope, applied JSON envelope. Security — null byte / ANSI injection in ref and format args. """ from __future__ import annotations import argparse import json import os import pathlib import pytest from tests.cli_test_helper import CliRunner, InvokeResult runner = CliRunner() # ────────────────────────────────────────────────────────────────────────────── # Helpers # ────────────────────────────────────────────────────────────────────────────── def _invoke(repo: pathlib.Path, args: list[str]) -> InvokeResult: saved = os.getcwd() try: os.chdir(repo) return runner.invoke(None, args) finally: os.chdir(saved) def _reset(repo: pathlib.Path, *extra: str) -> InvokeResult: return _invoke(repo, ["reset", *extra]) def _commit(repo: pathlib.Path, message: str) -> str: import re _invoke(repo, ["code", "add", "."]) result = _invoke(repo, ["commit", "-m", message]) m = re.search(r"sha256:[0-9a-f]{64}", result.output + (result.stderr or "")) return m.group(0) if m else "" @pytest.fixture() def repo(tmp_path: pathlib.Path) -> pathlib.Path: saved = os.getcwd() try: os.chdir(tmp_path) runner.invoke(None, ["init"]) finally: os.chdir(saved) (tmp_path / "a.py").write_text("x = 1\n") _commit(tmp_path, "initial") (tmp_path / "b.py").write_text("y = 2\n") _commit(tmp_path, "add b") return tmp_path @pytest.fixture() def c1_id(repo: pathlib.Path) -> str: """Full commit ID of the first commit (HEAD~1).""" from muse.core.refs import get_head_commit_id from muse.core.commits import read_commit head_id = get_head_commit_id(repo, "main") or "" head = read_commit(repo, head_id) return (head.parent_commit_id or "") if head else "" # ────────────────────────────────────────────────────────────────────────────── # Unit — TypedDict # ────────────────────────────────────────────────────────────────────────────── class TestTypedDict: def test_reset_json_typed_dict_exists(self) -> None: from muse.cli.commands.reset import _ResetJson # noqa: F401 def test_reset_json_typed_dict_has_exit_code(self) -> None: from muse.cli.commands.reset import _ResetJson import typing hints = typing.get_type_hints(_ResetJson) assert "exit_code" in hints, "exit_code missing from _ResetJson" def test_reset_json_typed_dict_has_duration_ms(self) -> None: from muse.cli.commands.reset import _ResetJson import typing hints = typing.get_type_hints(_ResetJson) assert "duration_ms" in hints, "duration_ms missing from _ResetJson" def test_reset_json_typed_dict_has_schema_version(self) -> None: from muse.cli.commands.reset import _ResetJson import typing hints = typing.get_type_hints(_ResetJson) assert "schema" in hints, "schema_version missing from _ResetJson" def test_reset_json_typed_dict_has_all_core_fields(self) -> None: from muse.cli.commands.reset import _ResetJson import typing hints = typing.get_type_hints(_ResetJson) required = {"branch", "ref", "old_commit_id", "new_commit_id", "snapshot_id", "mode", "dry_run"} missing = required - set(hints) assert not missing, f"Missing fields in _ResetJson: {missing}" # ────────────────────────────────────────────────────────────────────────────── # Unit — alias registration # ────────────────────────────────────────────────────────────────────────────── class TestAliasRegistration: def _make_parser(self) -> "argparse.ArgumentParser": import argparse from muse.cli.commands.reset import register p = argparse.ArgumentParser() sub = p.add_subparsers() register(sub) return p def test_j_alias_sets_json_fmt(self) -> None: p = self._make_parser() ns = p.parse_args(["reset", "HEAD~1", "-j"]) assert ns.json_out is True def test_n_alias_sets_dry_run(self) -> None: p = self._make_parser() ns = p.parse_args(["reset", "HEAD~1", "-n"]) assert ns.dry_run is True def test_j_and_n_together(self) -> None: p = self._make_parser() ns = p.parse_args(["reset", "HEAD~1", "-j", "-n"]) assert ns.json_out is True assert ns.dry_run is True # ────────────────────────────────────────────────────────────────────────────── # Integration — -j alias produces identical output to --json # ────────────────────────────────────────────────────────────────────────────── class TestJsonAlias: def test_j_alias_exit_code_zero(self, repo: pathlib.Path, c1_id: str) -> None: result = _reset(repo, c1_id, "-j") assert result.exit_code == 0 def test_j_alias_output_is_valid_json(self, repo: pathlib.Path, c1_id: str) -> None: result = _reset(repo, c1_id, "-j") data = json.loads(result.output) assert isinstance(data, dict) def test_j_alias_same_keys_as_json_flag(self, repo: pathlib.Path, c1_id: str) -> None: # Use dry-run so neither call actually moves HEAD; both see same state. r_json = _reset(repo, c1_id, "--json", "--dry-run") r_j = _reset(repo, c1_id, "-j", "--dry-run") assert set(json.loads(r_json.output)) == set(json.loads(r_j.output)) # ────────────────────────────────────────────────────────────────────────────── # Integration — -n alias for --dry-run # ────────────────────────────────────────────────────────────────────────────── class TestDryRunAlias: def test_n_alias_no_write(self, repo: pathlib.Path, c1_id: str) -> None: from muse.core.refs import get_head_commit_id before = get_head_commit_id(repo, "main") _reset(repo, c1_id, "-n") after = get_head_commit_id(repo, "main") assert before == after, "-n should not advance HEAD" def test_n_alias_json_dry_run_true(self, repo: pathlib.Path, c1_id: str) -> None: result = _reset(repo, c1_id, "-n", "-j") data = json.loads(result.output) assert data["dry_run"] is True def test_n_alias_exit_code_zero(self, repo: pathlib.Path, c1_id: str) -> None: result = _reset(repo, c1_id, "-n") assert result.exit_code == 0 # ────────────────────────────────────────────────────────────────────────────── # Integration — JSON envelope completeness # ────────────────────────────────────────────────────────────────────────────── class TestJsonEnvelope: def test_applied_json_has_exit_code(self, repo: pathlib.Path, c1_id: str) -> None: result = _reset(repo, c1_id, "--json") data = json.loads(result.output) assert "exit_code" in data def test_applied_json_exit_code_is_zero(self, repo: pathlib.Path, c1_id: str) -> None: result = _reset(repo, c1_id, "--json") data = json.loads(result.output) assert data["exit_code"] == 0 def test_applied_json_has_duration_ms(self, repo: pathlib.Path, c1_id: str) -> None: result = _reset(repo, c1_id, "--json") data = json.loads(result.output) assert "duration_ms" in data def test_applied_json_duration_ms_is_float(self, repo: pathlib.Path, c1_id: str) -> None: result = _reset(repo, c1_id, "--json") data = json.loads(result.output) assert isinstance(data["duration_ms"], float) assert data["duration_ms"] >= 0.0 def test_applied_json_has_schema_version(self, repo: pathlib.Path, c1_id: str) -> None: result = _reset(repo, c1_id, "--json") data = json.loads(result.output) assert "schema" in data def test_applied_json_schema_version_is_string(self, repo: pathlib.Path, c1_id: str) -> None: result = _reset(repo, c1_id, "--json") data = json.loads(result.output) assert isinstance(data["schema"], int) assert data["schema"] > 0 def test_dry_run_json_has_exit_code(self, repo: pathlib.Path, c1_id: str) -> None: result = _reset(repo, c1_id, "--json", "--dry-run") data = json.loads(result.output) assert "exit_code" in data def test_dry_run_json_exit_code_is_zero(self, repo: pathlib.Path, c1_id: str) -> None: result = _reset(repo, c1_id, "--json", "--dry-run") data = json.loads(result.output) assert data["exit_code"] == 0 def test_dry_run_json_has_duration_ms(self, repo: pathlib.Path, c1_id: str) -> None: result = _reset(repo, c1_id, "--json", "--dry-run") data = json.loads(result.output) assert "duration_ms" in data def test_dry_run_json_duration_ms_is_float(self, repo: pathlib.Path, c1_id: str) -> None: result = _reset(repo, c1_id, "--json", "--dry-run") data = json.loads(result.output) assert isinstance(data["duration_ms"], float) assert data["duration_ms"] >= 0.0 def test_dry_run_json_has_schema_version(self, repo: pathlib.Path, c1_id: str) -> None: result = _reset(repo, c1_id, "--json", "--dry-run") data = json.loads(result.output) assert "schema" in data # ────────────────────────────────────────────────────────────────────────────── # Security — input sanitization # ────────────────────────────────────────────────────────────────────────────── class TestSecurity: def test_null_byte_in_ref_does_not_crash(self, repo: pathlib.Path) -> None: result = _reset(repo, "HEAD\x00malicious") assert result.exit_code != 0 def test_ansi_in_ref_not_echoed_raw(self, repo: pathlib.Path) -> None: result = _reset(repo, "\x1b[31mred\x1b[0m") combined = result.output + (result.stderr or "") assert "\x1b[31m" not in combined def test_null_byte_in_format_does_not_crash(self, repo: pathlib.Path) -> None: result = _reset(repo, "HEAD~1", "--format", "json\x00malicious") assert result.exit_code != 0 def test_ansi_in_format_not_echoed_raw(self, repo: pathlib.Path) -> None: result = _reset(repo, "HEAD~1", "--format", "\x1b[31mred\x1b[0m") combined = result.output + (result.stderr or "") assert "\x1b[31m" not in combined # ────────────────────────────────────────────────────────────────────────────── # Unit — docstrings # ────────────────────────────────────────────────────────────────────────────── class TestDocstrings: def test_register_has_docstring(self) -> None: from muse.cli.commands.reset import register assert register.__doc__ and len(register.__doc__.strip()) > 20 def test_register_docstring_mentions_flags(self) -> None: from muse.cli.commands.reset import register doc = register.__doc__ or "" assert "--hard" in doc or "hard" in doc.lower() assert "--dry-run" in doc or "dry_run" in doc or "dry-run" in doc.lower() def test_run_has_docstring(self) -> None: from muse.cli.commands.reset import run assert run.__doc__ and len(run.__doc__.strip()) > 20 def test_run_docstring_mentions_schema_version(self) -> None: from muse.cli.commands.reset import run doc = run.__doc__ or "" assert "json" in doc.lower() or "exit_code" in doc