SPB Git

spb/air Public MIT

AIR — The Language of Accounting.

Python 100%
4.0 KB · 106 lines python
Raw Blame History
1# =============================================================================2# Projet : AIR — Accounting Intermediate Representation3# Auteur : Simon-Pierre Boucher4# Contact : contact@spboucher.ai5# Fichier : test_workspace.py6# Description : Tests — the AIR home (managed local data) and the standalone CLI flows.7# =============================================================================8"""AIR home + CLI tests: init, compile into the home, archives, status,9incremental recompile, statements, and offline QBO export — all without any10third-party system."""11from __future__ import annotations1213import json14from pathlib import Path1516import pytest1718from kernel.workspace import Workspace, WorkspaceError19from sdk.cli import main2021ROOT = Path(__file__).resolve().parents[1]22POLICY = str(ROOT / "alsl" / "policies" / "ca-qc-2026.yaml")23DEMO = str(ROOT / "tests" / "fixtures" / "demo_document.yaml")242526def test_workspace_init_open_and_guardrails(tmp_path: Path) -> None:27    home = tmp_path / "books"28    ws = Workspace.init(home, name="acme", policies=POLICY)29    assert ws.meta["name"] == "acme"30    with pytest.raises(WorkspaceError, match="already initialized"):31        Workspace.init(home)32    with pytest.raises(WorkspaceError, match="no AIR home"):33        Workspace.open(tmp_path / "elsewhere")343536def test_cli_full_standalone_lifecycle(tmp_path: Path, capsys) -> None:37    home = str(tmp_path / "books")3839    assert main(["init", "--home", home, "--policies", POLICY]) == 040    assert main(["compile", DEMO, "--home", home]) == 041    out = capsys.readouterr().out42    assert "8 entries" in out and "document archived" in out4344    # replaying the same document is idempotent (0 appended)45    assert main(["compile", DEMO, "--home", home]) == 046    assert "+0 appended" in capsys.readouterr().out4748    # data is managed inside the home49    ws = Workspace.open(home)50    status = ws.status()51    assert status["entries"] == 852    assert status["chain_valid"] is True53    assert status["documents_archived"] == 1  # content-addressed, no duplicate5455    # statements straight from the home56    assert main(["report", "trial-balance", "--home", home]) == 057    tb = capsys.readouterr().out58    assert "TOTAL" in tb5960    assert main(["status", "--home", home]) == 061    assert "chain_valid" in capsys.readouterr().out626364def test_cli_incremental_into_home(tmp_path: Path, capsys) -> None:65    home = str(tmp_path / "books")66    main(["init", "--home", home, "--policies", POLICY])67    main(["compile", DEMO, "--home", home])68    capsys.readouterr()6970    corrected = tmp_path / "demo_v2.yaml"71    corrected.write_text(72        Path(DEMO).read_text().replace('amount: "333.33"', 'amount: "349.99"'),73        encoding="utf-8",74    )75    assert main(["recompile", DEMO, str(corrected), "--home", home]) == 076    out = capsys.readouterr().out77    assert "~1 changed" in out and "1 reversal(s)" in out7879    status = Workspace.open(home).status()80    assert status["entries"] == 10          # 8 + reversal + replacement81    assert status["documents_archived"] == 282    assert status["chain_valid"] is True838485def test_cli_qbo_export_needs_no_quickbooks(tmp_path: Path, capsys) -> None:86    home = str(tmp_path / "books")87    main(["init", "--home", home, "--policies", POLICY])88    capsys.readouterr()89    assert main(["compile", DEMO, "--home", home, "--backend", "qbo-export"]) == 090    out = capsys.readouterr().out91    assert "QBO JSON export" in out9293    exports = list(Workspace.open(home).exports_dir.glob("qbo_journal_*.json"))94    assert len(exports) == 195    data = json.loads(exports[0].read_text())96    assert len(data["journal_entries"]) == 897    assert data["journal_entries"][0]["Line"]  # QBO JournalEntry shape9899100def test_cli_missing_policies_is_helpful(tmp_path: Path, capsys) -> None:101    home = str(tmp_path / "books")102    main(["init", "--home", home])           # no default policies103    capsys.readouterr()104    assert main(["compile", DEMO, "--home", home]) == 1105    assert "no policy set" in capsys.readouterr().err106