import sys import re import unittest from pathlib import Path sys.path.insert(0, str(Path(__file__).resolve().parents[1])) import gradio as gr from jujo_browser import assignment, entries_for_browser from scripts.update_jujo_catalog import image_path, pupil_sample_viewport class TestAssignment(unittest.TestCase): def setUp(self): self.values = [True, "a", .8, False, "b", .7, False, "---", .8, False, "c", 1.0] self.name = entries_for_browser("anima")[0]["name"] def test_only_selected_slot_changes(self): payload = dict(selected=self.name, slot=3, strength=.9) offset, updated = assignment("anima", payload, self.values) self.assertEqual(offset, 6) self.assertEqual(updated[6:9], [True, self.name, .9]) self.assertEqual(updated[:6], self.values[:6]) self.assertEqual(updated[9:], self.values[9:]) self.assertFalse(self.values[6]) def test_invalid_or_cross_family_action_rejected(self): for patch in (dict(slot=0), dict(slot=5), dict(slot=True), dict(slot="1"), dict(strength=float("nan")), dict(strength=3), dict(strength=-1), dict(selected=entries_for_browser("illustrious")[0]["name"])): payload = dict(selected=self.name, slot=1, strength=.8) payload.update(patch) with self.assertRaises(gr.Error): assignment("anima", payload, self.values) def test_every_entry_has_browser_metadata(self): categories = {"目の形", "眉", "口", "表情・人物", "効果"} for family in ("anima", "illustrious"): for entry in entries_for_browser(family): self.assertIn(entry["category"], categories) self.assertTrue(entry["image"].startswith("https://huggingface.co/JujoHotaru/")) self.assertTrue(0 <= entry["strength"] <= 2) def test_eye_collection_uses_exact_code_ill_samples(self): entries = [e for e in entries_for_browser("illustrious") if e["name"].startswith("eyecolle_xl_code")] self.assertEqual(len(entries), 81) self.assertEqual(len({e["image"] for e in entries}), 81) for entry in entries: code = re.fullmatch(r"eyecolle_xl_code(\d{3})\.safetensors", entry["name"])[1] self.assertRegex(entry["image"], rf"/(tareme|tsurime)_ill{code}\.webp$") self.assertFalse(entry["group_sample"]) self.assertEqual(entry["code"], "code" + code) self.assertIn(entry["code"], entry["sample_note"]) self.assertIn("Illustrious", entry["sample_note"]) shape = "tareme" if "/tareme_" in entry["image"] else "tsurime" self.assertIn(shape, entry["hint"]) self.assertEqual(entry["strength"], 1.5) def test_catalog_generator_prefers_ill_not_pony_or_other_code(self): doc = "sdxl/eyecollexl/README.md" base = "sdxl/eyecollexl/" path = base + "eyecolle_xl_code127.safetensors" markdown = "![](thumb.webp)\n![](tareme_pny127.webp)![](tareme_ill1270.webp)![](tareme_ill127.webp)" available = {base + name for name in ("thumb.webp", "tareme_pny127.webp", "tareme_ill1270.webp", "tareme_ill127.webp")} self.assertEqual(image_path(markdown, "JujoHotaru/lora", "pinned", doc, path, available), (base + "tareme_ill127.webp", False)) available.remove(base + "tareme_ill127.webp") self.assertEqual(image_path(markdown, "JujoHotaru/lora", "pinned", doc, path, available), (base + "thumb.webp", True)) def test_eye_type_metadata_and_individual_samples(self): entries = {e["name"]: e for e in entries_for_browser("illustrious")} for code, version in (("01", "20"), ("04", "10")): entry = entries[f"hotarueye_xl_comic{code}_v{version}_ill.safetensors"] self.assertTrue(entry["image"].endswith(f"/sdxl/hotarueye_xl_comic{code}_v{version}.webp")) self.assertIn(f"Type {int(code)}", entry["sample_note"]) self.assertEqual(entry["category"], "目の形") self.assertFalse(entry["group_sample"]) for number in (1, 2): entry = entries[f"hotarueye_xl_hosome{number}_v30.safetensors"] self.assertTrue(entry["image"].endswith(f"/sdxl/hosome/type{number}_v30.webp")) self.assertIn(f"Type {number}", entry["sample_note"]) self.assertIn("Illustrious", entry["sample_note"]) self.assertFalse(entry["group_sample"]) for number, xy in enumerate(((768,0),(1168,0),(1568,0),(768,400),(1168,400),(1568,400)), 1): entry = entries[f"hotarupupil_xl_type{number}_v10.safetensors"] view = entry["sample_viewport"] self.assertTrue(entry["image"].endswith("/sdxl/pupil/v10_sample1.webp")) self.assertEqual((view["x"], view["y"]), xy) self.assertEqual((view["width"], view["height"]), (400,400)) self.assertLessEqual(view["x"] + view["width"], view["source_width"]) self.assertLessEqual(view["y"] + view["height"], view["source_height"]) self.assertIn(f"Type {number}", entry["sample_note"]) self.assertTrue(entry["group_sample"]) # source is still a comparison sheet def test_type_sample_generator_handles_author_filenames(self): def pick(doc, name, images): folder = str(Path(doc).parent).replace("\\", "/") available = {f"{folder}/{image}" for image in images} text = "".join(f"![]({image})" for image in images) return image_path(text, "JujoHotaru/lora", "pinned", doc, "sdxl/" + name, available) self.assertEqual(pick("sdxl/README.md", "hotarueye_xl_comic01_v20_ill.safetensors", ["header.webp","hotarueye_xl_comic01_v10.webp","hotarueye_xl_comic01_v20.webp"]), ("sdxl/hotarueye_xl_comic01_v20.webp", False)) self.assertEqual(pick("sdxl/hosome/README.md", "hotarueye_xl_hosome2_v30.safetensors", ["thumb.webp","type1_v30.webp","type2_v30.webp"]), ("sdxl/hosome/type2_v30.webp", False)) self.assertEqual(pick("sdxl/pupil/README.md", "hotarupupil_xl_type6_v10.safetensors", ["thumb.webp","v10_sample1.webp","v10_sample2.webp"]), ("sdxl/pupil/v10_sample1.webp", True)) self.assertIsNone(pupil_sample_viewport("hotarupupil_xl_type7_v10.safetensors", "sdxl/pupil/v10_sample1.webp")) self.assertIsNone(pupil_sample_viewport("hotarupupil_xl_type1_v10.safetensors", "sdxl/pupil/v10_sample2.webp")) if __name__ == "__main__": unittest.main()