"""Testes do app: fallback de data, autenticação e CRUD de documentos.""" import os import tempfile import unittest from datetime import date from pathlib import Path class DateFallbackTests(unittest.TestCase): def test_iso_date_is_kept(self): from app.dates import resolve_purchase_date self.assertEqual(resolve_purchase_date("2026-06-09"), "2026-06-09") def test_br_date_is_normalized(self): from app.dates import resolve_purchase_date self.assertEqual(resolve_purchase_date("09/06/2026"), "2026-06-09") def test_illegible_date_falls_back_to_first_of_month(self): from app.dates import resolve_purchase_date ref = date(2026, 7, 24) self.assertEqual(resolve_purchase_date("ilegível", reference=ref), "2026-07-01") self.assertEqual(resolve_purchase_date(None, reference=ref), "2026-07-01") self.assertEqual(resolve_purchase_date("", reference=ref), "2026-07-01") def test_invalid_calendar_date_falls_back(self): from app.dates import resolve_purchase_date ref = date(2026, 7, 24) self.assertEqual(resolve_purchase_date("2026-13-40", reference=ref), "2026-07-01") class PasswordTests(unittest.TestCase): def test_hash_and_verify(self): from app import auth h = auth.hash_password("segredo-forte") self.assertTrue(auth.verify_password("segredo-forte", h)) self.assertFalse(auth.verify_password("errada", h)) class CrudTests(unittest.TestCase): def setUp(self): self._tmp = tempfile.TemporaryDirectory() os.environ["DB_PATH"] = str(Path(self._tmp.name) / "crud.sqlite3") # zera o cache de settings para pegar o DB_PATH novo from app.config import get_settings get_settings.cache_clear() def tearDown(self): os.environ.pop("DB_PATH", None) from app.config import get_settings get_settings.cache_clear() self._tmp.cleanup() def test_create_update_delete_list(self): from app import database as db with db.session() as conn: doc_id = db.create_fiscal( conn, purchase_date="2026-07-01", supplier_name="Padaria X", total_paid=10.0 ) self.assertEqual(db.overall_totals(conn)["count"], 1) db.update_fiscal( conn, doc_id, purchase_date="2026-07-02", supplier_name="Padaria Y", total_paid=12.5 ) row = db.get_fiscal(conn, doc_id) self.assertEqual(row["supplier_name"], "Padaria Y") self.assertEqual(row["total_paid"], 12.5) rows = db.list_fiscal(conn, supplier="Padaria") self.assertEqual(len(rows), 1) db.delete_fiscal(conn, doc_id) self.assertEqual(db.overall_totals(conn)["count"], 0) class StagingGateTests(unittest.TestCase): def setUp(self): self._tmp = tempfile.TemporaryDirectory() os.environ["DB_PATH"] = str(Path(self._tmp.name) / "stage.sqlite3") from app.config import get_settings get_settings.cache_clear() def tearDown(self): os.environ.pop("DB_PATH", None) from app.config import get_settings get_settings.cache_clear() self._tmp.cleanup() def _stage(self, conn, batch_id, upload_id, **over): base = dict( upload_id=upload_id, batch_id=batch_id, source_file_name="f.pdf", source_page=None, source_location="f.pdf", raw_text="", purchase_date="2026-07-01", supplier_name="Loja", total_paid=10.0, confidence="high", field_confidence={}, legible=True, uncertain_fields=[], extractor="local", ) base.update(over) from app import database as db return db.insert_detected(conn, **base) def test_incomplete_row_counts_as_pending_and_is_not_imported(self): from app import database as db with db.session() as conn: batch = db.create_batch(conn) up = db.insert_upload(conn, batch, "f.pdf", Path("f.pdf"), "application/pdf", 1) self._stage(conn, batch, up) # completo # legível mas SEM fornecedor -> incompleto, deve contar como pendente self._stage(conn, batch, up, supplier_name=None, legible=True) summary = db.batch_summary(conn, batch) self.assertEqual(summary["count"], 2) self.assertEqual(summary["incompletos"], 1) self.assertEqual(summary["pendentes"], 1) def test_confirm_only_promotes_complete_rows(self): from app import database as db with db.session() as conn: batch = db.create_batch(conn) up = db.insert_upload(conn, batch, "f.pdf", Path("f.pdf"), "application/pdf", 1) self._stage(conn, batch, up, supplier_name="Loja A", total_paid=10.0) self._stage(conn, batch, up, supplier_name="Loja B", total_paid=20.0) inserted = db.confirm_batch(conn, batch) self.assertEqual(inserted, 2) self.assertEqual(db.overall_totals(conn)["total"], 30.0) if __name__ == "__main__": unittest.main()