from genesis.parsers.sheet_nature import SheetNature, classify_sheet, find_header_row def test_table_detection(): m = [["機能ID", "機能名"], ["A001", "社員登録"], ["A002", "退職処理"]] assert classify_sheet(m) == SheetNature.TABLE def test_free_text_single_col(): m = [["新入社員を登録できる。"], ["氏名・所属・入社日を入力する。"]] assert classify_sheet(m) == SheetNature.FREE_TEXT def test_free_text_many_empty_rows(): m = [["要求A"], [], [], [], ["要求B"]] assert classify_sheet(m) == SheetNature.FREE_TEXT def test_header_row_index(): m = [["機能ID", "名前"], ["1", "田中"]] assert find_header_row(m) == 0 assert find_header_row([["自由テキスト"]]) == -1 def test_classify_sheet_mixed_with_bullet_line(): m = [["ID", "名前"], ["1", "田中"], ["・備考行"]] assert classify_sheet(m) == SheetNature.MIXED def test_classify_sheet_mixed_with_square_line(): m = [["ID", "名前"], ["1", "田中"], ["■備考行"]] assert classify_sheet(m) == SheetNature.MIXED def test_classify_empty_matrix_is_free_text(): # 空矩阵:_free_text_like 对空矩阵返回 True(L26 分支) assert classify_sheet([]) == SheetNature.FREE_TEXT def test_classify_sparse_multicol_is_free_text(): # 多列但非空行占比 < 0.7 → FREE_TEXT(L32 稀疏分支) m = [["ID", "名前"], [], [], [], [], ["1", "田中"]] assert classify_sheet(m) == SheetNature.FREE_TEXT def test_classify_header_no_bullet_is_table(): # 表头有效且无 ・/■ 行 → 落入 TABLE(L40→44 无匹配循环路径) m = [["ID", "名前"], ["1", "田中"], ["2", "佐藤"]] assert classify_sheet(m) == SheetNature.TABLE