"""Unit tests for the lightning package (factory + ledger).""" from __future__ import annotations import pytest from lightning.factory import Invoice, MockBackend, get_backend from lightning.ledger import ( TxStatus, TxType, clear, create_invoice_entry, get_balance, get_transactions, mark_settled, ) @pytest.fixture(autouse=True) def _clean_ledger(): """Reset the in-memory ledger between tests.""" clear() yield clear() # ── Factory tests ──────────────────────────────────────────────────── class TestMockBackend: def test_create_invoice_returns_invoice(self): backend = MockBackend() inv = backend.create_invoice(100, "test memo") assert isinstance(inv, Invoice) assert inv.amount_sats == 100 assert inv.memo == "test memo" assert len(inv.payment_hash) == 64 # SHA-256 hex assert inv.payment_request.startswith("lnbc") def test_invoices_have_unique_hashes(self): backend = MockBackend() a = backend.create_invoice(10) b = backend.create_invoice(10) assert a.payment_hash != b.payment_hash class TestGetBackend: def test_returns_mock_backend(self): backend = get_backend() assert isinstance(backend, MockBackend) # ── Ledger tests ───────────────────────────────────────────────────── class TestLedger: def test_create_invoice_entry(self): entry = create_invoice_entry( payment_hash="abc123", amount_sats=500, memo="test", source="unit_test", ) assert entry.tx_type == TxType.incoming assert entry.status == TxStatus.pending assert entry.amount_sats == 500 def test_mark_settled(self): create_invoice_entry(payment_hash="hash1", amount_sats=100) result = mark_settled("hash1", preimage="secret") assert result is not None assert result.status == TxStatus.settled assert result.preimage == "secret" assert result.settled_at != "" def test_mark_settled_unknown_hash(self): assert mark_settled("nonexistent") is None def test_get_balance_empty(self): bal = get_balance() assert bal["net_sats"] == 0 assert bal["available_sats"] == 0 def test_get_balance_with_settled(self): create_invoice_entry(payment_hash="h1", amount_sats=1000) mark_settled("h1") bal = get_balance() assert bal["incoming_total_sats"] == 1000 assert bal["net_sats"] == 1000 assert bal["available_sats"] == 1000 def test_get_balance_pending_not_counted(self): create_invoice_entry(payment_hash="h2", amount_sats=500) bal = get_balance() assert bal["incoming_total_sats"] == 0 assert bal["pending_incoming_sats"] == 500 def test_get_transactions_returns_entries(self): create_invoice_entry(payment_hash="t1", amount_sats=10) create_invoice_entry(payment_hash="t2", amount_sats=20) txs = get_transactions() assert len(txs) == 2 def test_get_transactions_filter_by_status(self): create_invoice_entry(payment_hash="f1", amount_sats=10) create_invoice_entry(payment_hash="f2", amount_sats=20) mark_settled("f1") assert len(get_transactions(status="settled")) == 1 assert len(get_transactions(status="pending")) == 1