"""Unit tests for the pure filename-normalization helpers in imagehub_routes. These cover the {prefix}_{caseID}_0000.{ext} rename convention (caseID = the file's number, 5-digit zero-padded), the case-number extraction, and the double-extension split — with no Postgres / MinIO dependency. """ from __future__ import annotations import unittest from src.imagehub_routes import _case_number, _normalized_name, _split_name_ext class TestSplitNameExt(unittest.TestCase): def test_double_extension_nii_gz(self): self.assertEqual(_split_name_ext("a.nii.gz"), ("a", ".nii.gz")) def test_double_extension_tar_gz(self): self.assertEqual(_split_name_ext("a.tar.gz"), ("a", ".tar.gz")) def test_single_extension(self): self.assertEqual(_split_name_ext("a.png"), ("a", ".png")) def test_no_extension(self): self.assertEqual(_split_name_ext("a"), ("a", "")) class TestCaseNumber(unittest.TestCase): def test_plain_number(self): self.assertEqual(_case_number("1"), 1) self.assertEqual(_case_number("100"), 100) def test_strips_channel_tag(self): self.assertEqual(_case_number("10_0000"), 10) def test_prefixed_stem(self): # year digits in the prefix must NOT be mistaken for the case number self.assertEqual(_case_number("POLYP25_00001"), 1) self.assertEqual(_case_number("POLYP25_00123_0000"), 123) def test_no_digits(self): self.assertIsNone(_case_number("frame")) class TestNormalizedName(unittest.TestCase): def test_image_gets_prefix_padding_and_channel(self): self.assertEqual(_normalized_name("1.png", "POLYP25", False), "POLYP25_00001_0000.png") self.assertEqual(_normalized_name("100.png", "POLYP25", False), "POLYP25_00100_0000.png") def test_label_gets_prefix_padding_no_channel(self): self.assertEqual(_normalized_name("1.png", "POLYP25", True), "POLYP25_00001.png") def test_image_and_label_share_case_id(self): img = _normalized_name("7.png", "POLYP25", False) lbl = _normalized_name("7.png", "POLYP25", True) self.assertEqual(img, "POLYP25_00007_0000.png") self.assertEqual(lbl, "POLYP25_00007.png") def test_double_extension(self): self.assertEqual(_normalized_name("5.nii.gz", "RIB25", False), "RIB25_00005_0000.nii.gz") def test_idempotent_already_correct(self): self.assertIsNone(_normalized_name("POLYP25_00001_0000.png", "POLYP25", False)) self.assertIsNone(_normalized_name("POLYP25_00001.png", "POLYP25", True)) def test_reprefix_changes_prefix_keeps_case(self): self.assertEqual( _normalized_name("OLD25_00009_0000.png", "POLYP25", False), "POLYP25_00009_0000.png" ) def test_no_case_number_returns_none(self): self.assertIsNone(_normalized_name("frame.png", "POLYP25", False)) if __name__ == "__main__": unittest.main()