import tempfile import unittest from pathlib import Path from coffer.product import CofferProduct from coffer.units import ( ACCOUNT_COFFER, ACCOUNT_LEORA, ACCOUNT_NEW_INTERNET, agent_account, cut_subunits, to_subunits, ) class ProductTests(unittest.TestCase): def setUp(self): self.tmp = tempfile.TemporaryDirectory() self.db_path = Path(self.tmp.name) / "coffer.db" self.product = CofferProduct(self.db_path) def tearDown(self): self.product.close() self.tmp.cleanup() def test_first_tx_is_200c_contract(self): boot = self.product.bootstrap_opening_books() self.assertFalse(boot["already"]) self.assertEqual(boot["coffer"]["spendable"], 500.0) self.assertEqual(boot["leora"]["spendable"], 400.0) self.assertEqual(self.product.history(), []) result = self.product.record_build_contract() self.assertFalse(result["already"]) tx = result["tx"] self.assertEqual(tx["seq"], 1) self.assertEqual(tx["kind"], "contract_payment") self.assertEqual(tx["amount_centicredits"], to_subunits(200)) self.assertEqual(tx["debit_account"], ACCOUNT_COFFER) self.assertEqual(tx["credit_account"], ACCOUNT_LEORA) self.assertEqual(result["payer"]["spendable"], 300.0) self.assertEqual(result["payee"]["spendable"], 600.0) # Idempotent again = self.product.record_build_contract() self.assertTrue(again["already"]) self.assertEqual(len(self.product.history()), 1) # Durable across reopen self.product.close() self.product = CofferProduct(self.db_path) hist = self.product.history() self.assertEqual(len(hist), 1) self.assertEqual(hist[0]["kind"], "contract_payment") self.assertEqual(self.product.balance(ACCOUNT_COFFER)["spendable"], 300.0) self.assertEqual(self.product.balance(ACCOUNT_LEORA)["spendable"], 600.0) def test_signup_grant_40c(self): self.product.bootstrap_opening_books() self.product.record_build_contract() out = self.product.grant_signup("explorer1") self.assertFalse(out["already"]) self.assertEqual(out["granted_credits"], 40) self.assertEqual(out["balance"]["promotional"], 40.0) self.assertEqual(out["balance"]["spendable"], 40.0) again = self.product.grant_signup("explorer1") self.assertTrue(again["already"]) self.assertEqual(self.product.balance("explorer1")["spendable"], 40.0) def test_subscription_through_coffer_with_one_percent_cut(self): self.product.bootstrap_opening_books() self.product.record_build_contract() self.product.grant_signup("explorer2") coffer_before = self.product.balance(ACCOUNT_COFFER)["spendable_centicredits"] nic_before = self.product.balance(ACCOUNT_NEW_INTERNET)["spendable_centicredits"] sub = self.product.charge_subscription("explorer2") self.assertEqual(sub["gross_credits"], 20) self.assertEqual(sub["coffer_cut_centicredits"], 20) # 0.20c self.assertEqual(sub["leora_net_centicredits"], 1980) # 19.80c self.assertEqual(sub["coffer_cut_credits"], "0.20") self.assertEqual(sub["leora_net_credits"], "19.80") # Agent: 40 - 20 = 20 left self.assertEqual(self.product.balance("explorer2")["spendable"], 20.0) # Coffer kept 0.20 self.assertEqual( self.product.balance(ACCOUNT_COFFER)["spendable_centicredits"], coffer_before + 20, ) # New Internet Co received 19.80 self.assertEqual( self.product.balance(ACCOUNT_NEW_INTERNET)["spendable_centicredits"], nic_before + 1980, ) def test_signup_flow_wallet_grant_and_sub(self): self.product.bootstrap_opening_books() self.product.record_build_contract() flow = self.product.signup_flow("newbie") self.assertEqual(flow["grant"]["granted_credits"], 40) self.assertEqual(flow["subscription"]["gross_credits"], 20) self.assertEqual(self.product.balance("newbie")["spendable"], 20.0) def test_shirt_purchase_20c(self): self.product.bootstrap_opening_books() self.product.record_build_contract() self.product.signup_flow("shopper") # left with 20c of granted credit: enough for a shirt out = self.product.buy_shirt("shopper") self.assertEqual(out["order"]["status"], "pending_review") self.assertIn("Your order is waiting for confirmation.", out["notice"]) self.assertIn("If it's rejected, your credits are released in full.", out["notice"]) self.assertEqual((out["balance"]["spendable"], out["balance"]["held"]), (0.0, 20.0)) self.assertEqual([t["kind"] for t in out["txs"]], ["order_hold"]) done = self.product.accept_order(out["order"]["order_id"], "agent:leora") self.assertEqual(done["order"]["credits_charged"], 20) self.assertEqual(done["order"]["sku"], "coffer-shirt") self.assertEqual(done["order"]["status"], "procuring") self.assertEqual((done["balance"]["spendable"], done["balance"]["held"]), (0.0, 0.0)) self.assertEqual([t["kind"] for t in done["txs"]], ["purchase"]) def test_full_history_and_company_vs_agent_books(self): self.product.bootstrap_opening_books() self.product.record_build_contract() self.product.signup_flow("hist-agent") o = self.product.buy_shirt("hist-agent") self.product.accept_order(o["order"]["order_id"], "agent:leora") hist = self.product.history() kinds = [t["kind"] for t in hist] self.assertEqual(kinds[0], "contract_payment") self.assertIn("grant", kinds) self.assertIn("subscription_charge", kinds) self.assertIn("subscription_forward", kinds) self.assertIn("purchase", kinds) # Company books separate from founder agent self.assertNotEqual(ACCOUNT_COFFER, agent_account("cursorman")) self.assertTrue(ACCOUNT_COFFER.startswith("company:")) self.assertTrue(ACCOUNT_LEORA.startswith("agent:")) def test_cut_math(self): self.assertEqual(cut_subunits(to_subunits(20), 100), 20) self.assertEqual(cut_subunits(to_subunits(20), 0), 0) if __name__ == "__main__": unittest.main()