from copy import copy from openpyxl import Workbook from openpyxl.comments import Comment from genesis.data_models import CellComment, CellFormatting from genesis.parsers.formatting_detector import ( cell_comment, cell_formatting, collect_comments, ) def make_wb(): wb = Workbook() ws = wb.active ws.title = "機能一覧" ws["A1"] = "F001" font = copy(ws["A1"].font) font.strike = True ws["A1"].font = font ws["A2"] = "F002" ws["A2"].comment = Comment("要確認", "reviewer") return wb def test_cell_formatting_detects_strike(): fmt = cell_formatting(make_wb().active["A1"]) assert fmt is not None assert fmt.strikethrough is True def test_cell_formatting_none_when_plain(): wb = Workbook() ws = wb.active ws["A1"] = "x" assert cell_formatting(ws["A1"]) is None def test_cell_formatting_detects_font_color(): from openpyxl.styles import Font wb = Workbook() ws = wb.active ws["A1"] = "x" f = copy(ws["A1"].font) f.color = Font(color="FF0000FF").color ws["A1"].font = f fmt = cell_formatting(ws["A1"]) assert fmt is not None assert fmt.font_color is not None def test_cell_comment_returns_obj(): wb = make_wb() cm = cell_comment(wb.active["A2"], "f.xlsx") assert isinstance(cm, CellComment) assert cm.author == "reviewer" assert cm.text == "要確認" assert cm.source_uri == "f.xlsx#機能一覧!A2" def test_collect_comments(): comments = collect_comments(make_wb().active, "f.xlsx") assert len(comments) == 1 def test_to_rgb_hex_accepts_6_digit_hex(): from types import SimpleNamespace from genesis.parsers.formatting_detector import _to_rgb_hex assert _to_rgb_hex(SimpleNamespace(rgb="FF3333")) == "FF3333" assert _to_rgb_hex(SimpleNamespace(rgb="00FF00FF")) == "00FF00FF" def test_to_rgb_hex_rejects_black_and_theme(): from types import SimpleNamespace from genesis.parsers.formatting_detector import _to_rgb_hex # 纯黑(默认色)与主题色(rgb 为空/异常/非 hex)→ None assert _to_rgb_hex(SimpleNamespace(rgb="00000000")) is None assert _to_rgb_hex(SimpleNamespace(rgb="FF000000")) is None assert _to_rgb_hex(SimpleNamespace(rgb="")) is None assert _to_rgb_hex(SimpleNamespace(rgb="ZZZZZZ")) is None assert _to_rgb_hex(SimpleNamespace(rgb="FFFFF")) is None # 长度不足 class _ExplodingRgb: @property def rgb(self): raise Exception("boom") def test_to_rgb_hex_rgb_access_exception_returns_none(): from genesis.parsers.formatting_detector import _to_rgb_hex # L15-16:color.rgb 访问抛异常 → 返回 None(防御分支) assert _to_rgb_hex(_ExplodingRgb()) is None def test_cell_formatting_fills_only_color(): from copy import copy from openpyxl.styles import PatternFill from genesis.parsers.formatting_detector import cell_formatting wb = Workbook() ws = wb.active ws["A1"] = "x" # 仅背景色(无 strikethrough / 无字体色)→ 返回 CellFormatting 含 bg_color f = copy(ws["A1"].fill) f.fgColor = PatternFill(start_color="00CC00").fgColor ws["A1"].fill = f fmt = cell_formatting(ws["A1"]) assert fmt is not None assert fmt.bg_color is not None def test_cell_formatting_fill_none_branch(): # 覆盖 L31 防御分支:fill 为 None(无样式对象)时直接返回 None from types import SimpleNamespace from genesis.parsers.formatting_detector import cell_formatting fake = SimpleNamespace(font=SimpleNamespace(strike=False), fill=None) assert cell_formatting(fake) is None