from io import BytesIO from types import SimpleNamespace import openpyxl from django.test import SimpleTestCase from artifacts.views import XLSX_CONTENT_TYPE, is_xlsx_upload, xlsx_to_csv_text class IsXlsxUploadTestCase(SimpleTestCase): def test_matches_exact_content_type(self): upload = SimpleNamespace(name="whatever.bin") self.assertTrue(is_xlsx_upload(upload, XLSX_CONTENT_TYPE)) def test_matches_by_extension_regardless_of_content_type(self): upload = SimpleNamespace(name="sheet.xlsx") self.assertTrue(is_xlsx_upload(upload, "application/octet-stream")) self.assertTrue(is_xlsx_upload(upload, "")) def test_extension_match_is_case_insensitive(self): upload = SimpleNamespace(name="SHEET.XLSX") self.assertTrue(is_xlsx_upload(upload, "")) def test_rejects_other_files(self): upload = SimpleNamespace(name="report.pdf") self.assertFalse(is_xlsx_upload(upload, "application/pdf")) class XlsxToCsvTextTestCase(SimpleTestCase): def make_xlsx(self, rows): workbook = openpyxl.Workbook() sheet = workbook.active for row in rows: sheet.append(row) buffer = BytesIO() workbook.save(buffer) buffer.seek(0) return buffer def test_converts_active_sheet_to_csv(self): upload = self.make_xlsx([["Item", "Q1", "Q2"], ["Cash", 1000, 1200]]) content = xlsx_to_csv_text(upload) self.assertEqual(content, "Item,Q1,Q2\nCash,1000,1200\n") def test_uses_single_line_terminator_not_doubled(self): """Regression test: csv.writer's default "\\r\\n" gets a second newline translation from Path.write_text()'s text-mode handling when this string is later saved to disk, producing a blank line between every row on Windows - lineterminator="\\n" avoids embedding "\\r\\n" in the string in the first place, leaving the OS-level text-mode write as the only place "\\n" becomes "\\r\\n".""" upload = self.make_xlsx([["a"], ["b"], ["c"]]) content = xlsx_to_csv_text(upload) self.assertNotIn("\r", content) self.assertEqual(content.count("\n"), 3) def test_empty_cells_become_empty_strings(self): upload = self.make_xlsx([["a", "b"], ["x", None]]) content = xlsx_to_csv_text(upload) self.assertEqual(content, "a,b\nx,\n")