"""Tests for CommitRecord and CommitDict schema contract. Canonical field names: - ``branch`` — the branch the commit was made on (not ``created_on_branch``) - ``format_version`` — removed entirely; not stored, not serialised """ from __future__ import annotations import datetime import pytest from muse.core.store import CommitRecord, CommitDict from muse.core.types import MsgpackDict, long_id # --------------------------------------------------------------------------- # Helpers # --------------------------------------------------------------------------- _NOW = datetime.datetime(2025, 1, 1, 0, 0, 0, tzinfo=datetime.timezone.utc) _TS = _NOW.isoformat() _CID = long_id("a" * 64) _SID = long_id("b" * 64) def _minimal_dict(branch_key: str = "branch") -> MsgpackDict: """Minimal raw dict for CommitRecord.from_dict.""" return { "commit_id": _CID, "repo_id": "test-repo", branch_key: "main", "snapshot_id": _SID, "message": "test commit", "committed_at": _TS, } # --------------------------------------------------------------------------- # CommitRecord field existence # --------------------------------------------------------------------------- class TestCommitRecordFields: def test_has_branch_field(self) -> None: rec = CommitRecord( commit_id=_CID, branch="main", snapshot_id=_SID, message="m", committed_at=_NOW, ) assert rec.branch == "main" def test_has_no_created_on_branch_field(self) -> None: rec = CommitRecord( commit_id=_CID, branch="main", snapshot_id=_SID, message="m", committed_at=_NOW, ) assert not hasattr(rec, "created_on_branch"), ( "CommitRecord must not have a 'created_on_branch' field" ) def test_has_no_format_version_field(self) -> None: rec = CommitRecord( commit_id=_CID, branch="main", snapshot_id=_SID, message="m", committed_at=_NOW, ) assert not hasattr(rec, "format_version"), ( "CommitRecord must not have a 'format_version' field" ) # --------------------------------------------------------------------------- # to_dict serialisation # --------------------------------------------------------------------------- class TestCommitRecordToDict: def _make(self) -> CommitRecord: return CommitRecord( commit_id=_CID, branch="dev", snapshot_id=_SID, message="m", committed_at=_NOW, ) def test_to_dict_has_branch_key(self) -> None: d = self._make().to_dict() assert d["branch"] == "dev" def test_to_dict_has_no_created_on_branch_key(self) -> None: d = self._make().to_dict() assert "created_on_branch" not in d, ( "to_dict() must not emit 'created_on_branch' key" ) def test_to_dict_has_no_format_version_key(self) -> None: d = self._make().to_dict() assert "format_version" not in d, ( "to_dict() must not emit 'format_version' key" ) # --------------------------------------------------------------------------- # from_dict deserialisation # --------------------------------------------------------------------------- class TestCommitRecordFromDict: def test_reads_branch_key(self) -> None: raw = _minimal_dict("branch") rec = CommitRecord.from_dict(raw) assert rec.branch == "main" def test_falls_back_to_created_on_branch_for_old_records(self) -> None: """Old stored files with 'created_on_branch' key must still deserialise. This shim supports repos not yet migrated via 'muse code migrate'. New commits are always written with 'branch'. """ raw = _minimal_dict("created_on_branch") rec = CommitRecord.from_dict(raw) assert rec.branch == "main" def test_raises_when_neither_key_present(self) -> None: raw = _minimal_dict("branch") del raw["branch"] with pytest.raises(TypeError, match="branch"): CommitRecord.from_dict(raw) def test_from_dict_ignores_format_version_key(self) -> None: """Old records with format_version in the dict must still deserialise without storing the field on the returned record.""" raw = _minimal_dict("branch") raw["format_version"] = 8 rec = CommitRecord.from_dict(raw) assert not hasattr(rec, "format_version") # --------------------------------------------------------------------------- # CommitDict TypedDict # --------------------------------------------------------------------------- class TestCommitDict: def test_commit_dict_has_branch_key(self) -> None: """CommitDict must declare 'branch', not 'created_on_branch'.""" annotations = CommitDict.__annotations__ assert "branch" in annotations, ( "CommitDict must have 'branch' key" ) assert "created_on_branch" not in annotations, ( "CommitDict must not have 'created_on_branch' key" ) def test_commit_dict_has_no_format_version_key(self) -> None: annotations = CommitDict.__annotations__ assert "format_version" not in annotations, ( "CommitDict must not have 'format_version' key" )