"""Envelope tests for describe command.""" from __future__ import annotations import datetime import json import pathlib from collections.abc import Mapping import argparse import pytest from tests.cli_test_helper import CliRunner from muse.core.ids import hash_commit, hash_snapshot from muse.core.commits import CommitRecord, write_commit from muse.core.snapshots import SnapshotRecord, write_snapshot from muse.core.version_tags import VersionTagRecord, write_version_tag from muse.core.semver import parse_semver from muse.core.types import Manifest, content_hash from muse.core.paths import muse_dir, ref_path runner = CliRunner() _FIELDS = ("muse_version", "schema", "timestamp", "warnings") _REPO_ID = content_hash({"name": "envelope-test"}) def _check(d: Mapping[str, object]) -> None: for f in _FIELDS: assert f in d, f"missing {f}" assert "schema_version" not in d def _init_repo(path: pathlib.Path) -> pathlib.Path: dot_muse = muse_dir(path) for d in ("commits", "snapshots", "objects", "refs/heads"): (dot_muse / d).mkdir(parents=True, exist_ok=True) (dot_muse / "HEAD").write_text("ref: refs/heads/main", encoding="utf-8") (dot_muse / "repo.json").write_text( json.dumps({"repo_id": _REPO_ID, "domain": "code"}), encoding="utf-8" ) return path def _make_commit(root: pathlib.Path, parent_id: str | None = None, content: bytes = b"data") -> str: manifest: Manifest = {} snap_id = hash_snapshot(manifest) write_snapshot(root, SnapshotRecord(snapshot_id=snap_id, manifest=manifest)) committed_at = datetime.datetime.now(datetime.timezone.utc) parent_ids = [parent_id] if parent_id else [] commit_id = hash_commit( parent_ids=parent_ids, snapshot_id=snap_id, message="msg", committed_at_iso=committed_at.isoformat(), ) write_commit(root, CommitRecord( commit_id=commit_id, branch="main", snapshot_id=snap_id, message="msg", committed_at=committed_at, parent_commit_id=parent_id, )) ref_path(root, "main").write_text(commit_id, encoding="utf-8") return commit_id def _make_vtag(root: pathlib.Path, tag: str, commit_id: str) -> None: write_version_tag(root, VersionTagRecord( tag_id=content_hash({"tag": tag, "commit_id": commit_id}), repo_id=_REPO_ID, tag=tag, semver=parse_semver(tag), commit_id=commit_id, created_at=datetime.datetime.now(datetime.timezone.utc), author="", message="", )) class TestDescribeEnvelope: def test_describe_has_envelope_on_tag(self, tmp_path: pathlib.Path) -> None: _init_repo(tmp_path) cid = _make_commit(tmp_path, content=b"env-test") _make_vtag(tmp_path, "v1.0.0", cid) r = runner.invoke(None, ["describe", "--json"], env={"MUSE_REPO_ROOT": str(tmp_path)}) assert r.exit_code == 0, r.output _check(json.loads(r.output)) def test_describe_has_envelope_no_tag(self, tmp_path: pathlib.Path) -> None: _init_repo(tmp_path) _make_commit(tmp_path, content=b"no-tag") r = runner.invoke(None, ["describe", "--json"], env={"MUSE_REPO_ROOT": str(tmp_path)}) assert r.exit_code == 1 _check(json.loads(r.output)) # --------------------------------------------------------------------------- # TestRegisterFlags — argparse-level verification # --------------------------------------------------------------------------- class TestRegisterFlags: """Verify that register() wires --json / -j correctly.""" def _make_parser(self) -> "argparse.ArgumentParser": import argparse from muse.cli.commands.describe import register ap = argparse.ArgumentParser() subs = ap.add_subparsers() register(subs) return ap def test_json_flag_long(self) -> None: ns = self._make_parser().parse_args(["describe", "--json"]) assert ns.json_out is True def test_j_alias(self) -> None: ns = self._make_parser().parse_args(["describe", "-j"]) assert ns.json_out is True def test_default_is_text(self) -> None: ns = self._make_parser().parse_args(["describe"]) assert ns.json_out is False def test_dest_is_json_out(self) -> None: ns = self._make_parser().parse_args(["describe", "-j"]) assert hasattr(ns, "json_out") assert not hasattr(ns, "fmt")