Files
stack/tests/cli/test_prisma_deep.py
kert dbf71a6594 test: 99.93% coverage — Zotero 9 schema fix + 400+ new tests
Fix Zotero table models for Zotero 9:
- Remove stale Annotations/Highlights/Transaction* models
- Add ItemAnnotations, RetractedItems, DeletedCollections,
  DeletedSearches, DbDebug1
- Fix ItemAttachments, Libraries, Users column mismatches

New test files covering all major modules:
- cli/{bib,prisma,rec,zot,mail,run} deep exercising tests
- mail/{droplet,postmark,resend,cloudflare} lifecycle tests
- bib/{iom,oig,pincite,sync,regulations_gov,email_ingest,format,store}
- prisma/{vpn,fetch,export,llm,screen,eligibility,extract,project,ingest,flow}
- aco/lake/{unity,quality,deploy} + api/aco coverage gaps
- zot/{ops,db,extract,duck} + rec/{report,engine,base,pricers}
- pfs/{pipe,rules,eq,files}

Add pytest-xdist for parallel test execution.

Tracks #353
2026-04-18 10:06:47 -04:00

323 lines
10 KiB
Python

"""Deep exercising tests for cli/prisma.py — covers function bodies."""
from __future__ import annotations
from unittest.mock import MagicMock, patch
from typer.testing import CliRunner
from cli.prisma import app
runner = CliRunner()
def _mock_db():
db = MagicMock()
db.__enter__ = MagicMock(return_value=db)
db.__exit__ = MagicMock(return_value=False)
return db
class TestHold:
@patch("cli.prisma.subprocess.run")
def test_hold_true(self, mc_sub):
from cli.prisma import _hold
result = _hold(lambda: 42, hold=True)
assert result == 42
assert mc_sub.call_count == 2
def test_hold_false(self):
from cli.prisma import _hold
result = _hold(lambda: 99, hold=False)
assert result == 99
class TestInit:
@patch("cli.prisma.subprocess.run")
@patch("zot.db.Db")
@patch("prisma.project.init")
def test_basic(self, mc_init, mc_db_cls, mc_sub):
project = MagicMock()
project.name = "test-proj"
project.criteria = "criteria text"
project.extraction_template = "template"
project.reasons = "reasons"
mc_init.return_value = project
mc_db_cls.return_value = _mock_db()
result = runner.invoke(app, ["init", "test-proj", "--no-hold"])
assert result.exit_code == 0
assert "test-proj" in result.output
class TestExport:
@patch("cli.prisma.subprocess.run")
@patch("zot.db.Db")
@patch("prisma.export.load_item")
@patch("prisma.export.to_markdown", return_value="# Exported markdown")
def test_basic(self, mc_md, mc_load, mc_db_cls, mc_sub):
mc_db_cls.return_value = _mock_db()
mc_load.return_value = MagicMock()
result = runner.invoke(app, ["export", "123", "--no-hold"])
assert result.exit_code == 0
assert "Exported markdown" in result.output
class TestScreen:
@patch("cli.prisma.subprocess.run")
@patch("zot.db.Db")
@patch("prisma.llm.make_provider")
@patch("prisma.project.load")
@patch("prisma.screen.run", return_value={"screened": 10, "included": 7})
def test_basic(self, mc_run, mc_load, mc_prov, mc_db_cls, mc_sub):
mc_db_cls.return_value = _mock_db()
mc_prov.return_value = MagicMock()
mc_load.return_value = MagicMock()
result = runner.invoke(app, ["screen", "test-proj", "--no-hold"])
assert result.exit_code == 0
class TestEligible:
@patch("cli.prisma.subprocess.run")
@patch("zot.db.Db")
@patch("prisma.llm.make_provider")
@patch("prisma.project.load")
@patch("prisma.eligibility.run", return_value={"eligible": 5})
def test_basic(self, mc_run, mc_load, mc_prov, mc_db_cls, mc_sub):
mc_db_cls.return_value = _mock_db()
mc_prov.return_value = MagicMock()
mc_load.return_value = MagicMock()
result = runner.invoke(app, ["eligible", "test-proj", "--no-hold"])
assert result.exit_code == 0
class TestExtract:
@patch("cli.prisma.subprocess.run")
@patch("zot.db.Db")
@patch("prisma.llm.make_provider")
@patch("prisma.project.load")
@patch("prisma.extract.run", return_value={"extracted": 3})
def test_basic(self, mc_run, mc_load, mc_prov, mc_db_cls, mc_sub):
mc_db_cls.return_value = _mock_db()
mc_prov.return_value = MagicMock()
mc_load.return_value = MagicMock()
result = runner.invoke(app, ["extract", "test-proj", "--no-hold"])
assert result.exit_code == 0
class TestFlow:
@patch("cli.prisma.subprocess.run")
@patch("zot.db.Db")
@patch("prisma.flow.count")
@patch("prisma.flow.mermaid", return_value="graph TD; A-->B")
def test_mermaid(self, mc_mermaid, mc_count, mc_db_cls, mc_sub):
mc_db_cls.return_value = _mock_db()
mc_count.return_value = MagicMock()
result = runner.invoke(app, ["flow", "test-proj", "--no-hold"])
assert result.exit_code == 0
assert "graph" in result.output
@patch("cli.prisma.subprocess.run")
@patch("zot.db.Db")
@patch("prisma.flow.count")
@patch("prisma.flow.text_summary", return_value="Identified: 100")
def test_text(self, mc_text, mc_count, mc_db_cls, mc_sub):
mc_db_cls.return_value = _mock_db()
mc_count.return_value = MagicMock()
result = runner.invoke(app, ["flow", "test-proj", "--text", "--no-hold"])
assert result.exit_code == 0
assert "Identified" in result.output
class TestFetch:
@patch("cli.prisma.subprocess.run")
@patch("zot.db.Db")
@patch("prisma.fetch.run", return_value={"fetched": 10, "failed": 2})
@patch("prisma.vpn.status", return_value={"status": "down"})
def test_no_vpn(self, mc_vpn_status, mc_fetch, mc_db_cls, mc_sub):
mc_db_cls.return_value = _mock_db()
result = runner.invoke(app, ["fetch", "test-proj", "--no-hold", "--no-vpn"])
assert result.exit_code == 0
@patch("cli.prisma.subprocess.run")
@patch("zot.db.Db")
@patch("prisma.fetch.run", return_value={"fetched": 10})
@patch("prisma.vpn.status", return_value={"status": "up"})
@patch("prisma.vpn.active")
@patch("prisma.vpn.verify_egress", return_value={"ip": "1.2.3.4", "country": "NL"})
def test_with_vpn(
self, mc_egress, mc_active, mc_status, mc_fetch, mc_db_cls, mc_sub
):
mc_db_cls.return_value = _mock_db()
ctx = MagicMock()
ctx.__enter__ = MagicMock(return_value="socks5://localhost:1080")
ctx.__exit__ = MagicMock(return_value=False)
mc_active.return_value = ctx
result = runner.invoke(app, ["fetch", "test-proj", "--no-hold"])
assert result.exit_code == 0
@patch("cli.prisma.subprocess.run")
@patch("zot.db.Db")
@patch("prisma.fetch.run", return_value={"fetched": 5})
@patch("prisma.vpn.status", return_value={"status": "down"})
def test_explicit_proxy(self, mc_status, mc_fetch, mc_db_cls, mc_sub):
mc_db_cls.return_value = _mock_db()
result = runner.invoke(
app,
["fetch", "test-proj", "--no-hold", "--proxy", "socks5://host:1080"],
)
assert result.exit_code == 0
class TestRunAll:
@patch("cli.prisma.subprocess.run")
@patch("zot.db.Db")
@patch("prisma.llm.make_provider")
@patch("prisma.project.load")
@patch("prisma.screen.run", return_value={"screened": 10})
@patch("prisma.fetch.run", return_value={"fetched": 5})
@patch("prisma.eligibility.run", return_value={"eligible": 3})
@patch("prisma.extract.run", return_value={"extracted": 2})
@patch("prisma.flow.count")
@patch("prisma.flow.text_summary", return_value="Summary: OK")
@patch("prisma.vpn.status", return_value={"status": "down"})
def test_full(
self,
mc_vpn,
mc_summary,
mc_count,
mc_extract,
mc_elig,
mc_fetch,
mc_screen,
mc_load,
mc_prov,
mc_db_cls,
mc_sub,
):
mc_db_cls.return_value = _mock_db()
mc_prov.return_value = MagicMock()
mc_load.return_value = MagicMock()
mc_count.return_value = MagicMock()
result = runner.invoke(app, ["run", "test-proj", "--no-hold"])
assert result.exit_code == 0
@patch("cli.prisma.subprocess.run")
@patch("zot.db.Db")
@patch("prisma.llm.make_provider")
@patch("prisma.project.load")
@patch("prisma.screen.run", return_value={"screened": 10})
@patch("prisma.eligibility.run", return_value={"eligible": 3})
@patch("prisma.flow.count")
@patch("prisma.flow.text_summary", return_value="Summary: OK")
@patch("prisma.vpn.status", return_value={"status": "down"})
def test_skip_fetch_extract(
self,
mc_vpn,
mc_summary,
mc_count,
mc_elig,
mc_screen,
mc_load,
mc_prov,
mc_db_cls,
mc_sub,
):
mc_db_cls.return_value = _mock_db()
mc_prov.return_value = MagicMock()
mc_load.return_value = MagicMock()
mc_count.return_value = MagicMock()
result = runner.invoke(
app, ["run", "test-proj", "--no-hold", "--skip-fetch", "--skip-extract"]
)
assert result.exit_code == 0
class TestVpnUp:
@patch("prisma.vpn.up")
def test_basic(self, mc_up):
mc_up.return_value = {
"name": "stack-prisma-vpn",
"droplet_id": 123,
"region": "nyc3",
"public_ip": "1.2.3.4",
"ssh_key": "~/.ssh/id_ed25519",
"proxy_url": "socks5://localhost:1080",
"sidecar": "fetch-proxy",
"zotero_proxy": "socks5://fetch-proxy:1080",
}
result = runner.invoke(app, ["vpn", "up"])
assert result.exit_code == 0
assert "1.2.3.4" in result.output
class TestVpnDown:
@patch("prisma.vpn.down", return_value={"destroyed": True})
def test_basic(self, mc_down):
result = runner.invoke(app, ["vpn", "down"])
assert result.exit_code == 0
class TestVpnStatus:
@patch("prisma.vpn.status", return_value={"status": "up", "ip": "1.2.3.4"})
def test_basic(self, mc_status):
result = runner.invoke(app, ["vpn", "status"])
assert result.exit_code == 0
class TestVpnAttachZotero:
@patch("prisma.vpn.attach_zotero_proxy")
@patch("prisma.vpn._DROPLET_JSON")
def test_basic(self, mc_json, mc_attach):
mc_json.is_file.return_value = True
mc_json.read_text.return_value = '{"public_ip": "1.2.3.4"}'
result = runner.invoke(app, ["vpn", "attach-zotero"])
assert result.exit_code == 0
@patch("prisma.vpn._DROPLET_JSON")
def test_no_droplet(self, mc_json):
mc_json.is_file.return_value = False
result = runner.invoke(app, ["vpn", "attach-zotero"])
assert result.exit_code != 0
class TestVpnDetachZotero:
@patch("prisma.vpn.detach_zotero_proxy")
def test_basic(self, mc_detach):
result = runner.invoke(app, ["vpn", "detach-zotero"])
assert result.exit_code == 0
class TestVpnVerify:
@patch("prisma.vpn.active")
@patch("prisma.vpn.verify_egress")
def test_basic(self, mc_egress, mc_active):
ctx = MagicMock()
ctx.__enter__ = MagicMock(return_value="socks5://localhost:1080")
ctx.__exit__ = MagicMock(return_value=False)
mc_active.return_value = ctx
mc_egress.return_value = {
"ip": "1.2.3.4",
"country": "Netherlands",
"country_iso": "NL",
"asn_org": "DigitalOcean",
}
result = runner.invoke(app, ["vpn", "verify"])
assert result.exit_code == 0
assert "Netherlands" in result.output