Oracle / tests /test_extract.py
spacedout-bits's picture
Deploy coco-finbot
bfd6783 verified
Raw History Blame Contribute Delete
3.12 kB
import io
from finbot.extract import extract, extract_csv, extract_xlsx, rows_to_text
CSV_BYTES = (
b"Date,Narration,Withdrawal,Deposit\n"
b"01/08/2026,SWIGGY BANGALORE,450.00,\n"
b"03/08/2026,SALARY AUG,,85000.00\n"
b"05/08/2026,NETFLIX.COM,649.00,\n"
)
def make_xlsx() -> bytes:
from openpyxl import Workbook
workbook = Workbook()
sheet = workbook.active
sheet.append(["Date", "Description", "Amount"])
sheet.append(["2026-08-01", "Swiggy", 450])
sheet.append([None, None, None]) # blank row must be dropped
sheet.append(["2026-08-05", "Netflix", 649])
buffer = io.BytesIO()
workbook.save(buffer)
return buffer.getvalue()
class TestCSV:
def test_parses_rows(self):
doc = extract_csv(CSV_BYTES)
assert doc.kind == "csv"
assert len(doc.rows) == 4 # header + 3
assert doc.rows[1][1] == "SWIGGY BANGALORE"
def test_semicolon_delimiter(self):
doc = extract_csv(b"a;b;c\n1;2;3\n4;5;6\n")
assert doc.rows[0] == ["a", "b", "c"]
def test_skips_blank_rows(self):
doc = extract_csv(b"a,b\n\n1,2\n")
assert len(doc.rows) == 2
def test_handles_bom(self):
doc = extract_csv(b"\xef\xbb\xbfDate,Amount\n2026-08-01,10\n")
assert doc.rows[0][0] == "Date"
def test_handles_non_utf8(self):
doc = extract_csv("Caf\xe9,10\n".encode("latin-1"))
assert "Caf" in doc.rows[0][0]
def test_single_column_does_not_crash(self):
doc = extract_csv(b"justonecolumn\nvalue\n")
assert len(doc.rows) == 2
class TestXLSX:
def test_parses_rows(self):
doc = extract_xlsx(make_xlsx())
assert doc.kind == "xlsx"
assert doc.rows[0] == ["Date", "Description", "Amount"]
assert ["2026-08-05", "Netflix", "649"] in doc.rows
def test_drops_blank_rows(self):
doc = extract_xlsx(make_xlsx())
assert all(any(cell for cell in row) for row in doc.rows)
class TestDispatch:
def test_by_extension(self):
assert extract(CSV_BYTES, "statement.csv").kind == "csv"
assert extract(make_xlsx(), "book.xlsx").kind == "xlsx"
def test_by_mime_when_no_extension(self):
assert extract(CSV_BYTES, "", "text/csv").kind == "csv"
def test_plain_text(self):
doc = extract(b"hello", "notes.txt")
assert doc.kind == "text"
assert doc.text == "hello"
def test_legacy_xls_is_reported_not_crashed(self):
doc = extract(b"\xd0\xcf\x11\xe0", "old.xls")
assert doc.kind == "unsupported"
assert ".xlsx" in doc.note
def test_unknown_type_explains_itself(self):
doc = extract(b"\x00\x01", "thing.bin")
assert doc.kind == "unsupported"
assert doc.note
def test_is_empty(self):
assert extract(b"", "empty.txt").is_empty
class TestRowsToText:
def test_pipe_delimited(self):
text = rows_to_text([["a", "b"], ["1", "2"]])
assert text == "a | b\n1 | 2"
def test_respects_limit(self):
text = rows_to_text([["x"]] * 100, limit=3)
assert len(text.splitlines()) == 3